Skip to content

Commit

Permalink
Add short share links for named examples. See #115
Browse files Browse the repository at this point in the history
  • Loading branch information
katauber committed Jun 21, 2023
1 parent 90ec14a commit d67d369
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 102 deletions.
15 changes: 12 additions & 3 deletions src/cljs/metafacture_playground/effects.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns metafacture-playground.effects
(:require [re-frame.core :as re-frame]
[clojure.string :as clj-str]))
[clojure.string :as clj-str]
[lambdaisland.uri :refer [uri assoc-query*]]))

(re-frame/reg-fx
::copy-to-clipboard
Expand All @@ -14,10 +15,18 @@

(re-frame/reg-fx
::unset-url-query-params
(fn [href]
(let [new-href (clj-str/replace href #"\?.*" "")]
(fn [& [href]]
(let [href (or href (-> js/window .-location .-href))
new-href (clj-str/replace href #"\?.*" "")]
(-> js/window .-history (.replaceState {} "" new-href)))))

(re-frame/reg-fx
::set-url-query-params
(fn [example]
(let [href (-> js/window .-location .-href)
href-with-params (-> href uri (assoc-query* {:example example}))]
(-> js/window .-history (.replaceState {} "" href-with-params)))))

(defn- file-blob [datamap mimetype]
(js/Blob. [datamap] {"type" mimetype}))

Expand Down
149 changes: 99 additions & 50 deletions src/cljs/metafacture_playground/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
;;; Editing input fields

(defn edit-value
[{db :db} [_ field-name new-value & triggered-by-button?]]
[{db :db} [_ field-name new-value & [triggered-by-code?]]]
(let [db-path [:input-fields field-name :content]
disable-editors (when (= field-name :flux)
(let [val (-> new-value
Expand All @@ -140,23 +140,31 @@
fix-used? (boolean (re-find #"\|fix\|" val))]
{[:input-fields :data :disabled?] (not data-used?)
[:input-fields :morph :disabled?] (not morph-used?)
[:input-fields :fix :disabled?] (not fix-used?)}))]
[:input-fields :fix :disabled?] (not fix-used?)}))
db (cond-> (reduce
(fn [db [path v]]
(assoc-in db path v))
db
disable-editors)
true (assoc-in db-path new-value)
triggered-by-code? (update-in [:input-fields field-name :key-count] inc)
(not triggered-by-code?) (assoc-in [:ui :dropdown :active-item] nil))]
{:db (cond-> (reduce
(fn [db [path v]]
(assoc-in db path v))
db
disable-editors)
true (assoc-in db-path new-value)
triggered-by-button? (update-in [:input-fields field-name :key-count] inc)
(not triggered-by-button?) (assoc-in [:ui :dropdown :active-item] nil))
triggered-by-code? (update-in [:input-fields field-name :key-count] inc)
(not triggered-by-code?) (assoc-in [:ui :dropdown :active-item] nil))
:storage/set {:session? true
:pairs (conj
(mapv
(fn [[db-path v]]
{:name (->storage-key db-path) :value v})
disable-editors)
{:name (->storage-key db-path) :value new-value}
(when-not triggered-by-button? {:name (->storage-key [:ui :dropdown :active-item]) :value nil}))}
(when-not triggered-by-code? {:name (->storage-key [:ui :dropdown :active-item]) :value nil}))}
:dispatch [::update-width field-name new-value]}))

(re-frame/reg-event-fx
Expand All @@ -171,24 +179,43 @@
::open-dropdown
open-dropdown)

(defn load-sample
[{db :db} [_ dropdown-value sample]]
{:db (-> db
(assoc :result nil)
(assoc-in [:ui :dropdown :active-item] dropdown-value))
:fx (conj
(mapv
(fn [editor]
[:dispatch [::edit-input-value editor (get sample editor "") true]])
[:data :flux :fix :morph])
[:dispatch [::switch-editor (:active-editor sample)]])
:storage/set {:session? true
:name (->storage-key [:ui :dropdown :active-item])
:value dropdown-value}})
(defn- find-example-data [example-name data]
(some #(cond
(and (map? (val %))
(= (-> % key utils/display-name) example-name))
(val %)

(and (map? (val %))
(not-any? #{:data :flux :fix :morph} (keys (val %))))
(find-example-data example-name (val %))

:else false)
data))

(defn load-example
[{db :db} [_ example-name]]
(let [example-data (find-example-data example-name (:examples db))]
(if example-data
{:db (-> db
(assoc :result nil)
(assoc-in [:ui :dropdown :active-item] example-name))
:fx (conj
(mapv
(fn [editor]
[:dispatch [::edit-input-value editor (get example-data editor "") true]])
[:data :flux :fix :morph])
[:dispatch [::switch-editor (:active-editor example-data)]])
:storage/set {:session? true
:name (->storage-key [:ui :dropdown :active-item])
:value example-name}
::effects/set-url-query-params example-name}
{:db (assoc db :message {:content (str "Could not find example with name \"" example-name "\".")
:type :warning})
::effects/unset-url-query-params nil})))

(re-frame/reg-event-fx
::load-sample
load-sample)
::load-example
load-example)

(defn switch-editor
[{db :db} [_ editor]]
Expand Down Expand Up @@ -493,28 +520,44 @@

;;; Initialize-db

(defn- links->examples []
(map
(fn [[k v]]
(if (map? v)
{k (into (sorted-map)
(links->examples)
v)}
{(utils/display-name k) (utils/parse-url v)}))))

(defn examples-response
[{db :db} [_ {:keys [body]}]]
[{db :db} [_ initial-example {:keys [body]}]]
(let [body (transit/read (transit/reader :json) body)]
{:db (assoc db :examples body)}))
(if initial-example
{:db (assoc db :examples (into (sorted-map)
(links->examples)
body))
:fx [[:dispatch [::load-example initial-example]]]}
{:db (assoc db :examples (into (sorted-map)
(links->examples)
body))})))

(re-frame/reg-event-fx
::examples-response
examples-response)

(defn load-samples
[{db :db} _]
(defn load-examples
[{db :db} [_ initial-example]]
{:db db
:fetch {:method :get
:url "examples"
:timeout 10000
:response-content-types {#"application/.*json" :json}
:on-success [::examples-response]
:on-success [::examples-response initial-example]
:on-failure [::bad-response]}})

(re-frame/reg-event-fx
::load-samples
load-samples)
::load-examples
load-examples)

(defn versions-response
[{db :db} [_ {:keys [body]}]]
Expand Down Expand Up @@ -556,28 +599,34 @@
(defn initialize-db
[{[_ href window-height] :event
web-storage :storage/all}]
(let [query-params (utils/parse-url href)]
(if (empty? query-params)
{:db (deep-merge
db/default-db
(restore-db web-storage)
{:ui {:height window-height}})
:fx [[:dispatch [::load-samples]]
[:dispatch [::get-backend-versions]]]}
{:db (-> db/default-db
(assoc-in [:ui :height] window-height))
:fx (cond->
(mapv
(fn [editor]
[:dispatch [::edit-input-value editor (get query-params editor "")]])
[:data :flux :fix :morph])
true (conj [:dispatch [::load-samples]])
true (conj [:dispatch [::get-backend-versions]])
(get query-params :active-editor) (conj [:dispatch [::switch-editor (-> query-params :active-editor keyword)]]))
:storage/set {:session? true
:pairs (-> (assoc-query-params {} query-params)
generate-pairs)}
::effects/unset-url-query-params href})))
(let [query-params (utils/parse-url href)
fx [[:dispatch [::get-backend-versions]]]]
(cond
(empty? query-params) {:db (deep-merge
db/default-db
(restore-db web-storage)
{:ui {:height window-height}})
:fx (conj fx [:dispatch [::load-examples]])}
(:example query-params) {:db (-> db/default-db
(assoc-in [:ui :height] window-height))
:fx (conj fx [:dispatch [::load-examples (get query-params :example)]])
:storage/set {:session? true
:pairs (-> (assoc-query-params {} query-params)
generate-pairs)}}
:else {:db (-> db/default-db
(assoc-in [:ui :height] window-height))
:fx (concat fx
[[:dispatch [::load-examples]]]
(mapv
(fn [editor]
[:dispatch [::edit-input-value editor (get query-params editor "")]])
[:data :flux :fix :morph])
(when-let [active-editor (get query-params :active-editor)]
[[:dispatch [::switch-editor (keyword active-editor)]]]))
:storage/set {:session? true
:pairs (-> (assoc-query-params {} query-params)
generate-pairs)}
::effects/unset-url-query-params href})))

(re-frame/reg-event-fx
::initialize-db
Expand Down
20 changes: 2 additions & 18 deletions src/cljs/metafacture_playground/subs.cljs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
(ns metafacture-playground.subs
(:require
[re-frame.core :as re-frame]
[clojure.string :as clj-str]
[metafacture-playground.utils :as utils]))
[clojure.string :as clj-str]))

(defn- expand-indentation [details]
(when details
Expand Down Expand Up @@ -31,25 +30,10 @@
(fn [db [_ folder]]
(get-in db [:ui :dropdown folder :open?])))

(defn- display-name [str]
(clj-str/replace str "_" " "))

(defn- examples->dropdown-entries []
(map
(fn [[k v]]
(if (map? v)
{k (into (sorted-map)
(examples->dropdown-entries)
v)}
{k {:display-name (display-name k)
:value (utils/parse-url v)}}))))

(re-frame/reg-sub
::examples
(fn [db _]
(into (sorted-map)
(examples->dropdown-entries)
(get db :examples))))
(get db :examples)))

(re-frame/reg-sub
::editor-key
Expand Down
6 changes: 5 additions & 1 deletion src/cljs/metafacture_playground/utils.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
(ns metafacture-playground.utils
(:require
[lambdaisland.uri :refer [uri query-string->map]]))
[lambdaisland.uri :refer [uri query-string->map]]
[clojure.string :as clj-str]))

(defn display-name [s]
(clj-str/replace s "_" " "))

(defn parse-url [href]
(let [query-params (-> href
Expand Down
14 changes: 8 additions & 6 deletions src/cljs/metafacture_playground/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[goog.object :as g]
[re-pressed.core :as rp]
["@monaco-editor/react" :as monaco-react]
[cljs.pprint :as pprint]))
[metafacture-playground.utils :as utils]))

;;; Using semantic ui react components

Expand Down Expand Up @@ -201,7 +201,10 @@

(defn is-group? [entry]
(try
(when (-> entry val :display-name) false)
(when (or (-> entry val :data)
(-> entry val :flux)
(-> entry val :fix)
(-> entry val :morph)) false)
(catch :default _
true)))

Expand All @@ -217,9 +220,8 @@
:item true
:on-click #(re-frame/dispatch [::events/open-dropdown (key entry) (not @dropdown-open?)])}
(dropdown-entries (val entry))])
(let [[k v] entry
display-name (:display-name v)
value (:value v)
(let [[k _] entry
display-name (utils/display-name k)
dropdown-value (re-frame/subscribe [::subs/dropdown-active-item])]
^{:key k}
[:> dropdown-item
Expand All @@ -228,7 +230,7 @@
:value display-name
:active (= display-name @dropdown-value)
:selected (= display-name @dropdown-value)
:onClick #(re-frame/dispatch [::events/load-sample display-name value])}]))))])
:onClick #(re-frame/dispatch [::events/load-example display-name])}]))))])

(defn examples-dropdown []
[:> button-group {:color color
Expand Down
Loading

0 comments on commit d67d369

Please sign in to comment.