Add new state snapshotting feature

This commit is contained in:
Daniel Compton 2017-12-04 17:00:10 +13:00
parent 4c4ecf9e49
commit 5bbe678856
11 changed files with 120 additions and 27 deletions

View File

@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This change
## [Unreleased] ## [Unreleased]
### Added
* New state snapshotting feature: Click the camera to snapshot app-db, and click the load button to restore to your snapshot.
### Changed ### Changed
* Switched from LESS to Garden styles. Now interactive development and debugging of re-frame-trace is even faster. * Switched from LESS to Garden styles. Now interactive development and debugging of re-frame-trace is even faster.

View File

@ -106,4 +106,6 @@ If you want to work on re-frame-trace, see [DEVELOPERS.md](DEVELOPERS.md).
## Citations ## Citations
[open](https://thenounproject.com/search/?q=popout&i=334227) by Bluetip Design from the Noun Project * [open](https://thenounproject.com/search/?q=popout&i=334227) by Bluetip Design from the Noun Project
* [reload](https://thenounproject.com/adnen.kadri/collection/arrows/?i=798299) by Adnen Kadri from the Noun Project
* [Camera](https://thenounproject.com/search/?q=snapshot&i=200965) by Christian Shannon from the Noun Project

View File

@ -1,9 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" x="0px" y="0px"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 10 10" x="0px" y="0px">
<path d="M0 0v8h8v-2h-1v1h-6v-6h1v-1h-2zm4 0l1.5 1.5-2.5 2.5 1 1 2.5-2.5 1.5 1.5v-4h-4z"/> <path fill="#444444" d="M0 0v8h8v-2h-1v1h-6v-6h1v-1h-2zm4 0l1.5 1.5-2.5 2.5 1 1 2.5-2.5 1.5 1.5v-4h-4z"/>
<text x="0" y="23" fill="#000000" font-size="5px" font-weight="bold"
font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by Bluetip Design
</text>
<text x="0" y="28" fill="#000000" font-size="5px" font-weight="bold"
font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project
</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 567 B

After

Width:  |  Height:  |  Size: 196 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" x="0px" y="0px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<path fill="#666666" d="M27.773,22.766c2.379-6.494-0.967-13.711-7.459-16.091c-4.11-1.506-8.5-0.707-11.777,1.721l1.483-6.743L7.09,1.009 l-1.946,8.85L4.5,12.79l2.93,0.646v-0.001l8.85,1.948l0.645-2.931l-6.794-1.494c2.514-1.963,5.943-2.642,9.152-1.466 c4.939,1.81,7.486,7.302,5.676,12.242c-1.811,4.938-7.302,7.484-12.242,5.675c-4.155-1.522-6.604-5.646-6.207-9.858l-2.896-1.06 c-0.918,5.798,2.354,11.64,8.07,13.735C18.178,32.604,25.395,29.259,27.773,22.766z"/>
</svg>

After

Width:  |  Height:  |  Size: 660 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" x="0px" y="0px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<path fill="#444444" d="M27.773,22.766c2.379-6.494-0.967-13.711-7.459-16.091c-4.11-1.506-8.5-0.707-11.777,1.721l1.483-6.743L7.09,1.009 l-1.946,8.85L4.5,12.79l2.93,0.646v-0.001l8.85,1.948l0.645-2.931l-6.794-1.494c2.514-1.963,5.943-2.642,9.152-1.466 c4.939,1.81,7.486,7.302,5.676,12.242c-1.811,4.938-7.302,7.484-12.242,5.675c-4.155-1.522-6.604-5.646-6.207-9.858l-2.896-1.06 c-0.918,5.798,2.354,11.64,8.07,13.735C18.178,32.604,25.395,29.259,27.773,22.766z"/>
</svg>

After

Width:  |  Height:  |  Size: 660 B

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<g>
<g>
<path fill="#444444" d="M91.9,30.6H75.8l-10.2-14c-0.7-1-1.9-1.6-3.1-1.6H38.8c-1.2,0-2.4,0.6-3.1,1.6l-9.6,14H8.5c-1.9,0-3.5,1.6-3.5,3.5v49.4 c0,1.9,1.6,3.5,3.5,3.5h83.4c1.9,0,3.5-1.6,3.5-3.5V34.1C95.5,32.2,93.9,30.6,91.9,30.6z M88.4,80H12.1V37.6h16.8 c1.7,0,3.1-1.2,3.5-2.8l8.5-12.3h19.8l9,12.3c0.4,1.6,1.8,2.8,3.4,2.8h15.4V80z"/>
<g>
<path fill="#A66900" d="M50.2,73.9c-9.8,0-17.7-7.9-17.7-17.7s7.9-17.7,17.7-17.7s17.7,7.9,17.7,17.7S60,73.9,50.2,73.9z M50.2,46.1 c-5.6,0-10.1,4.5-10.1,10.1s4.5,10.1,10.1,10.1s10.1-4.5,10.1-10.1S55.8,46.1,50.2,46.1z"/>
</g>
<g>
<circle fill="#A66900" cx="79.8" cy="44.7" r="2.4"/></g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 957 B

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<g>
<g>
<path fill="#444444" d="M91.9,30.6H75.8l-10.2-14c-0.7-1-1.9-1.6-3.1-1.6H38.8c-1.2,0-2.4,0.6-3.1,1.6l-9.6,14H8.5c-1.9,0-3.5,1.6-3.5,3.5v49.4 c0,1.9,1.6,3.5,3.5,3.5h83.4c1.9,0,3.5-1.6,3.5-3.5V34.1C95.5,32.2,93.9,30.6,91.9,30.6z M88.4,80H12.1V37.6h16.8 c1.7,0,3.1-1.2,3.5-2.8l8.5-12.3h19.8l9,12.3c0.4,1.6,1.8,2.8,3.4,2.8h15.4V80z"/>
<g>
<path fill="#444444" d="M50.2,73.9c-9.8,0-17.7-7.9-17.7-17.7s7.9-17.7,17.7-17.7s17.7,7.9,17.7,17.7S60,73.9,50.2,73.9z M50.2,46.1 c-5.6,0-10.1,4.5-10.1,10.1s4.5,10.1,10.1,10.1s10.1-4.5,10.1-10.1S55.8,46.1,50.2,46.1z"/>
</g>
<g>
<circle fill="#444444" cx="79.8" cy="44.7" r="2.4"/></g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 957 B

View File

@ -1,4 +1,5 @@
(ns day8.re-frame.trace.components.container (ns day8.re-frame.trace.components.container
(:require-macros [day8.re-frame.trace.utils.macros :as macros])
(:require [mranderson047.re-frame.v0v10v2.re-frame.core :as rf] (:require [mranderson047.re-frame.v0v10v2.re-frame.core :as rf]
[re-frame.db :as db] [re-frame.db :as db]
[day8.re-frame.trace.panels.app-db :as app-db] [day8.re-frame.trace.panels.app-db :as app-db]
@ -6,35 +7,67 @@
[day8.re-frame.trace.panels.traces :as traces] [day8.re-frame.trace.panels.traces :as traces]
[day8.re-frame.trace.panels.subs :as subs] [day8.re-frame.trace.panels.subs :as subs]
[re-frame.trace] [re-frame.trace]
[reagent.core :as r])) [reagent.core :as r]
[day8.re-frame.trace.utils.re-com :as rc]))
(defn tab-button [panel-id title] (defn tab-button [panel-id title]
(let [selected-tab @(rf/subscribe [:settings/selected-tab])] (let [selected-tab @(rf/subscribe [:settings/selected-tab])]
[:button {:class (str "tab button " (when (= selected-tab panel-id) "active")) [:button {:class (str "tab button " (when (= selected-tab panel-id) "active"))
:on-click #(rf/dispatch [:settings/selected-tab panel-id])} title])) :on-click #(rf/dispatch [:settings/selected-tab panel-id])} title]))
(def reload (macros/slurp-macro "day8/re_frame/trace/images/reload.svg"))
(def reload-disabled (macros/slurp-macro "day8/re_frame/trace/images/reload-disabled.svg"))
(def open-external (macros/slurp-macro "day8/re_frame/trace/images/open-external.svg"))
(def snapshot (macros/slurp-macro "day8/re_frame/trace/images/snapshot.svg"))
(def snapshot-ready (macros/slurp-macro "day8/re_frame/trace/images/snapshot-ready.svg"))
(defn devtools-inner [traces opts] (defn devtools-inner [traces opts]
(let [selected-tab (rf/subscribe [:settings/selected-tab]) (let [selected-tab (rf/subscribe [:settings/selected-tab])
panel-type (:panel-type opts) panel-type (:panel-type opts)
external-window? (= panel-type :popup) external-window? (= panel-type :popup)
unloading? (rf/subscribe [:global/unloading?])] unloading? (rf/subscribe [:global/unloading?])
snapshot-ready? (rf/subscribe [:snapshot/snapshot-ready?])]
[:div.panel-content [:div.panel-content
{:style {:width "100%" :display "flex" :flex-direction "column"}} {:style {:width "100%" :display "flex" :flex-direction "column"}}
[rc/h-box
:class "panel-content-top nav"
:justify :between
:children
[[rc/h-box
:children
[(tab-button :traces "Traces")
(tab-button :app-db "App DB")
(tab-button :subs "Subs")
#_(tab-button :subvis "SubVis")
]]
[rc/h-box
:align :center
:children
[[:img.nav-icon
{:title "Load app-db snapshot"
:class (when-not @snapshot-ready? "inactive")
:src (str "data:image/svg+xml;utf8,"
(if @snapshot-ready?
reload
reload-disabled))
:on-click #(rf/dispatch-sync [:snapshot/load-snapshot])}]
[:img.nav-icon
{:title "Snapshot app-db"
:class (when @snapshot-ready? "active")
:src (str "data:image/svg+xml;utf8,"
(if @snapshot-ready?
snapshot-ready
snapshot))
:on-click #(rf/dispatch-sync [:snapshot/save-snapshot])}]
(when-not external-window?
[:img.nav-icon.active
{:src (str "data:image/svg+xml;utf8,"
open-external)
:on-click #(rf/dispatch-sync [:global/launch-external])}])]]]]
(when (and external-window? @unloading?) (when (and external-window? @unloading?)
[:h1.host-closed "Host window has closed. Reopen external window to continue tracing."]) [:h1.host-closed "Host window has closed. Reopen external window to continue tracing."])
(when-not (re-frame.trace/is-trace-enabled?) (when-not (re-frame.trace/is-trace-enabled?)
[:h1.host-closed {:style {:word-wrap "break-word"}} "Tracing is not enabled. Please set " [:pre "{\"re_frame.trace.trace_enabled_QMARK_\" true}"] " in " [:pre ":closure-defines"]]) [:h1.host-closed {:style {:word-wrap "break-word"}} "Tracing is not enabled. Please set " [:pre "{\"re_frame.trace.trace_enabled_QMARK_\" true}"] " in " [:pre ":closure-defines"]])
[:div.panel-content-top
[:div.nav
(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,"
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 8 8\" x=\"0px\" y=\"0px\">\n <path fill=\"#444444\" d=\"M0 0v8h8v-2h-1v1h-6v-6h1v-1h-2zm4 0l1.5 1.5-2.5 2.5 1 1 2.5-2.5 1.5 1.5v-4h-4z\"/>\n</svg>\n")
:on-click #(rf/dispatch-sync [:global/launch-external])}])]]
(case @selected-tab (case @selected-tab
:traces [traces/render-trace-panel traces] :traces [traces/render-trace-panel traces]
:app-db [app-db/render-state db/app-db] :app-db [app-db/render-state db/app-db]

View File

@ -5,6 +5,7 @@
[day8.re-frame.trace.utils.localstorage :as localstorage] [day8.re-frame.trace.utils.localstorage :as localstorage]
[clojure.string :as str] [clojure.string :as str]
[reagent.core :as r] [reagent.core :as r]
[re-frame.db]
[day8.re-frame.trace.components.container :as container] [day8.re-frame.trace.components.container :as container]
[day8.re-frame.trace.styles :as styles])) [day8.re-frame.trace.styles :as styles]))
@ -208,3 +209,16 @@
(conj paths path))] (conj paths path))]
(localstorage/save! "app-db-json-ml-expansions" new-paths) (localstorage/save! "app-db-json-ml-expansions" new-paths)
new-paths))) new-paths)))
(rf/reg-event-db
:snapshot/save-snapshot
[(rf/path [:snapshot])]
(fn [snapshot _]
(assoc snapshot :current-snapshot @re-frame.db/app-db)))
(rf/reg-event-db
:snapshot/load-snapshot
[(rf/path [:snapshot])]
(fn [snapshot _]
(reset! re-frame.db/app-db (:current-snapshot snapshot))
snapshot))

View File

@ -225,11 +225,14 @@
[:.icon-button {:font-size "10px"}] [:.icon-button {:font-size "10px"}]
[:button.tab {}] [:button.tab {}]
[:.popout-icon [:.nav-icon
{:max-width "15px" {:width "15px"
:height "15px"
:cursor "pointer" :cursor "pointer"
:padding "0 5px" :padding "0 5px"
:margin "0 5px"}] :margin "0 5px"}
["&.inactive"
{:cursor "initial"}]]
[:.tab [:.tab
{:background "transparent" {:background "transparent"
:border-radius 0 :border-radius 0

View File

@ -66,3 +66,16 @@
:global/unloading? :global/unloading?
(fn [db _] (fn [db _]
(get-in db [:global :unloading?]))) (get-in db [:global :unloading?])))
;;
(rf/reg-sub
:snapshot/snapshot-root
(fn [db _]
(:snapshot db)))
(rf/reg-sub
:snapshot/snapshot-ready?
:<- [:snapshot/snapshot-root]
(fn [snapshot _]
(contains? snapshot :current-snapshot)))