From 219ddfabaf109c959a7a7921323d438e37928f8c Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Fri, 25 Apr 2025 12:21:37 +0200 Subject: [PATCH] :sparkles: Restore a deleted variant --- common/src/app/common/logic/libraries.cljc | 11 +++- .../app/common/logic/variant_properties.cljc | 55 ++++++++++++------- common/src/app/common/types/component.cljc | 2 +- .../ui/workspace/sidebar/assets/common.cljs | 24 +++++++- .../sidebar/options/menus/component.cljs | 10 +++- frontend/translations/en.po | 6 ++ frontend/translations/es.po | 6 ++ 7 files changed, 86 insertions(+), 28 deletions(-) diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index c1cf29d58..9e7370ed5 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -423,6 +423,8 @@ (not inside-component?) (assoc :component-root true)) + restoring-into-parent (get objects (:parent-id first-shape)) + changes (-> changes (pcb/with-page page) (pcb/with-objects (:objects page)) @@ -433,12 +435,15 @@ changes (rest moved-shapes)) 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))) (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 - (ctk/is-variant-container? parent) - (clvp/generate-make-shapes-variant [first-shape] parent))] + (ctk/is-variant-container? restoring-into-parent) + (clvp/generate-make-shapes-variant [first-shape] restoring-into-parent))] {:changes (pcb/restore-component changes component-id (:id page) minusdelta) :shape (first moved-shapes)}))) diff --git a/common/src/app/common/logic/variant_properties.cljc b/common/src/app/common/logic/variant_properties.cljc index e39e7d223..fd4acd701 100644 --- a/common/src/app/common/logic/variant_properties.cljc +++ b/common/src/app/common/logic/variant_properties.cljc @@ -93,6 +93,16 @@ related-components)] 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 [changes shape] (let [new-name (ctv/variant-name-to-name shape) @@ -112,9 +122,10 @@ (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] (let [component (ctcl/get-component data (:component-id shape) true) + add-name? (not= (:name component) container-name) props (ctv/merge-properties base-properties (:variant-properties component)) @@ -127,7 +138,7 @@ (ctv/add-new-prop props (:name component)) props))) -(defn- generate-new-properties-from-non-variant +(defn- create-new-properties-from-non-variant [shape min-props container-name base-properties] (let [;; Remove container name from shape name if present shape-name (ctv/remove-prefix (:name shape) container-name)] @@ -155,14 +166,14 @@ [cpath cname] (cfh/parse-path-name (:name variant-container)) container-name (:name variant-container) - generate-new-properties + create-new-properties (fn [shape min-props] (if (ctk/is-variant? shape) - (generate-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-variant shape min-props data container-name base-props) + (create-new-properties-from-non-variant shape min-props container-name base-props))) 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 shapes) @@ -180,19 +191,21 @@ :name (:name variant-container)))] (reduce (fn [changes shape] - (if (or (zero? num-base-props) - (= variant-id (:variant-id shape))) - changes ;; do nothing more if we aren't changing the parent or there are no base props - (let [props (generate-new-properties shape total-props) - variant-name (ctv/properties-to-name props)] - (-> (pcb/update-component changes - (:component-id shape) - #(assoc % :variant-id variant-id - :variant-properties props - :name cname - :path cpath) - {:apply-changes-local-library? true}) - (pcb/update-shapes [(:id shape)] - #(assoc % :variant-name variant-name)))))) + (let [component (ctcl/get-component data (:component-id shape) true)] + (if (or (zero? num-base-props) ;; do nothing if there are no base props + (and (= variant-id (:variant-id shape)) ;; or we are only moving the shape inside its parent (it is + (not (:deleted component)))) ;; the same parent and the component isn't deleted) + changes + (let [props (create-new-properties shape total-props) + variant-name (ctv/properties-to-name props)] + (-> (pcb/update-component changes + (:component-id shape) + #(assoc % :variant-id variant-id + :variant-properties props + :name cname + :path cpath) + {:apply-changes-local-library? true}) + (pcb/update-shapes [(:id shape)] + #(assoc % :variant-name variant-name))))))) changes - shapes))) \ No newline at end of file + shapes))) diff --git a/common/src/app/common/types/component.cljc b/common/src/app/common/types/component.cljc index 09aa6b6f1..93fabc973 100644 --- a/common/src/app/common/types/component.cljc +++ b/common/src/app/common/types/component.cljc @@ -287,7 +287,7 @@ (defn get-component-root [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 (:id component)]))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs index 0fa0a2d88..4c5a3a246 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs @@ -8,6 +8,7 @@ (ns app.main.ui.workspace.sidebar.assets.common (:require-macros [app.main.style :as stl]) (:require + [app.common.data.macros :as dm] [app.common.files.helpers :as cfh] [app.common.spec :as us] [app.common.thumbnails :as thc] @@ -384,6 +385,24 @@ 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 #(st/emit! (dwl/detach-components (map :id copies))) @@ -464,7 +483,10 @@ {:title (tr "workspace.shape.menu.reset-overrides") :action do-reset-component}) (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}) (when can-show-component? {:title (tr "workspace.shape.menu.show-main") diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs index 1e03813a1..ab7bcf84b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs @@ -756,7 +756,9 @@ (when (and can-swap? (not multi)) [: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? [:div {:class (stl/css :component-actions)} @@ -776,7 +778,11 @@ (when (and (not swap-opened?) (not multi)) [:& 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 :shape shape :data data}]) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 679a703e3..fc5faebec 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -5177,6 +5177,9 @@ msgstr "Annotation" msgid "workspace.options.component.copy" msgstr "Copy" +msgid "workspace.options.component.unlinked" +msgstr "Unlinked" + #: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:180 msgid "workspace.options.component.create-annotation" msgstr "Create an annotation" @@ -6626,6 +6629,9 @@ msgstr "Reset overrides" msgid "workspace.shape.menu.restore-main" msgstr "Restore main component" +msgid "workspace.shape.menu.restore-variant" +msgstr "Restore variant" + #: src/app/main/ui/workspace/context_menu.cljs:247 msgid "workspace.shape.menu.select-layer" msgstr "Select layer" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index f9a319e92..4cd9f93eb 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -5203,6 +5203,9 @@ msgstr "Nota" msgid "workspace.options.component.copy" msgstr "Copia" +msgid "workspace.options.component.unlinked" +msgstr "Desvinculado" + #: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:180 msgid "workspace.options.component.create-annotation" msgstr "Crear una nota" @@ -6656,6 +6659,9 @@ msgstr "Deshacer modificaciones" msgid "workspace.shape.menu.restore-main" msgstr "Restaurar componente principal" +msgid "workspace.shape.menu.restore-variant" +msgstr "Restaurar variante" + #: src/app/main/ui/workspace/context_menu.cljs:247 msgid "workspace.shape.menu.select-layer" msgstr "Seleccionar capa"