        (map #(zipmap [:day :shift :name] %))))
 
 (defn updatePlan [e]
-  (println e)
   (let [v (.-value planInput)
         p (extractPlan v)]
     (plotPlan p)))
 
+(defn prepareCanvas! []
+  (-> d3
+      (.select "#canvas")
+      (.selectAll "text.days")
+      (.data (clj->js DAYS))
+      (.enter)
+      (.append "text")
+      (.attr #js {:class "days"})
+      (.attr "transform" #(str "translate("
+                               (+ 5 (* WIDTH (inc %2)))
+                               ",20)"))
+      (.text #(str %)))
+  (-> d3
+      (.select "#canvas")
+      (.selectAll "text.hours")
+      (.data (clj->js HOURS))
+      (.enter)
+      (.append "text")
+      (.attr #js {:class "dahoursys"})
+      (.attr "transform" #(str "translate(" (- WIDTH 20) ", "
+                               (+ HEIGHT-HOUR ;; offset legend
+                                  (/ HEIGHT-HOUR 2) ;; text to the middle
+                                  (* HEIGHT-HOUR (inc %2)))
+                               ")"))
+      (.text #(str %))))
+
 (defn setup! []
+  (prepareCanvas!)
   (.addEventListener renderInput "click" updatePlan))
 
 (setup!)

(def WIDTH 60)
(def HEIGHT-HOUR 20)
(def HEIGHT (* 8 HEIGHT-HOUR))

(defn shift-color [name]
  (let [toNumber #(-> (window/parseInt (nth (lower-case %1) %2) 36)

                     (int))]
    (str "rgb(" (join "," [(toNumber name 0) (toNumber name 1) (toNumber name 2)]) ")")))

(defn plotPlan [plan]
  (let [jsPlan (clj->js plan)
        dataSet (-> d3
                    (.select "#canvas")
                    (.selectAll "g")
                    (.data jsPlan (fn [key] (str
                                              (.-day key)
                                              (.-shift key)
                                              (.-name key)))))
        enterSet (.enter dataSet)
        enterGroup (-> enterSet
                     (.append "g")
