mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 10:38:13 -05:00
🎉 Synchronize page with a library
This commit is contained in:
parent
5e585201d3
commit
917643489f
3 changed files with 131 additions and 11 deletions
|
@ -362,6 +362,9 @@
|
|||
(defmethod change-spec :del-component [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(defmethod change-spec :sync-library [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(s/def ::change (s/multi-spec change-spec :type))
|
||||
(s/def ::changes (s/coll-of ::change))
|
||||
|
||||
|
@ -774,6 +777,81 @@
|
|||
[data {:keys [id]}]
|
||||
(d/dissoc-in data [:components id]))
|
||||
|
||||
(declare sync-page)
|
||||
(declare sync-shape-and-children)
|
||||
(declare sync-shape)
|
||||
|
||||
(defmethod process-change :sync-library
|
||||
[data id]
|
||||
(cph/walk-pages (sync-page (:components data)) data))
|
||||
|
||||
(defn- sync-page
|
||||
[components]
|
||||
(fn [page-id page]
|
||||
(let [linked-shapes
|
||||
(cph/select-objects #(some? (:component-id %)) page)
|
||||
|
||||
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)))))
|
||||
|
||||
(defmethod process-operation :set
|
||||
[shape op]
|
||||
(let [attr (:attr op)
|
||||
|
|
|
@ -12,6 +12,24 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
(defn walk-pages
|
||||
"Go through all pages of a file and apply a function to each one"
|
||||
;; The function receives two parameters (page-id and page), and
|
||||
;; returns the updated page.
|
||||
[f data]
|
||||
(update data :pages-index #(d/mapm f %)))
|
||||
|
||||
(defn select-objects
|
||||
"Get a list of all objects in a page that satisfy a condition"
|
||||
[f page]
|
||||
(filter f (vals (get page :objects))))
|
||||
|
||||
(defn update-object-list
|
||||
"Update multiple objects in a page at once"
|
||||
[page objects-list]
|
||||
(update page :objects
|
||||
#(into % (d/index-by :id objects-list))))
|
||||
|
||||
(defn get-children
|
||||
"Retrieve all children ids recursively for a given object"
|
||||
[id objects]
|
||||
|
@ -20,6 +38,11 @@
|
|||
(d/concat shapes (mapcat #(get-children % objects) shapes))
|
||||
[])))
|
||||
|
||||
(defn get-children-objects
|
||||
"Retrieve all children objects recursively for a given object"
|
||||
[id objects]
|
||||
(map #(get objects %) (get-children id objects)))
|
||||
|
||||
(defn is-shape-grouped
|
||||
"Checks if a shape is inside a group"
|
||||
[shape-id objects]
|
||||
|
|
|
@ -142,7 +142,10 @@
|
|||
:id (:id updated-shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val (:component-id updated-shape)}]})
|
||||
:val (:component-id updated-shape)}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val (:shape-ref updated-shape)}]})
|
||||
updated-shapes))
|
||||
|
||||
uchanges (conj uchanges
|
||||
|
@ -156,6 +159,9 @@
|
|||
:id (:id updated-shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val nil}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val nil}]})
|
||||
updated-shapes))]
|
||||
|
||||
|
@ -174,10 +180,15 @@
|
|||
(let [new-shape (assoc shape
|
||||
:id new-id
|
||||
:parent-id parent-id
|
||||
:frame-id nil)]
|
||||
[new-shape
|
||||
[new-shape]
|
||||
[(assoc shape :component-id (:id new-shape))]])
|
||||
:frame-id nil)
|
||||
|
||||
new-shapes [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 []
|
||||
|
@ -188,11 +199,17 @@
|
|||
:id new-id
|
||||
:parent-id parent-id
|
||||
:frame-id nil
|
||||
:shapes (map :id new-children))]
|
||||
[new-shape
|
||||
(conj new-children new-shape)
|
||||
(conj updated-children
|
||||
(assoc shape :component-id (:id new-shape)))])
|
||||
: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)
|
||||
|
@ -213,7 +230,9 @@
|
|||
(let [component (get-in state [:workspace-data :components id])
|
||||
|
||||
rchanges [{:type :del-component
|
||||
:id id}]
|
||||
:id id}
|
||||
{:type :sync-library
|
||||
:id (get-in state [:workspace-file :id])}]
|
||||
|
||||
uchanges [{:type :add-component
|
||||
:id id
|
||||
|
|
Loading…
Add table
Reference in a new issue