mirror of
https://github.com/penpot/penpot.git
synced 2025-03-18 10:41:29 -05:00
🎉 Add more test cases, and some fixes
This commit is contained in:
parent
31bfe3930d
commit
ca56e08459
10 changed files with 1386 additions and 484 deletions
|
@ -7,6 +7,7 @@
|
|||
(ns app.common.pages.changes-builder
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.bool :as gshb]
|
||||
[app.common.pages :as cp]
|
||||
|
@ -94,6 +95,11 @@
|
|||
[changes]
|
||||
(assert (contains? (meta changes) ::library-data) "Call (with-library-data) before using this function"))
|
||||
|
||||
(defn- lookup-objects
|
||||
[changes]
|
||||
(let [data (::file-data (meta changes))]
|
||||
(dm/get-in data [:pages-index uuid/zero :objects])))
|
||||
|
||||
(defn- apply-changes-local
|
||||
[changes]
|
||||
(if-let [file-data (::file-data (meta changes))]
|
||||
|
@ -221,7 +227,7 @@
|
|||
([changes parent-id shapes index]
|
||||
(assert-page-id changes)
|
||||
(assert-objects changes)
|
||||
(let [objects (get-in (meta changes) [::file-data :pages-index uuid/zero :objects])
|
||||
(let [objects (lookup-objects changes)
|
||||
|
||||
set-parent-change
|
||||
(cond-> {:type :mov-objects
|
||||
|
@ -253,12 +259,13 @@
|
|||
([changes ids update-fn]
|
||||
(update-shapes changes ids update-fn nil))
|
||||
|
||||
([changes ids update-fn {:keys [attrs ignore-geometry?] :or {attrs nil ignore-geometry? false}}]
|
||||
([changes ids update-fn {:keys [attrs ignore-geometry? ignore-touched]
|
||||
:or {ignore-geometry? false ignore-touched false}}]
|
||||
(assert-container-id changes)
|
||||
(assert-objects changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
component-id (::component-id (meta changes))
|
||||
objects (get-in (meta changes) [::file-data :pages-index uuid/zero :objects])
|
||||
objects (lookup-objects changes)
|
||||
|
||||
generate-operation
|
||||
(fn [operations attr old new ignore-geometry?]
|
||||
|
@ -267,8 +274,11 @@
|
|||
(if (= old-val new-val)
|
||||
operations
|
||||
(-> operations
|
||||
(update :rops conj {:type :set :attr attr :val new-val :ignore-geometry ignore-geometry?})
|
||||
(update :uops conj {:type :set :attr attr :val old-val :ignore-touched true})))))
|
||||
(update :rops conj {:type :set :attr attr :val new-val
|
||||
:ignore-geometry ignore-geometry?
|
||||
:ignore-touched ignore-touched})
|
||||
(update :uops conj {:type :set :attr attr :val old-val
|
||||
:ignore-touched true})))))
|
||||
|
||||
update-shape
|
||||
(fn [changes id]
|
||||
|
@ -310,7 +320,7 @@
|
|||
(assert-page-id changes)
|
||||
(assert-objects changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
objects (get-in (meta changes) [::file-data :pages-index uuid/zero :objects])
|
||||
objects (lookup-objects changes)
|
||||
|
||||
add-redo-change
|
||||
(fn [change-set id]
|
||||
|
@ -358,7 +368,7 @@
|
|||
(assert-page-id changes)
|
||||
(assert-objects changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
objects (get-in (meta changes) [::file-data :pages-index uuid/zero :objects])
|
||||
objects (lookup-objects changes)
|
||||
|
||||
xform (comp
|
||||
(mapcat #(cons % (cph/get-parent-ids objects %)))
|
||||
|
@ -504,8 +514,28 @@
|
|||
(assert-page-id changes)
|
||||
(assert-objects changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
objects (-> changes meta ::file-data (get-in [:pages-index uuid/zero :objects]))]
|
||||
objects (lookup-objects changes)
|
||||
lookupf (d/getf objects)
|
||||
|
||||
mk-change (fn [shape]
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id (:id shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val (:component-id shape)}
|
||||
{:type :set
|
||||
:attr :component-file
|
||||
:val (:component-file shape)}
|
||||
{:type :set
|
||||
:attr :component-root?
|
||||
:val (:component-root? shape)}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val (:shape-ref shape)}
|
||||
{:type :set
|
||||
:attr :touched
|
||||
:val (:touched shape)}]}) ]
|
||||
(-> changes
|
||||
(update :redo-changes
|
||||
(fn [redo-changes]
|
||||
|
@ -515,52 +545,16 @@
|
|||
:path path
|
||||
:name name
|
||||
:shapes new-shapes})
|
||||
(into (map (fn [updated-shape]
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id (:id updated-shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val (:component-id updated-shape)}
|
||||
{:type :set
|
||||
:attr :component-file
|
||||
:val (:component-file updated-shape)}
|
||||
{:type :set
|
||||
:attr :component-root?
|
||||
:val (:component-root? updated-shape)}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val (:shape-ref updated-shape)}
|
||||
{:type :set
|
||||
:attr :touched
|
||||
:val (:touched updated-shape)}]})
|
||||
updated-shapes)))))
|
||||
(into (map mk-change) updated-shapes))))
|
||||
(update :undo-changes
|
||||
(fn [undo-changes]
|
||||
(-> undo-changes
|
||||
(conj {:type :del-component
|
||||
:id id})
|
||||
(into (map (fn [updated-shape]
|
||||
(let [original-shape (get objects (:id updated-shape))]
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id (:id updated-shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val (:component-id original-shape)}
|
||||
{:type :set
|
||||
:attr :component-file
|
||||
:val (:component-file original-shape)}
|
||||
{:type :set
|
||||
:attr :component-root?
|
||||
:val (:component-root? original-shape)}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val (:shape-ref original-shape)}
|
||||
{:type :set
|
||||
:attr :touched
|
||||
:val (:touched original-shape)}]}))
|
||||
updated-shapes)))))
|
||||
(into (comp (map :id)
|
||||
(map lookupf)
|
||||
(map mk-change))
|
||||
updated-shapes))))
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn update-component
|
||||
|
|
|
@ -307,7 +307,6 @@
|
|||
(defn clean-loops
|
||||
"Clean a list of ids from circular references."
|
||||
[objects ids]
|
||||
|
||||
(let [parent-selected?
|
||||
(fn [id]
|
||||
(let [parents (get-parent-ids objects id)]
|
||||
|
|
|
@ -660,8 +660,9 @@
|
|||
moved-shape (assoc shape
|
||||
:parent-id parent-id
|
||||
:frame-id frame-id)]
|
||||
(assoc shape :constraints-h (gsh/default-constraints-h moved-shape)
|
||||
:constraints-v (gsh/default-constraints-v moved-shape))))
|
||||
(assoc shape
|
||||
:constraints-h (gsh/default-constraints-h moved-shape)
|
||||
:constraints-v (gsh/default-constraints-v moved-shape))))
|
||||
{:ignore-touched true})
|
||||
|
||||
; Resize parent containers that need to
|
||||
|
|
|
@ -250,7 +250,7 @@
|
|||
objects (wsh/lookup-page-objects state page-id)
|
||||
shapes (dwg/shapes-for-grouping objects selected)]
|
||||
(when-not (empty? shapes)
|
||||
(let [[group changes]
|
||||
(let [[group _ changes]
|
||||
(dwlh/generate-add-component it shapes objects page-id file-id)]
|
||||
(when-not (empty? (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
|
@ -306,7 +306,7 @@
|
|||
(ptk/reify ::duplicate-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [libraries (dwlh/get-libraries state)
|
||||
(let [libraries (wsh/get-libraries state)
|
||||
component (cph/get-component libraries id)
|
||||
all-components (-> state :workspace-data :components vals)
|
||||
unames (into #{} (map :name) all-components)
|
||||
|
@ -349,57 +349,16 @@
|
|||
(ptk/reify ::instantiate-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [libraries (dwlh/get-libraries state)
|
||||
component (cph/get-component libraries file-id component-id)
|
||||
component-shape (cph/get-shape component component-id)
|
||||
|
||||
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
||||
delta (gpt/subtract position orig-pos)
|
||||
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
unames (volatile! (dwc/retrieve-used-names objects))
|
||||
|
||||
frame-id (cph/frame-id-by-position objects (gpt/add orig-pos delta))
|
||||
|
||||
update-new-shape
|
||||
(fn [new-shape original-shape]
|
||||
(let [new-name (dwc/generate-unique-name @unames (:name new-shape))]
|
||||
|
||||
(when (nil? (:parent-id original-shape))
|
||||
(vswap! unames conj new-name))
|
||||
|
||||
(cond-> new-shape
|
||||
true
|
||||
(as-> $
|
||||
(geom/move $ delta)
|
||||
(assoc $ :frame-id frame-id)
|
||||
(assoc $ :parent-id
|
||||
(or (:parent-id $) (:frame-id $)))
|
||||
(dissoc $ :touched))
|
||||
|
||||
(nil? (:shape-ref original-shape))
|
||||
(assoc :shape-ref (:id original-shape))
|
||||
|
||||
(nil? (:parent-id original-shape))
|
||||
(assoc :component-id (:id original-shape)
|
||||
:component-file file-id
|
||||
:component-root? true
|
||||
:name new-name)
|
||||
|
||||
(some? (:parent-id original-shape))
|
||||
(dissoc :component-root?))))
|
||||
|
||||
[new-shape new-shapes _]
|
||||
(cph/clone-object component-shape
|
||||
nil
|
||||
(get component :objects)
|
||||
update-new-shape)
|
||||
|
||||
changes (reduce #(pcb/add-object %1 %2 {:ignore-touched true})
|
||||
(pcb/empty-changes it page-id)
|
||||
new-shapes)]
|
||||
(let [page (wsh/lookup-page state)
|
||||
libraries (wsh/get-libraries state)
|
||||
|
||||
[new-shape changes]
|
||||
(dwlh/generate-instantiate-component it
|
||||
file-id
|
||||
component-id
|
||||
position
|
||||
page
|
||||
libraries)]
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwc/select-shapes (d/ordered-set (:id new-shape))))))))
|
||||
|
||||
|
@ -411,7 +370,7 @@
|
|||
(ptk/reify ::detach-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file (dwlh/get-local-file state)
|
||||
(let [file (wsh/get-local-file state)
|
||||
page-id (get state :current-page-id)
|
||||
container (cph/get-container file :page page-id)
|
||||
|
||||
|
@ -428,7 +387,7 @@
|
|||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
file (dwlh/get-local-file state)
|
||||
file (wsh/get-local-file state)
|
||||
container (cph/get-container file :page page-id)
|
||||
selected (->> state
|
||||
(wsh/lookup-selected)
|
||||
|
@ -482,8 +441,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(log/info :msg "RESET-COMPONENT of shape" :id (str id))
|
||||
(let [file (dwlh/get-local-file state)
|
||||
libraries (dwlh/get-libraries state)
|
||||
(let [file (wsh/get-local-file state)
|
||||
libraries (wsh/get-libraries state)
|
||||
|
||||
page-id (:current-page-id state)
|
||||
container (cph/get-container file :page page-id)
|
||||
|
@ -516,8 +475,8 @@
|
|||
(log/info :msg "UPDATE-COMPONENT of shape" :id (str id))
|
||||
(let [page-id (get state :current-page-id)
|
||||
|
||||
local-file (dwlh/get-local-file state)
|
||||
libraries (dwlh/get-libraries state)
|
||||
local-file (wsh/get-local-file state)
|
||||
libraries (wsh/get-libraries state)
|
||||
|
||||
container (cph/get-container local-file :page page-id)
|
||||
shape (cph/get-shape container id)
|
||||
|
@ -528,7 +487,7 @@
|
|||
(dwlh/generate-sync-shape-inverse libraries container id))
|
||||
|
||||
file-id (:component-file shape)
|
||||
file (dwlh/get-file state file-id)
|
||||
file (wsh/get-file state file-id)
|
||||
|
||||
xf-filter (comp
|
||||
(filter :local-change?)
|
||||
|
@ -608,7 +567,7 @@
|
|||
(log/info :msg "SYNC-FILE"
|
||||
:file (dwlh/pretty-file file-id state)
|
||||
:library (dwlh/pretty-file library-id state))
|
||||
(let [file (dwlh/get-file state file-id)
|
||||
(let [file (wsh/get-file state file-id)
|
||||
|
||||
library-changes (reduce
|
||||
pcb/concat-changes
|
||||
|
@ -665,7 +624,7 @@
|
|||
(log/info :msg "SYNC-FILE (2nd stage)"
|
||||
:file (dwlh/pretty-file file-id state)
|
||||
:library (dwlh/pretty-file library-id state))
|
||||
(let [file (dwlh/get-file state file-id)
|
||||
(let [file (wsh/get-file state file-id)
|
||||
changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.text :as txt]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]))
|
||||
|
||||
|
@ -52,31 +54,12 @@
|
|||
(declare reposition-shape)
|
||||
(declare make-change)
|
||||
|
||||
(defn get-local-file
|
||||
[state]
|
||||
(get state :workspace-data))
|
||||
|
||||
(defn get-file
|
||||
[state file-id]
|
||||
(if (= file-id (:current-file-id state))
|
||||
(get state :workspace-data)
|
||||
(get-in state [:workspace-libraries file-id :data])))
|
||||
|
||||
(defn get-libraries
|
||||
"Retrieve all libraries, including the local file."
|
||||
[state]
|
||||
(let [{:keys [id] :as local} (:workspace-data state)]
|
||||
(-> (:workspace-libraries state)
|
||||
(assoc id {:id id
|
||||
:data local}))))
|
||||
|
||||
(defn pretty-file
|
||||
[file-id state]
|
||||
(if (= file-id (:current-file-id state))
|
||||
"<local>"
|
||||
(str "<" (get-in state [:workspace-libraries file-id :name]) ">")))
|
||||
|
||||
|
||||
;; ---- Create a new component ----
|
||||
|
||||
(defn make-component-shape
|
||||
|
@ -146,7 +129,7 @@
|
|||
name
|
||||
new-shapes
|
||||
updated-shapes))]
|
||||
[group changes])))
|
||||
[group new-shape changes])))
|
||||
|
||||
(defn duplicate-component
|
||||
"Clone the root shape of the component and all children. Generate new
|
||||
|
@ -158,6 +141,60 @@
|
|||
(get component :objects)
|
||||
identity)))
|
||||
|
||||
(defn generate-instantiate-component
|
||||
"Generate changes to create a new instance from a component."
|
||||
[it file-id component-id position page libraries]
|
||||
(let [component (cph/get-component libraries file-id component-id)
|
||||
component-shape (cph/get-shape component component-id)
|
||||
|
||||
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
||||
delta (gpt/subtract position orig-pos)
|
||||
|
||||
objects (:objects page)
|
||||
unames (volatile! (dwc/retrieve-used-names objects))
|
||||
|
||||
frame-id (cph/frame-id-by-position objects (gpt/add orig-pos delta))
|
||||
|
||||
update-new-shape
|
||||
(fn [new-shape original-shape]
|
||||
(let [new-name (dwc/generate-unique-name @unames (:name new-shape))]
|
||||
|
||||
(when (nil? (:parent-id original-shape))
|
||||
(vswap! unames conj new-name))
|
||||
|
||||
(cond-> new-shape
|
||||
true
|
||||
(as-> $
|
||||
(geom/move $ delta)
|
||||
(assoc $ :frame-id frame-id)
|
||||
(assoc $ :parent-id
|
||||
(or (:parent-id $) (:frame-id $)))
|
||||
(dissoc $ :touched))
|
||||
|
||||
(nil? (:shape-ref original-shape))
|
||||
(assoc :shape-ref (:id original-shape))
|
||||
|
||||
(nil? (:parent-id original-shape))
|
||||
(assoc :component-id (:id original-shape)
|
||||
:component-file file-id
|
||||
:component-root? true
|
||||
:name new-name)
|
||||
|
||||
(some? (:parent-id original-shape))
|
||||
(dissoc :component-root?))))
|
||||
|
||||
[new-shape new-shapes _]
|
||||
(cph/clone-object component-shape
|
||||
nil
|
||||
(get component :objects)
|
||||
update-new-shape)
|
||||
|
||||
changes (reduce #(pcb/add-object %1 %2 {:ignore-touched true})
|
||||
(pcb/empty-changes it (:id page))
|
||||
new-shapes)]
|
||||
|
||||
[new-shape changes]))
|
||||
|
||||
(defn generate-detach-instance
|
||||
"Generate changes to remove the links between a shape and all its children
|
||||
with a component."
|
||||
|
@ -193,7 +230,7 @@
|
|||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state))
|
||||
|
||||
(let [file (get-file state file-id)]
|
||||
(let [file (wsh/get-file state file-id)]
|
||||
(loop [pages (vals (get file :pages-index))
|
||||
changes (pcb/empty-changes it)]
|
||||
(if-let [page (first pages)]
|
||||
|
@ -218,7 +255,7 @@
|
|||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state))
|
||||
|
||||
(let [file (get-file state file-id)]
|
||||
(let [file (wsh/get-file state file-id)]
|
||||
(loop [local-components (vals (get file :components))
|
||||
changes (pcb/empty-changes it)]
|
||||
(if-let [local-component (first local-components)]
|
||||
|
@ -305,7 +342,7 @@
|
|||
(defmethod generate-sync-shape :components
|
||||
[_ changes _library-id state container shape]
|
||||
(let [shape-id (:id shape)
|
||||
libraries (get-libraries state)]
|
||||
libraries (wsh/get-libraries state)]
|
||||
(generate-sync-shape-direct changes libraries container shape-id false)))
|
||||
|
||||
(defn- generate-sync-text-shape
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
(get-in state [:workspace-data :components])))
|
||||
|
||||
;; TODO: improve performance of this
|
||||
|
||||
(defn lookup-selected
|
||||
([state]
|
||||
(lookup-selected state nil))
|
||||
|
@ -68,3 +67,24 @@
|
|||
([state page-id filter-fn]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(into [] (filter filter-fn) (vals objects)))))
|
||||
|
||||
(defn get-local-file
|
||||
"Get the data content of the file you are currently working with."
|
||||
[state]
|
||||
(get state :workspace-data))
|
||||
|
||||
(defn get-file
|
||||
"Get the data content of the given file (it may be the current file
|
||||
or one library)."
|
||||
[state file-id]
|
||||
(if (= file-id (:current-file-id state))
|
||||
(get state :workspace-data)
|
||||
(get-in state [:workspace-libraries file-id :data])))
|
||||
|
||||
(defn get-libraries
|
||||
"Retrieve all libraries, including the local file."
|
||||
[state]
|
||||
(let [{:keys [id] :as local} (:workspace-data state)]
|
||||
(-> (:workspace-libraries state)
|
||||
(assoc id {:id id
|
||||
:data local}))))
|
||||
|
|
|
@ -31,34 +31,34 @@
|
|||
{:name "Rect-1"}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id shape1))
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id shape1))
|
||||
|
||||
file (dwlh/get-local-file new-state)]
|
||||
file (wsh/get-local-file new-state)]
|
||||
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name group) "Rect-2"))
|
||||
(t/is (= (:name component) "Rect-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-1"))
|
||||
(t/is (= (:name c-group) "Rect-2"))
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name group) "Rect-2"))
|
||||
(t/is (= (:name component) "Rect-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-1"))
|
||||
(t/is (= (:name c-group) "Rect-2"))
|
||||
|
||||
(thl/is-from-file group file))))]
|
||||
(thl/is-from-file group file))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -88,7 +88,7 @@
|
|||
new-state
|
||||
(:parent-id shape1))
|
||||
|
||||
file (dwlh/get-local-file new-state)]
|
||||
file (wsh/get-local-file new-state)]
|
||||
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name group) "Component-1"))
|
||||
|
@ -109,41 +109,42 @@
|
|||
{:name "Rect-1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect-2"}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1 #--> Component-1
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-2 ---> Rect-2
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect-1
|
||||
; Rect-2
|
||||
;
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1 #--> Component-1
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-2 ---> Rect-2
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect-1
|
||||
; Rect-2
|
||||
;
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
|
||||
[[group shape1 shape2]
|
||||
[c-group c-shape1 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id shape1))
|
||||
[[group shape1 shape2]
|
||||
[c-group c-shape1 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id shape1))
|
||||
|
||||
file (dwlh/get-local-file new-state)]
|
||||
file (wsh/get-local-file new-state)]
|
||||
|
||||
(t/is (= (:name group) "Component-1"))
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name shape2) "Rect-2"))
|
||||
(t/is (= (:name component) "Component-1"))
|
||||
(t/is (= (:name c-group) "Component-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-1"))
|
||||
(t/is (= (:name c-shape2) "Rect-2"))
|
||||
(t/is (= (:name group) "Component-1"))
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name shape2) "Rect-2"))
|
||||
(t/is (= (:name component) "Component-1"))
|
||||
(t/is (= (:name c-group) "Component-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-1"))
|
||||
(t/is (= (:name c-shape2) "Rect-2"))
|
||||
|
||||
(thl/is-from-file group file))))]
|
||||
(thl/is-from-file group file))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -164,39 +165,40 @@
|
|||
(thp/group-shapes :group1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)]))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Group-1 #--> Group-1
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-2 ---> Rect-2
|
||||
;
|
||||
; [Group-1]
|
||||
; Group-1
|
||||
; Rect-1
|
||||
; Rect-2
|
||||
;
|
||||
(let [[[group shape1 shape2]
|
||||
[c-group c-shape1 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(thp/id :group1))
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Group-1 #--> Group-1
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-2 ---> Rect-2
|
||||
;
|
||||
; [Group-1]
|
||||
; Group-1
|
||||
; Rect-1
|
||||
; Rect-2
|
||||
;
|
||||
(let [[[group shape1 shape2]
|
||||
[c-group c-shape1 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(thp/id :group1))
|
||||
|
||||
file (dwlh/get-local-file new-state)]
|
||||
file (wsh/get-local-file new-state)]
|
||||
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name shape2) "Rect-2"))
|
||||
(t/is (= (:name group) "Group-1"))
|
||||
(t/is (= (:name component) "Group-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-1"))
|
||||
(t/is (= (:name c-shape2) "Rect-2"))
|
||||
(t/is (= (:name c-group) "Group-1"))
|
||||
(t/is (= (:name shape1) "Rect-1"))
|
||||
(t/is (= (:name shape2) "Rect-2"))
|
||||
(t/is (= (:name group) "Group-1"))
|
||||
(t/is (= (:name component) "Group-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-1"))
|
||||
(t/is (= (:name c-shape2) "Rect-2"))
|
||||
(t/is (= (:name c-group) "Group-1"))
|
||||
|
||||
(thl/is-from-file group file))))]
|
||||
(thl/is-from-file group file))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -211,29 +213,29 @@
|
|||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Renamed component
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Renamed]
|
||||
; Renamed component
|
||||
; Rect-1
|
||||
(let [libs (dwlh/get-libraries new-state)
|
||||
component (cph/get-component libs
|
||||
(:component-file instance1)
|
||||
(:component-id instance1))]
|
||||
(t/is (= (:name component)
|
||||
"Renamed component")))))]
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Renamed component
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Renamed]
|
||||
; Renamed component
|
||||
; Rect-1
|
||||
(let [libs (wsh/get-libraries new-state)
|
||||
component (cph/get-component libs
|
||||
(:component-file instance1)
|
||||
(:component-id instance1))]
|
||||
(t/is (= (:name component)
|
||||
"Renamed component")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -247,50 +249,50 @@
|
|||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
component-id (:component-id instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [new-component-id (->> (get-in new-state
|
||||
[:workspace-data
|
||||
:components])
|
||||
(keys)
|
||||
(filter #(not= % component-id))
|
||||
(first))
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [new-component-id (->> (get-in new-state
|
||||
[:workspace-data
|
||||
:components])
|
||||
(keys)
|
||||
(filter #(not= % component-id))
|
||||
(first))
|
||||
|
||||
[[instance1 shape1]
|
||||
[c-instance1 c-shape1]
|
||||
component1]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))
|
||||
[[instance1 shape1]
|
||||
[c-instance1 c-shape1]
|
||||
component1]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))
|
||||
|
||||
[[c-component2 c-shape2]
|
||||
component2]
|
||||
(thl/resolve-component
|
||||
new-state
|
||||
new-component-id)]
|
||||
[[c-component2 c-shape2]
|
||||
component2]
|
||||
(thl/resolve-component
|
||||
new-state
|
||||
new-component-id)]
|
||||
|
||||
(t/is (= (:name component2) "Rect-2")))))]
|
||||
(t/is (= (:name component2) "Rect-2")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -304,36 +306,36 @@
|
|||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
file (dwlh/get-local-file state)
|
||||
file (wsh/get-local-file state)
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
component-id (:component-id instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [[instance1 shape1]
|
||||
(thl/resolve-noninstance
|
||||
new-state
|
||||
(:id instance1))
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [[instance1 shape1]
|
||||
(thl/resolve-noninstance
|
||||
new-state
|
||||
(:id instance1))
|
||||
|
||||
libs (dwlh/get-libraries new-state)
|
||||
component (cph/get-component libs
|
||||
(:component-file instance1)
|
||||
(:component-id instance1))]
|
||||
libs (wsh/get-libraries new-state)
|
||||
component (cph/get-component libs
|
||||
(:component-file instance1)
|
||||
(:component-id instance1))]
|
||||
|
||||
(t/is (some? instance1))
|
||||
(t/is (some? shape1))
|
||||
(t/is (nil? component)))))]
|
||||
(t/is (some? instance1))
|
||||
(t/is (some? shape1))
|
||||
(t/is (nil? component)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -348,50 +350,101 @@
|
|||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
file (dwlh/get-local-file state)
|
||||
file (wsh/get-local-file state)
|
||||
component-id (thp/id :component-1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
component-id (:component-id instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-3 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [new-instance-id (-> new-state
|
||||
wsh/lookup-selected
|
||||
first)
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-3 #--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [new-instance-id (-> new-state
|
||||
wsh/lookup-selected
|
||||
first)
|
||||
|
||||
[[instance2 shape2]
|
||||
[c-instance2 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
new-instance-id)]
|
||||
[[instance2 shape2]
|
||||
[c-instance2 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
new-instance-id)]
|
||||
|
||||
(t/is (not= (:id instance1) (:id instance2)))
|
||||
(t/is (= (:id component) component-id))
|
||||
(t/is (= (:name instance2) "Rect-3"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name c-instance2) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1")))))]
|
||||
(t/is (not= (:id instance1) (:id instance2)))
|
||||
(t/is (= (:id component) component-id))
|
||||
(t/is (= (:name instance2) "Rect-3"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name c-instance2) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1"))
|
||||
(t/is (= (:component-file instance2)
|
||||
thp/current-file-id)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwl/instantiate-component (:id file)
|
||||
(:component-id instance1)
|
||||
component-id
|
||||
(gpt/point 100 100))
|
||||
:the/end))))
|
||||
|
||||
(t/deftest test-instantiate-component-from-lib
|
||||
(t/async
|
||||
done
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/move-to-library :lib1 "Library 1")
|
||||
(thp/sample-page))
|
||||
|
||||
library-id (thp/id :lib1)
|
||||
component-id (thp/id :component-1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> <Library 1> Rect-2
|
||||
; Rect-1 ---> <Library 1> Rect-1
|
||||
;
|
||||
(let [new-instance-id (-> new-state
|
||||
wsh/lookup-selected
|
||||
first)
|
||||
|
||||
[[instance2 shape2]
|
||||
[c-instance2 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
new-instance-id)]
|
||||
|
||||
(t/is (= (:id component) component-id))
|
||||
(t/is (= (:name instance2) "Rect-2"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name c-instance2) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1"))
|
||||
(t/is (= (:component-file instance2) library-id)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwl/instantiate-component library-id
|
||||
component-id
|
||||
(gpt/point 100 100))
|
||||
:the/end))))
|
||||
|
||||
|
@ -402,32 +455,32 @@
|
|||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
component-id (:component-id instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [[instance1 shape1]
|
||||
(thl/resolve-noninstance
|
||||
new-state
|
||||
(:id instance1))]
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
(let [[instance1 shape1]
|
||||
(thl/resolve-noninstance
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (some? instance1))
|
||||
(t/is (some? shape1)))))]
|
||||
(t/is (some? instance1))
|
||||
(t/is (some? shape1)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -442,47 +495,47 @@
|
|||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"}))
|
||||
|
||||
file (dwlh/get-local-file state)
|
||||
file (wsh/get-local-file state)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
component-id (:component-id instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Group-1 #--> Group-1
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Group-1]
|
||||
; Group-1
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
(let [page (thp/current-page new-state)
|
||||
shape1 (thp/get-shape new-state :shape1)
|
||||
parent1 (cph/get-shape page (:parent-id shape1))
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Group-1 #--> Group-1
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Group-1]
|
||||
; Group-1
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
(let [page (thp/current-page new-state)
|
||||
shape1 (thp/get-shape new-state :shape1)
|
||||
parent1 (cph/get-shape page (:parent-id shape1))
|
||||
|
||||
[[group shape1 shape2]
|
||||
[c-group c-shape1 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id parent1))]
|
||||
[[group shape1 shape2]
|
||||
[c-group c-shape1 c-shape2]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id parent1))]
|
||||
|
||||
(t/is (= (:name group) "Group-1"))
|
||||
(t/is (= (:name shape1) "Rect-2"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name component) "Group-1"))
|
||||
(t/is (= (:name c-group) "Group-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1")))))]
|
||||
(t/is (= (:name group) "Group-1"))
|
||||
(t/is (= (:name shape1) "Rect-2"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name component) "Group-1"))
|
||||
(t/is (= (:name c-group) "Group-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -499,59 +552,59 @@
|
|||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/group-shapes :group1
|
||||
[(thp/id :instance1)])
|
||||
(thp/make-component :instance2
|
||||
(thp/make-component :instance2 :component-2
|
||||
[(thp/id :group1)]))
|
||||
|
||||
file (dwlh/get-local-file state)
|
||||
file (wsh/get-local-file state)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
instance2 (thp/get-shape state :instance2)
|
||||
component-id (:component-id instance2)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-3 #--> Rect-2
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
(let [new-instance-id (-> new-state
|
||||
wsh/lookup-selected
|
||||
first)
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect-2 #--> Rect-2
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
; Rect-3 #--> Rect-2
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
; [Rect-1]
|
||||
; Rect-2
|
||||
; Rect-1
|
||||
;
|
||||
; [Rect-2]
|
||||
; Rect-2
|
||||
; Rect-2 @--> Rect-2
|
||||
; Rect-1 ---> Rect-1
|
||||
;
|
||||
(let [new-instance-id (-> new-state
|
||||
wsh/lookup-selected
|
||||
first)
|
||||
|
||||
[[instance3 shape3 shape4]
|
||||
[c-instance3 c-shape3 c-shape4]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
new-instance-id)]
|
||||
[[instance3 shape3 shape4]
|
||||
[c-instance3 c-shape3 c-shape4]
|
||||
component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
new-instance-id)]
|
||||
|
||||
(t/is (not= (:id instance1) (:id instance3)))
|
||||
(t/is (= (:id component) component-id))
|
||||
(t/is (= (:name instance3) "Rect-3"))
|
||||
(t/is (= (:name shape3) "Rect-2"))
|
||||
(t/is (= (:name shape4) "Rect-1"))
|
||||
(t/is (= (:name c-instance3) "Rect-2"))
|
||||
(t/is (= (:name c-shape3) "Rect-2"))
|
||||
(t/is (= (:name c-shape4) "Rect-1")))))]
|
||||
(t/is (not= (:id instance1) (:id instance3)))
|
||||
(t/is (= (:id component) component-id))
|
||||
(t/is (= (:name instance3) "Rect-3"))
|
||||
(t/is (= (:name shape3) "Rect-2"))
|
||||
(t/is (= (:name shape4) "Rect-1"))
|
||||
(t/is (= (:name c-instance3) "Rect-2"))
|
||||
(t/is (= (:name c-shape3) "Rect-2"))
|
||||
(t/is (= (:name c-shape4) "Rect-1")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
|
@ -560,3 +613,63 @@
|
|||
(gpt/point 100 100))
|
||||
:the/end))))
|
||||
|
||||
(t/deftest test-instantiate-nested-component-from-lib
|
||||
(t/async
|
||||
done
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/move-to-library :lib1 "Library 1")
|
||||
(thp/sample-page)
|
||||
(thp/instantiate-component :instance2
|
||||
(thp/id :component-1)
|
||||
(thp/id :lib1)))
|
||||
|
||||
library-id (thp/id :lib1)
|
||||
component-id (thp/id :component-1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Group-1 #--> Group-1
|
||||
; Rect-2 @--> <Library 1> Rect-2
|
||||
; Rect-1 ---> <Library 1> Rect-1
|
||||
;
|
||||
; [Group-1]
|
||||
; Group-1
|
||||
; Rect-2 @--> <Library 1> Rect-2
|
||||
; Rect-1 ---> <Library 1> Rect-1
|
||||
;
|
||||
(let [instance2 (thp/get-shape new-state :instance2)
|
||||
|
||||
[[group1 shape1 shape2] [c-group1 c-shape1 c-shape2] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:parent-id instance2))]
|
||||
|
||||
(t/is (= (:name group1) "Group-1"))
|
||||
(t/is (= (:name shape1) "Rect-2"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name c-group1) "Group-1"))
|
||||
(t/is (= (:name c-shape1) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1"))
|
||||
(t/is (= (:component-file group1) thp/current-file-id))
|
||||
(t/is (= (:component-file shape1) library-id))
|
||||
(t/is (= (:component-file shape2) nil))
|
||||
(t/is (= (:component-file c-group1) nil))
|
||||
(t/is (= (:component-file c-shape1) library-id))
|
||||
(t/is (= (:component-file c-shape2) nil)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dw/select-shape (thp/id :instance2))
|
||||
dwg/group-selected
|
||||
(dwl/add-component)
|
||||
:the/end))))
|
||||
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
(ns app.components-sync-test
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.main.data.workspace.changes :as dwc]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||
[app.test-helpers.events :as the]
|
||||
[app.test-helpers.libraries :as thl]
|
||||
[app.test-helpers.pages :as thp]
|
||||
[beicon.core :as rx]
|
||||
[cljs.pprint :refer [pprint]]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[linked.core :as lks]
|
||||
[potok.core :as ptk]))
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.test-helpers.events :as the]
|
||||
[app.test-helpers.libraries :as thl]
|
||||
[app.test-helpers.pages :as thp]
|
||||
[beicon.core :as rx]
|
||||
[cljs.pprint :refer [pprint]]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[linked.core :as lks]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(t/use-fixtures :each
|
||||
{:before thp/reset-idmap!})
|
||||
|
@ -27,37 +31,220 @@
|
|||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
|
||||
update-fn (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:fill-opacity 0.5}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1* ---> Rect 1
|
||||
; #{:fill-group}
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
shape1 (thp/get-shape new-state :shape1)
|
||||
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (= (:touched instance1) nil))
|
||||
(t/is (= (:touched shape1) #{:fill-group}))
|
||||
(t/is (= (:fill-color shape1) clr/test))
|
||||
(t/is (= (:fill-opacity shape1) 0.5))
|
||||
(t/is (= (:touched c-group) nil))
|
||||
(t/is (= (:touched c-shape1) nil))
|
||||
(t/is (= (:fill-color c-shape1) clr/white))
|
||||
(t/is (= (:fill-opacity c-shape1) 1)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dch/update-shapes [(:id shape1)] update-fn)
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-touched-children-add
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/sample-shape :shape2 :circle
|
||||
{:name "Circle 1"}))
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
shape2 (thp/get-shape state :shape2)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1* #--> Rect 1-1
|
||||
; #{:shapes-group}
|
||||
; Circle 1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1 shape2] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main-allow-dangling
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (= (:touched group) #{:shapes-group}))
|
||||
(t/is (nil? (:touched shape1)))
|
||||
(t/is (= (:name shape1) "Circle 1"))
|
||||
(t/is (nil? (:shape-ref shape1)))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (= (:name shape2) "Rect 1"))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape1))))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dw/relocate-shapes #{(:id shape2)} (:id instance1) 0)
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-touched-children-delete
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect 2"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)]))
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1* #--> Component-1
|
||||
; #{:shapes-group}
|
||||
; Rect 2 ---> Rect 2
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect 1
|
||||
; Rect 2
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape2] [c-group c-shape2] component]
|
||||
(thl/resolve-instance-and-main-allow-dangling
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (= (:touched group) #{:shapes-group}))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (= (:name shape2) "Rect 2"))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape2))))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwc/delete-shapes #{(:id shape1)})
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-touched-children-move
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect 2"})
|
||||
(thp/sample-shape :shape3 :rect
|
||||
{:name "Rect 3"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)
|
||||
(thp/id :shape3)]))
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
update-shape (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:fill-opacity 0.5}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1* #--> Component-1
|
||||
; #{:shapes-group}
|
||||
; Rect 2 ---> Rect 2
|
||||
; Rect 1 ---> Rect 1
|
||||
; Rect 3 ---> Rect 3
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect 1
|
||||
; Rect 2
|
||||
; Rect 3
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))
|
||||
[[group shape1 shape2 shape3]
|
||||
[c-group c-shape1 c-shape2 c-shape3] component]
|
||||
(thl/resolve-instance-and-main-allow-dangling
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
file (dwlh/get-local-file new-state)]
|
||||
|
||||
(t/is (= (:fill-color shape1) clr/test))
|
||||
(t/is (= (:fill-opacity shape1) 0.5))
|
||||
(t/is (= (:touched shape1) #{:fill-group}))
|
||||
(t/is (= (:fill-color c-shape1) clr/white))
|
||||
(t/is (= (:fill-opacity c-shape1) 1))
|
||||
(t/is (= (:touched c-shape1) nil)))))]
|
||||
(t/is (= (:touched group) #{:shapes-group}))
|
||||
(t/is (nil? (:touched shape1)))
|
||||
(t/is (some? (:shape-ref shape1)))
|
||||
(t/is (= (:name shape1) "Rect 2"))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (= (:name shape2) "Rect 1"))
|
||||
(t/is (nil? (:touched shape3)))
|
||||
(t/is (some? (:shape-ref shape3)))
|
||||
(t/is (= (:name shape3) "Rect 3"))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape1)))
|
||||
(t/is (= (:name c-shape1) "Rect 1"))
|
||||
(t/is (nil? (:touched c-shape2)))
|
||||
(t/is (= (:name c-shape2) "Rect 2"))
|
||||
(t/is (nil? (:touched c-shape3)))
|
||||
(t/is (= (:name c-shape3) "Rect 3")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwc/update-shapes [(:id shape1)] update-shape)
|
||||
(dw/relocate-shapes #{(:id shape1)} (:id instance1) 2)
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-reset-changes
|
||||
|
@ -69,37 +256,561 @@
|
|||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
update-shape (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:fill-opacity 0.5}))
|
||||
update-fn (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:fill-opacity 0.5}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [shape1 (thp/get-shape new-state :shape1)
|
||||
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
file (dwlh/get-local-file new-state)]
|
||||
|
||||
(t/is (= (:fill-color shape1) clr/white))
|
||||
(t/is (= (:fill-opacity shape1) 1))
|
||||
(t/is (= (:touched shape1) nil))
|
||||
(t/is (= (:fill-color c-shape1) clr/white))
|
||||
(t/is (= (:fill-opacity c-shape1) 1))
|
||||
(t/is (= (:touched c-shape1) nil)))))]
|
||||
(t/is (= (:fill-color shape1) clr/white))
|
||||
(t/is (= (:fill-opacity shape1) 1))
|
||||
(t/is (= (:touched shape1) nil))
|
||||
(t/is (= (:fill-color c-shape1) clr/white))
|
||||
(t/is (= (:fill-opacity c-shape1) 1))
|
||||
(t/is (= (:touched c-shape1) nil)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwc/update-shapes [(:id shape1)] update-shape)
|
||||
(dch/update-shapes [(:id shape1)] update-fn)
|
||||
(dwl/reset-component (:id instance1))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-reset-children-add
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/sample-shape :shape2 :circle
|
||||
{:name "Circle 1"}))
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
shape2 (thp/get-shape state :shape2)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (nil? (:touched instance1)))
|
||||
(t/is (= (:name shape1) "Rect 1"))
|
||||
(t/is (some? (:shape-ref shape1))))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dw/relocate-shapes #{(:id shape2)} (:id instance1) 0)
|
||||
(dwl/reset-component (:id instance1))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-reset-children-delete
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect 2"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)]))
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (nil? (:touched instance1)))
|
||||
(t/is (= (:name shape1) "Rect 1"))
|
||||
(t/is (some? (:shape-ref shape1))))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwc/delete-shapes #{(:id shape1)})
|
||||
(dwl/reset-component (:id instance1))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-reset-children-move
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect 2"})
|
||||
(thp/sample-shape :shape3 :rect
|
||||
{:name "Rect 3"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)
|
||||
(thp/id :shape3)]))
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1 #--> Component-1
|
||||
; Rect 1 ---> Rect 1
|
||||
; Rect 2 ---> Rect 2
|
||||
; Rect 3 ---> Rect 3
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect 1
|
||||
; Rect 2
|
||||
; Rect 3
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1 shape2 shape3] [c-group c-shape1 c-shape2 c-shape3] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (nil? (:touched group)))
|
||||
(t/is (nil? (:touched shape1)))
|
||||
(t/is (some? (:shape-ref shape1)))
|
||||
(t/is (= (:name shape1) "Rect 1"))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (= (:name shape2) "Rect 2"))
|
||||
(t/is (nil? (:touched shape3)))
|
||||
(t/is (some? (:shape-ref shape3)))
|
||||
(t/is (= (:name shape3) "Rect 3"))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape1)))
|
||||
(t/is (= (:name c-shape1) "Rect 1"))
|
||||
(t/is (nil? (:touched c-shape2)))
|
||||
(t/is (= (:name c-shape2) "Rect 2"))
|
||||
(t/is (nil? (:touched c-shape3)))
|
||||
(t/is (= (:name c-shape3) "Rect 3")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dw/relocate-shapes #{(:id shape1)} (:id instance1) 2)
|
||||
(dwl/reset-component (:id instance1))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-update-component
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
update-fn (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:fill-opacity 0.5}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [[[group shape1] [c-group c-shape1] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (= (:fill-color shape1) clr/test))
|
||||
(t/is (= (:fill-opacity shape1) 0.5))
|
||||
(t/is (= (:touched shape1) nil))
|
||||
(t/is (= (:fill-color c-shape1) clr/test))
|
||||
(t/is (= (:fill-opacity c-shape1) 0.5))
|
||||
(t/is (= (:touched c-shape1) nil)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dch/update-shapes [(:id shape1)] update-fn)
|
||||
(dwl/update-component (:id instance1))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-update-component-and-sync
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/instantiate-component :instance2
|
||||
(thp/id :component-1)))
|
||||
|
||||
file (wsh/get-local-file state)
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
update-fn (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:fill-opacity 0.5}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
; Rect 1-2 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance2 (thp/get-shape state :instance2)
|
||||
|
||||
[[group shape2] [c-group c-shape2] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance2))]
|
||||
|
||||
(t/is (= (:fill-color shape2) clr/test))
|
||||
(t/is (= (:fill-opacity shape2) 0.5))
|
||||
(t/is (= (:touched shape2) nil))
|
||||
(t/is (= (:fill-color c-shape2) clr/test))
|
||||
(t/is (= (:fill-opacity c-shape2) 0.5))
|
||||
(t/is (= (:touched c-shape2) nil)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dch/update-shapes [(:id shape1)] update-fn)
|
||||
(dwl/update-component-sync (:id instance1) (:id file))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-update-preserve-touched
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/instantiate-component :instance2
|
||||
(thp/id :component-1)))
|
||||
|
||||
file (wsh/get-local-file state)
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
instance2 (thp/get-shape state :instance2)
|
||||
|
||||
shape2 (cph/get-shape (wsh/lookup-page state)
|
||||
(first (:shapes instance2)))
|
||||
|
||||
update-fn1 (fn [shape]
|
||||
(merge shape {:fill-color clr/test
|
||||
:stroke-width 0.5}))
|
||||
|
||||
update-fn2 (fn [shape]
|
||||
(merge shape {:stroke-width 0.2}))
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Rect 1 ---> Rect 1
|
||||
; Rect 1-2 #--> Rect 1-1
|
||||
; Rect 1* ---> Rect 1
|
||||
; #{:stroke-group}
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance2 (thp/get-shape state :instance2)
|
||||
|
||||
[[group shape2] [c-group c-shape2] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance2))]
|
||||
|
||||
(t/is (= (:fill-color shape2) clr/test))
|
||||
(t/is (= (:stroke-width shape2) 0.2))
|
||||
(t/is (= (:touched shape2 #{:stroke-group})))
|
||||
(t/is (= (:fill-color c-shape2) clr/test))
|
||||
(t/is (= (:stroke-width c-shape2) 0.5))
|
||||
(t/is (= (:touched c-shape2) nil)))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dch/update-shapes [(:id shape1)] update-fn1)
|
||||
(dch/update-shapes [(:id shape2)] update-fn2)
|
||||
(dwl/update-component-sync (:id instance1) (:id file))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-update-children-add
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"
|
||||
:fill-color clr/white
|
||||
:fill-opacity 1})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)])
|
||||
(thp/sample-shape :shape2 :circle
|
||||
{:name "Circle 1"}))
|
||||
|
||||
file (wsh/get-local-file state)
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
shape2 (thp/get-shape state :shape2)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Rect 1-1 #--> Rect 1-1
|
||||
; Circle 1 ---> Circle 1
|
||||
; Rect 1 ---> Rect 1
|
||||
;
|
||||
; [Rect 1]
|
||||
; Rect 1-1
|
||||
; Circle 1
|
||||
; Rect 1
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1 shape2] [c-group c-shape1 c-shape2] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (nil? (:touched group)))
|
||||
(t/is (nil? (:touched shape1)))
|
||||
(t/is (= (:name shape1) "Circle 1"))
|
||||
(t/is (some? (:shape-ref shape1)))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (= (:name shape2) "Rect 1"))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape1)))
|
||||
(t/is (= (:name c-shape1) "Circle 1"))
|
||||
(t/is (nil? (:touched c-shape2)))
|
||||
(t/is (= (:name c-shape2) "Rect 1")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dw/relocate-shapes #{(:id shape2)} (:id instance1) 0)
|
||||
(dwl/update-component-sync (:id instance1) (:id file))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-update-children-delete
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect 2"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)]))
|
||||
|
||||
file (wsh/get-local-file state)
|
||||
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1 #--> Component-1
|
||||
; Rect 2 ---> Rect 2
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect 2
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape2] [c-group c-shape2] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (nil? (:touched group)))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (= (:name shape2) "Rect 2"))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape2)))
|
||||
(t/is (= (:name c-shape2) "Rect 2")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dwc/delete-shapes #{(:id shape1)})
|
||||
(dwl/update-component-sync (:id instance1) (:id file))
|
||||
:the/end)))))
|
||||
|
||||
(t/deftest test-update-children-move
|
||||
(t/async done
|
||||
(try
|
||||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
(thp/sample-shape :shape2 :rect
|
||||
{:name "Rect 2"})
|
||||
(thp/sample-shape :shape3 :rect
|
||||
{:name "Rect 3"})
|
||||
(thp/make-component :instance1 :component-1
|
||||
[(thp/id :shape1)
|
||||
(thp/id :shape2)
|
||||
(thp/id :shape3)]))
|
||||
|
||||
file (wsh/get-local-file state)
|
||||
|
||||
shape1 (thp/get-shape state :shape1)
|
||||
instance1 (thp/get-shape state :instance1)
|
||||
|
||||
store (the/prepare-store state done
|
||||
(fn [new-state]
|
||||
; Expected shape tree:
|
||||
;
|
||||
; [Page]
|
||||
; Root Frame
|
||||
; Component-1 #--> Component-1
|
||||
; Rect 2 ---> Rect 2
|
||||
; Rect 1 ---> Rect 1
|
||||
; Rect 3 ---> Rect 3
|
||||
;
|
||||
; [Component-1]
|
||||
; Component-1
|
||||
; Rect 2
|
||||
; Rect 1
|
||||
; Rect 3
|
||||
;
|
||||
(let [instance1 (thp/get-shape new-state :instance1)
|
||||
|
||||
[[group shape1 shape2 shape3] [c-group c-shape1 c-shape2 c-shape3] component]
|
||||
(thl/resolve-instance-and-main
|
||||
new-state
|
||||
(:id instance1))]
|
||||
|
||||
(t/is (nil? (:touched group)))
|
||||
(t/is (nil? (:touched shape1)))
|
||||
(t/is (some? (:shape-ref shape1)))
|
||||
(t/is (= (:name shape1) "Rect 2"))
|
||||
(t/is (nil? (:touched shape2)))
|
||||
(t/is (some? (:shape-ref shape2)))
|
||||
(t/is (= (:name shape2) "Rect 1"))
|
||||
(t/is (nil? (:touched shape3)))
|
||||
(t/is (some? (:shape-ref shape3)))
|
||||
(t/is (= (:name shape3) "Rect 3"))
|
||||
(t/is (nil? (:touched c-group)))
|
||||
(t/is (nil? (:touched c-shape1)))
|
||||
(t/is (= (:name c-shape1) "Rect 2"))
|
||||
(t/is (nil? (:touched c-shape2)))
|
||||
(t/is (= (:name c-shape2) "Rect 1"))
|
||||
(t/is (nil? (:touched c-shape3)))
|
||||
(t/is (= (:name c-shape3) "Rect 3")))))]
|
||||
|
||||
(ptk/emit!
|
||||
store
|
||||
(dw/relocate-shapes #{(:id shape1)} (:id instance1) 2)
|
||||
(dwl/update-component-sync (:id instance1) (:id file))
|
||||
:the/end)))))
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.test-helpers.pages :as thp]))
|
||||
|
||||
;; ---- Helpers to manage libraries and synchronization
|
||||
|
@ -85,7 +86,7 @@
|
|||
(let [page (thp/current-page state)
|
||||
root-inst (cph/get-shape page root-inst-id)
|
||||
|
||||
libs (dwlh/get-libraries state)
|
||||
libs (wsh/get-libraries state)
|
||||
component (cph/get-component libs (:component-id root-inst))
|
||||
|
||||
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
|
||||
|
@ -115,11 +116,44 @@
|
|||
|
||||
[shapes-inst shapes-main component]))
|
||||
|
||||
(defn resolve-instance-and-main-allow-dangling
|
||||
"Get the shape with the given id and all its children, and also
|
||||
the main component and all its shapes. Allows shapes with the
|
||||
corresponding component shape missing."
|
||||
[state root-inst-id]
|
||||
(let [page (thp/current-page state)
|
||||
root-inst (cph/get-shape page root-inst-id)
|
||||
|
||||
libs (wsh/get-libraries state)
|
||||
component (cph/get-component libs (:component-id root-inst))
|
||||
|
||||
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
|
||||
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
|
||||
|
||||
unique-refs (into #{} (map :shape-ref) shapes-inst)
|
||||
|
||||
main-exists? (fn [shape]
|
||||
(let [component-shape
|
||||
(cph/get-component-shape (:objects page) shape)
|
||||
|
||||
component
|
||||
(cph/get-component libs (:component-id component-shape))
|
||||
|
||||
main-shape
|
||||
(cph/get-shape component (:shape-ref shape))]
|
||||
|
||||
(t/is (some? main-shape))))]
|
||||
|
||||
;; Validate that the instance tree is well constructed
|
||||
(is-instance-root (first shapes-inst))
|
||||
|
||||
[shapes-inst shapes-main component]))
|
||||
|
||||
(defn resolve-component
|
||||
"Get the component with the given id and all its shapes."
|
||||
[state component-id]
|
||||
(let [page (thp/current-page state)
|
||||
libs (dwlh/get-libraries state)
|
||||
libs (wsh/get-libraries state)
|
||||
component (cph/get-component libs component-id)
|
||||
root-main (cph/get-component-root component)
|
||||
shapes-main (cph/get-children-with-self (:objects component) (:id root-main))]
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
[app.common.pages :as cp]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.layout :as layout]
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]))
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]))
|
||||
|
||||
;; ---- Helpers to manage pages and objects
|
||||
|
||||
|
@ -96,19 +96,53 @@
|
|||
cp/process-changes (:redo-changes changes)))))))
|
||||
|
||||
(defn make-component
|
||||
[state label ids]
|
||||
[state instance-label component-label shape-ids]
|
||||
(let [page (current-page state)
|
||||
objects (wsh/lookup-page-objects state (:id page))
|
||||
shapes (dwg/shapes-for-grouping objects ids)
|
||||
shapes (dwg/shapes-for-grouping objects shape-ids)
|
||||
|
||||
[group changes]
|
||||
[group component-root changes]
|
||||
(dwlh/generate-add-component nil
|
||||
shapes
|
||||
(:objects page)
|
||||
(:id page)
|
||||
current-file-id)]
|
||||
|
||||
(swap! idmap assoc label (:id group))
|
||||
(swap! idmap assoc instance-label (:id group)
|
||||
component-label (:id component-root))
|
||||
(update state :workspace-data
|
||||
cp/process-changes (:redo-changes changes))))
|
||||
|
||||
(defn instantiate-component
|
||||
([state label component-id]
|
||||
(instantiate-component state label component-id current-file-id))
|
||||
([state label component-id file-id]
|
||||
(let [page (current-page state)
|
||||
libraries (wsh/get-libraries state)
|
||||
|
||||
[new-shape changes]
|
||||
(dwlh/generate-instantiate-component nil
|
||||
file-id
|
||||
component-id
|
||||
(gpt/point 100 100)
|
||||
page
|
||||
libraries)]
|
||||
|
||||
(swap! idmap assoc label (:id new-shape))
|
||||
(update state :workspace-data
|
||||
cp/process-changes (:redo-changes changes)))))
|
||||
|
||||
(defn move-to-library
|
||||
[state label name]
|
||||
(let [library-id (uuid/next)
|
||||
data (get state :workspace-data)]
|
||||
(swap! idmap assoc label library-id)
|
||||
(-> state
|
||||
(update :workspace-libraries
|
||||
assoc library-id {:id library-id
|
||||
:name name
|
||||
:data {:id library-id
|
||||
:components (:components data)}})
|
||||
(update :workspace-data
|
||||
assoc :components {} :pages [] :pages-index {}))))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue