From dd283381a1e7ea7bd2db6b1f600f2db035e7759a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 19 Jan 2021 07:55:29 +0100 Subject: [PATCH] :sparkles: Duplicate pages --- .../styles/main/partials/sidebar.scss | 13 +++ frontend/src/app/main/data/workspace.cljs | 18 ++++ .../main/ui/workspace/sidebar/sitemap.cljs | 86 +++++++++++++------ 3 files changed, 92 insertions(+), 25 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar.scss b/frontend/resources/styles/main/partials/sidebar.scss index e93c5b4d4..57baeec1b 100644 --- a/frontend/resources/styles/main/partials/sidebar.scss +++ b/frontend/resources/styles/main/partials/sidebar.scss @@ -214,4 +214,17 @@ $width-settings-bar: 16rem; .element-list.pages-list { max-height: 10rem; + + .context-menu { + position: fixed; + } + + .context-menu-items { + border: none; + margin: none; + } + + .context-menu-action { + width: 100%; + } } diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 21e3a2563..53fe4d1a8 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -268,6 +268,24 @@ :id id}] (rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true})))))) +(defn duplicate-page [page-id] + (ptk/reify ::duplicate-page + ptk/WatchEvent + (watch [this state stream] + (let [id (uuid/next) + pages (get-in state [:workspace-data :pages-index]) + unames (dwc/retrieve-used-names pages) + page (get-in state [:workspace-data :pages-index page-id]) + name (dwc/generate-unique-name unames (:name page)) + + page (-> page (assoc :name name :id id)) + + rchange {:type :add-page + :page page} + uchange {:type :del-page + :id id}] + (rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true})))))) + (s/def ::rename-page (s/keys :req-un [::id ::name])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs index 4380d9619..bb28e672b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs @@ -9,6 +9,7 @@ (ns app.main.ui.workspace.sidebar.sitemap (:require + [app.main.ui.components.context-menu :refer [context-menu]] [app.common.data :as d] [app.main.data.modal :as modal] [app.main.data.workspace :as dw] @@ -33,9 +34,23 @@ input-ref (mf/use-ref) id (:id page) + state (mf/use-state {:menu-open false}) + delete-fn (mf/use-callback (mf/deps id) #(st/emit! (dw/delete-page id))) navigate-fn (mf/use-callback (mf/deps id) #(st/emit! (dw/go-to-page id))) + on-context-menu + (mf/use-callback + (mf/deps id) + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (let [pos (dom/get-client-position event)] + (swap! state assoc + :menu-open true + :top (:y pos) + :left (:x pos))))) + on-delete (mf/use-callback (mf/deps id) @@ -50,7 +65,8 @@ (fn [event] (dom/prevent-default event) (dom/stop-propagation event) - (swap! local assoc :edition true))) + (swap! local assoc :edition true) + (swap! state assoc :menu-open false))) on-blur (mf/use-callback @@ -77,6 +93,10 @@ (let [index (if (= :bot side) (inc index) index)] (st/emit! (dw/relocate-page id index))))) + on-duplicate + (fn [event] + (st/emit! (dw/duplicate-page id))) + [dprops dref] (hooks/use-sortable :data-type "app/page" @@ -93,30 +113,46 @@ (dom/select-text! edit-input)) nil))) - [:li {:class (dom/classnames - :selected selected? - :dnd-over-top (= (:over dprops) :top) - :dnd-over-bot (= (:over dprops) :bot)) - :ref dref} - [:div.element-list-body - {:class (dom/classnames - :selected selected?) - :on-click navigate-fn - :on-double-click on-double-click} - [:div.page-icon i/file-html] - (if (:edition @local) - [:* - [:input.element-name {:type "text" - :ref input-ref - :on-blur on-blur - :on-key-down on-key-down - :auto-focus true - :default-value (:name page "")}]] - [:* - [:span (:name page)] - [:div.page-actions - (when deletable? - [:a {:on-click on-delete} i/trash])]])]])) + [:* + [:li {:class (dom/classnames + :selected selected? + :dnd-over-top (= (:over dprops) :top) + :dnd-over-bot (= (:over dprops) :bot)) + :ref dref} + [:div.element-list-body + {:class (dom/classnames + :selected selected?) + :on-click navigate-fn + :on-double-click on-double-click + :on-context-menu on-context-menu} + [:div.page-icon i/file-html] + (if (:edition @local) + [:* + [:input.element-name {:type "text" + :ref input-ref + :on-blur on-blur + :on-key-down on-key-down + :auto-focus true + :default-value (:name page "")}]] + [:* + [:span (:name page)] + [:div.page-actions + (when deletable? + [:a {:on-click on-delete} i/trash])]])]] + + [:& context-menu + {:selectable false + :show (:menu-open @state) + :on-close #(swap! state assoc :menu-open false) + :top (:top @state) + :left (:left @state) + :options (cond-> [] + deletable? + (conj [(tr "workspace.assets.delete") on-delete]) + + :always + (-> (conj [(tr "workspace.assets.rename") on-double-click]) + (conj [(tr "workspace.assets.duplicate") on-duplicate])))}]])) ;; --- Page Item Wrapper