|  | @@ -2,17 +2,78 @@
 | 
	
		
			
				|  |  |      (:require
 | 
	
		
			
				|  |  |        [reagent.core :as r]))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +; to generate random values
 | 
	
		
			
				|  |  | +;for(let i = 0, s = new Set(); i < 10; i++){ let r = Math.floor(Math.random() * 15)+1, c = a[Math.floor(Math.random() * a.length)], k = `${c}${r}`; if(s.has(k)){ i--; continue; } s.add(k); v.push(`{:row ${r} :col "${c}" :value "${Math.floor(Math.random() * 10000)}"}`); }
 | 
	
		
			
				|  |  | +(def sample-data [{:row 1 :col "A" :value "59"}
 | 
	
		
			
				|  |  | +                  {:row 5 :col "C" :value "269"}
 | 
	
		
			
				|  |  | +                  {:row 5 :col "H" :value "2001"}
 | 
	
		
			
				|  |  | +                  {:row 4 :col "B" :value "7893"}
 | 
	
		
			
				|  |  | +                  {:row 8 :col "K" :value "8291"}
 | 
	
		
			
				|  |  | +                  {:row 8 :col "H" :value "755"}
 | 
	
		
			
				|  |  | +                  {:row 2 :col "F" :value "8650"}
 | 
	
		
			
				|  |  | +                  {:row 6 :col "D" :value "4065"}
 | 
	
		
			
				|  |  | +                  {:row 10 :col "G" :value "788"}
 | 
	
		
			
				|  |  | +                  {:row 7 :col "F" :value "5316"}
 | 
	
		
			
				|  |  | +                  {:row 15 :col "G" :value "8599"}
 | 
	
		
			
				|  |  | +                  {:row 1 :col "A" :value "4910"}
 | 
	
		
			
				|  |  | +                  {:row 12 :col "A" :value "2405"}
 | 
	
		
			
				|  |  | +                  {:row 14 :col "H" :value "7292"}
 | 
	
		
			
				|  |  | +                  {:row 5 :col "B" :value "7863"}
 | 
	
		
			
				|  |  | +                  {:row 9 :col "E" :value "3144"}
 | 
	
		
			
				|  |  | +                  {:row 10 :col "D" :value "8272"}
 | 
	
		
			
				|  |  | +                  {:row 2 :col "F" :value "3013"}
 | 
	
		
			
				|  |  | +                  {:row 12 :col "G" :value "9411"}
 | 
	
		
			
				|  |  | +                  {:row 11 :col "D" :value "2495"}
 | 
	
		
			
				|  |  | +                  {:row 15 :col "E" :value "8968"}])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn highest [dir data] (apply max (map dir data)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn upgrade-letter-code [s]
 | 
	
		
			
				|  |  | +  (let [l (last s)]
 | 
	
		
			
				|  |  | +    (cond
 | 
	
		
			
				|  |  | +      (empty? s) [65]
 | 
	
		
			
				|  |  | +      (= l 90) (conj (upgrade-letter-code (subvec s 0 (dec (count s)))) 65)
 | 
	
		
			
				|  |  | +      :else (conj (subvec s 0 (dec (count s))) (inc l)))))
 | 
	
		
			
				|  |  | +(defn next-letter [lc]
 | 
	
		
			
				|  |  | +  (apply str (map char (upgrade-letter-code (mapv #(.charCodeAt % 0) lc)))))
 | 
	
		
			
				|  |  | +(def col-letters (iterate next-letter "A"))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  ;; -------------------------
 | 
	
		
			
				|  |  |  ;; Views
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -(defn home-page []
 | 
	
		
			
				|  |  | -  [:div [:h2 "Welcome to Reagent"]])
 | 
	
		
			
				|  |  | +(defn cell [c r data]
 | 
	
		
			
				|  |  | +  ^{:key (str c r)} [:td (str c r)]
 | 
	
		
			
				|  |  | +  )
 | 
	
		
			
				|  |  | +(defn row [r cols data]
 | 
	
		
			
				|  |  | +  ^{:key (str "row-" r)} [:tr
 | 
	
		
			
				|  |  | +                          (cons
 | 
	
		
			
				|  |  | +                            ^{:key (str "row-head-" r)} [:th (str r)]
 | 
	
		
			
				|  |  | +                            (map #(cell % r data) cols))])
 | 
	
		
			
				|  |  | +(defn header-row [cols]
 | 
	
		
			
				|  |  | +  ^{:key "header"} [:tr
 | 
	
		
			
				|  |  | +   (cons
 | 
	
		
			
				|  |  | +     ^{:key "corner"} [:th]
 | 
	
		
			
				|  |  | +     (map (fn [c] ^{:key (str "col-head-" c)} [:th c]) cols))])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn sheet [data]
 | 
	
		
			
				|  |  | +  [:table [:tbody
 | 
	
		
			
				|  |  | +           (let [maxrow (highest :row data)
 | 
	
		
			
				|  |  | +                 cols (take-while (partial not= (next-letter (highest :col sample-data))) col-letters)]
 | 
	
		
			
				|  |  | +             (cons
 | 
	
		
			
				|  |  | +               (header-row cols)
 | 
	
		
			
				|  |  | +               (map #(row % cols data) (range 1 (inc maxrow)))))
 | 
	
		
			
				|  |  | +           ]])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn app []
 | 
	
		
			
				|  |  | +  [:div
 | 
	
		
			
				|  |  | +   [:h3 "Microtable"]
 | 
	
		
			
				|  |  | +   [sheet sample-data]])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ;; -------------------------
 | 
	
		
			
				|  |  |  ;; Initialize app
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (defn mount-root []
 | 
	
		
			
				|  |  | -  (r/render [home-page] (.getElementById js/document "app")))
 | 
	
		
			
				|  |  | +  (r/render [app] (.getElementById js/document "app")))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (defn init! []
 | 
	
		
			
				|  |  |    (mount-root))
 |