Show previous value for subscription state
This commit is contained in:
parent
e0dea398f4
commit
d652ef17e3
|
@ -10,6 +10,7 @@ This version requires re-frame 0.10.4 to make use of the newly added Event panel
|
||||||
* New event panel. This panel shows the coeffects given to your event handler, the effects your event handler produced, and all of the interceptors in the chain.
|
* New event panel. This panel shows the coeffects given to your event handler, the effects your event handler produced, and all of the interceptors in the chain.
|
||||||
* Debugging instructions if re-frame-trace fails to start.
|
* Debugging instructions if re-frame-trace fails to start.
|
||||||
* Setting to drop low level traces. This reduces the memory overhead of re-frame-trace as we can drop more traces that you are unlikely to want most of the time.
|
* Setting to drop low level traces. This reduces the memory overhead of re-frame-trace as we can drop more traces that you are unlikely to want most of the time.
|
||||||
|
* Diff the previous value of a subscription with its current value.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -513,40 +513,16 @@
|
||||||
new-matches (remove (fn [match]
|
new-matches (remove (fn [match]
|
||||||
(let [event (get-in (metam/matched-event match) [:tags :event])]
|
(let [event (get-in (metam/matched-event match) [:tags :event])]
|
||||||
(contains? events-to-ignore (first event)))) new-matches)
|
(contains? events-to-ignore (first event)))) new-matches)
|
||||||
sub-state {}
|
;; subscription-info is calculated separately from subscription-match-state because they serve different purposes:
|
||||||
subscription-match-state (rest
|
;; - subscription-info collects all the data that we know about the subscription itself, like its layer, inputs and other
|
||||||
(reductions (fn [state match]
|
;; things that are defined as part of the reg-sub.
|
||||||
(let [epoch-traces (into []
|
;; - subscription-match-state collects all the data that we know about the state of specific instances of subscriptions
|
||||||
(comp
|
;; like its reagent id, when it was created, run, disposed, what values it returned, e.t.c.
|
||||||
(utils/id-between-xf (:id (first match)) (:id (last match)))
|
subscription-info (metam/subscription-info (get-in db [:epochs :subscription-info] {}) filtered-traces (get-in db [:app-db :reagent-id]))
|
||||||
(filter metam/subscription?))
|
sub-state (get-in db [:epochs :sub-state] {})
|
||||||
filtered-traces)
|
subscription-match-state (metam/subscription-match-state sub-state filtered-traces new-matches)
|
||||||
reset-state (into {}
|
subscription-matches (rest subscription-match-state)
|
||||||
(map (fn [[k v]]
|
new-sub-state (last subscription-match-state)
|
||||||
[k (dissoc v :order :created? :run? :disposed? :previous-value)]))
|
|
||||||
state)]
|
|
||||||
(->> epoch-traces
|
|
||||||
(reduce (fn [state trace]
|
|
||||||
(let [tags (get trace :tags)
|
|
||||||
reaction-id (:reaction tags)]
|
|
||||||
(case (:op-type trace)
|
|
||||||
:sub/create (assoc state reaction-id {:created? true
|
|
||||||
:subscription (:query-v tags)
|
|
||||||
:order [:sub/create]})
|
|
||||||
:sub/run (update state reaction-id (fn [sub-state]
|
|
||||||
(-> (if (contains? sub-state :value)
|
|
||||||
(assoc sub-state :previous-value (:value sub-state))
|
|
||||||
sub-state)
|
|
||||||
(assoc :run? true
|
|
||||||
:value (:value tags))
|
|
||||||
(update :order (fnil conj []) :sub/run))))
|
|
||||||
:sub/dispose (-> (assoc-in state [reaction-id :disposed?] true)
|
|
||||||
(update-in [reaction-id :order] (fnil conj []) :sub/dispose))
|
|
||||||
(do (js/console.warn "Unhandled sub trace, this is a bug, report to re-frame-trace please" trace)
|
|
||||||
state))))
|
|
||||||
reset-state))))
|
|
||||||
sub-state
|
|
||||||
new-matches))
|
|
||||||
timing (mapv (fn [match]
|
timing (mapv (fn [match]
|
||||||
(let [epoch-traces (into []
|
(let [epoch-traces (into []
|
||||||
(comp
|
(comp
|
||||||
|
@ -560,27 +536,10 @@
|
||||||
|
|
||||||
new-matches (map (fn [match sub-match t] {:match-info match
|
new-matches (map (fn [match sub-match t] {:match-info match
|
||||||
:sub-state sub-match
|
:sub-state sub-match
|
||||||
:timing t}) new-matches subscription-match-state timing)
|
:timing t})
|
||||||
|
new-matches subscription-matches timing)
|
||||||
all-matches (reduce conj previous-matches new-matches)
|
all-matches (reduce conj previous-matches new-matches)
|
||||||
retained-matches (into [] (take-last number-of-epochs-to-retain all-matches))
|
retained-matches (into [] (take-last number-of-epochs-to-retain all-matches))
|
||||||
app-db-id (get-in db [:app-db :reagent-id])
|
|
||||||
subscription-info (->> filtered-traces
|
|
||||||
(filter metam/subscription-re-run?)
|
|
||||||
(reduce (fn [state trace]
|
|
||||||
;; Can we take any shortcuts by assuming that a sub with
|
|
||||||
;; multiple input signals is a layer 3? I don't *think* so because
|
|
||||||
;; one of those input signals could be a naughty subscription to app-db
|
|
||||||
;; directly.
|
|
||||||
;; If we knew when subscription handlers were loaded/reloaded then
|
|
||||||
;; we could avoid doing most of this work, and only check the input
|
|
||||||
;; signals if we hadn't seen it before, or it had been reloaded.
|
|
||||||
(assoc-in state
|
|
||||||
[(:operation trace) :layer]
|
|
||||||
;; If any of the input signals are app-db, it is a layer 2 sub, else 3
|
|
||||||
(if (some #(= app-db-id %) (get-in trace [:tags :input-signals]))
|
|
||||||
2
|
|
||||||
3)))
|
|
||||||
(get-in db [:epochs :subscription-info] {})))
|
|
||||||
first-id-to-retain (first-match-id (first retained-matches))
|
first-id-to-retain (first-match-id (first retained-matches))
|
||||||
retained-traces (into [] (comp (drop-while #(< (:id %) first-id-to-retain))
|
retained-traces (into [] (comp (drop-while #(< (:id %) first-id-to-retain))
|
||||||
(remove (fn [trace]
|
(remove (fn [trace]
|
||||||
|
@ -594,6 +553,7 @@
|
||||||
:matches-by-id (into {} (map (juxt first-match-id identity)) retained-matches)
|
:matches-by-id (into {} (map (juxt first-match-id identity)) retained-matches)
|
||||||
:match-ids (mapv first-match-id retained-matches)
|
:match-ids (mapv first-match-id retained-matches)
|
||||||
:parse-state parse-state
|
:parse-state parse-state
|
||||||
|
:sub-state new-sub-state
|
||||||
:subscription-info subscription-info)))))
|
:subscription-info subscription-info)))))
|
||||||
;; Else
|
;; Else
|
||||||
db)))
|
db)))
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
(ns day8.re-frame.trace.metamorphic)
|
(ns day8.re-frame.trace.metamorphic)
|
||||||
|
|
||||||
|
(defn id-between-xf
|
||||||
|
;; Copied here because I got undeclared Var warnings from figwheel when requiring a CLJC utils ns.
|
||||||
|
"Returns a transducer that filters for :id between beginning and ending."
|
||||||
|
[beginning ending]
|
||||||
|
(filter #(<= beginning (:id %) ending)))
|
||||||
|
|
||||||
;; What starts an epoch?
|
;; What starts an epoch?
|
||||||
|
|
||||||
;;; idle -> dispatch -> running
|
;;; idle -> dispatch -> running
|
||||||
|
@ -68,7 +74,7 @@
|
||||||
end-of-epoch (:end ev2)]
|
end-of-epoch (:end ev2)]
|
||||||
(when (and (some? start-of-epoch) (some? end-of-epoch))
|
(when (and (some? start-of-epoch) (some? end-of-epoch))
|
||||||
#?(:cljs (js/Math.round (- end-of-epoch start-of-epoch))
|
#?(:cljs (js/Math.round (- end-of-epoch start-of-epoch))
|
||||||
:clj (Math/round ^double (- end-of-epoch start-of-epoch))))))
|
:clj (Math/round ^double (- end-of-epoch start-of-epoch))))))
|
||||||
|
|
||||||
(defn run-queue? [event]
|
(defn run-queue? [event]
|
||||||
(and (fsm-trigger? event)
|
(and (fsm-trigger? event)
|
||||||
|
@ -245,3 +251,64 @@
|
||||||
(->> match
|
(->> match
|
||||||
(filter event-run?)
|
(filter event-run?)
|
||||||
(first)))
|
(first)))
|
||||||
|
|
||||||
|
(defn subscription-info
|
||||||
|
"Collect information about the subscription that we'd like
|
||||||
|
to know, like its layer."
|
||||||
|
[initial-state filtered-traces app-db-id]
|
||||||
|
(->> filtered-traces
|
||||||
|
(filter subscription-re-run?)
|
||||||
|
(reduce (fn [state trace]
|
||||||
|
;; Can we take any shortcuts by assuming that a sub with
|
||||||
|
;; multiple input signals is a layer 3? I don't *think* so because
|
||||||
|
;; one of those input signals could be a naughty subscription to app-db
|
||||||
|
;; directly.
|
||||||
|
;; If we knew when subscription handlers were loaded/reloaded then
|
||||||
|
;; we could avoid doing most of this work, and only check the input
|
||||||
|
;; signals if we hadn't seen it before, or it had been reloaded.
|
||||||
|
(assoc-in state
|
||||||
|
[(:operation trace) :layer]
|
||||||
|
;; If any of the input signals are app-db, it is a layer 2 sub, else 3
|
||||||
|
(if (some #(= app-db-id %) (get-in trace [:tags :input-signals]))
|
||||||
|
2
|
||||||
|
3)))
|
||||||
|
initial-state)))
|
||||||
|
|
||||||
|
(defn subscription-match-state
|
||||||
|
"Build up the state of re-frame's running subscriptions over each matched epoch.
|
||||||
|
Returns initial state as first item in list"
|
||||||
|
[sub-state filtered-traces new-matches]
|
||||||
|
(reductions (fn [state match]
|
||||||
|
(let [epoch-traces (into []
|
||||||
|
(comp
|
||||||
|
(id-between-xf (:id (first match)) (:id (last match)))
|
||||||
|
(filter subscription?))
|
||||||
|
filtered-traces)
|
||||||
|
reset-state (into {}
|
||||||
|
(comp
|
||||||
|
(filter (fn [me] (when-not (:disposed? (val me)) me)))
|
||||||
|
(map (fn [[k v]]
|
||||||
|
[k (dissoc v :order :created? :run? :disposed? :previous-value)])))
|
||||||
|
state)]
|
||||||
|
(->> epoch-traces
|
||||||
|
(reduce (fn [state trace]
|
||||||
|
(let [tags (get trace :tags)
|
||||||
|
reaction-id (:reaction tags)]
|
||||||
|
(case (:op-type trace)
|
||||||
|
:sub/create (assoc state reaction-id {:created? true
|
||||||
|
:subscription (:query-v tags)
|
||||||
|
:order [:sub/create]})
|
||||||
|
:sub/run (update state reaction-id (fn [sub-state]
|
||||||
|
(-> (if (contains? sub-state :value)
|
||||||
|
(assoc sub-state :previous-value (:value sub-state))
|
||||||
|
sub-state)
|
||||||
|
(assoc :run? true
|
||||||
|
:value (:value tags))
|
||||||
|
(update :order (fnil conj []) :sub/run))))
|
||||||
|
:sub/dispose (-> (assoc-in state [reaction-id :disposed?] true)
|
||||||
|
(update-in [reaction-id :order] (fnil conj []) :sub/dispose))
|
||||||
|
(do #?(:cljs (js/console.warn "Unhandled sub trace, this is a bug, report to re-frame-trace please" trace))
|
||||||
|
state))))
|
||||||
|
reset-state))))
|
||||||
|
sub-state
|
||||||
|
new-matches))
|
||||||
|
|
|
@ -373,6 +373,18 @@
|
||||||
(fn [epoch]
|
(fn [epoch]
|
||||||
(:subscription-info epoch)))
|
(:subscription-info epoch)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:subs/sub-state
|
||||||
|
:<- [:epochs/epoch-root]
|
||||||
|
(fn [epochs]
|
||||||
|
(:sub-state epochs)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:subs/current-epoch-sub-state
|
||||||
|
:<- [:epochs/current-match-state]
|
||||||
|
(fn [match-state]
|
||||||
|
(:sub-state match-state)))
|
||||||
|
|
||||||
(defn sub-sort-val
|
(defn sub-sort-val
|
||||||
[sub]
|
[sub]
|
||||||
(case (:type sub)
|
(case (:type sub)
|
||||||
|
@ -398,26 +410,27 @@
|
||||||
:<- [:subs/all-sub-traces]
|
:<- [:subs/all-sub-traces]
|
||||||
:<- [:app-db/reagent-id]
|
:<- [:app-db/reagent-id]
|
||||||
:<- [:subs/subscription-info]
|
:<- [:subs/subscription-info]
|
||||||
(fn [[traces app-db-id sub-info]]
|
:<- [:subs/current-epoch-sub-state]
|
||||||
|
(fn [[traces app-db-id sub-info sub-state]]
|
||||||
(let [raw (map (fn [trace]
|
(let [raw (map (fn [trace]
|
||||||
(let [pod-type (sub-op-type->type trace)
|
(let [pod-type (sub-op-type->type trace)
|
||||||
path-data (get-in trace [:tags :query-v])
|
path-data (get-in trace [:tags :query-v])
|
||||||
;; TODO: detect layer 2/3 for sub/create and sub/destroy
|
reagent-id (get-in trace [:tags :reaction])
|
||||||
;; This information needs to be accumulated.
|
sub (-> {:id (str pod-type reagent-id)
|
||||||
layer (if (some #(= app-db-id %) (get-in trace [:tags :input-signals]))
|
:reagent-id reagent-id
|
||||||
2
|
:type pod-type
|
||||||
3)
|
:layer (get-in sub-info [(:operation trace) :layer])
|
||||||
sub
|
:path-data path-data
|
||||||
(-> {:id (str pod-type (get-in trace [:tags :reaction]))
|
:path (pr-str path-data)
|
||||||
:type pod-type
|
;; TODO: Get not run subscriptions
|
||||||
:layer (get-in sub-info [(:operation trace) :layer])
|
})
|
||||||
:path-data path-data
|
sub (if (contains? (:tags trace) :value)
|
||||||
:path (pr-str path-data)
|
(assoc sub :value (get-in trace [:tags :value]))
|
||||||
;; TODO: Get not run subscriptions
|
sub)
|
||||||
})]
|
sub (if (contains? (get sub-state reagent-id) :previous-value)
|
||||||
(if (contains? (:tags trace) :value)
|
(assoc sub :previous-value (get-in sub-state [reagent-id :previous-value]))
|
||||||
(assoc sub :value (get-in trace [:tags :value]))
|
sub)]
|
||||||
sub)))
|
sub))
|
||||||
traces)
|
traces)
|
||||||
re-run (->> raw
|
re-run (->> raw
|
||||||
(filter #(= :re-run (:type %)))
|
(filter #(= :re-run (:type %)))
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
(defn spy
|
(defn spy
|
||||||
([x]
|
([x]
|
||||||
#?(:cljs (js/console.log x))
|
(js/console.log x)
|
||||||
x)
|
x)
|
||||||
([label x]
|
([label x]
|
||||||
#?(:cljs (js/console.log label x))
|
(js/console.log label x)
|
||||||
x))
|
x))
|
||||||
|
|
|
@ -197,11 +197,7 @@
|
||||||
|
|
||||||
(defn pod [{:keys [id path open? diff?] :as pod-info}]
|
(defn pod [{:keys [id path open? diff?] :as pod-info}]
|
||||||
(let [render-diff? (and open? diff?)
|
(let [render-diff? (and open? diff?)
|
||||||
app-db-after (rf/subscribe [:app-db/current-epoch-app-db-after])
|
app-db-after (rf/subscribe [:app-db/current-epoch-app-db-after])]
|
||||||
app-db-before (rf/subscribe [:app-db/current-epoch-app-db-before])
|
|
||||||
[diff-before diff-after _] (when render-diff?
|
|
||||||
(clojure.data/diff (get-in @app-db-before path)
|
|
||||||
(get-in @app-db-after path)))]
|
|
||||||
[rc/v-box
|
[rc/v-box
|
||||||
:style {:margin-bottom pod-gap
|
:style {:margin-bottom pod-gap
|
||||||
:margin-right "1px"}
|
:margin-right "1px"}
|
||||||
|
@ -242,41 +238,45 @@
|
||||||
:leave-animation "accordionVertical"
|
:leave-animation "accordionVertical"
|
||||||
:duration animation-duration})
|
:duration animation-duration})
|
||||||
(when render-diff?
|
(when render-diff?
|
||||||
[rc/v-box
|
(let [app-db-before (rf/subscribe [:app-db/current-epoch-app-db-before])
|
||||||
:children [[rc/v-box
|
[diff-before diff-after _] (when render-diff?
|
||||||
:class "app-db-path--link"
|
(clojure.data/diff (get-in @app-db-before path)
|
||||||
:justify :end
|
(get-in @app-db-after path)))]
|
||||||
:children [[rc/hyperlink-href
|
[rc/v-box
|
||||||
;:class "app-db-path--label"
|
:children [[rc/v-box
|
||||||
:label "ONLY BEFORE"
|
:class "app-db-path--link"
|
||||||
:style {:margin-left common/gs-7s}
|
:justify :end
|
||||||
:attr {:rel "noopener noreferrer"}
|
:children [[rc/hyperlink-href
|
||||||
:target "_blank"
|
;:class "app-db-path--label"
|
||||||
:href utils/diff-link]]]
|
:label "ONLY BEFORE"
|
||||||
[rc/v-box
|
:style {:margin-left common/gs-7s}
|
||||||
:class "data-viewer data-viewer--top-rule"
|
:attr {:rel "noopener noreferrer"}
|
||||||
:style {:overflow-x "auto"
|
:target "_blank"
|
||||||
:overflow-y "hidden"}
|
:href utils/diff-link]]]
|
||||||
:children [[components/simple-render
|
[rc/v-box
|
||||||
diff-before
|
:class "data-viewer data-viewer--top-rule"
|
||||||
["app-db-diff" path]]]]
|
:style {:overflow-x "auto"
|
||||||
[rc/v-box
|
:overflow-y "hidden"}
|
||||||
:class "app-db-path--link"
|
:children [[components/simple-render
|
||||||
:justify :end
|
diff-before
|
||||||
:children [[rc/hyperlink-href
|
["app-db-diff" path]]]]
|
||||||
;:class "app-db-path--label"
|
[rc/v-box
|
||||||
:label "ONLY AFTER"
|
:class "app-db-path--link"
|
||||||
:style {:margin-left common/gs-7s}
|
:justify :end
|
||||||
:attr {:rel "noopener noreferrer"}
|
:children [[rc/hyperlink-href
|
||||||
:target "_blank"
|
;:class "app-db-path--label"
|
||||||
:href utils/diff-link]]]
|
:label "ONLY AFTER"
|
||||||
[rc/v-box
|
:style {:margin-left common/gs-7s}
|
||||||
:class "data-viewer data-viewer--top-rule rounded-bottom"
|
:attr {:rel "noopener noreferrer"}
|
||||||
:style {:overflow-x "auto"
|
:target "_blank"
|
||||||
:overflow-y "hidden"}
|
:href utils/diff-link]]]
|
||||||
:children [[components/simple-render
|
[rc/v-box
|
||||||
diff-after
|
:class "data-viewer data-viewer--top-rule rounded-bottom"
|
||||||
["app-db-diff" path]]]]]])]
|
:style {:overflow-x "auto"
|
||||||
|
:overflow-y "hidden"}
|
||||||
|
:children [[components/simple-render
|
||||||
|
diff-after
|
||||||
|
["app-db-diff" path]]]]]]))]
|
||||||
(when open?
|
(when open?
|
||||||
[rc/gap-f :size pod-padding])]]]]))
|
[rc/gap-f :size pod-padding])]]]]))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns day8.re-frame.trace.view.debug
|
(ns day8.re-frame.trace.view.debug
|
||||||
(:require [day8.re-frame.trace.utils.re-com :as rc]
|
(:require [day8.re-frame.trace.utils.re-com :as rc]
|
||||||
|
[day8.re-frame.trace.view.components :as components]
|
||||||
[mranderson047.re-frame.v0v10v2.re-frame.core :as rf]
|
[mranderson047.re-frame.v0v10v2.re-frame.core :as rf]
|
||||||
[day8.re-frame.trace.metamorphic :as metam]))
|
[day8.re-frame.trace.metamorphic :as metam]))
|
||||||
|
|
||||||
|
@ -14,6 +15,9 @@
|
||||||
[rc/label :label (str "Ending " (prn-str @(rf/subscribe [:epochs/ending-trace-id])))]
|
[rc/label :label (str "Ending " (prn-str @(rf/subscribe [:epochs/ending-trace-id])))]
|
||||||
[rc/label :label (str "Current epoch ID " (prn-str @(rf/subscribe [:epochs/current-epoch-id])))]
|
[rc/label :label (str "Current epoch ID " (prn-str @(rf/subscribe [:epochs/current-epoch-id])))]
|
||||||
|
|
||||||
|
[:h2 "Subscriptions"]
|
||||||
|
[components/simple-render @(rf/subscribe [:subs/sub-state]) ["debug-subs"]]
|
||||||
|
|
||||||
[rc/label :label "Epochs"]
|
[rc/label :label "Epochs"]
|
||||||
(let [current-match @(rf/subscribe [:epochs/current-match])]
|
(let [current-match @(rf/subscribe [:epochs/current-match])]
|
||||||
(for [match (:matches @(rf/subscribe [:epochs/epoch-root]))
|
(for [match (:matches @(rf/subscribe [:epochs/epoch-root]))
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
|
|
||||||
(defn sub-tag-class [type]
|
(defn sub-tag-class [type]
|
||||||
(case type
|
(case type
|
||||||
:created "rft-tag__subscription_created"
|
:created "rft-tag__subscription_created"
|
||||||
:destroyed "rft-tag__subscription_destroyed"
|
:destroyed "rft-tag__subscription_destroyed"
|
||||||
:re-run "rft-tag__subscription_re_run"
|
:re-run "rft-tag__subscription_re_run"
|
||||||
:not-run "rft-tag__subscription_not_run"
|
:not-run "rft-tag__subscription_not_run"
|
||||||
""))
|
""))
|
||||||
|
|
||||||
(def tag-types {:created {:long "CREATED" :short "CREATED"}
|
(def tag-types {:created {:long "CREATED" :short "CREATED"}
|
||||||
|
@ -45,9 +45,9 @@
|
||||||
|
|
||||||
(defn title-tag [type title label]
|
(defn title-tag [type title label]
|
||||||
[rc/v-box
|
[rc/v-box
|
||||||
:class "noselect"
|
:class "noselect"
|
||||||
:align :center
|
:align :center
|
||||||
:gap "2px"
|
:gap "2px"
|
||||||
:children [[:span {:style {:font-size "9px"}} title]
|
:children [[:span {:style {:font-size "9px"}} title]
|
||||||
[components/tag (sub-tag-class type) label]]])
|
[components/tag (sub-tag-class type) label]]])
|
||||||
|
|
||||||
|
@ -91,55 +91,56 @@
|
||||||
:children [[rc/checkbox
|
:children [[rc/checkbox
|
||||||
:model ignore-unchanged?
|
:model ignore-unchanged?
|
||||||
;; TODO: change from l2 subs to ignored l2 subs
|
;; TODO: change from l2 subs to ignored l2 subs
|
||||||
:label [:span "Ignore " [:b {:style {:font-weight "700"}} @ignore-unchanged-l2-count] #_ " unchanged" [:br]
|
:label [:span "Ignore " [:b {:style {:font-weight "700"}} @ignore-unchanged-l2-count] #_" unchanged" [:br]
|
||||||
[rc/link {:label "layer 2 subs"
|
[rc/link {:label "layer 2 subs"
|
||||||
:href "https://github.com/Day8/re-frame-trace/blob/master/docs/HyperlinkedInformation/UnchangedLayer2.md"}]]
|
:href "https://github.com/Day8/re-frame-trace/blob/master/docs/HyperlinkedInformation/UnchangedLayer2.md"}]]
|
||||||
:style {:margin-top "6px"}
|
:style {:margin-top "6px"}
|
||||||
:on-change #(rf/dispatch [:subs/ignore-unchanged-subs? %])]]]]]))
|
:on-change #(rf/dispatch [:subs/ignore-unchanged-subs? %])]]]]]))
|
||||||
|
|
||||||
(defn pod-header [{:keys [id type layer path open? diff? run-times]}]
|
(defn pod-header [{:keys [id type layer path open? diff? run-times]}]
|
||||||
[rc/h-box
|
[rc/h-box
|
||||||
:class (str "app-db-path--header " (when-not open? "rounded-bottom"))
|
:class (str "app-db-path--header " (when-not open? "rounded-bottom"))
|
||||||
:align :center
|
:align :center
|
||||||
:height common/gs-31s
|
:height common/gs-31s
|
||||||
:children [[rc/box
|
:children [[rc/box
|
||||||
:width "36px"
|
:width "36px"
|
||||||
:height common/gs-31s
|
:height common/gs-31s
|
||||||
:class "noselect"
|
:class "noselect"
|
||||||
:style {:cursor "pointer"}
|
:style {:cursor "pointer"}
|
||||||
:attr {:title (str (if open? "Close" "Open") " the pod bay doors, HAL")
|
:attr {:title (str (if open? "Close" "Open") " the pod bay doors, HAL")
|
||||||
:on-click #(rf/dispatch [:subs/open-pod? id (not open?)])}
|
:on-click #(rf/dispatch [:subs/open-pod? id (not open?)])}
|
||||||
:child [rc/box
|
:child [rc/box
|
||||||
:margin "auto"
|
:margin "auto"
|
||||||
:child [:span.arrow (if open? "▼" "▶")]]]
|
:child [:span.arrow (if open? "▼" "▶")]]]
|
||||||
[rc/box
|
[rc/box
|
||||||
:width "64px" ;; (100-36)px from box above
|
:width "64px" ;; (100-36)px from box above
|
||||||
:child [sub-tag type (short-tag-desc type)]]
|
:child [sub-tag type (short-tag-desc type)]]
|
||||||
;; TODO: report if a sub was run multiple times
|
;; TODO: report if a sub was run multiple times
|
||||||
#_(when run-times
|
#_(when run-times
|
||||||
[:span "Warning: run " run-times " times"])
|
[:span "Warning: run " run-times " times"])
|
||||||
[rc/h-box
|
[rc/h-box
|
||||||
:class "app-db-path--path-header"
|
:class "app-db-path--path-header"
|
||||||
:size "auto"
|
:size "auto"
|
||||||
:children [[rc/input-text
|
:children [[rc/input-text
|
||||||
:style {:height "25px"
|
:style {:height "25px"
|
||||||
:padding (css-join "0px" common/gs-7s)
|
:padding (css-join "0px" common/gs-7s)
|
||||||
:width "-webkit-fill-available"} ;; This took a bit of finding!
|
:width "-webkit-fill-available"} ;; This took a bit of finding!
|
||||||
:width "100%"
|
:width "100%"
|
||||||
:model path
|
:model path
|
||||||
:disabled? true]]]
|
:disabled? true]]]
|
||||||
|
(when @(rf/subscribe [:settings/debug?])
|
||||||
|
[rc/label :label (str id)])
|
||||||
[rc/gap-f :size common/gs-12s]
|
[rc/gap-f :size common/gs-12s]
|
||||||
[rc/label :label (if (some? layer)
|
[rc/label :label (if (some? layer)
|
||||||
(str "Layer " layer)
|
(str "Layer " layer)
|
||||||
[rc/link {:label "Layer ?"
|
[rc/link {:label "Layer ?"
|
||||||
:href "https://github.com/Day8/re-frame-trace/blob/master/docs/HyperlinkedInformation/UnchangedLayer2.md#why-do-i-sometimes-see-layer--when-viewing-a-subscription"}])]
|
:href "https://github.com/Day8/re-frame-trace/blob/master/docs/HyperlinkedInformation/UnchangedLayer2.md#why-do-i-sometimes-see-layer--when-viewing-a-subscription"}])]
|
||||||
|
|
||||||
;; TODO: capture previous sub run value and allow diffing it.
|
[rc/gap-f :size common/gs-12s]
|
||||||
#_[rc/gap-f :size common/gs-12s]
|
[rc/box
|
||||||
#_[rc/box
|
|
||||||
:class "bm-muted-button app-db-path--button noselect"
|
:class "bm-muted-button app-db-path--button noselect"
|
||||||
:attr {:title "Show diff"
|
:attr {:title "Show diff"
|
||||||
:on-click #(when open? (rf/dispatch [:subs/diff-pod? id (not diff?)]))}
|
:on-click #(when open? (rf/dispatch [:subs/diff-pod? id (not diff?)]))}
|
||||||
:child [:img
|
:child [:img
|
||||||
{:src (str "data:image/svg+xml;utf8," copy)
|
{:src (str "data:image/svg+xml;utf8," copy)
|
||||||
:style {:width "19px"
|
:style {:width "19px"
|
||||||
|
@ -147,86 +148,99 @@
|
||||||
[rc/gap-f :size common/gs-12s]]])
|
[rc/gap-f :size common/gs-12s]]])
|
||||||
|
|
||||||
(defn pod [{:keys [id type layer path open? diff?] :as pod-info}]
|
(defn pod [{:keys [id type layer path open? diff?] :as pod-info}]
|
||||||
(let [render-diff? (and open? diff?)
|
(let [render-diff? (and open? diff?)
|
||||||
#_#_app-db-after (rf/subscribe [:app-db/current-epoch-app-db-after])
|
value? (contains? pod-info :value)
|
||||||
#_#_app-db-before (rf/subscribe [:app-db/current-epoch-app-db-before])
|
previous-value? (contains? pod-info :previous-value)]
|
||||||
#_#_[diff-before diff-after _] (when render-diff?
|
|
||||||
(clojure.data/diff (get-in @app-db-before path)
|
|
||||||
(get-in @app-db-after path)))]
|
|
||||||
[rc/v-box
|
[rc/v-box
|
||||||
:style {:margin-bottom pod-gap
|
:style {:margin-bottom pod-gap
|
||||||
:margin-right "1px"}
|
:margin-right "1px"}
|
||||||
:children [[pod-header pod-info]
|
:children [[pod-header pod-info]
|
||||||
[rc/v-box
|
[rc/v-box
|
||||||
:class (when open? "app-db-path--pod-border")
|
:class (when open? "app-db-path--pod-border")
|
||||||
:children [[animated/component
|
:children [[animated/component
|
||||||
(animated/v-box-options {:enter-animation "accordionVertical"
|
(animated/v-box-options {:enter-animation "accordionVertical"
|
||||||
:leave-animation "accordionVertical"
|
:leave-animation "accordionVertical"
|
||||||
:duration animation-duration})
|
:duration animation-duration})
|
||||||
(when open?
|
(when open?
|
||||||
[rc/v-box
|
(let [main-value (cond value? (:value pod-info)
|
||||||
:class (str "data-viewer" (when-not diff? " rounded-bottom"))
|
previous-value? (:previous-value pod-info)
|
||||||
:style {:margin (css-join pod-padding pod-padding "0px" pod-padding)
|
:else nil)]
|
||||||
:overflow-x "auto"
|
[rc/v-box
|
||||||
:overflow-y "hidden"}
|
:class (str "data-viewer" (when-not diff? " rounded-bottom"))
|
||||||
:children [(if (contains? pod-info :value)
|
:style {:margin (css-join pod-padding pod-padding "0px" pod-padding)
|
||||||
[components/simple-render
|
:overflow-x "auto"
|
||||||
(:value pod-info)
|
:overflow-y "hidden"}
|
||||||
["sub-path" path]]
|
:children [(if (or value? previous-value?)
|
||||||
[rc/label :style {:font-style "italic"} :label "Subscription not run, so no value produced."]
|
[components/simple-render
|
||||||
)]])]
|
main-value
|
||||||
|
["sub-path" path]]
|
||||||
|
[rc/label :style {:font-style "italic"} :label "Subscription not run, so no value produced."]
|
||||||
|
)]]))]
|
||||||
[animated/component
|
[animated/component
|
||||||
(animated/v-box-options {:enter-animation "accordionVertical"
|
(animated/v-box-options {:enter-animation "accordionVertical"
|
||||||
:leave-animation "accordionVertical"
|
:leave-animation "accordionVertical"
|
||||||
:duration animation-duration})
|
:duration animation-duration})
|
||||||
(when render-diff?
|
(when render-diff?
|
||||||
[rc/v-box
|
(let [diffable? (and value? previous-value?)
|
||||||
:children [[rc/v-box
|
[diff-before diff-after _] (when render-diff?
|
||||||
:class "app-db-path--link"
|
(clojure.data/diff (:previous-value pod-info)
|
||||||
:justify :end
|
(:value pod-info)))]
|
||||||
:children [[rc/hyperlink-href
|
[rc/v-box
|
||||||
;:class "app-db-path--label"
|
:children [[rc/v-box
|
||||||
:label "ONLY BEFORE"
|
:class "app-db-path--link"
|
||||||
:style {:margin-left common/gs-7s}
|
:justify :end
|
||||||
:attr {:rel "noopener noreferrer"}
|
:children [[rc/hyperlink-href
|
||||||
:target "_blank"
|
;:class "app-db-path--label"
|
||||||
:href utils/diff-link]]]
|
:label "ONLY BEFORE"
|
||||||
[rc/v-box
|
:style {:margin-left common/gs-7s}
|
||||||
:class "data-viewer data-viewer--top-rule"
|
:attr {:rel "noopener noreferrer"}
|
||||||
:style {:overflow-x "auto"
|
:target "_blank"
|
||||||
:overflow-y "hidden"}
|
:href utils/diff-link]]]
|
||||||
:height "50px"
|
[rc/v-box
|
||||||
:children ["---before-diff---"]]
|
:class "data-viewer data-viewer--top-rule"
|
||||||
[rc/v-box
|
:style {:overflow-x "auto"
|
||||||
:class "app-db-path--link"
|
:overflow-y "hidden"}
|
||||||
:justify :end
|
:children [(if diffable?
|
||||||
:children [[rc/hyperlink-href
|
[components/simple-render
|
||||||
;:class "app-db-path--label"
|
diff-before
|
||||||
:label "ONLY AFTER"
|
["app-db-diff" path]]
|
||||||
:style {:margin-left common/gs-7s}
|
[:p {:style {:font-style "italic"}} "No previous value exists to diff"])]]
|
||||||
:attr {:rel "noopener noreferrer"}
|
[rc/v-box
|
||||||
:target "_blank"
|
:class "app-db-path--link"
|
||||||
:href utils/diff-link]]]
|
:justify :end
|
||||||
[rc/v-box
|
:children [[rc/hyperlink-href
|
||||||
:class "data-viewer data-viewer--top-rule rounded-bottom"
|
;:class "app-db-path--label"
|
||||||
:style {:overflow-x "auto"
|
:label "ONLY AFTER"
|
||||||
:overflow-y "hidden"}
|
:style {:margin-left common/gs-7s}
|
||||||
:height "50px"
|
:attr {:rel "noopener noreferrer"}
|
||||||
:children ["---after-diff---"]]]])]
|
:target "_blank"
|
||||||
|
:href utils/diff-link]]]
|
||||||
|
[rc/v-box
|
||||||
|
:class "data-viewer data-viewer--top-rule rounded-bottom"
|
||||||
|
:style {:overflow-x "auto"
|
||||||
|
:overflow-y "hidden"}
|
||||||
|
:children [(if diffable?
|
||||||
|
[components/simple-render
|
||||||
|
diff-after
|
||||||
|
["app-db-diff" path]]
|
||||||
|
[:p {:style {:font-style "italic"}} "No previous value exists to diff"])]]]]))]
|
||||||
(when open?
|
(when open?
|
||||||
[rc/gap-f :size pod-padding])]]]]))
|
[rc/gap-f :size pod-padding])]]]]))
|
||||||
|
|
||||||
(defn no-pods []
|
(defn no-pods []
|
||||||
[rc/h-box
|
[rc/h-box
|
||||||
:margin (css-join "0px 0px 0px" common/gs-19s)
|
:margin (css-join "0px 0px 0px" common/gs-19s)
|
||||||
:gap common/gs-7s
|
:gap common/gs-7s
|
||||||
:align :start
|
:align :start
|
||||||
:align-self :start
|
:align-self :start
|
||||||
:children [[rc/label :label "There are no subscriptions to show"]]])
|
:children [[rc/label :label "There are no subscriptions to show"]]])
|
||||||
|
|
||||||
(defn pod-section []
|
(defn pod-section []
|
||||||
(let [all-subs @(rf/subscribe [:subs/visible-subs])
|
(let [all-subs @(rf/subscribe [:subs/visible-subs])
|
||||||
sub-expansions @(rf/subscribe [:subs/sub-expansions])]
|
sub-expansions @(rf/subscribe [:subs/sub-expansions])
|
||||||
|
all-subs (if @(rf/subscribe [:settings/debug?])
|
||||||
|
(cons {:id "debug" :value @(rf/subscribe [:subs/current-epoch-sub-state])} all-subs)
|
||||||
|
all-subs)]
|
||||||
[rc/v-box
|
[rc/v-box
|
||||||
:size "1"
|
:size "1"
|
||||||
;:gap pod-gap
|
;:gap pod-gap
|
||||||
|
@ -243,14 +257,14 @@
|
||||||
[animated/component
|
[animated/component
|
||||||
(animated/v-box-options {:on-finish #(reset! *finished-animation? true)
|
(animated/v-box-options {:on-finish #(reset! *finished-animation? true)
|
||||||
:duration animation-duration
|
:duration animation-duration
|
||||||
:style {:flex "1 1 0px"
|
:style {:flex "1 1 0px"
|
||||||
:overflow-x "hidden"
|
:overflow-x "hidden"
|
||||||
:overflow-y "auto"}})
|
:overflow-y "auto"}})
|
||||||
|
|
||||||
(for [p all-subs]
|
(for [p all-subs]
|
||||||
^{:key (:id p)}
|
^{:key (:id p)}
|
||||||
[pod (merge p (get sub-expansions (:id p)))])]]
|
[pod (merge p (get sub-expansions (:id p)))])]]
|
||||||
|
|
||||||
|
|
||||||
]))
|
]))
|
||||||
|
|
||||||
(defn render []
|
(defn render []
|
||||||
|
@ -266,25 +280,25 @@
|
||||||
|
|
||||||
;; TODO: OLD UI - REMOVE
|
;; TODO: OLD UI - REMOVE
|
||||||
#_[:div.panel-content-scrollable
|
#_[:div.panel-content-scrollable
|
||||||
{:style {:border "1px solid lightgrey"
|
{:style {:border "1px solid lightgrey"
|
||||||
:margin "0px"}}
|
:margin "0px"}}
|
||||||
[:div.subtrees
|
[:div.subtrees
|
||||||
{:style {:margin "20px 0"}}
|
{:style {:margin "20px 0"}}
|
||||||
(doall
|
(doall
|
||||||
(->> @subs/query->reaction
|
(->> @subs/query->reaction
|
||||||
(sort-by (fn [me] (ffirst (key me))))
|
(sort-by (fn [me] (ffirst (key me))))
|
||||||
(map (fn [me]
|
(map (fn [me]
|
||||||
(let [[query-v dyn-v :as inputs] (key me)]
|
(let [[query-v dyn-v :as inputs] (key me)]
|
||||||
^{:key query-v}
|
^{:key query-v}
|
||||||
[:div.subtree-wrapper {:style {:margin "10px 0"}}
|
[:div.subtree-wrapper {:style {:margin "10px 0"}}
|
||||||
[:div.subtree
|
[:div.subtree
|
||||||
[components/subscription-render
|
[components/subscription-render
|
||||||
(rc/deref-or-value-peek (val me))
|
(rc/deref-or-value-peek (val me))
|
||||||
[:button.subtree-button {:on-click #(rf/dispatch [:app-db/remove-path (key me)])}
|
[:button.subtree-button {:on-click #(rf/dispatch [:app-db/remove-path (key me)])}
|
||||||
[:span.subtree-button-string
|
[:span.subtree-button-string
|
||||||
(prn-str (first (key me)))]]
|
(prn-str (first (key me)))]]
|
||||||
(into [:subs] query-v)]]]))
|
(into [:subs] query-v)]]]))
|
||||||
)))
|
)))
|
||||||
(do @re-frame.db/app-db
|
(do @re-frame.db/app-db
|
||||||
nil)]]]])
|
nil)]]]])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue