diff --git a/project.clj b/project.clj index cbb8540..315ca48 100644 --- a/project.clj +++ b/project.clj @@ -3,7 +3,7 @@ :url "https://github.com/Day8/re-frame-trace" :license {:name "MIT"} :dependencies [[org.clojure/clojure "1.8.0"] - [org.clojure/clojurescript "1.9.227"] + [org.clojure/clojurescript "1.9.671"] [reagent "0.6.0" :scope "provided"] [re-frame "0.10.2" :scope "provided"] [cljsjs/d3 "4.3.0-5"] diff --git a/src/day8/re_frame/trace/components/container.cljs b/src/day8/re_frame/trace/components/container.cljs index c23bcd4..63c940f 100644 --- a/src/day8/re_frame/trace/components/container.cljs +++ b/src/day8/re_frame/trace/components/container.cljs @@ -4,8 +4,14 @@ [day8.re-frame.trace.panels.app-db :as app-db] [day8.re-frame.trace.panels.subvis :as subvis] [day8.re-frame.trace.panels.traces :as traces] + [day8.re-frame.trace.panels.subs :as subs] [reagent.core :as r])) +(defn tab-button [panel-id title] + (let [selected-tab @(rf/subscribe [:settings/selected-tab])] + [:button {:class (str "tab button " (when (= selected-tab panel-id) "active")) + :on-click #(rf/dispatch [:settings/selected-tab panel-id])} title])) + (defn devtools-inner [traces opts] (let [selected-tab (rf/subscribe [:settings/selected-tab]) panel-type (:panel-type opts) @@ -17,13 +23,10 @@ [:h1.host-closed "Host window has closed. Reopen external window to continue tracing."]) [:div.panel-content-top [:div.nav - [:button {:class (str "tab button " (when (= @selected-tab :traces) "active")) - :on-click #(rf/dispatch [:settings/selected-tab :traces])} "Traces"] - [:button {:class (str "tab button " (when (= @selected-tab :app-db) "active")) - :on-click #(rf/dispatch [:settings/selected-tab :app-db])} "App DB"] - #_[:button {:class (str "tab button " (when (= @selected-tab :subvis) "active")) - :on-click #(reset! selected-tab :subvis)} "SubVis"] - + (tab-button :traces "Traces") + (tab-button :app-db "App DB") + (tab-button :subs "Subs") + #_ (tab-button :subvis "SubVis") (when-not external-window? [:img.popout-icon {:src (str "data:image/svg+xml;utf8," @@ -33,4 +36,5 @@ :traces [traces/render-trace-panel traces] :app-db [app-db/render-state db/app-db] :subvis [subvis/render-subvis traces] + :subs [subs/subs-panel] [app-db/render-state db/app-db])])) diff --git a/src/day8/re_frame/trace/components/data_browser.cljs b/src/day8/re_frame/trace/components/data_browser.cljs index 0dd53cc..6a8213f 100644 --- a/src/day8/re_frame/trace/components/data_browser.cljs +++ b/src/day8/re_frame/trace/components/data_browser.cljs @@ -133,7 +133,7 @@ [:div {:class (str/join " " ["re-frame-trace--object" (when @expanded? "expanded")])} - [:span {:class "toggle" + #_[:span {:class "toggle" :on-click #(rf/dispatch [:app-db/toggle-expansion path])} [:button.expansion-button (if @expanded? "▼ " "▶ ")]] (or title "data") diff --git a/src/day8/re_frame/trace/panels/subs.cljs b/src/day8/re_frame/trace/panels/subs.cljs new file mode 100644 index 0000000..505abae --- /dev/null +++ b/src/day8/re_frame/trace/panels/subs.cljs @@ -0,0 +1,37 @@ +(ns day8.re-frame.trace.panels.subs + (:require [re-frame.subs :as subs] + [day8.re-frame.trace.utils.re-com :as rc] + [cljs.spec.alpha :as s] + [day8.re-frame.trace.components.data-browser :as data-browser] + [mranderson047.re-frame.v0v10v2.re-frame.core :as rf])) + +(s/def ::query-v any?) +(s/def ::dyn-v any?) +(s/def ::query-cache-params (s/tuple ::query-v ::dyn-v)) +(s/def ::deref #(satisfies? IDeref %)) +(s/def ::query-cache (s/map-of ::query-cache-params ::deref)) +;(assert (s/valid? ::query-cache (rc/deref-or-value-peek subs/query->reaction))) + + + + +(defn subs-panel [] + [] + [:div {:style {:flex "1 1 auto" :display "flex" :flex-direction "column"}} + [:div.panel-content-scrollable {:style {:margin-left "10px"}} + [:div.subtrees {:style {:margin "20px 0"}} + (doall + (map (fn [me] + (let [[query-v dyn-v :as inputs] (key me)] + @(val me) + ^{:key query-v} + [:div.subtree-wrapper {:style {:margin "10px 0"}} + [:div.subtree + [data-browser/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)]]])) + @subs/query->reaction))]]]) + diff --git a/src/day8/re_frame/trace/panels/traces.cljs b/src/day8/re_frame/trace/panels/traces.cljs index 02ef3b3..d30f0a3 100644 --- a/src/day8/re_frame/trace/panels/traces.cljs +++ b/src/day8/re_frame/trace/panels/traces.cljs @@ -165,5 +165,15 @@ (when (pos? (count @traces)) [:span "(" [:button.text-button {:on-click #(do (trace/reset-tracing!) (reset! traces []))} "clear"] ")"])] [:th {:style {:text-align "right"}} "meta"]] - [:tbody (render-traces visible-traces filter-items filter-input trace-detail-expansions)]]] - ])))) + [:tbody (render-traces visible-traces filter-items filter-input trace-detail-expansions)] + [:hr {:style {:unicode-bidi "isolate" + :-webkit-margin-before "0.5em" + :-webkit-margin-after "0.5em" + :-webkit-margin-start "auto" + :-webkit-margin-end "auto" + :overflow "hidden" + :border-style "inset" + :border-width "1px" }}]]] + ])))) + + diff --git a/src/day8/re_frame/trace/utils/re_com.cljs b/src/day8/re_frame/trace/utils/re_com.cljs index 243c72d..1c6c4f6 100644 --- a/src/day8/re_frame/trace/utils/re_com.cljs +++ b/src/day8/re_frame/trace/utils/re_com.cljs @@ -4,6 +4,28 @@ (:require [reagent.ratom :as reagent :refer [RAtom Reaction RCursor Track Wrapper]] [clojure.string :as string])) +(defn deref-or-value-peek + "Takes a value or an atom + If it's a value, returns it + If it's a Reagent object that supports IDeref, returns the value inside it, but WITHOUT derefing + The arg validation code uses this, since calling deref-or-value adds this arg to the watched ratom list for the component + in question, which in turn can cause different rendering behaviour between dev (where we validate) and prod (where we don't). + This was experienced in popover-content-wrapper with the position-injected atom which was not derefed there, however + the dev-only validation caused it to be derefed, modifying its render behaviour and causing mayhem and madness for the developer. + See below that different Reagent types have different ways of retrieving the value without causing capture, although in the case of + Track, we just deref it as there is no peek or state, so hopefully this won't cause issues (surely this is used very rarely). + " + [val-or-atom] + (if (satisfies? IDeref val-or-atom) + (cond + (instance? RAtom val-or-atom) val-or-atom.state + (instance? Reaction val-or-atom) (._peek-at val-or-atom) + (instance? RCursor val-or-atom) (._peek val-or-atom) + (instance? Track val-or-atom) @val-or-atom + (instance? Wrapper val-or-atom) val-or-atom.state + :else (throw (js/Error. "Unknown reactive data type"))) + val-or-atom)) + (defn deref-or-value "Takes a value or an atom If it's a value, returns it