mirror of
https://github.com/penpot/penpot.git
synced 2026-04-29 05:08:08 +00:00
✨ Add "Delete group" to assets panel context menu (#9151)
When working with large asset groups, users asked for a one-click way to remove every asset under a group path. Multi-select across hundreds of items is impractical, and ungrouping first and then deleting leaves the orphaned items in the flat list. This change adds a "Delete group" option to the assets-panel context-menu for three asset types that already carry group structure: - Components (including variants — sibling variants sharing a variant container are deduplicated, and the container is deleted once via the same dispatch the per-item delete uses in file_library.cljs). - Colors. - Typographies. A confirmation modal is shown before deletion, with the count of assets to be removed, so the action is never silent. All deletes run inside a single undo transaction, so one Cmd+Z restores the whole group. Changes ------- - `assets/groups.cljs` — `asset-group-title*` accepts an optional `on-delete-group` prop and conditionally adds the menu entry between "Ungroup" and "Combine as variants". When the callback is not supplied the option is hidden, so asset sections that do not implement it stay unaffected. - `assets/components.cljs` — threads `on-delete-group` through the recursive `components-group*` and defines the section-level handler, dispatching to `dwsh/delete-shapes` for variant containers and `dwl/delete-component` for plain components. - `assets/colors.cljs` — same threading + a simple `dwl/delete-color` dispatch per color in the group. - `assets/typographies.cljs` — same threading + a `dwl/delete-typography` dispatch per typography in the group. - `translations/en.po` — three new strings: the menu label (`workspace.assets.delete-group`) and the modal title/message (`modals.delete-asset-group.title`/`.message`, plural-aware). Github #9141 Signed-off-by: FairyPigDev <luislee3108@gmail.com> Signed-off-by: FairyPiggyDev <luislee3108@gmail.com>
This commit is contained in:
parent
b0ce644752
commit
61ce4b9e0d
@ -8,6 +8,7 @@
|
||||
|
||||
### :sparkles: New features & Enhancements
|
||||
|
||||
- Add "Delete group" option to the assets panel context menu for components, colors and typographies (by @FairyPigDev) [Github #9141](https://github.com/penpot/penpot/issues/9141)
|
||||
- Add `Alt+click` on a layer's disclosure arrow to recursively expand the entire subtree rooted at that layer in the Layers sidebar; symmetric with the existing `Shift+click` collapse-all gesture, and removes the O(siblings × depth) click cost of unfolding a deep subtree one level at a time [Github #7736](https://github.com/penpot/penpot/issues/7736)
|
||||
- Show alpha percentage next to library color values to distinguish colors that differ only in opacity (by @rockchris099) [Github #6328](https://github.com/penpot/penpot/issues/6328)
|
||||
- Add "Clear artboard guides" option to right-click context menu for frames (by @eureka0928) [Github #6987](https://github.com/penpot/penpot/issues/6987)
|
||||
|
||||
@ -280,7 +280,7 @@
|
||||
(mf/defc colors-group
|
||||
[{:keys [file-id prefix groups open-groups force-open? local? selected
|
||||
multi-colors? multi-assets? on-asset-click on-assets-delete
|
||||
on-clear-selection on-group on-rename-group on-ungroup colors
|
||||
on-clear-selection on-group on-rename-group on-ungroup on-delete-group colors
|
||||
selected-full]}]
|
||||
(let [group-open? (if (false? (get open-groups prefix)) ;; if the user has closed it specifically, respect that
|
||||
false
|
||||
@ -325,7 +325,8 @@
|
||||
:path prefix
|
||||
:is-group-open group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group}]
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [colors (get groups "" [])]
|
||||
@ -378,6 +379,7 @@
|
||||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:colors colors
|
||||
:selected-full selected-full}]))])]))
|
||||
|
||||
@ -499,6 +501,39 @@
|
||||
file-id))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
;; Issue #9141. Delete every color under a group path in a
|
||||
;; single undo transaction, after user confirmation.
|
||||
on-delete-group
|
||||
(mf/use-fn
|
||||
(mf/deps colors on-clear-selection)
|
||||
(fn [path]
|
||||
(let [group-colors
|
||||
(->> colors
|
||||
(filter #(str/starts-with? (:path %) path)))
|
||||
|
||||
;; Hoisted so the start/commit pair is bound to the
|
||||
;; same symbol regardless of how `do-delete` is
|
||||
;; invoked by the confirm modal. Review suggestion
|
||||
;; on PR #9151.
|
||||
undo-id (js/Symbol)
|
||||
|
||||
do-delete
|
||||
(fn []
|
||||
(on-clear-selection)
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(map #(dwl/delete-color {:id (:id %)}) group-colors))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))]
|
||||
(when (seq group-colors)
|
||||
(st/emit!
|
||||
(modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-asset-group.title")
|
||||
:message (tr "modals.delete-asset-group.message"
|
||||
(i18n/c (count group-colors)))
|
||||
:accept-label (tr "labels.delete")
|
||||
:on-accept do-delete}))))))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
||||
|
||||
@ -533,5 +568,6 @@
|
||||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:colors colors
|
||||
:selected-full selected-full}]]]))
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.media :as dwm]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.variants :as dwv]
|
||||
[app.main.refs :as refs]
|
||||
@ -191,7 +192,7 @@
|
||||
|
||||
(mf/defc components-group*
|
||||
[{:keys [file-id prefix groups open-groups is-force-open renaming is-listing-thumbs selected on-asset-click
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-delete-group on-context-menu
|
||||
selected-full is-local count-variants on-group-combine-variants]}]
|
||||
|
||||
(let [group-open? (if (false? (get open-groups prefix)) ;; if the user has closed it specifically, respect that
|
||||
@ -246,6 +247,7 @@
|
||||
:is-can-combine can-combine?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:on-group-combine-variants on-group-combine-variants}]
|
||||
|
||||
(when group-open?
|
||||
@ -303,6 +305,7 @@
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:on-context-menu on-context-menu
|
||||
:on-group-combine-variants on-group-combine-variants
|
||||
:selected-full selected-full
|
||||
@ -493,6 +496,60 @@
|
||||
(map #(dwv/rename-comp-or-variant-and-main (:id %) (cmm/ungroup % path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
;; Issue #9141. Delete every component under a group path in a
|
||||
;; single undo transaction, after user confirmation. Variants
|
||||
;; are handled via their variant container (matching the
|
||||
;; per-item delete dispatch in file_library.cljs); sibling
|
||||
;; variants sharing a container are deduplicated so we delete
|
||||
;; each container only once.
|
||||
on-delete-group
|
||||
(mf/use-fn
|
||||
(mf/deps components on-clear-selection)
|
||||
(fn [path]
|
||||
(let [group-components
|
||||
(->> components
|
||||
(filter #(cpn/inside-path? (:path %) path)))
|
||||
|
||||
{variants true non-variants false}
|
||||
(group-by (comp boolean ctc/is-variant?) group-components)
|
||||
|
||||
;; One delete-shapes per variant container, not per
|
||||
;; sibling variant within that container.
|
||||
variant-containers
|
||||
(->> variants
|
||||
(group-by :variant-id)
|
||||
(map (fn [[_ comps]] (first comps))))
|
||||
|
||||
;; Hoisted so the start/commit pair is bound to the
|
||||
;; same symbol regardless of how `do-delete` is
|
||||
;; invoked by the confirm modal. Review suggestion
|
||||
;; on PR #9151.
|
||||
undo-id (js/Symbol)
|
||||
|
||||
do-delete
|
||||
(fn []
|
||||
(on-clear-selection)
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(map (fn [component]
|
||||
(dwsh/delete-shapes (:main-instance-page component)
|
||||
#{(:variant-id component)}))
|
||||
variant-containers))
|
||||
(run! st/emit!
|
||||
(map (fn [component]
|
||||
(dwl/delete-component {:id (:id component)}))
|
||||
non-variants))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))]
|
||||
(when (seq group-components)
|
||||
(st/emit!
|
||||
(modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-asset-group.title")
|
||||
:message (tr "modals.delete-asset-group.message"
|
||||
(i18n/c (count group-components)))
|
||||
:accept-label (tr "labels.delete")
|
||||
:on-accept do-delete}))))))
|
||||
|
||||
on-group-combine-variants
|
||||
(mf/use-fn
|
||||
(mf/deps components on-clear-selection)
|
||||
@ -602,6 +659,7 @@
|
||||
:on-rename-group on-rename-group
|
||||
:on-group on-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:on-group-combine-variants on-group-combine-variants
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc asset-group-title*
|
||||
[{:keys [file-id section path is-group-open on-rename on-ungroup on-group-combine-variants is-can-combine on-add]}]
|
||||
[{:keys [file-id section path is-group-open on-rename on-ungroup on-delete-group on-group-combine-variants is-can-combine on-add]}]
|
||||
(when-not (empty? path)
|
||||
(let [[other-path last-path truncated] (cpn/compact-path path 35 true)
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
@ -69,6 +69,12 @@
|
||||
{:name (tr "workspace.assets.ungroup")
|
||||
:id "assets-ungroup-group"
|
||||
:handler #(on-ungroup path)}]
|
||||
on-delete-group
|
||||
(conj
|
||||
{:name (tr "workspace.assets.delete-group")
|
||||
:id "assets-delete-group"
|
||||
:handler #(on-delete-group path)})
|
||||
|
||||
is-can-combine
|
||||
(conj
|
||||
{:name (tr "workspace.shape.menu.combine-as-variants")
|
||||
|
||||
@ -134,7 +134,7 @@
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id prefix groups open-groups force-open? file local? selected local-data
|
||||
editing-id renaming-id on-asset-click handle-change on-rename-group
|
||||
on-ungroup on-context-menu selected-full is-read-only]}]
|
||||
on-ungroup on-delete-group on-context-menu selected-full is-read-only]}]
|
||||
(let [group-open? (if (false? (get open-groups prefix)) ;; if the user has closed it specifically, respect that
|
||||
false
|
||||
(get open-groups prefix true))
|
||||
@ -185,6 +185,7 @@
|
||||
:is-group-open group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:on-add (when (and local? (not is-read-only))
|
||||
add-typography-to-group)}]
|
||||
|
||||
@ -238,6 +239,7 @@
|
||||
:handle-change handle-change
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:is-read-only is-read-only}]))])]))
|
||||
@ -352,6 +354,39 @@
|
||||
(cmm/ungroup % path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
;; Issue #9141. Delete every typography under a group path in a
|
||||
;; single undo transaction, after user confirmation.
|
||||
on-delete-group
|
||||
(mf/use-fn
|
||||
(mf/deps typographies file-id on-clear-selection)
|
||||
(fn [path]
|
||||
(let [group-typographies
|
||||
(->> typographies
|
||||
(filter #(str/starts-with? (:path %) path)))
|
||||
|
||||
;; Hoisted so the start/commit pair is bound to the
|
||||
;; same symbol regardless of how `do-delete` is
|
||||
;; invoked by the confirm modal. Review suggestion
|
||||
;; on PR #9151.
|
||||
undo-id (js/Symbol)
|
||||
|
||||
do-delete
|
||||
(fn []
|
||||
(on-clear-selection)
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(map #(dwl/delete-typography (:id %)) group-typographies))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))]
|
||||
(when (seq group-typographies)
|
||||
(st/emit!
|
||||
(modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-asset-group.title")
|
||||
:message (tr "modals.delete-asset-group.message"
|
||||
(i18n/c (count group-typographies)))
|
||||
:accept-label (tr "labels.delete")
|
||||
:on-accept do-delete}))))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps selected on-clear-selection read-only?)
|
||||
@ -441,6 +476,7 @@
|
||||
:handle-change handle-change
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-delete-group on-delete-group
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:is-read-only read-only?}]
|
||||
|
||||
@ -3561,6 +3561,16 @@ msgstr "Are you sure you want to delete this page?"
|
||||
msgid "modals.delete-page.title"
|
||||
msgstr "Delete page"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/assets/components.cljs, src/app/main/ui/workspace/sidebar/assets/colors.cljs, src/app/main/ui/workspace/sidebar/assets/typographies.cljs
|
||||
msgid "modals.delete-asset-group.title"
|
||||
msgstr "Delete group"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/assets/components.cljs, src/app/main/ui/workspace/sidebar/assets/colors.cljs, src/app/main/ui/workspace/sidebar/assets/typographies.cljs
|
||||
msgid "modals.delete-asset-group.message"
|
||||
msgid_plural "modals.delete-asset-group.message"
|
||||
msgstr[0] "Are you sure you want to delete this asset?"
|
||||
msgstr[1] "Are you sure you want to delete these %s assets?"
|
||||
|
||||
#: src/app/main/ui/dashboard/project_menu.cljs:73
|
||||
msgid "modals.delete-project-confirm.accept"
|
||||
msgstr "Delete project"
|
||||
@ -5733,6 +5743,10 @@ msgstr "Text Transform"
|
||||
msgid "workspace.assets.ungroup"
|
||||
msgstr "Ungroup"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/assets/groups.cljs
|
||||
msgid "workspace.assets.delete-group"
|
||||
msgstr "Delete group"
|
||||
|
||||
#: src/app/main/ui/workspace/colorpicker.cljs:428, src/app/main/ui/workspace/colorpicker.cljs:441
|
||||
msgid "workspace.colorpicker.color-tokens"
|
||||
msgstr "Color tokens"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user