mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 19:41:27 -05:00
✨ Duplicate pages
This commit is contained in:
parent
c775f5aba0
commit
dd283381a1
3 changed files with 92 additions and 25 deletions
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue