diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index 37c1bbc279..5e030ffb56 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -426,7 +426,6 @@ (not (has-any-main? objects shape)) (not (has-any-copy-parent? objects shape)))) - (defn collect-main-shapes [shape objects] (if (ctk/main-instance? shape) [shape] @@ -434,6 +433,10 @@ (mapcat collect-main-shapes children objects) []))) +(defn get-component-from-shape + [shape libraries] + (get-in libraries [(:component-file shape) :data :components (:component-id shape)])) + (defn invalid-structure-for-component? "Check if the structure generated nesting children in parent is invalid in terms of nested components" [objects parent children pasting? libraries] @@ -446,7 +449,7 @@ ; original component doesn't exist or is deleted. So for this function purposes, they ; are removed from the list remove? (fn [shape] - (let [component (get-in libraries [(:component-file shape) :data :components (:component-id shape)])] + (let [component (get-component-from-shape shape libraries)] (and component (not (:deleted component))))) selected-components (cond->> (mapcat collect-main-shapes children objects) diff --git a/frontend/src/app/main/data/workspace/clipboard.cljs b/frontend/src/app/main/data/workspace/clipboard.cljs index 9cc7a10ce1..5fbbdae994 100644 --- a/frontend/src/app/main/data/workspace/clipboard.cljs +++ b/frontend/src/app/main/data/workspace/clipboard.cljs @@ -121,6 +121,8 @@ ;; Collects all the items together and split images into a ;; separated data structure for a more easy paste process. ;; Also collects the variant properties of the copied variants + + (collect-data [state result {:keys [id ::images] :as item}] (cond-> result :always @@ -132,8 +134,6 @@ (ctc/is-variant-container? item) (update :variant-properties merge (collect-variants state item)))) - - (maybe-translate [shape objects parent-frame-id] (if (= parent-frame-id uuid/zero) shape @@ -829,7 +829,6 @@ variant-props (:variant-properties pdata) - position (deref ms/mouse-position) ;; Calculate position for the pasted elements @@ -895,6 +894,7 @@ (rx/map (fn [shape] (let [parent-type (cfh/get-shape-type all-objects (:parent-id shape)) external-lib? (not= file-id (:component-file shape)) + component (ctn/get-component-from-shape shape libraries) origin "workspace:paste"] ;; NOTE: we don't emit the create-shape event all the time for @@ -905,7 +905,8 @@ ::ev/origin origin :is-external-library external-lib? :type (get shape :type) - :parent-type parent-type}) + :parent-type parent-type + :is-variant (ctc/is-variant? component)}) (if (cfh/has-layout? objects (:parent-id shape)) (ev/event {::ev/name "layout-add-element" ::ev/origin origin diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index f1a2c10e41..c4cb6bba4a 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -549,7 +549,6 @@ (when local? (ptk/data-event :layout/update {:page-id page-id :ids frames}))))))) - (defn restore-components "Restore multiple deleted component definded by a map with the component id as key and the component library as value" [components-data] @@ -592,6 +591,7 @@ position page libraries) + component (ctn/get-component-from-shape new-shape libraries) undo-id (js/Symbol)] @@ -601,7 +601,8 @@ (rx/of (ptk/event ::ev/event {::ev/name "use-library-component" ::ev/origin origin - :external-library (not= file-id current-file-id)}) + :external-library (not= file-id current-file-id) + :is-variant (ctk/is-variant? component)}) (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (ptk/data-event :layout/update {:ids [(:id new-shape)]}) @@ -704,7 +705,6 @@ data (dsh/lookup-file-data state) objects (dsh/lookup-page-objects state current-page-id) - select-and-zoom (fn [ids] (let [parent-ids (when update-layout? @@ -1158,6 +1158,7 @@ ;; FIXME: the data should be set on the backend for clock consistency + (def ignore-sync "Mark the file as ignore syncs. All library changes before this moment will not ber notified to sync." @@ -1226,7 +1227,6 @@ :callback do-update} :tag :sync-dialog))))))) - (defn touch-component "Update the modified-at attribute of the component to now" [id] diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 531720fa78..498dbd2bad 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -16,6 +16,7 @@ [app.common.geom.shapes :as gsh] [app.common.logic.libraries :as cll] [app.common.types.component :as ctk] + [app.common.types.container :as ctn] [app.common.uuid :as uuid] [app.main.data.changes :as dch] [app.main.data.event :as ev] @@ -484,6 +485,7 @@ (let [shape (get objects shape-id) parent-type (cfh/get-shape-type objects (:parent-id shape)) external-lib? (not= file-id (:component-file shape)) + component (ctn/get-component-from-shape shape libraries) origin "workspace:duplicate-shapes"] ;; NOTE: we don't emit the create-shape event all the time for @@ -494,7 +496,8 @@ ::ev/origin origin :is-external-library external-lib? :type (get shape :type) - :parent-type parent-type}) + :parent-type parent-type + :is-variant (ctk/is-variant? component)}) (if (cfh/has-layout? objects (:parent-id shape)) (ev/event {::ev/name "layout-add-element" ::ev/origin origin @@ -555,10 +558,10 @@ (assoc :workspace-focus-selected focus)))))) (defn toggle-focus-mode - "Zoom in on and center viewport on selection; + "Zoom in on and center viewport on selection; hide all other layers in viewport and layer panel. - When in focus mode, exit restoring previous viewport and selection. + When in focus mode, exit restoring previous viewport and selection. " [] (ptk/reify ::toggle-focus-mode @@ -597,7 +600,7 @@ (rx/map (comp set keys)) (rx/buffer 2 1) (rx/merge-map - ;; While focus is active, update it with any new and deleted shapes + ;; While focus is active, update it with any new and deleted shapes (fn [[old-keys new-keys]] (let [removed (set/difference old-keys new-keys) added (set/difference new-keys old-keys)] diff --git a/frontend/src/app/main/data/workspace/variants.cljs b/frontend/src/app/main/data/workspace/variants.cljs index 7861582c5f..8193e33a6c 100644 --- a/frontend/src/app/main/data/workspace/variants.cljs +++ b/frontend/src/app/main/data/workspace/variants.cljs @@ -21,6 +21,7 @@ [app.common.uuid :as uuid] [app.main.data.changes :as dch] [app.main.data.common :as dcm] + [app.main.data.event :as ev] [app.main.data.helpers :as dsh] [app.main.data.workspace.colors :as cl] [app.main.data.workspace.libraries :as dwl] @@ -85,6 +86,10 @@ undo-id (js/Symbol)] (rx/of + (when (or (seq properties-to-remove) (seq properties-to-update)) + (ptk/event ::ev/event {::ev/name "variant-edit-property-value" :trigger "rename-in-layers"})) + (when (seq properties-to-add) + (ptk/event ::ev/event {::ev/name "variant-add-property" :trigger "rename-in-layers"})) (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dwu/commit-undo-transaction undo-id)))))) @@ -132,7 +137,6 @@ (dch/commit-changes changes) (dwu/commit-undo-transaction undo-id)))))) - (defn update-error "Sets or unsets an error for a component" ([component-id] @@ -156,7 +160,6 @@ (dch/commit-changes changes) (dwu/commit-undo-transaction undo-id))))))) - (defn remove-property "Remove the variant property on the position pos in all the components with this variant-id" @@ -180,7 +183,6 @@ (dch/commit-changes changes) (dwu/commit-undo-transaction undo-id)))))) - (defn remove-empty-properties "Remove every empty property for all components when their respective values are empty for all of them" @@ -221,11 +223,12 @@ undo-id (js/Symbol)] - (rx/of - (dwu/start-undo-transaction undo-id) - (dch/commit-changes changes) - (dwu/commit-undo-transaction undo-id)))))) - + (when (seq (:redo-changes changes)) + (rx/of + (ptk/event ::ev/event {::ev/name "variant-remove-property" :trigger "rename-in-layers"}) + (dwu/start-undo-transaction undo-id) + (dch/commit-changes changes) + (dwu/commit-undo-transaction undo-id))))))) (defn add-new-property "Add a new variant property to all the components with this variant-id" @@ -273,7 +276,6 @@ (effect [_ _ _] (dom/focus! (dom/get-element (str "variant-prop-" shape-id prop-num)))))) - (defn- resposition-and-resize-variant "Resize the variant container, and move the shape (that is a variant) to the right" [shape-id] @@ -292,7 +294,6 @@ {:x x} {:absolute? false})))))) - (defn add-new-variant "Create a new variant and add it to the variant-container" [shape-id] @@ -403,6 +404,8 @@ ;;TODO Refactor all called methods in order to be able to ;;generate changes instead of call the events + + (rx/concat (rx/of (dwu/start-undo-transaction undo-id) @@ -458,11 +461,15 @@ undo-id (js/Symbol)] (cond transform-in-variant? - (rx/of (transform-in-variant (:id first-shape))) + (rx/of + (ptk/event ::ev/event {::ev/name "transform-in-variant" :trigger "shortcut"}) + (transform-in-variant (:id first-shape))) add-new-variant? (rx/concat - (rx/of (dwu/start-undo-transaction undo-id)) + (rx/of + (ptk/event ::ev/event {::ev/name "add-new-variant" :trigger "shortcut-create-component"}) + (dwu/start-undo-transaction undo-id)) (rx/from (map add-new-variant selected-ids)) (rx/of (dwu/commit-undo-transaction undo-id))) @@ -482,12 +489,13 @@ undo-id (js/Symbol)] (if add-new-variant? (rx/concat - (rx/of (dwu/start-undo-transaction undo-id)) + (rx/of + (ptk/event ::ev/event {::ev/name "add-new-variant" :trigger "shortcut-duplicate"}) + (dwu/start-undo-transaction undo-id)) (rx/from (map add-new-variant selected-ids)) (rx/of (dwu/commit-undo-transaction undo-id))) (rx/of (dws/duplicate-selected true))))))) - (defn rename-variant "Rename the variant container and all components belonging to this variant" [variant-id name] @@ -511,7 +519,6 @@ variant-components)) (rx/of (dwu/commit-undo-transaction undo-id))))))) - (defn rename-comp-or-variant-and-main "If the component is in a variant, rename the variant. If it is not, rename the component and its main" @@ -526,7 +533,6 @@ (rx/of (rename-variant (:variant-id component) name)) (rx/of (dwl/rename-component-and-main-instance component-id name))))))) - (defn- bounding-rect "Receives a list of frames (with X, y, width and height) and calculates a rect that contains them all" diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index e034dd7658..28a683a36b 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -580,7 +580,9 @@ do-combine-as-variants (mf/use-fn #(st/emit! (dwv/combine-as-variants))) do-add-variant (mf/use-fn (mf/deps shapes) - #(st/emit! (dwv/add-new-variant (:id (first shapes)))))] + #(st/emit! + (ptk/event ::ev/event {::ev/name "add-new-variant" :trigger "context-menu-component"}) + (dwv/add-new-variant (:id (first shapes)))))] [:* (when can-make-component ;; We don't want to change the structure of component copies [:* 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 aba00f1c47..2fb9829c1d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs @@ -17,6 +17,7 @@ [app.common.types.file :as ctf] [app.common.types.variant :as ctv] [app.config :as cf] + [app.main.data.event :as ev] [app.main.data.helpers :as dsh] [app.main.data.modal :as modal] [app.main.data.workspace :as dw] @@ -38,6 +39,7 @@ [app.util.timers :as ts] [cljs.spec.alpha :as s] [cuerdas.core :as str] + [potok.v2.core :as ptk] [rumext.v2 :as mf])) (def assets-filters (mf/create-context nil)) @@ -323,7 +325,7 @@ :is-hidden is-hidden}]))) (defn generate-components-menu-entries - [shapes] + [shapes & {:keys [for-design-tab?]}] (let [multi (> (count shapes) 1) copies (filter ctk/in-component-copy? shapes) @@ -434,12 +436,19 @@ do-add-variant #(if (ctk/is-variant? shape) - (st/emit! (dwv/add-new-variant id)) - (st/emit! (dwv/transform-in-variant id))) + (st/emit! + (ptk/event ::ev/event {::ev/name "add-new-variant" + :trigger (if for-design-tab? "design-tab-menu-variant" "context-menu-variant")}) + (dwv/add-new-variant id)) + (st/emit! + (ptk/event ::ev/event {::ev/name "transform-in-variant" + :trigger (if for-design-tab? "design-tab-menu" "context-menu")}) + (dwv/transform-in-variant id))) do-add-new-property - #(st/emit! (dwv/add-new-property variant-id {:property-value "Value 1" - :editing? true})) + #(st/emit! + (ptk/event ::ev/event {::ev/name "add-new-property" :trigger "design-tab-menu-variant"}) + (dwv/add-new-property variant-id {:property-value "Value 1" :editing? true})) do-show-local-component #(st/emit! (dwl/go-to-local-component :id component-id)) @@ -500,7 +509,7 @@ {:title (tr "workspace.shape.menu.add-variant") :shortcut :create-component :action do-add-variant}) - (when (and same-variant? main-instance? variant-id) + (when (and same-variant? main-instance? variant-id for-design-tab?) {:title (tr "workspace.shape.menu.add-variant-property") :action do-add-new-property})]] (filter (complement nil?) menu-entries))) 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 0408a70912..165e01495d 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 @@ -17,6 +17,7 @@ [app.common.types.file :as ctf] [app.common.types.variant :as ctv] [app.common.uuid :as uuid] + [app.main.data.event :as ev] [app.main.data.helpers :as dsh] [app.main.data.modal :as modal] [app.main.data.notifications :as ntf] @@ -47,6 +48,7 @@ [app.util.timers :as tm] [cuerdas.core :as str] [okulary.core :as l] + [potok.v2.core :as ptk] [rumext.v2 :as mf])) (def ref:annotations-state @@ -239,7 +241,6 @@ (when (or editing? creating?) [:div {:class (stl/css :counter)} (str size "/300")])]]))) - (defn- get-variant-malformed-warning-message "Receive a list of booleans, one for each selected variant, indicating if that variant is malformed, and generate a warning message accordingly" @@ -256,7 +257,6 @@ :else nil)) - (defn- get-variant-duplicated-warning-message "Receive a list of booleans, one for each selected variant, indicating if that variant is duplicated, and generate a warning message accordingly" @@ -273,7 +273,6 @@ :else nil)) - (defn- get-components-with-duplicated-variant-props-and-values "Get a list of components whose property names and values are duplicated" [components] @@ -293,7 +292,6 @@ get-components-with-duplicated-variant-props-and-values (map :main-instance-id))) - (defn- get-variant-options "Get variant options for a given property name" [prop-name prop-vals] @@ -303,7 +301,6 @@ (mapv (fn [val] {:id val :label (if (str/blank? val) (str "(" (tr "labels.empty") ")") val)})))) - (mf/defc component-variant-main-instance* [{:keys [components shapes data]}] (let [component (first components) @@ -345,7 +342,9 @@ (fn [pos value] (let [value (d/nilv (str/trim value) "")] (doseq [id component-ids] - (st/emit! (dwv/update-property-value id pos value)) + (st/emit! + (ptk/event ::ev/event {::ev/name "variant-edit-property-value" :trigger "combo-design-tab"}) + (dwv/update-property-value id pos value)) (st/emit! (dwv/update-error id)))))) update-property-name @@ -357,7 +356,9 @@ (dom/get-data "position") int)] (when (seq value) - (st/emit! (dwv/update-property-name variant-id pos value))))))] + (st/emit! + (ptk/event ::ev/event {::ev/name "variant-edit-property-name" :trigger "design-tab-variant"}) + (dwv/update-property-name variant-id pos value))))))] [:* [:div {:class (stl/css :variant-property-list)} @@ -398,7 +399,6 @@ [:div {:class (stl/css :variant-warning-highlight)} (str duplicated-msg)]]))])) - (mf/defc component-variant-copy* [{:keys [component shape data current-file-id]}] (let [page-objects (mf/deref refs/workspace-page-objects) @@ -514,7 +514,6 @@ :on-click select-duplicated-comps} (tr "workspace.options.component.variant.duplicated.copy.locate")]]))])) - (mf/defc component-swap-item* [{:keys [item loop shapes file-id root-shape container component-id is-search listing-thumbs num-variants]}] (let [on-select @@ -627,7 +626,6 @@ is-search? (not (str/blank? (:term filters))) - current-library-id (if (contains? libraries (:file-id filters)) (:file-id filters) current-file-id) @@ -638,7 +636,6 @@ current-lib-data (get-in libraries [current-library-id :data]) - components (->> (get-in libraries [current-library-id :data :components]) vals (remove #(true? (:deleted %))) @@ -688,7 +685,6 @@ ;; Get the ids of the components that are parents of the shapes, to avoid loops parent-components (mapcat find-parent-components shapes) - libraries-options (map (fn [library] {:value (:id library) :label (:name library)}) (vals libraries)) @@ -702,7 +698,6 @@ (fn [term] (swap! filters* assoc :term term))) - on-search-clear-click (mf/use-fn #(swap! filters* assoc :term "")) @@ -817,8 +812,6 @@ :on-click (partial do-action action)} [:span {:class (stl/css :dropdown-label)} title]]))]])) - - (mf/defc component-menu {::mf/props :obj} [{:keys [shapes swap-opened?]}] @@ -827,7 +820,6 @@ libraries (mf/deref refs/files) current-file (get libraries current-file-id) - state* (mf/use-state #(do {:show-content true :menu-open false})) @@ -903,13 +895,17 @@ create-variant (mf/use-fn (mf/deps id) - #(st/emit! (dwv/add-new-variant id))) + #(st/emit! + (ptk/event ::ev/event {::ev/name "add-new-variant" :trigger "button-design-tab-variant"}) + (dwv/add-new-variant id))) add-new-property (mf/use-fn (mf/deps shape) - #(st/emit! (dwv/add-new-property (:variant-id shape) {:property-value "Value 1" - :editing? true}))) + #(st/emit! + (ptk/event ::ev/event {::ev/name "add-new-property" :trigger "button-design-tab-variant"}) + (dwv/add-new-property (:variant-id shape) {:property-value "Value 1" + :editing? true}))) on-combine-as-variants (mf/use-fn @@ -926,7 +922,7 @@ (fn [] (swap! state* update :render inc))) - menu-entries (cmm/generate-components-menu-entries shapes) + menu-entries (cmm/generate-components-menu-entries shapes {:for-design-tab? true}) show-menu? (seq menu-entries) path (->> component (:path) (cfh/split-path) (cfh/join-path-with-dot))] @@ -1047,7 +1043,6 @@ (when (dbg/enabled? :display-touched) [:div ":touched " (str (:touched shape))])])]))) - (defn- move-empty-items-to-end "Creates a new vector with the empty items at the end" [v] @@ -1055,7 +1050,6 @@ (into (remove empty?) v) (into (filter empty?) v))) - (mf/defc variant-menu* [{:keys [shapes]}] (let [multi? (> (count shapes) 1) @@ -1095,18 +1089,23 @@ create-variant (mf/use-fn (mf/deps shape) - #(st/emit! (dwv/add-new-variant (:id shape)))) + (fn [trigger] + (st/emit! (ptk/event ::ev/event {::ev/name "add-new-variant" :trigger trigger}) + (dwv/add-new-variant (:id shape))))) add-new-property (mf/use-fn (mf/deps variant-id) - #(st/emit! (dwv/add-new-property variant-id {:property-value "Value 1" - :editing? true}))) + (fn [trigger] + (st/emit! + (ptk/event ::ev/event {::ev/name "add-new-property" :trigger trigger}) + (dwv/add-new-property variant-id {:property-value "Value 1" + :editing? true})))) menu-entries [{:title (tr "workspace.shape.menu.add-variant-property") - :action add-new-property} + :action (partial add-new-property "design-tab-menu-component")} {:title (tr "workspace.shape.menu.add-variant") - :action create-variant}] + :action (partial create-variant "design-tab-menu-component")}] toggle-content (mf/use-fn @@ -1140,7 +1139,9 @@ (dom/get-data "position") int)] (when (seq value) - (st/emit! (dwv/update-property-name variant-id pos value)))))) + (st/emit! + (ptk/event ::ev/event {::ev/name "variant-edit-property-name" :trigger "design-tab-component"}) + (dwv/update-property-name variant-id pos value)))))) remove-property (mf/use-fn @@ -1150,7 +1151,9 @@ (dom/get-data "position") int)] (when (> (count properties) 1) - (st/emit! (dwv/remove-property variant-id pos)))))) + (st/emit! + (ptk/event ::ev/event {::ev/name "variant-remove-property" :trigger "button-design-tab"}) + (dwv/remove-property variant-id pos)))))) select-shapes-with-malformed (mf/use-fn @@ -1183,7 +1186,7 @@ :icon i/help}] [:> icon-button* {:variant "ghost" :aria-label (tr "workspace.shape.menu.add-variant") - :on-click create-variant + :on-click (partial create-variant "button-design-tab-component") :icon i/variant}]]]] (when open? @@ -1221,7 +1224,7 @@ [:> icon-button* {:variant "ghost" :aria-label (tr "workspace.shape.menu.add-variant-property") - :on-click add-new-property + :on-click (partial add-new-property "button-design-tab-component") :icon i/add}]] (when-not multi?