Use state machine for new recipes

This commit is contained in:
Nicholas Kariniemi 2014-08-06 00:09:25 +03:00
parent 00efd3d53a
commit 0db764b145

View file

@ -14,77 +14,69 @@
(not (empty? grubs)))
(om/set-state! owner :new-recipe-name "")
(om/set-state! owner :new-recipe-grubs "")
(om/set-state! owner :editing false)
(put! ch (recipe/add-event name grubs))))
(def transitions
{:waiting {:click :editing}
:editing {:body-mousedown :waiting
:save :waiting}})
(defn transition-state [owner event]
(let [current (om/get-state owner :edit-state)
next (or (get-in transitions [current event]) current)]
(condp = [current event next]
[:editing :save :waiting] (let [add-ch (om/get-shared owner :recipe-add)
name (om/get-state owner :new-recipe-name)
grubs (om/get-state owner :new-recipe-grubs)]
(add-recipe add-ch name grubs owner))
nil)
(om/set-state! owner :edit-state next)))
(defn new-recipe-view [_ owner]
(reify
om/IInitState
(init-state [_]
(let [publisher (chan)]
{:editing false
:>local-events publisher
:<local-events (a/pub publisher identity)
{:edit-state :waiting
:new-recipe-name ""
:new-recipe-grubs ""}))
om/IRenderState
(render-state [this {:keys [editing >local-events new-recipe-name new-recipe-grubs]}]
(let [add (om/get-shared owner :recipe-add)]
(html
[:div.panel.panel-default.recipe-panel
{:on-click #(put! >local-events :click)}
[:div.panel-heading.recipe-header
[:input.form-control.recipe-header-input
{:id "new-recipe-name"
:type "text"
:placeholder "New recipe"
:value new-recipe-name
:on-change #(om/set-state! owner :new-recipe-name (dom/event-val %))}]]
[:div.panel-body.recipe-grubs
{:class (when (not editing) "hidden")}
[:textarea.form-control.recipe-grubs-input
{:id "new-recipe-grubs"
:rows 3
:placeholder "Recipe ingredients"
:value new-recipe-grubs
:on-change #(om/set-state! owner :new-recipe-grubs (dom/event-val %))}]
[:button.btn.btn-primary.pull-right.recipe-btn.recipe-done-btn
{:type "button"
:on-click #(put! >local-events :done)}
"Done"]]])))
(render-state [this {:keys [edit-state new-recipe-name new-recipe-grubs]}]
(html
[:div.panel.panel-default.recipe-panel
{:on-click #(when (not (dom/click-on-elem? % (om/get-node owner :save-btn)))
(transition-state owner :click))}
[:div.panel-heading.recipe-header
[:input.form-control.recipe-header-input
{:id "new-recipe-name"
:type "text"
:placeholder "New recipe"
:value new-recipe-name
:on-change #(om/set-state! owner :new-recipe-name (dom/event-val %))}]]
[:div.panel-body.recipe-grubs
{:class (when (= edit-state :waiting) "hidden")}
[:textarea.form-control.recipe-grubs-input
{:id "new-recipe-grubs"
:rows 3
:placeholder "Recipe ingredients"
:value new-recipe-grubs
:on-change #(om/set-state! owner :new-recipe-grubs (dom/event-val %))}]
[:button.btn.btn-primary.pull-right.recipe-btn.recipe-done-btn
{:type "button"
:ref :save-btn
:on-click #(transition-state owner :save)}
"Save"]]]))
om/IWillMount
(will-mount [_]
(let [<local-events (om/get-state owner :<local-events)
<events (om/get-shared owner :<events)
add (om/get-shared owner :recipe-add)
]
(go-loop []
(let [subscriber (chan)]
(a/sub <local-events :click subscriber)
(<! subscriber)
(a/unsub <local-events :click subscriber)
(a/close! subscriber))
(om/set-state! owner :editing true)
(let [subscriber (chan)]
(a/sub <events :body-mousedown subscriber)
(a/sub <local-events :done subscriber)
(loop []
(let [event (<! subscriber)]
(if-not (and (= (:type event) :body-mousedown)
(dom/click-on-self? (:event event) (om/get-node owner)))
(when (= event :done)
(add-recipe add
(om/get-state owner :new-recipe-name)
(om/get-state owner :new-recipe-grubs)
owner))
(recur))))
(a/unsub <events :body-mousedown subscriber)
(a/unsub <local-events :done subscriber)
(a/close! subscriber))
(om/set-state! owner :editing false)
(recur))))))
(let [<events (om/get-shared owner :<events)
subscriber (chan)]
(a/sub <events :body-mousedown subscriber)
(go-loop [] (let [event (<! subscriber)]
(when-not (dom/click-on-self? (:event event) (om/get-node owner))
(transition-state owner :body-mousedown))
(recur)))))))
(defn view [recipes owner]
(reify