🐛 Prevent token-set overwrite on creation and edition

This commit is contained in:
Andrey Antukh 2025-03-14 15:10:52 +01:00
parent 1965490bee
commit 096b685e2c
6 changed files with 1397 additions and 1369 deletions

View file

@ -387,7 +387,6 @@
[:set-group-path [:vector :string]] [:set-group-path [:vector :string]]
[:set-group-fname :string]]] [:set-group-fname :string]]]
[:move-token-set-before [:move-token-set-before
[:map {:title "MoveTokenSetBefore"} [:map {:title "MoveTokenSetBefore"}
[:type [:= :move-token-set-before]] [:type [:= :move-token-set-before]]

View file

@ -875,9 +875,28 @@
:token nil})) :token nil}))
(apply-changes-local)))) (apply-changes-local))))
(defn set-token-set [changes set-name group? token-set] (defn rename-token-set
[changes name new-name]
(assert-library! changes) (assert-library! changes)
(let [library-data (::library-data (meta changes)) (let [library-data (::library-data (meta changes))
prev-token-set (some-> (get library-data :tokens-lib)
(ctob/get-set name))]
(-> changes
(update :redo-changes conj {:type :set-token-set
:set-name name
:token-set (assoc prev-token-set :name new-name)
:group? false})
(update :undo-changes conj {:type :set-token-set
:set-name new-name
:token-set prev-token-set
:group? false})
(apply-changes-local))))
(defn set-token-set
[changes set-name group? token-set]
(assert-library! changes)
(let [library-data (::library-data (meta changes))
prev-token-set (some-> (get library-data :tokens-lib) prev-token-set (some-> (get library-data :tokens-lib)
(ctob/get-set set-name))] (ctob/get-set set-name))]
(-> changes (-> changes

View file

@ -27,14 +27,17 @@
(def valid-groupable-item? (def valid-groupable-item?
(sm/validator schema:groupable-item)) (sm/validator schema:groupable-item))
(def xf-map-trim
(comp
(map str/trim)
(remove str/empty?)))
(defn split-path (defn split-path
"Decompose a string in the form 'one.two.three' into a vector of strings, removing spaces." "Decompose a string in the form 'one.two.three' into a vector of strings, removing spaces."
[path separator] [path separator]
(let [xf (comp (map str/trim) (->> (str/split path separator)
(remove str/empty?))] (into [] xf-map-trim)
(->> (str/split path separator) (not-empty)))
(into [] xf))))
(defn split-path-name [s separator] (defn split-path-name [s separator]
(let [[path name] (str/split s (re-pattern (str "\\" separator)) 2)] (let [[path name] (str/split s (re-pattern (str "\\" separator)) 2)]
@ -61,10 +64,12 @@
(join-path separator)))) (join-path separator))))
(defn get-path (defn get-path
"Get the groups part of the name as a vector. E.g. group.subgroup.name -> ['group' 'subgroup']" "Get the path of object by specified separator (E.g. with '.'
separator, the 'group.subgroup.name' -> ['group' 'subgroup'])"
[item separator] [item separator]
(assert (valid-groupable-item? item) "expected groupable item") (assert (valid-groupable-item? item) "expected groupable item")
(split-path (:name item) separator)) (->> (split-path (:name item) separator)
(not-empty)))
(defn get-groups-str (defn get-groups-str
"Get the groups part of the name. E.g. group.subgroup.name -> group.subgroup" "Get the groups part of the name. E.g. group.subgroup.name -> group.subgroup"
@ -97,14 +102,9 @@
(def token-separator ".") (def token-separator ".")
(defn get-token-path [path] (defn get-token-path
(get-path path token-separator)) [token]
(get-path token token-separator))
;; FIXME: misleading name, we are spliting name into path, not
;; spliting path into path
(defn split-token-path
[path]
(split-path path token-separator))
(defrecord Token [name type value description modified-at]) (defrecord Token [name type value description modified-at])
@ -247,28 +247,38 @@
set-name (add-set-prefix (last paths))] set-name (add-set-prefix (last paths))]
(conj set-path set-name))) (conj set-path set-name)))
(defn get-token-set-path
[token-set]
(get-path token-set set-separator))
(defn split-token-set-name (defn split-token-set-name
[name] [name]
(split-path name set-separator)) (split-path name set-separator))
;; (defn rename-token-set-preserving-group
;; [token-set name]
;; (let [base (butlast (get-path token-set))
(defn normalize-set-name (defn normalize-set-name
[name] "Normalize a set name.
(->> (split-token-set-name name)
(map str/trim)
(str/join set-separator)))
(defn get-token-set-path [token-set] If `relative-to` is provided, the normalized name will preserve the
(let [path (get-path token-set set-separator)] same group prefix as reference name"
(add-token-set-paths-prefix path))) ([name]
(->> (split-token-set-name name)
(str/join set-separator)))
([name relative-to]
(->> (concat (butlast (split-token-set-name relative-to))
(split-token-set-name name))
(str/join set-separator))))
;; FIXME: revisit
(defn get-token-set-final-name (defn get-token-set-final-name
[name] [name]
(-> (split-token-set-name name) (-> (split-token-set-name name)
(peek))) (peek)))
(defn split-token-set-path [token-set-path]
(split-path token-set-path set-separator))
(defn set-name->prefixed-full-path [name-str] (defn set-name->prefixed-full-path [name-str]
(-> (split-token-set-name name-str) (-> (split-token-set-name name-str)
(set-full-path->set-prefixed-full-path))) (set-full-path->set-prefixed-full-path)))
@ -297,7 +307,7 @@
[tokens & {:keys [update-token-fn] [tokens & {:keys [update-token-fn]
:or {update-token-fn identity}}] :or {update-token-fn identity}}]
(reduce-kv (fn [acc _ token] (reduce-kv (fn [acc _ token]
(let [path (split-token-path (:name token))] (let [path (get-token-path token)]
(assoc-in acc path (update-token-fn token)))) (assoc-in acc path (update-token-fn token))))
{} tokens)) {} tokens))
@ -309,8 +319,8 @@
(reduce (reduce
(fn [acc [_ token]] (fn [acc [_ token]]
(let [temp-id (random-uuid) (let [temp-id (random-uuid)
token (assoc token :temp/id temp-id) token (assoc token :temp/id temp-id)
path (split-token-path (:name token))] path (get-token-path token)]
(-> acc (-> acc
(assoc-in (concat [:tokens-tree] path) token) (assoc-in (concat [:tokens-tree] path) token)
(assoc-in [:ids temp-id] token)))) (assoc-in [:ids temp-id] token))))
@ -378,6 +388,7 @@
(get-tokens-tree [_] (get-tokens-tree [_]
(tokens-tree tokens)) (tokens-tree tokens))
;; FIXME: looks redundant
(get-dtcg-tokens-tree [_] (get-dtcg-tokens-tree [_]
(tokens-tree tokens :update-token-fn (fn [token] (tokens-tree tokens :update-token-fn (fn [token]
(cond-> {"$value" (:value token) (cond-> {"$value" (:value token)
@ -926,7 +937,7 @@ Will return a value that matches this schema:
active-themes))) active-themes)))
(delete-set-group [this set-group-name] (delete-set-group [this set-group-name]
(let [path (split-token-set-path set-group-name) (let [path (split-token-set-name set-group-name)
prefixed-path (map add-set-group-prefix path) prefixed-path (map add-set-group-prefix path)
child-set-names (->> (get-sets-at-path this path) child-set-names (->> (get-sets-at-path this path)
(map :name) (map :name)
@ -1268,14 +1279,17 @@ Will return a value that matches this schema:
(tree-seq d/ordered-map? vals themes)) (tree-seq d/ordered-map? vals themes))
;; Active themes without exposing hidden penpot theme ;; Active themes without exposing hidden penpot theme
active-themes-clear (disj active-themes hidden-token-theme-path) active-themes-clear (disj active-themes hidden-token-theme-path)
name-set-tuples (->> sets name-set-tuples (->> sets
(tree-seq d/ordered-map? vals) (tree-seq d/ordered-map? vals)
(filter (partial instance? TokenSet)) (filter (partial instance? TokenSet))
(map (fn [token-set] (map (fn [token-set]
[(:name token-set) (get-dtcg-tokens-tree token-set)]))) [(:name token-set) (get-dtcg-tokens-tree token-set)])))
ordered-set-names (map first name-set-tuples) ordered-set-names (mapv first name-set-tuples)
sets (into {} name-set-tuples) sets (into {} name-set-tuples)
active-sets (get-active-themes-set-names this)] active-sets (get-active-themes-set-names this)]
(-> sets (-> sets
(assoc "$themes" themes) (assoc "$themes" themes)
(assoc-in ["$metadata" "tokenSetOrder"] ordered-set-names) (assoc-in ["$metadata" "tokenSetOrder"] ordered-set-names)

File diff suppressed because it is too large Load diff

View file

@ -127,7 +127,7 @@
(wtu/update-workspace-tokens)))))) (wtu/update-workspace-tokens))))))
(defn create-token-set (defn create-token-set
[set-name token-set] [set-name]
(ptk/reify ::create-token-set (ptk/reify ::create-token-set
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
@ -136,28 +136,16 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [token-set' (let [data (dsh/lookup-file-data state)
;; FIXME: wtf is this? tokens-lib (get data :tokens-lib)
(update token-set :name #(if (empty? %) set-name (ctob/normalize-set-name set-name)]
set-name (when-not (ctob/get-set tokens-lib set-name)
(ctob/join-set-path [% set-name]))) (let [token-set (ctob/make-token-set :name set-name)
changes (-> (pcb/empty-changes it)
token-set' (pcb/with-library-data data)
(update token-set' :name ctob/normalize-set-name) (pcb/set-token-set set-name false token-set))]
(rx/of (set-selected-token-set-name set-name)
data (dch/commit-changes changes))))))))
(dsh/lookup-file-data state)
token-set-name
(:name token-set')
changes
(-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/set-token-set token-set-name false token-set'))]
(rx/of (set-selected-token-set-name token-set-name)
(dch/commit-changes changes))))))
(defn rename-token-set-group [set-group-path set-group-fname] (defn rename-token-set-group [set-group-path set-group-fname]
(ptk/reify ::rename-token-set-group (ptk/reify ::rename-token-set-group
@ -168,17 +156,28 @@
(rx/of (rx/of
(dch/commit-changes changes)))))) (dch/commit-changes changes))))))
(defn update-token-set [set-name token-set] (defn update-token-set
[token-set name]
(ptk/reify ::update-token-set (ptk/reify ::update-token-set
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [data (dsh/lookup-file-data state) (let [data (dsh/lookup-file-data state)
changes (-> (pcb/empty-changes it) name (ctob/normalize-set-name name (:name token-set))
(pcb/with-library-data data) tokens-lib (get data :tokens-lib)]
(pcb/set-token-set set-name false token-set))]
(rx/of (cond
(set-selected-token-set-name (:name token-set)) (= (:name token-set) name)
(dch/commit-changes changes)))))) nil
(ctob/get-set tokens-lib name)
nil
:else
(let [changes (-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/rename-token-set (:name token-set) name))]
(rx/of (set-selected-token-set-name (:name token-set))
(dch/commit-changes changes))))))))
(defn toggle-token-set (defn toggle-token-set
[name] [name]

View file

@ -43,17 +43,27 @@
(st/emit! (dt/set-selected-token-set-name name))) (st/emit! (dt/set-selected-token-set-name name)))
(defn on-update-token-set (defn on-update-token-set
[name token-set] [token-set name]
(st/emit! (dt/clear-token-set-edition) (st/emit! (dt/clear-token-set-edition)
(dt/update-token-set (:name token-set) (ctob/update-name token-set name)))) (dt/update-token-set token-set name)))
(defn- on-update-token-set-group [path name] (defn- on-update-token-set-group
[path name]
(st/emit! (dt/clear-token-set-edition) (st/emit! (dt/clear-token-set-edition)
(dt/rename-token-set-group path name))) (dt/rename-token-set-group path name)))
(defn- on-create-token-set [name token-set] (defn- on-create-token-set
(st/emit! (ptk/data-event ::ev/event {::ev/name "create-token-set" :name name}) [parent-set name]
(dt/create-token-set name token-set))) (let [;; FIXME: this code should be reusable under helper under
;; common types namespace
name
(if-let [parent-path (ctob/get-token-set-path parent-set)]
(->> (concat parent-path (ctob/split-token-set-name name))
(ctob/join-set-path))
(ctob/normalize-set-name name))]
(st/emit! (ptk/data-event ::ev/event {::ev/name "create-token-set" :name name})
(dt/create-token-set name))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMPONENTS ;; COMPONENTS
@ -62,13 +72,11 @@
(mf/defc editing-label* (mf/defc editing-label*
{::mf/private true} {::mf/private true}
[{:keys [default-value on-cancel on-submit]}] [{:keys [default-value on-cancel on-submit]}]
(let [ref (mf/use-ref) (let [on-submit
on-submit-valid
(mf/use-fn (mf/use-fn
(mf/deps on-cancel on-submit default-value) (mf/deps on-cancel on-submit default-value)
(fn [event] (fn [event]
(let [value (str/trim (dom/get-target-val event))] (let [value (dom/get-target-val event)]
(if (or (str/empty? value) (if (or (str/empty? value)
(= value default-value)) (= value default-value))
(on-cancel) (on-cancel)
@ -76,16 +84,15 @@
on-key-down on-key-down
(mf/use-fn (mf/use-fn
(mf/deps on-submit-valid on-cancel) (mf/deps on-submit on-cancel)
(fn [event] (fn [event]
(cond (cond
(kbd/enter? event) (on-submit-valid event) (kbd/enter? event) (on-submit event)
(kbd/esc? event) (on-cancel))))] (kbd/esc? event) (on-cancel))))]
[:input [:input
{:class (stl/css :editing-node) {:class (stl/css :editing-node)
:type "text" :type "text"
:ref ref :on-blur on-submit
:on-blur on-submit-valid
:on-key-down on-key-down :on-key-down on-key-down
:auto-focus true :auto-focus true
:placeholder (tr "workspace.token.set-edit-placeholder") :placeholder (tr "workspace.token.set-edit-placeholder")
@ -234,6 +241,7 @@
(mf/defc sets-tree-set* (mf/defc sets-tree-set*
[{:keys [id set label tree-depth tree-path tree-index is-selected is-active is-draggable is-editing [{:keys [id set label tree-depth tree-path tree-index is-selected is-active is-draggable is-editing
on-select on-drop on-toggle on-start-edition on-reset-edition on-edit-submit]}] on-select on-drop on-toggle on-start-edition on-reset-edition on-edit-submit]}]
(let [set-name (get set :name) (let [set-name (get set :name)
can-edit? (mf/use-ctx ctx/can-edit?) can-edit? (mf/use-ctx ctx/can-edit?)
@ -273,7 +281,7 @@
on-edit-submit' on-edit-submit'
(mf/use-fn (mf/use-fn
(mf/deps set on-edit-submit) (mf/deps set on-edit-submit)
#(on-edit-submit % set)) #(on-edit-submit set %))
on-drag on-drag
(mf/use-fn (mf/use-fn