(ns microtables-frontend.views (:require [re-frame.core :as re-frame] [microtables-frontend.subs :as subs] [microtables-frontend.events :as events] [microtables-frontend.utils :as utils])) ;; TABLE COMPONENTS (defn cell [c r data] (let [datum (get-in data [c r])] ^{:key (str c r)} [:td [:input {:id (str c r) :value (if (= (get datum :view nil) :value) (get datum :value "") (get datum :error (get datum :display (get datum :value ""))));TODO: add "highlight" display mode (possibly just a css class) :on-change #(re-frame/dispatch [::events/edit-cell-value c r (.. % -target -value)]) :on-focus #(re-frame/dispatch [::events/movement-enter-cell c r]) :on-blur #(re-frame/dispatch [::events/movement-leave-cell c r]) :on-keyPress #(when (= (.. % -which) 13) (re-frame/dispatch [::events/press-enter-in-cell 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 {:id "main-table"} [:tbody ;TODO: figure out appropriate starting values for maxrow and maxcol (maybe keep them intentionally small) ;TODO: figure out movement (maybe allow scroll overflow) (let [maxrow 50;(utils/highest-row data) maxcol "L";(utils/highest-col data) cols (take-while (partial not= (utils/next-letter maxcol)) utils/col-letters)] (cons (header-row cols) (map #(row % cols data) (range 1 (inc maxrow)))))]]) (defn controls [] [:div [:button "one"] ;extend range (number field, then shrink/left/up and expand/right/down buttons on either side) ;fill range (single tap, single column/row fill? number field and button?) ;move range (designate new "top-left corner" cell for range, figure out overwriting destination cells) ;empty range (delete contents, re-evaluate) ;delete range (figure out how to move cells over) ;copy range (figure out clipboard) [:button "two"]]) (defn controls-group [state] [:div {:id "controls"} [:div ;TODO: link left controls with position of the whole table {:id "controls-left" :class (if (= state :left) "open" "")} [controls]] [:div {:id "controls-bottom" :class (if (= state :bottom) "open" "")} [controls]] ;←↑→↓ [:button {:id "left-controls-button" :on-click #(re-frame/dispatch [::events/set-controls-state (if (= state :left) nil :left)])} (if (= state :left) "←" "→")] [:button {:id "bottom-controls-button" :on-click #(re-frame/dispatch [::events/set-controls-state (if (= state :bottom) nil :bottom)])} (if (= state :bottom) "↓" "↑")] [:div {:id "main-logo" :title "Microtables"} [:img {:src "logo.svg"}]]]) (defn main-panel [] (let [data (re-frame/subscribe [::subs/table-data]) controls-state (re-frame/subscribe [::subs/controls-state])] [:div [sheet @data] [controls-group @controls-state]]))