Permalink
Browse files

ported some things to defsc as an additional check

Took 29 minutes
  • Loading branch information...
awkay committed Dec 2, 2017
1 parent 0c5b6a1 commit 8dcd87d5a8567bf6cb76f255956e5a2b2615edeb
@@ -8,7 +8,7 @@
[fulcro.client.cards :refer [defcard-fulcro]]
[fulcro.client.mutations :as m :refer [defmutation]]
[fulcro.client.dom :as dom]
[fulcro.client.primitives :as prim :refer-macros [defui]]
[fulcro.client.primitives :as prim :refer [defsc]]
[fulcro.util :as util]
[fulcro.client.core :as fc]))
@@ -38,41 +38,37 @@
;; (def vline (js/React.createFactory js/Victory.VictoryLine))
;; " [ {:year 1991 :value 2345 } ...] "
(defui ^:once YearlyValueChart
Object
(render [this]
(let [{:keys [label
plot-data
x-step]} (prim/props this)
start-year (apply min (map :year plot-data))
end-year (apply max (map :year plot-data))
years (range start-year (inc end-year) x-step)
dates (clj->js (mapv #(new js/Date % 1 2) years))
{:keys [min-value
max-value]} (reduce (fn [{:keys [min-value max-value] :as acc}
{:keys [value] :as n}]
(assoc acc
:min-value (min min-value value)
:max-value (max max-value value)))
{}
plot-data)
min-value (int (* 0.8 min-value))
max-value (int (* 1.2 max-value))
points (clj->js (mapv (fn [{:keys [year value]}]
{:x (new js/Date year 1 2)
:y value})
plot-data))]
(vchart nil
(vaxis #js {:label label
:standalone false
:scale "time"
:tickFormat (fn [d] (.getFullYear d))
:tickValues dates})
(vaxis #js {:dependentAxis true
:standalone false
:tickFormat (fn [y] (us-dollars y))
:domain #js [min-value max-value]})
(vline #js {:data points})))))
(defsc YearlyValueChart [this {:keys [label plot-data x-step]}]
{}
(let [start-year (apply min (map :year plot-data))
end-year (apply max (map :year plot-data))
years (range start-year (inc end-year) x-step)
dates (clj->js (mapv #(new js/Date % 1 2) years))
{:keys [min-value
max-value]} (reduce (fn [{:keys [min-value max-value] :as acc}
{:keys [value] :as n}]
(assoc acc
:min-value (min min-value value)
:max-value (max max-value value)))
{}
plot-data)
min-value (int (* 0.8 min-value))
max-value (int (* 1.2 max-value))
points (clj->js (mapv (fn [{:keys [year value]}]
{:x (new js/Date year 1 2)
:y value})
plot-data))]
(vchart nil
(vaxis #js {:label label
:standalone false
:scale "time"
:tickFormat (fn [d] (.getFullYear d))
:tickValues dates})
(vaxis #js {:dependentAxis true
:standalone false
:tickFormat (fn [y] (us-dollars y))
:domain #js [min-value max-value]})
(vline #js {:data points}))))
(def yearly-value-chart (prim/factory YearlyValueChart))
@@ -127,14 +123,13 @@
(dc/mkdn-pprint-source vaxis)
(dc/mkdn-pprint-source vline)
"Next, lets build our `Om.next` component using `defui`:"
"Next, lets build our component using `defsc` (see M05-More-Concise-UI):"
(dc/mkdn-pprint-source YearlyValueChart)
"You will notice in the above code, that we convert relevant clojure datastructures to JS datastructures via
`clj->js`. This is important, because a JS library is going to expect that kind of data. Other than that,
the code is fairly straight forward. And the final product:"
)
the code is fairly straight forward. And the final product:")
(defcard sample-victory-chart
@@ -167,19 +162,15 @@
(def minion-image "https://s-media-cache-ak0.pinimg.com/736x/34/c2/f5/34c2f59284fcdff709217e14df2250a0--film-minions-minions-images.jpg")
(defui ^:once ICRoot
static prim/InitialAppState
(initial-state [c p] {:ctool (prim/get-initial-state ct/ClipTool {:id :clipper :aspect-ratio 0.5
:image-url minion-image})})
static prim/IQuery
(query [this] [:ui/react-key :ctool])
Object
(render [this]
(let [{:keys [ui/react-key ctool]} (prim/props this)]
(dom/div #js {:key react-key}
(ct/ui-clip-tool (prim/computed ctool {:onChange (fn [props] (prim/set-state! this props))}))
(ct/ui-preview-clip (merge (prim/get-state this) {:filename "minions.jpg"
:width 100 :height 200}))))))
(defsc ICRoot [this {:keys [ui/react-key ctool]}]
{:initial-state
(fn [p] {:ctool (prim/get-initial-state ct/ClipTool {:id :clipper :aspect-ratio 0.5
:image-url minion-image})})
:query [:ui/react-key :ctool]}
(dom/div #js {:key react-key}
(ct/ui-clip-tool (prim/computed ctool {:onChange (fn [props] (prim/set-state! this props))}))
(ct/ui-preview-clip (merge (prim/get-state this) {:filename "minions.jpg"
:width 100 :height 200}))))
(defcard-doc
"
@@ -235,58 +226,39 @@
(action [{:keys [state]}]
(swap! state update-in [:child/by-id id :n] dec)))
(defui ^:once ListItem
static prim/InitialAppState
(initial-state [c {:keys [id n]}] {:id id :n n})
static prim/IQuery
(query [this] [:id :n])
static prim/Ident
(ident [this props] [:child/by-id (:id props)])
Object
(render [this]
(let [{:keys [id n]} (prim/props this)]
(dom/li #js {:className "item"}
(dom/span nil "n: " n)
(dom/button #js {:onClick #(prim/transact! this `[(bump-up {:id ~id})])} "Increment")
(dom/button #js {:onClick #(prim/transact! this `[(bump-down {:id ~id})])} "Decrement")))))
(defsc ListItem [this {:keys [id n]}]
{:initial-state {:id :param/id :n :param/n}
:query [:id :n]
:ident [:child/by-id :id]}
(dom/li #js {:className "item"}
(dom/span nil "n: " n)
(dom/button #js {:onClick #(prim/transact! this `[(bump-up {:id ~id})])} "Increment")
(dom/button #js {:onClick #(prim/transact! this `[(bump-down {:id ~id})])} "Decrement")))
(def ui-list-item (prim/factory ListItem {:keyfn :id}))
(defui ^:once ItemList
static prim/InitialAppState
(initial-state [c p] {:id 1 :title "My List" :min 1 :max 1000 :items [(prim/get-initial-state ListItem {:id 1 :n 2})
(prim/get-initial-state ListItem {:id 2 :n 5})
(prim/get-initial-state ListItem {:id 3 :n 7})]})
static prim/IQuery
(query [this] [:id :title :max :min {:items (prim/get-query ListItem)}])
static prim/Ident
(ident [this props] [:list/by-id (:id props)])
Object
(render [this]
(let [{:keys [title min max items] :or {min 0 max 1000000}} (prim/props this)]
(dom/div #js {:style {:float "left" :width "300px"}}
(dom/h4 nil (str title (when (= 0 min) (str " (n <= " max ")"))))
(dom/ul nil (->> items
(filter (fn [{:keys [n]}] (<= min n max)))
(map ui-list-item)))))))
(defsc ItemList [this {:keys [title min max items] :or {min 0 max 1000000}}]
{:initial-state {:id 1 :title "My List" :min 1 :max 1000 :items [{:id 1 :n 2} {:id 2 :n 5} {:id 3 :n 7}]}
:query [:id :title :max :min {:items (prim/get-query ListItem)}]
:ident [:list/by-id :id]}
(dom/div #js {:style {:float "left" :width "300px"}}
(dom/h4 nil (str title (when (= 0 min) (str " (n <= " max ")"))))
(dom/ul nil (->> items
(filter (fn [{:keys [n]}] (<= min n max)))
(map ui-list-item)))))
(def ui-list (prim/factory ItemList {:keyfn :id}))
(defui ^:once SDRoot
static prim/InitialAppState
(initial-state [c p] {:lists [(prim/get-initial-state ItemList {})]})
static prim/IQuery
(query [this] [:ui/react-key {:lists (prim/get-query ItemList)}])
Object
(render [this]
(let [{:keys [ui/react-key lists]} (prim/props this)]
(dom/div nil
(dom/style #js {} ".item {font-size: 40pt}")
(ele/ui-shadow-dom {:open-boundary? false}
(dom/div #js {:key react-key}
(dom/style #js {} ".item {color: red}")
(map ui-list lists)))
(dom/div #js {:className "item"} "sibling")))))
(defsc SDRoot [this {:keys [ui/react-key lists]}]
{:initial-state {:lists [{}]}
:query [:ui/react-key {:lists (prim/get-query ItemList)}]}
(dom/div nil
(dom/style #js {} ".item {font-size: 40pt}")
(ele/ui-shadow-dom {:open-boundary? false}
(dom/div #js {:key react-key}
(dom/style #js {} ".item {color: red}")
(map ui-list lists)))
(dom/div #js {:className "item"} "sibling")))
(defcard-fulcro shadow-dom
"This card is running with shadow dom. There is a top-level CSS style to set the font size
@@ -5,61 +5,38 @@
[fulcro.client.core :as fc]
[fulcro.client.cards :refer [defcard-fulcro]]
[fulcro.client.data-fetch :as df]
[fulcro.client.primitives :as prim :refer [defui defsc InitialAppState initial-state]]
[fulcro.client.primitives :as prim :refer [defsc InitialAppState initial-state]]
[fulcro.client.mutations :as m]))
(prim/defui ^:once Main
static prim/InitialAppState
(initial-state [clz params] {:page :main :label "MAIN"})
static prim/IQuery
(query [this] [:page :label])
Object
(render [this]
(let [{:keys [label]} (prim/props this)]
(dom/div #js {:style #js {:backgroundColor "red"}}
label))))
(prim/defui ^:once Login
static prim/InitialAppState
(initial-state [clz params] {:page :login :label "LOGIN"})
static prim/IQuery
(query [this] [:page :label])
Object
(render [this]
(let [{:keys [label]} (prim/props this)]
(dom/div #js {:style #js {:backgroundColor "green"}}
label))))
(prim/defui ^:once NewUser
static prim/InitialAppState
(initial-state [clz params] {:page :new-user :label "New User"})
static prim/IQuery
(query [this] [:page :label])
Object
(render [this]
(let [{:keys [label]} (prim/props this)]
(dom/div #js {:style #js {:backgroundColor "skyblue"}}
label))))
(prim/defui ^:once StatusReport
static prim/InitialAppState
(initial-state [clz params] {:id :a :page :status-report})
static prim/IQuery
(query [this] [:id :page :label])
Object
(render [this] (let [{:keys [id]} (prim/props this)]
(dom/div #js {:style #js {:backgroundColor "yellow"}}
(dom/div nil (str "Status " id))))))
(prim/defui ^:once GraphingReport
static prim/InitialAppState
(initial-state [clz params] {:id :a :page :graphing-report})
static prim/IQuery
(query [this] [:id :page :label]) ; make sure you query for everything need by the router's ident function!
Object
(render [this] (let [{:keys [id]} (prim/props this)]
(dom/div #js {:style #js {:backgroundColor "orange"}}
(dom/div nil (str "Graph " id))))))
(defsc Main [this {:keys [label]}]
{:initial-state {:page :main :label "MAIN"}
:query [:page :label]}
(dom/div #js {:style #js {:backgroundColor "red"}}
label))
(defsc Login [this {:keys [label]}]
{:initial-state {:page :login :label "LOGIN"}
:query [:page :label]}
(dom/div #js {:style #js {:backgroundColor "green"}}
label))
(defsc NewUser [this {:keys [label]}]
{:initial-state {:page :new-user :label "New User"}
:query [:page :label]}
(dom/div #js {:style #js {:backgroundColor "skyblue"}}
label))
(defsc StatusReport [this {:keys [id]}]
{:initial-state {:id :a :page :status-report}
:query [:id :page :label]}
(dom/div #js {:style #js {:backgroundColor "yellow"}}
(dom/div nil (str "Status " id))))
(defsc GraphingReport [this {:keys [id]}]
{:initial-state {:id :a :page :graphing-report}
:query [:id :page :label]} ; make sure you query for everything need by the router's ident function!
(dom/div #js {:style #js {:backgroundColor "orange"}}
(dom/div nil (str "Graph " id))))
(defrouter ReportRouter :report-router
; This router expects numerous possible status and graph reports. The :id in the props of the report will determine
@@ -73,20 +50,15 @@
(def ui-report-router (prim/factory ReportRouter))
; BIG GOTCHA: Make sure you query for the prop (in this case :page) that the union needs in order to decide. It won't pull it itself!
(prim/defui ^:once ReportsMain
static prim/InitialAppState
(defsc ReportsMain [this {:keys [report-router]}]
; nest the router under any arbitrary key, just be consistent in your query and props extraction.
(initial-state [clz params] {:page :report :report-router (prim/get-initial-state ReportRouter {})})
static prim/IQuery
(query [this] [:page {:report-router (prim/get-query ReportRouter)}])
Object
(render [this]
(dom/div #js {:style #js {:backgroundColor "grey"}}
; Screen-specific content to be shown "around" or "above" the subscreen
"REPORT MAIN SCREEN"
; Render the sub-router. You can also def a factory for the router (e.g. ui-report-router)
(ui-report-router (:report-router (prim/props this))))))
{:initial-state {:page :report :report-router {}}
:query [:page {:report-router (prim/get-query ReportRouter)}]}
(dom/div #js {:style #js {:backgroundColor "grey"}}
; Screen-specific content to be shown "around" or "above" the subscreen
"REPORT MAIN SCREEN"
; Render the sub-router. You can also def a factory for the router (e.g. ui-report-router)
(ui-report-router report-router)))
(defrouter TopRouter :top-router
(ident [this props] [(:page props) :top])
@@ -115,24 +87,19 @@
(r/make-route :status [(r/router-instruction :top-router [:report :top])
(r/router-instruction :report-router [:status-report :param/report-id])])))
(prim/defui ^:once Root
static prim/InitialAppState
(defsc Root [this {:keys [ui/react-key top-router]}]
; r/routing-tree-key implies the alias of fulcro.client.routing as r.
(initial-state [clz params] (merge routing-tree
{:top-router (prim/get-initial-state TopRouter {})}))
static prim/IQuery
(query [this] [:ui/react-key {:top-router (prim/get-query TopRouter)}])
Object
(render [this]
(let [{:keys [ui/react-key top-router]} (prim/props this)]
(dom/div #js {:key react-key}
; Sample nav mutations
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :main})])} "Main") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :new-user})])} "New User") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :login})])} "Login") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :status :route-params {:report-id :a}})])} "Status A") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :graph :route-params {:report-id :a}})])} "Graph A")
(ui-top top-router)))))
{:initial-state (fn [params] (merge routing-tree
{:top-router (prim/get-initial-state TopRouter {})}))
:query [:ui/react-key {:top-router (prim/get-query TopRouter)}]}
(dom/div #js {:key react-key}
; Sample nav mutations
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :main})])} "Main") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :new-user})])} "New User") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :login})])} "Login") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :status :route-params {:report-id :a}})])} "Status A") " | "
(dom/a #js {:onClick #(prim/transact! this `[(r/route-to {:handler :graph :route-params {:report-id :a}})])} "Graph A")
(ui-top top-router)))
(defcard-fulcro router-demo
"# Router Demo
Oops, something went wrong.

0 comments on commit 8dcd87d

Please sign in to comment.