Commit changes

This commit is contained in:
Daniel Compton 2016-11-15 15:06:10 +13:00
parent c6384dcd74
commit 6b8b961d13
5 changed files with 259 additions and 572 deletions

View File

@ -11,7 +11,10 @@
[reagent.ratom :as ratom] [reagent.ratom :as ratom]
[re-frame.utils :as rutils] [re-frame.utils :as rutils]
[goog.object :as gob] [goog.object :as gob]
[re-frame.interop :as interop])) [re-frame.interop :as interop]
[devtools.formatters.core :as devtools]
))
(defn comp-name [c] (defn comp-name [c]
(let [n (or (component/component-path c) (let [n (or (component/component-path c)
@ -72,7 +75,8 @@
(fn [] (this-as c (fn [] (this-as c
(trace/with-trace {:op-type key (trace/with-trace {:op-type key
:operation (last (str/split (comp-name c) #" > ")) :operation (last (str/split (comp-name c) #" > "))
:tags {:component-path (reagent.impl.component/component-path c)}}) :tags {:component-path (reagent.impl.component/component-path c)
:reaction (rutils/reagent-id ($ c :cljsRatom))}})
(.call (real-custom-wrapper key f) c c))) (.call (real-custom-wrapper key f) c c)))
(real-custom-wrapper key f)))) (real-custom-wrapper key f))))
@ -151,7 +155,9 @@
[:tbody [:tbody
(doall (doall
(for [{:keys [type id operation tags duration] :as trace} showing-traces] (for [{:keys [type id operation tags duration] :as trace} showing-traces]
(let [row-style (merge padding {:border-top (case type :event "1px solid lightgrey" nil)})] (let [row-style (merge padding {:border-top (case type :event "1px solid lightgrey" nil)})
_ (js/console.log (devtools/header-api-call tags))
]
(list [:tr {:key id (list [:tr {:key id
:style {:color (case type :style {:color (case type
:sub/create "green" :sub/create "green"
@ -169,7 +175,8 @@
(.toFixed duration 1) " ms"]] (.toFixed duration 1) " ms"]]
(when true (when true
[:tr {:key (str id "-details")} [:tr {:key (str id "-details")}
[:td {:col-span 3} (with-out-str (pprint/pprint (dissoc tags :query-v :event :duration)))]])))))]]])))) [:td {:col-span 3} (with-out-str (pprint/pprint (dissoc tags :query-v :event :duration)))]])
))))]]]))))
(defn resizer-style [draggable-area] (defn resizer-style [draggable-area]
{:position "absolute" :z-index 2 :opacity 0 {:position "absolute" :z-index 2 :opacity 0

View File

@ -1,110 +1,37 @@
(ns day8.re-frame.trace.d3 (ns day8.re-frame.trace.d3
(:require [reagent.core :as r])) (:require [reagent.core :as r]))
(defn component-did-update [{:keys [d3-enter d3-update d3-exit]} ratoms]
(apply d3-enter ratoms)
(apply d3-update ratoms)
(apply d3-exit ratoms))
(defn component-did-mount [{:keys [d3-did-mount] :as lifecycle-fns} ratoms]
(apply d3-did-mount ratoms)
(component-did-update lifecycle-fns ratoms))
(defn no-op [desc] (defn no-op [desc]
(fn [& args] (fn [& args] nil))
(println "No-op" desc)))
(defn component-did-update [{:keys [d3-update]} ratoms]
(apply d3-update ratoms))
(defn component-did-mount [{:keys [d3-once] :as lifecycle-fns} ratoms]
(apply d3-once ratoms)
(component-did-update lifecycle-fns ratoms))
(defn create-d3 (defn create-d3
"Creates a bridging component from Reagent to D3. Takes a map of "Creates a bridging component from Reagent to D3. Takes a map of
lifecycle functions, and reactive data sources. lifecycle functions, and reactive data sources.
:render-component - Render the outer Reagent component, and a place for your D3 component to mount to (probably an SVG element) :render-component - Render the outer Reagent component, and a place for your D3 component to mount to (probably an SVG element)
:d3-did-mount - Function called after the component has been rendered, for you to setup anything you need in D3 (e.g. adding <g> or classes) :d3-once - Function called after the component has been rendered, for you to setup anything you need in D3 (e.g. adding <g> or classes)
:d3-enter, :d3-update, :d3-exit - correspond to functions in the D3 general update pattern: https://bl.ocks.org/mbostock/3808218 :d3-update - Run the D3 general update pattern: https://bl.ocks.org/mbostock/3808218
" "
[{:keys [render-component d3-did-mount d3-enter d3-update d3-exit] [{:keys [render-component d3-once d3-update]
:or {render-component no-op :or {render-component (no-op :render)
d3-did-mount (no-op :d3-did-mount) d3-once (no-op :d3-did-mount)
d3-enter (no-op :d3-enter) d3-update (no-op :d3-update)}}
d3-update (no-op :d3-update)
d3-exit (no-op :d3-exit)}}
& ratoms] & ratoms]
(let [lifecycle-fns {:render-component render-component (let [lifecycle-fns {:render-component render-component
:d3-did-mount d3-did-mount :d3-once d3-once
:d3-enter d3-enter :d3-update d3-update}]
:d3-update d3-update
:d3-exit d3-exit}]
(r/create-class (r/create-class
{:reagent-render (fn [] {:reagent-render (fn []
(doseq [r ratoms] (deref r)) (doseq [r ratoms] (deref r))
(apply render-component ratoms)) (apply render-component ratoms))
:component-did-mount (fn [this] (component-did-mount lifecycle-fns ratoms)) :component-did-mount (fn [this]
:component-did-update (fn [this old-argv] (component-did-update lifecycle-fns ratoms))})) (component-did-mount lifecycle-fns ratoms))
) :component-did-update (fn [this old-argv]
(component-did-update lifecycle-fns ratoms))})))
;;;;
;;;;
;;; app
;
;
;(def data (r/atom {}))
;
;(defn my-render [ratom]
; (let [width 100
; height 100]
; [:div
; {:id "barchart"}
; [:svg
; {:width width
; :height height}]]))
;
;(defn bars-did-mount [ratom]
; (-> (js/d3.select "#barchart svg")
; (.append "g")
; (.attr "class" "container")
; (.append "g")
; (.attr "class" "bars")))
;
;(defn bars-enter [ratom]
; (let [data (get-data ratom)]
; (-> (js/d3.select "#barchart svg .container .bars")
; (.selectAll "rect")
; (.data (clj->js data))
; .enter
; (.append "rect"))))
;
;(defn bars-update [ratom]
; (let [width (get-width ratom)
; height (get-height ratom)
; data (get-data ratom)
; data-n (count data)
; rect-height (/ height data-n)
; x-scale (-> js/d3
; .scaleLinear
; (.domain #js [0 5])
; (.range #js [0 width]))]
; (-> (js/d3.select "#barchart svg .container .bars")
; (.selectAll "rect")
; (.data (clj->js data))
; (.attr "fill" "green")
; (.attr "x" (x-scale 0))
; (.attr "y" (fn [_ i]
; (* i rect-height)))
; (.attr "height" (- rect-height 1))
; (.attr "width" (fn [d]
; (x-scale (aget d "x")))))))
;
;(defn bars-exit [ratom]
; (let [data (get-data ratom)]
; (-> (js/d3.select "#barchart svg .container .bars")
; (.selectAll "rect")
; (.data (clj->js data))
; .exit
; .remove)))
;
;(create-d3 data {:reagent-render my-render
; :d3-did-mount bars-did-mount
; :d3-enter bars-enter
; :d3-update bars-update
; :d3-exit bars-exit})

View File

@ -0,0 +1,86 @@
(ns day8.re-frame.trace.graph
(:require [clojure.set :as set]))
(defn select-type [type traces]
(filter #(= type (:type %)) traces))
(defn get-reaction [trace]
(get-in trace [:tags :reaction]))
(defn distinct-k
"Returns a lazy sequence of the elements of coll with duplicates removed."
([key-fn coll]
(let [step (fn step [xs seen]
(lazy-seq
((fn [[f :as xs] seen]
(when-let [s (seq xs)]
(let [f-fn (key-fn f)]
(if (contains? seen f-fn)
(recur (rest s) seen)
(cons f (step (rest s) (conj seen f-fn)))))))
xs seen)))]
(step coll #{}))))
(defn select-links [traces type disposed-ids link-val]
(->> traces
(select-type type)
(remove #(contains? disposed-ids (get-reaction %)))
(mapcat (fn [trace]
(for [input-signal (get-in trace [:tags :input-signals])
:let [reaction (get-reaction trace)]
:when (every? some? [input-signal reaction])]
{:source input-signal :target reaction :value link-val
:id (str input-signal "|" reaction)})))
(into {} (map (fn [trace] [(:id trace) trace])))
(vals)))
(defn select-sub-nodes [traces type disposed-ids r]
(->> traces
(select-type type)
(remove #(contains? disposed-ids (get-reaction %)))
(remove #(get-in % [:tags :cached?]))
(map (fn [trace]
{:id (get-reaction trace)
:title (str (:operation trace))
:group 2
:r r
:data trace}))
(into {} (map (fn [trace] [(:id trace) trace])))
(vals)))
(defn select-view-nodes [traces type unmounted-components r]
(->> traces
(select-type type)
(remove #(contains? unmounted-components (:id %)))
(map (fn [trace]
{:id (get-reaction trace)
:title (str (get-reaction trace) " " (:operation trace))
:group 3
:r r
:data trace
:fx 250}))
(remove #(nil? (:id %))) ;; remove reactions that are null (mostly from input fields???)
(into {} (map (fn [trace] [(:id trace) trace])))
(vals)
))
(defn trace->sub-graph [traces extra-nodes]
(let [disposed-ids (->> (select-type :sub/dispose traces)
(map get-reaction)
set)
unmounted-components (->> (select-type :componentWillUnmount traces)
(map get-reaction)
set)
sub-nodes (select-sub-nodes traces :sub/create disposed-ids 10)
view-nodes (select-view-nodes traces :render unmounted-components 5)
sub-links (select-links traces :sub/run disposed-ids 1)
view-links (select-links traces :render unmounted-components 0.5)
all-nodes (concat extra-nodes sub-nodes view-nodes)
node-ids (set (map :id all-nodes))
nodes-links (->> (mapcat (fn [{:keys [source target]}] [source target]) view-links) set)
missing-nodes (set/difference nodes-links node-ids) ;; These are local ratoms
view-links (->> view-links
(remove #(get missing-nodes (:source %))))
all-links (concat sub-links view-links)]
{:nodes all-nodes
:links all-links}))

View File

@ -1,6 +1,7 @@
(ns day8.re-frame.trace.subvis (ns day8.re-frame.trace.subvis
(:require cljsjs.d3 (:require cljsjs.d3
[day8.re-frame.trace.d3 :as d3t] [day8.re-frame.trace.d3 :as d3t]
[day8.re-frame.trace.graph :as graph]
[reagent.core :as r] [reagent.core :as r]
[re-frame.utils :as rutils] [re-frame.utils :as rutils]
[re-frame.db :as db] [re-frame.db :as db]
@ -8,80 +9,20 @@
[clojure.set :as set])) [clojure.set :as set]))
(def width 400) (def width 400)
(def height 200) (def height 400)
(def mygraph (r/atom {:nodes [{:id 1 :group 1} (def mygraph (r/atom {:nodes [{:id 1 :group 1}
{:id 2 :group 1} {:id 2 :group 1}
{:id 3 :group 2}] {:id 3 :group 2}]
:links [{:source 1 :target 2 :value 1}]})) :links [{:source 1 :target 2 :value 1}]}))
(defn trace->sub-graph [traces] (def app-db-node {:id (rutils/reagent-id db/app-db)
(let [disposed (->> traces :title "app-db"
(filter #(#{:sub/dispose} (:type %))) :group 1
(map #(get-in % [:tags :reaction])) :r 20
set) :fx 15
sub-nodes (->> traces :fy (/ height 2)})
(filter #(#{:sub/create} (:type %)))
(remove #(contains? disposed (get-in % [:tags :reaction])))
(remove #(get-in % [:tags :cached?]))
(map (fn [trace]
{:id (get-in trace [:tags :reaction])
:title (str (:operation trace))
:group (mod (:id trace) 20)
:r 10
:data trace})))
unmounted-components #{}
view-nodes (->> traces
(filter #(#{:render} (:type %)))
(remove #(contains? unmounted-components (:id %))) ;; todo
(map (fn [trace]
{:id (get-in trace [:tags :reaction])
:title (:operation trace)
:group (mod (:id trace) 20)
:r 5
:data trace}))
)
sub-links (->> traces
(filter #(#{:sub/run} (:type %)))
(remove #(contains? disposed (get-in % [:tags :reaction])))
(mapcat (fn [trace]
(for [input-signal (get-in trace [:tags :input-signals])
:let [reaction (get-in trace [:tags :reaction])]
:when (every? some? [input-signal reaction])]
{:source input-signal :target reaction :value 1}))))
view-links (->> traces
(filter #(#{:render} (:type %)))
(remove #(contains? unmounted-components (get-in % [:tags :reaction])))
(mapcat (fn [trace]
(for [input-signal (get-in trace [:tags :input-signals])
:let [reaction (get-in trace [:tags :reaction])]
:when (every? some? [input-signal reaction])]
{:source input-signal :target reaction :value 0.5}))))
app-db {:id (rutils/reagent-id db/app-db)
:title "app-db"
:group 1
:r 20
:fx (/ width 2)
:fy 30}
all-nodes (concat sub-nodes [app-db] view-nodes)
node-ids (set (map :id all-nodes))
nodes-links (->> (mapcat (fn [{:keys [source target]}] [source target]) view-links)
set)
missing-nodes (set/difference nodes-links node-ids) ;; These are local ratoms
view-links (->> view-links
(remove #(get missing-nodes (:source %))))
]
{:nodes all-nodes
:links (concat sub-links view-links)}))
(defn min-max (defn min-max
"Returns x if it is within min-val and max-val "Returns x if it is within min-val and max-val
@ -93,267 +34,76 @@
(assert (<= min-val max-val)) (assert (<= min-val max-val))
(cljs.core/max min-val (cljs.core/min x max-val))) (cljs.core/max min-val (cljs.core/min x max-val)))
(defn force-inner [graph]
(r/create-class
{:reagent-render (fn [] [:div [:svg {:width width :height height}]])
:component-did-mount (fn [] (defn ticked [selector]
(let [nodes (clj->js (:nodes graph))
links (clj->js (:links graph))
color (.scaleOrdinal js/d3 (.-schemeCategory20 js/d3))
svg (. js/d3 select "svg")
simulation (.. js/d3
(forceSimulation)
(force "link" (.. js/d3 (forceLink)
(id #(.-id %))
(distance (constantly 100))))
(force "charge" (.. js/d3 (forceManyBody)
(strength (constantly -100))))
(force "center" (. js/d3 forceCenter (/ width 2) (/ height 2))))
dragstarted (fn [d]
(when (zero? (.. js/d3 -event -active))
(.. simulation
(alphaTarget 0.3)
(restart)))
(set! (.-fx d) (.-x d))
(set! (.-fy d) (.-y d)))
dragged (fn [d]
(set! (.-fx d) (.. js/d3 -event -x))
(set! (.-fy d) (.. js/d3 -event -y)))
dragended (fn [d]
(when (zero? (.. js/d3 -event -active))
(.. simulation
(alphaTarget 0.0)))
(set! (.-fx d) nil)
(set! (.-fy d) nil))
link (.. (. svg append "g")
(attr "class" "links")
(selectAll "line")
(data links)
(enter)
(append "line")
(attr "stroke-width" (fn [d] (Math/sqrt (.-value d)))))
node (.. (. svg append "g")
(attr "class" "nodes")
(selectAll "circle")
(data nodes)
(enter)
(append "g")
(attr "class" "node"))
circle (.. node
(append "circle")
(attr "r" #(or (gob/get % "r" 10)))
(attr "fill" (fn [d] (color (.-group d))))
(call (.. (. js/d3 drag)
(on "start" dragstarted)
(on "drag" dragged)
(on "end" dragended))))
label (.. node
(append "text")
(attr "dy" ".35em")
(text #(gob/get % "title" "")))
ticked (fn []
(.. link
(attr "x1" (fn [d] (.. d -source -x)))
(attr "y1" (fn [d] (.. d -source -y)))
(attr "x2" (fn [d] (.. d -target -x)))
(attr "y2" (fn [d] (.. d -target -y))))
(.. circle
(attr "cx" (fn [d] (min-max (.. d -r) (.. d -x) (- width (.. d -r)))))
(attr "cy" (fn [d] (min-max (.. d -r) (.. d -y) (- height (.. d -r))))))
(.. label
(attr "x" #(+ (.-x %) 2 (.-r %)))
(attr "y" #(+ (.-y %))))
nil)
]
(.. simulation
(nodes nodes)
(on "tick" ticked))
(.. simulation
(force "link")
(links links))))
:component-did-update (fn [this]
#_(let [[_ data] (r/argv this)
d3data (clj->js data)
circles (.. js/d3
(select "svg")
(selectAll "circle")
(data d3data (fn [d i] (when d (.-name d)))))]
(.. circles
;(attr "cx" (fn [d] (.-x d)))
;(attr "cy" (fn [d] (.-y d)))
;(attr "r" (fn [d] (.-r d)))
enter
(append "circle")
(attr "cx" 200)
(attr "cy" 200)
(attr "r" 500)
(transition)
(attr "cx" (fn [d] (.-x d)))
(attr "cy" (fn [d] (.-y d)))
(attr "r" (fn [d] (.-r d)))
(attr "fill" (fn [d] (.-color d))))
(.. circles
exit
remove)))}))
(defn force-outer [traces-ratom]
(fn [] (fn []
(let [trace-graph (trace->sub-graph @traces-ratom)] ;(println "ticked")
[force-inner trace-graph]))) (let [link-sel (.. selector
(selectAll "g.links > line"))
(defonce desc (r/atom 1)) circle-sel (.. selector
(selectAll "g.node > circle"))
label-sel (.. selector
(selectAll "g.node > text"))]
(.. link-sel
(attr "x1" (fn [d] (.. d -source -x)))
(attr "y1" (fn [d] (.. d -source -y)))
(attr "x2" (fn [d] (.. d -target -x)))
(attr "y2" (fn [d] (.. d -target -y))))
(.. circle-sel
(attr "cx" (fn [d] (set! (.-x d) (min-max (.. d -r) (.. d -x) (- width (.. d -r))))))
(attr "cy" (fn [d] (set! (.-y d) (min-max (.. d -r) (.. d -y) (- height (.. d -r)))))))
(.. label-sel
(attr "x" (fn [d] (+ 2 (.-x d) (.-r d))))
(attr "y" #(+ (.-y %)))))))
(defn render-subvis [traces-ratom] (defn render-subvis [traces-ratom]
(let [color-a (atom nil) (let [color-a (atom nil)
svg-a (atom nil) svg-a (atom nil)
simulation-a (atom nil)] simulation-a (atom nil)
run? (atom false)]
(fn [] (fn []
(println "Render subvis")
[:div [:div
{:style {:padding "10px"}} {:style {:padding "10px"}}
[:h1 "SUBVIS"] [:h1 "SUBVIS"]
[force-outer traces-ratom] [d3t/create-d3
[:hr] {:render-component (fn [ratom]
[:h2 {:on-click #(swap! desc inc)} "Click"] [:svg#d3cmp {:width width :height height}])
[(d3t/create-d3 :d3-once (fn [ratom]
{:render-component (fn [ratom] (let [color (reset! color-a (.scaleOrdinal js/d3 (.-schemeCategory20 js/d3)))
[:div svg (reset! svg-a (. js/d3 select "#d3cmp"))
[:h1 (str "SVG")] simulation (reset! simulation-a
[:svg#d3cmp {:width width :height height}]]) (.. js/d3
:d3-did-mount (fn [ratom] (forceSimulation)
(let [graph (trace->sub-graph @ratom) (force "link" (.. js/d3 (forceLink)
(id #(.-id %))
(distance (constantly 100))))
(force "charge" (.. js/d3 (forceManyBody)
(strength (constantly -100))))
(force "center" (. js/d3 forceCenter (/ width 2) (/ height 2)))))
link (.. (. svg append "g")
(attr "class" "links"))
node (.. (. svg append "g")
(attr "class" "nodes"))]))
:d3-update (fn [ratom]
(when-not false #_@run?
#_(reset! run? true)
(let [graph (graph/trace->sub-graph @ratom [app-db-node])
nodes (clj->js (:nodes graph)) nodes (clj->js (:nodes graph))
links (clj->js (:links graph)) links (clj->js (:links graph))
color (reset! color-a (.scaleOrdinal js/d3 (.-schemeCategory20 js/d3)))
svg (reset! svg-a (. js/d3 select "#d3cmp"))
simulation (reset! simulation-a
(.. js/d3
(forceSimulation)
(force "link" (.. js/d3 (forceLink)
(id #(.-id %))
(distance (constantly 100))))
(force "charge" (.. js/d3 (forceManyBody)
(strength (constantly -100))))
(force "center" (. js/d3 forceCenter (/ width 2) (/ height 2)))))
dragstarted (fn [d]
(when (zero? (.. js/d3 -event -active))
(.. simulation
(alphaTarget 0.3)
(restart)))
(set! (.-fx d) (.-x d))
(set! (.-fy d) (.-y d)))
dragged (fn [d]
(set! (.-fx d) (.. js/d3 -event -x))
(set! (.-fy d) (.. js/d3 -event -y)))
dragended (fn [d]
(when (zero? (.. js/d3 -event -active))
(.. simulation
(alphaTarget 0.0)))
(set! (.-fx d) nil)
(set! (.-fy d) nil))
link (.. (. svg append "g")
(attr "class" "links")
(selectAll "line")
(data links)
(enter)
(append "line")
(attr "stroke-width" (fn [d] (Math/sqrt (.-value d))))
)
node (.. (. svg append "g")
(attr "class" "nodes")
(selectAll "circle")
(data nodes)
(enter)
(append "g")
(attr "class" "node"))
circle (.. node
(append "circle")
(attr "r" #(or (gob/get % "r" 10)))
(attr "fill" (fn [d] (color (.-group d))))
(call (.. (. js/d3 drag)
(on "start" dragstarted)
(on "drag" dragged)
(on "end" dragended))))
label (.. node
(append "text")
(attr "dy" ".35em")
(text #(gob/get % "title" "")))
ticked (fn []
(let [link-sel (.. svg
(selectAll ".links > line"))
circle-sel (.. svg
(selectAll ".node > circle"))
label-sel (.. svg
(selectAll ".node > text"))]
(.. link-sel
(attr "x1" (fn [d] (.. d -source -x)))
(attr "y1" (fn [d] (.. d -source -y)))
(attr "x2" (fn [d] (.. d -target -x)))
(attr "y2" (fn [d] (.. d -target -y))))
(.. circle-sel
(attr "cx" (fn [d] (min-max (.. d -r) (.. d -x) (- width (.. d -r)))))
(attr "cy" (fn [d] (min-max (.. d -r) (.. d -y) (- height (.. d -r))))))
(.. label-sel
(attr "x" #(+ (.-x %) 2 (.-r %)))
(attr "y" #(+ (.-y %)))))
nil)
]
(.. simulation
(nodes nodes)
(on "tick" ticked))
(.. simulation
(force "link")
(links links))
))
:d3-enter (fn [ratom]
(let [graph (trace->sub-graph @ratom)
nodes (clj->js (:nodes graph))
links (clj->js (:links graph))
svg @svg-a svg @svg-a
color @color-a color @color-a
simulation @simulation-a simulation @simulation-a
_ (js/console.log "d3ent" (.. svg
(selectAll ".links > line")
size))
dragstarted (fn [d] dragstarted (fn [d]
(when (zero? (.. js/d3 -event -active)) (when (zero? (.. js/d3 -event -active))
(.. simulation (.. simulation
(alphaTarget 0.3) (alphaTarget 0.3)
(restart))) (restart)))
(set! (.-fx d) (.-x d)) #_(set! (.-fx d) (.. js/d3 -event -x)) ; (.-x d)
(set! (.-fy d) (.-y d))) #_(set! (.-fy d) (.. js/d3 -event -y)))
dragged (fn [d] dragged (fn [d]
(set! (.-fx d) (.. js/d3 -event -x)) (set! (.-fx d) (.. js/d3 -event -x))
@ -366,23 +116,27 @@
(set! (.-fx d) nil) (set! (.-fx d) nil)
(set! (.-fy d) nil)) (set! (.-fy d) nil))
link (.. (. svg append "g") link (.. svg
(attr "class" "links") (select ".links")
(selectAll "line") (selectAll "line")
(data links) (data links (fn [d] (.-id d))))
new-link (.. link
(enter) (enter)
(append "line") (append "line")
(attr "stroke-width" (fn [d] (Math/sqrt (.-value d))))) (attr "stroke-width" (fn [d] (Math/sqrt (.-value d)))))
node (.. (. svg append "g") node (.. svg
(attr "class" "nodes") (select ".nodes")
(selectAll "circle") (selectAll "circle")
(data nodes) (data nodes))
new-node (.. node
(enter) (enter)
(append "g") (append "g")
(attr "class" "node")) (attr "class" "node"))
circle (.. node circle (.. new-node
(append "circle") (append "circle")
(attr "r" #(or (gob/get % "r" 10))) (attr "r" #(or (gob/get % "r" 10)))
(attr "fill" (fn [d] (color (.-group d)))) (attr "fill" (fn [d] (color (.-group d))))
@ -391,174 +145,34 @@
(on "drag" dragged) (on "drag" dragged)
(on "end" dragended)))) (on "end" dragended))))
label (.. new-node
label (.. node
(append "text") (append "text")
(attr "dy" ".35em") (attr "dy" ".35em")
(text #(gob/get % "title" ""))) (text #(gob/get % "title" "")))
] exit-node (.. node
(exit)
(remove "g"))
exit-link (.. link
(exit)
(remove "line"))
]
(println "Nodes count" (count nodes))
(println "Links count" (count links))
(.. simulation
(nodes nodes)
(on "tick" (ticked svg)))
(.. simulation (.. simulation
(force "link") (force "link")
(links links)) (links links))
(println "D3 did enter") (.. simulation
(js/console.log "d3 ent done" (.. svg (alphaTarget 0.3)
(selectAll ".links > line") (restart))
size))))}
traces-ratom)] )))}
traces-ratom]
[:hr]]))) [:hr]])))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;(ns todomvc.subvis2
; (:require [reagent.core :as r]))
;
;(defn prep-parent [parent]
; (-> parent
; (.selectAll "*")
; .remove)
; (.append parent "g"))
;
;(defn draw-circle [parent]
; (let [OUTER_WIDTH 208
; OUTER_HEIGHT 208
; parent (-> (js/d3.select parent)
; (.select "svg")
; (.attr "width" OUTER_WIDTH)
; (.attr "height" OUTER_HEIGHT))]
;
; ; Clear everything under the parent node so we can re-render it.
; (prep-parent parent)
;
; (let [top-node (.select parent "g")
; COLOR_CIRCLE "#fdb74a"]
; (.attr top-node
; "transform"
; (str "translate("
; (/ OUTER_WIDTH 2.0)
; ","
; (/ OUTER_HEIGHT 2.0)
; ")"))
;
; (-> top-node
; (.append "circle")
; (.attr "cx" 0)
; (.attr "cy" 0)
; (.attr "r" 100)
; (.style "stroke" COLOR_CIRCLE)))))
;
;(defn d3-gauge [args]
; (let [dom-node (r/atom nil)]
; (r/create-class
; {:component-did-update
; (fn [this old-argv]
; (let [[_ args] (r/argv this)]
; ;; This is where we get to actually draw the D3 gauge.
; (draw-circle @dom-node)))
;
; :component-did-mount
; (fn [this]
; (let [node (r/dom-node this)]
; ;; This will trigger a re-render of the component.
; (reset! dom-node node)))
;
; :reagent-render
; (fn [args]
; ;; Necessary for Reagent to see that we depend on the dom-node r/atom.
; ;; Note: we don't actually use any of the args here. This is because
; ;; we cannot render D3 at this point. We have to wait for the update.
; @dom-node
; [:div.gauge [:svg]])})))
;
;
;(def circles (r/atom [{:name "circle 1"
; :x 10
; :y 10
; :r 20
; :color "black"}
; {:name "circle 2"
; :x 35
; :y 35
; :r 15
; :color "red"}
; {:name "circle 3"
; :x 100
; :y 100
; :r 30
; :color "blue"}
; {:name "circle 4" :x 55 :y 55 :r 10 :color "red"}]))
;
;(defn new-circle []
; {:name (str (gensym "circle"))
; :x (rand-int 400)
; :y (rand-int 400)
; :r (+ 10 (rand-int 20))
; :color (str "hsl(" (rand-int 360) ", 100%, 50%)")})
;
;(defn add-new [n]
; (swap! circles conj (new-circle)))
;
;(defn d3-inner [data]
; (r/create-class
; {:reagent-render (fn [] [:div [:svg {:width 400 :height 800}]])
;
; :component-did-mount (fn []
; (let [d3data (clj->js data)]
; (.interval js/d3 add-new 1000)
; (.. js/d3
; (select "svg")
; (selectAll "circle")
; (data d3data (fn [d i] (.-name d)))
; enter
; (append "circle")
; (attr "cx" (fn [d] (.-x d)))
; (attr "cy" (fn [d] (.-y d)))
; (attr "r" (fn [d] (.-r d)))
; (attr "fill" (fn [d] (.-color d))))))
;
; :component-did-update (fn [this]
; (let [[_ data] (r/argv this)
; d3data (clj->js data)
; circles (.. js/d3
; (select "svg")
; (selectAll "circle")
; (data d3data (fn [d i] (when d (.-name d)))))]
; (.. circles
; ;(attr "cx" (fn [d] (.-x d)))
; ;(attr "cy" (fn [d] (.-y d)))
; ;(attr "r" (fn [d] (.-r d)))
; enter
; (append "circle")
; (attr "cx" 200)
; (attr "cy" 200)
; (attr "r" 500)
; (transition)
; (attr "cx" (fn [d] (.-x d)))
; (attr "cy" (fn [d] (.-y d)))
; (attr "r" (fn [d] (.-r d)))
; (attr "fill" (fn [d] (.-color d))))
; (.. circles
; exit
; remove)))}))
;
;(defn outer []
; (let [data circles #_(subscribe [:circles])]
; (fn []
; [d3-inner @data])))
;
;

View File

@ -0,0 +1,53 @@
(ns day8.re-frame.trace.graph-test
(:require [day8.re-frame.trace.graph :as graph]
[clojure.test :refer :all]))
(def t1
'({:id 1, :operation :initialise-db, :type :event, :tags {:event [:initialise-db]}, :child-of nil}
{:id 2, :operation "todomvc.core.wrapper", :type :render, :tags {:component-path "todomvc.core.wrapper", :reaction "rx2", :input-signals ("ra18")}, :child-of nil}
{:id 5, :operation :sorted-todos, :type :sub/create, :tags {:query-v [:sorted-todos], :cached? false, :reaction "rx3"}, :child-of 4}
{:id 4, :operation :todos, :type :sub/create, :tags {:query-v [:todos], :cached? false, :reaction "rx4"}, :child-of 3}
{:id 7, :operation :sorted-todos, :type :sub/run, :tags {:query-v [:sorted-todos], :reaction "rx3", :input-signals ["ra5"]}, :child-of 6}
{:id 6, :operation :todos, :type :sub/run, :tags {:query-v [:todos], :reaction "rx4", :input-signals ["rx3"]}, :child-of 3}
{:id 3, :operation "todomvc.views.todo_app", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app", :reaction "rx6", :input-signals ("rx4")}, :child-of nil}
{:id 8, :operation "todomvc.views.task_entry", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_entry", :reaction nil, :input-signals nil}, :child-of nil}
{:id 9, :operation "todomvc.views.todo_input", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_entry > todomvc.views.todo_input", :reaction "rx7", :input-signals ("ra19")}, :child-of nil}
{:id 10, :operation "ReagentInput", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_entry > todomvc.views.todo_input > ReagentInput", :reaction nil, :input-signals nil}, :child-of nil}
{:id 13, :operation :todos, :type :sub/create, :tags {:query-v [:todos], :cached? true, :reaction "rx4"}, :child-of 12}
{:id 14, :operation :showing, :type :sub/create, :tags {:query-v [:showing], :cached? false, :reaction "rx8"}, :child-of 12}
{:id 12, :operation :visible-todos, :type :sub/create, :tags {:query-v [:visible-todos], :cached? false, :reaction "rx9"}, :child-of 11}
{:id 16, :operation :todos, :type :sub/create, :tags {:query-v [:todos], :cached? true, :reaction "rx4"}, :child-of 15}
{:id 15, :operation :all-complete?, :type :sub/create, :tags {:query-v [:all-complete?], :cached? false, :reaction "rx10"}, :child-of 11}
{:id 17, :operation :all-complete?, :type :sub/run, :tags {:query-v [:all-complete?], :reaction "rx10", :input-signals ["rx4"]}, :child-of 11}
{:id 19, :operation :showing, :type :sub/run, :tags {:query-v [:showing], :reaction "rx8", :input-signals ["ra5"]}, :child-of 18}
{:id 18, :operation :visible-todos, :type :sub/run, :tags {:query-v [:visible-todos], :reaction "rx9", :input-signals ("rx4" "rx8")}, :child-of 11}
{:id 11, :operation "todomvc.views.task_list", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_list", :reaction "rx11", :input-signals ("rx10" "rx9")}, :child-of nil}
{:id 20, :operation "ReagentInput", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_list > ReagentInput", :reaction nil, :input-signals nil}, :child-of nil}
{:id 21, :operation "todomvc.views.todo_item", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_list > todomvc.views.todo_item", :reaction "rx12", :input-signals ("ra20" "ra20")}, :child-of nil}
{:id 22, :operation "ReagentInput", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.task_list > todomvc.views.todo_item > ReagentInput", :reaction nil, :input-signals nil}, :child-of nil}
{:id 24, :operation :footer-counts, :type :sub/create, :tags {:query-v [:footer-counts], :cached? false, :reaction "rx13"}, :child-of 23}
{:id 25, :operation :showing, :type :sub/create, :tags {:query-v [:showing], :cached? true, :reaction "rx8"}, :child-of 23}
{:id 27, :operation :todos, :type :sub/create, :tags {:query-v [:todos], :cached? true, :reaction "rx4"}, :child-of 26}
{:id 29, :operation :todos, :type :sub/create, :tags {:query-v [:todos], :cached? true, :reaction "rx4"}, :child-of 28}
{:id 28, :operation :completed-count, :type :sub/create, :tags {:query-v [:completed-count], :cached? false, :reaction "rx14"}, :child-of 26}
{:id 30, :operation :completed-count, :type :sub/run, :tags {:query-v [:completed-count], :reaction "rx14", :input-signals ["rx4"]}, :child-of 26}
{:id 26, :operation :footer-counts, :type :sub/run, :tags {:query-v [:footer-counts], :reaction "rx13", :input-signals ("rx4" "rx14")}, :child-of 23}
{:id 23, :operation "todomvc.views.footer_controls", :type :render, :tags {:component-path "todomvc.core.wrapper > todomvc.views.todo_app > todomvc.views.footer_controls", :reaction "rx15", :input-signals ("rx13" "rx8" "rx8" "rx8")}, :child-of nil}))
(deftest sub-graph-test
(is (= {:links []
:nodes [{:id "rx4"
:r 10
:title ""
:group 2
:data {:id 1
:tags {:cached? false
:reaction "rx4"}
:type :sub/create}}]}
(graph/trace->sub-graph [{:id 1 :type :sub/create :tags {:cached? false :reaction "rx4"}}] []))))
(deftest dispose-view-test
(is (= {:links []
:nodes []}
(graph/trace->sub-graph [{:id 1 :type :render :tags {:cached? false :reaction "rx4"}}
{:id 2 :type :componentWillUnmount :tags {:reaction "rx4"}}] []))))