diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index ae9b6362fe..34b3a28e1d 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -263,7 +263,8 @@ [:delete-temporary-token-theme [:map {:title "DeleteTemporaryTokenThemeChange"} [:type [:= :delete-temporary-token-theme]] - [:id ::sm/uuid]]] + [:id ::sm/uuid] + [:name :string]]] [:add-token-theme [:map {:title "AddTokenThemeChange"} @@ -274,12 +275,14 @@ [:map {:title "ModTokenThemeChange"} [:type [:= :mod-token-theme]] [:id ::sm/uuid] + [:name :string] [:token-theme ::ctot/token-theme]]] [:del-token-theme [:map {:title "DelTokenThemeChange"} [:type [:= :del-token-theme]] - [:id ::sm/uuid]]] + [:id ::sm/uuid] + [:name :string]]] [:add-token-set [:map {:title "AddTokenSetChange"} @@ -822,29 +825,69 @@ set-name name))))) +(defn- set-ids->names + [data sets] + (let [lib-sets (:token-sets-index data) + set-id->name + (fn [set-id] + (dm/get-in lib-sets [set-id :name]))] + (map set-id->name sets))) + (defmethod process-change :add-temporary-token-theme [data {:keys [token-theme]}] - (ctotl/add-temporary-token-theme data token-theme)) + (-> data + (ctotl/add-temporary-token-theme token-theme) + (update :tokens-lib + #(-> % + (ctob/ensure-tokens-lib) + (ctob/add-theme (-> token-theme + (update :sets (partial set-ids->names data)) + (ctob/make-token-theme))))))) (defmethod process-change :update-active-token-themes [data {:keys [theme-ids]}] (ctotl/assoc-active-token-themes data theme-ids)) (defmethod process-change :delete-temporary-token-theme - [data {:keys [id]}] - (ctotl/delete-temporary-token-theme data id)) + [data {:keys [id name]}] + (-> data + (ctotl/delete-temporary-token-theme id) + (update :tokens-lib + #(-> % + (ctob/ensure-tokens-lib) + (ctob/delete-theme name))))) (defmethod process-change :add-token-theme [data {:keys [token-theme]}] - (ctotl/add-token-theme data token-theme)) + (-> data + (ctotl/add-token-theme token-theme) + (update :tokens-lib + #(-> % + (ctob/ensure-tokens-lib) + (ctob/add-theme (-> token-theme + (update :sets (partial set-ids->names data)) + (ctob/make-token-theme))))))) (defmethod process-change :mod-token-theme - [data {:keys [id token-theme]}] - (ctotl/update-token-theme data id merge token-theme)) + [data {:keys [id name token-theme]}] + (-> data + (ctotl/update-token-theme id merge token-theme) + (update :tokens-lib + #(-> % + (ctob/ensure-tokens-lib) + (ctob/update-theme name (fn [prev-theme] + (merge prev-theme + (-> token-theme + (update :sets (partial set-ids->names data)))))))))) (defmethod process-change :del-token-theme - [data {:keys [id]}] - (ctotl/delete-token-theme data id)) + [data {:keys [id name]}] + (-> data + (ctotl/delete-token-theme id) + (update :tokens-lib + #(-> % + (ctob/ensure-tokens-lib) + (ctob/delete-theme name))))) (defmethod process-change :add-token-set [data {:keys [token-set]}] diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc index 09148d5423..44f57464c3 100644 --- a/common/src/app/common/files/changes_builder.cljc +++ b/common/src/app/common/files/changes_builder.cljc @@ -699,7 +699,7 @@ [changes token-theme] (-> changes (update :redo-changes conj {:type :add-temporary-token-theme :token-theme token-theme}) - (update :undo-changes conj {:type :delete-temporary-token-theme :id (:id token-theme)}) + (update :undo-changes conj {:type :delete-temporary-token-theme :id (:id token-theme) :name (:name token-theme)}) (apply-changes-local))) (defn update-active-token-themes @@ -713,14 +713,14 @@ [changes token-theme] (-> changes (update :redo-changes conj {:type :add-token-theme :token-theme token-theme}) - (update :undo-changes conj {:type :del-token-theme :id (:id token-theme)}) + (update :undo-changes conj {:type :del-token-theme :id (:id token-theme) :name (:name token-theme)}) (apply-changes-local))) (defn update-token-theme [changes token-theme prev-token-theme] (-> changes - (update :redo-changes conj {:type :mod-token-theme :id (:id token-theme) :token-theme token-theme}) - (update :undo-changes conj {:type :mod-token-theme :id (:id token-theme) :token-theme (or prev-token-theme token-theme)}) + (update :redo-changes conj {:type :mod-token-theme :id (:id token-theme) :name (:name prev-token-theme) :token-theme token-theme}) + (update :undo-changes conj {:type :mod-token-theme :id (:id token-theme) :name (:name token-theme) :token-theme (or prev-token-theme token-theme)}) (apply-changes-local))) (defn delete-token-theme @@ -729,7 +729,7 @@ (let [library-data (::library-data (meta changes)) prev-token-theme (get-in library-data [:token-themes-index token-theme-id])] (-> changes - (update :redo-changes conj {:type :del-token-theme :id token-theme-id}) + (update :redo-changes conj {:type :del-token-theme :id token-theme-id :name (:name prev-token-theme)}) (update :undo-changes conj {:type :add-token-theme :token-theme prev-token-theme}) (apply-changes-local)))) diff --git a/common/src/app/common/fressian.clj b/common/src/app/common/fressian.clj index 4a640cd8cb..f75ece0bfc 100644 --- a/common/src/app/common/fressian.clj +++ b/common/src/app/common/fressian.clj @@ -16,6 +16,7 @@ java.time.OffsetDateTime java.util.List linked.map.LinkedMap + linked.set.LinkedSet org.fressian.Reader org.fressian.StreamingWriter org.fressian.Writer @@ -275,7 +276,12 @@ {:name "clj/seq" :class clojure.lang.ISeq :wfn write-list-like - :rfn (comp sequence read-object!)}) + :rfn (comp sequence read-object!)} + + {:name "linked/set" + :class LinkedSet + :wfn write-list-like + :rfn (comp #(into (d/ordered-set) %) read-object!)}) ;; --- PUBLIC API diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index 7e34404c43..3ba7aa5af3 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -94,7 +94,8 @@ [:name :string] [:description [:maybe :string]] [:modified-at ::sm/inst] - [:tokens [:map-of {:gen/max 5} :string ::token]]] + [:tokens [:and [:map-of {:gen/max 5} :string ::token] + [:fn d/ordered-map?]]]] [:fn (partial instance? TokenSet)]]) (sm/register! ::token-set schema:token-set) @@ -127,8 +128,7 @@ (delete-set [_ set-name] "delete a set in the library") (set-count [_] "get the total number if sets in the library") (get-sets [_] "get an ordered sequence of all sets in the library") - (get-set [_ set-name] "get one set looking for name") - (validate [_])) + (get-set [_ set-name] "get one set looking for name")) (def schema:token-sets [:and @@ -144,10 +144,79 @@ (def check-token-sets! (sm/check-fn ::token-sets)) +;; === TokenTheme + +(defprotocol ITokenTheme + (toggle-set [_ set-name] "togle a set used / not used in the theme")) + +(defrecord TokenTheme [name description is-source modified-at sets] + ITokenTheme + (toggle-set [_ set-name] + (TokenTheme. name + description + is-source + (dt/now) + (if (sets set-name) + (disj sets set-name) + (conj sets set-name))))) + +(def schema:token-theme + [:and [:map {:title "TokenTheme"} + [:name :string] + [:description [:maybe :string]] + [:is-source :boolean] + [:modified-at ::sm/inst] + [:sets [:and [:set {:gen/max 5} :string] + [:fn d/ordered-set?]]]] + [:fn (partial instance? TokenTheme)]]) + +(sm/register! ::token-theme schema:token-theme) + +(def valid-token-theme? + (sm/validator schema:token-theme)) + +(def check-token-theme! + (sm/check-fn ::token-theme)) + +(defn make-token-theme + [& {:keys [] :as params}] + (let [params (-> params + (dissoc :id) + (dissoc :group) + (update :is-source #(or % false)) + (update :modified-at #(or % (dt/now))) + (update :sets #(into (d/ordered-set) %))) + token-theme (map->TokenTheme params)] + + (dm/assert! + "expected valid token theme" + (check-token-theme! token-theme)) + + token-theme)) + ;; === TokenThemes (collection) +(defprotocol ITokenThemes + (add-theme [_ token-theme] "add a theme to the library, at the end") + (update-theme [_ theme-name f] "modify a theme in the ilbrary") + (delete-theme [_ theme-name] "delete a theme in the library") + (theme-count [_] "get the total number if themes in the library") + (get-themes [_] "get an ordered sequence of all themes in the library") + (get-theme [_ theme-name] "get one theme looking for name")) + +(def schema:token-themes + [:and + [:map-of {:title "TokenThemes"} + :string ::token-theme] + [:fn d/ordered-map?]]) + +(sm/register! ::token-themes schema:token-themes) + (def valid-token-themes? - (constantly true)) + (sm/validator schema:token-themes)) + +(def check-token-themes! + (sm/check-fn ::token-themes)) ;; === Tokens Lib @@ -155,7 +224,9 @@ "A library of tokens, sets and themes." (add-token-in-set [_ set-name token] "add token to a set") (update-token-in-set [_ set-name token-name f] "update a token in a set") - (delete-token-from-set [_ set-name token-name] "delete a token from a set")) + (delete-token-from-set [_ set-name token-name] "delete a token from a set") + (toggle-set-in-theme [_ theme-name set-name] "toggle a set used / not used in a theme") + (validate [_])) (deftype TokensLib [sets themes] ;; NOTE: This is only for debug purposes, pending to properly @@ -188,15 +259,11 @@ (d/addm-at-index index (:name set') set')))) themes)) this)) - + (delete-set [_ set-name] (TokensLib. (dissoc sets set-name) themes)) - (validate [_] - (and (valid-token-sets? sets) - (valid-token-themes? themes))) - (set-count [_] (count sets)) @@ -206,6 +273,39 @@ (get-set [_ set-name] (get sets set-name)) + ITokenThemes + (add-theme [_ token-theme] + (dm/assert! "expected valid token theme" (check-token-theme! token-theme)) + (TokensLib. sets + (assoc themes (:name token-theme) token-theme))) + + (update-theme [this theme-name f] + (if-let [theme (get themes theme-name)] + (let [theme' (-> (make-token-theme (f theme)) + (assoc :modified-at (dt/now)))] + (check-token-theme! theme') + (TokensLib. sets + (if (= (:name theme) (:name theme')) + (assoc themes (:name theme') theme') + (let [index (d/index-of (keys themes) (:name theme))] + (-> themes + (dissoc (:name theme)) + (d/addm-at-index index (:name theme') theme')))))) + this)) + + (delete-theme [_ theme-name] + (TokensLib. sets + (dissoc themes theme-name))) + + (theme-count [_] + (count themes)) + + (get-themes [_] + (vals themes)) + + (get-theme [_ theme-name] + (get themes theme-name)) + ITokensLib (add-token-in-set [this set-name token] (dm/assert! "expected valid token instance" (check-token! token)) @@ -226,7 +326,18 @@ (TokensLib. (update sets set-name #(delete-token % token-name)) themes) - this))) + this)) + + (toggle-set-in-theme [this theme-name set-name] + (if (contains? themes theme-name) + (TokensLib. sets + (update themes theme-name + #(toggle-set % set-name))) + this)) + + (validate [_] + (and (valid-token-sets? sets) + (valid-token-themes? themes)))) (defn valid-tokens-lib? [o] @@ -269,7 +380,7 @@ (sm/register! ::tokens-lib type:tokens-lib) -;; === Serialization handlers for RPC API and database +;; === Serialization handlers for RPC API (transit) and database (fressian) (t/add-handlers! {:id "penpot/tokens-lib" @@ -281,6 +392,11 @@ :class TokenSet :wfn #(into {} %) :rfn #(make-token-set %)} + + {:id "penpot/token-theme" + :class TokenTheme + :wfn #(into {} %) + :rfn #(make-token-theme %)} {:id "penpot/token" :class Token @@ -307,6 +423,15 @@ (let [obj (fres/read-object! r)] (map->TokenSet obj)))} + {:name "penpot/token-theme/v1" + :class TokenTheme + :wfn (fn [n w o] + (fres/write-tag! w n 1) + (fres/write-object! w (into {} o))) + :rfn (fn [r] + (let [obj (fres/read-object! r)] + (map->TokenTheme obj)))} + {:name "penpot/tokens-lib/v1" :class TokensLib :wfn (fn [n w o] diff --git a/common/src/app/common/types/tokens_theme_list.cljc b/common/src/app/common/types/tokens_theme_list.cljc index f9c3857ff2..971c96946c 100644 --- a/common/src/app/common/types/tokens_theme_list.cljc +++ b/common/src/app/common/types/tokens_theme_list.cljc @@ -19,16 +19,17 @@ (assoc file-data :token-active-themes theme-ids)) (defn add-temporary-token-theme - [file-data {:keys [id] :as token-theme}] + [file-data {:keys [id name] :as token-theme}] (-> file-data (d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)]) (assoc :token-theme-temporary-id id) + (assoc :token-theme-temporary-name name) (update :token-themes-index assoc id token-theme))) (defn delete-temporary-token-theme [file-data token-theme-id] (cond-> file-data - (= (:token-theme-temporary-id file-data) token-theme-id) (dissoc :token-theme-temporary-id) + (= (:token-theme-temporary-id file-data) token-theme-id) (dissoc :token-theme-temporary-id :token-theme-temporary-name) :always (d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)]))) (defn add-token-theme diff --git a/common/test/common_tests/types/tokens_lib_test.cljc b/common/test/common_tests/types/tokens_lib_test.cljc index 09ad19b177..3c24353da7 100644 --- a/common/test/common_tests/types/tokens_lib_test.cljc +++ b/common/test/common_tests/types/tokens_lib_test.cljc @@ -13,247 +13,399 @@ [app.common.types.tokens-lib :as ctob] [clojure.test :as t])) -(t/deftest make-token - (let [now (dt/now) - token1 (ctob/make-token :name "test-token-1" - :type :boolean - :value true) - token2 (ctob/make-token :name "test-token-2" - :type :numeric - :value 66 - :description "test description" - :modified-at now)] +(t/testing "token" + (t/deftest make-token + (let [now (dt/now) + token1 (ctob/make-token :name "test-token-1" + :type :boolean + :value true) + token2 (ctob/make-token :name "test-token-2" + :type :numeric + :value 66 + :description "test description" + :modified-at now)] - (t/is (= (:name token1) "test-token-1")) - (t/is (= (:type token1) :boolean)) - (t/is (= (:value token1) true)) - (t/is (nil? (:description token1))) - (t/is (some? (:modified-at token1))) - (t/is (ctob/valid-token? token1)) + (t/is (= (:name token1) "test-token-1")) + (t/is (= (:type token1) :boolean)) + (t/is (= (:value token1) true)) + (t/is (nil? (:description token1))) + (t/is (some? (:modified-at token1))) + (t/is (ctob/valid-token? token1)) - (t/is (= (:name token2) "test-token-2")) - (t/is (= (:type token2) :numeric)) - (t/is (= (:value token2) 66)) - (t/is (= (:description token2) "test description")) - (t/is (= (:modified-at token2) now)) - (t/is (ctob/valid-token? token2)))) + (t/is (= (:name token2) "test-token-2")) + (t/is (= (:type token2) :numeric)) + (t/is (= (:value token2) 66)) + (t/is (= (:description token2) "test description")) + (t/is (= (:modified-at token2) now)) + (t/is (ctob/valid-token? token2)))) -(t/deftest invalid-tokens - (let [args {:name 777 - :type :invalid}] - (t/is (thrown-with-msg? Exception #"expected valid token" - (apply ctob/make-token args))) - (t/is (false? (ctob/valid-token? {}))))) + (t/deftest invalid-tokens + (let [args {:name 777 + :type :invalid}] + (t/is (thrown-with-msg? Exception #"expected valid token" + (apply ctob/make-token args))) + (t/is (false? (ctob/valid-token? {})))))) -(t/deftest make-token-set - (let [now (dt/now) - token-set1 (ctob/make-token-set :name "test-token-set-1") - token-set2 (ctob/make-token-set :name "test-token-set-2" - :description "test description" - :modified-at now - :tokens [])] - (t/is (= (:name token-set1) "test-token-set-1")) - (t/is (nil? (:description token-set1))) - (t/is (some? (:modified-at token-set1))) - (t/is (empty? (:tokens token-set1))) +(t/testing "token-set" + (t/deftest make-token-set + (let [now (dt/now) + token-set1 (ctob/make-token-set :name "test-token-set-1") + token-set2 (ctob/make-token-set :name "test-token-set-2" + :description "test description" + :modified-at now + :tokens [])] - (t/is (= (:name token-set2) "test-token-set-2")) - (t/is (= (:description token-set2) "test description")) - (t/is (= (:modified-at token-set2) now)) - (t/is (empty? (:tokens token-set2))))) + (t/is (= (:name token-set1) "test-token-set-1")) + (t/is (nil? (:description token-set1))) + (t/is (some? (:modified-at token-set1))) + (t/is (empty? (:tokens token-set1))) -(t/deftest invalid-token-set - (let [args {:name 777 - :description 999}] - (t/is (thrown-with-msg? Exception #"expected valid token set" - (apply ctob/make-token-set args))))) + (t/is (= (:name token-set2) "test-token-set-2")) + (t/is (= (:description token-set2) "test description")) + (t/is (= (:modified-at token-set2) now)) + (t/is (empty? (:tokens token-set2))))) -(t/deftest make-tokens-lib - (let [tokens-lib (ctob/make-tokens-lib)] - (t/is (= (ctob/set-count tokens-lib) 0)))) + (t/deftest invalid-token-set + (let [args {:name 777 + :description 999}] + (t/is (thrown-with-msg? Exception #"expected valid token set" + (apply ctob/make-token-set args)))))) -(t/deftest add-token-set - (let [tokens-lib (ctob/make-tokens-lib) - token-set (ctob/make-token-set :name "test-token-set") - tokens-lib' (ctob/add-set tokens-lib token-set) - token-sets' (ctob/get-sets tokens-lib') - token-set' (ctob/get-set tokens-lib' "test-token-set")] +(t/testing "token-theme" + (t/deftest make-token-theme + (let [now (dt/now) + token-theme1 (ctob/make-token-theme :name "test-token-theme-1") + token-theme2 (ctob/make-token-theme :name "test-token-theme-2" + :description "test description" + :is-source true + :modified-at now + :sets #{})] - (t/is (= (ctob/set-count tokens-lib') 1)) - (t/is (= (first token-sets') token-set)) - (t/is (= token-set' token-set)))) + (t/is (= (:name token-theme1) "test-token-theme-1")) + (t/is (nil? (:description token-theme1))) + (t/is (false? (:is-source token-theme1))) + (t/is (some? (:modified-at token-theme1))) + (t/is (empty? (:sets token-theme1))) -(t/deftest update-token-set - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set"))) + (t/is (= (:name token-theme2) "test-token-theme-2")) + (t/is (= (:description token-theme2) "test description")) + (t/is (true? (:is-source token-theme2))) + (t/is (= (:modified-at token-theme2) now)) + (t/is (empty? (:sets token-theme2))))) - tokens-lib' (-> tokens-lib - (ctob/update-set "test-token-set" - (fn [token-set] - (assoc token-set - :name "updated-name" - :description "some description"))) - (ctob/update-set "not-existing-set" - (fn [token-set] - (assoc token-set - :name "no-effect")))) + (t/deftest invalid-token-theme + (let [args {:name 777 + :description 999 + :is-source 42}] + (t/is (thrown-with-msg? Exception #"expected valid token theme" + (apply ctob/make-token-theme args)))))) - token-set (ctob/get-set tokens-lib "test-token-set") - token-set' (ctob/get-set tokens-lib' "updated-name")] - (t/is (= (ctob/set-count tokens-lib') 1)) - (t/is (= (:name token-set') "updated-name")) - (t/is (= (:description token-set') "some description")) - (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))) +(t/testing "tokens-lib" + (t/deftest make-tokens-lib + (let [tokens-lib (ctob/make-tokens-lib)] + (t/is (= (ctob/set-count tokens-lib) 0)))) -(t/deftest delete-token-set - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set"))) + (t/deftest invalid-tokens-lib + (let [args {:sets nil + :themes nil}] + (t/is (thrown-with-msg? Exception #"expected valid tokens lib" + (apply ctob/make-tokens-lib args)))))) - tokens-lib' (-> tokens-lib - (ctob/delete-set "test-token-set") - (ctob/delete-set "not-existing-set")) - token-set' (ctob/get-set tokens-lib' "updated-name")] +(t/testing "token-set in a lib" + (t/deftest add-token-set + (let [tokens-lib (ctob/make-tokens-lib) + token-set (ctob/make-token-set :name "test-token-set") + tokens-lib' (ctob/add-set tokens-lib token-set) - (t/is (= (ctob/set-count tokens-lib') 0)) - (t/is (nil? token-set')))) + token-sets' (ctob/get-sets tokens-lib') + token-set' (ctob/get-set tokens-lib' "test-token-set")] -(t/deftest add-token - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set"))) - token (ctob/make-token :name "test-token" - :type :boolean - :value true) - tokens-lib' (-> tokens-lib - (ctob/add-token-in-set "test-token-set" token) - (ctob/add-token-in-set "not-existing-set" token)) + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (first token-sets') token-set)) + (t/is (= token-set' token-set)))) - token-set (ctob/get-set tokens-lib "test-token-set") - token-set' (ctob/get-set tokens-lib' "test-token-set") - token' (get-in token-set' [:tokens "test-token"])] + (t/deftest update-token-set + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set"))) - (t/is (= (ctob/set-count tokens-lib') 1)) - (t/is (= (count (:tokens token-set')) 1)) - (t/is (= (:name token') "test-token")) - (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))) + tokens-lib' (-> tokens-lib + (ctob/update-set "test-token-set" + (fn [token-set] + (assoc token-set + :description "some description"))) + (ctob/update-set "not-existing-set" + (fn [token-set] + (assoc token-set + :description "no-effect")))) -(t/deftest update-token - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set")) - (ctob/add-token-in-set "test-token-set" - (ctob/make-token :name "test-token-1" - :type :boolean - :value true)) - (ctob/add-token-in-set "test-token-set" - (ctob/make-token :name "test-token-2" - :type :boolean - :value true))) + token-set (ctob/get-set tokens-lib "test-token-set") + token-set' (ctob/get-set tokens-lib' "test-token-set")] - tokens-lib' (-> tokens-lib - (ctob/update-token-in-set "test-token-set" "test-token-1" - (fn [token] - (assoc token - :description "some description" - :value false))) - (ctob/update-token-in-set "not-existing-set" "test-token-1" - (fn [token] - (assoc token - :name "no-effect"))) - (ctob/update-token-in-set "test-token-set" "not-existing-token" - (fn [token] - (assoc token - :name "no-effect")))) + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (:name token-set') "test-token-set")) + (t/is (= (:description token-set') "some description")) + (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))) - token-set (ctob/get-set tokens-lib "test-token-set") - token-set' (ctob/get-set tokens-lib' "test-token-set") - token (get-in token-set [:tokens "test-token-1"]) - token' (get-in token-set' [:tokens "test-token-1"])] + (t/deftest rename-token-set + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set"))) - (t/is (= (ctob/set-count tokens-lib') 1)) - (t/is (= (count (:tokens token-set')) 2)) - (t/is (= (d/index-of (keys (:tokens token-set')) "test-token-1") 0)) - (t/is (= (:name token') "test-token-1")) - (t/is (= (:description token') "some description")) - (t/is (= (:value token') false)) - (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))) - (t/is (dt/is-after? (:modified-at token') (:modified-at token))))) + tokens-lib' (-> tokens-lib + (ctob/update-set "test-token-set" + (fn [token-set] + (assoc token-set + :name "updated-name")))) -(t/deftest rename-token - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set")) - (ctob/add-token-in-set "test-token-set" - (ctob/make-token :name "test-token-1" - :type :boolean - :value true)) - (ctob/add-token-in-set "test-token-set" - (ctob/make-token :name "test-token-2" - :type :boolean - :value true))) + token-set (ctob/get-set tokens-lib "test-token-set") + token-set' (ctob/get-set tokens-lib' "updated-name")] - tokens-lib' (-> tokens-lib - (ctob/update-token-in-set "test-token-set" "test-token-1" - (fn [token] - (assoc token - :name "updated-name")))) + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (:name token-set') "updated-name")) + (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))) - token-set (ctob/get-set tokens-lib "test-token-set") - token-set' (ctob/get-set tokens-lib' "test-token-set") - token (get-in token-set [:tokens "test-token-1"]) - token' (get-in token-set' [:tokens "updated-name"])] + (t/deftest delete-token-set + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set"))) - (t/is (= (ctob/set-count tokens-lib') 1)) - (t/is (= (count (:tokens token-set')) 2)) - (t/is (= (d/index-of (keys (:tokens token-set')) "updated-name") 0)) - (t/is (= (:name token') "updated-name")) - (t/is (= (:description token') nil)) - (t/is (= (:value token') true)) - (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))) - (t/is (dt/is-after? (:modified-at token') (:modified-at token))))) + tokens-lib' (-> tokens-lib + (ctob/delete-set "test-token-set") + (ctob/delete-set "not-existing-set")) -(t/deftest delete-token - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set")) - (ctob/add-token-in-set "test-token-set" - (ctob/make-token :name "test-token" - :type :boolean - :value true))) - tokens-lib' (-> tokens-lib - (ctob/delete-token-from-set "test-token-set" "test-token") - (ctob/delete-token-from-set "not-existing-set" "test-token") - (ctob/delete-token-from-set "test-set" "not-existing-token")) + token-set' (ctob/get-set tokens-lib' "updated-name")] - token-set (ctob/get-set tokens-lib "test-token-set") - token-set' (ctob/get-set tokens-lib' "test-token-set") - token' (get-in token-set' [:tokens "test-token"])] + (t/is (= (ctob/set-count tokens-lib') 0)) + (t/is (nil? token-set'))))) - (t/is (= (ctob/set-count tokens-lib') 1)) - (t/is (= (count (:tokens token-set')) 0)) - (t/is (nil? token')) - (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))) -(t/deftest transit-serialization - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set")) - (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "test-token" - :type :boolean - :value true))) - encoded-str (tr/encode-str tokens-lib) - tokens-lib' (tr/decode-str encoded-str)] +(t/testing "token in a lib" + (t/deftest add-token + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set"))) + token (ctob/make-token :name "test-token" + :type :boolean + :value true) + tokens-lib' (-> tokens-lib + (ctob/add-token-in-set "test-token-set" token) + (ctob/add-token-in-set "not-existing-set" token)) - (t/is (ctob/valid-tokens-lib? tokens-lib')) - (t/is (= (ctob/set-count tokens-lib') 1)))) + token-set (ctob/get-set tokens-lib "test-token-set") + token-set' (ctob/get-set tokens-lib' "test-token-set") + token' (get-in token-set' [:tokens "test-token"])] -(t/deftest fressian-serialization - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :name "test-token-set")) - (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "test-token" - :type :boolean - :value true))) - encoded-blob (fres/encode tokens-lib) - tokens-lib' (fres/decode encoded-blob)] + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (count (:tokens token-set')) 1)) + (t/is (= (:name token') "test-token")) + (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))) - (t/is (ctob/valid-tokens-lib? tokens-lib')) - (t/is (= (ctob/set-count tokens-lib') 1)))) + (t/deftest update-token + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set")) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "test-token-1" + :type :boolean + :value true)) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "test-token-2" + :type :boolean + :value true))) + + tokens-lib' (-> tokens-lib + (ctob/update-token-in-set "test-token-set" "test-token-1" + (fn [token] + (assoc token + :description "some description" + :value false))) + (ctob/update-token-in-set "not-existing-set" "test-token-1" + (fn [token] + (assoc token + :name "no-effect"))) + (ctob/update-token-in-set "test-token-set" "not-existing-token" + (fn [token] + (assoc token + :name "no-effect")))) + + token-set (ctob/get-set tokens-lib "test-token-set") + token-set' (ctob/get-set tokens-lib' "test-token-set") + token (get-in token-set [:tokens "test-token-1"]) + token' (get-in token-set' [:tokens "test-token-1"])] + + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (count (:tokens token-set')) 2)) + (t/is (= (d/index-of (keys (:tokens token-set')) "test-token-1") 0)) + (t/is (= (:name token') "test-token-1")) + (t/is (= (:description token') "some description")) + (t/is (= (:value token') false)) + (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))) + (t/is (dt/is-after? (:modified-at token') (:modified-at token))))) + + (t/deftest rename-token + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set")) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "test-token-1" + :type :boolean + :value true)) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "test-token-2" + :type :boolean + :value true))) + + tokens-lib' (-> tokens-lib + (ctob/update-token-in-set "test-token-set" "test-token-1" + (fn [token] + (assoc token + :name "updated-name")))) + + token-set (ctob/get-set tokens-lib "test-token-set") + token-set' (ctob/get-set tokens-lib' "test-token-set") + token (get-in token-set [:tokens "test-token-1"]) + token' (get-in token-set' [:tokens "updated-name"])] + + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (count (:tokens token-set')) 2)) + (t/is (= (d/index-of (keys (:tokens token-set')) "updated-name") 0)) + (t/is (= (:name token') "updated-name")) + (t/is (= (:description token') nil)) + (t/is (= (:value token') true)) + (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))) + (t/is (dt/is-after? (:modified-at token') (:modified-at token))))) + + (t/deftest delete-token + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set")) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "test-token" + :type :boolean + :value true))) + tokens-lib' (-> tokens-lib + (ctob/delete-token-from-set "test-token-set" "test-token") + (ctob/delete-token-from-set "not-existing-set" "test-token") + (ctob/delete-token-from-set "test-set" "not-existing-token")) + + token-set (ctob/get-set tokens-lib "test-token-set") + token-set' (ctob/get-set tokens-lib' "test-token-set") + token' (get-in token-set' [:tokens "test-token"])] + + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (count (:tokens token-set')) 0)) + (t/is (nil? token')) + (t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))))) + + +(t/testing "token-theme in a lib" + (t/deftest add-token-theme + (let [tokens-lib (ctob/make-tokens-lib) + token-theme (ctob/make-token-theme :name "test-token-theme") + tokens-lib' (ctob/add-theme tokens-lib token-theme) + + token-themes' (ctob/get-themes tokens-lib') + token-theme' (ctob/get-theme tokens-lib' "test-token-theme")] + + (prn "lib" tokens-lib') + (t/is (= (ctob/theme-count tokens-lib') 1)) + (t/is (= (first token-themes') token-theme)) + (t/is (= token-theme' token-theme)))) + + (t/deftest update-token-theme + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-theme (ctob/make-token-theme :name "test-token-theme"))) + + tokens-lib' (-> tokens-lib + (ctob/update-theme "test-token-theme" + (fn [token-theme] + (assoc token-theme + :description "some description"))) + (ctob/update-theme "not-existing-theme" + (fn [token-theme] + (assoc token-theme + :description "no-effect")))) + + token-theme (ctob/get-theme tokens-lib "test-token-theme") + token-theme' (ctob/get-theme tokens-lib' "test-token-theme")] + + (t/is (= (ctob/theme-count tokens-lib') 1)) + (t/is (= (:name token-theme') "test-token-theme")) + (t/is (= (:description token-theme') "some description")) + (t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme))))) + + (t/deftest rename-token-theme + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-theme (ctob/make-token-theme :name "test-token-theme"))) + + tokens-lib' (-> tokens-lib + (ctob/update-theme "test-token-theme" + (fn [token-theme] + (assoc token-theme + :name "updated-name")))) + + token-theme (ctob/get-theme tokens-lib "test-token-theme") + token-theme' (ctob/get-theme tokens-lib' "updated-name")] + + (t/is (= (ctob/theme-count tokens-lib') 1)) + (t/is (= (:name token-theme') "updated-name")) + (t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme))))) + + (t/deftest delete-token-theme + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-theme (ctob/make-token-theme :name "test-token-theme"))) + + tokens-lib' (-> tokens-lib + (ctob/delete-theme "test-token-theme") + (ctob/delete-theme "not-existing-theme")) + + token-theme' (ctob/get-theme tokens-lib' "updated-name")] + + (t/is (= (ctob/theme-count tokens-lib') 0)) + (t/is (nil? token-theme')))) + + (t/deftest toggle-set-in-theme + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "token-set-1")) + (ctob/add-set (ctob/make-token-set :name "token-set-2")) + (ctob/add-set (ctob/make-token-set :name "token-set-3")) + (ctob/add-theme (ctob/make-token-theme :name "test-token-theme"))) + tokens-lib' (-> tokens-lib + (ctob/toggle-set-in-theme "test-token-theme" "token-set-1") + (ctob/toggle-set-in-theme "test-token-theme" "token-set-2") + (ctob/toggle-set-in-theme "test-token-theme" "token-set-2")) + + token-theme (ctob/get-theme tokens-lib "test-token-theme") + token-theme' (ctob/get-theme tokens-lib' "test-token-theme")] + + (t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))) + + +(t/testing "serialization" + (t/deftest transit-serialization + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set")) + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "test-token" + :type :boolean + :value true)) + (ctob/add-theme (ctob/make-token-theme :name "test-token-theme")) + (ctob/toggle-set-in-theme "test-token-theme" "test-token-set")) + encoded-str (tr/encode-str tokens-lib) + tokens-lib' (tr/decode-str encoded-str)] + + (t/is (ctob/valid-tokens-lib? tokens-lib')) + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (ctob/theme-count tokens-lib') 1)))) + + (t/deftest fressian-serialization + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :name "test-token-set")) + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "test-token" + :type :boolean + :value true)) + (ctob/add-theme (ctob/make-token-theme :name "test-token-theme")) + (ctob/toggle-set-in-theme "test-token-theme" "test-token-set")) + encoded-blob (fres/encode tokens-lib) + tokens-lib' (fres/decode encoded-blob)] + + (t/is (ctob/valid-tokens-lib? tokens-lib')) + (t/is (= (ctob/set-count tokens-lib') 1)) + (t/is (= (ctob/theme-count tokens-lib') 1))))) diff --git a/frontend/src/app/main/data/tokens.cljs b/frontend/src/app/main/data/tokens.cljs index 904811b804..820911b826 100644 --- a/frontend/src/app/main/data/tokens.cljs +++ b/frontend/src/app/main/data/tokens.cljs @@ -115,10 +115,9 @@ (ptk/reify ::update-token-theme ptk/WatchEvent (watch [it state _] - (let [prev-token-theme (wtts/get-workspace-token-theme state (:id token-theme)) + (let [prev-token-theme (wtts/get-workspace-token-theme (:id token-theme) state) changes (-> (pcb/empty-changes it) (pcb/update-token-theme token-theme prev-token-theme))] - (js/console.log "changes" changes) (rx/of (dch/commit-changes changes))))))