mirror of
https://github.com/penpot/penpot.git
synced 2025-08-03 07:38:35 +02:00
♻️ Components refactor: generator for relocate shapes (and tests)
This commit is contained in:
parent
78d0611632
commit
f354942487
7 changed files with 499 additions and 229 deletions
|
@ -6,7 +6,8 @@
|
|||
|
||||
(ns common-tests.helpers.compositions
|
||||
(:require
|
||||
[common-tests.helpers.files :as thf]))
|
||||
[common-tests.helpers.files :as thf]
|
||||
[common-tests.helpers.ids-map :as thi]))
|
||||
|
||||
(defn add-rect
|
||||
[file rect-label]
|
||||
|
@ -15,10 +16,11 @@
|
|||
:name "Rect1"))
|
||||
|
||||
(defn add-frame
|
||||
[file frame-label]
|
||||
(thf/add-sample-shape file frame-label
|
||||
:type :frame
|
||||
:name "Frame1"))
|
||||
([file frame-label & {:keys [parent-label]}]
|
||||
(thf/add-sample-shape file frame-label
|
||||
:type :frame
|
||||
:name "Frame1"
|
||||
:parent-label parent-label)))
|
||||
|
||||
(defn add-frame-with-child
|
||||
[file frame-label child-label]
|
||||
|
|
33
common/test/common_tests/helpers/debug.cljc
Normal file
33
common/test/common_tests/helpers/debug.cljc
Normal file
|
@ -0,0 +1,33 @@
|
|||
(ns common-tests.helpers.debug
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[common-tests.helpers.ids-map :as thi]))
|
||||
|
||||
(defn dump-shape
|
||||
"Dumps a shape, with each attribute in a line"
|
||||
[shape]
|
||||
(println "{")
|
||||
(doseq [[k v] (sort shape)]
|
||||
(when (some? v)
|
||||
(println (str " " k " : " v))))
|
||||
(println "}"))
|
||||
|
||||
(defn- stringify-keys [m keys]
|
||||
(apply str (interpose ", " (map #(str % ": " (get m %)) keys))))
|
||||
|
||||
(defn dump-page
|
||||
"Dumps the layer tree of the page. Prints the label of each shape, and the specified keys.
|
||||
Example: (thd/dump-page (thf/current-page file) [:id :touched])"
|
||||
([page keys]
|
||||
(dump-page page uuid/zero "" keys))
|
||||
([page id padding keys]
|
||||
(let [objects (vals (:objects page))
|
||||
root-objects (filter #(and
|
||||
(= (:parent-id %) id)
|
||||
(not= (:id %) id))
|
||||
objects)]
|
||||
(doseq [val root-objects]
|
||||
(println padding (thi/label (:id val))
|
||||
(when keys
|
||||
(str "[" (stringify-keys val keys) "]")))
|
||||
(dump-page page (:id val) (str padding " ") keys)))))
|
|
@ -9,12 +9,15 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.features :as ffeat]
|
||||
[app.common.files.changes :as cfc]
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.files.libraries-helpers :as cflh]
|
||||
[app.common.files.validate :as cfv]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.pprint :refer [pprint]]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.colors-list :as ctcl]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
|
@ -206,8 +209,16 @@
|
|||
[file id]
|
||||
(ctkl/get-component (:data file) id))
|
||||
|
||||
(defn set-child-label
|
||||
[file shape-label child-idx label]
|
||||
(let [id (-> (get-shape file shape-label)
|
||||
:shapes
|
||||
(nth child-idx))]
|
||||
(when id
|
||||
(thi/set-id! label id))))
|
||||
|
||||
(defn instantiate-component
|
||||
[file component-label copy-root-label & {:keys [parent-label library] :as params}]
|
||||
[file component-label copy-root-label & {:keys [parent-label library children-labels] :as params}]
|
||||
(let [page (current-page file)
|
||||
library (or library file)
|
||||
component (get-component library component-label)
|
||||
|
@ -236,33 +247,60 @@
|
|||
(assoc :frame-id frame-id)
|
||||
|
||||
(and (some? parent) (ctn/in-any-component? (:objects page) parent))
|
||||
(dissoc :component-root))]
|
||||
(dissoc :component-root))
|
||||
file' (ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(as-> file-data $
|
||||
(ctpl/update-page $
|
||||
(:id page)
|
||||
#(ctst/add-shape (:id copy-root')
|
||||
copy-root'
|
||||
%
|
||||
frame-id
|
||||
parent-id
|
||||
nil
|
||||
true))
|
||||
(reduce (fn [file-data shape]
|
||||
(ctpl/update-page file-data
|
||||
(:id page)
|
||||
#(ctst/add-shape (:id shape)
|
||||
shape
|
||||
%
|
||||
(:parent-id shape)
|
||||
(:frame-id shape)
|
||||
nil
|
||||
true)))
|
||||
$
|
||||
(remove #(= (:id %) (:did copy-root')) copy-shapes)))))]
|
||||
(when children-labels
|
||||
(dotimes [idx (count children-labels)]
|
||||
(set-child-label file' copy-root-label idx (nth children-labels idx))))
|
||||
file'))
|
||||
|
||||
|
||||
|
||||
(defn component-swap
|
||||
[file shape-label new-component-label new-shape-label & {:keys [library] :as params}]
|
||||
(let [shape (get-shape file shape-label)
|
||||
library (or library file)
|
||||
libraries {(:id library) library}
|
||||
page (current-page file)
|
||||
objects (:objects page)
|
||||
id-new-component (-> (get-component library new-component-label)
|
||||
:id)
|
||||
|
||||
;; Store the properties that need to be maintained when the component is swapped
|
||||
keep-props-values (select-keys shape ctk/swap-keep-attrs)
|
||||
|
||||
|
||||
[new_shape _ changes]
|
||||
(-> (pcb/empty-changes nil (:id page))
|
||||
(cflh/generate-component-swap objects shape (:data file) page libraries id-new-component 0 nil keep-props-values))]
|
||||
|
||||
(thi/set-id! new-shape-label (:id new_shape))
|
||||
(apply-changes file changes)))
|
||||
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(as-> file-data $
|
||||
(ctpl/update-page $
|
||||
(:id page)
|
||||
#(ctst/add-shape (:id copy-root')
|
||||
copy-root'
|
||||
%
|
||||
frame-id
|
||||
parent-id
|
||||
nil
|
||||
true))
|
||||
(reduce (fn [file-data shape]
|
||||
(ctpl/update-page file-data
|
||||
(:id page)
|
||||
#(ctst/add-shape (:id shape)
|
||||
shape
|
||||
%
|
||||
(:parent-id shape)
|
||||
(:frame-id shape)
|
||||
nil
|
||||
true)))
|
||||
$
|
||||
(remove #(= (:id %) (:did copy-root')) copy-shapes)))))))
|
||||
|
||||
(defn sample-color
|
||||
[label & {:keys [] :as params}]
|
||||
|
|
|
@ -34,3 +34,9 @@
|
|||
[f]
|
||||
(reset-idmap!)
|
||||
(f))
|
||||
|
||||
(defn label [id]
|
||||
(->> @idmap
|
||||
(filter #(= id (val %)))
|
||||
(map key)
|
||||
(first)))
|
||||
|
|
194
common/test/common_tests/logic/comp_remove_swap_slots_test.cljc
Normal file
194
common/test/common_tests/logic/comp_remove_swap_slots_test.cljc
Normal file
|
@ -0,0 +1,194 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns common-tests.logic.comp-remove-swap-slots-test
|
||||
(:require
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.files.libraries-helpers :as cflh]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.uuid :as uuid]
|
||||
[clojure.test :as t]
|
||||
[common-tests.helpers.compositions :as tho]
|
||||
[common-tests.helpers.files :as thf]
|
||||
[common-tests.helpers.ids-map :as thi]))
|
||||
|
||||
(t/use-fixtures :each thi/test-fixture)
|
||||
|
||||
|
||||
;; Related .penpot file: common/test/cases/remove-swap-slots.penpot
|
||||
(defn- setup-file
|
||||
[]
|
||||
;; :frame-b1 [:id: 3aee2370-44e4-81c8-8004-46e56a459d70, :touched: ]
|
||||
;; :blue1 [:id: 3aee2370-44e4-81c8-8004-46e56a45fc55, :touched: #{:swap-slot-3aee2370-44e4-81c8-8004-46e56a459d75}]
|
||||
;; :green-copy [:id: 3aee2370-44e4-81c8-8004-46e56a45fc56, :touched: ]
|
||||
;; :blue-copy-in-green-copy [:id: 3aee2370-44e4-81c8-8004-46e56a4631a4, :touched: #{:swap-slot-3aee2370-44e4-81c8-8004-46e56a459d6f}]
|
||||
;; :frame-yellow [:id: 3aee2370-44e4-81c8-8004-46e56a459d73, :touched: ]
|
||||
;; :frame-green [:id: 3aee2370-44e4-81c8-8004-46e56a459d6c, :touched: ]
|
||||
;; :red-copy-green [:id: 3aee2370-44e4-81c8-8004-46e56a459d6f, :touched: ]
|
||||
;; :frame-blue [:id: 3aee2370-44e4-81c8-8004-46e56a459d69, :touched: ]
|
||||
;; :frame-b2 [:id: 3aee2370-44e4-81c8-8004-46e56a4631a5, :touched: ]
|
||||
;; :frame-red [:id: 3aee2370-44e4-81c8-8004-46e56a459d66, :touched: ]
|
||||
|
||||
(-> (thf/sample-file :file1)
|
||||
(tho/add-frame :frame-red)
|
||||
(thf/make-component :red :frame-red)
|
||||
(tho/add-frame :frame-blue)
|
||||
(thf/make-component :blue :frame-blue)
|
||||
(tho/add-frame :frame-green)
|
||||
(thf/make-component :green :frame-green)
|
||||
(thf/instantiate-component :red :red-copy-green :parent-label :frame-green)
|
||||
(tho/add-frame :frame-b1)
|
||||
(thf/make-component :b1 :frame-b1)
|
||||
(tho/add-frame :frame-yellow :parent-label :frame-b1)
|
||||
(thf/instantiate-component :red :red-copy :parent-label :frame-b1)
|
||||
(thf/component-swap :red-copy :blue :blue1)
|
||||
(thf/instantiate-component :green :green-copy :parent-label :frame-b1 :children-labels [:red-copy-in-green-copy])
|
||||
(thf/component-swap :red-copy-in-green-copy :blue :blue-copy-in-green-copy)
|
||||
(tho/add-frame :frame-b2)
|
||||
(thf/make-component :b2 :frame-b2)))
|
||||
|
||||
(t/deftest test-keep-swap-slot-relocating-blue1-to-root
|
||||
(let [;; ============================== Setup ===============================
|
||||
file (setup-file)
|
||||
page (thf/current-page file)
|
||||
blue1 (thf/get-shape file :blue1)
|
||||
|
||||
;; ============================== Action ==============================
|
||||
changes (cflh/generate-relocate-shapes (pcb/empty-changes nil)
|
||||
(:objects page)
|
||||
#{(:parent-id blue1)} ;; parents
|
||||
uuid/zero ;; paremt-id
|
||||
(:id page) ;; page-id
|
||||
0 ;; to-index
|
||||
#{(:id blue1)}) ;; ids
|
||||
file' (thf/apply-changes file changes)
|
||||
|
||||
;; ============================== Get =================================
|
||||
blue1' (thf/get-shape file' :blue1)]
|
||||
|
||||
;; ================================== Check ===============================
|
||||
;; blue1 had swap-id before move
|
||||
(t/is (some? (ctk/get-swap-slot blue1)))
|
||||
|
||||
;; blue1 has not swap-id after move
|
||||
(t/is (some? blue1'))
|
||||
(t/is (nil? (ctk/get-swap-slot blue1')))))
|
||||
|
||||
|
||||
(t/deftest test-keep-swap-slot-relocating-blue1-to-b2
|
||||
(let [;; ============================== Setup ===============================
|
||||
file (setup-file)
|
||||
page (thf/current-page file)
|
||||
blue1 (thf/get-shape file :blue1)
|
||||
b2 (thf/get-shape file :frame-b2)
|
||||
|
||||
|
||||
;; ============================== Action ==============================
|
||||
changes (cflh/generate-relocate-shapes (pcb/empty-changes nil)
|
||||
(:objects page)
|
||||
#{(:parent-id blue1)} ;; parents
|
||||
(:id b2) ;; parent-id
|
||||
(:id page) ;; page-id
|
||||
0 ;; to-index
|
||||
#{(:id blue1)}) ;; ids
|
||||
file' (thf/apply-changes file changes)
|
||||
|
||||
;; ============================== Get =================================
|
||||
blue1' (thf/get-shape file' :blue1)]
|
||||
|
||||
;; ================================== Check ===============================
|
||||
;; blue1 had swap-id before move
|
||||
(t/is (some? (ctk/get-swap-slot blue1)))
|
||||
|
||||
;; blue1 has not swap-id after move
|
||||
(t/is (some? blue1'))
|
||||
(t/is (nil? (ctk/get-swap-slot blue1')))))
|
||||
|
||||
(t/deftest test-keep-swap-slot-relocating-yellow-to-root
|
||||
(let [;; ============================== Setup ===============================
|
||||
file (setup-file)
|
||||
page (thf/current-page file)
|
||||
blue1 (thf/get-shape file :blue1)
|
||||
yellow (thf/get-shape file :frame-yellow)
|
||||
|
||||
;; ============================== Action ==============================
|
||||
;; Move blue1 into yellow
|
||||
changes (cflh/generate-relocate-shapes (pcb/empty-changes nil)
|
||||
(:objects page)
|
||||
#{(:parent-id blue1)} ;; parents
|
||||
(:id yellow) ;; parent-id
|
||||
(:id page) ;; page-id
|
||||
0 ;; to-index
|
||||
#{(:id blue1)}) ;; ids
|
||||
|
||||
file' (thf/apply-changes file changes)
|
||||
page' (thf/current-page file')
|
||||
yellow' (thf/get-shape file' :frame-yellow)
|
||||
|
||||
;; Move yellow into root
|
||||
changes' (cflh/generate-relocate-shapes (pcb/empty-changes nil)
|
||||
(:objects page')
|
||||
#{(:parent-id yellow')} ;; parents
|
||||
uuid/zero ;; parent-id
|
||||
(:id page') ;; page-id
|
||||
0 ;; to-index
|
||||
#{(:id yellow')}) ;; ids
|
||||
file'' (thf/apply-changes file' changes')
|
||||
|
||||
;; ============================== Get =================================
|
||||
blue1'' (thf/get-shape file'' :blue1)]
|
||||
|
||||
;; ================================== Check ===============================
|
||||
;; blue1 had swap-id before move
|
||||
(t/is (some? (ctk/get-swap-slot blue1)))
|
||||
|
||||
;; blue1 has not swap-id after move
|
||||
(t/is (some? blue1''))
|
||||
(t/is (nil? (ctk/get-swap-slot blue1'')))))
|
||||
|
||||
|
||||
(t/deftest test-keep-swap-slot-relocating-yellow-to-b2
|
||||
(let [;; ============================== Setup ===============================
|
||||
file (setup-file)
|
||||
page (thf/current-page file)
|
||||
blue1 (thf/get-shape file :blue1)
|
||||
yellow (thf/get-shape file :frame-yellow)
|
||||
|
||||
;; ============================== Action ==============================
|
||||
;; Move blue1 into yellow
|
||||
changes (cflh/generate-relocate-shapes (pcb/empty-changes nil)
|
||||
(:objects page)
|
||||
#{(:parent-id blue1)} ;; parents
|
||||
(:id yellow) ;; parent-id
|
||||
(:id page) ;; page-id
|
||||
0 ;; to-index
|
||||
#{(:id blue1)}) ;; ids
|
||||
|
||||
file' (thf/apply-changes file changes)
|
||||
page' (thf/current-page file')
|
||||
yellow' (thf/get-shape file' :frame-yellow)
|
||||
b2' (thf/get-shape file' :frame-b2)
|
||||
|
||||
;; Move yellow into b2
|
||||
changes' (cflh/generate-relocate-shapes (pcb/empty-changes nil)
|
||||
(:objects page')
|
||||
#{(:parent-id yellow')} ;; parents
|
||||
(:id b2') ;; parent-id
|
||||
(:id page') ;; page-id
|
||||
0 ;; to-index
|
||||
#{(:id yellow')}) ;; ids
|
||||
file'' (thf/apply-changes file' changes')
|
||||
|
||||
;; ============================== Get =================================
|
||||
blue1'' (thf/get-shape file'' :blue1)]
|
||||
|
||||
;; ================================== Check ===============================
|
||||
;; blue1 had swap-id before move
|
||||
(t/is (some? (ctk/get-swap-slot blue1)))
|
||||
|
||||
;; blue1 has not swap-id after move
|
||||
(t/is (some? blue1''))
|
||||
(t/is (nil? (ctk/get-swap-slot blue1'')))))
|
Loading…
Add table
Add a link
Reference in a new issue