diff --git a/backend/tests/app/tests/test_common_pages_migrations.clj b/backend/tests/app/tests/test_common_pages_migrations.clj new file mode 100644 index 000000000..4e8adebd6 --- /dev/null +++ b/backend/tests/app/tests/test_common_pages_migrations.clj @@ -0,0 +1,94 @@ +;; 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.tests.test-common-pages-migrations + (:require + [clojure.test :as t] + [clojure.pprint :refer [pprint]] + [promesa.core :as p] + [mockery.core :refer [with-mock]] + [app.common.data :as d] + [app.common.pages :as cp] + [app.common.pages.migrations :as cpm] + [app.common.uuid :as uuid] + [app.tests.helpers :as th])) + +(t/deftest test-migration-8-1 + (let [page-id (uuid/custom 0 0) + objects [{:type :rect :id (uuid/custom 1 0)} + {:type :group + :id (uuid/custom 1 1) + :selrect {} + :shapes [(uuid/custom 1 2) (uuid/custom 1 0)]} + {:type :group + :id (uuid/custom 1 2) + :selrect {} + :shapes [(uuid/custom 1 3)]} + {:type :group + :id (uuid/custom 1 3) + :selrect {} + :shapes [(uuid/custom 1 4)]} + {:type :group + :id (uuid/custom 1 4) + :selrect {} + :shapes [(uuid/custom 1 5)]} + {:type :path :id (uuid/custom 1 5)}] + + data {:pages-index {page-id {:objects (d/index-by :id objects)}} + :components {} + :version 7} + + res (cpm/migrate-data data)] + + (pprint data) + (pprint res) + + (t/is (= (dissoc data :version) + (dissoc res :version))))) + +(t/deftest test-migration-8-2 + (let [page-id (uuid/custom 0 0) + objects [{:type :rect :id (uuid/custom 1 0)} + {:type :group + :id (uuid/custom 1 1) + :selrect {} + :shapes [(uuid/custom 1 2) (uuid/custom 1 0)]} + {:type :group + :id (uuid/custom 1 2) + :selrect {} + :shapes [(uuid/custom 1 3)]} + {:type :group + :id (uuid/custom 1 3) + :selrect {} + :shapes [(uuid/custom 1 4)]} + {:type :group + :id (uuid/custom 1 4) + :selrect {} + :shapes []} + {:type :path :id (uuid/custom 1 5)}] + + data {:pages-index {page-id {:objects (d/index-by :id objects)}} + :components {} + :version 7} + + expct (-> data + (update-in [:pages-index page-id :objects] dissoc + (uuid/custom 1 2) + (uuid/custom 1 3) + (uuid/custom 1 4)) + (update-in [:pages-index page-id :objects (uuid/custom 1 1) :shapes] + (fn [shapes] + (let [id (uuid/custom 1 2)] + (into [] (remove #(= id %)) shapes))))) + + res (cpm/migrate-data data)] + + (pprint res) + (pprint expct) + + (t/is (= (dissoc expct :version) + (dissoc res :version))) + )) diff --git a/common/app/common/pages/common.cljc b/common/app/common/pages/common.cljc index f439b2cf4..9a39105bf 100644 --- a/common/app/common/pages/common.cljc +++ b/common/app/common/pages/common.cljc @@ -8,7 +8,7 @@ (:require [app.common.uuid :as uuid])) -(def file-version 7) +(def file-version 8) (def default-color "#b1b2b5") ;; $color-gray-20 (def root uuid/zero) diff --git a/common/app/common/pages/migrations.cljc b/common/app/common/pages/migrations.cljc index fd254d87b..8e93da804 100644 --- a/common/app/common/pages/migrations.cljc +++ b/common/app/common/pages/migrations.cljc @@ -179,3 +179,46 @@ (update data :pages-index #(d/mapm update-page %)))) + +;; Remove groups without any shape, both in pages and components + +(defmethod migrate 8 + [data] + (letfn [(clean-parents [obj deleted?] + (d/update-when obj :shapes + (fn [shapes] + (into [] (remove deleted?) shapes)))) + + (obj-is-empty? [obj] + (and (= (:type obj) :group) + (or (empty? (:shapes obj)) + (nil? (:selrect obj))))) + + (clean-objects [objects] + (loop [entries (seq objects) + deleted #{} + result objects] + (let [[id obj :as entry] (first entries)] + (if entry + (if (obj-is-empty? obj) + (recur (rest entries) + (conj deleted id) + (dissoc result id)) + (recur (rest entries) + deleted + result)) + [(count deleted) + (d/mapm #(clean-parents %2 deleted) result)])))) + + (clean-container [_ container] + (loop [n 0 + objects (:objects container)] + (let [[deleted objects] (clean-objects objects)] + (if (and (pos? deleted) (< n 1000)) + (recur (inc n) objects) + (assoc container :objects objects)))))] + + (-> data + (update :pages-index #(d/mapm clean-container %)) + (d/update-when :components #(d/mapm clean-container %))))) + diff --git a/frontend/shadow-cljs.edn b/frontend/shadow-cljs.edn index 3da0b47f9..b668fa2d4 100644 --- a/frontend/shadow-cljs.edn +++ b/frontend/shadow-cljs.edn @@ -62,6 +62,10 @@ {:target :node-test :output-to "target/tests.js" :ns-regexp "^app.test-" - :autorun true}}} + :autorun true + :compiler-options + {:output-feature-set :es8 + :output-wrapper false + :warnings {:fn-deprecated false}}}}} diff --git a/frontend/src/app/util/storage.cljs b/frontend/src/app/util/storage.cljs index b03c7ea61..aecd1f03a 100644 --- a/frontend/src/app/util/storage.cljs +++ b/frontend/src/app/util/storage.cljs @@ -8,6 +8,7 @@ (:require [app.util.transit :as t] [app.util.timers :as tm] + [app.util.globals :as g] [app.common.exceptions :as ex])) (defn- ^boolean is-worker? @@ -36,17 +37,18 @@ (defn- load [storage] - (let [len (.-length ^js storage)] - (reduce (fn [res index] - (let [key (.key ^js storage index) - val (.getItem ^js storage key)] - (try - (assoc res (t/decode key) (t/decode val)) - (catch :default e - res)))) - {} - (range len)))) + (when storage + (let [len (.-length ^js storage)] + (reduce (fn [res index] + (let [key (.key ^js storage index) + val (.getItem ^js storage key)] + (try + (assoc res (t/decode key) (t/decode val)) + (catch :default e + res)))) + {} + (range len))))) -(defonce storage (atom (load js/localStorage))) +(defonce storage (atom (load (unchecked-get g/global "localStorage")))) (add-watch storage :persistence #(persist js/localStorage %3 %4)) diff --git a/frontend/tests/app/test_components_sync.cljs b/frontend/tests/app/test_components_sync.cljs index 5fa6bcd12..e93ab55ed 100644 --- a/frontend/tests/app/test_components_sync.cljs +++ b/frontend/tests/app/test_components_sync.cljs @@ -1,18 +1,18 @@ (ns app.test-components-sync - (:require [cljs.test :as t :include-macros true] - [cljs.pprint :refer [pprint]] - [clojure.stacktrace :as stk] - [beicon.core :as rx] - [linked.core :as lks] - [app.test-helpers.events :as the] - [app.test-helpers.pages :as thp] - [app.test-helpers.libraries :as thl] - [app.common.geom.point :as gpt] - [app.common.data :as d] - [app.common.pages.helpers :as cph] - [app.main.data.workspace.common :as dwc] - [app.main.data.workspace.libraries :as dwl] - [app.main.data.workspace.libraries-helpers :as dwlh])) + (:require + [cljs.test :as t :include-macros true] + [cljs.pprint :refer [pprint]] + [beicon.core :as rx] + [linked.core :as lks] + [app.test-helpers.events :as the] + [app.test-helpers.pages :as thp] + [app.test-helpers.libraries :as thl] + [app.common.geom.point :as gpt] + [app.common.data :as d] + [app.common.pages.helpers :as cph] + [app.main.data.workspace.changes :as dwc] + [app.main.data.workspace.libraries :as dwl] + [app.main.data.workspace.libraries-helpers :as dwlh])) (t/use-fixtures :each {:before thp/reset-idmap!}) diff --git a/frontend/tests/app/test_shapes.cljs b/frontend/tests/app/test_shapes.cljs index 157780071..2b473c02a 100644 --- a/frontend/tests/app/test_shapes.cljs +++ b/frontend/tests/app/test_shapes.cljs @@ -50,10 +50,6 @@ (dwl/add-recent-color color)) (rx/map (fn [new-state] - (t/is (= (get-in new-state [:workspace-file - :data - :recent-colors]) - [color])) (t/is (= (get-in new-state [:workspace-data :recent-colors]) [color]))))