Merge pull request #283 from tokens-studio/refactor-types-2

Refactor types 2
This commit is contained in:
Florian Schrödl 2024-09-17 09:44:00 +02:00 committed by GitHub
commit 0697e69888
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 1332 additions and 280 deletions

View file

@ -57,6 +57,54 @@
#?(:cljs (instance? lkm/LinkedMap o) #?(:cljs (instance? lkm/LinkedMap o)
:clj (instance? LinkedMap o))) :clj (instance? LinkedMap o)))
(defn oassoc
[o & kvs]
(apply assoc (or o (ordered-map)) kvs))
(defn oassoc-in
[o [k & ks] v]
(if ks
(oassoc o k (oassoc-in (get o k) ks v))
(oassoc o k v)))
(defn oupdate-in
[m ks f & args]
(let [up (fn up [m ks f args]
(let [[k & ks] ks]
(if ks
(oassoc m k (up (get m k) ks f args))
(oassoc m k (apply f (get m k) args)))))]
(up m ks f args)))
(declare index-of)
(defn oassoc-before
"Assoc a k v pair, in the order position just before the other key"
[o before-k k v]
(if-let [index (index-of (keys o) before-k)]
(-> (ordered-map)
(into (take index o))
(assoc k v)
(into (drop index o)))
(oassoc o k v)))
(defn oassoc-in-before
[o [before-k & before-ks] [k & ks] v]
(if-let [index (index-of (keys o) before-k)]
(let [new-v (if ks
(oassoc-in-before (get o k) before-ks ks v)
v)]
(if (= k before-k)
(-> (ordered-map)
(into (take index o))
(assoc k new-v)
(into (drop (inc index) o)))
(-> (ordered-map)
(into (take index o))
(assoc k new-v)
(into (drop index o)))))
(oassoc-in o (cons k ks) v)))
(defn vec2 (defn vec2
"Creates a optimized vector compatible type of length 2 backed "Creates a optimized vector compatible type of length 2 backed
internally with MapEntry impl because it has faster access method internally with MapEntry impl because it has faster access method
@ -564,6 +612,7 @@
new-elems new-elems
(remove p? after)))) (remove p? after))))
;; TODO: remove this
(defn addm-at-index (defn addm-at-index
"Insert an element in an ordered map at an arbitrary index" "Insert an element in an ordered map at an arbitrary index"
[coll index key element] [coll index key element]

View file

@ -263,7 +263,8 @@
[:delete-temporary-token-theme [:delete-temporary-token-theme
[:map {:title "DeleteTemporaryTokenThemeChange"} [:map {:title "DeleteTemporaryTokenThemeChange"}
[:type [:= :delete-temporary-token-theme]] [:type [:= :delete-temporary-token-theme]]
[:id ::sm/uuid]]] [:id ::sm/uuid]
[:name :string]]]
[:add-token-theme [:add-token-theme
[:map {:title "AddTokenThemeChange"} [:map {:title "AddTokenThemeChange"}
@ -274,12 +275,14 @@
[:map {:title "ModTokenThemeChange"} [:map {:title "ModTokenThemeChange"}
[:type [:= :mod-token-theme]] [:type [:= :mod-token-theme]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string]
[:token-theme ::ctot/token-theme]]] [:token-theme ::ctot/token-theme]]]
[:del-token-theme [:del-token-theme
[:map {:title "DelTokenThemeChange"} [:map {:title "DelTokenThemeChange"}
[:type [:= :del-token-theme]] [:type [:= :del-token-theme]]
[:id ::sm/uuid]]] [:id ::sm/uuid]
[:name :string]]]
[:add-token-set [:add-token-set
[:map {:title "AddTokenSetChange"} [:map {:title "AddTokenSetChange"}
@ -822,29 +825,70 @@
set-name set-name
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 (defmethod process-change :add-temporary-token-theme
[data {:keys [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 (defmethod process-change :update-active-token-themes
[data {:keys [theme-ids]}] [data {:keys [theme-ids]}]
(ctotl/assoc-active-token-themes data theme-ids)) (ctotl/assoc-active-token-themes data theme-ids))
(defmethod process-change :delete-temporary-token-theme (defmethod process-change :delete-temporary-token-theme
[data {:keys [id]}] [data {:keys [id group name]}]
(ctotl/delete-temporary-token-theme data id)) (-> data
(ctotl/delete-temporary-token-theme id)
(update :tokens-lib
#(-> %
(ctob/ensure-tokens-lib)
(ctob/delete-theme group name)))))
(defmethod process-change :add-token-theme (defmethod process-change :add-token-theme
[data {:keys [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 (defmethod process-change :mod-token-theme
[data {:keys [id token-theme]}] [data {:keys [id name group token-theme]}]
(ctotl/update-token-theme data id merge token-theme)) (-> data
(ctotl/update-token-theme id merge token-theme)
(update :tokens-lib
#(-> %
(ctob/ensure-tokens-lib)
(ctob/update-theme name group
(fn [prev-theme]
(merge prev-theme
(-> token-theme
(update :sets (partial set-ids->names data))))))))))
(defmethod process-change :del-token-theme (defmethod process-change :del-token-theme
[data {:keys [id]}] [data {:keys [id group name]}]
(ctotl/delete-token-theme data id)) (-> data
(ctotl/delete-token-theme id)
(update :tokens-lib
#(-> %
(ctob/ensure-tokens-lib)
(ctob/delete-theme group name)))))
(defmethod process-change :add-token-set (defmethod process-change :add-token-set
[data {:keys [token-set]}] [data {:keys [token-set]}]

View file

@ -699,7 +699,7 @@
[changes token-theme] [changes token-theme]
(-> changes (-> changes
(update :redo-changes conj {:type :add-temporary-token-theme :token-theme token-theme}) (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))) (apply-changes-local)))
(defn update-active-token-themes (defn update-active-token-themes
@ -713,14 +713,14 @@
[changes token-theme] [changes token-theme]
(-> changes (-> changes
(update :redo-changes conj {:type :add-token-theme :token-theme token-theme}) (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))) (apply-changes-local)))
(defn update-token-theme (defn update-token-theme
[changes token-theme prev-token-theme] [changes token-theme prev-token-theme]
(-> changes (-> changes
(update :redo-changes conj {:type :mod-token-theme :id (:id token-theme) :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) :token-theme (or prev-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))) (apply-changes-local)))
(defn delete-token-theme (defn delete-token-theme
@ -729,7 +729,7 @@
(let [library-data (::library-data (meta changes)) (let [library-data (::library-data (meta changes))
prev-token-theme (get-in library-data [:token-themes-index token-theme-id])] prev-token-theme (get-in library-data [:token-themes-index token-theme-id])]
(-> changes (-> 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}) (update :undo-changes conj {:type :add-token-theme :token-theme prev-token-theme})
(apply-changes-local)))) (apply-changes-local))))

View file

@ -16,6 +16,7 @@
java.time.OffsetDateTime java.time.OffsetDateTime
java.util.List java.util.List
linked.map.LinkedMap linked.map.LinkedMap
linked.set.LinkedSet
org.fressian.Reader org.fressian.Reader
org.fressian.StreamingWriter org.fressian.StreamingWriter
org.fressian.Writer org.fressian.Writer
@ -275,7 +276,12 @@
{:name "clj/seq" {:name "clj/seq"
:class clojure.lang.ISeq :class clojure.lang.ISeq
:wfn write-list-like :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 ;; --- PUBLIC API

View file

@ -12,9 +12,88 @@
[app.common.time :as dt] [app.common.time :as dt]
[app.common.transit :as t] [app.common.transit :as t]
[app.common.types.token :as cto] [app.common.types.token :as cto]
[cuerdas.core :as str]
#?(:clj [app.common.fressian :as fres]))) #?(:clj [app.common.fressian :as fres])))
;; #?(:clj (set! *warn-on-reflection* true)) ;; === Groups handling
(def schema:groupable-item
[:map {:title "Groupable item"}
[:name :string]])
(def valid-groupable-item?
(sm/validator schema:groupable-item))
(defn split-path
"Decompose a string in the form 'one.two.three' into a vector of strings, removing spaces."
[path separator]
(let [xf (comp (map str/trim)
(remove str/empty?))]
(->> (str/split path separator)
(into [] xf))))
(defn join-path
"Regenerate a path as a string, from a vector."
[path separator]
(str/join separator path))
(defn group-item
"Add a group to the item name, in the form group.name."
[item group-name separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(update item :name #(str group-name separator %)))
(defn ungroup-item
"Remove the first group from the item name."
[item separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(update item :name #(-> %
(split-path separator)
(rest)
(join-path separator))))
(defn get-path
"Get the groups part of the name as a vector. E.g. group.subgroup.name -> ['group' 'subrgoup']"
[item separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(split-path (:name item) separator))
(defn get-groups-str
"Get the groups part of the name. E.g. group.subgroup.name -> group.subrgoup"
[item separator]
(-> (get-path item separator)
(butlast)
(join-path separator)))
(defn get-final-name
"Get the final part of the name. E.g. group.subgroup.name -> name"
[item separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(-> (:name item)
(split-path separator)
(last)))
(defn group?
"Check if a node of the grouping tree is a group or a final item."
[item]
(d/ordered-map? item))
(defn get-children
"Get all children of a group of a grouping tree. Each child is
a tuple [name item], where item "
[group]
(dm/assert!
"expected group node"
(group? group))
(seq group))
;; === Token ;; === Token
@ -23,10 +102,10 @@
(def schema:token (def schema:token
[:and [:and
[:map {:title "Token"} [:map {:title "Token"}
[:name cto/token-name-ref] ;; not necessary to have uuid [:name cto/token-name-ref] ;; not necessary to have uuid
[:type [::sm/one-of cto/token-types]] [:type [::sm/one-of cto/token-types]]
[:value :any] [:value :any]
[:description [:maybe :string]] ;; defrecord always have the attributes, even with nil value [:description [:maybe :string]] ;; defrecord always have the attributes, even with nil value
[:modified-at ::sm/inst]] [:modified-at ::sm/inst]]
[:fn (partial instance? Token)]]) [:fn (partial instance? Token)]])
@ -56,7 +135,8 @@
(defprotocol ITokenSet (defprotocol ITokenSet
(add-token [_ token] "add a token at the end of the list") (add-token [_ token] "add a token at the end of the list")
(update-token [_ token-name f] "update a token in the list") (update-token [_ token-name f] "update a token in the list")
(delete-token [_ token-name] "delete a token from the list")) (delete-token [_ token-name] "delete a token from the list")
(get-tokens [_] "return an ordered sequence of all tokens in the set"))
(defrecord TokenSet [name description modified-at tokens] (defrecord TokenSet [name description modified-at tokens]
ITokenSet ITokenSet
@ -77,24 +157,27 @@
(dt/now) (dt/now)
(if (= (:name token) (:name token')) (if (= (:name token) (:name token'))
(assoc tokens (:name token') token') (assoc tokens (:name token') token')
(let [index (d/index-of (keys tokens) (:name token))] (-> tokens
(-> tokens (d/oassoc-before (:name token) (:name token') token')
(dissoc (:name token)) (dissoc (:name token))))))
(d/addm-at-index index (:name token') token'))))))
this)) this))
(delete-token [_ token-name] (delete-token [_ token-name]
(TokenSet. name (TokenSet. name
description description
(dt/now) (dt/now)
(dissoc tokens token-name)))) (dissoc tokens token-name)))
(get-tokens [_]
(vals tokens)))
(def schema:token-set (def schema:token-set
[:and [:map {:title "TokenSet"} [:and [:map {:title "TokenSet"}
[:name :string] [:name :string]
[:description [:maybe :string]] [:description [:maybe :string]]
[:modified-at ::sm/inst] [: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)]]) [:fn (partial instance? TokenSet)]])
(sm/register! ::token-set schema:token-set) (sm/register! ::token-set schema:token-set)
@ -119,6 +202,16 @@
token-set)) token-set))
;; === TokenSetGroup
(defrecord TokenSetGroup [attr1 attr2])
;; TODO schema, validators, etc.
(defn make-token-set-group
[]
(TokenSetGroup. "one" "two"))
;; === TokenSets (collection) ;; === TokenSets (collection)
(defprotocol ITokenSets (defprotocol ITokenSets
@ -126,14 +219,24 @@
(update-set [_ set-name f] "modify a set in the ilbrary") (update-set [_ set-name f] "modify a set in the ilbrary")
(delete-set [_ set-name] "delete a set in the library") (delete-set [_ set-name] "delete a set in the library")
(set-count [_] "get the total number if sets in the library") (set-count [_] "get the total number if sets in the library")
(get-set-tree [_] "get a nested tree of all sets in the library")
(get-sets [_] "get an ordered sequence of all 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") (get-set [_ set-name] "get one set looking for name")
(validate [_])) (get-set-group [_ set-group-path] "get the attributes of a set group"))
(def schema:token-set-node
[:schema {:registry {::node [:or ::token-set
[:and
[:map-of {:gen/max 5} :string [:ref ::node]]
[:fn d/ordered-map?]]]}}
[:ref ::node]])
(sm/register! ::token-set-node schema:token-set-node)
(def schema:token-sets (def schema:token-sets
[:and [:and
[:map-of {:title "TokenSets"} [:map-of {:title "TokenSets"}
:string ::token-set] :string ::token-set-node]
[:fn d/ordered-map?]]) [:fn d/ordered-map?]])
(sm/register! ::token-sets schema:token-sets) (sm/register! ::token-sets schema:token-sets)
@ -144,10 +247,83 @@
(def check-token-sets! (def check-token-sets!
(sm/check-fn ::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 group description is-source modified-at sets]
ITokenTheme
(toggle-set [_ set-name]
(TokenTheme. name
group
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]
[:group :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)
(update :group #(or % ""))
(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) ;; === TokenThemes (collection)
(defprotocol ITokenThemes
(add-theme [_ token-theme] "add a theme to the library, at the end")
(update-theme [_ group name f] "modify a theme in the ilbrary")
(delete-theme [_ group name] "delete a theme in the library")
(theme-count [_] "get the total number if themes in the library")
(get-theme-tree [_] "get a nested tree of all themes in the library")
(get-themes [_] "get an ordered sequence of all themes in the library")
(get-theme [_ group name] "get one theme looking for name"))
(def schema:token-themes
[:and
[:map-of {:title "TokenThemes"}
:string [:and [:map-of :string ::token-theme]
[:fn d/ordered-map?]]]
[:fn d/ordered-map?]])
(sm/register! ::token-themes schema:token-themes)
(def valid-token-themes? (def valid-token-themes?
(constantly true)) (sm/validator schema:token-themes))
(def check-token-themes!
(sm/check-fn ::token-themes))
;; === Tokens Lib ;; === Tokens Lib
@ -155,62 +331,122 @@
"A library of tokens, sets and themes." "A library of tokens, sets and themes."
(add-token-in-set [_ set-name token] "add token to a set") (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") (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 [_ group-name theme-name set-name] "toggle a set used / not used in a theme")
(validate [_]))
(deftype TokensLib [sets themes] (deftype TokensLib [sets set-groups themes]
;; NOTE: This is only for debug purposes, pending to properly ;; NOTE: This is only for debug purposes, pending to properly
;; implement the toString and alternative printing. ;; implement the toString and alternative printing.
#?@(:clj [clojure.lang.IDeref #?@(:clj [clojure.lang.IDeref
(deref [_] {:sets sets :themes themes})] (deref [_] {:sets sets :set-groups set-groups :themes themes})]
:cljs [cljs.core/IDeref :cljs [cljs.core/IDeref
(-deref [_] {:sets sets :themes themes})]) (-deref [_] {:sets sets :set-groups set-groups :themes themes})])
#?@(:cljs [cljs.core/IEncodeJS #?@(:cljs [cljs.core/IEncodeJS
(-clj->js [_] (js-obj "sets" (clj->js sets) (-clj->js [_] (js-obj "sets" (clj->js sets)
"set-groups" (clj->js set-groups)
"themes" (clj->js themes)))]) "themes" (clj->js themes)))])
ITokenSets ITokenSets
(add-set [_ token-set] (add-set [_ token-set]
(dm/assert! "expected valid token set" (check-token-set! token-set)) (dm/assert! "expected valid token set" (check-token-set! token-set))
(TokensLib. (assoc sets (:name token-set) token-set) (let [path (get-path token-set "/")
themes)) groups-str (get-groups-str token-set "/")]
(TokensLib. (d/oassoc-in sets path token-set)
(cond-> set-groups
(not (str/empty? groups-str))
(assoc groups-str (make-token-set-group)))
themes)))
(update-set [this set-name f] (update-set [this set-name f]
(if-let [set (get sets set-name)] (let [path (split-path set-name "/")
(let [set' (-> (make-token-set (f set)) set (get-in sets path)]
(assoc :modified-at (dt/now)))] (if set
(check-token-set! set') (let [set' (-> (make-token-set (f set))
(TokensLib. (if (= (:name set) (:name set')) (assoc :modified-at (dt/now)))
(assoc sets (:name set') set') path' (get-path set' "/")]
(let [index (d/index-of (keys sets) (:name set))] (check-token-set! set')
(TokensLib. (if (= (:name set) (:name set'))
(d/oassoc-in sets path set')
(-> sets (-> sets
(dissoc (:name set)) (d/oassoc-in-before path path' set')
(d/addm-at-index index (:name set') set')))) (d/dissoc-in path)))
themes)) set-groups ;; TODO update set-groups as needed
this)) themes))
this)))
(delete-set [_ set-name] (delete-set [_ set-name]
(TokensLib. (dissoc sets set-name) (let [path (split-path set-name "/")]
themes)) (TokensLib. (d/dissoc-in sets path)
set-groups ;; TODO remove set-group if needed
themes)))
(validate [_] (get-set-tree [_]
(and (valid-token-sets? sets) sets)
(valid-token-themes? themes)))
(set-count [_]
(count sets))
(get-sets [_] (get-sets [_]
(vals sets)) (->> (tree-seq d/ordered-map? vals sets)
(filter (partial instance? TokenSet))))
(set-count [this]
(count (get-sets this)))
(get-set [_ set-name] (get-set [_ set-name]
(get sets set-name)) (let [path (split-path set-name "/")]
(get-in sets path)))
(get-set-group [_ set-group-path]
(get set-groups set-group-path))
ITokenThemes
(add-theme [_ token-theme]
(dm/assert! "expected valid token theme" (check-token-theme! token-theme))
(TokensLib. sets
set-groups
(update themes (:group token-theme) d/oassoc (:name token-theme) token-theme)))
(update-theme [this group name f]
(let [theme (dm/get-in themes [group name])]
(if theme
(let [theme' (-> (make-token-theme (f theme))
(assoc :modified-at (dt/now)))
group' (:group theme')
name' (:name theme')]
(check-token-theme! theme')
(TokensLib. sets
set-groups
(if (and (= group group') (= name name'))
(update themes group' assoc name' theme')
(-> themes
(d/oassoc-in-before [group name] [group' name'] theme')
(d/dissoc-in [group name])))))
this)))
(delete-theme [_ group name]
(TokensLib. sets
set-groups
(d/dissoc-in themes [group name])))
(get-theme-tree [_]
themes)
(get-themes [_]
(->> (tree-seq d/ordered-map? vals themes)
(filter (partial instance? TokenTheme))))
(theme-count [this]
(count (get-themes this)))
(get-theme [_ group name]
(dm/get-in themes [group name]))
ITokensLib ITokensLib
(add-token-in-set [this set-name token] (add-token-in-set [this set-name token]
(dm/assert! "expected valid token instance" (check-token! token)) (dm/assert! "expected valid token instance" (check-token! token))
(if (contains? sets set-name) (if (contains? sets set-name)
(TokensLib. (update sets set-name add-token token) (TokensLib. (update sets set-name add-token token)
set-groups
themes) themes)
this)) this))
@ -218,6 +454,7 @@
(if (contains? sets set-name) (if (contains? sets set-name)
(TokensLib. (update sets set-name (TokensLib. (update sets set-name
#(update-token % token-name f)) #(update-token % token-name f))
set-groups
themes) themes)
this)) this))
@ -225,8 +462,21 @@
(if (contains? sets set-name) (if (contains? sets set-name)
(TokensLib. (update sets set-name (TokensLib. (update sets set-name
#(delete-token % token-name)) #(delete-token % token-name))
set-groups
themes) themes)
this))) this))
(toggle-set-in-theme [this theme-group theme-name set-name]
(if-let [_theme (get-in themes theme-group theme-name)]
(TokensLib. sets
set-groups
(d/oupdate-in themes [theme-group theme-name]
#(toggle-set % set-name)))
this))
(validate [_]
(and (valid-token-sets? sets) ;; TODO: validate set-groups
(valid-token-themes? themes))))
(defn valid-tokens-lib? (defn valid-tokens-lib?
[o] [o]
@ -248,10 +498,11 @@
;; structure the data and the order separately as we already do ;; structure the data and the order separately as we already do
;; with pages and pages-index. ;; with pages and pages-index.
(make-tokens-lib :sets (d/ordered-map) (make-tokens-lib :sets (d/ordered-map)
:set-groups {}
:themes (d/ordered-map))) :themes (d/ordered-map)))
([& {:keys [sets themes]}] ([& {:keys [sets set-groups themes]}]
(let [tokens-lib (TokensLib. sets themes)] (let [tokens-lib (TokensLib. sets set-groups themes)]
(dm/assert! (dm/assert!
"expected valid tokens lib" "expected valid tokens lib"
@ -269,7 +520,7 @@
(sm/register! ::tokens-lib type:tokens-lib) (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! (t/add-handlers!
{:id "penpot/tokens-lib" {:id "penpot/tokens-lib"
@ -282,6 +533,11 @@
:wfn #(into {} %) :wfn #(into {} %)
:rfn #(make-token-set %)} :rfn #(make-token-set %)}
{:id "penpot/token-theme"
:class TokenTheme
:wfn #(into {} %)
:rfn #(make-token-theme %)}
{:id "penpot/token" {:id "penpot/token"
:class Token :class Token
:wfn #(into {} %) :wfn #(into {} %)
@ -307,13 +563,24 @@
(let [obj (fres/read-object! r)] (let [obj (fres/read-object! r)]
(map->TokenSet obj)))} (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" {:name "penpot/tokens-lib/v1"
:class TokensLib :class TokensLib
:wfn (fn [n w o] :wfn (fn [n w o]
(fres/write-tag! w n 2) (fres/write-tag! w n 3)
(fres/write-object! w (.-sets o)) (fres/write-object! w (.-sets o))
(fres/write-object! w (.-set-groups o))
(fres/write-object! w (.-themes o))) (fres/write-object! w (.-themes o)))
:rfn (fn [r] :rfn (fn [r]
(let [sets (fres/read-object! r) (let [sets (fres/read-object! r)
themes (fres/read-object! r)] set-groups (fres/read-object! r)
(->TokensLib sets themes)))})) themes (fres/read-object! r)]
(->TokensLib sets set-groups themes)))}))

View file

@ -19,16 +19,17 @@
(assoc file-data :token-active-themes theme-ids)) (assoc file-data :token-active-themes theme-ids))
(defn add-temporary-token-theme (defn add-temporary-token-theme
[file-data {:keys [id] :as token-theme}] [file-data {:keys [id name] :as token-theme}]
(-> file-data (-> file-data
(d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)]) (d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)])
(assoc :token-theme-temporary-id id) (assoc :token-theme-temporary-id id)
(assoc :token-theme-temporary-name name)
(update :token-themes-index assoc id token-theme))) (update :token-themes-index assoc id token-theme)))
(defn delete-temporary-token-theme (defn delete-temporary-token-theme
[file-data token-theme-id] [file-data token-theme-id]
(cond-> file-data (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)]))) :always (d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)])))
(defn add-token-theme (defn add-token-theme

File diff suppressed because it is too large Load diff

View file

@ -115,10 +115,9 @@
(ptk/reify ::update-token-theme (ptk/reify ::update-token-theme
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (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) changes (-> (pcb/empty-changes it)
(pcb/update-token-theme token-theme prev-token-theme))] (pcb/update-token-theme token-theme prev-token-theme))]
(js/console.log "changes" changes)
(rx/of (rx/of
(dch/commit-changes changes)))))) (dch/commit-changes changes))))))

View file

@ -69,11 +69,11 @@
(defn group-assets (defn group-assets
"Convert a list of assets in a nested structure like this: "Convert a list of assets in a nested structure like this:
{'': [{assetA} {assetB}] {'': [assetA assetB]
'group1': {'': [{asset1A} {asset1B}] 'group1': {'': [asset1A asset1B]
'subgroup11': {'': [{asset11A} {asset11B} {asset11C}]} 'subgroup11': {'': [asset11A asset11B asset11C]}
'subgroup12': {'': [{asset12A}]}} 'subgroup12': {'': [asset12A]}}
'group2': {'subgroup21': {'': [{asset21A}}}} 'group2': {'subgroup21': {'': [asset21A]}}}
" "
[assets reverse-sort?] [assets reverse-sort?]
(when-not (empty? assets) (when-not (empty? assets)