Persist app-db expansions

Uses the path through the hiccup as the expansion path. This means that
if the hiccup layout changes, the wrong item can be expanded. However
it is still better than the alternative, and can be improved in the
future.

Fixes #105
This commit is contained in:
Daniel Compton 2017-11-16 15:33:07 +13:00
parent 4d2db30dee
commit 87e5679ebb
5 changed files with 60 additions and 20 deletions

5
docs/README.md Normal file
View File

@ -0,0 +1,5 @@
# Usage
## App DB path expansions
re-frame-trace preserves path expansions by using the through the JSONML that is rendered, rather than the actual data path. This has the advantage of being feasible, but the disadvantage that if the HTML layout changes, then that can trigger expansion changes. This means that if the map keys change ordering (say when switching from an ArrayMap to a HashMap), then different items will be expanded/contracted.

View File

@ -13,6 +13,7 @@
(rf/dispatch [:settings/selected-tab selected-tab])
(rf/dispatch [:traces/filter-items filter-items])
(rf/dispatch [:app-db/paths app-db-paths])
(rf/dispatch [:app-db/set-json-ml-paths #{}])
(rf/dispatch [:global/add-unload-hook])
(when show-panel?
(rf/dispatch [:global/enable-tracing]))))

View File

@ -183,3 +183,16 @@
:app-db/search-string
(fn [db [_ search-string]]
(assoc-in db [:app-db :search-string] search-string)))
(rf/reg-event-db
:app-db/set-json-ml-paths
(fn [db [_ paths]]
(assoc-in db [:app-db :json-ml-paths] paths)))
(rf/reg-event-db
:app-db/toggle-expansion
[(rf/path [:app-db :json-ml-paths])]
(fn [paths [_ path]]
(if (contains? paths path)
(disj paths path)
(conj paths path))))

View File

@ -66,21 +66,25 @@
(defn get-config [jsonml]
(.-config (get jsonml 1)))
(defn data-structure [jsonml]
(let [expanded? (r/atom false)]
(fn [jsonml]
(defn data-structure [jsonml path]
(let [expanded? (rf/subscribe [:app-db/node-expanded? path])]
(fn [jsonml path]
[:span
{:class (str "re-frame-trace--object" (when @expanded? " expanded"))}
[:span {:class "toggle"
:on-click #(swap! expanded? not)}
:on-click #(rf/dispatch [:app-db/toggle-expansion path])}
[:button.expansion-button (if @expanded? "▼" "▶")]]
(jsonml->hiccup (if (and @expanded? (cljs-devtools-has-body (get-object jsonml) (get-config jsonml)))
(cljs-devtools-body
(get-object jsonml)
(get-config jsonml))
(cljs-devtools-header
(get-object jsonml)
(get-config jsonml))))])))
(if (and @expanded? (cljs-devtools-has-body (get-object jsonml) (get-config jsonml)))
(jsonml->hiccup
(cljs-devtools-body
(get-object jsonml)
(get-config jsonml))
(conj path :body))
(jsonml->hiccup
(cljs-devtools-header
(get-object jsonml)
(get-config jsonml))
(conj path :header)))])))
(defn jsonml->hiccup
"JSONML is the format used by Chrome's Custom Object Formatters.
@ -89,7 +93,7 @@
JSONML is pretty much Hiccup over JSON. Chrome's implementation of this can
be found at https://cs.chromium.org/chromium/src/third_party/WebKit/Source/devtools/front_end/object_ui/CustomPreviewComponent.js
"
[jsonml]
[jsonml path]
(if (number? jsonml)
jsonml
(let [[tag-name attributes & children] jsonml
@ -99,20 +103,20 @@
[(keyword tag-name) {:style (-> (js->clj attributes)
(get "style")
(string->css))}]
(map jsonml->hiccup)
(map-indexed (fn [i child] (jsonml->hiccup child (conj path i))))
children)
(= tag-name "object") [data-structure jsonml]
(= tag-name "object") [data-structure jsonml path]
:else jsonml))))
(defn subtree [data title]
(let [expanded? (r/atom false)]
(defn subtree [data title path]
(let [expanded? (rf/subscribe [:app-db/node-expanded? path])]
(fn [data]
[:div
{:class (str/join " " ["re-frame-trace--object"
(when @expanded? "expanded")])}
[:span {:class "toggle"
:on-click #(swap! expanded? not)}
:on-click #(rf/dispatch [:app-db/toggle-expansion path])}
[:button.expansion-button (if @expanded? "▼ " "▶ ")]]
(or title "data")
[:div {:style {:margin-left 20}}
@ -120,7 +124,7 @@
(and @expanded?
(or (string? data)
(number? data))) [:div {:style {:margin "10px 0"}} data]
@expanded? (jsonml->hiccup (cljs-devtools-header data)))]])))
@expanded? (jsonml->hiccup (cljs-devtools-header data) (conj path 0)))]])))
(defn render-state [data]
(let [subtree-input (r/atom "")
@ -152,7 +156,8 @@
(get-in @data path)
[:button.subtree-button {:on-click #(rf/dispatch [:app-db/remove-path path])}
[:span.subtree-button-string
(str path)]]]]])
(str path)]]
[path]]]])
@subtree-paths))]
[:div {:style {:margin-bottom "20px"}}
[subtree @data [:span.label "app-db"]]]]])))
[subtree @data [:span.label "app-db"] [:app-db]]]]])))

View File

@ -24,6 +24,8 @@
(fn [settings _]
(get settings :selected-tab)))
;; App DB
(rf/reg-sub
:app-db/root
(fn [db _]
@ -41,6 +43,20 @@
(fn [app-db-settings _]
(get app-db-settings :search-string)))
(rf/reg-sub
:app-db/expansions
:<- [:app-db/root]
(fn [app-db-settings _]
(get app-db-settings :json-ml-paths)))
(rf/reg-sub
:app-db/node-expanded?
:<- [:app-db/expansions]
(fn [expansions [_ path]]
(contains? expansions path)))
;;
(rf/reg-sub
:traces/filter-items
(fn [db _]