Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project config settings #402

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,36 @@ Reagent Versions | React Versions | re-frame-10x Artifact | Status |

re-frame-10x includes an experimental code tracing feature for tracing the code in your event handlers. See [day8/re-frame-debux](https://github.com/day8/re-frame-debux) for instructions on how to set it up.

### Project configuration

For some settings, re-frame-10x supports project-level configuration via additional [closure-defines](https://clojurescript.org/reference/compiler-options#closure-defines). This way, some default behavior of 10x can be version-controlled alongside your project. Example:

```cljs
{:closure-defines
{re-frame.trace.trace-enabled? true
day8.re-frame.tracing.trace-enabled? true
day8.re-frame-10x.hidden-namespaces "[com.me.uninteresting re-com.box]"}}
```

- Settings which are already stored take precedence. Be sure to [clear your localStorage](#factory-reset) for your project-level config to take effect.

- Keys always begin with `day8.re-frame-10x.`

- Any value which is a collection must appear stringified, due to [limitations in the closure compiler](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#define-type-description)

Supported keys:

name | description | type | example
------------------|--------------|----------------|-------
...`history-size` | how many epochs to retain | integer | `25`
...`ignored-events` | ignore events of this type | seq of keywords | `"[:init :event-B]"`
...`hidden-namespaces` | hide trace from these namespaces | seq of symbols | `"[re-com.box re-com.input-text]"`
...`time-travel?` | selecting an event reverts your app-db | boolean | `true`
...`ignored-libs` | ignore low-level trace | seq of keywords | `"[:reagent :re-frame]"`
...`ns-aliases` | display aliased keywords in data inspectors | map of symbol->symbol | `"{long-namespace ln}"`



## Usage

- **Make sure you have followed all of the installation instructions above.**
Expand Down
42 changes: 21 additions & 21 deletions examples/todomvc/shadow-cljs.edn
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@
:nrepl {:port 8777}

:builds
{:app
{:target :browser
:output-dir "resources/public/js"
:modules
{:todomvc
{:init-fn todomvc.core/main
:preloads [day8.re-frame-10x.preload]}}
:dev
{:compiler-options
{:infer-externs false
:closure-defines
{re-frame.trace.trace-enabled? true
day8.re-frame-10x.debug? true
day8.re-frame.tracing.trace-enabled? true}
:external-config
{:devtools/config
{:features-to-install
[:formatters :hints]}}}}
:devtools
{:http-root "resources/public"
:http-port 8280}}}}
{:app
{:target :browser
:output-dir "resources/public/js"
:modules
{:todomvc
{:init-fn todomvc.core/main
:preloads [day8.re-frame-10x.preload]}}
:dev
{:compiler-options
{:infer-externs false
:closure-defines
{re-frame.trace.trace-enabled? true
day8.re-frame-10x.debug? true
day8.re-frame.tracing.trace-enabled? true}
:external-config
{:devtools/config
{:features-to-install
[:formatters :hints]}}}}
:devtools
{:http-root "resources/public"
:http-port 8280}}}}
25 changes: 24 additions & 1 deletion src/day8/re_frame_10x.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
[day8.re-frame-10x.inlined-deps.spade.git-sha-93ef290.react :as spade.react]
[day8.reagent.impl.batching :refer [patch-next-tick]]
[day8.reagent.impl.component :refer [patch-wrap-funs patch-custom-wrapper]]
[day8.re-frame-10x.tools.coll :refer [sortable-uuid-map pred-map]]
[day8.re-frame-10x.tools.datafy :as tools.datafy]
[day8.re-frame-10x.tools.reader.edn :as reader.edn]
[day8.re-frame-10x.tools.shadow-dom :as tools.shadow-dom]
[day8.re-frame-10x.events :as events]
[day8.re-frame-10x.components.re-com :as rc]
Expand Down Expand Up @@ -146,8 +148,29 @@
(patch-wrap-funs)
(patch-next-tick))

(goog-define history-size 25)
(goog-define ignored-events "{}")
(goog-define hidden-namespaces "[re-com.box re-com.input-text]")
(goog-define time-travel? true)
(goog-define ignored-libs "[:reagent :re-frame]")
(goog-define ns-aliases "{long-namespace ln}")

(def project-config
(let [read reader.edn/read-string-maybe
keep-vals (remove (comp nil? second))
view #(do {:ns % :ns-str (str %)})
alias (fn [[k v]] {:ns-full (str k) :ns-alias (str v)})]
(->> {:debug? debug?
:retained-epochs history-size
:ignored-events (some-> ignored-events read sortable-uuid-map)
:filtered-view-trace (some->> hidden-namespaces read (map view) sortable-uuid-map)
:app-db-follows-events? time-travel?
:low-level-trace (some-> ignored-libs read (pred-map #{:re-frame :reagent}))
:ns-aliases (some->> ns-aliases read (map alias) sortable-uuid-map)}
(into {} keep-vals))))

(defn init!
[]
(patch!)
(rf/dispatch-sync [::events/init {:debug? debug?}])
(rf/dispatch-sync [::events/init project-config])
(inject!))
98 changes: 50 additions & 48 deletions src/day8/re_frame_10x/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
[day8.re-frame-10x.navigation.views :as navigation.views]
[day8.re-frame-10x.panels.app-db.events :as app-db.events]
[day8.re-frame-10x.panels.settings.events :as settings.events]
[day8.re-frame-10x.panels.traces.events :as traces.events]))
[day8.re-frame-10x.panels.traces.events :as traces.events]
[day8.re-frame-10x.tools.coll :refer [sortable-uuid-map]]))

