Created
January 12, 2016 21:03
-
-
Save anmonteiro/72ec13f94446936edb09 to your computer and use it in GitHub Desktop.
Composite with mutations & path optimization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(def composite-data | |
{:composite/item {:id 0 | |
:width 400 | |
:height 400 | |
:color "#428BCA" | |
:value 0 | |
:children [{:id 1 | |
:width 200 | |
:height 200 | |
:color "#9ACD32" | |
:value 0 | |
:children [{:id 3 | |
:width 100 | |
:height 100 | |
:color "#CD329A" | |
:value 0} | |
{:id 4 | |
:width 100 | |
:height 100 | |
:color "#32CD65" | |
:value 0}]} | |
{:id 2 | |
:width 200 | |
:height 200 | |
:color "#39DBBE" | |
:value 0}]}}) | |
(declare component) | |
(defn display-id [this] | |
(let [{:keys [id value children]} (om/props this) | |
type (if children :composite :leaf)] | |
(dom/div #js {:style #js {:position "absolute" | |
:textAlign "right" | |
:bottom 0 | |
:zIndex 1 | |
:right 5}} | |
(dom/span nil | |
(str "id: "id " value: " value) | |
(dom/button #js {:onClick #(om/transact! this | |
`[(comp/inc ~{:id id :type type})])} | |
"+"))))) | |
(defn common-div [this props & children] | |
(let [{:keys [id width height color value]} props] | |
(dom/div #js {:className (str id) | |
:style | |
#js {:position "relative" | |
:float "left" | |
:width width | |
:height height | |
:zIndex 2 | |
:textAlign "center" | |
:backgroundColor color}} | |
children | |
(display-id this)))) | |
(defui Composite | |
static om/Ident | |
(ident [this {:keys [id children]}] | |
(if-not (nil? children) | |
[:composite id] | |
[:leaf id])) | |
static om/IQuery | |
(query [this] | |
'[:id :width :height :color :value {:children ...}]) | |
Object | |
(render [this] | |
(let [{:keys [children] :as props} (om/props this)] | |
(common-div this props (map component children))))) | |
(def composite (om/factory Composite)) | |
(defui Leaf | |
static om/Ident | |
(ident [this {:keys [id children]}] | |
(if-not (nil? children) | |
[:composite id] | |
[:leaf id])) | |
static om/IQuery | |
(query [this] | |
'[:id :width :height :color :value]) | |
Object | |
(render [this] | |
(common-div this (om/props this)))) | |
(def leaf (om/factory Leaf)) | |
(defui Component | |
static om/Ident | |
(ident [this {:keys [id children]}] | |
(if-not (nil? children) | |
[:composite id] | |
[:leaf id])) | |
static om/IQuery | |
(query [this] | |
{:leaf (om/get-query Leaf) | |
:composite (om/get-query Composite)}) | |
Object | |
(render [this] | |
(let [{:keys [id] :as props} (om/props this) | |
[type id] (om/get-ident this)] | |
(({:composite composite | |
:leaf leaf} type) props)))) | |
(def component (om/factory Component)) | |
(defui CompositeApp | |
static om/IQuery | |
(query [this] | |
[{:composite/item (om/get-query Component)}]) | |
Object | |
(render [this] | |
(let [{:keys [composite/item]} (om/props this)] | |
(dom/div #js {:style #js {:margin "0 auto" | |
:display "table"}} | |
(component item) | |
(dom/div #js {:style #js {:clear "both"}}))))) | |
(defmulti composite-read | |
(fn [{:keys [ast]} k _] | |
;(println k ast) | |
k)) ;; DEBUG | |
(defmethod composite-read :default | |
[{:keys [data] :as env} k _] | |
{:value (get data k)}) | |
(defmethod composite-read :children | |
[{:keys [parser data union-query state] :as env} k _] | |
(let [st @state | |
f #(parser (assoc env :data (get-in st %)) ((first %) union-query))] | |
{:value (into [] (map f) (:children data))})) | |
(defmethod composite-read :leaf | |
[{:keys [state query query-root] :as env} k _] | |
{:value (om/db->tree query query-root @state)}) | |
(defmethod composite-read :composite | |
[{:keys [state query query-root] :as env} k _] | |
{:value (om/db->tree (:composite query) query-root @state)}) | |
(defmethod composite-read :composite/item | |
[{:keys [state parser query ast] :as env} k _] | |
(println "query " query) | |
(let [st @state | |
[type id :as entry] (get st k) | |
data (get-in st entry) | |
new-env (assoc env :data data :union-query query)] | |
{:value (parser new-env (type query))})) | |
(defmulti composite-mutate om/dispatch) | |
(defmethod composite-mutate 'comp/inc | |
[{:keys [state]} k {:keys [id type]}] | |
{:action #(swap! state update-in [type id :value] inc)}) | |
(def composite-reconciler | |
(om/reconciler {:state composite-data | |
:parser (om/parser {:read composite-read :mutate composite-mutate}) | |
:pathopt true})) | |
(om/add-root! composite-reconciler CompositeApp (js/document.getElementById "app")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment