mirror of
https://github.com/penpot/penpot.git
synced 2025-06-06 23:41:40 +02:00
Merge pull request #6214 from penpot/palba-cleanup-components-v2
♻️ Cleanup of componentsv2 ✨ Add check to avoid open files with components v1
This commit is contained in:
commit
af1d5b86e1
44 changed files with 346 additions and 1208 deletions
|
@ -1462,8 +1462,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
file-id
|
file-id
|
||||||
true
|
|
||||||
nil
|
|
||||||
cfsh/prepare-create-artboard-from-selection)]
|
cfsh/prepare-create-artboard-from-selection)]
|
||||||
|
|
||||||
(shape-cb shape)
|
(shape-cb shape)
|
||||||
|
|
|
@ -179,7 +179,7 @@
|
||||||
component-child (first component-children)]
|
component-child (first component-children)]
|
||||||
(if (or (nil? child) (nil? component-child))
|
(if (or (nil? child) (nil? component-child))
|
||||||
container
|
container
|
||||||
(let [container (if (and (not (ctk/is-main-of? component-child child true))
|
(let [container (if (and (not (ctk/is-main-of? component-child child))
|
||||||
(nil? (ctk/get-swap-slot child))
|
(nil? (ctk/get-swap-slot child))
|
||||||
(ctk/instance-head? child))
|
(ctk/instance-head? child))
|
||||||
(let [slot (guess-swap-slot component-child component-container)]
|
(let [slot (guess-swap-slot component-child component-container)]
|
||||||
|
|
|
@ -104,7 +104,6 @@
|
||||||
"Translate a flag to a feature name"
|
"Translate a flag to a feature name"
|
||||||
[flag]
|
[flag]
|
||||||
(case flag
|
(case flag
|
||||||
:feature-components-v2 "components/v2"
|
|
||||||
:feature-styles-v2 "styles/v2"
|
:feature-styles-v2 "styles/v2"
|
||||||
:feature-fdata-objects-map "fdata/objects-map"
|
:feature-fdata-objects-map "fdata/objects-map"
|
||||||
:feature-fdata-pointer-map "fdata/pointer-map"
|
:feature-fdata-pointer-map "fdata/pointer-map"
|
||||||
|
@ -241,7 +240,13 @@
|
||||||
:code :file-feature-mismatch
|
:code :file-feature-mismatch
|
||||||
:feature (first not-supported)
|
:feature (first not-supported)
|
||||||
:hint (str/ffmt "file features '%' not enabled"
|
:hint (str/ffmt "file features '%' not enabled"
|
||||||
(str/join "," not-supported))))))
|
(str/join "," not-supported)))))
|
||||||
|
|
||||||
|
;; Components v1 is deprecated
|
||||||
|
(when-not (contains? file-features "components/v2")
|
||||||
|
(ex/raise :type :restriction
|
||||||
|
:code :file-in-components-v1
|
||||||
|
:hint "components v1 is deprecated")))
|
||||||
|
|
||||||
enabled-features))
|
enabled-features))
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.files.changes :as ch]
|
[app.common.files.changes :as ch]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.rect :as grc]
|
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pprint :as pp]
|
[app.common.pprint :as pp]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
|
@ -38,20 +37,12 @@
|
||||||
fail-on-spec?]
|
fail-on-spec?]
|
||||||
:or {add-container? false
|
:or {add-container? false
|
||||||
fail-on-spec? false}}]
|
fail-on-spec? false}}]
|
||||||
(let [components-v2 (dm/get-in file [:data :options :components-v2])
|
(let [change (cond-> change
|
||||||
component-id (:current-component-id file)
|
add-container?
|
||||||
change (cond-> change
|
|
||||||
(and add-container? (some? component-id) (not components-v2))
|
|
||||||
(-> (assoc :component-id component-id)
|
|
||||||
(cond-> (some? (:current-frame-id file))
|
|
||||||
(assoc :frame-id (:current-frame-id file))))
|
|
||||||
|
|
||||||
(and add-container? (or (nil? component-id) components-v2))
|
|
||||||
(assoc :page-id (:current-page-id file)
|
(assoc :page-id (:current-page-id file)
|
||||||
:frame-id (:current-frame-id file)))
|
:frame-id (:current-frame-id file)))
|
||||||
|
|
||||||
valid? (or (and components-v2
|
valid? (or (and (nil? (:component-id change))
|
||||||
(nil? (:component-id change))
|
|
||||||
(nil? (:page-id change)))
|
(nil? (:page-id change)))
|
||||||
(ch/valid-change? change))]
|
(ch/valid-change? change))]
|
||||||
|
|
||||||
|
@ -66,11 +57,11 @@
|
||||||
|
|
||||||
(cond-> file
|
(cond-> file
|
||||||
(and valid? (or (not add-container?) (some? (:component-id change)) (some? (:page-id change))))
|
(and valid? (or (not add-container?) (some? (:component-id change)) (some? (:page-id change))))
|
||||||
(-> (update :changes conjv change) ;; In components-v2 we do not add shapes
|
(-> (update :changes conjv change)
|
||||||
(update :data ch/process-changes [change] false)) ;; inside a component
|
(update :data ch/process-changes [change] false))
|
||||||
|
|
||||||
(not valid?)
|
(not valid?)
|
||||||
(update :errors conjv change)))));)
|
(update :errors conjv change)))))
|
||||||
|
|
||||||
(defn- lookup-objects
|
(defn- lookup-objects
|
||||||
([file]
|
([file]
|
||||||
|
@ -185,12 +176,10 @@
|
||||||
(update :parent-stack conjv (:id obj)))))
|
(update :parent-stack conjv (:id obj)))))
|
||||||
|
|
||||||
(defn close-artboard [file]
|
(defn close-artboard [file]
|
||||||
(let [components-v2 (dm/get-in file [:data :options :components-v2])
|
(let [parent-id (-> file :parent-stack peek)
|
||||||
parent-id (-> file :parent-stack peek)
|
|
||||||
parent (lookup-shape file parent-id)
|
parent (lookup-shape file parent-id)
|
||||||
current-frame-id (or (:frame-id parent)
|
current-frame-id (or (:frame-id parent)
|
||||||
(when (or (nil? (:current-component-id file)) components-v2)
|
root-id)]
|
||||||
root-id))]
|
|
||||||
(-> file
|
(-> file
|
||||||
(assoc :current-frame-id current-frame-id)
|
(assoc :current-frame-id current-frame-id)
|
||||||
(update :parent-stack pop))))
|
(update :parent-stack pop))))
|
||||||
|
@ -514,58 +503,29 @@
|
||||||
|
|
||||||
(defn start-component
|
(defn start-component
|
||||||
([file data]
|
([file data]
|
||||||
(let [components-v2 (dm/get-in file [:data :options :components-v2])
|
(start-component file data :frame))
|
||||||
root-type (if components-v2 :frame :group)]
|
|
||||||
(start-component file data root-type)))
|
|
||||||
|
|
||||||
([file data root-type]
|
([file data root-type]
|
||||||
;; FIXME: data probably can be a shape instance, then we can use gsh/shape->rect
|
(let [name (:name data)
|
||||||
(let [components-v2 (dm/get-in file [:data :options :components-v2])
|
|
||||||
selrect (or (grc/make-rect (:x data) (:y data) (:width data) (:height data))
|
|
||||||
grc/empty-rect)
|
|
||||||
name (:name data)
|
|
||||||
path (:path data)
|
path (:path data)
|
||||||
main-instance-id (:main-instance-id data)
|
main-instance-id (:main-instance-id data)
|
||||||
main-instance-page (:main-instance-page data)
|
main-instance-page (:main-instance-page data)
|
||||||
|
|
||||||
;; In components v1 we must create the root shape and set it inside
|
obj-id (or (:id data) (uuid/next))]
|
||||||
;; the :objects attribute of the component. When in components-v2,
|
|
||||||
;; this will be ignored as the root shape has already been created
|
|
||||||
;; in its page, by the normal page import.
|
|
||||||
attrs (-> data
|
|
||||||
(assoc :type root-type)
|
|
||||||
(assoc :x (:x selrect))
|
|
||||||
(assoc :y (:y selrect))
|
|
||||||
(assoc :width (:width selrect))
|
|
||||||
(assoc :height (:height selrect))
|
|
||||||
(assoc :selrect selrect)
|
|
||||||
(dissoc :path)
|
|
||||||
(dissoc :main-instance-id)
|
|
||||||
(dissoc :main-instance-page)
|
|
||||||
(dissoc :main-instance-x)
|
|
||||||
(dissoc :main-instance-y))
|
|
||||||
|
|
||||||
obj (-> (cts/setup-shape attrs)
|
|
||||||
(check-name file root-type)
|
|
||||||
;; Components need to have nil values for frame and parent
|
|
||||||
(assoc :frame-id nil)
|
|
||||||
(assoc :parent-id nil))]
|
|
||||||
|
|
||||||
(-> file
|
(-> file
|
||||||
(commit-change
|
(commit-change
|
||||||
(cond-> {:type :add-component
|
{:type :add-component
|
||||||
:id (:id obj)
|
:id obj-id
|
||||||
:name name
|
:name name
|
||||||
:path path
|
:path path
|
||||||
:main-instance-id main-instance-id
|
:main-instance-id main-instance-id
|
||||||
:main-instance-page main-instance-page}
|
:main-instance-page main-instance-page})
|
||||||
(not components-v2)
|
|
||||||
(assoc :shapes [obj])))
|
|
||||||
|
|
||||||
(assoc :last-id (:id obj))
|
(assoc :last-id obj-id)
|
||||||
(assoc :parent-stack [(:id obj)])
|
(assoc :parent-stack [obj-id])
|
||||||
(assoc :current-component-id (:id obj))
|
(assoc :current-component-id obj-id)
|
||||||
(assoc :current-frame-id (if (= (:type obj) :frame) (:id obj) uuid/zero))))))
|
(assoc :current-frame-id (if (= root-type :frame) obj-id uuid/zero))))))
|
||||||
|
|
||||||
(defn start-deleted-component
|
(defn start-deleted-component
|
||||||
[file data]
|
[file data]
|
||||||
|
@ -600,8 +560,7 @@
|
||||||
|
|
||||||
file
|
file
|
||||||
(cond
|
(cond
|
||||||
;; In components-v2 components haven't any shape inside them.
|
component-data
|
||||||
(and component-data (:main-instance-id component-data))
|
|
||||||
(update file :data
|
(update file :data
|
||||||
(fn [data]
|
(fn [data]
|
||||||
(ctkl/update-component data component-id dissoc :objects)))
|
(ctkl/update-component data component-id dissoc :objects)))
|
||||||
|
@ -677,17 +636,12 @@
|
||||||
page (ctpl/get-page (:data file) page-id)
|
page (ctpl/get-page (:data file) page-id)
|
||||||
component (ctkl/get-component (:data file) component-id)
|
component (ctkl/get-component (:data file) component-id)
|
||||||
|
|
||||||
components-v2 (dm/get-in file [:options :components-v2])
|
|
||||||
|
|
||||||
[shape shapes]
|
[shape shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:id file)
|
(:id file)
|
||||||
(gpt/point x
|
(gpt/point x
|
||||||
y)
|
y))]
|
||||||
components-v2
|
|
||||||
#_{:main-instance true
|
|
||||||
:force-id main-instance-id})]
|
|
||||||
|
|
||||||
(as-> file $
|
(as-> file $
|
||||||
(reduce #(commit-change %1
|
(reduce #(commit-change %1
|
||||||
|
|
|
@ -921,11 +921,11 @@
|
||||||
(apply-changes-local))))
|
(apply-changes-local))))
|
||||||
|
|
||||||
(defn add-component
|
(defn add-component
|
||||||
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page]
|
([changes id path name updated-shapes main-instance-id main-instance-page]
|
||||||
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page nil nil nil))
|
(add-component changes id path name updated-shapes main-instance-id main-instance-page nil nil nil))
|
||||||
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation]
|
([changes id path name updated-shapes main-instance-id main-instance-page annotation]
|
||||||
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation nil nil))
|
(add-component changes id path name updated-shapes main-instance-id main-instance-page annotation nil nil))
|
||||||
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation variant-id variant-properties & {:keys [apply-changes-local-library?]}]
|
([changes id path name updated-shapes main-instance-id main-instance-page annotation variant-id variant-properties & {:keys [apply-changes-local-library?]}]
|
||||||
(assert-page-id! changes)
|
(assert-page-id! changes)
|
||||||
(assert-objects! changes)
|
(assert-objects! changes)
|
||||||
(let [page-id (::page-id (meta changes))
|
(let [page-id (::page-id (meta changes))
|
||||||
|
@ -965,8 +965,6 @@
|
||||||
:main-instance-id main-instance-id
|
:main-instance-id main-instance-id
|
||||||
:main-instance-page main-instance-page
|
:main-instance-page main-instance-page
|
||||||
:annotation annotation}
|
:annotation annotation}
|
||||||
(some? new-shapes) ;; this will be null in components-v2
|
|
||||||
(assoc :shapes (vec new-shapes))
|
|
||||||
(some? variant-id)
|
(some? variant-id)
|
||||||
(assoc :variant-id variant-id)
|
(assoc :variant-id variant-id)
|
||||||
(seq variant-properties)
|
(seq variant-properties)
|
||||||
|
@ -1000,7 +998,7 @@
|
||||||
:main-instance-id (:main-instance-id new-component)
|
:main-instance-id (:main-instance-id new-component)
|
||||||
:main-instance-page (:main-instance-page new-component)
|
:main-instance-page (:main-instance-page new-component)
|
||||||
:annotation (:annotation new-component)
|
:annotation (:annotation new-component)
|
||||||
:objects (:objects new-component) ;; this won't exist in components-v2 (except for deleted components)
|
:objects (:objects new-component) ;; for deleted components
|
||||||
:modified-at (:modified-at new-component)}
|
:modified-at (:modified-at new-component)}
|
||||||
(some? (:variant-id new-component))
|
(some? (:variant-id new-component))
|
||||||
(assoc :variant-id (:variant-id new-component))
|
(assoc :variant-id (:variant-id new-component))
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
:file-schema-validation
|
:file-schema-validation
|
||||||
;; Reports the schema validation errors internally.
|
;; Reports the schema validation errors internally.
|
||||||
:soft-file-schema-validation
|
:soft-file-schema-validation
|
||||||
;; Activates the referential integrity validation during update file; related to components-v2.
|
;; Activates the referential integrity validation during update file.
|
||||||
:file-validation
|
:file-validation
|
||||||
;; Reports the referential integrity validation errors internally.
|
;; Reports the referential integrity validation errors internally.
|
||||||
:soft-file-validation
|
:soft-file-validation
|
||||||
|
|
|
@ -168,22 +168,17 @@
|
||||||
|
|
||||||
new-instance-shapes (into [] xf-shape new-instance-shapes)]
|
new-instance-shapes (into [] xf-shape new-instance-shapes)]
|
||||||
|
|
||||||
[nil nil new-instance-shape new-instance-shapes]))
|
[new-instance-shape new-instance-shapes]))
|
||||||
|
|
||||||
(defn generate-duplicate-component
|
(defn generate-duplicate-component
|
||||||
"Create a new component copied from the one with the given id."
|
"Create a new component copied from the one with the given id."
|
||||||
[changes library component-id new-component-id components-v2 & {:keys [new-shape-id apply-changes-local-library? delta new-variant-id]}]
|
[changes library component-id new-component-id & {:keys [new-shape-id apply-changes-local-library? delta new-variant-id]}]
|
||||||
(let [component (ctkl/get-component (:data library) component-id)
|
(let [component (ctkl/get-component (:data library) component-id)
|
||||||
new-name (:name component)
|
new-name (:name component)
|
||||||
|
|
||||||
main-instance-page (when components-v2
|
main-instance-page (ctf/get-component-page (:data library) component)
|
||||||
(ctf/get-component-page (:data library) component))
|
|
||||||
|
|
||||||
new-component-id (when components-v2
|
[new-main-instance-shape new-main-instance-shapes]
|
||||||
new-component-id)
|
|
||||||
|
|
||||||
[new-component-shape new-component-shapes ; <- null in components-v2
|
|
||||||
new-main-instance-shape new-main-instance-shapes]
|
|
||||||
(duplicate-component component new-component-id (:data library) new-shape-id delta new-variant-id)]
|
(duplicate-component component new-component-id (:data library) new-shape-id delta new-variant-id)]
|
||||||
|
|
||||||
[new-main-instance-shape
|
[new-main-instance-shape
|
||||||
|
@ -191,12 +186,9 @@
|
||||||
(pcb/with-page main-instance-page)
|
(pcb/with-page main-instance-page)
|
||||||
(pcb/with-objects (:objects main-instance-page))
|
(pcb/with-objects (:objects main-instance-page))
|
||||||
(pcb/add-objects new-main-instance-shapes {:ignore-touched true})
|
(pcb/add-objects new-main-instance-shapes {:ignore-touched true})
|
||||||
(pcb/add-component (if components-v2
|
(pcb/add-component new-component-id
|
||||||
new-component-id
|
|
||||||
(:id new-component-shape))
|
|
||||||
(:path component)
|
(:path component)
|
||||||
new-name
|
new-name
|
||||||
new-component-shapes
|
|
||||||
[]
|
[]
|
||||||
(:id new-main-instance-shape)
|
(:id new-main-instance-shape)
|
||||||
(:id main-instance-page)
|
(:id main-instance-page)
|
||||||
|
@ -226,14 +218,11 @@
|
||||||
parent (when parent-id (get objects parent-id))
|
parent (when parent-id (get objects parent-id))
|
||||||
library (get libraries file-id)
|
library (get libraries file-id)
|
||||||
|
|
||||||
components-v2 (dm/get-in library [:data :options :components-v2])
|
|
||||||
|
|
||||||
[new-shape new-shapes]
|
[new-shape new-shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:data library)
|
(:data library)
|
||||||
position
|
position
|
||||||
components-v2
|
|
||||||
(cond-> {}
|
(cond-> {}
|
||||||
force-frame?
|
force-frame?
|
||||||
(assoc :force-frame-id frame-id)))
|
(assoc :force-frame-id frame-id)))
|
||||||
|
@ -427,8 +416,7 @@
|
||||||
:file (pretty-file file-id libraries current-file-id)
|
:file (pretty-file file-id libraries current-file-id)
|
||||||
:library (pretty-file library-id libraries current-file-id))
|
:library (pretty-file library-id libraries current-file-id))
|
||||||
|
|
||||||
(let [file (get-in libraries [file-id :data])
|
(let [file (get-in libraries [file-id :data])]
|
||||||
components-v2 (get-in file [:options :components-v2])]
|
|
||||||
(loop [containers (ctf/object-containers-seq file)
|
(loop [containers (ctf/object-containers-seq file)
|
||||||
changes changes]
|
changes changes]
|
||||||
(if-let [container (first containers)]
|
(if-let [container (first containers)]
|
||||||
|
@ -441,7 +429,6 @@
|
||||||
asset-id
|
asset-id
|
||||||
library-id
|
library-id
|
||||||
container
|
container
|
||||||
components-v2
|
|
||||||
libraries
|
libraries
|
||||||
current-file-id))))
|
current-file-id))))
|
||||||
changes))))
|
changes))))
|
||||||
|
@ -466,8 +453,7 @@
|
||||||
:file (pretty-file file-id libraries current-file-id)
|
:file (pretty-file file-id libraries current-file-id)
|
||||||
:library (pretty-file library-id libraries current-file-id))
|
:library (pretty-file library-id libraries current-file-id))
|
||||||
|
|
||||||
(let [file (get-in libraries [file-id :data])
|
(let [file (get-in libraries [file-id :data])]
|
||||||
components-v2 (get-in file [:options :components-v2])]
|
|
||||||
(loop [local-components (ctkl/components-seq file)
|
(loop [local-components (ctkl/components-seq file)
|
||||||
changes changes]
|
changes changes]
|
||||||
(if-let [local-component (first local-components)]
|
(if-let [local-component (first local-components)]
|
||||||
|
@ -479,7 +465,6 @@
|
||||||
asset-id
|
asset-id
|
||||||
library-id
|
library-id
|
||||||
(cfh/make-container local-component :component)
|
(cfh/make-container local-component :component)
|
||||||
components-v2
|
|
||||||
libraries
|
libraries
|
||||||
current-file-id)))
|
current-file-id)))
|
||||||
changes))))
|
changes))))
|
||||||
|
@ -487,7 +472,7 @@
|
||||||
(defn- generate-sync-container
|
(defn- generate-sync-container
|
||||||
"Generate changes to synchronize all shapes in a particular container (a page
|
"Generate changes to synchronize all shapes in a particular container (a page
|
||||||
or a component) that use assets of the given type in the given library."
|
or a component) that use assets of the given type in the given library."
|
||||||
[changes asset-type asset-id library-id container components-v2 libraries current-file-id]
|
[changes asset-type asset-id library-id container libraries current-file-id]
|
||||||
|
|
||||||
(if (cfh/page? container)
|
(if (cfh/page? container)
|
||||||
(container-log :debug (:id container) :msg "Sync page in local file" :page-id (:id container))
|
(container-log :debug (:id container) :msg "Sync page in local file" :page-id (:id container))
|
||||||
|
@ -506,7 +491,6 @@
|
||||||
library-id
|
library-id
|
||||||
container
|
container
|
||||||
shape
|
shape
|
||||||
components-v2
|
|
||||||
libraries
|
libraries
|
||||||
current-file-id))
|
current-file-id))
|
||||||
changes))))
|
changes))))
|
||||||
|
@ -536,13 +520,13 @@
|
||||||
(defmulti generate-sync-shape
|
(defmulti generate-sync-shape
|
||||||
"Generate changes to synchronize one shape from all assets of the given type
|
"Generate changes to synchronize one shape from all assets of the given type
|
||||||
that is using, in the given library."
|
that is using, in the given library."
|
||||||
(fn [asset-type _changes _library-id _container _shape _components-v2 _libraries _current-file-id] asset-type))
|
(fn [asset-type _changes _library-id _container _shape _libraries _current-file-id] asset-type))
|
||||||
|
|
||||||
(defmethod generate-sync-shape :components
|
(defmethod generate-sync-shape :components
|
||||||
[_ changes _library-id container shape components-v2 libraries current-file-id]
|
[_ changes _library-id container shape libraries current-file-id]
|
||||||
(let [shape-id (:id shape)
|
(let [shape-id (:id shape)
|
||||||
file (get current-file-id libraries)]
|
file (get current-file-id libraries)]
|
||||||
(generate-sync-shape-direct changes file libraries container shape-id false components-v2)))
|
(generate-sync-shape-direct changes file libraries container shape-id false)))
|
||||||
|
|
||||||
(defmethod generate-sync-shape :colors
|
(defmethod generate-sync-shape :colors
|
||||||
[_ changes library-id _ shape _ libraries _]
|
[_ changes library-id _ shape _ libraries _]
|
||||||
|
@ -718,7 +702,7 @@
|
||||||
(defn generate-sync-shape-direct
|
(defn generate-sync-shape-direct
|
||||||
"Generate changes to synchronize one shape that is the root of a component
|
"Generate changes to synchronize one shape that is the root of a component
|
||||||
instance, and all its children, from the given component."
|
instance, and all its children, from the given component."
|
||||||
[changes file libraries container shape-id reset? components-v2]
|
[changes file libraries container shape-id reset?]
|
||||||
(shape-log :debug shape-id container
|
(shape-log :debug shape-id container
|
||||||
:msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?)
|
:msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?)
|
||||||
(let [shape-inst (ctn/get-shape container shape-id)
|
(let [shape-inst (ctn/get-shape container shape-id)
|
||||||
|
@ -729,12 +713,12 @@
|
||||||
(let [redirect-shaperef (partial redirect-shaperef container libraries)
|
(let [redirect-shaperef (partial redirect-shaperef container libraries)
|
||||||
|
|
||||||
shape-main (when component
|
shape-main (when component
|
||||||
(if (and reset? components-v2)
|
(if reset?
|
||||||
;; the reset is against the ref-shape, not against the original shape of the component
|
;; the reset is against the ref-shape, not against the original shape of the component
|
||||||
(ctf/find-ref-shape file container libraries shape-inst)
|
(ctf/find-ref-shape file container libraries shape-inst)
|
||||||
(ctf/get-ref-shape library component shape-inst)))
|
(ctf/get-ref-shape library component shape-inst)))
|
||||||
|
|
||||||
shape-inst (if (and reset? components-v2)
|
shape-inst (if reset?
|
||||||
(redirect-shaperef shape-inst shape-main)
|
(redirect-shaperef shape-inst shape-main)
|
||||||
shape-inst)
|
shape-inst)
|
||||||
|
|
||||||
|
@ -756,13 +740,10 @@
|
||||||
root-main
|
root-main
|
||||||
reset?
|
reset?
|
||||||
initial-root?
|
initial-root?
|
||||||
redirect-shaperef
|
redirect-shaperef)
|
||||||
components-v2)
|
|
||||||
;; If the component is not found, because the master component has been
|
;; If the component is not found, because the master component has been
|
||||||
;; deleted or the library unlinked, do nothing in v2 or detach in v1.
|
;; deleted or the library unlinked, do nothing.
|
||||||
(if components-v2
|
changes))
|
||||||
changes
|
|
||||||
(generate-detach-instance changes libraries container shape-id))))
|
|
||||||
changes)))
|
changes)))
|
||||||
|
|
||||||
(defn- find-main-container
|
(defn- find-main-container
|
||||||
|
@ -783,7 +764,7 @@
|
||||||
nil))))))
|
nil))))))
|
||||||
|
|
||||||
(defn- generate-sync-shape-direct-recursive
|
(defn- generate-sync-shape-direct-recursive
|
||||||
[changes container shape-inst component library file libraries shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2]
|
[changes container shape-inst component library file libraries shape-main root-inst root-main reset? initial-root? redirect-shaperef]
|
||||||
(shape-log :debug (:id shape-inst) container
|
(shape-log :debug (:id shape-inst) container
|
||||||
:msg "Sync shape direct recursive"
|
:msg "Sync shape direct recursive"
|
||||||
:shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst)))
|
:shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst)))
|
||||||
|
@ -791,9 +772,7 @@
|
||||||
|
|
||||||
(if (nil? shape-main)
|
(if (nil? shape-main)
|
||||||
;; This should not occur, but protect against it in any case
|
;; This should not occur, but protect against it in any case
|
||||||
(if components-v2
|
|
||||||
changes
|
changes
|
||||||
(generate-detach-instance changes container {(:id library) library} (:id shape-inst)))
|
|
||||||
(let [omit-touched? (not reset?)
|
(let [omit-touched? (not reset?)
|
||||||
clear-remote-synced? (and initial-root? reset?)
|
clear-remote-synced? (and initial-root? reset?)
|
||||||
set-remote-synced? (and (not initial-root?) reset?)
|
set-remote-synced? (and (not initial-root?) reset?)
|
||||||
|
@ -832,7 +811,7 @@
|
||||||
children-inst (vec (ctn/get-direct-children container shape-inst))
|
children-inst (vec (ctn/get-direct-children container shape-inst))
|
||||||
children-main (vec (ctn/get-direct-children component-container shape-main))
|
children-main (vec (ctn/get-direct-children component-container shape-main))
|
||||||
|
|
||||||
children-inst (if (and reset? components-v2)
|
children-inst (if reset?
|
||||||
(map #(redirect-shaperef %) children-inst) children-inst)
|
(map #(redirect-shaperef %) children-inst) children-inst)
|
||||||
|
|
||||||
only-inst (fn [changes child-inst]
|
only-inst (fn [changes child-inst]
|
||||||
|
@ -864,8 +843,7 @@
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
omit-touched?
|
omit-touched?
|
||||||
set-remote-synced?
|
set-remote-synced?)
|
||||||
components-v2)
|
|
||||||
changes))
|
changes))
|
||||||
|
|
||||||
both (fn [changes child-inst child-main]
|
both (fn [changes child-inst child-main]
|
||||||
|
@ -885,8 +863,7 @@
|
||||||
root-main
|
root-main
|
||||||
reset?
|
reset?
|
||||||
initial-root?
|
initial-root?
|
||||||
redirect-shaperef
|
redirect-shaperef))
|
||||||
components-v2))
|
|
||||||
|
|
||||||
swapped (fn [changes child-inst child-main]
|
swapped (fn [changes child-inst child-main]
|
||||||
(shape-log :trace (:id child-inst) container
|
(shape-log :trace (:id child-inst) container
|
||||||
|
@ -924,8 +901,7 @@
|
||||||
swapped
|
swapped
|
||||||
moved
|
moved
|
||||||
false
|
false
|
||||||
reset?
|
reset?)
|
||||||
components-v2)
|
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(cond-> changes
|
(cond-> changes
|
||||||
|
@ -941,27 +917,16 @@
|
||||||
|
|
||||||
(defn generate-rename-component
|
(defn generate-rename-component
|
||||||
"Generate the changes for rename the component with the given id, in the current file library."
|
"Generate the changes for rename the component with the given id, in the current file library."
|
||||||
[changes id new-name library-data components-v2]
|
[changes id new-name library-data]
|
||||||
(let [[path name] (cfh/parse-path-name new-name)
|
(let [[path name] (cfh/parse-path-name new-name)]
|
||||||
update-fn
|
|
||||||
(fn [component]
|
|
||||||
(cond-> component
|
|
||||||
:always
|
|
||||||
(assoc :path path
|
|
||||||
:name name)
|
|
||||||
|
|
||||||
(not components-v2)
|
|
||||||
(update :objects
|
|
||||||
;; Give the same name to the root shape
|
|
||||||
#(assoc-in % [id :name] name))))]
|
|
||||||
(-> changes
|
(-> changes
|
||||||
(pcb/with-library-data library-data)
|
(pcb/with-library-data library-data)
|
||||||
(pcb/update-component id update-fn))))
|
(pcb/update-component id #(assoc % :path path :name name)))))
|
||||||
|
|
||||||
(defn generate-sync-shape-inverse
|
(defn generate-sync-shape-inverse
|
||||||
"Generate changes to update the component a shape is linked to, from
|
"Generate changes to update the component a shape is linked to, from
|
||||||
the values in the shape and all its children."
|
the values in the shape and all its children."
|
||||||
[changes file libraries container shape-id components-v2]
|
[changes file libraries container shape-id]
|
||||||
(shape-log :debug shape-id container :msg "Sync shape inverse" :shape (str shape-id))
|
(shape-log :debug shape-id container :msg "Sync shape inverse" :shape (str shape-id))
|
||||||
(let [redirect-shaperef (partial redirect-shaperef container libraries)
|
(let [redirect-shaperef (partial redirect-shaperef container libraries)
|
||||||
shape-inst (ctn/get-shape container shape-id)
|
shape-inst (ctn/get-shape container shape-id)
|
||||||
|
@ -969,13 +934,9 @@
|
||||||
component (ctkl/get-component library (:component-id shape-inst))
|
component (ctkl/get-component library (:component-id shape-inst))
|
||||||
|
|
||||||
shape-main (when component
|
shape-main (when component
|
||||||
(if components-v2
|
(ctf/find-remote-shape container libraries shape-inst))
|
||||||
(ctf/find-remote-shape container libraries shape-inst)
|
|
||||||
(ctf/get-ref-shape library component shape-inst)))
|
|
||||||
|
|
||||||
shape-inst (if components-v2
|
shape-inst (redirect-shaperef shape-inst shape-main)
|
||||||
(redirect-shaperef shape-inst shape-main)
|
|
||||||
shape-inst)
|
|
||||||
|
|
||||||
initial-root? (:component-root shape-inst)
|
initial-root? (:component-root shape-inst)
|
||||||
|
|
||||||
|
@ -984,7 +945,7 @@
|
||||||
|
|
||||||
changes (cond-> changes
|
changes (cond-> changes
|
||||||
(and component (contains? (:touched shape-inst) :name-group))
|
(and component (contains? (:touched shape-inst) :name-group))
|
||||||
(generate-rename-component (:component-id shape-inst) (:name shape-inst) library components-v2))]
|
(generate-rename-component (:component-id shape-inst) (:name shape-inst) library))]
|
||||||
|
|
||||||
(if component
|
(if component
|
||||||
(generate-sync-shape-inverse-recursive changes
|
(generate-sync-shape-inverse-recursive changes
|
||||||
|
@ -998,12 +959,11 @@
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
initial-root?
|
initial-root?
|
||||||
redirect-shaperef
|
redirect-shaperef)
|
||||||
components-v2)
|
|
||||||
changes)))
|
changes)))
|
||||||
|
|
||||||
(defn- generate-sync-shape-inverse-recursive
|
(defn- generate-sync-shape-inverse-recursive
|
||||||
[changes container shape-inst component library file libraries shape-main root-inst root-main initial-root? redirect-shaperef components-v2]
|
[changes container shape-inst component library file libraries shape-main root-inst root-main initial-root? redirect-shaperef]
|
||||||
(shape-log :trace (:id shape-inst) container
|
(shape-log :trace (:id shape-inst) container
|
||||||
:msg "Sync shape inverse recursive"
|
:msg "Sync shape inverse recursive"
|
||||||
:shape (str (:name shape-inst))
|
:shape (str (:name shape-inst))
|
||||||
|
@ -1060,9 +1020,7 @@
|
||||||
children-main (mapv #(ctn/get-shape component-container %)
|
children-main (mapv #(ctn/get-shape component-container %)
|
||||||
(:shapes shape-main))
|
(:shapes shape-main))
|
||||||
|
|
||||||
children-inst (if components-v2
|
children-inst (map #(redirect-shaperef %) children-inst)
|
||||||
(map #(redirect-shaperef %) children-inst)
|
|
||||||
children-inst)
|
|
||||||
|
|
||||||
only-inst (fn [changes child-inst]
|
only-inst (fn [changes child-inst]
|
||||||
(add-shape-to-main changes
|
(add-shape-to-main changes
|
||||||
|
@ -1073,8 +1031,7 @@
|
||||||
component-container
|
component-container
|
||||||
container
|
container
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main))
|
||||||
components-v2))
|
|
||||||
|
|
||||||
only-main (fn [changes child-main]
|
only-main (fn [changes child-main]
|
||||||
(remove-shape changes
|
(remove-shape changes
|
||||||
|
@ -1094,8 +1051,7 @@
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
initial-root?
|
initial-root?
|
||||||
redirect-shaperef
|
redirect-shaperef))
|
||||||
components-v2))
|
|
||||||
|
|
||||||
swapped (fn [changes child-inst child-main]
|
swapped (fn [changes child-inst child-main]
|
||||||
(shape-log :trace (:id child-inst) container
|
(shape-log :trace (:id child-inst) container
|
||||||
|
@ -1129,8 +1085,7 @@
|
||||||
swapped
|
swapped
|
||||||
moved
|
moved
|
||||||
true
|
true
|
||||||
true
|
true)
|
||||||
components-v2)
|
|
||||||
|
|
||||||
;; The inverse sync may be made on a component that is inside a
|
;; The inverse sync may be made on a component that is inside a
|
||||||
;; remote library. We need to separate changes that are from
|
;; remote library. We need to separate changes that are from
|
||||||
|
@ -1148,7 +1103,7 @@
|
||||||
;; ---- Operation generation helpers ----
|
;; ---- Operation generation helpers ----
|
||||||
|
|
||||||
(defn- compare-children
|
(defn- compare-children
|
||||||
[changes shape-inst children-inst children-main container-inst container-main file libraries only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset? components-v2]
|
[changes shape-inst children-inst children-main container-inst container-main file libraries only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset?]
|
||||||
(shape-log :trace (:id shape-inst) container-inst :msg "Compare children")
|
(shape-log :trace (:id shape-inst) container-inst :msg "Compare children")
|
||||||
(loop [children-inst (seq (or children-inst []))
|
(loop [children-inst (seq (or children-inst []))
|
||||||
children-main (seq (or children-main []))
|
children-main (seq (or children-main []))
|
||||||
|
@ -1169,18 +1124,18 @@
|
||||||
(reduce only-inst-cb changes children-inst)
|
(reduce only-inst-cb changes children-inst)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(if (or (ctk/is-main-of? child-main child-inst components-v2)
|
(if (or (ctk/is-main-of? child-main child-inst)
|
||||||
(and (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries) (not reset?)))
|
(and (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries) (not reset?)))
|
||||||
(recur (next children-inst)
|
(recur (next children-inst)
|
||||||
(next children-main)
|
(next children-main)
|
||||||
(if (ctk/is-main-of? child-main child-inst components-v2)
|
(if (ctk/is-main-of? child-main child-inst)
|
||||||
(both-cb changes child-inst child-main)
|
(both-cb changes child-inst child-main)
|
||||||
(swapped-cb changes child-inst child-main)))
|
(swapped-cb changes child-inst child-main)))
|
||||||
|
|
||||||
(let [child-inst' (d/seek #(or (ctk/is-main-of? child-main % components-v2)
|
(let [child-inst' (d/seek #(or (ctk/is-main-of? child-main %)
|
||||||
(and (ctf/match-swap-slot? child-main % container-inst container-main file libraries) (not reset?)))
|
(and (ctf/match-swap-slot? child-main % container-inst container-main file libraries) (not reset?)))
|
||||||
children-inst)
|
children-inst)
|
||||||
child-main' (d/seek #(or (ctk/is-main-of? % child-inst components-v2)
|
child-main' (d/seek #(or (ctk/is-main-of? % child-inst)
|
||||||
(and (ctf/match-swap-slot? % child-inst container-inst container-main file libraries) (not reset?)))
|
(and (ctf/match-swap-slot? % child-inst container-inst container-main file libraries) (not reset?)))
|
||||||
children-main)]
|
children-main)]
|
||||||
(cond
|
(cond
|
||||||
|
@ -1196,7 +1151,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(if inverse?
|
(if inverse?
|
||||||
(let [is-main? (ctk/is-main-of? child-inst child-main' components-v2)]
|
(let [is-main? (ctk/is-main-of? child-inst child-main')]
|
||||||
(recur (next children-inst)
|
(recur (next children-inst)
|
||||||
(remove #(= (:id %) (:id child-main')) children-main)
|
(remove #(= (:id %) (:id child-main')) children-main)
|
||||||
(cond-> changes
|
(cond-> changes
|
||||||
|
@ -1206,7 +1161,7 @@
|
||||||
(swapped-cb child-inst child-main')
|
(swapped-cb child-inst child-main')
|
||||||
:always
|
:always
|
||||||
(moved-cb child-inst child-main'))))
|
(moved-cb child-inst child-main'))))
|
||||||
(let [is-main? (ctk/is-main-of? child-inst' child-main components-v2)]
|
(let [is-main? (ctk/is-main-of? child-inst' child-main)]
|
||||||
(recur (remove #(= (:id %) (:id child-inst')) children-inst)
|
(recur (remove #(= (:id %) (:id child-inst')) children-inst)
|
||||||
(next children-main)
|
(next children-main)
|
||||||
(cond-> changes
|
(cond-> changes
|
||||||
|
@ -1218,14 +1173,14 @@
|
||||||
(moved-cb child-inst' child-main))))))))))))
|
(moved-cb child-inst' child-main))))))))))))
|
||||||
|
|
||||||
(defn- add-shape-to-instance
|
(defn- add-shape-to-instance
|
||||||
[changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced? components-v2]
|
[changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced?]
|
||||||
(shape-log :info (:id component-shape) component-page
|
(shape-log :info (:id component-shape) component-page
|
||||||
:msg (str "ADD [P " (pretty-uuid (:id container)) "] "
|
:msg (str "ADD [P " (pretty-uuid (:id container)) "] "
|
||||||
(:name component-shape)
|
(:name component-shape)
|
||||||
" "
|
" "
|
||||||
(pretty-uuid (:id component-shape))))
|
(pretty-uuid (:id component-shape))))
|
||||||
(let [component-parent-shape (ctn/get-shape component-page (:parent-id component-shape))
|
(let [component-parent-shape (ctn/get-shape component-page (:parent-id component-shape))
|
||||||
parent-shape (d/seek #(ctk/is-main-of? component-parent-shape % components-v2)
|
parent-shape (d/seek #(ctk/is-main-of? component-parent-shape %)
|
||||||
(cfh/get-children-with-self (:objects container)
|
(cfh/get-children-with-self (:objects container)
|
||||||
(:id root-instance)))
|
(:id root-instance)))
|
||||||
all-parents (into [(:id parent-shape)]
|
all-parents (into [(:id parent-shape)]
|
||||||
|
@ -1294,14 +1249,14 @@
|
||||||
changes')))
|
changes')))
|
||||||
|
|
||||||
(defn- add-shape-to-main
|
(defn- add-shape-to-main
|
||||||
[changes shape index component component-container page root-instance root-main components-v2]
|
[changes shape index component component-container page root-instance root-main]
|
||||||
(shape-log :info (:id shape) page
|
(shape-log :info (:id shape) page
|
||||||
:msg (str "ADD [C " (pretty-uuid (:id component-container)) "] "
|
:msg (str "ADD [C " (pretty-uuid (:id component-container)) "] "
|
||||||
(:name shape)
|
(:name shape)
|
||||||
" "
|
" "
|
||||||
(pretty-uuid (:id shape))))
|
(pretty-uuid (:id shape))))
|
||||||
(let [parent-shape (ctn/get-shape page (:parent-id shape))
|
(let [parent-shape (ctn/get-shape page (:parent-id shape))
|
||||||
component-parent-shape (d/seek #(ctk/is-main-of? % parent-shape components-v2)
|
component-parent-shape (d/seek #(ctk/is-main-of? % parent-shape)
|
||||||
(cfh/get-children-with-self (:objects component-container)
|
(cfh/get-children-with-self (:objects component-container)
|
||||||
(:id root-main)))
|
(:id root-main)))
|
||||||
all-parents (into [(:id component-parent-shape)]
|
all-parents (into [(:id component-parent-shape)]
|
||||||
|
@ -1886,30 +1841,27 @@
|
||||||
(assoc change :component-id (:id container))))
|
(assoc change :component-id (:id container))))
|
||||||
|
|
||||||
(defn generate-add-component-changes
|
(defn generate-add-component-changes
|
||||||
[changes root objects file-id page-id components-v2]
|
[changes root objects file-id page-id]
|
||||||
(let [name (:name root)
|
(let [name (:name root)
|
||||||
[path name] (cfh/parse-path-name name)
|
[path name] (cfh/parse-path-name name)
|
||||||
|
|
||||||
[root-shape new-shapes updated-shapes]
|
[root-shape updated-shapes]
|
||||||
(if-not components-v2
|
(ctn/convert-shape-in-component root objects file-id)
|
||||||
(ctn/make-component-shape root objects file-id components-v2)
|
|
||||||
(ctn/convert-shape-in-component root objects file-id))
|
|
||||||
|
|
||||||
changes (-> changes
|
changes (-> changes
|
||||||
(pcb/add-component (:id root-shape)
|
(pcb/add-component (:id root-shape)
|
||||||
path
|
path
|
||||||
name
|
name
|
||||||
new-shapes
|
|
||||||
updated-shapes
|
updated-shapes
|
||||||
(:id root)
|
(:id root)
|
||||||
page-id))]
|
page-id))]
|
||||||
[root-shape changes]))
|
[root-shape changes]))
|
||||||
|
|
||||||
(defn generate-add-component
|
(defn generate-add-component
|
||||||
"If there is exactly one id, and it's a frame (or a group in v1), and not already a component,
|
"If there is exactly one id, and it's a frame, and not already a component,
|
||||||
use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a
|
use it as root. Otherwise, create a frame that contains all ids. Then, make a
|
||||||
component with it, and link all shapes to their corresponding one in the component."
|
component with it, and link all shapes to their corresponding one in the component."
|
||||||
[changes shapes objects page-id file-id components-v2 prepare-create-group prepare-create-board]
|
[changes shapes objects page-id file-id prepare-create-board]
|
||||||
|
|
||||||
(let [changes (pcb/with-page-id changes page-id)
|
(let [changes (pcb/with-page-id changes page-id)
|
||||||
shapes-count (count shapes)
|
shapes-count (count shapes)
|
||||||
|
@ -1921,9 +1873,7 @@
|
||||||
|
|
||||||
[root changes old-root-ids]
|
[root changes old-root-ids]
|
||||||
(if (and (= shapes-count 1)
|
(if (and (= shapes-count 1)
|
||||||
(or (and (cfh/group-shape? first-shape)
|
(cfh/frame-shape? first-shape)
|
||||||
(not components-v2))
|
|
||||||
(cfh/frame-shape? first-shape))
|
|
||||||
(not (ctk/instance-head? first-shape)))
|
(not (ctk/instance-head? first-shape)))
|
||||||
[first-shape
|
[first-shape
|
||||||
(-> changes
|
(-> changes
|
||||||
|
@ -1938,13 +1888,6 @@
|
||||||
shape-ids (into (d/ordered-set) (map :id) shapes)
|
shape-ids (into (d/ordered-set) (map :id) shapes)
|
||||||
|
|
||||||
[root changes]
|
[root changes]
|
||||||
(if-not components-v2
|
|
||||||
(prepare-create-group changes ; These functions needs to be passed as argument
|
|
||||||
objects ; to avoid a circular dependence
|
|
||||||
page-id
|
|
||||||
shapes
|
|
||||||
root-name
|
|
||||||
(not (ctk/instance-head? first-shape)))
|
|
||||||
(prepare-create-board changes
|
(prepare-create-board changes
|
||||||
(uuid/next)
|
(uuid/next)
|
||||||
(:parent-id first-shape)
|
(:parent-id first-shape)
|
||||||
|
@ -1952,7 +1895,7 @@
|
||||||
shape-ids
|
shape-ids
|
||||||
nil
|
nil
|
||||||
root-name
|
root-name
|
||||||
true))]
|
true)]
|
||||||
|
|
||||||
[root changes shape-ids]))
|
[root changes shape-ids]))
|
||||||
|
|
||||||
|
@ -1966,7 +1909,7 @@
|
||||||
|
|
||||||
objects' (assoc objects (:id root) root)
|
objects' (assoc objects (:id root) root)
|
||||||
|
|
||||||
[root-shape changes] (generate-add-component-changes changes root objects' file-id page-id components-v2)
|
[root-shape changes] (generate-add-component-changes changes root objects' file-id page-id)
|
||||||
|
|
||||||
changes (pcb/update-shapes changes
|
changes (pcb/update-shapes changes
|
||||||
old-root-ids
|
old-root-ids
|
||||||
|
@ -2052,8 +1995,7 @@
|
||||||
[changes objects shape file page libraries id-new-component index target-cell keep-props-values]
|
[changes objects shape file page libraries id-new-component index target-cell keep-props-values]
|
||||||
(let [[all-parents changes]
|
(let [[all-parents changes]
|
||||||
(-> changes
|
(-> changes
|
||||||
(cls/generate-delete-shapes file page objects (d/ordered-set (:id shape)) {:components-v2 true
|
(cls/generate-delete-shapes file page objects (d/ordered-set (:id shape)) {:component-swap true}))
|
||||||
:component-swap true}))
|
|
||||||
[new-shape changes]
|
[new-shape changes]
|
||||||
(-> changes
|
(-> changes
|
||||||
(generate-new-shape-for-swap shape file page libraries id-new-component index target-cell keep-props-values))]
|
(generate-new-shape-for-swap shape file page libraries id-new-component index target-cell keep-props-values))]
|
||||||
|
@ -2084,7 +2026,7 @@
|
||||||
(generate-sync-file file-id :typographies asset-id library-id libraries current-file-id))))
|
(generate-sync-file file-id :typographies asset-id library-id libraries current-file-id))))
|
||||||
|
|
||||||
(defn generate-sync-head
|
(defn generate-sync-head
|
||||||
[changes file-full libraries container id components-v2 reset?]
|
[changes file-full libraries container id reset?]
|
||||||
(let [shape-inst (ctn/get-shape container id)
|
(let [shape-inst (ctn/get-shape container id)
|
||||||
objects (:objects container)
|
objects (:objects container)
|
||||||
parent (get objects (:parent-id shape-inst))
|
parent (get objects (:parent-id shape-inst))
|
||||||
|
@ -2093,11 +2035,11 @@
|
||||||
(-> changes
|
(-> changes
|
||||||
(pcb/with-container container)
|
(pcb/with-container container)
|
||||||
(pcb/with-objects (:objects container))
|
(pcb/with-objects (:objects container))
|
||||||
(generate-sync-shape-direct file-full libraries container (:id head) reset? components-v2))]
|
(generate-sync-shape-direct file-full libraries container (:id head) reset?))]
|
||||||
changes))
|
changes))
|
||||||
|
|
||||||
(defn generate-reset-component
|
(defn generate-reset-component
|
||||||
[changes file-full libraries container id components-v2]
|
[changes file-full libraries container id]
|
||||||
(let [objects (:objects container)
|
(let [objects (:objects container)
|
||||||
swap-slot (-> (ctn/get-shape container id)
|
swap-slot (-> (ctn/get-shape container id)
|
||||||
(ctk/get-swap-slot))
|
(ctk/get-swap-slot))
|
||||||
|
@ -2105,11 +2047,11 @@
|
||||||
(-> changes
|
(-> changes
|
||||||
(pcb/with-container container)
|
(pcb/with-container container)
|
||||||
(pcb/with-objects objects)
|
(pcb/with-objects objects)
|
||||||
(generate-sync-shape-direct file-full libraries container id true components-v2))]
|
(generate-sync-shape-direct file-full libraries container id true))]
|
||||||
|
|
||||||
(cond-> changes
|
(cond-> changes
|
||||||
(some? swap-slot)
|
(some? swap-slot)
|
||||||
(generate-sync-head file-full libraries container id components-v2 true))))
|
(generate-sync-head file-full libraries container id true))))
|
||||||
|
|
||||||
(defn generate-duplicate-flows
|
(defn generate-duplicate-flows
|
||||||
[changes shapes page ids-map]
|
[changes shapes page ids-map]
|
||||||
|
@ -2174,7 +2116,6 @@
|
||||||
library
|
library
|
||||||
(:component-id component-shape)
|
(:component-id component-shape)
|
||||||
new-component-id
|
new-component-id
|
||||||
true
|
|
||||||
{:apply-changes-local-library? true
|
{:apply-changes-local-library? true
|
||||||
:delta delta
|
:delta delta
|
||||||
:new-variant-id parent-id})]
|
:new-variant-id parent-id})]
|
||||||
|
@ -2271,8 +2212,7 @@
|
||||||
|
|
||||||
regenerate-component
|
regenerate-component
|
||||||
(fn [changes shape]
|
(fn [changes shape]
|
||||||
(let [components-v2 (dm/get-in library-data [:options :components-v2])
|
(let [[_ changes] (generate-add-component-changes changes shape objects file-id (:id page))]
|
||||||
[_ changes] (generate-add-component-changes changes shape objects file-id (:id page) components-v2)]
|
|
||||||
changes))
|
changes))
|
||||||
|
|
||||||
new-obj
|
new-obj
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
(pcb/update-shapes ids update-fn {:attrs #{:blocked :hidden}}))))
|
(pcb/update-shapes ids update-fn {:attrs #{:blocked :hidden}}))))
|
||||||
|
|
||||||
(defn generate-delete-shapes
|
(defn generate-delete-shapes
|
||||||
[changes file page objects ids {:keys [components-v2 ignore-touched component-swap]}]
|
[changes file page objects ids {:keys [ignore-touched component-swap]}]
|
||||||
(let [ids (cfh/clean-loops objects ids)
|
(let [ids (cfh/clean-loops objects ids)
|
||||||
|
|
||||||
in-component-copy?
|
in-component-copy?
|
||||||
|
@ -97,7 +97,6 @@
|
||||||
(not component-swap))))
|
(not component-swap))))
|
||||||
|
|
||||||
[ids-to-delete ids-to-hide]
|
[ids-to-delete ids-to-hide]
|
||||||
(if components-v2
|
|
||||||
(loop [ids-seq (seq ids)
|
(loop [ids-seq (seq ids)
|
||||||
ids-to-delete []
|
ids-to-delete []
|
||||||
ids-to-hide []]
|
ids-to-hide []]
|
||||||
|
@ -111,7 +110,7 @@
|
||||||
(recur (rest ids-seq)
|
(recur (rest ids-seq)
|
||||||
(conj ids-to-delete id)
|
(conj ids-to-delete id)
|
||||||
ids-to-hide)))))
|
ids-to-hide)))))
|
||||||
[ids []])
|
|
||||||
|
|
||||||
changes (-> changes
|
changes (-> changes
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
|
@ -190,7 +189,6 @@
|
||||||
#{})
|
#{})
|
||||||
|
|
||||||
components-to-delete
|
components-to-delete
|
||||||
(if components-v2
|
|
||||||
(reduce (fn [components id]
|
(reduce (fn [components id]
|
||||||
(let [shape (get objects id)]
|
(let [shape (get objects id)]
|
||||||
(if (and (= (:component-file shape) (:id file)) ;; Main instances should exist only in local file
|
(if (and (= (:component-file shape) (:id file)) ;; Main instances should exist only in local file
|
||||||
|
@ -199,7 +197,7 @@
|
||||||
components)))
|
components)))
|
||||||
[]
|
[]
|
||||||
(into ids-to-delete all-children))
|
(into ids-to-delete all-children))
|
||||||
[])
|
|
||||||
|
|
||||||
ids-set (set ids-to-delete)
|
ids-set (set ids-to-delete)
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
{:data data}
|
{:data data}
|
||||||
component-id
|
component-id
|
||||||
new-component-id
|
new-component-id
|
||||||
true
|
|
||||||
{:new-shape-id new-shape-id :apply-changes-local-library? true}))]
|
{:new-shape-id new-shape-id :apply-changes-local-library? true}))]
|
||||||
(-> changes
|
(-> changes
|
||||||
(clvp/generate-update-property-value new-component-id prop-num value)
|
(clvp/generate-update-property-value new-component-id prop-num value)
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
"Need that root is already a frame"
|
"Need that root is already a frame"
|
||||||
(cfh/frame-shape? root))
|
(cfh/frame-shape? root))
|
||||||
|
|
||||||
(let [[_new-root _new-shapes updated-shapes]
|
(let [[_new-root updated-shapes]
|
||||||
(ctn/convert-shape-in-component root (:objects page) (:id file))
|
(ctn/convert-shape-in-component root (:objects page) (:id file))
|
||||||
|
|
||||||
updated-root (first updated-shapes) ; Can't use new-root because it has a new id
|
updated-root (first updated-shapes) ; Can't use new-root because it has a new id
|
||||||
|
@ -54,8 +54,7 @@
|
||||||
:name name
|
:name name
|
||||||
:path path
|
:path path
|
||||||
:main-instance-id (:id updated-root)
|
:main-instance-id (:id updated-root)
|
||||||
:main-instance-page (:id page)
|
:main-instance-page (:id page)))))))))
|
||||||
:shapes updated-shapes))))))))
|
|
||||||
|
|
||||||
(defn update-component
|
(defn update-component
|
||||||
[file component-label & {:keys [] :as params}]
|
[file component-label & {:keys [] :as params}]
|
||||||
|
@ -98,7 +97,6 @@
|
||||||
component
|
component
|
||||||
(:data library)
|
(:data library)
|
||||||
(gpt/point 100 100)
|
(gpt/point 100 100)
|
||||||
true
|
|
||||||
{:force-id (thi/new-id! copy-root-label)
|
{:force-id (thi/new-id! copy-root-label)
|
||||||
:force-frame-id frame-id})
|
:force-frame-id frame-id})
|
||||||
|
|
||||||
|
|
|
@ -336,8 +336,7 @@
|
||||||
file
|
file
|
||||||
{file-id file}
|
{file-id file}
|
||||||
(ctn/make-container container :page)
|
(ctn/make-container container :page)
|
||||||
(:id shape)
|
(:id shape)))
|
||||||
true))
|
|
||||||
file' (thf/apply-changes file changes)]
|
file' (thf/apply-changes file changes)]
|
||||||
(if propagate-fn
|
(if propagate-fn
|
||||||
(propagate-fn file')
|
(propagate-fn file')
|
||||||
|
@ -361,7 +360,7 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
#{(-> (ths/get-shape file shape-tag :page-label page-label)
|
#{(-> (ths/get-shape file shape-tag :page-label page-label)
|
||||||
:id)}
|
:id)}
|
||||||
{:components-v2 true})
|
{})
|
||||||
file' (thf/apply-changes file changes)]
|
file' (thf/apply-changes file changes)]
|
||||||
(if propagate-fn
|
(if propagate-fn
|
||||||
(propagate-fn file')
|
(propagate-fn file')
|
||||||
|
|
|
@ -182,10 +182,8 @@
|
||||||
(= (:component-file shape) file-id)))
|
(= (:component-file shape) file-id)))
|
||||||
|
|
||||||
(defn is-main-of?
|
(defn is-main-of?
|
||||||
[shape-main shape-inst components-v2]
|
[shape-main shape-inst]
|
||||||
(or (= (:shape-ref shape-inst) (:id shape-main))
|
(= (:shape-ref shape-inst) (:id shape-main)))
|
||||||
(and (= (:shape-ref shape-inst) (:shape-ref shape-main))
|
|
||||||
(not components-v2))))
|
|
||||||
|
|
||||||
(defn main-instance?
|
(defn main-instance?
|
||||||
"Check if this shape is the root of the main instance of some
|
"Check if this shape is the root of the main instance of some
|
||||||
|
|
|
@ -34,20 +34,12 @@
|
||||||
(assoc component :modified-at (dt/now)))
|
(assoc component :modified-at (dt/now)))
|
||||||
|
|
||||||
(defn add-component
|
(defn add-component
|
||||||
[fdata {:keys [id name path main-instance-id main-instance-page shapes annotation variant-id variant-properties]}]
|
[fdata {:keys [id name path main-instance-id main-instance-page annotation variant-id variant-properties]}]
|
||||||
(let [components-v2 (dm/get-in fdata [:options :components-v2])
|
(let [fdata (update fdata :components assoc id (touch {:id id :name name :path path}))]
|
||||||
fdata (update fdata :components assoc id (touch {:id id :name name :path path}))]
|
|
||||||
(if components-v2
|
|
||||||
(cond-> (update-in fdata [:components id] assoc :main-instance-id main-instance-id :main-instance-page main-instance-page)
|
(cond-> (update-in fdata [:components id] assoc :main-instance-id main-instance-id :main-instance-page main-instance-page)
|
||||||
annotation (update-in [:components id] assoc :annotation annotation)
|
annotation (update-in [:components id] assoc :annotation annotation)
|
||||||
variant-id (update-in [:components id] assoc :variant-id variant-id)
|
variant-id (update-in [:components id] assoc :variant-id variant-id)
|
||||||
variant-properties (update-in [:components id] assoc :variant-properties variant-properties))
|
variant-properties (update-in [:components id] assoc :variant-properties variant-properties))))
|
||||||
|
|
||||||
(let [wrap-object-fn cfeat/*wrap-with-objects-map-fn*]
|
|
||||||
(assoc-in fdata [:components id :objects]
|
|
||||||
(->> shapes
|
|
||||||
(d/index-by :id)
|
|
||||||
(wrap-object-fn)))))))
|
|
||||||
|
|
||||||
(defn mod-component
|
(defn mod-component
|
||||||
[file-data {:keys [id name path main-instance-id main-instance-page objects annotation variant-id variant-properties modified-at]}]
|
[file-data {:keys [id name path main-instance-id main-instance-page objects annotation variant-id variant-properties modified-at]}]
|
||||||
|
|
|
@ -267,67 +267,8 @@
|
||||||
new-children (->> (cfh/get-children objects (:id root))
|
new-children (->> (cfh/get-children objects (:id root))
|
||||||
(map #(dissoc % :component-root)))]
|
(map #(dissoc % :component-root)))]
|
||||||
[(assoc new-root :id new-id)
|
[(assoc new-root :id new-id)
|
||||||
nil
|
|
||||||
(into [new-root] new-children)]))
|
(into [new-root] new-children)]))
|
||||||
|
|
||||||
(defn make-component-shape ;; Only used for components v1
|
|
||||||
"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 objects file-id components-v2]
|
|
||||||
(assert (nil? (:component-id shape)))
|
|
||||||
(assert (nil? (:component-file shape)))
|
|
||||||
(assert (nil? (:shape-ref shape)))
|
|
||||||
(let [frame-ids-map (volatile! {})
|
|
||||||
|
|
||||||
;; Ensure that the component root is not an instance
|
|
||||||
update-new-shape (fn [new-shape original-shape]
|
|
||||||
(when (= (:type original-shape) :frame)
|
|
||||||
(vswap! frame-ids-map assoc (:id original-shape) (:id new-shape)))
|
|
||||||
|
|
||||||
(cond-> new-shape
|
|
||||||
true
|
|
||||||
(dissoc :component-root)
|
|
||||||
|
|
||||||
(nil? (:parent-id new-shape))
|
|
||||||
(dissoc :component-id
|
|
||||||
:component-file
|
|
||||||
:shape-ref)))
|
|
||||||
|
|
||||||
;; Make the original shape an instance of the new component.
|
|
||||||
;; If one of the original shape children already was a component
|
|
||||||
;; instance, maintain this instanceness untouched.
|
|
||||||
update-original-shape (fn [original-shape new-shape]
|
|
||||||
(cond-> original-shape
|
|
||||||
(nil? (:shape-ref original-shape))
|
|
||||||
(-> (assoc :shape-ref (:id new-shape))
|
|
||||||
(dissoc :touched))
|
|
||||||
|
|
||||||
(nil? (:parent-id new-shape))
|
|
||||||
(assoc :component-id (:id new-shape)
|
|
||||||
:component-file file-id
|
|
||||||
:component-root true)
|
|
||||||
|
|
||||||
(and (nil? (:parent-id new-shape)) components-v2)
|
|
||||||
(assoc :main-instance true)
|
|
||||||
|
|
||||||
(some? (:parent-id new-shape))
|
|
||||||
(dissoc :component-root)))
|
|
||||||
|
|
||||||
[new-root-shape new-shapes updated-shapes]
|
|
||||||
(ctst/clone-shape shape
|
|
||||||
nil
|
|
||||||
objects
|
|
||||||
:update-new-shape update-new-shape
|
|
||||||
:update-original-shape update-original-shape)
|
|
||||||
|
|
||||||
;; If frame-id points to a shape inside the component, remap it to the
|
|
||||||
;; corresponding new frame shape. If not, set it to nil.
|
|
||||||
remap-frame-id (fn [shape]
|
|
||||||
(update shape :frame-id #(get @frame-ids-map % nil)))]
|
|
||||||
|
|
||||||
[new-root-shape (map remap-frame-id new-shapes) updated-shapes]))
|
|
||||||
|
|
||||||
(defn remove-swap-keep-attrs
|
(defn remove-swap-keep-attrs
|
||||||
"Remove flex children properties except the fit-content for flex layouts. These are properties
|
"Remove flex children properties except the fit-content for flex layouts. These are properties
|
||||||
that we don't have to propagate to copies but will be respected when swapping components"
|
that we don't have to propagate to copies but will be respected when swapping components"
|
||||||
|
@ -352,20 +293,18 @@
|
||||||
WARNING: This process does not remap media references (on fills, strokes, ...); that is
|
WARNING: This process does not remap media references (on fills, strokes, ...); that is
|
||||||
delegated to an async process on the backend side that checks unreferenced shapes and
|
delegated to an async process on the backend side that checks unreferenced shapes and
|
||||||
automatically creates correct references."
|
automatically creates correct references."
|
||||||
([page component library-data position components-v2]
|
([page component library-data position]
|
||||||
(make-component-instance page component library-data position components-v2 {}))
|
(make-component-instance page component library-data position {}))
|
||||||
([page component library-data position components-v2
|
([page component library-data position
|
||||||
{:keys [main-instance? force-id force-frame-id keep-ids?]
|
{:keys [main-instance? force-id force-frame-id keep-ids?]
|
||||||
:or {main-instance? false force-id nil force-frame-id nil keep-ids? false}}]
|
:or {main-instance? false force-id nil force-frame-id nil keep-ids? false}}]
|
||||||
(let [component-page (when components-v2
|
(let [component-page (ctpl/get-page library-data (:main-instance-page component))
|
||||||
(ctpl/get-page library-data (:main-instance-page component)))
|
|
||||||
|
|
||||||
component-shape (if components-v2
|
component-shape (-> (get-shape component-page (:main-instance-id component))
|
||||||
(-> (get-shape component-page (:main-instance-id component))
|
|
||||||
(assoc :parent-id nil) ;; On v2 we force parent-id to nil in order to behave like v1
|
(assoc :parent-id nil) ;; On v2 we force parent-id to nil in order to behave like v1
|
||||||
(assoc :frame-id uuid/zero)
|
(assoc :frame-id uuid/zero)
|
||||||
(remove-swap-keep-attrs))
|
(remove-swap-keep-attrs))
|
||||||
(get-shape component (:id component)))
|
|
||||||
|
|
||||||
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
||||||
delta (gpt/subtract position orig-pos)
|
delta (gpt/subtract position orig-pos)
|
||||||
|
@ -395,8 +334,7 @@
|
||||||
update-new-shape
|
update-new-shape
|
||||||
(fn [new-shape original-shape]
|
(fn [new-shape original-shape]
|
||||||
(let [new-name (:name new-shape)
|
(let [new-name (:name new-shape)
|
||||||
root? (or (ctk/instance-root? original-shape) ; If shape is inside a component (not components-v2)
|
root? (ctk/instance-root? original-shape)]
|
||||||
(nil? (:parent-id original-shape)))] ; we detect it by having no parent)
|
|
||||||
|
|
||||||
(when root?
|
(when root?
|
||||||
(vswap! unames conj new-name))
|
(vswap! unames conj new-name))
|
||||||
|
@ -417,10 +355,8 @@
|
||||||
main-instance?
|
main-instance?
|
||||||
(dissoc :shape-ref)
|
(dissoc :shape-ref)
|
||||||
|
|
||||||
(and (not main-instance?)
|
(not main-instance?)
|
||||||
(or components-v2 ; In v1, shape-ref points to the remote instance
|
(assoc :shape-ref (:id original-shape)) ; shape-ref points to the near instance
|
||||||
(nil? (:shape-ref original-shape)))) ; in v2, shape-ref points to the near instance
|
|
||||||
(assoc :shape-ref (:id original-shape))
|
|
||||||
|
|
||||||
(nil? (:parent-id original-shape))
|
(nil? (:parent-id original-shape))
|
||||||
(assoc :component-id (:id component)
|
(assoc :component-id (:id component)
|
||||||
|
@ -428,14 +364,14 @@
|
||||||
:component-root true
|
:component-root true
|
||||||
:name new-name)
|
:name new-name)
|
||||||
|
|
||||||
(or (some? (:parent-id original-shape)) ; On v2 we have removed the parent-id for component roots (see above)
|
(or (some? (:parent-id original-shape)) ; On v2 we have removed the parent-id for component roots
|
||||||
(some? component-frame))
|
(some? component-frame))
|
||||||
(dissoc :component-root))))
|
(dissoc :component-root))))
|
||||||
|
|
||||||
[new-shape new-shapes _]
|
[new-shape new-shapes _]
|
||||||
(ctst/clone-shape component-shape
|
(ctst/clone-shape component-shape
|
||||||
frame-id
|
frame-id
|
||||||
(if components-v2 (:objects component-page) (:objects component))
|
(:objects component-page)
|
||||||
:update-new-shape update-new-shape
|
:update-new-shape update-new-shape
|
||||||
:force-id force-id
|
:force-id force-id
|
||||||
:keep-ids? keep-ids?
|
:keep-ids? keep-ids?
|
||||||
|
@ -593,8 +529,7 @@
|
||||||
|
|
||||||
;; TODO: the check of :width and :height probably may be
|
;; TODO: the check of :width and :height probably may be
|
||||||
;; removed after the check added in
|
;; removed after the check added in
|
||||||
;; data/workspace/modifiers/check-delta function. Better check
|
;; data/workspace/modifiers/check-delta function.
|
||||||
;; it and test toroughly when activating components-v2 mode.
|
|
||||||
in-copy?
|
in-copy?
|
||||||
(ctk/in-component-copy? shape)
|
(ctk/in-component-copy? shape)
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
(some? page-id)
|
(some? page-id)
|
||||||
(ctpl/add-page page)
|
(ctpl/add-page page)
|
||||||
|
|
||||||
(contains? cfeat/*current* "components/v2")
|
:always
|
||||||
(assoc-in [:options :components-v2] true)))))
|
(assoc-in [:options :components-v2] true)))))
|
||||||
|
|
||||||
(defn make-file
|
(defn make-file
|
||||||
|
@ -221,31 +221,28 @@
|
||||||
(ctpl/get-page file-data (:main-instance-page component)))
|
(ctpl/get-page file-data (:main-instance-page component)))
|
||||||
|
|
||||||
(defn get-component-container
|
(defn get-component-container
|
||||||
"Retrieve the container that holds the component shapes (the page in components-v2
|
"Retrieve the container that holds the component shapes (the page
|
||||||
or the component itself in v1 or deleted component)."
|
or the component itself on deleted component)."
|
||||||
[file-data component]
|
[file-data component]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
(if (not (:deleted component))
|
||||||
(if (and components-v2 (not (:deleted component)))
|
|
||||||
(let [component-page (get-component-page file-data component)]
|
(let [component-page (get-component-page file-data component)]
|
||||||
(cfh/make-container component-page :page))
|
(cfh/make-container component-page :page))
|
||||||
(cfh/make-container component :component))))
|
(cfh/make-container component :component)))
|
||||||
|
|
||||||
(defn get-component-root
|
(defn get-component-root
|
||||||
"Retrieve the root shape of the component."
|
"Retrieve the root shape of the component."
|
||||||
[file-data component]
|
[file-data component]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
(if (not (:deleted component))
|
||||||
(if (and components-v2 (not (:deleted component)))
|
|
||||||
(-> file-data
|
(-> file-data
|
||||||
(get-component-page component)
|
(get-component-page component)
|
||||||
(ctn/get-shape (:main-instance-id component)))
|
(ctn/get-shape (:main-instance-id component)))
|
||||||
(ctk/get-component-root component))))
|
(ctk/get-component-root component)))
|
||||||
|
|
||||||
(defn get-component-shape
|
(defn get-component-shape
|
||||||
"Retrieve one shape in the component by id. If with-context? is true, add the
|
"Retrieve one shape in the component by id. If with-context? is true, add the
|
||||||
file and container where the shape resides in its metadata."
|
file and container where the shape resides in its metadata."
|
||||||
[file-data component shape-id & {:keys [with-context?] :or {with-context? false}}]
|
[file-data component shape-id & {:keys [with-context?] :or {with-context? false}}]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
(if (not (:deleted component))
|
||||||
(if (and components-v2 (not (:deleted component)))
|
|
||||||
(let [component-page (get-component-page file-data component)]
|
(let [component-page (get-component-page file-data component)]
|
||||||
(when component-page
|
(when component-page
|
||||||
(let [child (cfh/get-child (:objects component-page)
|
(let [child (cfh/get-child (:objects component-page)
|
||||||
|
@ -262,7 +259,7 @@
|
||||||
(and shape with-context?)
|
(and shape with-context?)
|
||||||
(with-meta {:file {:id (:id file-data)
|
(with-meta {:file {:id (:id file-data)
|
||||||
:data file-data}
|
:data file-data}
|
||||||
:container (ctn/make-container component :component)}))))))
|
:container (ctn/make-container component :component)})))))
|
||||||
|
|
||||||
(defn get-ref-shape
|
(defn get-ref-shape
|
||||||
"Retrieve the shape in the component that is referenced by the instance shape."
|
"Retrieve the shape in the component that is referenced by the instance shape."
|
||||||
|
@ -384,12 +381,11 @@
|
||||||
(defn get-component-shapes
|
(defn get-component-shapes
|
||||||
"Retrieve all shapes of the component"
|
"Retrieve all shapes of the component"
|
||||||
[file-data component]
|
[file-data component]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
|
||||||
(if (and components-v2
|
(if (not (:deleted component)) ;; the deleted components have its children in the :objects property
|
||||||
(not (:deleted component))) ;; the deleted components have its children in the :objects property
|
|
||||||
(let [instance-page (get-component-page file-data component)]
|
(let [instance-page (get-component-page file-data component)]
|
||||||
(cfh/get-children-with-self (:objects instance-page) (:main-instance-id component)))
|
(cfh/get-children-with-self (:objects instance-page) (:main-instance-id component)))
|
||||||
(vals (:objects component)))))
|
(vals (:objects component))))
|
||||||
|
|
||||||
;; Return true if the object is a component that exists on the file or its libraries (even a deleted one)
|
;; Return true if the object is a component that exists on the file or its libraries (even a deleted one)
|
||||||
(defn is-main-of-known-component?
|
(defn is-main-of-known-component?
|
||||||
|
@ -406,8 +402,7 @@
|
||||||
([file-data component]
|
([file-data component]
|
||||||
(load-component-objects file-data component (gpt/point 0 0)))
|
(load-component-objects file-data component (gpt/point 0 0)))
|
||||||
([file-data component delta]
|
([file-data component delta]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
(if (and component (empty? (:objects component))) ;; This operation may be called twice, e.g. in an idempotent change
|
||||||
(if (and components-v2 component (empty? (:objects component))) ;; This operation may be called twice, e.g. in an idempotent change
|
|
||||||
(let [component-page (get-component-page file-data component)
|
(let [component-page (get-component-page file-data component)
|
||||||
page-objects (:objects component-page)
|
page-objects (:objects component-page)
|
||||||
objects (->> (cons (:main-instance-id component)
|
objects (->> (cons (:main-instance-id component)
|
||||||
|
@ -418,15 +413,14 @@
|
||||||
(map #(gsh/move % delta))
|
(map #(gsh/move % delta))
|
||||||
(d/index-by :id))]
|
(d/index-by :id))]
|
||||||
(assoc component :objects objects))
|
(assoc component :objects objects))
|
||||||
component))))
|
component)))
|
||||||
|
|
||||||
(defn delete-component
|
(defn delete-component
|
||||||
"Mark a component as deleted and store the main instance shapes iside it, to
|
"Mark a component as deleted and store the main instance shapes iside it, to
|
||||||
be able to be recovered later."
|
be able to be recovered later."
|
||||||
[file-data component-id skip-undelete? delta]
|
[file-data component-id skip-undelete? delta]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])
|
(let [delta (or delta (gpt/point 0 0))]
|
||||||
delta (or delta (gpt/point 0 0))]
|
(if skip-undelete?
|
||||||
(if (or (not components-v2) skip-undelete?)
|
|
||||||
(ctkl/delete-component file-data component-id)
|
(ctkl/delete-component file-data component-id)
|
||||||
(-> file-data
|
(-> file-data
|
||||||
(ctkl/update-component component-id #(load-component-objects file-data % delta))
|
(ctkl/update-component component-id #(load-component-objects file-data % delta))
|
||||||
|
@ -435,8 +429,7 @@
|
||||||
(defn restore-component
|
(defn restore-component
|
||||||
"Recover a deleted component and all its shapes and put all this again in place."
|
"Recover a deleted component and all its shapes and put all this again in place."
|
||||||
[file-data component-id page-id parent-id]
|
[file-data component-id page-id parent-id]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])
|
(let [update-page? (not (nil? page-id))
|
||||||
update-page? (and components-v2 (not (nil? page-id)))
|
|
||||||
component (ctkl/get-component file-data component-id true)
|
component (ctkl/get-component file-data component-id true)
|
||||||
update-variant? (and (some? parent-id)
|
update-variant? (and (some? parent-id)
|
||||||
(ctk/is-variant? component))]
|
(ctk/is-variant? component))]
|
||||||
|
@ -563,7 +556,6 @@
|
||||||
component
|
component
|
||||||
library-data
|
library-data
|
||||||
position
|
position
|
||||||
(dm/get-in file-data [:options :components-v2])
|
|
||||||
{:main-instance? true
|
{:main-instance? true
|
||||||
:keep-ids? true})
|
:keep-ids? true})
|
||||||
|
|
||||||
|
@ -595,8 +587,7 @@
|
||||||
:name (:name component)
|
:name (:name component)
|
||||||
:path (:path component)
|
:path (:path component)
|
||||||
:main-instance-id (:id main-instance-shape)
|
:main-instance-id (:id main-instance-shape)
|
||||||
:main-instance-page page-id
|
:main-instance-page page-id}))
|
||||||
:shapes (get-component-shapes library-data component)}))
|
|
||||||
|
|
||||||
; Change all existing instances to point to the local file
|
; Change all existing instances to point to the local file
|
||||||
remap-instances
|
remap-instances
|
||||||
|
|
|
@ -40,8 +40,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
(:id file)
|
(:id file)
|
||||||
true
|
|
||||||
nil
|
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
@ -74,8 +72,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
(:id file)
|
(:id file)
|
||||||
true
|
|
||||||
nil
|
|
||||||
cfsh/prepare-create-artboard-from-selection)
|
cfsh/prepare-create-artboard-from-selection)
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
@ -111,8 +107,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
(:id file)
|
(:id file)
|
||||||
true
|
|
||||||
nil
|
|
||||||
cfsh/prepare-create-artboard-from-selection)
|
cfsh/prepare-create-artboard-from-selection)
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
@ -151,8 +145,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
(:id file)
|
(:id file)
|
||||||
true
|
|
||||||
nil
|
|
||||||
cfsh/prepare-create-artboard-from-selection)
|
cfsh/prepare-create-artboard-from-selection)
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
@ -191,8 +183,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
(:id file)
|
(:id file)
|
||||||
true
|
|
||||||
nil
|
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
@ -232,8 +222,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
(:id file)
|
(:id file)
|
||||||
true
|
|
||||||
nil
|
|
||||||
cfsh/prepare-create-artboard-from-selection)
|
cfsh/prepare-create-artboard-from-selection)
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
@ -265,8 +253,7 @@
|
||||||
changes (cll/generate-rename-component (pcb/empty-changes)
|
changes (cll/generate-rename-component (pcb/empty-changes)
|
||||||
(:id component)
|
(:id component)
|
||||||
"Test component after"
|
"Test component after"
|
||||||
(:data file)
|
(:data file))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -445,8 +432,8 @@
|
||||||
(t/is (some? copy1-child'))
|
(t/is (some? copy1-child'))
|
||||||
(t/is (ctk/instance-root? copy1-root'))
|
(t/is (ctk/instance-root? copy1-root'))
|
||||||
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
|
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
|
||||||
(t/is (ctk/is-main-of? main1-root' copy1-root' true))
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
||||||
(t/is (ctk/is-main-of? main1-child' copy1-child' true))
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
||||||
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
||||||
|
|
||||||
(t/deftest test-instantiate-component-from-lib
|
(t/deftest test-instantiate-component-from-lib
|
||||||
|
@ -489,8 +476,8 @@
|
||||||
(t/is (some? copy1-child'))
|
(t/is (some? copy1-child'))
|
||||||
(t/is (ctk/instance-root? copy1-root'))
|
(t/is (ctk/instance-root? copy1-root'))
|
||||||
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
|
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
|
||||||
(t/is (ctk/is-main-of? main1-root' copy1-root' true))
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
||||||
(t/is (ctk/is-main-of? main1-child' copy1-child' true))
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
||||||
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
||||||
|
|
||||||
(t/deftest test-instantiate-nested-component
|
(t/deftest test-instantiate-nested-component
|
||||||
|
@ -533,8 +520,8 @@
|
||||||
(t/is (some? copy1-child'))
|
(t/is (some? copy1-child'))
|
||||||
(t/is (ctk/instance-root? copy1-root'))
|
(t/is (ctk/instance-root? copy1-root'))
|
||||||
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
|
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
|
||||||
(t/is (ctk/is-main-of? main1-root' copy1-root' true))
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
||||||
(t/is (ctk/is-main-of? main1-child' copy1-child' true))
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
||||||
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
||||||
|
|
||||||
(t/deftest test-instantiate-nested-component-from-lib
|
(t/deftest test-instantiate-nested-component-from-lib
|
||||||
|
@ -580,8 +567,8 @@
|
||||||
(t/is (some? copy1-child'))
|
(t/is (some? copy1-child'))
|
||||||
(t/is (ctk/instance-root? copy1-root'))
|
(t/is (ctk/instance-root? copy1-root'))
|
||||||
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
|
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
|
||||||
(t/is (ctk/is-main-of? main1-root' copy1-root' true))
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
||||||
(t/is (ctk/is-main-of? main1-child' copy1-child' true))
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
||||||
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
||||||
|
|
||||||
(t/deftest test-detach-copy
|
(t/deftest test-detach-copy
|
||||||
|
|
|
@ -47,8 +47,7 @@
|
||||||
file-mdf
|
file-mdf
|
||||||
{(:id file-mdf) file-mdf}
|
{(:id file-mdf) file-mdf}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy-root)
|
(:id copy-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -99,8 +98,7 @@
|
||||||
{(:id file-mdf) file-mdf
|
{(:id file-mdf) file-mdf
|
||||||
(:id library) library}
|
(:id library) library}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy-root)
|
(:id copy-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -151,8 +149,7 @@
|
||||||
file-mdf
|
file-mdf
|
||||||
{(:id file-mdf) file-mdf}
|
{(:id file-mdf) file-mdf}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy-root)
|
(:id copy-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -198,8 +195,7 @@
|
||||||
file-mdf
|
file-mdf
|
||||||
{(:id file-mdf) file-mdf}
|
{(:id file-mdf) file-mdf}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy-root)
|
(:id copy-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -246,8 +242,7 @@
|
||||||
file-mdf
|
file-mdf
|
||||||
{(:id file-mdf) file-mdf}
|
{(:id file-mdf) file-mdf}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy-root)
|
(:id copy-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -291,8 +286,7 @@
|
||||||
file-mdf
|
file-mdf
|
||||||
{(:id file-mdf) file-mdf}
|
{(:id file-mdf) file-mdf}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy2-root)
|
(:id copy2-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
@ -338,8 +332,7 @@
|
||||||
file-mdf
|
file-mdf
|
||||||
{(:id file-mdf) file-mdf}
|
{(:id file-mdf) file-mdf}
|
||||||
page-mdf
|
page-mdf
|
||||||
(:id copy2-root)
|
(:id copy2-root))
|
||||||
true)
|
|
||||||
|
|
||||||
file' (thf/apply-changes file changes)
|
file' (thf/apply-changes file changes)
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@
|
||||||
(t/is (= (:touched copy-root') nil))
|
(t/is (= (:touched copy-root') nil))
|
||||||
(t/is (= (:touched copy-new-child') nil))
|
(t/is (= (:touched copy-new-child') nil))
|
||||||
(t/is (ctst/parent-of? copy-root' copy-new-child'))
|
(t/is (ctst/parent-of? copy-root' copy-new-child'))
|
||||||
(t/is (ctk/is-main-of? main-free-shape' copy-new-child' true))))
|
(t/is (ctk/is-main-of? main-free-shape' copy-new-child'))))
|
||||||
|
|
||||||
(t/deftest test-sync-when-deleting-shape
|
(t/deftest test-sync-when-deleting-shape
|
||||||
(let [;; ==== Setup
|
(let [;; ==== Setup
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
(t/is (= (count components') 1))
|
(t/is (= (count components') 1))
|
||||||
|
|
||||||
(t/is (ctk/instance-of? copy-root' (:id file') (:id component')))
|
(t/is (ctk/instance-of? copy-root' (:id file') (:id component')))
|
||||||
(t/is (ctk/is-main-of? main-root' copy-root' true))
|
(t/is (ctk/is-main-of? main-root' copy-root'))
|
||||||
(t/is (ctk/main-instance-of? (:id main-root') (:id (second pages')) component'))))
|
(t/is (ctk/main-instance-of? (:id main-root') (:id (second pages')) component'))))
|
||||||
|
|
||||||
(t/deftest absorb-colors
|
(t/deftest absorb-colors
|
||||||
|
|
|
@ -582,7 +582,6 @@
|
||||||
component
|
component
|
||||||
fdata
|
fdata
|
||||||
(gpt/point (:x shape) (:y shape))
|
(gpt/point (:x shape) (:y shape))
|
||||||
true
|
|
||||||
{:keep-ids? true :force-frame-id (:frame-id shape)})
|
{:keep-ids? true :force-frame-id (:frame-id shape)})
|
||||||
children (into {} (map (fn [shape] [(:id shape) shape]) new-shapes))
|
children (into {} (map (fn [shape] [(:id shape) shape]) new-shapes))
|
||||||
objs (assoc objs id new-shape)]
|
objs (assoc objs id new-shape)]
|
||||||
|
|
|
@ -395,9 +395,9 @@
|
||||||
|
|
||||||
(defn- add-component2
|
(defn- add-component2
|
||||||
"This is the second step of the component creation."
|
"This is the second step of the component creation."
|
||||||
([selected components-v2]
|
([selected]
|
||||||
(add-component2 nil selected components-v2))
|
(add-component2 nil selected))
|
||||||
([id-ref selected components-v2]
|
([id-ref selected]
|
||||||
(ptk/reify ::add-component2
|
(ptk/reify ::add-component2
|
||||||
ev/Event
|
ev/Event
|
||||||
(-data [_]
|
(-data [_]
|
||||||
|
@ -413,8 +413,7 @@
|
||||||
parents (into #{} (map :parent-id) shapes)]
|
parents (into #{} (map :parent-id) shapes)]
|
||||||
(when-not (empty? shapes)
|
(when-not (empty? shapes)
|
||||||
(let [[root component-id changes]
|
(let [[root component-id changes]
|
||||||
(cll/generate-add-component (pcb/empty-changes it) shapes objects page-id file-id components-v2
|
(cll/generate-add-component (pcb/empty-changes it) shapes objects page-id file-id
|
||||||
dwg/prepare-create-group
|
|
||||||
cfsh/prepare-create-artboard-from-selection)]
|
cfsh/prepare-create-artboard-from-selection)]
|
||||||
(when id-ref
|
(when id-ref
|
||||||
(reset! id-ref component-id))
|
(reset! id-ref component-id))
|
||||||
|
@ -439,12 +438,11 @@
|
||||||
selected (->> (d/nilv ids (dsh/lookup-selected state))
|
selected (->> (d/nilv ids (dsh/lookup-selected state))
|
||||||
(cfh/clean-loops objects))
|
(cfh/clean-loops objects))
|
||||||
selected-objects (map #(get objects %) selected)
|
selected-objects (map #(get objects %) selected)
|
||||||
components-v2 (features/active-feature? state "components/v2")
|
|
||||||
;; We don't want to change the structure of component copies
|
;; We don't want to change the structure of component copies
|
||||||
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))]
|
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))]
|
||||||
|
|
||||||
(when can-make-component
|
(when can-make-component
|
||||||
(rx/of (add-component2 id-ref selected components-v2))))))))
|
(rx/of (add-component2 id-ref selected))))))))
|
||||||
|
|
||||||
(defn add-multiple-components
|
(defn add-multiple-components
|
||||||
"Add several new components to current file library, from the currently selected shapes."
|
"Add several new components to current file library, from the currently selected shapes."
|
||||||
|
@ -452,15 +450,14 @@
|
||||||
(ptk/reify ::add-multiple-components
|
(ptk/reify ::add-multiple-components
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [components-v2 (features/active-feature? state "components/v2")
|
(let [objects (dsh/lookup-page-objects state)
|
||||||
objects (dsh/lookup-page-objects state)
|
|
||||||
selected (->> (dsh/lookup-selected state)
|
selected (->> (dsh/lookup-selected state)
|
||||||
(cfh/clean-loops objects))
|
(cfh/clean-loops objects))
|
||||||
selected-objects (map #(get objects %) selected)
|
selected-objects (map #(get objects %) selected)
|
||||||
;; We don't want to change the structure of component copies
|
;; We don't want to change the structure of component copies
|
||||||
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))
|
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))
|
||||||
added-components (map (fn [id]
|
added-components (map (fn [id]
|
||||||
(with-meta (add-component2 [id] components-v2)
|
(with-meta (add-component2 [id])
|
||||||
{:multiple true}))
|
{:multiple true}))
|
||||||
selected)
|
selected)
|
||||||
undo-id (js/Symbol)]
|
undo-id (js/Symbol)]
|
||||||
|
@ -489,7 +486,7 @@
|
||||||
(rx/empty)
|
(rx/empty)
|
||||||
(let [data (dsh/lookup-file-data state)
|
(let [data (dsh/lookup-file-data state)
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(cll/generate-rename-component id new-name data true))]
|
(cll/generate-rename-component id new-name data))]
|
||||||
(rx/of (dch/commit-changes changes))))))))
|
(rx/of (dch/commit-changes changes))))))))
|
||||||
|
|
||||||
(defn rename-component-and-main-instance
|
(defn rename-component-and-main-instance
|
||||||
|
@ -512,7 +509,6 @@
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (rename-component component-id clean-name))
|
(rx/of (rename-component component-id clean-name))
|
||||||
|
|
||||||
;; NOTE: only when components-v2 is enabled
|
|
||||||
(when (and shape-id page-id)
|
(when (and shape-id page-id)
|
||||||
(rx/of (dwsh/update-shapes [shape-id] #(assoc % :name clean-name) {:page-id page-id :stack-undo? true}))))))))))
|
(rx/of (dwsh/update-shapes [shape-id] #(assoc % :name clean-name) {:page-id page-id :stack-undo? true}))))))))))
|
||||||
|
|
||||||
|
@ -526,11 +522,10 @@
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [libraries (dsh/lookup-libraries state)
|
(let [libraries (dsh/lookup-libraries state)
|
||||||
library (get libraries library-id)
|
library (get libraries library-id)
|
||||||
components-v2 (features/active-feature? state "components/v2")
|
|
||||||
|
|
||||||
[main-instance changes]
|
[main-instance changes]
|
||||||
(-> (pcb/empty-changes it nil)
|
(-> (pcb/empty-changes it nil)
|
||||||
(cll/generate-duplicate-component library component-id new-component-id components-v2))]
|
(cll/generate-duplicate-component library component-id new-component-id))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(ptk/data-event :layout/update {:ids [(:id main-instance)]})
|
(ptk/data-event :layout/update {:ids [(:id main-instance)]})
|
||||||
(dch/commit-changes changes)))))))
|
(dch/commit-changes changes)))))))
|
||||||
|
@ -560,8 +555,7 @@
|
||||||
[all-parents changes]
|
[all-parents changes]
|
||||||
(-> (pcb/empty-changes it page-id)
|
(-> (pcb/empty-changes it page-id)
|
||||||
;; Deleting main root triggers component delete
|
;; Deleting main root triggers component delete
|
||||||
(cls/generate-delete-shapes fdata page objects #{root-id} {:components-v2 true
|
(cls/generate-delete-shapes fdata page objects #{root-id} {:undo-group undo-group
|
||||||
:undo-group undo-group
|
|
||||||
:undo-id undo-id}))]
|
:undo-id undo-id}))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(dwu/start-undo-transaction undo-id)
|
(dwu/start-undo-transaction undo-id)
|
||||||
|
@ -827,7 +821,7 @@
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(cll/generate-reset-component file libraries container id true))]
|
(cll/generate-reset-component file libraries container id))]
|
||||||
|
|
||||||
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
|
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
|
||||||
(:redo-changes changes)
|
(:redo-changes changes)
|
||||||
|
@ -879,7 +873,7 @@
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/set-undo-group undo-group)
|
(pcb/set-undo-group undo-group)
|
||||||
(pcb/with-container container)
|
(pcb/with-container container)
|
||||||
(cll/generate-sync-shape-inverse fdata libraries container id true))
|
(cll/generate-sync-shape-inverse fdata libraries container id))
|
||||||
|
|
||||||
ldata (->> (:component-file shape)
|
ldata (->> (:component-file shape)
|
||||||
(dsh/lookup-file-data state))
|
(dsh/lookup-file-data state))
|
||||||
|
@ -1269,10 +1263,8 @@
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::watch-component-changes
|
(ptk/reify ::watch-component-changes
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ _ stream]
|
||||||
(let [components-v2? (features/active-feature? state "components/v2")
|
(let [stopper-s
|
||||||
|
|
||||||
stopper-s
|
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter #(or (= ::dw/finalize-page (ptk/type %))
|
(rx/filter #(or (= ::dw/finalize-page (ptk/type %))
|
||||||
(= ::watch-component-changes (ptk/type %)))))
|
(= ::watch-component-changes (ptk/type %)))))
|
||||||
|
@ -1335,7 +1327,7 @@
|
||||||
(rx/debounce 5000)
|
(rx/debounce 5000)
|
||||||
(rx/tap #(log/trc :hint "buffer initialized")))]
|
(rx/tap #(log/trc :hint "buffer initialized")))]
|
||||||
|
|
||||||
(when (and components-v2? (contains? cf/flags :component-thumbnails))
|
(when (contains? cf/flags :component-thumbnails)
|
||||||
(->> (rx/merge
|
(->> (rx/merge
|
||||||
changes-s
|
changes-s
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.media :as dmm]
|
[app.main.data.media :as dmm]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
[app.main.data.workspace.svg-upload :as svg]
|
[app.main.data.workspace.svg-upload :as svg]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
@ -235,16 +234,6 @@
|
||||||
(rx/catch #(handle-media-error % on-error))
|
(rx/catch #(handle-media-error % on-error))
|
||||||
(rx/finalize #(st/emit! (ntf/hide :tag :media-loading))))))))
|
(rx/finalize #(st/emit! (ntf/hide :tag :media-loading))))))))
|
||||||
|
|
||||||
;; Deprecated in components-v2
|
|
||||||
(defn upload-media-asset
|
|
||||||
[params]
|
|
||||||
(let [params (assoc params
|
|
||||||
:force-media true
|
|
||||||
:local? false
|
|
||||||
:on-image #(st/emit! (dwl/add-media %))
|
|
||||||
:on-svg #(st/emit! (dwl/add-media %)))]
|
|
||||||
(process-media-objects params)))
|
|
||||||
|
|
||||||
(defn upload-media-workspace
|
(defn upload-media-workspace
|
||||||
[{:keys [position file-id] :as params}]
|
[{:keys [position file-id] :as params}]
|
||||||
(let [params (assoc params
|
(let [params (assoc params
|
||||||
|
@ -378,7 +367,7 @@
|
||||||
|
|
||||||
(defn- add-shapes-and-component
|
(defn- add-shapes-and-component
|
||||||
[it file-data page name [shape children]]
|
[it file-data page name [shape children]]
|
||||||
(let [[component-shape component-shapes updated-shapes]
|
(let [[component-shape updated-shapes]
|
||||||
(ctn/convert-shape-in-component shape children (:id file-data))
|
(ctn/convert-shape-in-component shape children (:id file-data))
|
||||||
|
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
|
@ -389,7 +378,6 @@
|
||||||
(pcb/add-component (:id component-shape)
|
(pcb/add-component (:id component-shape)
|
||||||
""
|
""
|
||||||
name
|
name
|
||||||
component-shapes
|
|
||||||
updated-shapes
|
updated-shapes
|
||||||
(:id shape)
|
(:id shape)
|
||||||
(:id page)))]
|
(:id page)))]
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
[app.main.data.workspace.edition :as dwe]
|
[app.main.data.workspace.edition :as dwe]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.features :as features]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
@ -171,12 +170,10 @@
|
||||||
page (dsh/get-page fdata page-id)
|
page (dsh/get-page fdata page-id)
|
||||||
objects (:objects page)
|
objects (:objects page)
|
||||||
|
|
||||||
components-v2 (features/active-feature? state "components/v2")
|
|
||||||
undo-id (or (:undo-id options) (js/Symbol))
|
undo-id (or (:undo-id options) (js/Symbol))
|
||||||
[all-parents changes] (-> (pcb/empty-changes it (:id page))
|
[all-parents changes] (-> (pcb/empty-changes it (:id page))
|
||||||
(cls/generate-delete-shapes fdata page objects ids
|
(cls/generate-delete-shapes fdata page objects ids
|
||||||
{:components-v2 components-v2
|
{:ignore-touched (:component-swap options)
|
||||||
:ignore-touched (:component-swap options)
|
|
||||||
:undo-group (:undo-group options)
|
:undo-group (:undo-group options)
|
||||||
:undo-id undo-id}))]
|
:undo-id undo-id}))]
|
||||||
|
|
||||||
|
|
|
@ -260,6 +260,14 @@
|
||||||
(let [message (tr "errors.feature-not-supported" (:feature error))]
|
(let [message (tr "errors.feature-not-supported" (:feature error))]
|
||||||
(st/emit! (modal/show {:type :alert :message message})))
|
(st/emit! (modal/show {:type :alert :message message})))
|
||||||
|
|
||||||
|
(= :file-in-components-v1 code)
|
||||||
|
(st/emit! (modal/show {:type :alert
|
||||||
|
:message (tr "errors.deprecated")
|
||||||
|
:link-message {:before (tr "errors.deprecated.contact.before")
|
||||||
|
:text (tr "errors.deprecated.contact.text")
|
||||||
|
:after (tr "errors.deprecated.contact.after")
|
||||||
|
:on-click #(st/emit! (rt/nav :settings-feedback))}}))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(print-cause! "Restriction Error" error)))
|
(print-cause! "Restriction Error" error)))
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
[app.main.ui.components.link :as lk]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
::mf/register-as :alert}
|
::mf/register-as :alert}
|
||||||
[{:keys [message
|
[{:keys [message
|
||||||
scd-message
|
scd-message
|
||||||
|
link-message
|
||||||
title
|
title
|
||||||
on-accept
|
on-accept
|
||||||
hint
|
hint
|
||||||
|
@ -59,8 +61,16 @@
|
||||||
[:div {:class (stl/css :modal-content)}
|
[:div {:class (stl/css :modal-content)}
|
||||||
(when (and (string? message) (not= message ""))
|
(when (and (string? message) (not= message ""))
|
||||||
[:h3 {:class (stl/css :modal-msg)} message])
|
[:h3 {:class (stl/css :modal-msg)} message])
|
||||||
|
(when (seq link-message)
|
||||||
|
[:h3 {:class (stl/css :modal-msg)}
|
||||||
|
[:span (:before link-message)]
|
||||||
|
[:& lk/link {:action (:on-click link-message)
|
||||||
|
:class (stl/css :link)}
|
||||||
|
(:text link-message)]
|
||||||
|
[:span (:after link-message)]])
|
||||||
(when (and (string? scd-message) (not= scd-message ""))
|
(when (and (string? scd-message) (not= scd-message ""))
|
||||||
[:h3 {:class (stl/css :modal-scd-msg)} scd-message])
|
[:h3 {:class (stl/css :modal-scd-msg)} scd-message])
|
||||||
|
|
||||||
(when (string? hint)
|
(when (string? hint)
|
||||||
[:p {:class (stl/css :modal-hint)} hint])]
|
[:p {:class (stl/css :modal-hint)} hint])]
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,12 @@
|
||||||
|
|
||||||
.modal-overlay {
|
.modal-overlay {
|
||||||
@extend .modal-overlay-base;
|
@extend .modal-overlay-base;
|
||||||
|
|
||||||
&.transparent {
|
&.transparent {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-container {
|
.modal-container {
|
||||||
@extend .modal-container-base;
|
@extend .modal-container-base;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +50,7 @@
|
||||||
|
|
||||||
.accept-btn {
|
.accept-btn {
|
||||||
@extend .modal-accept-btn;
|
@extend .modal-accept-btn;
|
||||||
|
|
||||||
&.danger {
|
&.danger {
|
||||||
@extend .modal-danger-btn;
|
@extend .modal-danger-btn;
|
||||||
}
|
}
|
||||||
|
@ -60,3 +63,15 @@
|
||||||
color: var(--modal-text-foreground-color);
|
color: var(--modal-text-foreground-color);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link::before {
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.link::after {
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
(def render-thumbnails (mf/create-context nil))
|
(def render-thumbnails (mf/create-context nil))
|
||||||
|
|
||||||
(def libraries (mf/create-context nil))
|
(def libraries (mf/create-context nil))
|
||||||
(def components-v2 (mf/create-context nil))
|
|
||||||
(def design-tokens (mf/create-context nil))
|
(def design-tokens (mf/create-context nil))
|
||||||
|
|
||||||
(def current-scroll (mf/create-context nil))
|
(def current-scroll (mf/create-context nil))
|
||||||
|
|
|
@ -159,7 +159,7 @@
|
||||||
[:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
|
[:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
|
||||||
[:div {:class (stl/css :asset-list)}
|
[:div {:class (stl/css :asset-list)}
|
||||||
(for [component (:sample components)]
|
(for [component (:sample components)]
|
||||||
(let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
|
(let [root-id (:main-instance-id component)]
|
||||||
[:div {:class (stl/css :asset-list-item)
|
[:div {:class (stl/css :asset-list-item)
|
||||||
:key (str "assets-component-" (:id component))}
|
:key (str "assets-component-" (:id component))}
|
||||||
[:& render/component-svg {:root-shape (get-in component [:objects root-id])
|
[:& render/component-svg {:root-shape (get-in component [:objects root-id])
|
||||||
|
|
|
@ -200,7 +200,6 @@
|
||||||
[:> (mf/provider ctx/current-project-id) {:value project-id}
|
[:> (mf/provider ctx/current-project-id) {:value project-id}
|
||||||
[:> (mf/provider ctx/current-file-id) {:value file-id}
|
[:> (mf/provider ctx/current-file-id) {:value file-id}
|
||||||
[:> (mf/provider ctx/current-page-id) {:value page-id}
|
[:> (mf/provider ctx/current-page-id) {:value page-id}
|
||||||
[:> (mf/provider ctx/components-v2) {:value true}
|
|
||||||
[:> (mf/provider ctx/design-tokens) {:value design-tokens?}
|
[:> (mf/provider ctx/design-tokens) {:value design-tokens?}
|
||||||
[:> (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
[:> (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
||||||
[:> modal-container*]
|
[:> modal-container*]
|
||||||
|
@ -216,4 +215,4 @@
|
||||||
:file file
|
:file file
|
||||||
:wglobal wglobal
|
:wglobal wglobal
|
||||||
:layout layout}]
|
:layout layout}]
|
||||||
[:> workspace-loader*])]]]]]]]))
|
[:> workspace-loader*])]]]]]]))
|
||||||
|
|
|
@ -555,7 +555,7 @@
|
||||||
objects (deref refs/workspace-page-objects)
|
objects (deref refs/workspace-page-objects)
|
||||||
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) shapes))
|
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) shapes))
|
||||||
heads (filter ctk/instance-head? shapes)
|
heads (filter ctk/instance-head? shapes)
|
||||||
components-menu-entries (cmm/generate-components-menu-entries heads true)
|
components-menu-entries (cmm/generate-components-menu-entries heads)
|
||||||
variant-container? (and single? (ctk/is-variant-container? (first shapes)))
|
variant-container? (and single? (ctk/is-variant-container? (first shapes)))
|
||||||
do-add-component #(st/emit! (dwl/add-component))
|
do-add-component #(st/emit! (dwl/add-component))
|
||||||
do-add-multiple-components #(st/emit! (dwl/add-multiple-components))
|
do-add-multiple-components #(st/emit! (dwl/add-multiple-components))
|
||||||
|
|
|
@ -75,8 +75,7 @@
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[{:keys [size file-id]}]
|
[{:keys [size file-id]}]
|
||||||
(let [components-v2 (mf/use-ctx ctx/components-v2)
|
(let [read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
|
||||||
filters* (mf/use-state
|
filters* (mf/use-state
|
||||||
{:term ""
|
{:term ""
|
||||||
:section "all"
|
:section "all"
|
||||||
|
@ -148,11 +147,6 @@
|
||||||
:id "components"
|
:id "components"
|
||||||
:handler on-section-filter-change}
|
:handler on-section-filter-change}
|
||||||
|
|
||||||
(when (not components-v2)
|
|
||||||
{:name (tr "workspace.assets.graphics")
|
|
||||||
:id "graphics"
|
|
||||||
:handler on-section-filter-change})
|
|
||||||
|
|
||||||
{:name (tr "workspace.assets.colors")
|
{:name (tr "workspace.assets.colors")
|
||||||
:id "colors"
|
:id "colors"
|
||||||
:handler on-section-filter-change}
|
:handler on-section-filter-change}
|
||||||
|
|
|
@ -322,7 +322,7 @@
|
||||||
:is-hidden is-hidden}])))
|
:is-hidden is-hidden}])))
|
||||||
|
|
||||||
(defn generate-components-menu-entries
|
(defn generate-components-menu-entries
|
||||||
[shapes components-v2]
|
[shapes]
|
||||||
(let [multi (> (count shapes) 1)
|
(let [multi (> (count shapes) 1)
|
||||||
copies (filter ctk/in-component-copy? shapes)
|
copies (filter ctk/in-component-copy? shapes)
|
||||||
|
|
||||||
|
@ -350,13 +350,13 @@
|
||||||
|
|
||||||
touched-not-dangling (filter #(and (cfh/component-touched? objects (:id %))
|
touched-not-dangling (filter #(and (cfh/component-touched? objects (:id %))
|
||||||
(find-component % false)) copies)
|
(find-component % false)) copies)
|
||||||
can-reset-overrides? (or (not components-v2) (seq touched-not-dangling))
|
can-reset-overrides? (seq touched-not-dangling)
|
||||||
|
|
||||||
|
|
||||||
;; For when it's only one shape
|
;; For when it's only one shape
|
||||||
shape (first shapes)
|
shape (first shapes)
|
||||||
id (:id shape)
|
id (:id shape)
|
||||||
main-instance? (if components-v2 (ctk/main-instance? shape) true)
|
main-instance? (ctk/main-instance? shape)
|
||||||
|
|
||||||
component-id (:component-id shape)
|
component-id (:component-id shape)
|
||||||
library-id (:component-file shape)
|
library-id (:component-file shape)
|
||||||
|
@ -372,10 +372,9 @@
|
||||||
|
|
||||||
can-update-main? (and (not multi)
|
can-update-main? (and (not multi)
|
||||||
(not is-dangling?)
|
(not is-dangling?)
|
||||||
(or (not components-v2)
|
|
||||||
(and (not main-instance?)
|
(and (not main-instance?)
|
||||||
(not (ctn/has-any-copy-parent? objects shape))
|
(not (ctn/has-any-copy-parent? objects shape))
|
||||||
(cfh/component-touched? objects (:id shape)))))
|
(cfh/component-touched? objects (:id shape))))
|
||||||
|
|
||||||
can-detach? (and (seq copies)
|
can-detach? (and (seq copies)
|
||||||
(every? #(not (ctn/has-any-copy-parent? objects %)) copies))
|
(every? #(not (ctn/has-any-copy-parent? objects %)) copies))
|
||||||
|
@ -450,7 +449,7 @@
|
||||||
menu-entries [(when (and (not multi) main-instance?)
|
menu-entries [(when (and (not multi) main-instance?)
|
||||||
{:title (tr "workspace.shape.menu.show-in-assets")
|
{:title (tr "workspace.shape.menu.show-in-assets")
|
||||||
:action do-show-in-assets})
|
:action do-show-in-assets})
|
||||||
(when (and (not multi) main-instance? local-component? lacks-annotation? components-v2)
|
(when (and (not multi) main-instance? local-component? lacks-annotation?)
|
||||||
{:title (tr "workspace.shape.menu.create-annotation")
|
{:title (tr "workspace.shape.menu.create-annotation")
|
||||||
:action do-create-annotation})
|
:action do-create-annotation})
|
||||||
(when can-detach?
|
(when can-detach?
|
||||||
|
@ -462,7 +461,7 @@
|
||||||
(when can-reset-overrides?
|
(when can-reset-overrides?
|
||||||
{:title (tr "workspace.shape.menu.reset-overrides")
|
{:title (tr "workspace.shape.menu.reset-overrides")
|
||||||
:action do-reset-component})
|
:action do-reset-component})
|
||||||
(when (and (seq restorable-copies) components-v2)
|
(when (seq restorable-copies)
|
||||||
{:title (tr "workspace.shape.menu.restore-main")
|
{:title (tr "workspace.shape.menu.restore-main")
|
||||||
:action do-restore-component})
|
:action do-restore-component})
|
||||||
(when can-show-component?
|
(when can-show-component?
|
||||||
|
|
|
@ -308,7 +308,6 @@
|
||||||
|
|
||||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
components-v2 (mf/use-ctx ctx/components-v2)
|
|
||||||
toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
|
toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
|
||||||
|
|
||||||
selected (:components selected)
|
selected (:components selected)
|
||||||
|
@ -521,7 +520,7 @@
|
||||||
:title (tr "workspace.assets.grid-view")
|
:title (tr "workspace.assets.grid-view")
|
||||||
:id "opt-grid"}]]])
|
:id "opt-grid"}]]])
|
||||||
|
|
||||||
(when (and components-v2 (not read-only?) is-local)
|
(when (and (not read-only?) is-local)
|
||||||
[:> icon-button* {:variant "ghost"
|
[:> icon-button* {:variant "ghost"
|
||||||
:aria-label (tr "workspace.assets.components.add-component")
|
:aria-label (tr "workspace.assets.components.add-component")
|
||||||
:on-click add-component
|
:on-click add-component
|
||||||
|
@ -561,9 +560,7 @@
|
||||||
:id "assets-rename-component"
|
:id "assets-rename-component"
|
||||||
:handler on-rename})
|
:handler on-rename})
|
||||||
(when (and is-local (not (or multi-assets? read-only? any-variant?)))
|
(when (and is-local (not (or multi-assets? read-only? any-variant?)))
|
||||||
{:name (if components-v2
|
{:name (tr "workspace.assets.duplicate-main")
|
||||||
(tr "workspace.assets.duplicate-main")
|
|
||||||
(tr "workspace.assets.duplicate"))
|
|
||||||
:id "assets-duplicate-component"
|
:id "assets-duplicate-component"
|
||||||
:handler on-duplicate})
|
:handler on-duplicate})
|
||||||
|
|
||||||
|
@ -576,7 +573,7 @@
|
||||||
:id "assets-group-component"
|
:id "assets-group-component"
|
||||||
:handler on-group})
|
:handler on-group})
|
||||||
|
|
||||||
(when (and components-v2 (not multi-assets?))
|
(when (not multi-assets?)
|
||||||
{:name (tr "workspace.shape.menu.show-main")
|
{:name (tr "workspace.shape.menu.show-main")
|
||||||
:id "assets-show-main-component"
|
:id "assets-show-main-component"
|
||||||
:handler on-show-main})]}]]]))
|
:handler on-show-main})]}]]]))
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
[app.main.ui.workspace.sidebar.assets.colors :refer [colors-section]]
|
[app.main.ui.workspace.sidebar.assets.colors :refer [colors-section]]
|
||||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||||
[app.main.ui.workspace.sidebar.assets.components :refer [components-section]]
|
[app.main.ui.workspace.sidebar.assets.components :refer [components-section]]
|
||||||
[app.main.ui.workspace.sidebar.assets.graphics :refer [graphics-section]]
|
|
||||||
[app.main.ui.workspace.sidebar.assets.typographies :refer [typographies-section]]
|
[app.main.ui.workspace.sidebar.assets.typographies :refer [typographies-section]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
@ -145,11 +144,10 @@
|
||||||
|
|
||||||
(mf/defc file-library-content*
|
(mf/defc file-library-content*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [file is-local is-loaded open-status-ref on-clear-selection filters colors media typographies components count-variants]}]
|
[{:keys [file is-local is-loaded open-status-ref on-clear-selection filters colors typographies components count-variants]}]
|
||||||
(let [open-status (mf/deref open-status-ref)
|
(let [open-status (mf/deref open-status-ref)
|
||||||
|
|
||||||
file-id (:id file)
|
file-id (:id file)
|
||||||
project-id (:project-id file)
|
|
||||||
|
|
||||||
filters-section (:section filters)
|
filters-section (:section filters)
|
||||||
has-filters-term? (not ^boolean (str/empty? (:term filters)))
|
has-filters-term? (not ^boolean (str/empty? (:term filters)))
|
||||||
|
@ -165,11 +163,6 @@
|
||||||
(or (pos? (count components))
|
(or (pos? (count components))
|
||||||
(not has-filters-term?)))
|
(not has-filters-term?)))
|
||||||
|
|
||||||
show-graphics?
|
|
||||||
(and (or (= filters-section "all")
|
|
||||||
(= filters-section "graphics"))
|
|
||||||
(pos? (count media)))
|
|
||||||
|
|
||||||
show-colors?
|
show-colors?
|
||||||
(and (or (= filters-section "all")
|
(and (or (= filters-section "all")
|
||||||
(= filters-section "colors"))
|
(= filters-section "colors"))
|
||||||
|
@ -188,9 +181,6 @@
|
||||||
force-open-colors?
|
force-open-colors?
|
||||||
(when ^boolean has-filters-term? (> 60 (count colors)))
|
(when ^boolean has-filters-term? (> 60 (count colors)))
|
||||||
|
|
||||||
force-open-graphics?
|
|
||||||
(when ^boolean has-filters-term? (> 60 (count media)))
|
|
||||||
|
|
||||||
force-open-typographies?
|
force-open-typographies?
|
||||||
(when ^boolean has-filters-term? (> 60 (count typographies)))
|
(when ^boolean has-filters-term? (> 60 (count typographies)))
|
||||||
|
|
||||||
|
@ -214,9 +204,6 @@
|
||||||
on-component-click
|
on-component-click
|
||||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :components))
|
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :components))
|
||||||
|
|
||||||
on-graphics-click
|
|
||||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :graphics))
|
|
||||||
|
|
||||||
on-colors-click
|
on-colors-click
|
||||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :colors))
|
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :colors))
|
||||||
|
|
||||||
|
@ -266,23 +253,6 @@
|
||||||
:on-clear-selection on-clear-selection
|
:on-clear-selection on-clear-selection
|
||||||
:count-variants count-variants}])
|
:count-variants count-variants}])
|
||||||
|
|
||||||
(when ^boolean show-graphics?
|
|
||||||
[:& graphics-section
|
|
||||||
{:file-id file-id
|
|
||||||
:project-id project-id
|
|
||||||
:local? is-local
|
|
||||||
:objects media
|
|
||||||
:listing-thumbs? listing-thumbs?
|
|
||||||
:open? (or ^boolean force-open-graphics?
|
|
||||||
^boolean (get open-status :graphics false))
|
|
||||||
:force-open? force-open-graphics?
|
|
||||||
:open-status-ref open-status-ref
|
|
||||||
:reverse-sort? reverse-sort?
|
|
||||||
:selected selected
|
|
||||||
:on-asset-click on-graphics-click
|
|
||||||
:on-assets-delete on-assets-delete
|
|
||||||
:on-clear-selection on-clear-selection}])
|
|
||||||
|
|
||||||
(when ^boolean show-colors?
|
(when ^boolean show-colors?
|
||||||
[:& colors-section
|
[:& colors-section
|
||||||
{:file-id file-id
|
{:file-id file-id
|
||||||
|
@ -315,7 +285,6 @@
|
||||||
:on-clear-selection on-clear-selection}])
|
:on-clear-selection on-clear-selection}])
|
||||||
|
|
||||||
(when (and (not ^boolean show-components?)
|
(when (and (not ^boolean show-components?)
|
||||||
(not ^boolean show-graphics?)
|
|
||||||
(not ^boolean show-colors?)
|
(not ^boolean show-colors?)
|
||||||
(not ^boolean show-typography?))
|
(not ^boolean show-typography?))
|
||||||
[:div {:class (stl/css :asset-title)}
|
[:div {:class (stl/css :asset-title)}
|
||||||
|
@ -333,7 +302,6 @@
|
||||||
library (use-library-ref file-id)
|
library (use-library-ref file-id)
|
||||||
|
|
||||||
colors (:colors library)
|
colors (:colors library)
|
||||||
media (:media library)
|
|
||||||
typographies (:typographies library)
|
typographies (:typographies library)
|
||||||
|
|
||||||
filters-term (:term filters)
|
filters-term (:term filters)
|
||||||
|
@ -350,11 +318,6 @@
|
||||||
(cmm/apply-filters $ filters)
|
(cmm/apply-filters $ filters)
|
||||||
(remove #(cfv/is-secondary-variant? % library) $)))
|
(remove #(cfv/is-secondary-variant? % library) $)))
|
||||||
|
|
||||||
filtered-media
|
|
||||||
(mf/with-memo [filters media]
|
|
||||||
(-> (vals media)
|
|
||||||
(cmm/apply-filters filters)))
|
|
||||||
|
|
||||||
filtered-typographies
|
filtered-typographies
|
||||||
(mf/with-memo [filters typographies]
|
(mf/with-memo [filters typographies]
|
||||||
(-> (vals typographies)
|
(-> (vals typographies)
|
||||||
|
@ -372,7 +335,6 @@
|
||||||
(and (not (str/blank? filters-term))
|
(and (not (str/blank? filters-term))
|
||||||
(or (> 60 (count filtered-colors))
|
(or (> 60 (count filtered-colors))
|
||||||
(> 60 (count filtered-components))
|
(> 60 (count filtered-components))
|
||||||
(> 60 (count filtered-media))
|
|
||||||
(> 60 (count filtered-typographies))))
|
(> 60 (count filtered-typographies))))
|
||||||
|
|
||||||
open?
|
open?
|
||||||
|
@ -415,7 +377,6 @@
|
||||||
:filters filters
|
:filters filters
|
||||||
:colors filtered-colors
|
:colors filtered-colors
|
||||||
:components filtered-components
|
:components filtered-components
|
||||||
:media filtered-media
|
|
||||||
:typographies filtered-typographies
|
:typographies filtered-typographies
|
||||||
:on-clear-selection unselect-all
|
:on-clear-selection unselect-all
|
||||||
:open-status-ref open-status-ref
|
:open-status-ref open-status-ref
|
||||||
|
|
|
@ -1,432 +0,0 @@
|
||||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
;;
|
|
||||||
;; Copyright (c) KALEIDOS INC
|
|
||||||
|
|
||||||
(ns app.main.ui.workspace.sidebar.assets.graphics
|
|
||||||
(:require-macros [app.main.style :as stl])
|
|
||||||
(:require
|
|
||||||
[app.common.data :as d]
|
|
||||||
[app.common.data.macros :as dm]
|
|
||||||
[app.common.files.helpers :as cfh]
|
|
||||||
[app.common.media :as cm]
|
|
||||||
[app.config :as cf]
|
|
||||||
[app.main.data.event :as ev]
|
|
||||||
[app.main.data.modal :as modal]
|
|
||||||
[app.main.data.workspace :as dw]
|
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
|
||||||
[app.main.data.workspace.media :as dwm]
|
|
||||||
[app.main.data.workspace.undo :as dwu]
|
|
||||||
[app.main.store :as st]
|
|
||||||
[app.main.ui.components.editable-label :refer [editable-label]]
|
|
||||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
|
||||||
[app.main.ui.context :as ctx]
|
|
||||||
[app.main.ui.hooks :as h]
|
|
||||||
[app.main.ui.icons :as i]
|
|
||||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
|
||||||
[app.main.ui.workspace.sidebar.assets.groups :as grp]
|
|
||||||
[app.util.dom :as dom]
|
|
||||||
[app.util.dom.dnd :as dnd]
|
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
|
||||||
[cuerdas.core :as str]
|
|
||||||
[okulary.core :as l]
|
|
||||||
[potok.v2.core :as ptk]
|
|
||||||
[rumext.v2 :as mf]))
|
|
||||||
|
|
||||||
(mf/defc graphics-item
|
|
||||||
[{:keys [object renaming listing-thumbs? selected-objects file-id
|
|
||||||
on-asset-click on-context-menu on-drag-start do-rename cancel-rename
|
|
||||||
selected-full selected-graphics-paths]}]
|
|
||||||
(let [item-ref (mf/use-ref)
|
|
||||||
visible? (h/use-visible item-ref :once? true)
|
|
||||||
object-id (:id object)
|
|
||||||
|
|
||||||
dragging* (mf/use-state false)
|
|
||||||
dragging? (deref dragging*)
|
|
||||||
|
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
|
||||||
|
|
||||||
on-drop
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps object dragging* selected-objects selected-full selected-graphics-paths)
|
|
||||||
(fn [event]
|
|
||||||
(cmm/on-drop-asset event object dragging* selected-objects selected-full
|
|
||||||
selected-graphics-paths dwl/rename-media)))
|
|
||||||
|
|
||||||
on-drag-enter
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps object dragging* selected-objects selected-graphics-paths)
|
|
||||||
(fn [event]
|
|
||||||
(cmm/on-drag-enter-asset event object dragging* selected-objects selected-graphics-paths)))
|
|
||||||
|
|
||||||
on-drag-leave
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps dragging*)
|
|
||||||
(fn [event]
|
|
||||||
(cmm/on-drag-leave-asset event dragging*)))
|
|
||||||
|
|
||||||
on-grahic-drag-start
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps object file-id selected-objects item-ref on-drag-start read-only?)
|
|
||||||
(fn [event]
|
|
||||||
(if read-only?
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(cmm/on-asset-drag-start event file-id object selected-objects item-ref :graphics on-drag-start))))
|
|
||||||
|
|
||||||
on-context-menu
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps object-id)
|
|
||||||
(partial on-context-menu object-id))
|
|
||||||
|
|
||||||
on-asset-click
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps object-id on-asset-click)
|
|
||||||
(fn [event]
|
|
||||||
(on-asset-click event object-id)))]
|
|
||||||
|
|
||||||
[:div {:ref item-ref
|
|
||||||
:class-name (stl/css-case
|
|
||||||
:selected (contains? selected-objects object-id)
|
|
||||||
:grid-cell listing-thumbs?
|
|
||||||
:enum-item (not listing-thumbs?))
|
|
||||||
:draggable (not read-only?)
|
|
||||||
:on-click on-asset-click
|
|
||||||
:on-context-menu on-context-menu
|
|
||||||
:on-drag-start on-grahic-drag-start
|
|
||||||
:on-drag-enter on-drag-enter
|
|
||||||
:on-drag-leave on-drag-leave
|
|
||||||
:on-drag-over dom/prevent-default
|
|
||||||
:on-drop on-drop}
|
|
||||||
|
|
||||||
(when visible?
|
|
||||||
[:*
|
|
||||||
[:img {:src (when visible? (cf/resolve-file-media object true))
|
|
||||||
:class (stl/css :graphic-image)
|
|
||||||
:draggable false}] ;; Also need to add css pointer-events: none
|
|
||||||
|
|
||||||
(let [renaming? (= renaming (:id object))]
|
|
||||||
[:*
|
|
||||||
[:& editable-label
|
|
||||||
{:class (stl/css-case
|
|
||||||
:cell-name listing-thumbs?
|
|
||||||
:item-name (not listing-thumbs?)
|
|
||||||
:editing renaming?)
|
|
||||||
:value (cfh/merge-path-item (:path object) (:name object))
|
|
||||||
:tooltip (cfh/merge-path-item (:path object) (:name object))
|
|
||||||
:display-value (:name object)
|
|
||||||
:editing renaming?
|
|
||||||
:disable-dbl-click true
|
|
||||||
:on-change do-rename
|
|
||||||
:on-cancel cancel-rename}]
|
|
||||||
|
|
||||||
(when ^boolean dragging?
|
|
||||||
[:div {:class (stl/css :dragging)}])])])]))
|
|
||||||
|
|
||||||
(mf/defc graphics-group
|
|
||||||
[{:keys [file-id prefix groups open-groups force-open? renaming listing-thumbs? selected-objects on-asset-click
|
|
||||||
on-drag-start do-rename cancel-rename on-rename-group on-ungroup
|
|
||||||
on-context-menu selected-full]}]
|
|
||||||
(let [group-open? (get open-groups prefix true)
|
|
||||||
dragging* (mf/use-state false)
|
|
||||||
dragging? (deref dragging*)
|
|
||||||
|
|
||||||
selected-paths
|
|
||||||
(mf/with-memo [selected-full]
|
|
||||||
(into #{}
|
|
||||||
(comp (map :path) (d/nilv ""))
|
|
||||||
selected-full))
|
|
||||||
|
|
||||||
on-drag-enter
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps dragging* prefix selected-paths)
|
|
||||||
(fn [event]
|
|
||||||
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths)))
|
|
||||||
|
|
||||||
on-drag-leave
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps dragging*)
|
|
||||||
(fn [event]
|
|
||||||
(cmm/on-drag-leave-asset event dragging*)))
|
|
||||||
|
|
||||||
on-drop
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps dragging* prefix selected-paths selected-full)
|
|
||||||
(fn [event]
|
|
||||||
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-media)))]
|
|
||||||
[:div {:class (stl/css :graphics-group)
|
|
||||||
:on-drag-enter on-drag-enter
|
|
||||||
:on-drag-leave on-drag-leave
|
|
||||||
:on-drag-over dom/prevent-default
|
|
||||||
:on-drop on-drop}
|
|
||||||
[:& grp/asset-group-title
|
|
||||||
{:file-id file-id
|
|
||||||
:section :graphics
|
|
||||||
:path prefix
|
|
||||||
:group-open? group-open?
|
|
||||||
:on-rename on-rename-group
|
|
||||||
:on-ungroup on-ungroup}]
|
|
||||||
(when group-open?
|
|
||||||
[:*
|
|
||||||
(let [objects (get groups "" [])]
|
|
||||||
[:div {:class-name (stl/css-case
|
|
||||||
:asset-grid listing-thumbs?
|
|
||||||
:asset-enum (not listing-thumbs?)
|
|
||||||
:drop-space (and
|
|
||||||
(empty? objects)
|
|
||||||
(some? groups)
|
|
||||||
(not dragging?)))
|
|
||||||
:on-drag-enter on-drag-enter
|
|
||||||
:on-drag-leave on-drag-leave
|
|
||||||
:on-drag-over dom/prevent-default
|
|
||||||
:on-drop on-drop}
|
|
||||||
|
|
||||||
(when ^boolean dragging?
|
|
||||||
[:div {:class (stl/css :grid-placeholder)} "\u00A0"])
|
|
||||||
|
|
||||||
(when (and (empty? objects)
|
|
||||||
(some? groups))
|
|
||||||
[:div {:class (stl/css :drop-space)}])
|
|
||||||
|
|
||||||
(for [object objects]
|
|
||||||
[:& graphics-item
|
|
||||||
{:key (dm/str "object-" (:id object))
|
|
||||||
:file-id file-id
|
|
||||||
:object object
|
|
||||||
:renaming renaming
|
|
||||||
:listing-thumbs? listing-thumbs?
|
|
||||||
:selected-objects selected-objects
|
|
||||||
:on-asset-click on-asset-click
|
|
||||||
:on-context-menu on-context-menu
|
|
||||||
:on-drag-start on-drag-start
|
|
||||||
:do-rename do-rename
|
|
||||||
:cancel-rename cancel-rename
|
|
||||||
:selected-full selected-full
|
|
||||||
:selected-paths selected-paths}])])
|
|
||||||
(for [[path-item content] groups]
|
|
||||||
(when-not (empty? path-item)
|
|
||||||
[:& graphics-group {:file-id file-id
|
|
||||||
:key path-item
|
|
||||||
:prefix (cfh/merge-path-item prefix path-item)
|
|
||||||
:groups content
|
|
||||||
:open-groups open-groups
|
|
||||||
:force-open? force-open?
|
|
||||||
:renaming renaming
|
|
||||||
:listing-thumbs? listing-thumbs?
|
|
||||||
:selected-objects selected-objects
|
|
||||||
:on-asset-click on-asset-click
|
|
||||||
:on-drag-start on-drag-start
|
|
||||||
:do-rename do-rename
|
|
||||||
:cancel-rename cancel-rename
|
|
||||||
:on-rename-group on-rename-group
|
|
||||||
:on-ungroup on-ungroup
|
|
||||||
:on-context-menu on-context-menu
|
|
||||||
:selected-full selected-full
|
|
||||||
:selected-paths selected-paths}]))])]))
|
|
||||||
|
|
||||||
(mf/defc graphics-section
|
|
||||||
{::mf/wrap-props false}
|
|
||||||
[{:keys [file-id project-id local? objects listing-thumbs? open? force-open? open-status-ref selected reverse-sort?
|
|
||||||
on-asset-click on-assets-delete on-clear-selection]}]
|
|
||||||
(let [input-ref (mf/use-ref nil)
|
|
||||||
state (mf/use-state {:renaming nil :object-id nil})
|
|
||||||
|
|
||||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
|
||||||
|
|
||||||
open-groups-ref (mf/with-memo [open-status-ref]
|
|
||||||
(-> (l/in [:groups :graphics])
|
|
||||||
(l/derived open-status-ref)))
|
|
||||||
open-groups (mf/deref open-groups-ref)
|
|
||||||
|
|
||||||
selected (:graphics selected)
|
|
||||||
selected-full (into #{} (filter #(contains? selected (:id %))) objects)
|
|
||||||
multi-objects? (> (count selected) 1)
|
|
||||||
multi-assets? (or (seq (:components selected))
|
|
||||||
(seq (:colors selected))
|
|
||||||
(seq (:typographies selected)))
|
|
||||||
|
|
||||||
objects (mf/with-memo [objects]
|
|
||||||
(mapv dwl/extract-path-if-missing objects))
|
|
||||||
|
|
||||||
groups (mf/with-memo [objects reverse-sort?]
|
|
||||||
(grp/group-assets objects reverse-sort?))
|
|
||||||
|
|
||||||
components-v2 (mf/use-ctx ctx/components-v2)
|
|
||||||
team-id (mf/use-ctx ctx/current-team-id)
|
|
||||||
|
|
||||||
add-graphic
|
|
||||||
(mf/use-fn
|
|
||||||
(fn []
|
|
||||||
(st/emit! (dw/set-assets-section-open file-id :graphics true))
|
|
||||||
(dom/click (mf/ref-val input-ref))))
|
|
||||||
|
|
||||||
on-file-selected
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps file-id project-id team-id)
|
|
||||||
(fn [blobs]
|
|
||||||
(let [params {:file-id file-id
|
|
||||||
:blobs (seq blobs)}]
|
|
||||||
(st/emit! (dwm/upload-media-asset params)
|
|
||||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
|
||||||
:asset-type "graphics"
|
|
||||||
:file-id file-id
|
|
||||||
:project-id project-id
|
|
||||||
:team-id team-id})))))
|
|
||||||
on-delete
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps @state multi-objects? multi-assets?)
|
|
||||||
(fn []
|
|
||||||
(if (or multi-objects? multi-assets?)
|
|
||||||
(on-assets-delete)
|
|
||||||
(st/emit! (dwl/delete-media {:id (:object-id @state)})))))
|
|
||||||
|
|
||||||
on-rename
|
|
||||||
(mf/use-fn
|
|
||||||
(fn []
|
|
||||||
(swap! state (fn [state]
|
|
||||||
(assoc state :renaming (:object-id state))))))
|
|
||||||
cancel-rename
|
|
||||||
(mf/use-fn
|
|
||||||
(fn []
|
|
||||||
(swap! state assoc :renaming nil)))
|
|
||||||
|
|
||||||
do-rename
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps @state)
|
|
||||||
(fn [new-name]
|
|
||||||
(st/emit! (dwl/rename-media (:renaming @state) new-name))
|
|
||||||
(swap! state assoc :renaming nil)))
|
|
||||||
|
|
||||||
on-context-menu
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps selected on-clear-selection read-only?)
|
|
||||||
(fn [object-id event]
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(let [pos (dom/get-client-position event)]
|
|
||||||
(when (and local? (not read-only?))
|
|
||||||
(when-not (contains? selected object-id)
|
|
||||||
(on-clear-selection))
|
|
||||||
(swap! state assoc :object-id object-id)
|
|
||||||
(swap! menu-state cmm/open-context-menu pos)))))
|
|
||||||
|
|
||||||
on-close-menu
|
|
||||||
(mf/use-fn
|
|
||||||
(fn []
|
|
||||||
(swap! menu-state cmm/close-context-menu)))
|
|
||||||
|
|
||||||
create-group
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps objects selected on-clear-selection (:object-id @state))
|
|
||||||
(fn [group-name]
|
|
||||||
(on-clear-selection)
|
|
||||||
(let [undo-id (js/Symbol)]
|
|
||||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
|
||||||
(run! st/emit!
|
|
||||||
(->> objects
|
|
||||||
(filter #(if multi-objects?
|
|
||||||
(contains? selected (:id %))
|
|
||||||
(= (:object-id @state) (:id %))))
|
|
||||||
(map #(dwl/rename-media (:id %) (cmm/add-group % group-name)))))
|
|
||||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
|
||||||
|
|
||||||
rename-group
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps objects)
|
|
||||||
(fn [path last-path]
|
|
||||||
(on-clear-selection)
|
|
||||||
(let [undo-id (js/Symbol)]
|
|
||||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
|
||||||
(run! st/emit!
|
|
||||||
(->> objects
|
|
||||||
(filter #(str/starts-with? (:path %) path))
|
|
||||||
(map #(dwl/rename-media (:id %) (cmm/rename-group % path last-path)))))
|
|
||||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
|
||||||
|
|
||||||
on-group
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps objects selected create-group)
|
|
||||||
(fn [event]
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(modal/show! :name-group-dialog {:accept create-group})))
|
|
||||||
|
|
||||||
on-rename-group
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps objects)
|
|
||||||
(fn [event path last-path]
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(modal/show! :name-group-dialog {:path path
|
|
||||||
:last-path last-path
|
|
||||||
:accept rename-group})))
|
|
||||||
on-ungroup
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps objects)
|
|
||||||
(fn [path]
|
|
||||||
(on-clear-selection)
|
|
||||||
(let [undo-id (js/Symbol)]
|
|
||||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
|
||||||
(run! st/emit!
|
|
||||||
(->> objects
|
|
||||||
(filter #(str/starts-with? (:path %) path))
|
|
||||||
(map #(dwl/rename-media (:id %) (cmm/ungroup % path)))))
|
|
||||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
|
||||||
|
|
||||||
on-drag-start
|
|
||||||
(mf/use-fn
|
|
||||||
(fn [{:keys [name id mtype]} event]
|
|
||||||
(dnd/set-data! event "text/asset-id" (str id))
|
|
||||||
(dnd/set-data! event "text/asset-name" name)
|
|
||||||
(dnd/set-data! event "text/asset-type" mtype)
|
|
||||||
(dnd/set-allowed-effect! event "move")))
|
|
||||||
|
|
||||||
on-asset-click
|
|
||||||
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
|
||||||
|
|
||||||
[:& cmm/asset-section {:file-id file-id
|
|
||||||
:title (tr "workspace.assets.graphics")
|
|
||||||
:section :graphics
|
|
||||||
:assets-count (count objects)
|
|
||||||
:open? open?}
|
|
||||||
(when local?
|
|
||||||
[:& cmm/asset-section-block {:role :title-button}
|
|
||||||
(when (and (not components-v2) (not read-only?))
|
|
||||||
[:button {:class (stl/css :assets-btn)
|
|
||||||
:on-click add-graphic}
|
|
||||||
i/add
|
|
||||||
[:& file-uploader {:accept cm/str-image-types
|
|
||||||
:multi true
|
|
||||||
:ref input-ref
|
|
||||||
:on-selected on-file-selected}]])])
|
|
||||||
|
|
||||||
[:& cmm/asset-section-block {:role :content}
|
|
||||||
[:& graphics-group {:file-id file-id
|
|
||||||
:prefix ""
|
|
||||||
:groups groups
|
|
||||||
:open-groups open-groups
|
|
||||||
:force-open? force-open?
|
|
||||||
:renaming (:renaming @state)
|
|
||||||
:listing-thumbs? listing-thumbs?
|
|
||||||
:selected selected
|
|
||||||
:on-asset-click on-asset-click
|
|
||||||
:on-drag-start on-drag-start
|
|
||||||
:do-rename do-rename
|
|
||||||
:cancel-rename cancel-rename
|
|
||||||
:on-rename-group on-rename-group
|
|
||||||
:on-ungroup on-ungroup
|
|
||||||
:on-context-menu on-context-menu
|
|
||||||
:selected-full selected-full}]
|
|
||||||
(when local?
|
|
||||||
[:& cmm/assets-context-menu
|
|
||||||
{:on-close on-close-menu
|
|
||||||
:state @menu-state
|
|
||||||
:options [(when-not (or multi-objects? multi-assets?)
|
|
||||||
{:name (tr "workspace.assets.rename")
|
|
||||||
:id "assets-rename-graphics"
|
|
||||||
:handler on-rename})
|
|
||||||
{:name (tr "workspace.assets.delete")
|
|
||||||
:id "assets-delete-graphics"
|
|
||||||
:handler on-delete}
|
|
||||||
(when-not multi-assets?
|
|
||||||
{:name (tr "workspace.assets.group")
|
|
||||||
:id "assets-group-graphics"
|
|
||||||
:handler on-group})]}])]]))
|
|
|
@ -1,188 +0,0 @@
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
//
|
|
||||||
// Copyright (c) KALEIDOS INC
|
|
||||||
|
|
||||||
@import "refactor/common-refactor.scss";
|
|
||||||
|
|
||||||
.graphics-group {
|
|
||||||
.drop-space {
|
|
||||||
height: $s-12;
|
|
||||||
}
|
|
||||||
.asset-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: $s-4;
|
|
||||||
margin-left: $s-8;
|
|
||||||
.grid-cell {
|
|
||||||
@include flexCenter;
|
|
||||||
position: relative;
|
|
||||||
padding: $s-8;
|
|
||||||
border: $s-2 solid transparent;
|
|
||||||
border-radius: $br-8;
|
|
||||||
aspect-ratio: 1/1;
|
|
||||||
background-color: var(--color-foreground-secondary);
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
img {
|
|
||||||
height: auto;
|
|
||||||
width: auto;
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
svg {
|
|
||||||
height: 10vh;
|
|
||||||
}
|
|
||||||
.cell-name {
|
|
||||||
@include bodySmallTypography;
|
|
||||||
@include textEllipsis;
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
padding: $s-2;
|
|
||||||
|
|
||||||
&.editing {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editable-label-input {
|
|
||||||
height: unset;
|
|
||||||
width: 100%;
|
|
||||||
padding: $s-2;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editable-label-close {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--assets-item-background-color-hover);
|
|
||||||
.cell-name {
|
|
||||||
display: block;
|
|
||||||
color: var(--assets-item-name-foreground-color-hover);
|
|
||||||
background: linear-gradient(to top, rgba(52, 57, 59, 1) 0%, rgba(52, 57, 59, 0) 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border: $s-1 solid var(--assets-item-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dragging {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border-radius: $s-8;
|
|
||||||
background-color: var(--assets-item-background-color-drag);
|
|
||||||
border: $s-2 solid var(--assets-item-border-color-drag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.asset-enum {
|
|
||||||
padding-bottom: $s-4;
|
|
||||||
.enum-item {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: $s-36;
|
|
||||||
margin-bottom: $s-4;
|
|
||||||
padding: $s-2;
|
|
||||||
border-radius: $br-8;
|
|
||||||
background-color: var(--assets-item-background-color);
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
svg,
|
|
||||||
img {
|
|
||||||
@include flexCenter;
|
|
||||||
padding: $s-2;
|
|
||||||
height: $s-32;
|
|
||||||
width: $s-32;
|
|
||||||
border-radius: $br-6;
|
|
||||||
background-color: var(--assets-component-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-name {
|
|
||||||
@include bodySmallTypography;
|
|
||||||
@include textEllipsis;
|
|
||||||
padding-left: $s-8;
|
|
||||||
color: var(--assets-item-name-foreground-color);
|
|
||||||
|
|
||||||
&.editing {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.editable-label-input {
|
|
||||||
height: $s-24;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editable-label-close {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--assets-item-background-color-hover);
|
|
||||||
.item-name {
|
|
||||||
color: var(--assets-item-name-foreground-color-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.selected {
|
|
||||||
border: $s-1 solid var(--assets-item-border-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.grid-placeholder {
|
|
||||||
height: $s-2;
|
|
||||||
background-color: var(--color-accent-primary);
|
|
||||||
margin-bottom: $s-2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listing-options {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.listing-option-btn {
|
|
||||||
@include flexCenter;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.first {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
height: $s-16;
|
|
||||||
width: $s-16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.add-component {
|
|
||||||
@extend .button-tertiary;
|
|
||||||
height: $s-32;
|
|
||||||
width: $s-28;
|
|
||||||
margin-left: $s-2;
|
|
||||||
border-radius: $br-8;
|
|
||||||
svg {
|
|
||||||
@extend .button-icon;
|
|
||||||
stroke: var(--icon-foreground);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.assets-btn {
|
|
||||||
@extend .button-tertiary;
|
|
||||||
height: $s-32;
|
|
||||||
width: calc($s-24 + $s-4);
|
|
||||||
padding: 0;
|
|
||||||
border-radius: $br-8;
|
|
||||||
svg {
|
|
||||||
@extend .button-icon;
|
|
||||||
stroke: var(--icon-foreground);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -53,8 +53,7 @@
|
||||||
parent-board? (and (cfh/frame-shape? item)
|
parent-board? (and (cfh/frame-shape? item)
|
||||||
(= uuid/zero (:parent-id item)))
|
(= uuid/zero (:parent-id item)))
|
||||||
absolute? (ctl/item-absolute? item)
|
absolute? (ctl/item-absolute? item)
|
||||||
components-v2 (mf/use-ctx ctx/components-v2)
|
main-instance? (:main-instance item)
|
||||||
main-instance? (or (not components-v2) (:main-instance item))
|
|
||||||
variants? (features/use-feature "variants/v1")
|
variants? (features/use-feature "variants/v1")
|
||||||
is-variant? (when variants? (ctk/is-variant? item))
|
is-variant? (when variants? (ctk/is-variant? item))
|
||||||
variant-name (when is-variant? (:variant-name item))
|
variant-name (when is-variant? (:variant-name item))
|
||||||
|
|
|
@ -679,7 +679,7 @@
|
||||||
(fn []
|
(fn []
|
||||||
(swap! state* update :render inc)))
|
(swap! state* update :render inc)))
|
||||||
|
|
||||||
menu-entries (cmm/generate-components-menu-entries shapes true)
|
menu-entries (cmm/generate-components-menu-entries shapes)
|
||||||
show-menu? (seq menu-entries)
|
show-menu? (seq menu-entries)
|
||||||
path (->> component (:path) (cfh/split-path) (cfh/join-path-with-dot))]
|
path (->> component (:path) (cfh/split-path) (cfh/join-path-with-dot))]
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
|
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
|
||||||
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
|
|
||||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
|
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]]
|
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
|
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
|
||||||
|
@ -70,7 +69,6 @@
|
||||||
[:div {:class (stl/css :options)}
|
[:div {:class (stl/css :options)}
|
||||||
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
|
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
|
||||||
[:> measures-menu* {:type type :ids measure-ids :values measure-values :shape shape}]
|
[:> measures-menu* {:type type :ids measure-ids :values measure-values :shape shape}]
|
||||||
[:& component-menu {:shapes [shape]}] ;;remove this in components-v2
|
|
||||||
|
|
||||||
[:& layout-container-menu
|
[:& layout-container-menu
|
||||||
{:type type
|
{:type type
|
||||||
|
|
|
@ -251,8 +251,7 @@
|
||||||
on-frame-enter (unchecked-get props "on-frame-enter")
|
on-frame-enter (unchecked-get props "on-frame-enter")
|
||||||
on-frame-leave (unchecked-get props "on-frame-leave")
|
on-frame-leave (unchecked-get props "on-frame-leave")
|
||||||
on-frame-select (unchecked-get props "on-frame-select")
|
on-frame-select (unchecked-get props "on-frame-select")
|
||||||
components-v2 (mf/use-ctx ctx/components-v2)
|
shapes (ctt/get-frames objects {:skip-copies? true})
|
||||||
shapes (ctt/get-frames objects {:skip-copies? components-v2})
|
|
||||||
shapes (if (dbg/enabled? :shape-titles)
|
shapes (if (dbg/enabled? :shape-titles)
|
||||||
(into (set shapes)
|
(into (set shapes)
|
||||||
(map (d/getf objects))
|
(map (d/getf objects))
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
[app.plugins :as plugins]
|
[app.plugins :as plugins]
|
||||||
[app.util.timers :as tm]))
|
[app.util.timers :as tm]))
|
||||||
|
|
||||||
(defn ^:export is-components-v2 []
|
|
||||||
(features/active-feature? @st/state "components/v2"))
|
|
||||||
|
|
||||||
(defn ^:export grid []
|
(defn ^:export grid []
|
||||||
(tm/schedule-on-idle #(st/emit! (features/toggle-feature "layout/grid")))
|
(tm/schedule-on-idle #(st/emit! (features/toggle-feature "layout/grid")))
|
||||||
nil)
|
nil)
|
||||||
|
|
|
@ -146,8 +146,6 @@
|
||||||
(:objects page)
|
(:objects page)
|
||||||
(:id page)
|
(:id page)
|
||||||
current-file-id
|
current-file-id
|
||||||
true
|
|
||||||
dwg/prepare-create-group
|
|
||||||
cfsh/prepare-create-artboard-from-selection)]
|
cfsh/prepare-create-artboard-from-selection)]
|
||||||
|
|
||||||
(swap! idmap assoc instance-label (:id group)
|
(swap! idmap assoc instance-label (:id group)
|
||||||
|
|
|
@ -1237,6 +1237,18 @@ msgstr ""
|
||||||
"features of the file you are trying to open. Migrations for '%s' need to be "
|
"features of the file you are trying to open. Migrations for '%s' need to be "
|
||||||
"applied before the file can be opened."
|
"applied before the file can be opened."
|
||||||
|
|
||||||
|
msgid "errors.deprecated"
|
||||||
|
msgstr "Sorry! This is an old file that uses a deprecated type of Penpot assets and you can't open it."
|
||||||
|
|
||||||
|
msgid "errors.deprecated.contact.before"
|
||||||
|
msgstr "Although Penpot no longer support this type of Assets, you can"
|
||||||
|
|
||||||
|
msgid "errors.deprecated.contact.text"
|
||||||
|
msgstr "contact us"
|
||||||
|
|
||||||
|
msgid "errors.deprecated.contact.after"
|
||||||
|
msgstr "so we can help you."
|
||||||
|
|
||||||
#: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49
|
#: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49
|
||||||
msgid "errors.generic"
|
msgid "errors.generic"
|
||||||
msgstr "Something wrong has happened."
|
msgstr "Something wrong has happened."
|
||||||
|
|
|
@ -1245,6 +1245,18 @@ msgstr ""
|
||||||
"del fichero que se esta intentando abrir. Falta aplicar migraciones para "
|
"del fichero que se esta intentando abrir. Falta aplicar migraciones para "
|
||||||
"'%s' antes de poder abrir el fichero."
|
"'%s' antes de poder abrir el fichero."
|
||||||
|
|
||||||
|
msgid "errors.deprecated"
|
||||||
|
msgstr "¡Lo sentimos! Este es un fichero antiguo que utiliza un tipo de recurso de Penpot obsoleto, y no puedes abrirlo."
|
||||||
|
|
||||||
|
msgid "errors.deprecated.contact.before"
|
||||||
|
msgstr "Aunque Penpot ya no da soporte a este tipo de Recursos, puedes"
|
||||||
|
|
||||||
|
msgid "errors.deprecated.contact.text"
|
||||||
|
msgstr "contactar con nosotros"
|
||||||
|
|
||||||
|
msgid "errors.deprecated.contact.after"
|
||||||
|
msgstr "para que podamos ayudarte."
|
||||||
|
|
||||||
#: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49
|
#: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49
|
||||||
msgid "errors.generic"
|
msgid "errors.generic"
|
||||||
msgstr "Ha ocurrido algún error."
|
msgstr "Ha ocurrido algún error."
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue