mirror of
https://github.com/penpot/penpot.git
synced 2026-08-01 10:56:20 +00:00
🎉 Allow the user to choose the tokens-source of a file
This commit is contained in:
parent
9737ab504f
commit
41742a6aa4
@ -1091,10 +1091,10 @@
|
|||||||
|
|
||||||
(defn set-tokens-source
|
(defn set-tokens-source
|
||||||
[changes library-id]
|
[changes library-id]
|
||||||
(assert-file-data! changes)
|
(assert-library! changes)
|
||||||
(let [file-data (::file-data (meta changes))
|
(let [library-data (::library-data (meta changes))
|
||||||
file-id (:id file-data)
|
file-id (:id library-data)
|
||||||
prev-val (:tokens-source file-data)]
|
prev-val (:tokens-source library-data)]
|
||||||
(-> changes
|
(-> changes
|
||||||
(update :redo-changes conj {:type :set-tokens-source
|
(update :redo-changes conj {:type :set-tokens-source
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
|
|||||||
@ -463,13 +463,43 @@
|
|||||||
(update :tokens-status #(or % (ctos/make-tokens-status)))))
|
(update :tokens-status #(or % (ctos/make-tokens-status)))))
|
||||||
|
|
||||||
(defn get-tokens-source
|
(defn get-tokens-source
|
||||||
|
"Return the current tokens source of the file. When there is no explicit :tokens-source attribute,
|
||||||
|
the source is the file itself."
|
||||||
[file-data]
|
[file-data]
|
||||||
(:tokens-source file-data))
|
(or (:tokens-source file-data) (:id file-data)))
|
||||||
|
|
||||||
(defn set-tokens-source
|
(defn set-tokens-source
|
||||||
[file-data tokens-source]
|
[file-data tokens-source]
|
||||||
(assoc file-data :tokens-source tokens-source))
|
(assoc file-data :tokens-source tokens-source))
|
||||||
|
|
||||||
|
(defn tokens-source?
|
||||||
|
"Returns true if the given id is the current tokens source of the file-data.
|
||||||
|
When no tokens-source is set, the file's own id is considered the source if there are any tokens in it."
|
||||||
|
[file-data id]
|
||||||
|
(assert (uuid? id) "expected valid uuid")
|
||||||
|
(let [source (:tokens-source file-data)
|
||||||
|
tokens-lib (:tokens-lib file-data)
|
||||||
|
has-tokens? (and (some? tokens-lib)
|
||||||
|
(not (ctob/empty-lib? tokens-lib)))]
|
||||||
|
(if (= id (:id file-data))
|
||||||
|
(and has-tokens?
|
||||||
|
(or (nil? source) (= source id)))
|
||||||
|
(= source id))))
|
||||||
|
|
||||||
|
(defn tokens-provider?
|
||||||
|
"Returns true if the file MAY become a tokens source. This is if the file has tokens and has
|
||||||
|
not configured another tokens source."
|
||||||
|
[file-data]
|
||||||
|
(and (some? (:tokens-lib file-data))
|
||||||
|
(or (nil? (:tokens-source file-data))
|
||||||
|
(= (:tokens-source file-data) (:id file-data)))))
|
||||||
|
|
||||||
|
(defn editable-tokens?
|
||||||
|
"Returns true if the file-data owns its tokens (no external source or source is itself)."
|
||||||
|
[file-data]
|
||||||
|
(let [source (:tokens-source file-data)]
|
||||||
|
(or (nil? source) (= source (:id file-data)))))
|
||||||
|
|
||||||
(defn get-tokens-lib
|
(defn get-tokens-lib
|
||||||
[file-data]
|
[file-data]
|
||||||
(:tokens-lib file-data))
|
(:tokens-lib file-data))
|
||||||
@ -656,7 +686,9 @@
|
|||||||
(conj force-set-id))]
|
(conj force-set-id))]
|
||||||
(reduce (fn [tokens set-id]
|
(reduce (fn [tokens set-id]
|
||||||
(let [set (ctob/get-set tokens-lib set-id)]
|
(let [set (ctob/get-set tokens-lib set-id)]
|
||||||
(merge tokens (ctob/get-tokens- set))))
|
(if set
|
||||||
|
(merge tokens (ctob/get-tokens- set))
|
||||||
|
tokens)))
|
||||||
(d/ordered-map)
|
(d/ordered-map)
|
||||||
ordered-active)))
|
ordered-active)))
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
[app.common.types.tokens-status :as ctos]
|
[app.common.types.tokens-status :as ctos]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[clojure.datafy :refer [datafy]]
|
|
||||||
[clojure.test :as t]))
|
[clojure.test :as t]))
|
||||||
|
|
||||||
;; Helper functions
|
;; Helper functions
|
||||||
@ -235,25 +234,25 @@
|
|||||||
(t/is (ctos/tokens-status? (:tokens-status file-data')))))
|
(t/is (ctos/tokens-status? (:tokens-status file-data')))))
|
||||||
|
|
||||||
(t/testing "ensure-tokens-lib should not add a tokens-lib if there is a tokens-source"
|
(t/testing "ensure-tokens-lib should not add a tokens-lib if there is a tokens-source"
|
||||||
(let [tokens-source (uuid/next)
|
(let [source-id (uuid/next)
|
||||||
tokens-status (ctos/make-tokens-status)
|
tokens-status (ctos/make-tokens-status)
|
||||||
file (-> (thf/sample-file :file1)
|
file (-> (thf/sample-file :file1)
|
||||||
(assoc-in [:data :tokens-source] tokens-source)
|
(assoc-in [:data :tokens-source] source-id)
|
||||||
(assoc-in [:data :tokens-status] tokens-status))
|
(assoc-in [:data :tokens-status] tokens-status))
|
||||||
file-data (ctf/file-data file)
|
file-data (ctf/file-data file)
|
||||||
file-data' (cfo/ensure-tokens-lib file-data)]
|
file-data' (cfo/ensure-tokens-lib file-data)]
|
||||||
(t/is (not (contains? file-data' :tokens-lib)))
|
(t/is (not (contains? file-data' :tokens-lib)))
|
||||||
(t/is (= tokens-source (:tokens-source file-data')))
|
(t/is (= source-id (:tokens-source file-data')))
|
||||||
(t/is (= tokens-status (:tokens-status file-data')))))
|
(t/is (= tokens-status (:tokens-status file-data')))))
|
||||||
|
|
||||||
(t/testing "ensure-tokens-lib should not add a tokens-lib if there is a tokens-source, but should add a tokens-status if it's missing"
|
(t/testing "ensure-tokens-lib should not add a tokens-lib if there is a tokens-source, but should add a tokens-status if it's missing"
|
||||||
(let [tokens-source (uuid/next)
|
(let [source-id (uuid/next)
|
||||||
file (-> (thf/sample-file :file1)
|
file (-> (thf/sample-file :file1)
|
||||||
(assoc-in [:data :tokens-source] tokens-source))
|
(assoc-in [:data :tokens-source] source-id))
|
||||||
file-data (ctf/file-data file)
|
file-data (ctf/file-data file)
|
||||||
file-data' (cfo/ensure-tokens-lib file-data)]
|
file-data' (cfo/ensure-tokens-lib file-data)]
|
||||||
(t/is (not (contains? file-data' :tokens-lib)))
|
(t/is (not (contains? file-data' :tokens-lib)))
|
||||||
(t/is (= tokens-source (:tokens-source file-data')))
|
(t/is (= source-id (:tokens-source file-data')))
|
||||||
(t/is (contains? file-data' :tokens-status))
|
(t/is (contains? file-data' :tokens-status))
|
||||||
(t/is (ctos/tokens-status? (:tokens-status file-data'))))))
|
(t/is (ctos/tokens-status? (:tokens-status file-data'))))))
|
||||||
|
|
||||||
@ -268,20 +267,224 @@
|
|||||||
|
|
||||||
(t/deftest test-get-tokens-source
|
(t/deftest test-get-tokens-source
|
||||||
(t/testing "returns tokens-source from file data"
|
(t/testing "returns tokens-source from file data"
|
||||||
(let [file-id (thi/new-id! :tokens-source)
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
file-data {:tokens-source file-id}]
|
file (-> (thf/sample-file :file1)
|
||||||
(t/is (= file-id (cfo/get-tokens-source file-data)))))
|
(assoc-in [:data :tokens-source] source-id))]
|
||||||
|
(t/is (= source-id (cfo/get-tokens-source (:data file))))))
|
||||||
|
|
||||||
(t/testing "returns nil when no tokens-source"
|
(t/testing "returns file id when no tokens-source"
|
||||||
(t/is (nil? (cfo/get-tokens-source {})))))
|
(let [file (thf/sample-file :file1)]
|
||||||
|
(t/is (= (:id file) (cfo/get-tokens-source file))))))
|
||||||
|
|
||||||
(t/deftest test-set-tokens-source
|
(t/deftest test-set-tokens-source
|
||||||
(t/testing "sets tokens-source on file data"
|
(t/testing "sets tokens-source on file data"
|
||||||
(let [file-id (thi/new-id! :tokens-source)
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
file-data {:other :data}
|
file (thf/sample-file :file1)
|
||||||
file-data' (cfo/set-tokens-source file-data file-id)]
|
file-data (:data file)
|
||||||
(t/is (= file-id (:tokens-source file-data')))
|
file-data' (cfo/set-tokens-source file-data source-id)]
|
||||||
(t/is (= :data (:other file-data'))))))
|
(t/is (= source-id (:tokens-source file-data'))))))
|
||||||
|
|
||||||
|
(t/deftest test-tokens-source?
|
||||||
|
(t/testing "no tokens, no tokens-source, ask for file id -> false"
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, no tokens-source, ask for file id -> false"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "tokens, no tokens-source, ask for file id -> true"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (true? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "no tokens, no tokens source, ask for other id -> false"
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, no tokens source, ask for other id -> false"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
(t/testing "tokens, no tokens source, ask for other id -> false"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
;; ---
|
||||||
|
|
||||||
|
(t/testing "no tokens, tokens source = file id, ask for file id -> false" ;; This case should not occur
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, tokens source = file id, ask for file id -> false" ;; This case should not occur
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "tokens, tokens source = file id, ask for file id -> true"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (true? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "no tokens, tokens source = file id, ask for other id -> false" ;; This case should not occur
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, tokens source = file id, ask for other id -> false" ;; This case should not occur
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
(t/testing "tokens, tokens source = file id, ask for other id -> false"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
;; ---
|
||||||
|
|
||||||
|
(t/testing "no tokens, tokens source = other id, ask for file id -> false"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, tokens source = other id, ask for file id -> false"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "tokens, tokens source = other id, ask for file id -> false"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (:id file-data))))))
|
||||||
|
|
||||||
|
(t/testing "no tokens, tokens source = other id, ask for this same id -> true"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (true? (cfo/tokens-source? file-data source-id)))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, tokens source = other id, ask for this same id -> true"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (true? (cfo/tokens-source? file-data source-id)))))
|
||||||
|
|
||||||
|
(t/testing "tokens, tokens source = other id, ask for this same id -> true"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (true? (cfo/tokens-source? file-data source-id)))))
|
||||||
|
|
||||||
|
(t/testing "no tokens, tokens source = other id, ask for a different id -> false"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
(t/testing "empty tokens-lib, tokens source = other id, ask for a different id -> false"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next))))))
|
||||||
|
|
||||||
|
(t/testing "tokens, tokens source = other id, ask for a different id -> false"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib)
|
||||||
|
(tht/update-tokens-lib
|
||||||
|
#(-> %
|
||||||
|
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
|
||||||
|
(ctob/add-token (thi/id :set-a) (ctob/make-token :id (thi/new-id! :tok1) :name "spacing" :type :spacing :value "8px")))))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/tokens-source? file-data (uuid/next)))))))
|
||||||
|
|
||||||
|
(t/deftest test-tokens-provider?
|
||||||
|
(t/testing "returns false if it has no tokens"
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (false? (cfo/tokens-provider? file-data)))))
|
||||||
|
|
||||||
|
(t/testing "returns true if it has tokens and no tokens-source"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (true? (cfo/tokens-provider? file-data)))))
|
||||||
|
|
||||||
|
(t/testing "returns true if it has tokens and tokens-source is its own id"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id file))]
|
||||||
|
(t/is (true? (cfo/tokens-provider? file-data)))))
|
||||||
|
|
||||||
|
(t/testing "returns false if it has tokens and tokens-source is other id"
|
||||||
|
(let [file (-> (thf/sample-file :file1)
|
||||||
|
(tht/add-tokens-lib))
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (uuid/next))]
|
||||||
|
(t/is (false? (cfo/tokens-provider? file-data))))))
|
||||||
|
|
||||||
|
(t/deftest test-editable-tokens?
|
||||||
|
(t/testing "returns true when file-data has no tokens-source"
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (:data file)]
|
||||||
|
(t/is (true? (cfo/editable-tokens? file-data)))))
|
||||||
|
|
||||||
|
(t/testing "returns true when tokens-source is the file's own id"
|
||||||
|
(let [file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) (:id (:data file)))]
|
||||||
|
(t/is (true? (cfo/editable-tokens? file-data)))))
|
||||||
|
|
||||||
|
(t/testing "returns false when tokens-source is a different uuid"
|
||||||
|
(let [source-id (thi/new-id! :tokens-source)
|
||||||
|
file (thf/sample-file :file1)
|
||||||
|
file-data (cfo/set-tokens-source (:data file) source-id)]
|
||||||
|
(t/is (false? (cfo/editable-tokens? file-data))))))
|
||||||
|
|
||||||
(t/deftest test-get-tokens-status
|
(t/deftest test-get-tokens-status
|
||||||
(t/testing "returns tokens-status from file data"
|
(t/testing "returns tokens-status from file data"
|
||||||
|
|||||||
@ -38,10 +38,11 @@
|
|||||||
([state file-id]
|
([state file-id]
|
||||||
(dm/get-in state [:files file-id :data])))
|
(dm/get-in state [:files file-id :data])))
|
||||||
|
|
||||||
|
;; TODO perhaps this is not necessary, lookup-tokens-lib should be enough
|
||||||
(defn lookup-tokens-source-data
|
(defn lookup-tokens-source-data
|
||||||
[state]
|
[state]
|
||||||
(let [current-file-data (lookup-file-data state)
|
(let [current-file-data (lookup-file-data state)
|
||||||
tokens-source-id (or (cfo/get-tokens-source current-file-data) (:id current-file-data))]
|
tokens-source-id (cfo/get-tokens-source current-file-data)]
|
||||||
(lookup-file-data state tokens-source-id)))
|
(lookup-file-data state tokens-source-id)))
|
||||||
|
|
||||||
(defn lookup-tokens-lib
|
(defn lookup-tokens-lib
|
||||||
|
|||||||
@ -1628,10 +1628,6 @@
|
|||||||
(map first)
|
(map first)
|
||||||
set)]
|
set)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(when (contains? cf/flags :token-lib-sync)
|
|
||||||
(rx/of (dch/commit-changes (-> (pcb/empty-changes nil)
|
|
||||||
(pcb/with-file-data file-data)
|
|
||||||
(pcb/set-tokens-source library-id)))))
|
|
||||||
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
||||||
(rx/merge-map (fn [libraries-to-load]
|
(rx/merge-map (fn [libraries-to-load]
|
||||||
(as-> libraries-to-load $
|
(as-> libraries-to-load $
|
||||||
|
|||||||
@ -420,6 +420,17 @@
|
|||||||
(rx/of (dch/commit-changes changes)
|
(rx/of (dch/commit-changes changes)
|
||||||
(dwtp/propagate-workspace-tokens))))))
|
(dwtp/propagate-workspace-tokens))))))
|
||||||
|
|
||||||
|
(defn set-tokens-source
|
||||||
|
[library-id]
|
||||||
|
(ptk/reify ::set-tokens-source
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [it state _]
|
||||||
|
(let [data (dsh/lookup-file-data state)
|
||||||
|
changes (-> (pcb/empty-changes it)
|
||||||
|
(pcb/with-library-data data)
|
||||||
|
(pcb/set-tokens-source library-id))]
|
||||||
|
(rx/of (dch/commit-changes changes))))))
|
||||||
|
|
||||||
(defn delete-token-set
|
(defn delete-token-set
|
||||||
[id]
|
[id]
|
||||||
(ptk/reify ::delete-token-set
|
(ptk/reify ::delete-token-set
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.files.tokens :as cfo]
|
||||||
[app.common.files.variant :as cfv]
|
[app.common.files.variant :as cfv]
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
@ -24,6 +25,7 @@
|
|||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
[app.main.data.workspace.colors :as mdc]
|
[app.main.data.workspace.colors :as mdc]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
|
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.render :refer [component-svg]]
|
[app.main.render :refer [component-svg]]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
@ -262,7 +264,7 @@
|
|||||||
|
|
||||||
unlink-library
|
unlink-library
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
(mf/deps file-id local-library)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [library-id (some-> (dom/get-current-target event)
|
(let [library-id (some-> (dom/get-current-target event)
|
||||||
(dom/get-data "library-id")
|
(dom/get-data "library-id")
|
||||||
@ -270,7 +272,11 @@
|
|||||||
(when (= library-id @selected)
|
(when (= library-id @selected)
|
||||||
(reset! selected :file))
|
(reset! selected :file))
|
||||||
(st/emit! (dwl/unlink-file-from-library file-id library-id)
|
(st/emit! (dwl/unlink-file-from-library file-id library-id)
|
||||||
(dwl/sync-file file-id library-id)))))
|
(dwl/sync-file file-id library-id))
|
||||||
|
;; When the unlinked library is the current tokens source,
|
||||||
|
;; we must reset it to the local library.
|
||||||
|
(when (cfo/tokens-source? local-library library-id)
|
||||||
|
(st/emit! (dwtl/set-tokens-source (:id local-library)))))))
|
||||||
|
|
||||||
import-tokens
|
import-tokens
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -283,6 +289,14 @@
|
|||||||
:tokens/import-from-library {:file-id file-id
|
:tokens/import-from-library {:file-id file-id
|
||||||
:library-id library-id})))))
|
:library-id library-id})))))
|
||||||
|
|
||||||
|
set-as-tokens-source
|
||||||
|
(mf/use-fn
|
||||||
|
(fn [event]
|
||||||
|
(let [library-id (some-> (dom/get-current-target event)
|
||||||
|
(dom/get-data "library-id")
|
||||||
|
(uuid/parse))]
|
||||||
|
(st/emit! (dwtl/set-tokens-source library-id)))))
|
||||||
|
|
||||||
on-delete-accept
|
on-delete-accept
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
(mf/deps file-id)
|
||||||
@ -335,7 +349,16 @@
|
|||||||
[:div {:class (stl/css :item-content)}
|
[:div {:class (stl/css :item-content)}
|
||||||
[:div {:class (stl/css :item-title)} (tr "workspace.libraries.file-library")]
|
[:div {:class (stl/css :item-title)} (tr "workspace.libraries.file-library")]
|
||||||
[:ul {:class (stl/css :item-contents)}
|
[:ul {:class (stl/css :item-contents)}
|
||||||
[:> library-description* {:summary summary}]]]
|
[:> library-description* {:summary summary}]]
|
||||||
|
(when (contains? cf/flags :token-lib-sync)
|
||||||
|
(if (cfo/tokens-source? local-library (:id local-library))
|
||||||
|
[:div (tr "workspace.libraries.tokens-source")]
|
||||||
|
(when (not= (cfo/get-tokens-source local-library) (:id local-library))
|
||||||
|
[:> button* {:variant "secondary"
|
||||||
|
:type "button"
|
||||||
|
:data-library-id (dm/str (:id local-library))
|
||||||
|
:on-click set-as-tokens-source}
|
||||||
|
(tr "workspace.libraries.set-as-tokens-source")])))]
|
||||||
|
|
||||||
(if ^boolean is-shared
|
(if ^boolean is-shared
|
||||||
[:> button* {:variant "secondary"
|
[:> button* {:variant "secondary"
|
||||||
@ -366,16 +389,28 @@
|
|||||||
[:div {:class (stl/css :connected-to-wrapper)}
|
[:div {:class (stl/css :connected-to-wrapper)}
|
||||||
[:span "(" (tr "workspace.libraries.connected-to") " "]
|
[:span "(" (tr "workspace.libraries.connected-to") " "]
|
||||||
[:span {:class (stl/css :connected-to-values)} (str/join ", " connected-to-names)]
|
[:span {:class (stl/css :connected-to-values)} (str/join ", " connected-to-names)]
|
||||||
[:span ")"]])])]]
|
[:span ")"]])])]
|
||||||
|
(when (contains? cf/flags :token-lib-sync)
|
||||||
|
(when (cfo/tokens-source? local-library id)
|
||||||
|
[:div (tr "workspace.libraries.tokens-source")]))]
|
||||||
|
|
||||||
[:div {:class (stl/css :library-actions)}
|
[:div {:class (stl/css :library-actions)}
|
||||||
(when ^boolean has-tokens?
|
(if (contains? cf/flags :token-lib-sync)
|
||||||
[:> icon-button*
|
(when (and (cfo/tokens-provider? (:data library))
|
||||||
{:type "button"
|
(not (cfo/tokens-source? local-library id)))
|
||||||
:aria-label (tr "workspace.tokens.import-tokens")
|
[:> button* {:variant "secondary"
|
||||||
:icon i/import-export
|
:type "button"
|
||||||
:data-library-id (dm/str id)
|
:data-library-id (dm/str id)
|
||||||
:variant "secondary"
|
:on-click set-as-tokens-source}
|
||||||
:on-click import-tokens}])
|
(tr "workspace.libraries.set-as-tokens-source")])
|
||||||
|
(when ^boolean has-tokens?
|
||||||
|
[:> icon-button*
|
||||||
|
{:type "button"
|
||||||
|
:aria-label (tr "workspace.tokens.import-tokens")
|
||||||
|
:icon i/import-export
|
||||||
|
:data-library-id (dm/str id)
|
||||||
|
:variant "secondary"
|
||||||
|
:on-click import-tokens}]))
|
||||||
|
|
||||||
[:> icon-button* {:type "button"
|
[:> icon-button* {:type "button"
|
||||||
:aria-label (tr "workspace.libraries.unlink-library-btn")
|
:aria-label (tr "workspace.libraries.unlink-library-btn")
|
||||||
|
|||||||
@ -8,8 +8,10 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.files.tokens :as cfo]
|
[app.common.files.tokens :as cfo]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.main.data.changes :as dch]
|
||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.style-dictionary :as sd]
|
[app.main.data.style-dictionary :as sd]
|
||||||
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
@ -53,6 +55,31 @@
|
|||||||
"Stops on `send-update-indices` function being called, which should be the last function of an event chain."
|
"Stops on `send-update-indices` function being called, which should be the last function of an event chain."
|
||||||
(stop-on ::end))
|
(stop-on ::end))
|
||||||
|
|
||||||
|
(defn watch-undo-stack
|
||||||
|
"Maintain the workspace undo stack by watching for commit events.
|
||||||
|
Must be emitted before the events under test so undo entries are populated."
|
||||||
|
[]
|
||||||
|
(ptk/reify ::watch-undo-stack
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ stream]
|
||||||
|
(let [stopper-s (->> stream (rx/filter (ptk/type? ::watch-undo-stack)))]
|
||||||
|
(->> stream
|
||||||
|
(rx/filter dch/commit?)
|
||||||
|
(rx/map deref)
|
||||||
|
(rx/filter #(= :local (:source %)))
|
||||||
|
(rx/mapcat
|
||||||
|
(fn [{:keys [save-undo? undo-changes redo-changes undo-group tags stack-undo? selected-before]}]
|
||||||
|
(if (and save-undo? (seq undo-changes))
|
||||||
|
(rx/of (dwu/append-undo
|
||||||
|
{:undo-changes undo-changes
|
||||||
|
:redo-changes redo-changes
|
||||||
|
:undo-group undo-group
|
||||||
|
:tags tags
|
||||||
|
:selected-before selected-before}
|
||||||
|
stack-undo?))
|
||||||
|
(rx/empty))))
|
||||||
|
(rx/take-until stopper-s))))))
|
||||||
|
|
||||||
;; Support for async events in tests
|
;; Support for async events in tests
|
||||||
;; https://chat.kaleidos.net/penpot-partners/pl/tz1yoes3w3fr9qanxqpuhoz3ch
|
;; https://chat.kaleidos.net/penpot-partners/pl/tz1yoes3w3fr9qanxqpuhoz3ch
|
||||||
(defn run-store
|
(defn run-store
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
(ns frontend-tests.tokens.logic.token-actions-test
|
(ns frontend-tests.tokens.logic.token-actions-test
|
||||||
(:require
|
(:require
|
||||||
[app.common.files.tokens :as cfo]
|
|
||||||
[app.common.test-helpers.compositions :as ctho]
|
[app.common.test-helpers.compositions :as ctho]
|
||||||
[app.common.test-helpers.files :as cthf]
|
[app.common.test-helpers.files :as cthf]
|
||||||
[app.common.test-helpers.ids-map :as cthi]
|
[app.common.test-helpers.ids-map :as cthi]
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
[app.common.types.tokens-status :as ctos]
|
[app.common.types.tokens-status :as ctos]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||||
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[cljs.test :as t :include-macros true]
|
[cljs.test :as t :include-macros true]
|
||||||
[frontend-tests.helpers.pages :as thp]
|
[frontend-tests.helpers.pages :as thp]
|
||||||
[frontend-tests.helpers.state :as ths]
|
[frontend-tests.helpers.state :as ths]
|
||||||
@ -123,4 +124,32 @@
|
|||||||
sets' (ctob/get-sets tokens-lib')]
|
sets' (ctob/get-sets tokens-lib')]
|
||||||
|
|
||||||
(t/testing "Set has been deleted"
|
(t/testing "Set has been deleted"
|
||||||
(t/is (= (count sets') 0)))))))))
|
(t/is (= (count sets') 0)))))))))
|
||||||
|
|
||||||
|
(t/deftest set-tokens-source
|
||||||
|
(t/async
|
||||||
|
done
|
||||||
|
(let [file (setup-file-with-token-lib)
|
||||||
|
store (ths/setup-store file)
|
||||||
|
library-id (uuid/next)]
|
||||||
|
|
||||||
|
;; Phase 1: set tokens-source with undo watcher active
|
||||||
|
(tohs/run-store
|
||||||
|
store identity
|
||||||
|
[(tohs/watch-undo-stack)
|
||||||
|
(dwtl/set-tokens-source library-id)]
|
||||||
|
(fn [new-state]
|
||||||
|
(let [file-data' (-> (ths/get-file-from-state new-state) :data)]
|
||||||
|
(t/testing "tokens-source is set to the library id"
|
||||||
|
(t/is (= library-id (:tokens-source file-data'))))))
|
||||||
|
(tohs/stop-on ::dwtl/set-tokens-source))
|
||||||
|
|
||||||
|
;; Phase 2: undo and verify restoration
|
||||||
|
(tohs/run-store
|
||||||
|
store done
|
||||||
|
[dwu/undo]
|
||||||
|
(fn [undone-state]
|
||||||
|
(let [file-data'' (-> (ths/get-file-from-state undone-state) :data)]
|
||||||
|
(t/testing "tokens-source is restored to nil"
|
||||||
|
(t/is (nil? (:tokens-source file-data''))))))
|
||||||
|
(tohs/stop-on ::dwu/undo)))))
|
||||||
|
|||||||
@ -7248,6 +7248,14 @@ msgstr "some templates in here"
|
|||||||
msgid "workspace.libraries.file-library"
|
msgid "workspace.libraries.file-library"
|
||||||
msgstr "File library"
|
msgstr "File library"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/libraries.cljs:336
|
||||||
|
msgid "workspace.libraries.tokens-source"
|
||||||
|
msgstr "Tokens source"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/libraries.cljs:336
|
||||||
|
msgid "workspace.libraries.set-as-tokens-source"
|
||||||
|
msgstr "Set as tokens source"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/libraries.cljs:100, src/app/main/ui/workspace/libraries.cljs:124
|
#: src/app/main/ui/workspace/libraries.cljs:100, src/app/main/ui/workspace/libraries.cljs:124
|
||||||
msgid "workspace.libraries.graphics"
|
msgid "workspace.libraries.graphics"
|
||||||
msgid_plural "workspace.libraries.graphics"
|
msgid_plural "workspace.libraries.graphics"
|
||||||
|
|||||||
@ -7081,6 +7081,14 @@ msgstr "algunas plantillas aquí"
|
|||||||
msgid "workspace.libraries.file-library"
|
msgid "workspace.libraries.file-library"
|
||||||
msgstr "Biblioteca del archivo"
|
msgstr "Biblioteca del archivo"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/libraries.cljs:336
|
||||||
|
msgid "workspace.libraries.tokens-source"
|
||||||
|
msgstr "Fuente de tokens"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/libraries.cljs:336
|
||||||
|
msgid "workspace.libraries.set-as-tokens-source"
|
||||||
|
msgstr "Activar fuente de tokens"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/libraries.cljs:100, src/app/main/ui/workspace/libraries.cljs:124
|
#: src/app/main/ui/workspace/libraries.cljs:100, src/app/main/ui/workspace/libraries.cljs:124
|
||||||
msgid "workspace.libraries.graphics"
|
msgid "workspace.libraries.graphics"
|
||||||
msgid_plural "workspace.libraries.graphics"
|
msgid_plural "workspace.libraries.graphics"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user