Show previous value for subscription state

This commit is contained in:
Daniel Compton 2018-01-31 00:49:50 +13:00
parent e0dea398f4
commit d652ef17e3
8 changed files with 286 additions and 227 deletions

View File

@ -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

View File

@ -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)))

View File

@ -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))

View File

@ -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 %)))

View File

@ -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))

View File

@ -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])]]]]))

View File

@ -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]))

View File

@ -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)]]]])