🎉 Rename token group - modal form

This commit is contained in:
Xavier Julian
2026-02-06 14:04:25 +01:00
parent bca70d2bf1
commit efc08d4034
7 changed files with 156 additions and 27 deletions

View File

@@ -112,6 +112,13 @@
(def token-name-validation-regex
#"^[a-zA-Z0-9_-][a-zA-Z0-9$_-]*(\.[a-zA-Z0-9$_-]+)*$")
(def token-node-name-validation-regex
#"^[a-zA-Z0-9_-][a-zA-Z0-9$_-]*$")
(def node-name-ref
[:re {:title "TokenNodeNameRef" :gen/gen sg/text}
token-node-name-validation-regex])
(def token-name-ref
[:re {:title "TokenNameRef" :gen/gen sg/text}
token-name-validation-regex])

View File

@@ -48,7 +48,7 @@
[:> input* props]))
(mf/defc form-submit*
[{:keys [disabled on-submit] :rest props}]
[{:keys [disabled] :rest props}]
(let [form (mf/use-ctx context)
disabled? (or (and (some? form)
@@ -56,17 +56,9 @@
(seq (:async-errors @form))
(seq (:extra-errors @form))))
(true? disabled))
handle-key-down-save
(mf/use-fn
(mf/deps on-submit form)
(fn [e]
(when (or (k/enter? e) (k/space? e))
(dom/prevent-default e)
(on-submit form e))))
props
(mf/spread-props props {:disabled disabled?
:on-key-down handle-key-down-save
:type "submit"})]
[:> button* props]))
@@ -80,4 +72,4 @@
(when (fn? on-submit)
(on-submit form event))))]
[:> (mf/provider context) {:value form}
[:form {:class class :on-submit on-submit'} children]]))
[:form {:class class :on-submit on-submit'} children]]))

View File

@@ -165,21 +165,14 @@
(st/emit! (dwtl/toggle-token-path (str (name type) "." path)))
(st/emit! (dwtl/toggle-token-path (name type)))))))
;; node-to-rename (mf/use-state nil)
;; node-to-rename* (deref node-to-rename)
;; rename-node
;; (fn [node type]
;; (st/emit! (dwtl/assign-token-node-context-menu nil))
;; (st/emit! (modal/show :tokens/rename-node {:node node
;; :type type})))
rename-node
(mf/use-fn
(mf/deps selected-token-set-tokens)
(fn [node type]
(prn "Open rename node modal")
(modal/show! :tokens/rename-node {:node node
:type type})))
:type type
:tokens-in-active-set selected-token-set-tokens})))
delete-node
(mf/with-memo [selected-token-set-tokens selected-token-set-id]
@@ -210,7 +203,6 @@
[:& token-context-menu {:on-delete-token delete-token}]
[:> token-node-context-menu* {:on-rename-node rename-node
:on-delete-node delete-node}]
;; [:> rename-node-modal* {}]
[:> selected-set-info* {:tokens-lib tokens-lib
:selected-token-set-id selected-token-set-id}]

View File

@@ -1,28 +1,151 @@
(ns app.main.ui.workspace.tokens.management.forms.rename-node-modal
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.files.tokens :as cft]
[app.common.schema :as sm]
[app.common.types.token :as cto]
[app.common.types.tokens-lib :as ctob]
[app.main.data.modal :as modal]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.ds.foundations.typography.heading :refer [heading*]]
[app.main.ui.forms :as fc]
[app.util.forms :as fm]
[app.util.i18n :refer [tr]]
[app.util.keyboard :as kbd]
[rumext.v2 :as mf]))
(defn- make-schema
[tokens-tree]
(sm/schema
[:map
[:name
[:and
[:string {:min 1 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}]
(sm/update-properties cto/node-name-ref assoc :error/fn #(str (:value %) (tr "workspace.tokens.token-name-validation-error")))
[:fn {:error/fn #(tr "workspace.tokens.token-name-duplication-validation-error" (:value %))}
#(not (cft/token-name-path-exists? % tokens-tree))]]]]))
(mf/defc rename-node-form*
[{:keys [node type tokens-tree on-close on-submit]}]
(let [schema
(mf/with-memo [tokens-tree]
(make-schema tokens-tree))
initial (mf/with-memo [node]
{:name (:name node)})
form (fm/use-form :schema schema
:initial initial)
submit (mf/use-fn
(mf/deps form on-submit node)
(fn []
(let [name (get-in @form [:clean-data :name])
old-path (str (d/name type) "." (:name node))
new-path (str (d/name type) "." name)
_ (prn {:old-path old-path :new-path new-path})]
(prn "Submitting rename node form with name: " name " and path: " new-path)
(if (not= old-path new-path)
(on-submit {:name name})
(on-close)))))
#_(let [{:keys [clean-data valid extra-errors async-errors]} @form]
(when (and valid
(empty? extra-errors)
(empty? async-errors))
(on-submit clean-data)))]
;; (fn []
;; ;; Call shared remapping logic
;; (let [old-token-name (:old-token-name remap-modal)
;; new-token-name (:new-token-name remap-modal)]
;; (st/emit! [:tokens/remap-tokens old-token-name new-token-name]))
;; (when (fn? on-remap)
;; (on-remap))))
;; remap (mf/use-fn
;; (mf/deps form on-submit)
;; (fn []
;; (let [name (get-in @form [:clean-data :name])
;; path (str (d/name type) "." name)]
;; (prn "Submitting rename node form with name: " name " and path: " path))
;; #_(let [{:keys [clean-data valid extra-errors async-errors]} @form]
;; (when (and valid
;; (empty? extra-errors)
;; (empty? async-errors))
;; (on-submit clean-data)))))
;; submit (mf/use-fn
;; (mf/deps form on-submit)
;; (fn [_ event]
;; (let [event (dom/event->native-event event)
;; submitter (dom/get-event-submitter event)
;; handler (.-name submitter)
;; handlerKey (keyword handler)]
;; (if (= handlerKey :rename)
;; (rename)
;; (remap)))))]
[:div
[:> heading* {:level 2
:typography "headline-medium"
:class (stl/css :form-modal-title)}
(tr "workspace.tokens.rename-group")]
[:> fc/form* {:class (stl/css :form-wrapper)
:form form
:on-submit submit}
[:> fc/form-input* {:id (:name node)
:name :name
:label (tr "workspace.tokens.token-name")
:placeholder (tr "workspace.tokens.token-name")
:max-length 255
:variant "comfortable"
:hint-type "hint"
:hint-message (tr "workspace.tokens.rename-group-name-hint")
:auto-focus true}]
[:div {:class (stl/css :form-actions)}
#_[:> fc/form-submit* {:variant "secondary"
:name "rename"} "rename"]
[:> button* {:variant "secondary"
:name "cancel"
:on-click on-close} (tr "labels.cancel")]
[:> fc/form-submit* {:variant "primary"
:name "rename"} (tr "labels.rename")]]]]))
(mf/defc rename-node-modal*
{::mf/register modal/components
::mf/register-as :tokens/rename-node}
[{:keys [node type]}]
[{:keys [node type tokens-in-active-set]}]
(let [on-close
(let [tokens-tree-in-selected-set
(mf/with-memo [tokens-in-active-set node]
(-> (ctob/tokens-tree tokens-in-active-set)
(d/dissoc-in (:name node))))
close-modal
(mf/use-fn
(mf/deps [])
(fn []
(modal/hide!)))]
(modal/hide!)))
[:div {:class (stl/css :modal-overlay)}
on-key-down
(mf/use-fn
(mf/deps [close-modal])
(fn [event]
(when (kbd/esc? event)
(close-modal))))]
[:div {:class (stl/css :modal-overlay) :on-key-down on-key-down}
[:div {:class (stl/css :modal-dialog)}
[:> icon-button* {:class (stl/css :close-btn)
:on-click on-close
:on-click close-modal
:aria-label (tr "labels.close")
:variant "ghost"
:icon i/close}]
(str "Rename node modal for node: " node " of type: " type)]]))
[:> rename-node-form* {:node node
:type type
:tokens-tree tokens-tree-in-selected-set
:on-close close-modal}]]]))

View File

@@ -39,3 +39,8 @@
user-select: none;
position: relative;
}
.form-modal-title {
@include t.use-typography("headline-medium");
color: var(--color-foreground-primary);
}

View File

@@ -134,6 +134,12 @@
(when (some? event)
(.-relatedTarget event)))
(defn get-event-submitter
"Extract the submitter from a form submit event."
[^js event]
(when (some? event)
(.-submitter event)))
(defn select-target
"Extract the target from event instance and select it"
[^js event]

View File

@@ -8412,6 +8412,10 @@ msgstr "Invalid value: % is not allowed."
msgid "workspace.tokens.value-with-units"
msgstr "Invalid value: Units are not allowed."
#: src/app/main/ui/workspace/tokens/management/forms/rename_node_modal.cljs:16
msgid "workspace.tokens.rename-group"
msgstr "Rename tokens group"
#: src/app/main/ui/workspace/sidebar.cljs:154, src/app/main/ui/workspace/sidebar.cljs:161
msgid "workspace.toolbar.assets"
msgstr "Assets"