From 726afaea25d5e212c3884f5a66ff4801054d4c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 15 Jun 2026 20:51:00 +0200 Subject: [PATCH] wip --- common/src/app/common/files/changes.cljc | 7 ++-- .../src/app/common/files/changes_builder.cljc | 11 ++--- common/src/app/common/logic/tokens.cljc | 40 +++++++++++++++--- .../src/app/common/test_helpers/tokens.cljc | 5 ++- common/src/app/common/types/file.cljc | 11 ++--- common/src/app/common/types/token_status.cljc | 42 +++++++++++++------ common/src/app/common/types/tokens_lib.cljc | 20 +++++---- .../common_tests/types/tokens_lib_test.cljc | 10 +++++ frontend/src/app/main/data/helpers.cljs | 16 ++++--- .../data/workspace/tokens/library_edit.cljs | 8 ++-- .../tokens/themes/theme_selector.cljs | 20 ++++----- .../tokens/token_status_test.cljs | 38 +++++++++-------- 12 files changed, 149 insertions(+), 79 deletions(-) diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index b625a14ef1..4fb1385cfa 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -402,7 +402,8 @@ [:map {:title "SetTokenThemeStatus"} [:type [:= :set-token-theme-status]] [:id ::sm/uuid] - [:status :boolean]]] + [:theme-ids [:set ::sm/uuid]] + [:set-ids [:set ::sm/uuid]]]] ;; TODO deprecate this once everyone uses set-token-theme-status [:set-active-token-themes @@ -1050,10 +1051,10 @@ (ctob/make-token-theme (merge prev-token-theme attrs))))))))) (defmethod process-change :set-token-theme-status - [data {:keys [id status]}] + [data {:keys [id theme-ids set-ids]}] (let [data' (ctf/ensure-tokens-lib data)] (-> data' - (ctf/update-token-status ctos/set-theme-status (ctf/get-tokens-lib data') id status)))) + (ctf/update-token-status ctos/set-theme-status id theme-ids set-ids)))) (defmethod process-change :set-active-token-themes [data {:keys [theme-paths]}] diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc index af07b461ba..4e9c35aa69 100644 --- a/common/src/app/common/files/changes_builder.cljc +++ b/common/src/app/common/files/changes_builder.cljc @@ -1022,14 +1022,15 @@ (apply-changes-local)))) (defn set-token-theme-status - [changes id status] + [changes id theme-ids set-ids] (assert-library! changes) (let [library-data (::library-data (meta changes)) - token-status (ctf/get-token-status library-data) - prev-status (ctos/theme-active? token-status id)] + token-status (ctf/get-token-status library-data nil) + prev-theme-ids (ctos/get-active-theme-ids token-status) + prev-set-ids (ctos/get-active-set-ids token-status)] (-> changes - (update :redo-changes conj {:type :set-token-theme-status :id id :status status}) - (update :undo-changes conj {:type :set-token-theme-status :id id :status prev-status}) + (update :redo-changes conj {:type :set-token-theme-status :id id :theme-ids theme-ids :set-ids set-ids}) + (update :undo-changes conj {:type :set-token-theme-status :id id :theme-ids prev-theme-ids :set-ids prev-set-ids}) (apply-changes-local)))) (defn set-active-token-themes diff --git a/common/src/app/common/logic/tokens.cljc b/common/src/app/common/logic/tokens.cljc index aa419c2af1..2363f73d6e 100644 --- a/common/src/app/common/logic/tokens.cljc +++ b/common/src/app/common/logic/tokens.cljc @@ -8,7 +8,8 @@ (:require [app.common.files.changes-builder :as pcb] [app.common.types.token-status :as ctos] - [app.common.types.tokens-lib :as ctob])) + [app.common.types.tokens-lib :as ctob] + [clojure.set :as set])) (defn- generate-update-active-sets "Copy the active sets from the currently active themes and move them @@ -52,16 +53,45 @@ ;; (disj active-token-themes ctob/hidden-theme-path))] ;; (pcb/set-active-token-themes changes active-token-themes'))) +(defn generate-activate-token-theme + [changes token-status tokens-lib id] + (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") + (assert (uuid? id) "expected valid theme id") + (if-not (ctos/theme-active? token-status id) + (if-let [theme (ctob/get-theme tokens-lib id)] + (let [group-themes (into #{} (ctob/get-themes-in-group tokens-lib (:group theme))) + active-theme-ids (ctos/get-active-theme-ids token-status) + active-theme-ids' (-> (set/difference active-theme-ids group-themes) + (conj id)) + active-set-ids' (ctos/calculate-active-sets active-theme-ids' tokens-lib)] + (pcb/set-token-theme-status changes id active-theme-ids' active-set-ids')) + changes) + changes)) + +(defn generate-deactivate-token-theme + [changes token-status tokens-lib id] + (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") + (assert (uuid? id) "expected valid theme id") + (if (ctos/theme-active? token-status id) + (let [active-theme-ids' (disj (ctos/get-active-theme-ids token-status) id) + active-set-ids' (ctos/calculate-active-sets active-theme-ids' tokens-lib)] + (pcb/set-token-theme-status changes id active-theme-ids' active-set-ids')) + changes)) + (defn generate-set-token-theme-status "Activate or deactivate a token theme in `token-status`." - [changes _ id active?] - (pcb/set-token-theme-status changes id (not active?))) + [changes token-status tokens-lib id active?] + (if active? + (generate-activate-token-theme changes token-status tokens-lib id) + (generate-deactivate-token-theme changes token-status tokens-lib id))) (defn generate-toggle-token-theme "Toggle the active status of a token theme in `token-status`." - [changes token-status id] + [changes token-status tokens-lib id] (let [active? (ctos/theme-active? token-status id)] - (pcb/set-token-theme-status changes id (not active?)))) + (if active? + (generate-deactivate-token-theme changes token-status tokens-lib id) + (generate-activate-token-theme changes token-status tokens-lib id)))) (defn toggle-token-set-group "Toggle a token set group at `group-path` in `tokens-lib` for a `tokens-lib-theme`." diff --git a/common/src/app/common/test_helpers/tokens.cljc b/common/src/app/common/test_helpers/tokens.cljc index e0a1733167..164646d0ae 100644 --- a/common/src/app/common/test_helpers/tokens.cljc +++ b/common/src/app/common/test_helpers/tokens.cljc @@ -21,7 +21,7 @@ (defn get-token-status [file] - (-> file (ctf/file-data) (ctf/get-token-status))) + (-> file (ctf/file-data) (ctf/get-token-status nil))) (defn add-tokens-lib "Ensure the file has a tokens-lib and a token-statusin its data, creating empty ones if not" @@ -35,7 +35,8 @@ (defn update-token-status [file f] - (ctf/update-file-data file #(ctf/update-token-status % f))) + (let [tokens-lib (get-tokens-lib file)] + (ctf/update-file-data file #(ctf/update-token-status % f tokens-lib)))) (defn sample-file-with-tokens [tokens-lib-fn token-status-fn] (-> (thf/sample-file :file1) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index b2f7f0c9d1..baadd4a842 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -323,11 +323,12 @@ (:tokens-lib file-data)) (defn get-token-status - [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 - (ctos/make-token-status-from-lib (:tokens-lib file-data)) - (:token-status file-data))) + [file-data tokens-file-data] + (let [tokens-file-data (or tokens-file-data file-data)] + (if (and (some? (:tokens-lib tokens-file-data)) (nil? (:token-status file-data))) + ;; TODO: remove this when we deprecate old-style files without token-status + (ctos/make-token-status-from-lib (:tokens-lib tokens-file-data)) + (:token-status file-data)))) (defn update-tokens-lib "Update the tokens-lib inside file-data through a callback function. diff --git a/common/src/app/common/types/token_status.cljc b/common/src/app/common/types/token_status.cljc index d499e2de9a..3a1370d218 100644 --- a/common/src/app/common/types/token_status.cljc +++ b/common/src/app/common/types/token_status.cljc @@ -8,6 +8,7 @@ (:require #?(:clj [app.common.fressian :as fres]) #?(:clj [clojure.data.json :as c.json]) + [app.common.data :as d] [app.common.schema :as sm] [app.common.schema.generators :as sg] [app.common.transit :as t] @@ -25,6 +26,9 @@ (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") + (get-active-theme-ids [_] "Return a clojure set of active theme ids") + (get-active-set-ids [_] "Return a clojure set of active set ids") + (active-themes [_ tokens-lib] "Return an ordered sequence of active themes") (active-themes-count [_] "Return the number of active themes") (activate-set [_ set-id] "Add a set to active sets") (deactivate-set [_ set-id] "Remove a set from active sets") @@ -45,21 +49,27 @@ (c.json/-write (datafy this) writter options))]) ITokenStatus + (get-active-theme-ids [_] + active-theme-ids) + + (get-active-set-ids [_] + active-set-ids) + (activate-theme [this tokens-lib theme-id] - (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") + ;; (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") (assert (uuid? theme-id) "expected valid theme-id") (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)) + (let [group-themes (into #{} (ctob/get-themes-in-group tokens-lib (:group theme))) active-theme-ids' (-> (set/difference active-theme-ids group-themes) - (conj theme-id))] + (conj theme-id))] (TokenStatus. active-theme-ids' (calculate-active-sets active-theme-ids' tokens-lib))) this) this)) (deactivate-theme [this tokens-lib theme-id] - (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") + ;; (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") (assert (uuid? theme-id) "expected valid theme-id") (if (theme-active? this theme-id) (let [active-theme-ids' (disj active-theme-ids theme-id)] @@ -67,18 +77,25 @@ (calculate-active-sets active-theme-ids' tokens-lib))) this)) - (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 tokens-lib theme-id) - (deactivate-theme this tokens-lib theme-id))) + ;; (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 tokens-lib theme-id) + ;; (deactivate-theme this tokens-lib theme-id))) + + (set-theme-status [_ _id theme-ids set-ids] + (TokenStatus. theme-ids set-ids)) (theme-active? [_ theme-id] (assert (uuid? theme-id) "expected valid theme-id") (contains? active-theme-ids theme-id)) + (active-themes [this tokens-lib] + (->> (ctob/get-themes tokens-lib) + (filter #(theme-active? this (ctob/get-id %))))) + (active-themes-count [_] (count active-theme-ids)) @@ -103,7 +120,7 @@ (active-set-count [_] (count active-set-ids))) -(defn- calculate-active-sets +(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)) @@ -162,6 +179,7 @@ (ctob/get-active-themes tokens-lib)) active-set-ids (into #{} (comp (map #(ctob/get-set-by-name tokens-lib %)) + (remove nil?) (map ctob/get-id)) (ctob/get-active-themes-set-names tokens-lib))] (make-token-status :active-theme-ids active-theme-ids diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index cfa9d0d69d..ffc816d40e 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -755,11 +755,15 @@ (def ^:private theme-separator "/") -(defn- join-theme-path [group name] - (cpn/join-path [group name] :separator theme-separator :with-spaces? false)) +(defn- join-theme-path [group name with-spaces?] + (let [path (if (and (str/empty? group) with-spaces?) [name] [group name])] + (cpn/join-path path :separator theme-separator :with-spaces? with-spaces?))) -(defn get-theme-path [theme] - (join-theme-path (:group theme) (:name theme))) +(defn get-theme-path + ([theme] + (get-theme-path theme false)) + ([theme with-spaces?] + (join-theme-path (:group theme) (:name theme) with-spaces?))) (defn split-theme-path [path] (cpn/split-group-name path @@ -767,7 +771,7 @@ :with-spaces? false)) (def hidden-theme-path - (join-theme-path hidden-theme-group hidden-theme-name)) + (join-theme-path hidden-theme-group hidden-theme-name false)) ;; === TokenThemes (collection) @@ -1179,7 +1183,7 @@ Will return a value that matches this schema: (d/dissoc-in [group name]))) (if same-path? active-themes - (disj active-themes (join-theme-path group name))))))) + (disj active-themes (join-theme-path group name false))))))) this)) (delete-theme [this id] @@ -1188,14 +1192,14 @@ Will return a value that matches this schema: (if theme (TokensLib. sets (d/dissoc-in themes [group name]) - (disj active-themes (join-theme-path group name))) + (disj active-themes (join-theme-path group name false))) this))) (get-theme-tree [_] themes) (get-theme-tree-no-hidden [_] - (dissoc themes hidden-theme-group)) + (d/dissoc-in themes [hidden-theme-group hidden-theme-name])) (get-theme-groups [_] (into [] (comp diff --git a/common/test/common_tests/types/tokens_lib_test.cljc b/common/test/common_tests/types/tokens_lib_test.cljc index bb2d5cf204..b3a1e54864 100644 --- a/common/test/common_tests/types/tokens_lib_test.cljc +++ b/common/test/common_tests/types/tokens_lib_test.cljc @@ -247,6 +247,16 @@ theme' (ctob/toggle-set theme nil)] (t/is (= (:sets theme') #{}))))) +(t/deftest get-theme-path + (let [theme1 (ctob/make-token-theme :name "theme1") + theme2 (ctob/make-token-theme :group "group1" :name "theme2")] + (t/is (= "/theme1" (ctob/get-theme-path theme1))) ;; TODO perhaps we should remove the leading / + (t/is (= "/theme1" (ctob/get-theme-path theme1 false))) ;; but this may be a breaking change + (t/is (= " / theme1" (ctob/get-theme-path theme1 true))) + (t/is (= "group1/theme2" (ctob/get-theme-path theme2))) + (t/is (= "group1/theme2" (ctob/get-theme-path theme2 false))) + (t/is (= "group1 / theme2" (ctob/get-theme-path theme2 true))))) + (t/deftest make-tokens-lib (let [tokens-lib (ctob/make-tokens-lib)] (t/is (= (ctob/set-count tokens-lib) 0)))) diff --git a/frontend/src/app/main/data/helpers.cljs b/frontend/src/app/main/data/helpers.cljs index dd74cf292e..5fa3d2edb9 100644 --- a/frontend/src/app/main/data/helpers.cljs +++ b/frontend/src/app/main/data/helpers.cljs @@ -38,17 +38,23 @@ ([state file-id] (dm/get-in state [:files file-id :data]))) -(defn lookup-tokens-lib +(defn lookup-tokens-file-data [state] (let [current-file-data (lookup-file-data state) - tokens-file-id (or (:tokens-file current-file-data) (:id current-file-data)) - tokens-file-data (lookup-file-data state tokens-file-id)] + tokens-file-id (or (:tokens-file current-file-data) (:id current-file-data))] + (lookup-file-data state tokens-file-id))) + +(defn lookup-tokens-lib + [state] + (let [tokens-file-data (lookup-tokens-file-data state)] (ctf/get-tokens-lib tokens-file-data))) (defn lookup-token-status [state] - (let [current-file-data (lookup-file-data state)] - (ctf/get-token-status current-file-data))) + (let [current-file-data (lookup-file-data state) + tokens-file-id (or (:tokens-file current-file-data) (:id current-file-data)) + tokens-file-data (lookup-file-data state tokens-file-id)] + (ctf/get-token-status current-file-data tokens-file-data))) (defn get-page [fdata page-id] diff --git a/frontend/src/app/main/data/workspace/tokens/library_edit.cljs b/frontend/src/app/main/data/workspace/tokens/library_edit.cljs index d6f3170d7f..9b47ff2b8e 100644 --- a/frontend/src/app/main/data/workspace/tokens/library_edit.cljs +++ b/frontend/src/app/main/data/workspace/tokens/library_edit.cljs @@ -269,9 +269,10 @@ (watch [_ state _] (let [data (dsh/lookup-file-data state) token-status (dsh/lookup-token-status state) + tokens-lib (dsh/lookup-tokens-lib state) changes (-> (pcb/empty-changes) (pcb/with-library-data data) - (clt/generate-set-token-theme-status token-status id active?))] + (clt/generate-set-token-theme-status token-status tokens-lib id active?))] (rx/of (dch/commit-changes changes) (dwtp/propagate-workspace-tokens)))))) @@ -281,11 +282,12 @@ (ptk/reify ::toggle-token-theme-active ptk/WatchEvent (watch [it state _] - (let [data (dsh/lookup-file-data state) + (let [data (dsh/lookup-tokens-file-data state) token-status (dsh/lookup-token-status state) + tokens-lib (dsh/lookup-tokens-lib state) changes (-> (pcb/empty-changes it) (pcb/with-library-data data) - (clt/generate-toggle-token-theme token-status id))] + (clt/generate-toggle-token-theme token-status tokens-lib id))] (rx/of (dch/commit-changes changes) (dwtp/propagate-workspace-tokens)))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/themes/theme_selector.cljs b/frontend/src/app/main/ui/workspace/tokens/themes/theme_selector.cljs index cc02d29a44..4500c0722c 100644 --- a/frontend/src/app/main/ui/workspace/tokens/themes/theme_selector.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/themes/theme_selector.cljs @@ -66,7 +66,6 @@ [:> text* {:as "span" :typography "headline-small" :class (stl/css :group) :id (dm/str (str/kebab group) "-label") :title group} group]) [:> themes-list* {:themes themes :token-status token-status - ;; :active-theme-paths active-theme-paths :on-close on-close :is-grouped true}]]) [:li {:class (stl/css :separator) @@ -81,22 +80,19 @@ (mf/defc theme-selector* [{:keys []}] (let [;; Store - tokens-lib (mf/use-ctx ctx/tokens-lib) - token-status (mf/use-ctx ctx/token-status) + tokens-lib (mf/use-ctx ctx/tokens-lib) + token-status (mf/use-ctx ctx/token-status) - active-themes-count (ctos/active-themes-count token-status) - active-theme-paths (-> (ctob/get-active-theme-paths tokens-lib) ;; TODO replace by a call to ctos - (disj ctob/hidden-theme-path)) + active-themes (ctos/active-themes token-status tokens-lib) + active-themes-count (count active-themes) can-edit? (:can-edit (deref refs/permissions)) ;; Data current-label (cond (> active-themes-count 1) (tr "workspace.tokens.active-themes" active-themes-count) - (= active-themes-count 1) (some->> (first active-theme-paths) - (ctob/split-theme-path) - (remove empty?) - (str/join " / ")) + (= active-themes-count 1) (-> (first active-themes) + (ctob/get-theme-path true)) :else (tr "workspace.tokens.no-active-theme")) ;; State @@ -148,9 +144,7 @@ [:& dropdown {:show is-open? :on-close on-close-dropdown} - [:> theme-options* {;;:active-theme-paths active-theme-paths - ;;:themes themes - :tokens-lib tokens-lib + [:> theme-options* {:tokens-lib tokens-lib :token-status token-status :on-close on-close-dropdown}]]]) container))])) diff --git a/frontend/test/frontend_tests/tokens/token_status_test.cljs b/frontend/test/frontend_tests/tokens/token_status_test.cljs index 8d14c58965..e373af6757 100644 --- a/frontend/test/frontend_tests/tokens/token_status_test.cljs +++ b/frontend/test/frontend_tests/tokens/token_status_test.cljs @@ -16,25 +16,27 @@ (-> (thf/sample-file :file1) (tht/add-tokens-lib) (tht/update-tokens-lib - #(-> % - ;; Add token sets - (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-active) - :name "set-active")) - (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-inactive) - :name "set-inactive")) - ;; Add themes - (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-active) - :name "theme-active" - :group "group-1" - :sets #{"set-active"})) - (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-inactive) - :name "theme-inactive" - :group "group-1" - :sets #{"set-inactive"})))) + (fn [tokens-lib] + (-> tokens-lib + ;; Add token sets + (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-active) + :name "set-active")) + (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-inactive) + :name "set-inactive")) + ;; Add themes + (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-active) + :name "theme-active" + :group "group-1" + :sets #{"set-active"})) + (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-inactive) + :name "theme-inactive" + :group "group-1" + :sets #{"set-inactive"}))))) (tht/update-token-status - #(-> % - (ctos/activate-theme (thi/id :theme-active)) - (ctos/activate-set (thi/id :set-active)))))) + (fn [token-status tokens-lib] + (-> token-status + (ctos/activate-theme tokens-lib (thi/id :theme-active)) + (ctos/activate-set (thi/id :set-active))))))) (t/deftest test-token-status-active-inactive (t/testing "lookup helpers and active checks"