Restore a deleted variant

This commit is contained in:
Pablo Alba 2025-04-25 12:21:37 +02:00 committed by Pablo Alba
parent 7eab6a2f1d
commit 219ddfabaf
7 changed files with 86 additions and 28 deletions

View file

@ -423,6 +423,8 @@
(not inside-component?) (not inside-component?)
(assoc :component-root true)) (assoc :component-root true))
restoring-into-parent (get objects (:parent-id first-shape))
changes (-> changes changes (-> changes
(pcb/with-page page) (pcb/with-page page)
(pcb/with-objects (:objects page)) (pcb/with-objects (:objects page))
@ -433,12 +435,15 @@
changes changes
(rest moved-shapes)) (rest moved-shapes))
changes (cond-> changes changes (cond-> changes
;; Remove variant info when restoring into a parent that is not a variant-container ;; Transform variant info into name when restoring into a parent that is not a variant-container
(and is-variant? parent (not (ctk/is-variant-container? parent))) (and is-variant? parent (not (ctk/is-variant-container? parent)))
(clvp/generate-make-shapes-no-variant [first-shape]) (clvp/generate-make-shapes-no-variant [first-shape])
;; Remove variant info when restoring into a variant-container that doesn't exists anymore
(and is-variant? (nil? restoring-into-parent))
(clvp/generate-delete-variant-info first-shape)
;; Add variant info and rename when restoring into a variant-container ;; Add variant info and rename when restoring into a variant-container
(ctk/is-variant-container? parent) (ctk/is-variant-container? restoring-into-parent)
(clvp/generate-make-shapes-variant [first-shape] parent))] (clvp/generate-make-shapes-variant [first-shape] restoring-into-parent))]
{:changes (pcb/restore-component changes component-id (:id page) minusdelta) {:changes (pcb/restore-component changes component-id (:id page) minusdelta)
:shape (first moved-shapes)}))) :shape (first moved-shapes)})))

View file

@ -93,6 +93,16 @@
related-components)] related-components)]
changes)) changes))
(defn generate-delete-variant-info
[changes shape]
(-> changes
(pcb/update-component (:component-id shape)
#(dissoc % :variant-id :variant-properties)
{:apply-changes-local-library? true})
(pcb/update-shapes [(:id shape)]
#(dissoc % :variant-id :variant-name))))
(defn- generate-make-shape-no-variant (defn- generate-make-shape-no-variant
[changes shape] [changes shape]
(let [new-name (ctv/variant-name-to-name shape) (let [new-name (ctv/variant-name-to-name shape)
@ -112,9 +122,10 @@
(reduce generate-make-shape-no-variant changes shapes)) (reduce generate-make-shape-no-variant changes shapes))
(defn- generate-new-properties-from-variant (defn- create-new-properties-from-variant
[shape min-props data container-name base-properties] [shape min-props data container-name base-properties]
(let [component (ctcl/get-component data (:component-id shape) true) (let [component (ctcl/get-component data (:component-id shape) true)
add-name? (not= (:name component) container-name) add-name? (not= (:name component) container-name)
props (ctv/merge-properties base-properties props (ctv/merge-properties base-properties
(:variant-properties component)) (:variant-properties component))
@ -127,7 +138,7 @@
(ctv/add-new-prop props (:name component)) (ctv/add-new-prop props (:name component))
props))) props)))
(defn- generate-new-properties-from-non-variant (defn- create-new-properties-from-non-variant
[shape min-props container-name base-properties] [shape min-props container-name base-properties]
(let [;; Remove container name from shape name if present (let [;; Remove container name from shape name if present
shape-name (ctv/remove-prefix (:name shape) container-name)] shape-name (ctv/remove-prefix (:name shape) container-name)]
@ -155,14 +166,14 @@
[cpath cname] (cfh/parse-path-name (:name variant-container)) [cpath cname] (cfh/parse-path-name (:name variant-container))
container-name (:name variant-container) container-name (:name variant-container)
generate-new-properties create-new-properties
(fn [shape min-props] (fn [shape min-props]
(if (ctk/is-variant? shape) (if (ctk/is-variant? shape)
(generate-new-properties-from-variant shape min-props data container-name base-props) (create-new-properties-from-variant shape min-props data container-name base-props)
(generate-new-properties-from-non-variant shape min-props container-name base-props))) (create-new-properties-from-non-variant shape min-props container-name base-props)))
total-props (reduce (fn [m shape] total-props (reduce (fn [m shape]
(max m (count (generate-new-properties shape num-base-props)))) (max m (count (create-new-properties shape num-base-props))))
0 0
shapes) shapes)
@ -180,19 +191,21 @@
:name (:name variant-container)))] :name (:name variant-container)))]
(reduce (reduce
(fn [changes shape] (fn [changes shape]
(if (or (zero? num-base-props) (let [component (ctcl/get-component data (:component-id shape) true)]
(= variant-id (:variant-id shape))) (if (or (zero? num-base-props) ;; do nothing if there are no base props
changes ;; do nothing more if we aren't changing the parent or there are no base props (and (= variant-id (:variant-id shape)) ;; or we are only moving the shape inside its parent (it is
(let [props (generate-new-properties shape total-props) (not (:deleted component)))) ;; the same parent and the component isn't deleted)
variant-name (ctv/properties-to-name props)] changes
(-> (pcb/update-component changes (let [props (create-new-properties shape total-props)
(:component-id shape) variant-name (ctv/properties-to-name props)]
#(assoc % :variant-id variant-id (-> (pcb/update-component changes
:variant-properties props (:component-id shape)
:name cname #(assoc % :variant-id variant-id
:path cpath) :variant-properties props
{:apply-changes-local-library? true}) :name cname
(pcb/update-shapes [(:id shape)] :path cpath)
#(assoc % :variant-name variant-name)))))) {:apply-changes-local-library? true})
(pcb/update-shapes [(:id shape)]
#(assoc % :variant-name variant-name)))))))
changes changes
shapes))) shapes)))

View file

@ -287,7 +287,7 @@
(defn get-component-root (defn get-component-root
[component] [component]
(if (true? (:main-instance-id component)) (if (some? (:main-instance-id component))
(get-in component [:objects (:main-instance-id component)]) (get-in component [:objects (:main-instance-id component)])
(get-in component [:objects (:id component)]))) (get-in component [:objects (:id component)])))

View file

@ -8,6 +8,7 @@
(ns app.main.ui.workspace.sidebar.assets.common (ns app.main.ui.workspace.sidebar.assets.common
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.thumbnails :as thc] [app.common.thumbnails :as thc]
@ -384,6 +385,24 @@
same-variant? (ctv/same-variant? shapes) same-variant? (ctv/same-variant? shapes)
is-restorable-variant?
;; A shape is a restorable variant if its component is deleted, is a variant,
;; and the variant-container in which it will be restored still exists
(fn [shape]
(let [component (find-component shape true)
main (ctk/get-component-root component)
objects (dm/get-in libraries [(:component-file shape)
:data
:pages-index
(:main-instance-page component)
:objects])
parent (get objects (:parent-id main))]
(and (:deleted component) (ctk/is-variant? component) parent)))
restorable-variants? (and variants?
(every? is-restorable-variant? restorable-copies))
do-detach-component do-detach-component
#(st/emit! (dwl/detach-components (map :id copies))) #(st/emit! (dwl/detach-components (map :id copies)))
@ -464,7 +483,10 @@
{:title (tr "workspace.shape.menu.reset-overrides") {:title (tr "workspace.shape.menu.reset-overrides")
:action do-reset-component}) :action do-reset-component})
(when (seq restorable-copies) (when (seq restorable-copies)
{:title (tr "workspace.shape.menu.restore-main") {:title
(if restorable-variants?
(tr "workspace.shape.menu.restore-variant")
(tr "workspace.shape.menu.restore-main"))
:action do-restore-component}) :action do-restore-component})
(when can-show-component? (when can-show-component?
{:title (tr "workspace.shape.menu.show-main") {:title (tr "workspace.shape.menu.show-main")

View file

@ -756,7 +756,9 @@
(when (and can-swap? (not multi)) (when (and can-swap? (not multi))
[:div {:class (stl/css :component-parent-name)} [:div {:class (stl/css :component-parent-name)}
(cfh/merge-path-item-with-dot path (:name component))])]] (if (:deleted component)
(tr "workspace.options.component.unlinked")
(cfh/merge-path-item-with-dot path (:name component)))])]]
(when show-menu? (when show-menu?
[:div {:class (stl/css :component-actions)} [:div {:class (stl/css :component-actions)}
@ -776,7 +778,11 @@
(when (and (not swap-opened?) (not multi)) (when (and (not swap-opened?) (not multi))
[:& component-annotation {:id id :shape shape :component component :rerender-fn rerender-fn}]) [:& component-annotation {:id id :shape shape :component component :rerender-fn rerender-fn}])
(when (and is-variant? (not main-instance?) (not swap-opened?) (not multi)) (when (and is-variant?
(not main-instance?)
(not (:deleted component))
(not swap-opened?)
(not multi))
[:> component-variant* {:component component [:> component-variant* {:component component
:shape shape :shape shape
:data data}]) :data data}])

View file

@ -5177,6 +5177,9 @@ msgstr "Annotation"
msgid "workspace.options.component.copy" msgid "workspace.options.component.copy"
msgstr "Copy" msgstr "Copy"
msgid "workspace.options.component.unlinked"
msgstr "Unlinked"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:180 #: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:180
msgid "workspace.options.component.create-annotation" msgid "workspace.options.component.create-annotation"
msgstr "Create an annotation" msgstr "Create an annotation"
@ -6626,6 +6629,9 @@ msgstr "Reset overrides"
msgid "workspace.shape.menu.restore-main" msgid "workspace.shape.menu.restore-main"
msgstr "Restore main component" msgstr "Restore main component"
msgid "workspace.shape.menu.restore-variant"
msgstr "Restore variant"
#: src/app/main/ui/workspace/context_menu.cljs:247 #: src/app/main/ui/workspace/context_menu.cljs:247
msgid "workspace.shape.menu.select-layer" msgid "workspace.shape.menu.select-layer"
msgstr "Select layer" msgstr "Select layer"

View file

@ -5203,6 +5203,9 @@ msgstr "Nota"
msgid "workspace.options.component.copy" msgid "workspace.options.component.copy"
msgstr "Copia" msgstr "Copia"
msgid "workspace.options.component.unlinked"
msgstr "Desvinculado"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:180 #: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:180
msgid "workspace.options.component.create-annotation" msgid "workspace.options.component.create-annotation"
msgstr "Crear una nota" msgstr "Crear una nota"
@ -6656,6 +6659,9 @@ msgstr "Deshacer modificaciones"
msgid "workspace.shape.menu.restore-main" msgid "workspace.shape.menu.restore-main"
msgstr "Restaurar componente principal" msgstr "Restaurar componente principal"
msgid "workspace.shape.menu.restore-variant"
msgstr "Restaurar variante"
#: src/app/main/ui/workspace/context_menu.cljs:247 #: src/app/main/ui/workspace/context_menu.cljs:247
msgid "workspace.shape.menu.select-layer" msgid "workspace.shape.menu.select-layer"
msgstr "Seleccionar capa" msgstr "Seleccionar capa"