From f837bad894e8fa350191a7b3fee77db714bd1109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 9 Sep 2020 11:19:29 +0200 Subject: [PATCH] :tada: Update master component --- common/app/common/data.cljc | 14 ++ common/app/common/pages.cljc | 116 ++++------ common/app/common/pages_helpers.cljc | 81 +++++++ frontend/src/app/main/data/workspace.cljs | 8 +- .../src/app/main/data/workspace/common.cljs | 6 + .../app/main/data/workspace/libraries.cljs | 206 ++++++++++++++---- .../app/main/data/workspace/selection.cljs | 39 +--- .../app/main/ui/workspace/context_menu.cljs | 20 +- .../app/main/ui/workspace/sidebar/assets.cljs | 6 +- .../src/app/main/ui/workspace/viewport.cljs | 7 + 10 files changed, 337 insertions(+), 166 deletions(-) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index cef92e02e3..fe84e3f832 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -182,6 +182,20 @@ (assoc m key (apply f found args)) m))) +(defn assoc-in-when + [m key-seq v] + (let [found (get-in m key-seq sentinel)] + (if-not (identical? sentinel found) + (assoc-in m key-seq v) + m))) + +(defn assoc-when + [m key v] + (let [found (get m key sentinel)] + (if-not (identical? sentinel found) + (assoc m key v) + m))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data Parsing / Conversion ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 42acab8997..fba45543bb 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -362,8 +362,8 @@ (defmethod change-spec :del-component [_] (s/keys :req-un [::id])) -(defmethod change-spec :sync-library [_] - (s/keys :req-un [::id])) +(defmethod change-spec :update-component [_] + (s/keys :req-un [::id ::shapes])) (s/def ::change (s/multi-spec change-spec :type)) (s/def ::changes (s/coll-of ::change)) @@ -777,80 +777,50 @@ [data {:keys [id]}] (d/dissoc-in data [:components id])) -(declare sync-page) -(declare sync-shape-and-children) -(declare sync-shape) +(declare sync-component-shape) -(defmethod process-change :sync-library - [data id] - (cph/walk-pages (sync-page (:components data)) data)) +(defmethod process-change :update-component + [data {:keys [id shapes]}] + (let [sync-component + (fn [component] + (update component :objects + #(d/mapm (partial sync-component-shape shapes) %)))] -(defn- sync-page - [components] - (fn [page-id page] - (let [linked-shapes - (cph/select-objects #(some? (:component-id %)) page) + (update-in data [:components id] sync-component))) - updated-shapes - (reduce - (fn [updated-shapes linked-shape] - (let [component-id (:component-id linked-shape) - component (get components component-id)] - (into updated-shapes - (sync-shape-and-children linked-shape - component - (:objects page))))) - [] - linked-shapes)] - - (cph/update-object-list page updated-shapes)))) - -(defn- sync-shape-and-children - [linked-shape component objects] - (let [children (cph/get-children-objects (:id linked-shape) objects) - all-shapes (conj children linked-shape)] - (if (nil? component) - (map #(dissoc % :component-id :shape-ref) all-shapes) - (map #(sync-shape % (:objects component)) all-shapes)))) - -(defn- sync-shape - [shape component-objs] - (let [component-shape (get component-objs (:shape-ref shape))] - (if (nil? component-shape) - (assoc shape :shape-ref nil) - (-> shape - (d/update-when :content :content component-shape) - (d/update-when :fill-color :fill-color component-shape) - (d/update-when :fill-color-ref-file :fill-color-ref-file component-shape) - (d/update-when :fill-color-ref-id :fill-color-ref-id component-shape) - (d/update-when :fill-opacity :fill-opacity component-shape) - (d/update-when :font-family :font-family component-shape) - (d/update-when :font-size :font-size component-shape) - (d/update-when :font-style :font-style component-shape) - (d/update-when :font-weight :font-weight component-shape) - (d/update-when :letter-spacing :letter-spacing component-shape) - (d/update-when :line-height :line-height component-shape) - (d/update-when :proportion :proportion component-shape) - (d/update-when :rx :rx component-shape) - (d/update-when :ry :ry component-shape) - (d/update-when :cx :cx component-shape) - (d/update-when :cy :cy component-shape) - (d/update-when :x :x component-shape) - (d/update-when :y :y component-shape) - (d/update-when :exports :exports component-shape) - (d/update-when :stroke-color :stroke-color component-shape) - (d/update-when :stroke-color-ref-file :stroke-color-ref-file component-shape) - (d/update-when :stroke-color-ref-id :stroke-color-ref-id component-shape) - (d/update-when :stroke-opacity :stroke-opacity component-shape) - (d/update-when :stroke-style :stroke-style component-shape) - (d/update-when :stroke-width :stroke-width component-shape) - (d/update-when :stroke-alignment :stroke-alignment component-shape) - (d/update-when :text-align :text-align component-shape) - (d/update-when :width :width component-shape) - (d/update-when :height :height component-shape) - (d/update-when :interactions :interactions component-shape) - (d/update-when :selrect :selrect component-shape) - (d/update-when :points :points component-shape))))) +(defn- sync-component-shape + [new-shapes _ component-shape] + (let [shape (d/seek #(= (:shape-ref %) (:id component-shape)) new-shapes)] + (if (nil? shape) + component-shape + (-> component-shape + (d/assoc-when :content (:content shape)) + (d/assoc-when :fill-color (:fill-color shape)) + (d/assoc-when :fill-color-ref-file (:fill-color-ref-file shape)) + (d/assoc-when :fill-color-ref-id (:fill-color-ref-id shape)) + (d/assoc-when :fill-opacity (:fill-opacity shape)) + (d/assoc-when :font-family (:font-family shape)) + (d/assoc-when :font-size (:font-size shape)) + (d/assoc-when :font-style (:font-style shape)) + (d/assoc-when :font-weight (:font-weight shape)) + (d/assoc-when :letter-spacing (:letter-spacing shape)) + (d/assoc-when :line-height (:line-height shape)) + (d/assoc-when :proportion (:proportion shape)) + (d/assoc-when :rx (:rx shape)) + (d/assoc-when :ry (:ry shape)) + (d/assoc-when :stroke-color (:stroke-color shape)) + (d/assoc-when :stroke-color-ref-file (:stroke-color-ref-file shape)) + (d/assoc-when :stroke-color-ref-id (:stroke-color-ref-id shape)) + (d/assoc-when :stroke-opacity (:stroke-opacity shape)) + (d/assoc-when :stroke-style (:stroke-style shape)) + (d/assoc-when :stroke-width (:stroke-width shape)) + (d/assoc-when :stroke-alignment (:stroke-alignment shape)) + (d/assoc-when :text-align (:text-align shape)) + (d/assoc-when :width (:width shape)) + (d/assoc-when :height (:height shape)) + (d/assoc-when :interactions (:interactions shape)) + (d/assoc-when :selrect (:selrect shape)) + (d/assoc-when :points (:points shape)))))) (defmethod process-operation :set [shape op] diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index 57fbd955a2..1754665ffc 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -30,6 +30,16 @@ (update page :objects #(into % (d/index-by :id objects-list)))) +(defn get-root-component + "Get the root shape linked to the component for this shape, if any" + [id objects] + (let [obj (get objects id)] + (if-let [component-id (:component-id obj)] + id + (if-let [parent-id (:parent-id obj)] + (get-root-component parent-id obj) + nil)))) + (defn get-children "Retrieve all children ids recursively for a given object" [id objects] @@ -43,6 +53,26 @@ [id objects] (map #(get objects %) (get-children id objects))) +(defn get-object-with-children + "Retrieve a list with an object and all of its children" + [id objects] + (map #(get objects %) (concat [id] (get-children id objects)))) + +(defn walk-children + "Go through an object and all the children tree, and apply a + function to each one. Return the list of changed objects." + [id f objects] + (let [obj (get objects id)] + (if (nil? (:shapes obj)) + [(apply f obj)] + (loop [children (map #(get objects %) (:shapes obj)) + updated-children []] + (if (empty? children) + updated-children + (let [child (first children)] + (recur (rest children) + (concat [(apply f child)] updated-children)))))))) + (defn is-shape-grouped "Checks if a shape is inside a group" [shape-id objects] @@ -136,3 +166,54 @@ (lazy-seq (loopfn (rest ids))))))] (loopfn (:shapes root)))) +(defn clone-object + "Gets a copy of the object and all its children, with new ids + and with the parent-children links correctly set. Admits functions + to make more transformations to the cloned objects and the + original ones. + + Returns the cloned object, the list of all new objects (including + the cloned one), and possibly a list of original objects modified." + ([object parent-id objects xf-new-object] + (clone-object object parent-id objects xf-new-object identity)) + + ([object parent-id objects xf-new-object xf-original-object] + (let [new-id (uuid/next)] + (loop [child-ids (seq (:shapes object)) + new-direct-children [] + new-children [] + updated-children []] + + (if (empty? child-ids) + (let [new-object (cond-> object + true + (assoc :id new-id + :parent-id parent-id) + + (some? (:shapes object)) + (assoc :shapes (map :id new-direct-children))) + + new-object (xf-new-object new-object object) + + new-objects (concat [new-object] new-children) + + updated-object (xf-original-object object new-object) + + updated-objects (if (= object updated-object) + updated-children + (concat [updated-object] updated-children))] + + [new-object new-objects updated-objects]) + + (let [child-id (first child-ids) + child (get objects child-id) + + [new-child new-child-objects updated-child-objects] + (clone-object child new-id objects xf-new-object xf-original-object)] + + (recur + (next child-ids) + (concat new-direct-children [new-child]) + (concat new-children new-child-objects) + (concat updated-children updated-child-objects)))))))) + diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index d16ab658c7..4bf7debbdb 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -48,10 +48,6 @@ (s/def ::set-of-string (s/every string? :kind set?)) -;; --- Expose inner functions - -(defn interrupt? [e] (= e :interrupt)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Workspace Initialization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -956,7 +952,7 @@ ptk/WatchEvent (watch [_ state stream] (->> stream - (rx/filter interrupt?) + (rx/filter dwc/interrupt?) (rx/take 1) (rx/map (constantly clear-edition-mode)))))) @@ -985,7 +981,7 @@ ptk/WatchEvent (watch [_ state stream] (let [cancel-event? (fn [event] - (interrupt? event)) + (dwc/interrupt? event)) stoper (rx/filter (ptk/type? ::clear-drawing) stream)] (->> (rx/filter cancel-event? stream) (rx/take 1) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 0bae8964c6..726f037862 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -44,6 +44,11 @@ ([state page-id] (get-in state [:workspace-data :pages-index page-id :options]))) +(defn interrupt? [e] (= e :interrupt)) + +(defn lookup-component-objects + ([state component-id] + (get-in state [:workspace-data :components component-id :objects]))) ;; --- Changes Handling @@ -454,3 +459,4 @@ objects (lookup-page-objects state page-id) [rchanges uchanges] (impl-gen-changes objects page-id (seq ids))] (rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))) + diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 16ecdf42a3..0fb5d891bb 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -12,11 +12,15 @@ [app.common.data :as d] [app.common.spec :as us] [app.common.uuid :as uuid] + [app.common.pages-helpers :as cph] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as geom] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.selection :as dws] [app.common.pages :as cp] [app.main.repo :as rp] [app.main.store :as st] + [app.main.streams :as ms] [app.util.color :as color] [app.util.i18n :refer [tr]] [beicon.core :as rx] @@ -107,7 +111,7 @@ :object prev}] (rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})))))) -(declare clone-shape) +(declare make-component-shape) (def add-component (ptk/reify ::add-component @@ -127,7 +131,7 @@ (dws/prepare-create-group page-id shapes "Component-" true)) [new-shape new-shapes updated-shapes] - (clone-shape group nil objects) + (make-component-shape group nil objects) rchanges (conj rchanges {:type :add-component @@ -168,59 +172,23 @@ (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) (dws/select-shapes (d/ordered-set (:id group)))))))))) -(defn- clone-shape +(defn- make-component-shape "Clone the shape and all children. Generate new ids and detach from parent and frame. Update the original shapes to have links to the new ones." [shape parent-id objects] - (let [new-id (uuid/next)] - (if (nil? (:shapes shape)) + (let [xf-new-shape (fn [new-shape original-shape] + (assoc new-shape :frame-id nil)) - ; TODO: unify this case with the empty child-ids case. - (let [new-shape (assoc shape - :id new-id - :parent-id parent-id - :frame-id nil) + xf-original-shape (fn [original-shape new-shape] + (cond-> original-shape + true + (assoc :shape-ref (:id new-shape)) - new-shapes [new-shape] + (nil? (:parent-id new-shape)) + (assoc :component-id (:id new-shape))))] - updated-shapes [(cond-> shape - true (assoc :shape-ref (:id new-shape)) - (nil? parent-id) (assoc :component-id (:id new-shape)))]] - - [new-shape new-shapes updated-shapes]) - - (loop [child-ids (seq (:shapes shape)) - new-children [] - updated-children []] - - (if (empty? child-ids) - (let [new-shape (assoc shape - :id new-id - :parent-id parent-id - :frame-id nil - :shapes (map :id new-children)) - - new-shapes (conj new-children new-shape) - - updated-shapes - (conj updated-children - (cond-> shape - true (assoc :shape-ref (:id new-shape)) - (nil? parent-id) (assoc :component-id (:id new-shape))))] - - [new-shape new-shapes updated-shapes]) - - (let [child-id (first child-ids) - child (get objects child-id) - - [new-child new-child-shapes updated-child-shapes] - (clone-shape child new-id objects)] - - (recur - (next child-ids) - (into new-children new-child-shapes) - (into updated-children updated-child-shapes)))))))) + (cph/clone-object shape parent-id objects xf-new-shape xf-original-shape))) (defn delete-component [{:keys [id] :as params}] @@ -241,3 +209,145 @@ (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) +(defn instantiate-component + [id] + (us/assert ::us/uuid id) + (ptk/reify ::instantiate-component + ptk/WatchEvent + (watch [_ state stream] + (let [component (get-in state [:workspace-data :components id]) + component-shape (get-in component [:objects (:id component)]) + + orig-pos (gpt/point (:x component-shape) (:y component-shape)) + mouse-pos @ms/mouse-position + delta (gpt/subtract mouse-pos orig-pos) + + _ (js/console.log "orig-pos" (clj->js orig-pos)) + _ (js/console.log "mouse-pos" (clj->js mouse-pos)) + _ (js/console.log "delta" (clj->js delta)) + + page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + unames (dwc/retrieve-used-names objects) + + all-frames (cph/select-frames objects) + + xf-new-shape + (fn [new-shape original-shape] + (let [new-name ;; TODO: ojoooooooooo + (dwc/generate-unique-name unames (:name new-shape))] + + (cond-> new-shape + true + (as-> $ + (assoc $ :name new-name) + (geom/move $ delta) + (assoc $ :frame-id + (dwc/calculate-frame-overlap all-frames $)) + (assoc $ :parent-id + (or (:parent-id $) (:frame-id $))) + (assoc $ :shape-ref (:id original-shape))) + + (nil? (:parent-id original-shape)) + (assoc :component-id (:id original-shape))))) + + [new-shape new-shapes _] + (cph/clone-object component-shape + nil + (get component :objects) + xf-new-shape) + + rchanges (map (fn [obj] + {:type :add-obj + :id (:id obj) + :page-id page-id + :frame-id (:frame-id obj) + :parent-id (:parent-id obj) + :obj obj}) + new-shapes) + + uchanges (map (fn [obj] + {:type :del-obj + :id (:id obj) + :page-id page-id}) + new-shapes)] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) + (dws/select-shapes (d/ordered-set (:id new-shape)))))))) + +(defn detach-component + [id] + (us/assert ::us/uuid id) + (ptk/reify ::detach-component + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + root-id (cph/get-root-component id objects) + + shapes (cph/get-object-with-children root-id objects) + + rchanges (map (fn [obj] + {:type :mod-obj + :page-id page-id + :id (:id obj) + :operations [{:type :set + :attr :component-id + :val nil} + {:type :set + :attr :shape-ref + :val nil}]}) + shapes) + + uchanges (map (fn [obj] + {:type :mod-obj + :page-id page-id + :id (:id obj) + :operations [{:type :set + :attr :component-id + :val (:component-id obj)} + {:type :set + :attr :shape-ref + :val (:shape-ref obj)}]}) + shapes)] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) + +(defn reset-component + [id] + [id] + (us/assert ::us/uuid id) + (ptk/reify ::reset-component + ptk/WatchEvent + (watch [_ state stream] + ))) + +(defn update-component + [id] + [id] + (us/assert ::us/uuid id) + (ptk/reify ::update-component + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + root-id (cph/get-root-component id objects) + root-shape (get objects id) + component-id (get root-shape :component-id) + component-objs (dwc/lookup-component-objects state component-id) + + shapes (cph/get-object-with-children root-id objects) + + rchanges [{:type :update-component + :id component-id + :shapes shapes} + {:type :sync-library + :id (get-in state [:workspace-file :id])}] + + + uchanges [{:type :update-component + :id component-id + :shapes (vals component-objs)}]] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) + diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index c60fed1b70..27b32ac5bf 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -33,33 +33,6 @@ (s/def ::set-of-string (s/every string? :kind set?)) -;; Duplicate from workspace. -;; FIXME: Move these functions to a common place - -(defn interrupt? [e] (= e :interrupt)) - -(defn- retrieve-used-names - [objects] - (into #{} (map :name) (vals objects))) - -(defn- extract-numeric-suffix - [basename] - (if-let [[match p1 p2] (re-find #"(.*)-([0-9]+)$" basename)] - [p1 (+ 1 (d/parse-integer p2))] - [basename 1])) - -(defn- generate-unique-name - "A unique name generator" - [used basename] - (s/assert ::set-of-string used) - (s/assert ::us/string basename) - (let [[prefix initial] (extract-numeric-suffix basename)] - (loop [counter initial] - (let [candidate (str prefix "-" counter)] - (if (contains? used candidate) - (recur (inc counter)) - candidate))))) - ;; --- Selection Rect (declare select-shapes-by-current-selrect) @@ -88,7 +61,7 @@ (ptk/reify ::handle-selection ptk/WatchEvent (watch [_ state stream] - (let [stoper (rx/filter #(or (interrupt? %) + (let [stoper (rx/filter #(or (dwc/interrupt? %) (ms/mouse-up? %)) stream)] (rx/concat @@ -198,7 +171,9 @@ (let [selrect (geom/selection-rect shapes) frame-id (-> shapes first :frame-id) parent-id (-> shapes first :parent-id) - group-name (if (and keep-name (= (count shapes) 1)) + group-name (if (and keep-name + (= (count shapes) 1) + (= (:type (first shapes)) :group)) (:name (first shapes)) (name (gensym prefix)))] (-> (cp/make-minimal-group frame-id selrect group-name) @@ -298,7 +273,7 @@ (defn- prepare-duplicate-shape-change [objects page-id names obj delta frame-id parent-id] (let [id (uuid/next) - name (generate-unique-name names (:name obj)) + name (dwc/generate-unique-name names (:name obj)) renamed-obj (assoc obj :id id :name name) moved-obj (geom/move renamed-obj delta) frames (cph/select-frames objects) @@ -338,7 +313,7 @@ (defn- prepare-duplicate-frame-change [objects page-id names obj delta] (let [frame-id (uuid/next) - frame-name (generate-unique-name names (:name obj)) + frame-name (dwc/generate-unique-name names (:name obj)) sch (->> (map #(get objects %) (:shapes obj)) (mapcat #(prepare-duplicate-shape-change objects page-id names % delta frame-id frame-id))) @@ -367,7 +342,7 @@ selected (get-in state [:workspace-local :selected]) delta (gpt/point 0 0) - unames (retrieve-used-names objects) + unames (dwc/retrieve-used-names objects) rchanges (prepare-duplicate-changes objects page-id unames selected delta) uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %)) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 5277e32b32..7669046bcd 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -61,7 +61,10 @@ do-unlock-shape #(st/emit! (dw/update-shape-flags id {:blocked false})) do-create-group #(st/emit! dw/group-selected) do-remove-group #(st/emit! dw/ungroup-selected) - do-add-component #(st/emit! dwl/add-component)] + do-add-component #(st/emit! dwl/add-component) + do-detach-component #(st/emit! (dwl/detach-component id)) + do-reset-component #(st/emit! (dwl/reset-component id)) + do-update-component #(st/emit! (dwl/update-component id))] [:* [:& menu-entry {:title "Copy" :shortcut "Ctrl + c" @@ -110,9 +113,18 @@ :on-click do-lock-shape}]) [:& menu-separator] - [:& menu-entry {:title "Create component" - :shortcut "Ctrl + K" - :on-click do-add-component}] + + (if (nil? (:shape-ref shape)) + [:& menu-entry {:title "Create component" + :shortcut "Ctrl + K" + :on-click do-add-component}] + [:* + [:& menu-entry {:title "Detach instance" + :on-click do-detach-component}] + [:& menu-entry {:title "Reset overrides" + :on-click do-reset-component}] + [:& menu-entry {:title "Update master component" + :on-click do-update-component}]]) [:& menu-separator] [:& menu-entry {:title "Delete" diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index b3d6484a04..8323948357 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -69,8 +69,8 @@ on-drag-start (mf/use-callback - (fn [path event] - (dnd/set-data! event "text/uri-list" (cfg/resolve-media-path path)) + (fn [component-id event] + (dnd/set-data! event "app/component" component-id) (dnd/set-allowed-effect! event "move")))] [:div.asset-group @@ -82,7 +82,7 @@ [:div.grid-cell {:key (:id component) :draggable true :on-context-menu (on-context-menu (:id component)) - :on-drag-start (partial on-drag-start (:path component))} + :on-drag-start (partial on-drag-start (:id component))} [:& exports/component-svg {:group (get-in component [:objects (:id component)]) :objects (:objects component)}] [:div.cell-name (:name component)]]) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 2fec8d0f21..224eecda42 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -22,6 +22,7 @@ [app.common.data :as d] [app.main.constants :as c] [app.main.data.workspace :as dw] + [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.drawing :as dd] [app.main.data.colors :as dwc] [app.main.data.fetch :as mdf] @@ -454,6 +455,7 @@ on-drag-enter (fn [e] (when (or (dnd/has-type? e "app/shape") + (dnd/has-type? e "app/component") (dnd/has-type? e "Files") (dnd/has-type? e "text/uri-list")) (dom/prevent-default e))) @@ -461,6 +463,7 @@ on-drag-over (fn [e] (when (or (dnd/has-type? e "app/shape") + (dnd/has-type? e "app/component") (dnd/has-type? e "Files") (dnd/has-type? e "text/uri-list")) (dom/prevent-default e))) @@ -491,6 +494,10 @@ (assoc :x final-x) (assoc :y final-y))))) + (dnd/has-type? event "app/component") + (let [component-id (dnd/get-data event "app/component")] + (st/emit! (dwl/instantiate-component component-id))) + (dnd/has-type? event "text/uri-list") (let [data (dnd/get-data event "text/uri-list") lines (str/lines data)