Skip to content

Commit

Permalink
Edit, save & restore the app-db and its subtrees
Browse files Browse the repository at this point in the history
  • Loading branch information
kimo-k committed Aug 22, 2023
1 parent c6a0688 commit ce39974
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 96 deletions.
4 changes: 4 additions & 0 deletions src/day8/re_frame_10x/components/re_com.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@
[& args]
(apply input-text-base :input-type :input args))

(defn input-textarea
[& args]
(apply input-text-base :input-type :textarea args))

(defn label
"Returns markup for a basic label"
[& {:keys [label on-click width class style attr]}]
Expand Down
62 changes: 62 additions & 0 deletions src/day8/re_frame_10x/panels/app_db/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(:require
[re-frame.db]
[re-frame.interop]
[re-frame.core]
[clojure.string :as string]
[day8.re-frame-10x.inlined-deps.re-frame.v1v1v2.re-frame.core :as rf]
[day8.re-frame-10x.fx.local-storage :as local-storage]
Expand Down Expand Up @@ -147,3 +148,64 @@
[(rf/path [:app-db :expand-all?]) rf/trim-v]
(fn [db [path-id expand?]]
(assoc db path-id expand?)))

(rf/reg-event-db
::start-edit
paths-interceptors
(fn [paths [id]]
(assoc-in paths [id :editing?] true)))

(rf/reg-event-db
::finish-edit
paths-interceptors
(fn [paths [id]]
(assoc-in paths [id :editing?] false)))

(rf/reg-event-db
::set-edit-str
paths-interceptors
(fn [paths [id s]]
(assoc-in paths [id :edit-str] s)))

(re-frame.core/reg-event-db
::edit
(fn [db [_ path s]]
(let [new-data (reader.edn/read-string-maybe s)]
(if-not (seq path)
new-data
(assoc-in db path new-data)))))

(defn read-file [file callback]
(let [file-reader (js/FileReader.)]
(set! (.-onload ^js file-reader)
#(callback (.-name ^js file) (.-result (.-target %))))
(.readAsText ^js file-reader file)))

(rf/reg-fx :read-file
(fn [params]
(let [{:keys [file on-read]} params]
(read-file file (fn [_ content]
(rf/dispatch (conj on-read content)))))))

(rf/reg-event-fx
::open-file
(fn [_ [_ file on-read]]
{:read-file {:file file
:on-read on-read}}))

(rf/reg-fx
::save-to-file
(fn [s]
(let [blob (js/Blob. #js [s] #js {:type "text/plain"})
url (str (.createObjectURL js/URL blob))
link (js/document.createElement "a")]
(set! (.-href link) url)
(set! (.-download link) "re-frame-10x-db.edn")
(.appendChild js/document.body link)
(.click link)
(.remove link))))

(rf/reg-event-fx
::save-to-file
(fn [_ [_ s]]
{::save-to-file s}))
233 changes: 137 additions & 96 deletions src/day8/re_frame_10x/panels/app_db/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
[day8.re-frame-10x.panels.app-db.subs :as app-db.subs]
[day8.re-frame-10x.panels.event.events :as event.events]
[day8.re-frame-10x.tools.coll :as tools.coll]
[day8.re-frame-10x.tools.datafy :refer [pr-str-safe]]
[day8.re-frame-10x.fx.clipboard :as clipboard]))

(def pod-gap "-1px") ;; Overlap pods by 1px to avoid adjoining borders causing 2px borders
Expand Down Expand Up @@ -86,112 +87,148 @@
:attr attr
:children children]))