(rf/reg-event-fx
::init
Expand All @@ -21,15 +22,16 @@
(rf/inject-cofx ::local-storage/load {:key "filter-items" :or []})
(rf/inject-cofx ::local-storage/load {:key "app-db-json-ml-expansions" :or #{}})
(rf/inject-cofx ::local-storage/load {:key "external-window?" :or false})
(rf/inject-cofx ::local-storage/load {:key "external-window-dimensions" :or {:width 800 :height 800 :top 0 :left 0}})
(rf/inject-cofx ::local-storage/load {:key "external-window-dimensions"
:or {:width 800 :height 800 :top 0 :left 0}})
(rf/inject-cofx ::local-storage/load {:key "show-epoch-traces?" :or true})
(rf/inject-cofx ::local-storage/load {:key "using-trace?" :or true})
(rf/inject-cofx ::local-storage/load {:key "ignored-events" :or {}})
(rf/inject-cofx ::local-storage/load {:key "low-level-trace" :or {:reagent true :re-frame true}})
(rf/inject-cofx ::local-storage/load {:key "filtered-view-trace" :or (let [id1 (random-uuid)
id2 (random-uuid)]
{id1 {:id id1 :ns-str "re-com.box" :ns 're-com.box :sort 0}
id2 {:id id2 :ns-str "re-com.input-text" :ns 're-com.input-text :sort 1}})})
(rf/inject-cofx ::local-storage/load {:key "filtered-view-trace"
:or (sortable-uuid-map
[{:ns 're-com.box :ns-str "re-com.box"}
{:ns 're-com.input-text :ns-str "re-com.input-text"}])})
(rf/inject-cofx ::local-storage/load {:key "retained-epochs" :or 25})
(rf/inject-cofx ::local-storage/load {:key "app-db-paths" :or {}})
(rf/inject-cofx ::local-storage/load {:key "app-db-follows-events?" :or true})
Expand All @@ -47,49 +49,49 @@
:shiftKey true}}})
(rf/inject-cofx ::local-storage/load {:key "log-outputs" :or [:day8.re-frame-10x.fx.log/console]})
(rf/inject-cofx ::local-storage/load {:key "log-pretty?" :or true})
(rf/inject-cofx ::local-storage/load {:key "ns-aliases" :or
(let [id (random-uuid)]
{id {:id id :ns-full "long-namespace" :ns-alias "ln"}})})
(rf/inject-cofx ::local-storage/load {:key "ns-aliases"
:or (sortable-uuid-map [{:ns-full "long-namespace" :ns-alias "ln"}])})
rf/unwrap]
(fn [{:keys [panel-width-ratio show-panel selected-tab filter-items app-db-json-ml-expansions
external-window? external-window-dimensions show-epoch-traces? using-trace?
ignored-events low-level-trace filtered-view-trace retained-epochs app-db-paths
app-db-follows-events? ambiance syntax-color-scheme categories data-path-annotations?
show-event-history open-new-inspectors? handle-keys? key-bindings log-outputs log-pretty?
ns-aliases]}
{:keys [debug?]}]
{:fx [(when using-trace?
[:dispatch [::settings.events/enable-tracing]])
[:dispatch [::settings.events/panel-width% panel-width-ratio]]
[:dispatch [::settings.events/show-panel? show-panel]]
[:dispatch [::settings.events/selected-tab selected-tab]]
[:dispatch [::settings.events/set-ignored-events ignored-events]]
[:dispatch [::settings.events/set-filtered-view-trace filtered-view-trace]]
[:dispatch [::settings.events/set-low-level-trace low-level-trace]]
[:dispatch [::settings.events/set-number-of-retained-epochs retained-epochs]]
[:dispatch [::settings.events/app-db-follows-events? app-db-follows-events?]]
[:dispatch [::settings.events/set-ambiance ambiance]]
[:dispatch [::settings.events/set-syntax-color-scheme syntax-color-scheme]]
[:dispatch [::settings.events/debug? debug?]]
;; Important that window dimensions are set before we open an external window.
[:dispatch [::settings.events/external-window-dimensions external-window-dimensions]]
[:dispatch [::app-db.events/set-data-path-annotations? data-path-annotations?]]
(when external-window?
[:dispatch [::navigation.events/launch-external navigation.views/mount]])
[:dispatch [::traces.events/set-queries filter-items]]
[:dispatch [::traces.events/set-categories categories]]
[:dispatch [::traces.events/set-filter-by-selected-epoch? show-epoch-traces?]]
[:dispatch [::app-db.events/paths (into (sorted-map) app-db-paths)]]
[:dispatch [::app-db.events/set-json-ml-paths app-db-json-ml-expansions]]
[:dispatch [:global/add-unload-hook]]
[:dispatch [::app-db.events/reagent-id]]
[:dispatch [::settings.events/show-event-history? show-event-history]]
[:dispatch [::settings.events/open-new-inspectors? open-new-inspectors?]]
[:dispatch [::settings.events/handle-keys? handle-keys?]]
[:dispatch [::settings.events/key-bindings key-bindings]]
[:dispatch [::settings.events/log-outputs log-outputs]]
[:dispatch [::settings.events/log-pretty? log-pretty?]]
[:dispatch [::settings.events/ns-aliases ns-aliases]]]}))
(fn [{::local-storage/keys [stored fallback]} project-config]
(let [{:keys [panel-width-ratio show-panel selected-tab filter-items app-db-json-ml-expansions
external-window? external-window-dimensions show-epoch-traces? using-trace?
ignored-events low-level-trace filtered-view-trace retained-epochs app-db-paths
app-db-follows-events? ambiance syntax-color-scheme categories data-path-annotations?
show-event-history open-new-inspectors? handle-keys? key-bindings log-outputs log-pretty?
ns-aliases debug?]}
(merge fallback project-config stored)]
{:fx [(when using-trace?
[:dispatch [::settings.events/enable-tracing]])
[:dispatch [::settings.events/panel-width% panel-width-ratio]]
[:dispatch [::settings.events/show-panel? show-panel]]
[:dispatch [::settings.events/selected-tab selected-tab]]
[:dispatch [::settings.events/set-ignored-events ignored-events]]
[:dispatch [::settings.events/set-filtered-view-trace filtered-view-trace]]
[:dispatch [::settings.events/set-low-level-trace low-level-trace]]
[:dispatch [::settings.events/set-number-of-retained-epochs retained-epochs]]
[:dispatch [::settings.events/app-db-follows-events? app-db-follows-events?]]
[:dispatch [::settings.events/set-ambiance ambiance]]
[:dispatch [::settings.events/set-syntax-color-scheme syntax-color-scheme]]
[:dispatch [::settings.events/debug? debug?]]
;; Important that window dimensions are set before we open an external window.
[:dispatch [::settings.events/external-window-dimensions external-window-dimensions]]
[:dispatch [::app-db.events/set-data-path-annotations? data-path-annotations?]]
(when external-window?
[:dispatch [::navigation.events/launch-external navigation.views/mount]])
[:dispatch [::traces.events/set-queries filter-items]]
[:dispatch [::traces.events/set-categories categories]]
[:dispatch [::traces.events/set-filter-by-selected-epoch? show-epoch-traces?]]
[:dispatch [::app-db.events/paths (into (sorted-map) app-db-paths)]]
[:dispatch [::app-db.events/set-json-ml-paths app-db-json-ml-expansions]]
[:dispatch [:global/add-unload-hook]]
[:dispatch [::app-db.events/reagent-id]]
[:dispatch [::settings.events/show-event-history? show-event-history]]
[:dispatch [::settings.events/open-new-inspectors? open-new-inspectors?]]
[:dispatch [::settings.events/handle-keys? handle-keys?]]
[:dispatch [::settings.events/key-bindings key-bindings]]
[:dispatch [::settings.events/log-outputs log-outputs]]
[:dispatch [::settings.events/log-pretty? log-pretty?]]
[:dispatch [::settings.events/ns-aliases ns-aliases]]]})))

;; Global

Expand Down
22 changes: 11 additions & 11 deletions src/day8/re_frame_10x/fx/local_storage.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,10 @@

(defn load
"Loads a re-frame-10x value from local storage."
([key]
(load key nil))
([key not-found]
(let [value (.get storage (safe-key key))]
(if (undefined? value)
not-found
(reader/read-string value)))))
[key]
(let [value (.get storage (safe-key key))]
(when-not (undefined? value)
(reader/read-string value))))

(defn- all-keys []
(try
Expand Down Expand Up @@ -66,7 +63,10 @@

(rf/reg-cofx
::load
(fn [coeffects {:keys [key or]}]
(assoc coeffects
(keyword key)
(load key or))))
(fn [coeffects {storage-key :key fallback :or}]
(let [k (keyword storage-key)
v (load storage-key)]
(cond-> coeffects
:do (assoc k (or v fallback))
v (assoc-in [::stored k] v)
fallback (assoc-in [::fallback k] fallback)))))
13 changes: 12 additions & 1 deletion src/day8/re_frame_10x/tools/coll.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,15 @@
:else
(get ret k)))
m
ks))
ks))

(defn sortable-uuid-map [ms]
(let [entry (fn [id v i]
[id (into {:id id :sort i} v)])]
(into {} (map entry (repeatedly random-uuid) ms (range)))))

(defn pred-map [ks possible-ks]
(let [ks (set ks)]
(into {}
(map #(do [% (contains? ks %)]))
possible-ks)))
Loading