Commit changes
This commit is contained in:
parent
c6384dcd74
commit
6b8b961d13
|
@ -11,7 +11,10 @@
|
|||
[reagent.ratom :as ratom]
|
||||
[re-frame.utils :as rutils]
|
||||
[goog.object :as gob]
|
||||
[re-frame.interop :as interop]))
|
||||
[re-frame.interop :as interop]
|
||||
|
||||
[devtools.formatters.core :as devtools]
|
||||
))
|
||||
|
||||
(defn comp-name [c]
|
||||
(let [n (or (component/component-path c)
|
||||
|
@ -72,7 +75,8 @@
|
|||
(fn [] (this-as c
|
||||
(trace/with-trace {:op-type key
|
||||
: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)))
|
||||
|
||||
(real-custom-wrapper key f))))
|
||||
|
@ -151,7 +155,9 @@
|
|||
[:tbody
|
||||
(doall
|
||||
(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
|
||||
:style {:color (case type
|
||||
:sub/create "green"
|
||||
|
@ -169,7 +175,8 @@
|
|||
(.toFixed duration 1) " ms"]]
|
||||
(when true
|
||||
[: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]
|
||||
{:position "absolute" :z-index 2 :opacity 0
|
||||
|
|
|
@ -1,110 +1,37 @@
|
|||
(ns day8.re-frame.trace.d3
|
||||
(: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]
|
||||
(fn [& args]
|
||||
(println "No-op" desc)))
|
||||
(fn [& args] nil))
|
||||
|
||||
(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
|
||||
"Creates a bridging component from Reagent to D3. Takes a map of
|
||||
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)
|
||||
: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-enter, :d3-update, :d3-exit - correspond to functions in the D3 general update pattern: https://bl.ocks.org/mbostock/3808218
|
||||
: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-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]
|
||||
:or {render-component no-op
|
||||
d3-did-mount (no-op :d3-did-mount)
|
||||
d3-enter (no-op :d3-enter)
|
||||
d3-update (no-op :d3-update)
|
||||
d3-exit (no-op :d3-exit)}}
|
||||
[{:keys [render-component d3-once d3-update]
|
||||
:or {render-component (no-op :render)
|
||||
d3-once (no-op :d3-did-mount)
|
||||
d3-update (no-op :d3-update)}}
|
||||
& ratoms]
|
||||
(let [lifecycle-fns {:render-component render-component
|
||||
:d3-did-mount d3-did-mount
|
||||
:d3-enter d3-enter
|
||||
:d3-update d3-update
|
||||
:d3-exit d3-exit}]
|
||||
:d3-once d3-once
|
||||
:d3-update d3-update}]
|
||||
(r/create-class
|
||||
{:reagent-render (fn []
|
||||
(doseq [r ratoms] (deref r))
|
||||
(apply render-component ratoms))
|
||||
:component-did-mount (fn [this] (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})
|
||||
:component-did-mount (fn [this]
|
||||
(component-did-mount lifecycle-fns ratoms))
|
||||
:component-did-update (fn [this old-argv]
|
||||
(component-did-update lifecycle-fns ratoms))})))
|
||||
|
|
|
@ -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}))
|
|
@ -1,6 +1,7 @@
|
|||
(ns day8.re-frame.trace.subvis
|
||||
(:require cljsjs.d3
|
||||
[day8.re-frame.trace.d3 :as d3t]
|
||||
[day8.re-frame.trace.graph :as graph]
|
||||
[reagent.core :as r]
|
||||
[re-frame.utils :as rutils]
|
||||
[re-frame.db :as db]
|
||||
|
@ -8,80 +9,20 @@
|
|||
[clojure.set :as set]))
|
||||
|
||||
(def width 400)
|
||||
(def height 200)
|
||||
(def height 400)
|
||||
|
||||
(def mygraph (r/atom {:nodes [{:id 1 :group 1}
|
||||
{:id 2 :group 1}
|
||||
{:id 3 :group 2}]
|
||||
:links [{:source 1 :target 2 :value 1}]}))
|
||||
|
||||
(defn trace->sub-graph [traces]
|
||||
(let [disposed (->> traces
|
||||
(filter #(#{:sub/dispose} (:type %)))
|
||||
(map #(get-in % [:tags :reaction]))
|
||||
set)
|
||||
sub-nodes (->> traces
|
||||
(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})))
|
||||
(def app-db-node {:id (rutils/reagent-id db/app-db)
|
||||
:title "app-db"
|
||||
:group 1
|
||||
:r 20
|
||||
:fx 15
|
||||
:fy (/ height 2)})
|
||||
|
||||
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
|
||||
"Returns x if it is within min-val and max-val
|
||||
|
@ -93,267 +34,76 @@
|
|||
(assert (<= min-val 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 []
|
||||
(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]
|
||||
(defn ticked [selector]
|
||||
(fn []
|
||||
(let [trace-graph (trace->sub-graph @traces-ratom)]
|
||||
[force-inner trace-graph])))
|
||||
|
||||
(defonce desc (r/atom 1))
|
||||
;(println "ticked")
|
||||
(let [link-sel (.. selector
|
||||
(selectAll "g.links > line"))
|
||||
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]
|
||||
(let [color-a (atom nil)
|
||||
svg-a (atom nil)
|
||||
simulation-a (atom nil)]
|
||||
simulation-a (atom nil)
|
||||
run? (atom false)]
|
||||
(fn []
|
||||
(println "Render subvis")
|
||||
[:div
|
||||
{:style {:padding "10px"}}
|
||||
[:h1 "SUBVIS"]
|
||||
[force-outer traces-ratom]
|
||||
[:hr]
|
||||
[:h2 {:on-click #(swap! desc inc)} "Click"]
|
||||
[(d3t/create-d3
|
||||
{:render-component (fn [ratom]
|
||||
[:div
|
||||
[:h1 (str "SVG")]
|
||||
[:svg#d3cmp {:width width :height height}]])
|
||||
:d3-did-mount (fn [ratom]
|
||||
(let [graph (trace->sub-graph @ratom)
|
||||
[d3t/create-d3
|
||||
{:render-component (fn [ratom]
|
||||
[:svg#d3cmp {:width width :height height}])
|
||||
:d3-once (fn [ratom]
|
||||
(let [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)))))
|
||||
|
||||
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))
|
||||
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
|
||||
color @color-a
|
||||
simulation @simulation-a
|
||||
_ (js/console.log "d3ent" (.. svg
|
||||
(selectAll ".links > line")
|
||||
size))
|
||||
|
||||
dragstarted (fn [d]
|
||||
(when (zero? (.. js/d3 -event -active))
|
||||
(.. simulation
|
||||
(alphaTarget 0.3)
|
||||
(restart)))
|
||||
|
||||
(set! (.-fx d) (.-x d))
|
||||
(set! (.-fy d) (.-y d)))
|
||||
#_(set! (.-fx d) (.. js/d3 -event -x)) ; (.-x d)
|
||||
#_(set! (.-fy d) (.. js/d3 -event -y)))
|
||||
|
||||
dragged (fn [d]
|
||||
(set! (.-fx d) (.. js/d3 -event -x))
|
||||
|
@ -366,23 +116,27 @@
|
|||
(set! (.-fx d) nil)
|
||||
(set! (.-fy d) nil))
|
||||
|
||||
link (.. (. svg append "g")
|
||||
(attr "class" "links")
|
||||
link (.. svg
|
||||
(select ".links")
|
||||
(selectAll "line")
|
||||
(data links)
|
||||
(data links (fn [d] (.-id d))))
|
||||
|
||||
new-link (.. link
|
||||
(enter)
|
||||
(append "line")
|
||||
(attr "stroke-width" (fn [d] (Math/sqrt (.-value d)))))
|
||||
|
||||
node (.. (. svg append "g")
|
||||
(attr "class" "nodes")
|
||||
node (.. svg
|
||||
(select ".nodes")
|
||||
(selectAll "circle")
|
||||
(data nodes)
|
||||
(data nodes))
|
||||
|
||||
new-node (.. node
|
||||
(enter)
|
||||
(append "g")
|
||||
(attr "class" "node"))
|
||||
|
||||
circle (.. node
|
||||
circle (.. new-node
|
||||
(append "circle")
|
||||
(attr "r" #(or (gob/get % "r" 10)))
|
||||
(attr "fill" (fn [d] (color (.-group d))))
|
||||
|
@ -391,174 +145,34 @@
|
|||
(on "drag" dragged)
|
||||
(on "end" dragended))))
|
||||
|
||||
|
||||
label (.. node
|
||||
label (.. new-node
|
||||
(append "text")
|
||||
(attr "dy" ".35em")
|
||||
(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
|
||||
(force "link")
|
||||
(links links))
|
||||
(println "D3 did enter")
|
||||
(js/console.log "d3 ent done" (.. svg
|
||||
(selectAll ".links > line")
|
||||
size))))}
|
||||
traces-ratom)]
|
||||
(.. simulation
|
||||
(alphaTarget 0.3)
|
||||
(restart))
|
||||
|
||||
)))}
|
||||
traces-ratom]
|
||||
[: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])))
|
||||
;
|
||||
;
|
||||
|
|
|
@ -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"}}] []))))
|
Loading…
Reference in New Issue