From ec6935a379bf0dc58ffa2ca23cdcef3021f9dfad Mon Sep 17 00:00:00 2001 From: Oliver Marshall Date: Tue, 14 May 2024 18:06:12 +0100 Subject: [PATCH 1/5] feat: update the url as the user types --- src/xt_fiddle/client.cljs | 36 ++++++++++++++++++++++++--------- src/xt_fiddle/query_params.cljs | 6 +++++- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/xt_fiddle/client.cljs b/src/xt_fiddle/client.cljs index bdd91c8..805d54b 100644 --- a/src/xt_fiddle/client.cljs +++ b/src/xt_fiddle/client.cljs @@ -18,6 +18,10 @@ (rf/reg-event-fx :share (fn [{:keys [db]}] + +(rf/reg-event-fx + :update-url + (fn [{:keys [db]} _] {::query-params/set {:version (:version db) :type (name (:type db)) :txs (tx-batch/param-encode (tx-batch/list db)) @@ -36,6 +40,11 @@ (fn [db [_ query]] (assoc db :query query))) +(rf/reg-event-fx + :fx + (fn [_ [_ effects]] + {:fx effects})) + (rf/reg-sub :get-type :-> :type) @@ -52,7 +61,8 @@ [dropdown {:items [{:value :sql :label "SQL"} {:value :xtql :label "XTQL"}] :selected @(rf/subscribe [:get-type]) - :on-click #(rf/dispatch [:dropdown-selection (:value %)]) + :on-click #(rf/dispatch [:fx [[:dispatch [:dropdown-selection (:value %)]] + [:dispatch [:update-url]]]]) :label (case @(rf/subscribe [:get-type]) :xtql "XTQL" :sql "SQL")}]) @@ -146,19 +156,22 @@ (defn reset-system-time-button [id] [:> ArrowUturnLeftIcon {:class "h-5 w-5 cursor-pointer" - :on-click #(rf/dispatch [::tx-batch/assoc id :system-time nil])}]) + :on-click #(rf/dispatch [:fx [[:dispatch [::tx-batch/assoc id :system-time nil]] + [:dispatch [:update-url]]]])}]) (defn input-system-time [id system-time] ;; TODO: Show the picker when someone clicks the edit button ;; https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/showPicker [:input {:type "date" :value (-> system-time .toISOString (str/split #"T") first) - :on-change #(rf/dispatch [::tx-batch/assoc id :system-time (js/Date. (.. % -target -value))]) + :on-change #(rf/dispatch [:fx [[:dispatch [::tx-batch/assoc id :system-time (js/Date. (.. % -target -value))]] + [:dispatch [:update-url]]]]) :max (-> (js/Date.) .toISOString (str/split #"T") first)}]) (defn edit-system-time-button [id] [:> PencilIcon {:className "h-5 w-5 cursor-pointer" - :on-click #(rf/dispatch [::tx-batch/assoc id :system-time (js/Date. (.toDateString (js/Date.)))])}]) + :on-click #(rf/dispatch [:fx [[:dispatch [::tx-batch/assoc id :system-time (js/Date. (.toDateString (js/Date.)))]] + [:dispatch [:update-url]]]])}]) (defn single-transaction [{:keys [editor id]} {:keys [system-time txs]}] [:div {:class "h-full flex flex-col"} @@ -168,7 +181,8 @@ [reset-system-time-button id]]) [editor {:class "border md:flex-grow min-h-36" :source txs - :change-callback #(rf/dispatch [::tx-batch/assoc id :txs %])}]]) + :change-callback #(rf/dispatch [:fx [[:dispatch [::tx-batch/assoc id :txs %]] + [:dispatch [:update-url]]]])}]]) (defn multiple-transactions [{:keys [editor]} tx-batches] [:<> @@ -185,10 +199,12 @@ [input-system-time id system-time] [reset-system-time-button id]])] [:> XMarkIcon {:class "h-5 w-5 cursor-pointer" - :on-click #(rf/dispatch [::tx-batch/delete id])}]] + :on-click #(rf/dispatch [:fx [[:dispatch [::tx-batch/delete id]] + [:dispatch [:update-url]]]])}]] [editor {:class "border md:flex-grow min-h-36" :source txs - :change-callback #(rf/dispatch [::tx-batch/assoc id :txs %])}]])]) + :change-callback #(rf/dispatch [:fx [[:dispatch [::tx-batch/assoc id :txs %]] + [:dispatch [:update-url]]]])}]])]) (defn transactions [{:keys [editor]}] [:div {:class "mx-4 md:mx-0 md:ml-4 md:flex-1 flex flex-col"} @@ -206,7 +222,8 @@ tx-batches])) [:div {:class "flex flex-row justify-center"} [:button {:class "w-10 h-10 bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 rounded-full" - :on-click #(rf/dispatch [::tx-batch/append tx-batch/blank])} + :on-click #(rf/dispatch [:fx [[:dispatch [::tx-batch/append tx-batch/blank]] + [:dispatch [:update-url]]]])} "+"]]]]) (defn query [{:keys [editor]}] @@ -214,7 +231,8 @@ [:h2 "Query:"] [editor {:class "md:flex-grow h-full min-h-36 border" :source @(rf/subscribe [:query]) - :change-callback #(rf/dispatch [:set-query %])}]]) + :change-callback #(rf/dispatch [:fx [[:dispatch [:set-query %]] + [:dispatch [:update-url]]]])}]]) (defn results [] [:section {:class "md:h-1/2 mx-4 flex flex-1 flex-col"} diff --git a/src/xt_fiddle/query_params.cljs b/src/xt_fiddle/query_params.cljs index 69e1959..9ca9c47 100644 --- a/src/xt_fiddle/query_params.cljs +++ b/src/xt_fiddle/query_params.cljs @@ -18,6 +18,10 @@ (.toString search-params))) (defn set-query-params [params] - (set! (.-search js/window.location) (->query-string params))) + (let [url (js/URL. js/window.location.href)] + (set! (.-search url) (->query-string params)) + ;; We replace the history instead of pushing a new state + ;; because it's a pain to hook up the back and forward buttons + (js/window.history.replaceState "" "" (.toString url)))) (rf/reg-fx ::set set-query-params) From 1f490dfbf7b17c93f39cc7fc9281f9fa188cd84d Mon Sep 17 00:00:00 2001 From: Oliver Marshall Date: Tue, 14 May 2024 18:06:56 +0100 Subject: [PATCH 2/5] feat: have the share button copy to the user's clipboard w/ feedback --- src/xt_fiddle/client.cljs | 37 ++++++++++++++++++++++++++++++------ src/xt_fiddle/clipboard.cljs | 10 ++++++++++ src/xt_fiddle/href.cljs | 6 ++++++ 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/xt_fiddle/clipboard.cljs create mode 100644 src/xt_fiddle/href.cljs diff --git a/src/xt_fiddle/client.cljs b/src/xt_fiddle/client.cljs index 805d54b..1bedc7c 100644 --- a/src/xt_fiddle/client.cljs +++ b/src/xt_fiddle/client.cljs @@ -2,6 +2,8 @@ (:require [xt-fiddle.editor :as editor] [xt-fiddle.run :as run] [xt-fiddle.query-params :as query-params] + [xt-fiddle.clipboard :as clipboard] + [xt-fiddle.href :as href] [xt-fiddle.highlight :as hl] [xt-fiddle.tx-batch :as tx-batch] [xt-fiddle.query :as query] @@ -13,11 +15,25 @@ PencilIcon PlayIcon XMarkIcon]] - ["@heroicons/react/24/outline" :refer [BookmarkIcon]])) + ["@heroicons/react/24/outline" :refer [BookmarkIcon + CheckCircleIcon]])) + +(rf/reg-event-db + :share-hide-tick + (fn [db _] + (dissoc db :share-show-tick))) (rf/reg-event-fx :share - (fn [{:keys [db]}] + [(rf/inject-cofx ::href/get)] + (fn [{:keys [db href]} _] + {::clipboard/set {:text href} + :db (assoc db :share-show-tick true) + :dispatch-later {:ms 800 :dispatch [:share-hide-tick]}})) + +(rf/reg-sub + :share-show-tick + :-> :share-show-tick) (rf/reg-event-fx :update-url @@ -148,10 +164,19 @@ [:div {:class "w-full flex flex-row items-center gap-1 md:justify-end"} [language-dropdown] [:div {:class "md:hidden flex-grow"}] - [:div {:class "p-2 hover:bg-gray-300 cursor-pointer flex flex-row gap-1 items-center" - :on-click #(rf/dispatch [:share])} - "Save as URL" - [:> BookmarkIcon {:class "h-5 w-5"}]] + (let [share-show-tick @(rf/subscribe [:share-show-tick])] + [:div {:class (str "p-2 flex flex-row gap-1 items-center" + (when-not share-show-tick + " hover:bg-gray-300 cursor-pointer")) + :disabled share-show-tick + :on-click #(rf/dispatch-sync [:share])} + (if-not share-show-tick + [:<> + "Save as URL" + [:> BookmarkIcon {:class "h-5 w-5"}]] + [:<> + "Saved!" + [:> CheckCircleIcon {:class "h-5 w-5"}]])]) [run-button]]]]) (defn reset-system-time-button [id] diff --git a/src/xt_fiddle/clipboard.cljs b/src/xt_fiddle/clipboard.cljs new file mode 100644 index 0000000..9b37896 --- /dev/null +++ b/src/xt_fiddle/clipboard.cljs @@ -0,0 +1,10 @@ +(ns xt-fiddle.clipboard + (:require [re-frame.core :as rf])) + +(rf/reg-fx ::set + (fn [{:keys [text on-success on-failure]}] + (-> (js/navigator.clipboard.writeText text) + (.then #(when on-success + (rf/dispatch on-success))) + (.catch #(when on-failure + (rf/dispatch (conj on-failure %))))))) diff --git a/src/xt_fiddle/href.cljs b/src/xt_fiddle/href.cljs new file mode 100644 index 0000000..3e0fef6 --- /dev/null +++ b/src/xt_fiddle/href.cljs @@ -0,0 +1,6 @@ +(ns xt-fiddle.href + (:require [re-frame.core :as rf])) + +(rf/reg-cofx ::get + (fn [cofx _] + (assoc cofx :href js/window.location.href))) From 01c4e78216361741fe9dd5058ac413d776888dff Mon Sep 17 00:00:00 2001 From: Oliver Marshall Date: Tue, 14 May 2024 18:12:08 +0100 Subject: [PATCH 3/5] feat: click on the logo to reset the fiddle --- src/xt_fiddle/client.cljs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/xt_fiddle/client.cljs b/src/xt_fiddle/client.cljs index 1bedc7c..e8126fa 100644 --- a/src/xt_fiddle/client.cljs +++ b/src/xt_fiddle/client.cljs @@ -154,10 +154,11 @@ [:header {:class "bg-gray-200 py-2 px-4"} [:div {:class "container mx-auto flex flex-col md:flex-row items-center gap-1"} [:div {:class "w-full flex flex-row items-center gap-4"} - [:div {:class "flex flex-row items-center gap-1"} - [:img {:class "h-8" - :src "/public/images/xtdb-full-logo.svg"}] - [title "Fiddle"]] + [:a {:href "/"} + [:div {:class "flex flex-row items-center gap-1"} + [:img {:class "h-8" + :src "/public/images/xtdb-full-logo.svg"}] + [title "Fiddle"]]] [:span {:class "text-sm text-gray-400"} @(rf/subscribe [:version])]] [:div {:class "max-md:hidden flex-grow"}] From 0dbc9885031bf976152a42953e111740881b0827 Mon Sep 17 00:00:00 2001 From: Oliver Marshall Date: Wed, 15 May 2024 11:21:15 +0100 Subject: [PATCH 4/5] feat: rename share button to copy --- src/xt_fiddle/client.cljs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/xt_fiddle/client.cljs b/src/xt_fiddle/client.cljs index e8126fa..2cedf07 100644 --- a/src/xt_fiddle/client.cljs +++ b/src/xt_fiddle/client.cljs @@ -19,21 +19,21 @@ CheckCircleIcon]])) (rf/reg-event-db - :share-hide-tick + :hide-copy-tick (fn [db _] - (dissoc db :share-show-tick))) + (dissoc db :copy-tick))) (rf/reg-event-fx - :share + :copy-url [(rf/inject-cofx ::href/get)] (fn [{:keys [db href]} _] {::clipboard/set {:text href} - :db (assoc db :share-show-tick true) - :dispatch-later {:ms 800 :dispatch [:share-hide-tick]}})) + :db (assoc db :copy-tick true) + :dispatch-later {:ms 800 :dispatch [:hide-copy-tick]}})) (rf/reg-sub - :share-show-tick - :-> :share-show-tick) + :copy-tick + :-> :copy-tick) (rf/reg-event-fx :update-url @@ -165,18 +165,18 @@ [:div {:class "w-full flex flex-row items-center gap-1 md:justify-end"} [language-dropdown] [:div {:class "md:hidden flex-grow"}] - (let [share-show-tick @(rf/subscribe [:share-show-tick])] - [:div {:class (str "p-2 flex flex-row gap-1 items-center" - (when-not share-show-tick + (let [copy-tick @(rf/subscribe [:copy-tick])] + [:div {:class (str "p-2 flex flex-row gap-1 items-center select-none" + (when-not copy-tick " hover:bg-gray-300 cursor-pointer")) - :disabled share-show-tick - :on-click #(rf/dispatch-sync [:share])} - (if-not share-show-tick + :disabled copy-tick + :on-click #(rf/dispatch-sync [:copy-url])} + (if-not copy-tick [:<> - "Save as URL" + "Copy URL" [:> BookmarkIcon {:class "h-5 w-5"}]] [:<> - "Saved!" + "Copied!" [:> CheckCircleIcon {:class "h-5 w-5"}]])]) [run-button]]]]) From 3675fd014ecbbfaebbf44f8b3b480cda8a2dc812 Mon Sep 17 00:00:00 2001 From: Oliver Marshall Date: Wed, 15 May 2024 11:21:57 +0100 Subject: [PATCH 5/5] refactor: make separate copy button --- src/xt_fiddle/client.cljs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/xt_fiddle/client.cljs b/src/xt_fiddle/client.cljs index 2cedf07..ac46f34 100644 --- a/src/xt_fiddle/client.cljs +++ b/src/xt_fiddle/client.cljs @@ -150,6 +150,21 @@ "Run" [:> PlayIcon {:class "h-5 w-5"}]]]) +(defn copy-button [] + (let [copy-tick @(rf/subscribe [:copy-tick])] + [:div {:class (str "p-2 flex flex-row gap-1 items-center select-none" + (when-not copy-tick + " hover:bg-gray-300 cursor-pointer")) + :disabled copy-tick + :on-click #(rf/dispatch-sync [:copy-url])} + (if-not copy-tick + [:<> + "Copy URL" + [:> BookmarkIcon {:class "h-5 w-5"}]] + [:<> + "Copied!" + [:> CheckCircleIcon {:class "h-5 w-5"}]])])) + (defn header [] [:header {:class "bg-gray-200 py-2 px-4"} [:div {:class "container mx-auto flex flex-col md:flex-row items-center gap-1"} @@ -165,19 +180,7 @@ [:div {:class "w-full flex flex-row items-center gap-1 md:justify-end"} [language-dropdown] [:div {:class "md:hidden flex-grow"}] - (let [copy-tick @(rf/subscribe [:copy-tick])] - [:div {:class (str "p-2 flex flex-row gap-1 items-center select-none" - (when-not copy-tick - " hover:bg-gray-300 cursor-pointer")) - :disabled copy-tick - :on-click #(rf/dispatch-sync [:copy-url])} - (if-not copy-tick - [:<> - "Copy URL" - [:> BookmarkIcon {:class "h-5 w-5"}]] - [:<> - "Copied!" - [:> CheckCircleIcon {:class "h-5 w-5"}]])]) + [copy-button] [run-button]]]]) (defn reset-system-time-button [id]