diff --git a/CHANGELOG.md b/CHANGELOG.md index 00e1db4..9433d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. * 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. +* Diff the previous value of a subscription with its current value. ### Changed diff --git a/src/day8/re_frame/trace/events.cljs b/src/day8/re_frame/trace/events.cljs index d89afec..266e6d0 100644 --- a/src/day8/re_frame/trace/events.cljs +++ b/src/day8/re_frame/trace/events.cljs @@ -513,40 +513,16 @@ new-matches (remove (fn [match] (let [event (get-in (metam/matched-event match) [:tags :event])] (contains? events-to-ignore (first event)))) new-matches) - sub-state {} - subscription-match-state (rest - (reductions (fn [state match] - (let [epoch-traces (into [] - (comp - (utils/id-between-xf (:id (first match)) (:id (last match))) - (filter metam/subscription?)) - filtered-traces) - reset-state (into {} - (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 (js/console.warn "Unhandled sub trace, this is a bug, report to re-frame-trace please" trace) - state)))) - reset-state)))) - sub-state - new-matches)) + ;; subscription-info is calculated separately from subscription-match-state because they serve different purposes: + ;; - subscription-info collects all the data that we know about the subscription itself, like its layer, inputs and other + ;; things that are defined as part of the reg-sub. + ;; - subscription-match-state collects all the data that we know about the state of specific instances of subscriptions + ;; like its reagent id, when it was created, run, disposed, what values it returned, e.t.c. + subscription-info (metam/subscription-info (get-in db [:epochs :subscription-info] {}) filtered-traces (get-in db [:app-db :reagent-id])) + sub-state (get-in db [:epochs :sub-state] {}) + subscription-match-state (metam/subscription-match-state sub-state filtered-traces new-matches) + subscription-matches (rest subscription-match-state) + new-sub-state (last subscription-match-state) timing (mapv (fn [match] (let [epoch-traces (into [] (comp @@ -560,27 +536,10 @@ new-matches (map (fn [match sub-match t] {:match-info 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) 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)) retained-traces (into [] (comp (drop-while #(< (:id %) first-id-to-retain)) (remove (fn [trace] @@ -594,6 +553,7 @@ :matches-by-id (into {} (map (juxt first-match-id identity)) retained-matches) :match-ids (mapv first-match-id retained-matches) :parse-state parse-state + :sub-state new-sub-state :subscription-info subscription-info))))) ;; Else db))) diff --git a/src/day8/re_frame/trace/metamorphic.cljc b/src/day8/re_frame/trace/metamorphic.cljc index e7190d6..507db89 100644 --- a/src/day8/re_frame/trace/metamorphic.cljc +++ b/src/day8/re_frame/trace/metamorphic.cljc @@ -1,5 +1,11 @@ (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? ;;; idle -> dispatch -> running @@ -68,7 +74,7 @@ end-of-epoch (:end ev2)] (when (and (some? start-of-epoch) (some? end-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] (and (fsm-trigger? event) @@ -245,3 +251,64 @@ (->> match (filter event-run?) (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)) diff --git a/src/day8/re_frame/trace/subs.cljs b/src/day8/re_frame/trace/subs.cljs index 6df56c0..2d4e842 100644 --- a/src/day8/re_frame/trace/subs.cljs +++ b/src/day8/re_frame/trace/subs.cljs @@ -373,6 +373,18 @@ (fn [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 [sub] (case (:type sub) @@ -398,26 +410,27 @@ :<- [:subs/all-sub-traces] :<- [:app-db/reagent-id] :<- [: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 [pod-type (sub-op-type->type trace) - path-data (get-in trace [:tags :query-v]) - ;; TODO: detect layer 2/3 for sub/create and sub/destroy - ;; This information needs to be accumulated. - layer (if (some #(= app-db-id %) (get-in trace [:tags :input-signals])) - 2 - 3) - sub - (-> {:id (str pod-type (get-in trace [:tags :reaction])) - :type pod-type - :layer (get-in sub-info [(:operation trace) :layer]) - :path-data path-data - :path (pr-str path-data) - ;; TODO: Get not run subscriptions - })] - (if (contains? (:tags trace) :value) - (assoc sub :value (get-in trace [:tags :value])) - sub))) + (let [pod-type (sub-op-type->type trace) + path-data (get-in trace [:tags :query-v]) + reagent-id (get-in trace [:tags :reaction]) + sub (-> {:id (str pod-type reagent-id) + :reagent-id reagent-id + :type pod-type + :layer (get-in sub-info [(:operation trace) :layer]) + :path-data path-data + :path (pr-str path-data) + ;; TODO: Get not run subscriptions + }) + sub (if (contains? (:tags trace) :value) + (assoc sub :value (get-in trace [:tags :value])) + sub) + sub (if (contains? (get sub-state reagent-id) :previous-value) + (assoc sub :previous-value (get-in sub-state [reagent-id :previous-value])) + sub)] + sub)) traces) re-run (->> raw (filter #(= :re-run (:type %))) diff --git a/src/day8/re_frame/trace/utils/utils.cljs b/src/day8/re_frame/trace/utils/utils.cljs index 68c9f1a..17ad715 100644 --- a/src/day8/re_frame/trace/utils/utils.cljs +++ b/src/day8/re_frame/trace/utils/utils.cljs @@ -24,8 +24,8 @@ (defn spy ([x] - #?(:cljs (js/console.log x)) + (js/console.log x) x) ([label x] - #?(:cljs (js/console.log label x)) + (js/console.log label x) x)) diff --git a/src/day8/re_frame/trace/view/app_db.cljs b/src/day8/re_frame/trace/view/app_db.cljs index 8ef9c50..113be3e 100644 --- a/src/day8/re_frame/trace/view/app_db.cljs +++ b/src/day8/re_frame/trace/view/app_db.cljs @@ -197,11 +197,7 @@ (defn pod [{:keys [id path open? diff?] :as pod-info}] (let [render-diff? (and open? diff?) - 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)))] + app-db-after (rf/subscribe [:app-db/current-epoch-app-db-after])] [rc/v-box :style {:margin-bottom pod-gap :margin-right "1px"} @@ -242,41 +238,45 @@ :leave-animation "accordionVertical" :duration animation-duration}) (when render-diff? - [rc/v-box - :children [[rc/v-box - :class "app-db-path--link" - :justify :end - :children [[rc/hyperlink-href - ;:class "app-db-path--label" - :label "ONLY BEFORE" - :style {:margin-left common/gs-7s} - :attr {:rel "noopener noreferrer"} - :target "_blank" - :href utils/diff-link]]] - [rc/v-box - :class "data-viewer data-viewer--top-rule" - :style {:overflow-x "auto" - :overflow-y "hidden"} - :children [[components/simple-render - diff-before - ["app-db-diff" path]]]] - [rc/v-box - :class "app-db-path--link" - :justify :end - :children [[rc/hyperlink-href - ;:class "app-db-path--label" - :label "ONLY AFTER" - :style {:margin-left common/gs-7s} - :attr {:rel "noopener noreferrer"} - :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 [[components/simple-render - diff-after - ["app-db-diff" path]]]]]])] + (let [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 + :children [[rc/v-box + :class "app-db-path--link" + :justify :end + :children [[rc/hyperlink-href + ;:class "app-db-path--label" + :label "ONLY BEFORE" + :style {:margin-left common/gs-7s} + :attr {:rel "noopener noreferrer"} + :target "_blank" + :href utils/diff-link]]] + [rc/v-box + :class "data-viewer data-viewer--top-rule" + :style {:overflow-x "auto" + :overflow-y "hidden"} + :children [[components/simple-render + diff-before + ["app-db-diff" path]]]] + [rc/v-box + :class "app-db-path--link" + :justify :end + :children [[rc/hyperlink-href + ;:class "app-db-path--label" + :label "ONLY AFTER" + :style {:margin-left common/gs-7s} + :attr {:rel "noopener noreferrer"} + :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 [[components/simple-render + diff-after + ["app-db-diff" path]]]]]]))] (when open? [rc/gap-f :size pod-padding])]]]])) diff --git a/src/day8/re_frame/trace/view/debug.cljs b/src/day8/re_frame/trace/view/debug.cljs index a7ebe10..1fdddf6 100644 --- a/src/day8/re_frame/trace/view/debug.cljs +++ b/src/day8/re_frame/trace/view/debug.cljs @@ -1,5 +1,6 @@ (ns day8.re-frame.trace.view.debug (: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] [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 "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"] (let [current-match @(rf/subscribe [:epochs/current-match])] (for [match (:matches @(rf/subscribe [:epochs/epoch-root])) diff --git a/src/day8/re_frame/trace/view/subs.cljs b/src/day8/re_frame/trace/view/subs.cljs index 509ca48..f03d2ee 100644 --- a/src/day8/re_frame/trace/view/subs.cljs +++ b/src/day8/re_frame/trace/view/subs.cljs @@ -20,10 +20,10 @@ (defn sub-tag-class [type] (case type - :created "rft-tag__subscription_created" + :created "rft-tag__subscription_created" :destroyed "rft-tag__subscription_destroyed" - :re-run "rft-tag__subscription_re_run" - :not-run "rft-tag__subscription_not_run" + :re-run "rft-tag__subscription_re_run" + :not-run "rft-tag__subscription_not_run" "")) (def tag-types {:created {:long "CREATED" :short "CREATED"} @@ -45,9 +45,9 @@ (defn title-tag [type title label] [rc/v-box - :class "noselect" - :align :center - :gap "2px" + :class "noselect" + :align :center + :gap "2px" :children [[:span {:style {:font-size "9px"}} title] [components/tag (sub-tag-class type) label]]]) @@ -91,55 +91,56 @@ :children [[rc/checkbox :model ignore-unchanged? ;; 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" - :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"} :on-change #(rf/dispatch [:subs/ignore-unchanged-subs? %])]]]]])) (defn pod-header [{:keys [id type layer path open? diff? run-times]}] [rc/h-box - :class (str "app-db-path--header " (when-not open? "rounded-bottom")) - :align :center - :height common/gs-31s + :class (str "app-db-path--header " (when-not open? "rounded-bottom")) + :align :center + :height common/gs-31s :children [[rc/box - :width "36px" + :width "36px" :height common/gs-31s - :class "noselect" - :style {:cursor "pointer"} - :attr {:title (str (if open? "Close" "Open") " the pod bay doors, HAL") - :on-click #(rf/dispatch [:subs/open-pod? id (not open?)])} - :child [rc/box - :margin "auto" - :child [:span.arrow (if open? "▼" "▶")]]] + :class "noselect" + :style {:cursor "pointer"} + :attr {:title (str (if open? "Close" "Open") " the pod bay doors, HAL") + :on-click #(rf/dispatch [:subs/open-pod? id (not open?)])} + :child [rc/box + :margin "auto" + :child [:span.arrow (if open? "▼" "▶")]]] [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)]] ;; TODO: report if a sub was run multiple times #_(when run-times - [:span "Warning: run " run-times " times"]) + [:span "Warning: run " run-times " times"]) [rc/h-box - :class "app-db-path--path-header" - :size "auto" + :class "app-db-path--path-header" + :size "auto" :children [[rc/input-text :style {:height "25px" :padding (css-join "0px" common/gs-7s) :width "-webkit-fill-available"} ;; This took a bit of finding! - :width "100%" - :model path + :width "100%" + :model path :disabled? true]]] + (when @(rf/subscribe [:settings/debug?]) + [rc/label :label (str id)]) [rc/gap-f :size common/gs-12s] [rc/label :label (if (some? layer) (str "Layer " 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/box + [rc/gap-f :size common/gs-12s] + [rc/box :class "bm-muted-button app-db-path--button noselect" - :attr {:title "Show diff" - :on-click #(when open? (rf/dispatch [:subs/diff-pod? id (not diff?)]))} + :attr {:title "Show diff" + :on-click #(when open? (rf/dispatch [:subs/diff-pod? id (not diff?)]))} :child [:img {:src (str "data:image/svg+xml;utf8," copy) :style {:width "19px" @@ -147,86 +148,99 @@ [rc/gap-f :size common/gs-12s]]]) (defn pod [{:keys [id type layer path open? diff?] :as pod-info}] - (let [render-diff? (and open? diff?) - #_#_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)))] + (let [render-diff? (and open? diff?) + value? (contains? pod-info :value) + previous-value? (contains? pod-info :previous-value)] [rc/v-box - :style {:margin-bottom pod-gap - :margin-right "1px"} + :style {:margin-bottom pod-gap + :margin-right "1px"} :children [[pod-header pod-info] [rc/v-box - :class (when open? "app-db-path--pod-border") + :class (when open? "app-db-path--pod-border") :children [[animated/component (animated/v-box-options {:enter-animation "accordionVertical" :leave-animation "accordionVertical" :duration animation-duration}) (when open? - [rc/v-box - :class (str "data-viewer" (when-not diff? " rounded-bottom")) - :style {:margin (css-join pod-padding pod-padding "0px" pod-padding) - :overflow-x "auto" - :overflow-y "hidden"} - :children [(if (contains? pod-info :value) - [components/simple-render - (:value pod-info) - ["sub-path" path]] - [rc/label :style {:font-style "italic"} :label "Subscription not run, so no value produced."] - )]])] + (let [main-value (cond value? (:value pod-info) + previous-value? (:previous-value pod-info) + :else nil)] + [rc/v-box + :class (str "data-viewer" (when-not diff? " rounded-bottom")) + :style {:margin (css-join pod-padding pod-padding "0px" pod-padding) + :overflow-x "auto" + :overflow-y "hidden"} + :children [(if (or value? previous-value?) + [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/v-box-options {:enter-animation "accordionVertical" :leave-animation "accordionVertical" :duration animation-duration}) (when render-diff? - [rc/v-box - :children [[rc/v-box - :class "app-db-path--link" - :justify :end - :children [[rc/hyperlink-href - ;:class "app-db-path--label" - :label "ONLY BEFORE" - :style {:margin-left common/gs-7s} - :attr {:rel "noopener noreferrer"} - :target "_blank" - :href utils/diff-link]]] - [rc/v-box - :class "data-viewer data-viewer--top-rule" - :style {:overflow-x "auto" - :overflow-y "hidden"} - :height "50px" - :children ["---before-diff---"]] - [rc/v-box - :class "app-db-path--link" - :justify :end - :children [[rc/hyperlink-href - ;:class "app-db-path--label" - :label "ONLY AFTER" - :style {:margin-left common/gs-7s} - :attr {:rel "noopener noreferrer"} - :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"} - :height "50px" - :children ["---after-diff---"]]]])] + (let [diffable? (and value? previous-value?) + [diff-before diff-after _] (when render-diff? + (clojure.data/diff (:previous-value pod-info) + (:value pod-info)))] + [rc/v-box + :children [[rc/v-box + :class "app-db-path--link" + :justify :end + :children [[rc/hyperlink-href + ;:class "app-db-path--label" + :label "ONLY BEFORE" + :style {:margin-left common/gs-7s} + :attr {:rel "noopener noreferrer"} + :target "_blank" + :href utils/diff-link]]] + [rc/v-box + :class "data-viewer data-viewer--top-rule" + :style {:overflow-x "auto" + :overflow-y "hidden"} + :children [(if diffable? + [components/simple-render + diff-before + ["app-db-diff" path]] + [:p {:style {:font-style "italic"}} "No previous value exists to diff"])]] + [rc/v-box + :class "app-db-path--link" + :justify :end + :children [[rc/hyperlink-href + ;:class "app-db-path--label" + :label "ONLY AFTER" + :style {:margin-left common/gs-7s} + :attr {:rel "noopener noreferrer"} + :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? [rc/gap-f :size pod-padding])]]]])) (defn no-pods [] [rc/h-box - :margin (css-join "0px 0px 0px" common/gs-19s) - :gap common/gs-7s - :align :start + :margin (css-join "0px 0px 0px" common/gs-19s) + :gap common/gs-7s + :align :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 [] (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 :size "1" ;:gap pod-gap @@ -243,14 +257,14 @@ [animated/component (animated/v-box-options {:on-finish #(reset! *finished-animation? true) :duration animation-duration - :style {:flex "1 1 0px" + :style {:flex "1 1 0px" :overflow-x "hidden" :overflow-y "auto"}}) + (for [p all-subs] ^{:key (:id p)} [pod (merge p (get sub-expansions (:id p)))])]] - ])) (defn render [] @@ -266,25 +280,25 @@ ;; TODO: OLD UI - REMOVE #_[:div.panel-content-scrollable - {:style {:border "1px solid lightgrey" - :margin "0px"}} - [:div.subtrees - {:style {:margin "20px 0"}} - (doall - (->> @subs/query->reaction - (sort-by (fn [me] (ffirst (key me)))) - (map (fn [me] - (let [[query-v dyn-v :as inputs] (key me)] - ^{:key query-v} - [:div.subtree-wrapper {:style {:margin "10px 0"}} - [:div.subtree - [components/subscription-render - (rc/deref-or-value-peek (val me)) - [:button.subtree-button {:on-click #(rf/dispatch [:app-db/remove-path (key me)])} - [:span.subtree-button-string - (prn-str (first (key me)))]] - (into [:subs] query-v)]]])) - ))) - (do @re-frame.db/app-db - nil)]]]]) + {:style {:border "1px solid lightgrey" + :margin "0px"}} + [:div.subtrees + {:style {:margin "20px 0"}} + (doall + (->> @subs/query->reaction + (sort-by (fn [me] (ffirst (key me)))) + (map (fn [me] + (let [[query-v dyn-v :as inputs] (key me)] + ^{:key query-v} + [:div.subtree-wrapper {:style {:margin "10px 0"}} + [:div.subtree + [components/subscription-render + (rc/deref-or-value-peek (val me)) + [:button.subtree-button {:on-click #(rf/dispatch [:app-db/remove-path (key me)])} + [:span.subtree-button-string + (prn-str (first (key me)))]] + (into [:subs] query-v)]]])) + ))) + (do @re-frame.db/app-db + nil)]]]])