(defn pod-header [{:keys [id path path-str open? diff? sort?]} data]
(defn pod-header [{:keys [id path path-str open? diff? sort? editing? edit-str]} data]
(let [ambiance @(rf/subscribe [::settings.subs/ambiance])
expand-all? @(rf/subscribe [::app-db.subs/expand-all? id])
log-any? @(rf/subscribe [::settings.subs/any-log-outputs?])]
[rc/h-box
:class (styles/section-header ambiance)
:align :center
:height styles/gs-31s
[rc/v-box
:children
[[pod-header-section
[[rc/h-box
:class (styles/section-header ambiance)
:align :center
:height styles/gs-31s
:children
[[rc/box
:width "30px"
:height styles/gs-31s
:justify :center
:align :center
:class (styles/no-select)
:style {:cursor "pointer"}
:attr {:title (str (if open? "Close" "Open") " the pod bay doors, HAL")
:on-click (handler-fn (rf/dispatch [::app-db.events/set-path-visibility id (not open?)]))}
:child [buttons/expansion {:open? open?
:size styles/gs-31s}]]]]
[[pod-header-section
:children
[[rc/box
:width "30px"
:height styles/gs-31s
:justify :center
:align :center
:class (styles/no-select)
:style {:cursor "pointer"}
:attr {:title (str (if open? "Close" "Open") " the pod bay doors, HAL")
:on-click (handler-fn (rf/dispatch [::app-db.events/set-path-visibility id (not open?)]))}
:child [buttons/expansion {:open? open?
:size styles/gs-31s}]]]]

[rc/h-box
:class (styles/path-header-style ambiance)
:size "auto"
:style {:height styles/gs-31s
:border-right pod-border-edge}
:align :center
:children
[[rc/input-text
:class (styles/path-text-input-style ambiance)
:attr {:on-blur #(rf/dispatch [::app-db.events/update-path-blur id])}
:width "100%"
:model path-str
:on-change #(rf/dispatch [::app-db.events/update-path id %]) ;;(fn [input-string] (rf/dispatch [:app-db/search-string input-string]))
:on-submit #() ;; #(rf/dispatch [::app-db.events/add-path %])
:change-on-blur? false
:placeholder "enter an app-db path like [:todos 1]"]]]
[rc/h-box
:class (styles/path-header-style ambiance)
:size "auto"
:style {:height styles/gs-31s
:border-right pod-border-edge}
:align :center
:children
[[rc/input-text
:class (styles/path-text-input-style ambiance)
:attr {:on-blur #(rf/dispatch [::app-db.events/update-path-blur id])}
:width "100%"
:model path-str
:on-change #(rf/dispatch [::app-db.events/update-path id %]) ;;(fn [input-string] (rf/dispatch [:app-db/search-string input-string]))
:on-submit #() ;; #(rf/dispatch [::app-db.events/add-path %])
:change-on-blur? false
:placeholder "enter an app-db path like [:todos 1]"]]]

(when (> (count path) 0)
[buttons/icon
{:icon [material/clear]
:title "Clear path in current inspector"
:on-click #(rf/dispatch [::app-db.events/update-path id ""])}])
(when (> (count path) 0)
[buttons/icon
{:icon [material/clear]
:title "Clear path in current inspector"
:on-click #(rf/dispatch [::app-db.events/update-path id ""])}])

(when (> (count path) 0)
[rc/gap-f :size styles/gs-7s])
(when (> (count path) 0)
[rc/gap-f :size styles/gs-7s])

(when (> (count path) 0)
[buttons/icon
{:icon [material/arrow-drop-up]
:title "Open parent path in current inspector"
:on-click #(rf/dispatch [::app-db.events/update-path id (str (if (> (count path) 1) (pop path) ""))])}])
(when (> (count path) 0)
[buttons/icon
{:icon [material/arrow-drop-up]
:title "Open parent path in current inspector"
:on-click #(rf/dispatch [::app-db.events/update-path id (str (if (> (count path) 1) (pop path) ""))])}])

[pod-header-section
:width "49px"
:justify :center
:align :center
:attr {:on-click (handler-fn (rf/dispatch [::app-db.events/set-diff-visibility id (not diff?)]))}
:children
[[rc/checkbox
:model diff?
:label ""
#_#_:style {:margin-left "6px"
:margin-top "1px"}
:on-change #(rf/dispatch [::app-db.events/set-diff-visibility id (not diff?)])]]]
[pod-header-section
:width "49px"
:justify :center
:align :center
:attr {:on-click (handler-fn (rf/dispatch [::app-db.events/set-sort-form? id (not sort?)]))}
:children
[[rc/checkbox
:model sort?
:label ""
:on-change #(rf/dispatch [::app-db.events/set-sort-form? id (not sort?)])]]]
[pod-header-section
:width "49px"
:justify :center
:align :center
:attr {:on-click (handler-fn (rf/dispatch [::app-db.events/set-expand-all? id (not expand-all?)]))}
:children
[[buttons/icon {:icon [(if expand-all? material/unfold-less material/unfold-more)]
:title (str (if expand-all? "Close" "Expand") " all nodes in this inspector")
:on-click #(rf/dispatch [::app-db.events/set-expand-all? id (not expand-all?)])}]]]
[pod-header-section
:width styles/gs-50s
:justify :center
:children
[[buttons/icon
{:icon [material/close]
:title "Remove this inspector"
:on-click #(rf/dispatch [::app-db.events/remove-path id])}]]]
[pod-header-section
:width styles/gs-31s
:justify :center
:last? true
:children
[[rc/box
:style {:margin "auto"}
:child
(when log-any?
[buttons/icon {:icon [material/print]
:title "Dump inspector data into DevTools"
:on-click #(rf/dispatch [:global/log data])}])]]]]]))
[pod-header-section
:width "49px"
:justify :center
:align :center
:attr {:on-click (handler-fn (rf/dispatch [::app-db.events/set-diff-visibility id (not diff?)]))}
:children
[[rc/checkbox
:model diff?
:label ""
#_#_:style {:margin-left "6px"
:margin-top "1px"}
:on-change #(rf/dispatch [::app-db.events/set-diff-visibility id (not diff?)])]]]
[pod-header-section
:width "49px"
:justify :center
:align :center
:attr {:on-click (handler-fn (rf/dispatch [::app-db.events/set-sort-form? id (not sort?)]))}
:children
[[rc/checkbox
:model sort?
:label ""
:on-change #(rf/dispatch [::app-db.events/set-sort-form? id (not sort?)])]]]
[pod-header-section
:width "49px"
:justify :center
:align :center
:attr {:on-click (handler-fn (rf/dispatch [::app-db.events/set-expand-all? id (not expand-all?)]))}
:children
[[buttons/icon {:icon [(if expand-all? material/unfold-less material/unfold-more)]
:title (str (if expand-all? "Close" "Expand") " all nodes in this inspector")
:on-click #(rf/dispatch [::app-db.events/set-expand-all? id (not expand-all?)])}]]]
[pod-header-section
:width styles/gs-50s
:justify :center
:children
[[buttons/icon
{:icon [material/close]
:title "Remove this inspector"
:on-click #(rf/dispatch [::app-db.events/remove-path id])}]]]
[pod-header-section
:width styles/gs-50s
:justify :center
:children
[[buttons/icon {:icon [(if editing? material/unfold-less material/unfold-more)]
:title (str (if expand-all? "Close" "Expand") " the node editor")
:on-click (if editing?
#(rf/dispatch [::app-db.events/finish-edit id])
#(rf/dispatch [::app-db.events/start-edit id]))}]]]
[pod-header-section
:width styles/gs-31s
:justify :center
:last? true
:children
[[rc/box
:style {:margin "auto"}
:child
(when log-any?
[buttons/icon {:icon [material/print]
:title "Dump inspector data into DevTools"
:on-click #(rf/dispatch [:global/log data])}])]]]]]
(when editing?
[rc/h-box
:width "100%"
:children
[[rc/input-textarea
:change-on-blur? false
:model edit-str
:on-change #(rf/dispatch [::app-db.events/set-edit-str id %])]
[:input {:type "file"
:on-change #(rf/dispatch [::app-db.events/open-file
(first (.-files (.-target %)))
[::app-db.events/set-edit-str id]])}]
[buttons/icon
{:icon [material/arrow-drop-down]
:title "Save data to EDN"
:on-click #(rf/dispatch [::app-db.events/save-to-file (pr-str-safe data)])}]
[buttons/icon
{:icon [material/refresh]
:title "Copy data"
:on-click #(rf/dispatch [::app-db.events/set-edit-str id (pr-str-safe data)])}]
[buttons/icon
{:icon [material/check-circle-outline]
:title "Edit data"
:on-click #(re-frame.core/dispatch
[::app-db.events/edit path edit-str])}]]])]]))

(def diff-url "https://github.com/day8/re-frame-10x/blob/master/docs/HyperlinkedInformation/Diffs.md")

Expand Down Expand Up @@ -307,6 +344,10 @@
:width styles/gs-50s ;; 50px + 1 border
:justify :center
:child [rc/label :style {:font-size "9px"} :label "DELETE"]]
[rc/box
:width styles/gs-50s ;; 50px + 1 border
:justify :center
:child [rc/label :style {:font-size "9px"} :label "EDIT"]]
[rc/box
:width styles/gs-31s ;; 31px + 1 border
:justify :center
Expand Down

0 comments on commit ce39974

Please sign in to comment.