Rework state/view handling

This commit is contained in:
Nicholas Kariniemi 2014-07-02 23:13:00 +03:00
parent fe6514a5f5
commit 0bf23c9255
2 changed files with 70 additions and 61 deletions

View file

@ -4,21 +4,21 @@
(:require-macros [grub.macros :refer [log logs]] (:require-macros [grub.macros :refer [log logs]]
[cljs.core.async.macros :refer [go go-loop]])) [cljs.core.async.macros :refer [go go-loop]]))
(def default-app-state {:grubs {} (def app-state (atom {:grubs {}
:recipes {}}) :recipes {}}))
(defmulti handle-grub-event (fn [event state] (:event event)) (defmulti handle-event (fn [event state] (:event event))
:default :unknown-event) :default :unknown-event)
(defmethod handle-grub-event :unknown-event [event grubs] (defmethod handle-event :unknown-event [event state]
grubs) state)
(defn new-grub [id grub completed] (defn new-grub [id grub completed]
{:id id :grub grub :completed completed}) {:id id :grub grub :completed completed})
(defmethod handle-grub-event :add-grub [event grubs] (defmethod handle-event :add-grub [event state]
(let [grub (new-grub (:id event) (:grub event) (:completed event))] (let [grub (new-grub (:id event) (:grub event) (:completed event))]
(assoc grubs (:id grub) grub))) (assoc-in state [:grubs (:id grub)] grub)))
(defn assoc-new-grub [current new] (defn assoc-new-grub [current new]
(assoc current (:id new) (assoc current (:id new)
@ -27,54 +27,49 @@
(defn make-add-grubs-map [grub-events] (defn make-add-grubs-map [grub-events]
(reduce assoc-new-grub {} grub-events)) (reduce assoc-new-grub {} grub-events))
(defmethod handle-grub-event :add-grub-list [event grubs] (defmethod handle-event :add-grub-list [event state]
(let [add-grub-events (:grubs event) (let [add-grub-events (:grubs event)
add-grubs (make-add-grubs-map add-grub-events)] add-grubs (make-add-grubs-map add-grub-events)]
(merge grubs add-grubs))) (assoc state :grubs (merge (:grubs state) add-grubs))))
(defmethod handle-grub-event :complete-grub [event grubs] (defmethod handle-event :complete-grub [event state]
(assoc-in grubs [(:id event) :completed] true)) (assoc-in state [:grubs (:id event) :completed] true))
(defmethod handle-grub-event :uncomplete-grub [event grubs] (defmethod handle-event :uncomplete-grub [event state]
(assoc-in grubs [(:id event) :completed] false)) (assoc-in state [:grubs (:id event) :completed] false))
(defmethod handle-grub-event :update-grub [event grubs] (defmethod handle-event :update-grub [event state]
(assoc-in grubs [(:id event) :grub] (:grub event))) (assoc-in state [:grubs (:id event) :grub] (:grub event)))
(defmethod handle-grub-event :clear-all-grubs [event grubs] (defmethod handle-event :clear-all-grubs [event state]
{}) (assoc state :grubs {}))
(defmulti handle-recipe-event (fn [event recipes] (:event event))
:default :unknown-event)
(defmethod handle-recipe-event :unknown-event [event recipes]
recipes)
(defn new-recipe [id name grubs] (defn new-recipe [id name grubs]
{:id id :name name :grubs grubs}) {:id id :name name :grubs grubs})
(defmethod handle-recipe-event :add-recipe [event recipes] (defmethod handle-event :add-recipe [event state]
(let [recipe (new-recipe (:id event) (:name event) (:grubs event))] (let [recipe (new-recipe (:id event) (:name event) (:grubs event))]
(assoc recipes (:id recipe) recipe))) (assoc-in state [:recipes (:id recipe)] recipe)))
(defmethod handle-recipe-event :add-recipe-list [event recipes] (defmethod handle-event :add-recipe-list [event state]
(->> (:recipes event) (->> (:recipes event)
(map #(new-recipe (:id %) (:name %) (:grubs %))) (map #(new-recipe (:id %) (:name %) (:grubs %)))
(reduce (fn [recipes r] (assoc recipes (:id r) r)) recipes))) (reduce (fn [recipes r] (assoc recipes (:id r) r)) (:recipes state))
(assoc state :recipes)))
(defmethod handle-recipe-event :update-recipe [event recipes] (defmethod handle-event :update-recipe [event state]
(->> recipes (->> state
(assoc-in [(:id event) :name] (:name event)) (assoc-in [:recipes (:id event) :name] (:name event))
(assoc-in [(:id event) :grubs] (:grubs event)))) (assoc-in [:recipes (:id event) :grubs] (:grubs event))))
(defn update-state-and-render [remote] (defn update-state-and-render [remote]
(go-loop [state default-app-state] (let [out (chan)
(let [event (<! (a/merge [remote view/out])) view-events (view/render-app app-state)]
new-grubs (handle-grub-event event (:grubs state)) (go-loop []
new-recipes (handle-recipe-event event (:recipes state)) (let [[event ch] (alts! [remote view-events])
new-state (assoc state new-state (handle-event event @app-state)]
:grubs new-grubs (reset! app-state new-state)
:recipes new-recipes)] (when (= ch view-events)
(view/render-app new-state) (>! out event))
(recur new-state))) (recur)))
view/out) out))

View file

@ -5,9 +5,6 @@
(:require-macros [grub.macros :refer [log logs]] (:require-macros [grub.macros :refer [log logs]]
[cljs.core.async.macros :refer [go go-loop]])) [cljs.core.async.macros :refer [go go-loop]]))
(def add (chan))
(def out add)
(defn recipe-view [recipe owner] (defn recipe-view [recipe owner]
(reify (reify
om/IRender om/IRender
@ -76,9 +73,10 @@
[:input.grub-input {:type "text" :value grub}]]))))) [:input.grub-input {:type "text" :value grub}]])))))
(defn get-grub-ingredient [grub] (defn get-grub-ingredient [grub]
(let [text (clojure.string/lower-case (:grub grub)) (when-not (nil? (:grub grub))
match (re-find #"[a-z]{3}.*$" text)] (let [text (clojure.string/lower-case (:grub grub))
match)) match (re-find #"[a-z]{3}.*$" text)]
match)))
(defn sort-grubs [grubs] (defn sort-grubs [grubs]
(sort-by (juxt :completed get-grub-ingredient) (vals grubs))) (sort-by (juxt :completed get-grub-ingredient) (vals grubs)))
@ -89,23 +87,35 @@
:grub grub :grub grub
:completed false}) :completed false})
(defn add-grub [add owner] (defn add-grub [add {:keys [new-grub]} owner]
(let [new-grub (.-value (om/get-node owner :new-grub))] (logs "add-grub:" new-grub)
(when (not (empty? new-grub)) (when (not (empty? new-grub))
(put! add (add-grub-event new-grub))))) (let [new-grub-event (add-grub-event new-grub)]
(logs "put event:" new-grub-event)
(go (>! add new-grub-event))
(om/set-state! owner :new-grub ""))
;(put! add (add-grub-event new-grub))
))
(defn enter-pressed? [event] (defn enter-pressed? [event]
(let [enter-keycode 13] (let [enter-keycode 13]
(= (.-which event) enter-keycode))) (= (.-which event) enter-keycode)))
(defn add-grub-on-enter [add owner event] (defn add-grub-on-enter [event add state owner]
(when (enter-pressed? event) (when (enter-pressed? event)
(add-grub add owner))) (log "enter pressed:" (:new-grub state))
(add-grub add state owner)))
(defn handle-new-grub-change [e owner {:keys [new-grub]}]
(om/set-state! owner :new-grub (.. e -target -value)))
(defn grubs-view [grubs owner] (defn grubs-view [grubs owner]
(reify (reify
om/IRender om/IInitState
(render [this] (init-state [_]
{:new-grub ""})
om/IRenderState
(render-state [this state]
(let [add (:add (om/get-shared owner))] (let [add (:add (om/get-shared owner))]
(html (html
[:div [:div
@ -116,11 +126,12 @@
{:ref :new-grub {:ref :new-grub
:type "text" :type "text"
:placeholder "2 grubs" :placeholder "2 grubs"
:on-key-up #(add-grub-on-enter add owner %)}]] :on-key-up #(add-grub-on-enter % add state owner)
:on-change #(handle-new-grub-change % owner state)}]]
[:button.btn.btn-primary [:button.btn.btn-primary
{:id "add-grub-btn" {:id "add-grub-btn"
:type "button" :type "button"
:on-click #(add-grub add owner)} :on-click #(add-grub (:add (om/get-shared owner)) (:new-grub state) owner)}
"Add"]] "Add"]]
[:ul#grub-list.list-group [:ul#grub-list.list-group
(for [grub (sort-grubs grubs)] (for [grub (sort-grubs grubs)]
@ -142,7 +153,10 @@
(om/build recipes-view (:recipes state))]]])))) (om/build recipes-view (:recipes state))]]]))))
(defn render-app [state] (defn render-app [state]
(om/root app-view (let [out (chan)
state add out]
{:target (.getElementById js/document "container") (om/root app-view
:shared {:add add}})) state
{:target (.getElementById js/document "container")
:shared {:add add}})
out))