From e7e7b2a4b314dc19e85f8283a4ceefd88b003cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 12 Jun 2026 16:41:47 +0200 Subject: [PATCH] wip --- common/src/app/common/files/changes.cljc | 5 +- common/src/app/common/files/tokens.cljc | 28 ----- common/src/app/common/types/file.cljc | 5 +- common/src/app/common/types/token_status.cljc | 106 ++++++++++++------ common/src/app/common/types/tokens_lib.cljc | 5 + .../test/common_tests/files/tokens_test.cljc | 44 -------- common/test/common_tests/types/file_test.cljc | 1 + .../common_tests/types/token_status_test.cljc | 81 +++++++++---- 8 files changed, 144 insertions(+), 131 deletions(-) diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index 7fa87eb692..b625a14ef1 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -1051,8 +1051,9 @@ (defmethod process-change :set-token-theme-status [data {:keys [id status]}] - (-> (ctf/ensure-tokens-lib data) - (ctf/update-token-status ctos/set-theme-status id status))) + (let [data' (ctf/ensure-tokens-lib data)] + (-> data' + (ctf/update-token-status ctos/set-theme-status (ctf/get-tokens-lib data') id status)))) (defmethod process-change :set-active-token-themes [data {:keys [theme-paths]}] diff --git a/common/src/app/common/files/tokens.cljc b/common/src/app/common/files/tokens.cljc index 1efaaa75c5..8c95b4c582 100644 --- a/common/src/app/common/files/tokens.cljc +++ b/common/src/app/common/files/tokens.cljc @@ -376,31 +376,3 @@ ;; FIXME: this should be precalculated ? (defn is-reference? [token] (str/includes? (:value token) "{")) - -;; Tokens status - -(defn make-token-status-from-lib - "Make a TokenStatus from a TokensLib, activating the themes and sets - marked as active in the library (to migrate from legacy files)." - [tokens-lib] - (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") - (let [active-themes (into #{} - (comp (map :id) - (filter #(not= % ctob/hidden-theme-id))) - (ctob/get-active-themes tokens-lib)) - active-sets (into #{} - (comp (map #(ctob/get-set-by-name tokens-lib %)) - (map ctob/get-id)) - (ctob/get-active-themes-set-names tokens-lib))] - (ctos/make-token-status :active-themes active-themes - :active-sets active-sets))) - -(defn set-theme-status - [token-status tokens-lib theme-id status] - (assert (ctos/token-status? token-status) "expected valid token-status") - (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") - (assert (uuid? theme-id) "expected valid theme-id") - (assert (boolean? status) "expected boolean status") - (if (ctob/get-theme tokens-lib theme-id) - (ctos/set-theme-status token-status theme-id status) - token-status)) \ No newline at end of file diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 81ac15a584..b2f7f0c9d1 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -11,7 +11,6 @@ [app.common.features :as cfeat] [app.common.files.defaults :refer [version]] [app.common.files.helpers :as cfh] - [app.common.files.tokens :as cfo] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.geom.shapes.tree-seq :as gsts] @@ -204,7 +203,7 @@ [file-data] (if (and (some? (:tokens-lib file-data)) (nil? (:token-status file-data))) ;; TODO: remove this when we deprecate old-style files without token-status - (assoc file-data :token-status (cfo/make-token-status-from-lib (:tokens-lib file-data))) + (assoc file-data :token-status (ctos/make-token-status-from-lib (:tokens-lib file-data))) (-> file-data (update :tokens-lib #(or % (ctob/make-tokens-lib))) (update :token-status #(or % (ctos/make-token-status)))))) @@ -327,7 +326,7 @@ [file-data] (if (and (some? (:tokens-lib file-data)) (nil? (:token-status file-data))) ;; TODO: remove this when we deprecate old-style files without token-status - (cfo/make-token-status-from-lib (:tokens-lib file-data)) + (ctos/make-token-status-from-lib (:tokens-lib file-data)) (:token-status file-data))) (defn update-tokens-lib diff --git a/common/src/app/common/types/token_status.cljc b/common/src/app/common/types/token_status.cljc index bc5a4db3b7..d499e2de9a 100644 --- a/common/src/app/common/types/token_status.cljc +++ b/common/src/app/common/types/token_status.cljc @@ -11,30 +11,33 @@ [app.common.schema :as sm] [app.common.schema.generators :as sg] [app.common.transit :as t] + [app.common.types.tokens-lib :as ctob] [clojure.core.protocols :as cp] [clojure.datafy :refer [datafy]] - [clojure.pprint :as pp])) + [clojure.pprint :as pp] + [clojure.set :as set])) ;; TokenStatus datatype contains the status of the active themes and sets ;; in a tokens library. (defprotocol ITokenStatus - (activate-theme [_ theme-id] "Add a theme uuid to active themes") - (deactivate-theme [_ theme-id] "Remove a theme uuid from active themes") - (set-theme-status [_ theme-id status] "Add or remove a theme uuid to active themes") - (theme-active? [_ theme-id] "Check if a theme uuid is active") + (activate-theme [_ tokens-lib theme-id] "Activate a theme and deactivate other themes in the same group. Update active sets.") + (deactivate-theme [_ tokens-lib theme-id] "Deactivate a theme and update active sets") + (set-theme-status [_ tokens-lib theme-id status] "Set the activation status of a theme") + (theme-active? [_ theme-id] "Check if a theme is active") (active-themes-count [_] "Return the number of active themes") - (activate-set [_ set-id] "Add a set uuid to active sets") - (deactivate-set [_ set-id] "Remove a set uuid from active sets") - (toggle-set-active [_ set-id] "Toggle a set uuid in active sets") - (set-active? [_ set-id] "Check if a set uuid is active") + (activate-set [_ set-id] "Add a set to active sets") + (deactivate-set [_ set-id] "Remove a set from active sets") + (toggle-set-active [_ set-id] "Toggle a set in active sets") + (set-active? [_ set-id] "Check if a set is active") (active-set-count [_] "Return the number of active sets")) -(deftype TokenStatus [active-themes active-sets] +(declare calculate-active-sets) +(deftype TokenStatus [active-theme-ids active-set-ids] cp/Datafiable (datafy [_] - {:active-themes active-themes - :active-sets active-sets}) + {:active-theme-ids active-theme-ids + :active-set-ids active-set-ids}) #?@(:clj [c.json/JSONWriter @@ -42,54 +45,77 @@ (c.json/-write (datafy this) writter options))]) ITokenStatus - (activate-theme [_ theme-id] + (activate-theme [this tokens-lib theme-id] + (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") (assert (uuid? theme-id) "expected valid theme-id") - (TokenStatus. (conj active-themes theme-id) active-sets)) + (if-not (theme-active? this theme-id) + (if-let [theme (ctob/get-theme tokens-lib theme-id)] + (let [group-themes (ctob/get-themes-in-group tokens-lib (:group theme)) + active-theme-ids' (-> (set/difference active-theme-ids group-themes) + (conj theme-id))] + (TokenStatus. active-theme-ids' + (calculate-active-sets active-theme-ids' tokens-lib))) + this) + this)) - (deactivate-theme [_ theme-id] + (deactivate-theme [this tokens-lib theme-id] + (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") (assert (uuid? theme-id) "expected valid theme-id") - (TokenStatus. (disj active-themes theme-id) active-sets)) + (if (theme-active? this theme-id) + (let [active-theme-ids' (disj active-theme-ids theme-id)] + (TokenStatus. active-theme-ids' + (calculate-active-sets active-theme-ids' tokens-lib))) + this)) - (set-theme-status [this theme-id status] + (set-theme-status [this tokens-lib theme-id status] + (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") (assert (uuid? theme-id) "expected valid theme-id") (assert (boolean? status) "expected boolean status") (if status - (activate-theme this theme-id) - (deactivate-theme this theme-id))) + (activate-theme this tokens-lib theme-id) + (deactivate-theme this tokens-lib theme-id))) (theme-active? [_ theme-id] (assert (uuid? theme-id) "expected valid theme-id") - (contains? active-themes theme-id)) + (contains? active-theme-ids theme-id)) (active-themes-count [_] - (count active-themes)) + (count active-theme-ids)) (activate-set [_ set-id] (assert (uuid? set-id) "expected valid set-id") - (TokenStatus. active-themes (conj active-sets set-id))) + (TokenStatus. active-theme-ids (conj active-set-ids set-id))) (deactivate-set [_ set-id] (assert (uuid? set-id) "expected valid set-id") - (TokenStatus. active-themes (disj active-sets set-id))) + (TokenStatus. active-theme-ids (disj active-set-ids set-id))) (toggle-set-active [this set-id] (assert (uuid? set-id) "expected valid set-id") - (if (contains? active-sets set-id) + (if (contains? active-set-ids set-id) (deactivate-set this set-id) (activate-set this set-id))) (set-active? [_ set-id] (assert (uuid? set-id) "expected valid set-id") - (contains? active-sets set-id)) + (contains? active-set-ids set-id)) (active-set-count [_] - (count active-sets))) + (count active-set-ids))) + +(defn- calculate-active-sets + [active-theme-ids tokens-lib] + (let [active-themes (map #(ctob/get-theme tokens-lib %) active-theme-ids) ;; OJOOOOOOOOOOOOOOOOOOOOO + active-set-names (reduce set/union #{} (map :sets active-themes)) + active-sets (map #(ctob/get-set-by-name tokens-lib %) active-set-names) + active-set-ids (into #{} (map ctob/get-id) active-sets)] + active-set-ids)) ;; === Helper & Predicate === (defn map->TokenStatus - [{:keys [active-themes active-sets]}] - (TokenStatus. active-themes active-sets)) + [{:keys [active-theme-ids active-set-ids]}] + (TokenStatus. active-theme-ids active-set-ids)) (defn token-status? [o] @@ -101,8 +127,8 @@ (def schema:token-status-attrs [:map {:title "TokenStatus"} - [:active-themes [:set {:gen/max 5} ::sm/uuid]] - [:active-sets [:set {:gen/max 5} ::sm/uuid]]]) + [:active-theme-ids [:set {:gen/max 5} ::sm/uuid]] + [:active-set-ids [:set {:gen/max 5} ::sm/uuid]]]) (def schema:token-status [:and {:gen/gen (->> (sg/generator schema:token-status-attrs) @@ -120,11 +146,27 @@ (defn make-token-status [& {:as attrs}] (-> attrs - (update :active-themes #(or % #{})) - (update :active-sets #(or % #{})) + (update :active-theme-ids #(or % #{})) + (update :active-set-ids #(or % #{})) (check-token-status-attrs) (map->TokenStatus))) +(defn make-token-status-from-lib + "Make a TokenStatus from a TokensLib, activating the themes and sets + marked as active in the library (to migrate from legacy files)." + [tokens-lib] + (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") + (let [active-theme-ids (into #{} + (comp (map :id) + (filter #(not= % ctob/hidden-theme-id))) + (ctob/get-active-themes tokens-lib)) + active-set-ids (into #{} + (comp (map #(ctob/get-set-by-name tokens-lib %)) + (map ctob/get-id)) + (ctob/get-active-themes-set-names tokens-lib))] + (make-token-status :active-theme-ids active-theme-ids + :active-set-ids active-set-ids))) + ;; === Pretty-print for debugging === (defmethod pp/simple-dispatch TokenStatus [^TokenStatus obj] diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index d30e83e6be..cfa9d0d69d 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -780,6 +780,7 @@ (get-theme-tree [_] "get a nested tree of all themes in the library") (get-theme-tree-no-hidden [_] "get a nested tree of all themes in the library except the hidden theme") (get-themes [_] "get an ordered sequence of all themes in the library") + (get-themes-in-group [_ group] "get an ordered sequence of the themes in the group") (get-theme [_ id] "get one theme looking for id") (get-theme-by-name [_ group name] "get one theme looking for group and name") (get-theme-groups [_] "get a sequence of group names by order") @@ -1206,6 +1207,10 @@ Will return a value that matches this schema: (->> (tree-seq d/ordered-map? vals themes) (filter (partial instance? TokenTheme)))) + (get-themes-in-group [_ group] + (->> (get themes group) + (map (comp get-id val)))) + (theme-count [this] (count (get-themes this))) diff --git a/common/test/common_tests/files/tokens_test.cljc b/common/test/common_tests/files/tokens_test.cljc index 8d9dafed6c..8052cbc981 100644 --- a/common/test/common_tests/files/tokens_test.cljc +++ b/common/test/common_tests/files/tokens_test.cljc @@ -7,11 +7,6 @@ (ns common-tests.files.tokens-test (:require [app.common.files.tokens :as cfo] - [app.common.test-helpers.files :as thf] - [app.common.test-helpers.ids-map :as thi] - [app.common.test-helpers.tokens :as tht] - [app.common.types.token-status :as ctos] - [app.common.types.tokens-lib :as ctob] [clojure.test :as t])) (t/deftest test-parse-token-value @@ -85,42 +80,3 @@ (t/is (nil? (cfo/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}} {:applied-tokens {:x "a"}}] #{:y}))))) - -;; Make TokenStatus from a TokensLib (to migrate from legacy files) -(t/deftest make-token-status-from-tokens-lib - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) - :name "set-a")) - (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-b) - :name "set-b")) - (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-c) - :name "set-c")) - (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-d) - :name "set-d")) - (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-1) - :name "theme-1" - :sets #{"set-a" "set-b"})) - (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-2) - :name "theme-2" - :sets #{"set-b"})) - (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-3) - :name "theme-3" - :sets #{"set-c" "set-d"})) - (ctob/set-active-themes #{"/theme-1" "/theme-2"})) - token-status (cfo/make-token-status-from-lib tokens-lib)] - (t/is (ctos/token-status? token-status)) - (t/is (ctos/check-token-status token-status)) - (t/is (= (ctos/active-themes-count token-status) 2)) - (t/is (ctos/theme-active? token-status (thi/id :theme-1))) - (t/is (ctos/theme-active? token-status (thi/id :theme-2))) - (t/is (= (ctos/active-set-count token-status) 2)) - (t/is (ctos/set-active? token-status (thi/id :set-a))) - (t/is (ctos/set-active? token-status (thi/id :set-b))))) - -(t/deftest set-theme-status - (t/testing "setting the status of a theme gets it activated or deactivated" - (let [tokens-lib (-> (ctob/make-tokens-lib) - (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme1) :name "theme"))) - token-status (ctos/make-token-status) - token-status' (cfo/set-theme-status token-status tokens-lib (thi/id :theme1) true)] - (t/is (ctos/theme-active? token-status' (thi/id :theme1)))))) diff --git a/common/test/common_tests/types/file_test.cljc b/common/test/common_tests/types/file_test.cljc index 106355883f..59c433d567 100644 --- a/common/test/common_tests/types/file_test.cljc +++ b/common/test/common_tests/types/file_test.cljc @@ -94,6 +94,7 @@ #(ctf/update-token-status % ctos/activate-theme + (tht/get-tokens-lib file) (thi/id :theme1))) token-status' (tht/get-token-status file')] (t/is (= 1 (ctos/active-themes-count token-status'))) diff --git a/common/test/common_tests/types/token_status_test.cljc b/common/test/common_tests/types/token_status_test.cljc index aa1f763ad8..21febe3e37 100644 --- a/common/test/common_tests/types/token_status_test.cljc +++ b/common/test/common_tests/types/token_status_test.cljc @@ -19,8 +19,8 @@ (t/deftest make-token-status (let [theme-id (uuid/next) set-id (uuid/next) - status (ctos/make-token-status :active-themes #{theme-id} - :active-sets #{set-id})] + status (ctos/make-token-status :active-theme-ids #{theme-id} + :active-set-ids #{set-id})] (t/is (ctos/token-status? status)) (t/is (ctos/check-token-status status)) (t/is (= (ctos/active-themes-count status) 1)) @@ -39,33 +39,70 @@ (t/testing "non-set for active-themes" (t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid params for token-status" - (ctos/make-token-status :active-themes [])))) + (ctos/make-token-status :active-theme-ids [])))) (t/testing "non-uuid in active-sets" (t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid params for token-status" - (ctos/make-token-status :active-sets #{"not-a-uuid"}))))) + (ctos/make-token-status :active-set-ids #{"not-a-uuid"}))))) + +;; Make TokenStatus from a TokensLib (to migrate from legacy files) +(t/deftest make-token-status-from-tokens-lib + (let [tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) + :name "set-a")) + (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-b) + :name "set-b")) + (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-c) + :name "set-c")) + (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-d) + :name "set-d")) + (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-1) + :name "theme-1" + :sets #{"set-a" "set-b"})) + (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-2) + :name "theme-2" + :sets #{"set-b"})) + (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-3) + :name "theme-3" + :sets #{"set-c" "set-d"})) + (ctob/set-active-themes #{"/theme-1" "/theme-2"})) + token-status (ctos/make-token-status-from-lib tokens-lib)] + (t/is (ctos/token-status? token-status)) + (t/is (ctos/check-token-status token-status)) + (t/is (= (ctos/active-themes-count token-status) 2)) + (t/is (ctos/theme-active? token-status (thi/id :theme-1))) + (t/is (ctos/theme-active? token-status (thi/id :theme-2))) + (t/is (= (ctos/active-set-count token-status) 2)) + (t/is (ctos/set-active? token-status (thi/id :set-a))) + (t/is (ctos/set-active? token-status (thi/id :set-b))))) (t/deftest activate-theme (let [theme-id (uuid/next) + tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-theme (ctob/make-token-theme :id theme-id :name "theme"))) status (ctos/make-token-status) - status' (ctos/activate-theme status theme-id)] + status' (ctos/activate-theme status tokens-lib theme-id)] (t/is (not (ctos/theme-active? status theme-id))) (t/is (ctos/theme-active? status' theme-id)) (t/is (= (ctos/active-themes-count status') 1)))) (t/deftest deactivate-theme (let [theme-id (uuid/next) - status (ctos/make-token-status :active-themes #{theme-id}) - status' (ctos/deactivate-theme status theme-id)] + tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-theme (ctob/make-token-theme :id theme-id :name "theme"))) + status (ctos/make-token-status :active-theme-ids #{theme-id}) + status' (ctos/deactivate-theme status tokens-lib theme-id)] (t/is (ctos/theme-active? status theme-id)) (t/is (not (ctos/theme-active? status' theme-id))) (t/is (= (ctos/active-themes-count status') 0)))) (t/deftest set-theme-status (let [theme-id (uuid/next) + tokens-lib (-> (ctob/make-tokens-lib) + (ctob/add-theme (ctob/make-token-theme :id theme-id :name "theme"))) status (ctos/make-token-status) - status' (ctos/set-theme-status status theme-id true) - status'' (ctos/set-theme-status status' theme-id false)] + status' (ctos/set-theme-status status tokens-lib theme-id true) + status'' (ctos/set-theme-status status' tokens-lib theme-id false)] (t/is (ctos/theme-active? status' theme-id)) (t/is (not (ctos/theme-active? status'' theme-id))) (t/is (= (ctos/active-themes-count status') 1)) @@ -81,7 +118,7 @@ (t/deftest deactivate-set (let [set-id (uuid/next) - status (ctos/make-token-status :active-sets #{set-id}) + status (ctos/make-token-status :active-set-ids #{set-id}) status' (ctos/deactivate-set status set-id)] (t/is (ctos/set-active? status set-id)) (t/is (not (ctos/set-active? status' set-id))) @@ -100,19 +137,19 @@ (t/deftest datafy-token-status (let [theme-id (uuid/next) set-id (uuid/next) - status (ctos/make-token-status :active-themes #{theme-id} - :active-sets #{set-id}) + status (ctos/make-token-status :active-theme-ids #{theme-id} + :active-set-ids #{set-id}) result (datafy status)] (t/is (map? result)) (t/is (not (ctos/token-status? result))) - (t/is (= (:active-themes result) #{theme-id})) - (t/is (= (:active-sets result) #{set-id})))) + (t/is (= (:active-theme-ids result) #{theme-id})) + (t/is (= (:active-set-ids result) #{set-id})))) (t/deftest transit-serialization (let [theme-id (uuid/next) set-id (uuid/next) - status (ctos/make-token-status :active-themes #{theme-id} - :active-sets #{set-id}) + status (ctos/make-token-status :active-theme-ids #{theme-id} + :active-set-ids #{set-id}) encoded (tr/encode-str status) status' (tr/decode-str encoded)] (t/is (ctos/token-status? status')) @@ -122,8 +159,8 @@ (t/deftest fressian-serialization (let [theme-id (uuid/next) set-id (uuid/next) - status (ctos/make-token-status :active-themes #{theme-id} - :active-sets #{set-id}) + status (ctos/make-token-status :active-theme-ids #{theme-id} + :active-set-ids #{set-id}) encoded (fres/encode status) status' (fres/decode encoded)] (t/is (ctos/token-status? status')) @@ -133,10 +170,10 @@ (t/deftest json-serialization (let [theme-id (uuid/next) set-id (uuid/next) - status (ctos/make-token-status :active-themes #{theme-id} - :active-sets #{set-id}) + status (ctos/make-token-status :active-theme-ids #{theme-id} + :active-set-ids #{set-id}) json-str (json/write-str status) parsed (json/read-str json-str :key-fn keyword)] (t/is (map? parsed)) - (t/is (= [(str theme-id)] (:active-themes parsed))) - (t/is (= [(str set-id)] (:active-sets parsed)))))) + (t/is (= [(str theme-id)] (:active-theme-ids parsed))) + (t/is (= [(str set-id)] (:active-set-ids parsed))))))