From 54e0071c9c9517468cb819da7d9d76be69e1ffb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 23 Jun 2022 17:43:43 +0200 Subject: [PATCH] :tada: Scaffolding to write unit tests of common types --- backend/src/app/rpc/mutations/files.clj | 3 +- backend/src/app/rpc/queries/files.clj | 2 +- backend/src/app/tasks/file_gc.clj | 1 - common/src/app/common/file_builder.cljc | 18 +- common/src/app/common/pages.cljc | 12 +- common/src/app/common/pages/changes.cljc | 16 +- .../src/app/common/pages/changes_builder.cljc | 3 +- common/src/app/common/pages/migrations.cljc | 8 +- .../src/app/common/types/components_list.cljc | 28 +++ common/src/app/common/types/container.cljc | 89 ++++++++-- common/src/app/common/types/file.cljc | 167 +++++++++++++++++- common/src/app/common/types/pages_list.cljc | 8 + common/src/app/common/types/shape.cljc | 158 +++++++++++++++++ common/src/app/common/types/shape_tree.cljc | 6 +- common/test/app/common/geom_shapes_test.cljc | 4 +- common/test/app/common/pages_test.cljc | 15 +- .../test/app/common/test_helpers/files.cljc | 110 ++++++++++++ common/test/app/common/types/file_test.cljc | 79 +++++++++ .../types/shape/spec_interactions_test.cljc | 26 +-- frontend/src/app/main/data/workspace.cljs | 7 +- .../src/app/main/data/workspace/common.cljs | 9 - .../src/app/main/data/workspace/drawing.cljs | 4 +- .../app/main/data/workspace/drawing/box.cljs | 4 +- .../main/data/workspace/drawing/common.cljs | 5 +- .../src/app/main/data/workspace/groups.cljs | 6 +- .../data/workspace/libraries_helpers.cljs | 42 +---- .../app/main/data/workspace/svg_upload.cljs | 8 +- .../main/ui/workspace/viewport/selection.cljs | 6 +- frontend/src/app/worker/import.cljs | 4 +- frontend/src/debug.cljs | 76 +------- frontend/test/app/components_basic_test.cljs | 4 +- frontend/test/app/components_sync_test.cljs | 4 +- frontend/test/app/test_helpers/libraries.cljs | 14 +- frontend/test/app/test_helpers/pages.cljs | 5 +- frontend/test/app/util/snap_data_test.cljs | 1 - 35 files changed, 724 insertions(+), 228 deletions(-) create mode 100644 common/src/app/common/types/components_list.cljc create mode 100644 common/test/app/common/test_helpers/files.cljc create mode 100644 common/test/app/common/types/file_test.cljc diff --git a/backend/src/app/rpc/mutations/files.clj b/backend/src/app/rpc/mutations/files.clj index dba09a40a..b3ee8cb3b 100644 --- a/backend/src/app/rpc/mutations/files.clj +++ b/backend/src/app/rpc/mutations/files.clj @@ -11,6 +11,7 @@ [app.common.pages :as cp] [app.common.pages.migrations :as pmg] [app.common.spec :as us] + [app.common.types.file :as ctf] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -69,7 +70,7 @@ :or {is-shared false revn 0} :as params}] (let [id (or id (:id data) (uuid/next)) - data (or data (cp/make-file-data id)) + data (or data (ctf/make-file-data id)) file (db/insert! conn :file (d/without-nils {:id id diff --git a/backend/src/app/rpc/queries/files.clj b/backend/src/app/rpc/queries/files.clj index 7adc19fbd..0fd9431e0 100644 --- a/backend/src/app/rpc/queries/files.clj +++ b/backend/src/app/rpc/queries/files.clj @@ -12,8 +12,8 @@ [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] [app.common.pages.migrations :as pmg] - [app.common.types.shape-tree :as ctt] [app.common.spec :as us] + [app.common.types.shape-tree :as ctt] [app.db :as db] [app.db.sql :as sql] [app.rpc.helpers :as rpch] diff --git a/backend/src/app/tasks/file_gc.clj b/backend/src/app/tasks/file_gc.clj index 1f9d5042e..ec8b0a2e8 100644 --- a/backend/src/app/tasks/file_gc.clj +++ b/backend/src/app/tasks/file_gc.clj @@ -12,7 +12,6 @@ (:require [app.common.data :as d] [app.common.logging :as l] - [app.common.pages.helpers :as cph] [app.common.pages.migrations :as pmg] [app.common.types.shape-tree :as ctt] [app.db :as db] diff --git a/common/src/app/common/file_builder.cljc b/common/src/app/common/file_builder.cljc index d744e41a9..a924186b3 100644 --- a/common/src/app/common/file_builder.cljc +++ b/common/src/app/common/file_builder.cljc @@ -12,10 +12,10 @@ [app.common.geom.shapes :as gsh] [app.common.pages.changes :as ch] [app.common.pages.changes-spec :as pcs] - [app.common.pages.init :as init] - [app.common.types.page :as ctp] [app.common.spec :as us] + [app.common.types.file :as ctf] [app.common.types.page :as ctp] + [app.common.types.shape :as cts] [app.common.uuid :as uuid] [cuerdas.core :as str])) @@ -169,7 +169,7 @@ ([id name] {:id id :name name - :data (-> init/empty-file-data + :data (-> ctf/empty-file-data (assoc :id id)) ;; We keep the changes so we can send them to the backend @@ -209,7 +209,7 @@ (defn add-artboard [file data] (assert (nil? (:current-component-id file))) - (let [obj (-> (init/make-minimal-shape :frame) + (let [obj (-> (cts/make-minimal-shape :frame) (merge data) (check-name file :frame) (setup-selrect) @@ -233,9 +233,9 @@ (defn add-group [file data] (let [frame-id (:current-frame-id file) - selrect init/empty-selrect + selrect cts/empty-selrect name (:name data) - obj (-> (init/make-minimal-group frame-id selrect name) + obj (-> (cts/make-minimal-group frame-id selrect name) (merge data) (check-name file :group) (d/without-nils))] @@ -347,7 +347,7 @@ (update :parent-stack pop)))) (defn create-shape [file type data] - (let [obj (-> (init/make-minimal-shape type) + (let [obj (-> (cts/make-minimal-shape type) (merge data) (check-name file :type) (setup-selrect) @@ -515,10 +515,10 @@ (defn start-component [file data] - (let [selrect init/empty-selrect + (let [selrect cts/empty-selrect name (:name data) path (:path data) - obj (-> (init/make-minimal-group nil selrect name) + obj (-> (cts/make-minimal-group nil selrect name) (merge data) (check-name file :group) (d/without-nils))] diff --git a/common/src/app/common/pages.cljc b/common/src/app/common/pages.cljc index e500d372d..b4c43458c 100644 --- a/common/src/app/common/pages.cljc +++ b/common/src/app/common/pages.cljc @@ -12,7 +12,7 @@ [app.common.pages.common :as common] [app.common.pages.focus :as focus] [app.common.pages.indices :as indices] - [app.common.pages.init :as init])) + [app.common.types.file :as ctf])) ;; Common (dm/export common/root) @@ -36,11 +36,5 @@ (dm/export changes/process-changes) ;; Initialization -(dm/export init/default-frame-attrs) -(dm/export init/default-shape-attrs) -(dm/export init/make-file-data) -(dm/export init/make-minimal-shape) -(dm/export init/make-minimal-group) -(dm/export init/empty-file-data) -(dm/export init/setup-shape) -(dm/export init/setup-rect-selrect) +(dm/export ctf/make-file-data) +(dm/export ctf/empty-file-data) diff --git a/common/src/app/common/pages/changes.cljc b/common/src/app/common/pages/changes.cljc index 2d912f7b0..139d37e65 100644 --- a/common/src/app/common/pages/changes.cljc +++ b/common/src/app/common/pages/changes.cljc @@ -14,9 +14,9 @@ [app.common.math :as mth] [app.common.pages.common :refer [component-sync-attrs]] [app.common.pages.helpers :as cph] - [app.common.pages.init :as init] [app.common.spec :as us] [app.common.pages.changes-spec :as pcs] + [app.common.types.components-list :as ctkl] [app.common.types.page :as ctp] [app.common.types.pages-list :as ctpl] [app.common.types.shape :as cts] @@ -346,13 +346,13 @@ (defmethod process-change :add-component [data {:keys [id name path main-instance-id main-instance-page shapes]}] - (assoc-in data [:components id] - {:id id - :name name - :path path - :main-instance-id main-instance-id - :main-instance-page main-instance-page - :objects (d/index-by :id shapes)})) + (ctkl/add-component data + id + name + path + main-instance-id + main-instance-page + shapes)) (defmethod process-change :mod-component [data {:keys [id name path objects]}] diff --git a/common/src/app/common/pages/changes_builder.cljc b/common/src/app/common/pages/changes_builder.cljc index bdf4a1a96..50891acc1 100644 --- a/common/src/app/common/pages/changes_builder.cljc +++ b/common/src/app/common/pages/changes_builder.cljc @@ -16,6 +16,7 @@ [app.common.math :as mth] [app.common.pages :as cp] [app.common.pages.helpers :as cph] + [app.common.types.file :as ctf] [app.common.uuid :as uuid])) ;; Auxiliary functions to help create a set of changes (undo + redo) @@ -49,7 +50,7 @@ (defn with-objects [changes objects] - (let [file-data (-> (cp/make-file-data (uuid/next) uuid/zero) + (let [file-data (-> (ctf/make-file-data (uuid/next) uuid/zero) (assoc-in [:pages-index uuid/zero :objects] objects))] (vary-meta changes assoc ::file-data file-data ::applied-changes-count 0))) diff --git a/common/src/app/common/pages/migrations.cljc b/common/src/app/common/pages/migrations.cljc index 512df7092..601671bfd 100644 --- a/common/src/app/common/pages/migrations.cljc +++ b/common/src/app/common/pages/migrations.cljc @@ -8,7 +8,6 @@ (:require [app.common.data :as d] [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.geom.shapes.path :as gsp] [app.common.geom.shapes.text :as gsht] @@ -16,9 +15,10 @@ [app.common.math :as mth] [app.common.pages :as cp] [app.common.pages.helpers :as cph] - [app.common.types.container :as ctc] + [app.common.types.container :as ctn] [app.common.types.page :as ctp] [app.common.types.pages-list :as ctpl] + [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctst] [app.common.uuid :as uuid] [cuerdas.core :as str])) @@ -89,7 +89,7 @@ (fix-empty-points [shape] (let [shape (cond-> shape - (empty? (:selrect shape)) (cp/setup-rect-selrect))] + (empty? (:selrect shape)) (cts/setup-rect-selrect))] (cond-> shape (empty? (:points shape)) (assoc :points (gsh/rect->points (:selrect shape)))))) @@ -456,7 +456,7 @@ (let [page (ctpl/get-page data page-id) [new-shape new-shapes] - (ctc/instantiate-component page + (ctn/instantiate-component page component (:id data) position) diff --git a/common/src/app/common/types/components_list.cljc b/common/src/app/common/types/components_list.cljc new file mode 100644 index 000000000..6f5643e67 --- /dev/null +++ b/common/src/app/common/types/components_list.cljc @@ -0,0 +1,28 @@ +;; 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) UXBOX Labs SL + +(ns app.common.types.components-list + (:require + [app.common.data :as d])) + +(defn components-seq + [file-data] + (vals (:components file-data))) + +(defn add-component + [file-data id name path main-instance-id main-instance-page shapes] + (assoc-in file-data [:components id] + {:id id + :name name + :path path + :main-instance-id main-instance-id + :main-instance-page main-instance-page + :objects (d/index-by :id shapes)})) + +(defn get-component + [file-data component-id] + (get-in file-data [:components component-id])) + diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index 168cfe8ca..7f7e8d985 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -9,7 +9,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.spec :as us] - [app.common.types.shape-tree :as ctt] + [app.common.types.shape-tree :as ctst] [clojure.spec.alpha :as s])) (s/def ::type #{:page :component}) @@ -18,9 +18,32 @@ (s/def ::path (s/nilable string?)) (s/def ::container - (s/keys :req-un [::id ::name ::ctt/objects] + (s/keys :req-un [::id ::name ::ctst/objects] :opt-un [::type ::path])) +(defn make-container + [page-or-component type] + (assoc page-or-component :type type)) + +(defn page? + [container] + (= (:type container) :page)) + +(defn component? + [container] + (= (:type container) :component)) + +(defn get-container + [file type id] + (us/assert map? file) + (us/assert ::type type) + (us/assert uuid? id) + + (-> (if (= type :page) + (get-in file [:pages-index id]) + (get-in file [:components id])) + (assoc :type type))) + (defn get-shape [container shape-id] (us/assert ::container container) @@ -29,21 +52,65 @@ (get :objects) (get shape-id))) +(defn shapes-seq + [container] + (vals (:objects container))) + +(defn make-component-shape + "Clone the shape and all children. Generate new ids and detach + from parent and frame. Update the original shapes to have links + to the new ones." + [shape objects file-id] + (assert (nil? (:component-id shape))) + (assert (nil? (:component-file shape))) + (assert (nil? (:shape-ref shape))) + (let [;; Ensure that the component root is not an instance and + ;; it's no longer tied to a frame. + update-new-shape (fn [new-shape _original-shape] + (cond-> new-shape + true + (-> (assoc :frame-id nil) + (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) + + (some? (:parent-id new-shape)) + (dissoc :component-root?)))] + + (ctst/clone-object shape nil objects update-new-shape update-original-shape))) + (defn instantiate-component - [container component component-file position] + [container component component-file-id position] (let [component-shape (get-shape component (:id component)) orig-pos (gpt/point (:x component-shape) (:y component-shape)) delta (gpt/subtract position orig-pos) objects (:objects container) - unames (volatile! (ctt/retrieve-used-names objects)) + unames (volatile! (ctst/retrieve-used-names objects)) - frame-id (ctt/frame-id-by-position objects (gpt/add orig-pos delta)) + frame-id (ctst/frame-id-by-position objects (gpt/add orig-pos delta)) update-new-shape (fn [new-shape original-shape] - (let [new-name (ctt/generate-unique-name @unames (:name new-shape))] + (let [new-name (ctst/generate-unique-name @unames (:name new-shape))] (when (nil? (:parent-id original-shape)) (vswap! unames conj new-name)) @@ -62,7 +129,7 @@ (nil? (:parent-id original-shape)) (assoc :component-id (:id original-shape) - :component-file component-file + :component-file component-file-id :component-root? true :name new-name) @@ -70,10 +137,10 @@ (dissoc :component-root?)))) [new-shape new-shapes _] - (ctt/clone-object component-shape - nil - (get component :objects) - update-new-shape)] + (ctst/clone-object component-shape + nil + (get component :objects) + update-new-shape)] [new-shape new-shapes])) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 5c7475d60..b999f3ccd 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -6,10 +6,20 @@ (ns app.common.types.file (:require + [app.common.data :as d] + [app.common.pages.common :refer [file-version]] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.types.color :as ctc] + [app.common.types.components-list :as ctkl] + [app.common.types.container :as ctn] [app.common.types.page :as ctp] - [clojure.spec.alpha :as s])) + [app.common.types.pages-list :as ctpl] + [app.common.uuid :as uuid] + [clojure.spec.alpha :as s] + [cuerdas.core :as str])) + +;; Specs (s/def :internal.media-object/name string?) (s/def :internal.media-object/width ::us/safe-integer) @@ -57,3 +67,158 @@ ::recent-colors ::typographies ::media])) + +;; Initialization + +(def empty-file-data + {:version file-version + :pages [] + :pages-index {}}) + +(defn make-file-data + ([file-id] + (make-file-data file-id (uuid/next))) + + ([file-id page-id] + (let [page (ctp/make-empty-page page-id "Page-1")] + (-> empty-file-data + (assoc :id file-id) + (ctpl/add-page page))))) + +;; Helpers + +(defn update-file-data + [file f] + (update file :data f)) + +(defn containers-seq + "Generate a sequence of all pages and all components, wrapped as containers" + [file-data] + (concat (map #(ctn/make-container % :page) (ctpl/pages-seq file-data)) + (map #(ctn/make-container % :component) (ctkl/components-seq file-data)))) + +(defn absorb-assets + "Find all assets of a library that are used in the file, and + move them to the file local library." + [file-data library-data] + (let [library-page-id (uuid/next) + + add-library-page + (fn [file-data] + (let [page (ctp/make-empty-page library-page-id "Library page")] + (-> file-data + (ctpl/add-page page)))) + + find-instances-in-container + (fn [container component] + (let [instances (filter #(= (:component-id %) (:id component)) + (ctn/shapes-seq container))] + (when (d/not-empty? instances) + [[container instances]]))) + + find-instances + (fn [file-data component] + (mapcat #(find-instances-in-container % component) (containers-seq file-data))) + + absorb-component + (fn [file-data _component] + ;; TODO: complete this + file-data) + + used-components + (mapcat (fn [component] + (let [instances (find-instances file-data component)] + (when instances + [[component instances]]))) + (ctkl/components-seq library-data))] + + (if (empty? used-components) + file-data + (as-> file-data $ + (add-library-page $) + (reduce absorb-component + $ + used-components))))) + +;; Debug helpers + +(defn dump-tree + ([file-data page-id libraries] + (dump-tree file-data page-id libraries false false)) + + ([file-data page-id libraries show-ids] + (dump-tree file-data page-id libraries show-ids false)) + + ([file-data page-id libraries show-ids show-touched] + (let [page (ctpl/get-page file-data page-id) + objects (:objects page) + components (:components file-data) + root (d/seek #(nil? (:parent-id %)) (vals objects))] + + (letfn [(show-shape [shape-id level objects] + (let [shape (get objects shape-id)] + (println (str/pad (str (str/repeat " " level) + (:name shape) + (when (seq (:touched shape)) "*") + (when show-ids (str/format " <%s>" (:id shape)))) + {:length 20 + :type :right}) + (show-component shape objects)) + (when show-touched + (when (seq (:touched shape)) + (println (str (str/repeat " " level) + " " + (str (:touched shape))))) + (when (:remote-synced? shape) + (println (str (str/repeat " " level) + " (remote-synced)")))) + (when (:shapes shape) + (dorun (for [shape-id (:shapes shape)] + (show-shape shape-id (inc level) objects)))))) + + (show-component [shape objects] + (if (nil? (:shape-ref shape)) + "" + (let [root-shape (cph/get-component-shape objects shape) + component-id (when root-shape (:component-id root-shape)) + component-file-id (when root-shape (:component-file root-shape)) + component-file (when component-file-id (get libraries component-file-id nil)) + component (when component-id + (if component-file + (get-in component-file [:data :components component-id]) + (get components component-id))) + component-shape (when (and component (:shape-ref shape)) + (get-in component [:objects (:shape-ref shape)]))] + (str/format " %s--> %s%s%s" + (cond (:component-root? shape) "#" + (:component-id shape) "@" + :else "-") + (when component-file (str/format "<%s> " (:name component-file))) + (or (:name component-shape) "?") + (if (or (:component-root? shape) + (nil? (:component-id shape)) + true) + "" + (let [component-id (:component-id shape) + component-file-id (:component-file shape) + component-file (when component-file-id (get libraries component-file-id nil)) + component (if component-file + (get-in component-file [:data :components component-id]) + (get components component-id))] + (str/format " (%s%s)" + (when component-file (str/format "<%s> " (:name component-file))) + (:name component))))))))] + + (println "[Page]") + (show-shape (:id root) 0 objects) + + (dorun (for [component (vals components)] + (do + (println) + (println (str/format "[%s]" (:name component)) + (when show-ids + (str/format " (main: %s/%s)" + (:main-instance-page component) + (:main-instance-id component)))) + (show-shape (:id component) 0 (:objects component))))))))) + diff --git a/common/src/app/common/types/pages_list.cljc b/common/src/app/common/types/pages_list.cljc index 3f037ece2..5275e480e 100644 --- a/common/src/app/common/types/pages_list.cljc +++ b/common/src/app/common/types/pages_list.cljc @@ -24,3 +24,11 @@ (update :pages conj-if-not-exists (:id page)) (update :pages-index assoc (:id page) page)))) +(defn pages-seq + [file-data] + (vals (:pages-index file-data))) + +(defn update-page + [file-data page-id f] + (update-in file-data [:pages-index page-id] f)) + diff --git a/common/src/app/common/types/shape.cljc b/common/src/app/common/types/shape.cljc index a5b182f64..249c589ce 100644 --- a/common/src/app/common/types/shape.cljc +++ b/common/src/app/common/types/shape.cljc @@ -6,8 +6,13 @@ (ns app.common.types.shape (:require + [app.common.colors :as clr] + [app.common.data :as d] + [app.common.exceptions :as ex] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] + [app.common.pages.common :refer [default-color]] [app.common.spec :as us] [app.common.types.color :as ctc] [app.common.types.shape.blur :as ctsb] @@ -16,6 +21,7 @@ [app.common.types.shape.layout :as ctsl] [app.common.types.shape.radius :as ctsr] [app.common.types.shape.shadow :as ctss] + [app.common.uuid :as uuid] [clojure.set :as set] [clojure.spec.alpha :as s])) @@ -316,3 +322,155 @@ (s/and (s/multi-spec shape-spec :type) #(contains? % :type) #(contains? % :name))) + + +;; --- Initialization + +(def default-shape-attrs + {}) + +(def default-frame-attrs + {:frame-id uuid/zero + :fills [{:fill-color clr/white + :fill-opacity 1}] + :strokes [] + :shapes [] + :hide-fill-on-export false}) + +(def ^:private minimal-shapes + [{:type :rect + :name "Rect-1" + :fills [{:fill-color default-color + :fill-opacity 1}] + :strokes [] + :rx 0 + :ry 0} + + {:type :image + :rx 0 + :ry 0 + :fills [] + :strokes []} + + {:type :circle + :name "Circle-1" + :fills [{:fill-color default-color + :fill-opacity 1}] + :strokes []} + + {:type :path + :name "Path-1" + :fills [] + :strokes [{:stroke-style :solid + :stroke-alignment :center + :stroke-width 2 + :stroke-color clr/black + :stroke-opacity 1}]} + + {:type :frame + :name "Board-1" + :fills [{:fill-color clr/white + :fill-opacity 1}] + :strokes [] + :stroke-style :none + :stroke-alignment :center + :stroke-width 0 + :stroke-color clr/black + :stroke-opacity 0 + :rx 0 + :ry 0} + + {:type :text + :name "Text-1" + :content nil} + + {:type :svg-raw}]) + +(def empty-selrect + {:x 0 :y 0 + :x1 0 :y1 0 + :x2 0.01 :y2 0.01 + :width 0.01 :height 0.01}) + +(defn make-minimal-shape + [type] + (let [type (cond (= type :curve) :path + :else type) + shape (d/seek #(= type (:type %)) minimal-shapes)] + (when-not shape + (ex/raise :type :assertion + :code :shape-type-not-implemented + :context {:type type})) + + (cond-> shape + :always + (assoc :id (uuid/next)) + + (not= :path (:type shape)) + (assoc :x 0 + :y 0 + :width 0.01 + :height 0.01 + :selrect {:x 0 + :y 0 + :x1 0 + :y1 0 + :x2 0.01 + :y2 0.01 + :width 0.01 + :height 0.01})))) + +(defn make-minimal-group + [frame-id rect group-name] + {:id (uuid/next) + :type :group + :name group-name + :shapes [] + :frame-id frame-id + :x (:x rect) + :y (:y rect) + :width (:width rect) + :height (:height rect)}) + +(defn setup-rect-selrect + "Initializes the selrect and points for a shape." + [shape] + (let [selrect (gsh/rect->selrect shape) + points (gsh/rect->points shape)] + (-> shape + (assoc :selrect selrect + :points points)))) + +(defn- setup-rect + "A specialized function for setup rect-like shapes." + [shape {:keys [x y width height]}] + (-> shape + (assoc :x x :y y :width width :height height) + (setup-rect-selrect))) + +(defn- setup-image + [{:keys [metadata] :as shape} props] + (-> (setup-rect shape props) + (assoc + :proportion (/ (:width metadata) + (:height metadata)) + :proportion-lock true))) + +(defn setup-shape + "A function that initializes the geometric data of + the shape. The props must have :x :y :width :height." + ([props] + (setup-shape {:type :rect} props)) + + ([shape props] + (case (:type shape) + :image (setup-image shape props) + (setup-rect shape props)))) + +(defn make-shape + "Make a non group shape, ready to use." + [type geom-props attrs] + (-> (make-minimal-shape type) + (setup-shape geom-props) + (merge attrs))) + diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc index 4fd9cb0a3..c7294699a 100644 --- a/common/src/app/common/types/shape_tree.cljc +++ b/common/src/app/common/types/shape_tree.cljc @@ -65,6 +65,11 @@ (update container :objects update-objects parent-id))) +(defn set-shape + "Replace a shape in the tree with a new one" + [container shape] + (assoc-in container [:objects (:id shape)] shape)) + (defn get-frames "Retrieves all frame objects as vector" [objects] @@ -149,7 +154,6 @@ [base index-base-a index-base-b])) - (defn is-shape-over-shape? [objects base-shape-id over-shape-id {:keys [top-frames?]}] diff --git a/common/test/app/common/geom_shapes_test.cljc b/common/test/app/common/geom_shapes_test.cljc index 079ecafd6..b7307b3c1 100644 --- a/common/test/app/common/geom_shapes_test.cljc +++ b/common/test/app/common/geom_shapes_test.cljc @@ -10,7 +10,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth :refer [close?]] - [app.common.pages :refer [make-minimal-shape]] + [app.common.types.shape :as cts] [clojure.test :as t])) (def default-path @@ -41,7 +41,7 @@ (defn create-test-shape ([type] (create-test-shape type {})) ([type params] - (-> (make-minimal-shape type) + (-> (cts/make-minimal-shape type) (merge params) (cond-> (= type :path) (add-path-data) diff --git a/common/test/app/common/pages_test.cljc b/common/test/app/common/pages_test.cljc index abfa5f8f3..7de27ffae 100644 --- a/common/test/app/common/pages_test.cljc +++ b/common/test/app/common/pages_test.cljc @@ -9,12 +9,13 @@ [clojure.test :as t] [clojure.pprint :refer [pprint]] [app.common.pages :as cp] + [app.common.types.file :as ctf] [app.common.uuid :as uuid])) (t/deftest process-change-set-option (let [file-id (uuid/custom 2 2) page-id (uuid/custom 1 1) - data (cp/make-file-data file-id page-id)] + data (ctf/make-file-data file-id page-id)] (t/testing "Sets option single" (let [chg {:type :set-option :page-id page-id @@ -80,7 +81,7 @@ (t/deftest process-change-add-obj (let [file-id (uuid/custom 2 2) page-id (uuid/custom 1 1) - data (cp/make-file-data file-id page-id) + data (ctf/make-file-data file-id page-id) id-a (uuid/custom 2 1) id-b (uuid/custom 2 2) id-c (uuid/custom 2 3)] @@ -134,7 +135,7 @@ (t/deftest process-change-mod-obj (let [file-id (uuid/custom 2 2) page-id (uuid/custom 1 1) - data (cp/make-file-data file-id page-id)] + data (ctf/make-file-data file-id page-id)] (t/testing "simple mod-obj" (let [chg {:type :mod-obj :page-id page-id @@ -161,7 +162,7 @@ (let [file-id (uuid/custom 2 2) page-id (uuid/custom 1 1) id (uuid/custom 2 1) - data (cp/make-file-data file-id page-id) + data (ctf/make-file-data file-id page-id) data (-> data (assoc-in [:pages-index page-id :objects uuid/zero :shapes] [id]) (assoc-in [:pages-index page-id :objects id] @@ -205,7 +206,7 @@ file-id (uuid/custom 2 2) page-id (uuid/custom 1 1) - data (cp/make-file-data file-id page-id) + data (ctf/make-file-data file-id page-id) data (update-in data [:pages-index page-id :objects] #(-> % @@ -449,7 +450,7 @@ :obj {:type :rect :name "Shape 3"}} ] - data (cp/make-file-data file-id page-id) + data (ctf/make-file-data file-id page-id) data (cp/process-changes data changes)] (t/testing "preserve order on multiple shape mov 1" @@ -556,7 +557,7 @@ :parent-id group-1-id :shapes [shape-1-id shape-2-id]}] - data (cp/make-file-data file-id page-id) + data (ctf/make-file-data file-id page-id) data (cp/process-changes data changes)] (t/testing "case 1" diff --git a/common/test/app/common/test_helpers/files.cljc b/common/test/app/common/test_helpers/files.cljc new file mode 100644 index 000000000..bbb9c58dd --- /dev/null +++ b/common/test/app/common/test_helpers/files.cljc @@ -0,0 +1,110 @@ +;; 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) UXBOX Labs SL + +(ns app.common.test-helpers.files + (:require + [app.common.geom.point :as gpt] + [app.common.types.components-list :as ctkl] + [app.common.types.container :as ctn] + [app.common.types.file :as ctf] + [app.common.types.pages-list :as ctpl] + [app.common.types.shape :as cts] + [app.common.types.shape-tree :as ctst] + [app.common.uuid :as uuid])) + +(def ^:private idmap (atom {})) + +(defn reset-idmap! [] + (reset! idmap {})) + +(defn id + [label] + (get @idmap label)) + +(defn sample-file + ([file-id page-id] (sample-file file-id page-id nil)) + ([file-id page-id props] + (merge {:id file-id + :name (get props :name "File1") + :data (ctf/make-file-data file-id page-id)} + props))) + +(defn sample-shape + [file label type page-id props] + (ctf/update-file-data + file + (fn [file-data] + (let [frame-id (get props :frame-id uuid/zero) + parent-id (get props :parent-id uuid/zero) + shape (if (= type :group) + (cts/make-minimal-group frame-id + {:x 0 :y 0 :width 1 :height 1} + (get props :name "Group1")) + (cts/make-shape type + {:x 0 :y 0 :width 1 :height 1} + props))] + + (swap! idmap assoc label (:id shape)) + (ctpl/update-page file-data + page-id + #(ctst/add-shape (:id shape) + shape + % + frame-id + parent-id + 0 + true)))))) + +(defn sample-component + [file label page-id shape-id] + (ctf/update-file-data + file + (fn [file-data] + (let [page (ctpl/get-page file-data page-id) + + [component-shape component-shapes updated-shapes] + (ctn/make-component-shape (ctn/get-shape page shape-id) + (:objects page) + (:id file))] + + (swap! idmap assoc label (:id component-shape)) + (-> file-data + (ctpl/update-page page-id + #(reduce (fn [page shape] (ctst/set-shape page shape)) + % + updated-shapes)) + (ctkl/add-component (:id component-shape) + (:name component-shape) + "" + shape-id + page-id + component-shapes)))))) + +(defn sample-instance + [file label page-id library component-id] + (ctf/update-file-data + file + (fn [file-data] + (let [[instance-shape instance-shapes] + (ctn/instantiate-component (ctpl/get-page file-data page-id) + (ctkl/get-component (:data library) component-id) + (:id library) + (gpt/point 0 0))] + + (swap! idmap assoc label (:id instance-shape)) + (-> file-data + (ctpl/update-page page-id + #(reduce (fn [page shape] + (ctst/add-shape (:id shape) + shape + page + uuid/zero + (:parent-id shape) + 0 + true)) + % + instance-shapes))))))) + diff --git a/common/test/app/common/types/file_test.cljc b/common/test/app/common/types/file_test.cljc new file mode 100644 index 000000000..0049732ab --- /dev/null +++ b/common/test/app/common/types/file_test.cljc @@ -0,0 +1,79 @@ +;; 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) UXBOX Labs SL + +(ns app.common.types.file-test + (:require + [clojure.test :as t] + [app.common.geom.point :as gpt] + [app.common.types.components-list :as ctkl] + [app.common.types.file :as ctf] + [app.common.types.pages-list :as ctpl] + [app.common.types.shape :as cts] + [app.common.types.shape-tree :as ctst] + [app.common.uuid :as uuid] + [app.common.test-helpers.files :as thf] + + [app.common.data :as d] + [app.common.pages.helpers :as cph] + [cuerdas.core :as str] + )) + +(t/use-fixtures :each + {:before thf/reset-idmap!}) + +(t/deftest test-absorb-assets + (let [library-id (uuid/custom 1 1) + library-page-id (uuid/custom 2 2) + file-id (uuid/custom 3 3) + file-page-id (uuid/custom 4 4) + + library (-> (thf/sample-file library-id library-page-id {:is-shared true}) + (thf/sample-shape :group1 + :group + library-page-id + {:name "Group1"}) + (thf/sample-shape :shape1 + :rect + library-page-id + {:name "Rect1" + :parent-id (thf/id :group1)}) + (thf/sample-component :component1 + library-page-id + (thf/id :group1))) + + file (-> (thf/sample-file file-id file-page-id) + (thf/sample-instance :instance1 + file-page-id + library + (thf/id :component1))) + + absorbed-file (ctf/update-file-data + file + #(ctf/absorb-assets % (:data library)))] + + (println "\n===== library") + (ctf/dump-tree (:data library) + library-page-id + {} + true) + + (println "\n===== file") + (ctf/dump-tree (:data file) + file-page-id + {library-id {:id library-id + :name "Library 1" + :data library}} + true) + + (println "\n===== absorbed file") + (ctf/dump-tree (:data absorbed-file) + file-page-id + {} + true) + + (t/is (= library-id (:id library))) + (t/is (= file-id (:id absorbed-file))))) + diff --git a/common/test/app/common/types/shape/spec_interactions_test.cljc b/common/test/app/common/types/shape/spec_interactions_test.cljc index 7c90b625c..a84019496 100644 --- a/common/test/app/common/types/shape/spec_interactions_test.cljc +++ b/common/test/app/common/types/shape/spec_interactions_test.cljc @@ -4,20 +4,20 @@ ;; ;; Copyright (c) UXBOX Labs SL -(ns app.common.spec-interactions-test +(ns app.common.types.shape.spec-interactions-test (:require [clojure.test :as t] [clojure.pprint :refer [pprint]] [app.common.exceptions :as ex] - [app.common.pages.init :as cpi] + [app.common.types.shape :as cts] [app.common.types.shape.interactions :as ctsi] [app.common.uuid :as uuid] [app.common.geom.point :as gpt])) (t/deftest set-event-type (let [interaction ctsi/default-interaction - shape (cpi/make-minimal-shape :rect) - frame (cpi/make-minimal-shape :frame)] + shape (cts/make-minimal-shape :rect) + frame (cts/make-minimal-shape :frame)] (t/testing "Set event type unchanged" (let [new-interaction @@ -148,7 +148,7 @@ (t/deftest option-delay - (let [frame (cpi/make-minimal-shape :frame) + (let [frame (cts/make-minimal-shape :frame) i1 ctsi/default-interaction i2 (ctsi/set-event-type i1 :after-delay frame)] @@ -211,10 +211,10 @@ (t/deftest option-overlay-opts - (let [base-frame (-> (cpi/make-minimal-shape :frame) + (let [base-frame (-> (cts/make-minimal-shape :frame) (assoc-in [:selrect :width] 100) (assoc-in [:selrect :height] 100)) - overlay-frame (-> (cpi/make-minimal-shape :frame) + overlay-frame (-> (cts/make-minimal-shape :frame) (assoc-in [:selrect :width] 30) (assoc-in [:selrect :height] 20)) objects {(:id base-frame) base-frame @@ -542,12 +542,12 @@ (t/deftest remap-interactions - (let [frame1 (cpi/make-minimal-shape :frame) - frame2 (cpi/make-minimal-shape :frame) - frame3 (cpi/make-minimal-shape :frame) - frame4 (cpi/make-minimal-shape :frame) - frame5 (cpi/make-minimal-shape :frame) - frame6 (cpi/make-minimal-shape :frame) + (let [frame1 (cts/make-minimal-shape :frame) + frame2 (cts/make-minimal-shape :frame) + frame3 (cts/make-minimal-shape :frame) + frame4 (cts/make-minimal-shape :frame) + frame5 (cts/make-minimal-shape :frame) + frame6 (cts/make-minimal-shape :frame) objects {(:id frame3) frame3 (:id frame4) frame4 diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index d778cdb0b..8407df47f 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -14,7 +14,6 @@ [app.common.geom.proportions :as gpr] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] [app.common.spec :as us] @@ -1591,7 +1590,7 @@ page-id (:current-page-id state) frame-id (-> (wsh/lookup-page-objects state page-id) (ctst/frame-id-by-position @ms/mouse-position)) - shape (cp/setup-rect-selrect + shape (cts/setup-rect-selrect {:id id :type :text :name "Text" @@ -1681,12 +1680,12 @@ (let [srect (gsh/selection-rect selected-objs) frame-id (get-in objects [(first selected) :frame-id]) parent-id (get-in objects [(first selected) :parent-id]) - shape (-> (cp/make-minimal-shape :frame) + shape (-> (cts/make-minimal-shape :frame) (merge {:x (:x srect) :y (:y srect) :width (:width srect) :height (:height srect)}) (assoc :frame-id frame-id :parent-id parent-id) (cond-> (not= frame-id uuid/zero) (assoc :fills [] :hide-in-viewer true)) - (cp/setup-rect-selrect))] + (cts/setup-rect-selrect))] (rx/of (dwu/start-undo-transaction) (dwsh/add-shape shape) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 39724ee8b..6f9ac6d35 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -7,15 +7,6 @@ (ns app.main.data.workspace.common (:require [app.common.logging :as log] - [app.common.pages :as cp] - [app.common.pages.changes-builder :as pcb] - [app.common.pages.helpers :as cph] - [app.common.spec :as us] - [app.common.types.page :as ctp] - [app.common.types.shape :as cts] - [app.common.types.shape-tree :as ctt] - [app.common.types.shape.interactions :as ctsi] - [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.undo :as dwu] [app.main.worker :as uw] diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index cb75f95cf..06384d41c 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -7,7 +7,7 @@ (ns app.main.data.workspace.drawing "Drawing interactions." (:require - [app.common.pages :as cp] + [app.common.types.shape :as cts] [app.common.uuid :as uuid] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.drawing.box :as box] @@ -91,7 +91,7 @@ (ptk/reify ::handle-drawing ptk/UpdateEvent (update [_ state] - (let [data (cp/make-minimal-shape type)] + (let [data (cts/make-minimal-shape type)] (update-in state [:workspace-drawing :object] merge data))) ptk/WatchEvent diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index aa550f98c..1868eb61b 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -9,8 +9,8 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] [app.common.pages.helpers :as cph] + [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctt] [app.common.uuid :as uuid] [app.main.data.workspace.drawing.common :as common] @@ -70,7 +70,7 @@ shape (get-in state [:workspace-drawing :object]) shape (-> shape - (cp/setup-shape {:x (:x initial) + (cts/setup-shape {:x (:x initial) :y (:y initial) :width 0.01 :height 0.01}) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 03f956aa5..95429a6e6 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -9,8 +9,9 @@ [app.common.geom.matrix :as gmt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] [app.common.pages.helpers :as cph] + [app.common.types.shape :as cts] + [app.main.data.workspace.common :as dwc] [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.undo :as dwu] @@ -55,7 +56,7 @@ (assoc :height 17 :width 4 :grow-type :auto-width) click-draw? - (cp/setup-rect-selrect) + (cts/setup-rect-selrect) :always (-> (gsh/transform-shape) diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index d5533bc98..5906db729 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -8,9 +8,9 @@ (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] + [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctt] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.selection :as dws] @@ -75,8 +75,8 @@ (ctt/generate-unique-name base-name))) selrect (gsh/selection-rect shapes) - group (-> (cp/make-minimal-group frame-id selrect gname) - (cp/setup-shape selrect) + group (-> (cts/make-minimal-group frame-id selrect gname) + (cts/setup-shape selrect) (assoc :shapes (mapv :id shapes) :parent-id parent-id :frame-id frame-id diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 39885b847..70000e1e0 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -56,46 +56,6 @@ ;; ---- Components and instances creation ---- -(defn make-component-shape - "Clone the shape and all children. Generate new ids and detach - from parent and frame. Update the original shapes to have links - to the new ones." - [shape objects file-id] - (assert (nil? (:component-id shape))) - (assert (nil? (:component-file shape))) - (assert (nil? (:shape-ref shape))) - (let [;; Ensure that the component root is not an instance and - ;; it's no longer tied to a frame. - update-new-shape (fn [new-shape _original-shape] - (cond-> new-shape - true - (-> (assoc :frame-id nil) - (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) - - (some? (:parent-id new-shape)) - (dissoc :component-root?)))] - - (ctst/clone-object shape nil objects update-new-shape update-original-shape))) - (defn generate-add-component "If there is exactly one id, and it's a group, use it as root. Otherwise, create a group that contains all ids. Then, make a component with it, @@ -115,7 +75,7 @@ (dwg/prepare-create-group it objects page-id shapes name true)) [new-shape new-shapes updated-shapes] - (make-component-shape group objects file-id) + (ctn/make-component-shape group objects file-id) changes (-> changes (pcb/add-component (:id new-shape) diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 683bc946f..2f3e5040e 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -11,9 +11,9 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] [app.common.pages.changes-builder :as pcb] [app.common.spec :refer [max-safe-int min-safe-int]] + [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctt] [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dch] @@ -182,7 +182,7 @@ (assoc :svg-attrs attrs) (assoc :svg-viewbox (-> (select-keys svg-data [:width :height]) (assoc :x offset-x :y offset-y))) - (cp/setup-rect-selrect)))) + (cts/setup-rect-selrect)))) (defn create-svg-root [frame-id svg-data] (let [{:keys [name x y width height offset-x offset-y]} svg-data] @@ -194,7 +194,7 @@ :height height :x (+ x offset-x) :y (+ y offset-y)} - (cp/setup-rect-selrect) + (cts/setup-rect-selrect) (assoc :svg-attrs (-> (:attrs svg-data) (dissoc :viewBox :xmlns) (d/without-keys usvg/inheritable-props)))))) @@ -214,7 +214,7 @@ (assoc :svg-attrs (d/without-keys attrs usvg/inheritable-props)) (assoc :svg-viewbox (-> (select-keys svg-data [:width :height]) (assoc :x offset-x :y offset-y))) - (cp/setup-rect-selrect)))) + (cts/setup-rect-selrect)))) (defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}] (when (and (contains? attrs :d) (seq (:d attrs))) diff --git a/frontend/src/app/main/ui/workspace/viewport/selection.cljs b/frontend/src/app/main/ui/workspace/viewport/selection.cljs index 4a1e4f7de..2f774d0d2 100644 --- a/frontend/src/app/main/ui/workspace/viewport/selection.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/selection.cljs @@ -11,7 +11,7 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] + [app.common.types.shape :as cts] [app.main.data.workspace :as dw] [app.main.refs :as refs] [app.main.store :as st] @@ -343,7 +343,7 @@ #(->> shapes (map gsh/transform-shape) (gsh/selection-rect) - (cp/setup-shape))) + (cts/setup-shape))) on-resize (fn [current-position _initial-position event] (when (dom/left-mouse? event) @@ -371,7 +371,7 @@ #(->> shapes (map gsh/transform-shape) (gsh/selection-rect) - (cp/setup-shape)))] + (cts/setup-shape)))] [:& controls-selection {:shape shape diff --git a/frontend/src/app/worker/import.cljs b/frontend/src/app/worker/import.cljs index aff53ab5b..b606ca3db 100644 --- a/frontend/src/app/worker/import.cljs +++ b/frontend/src/app/worker/import.cljs @@ -14,8 +14,8 @@ [app.common.geom.shapes.path :as gpa] [app.common.logging :as log] [app.common.media :as cm] - [app.common.pages :as cp] [app.common.text :as ct] + [app.common.types.file :as ctf] [app.common.uuid :as uuid] [app.main.repo :as rp] [app.util.http :as http] @@ -133,7 +133,7 @@ :name (:name context) :is-shared (:shared context) :project-id (:project-id context) - :data (-> cp/empty-file-data (assoc :id file-id))}))) + :data (-> ctf/empty-file-data (assoc :id file-id))}))) (defn link-file-libraries "Create a new file on the back-end" diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index 09d651d14..077993bc3 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -8,8 +8,8 @@ (:require [app.common.data :as d] [app.common.logging :as l] - [app.common.pages.helpers :as cph] [app.common.transit :as t] + [app.common.types.file :as ctf] [app.common.uuid :as uuid] [app.main.data.dashboard.shortcuts] [app.main.data.viewer.shortcuts] @@ -211,77 +211,9 @@ ([state show-ids] (dump-tree' state show-ids false)) ([state show-ids show-touched] (let [page-id (get state :current-page-id) - objects (get-in state [:workspace-data :pages-index page-id :objects]) - components (get-in state [:workspace-data :components]) - libraries (get state :workspace-libraries) - root (d/seek #(nil? (:parent-id %)) (vals objects))] - - (letfn [(show-shape [shape-id level objects] - (let [shape (get objects shape-id)] - (println (str/pad (str (str/repeat " " level) - (:name shape) - (when (seq (:touched shape)) "*") - (when show-ids (str/format " <%s>" (:id shape)))) - {:length 20 - :type :right}) - (show-component shape objects)) - (when show-touched - (when (seq (:touched shape)) - (println (str (str/repeat " " level) - " " - (str (:touched shape))))) - (when (:remote-synced? shape) - (println (str (str/repeat " " level) - " (remote-synced)")))) - (when (:shapes shape) - (dorun (for [shape-id (:shapes shape)] - (show-shape shape-id (inc level) objects)))))) - - (show-component [shape objects] - (if (nil? (:shape-ref shape)) - "" - (let [root-shape (cph/get-component-shape objects shape) - component-id (when root-shape (:component-id root-shape)) - component-file-id (when root-shape (:component-file root-shape)) - component-file (when component-file-id (get libraries component-file-id nil)) - component (when component-id - (if component-file - (get-in component-file [:data :components component-id]) - (get components component-id))) - component-shape (when (and component (:shape-ref shape)) - (get-in component [:objects (:shape-ref shape)]))] - (str/format " %s--> %s%s%s" - (cond (:component-root? shape) "#" - (:component-id shape) "@" - :else "-") - (when component-file (str/format "<%s> " (:name component-file))) - (or (:name component-shape) "?") - (if (or (:component-root? shape) - (nil? (:component-id shape)) - true) - "" - (let [component-id (:component-id shape) - component-file-id (:component-file shape) - component-file (when component-file-id (get libraries component-file-id nil)) - component (if component-file - (get-in component-file [:data :components component-id]) - (get components component-id))] - (str/format " (%s%s)" - (when component-file (str/format "<%s> " (:name component-file))) - (:name component))))))))] - - (println "[Page]") - (show-shape (:id root) 0 objects) - - (dorun (for [component (vals components)] - (do - (println) - (println (str/format "[%s]" (:name component)) - (when show-ids - (str/format " (main: %s/%s)" - (:main-instance-page component) - (:main-instance-id component)))) - (show-shape (:id component) 0 (:objects component))))))))) + file-data (get state :workspace-data) + libraries (get state :workspace-libraries)] + (ctf/dump-tree file-data page-id libraries show-ids show-touched)))) (defn ^:export dump-tree ([] (dump-tree' @st/state)) diff --git a/frontend/test/app/components_basic_test.cljs b/frontend/test/app/components_basic_test.cljs index bc0d2b744..05474e551 100644 --- a/frontend/test/app/components_basic_test.cljs +++ b/frontend/test/app/components_basic_test.cljs @@ -3,7 +3,7 @@ [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.pages.helpers :as cph] - [app.common.types.container :as ctc] + [app.common.types.container :as ctn] [app.main.data.workspace :as dw] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.libraries :as dwl] @@ -521,7 +521,7 @@ ; (let [page (thp/current-page new-state) shape1 (thp/get-shape new-state :shape1) - parent1 (ctc/get-shape page (:parent-id shape1)) + parent1 (ctn/get-shape page (:parent-id shape1)) [[group shape1 shape2] [c-group c-shape1 c-shape2] diff --git a/frontend/test/app/components_sync_test.cljs b/frontend/test/app/components_sync_test.cljs index 442b8c60f..05bf78ea2 100644 --- a/frontend/test/app/components_sync_test.cljs +++ b/frontend/test/app/components_sync_test.cljs @@ -4,7 +4,7 @@ [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.pages.helpers :as cph] - [app.common.types.container :as ctc] + [app.common.types.container :as ctn] [app.main.data.workspace :as dw] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.shapes :as dwsh] @@ -1353,7 +1353,7 @@ instance1 (thp/get-shape state :instance1) instance2 (thp/get-shape state :instance2) - shape2 (ctc/get-shape (wsh/lookup-page state) + shape2 (ctn/get-shape (wsh/lookup-page state) (first (:shapes instance2))) update-fn1 (fn [shape] diff --git a/frontend/test/app/test_helpers/libraries.cljs b/frontend/test/app/test_helpers/libraries.cljs index 428653234..6e0142b3e 100644 --- a/frontend/test/app/test_helpers/libraries.cljs +++ b/frontend/test/app/test_helpers/libraries.cljs @@ -8,7 +8,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] - [app.common.types.container :as ctc] + [app.common.types.container :as ctn] [app.main.data.workspace :as dw] [app.main.data.workspace.libraries-helpers :as dwlh] [app.main.data.workspace.state-helpers :as wsh] @@ -60,7 +60,7 @@ verify that they are a well constructed instance tree." [state root-inst-id] (let [page (thp/current-page state) - root-inst (ctc/get-shape page root-inst-id) + root-inst (ctn/get-shape page root-inst-id) shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)] (is-instance-root (first shapes-inst)) @@ -73,7 +73,7 @@ verify that they are not a component instance." [state root-inst-id] (let [page (thp/current-page state) - root-inst (ctc/get-shape page root-inst-id) + root-inst (ctn/get-shape page root-inst-id) shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)] (run! is-noninstance shapes-inst) @@ -85,7 +85,7 @@ the main component and all its shapes." [state root-inst-id] (let [page (thp/current-page state) - root-inst (ctc/get-shape page root-inst-id) + root-inst (ctn/get-shape page root-inst-id) libs (wsh/get-libraries state) component (cph/get-component libs (:component-id root-inst)) @@ -103,7 +103,7 @@ (cph/get-component libs (:component-id component-shape)) main-shape - (ctc/get-shape component (:shape-ref shape))] + (ctn/get-shape component (:shape-ref shape))] (t/is (some? main-shape))))] @@ -123,7 +123,7 @@ corresponding component shape missing." [state root-inst-id] (let [page (thp/current-page state) - root-inst (ctc/get-shape page root-inst-id) + root-inst (ctn/get-shape page root-inst-id) libs (wsh/get-libraries state) component (cph/get-component libs (:component-id root-inst)) @@ -141,7 +141,7 @@ (cph/get-component libs (:component-id component-shape)) main-shape - (ctc/get-shape component (:shape-ref shape))] + (ctn/get-shape component (:shape-ref shape))] (t/is (some? main-shape))))] diff --git a/frontend/test/app/test_helpers/pages.cljs b/frontend/test/app/test_helpers/pages.cljs index 6156a02ce..a061ecc43 100644 --- a/frontend/test/app/test_helpers/pages.cljs +++ b/frontend/test/app/test_helpers/pages.cljs @@ -9,6 +9,7 @@ [app.common.geom.shapes :as gsh] [app.common.pages :as cp] [app.common.pages.helpers :as cph] + [app.common.types.shape :as cts] [app.main.data.workspace :as dw] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.layout :as layout] @@ -69,9 +70,7 @@ ([state label type props] (let [page (current-page state) frame (cph/get-frame (:objects page)) - shape (-> (cp/make-minimal-shape type) - (cp/setup-shape {:x 0 :y 0 :width 1 :height 1}) - (merge props))] + shape (cts/make-shape type {:x 0 :y 0 :width 1 :height 1} props)] (swap! idmap assoc label (:id shape)) (update state :workspace-data cp/process-changes diff --git a/frontend/test/app/util/snap_data_test.cljs b/frontend/test/app/util/snap_data_test.cljs index 6982d4f6f..9f18e5a1c 100644 --- a/frontend/test/app/util/snap_data_test.cljs +++ b/frontend/test/app/util/snap_data_test.cljs @@ -9,7 +9,6 @@ [app.common.uuid :as uuid] [cljs.test :as t :include-macros true] [cljs.pprint :refer [pprint]] - [app.common.pages.init :as init] [app.common.file-builder :as fb] [app.util.snap-data :as sd]))