diff --git a/.gitignore b/.gitignore
index 8883932e85..0e271d1257 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@
/*.jpg
/*.md
/*.png
+/*.svg
/*.sql
/*.txt
/*.yml
diff --git a/backend/deps.edn b/backend/deps.edn
index b3cacd663a..d3c9893183 100644
--- a/backend/deps.edn
+++ b/backend/deps.edn
@@ -26,7 +26,7 @@
:git/url "https://github.com/funcool/yetti.git"
:exclusions [org.slf4j/slf4j-api]}
- com.github.seancorfield/next.jdbc {:mvn/version "1.3.894"}
+ com.github.seancorfield/next.jdbc {:mvn/version "1.3.909"}
metosin/reitit-core {:mvn/version "0.6.0"}
nrepl/nrepl {:mvn/version "1.1.0"}
cider/cider-nrepl {:mvn/version "0.43.1"}
diff --git a/backend/dev/user.clj b/backend/dev/user.clj
index 902ba62129..5d0cb7e371 100644
--- a/backend/dev/user.clj
+++ b/backend/dev/user.clj
@@ -8,6 +8,7 @@
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
+ [app.common.files.helpers :as cfh]
[app.common.fressian :as fres]
[app.common.geom.matrix :as gmt]
[app.common.logging :as l]
@@ -136,3 +137,12 @@
(add-tap #(locking debug-tap
(prn "tap debug:" %)))
1))
+
+
+(defn calculate-frames
+ [{:keys [data]}]
+ (->> (vals (:pages-index data))
+ (mapcat (comp vals :objects))
+ (filter cfh/is-direct-child-of-root?)
+ (filter cfh/frame-shape?)
+ (count)))
diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj
index f5a1602aff..ef021d7c1b 100644
--- a/backend/src/app/config.clj
+++ b/backend/src/app/config.clj
@@ -207,6 +207,7 @@
(s/def ::telemetry-uri ::us/string)
(s/def ::telemetry-with-taiga ::us/boolean)
(s/def ::tenant ::us/string)
+(s/def ::svgo-max-procs ::us/integer)
(s/def ::config
(s/keys :opt-un [::secret-key
@@ -326,7 +327,9 @@
::telemetry-uri
::telemetry-referer
::telemetry-with-taiga
- ::tenant]))
+ ::tenant
+
+ ::svgo-max-procs]))
(def default-flags
[:enable-backend-api-doc
diff --git a/backend/src/app/db.clj b/backend/src/app/db.clj
index 8d7fbef4c9..b1c8476a76 100644
--- a/backend/src/app/db.clj
+++ b/backend/src/app/db.clj
@@ -19,6 +19,7 @@
[app.util.json :as json]
[app.util.time :as dt]
[clojure.java.io :as io]
+ [clojure.set :as set]
[clojure.spec.alpha :as s]
[integrant.core :as ig]
[next.jdbc :as jdbc]
@@ -239,6 +240,10 @@
(ex/raise :type :internal
:code :unable-resolve-pool))))
+(defn get-update-count
+ [result]
+ (:next.jdbc/update-count result))
+
(defn get-connection
[cfg-or-conn]
(if (connection? cfg-or-conn)
@@ -265,48 +270,120 @@
:code :unable-resolve-connectable
:hint "expected conn, pool or system")))
+(def ^:private params-mapping
+ {::return-keys? :return-keys
+ ::return-keys :return-keys})
+
+(defn rename-opts
+ [opts]
+ (set/rename-keys opts params-mapping))
+
+(def ^:private default-insert-opts
+ {:builder-fn sql/as-kebab-maps
+ :return-keys true})
+
(def ^:private default-opts
{:builder-fn sql/as-kebab-maps})
(defn exec!
- ([ds sv]
- (-> (get-connectable ds)
- (jdbc/execute! sv default-opts)))
+ ([ds sv] (exec! ds sv nil))
([ds sv opts]
- (-> (get-connectable ds)
- (jdbc/execute! sv (into default-opts (sql/adapt-opts opts))))))
+ (let [conn (get-connectable ds)
+ opts (if (empty? opts)
+ default-opts
+ (into default-opts (rename-opts opts)))]
+ (jdbc/execute! conn sv opts))))
(defn exec-one!
- ([ds sv]
- (-> (get-connectable ds)
- (jdbc/execute-one! sv default-opts)))
+ ([ds sv] (exec-one! ds sv nil))
([ds sv opts]
- (-> (get-connectable ds)
- (jdbc/execute-one! sv (into default-opts (sql/adapt-opts opts))))))
+ (let [conn (get-connectable ds)
+ opts (if (empty? opts)
+ default-opts
+ (into default-opts (rename-opts opts)))]
+ (jdbc/execute-one! conn sv opts))))
(defn insert!
- [ds table params & {:as opts :keys [::return-keys?] :or {return-keys? true}}]
- (-> (get-connectable ds)
- (exec-one! (sql/insert table params opts)
- (assoc opts ::return-keys? return-keys?))))
+ "A helper that builds an insert sql statement and executes it. By
+ default returns the inserted row with all the field; you can delimit
+ the returned columns with the `::columns` option."
+ [ds table params & {:as opts}]
+ (let [conn (get-connectable ds)
+ sql (sql/insert table params opts)
+ opts (if (empty? opts)
+ default-insert-opts
+ (into default-insert-opts (rename-opts opts)))]
+ (jdbc/execute-one! conn sql opts)))
-(defn insert-multi!
- [ds table cols rows & {:as opts :keys [::return-keys?] :or {return-keys? true}}]
- (-> (get-connectable ds)
- (exec! (sql/insert-multi table cols rows opts)
- (assoc opts ::return-keys? return-keys?))))
+(defn insert-many!
+ "An optimized version of `insert!` that perform insertion of multiple
+ values at once.
+
+ This expands to a single SQL statement with placeholders for every
+ value being inserted. For large data sets, this may exceed the limit
+ of sql string size and/or number of parameters."
+ [ds table cols rows & {:as opts}]
+ (let [conn (get-connectable ds)
+ sql (sql/insert-many table cols rows opts)
+ opts (if (empty? opts)
+ default-insert-opts
+ (into default-insert-opts (rename-opts opts)))
+ opts (update opts :return-keys boolean)]
+ (jdbc/execute! conn sql opts)))
(defn update!
- [ds table params where & {:as opts :keys [::return-keys?] :or {return-keys? true}}]
- (-> (get-connectable ds)
- (exec-one! (sql/update table params where opts)
- (assoc opts ::return-keys? return-keys?))))
+ "A helper that build an UPDATE SQL statement and executes it.
+
+ Given a connectable object, a table name, a hash map of columns and
+ values to set, and either a hash map of columns and values to search
+ on or a vector of a SQL where clause and parameters, perform an
+ update on the table.
+
+ By default returns an object with the number of affected rows; a
+ complete row can be returned if you pass `::return-keys` with `true`
+ or with a vector of columns.
+
+ Also it can be combined with the `::many` option if you perform an
+ update to multiple rows and you want all the affected rows to be
+ returned."
+ [ds table params where & {:as opts}]
+ (let [conn (get-connectable ds)
+ sql (sql/update table params where opts)
+ opts (if (empty? opts)
+ default-opts
+ (into default-opts (rename-opts opts)))
+ opts (update opts :return-keys boolean)]
+ (if (::many opts)
+ (jdbc/execute! conn sql opts)
+ (jdbc/execute-one! conn sql opts))))
(defn delete!
- [ds table params & {:as opts :keys [::return-keys?] :or {return-keys? true}}]
- (-> (get-connectable ds)
- (exec-one! (sql/delete table params opts)
- (assoc opts ::return-keys? return-keys?))))
+ "A helper that builds an DELETE SQL statement and executes it.
+
+ Given a connectable object, a table name, and either a hash map of columns
+ and values to search on or a vector of a SQL where clause and parameters,
+ perform a delete on the table.
+
+ By default returns an object with the number of affected rows; a
+ complete row can be returned if you pass `::return-keys` with `true`
+ or with a vector of columns.
+
+ Also it can be combined with the `::many` option if you perform an
+ update to multiple rows and you want all the affected rows to be
+ returned."
+ [ds table params & {:as opts}]
+ (let [conn (get-connectable ds)
+ sql (sql/delete table params opts)
+ opts (if (empty? opts)
+ default-opts
+ (into default-opts (rename-opts opts)))]
+ (if (::many opts)
+ (jdbc/execute! conn sql opts)
+ (jdbc/execute-one! conn sql opts))))
+
+(defn query
+ [ds table params & {:as opts}]
+ (exec! ds (sql/select table params opts) opts))
(defn is-row-deleted?
[{:keys [deleted-at]}]
@@ -320,7 +397,7 @@
[ds table params & {:as opts}]
(let [rows (exec! ds (sql/select table params opts))
rows (cond->> rows
- (::remove-deleted? opts true)
+ (::remove-deleted opts true)
(remove is-row-deleted?))]
(first rows)))
@@ -329,7 +406,7 @@
filters. Raises :not-found exception if no object is found."
[ds table params & {:as opts}]
(let [row (get* ds table params opts)]
- (when (and (not row) (::check-deleted? opts true))
+ (when (and (not row) (::check-deleted opts true))
(ex/raise :type :not-found
:code :object-not-found
:table table
@@ -341,14 +418,29 @@
(-> (get-connectable ds)
(jdbc/plan sql sql/default-opts)))
+(defn cursor
+ "Return a lazy seq of rows using server side cursors"
+ [conn query & {:keys [chunk-size] :or {chunk-size 25}}]
+ (let [cname (str (gensym "cursor_"))
+ fquery [(str "FETCH " chunk-size " FROM " cname)]]
+
+ ;; declare cursor
+ (exec-one! conn
+ (if (vector? query)
+ (into [(str "DECLARE " cname " CURSOR FOR " (nth query 0))]
+ (rest query))
+ [(str "DECLARE " cname " CURSOR FOR " query)]))
+
+ ;; return a lazy seq
+ ((fn fetch-more []
+ (lazy-seq
+ (when-let [chunk (seq (exec! conn fquery))]
+ (concat chunk (fetch-more))))))))
+
(defn get-by-id
[ds table id & {:as opts}]
(get ds table {:id id} opts))
-(defn query
- [ds table params & {:as opts}]
- (exec! ds (sql/select table params opts)))
-
(defn pgobject?
([v]
(instance? PGobject v))
@@ -548,11 +640,6 @@
(.setType "jsonb")
(.setValue (json/encode-str data)))))
-(defn get-update-count
- [result]
- (:next.jdbc/update-count result))
-
-
;; --- Locks
(def ^:private siphash-state
diff --git a/backend/src/app/db/sql.clj b/backend/src/app/db/sql.clj
index 4b002f41b1..37814733de 100644
--- a/backend/src/app/db/sql.clj
+++ b/backend/src/app/db/sql.clj
@@ -8,7 +8,6 @@
(:refer-clojure :exclude [update])
(:require
[app.db :as-alias db]
- [clojure.set :as set]
[clojure.string :as str]
[next.jdbc.optional :as jdbc-opt]
[next.jdbc.sql.builder :as sql]))
@@ -20,14 +19,6 @@
{:table-fn snake-case
:column-fn snake-case})
-(def params-mapping
- {::db/return-keys? :return-keys
- ::db/columns :columns})
-
-(defn adapt-opts
- [opts]
- (set/rename-keys opts params-mapping))
-
(defn as-kebab-maps
[rs opts]
(jdbc-opt/as-unqualified-modified-maps rs (assoc opts :label-fn kebab-case)))
@@ -42,7 +33,7 @@
(assoc :suffix "ON CONFLICT DO NOTHING"))]
(sql/for-insert table key-map opts))))
-(defn insert-multi
+(defn insert-many
[table cols rows opts]
(let [opts (merge default-opts opts)]
(sql/for-insert-multi table cols rows opts)))
@@ -53,11 +44,9 @@
([table where-params opts]
(let [opts (merge default-opts opts)
opts (cond-> opts
- (::db/columns opts) (assoc :columns (::db/columns opts))
- (::db/for-update? opts) (assoc :suffix "FOR UPDATE")
- (::db/for-share? opts) (assoc :suffix "FOR KEY SHARE")
- (:for-update opts) (assoc :suffix "FOR UPDATE")
- (:for-key-share opts) (assoc :suffix "FOR KEY SHARE"))]
+ (::columns opts) (assoc :columns (::columns opts))
+ (::for-update opts) (assoc :suffix "FOR UPDATE")
+ (::for-share opts) (assoc :suffix "FOR KEY SHARE"))]
(sql/for-query table where-params opts))))
(defn update
@@ -65,11 +54,9 @@
(update table key-map where-params nil))
([table key-map where-params opts]
(let [opts (into default-opts opts)
- opts (if-let [columns (::db/columns opts)]
- (let [columns (if (seq columns)
- (sql/as-cols columns opts)
- "*")]
- (assoc opts :suffix (str "RETURNING " columns)))
+ keys (::db/return-keys opts)
+ opts (if (vector? keys)
+ (assoc opts :suffix (str "RETURNING " (sql/as-cols keys opts)))
opts)]
(sql/for-update table key-map where-params opts))))
@@ -77,5 +64,9 @@
([table where-params]
(delete table where-params nil))
([table where-params opts]
- (let [opts (merge default-opts opts)]
+ (let [opts (merge default-opts opts)
+ keys (::db/return-keys opts)
+ opts (if (vector? keys)
+ (assoc opts :suffix (str "RETURNING " (sql/as-cols keys opts)))
+ opts)]
(sql/for-delete table where-params opts))))
diff --git a/backend/src/app/features/components_v2.clj b/backend/src/app/features/components_v2.clj
index 99074dd598..3c5d3e5b0f 100644
--- a/backend/src/app/features/components_v2.clj
+++ b/backend/src/app/features/components_v2.clj
@@ -39,27 +39,54 @@
[app.rpc.commands.media :as cmd.media]
[app.storage :as sto]
[app.storage.tmp :as tmp]
+ [app.svgo :as svgo]
[app.util.blob :as blob]
[app.util.pointer-map :as pmap]
[app.util.time :as dt]
[buddy.core.codecs :as bc]
[cuerdas.core :as str]
[datoteka.io :as io]
- [promesa.exec :as px]
- [promesa.exec.semaphore :as ps]
- [promesa.util :as pu]))
+ [promesa.core :as p]))
-(def ^:dynamic *system* nil)
-(def ^:dynamic *stats* nil)
-(def ^:dynamic *file-stats* nil)
-(def ^:dynamic *team-stats* nil)
-(def ^:dynamic *semaphore* nil)
-(def ^:dynamic *skip-on-error* true)
+(def ^:dynamic *stats*
+ "A dynamic var for setting up state for collect stats globally."
+ nil)
+
+(def ^:dynamic *skip-on-error*
+ "A dynamic var for setting up the default error behavior."
+ true)
+
+(def ^:dynamic ^:private *system*
+ "An internal var for making the current `system` available to all
+ internal functions without the need to explicitly pass it top down."
+ nil)
+
+(def ^:dynamic ^:private *max-procs*
+ "A dynamic variable that can optionally indicates the maxumum number
+ of concurrent graphics migration processes."
+ nil)
+
+(def ^:dynamic ^:private *file-stats*
+ "An internal dynamic var for collect stats by file."
+ nil)
+
+(def ^:dynamic ^:private *team-stats*
+ "An internal dynamic var for collect stats by team."
+ nil)
(def grid-gap 50)
(def frame-gap 200)
(def max-group-size 50)
+(defn decode-row
+ [{:keys [features data] :as row}]
+ (cond-> row
+ (some? features)
+ (assoc :features (db/decode-pgarray features #{}))
+
+ (some? data)
+ (assoc :data (blob/decode data))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FILE PREPARATION BEFORE MIGRATION
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -220,19 +247,17 @@
(fn [file-data]
;; Transform component and copy heads to frames, and set the
;; frame-id of its childrens
- (letfn [(fix-container
- [container]
+ (letfn [(fix-container [container]
(update container :objects update-vals fix-shape))
- (fix-shape
- [shape]
+ (fix-shape [shape]
(if (or (nil? (:parent-id shape)) (ctk/instance-head? shape))
(assoc shape
- :type :frame ; Old groups must be converted
- :fills (or (:fills shape) []) ; to frames and conform to spec
- :hide-in-viewer (or (:hide-in-viewer shape) true)
- :rx (or (:rx shape) 0)
- :ry (or (:ry shape) 0))
+ :type :frame ; Old groups must be converted
+ :fills (or (:fills shape) []) ; to frames and conform to spec
+ :hide-in-viewer (or (:hide-in-viewer shape) true)
+ :rx (or (:rx shape) 0)
+ :ry (or (:ry shape) 0))
shape))]
(-> file-data
(update :pages-index update-vals fix-container)
@@ -310,10 +335,10 @@
(defn- get-asset-groups
[assets generic-name]
- (let [; Group by first element of the path.
+ (let [;; Group by first element of the path.
groups (d/group-by #(first (cfh/split-path (:path %))) assets)
- ; Split large groups in chunks of max-group-size elements
+ ;; Split large groups in chunks of max-group-size elements
groups (loop [groups (seq groups)
result {}]
(if (empty? groups)
@@ -334,15 +359,14 @@
result
splits)))))))
- ; Sort assets in each group by path
+ ;; Sort assets in each group by path
groups (update-vals groups (fn [assets]
(sort-by (fn [{:keys [path name]}]
(str/lower (cfh/merge-path-item path name)))
- assets)))
+ assets)))]
- ; Sort groups by name
- groups (into (sorted-map) groups)]
- groups))
+ ;; Sort groups by name
+ (into (sorted-map) groups)))
(defn- create-frame
[name position width height]
@@ -612,14 +636,11 @@
(defn- create-shapes-for-svg
[{:keys [id] :as mobj} file-id objects frame-id position]
- (let [svg-text (get-svg-content id)
-
- optimizer (::csvg/optimizer *system*)
- svg-text (csvg/optimize optimizer svg-text)
-
- svg-data (-> (csvg/parse svg-text)
- (assoc :name (:name mobj))
- (collect-and-persist-images file-id))]
+ (let [svg-text (get-svg-content id)
+ svg-text (svgo/optimize *system* svg-text)
+ svg-data (-> (csvg/parse svg-text)
+ (assoc :name (:name mobj))
+ (collect-and-persist-images file-id))]
(sbuilder/create-svg-shapes svg-data position objects frame-id frame-id #{} false)))
@@ -678,9 +699,7 @@
(defn- create-media-grid
[fdata page-id frame-id grid media-group]
- (let [factory (px/thread-factory :virtual true)
- executor (px/fixed-executor :parallelism 10 :factory factory)
- process (fn [mobj position]
+ (let [process (fn [mobj position]
(let [position (gpt/add position (gpt/point grid-gap grid-gap))
tp1 (dt/tpoint)]
(try
@@ -690,7 +709,6 @@
:file-id (str (:id fdata))
:id (str (:id mobj))
:cause cause)
-
(if-not *skip-on-error*
(throw cause)
nil))
@@ -699,21 +717,24 @@
:file-id (str (:id fdata))
:media-id (str (:id mobj))
:elapsed (dt/format-duration (tp1)))))))]
- (try
- (->> (d/zip media-group grid)
- (map (fn [[mobj position]]
- (sse/tap {:type :migration-progress
- :section :graphics
- :name (:name mobj)})
- (px/submit! executor (partial process mobj position))))
- (reduce (fn [fdata promise]
- (if-let [changes (deref promise)]
- (-> (assoc-in fdata [:options :components-v2] true)
- (cp/process-changes changes false))
- fdata))
- fdata))
- (finally
- (pu/close! executor)))))
+
+ (->> (d/zip media-group grid)
+ (partition-all (or *max-procs* 1))
+ (mapcat (fn [partition]
+ (->> partition
+ (map (fn [[mobj position]]
+ (sse/tap {:type :migration-progress
+ :section :graphics
+ :name (:name mobj)})
+ (p/vthread (process mobj position))))
+ (doall)
+ (map deref)
+ (doall))))
+ (filter some?)
+ (reduce (fn [fdata changes]
+ (-> (assoc-in fdata [:options :components-v2] true)
+ (cp/process-changes changes false)))
+ fdata))))
(defn- migrate-graphics
[fdata]
@@ -759,6 +780,11 @@
(create-media-grid fdata page-id (:id frame) grid assets)
(gpt/add position (gpt/point 0 (+ height (* 2 grid-gap) frame-gap))))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; PRIVATE HELPERS
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
(defn- migrate-fdata
[fdata libs]
(let [migrated? (dm/get-in fdata [:options :components-v2])]
@@ -771,11 +797,22 @@
(defn- get-file
[system id]
(binding [pmap/*load-fn* (partial fdata/load-pointer system id)]
- (-> (files/get-file system id :migrate? false)
+ (-> (db/get system :file {:id id}
+ {::db/remove-deleted false
+ ::db/check-deleted false})
+ (decode-row)
(update :data assoc :id id)
(update :data fdata/process-pointers deref)
(fmg/migrate-file))))
+
+(defn- get-team
+ [system team-id]
+ (-> (db/get system :team {:id team-id}
+ {::db/remove-deleted false
+ ::db/check-deleted false})
+ (decode-row)))
+
(defn- validate-file!
[file libs throw-on-validate?]
(try
@@ -791,7 +828,8 @@
(let [file (get-file system id)
libs (->> (files/get-file-libraries conn id)
- (into [file] (comp (map :id) (map (partial get-file system))))
+ (into [file] (comp (map :id)
+ (map (partial get-file system))))
(d/index-by :id))
file (-> file
@@ -816,18 +854,39 @@
{:data (blob/encode (:data file))
:features (db/create-array conn "text" (:features file))
:revn (:revn file)}
- {:id (:id file)}
- {::db/return-keys? false})
+ {:id (:id file)})
(dissoc file :data)))
+
+(def ^:private sql:get-and-lock-team-files
+ "SELECT f.id
+ FROM file AS f
+ JOIN project AS p ON (p.id = f.project_id)
+ WHERE p.team_id = ?
+ FOR UPDATE")
+
+(defn- get-and-lock-files
+ [conn team-id]
+ (->> (db/cursor conn [sql:get-and-lock-team-files team-id])
+ (map :id)))
+
+(defn- update-team-features!
+ [conn team-id features]
+ (let [features (db/create-array conn "text" features)]
+ (db/update! conn :team
+ {:features features}
+ {:id team-id})))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; PUBLIC API
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
(defn migrate-file!
- [system file-id & {:keys [validate? throw-on-validate?]}]
- (let [tpoint (dt/tpoint)
- file-id (if (string? file-id)
- (parse-uuid file-id)
- file-id)]
- (binding [*file-stats* (atom {})]
+ [system file-id & {:keys [validate? throw-on-validate? max-procs]}]
+ (let [tpoint (dt/tpoint)]
+ (binding [*file-stats* (atom {})
+ *max-procs* max-procs]
(try
(l/dbg :hint "migrate:file:start" :file-id (str file-id))
@@ -839,7 +898,6 @@
(process-file system file-id
:validate? validate?
:throw-on-validate? throw-on-validate?)))))
-
(finally
(let [elapsed (tpoint)
components (get @*file-stats* :processed/components 0)
@@ -855,73 +913,51 @@
(some-> *team-stats* (swap! update :processed/files (fnil inc 0)))))))))
(defn migrate-team!
- [system team-id & {:keys [validate? throw-on-validate?]}]
- (let [tpoint (dt/tpoint)
- team-id (if (string? team-id)
- (parse-uuid team-id)
- team-id)]
- (l/dbg :hint "migrate:team:start" :team-id (dm/str team-id))
+ [system team-id & {:keys [validate? throw-on-validate? max-procs]}]
+
+ (l/dbg :hint "migrate:team:start"
+ :team-id (dm/str team-id))
+
+ (let [tpoint (dt/tpoint)
+
+ migrate-file
+ (fn [system file-id]
+ (migrate-file! system file-id
+ :max-procs max-procs
+ :validate? validate?
+ :throw-on-validate? throw-on-validate?))
+ migrate-team
+ (fn [{:keys [::db/conn] :as system} {:keys [id features] :as team}]
+ (let [features (-> features
+ (disj "ephimeral/v2-migration")
+ (conj "components/v2")
+ (conj "layout/grid")
+ (conj "styles/v2"))]
+
+ (run! (partial migrate-file system)
+ (get-and-lock-files conn id))
+
+ (update-team-features! conn id features)))]
+
(binding [*team-stats* (atom {})]
(try
- ;; We execute this out of transaction because we want this
- ;; change to be visible to all other sessions before starting
- ;; the migration
- (let [sql (str "UPDATE team SET features = "
- " array_append(features, 'ephimeral/v2-migration') "
- " WHERE id = ?")]
- (db/exec-one! system [sql team-id]))
-
- (db/tx-run! system
- (fn [{:keys [::db/conn] :as system}]
- ;; Lock the team
- (db/exec-one! conn ["SET idle_in_transaction_session_timeout = 0"])
-
- (let [{:keys [features] :as team} (-> (db/get conn :team {:id team-id})
- (update :features db/decode-pgarray #{}))]
-
- (if (contains? features "components/v2")
- (l/dbg :hint "team already migrated")
- (let [sql (str/concat
- "SELECT f.id FROM file AS f "
- " JOIN project AS p ON (p.id = f.project_id) "
- "WHERE p.team_id = ? AND f.deleted_at IS NULL AND p.deleted_at IS NULL "
- "FOR UPDATE")]
-
- (doseq [file-id (->> (db/exec! conn [sql team-id])
- (map :id))]
- (migrate-file! system file-id
- :validate? validate?
- :throw-on-validate? throw-on-validate?))
-
- (let [features (-> features
- (disj "ephimeral/v2-migration")
- (conj "components/v2")
- (conj "layout/grid")
- (conj "styles/v2"))]
- (db/update! conn :team
- {:features (db/create-array conn "text" features)}
- {:id team-id})))))))
+ (db/tx-run! system (fn [system]
+ (db/exec-one! system ["SET idle_in_transaction_session_timeout = 0"])
+ (let [team (get-team system team-id)]
+ (if (contains? (:features team) "components/v2")
+ (l/inf :hint "team already migrated")
+ (migrate-team system team)))))
(finally
- (some-> *semaphore* ps/release!)
- (let [elapsed (tpoint)]
+ (let [elapsed (tpoint)
+ components (get @*team-stats* :processed/components 0)
+ graphics (get @*team-stats* :processed/graphics 0)
+ files (get @*team-stats* :processed/files 0)]
+
(some-> *stats* (swap! update :processed/teams (fnil inc 0)))
- ;; We execute this out of transaction because we want this
- ;; change to be visible to all other sessions before starting
- ;; the migration
- (let [sql (str "UPDATE team SET features = "
- " array_remove(features, 'ephimeral/v2-migration') "
- " WHERE id = ?")]
- (db/exec-one! system [sql team-id]))
-
- (let [components (get @*team-stats* :processed/components 0)
- graphics (get @*team-stats* :processed/graphics 0)
- files (get @*team-stats* :processed/files 0)]
- (l/dbg :hint "migrate:team:end"
- :team-id (dm/str team-id)
- :files files
- :components components
- :graphics graphics
- :elapsed (dt/format-duration elapsed)))))))))
-
-
+ (l/dbg :hint "migrate:team:end"
+ :team-id (dm/str team-id)
+ :files files
+ :components components
+ :graphics graphics
+ :elapsed (dt/format-duration elapsed))))))))
diff --git a/backend/src/app/features/fdata.clj b/backend/src/app/features/fdata.clj
index 832d3360d0..d04369d5d8 100644
--- a/backend/src/app/features/fdata.clj
+++ b/backend/src/app/features/fdata.clj
@@ -11,6 +11,7 @@
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.db :as db]
+ [app.db.sql :as-alias sql]
[app.util.blob :as blob]
[app.util.objects-map :as omap]
[app.util.pointer-map :as pmap]))
@@ -38,8 +39,8 @@
[system file-id id]
(let [{:keys [content]} (db/get system :file-data-fragment
{:id id :file-id file-id}
- {::db/columns [:content]
- ::db/check-deleted? false})]
+ {::sql/columns [:content]
+ ::db/check-deleted false})]
(when-not content
(ex/raise :type :internal
:code :fragment-not-found
diff --git a/backend/src/app/loggers/audit.clj b/backend/src/app/loggers/audit.clj
index 4171f52ab3..3fbd09bddf 100644
--- a/backend/src/app/loggers/audit.clj
+++ b/backend/src/app/loggers/audit.clj
@@ -133,7 +133,7 @@
[_ {:keys [::db/pool] :as cfg}]
(cond
(db/read-only? pool)
- (l/warn :hint "audit: disabled (db is read-only)")
+ (l/warn :hint "audit disabled (db is read-only)")
:else
cfg))
@@ -187,8 +187,7 @@
false)}))
(defn- handle-event!
- [conn-or-pool event]
- (us/verify! ::event event)
+ [cfg event]
(let [params {:id (uuid/next)
:name (::name event)
:type (::type event)
@@ -201,19 +200,22 @@
;; NOTE: this operation may cause primary key conflicts on inserts
;; because of the timestamp precission (two concurrent requests), in
;; this case we just retry the operation.
- (rtry/with-retry {::rtry/when rtry/conflict-exception?
- ::rtry/max-retries 6
- ::rtry/label "persist-audit-log"
- ::db/conn (dm/check db/connection? conn-or-pool)}
- (let [now (dt/now)]
- (db/insert! conn-or-pool :audit-log
- (-> params
- (update :props db/tjson)
- (update :context db/tjson)
- (update :ip-addr db/inet)
- (assoc :created-at now)
- (assoc :tracked-at now)
- (assoc :source "backend"))))))
+ (let [cfg (-> cfg
+ (assoc ::rtry/when rtry/conflict-exception?)
+ (assoc ::rtry/max-retries 6)
+ (assoc ::rtry/label "persist-audit-log"))
+ params (-> params
+ (update :props db/tjson)
+ (update :context db/tjson)
+ (update :ip-addr db/inet)
+ (assoc :source "backend"))]
+
+ (rtry/invoke cfg (fn [cfg]
+ (let [tnow (dt/now)
+ params (-> params
+ (assoc :created-at tnow)
+ (assoc :tracked-at tnow))]
+ (db/insert! cfg :audit-log params))))))
(when (and (contains? cf/flags :webhooks)
(::webhooks/event? event))
@@ -226,7 +228,7 @@
:else label)
dedupe? (boolean (and batch-key batch-timeout))]
- (wrk/submit! ::wrk/conn conn-or-pool
+ (wrk/submit! ::wrk/conn (::db/conn cfg)
::wrk/task :process-webhook-event
::wrk/queue :webhooks
::wrk/max-retries 0
@@ -243,12 +245,12 @@
(defn submit!
"Submit audit event to the collector."
[cfg params]
- (let [conn (or (::db/conn cfg) (::db/pool cfg))]
- (us/assert! ::db/pool-or-conn conn)
- (try
- (handle-event! conn (d/without-nils params))
- (catch Throwable cause
- (l/error :hint "audit: unexpected error processing event" :cause cause)))))
+ (try
+ (let [event (d/without-nils params)]
+ (us/verify! ::event event)
+ (db/tx-run! cfg handle-event! event))
+ (catch Throwable cause
+ (l/error :hint "unexpected error processing event" :cause cause))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TASK: ARCHIVE
diff --git a/backend/src/app/loggers/webhooks.clj b/backend/src/app/loggers/webhooks.clj
index eb0f14fc8c..00ebd3f383 100644
--- a/backend/src/app/loggers/webhooks.clj
+++ b/backend/src/app/loggers/webhooks.clj
@@ -111,9 +111,11 @@
" where id=?")
err
(:id whook)]
- res (db/exec-one! pool sql {::db/return-keys? true})]
+ res (db/exec-one! pool sql {::db/return-keys true})]
(when (>= (:error-count res) max-errors)
- (db/update! pool :webhook {:is-active false} {:id (:id whook)})))
+ (db/update! pool :webhook
+ {:is-active false}
+ {:id (:id whook)})))
(db/update! pool :webhook
{:updated-at (dt/now)
diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj
index 953f51d8be..c80210a06b 100644
--- a/backend/src/app/main.clj
+++ b/backend/src/app/main.clj
@@ -10,7 +10,6 @@
[app.auth.oidc :as-alias oidc]
[app.auth.oidc.providers :as-alias oidc.providers]
[app.common.logging :as l]
- [app.common.svg :as csvg]
[app.config :as cf]
[app.db :as-alias db]
[app.email :as-alias email]
@@ -34,7 +33,10 @@
[app.srepl :as-alias srepl]
[app.storage :as-alias sto]
[app.storage.fs :as-alias sto.fs]
+ [app.storage.gc-deleted :as-alias sto.gc-deleted]
+ [app.storage.gc-touched :as-alias sto.gc-touched]
[app.storage.s3 :as-alias sto.s3]
+ [app.svgo :as-alias svgo]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[cider.nrepl :refer [cider-nrepl-handler]]
@@ -202,11 +204,11 @@
:app.storage.tmp/cleaner
{::wrk/executor (ig/ref ::wrk/executor)}
- ::sto/gc-deleted-task
+ ::sto.gc-deleted/handler
{::db/pool (ig/ref ::db/pool)
::sto/storage (ig/ref ::sto/storage)}
- ::sto/gc-touched-task
+ ::sto.gc-touched/handler
{::db/pool (ig/ref ::db/pool)}
::http.client/client
@@ -314,7 +316,7 @@
::mtx/metrics (ig/ref ::mtx/metrics)
::mbus/msgbus (ig/ref ::mbus/msgbus)
::rds/redis (ig/ref ::rds/redis)
- ::csvg/optimizer (ig/ref ::csvg/optimizer)
+ ::svgo/optimizer (ig/ref ::svgo/optimizer)
::rpc/climit (ig/ref ::rpc/climit)
::rpc/rlimit (ig/ref ::rpc/rlimit)
@@ -337,12 +339,13 @@
::wrk/tasks
{:sendmail (ig/ref ::email/handler)
:objects-gc (ig/ref :app.tasks.objects-gc/handler)
+ :orphan-teams-gc (ig/ref :app.tasks.orphan-teams-gc/handler)
:file-gc (ig/ref :app.tasks.file-gc/handler)
:file-xlog-gc (ig/ref :app.tasks.file-xlog-gc/handler)
- :storage-gc-deleted (ig/ref ::sto/gc-deleted-task)
- :storage-gc-touched (ig/ref ::sto/gc-touched-task)
:tasks-gc (ig/ref :app.tasks.tasks-gc/handler)
:telemetry (ig/ref :app.tasks.telemetry/handler)
+ :storage-gc-deleted (ig/ref ::sto.gc-deleted/handler)
+ :storage-gc-touched (ig/ref ::sto.gc-touched/handler)
:session-gc (ig/ref ::session.tasks/gc)
:audit-log-archive (ig/ref ::audit.tasks/archive)
:audit-log-gc (ig/ref ::audit.tasks/gc)
@@ -373,6 +376,9 @@
{::db/pool (ig/ref ::db/pool)
::sto/storage (ig/ref ::sto/storage)}
+ :app.tasks.orphan-teams-gc/handler
+ {::db/pool (ig/ref ::db/pool)}
+
:app.tasks.file-gc/handler
{::db/pool (ig/ref ::db/pool)
::sto/storage (ig/ref ::sto/storage)}
@@ -403,8 +409,9 @@
;; module requires the migrations to run before initialize.
::migrations (ig/ref :app.migrations/migrations)}
- ::csvg/optimizer
- {}
+ ::svgo/optimizer
+ {::wrk/executor (ig/ref ::wrk/executor)
+ ::svgo/max-procs (cf/get :svgo-max-procs)}
::audit.tasks/archive
{::props (ig/ref ::setup/props)
@@ -458,6 +465,9 @@
{:cron #app/cron "0 0 0 * * ?" ;; daily
:task :objects-gc}
+ {:cron #app/cron "0 0 0 * * ?" ;; daily
+ :task :orphan-teams-gc}
+
{:cron #app/cron "0 0 0 * * ?" ;; daily
:task :storage-gc-deleted}
diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj
index d37c7fc32b..900ef75f53 100644
--- a/backend/src/app/migrations.clj
+++ b/backend/src/app/migrations.clj
@@ -337,7 +337,40 @@
:fn (mg/resource "app/migrations/sql/0106-mod-team-table.sql")}
{:name "0107-mod-file-tagged-object-thumbnail-table"
- :fn (mg/resource "app/migrations/sql/0107-mod-file-tagged-object-thumbnail-table.sql")}])
+ :fn (mg/resource "app/migrations/sql/0107-mod-file-tagged-object-thumbnail-table.sql")}
+
+ {:name "0107-add-deletion-protection-trigger-function"
+ :fn (mg/resource "app/migrations/sql/0107-add-deletion-protection-trigger-function.sql")}
+
+ {:name "0108-mod-file-thumbnail-table"
+ :fn (mg/resource "app/migrations/sql/0108-mod-file-thumbnail-table.sql")}
+
+ {:name "0109-mod-file-tagged-object-thumbnail-table"
+ :fn (mg/resource "app/migrations/sql/0109-mod-file-tagged-object-thumbnail-table.sql")}
+
+ {:name "0110-mod-file-media-object-table"
+ :fn (mg/resource "app/migrations/sql/0110-mod-file-media-object-table.sql")}
+
+ {:name "0111-mod-file-data-fragment-table"
+ :fn (mg/resource "app/migrations/sql/0111-mod-file-data-fragment-table.sql")}
+
+ {:name "0112-mod-profile-table"
+ :fn (mg/resource "app/migrations/sql/0112-mod-profile-table.sql")}
+
+ {:name "0113-mod-team-font-variant-table"
+ :fn (mg/resource "app/migrations/sql/0113-mod-team-font-variant-table.sql")}
+
+ {:name "0114-mod-team-table"
+ :fn (mg/resource "app/migrations/sql/0114-mod-team-table.sql")}
+
+ {:name "0115-mod-project-table"
+ :fn (mg/resource "app/migrations/sql/0115-mod-project-table.sql")}
+
+ {:name "0116-mod-file-table"
+ :fn (mg/resource "app/migrations/sql/0116-mod-file-table.sql")}
+
+ {:name "0117-mod-file-object-thumbnail-table"
+ :fn (mg/resource "app/migrations/sql/0117-mod-file-object-thumbnail-table.sql")}])
(defn apply-migrations!
[pool name migrations]
diff --git a/backend/src/app/migrations/sql/0107-add-deletion-protection-trigger-function.sql b/backend/src/app/migrations/sql/0107-add-deletion-protection-trigger-function.sql
new file mode 100644
index 0000000000..1ccf9b8b79
--- /dev/null
+++ b/backend/src/app/migrations/sql/0107-add-deletion-protection-trigger-function.sql
@@ -0,0 +1,8 @@
+CREATE OR REPLACE FUNCTION raise_deletion_protection()
+ RETURNS TRIGGER AS $$
+ BEGIN
+ RAISE EXCEPTION 'unable to proceed to delete row on "%"', TG_TABLE_NAME
+ USING HINT = 'disable deletion protection with "SET rules.deletion_protection TO off"';
+ RETURN NULL;
+ END;
+$$ LANGUAGE plpgsql;
diff --git a/backend/src/app/migrations/sql/0108-mod-file-thumbnail-table.sql b/backend/src/app/migrations/sql/0108-mod-file-thumbnail-table.sql
new file mode 100644
index 0000000000..b7d05bdc7f
--- /dev/null
+++ b/backend/src/app/migrations/sql/0108-mod-file-thumbnail-table.sql
@@ -0,0 +1,25 @@
+--- Add missing index for deleted_at column, we include all related
+--- columns because we expect the index to be small and expect use
+--- index-only scans.
+CREATE INDEX IF NOT EXISTS file_thumbnail__deleted_at__idx
+ ON file_thumbnail (deleted_at, file_id, revn, media_id)
+ WHERE deleted_at IS NOT NULL;
+
+--- Add missing for media_id column, used mainly for refs checking
+CREATE INDEX IF NOT EXISTS file_thumbnail__media_id__idx ON file_thumbnail (media_id);
+
+--- Remove CASCADE from media_id and file_id foreign constraint
+ALTER TABLE file_thumbnail
+ DROP CONSTRAINT file_thumbnail_file_id_fkey,
+ ADD FOREIGN KEY (file_id) REFERENCES file(id) DEFERRABLE;
+
+ALTER TABLE file_thumbnail
+ DROP CONSTRAINT file_thumbnail_media_id_fkey,
+ ADD FOREIGN KEY (media_id) REFERENCES storage_object(id) DEFERRABLE;
+
+--- Add deletion protection
+CREATE OR REPLACE TRIGGER deletion_protection__tgr
+BEFORE DELETE ON file_thumbnail FOR EACH STATEMENT
+ WHEN ((current_setting('rules.deletion_protection', true) IN ('on', '')) OR
+ (current_setting('rules.deletion_protection', true) IS NULL))
+ EXECUTE PROCEDURE raise_deletion_protection();
diff --git a/backend/src/app/migrations/sql/0109-mod-file-tagged-object-thumbnail-table.sql b/backend/src/app/migrations/sql/0109-mod-file-tagged-object-thumbnail-table.sql
new file mode 100644
index 0000000000..3184a6576f
--- /dev/null
+++ b/backend/src/app/migrations/sql/0109-mod-file-tagged-object-thumbnail-table.sql
@@ -0,0 +1,26 @@
+ALTER TABLE file_tagged_object_thumbnail
+ ADD COLUMN updated_at timestamptz NULL,
+ ADD COLUMN deleted_at timestamptz NULL;
+
+--- Add index for deleted_at column, we include all related columns
+--- because we expect the index to be small and expect use index-only
+--- scans.
+CREATE INDEX IF NOT EXISTS file_tagged_object_thumbnail__deleted_at__idx
+ ON file_tagged_object_thumbnail (deleted_at, file_id, object_id, media_id)
+ WHERE deleted_at IS NOT NULL;
+
+--- Remove CASCADE from media_id and file_id foreign constraint
+ALTER TABLE file_tagged_object_thumbnail
+ DROP CONSTRAINT file_tagged_object_thumbnail_media_id_fkey,
+ ADD FOREIGN KEY (media_id) REFERENCES storage_object(id) DEFERRABLE;
+
+ALTER TABLE file_tagged_object_thumbnail
+ DROP CONSTRAINT file_tagged_object_thumbnail_file_id_fkey,
+ ADD FOREIGN KEY (file_id) REFERENCES file(id) DEFERRABLE;
+
+--- Add deletion protection
+CREATE OR REPLACE TRIGGER deletion_protection__tgr
+BEFORE DELETE ON file_tagged_object_thumbnail FOR EACH STATEMENT
+ WHEN ((current_setting('rules.deletion_protection', true) IN ('on', '')) OR
+ (current_setting('rules.deletion_protection', true) IS NULL))
+ EXECUTE PROCEDURE raise_deletion_protection();
diff --git a/backend/src/app/migrations/sql/0110-mod-file-media-object-table.sql b/backend/src/app/migrations/sql/0110-mod-file-media-object-table.sql
new file mode 100644
index 0000000000..49cbebc96c
--- /dev/null
+++ b/backend/src/app/migrations/sql/0110-mod-file-media-object-table.sql
@@ -0,0 +1,27 @@
+--- Fix legacy naming
+ALTER INDEX media_object_pkey RENAME TO file_media_object_pkey;
+ALTER INDEX media_object__file_id__idx RENAME TO file_media_object__file_id__idx;
+
+--- Create index for the deleted_at column
+CREATE INDEX IF NOT EXISTS file_media_object__deleted_at__idx
+ ON file_media_object (deleted_at, id, media_id)
+ WHERE deleted_at IS NOT NULL;
+
+--- Drop now unnecesary trigger because this will be handled by the
+--- application code
+DROP TRIGGER file_media_object__on_delete__tgr ON file_media_object;
+DROP FUNCTION on_delete_file_media_object ( ) CASCADE;
+DROP TRIGGER file_media_object__on_insert__tgr ON file_media_object;
+DROP FUNCTION on_media_object_insert () CASCADE;
+
+--- Remove CASCADE from file FOREIGN KEY
+ALTER TABLE file_media_object
+ DROP CONSTRAINT file_media_object_file_id_fkey,
+ ADD FOREIGN KEY (file_id) REFERENCES file(id) DEFERRABLE;
+
+--- Add deletion protection
+CREATE OR REPLACE TRIGGER deletion_protection__tgr
+BEFORE DELETE ON file_media_object FOR EACH STATEMENT
+ WHEN ((current_setting('rules.deletion_protection', true) IN ('on', '')) OR
+ (current_setting('rules.deletion_protection', true) IS NULL))
+ EXECUTE PROCEDURE raise_deletion_protection();
diff --git a/backend/src/app/migrations/sql/0111-mod-file-data-fragment-table.sql b/backend/src/app/migrations/sql/0111-mod-file-data-fragment-table.sql
new file mode 100644
index 0000000000..8397124c3f
--- /dev/null
+++ b/backend/src/app/migrations/sql/0111-mod-file-data-fragment-table.sql
@@ -0,0 +1,9 @@
+ALTER TABLE file_data_fragment
+ ADD COLUMN deleted_at timestamptz NULL;
+
+--- Add index for deleted_at column, we include all related columns
+--- because we expect the index to be small and expect use index-only
+--- scans.
+CREATE INDEX IF NOT EXISTS file_data_fragment__deleted_at__idx
+ ON file_data_fragment (deleted_at, file_id, id)
+ WHERE deleted_at IS NOT NULL;
diff --git a/backend/src/app/migrations/sql/0112-mod-profile-table.sql b/backend/src/app/migrations/sql/0112-mod-profile-table.sql
new file mode 100644
index 0000000000..2db8d75b0a
--- /dev/null
+++ b/backend/src/app/migrations/sql/0112-mod-profile-table.sql
@@ -0,0 +1,15 @@
+ALTER TABLE profile
+ DROP CONSTRAINT profile_photo_id_fkey,
+ ADD FOREIGN KEY (photo_id) REFERENCES storage_object(id) DEFERRABLE,
+ DROP CONSTRAINT profile_default_project_id_fkey,
+ ADD FOREIGN KEY (default_project_id) REFERENCES project(id) DEFERRABLE,
+ DROP CONSTRAINT profile_default_team_id_fkey,
+ ADD FOREIGN KEY (default_team_id) REFERENCES team(id) DEFERRABLE;
+
+--- Add deletion protection
+CREATE OR REPLACE TRIGGER deletion_protection__tgr
+BEFORE DELETE ON profile FOR EACH STATEMENT
+ WHEN ((current_setting('rules.deletion_protection', true) IN ('on', '')) OR
+ (current_setting('rules.deletion_protection', true) IS NULL))
+ EXECUTE PROCEDURE raise_deletion_protection();
+
diff --git a/backend/src/app/migrations/sql/0113-mod-team-font-variant-table.sql b/backend/src/app/migrations/sql/0113-mod-team-font-variant-table.sql
new file mode 100644
index 0000000000..b9caa08f6e
--- /dev/null
+++ b/backend/src/app/migrations/sql/0113-mod-team-font-variant-table.sql
@@ -0,0 +1,20 @@
+--- Remove ON DELETE SET NULL from foreign constraint on
+--- storage_object table
+ALTER TABLE team_font_variant
+ DROP CONSTRAINT team_font_variant_otf_file_id_fkey,
+ ADD FOREIGN KEY (otf_file_id) REFERENCES storage_object(id) DEFERRABLE,
+ DROP CONSTRAINT team_font_variant_ttf_file_id_fkey,
+ ADD FOREIGN KEY (ttf_file_id) REFERENCES storage_object(id) DEFERRABLE,
+ DROP CONSTRAINT team_font_variant_woff1_file_id_fkey,
+ ADD FOREIGN KEY (woff1_file_id) REFERENCES storage_object(id) DEFERRABLE,
+ DROP CONSTRAINT team_font_variant_woff2_file_id_fkey,
+ ADD FOREIGN KEY (woff2_file_id) REFERENCES storage_object(id) DEFERRABLE,
+ DROP CONSTRAINT team_font_variant_team_id_fkey,
+ ADD FOREIGN KEY (team_id) REFERENCES team(id) DEFERRABLE;
+
+--- Add deletion protection
+CREATE OR REPLACE TRIGGER deletion_protection__tgr
+BEFORE DELETE ON team_font_variant FOR EACH STATEMENT
+ WHEN ((current_setting('rules.deletion_protection', true) IN ('on', '')) OR
+ (current_setting('rules.deletion_protection', true) IS NULL))
+ EXECUTE PROCEDURE raise_deletion_protection();
diff --git a/backend/src/app/migrations/sql/0114-mod-team-table.sql b/backend/src/app/migrations/sql/0114-mod-team-table.sql
new file mode 100644
index 0000000000..8c76756437
--- /dev/null
+++ b/backend/src/app/migrations/sql/0114-mod-team-table.sql
@@ -0,0 +1,10 @@
+--- Add deletion protection
+CREATE OR REPLACE TRIGGER deletion_protection__tgr
+BEFORE DELETE ON team FOR EACH STATEMENT
+ WHEN ((current_setting('rules.deletion_protection', true) IN ('on', '')) OR
+ (current_setting('rules.deletion_protection', true) IS NULL))
+ EXECUTE PROCEDURE raise_deletion_protection();
+
+ALTER TABLE team
+ DROP CONSTRAINT team_photo_id_fkey,
+ ADD FOREIGN KEY (photo_id) REFERENCES storage_object(id) DEFERRABLE;
diff --git a/backend/src/app/migrations/sql/0115-mod-project-table.sql b/backend/src/app/migrations/sql/0115-mod-project-table.sql
new file mode 100644
index 0000000000..f37470dce8
--- /dev/null
+++ b/backend/src/app/migrations/sql/0115-mod-project-table.sql
@@ -0,0 +1,3 @@
+ALTER TABLE project
+ DROP CONSTRAINT project_team_id_fkey,
+ ADD FOREIGN KEY (team_id) REFERENCES team(id) DEFERRABLE;
diff --git a/backend/src/app/migrations/sql/0116-mod-file-table.sql b/backend/src/app/migrations/sql/0116-mod-file-table.sql
new file mode 100644
index 0000000000..1d3bce11a2
--- /dev/null
+++ b/backend/src/app/migrations/sql/0116-mod-file-table.sql
@@ -0,0 +1,3 @@
+ALTER TABLE file
+ DROP CONSTRAINT file_project_id_fkey,
+ ADD FOREIGN KEY (project_id) REFERENCES project(id) DEFERRABLE;
diff --git a/backend/src/app/migrations/sql/0117-mod-file-object-thumbnail-table.sql b/backend/src/app/migrations/sql/0117-mod-file-object-thumbnail-table.sql
new file mode 100644
index 0000000000..e3f6cb6d4b
--- /dev/null
+++ b/backend/src/app/migrations/sql/0117-mod-file-object-thumbnail-table.sql
@@ -0,0 +1,12 @@
+ALTER TABLE file_object_thumbnail
+ DROP CONSTRAINT file_object_thumbnail_file_id_fkey,
+ ADD FOREIGN KEY (file_id) REFERENCES file(id) DEFERRABLE,
+ DROP CONSTRAINT file_object_thumbnail_media_id_fkey,
+ ADD FOREIGN KEY (media_id) REFERENCES storage_object(id) DEFERRABLE;
+
+--- Mark all related storage_object row as touched
+-- UPDATE storage_object SET touched_at = now()
+-- WHERE id IN (SELECT DISTINCT media_id
+-- FROM file_object_thumbnail
+-- WHERE media_id IS NOT NULL)
+-- AND touched_at IS NULL;
diff --git a/backend/src/app/rpc/commands/audit.clj b/backend/src/app/rpc/commands/audit.clj
index fa56087219..76bd6e1880 100644
--- a/backend/src/app/rpc/commands/audit.clj
+++ b/backend/src/app/rpc/commands/audit.clj
@@ -48,7 +48,7 @@
(map event->row))
events (sequence xform events)]
(when (seq events)
- (db/insert-multi! pool :audit-log event-columns events))))
+ (db/insert-many! pool :audit-log event-columns events))))
(def schema:event
[:map {:title "Event"}
diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj
index 13d05bf0f3..949d528acf 100644
--- a/backend/src/app/rpc/commands/auth.clj
+++ b/backend/src/app/rpc/commands/auth.clj
@@ -54,7 +54,9 @@
:hint "the current account does not have password")
(let [result (profile/verify-password cfg password (:password profile))]
(when (:update result)
- (l/trace :hint "updating profile password" :id (:id profile) :email (:email profile))
+ (l/trc :hint "updating profile password"
+ :id (str (:id profile))
+ :email (:email profile))
(profile/update-profile-password! conn (assoc profile :password password)))
(:valid result))))
@@ -131,7 +133,8 @@
(update-password [conn profile-id]
(let [pwd (profile/derive-password cfg password)]
- (db/update! conn :profile {:password pwd} {:id profile-id})))]
+ (db/update! conn :profile {:password pwd} {:id profile-id})
+ nil))]
(db/with-atomic [conn pool]
(->> (validate-token token)
@@ -301,7 +304,8 @@
(-> (db/update! conn :profile
{:default-team-id (:id team)
:default-project-id (:default-project-id team)}
- {:id id})
+ {:id id}
+ {::db/return-keys true})
(profile/decode-row))))
diff --git a/backend/src/app/rpc/commands/binfile.clj b/backend/src/app/rpc/commands/binfile.clj
index 7e7327b32e..c173ec3bb6 100644
--- a/backend/src/app/rpc/commands/binfile.clj
+++ b/backend/src/app/rpc/commands/binfile.clj
@@ -317,7 +317,7 @@
[cfg file-id]
(db/run! cfg (fn [{:keys [::db/conn] :as cfg}]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg file-id)]
- (some-> (db/get* conn :file {:id file-id} {::db/remove-deleted? false})
+ (some-> (db/get* conn :file {:id file-id} {::db/remove-deleted false})
(files/decode-row)
(update :data feat.fdata/process-pointers deref))))))
@@ -593,6 +593,7 @@
(declare lookup-index)
(declare update-index)
(declare relink-media)
+(declare relink-colors)
(declare relink-shapes)
(defmulti read-import ::version)
@@ -663,6 +664,7 @@
(case feature
"components/v2"
(feat.compv2/migrate-file! options file-id
+ :max-procs 2
:validate? validate?
:throw-on-validate? true)
@@ -723,6 +725,7 @@
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)
+ (update :colors relink-colors)
(d/without-nils))))))
@@ -997,6 +1000,17 @@
media
media))
+(defn- relink-colors
+ "A function responsible of process the :colors attr of file data and
+ remap the old ids with the new ones."
+ [colors]
+ (reduce-kv (fn [res k v]
+ (if (:image v)
+ (update-in res [k :image :id] lookup-index)
+ res))
+ colors
+ colors))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HIGH LEVEL API
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/backend/src/app/rpc/commands/comments.clj b/backend/src/app/rpc/commands/comments.clj
index 5e87884f6d..9e1a9d4365 100644
--- a/backend/src/app/rpc/commands/comments.clj
+++ b/backend/src/app/rpc/commands/comments.clj
@@ -12,6 +12,7 @@
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.db :as db]
+ [app.db.sql :as sql]
[app.features.fdata :as feat.fdata]
[app.loggers.audit :as-alias audit]
[app.loggers.webhooks :as-alias webhooks]
@@ -62,8 +63,8 @@
(decode-row)))
(defn- get-comment
- [conn comment-id & {:keys [for-update?]}]
- (db/get-by-id conn :comment comment-id {:for-update for-update?}))
+ [conn comment-id & {:as opts}]
+ (db/get-by-id conn :comment comment-id opts))
(defn- get-next-seqn
[conn file-id]
@@ -309,23 +310,21 @@
::quotes/project-id project-id
::quotes/file-id file-id}))
- (rtry/with-retry {::rtry/when rtry/conflict-exception?
- ::rtry/max-retries 3
- ::rtry/label "create-comment-thread"
- ::db/conn conn}
- (create-comment-thread conn
- {:created-at request-at
- :profile-id profile-id
- :file-id file-id
- :page-id page-id
- :page-name page-name
- :position position
- :content content
- :frame-id frame-id}))))))
+ (-> cfg
+ (assoc ::rtry/when rtry/conflict-exception?)
+ (assoc ::rtry/label "create-comment-thread")
+ (rtry/invoke create-comment-thread {:created-at request-at
+ :profile-id profile-id
+ :file-id file-id
+ :page-id page-id
+ :page-name page-name
+ :position position
+ :content content
+ :frame-id frame-id}))))))
(defn- create-comment-thread
- [conn {:keys [profile-id file-id page-id page-name created-at position content frame-id]}]
+ [{:keys [::db/conn]} {:keys [profile-id file-id page-id page-name created-at position content frame-id]}]
(let [;; NOTE: we take the next seq number from a separate query because the whole
;; operation can be retried on conflict, and in this case the new seq shold be
;; retrieved from the database.
@@ -377,7 +376,7 @@
{::doc/added "1.15"}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id share-id] :as params}]
(db/with-atomic [conn pool]
- (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::db/for-update? true)]
+ (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
(files/check-comment-permissions! conn profile-id file-id share-id)
(upsert-comment-thread-status! conn profile-id id))))
@@ -394,7 +393,7 @@
{::doc/added "1.15"}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id is-resolved share-id] :as params}]
(db/with-atomic [conn pool]
- (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::db/for-update? true)]
+ (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
(files/check-comment-permissions! conn profile-id file-id share-id)
(db/update! conn :comment-thread
{:is-resolved is-resolved}
@@ -417,7 +416,7 @@
[cfg {:keys [::rpc/profile-id ::rpc/request-at thread-id share-id content]}]
(db/tx-run! cfg
(fn [{:keys [::db/conn] :as cfg}]
- (let [{:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::db/for-update? true)
+ (let [{:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true)
{:keys [team-id project-id page-name] :as file} (get-file cfg file-id page-id)]
(files/check-comment-permissions! conn profile-id (:id file) share-id)
@@ -473,8 +472,8 @@
(db/tx-run! cfg
(fn [{:keys [::db/conn] :as cfg}]
- (let [{:keys [thread-id owner-id] :as comment} (get-comment conn id ::db/for-update? true)
- {:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::db/for-update? true)]
+ (let [{:keys [thread-id owner-id] :as comment} (get-comment conn id ::sql/for-update true)
+ {:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true)]
(files/check-comment-permissions! conn profile-id file-id share-id)
@@ -506,7 +505,7 @@
{::doc/added "1.15"}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id share-id]}]
(db/with-atomic [conn pool]
- (let [{:keys [owner-id file-id] :as thread} (get-comment-thread conn id ::db/for-update? true)]
+ (let [{:keys [owner-id file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
(files/check-comment-permissions! conn profile-id file-id share-id)
(when-not (= owner-id profile-id)
(ex/raise :type :validation
@@ -526,14 +525,14 @@
{::doc/added "1.15"}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id share-id] :as params}]
(db/with-atomic [conn pool]
- (let [{:keys [owner-id thread-id] :as comment} (get-comment conn id ::db/for-update? true)
+ (let [{:keys [owner-id thread-id] :as comment} (get-comment conn id ::sql/for-update true)
{:keys [file-id] :as thread} (get-comment-thread conn thread-id)]
(files/check-comment-permissions! conn profile-id file-id share-id)
(when-not (= owner-id profile-id)
(ex/raise :type :validation
:code :not-allowed))
- (db/delete! conn :comment {:id id}))))
-
+ (db/delete! conn :comment {:id id})
+ nil)))
;; --- COMMAND: Update comment thread position
@@ -546,7 +545,7 @@
{::doc/added "1.15"}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id ::rpc/request-at id position frame-id share-id]}]
(db/with-atomic [conn pool]
- (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::db/for-update? true)]
+ (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
(files/check-comment-permissions! conn profile-id file-id share-id)
(db/update! conn :comment-thread
{:modified-at request-at
@@ -566,7 +565,7 @@
{::doc/added "1.15"}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id ::rpc/request-at id frame-id share-id]}]
(db/with-atomic [conn pool]
- (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::db/for-update? true)]
+ (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
(files/check-comment-permissions! conn profile-id file-id share-id)
(db/update! conn :comment-thread
{:modified-at request-at
diff --git a/backend/src/app/rpc/commands/files.clj b/backend/src/app/rpc/commands/files.clj
index 096e961957..58b10742d7 100644
--- a/backend/src/app/rpc/commands/files.clj
+++ b/backend/src/app/rpc/commands/files.clj
@@ -20,6 +20,7 @@
[app.common.types.file :as ctf]
[app.config :as cf]
[app.db :as db]
+ [app.db.sql :as-alias sql]
[app.features.fdata :as feat.fdata]
[app.loggers.audit :as-alias audit]
[app.loggers.webhooks :as-alias webhooks]
@@ -238,8 +239,7 @@
(db/update! conn :file
{:data (blob/encode (:data file))
:features (db/create-array conn "text" (:features file))}
- {:id id}
- {::db/return-keys? false})
+ {:id id})
(when (contains? (:features file) "fdata/pointer-map")
(feat.fdata/persist-pointers! cfg id)))
@@ -262,9 +262,9 @@
(when (some? project-id)
{:project-id project-id}))
file (-> (db/get conn :file params
- {::db/check-deleted? (not include-deleted?)
- ::db/remove-deleted? (not include-deleted?)
- ::db/for-update? lock-for-update?})
+ {::db/check-deleted (not include-deleted?)
+ ::db/remove-deleted (not include-deleted?)
+ ::sql/for-update lock-for-update?})
(decode-row))]
(if migrate?
(migrate-file cfg file)
@@ -516,7 +516,7 @@
ft.media_id
from file as f
inner join project as p on (p.id = f.project_id)
- left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn)
+ left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn and ft.deleted_at is null)
where f.is_shared = true
and f.deleted_at is null
and p.deleted_at is null
@@ -733,7 +733,8 @@
(db/update! conn :file
{:name name
:modified-at (dt/now)}
- {:id id}))
+ {:id id}
+ {::db/return-keys true}))
(sv/defmethod ::rename-file
{::doc/added "1.17"
@@ -860,9 +861,7 @@
(let [file (assoc file :is-shared true)]
(db/update! conn :file
{:is-shared true}
- {:id id}
- ::db/return-keys? false)
-
+ {:id id})
file)
:else
@@ -899,7 +898,7 @@
(db/update! conn :file
{:deleted-at (dt/now)}
{:id file-id}
- {::db/columns [:id :name :is-shared :project-id :created-at :modified-at]}))
+ {::db/return-keys [:id :name :is-shared :project-id :created-at :modified-at]}))
(def ^:private
schema:delete-file
@@ -998,8 +997,8 @@
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(db/with-atomic [conn pool]
(check-edition-permissions! conn profile-id file-id)
- (unlink-file-from-library conn params)))
-
+ (unlink-file-from-library conn params)
+ nil))
;; --- MUTATION COMMAND: update-sync
@@ -1008,7 +1007,8 @@
(db/update! conn :file-library-rel
{:synced-at (dt/now)}
{:file-id file-id
- :library-file-id library-id}))
+ :library-file-id library-id}
+ {::db/return-keys true}))
(def ^:private schema:update-file-library-sync-status
[:map {:title "update-file-library-sync-status"}
@@ -1031,7 +1031,8 @@
[conn {:keys [file-id date] :as params}]
(db/update! conn :file
{:ignore-sync-until date}
- {:id file-id}))
+ {:id file-id}
+ {::db/return-keys true}))
(s/def ::ignore-file-library-sync-status
(s/keys :req [::rpc/profile-id]
diff --git a/backend/src/app/rpc/commands/files_thumbnails.clj b/backend/src/app/rpc/commands/files_thumbnails.clj
index 19f36072f4..712c212047 100644
--- a/backend/src/app/rpc/commands/files_thumbnails.clj
+++ b/backend/src/app/rpc/commands/files_thumbnails.clj
@@ -17,6 +17,7 @@
[app.common.types.shape-tree :as ctt]
[app.config :as cf]
[app.db :as db]
+ [app.db.sql :as-alias sql]
[app.features.fdata :as feat.fdata]
[app.loggers.audit :as-alias audit]
[app.loggers.webhooks :as-alias webhooks]
@@ -27,6 +28,7 @@
[app.rpc.commands.teams :as teams]
[app.rpc.cond :as-alias cond]
[app.rpc.doc :as-alias doc]
+ [app.rpc.retry :as rtry]
[app.storage :as sto]
[app.util.pointer-map :as pmap]
[app.util.services :as sv]
@@ -46,7 +48,7 @@
(let [sql (str/concat
"select object_id, media_id, tag "
" from file_tagged_object_thumbnail"
- " where file_id=? and tag=?")
+ " where file_id=? and tag=? and deleted_at is null")
res (db/exec! conn [sql file-id tag])]
(->> res
(d/index-by :object-id (fn [row]
@@ -58,7 +60,7 @@
(let [sql (str/concat
"select object_id, media_id, tag "
" from file_tagged_object_thumbnail"
- " where file_id=?")
+ " where file_id=? and deleted_at is null")
res (db/exec! conn [sql file-id])]
(->> res
(d/index-by :object-id (fn [row]
@@ -69,7 +71,7 @@
(let [sql (str/concat
"select object_id, media_id, tag "
" from file_tagged_object_thumbnail"
- " where file_id=? and object_id = ANY(?)")
+ " where file_id=? and object_id = ANY(?) and deleted_at is null")
ids (db/create-array conn "text" (seq object-ids))
res (db/exec! conn [sql file-id ids])]
@@ -226,34 +228,54 @@
;; MUTATION COMMANDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; --- MUTATION COMMAND: create-file-object-thumbnail
-
-(def ^:private sql:create-object-thumbnail
- "insert into file_tagged_object_thumbnail(file_id, object_id, media_id, tag)
- values (?, ?, ?, ?)
- on conflict(file_id, tag, object_id) do
- update set media_id = ?
- returning *;")
+;; MUTATION COMMAND: create-file-object-thumbnail
(defn- create-file-object-thumbnail!
[{:keys [::db/conn ::sto/storage]} file-id object-id media tag]
- (let [path (:path media)
+ (let [thumb (db/get* conn :file-tagged-object-thumbnail
+ {:file-id file-id
+ :object-id object-id
+ :tag tag}
+ {::db/remove-deleted false
+ ::sql/for-update true})
+
+ path (:path media)
mtype (:mtype media)
hash (sto/calculate-hash path)
data (-> (sto/content path)
(sto/wrap-with-hash hash))
+ tnow (dt/now)
+
media (sto/put-object! storage
{::sto/content data
::sto/deduplicate? true
- ::sto/touched-at (dt/now)
+ ::sto/touched-at tnow
:content-type mtype
:bucket "file-object-thumbnail"})]
- (db/exec-one! conn [sql:create-object-thumbnail file-id object-id
- (:id media) tag (:id media)])))
+ (if (some? thumb)
+ (do
+ ;; We mark the old media id as touched if it does not matches
+ (when (not= (:id media) (:media-id thumb))
+ (sto/touch-object! storage (:media-id thumb)))
+ (db/update! conn :file-tagged-object-thumbnail
+ {:media-id (:id media)
+ :deleted-at nil
+ :updated-at tnow}
+ {:file-id file-id
+ :object-id object-id
+ :tag tag}))
+ (db/insert! conn :file-tagged-object-thumbnail
+ {:file-id file-id
+ :object-id object-id
+ :created-at tnow
+ :updated-at tnow
+ :tag tag
+ :media-id (:id media)}))))
-(def schema:create-file-object-thumbnail
+(def ^:private
+ schema:create-file-object-thumbnail
[:map {:title "create-file-object-thumbnail"}
[:file-id ::sm/uuid]
[:object-id :string]
@@ -268,32 +290,36 @@
::audit/skip true
::sm/params schema:create-file-object-thumbnail}
- [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id object-id media tag]}]
- (db/with-atomic [conn pool]
- (files/check-edition-permissions! conn profile-id file-id)
- (media/validate-media-type! media)
- (media/validate-media-size! media)
+ [cfg {:keys [::rpc/profile-id file-id object-id media tag]}]
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn] :as cfg}]
+ (files/check-edition-permissions! conn profile-id file-id)
+ (media/validate-media-type! media)
+ (media/validate-media-size! media)
- (when-not (db/read-only? conn)
- (-> cfg
- (update ::sto/storage media/configure-assets-storage)
- (assoc ::db/conn conn)
- (create-file-object-thumbnail! file-id object-id media (or tag "frame"))))))
+ (when-not (db/read-only? conn)
+ (let [cfg (-> cfg
+ (update ::sto/storage media/configure-assets-storage)
+ (assoc ::rtry/when rtry/conflict-exception?)
+ (assoc ::rtry/max-retries 5)
+ (assoc ::rtry/label "create-file-object-thumbnail"))]
+ (rtry/invoke cfg create-file-object-thumbnail!
+ file-id object-id media (or tag "frame")))))))
;; --- MUTATION COMMAND: delete-file-object-thumbnail
(defn- delete-file-object-thumbnail!
[{:keys [::db/conn ::sto/storage]} file-id object-id]
- (when-let [{:keys [media-id]} (db/get* conn :file-tagged-object-thumbnail
- {:file-id file-id
- :object-id object-id}
- {::db/for-update? true})]
-
+ (when-let [{:keys [media-id tag]} (db/get* conn :file-tagged-object-thumbnail
+ {:file-id file-id
+ :object-id object-id}
+ {::sql/for-update true})]
(sto/touch-object! storage media-id)
- (db/delete! conn :file-tagged-object-thumbnail
+ (db/update! conn :file-tagged-object-thumbnail
+ {:deleted-at (dt/now)}
{:file-id file-id
- :object-id object-id})
- nil))
+ :object-id object-id
+ :tag tag})))
(s/def ::delete-file-object-thumbnail
(s/keys :req [::rpc/profile-id]
@@ -302,29 +328,21 @@
(sv/defmethod ::delete-file-object-thumbnail
{::doc/added "1.19"
::doc/module :files
+ ::doc/deprecated "1.20"
::climit/id :file-thumbnail-ops
::climit/key-fn ::rpc/profile-id
::audit/skip true}
- [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id object-id]}]
-
- (db/with-atomic [conn pool]
- (files/check-edition-permissions! conn profile-id file-id)
-
- (when-not (db/read-only? conn)
- (-> cfg
- (update ::sto/storage media/configure-assets-storage)
- (assoc ::db/conn conn)
- (delete-file-object-thumbnail! file-id object-id))
- nil)))
+ [cfg {:keys [::rpc/profile-id file-id object-id]}]
+ (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
+ (files/check-edition-permissions! conn profile-id file-id)
+ (when-not (db/read-only? conn)
+ (-> cfg
+ (update ::sto/storage media/configure-assets-storage conn)
+ (delete-file-object-thumbnail! file-id object-id))
+ nil))))
;; --- MUTATION COMMAND: create-file-thumbnail
-(def ^:private sql:create-file-thumbnail
- "insert into file_thumbnail (file_id, revn, media_id, props)
- values (?, ?, ?, ?::jsonb)
- on conflict(file_id, revn) do
- update set media_id=?, props=?, updated_at=now();")
-
(defn- create-file-thumbnail!
[{:keys [::db/conn ::sto/storage]} {:keys [file-id revn props media] :as params}]
(media/validate-media-type! media)
@@ -336,14 +354,42 @@
hash (sto/calculate-hash path)
data (-> (sto/content path)
(sto/wrap-with-hash hash))
+ tnow (dt/now)
media (sto/put-object! storage
{::sto/content data
- ::sto/deduplicate? false
+ ::sto/deduplicate? true
+ ::sto/touched-at tnow
:content-type mtype
- :bucket "file-thumbnail"})]
- (db/exec-one! conn [sql:create-file-thumbnail file-id revn
- (:id media) props
- (:id media) props])
+ :bucket "file-thumbnail"})
+
+ thumb (db/get* conn :file-thumbnail
+ {:file-id file-id
+ :revn revn}
+ {::db/remove-deleted false
+ ::sql/for-update true})]
+
+ (if (some? thumb)
+ (do
+ ;; We mark the old media id as touched if it does not match
+ (when (not= (:id media) (:media-id thumb))
+ (sto/touch-object! storage (:media-id thumb)))
+
+ (db/update! conn :file-thumbnail
+ {:media-id (:id media)
+ :deleted-at nil
+ :updated-at tnow
+ :props props}
+ {:file-id file-id
+ :revn revn}))
+
+ (db/insert! conn :file-thumbnail
+ {:file-id file-id
+ :revn revn
+ :created-at tnow
+ :updated-at tnow
+ :props props
+ :media-id (:id media)}))
+
media))
(sv/defmethod ::create-file-thumbnail
@@ -359,13 +405,14 @@
[:revn :int]
[:media ::media/upload]]}
- [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
- (db/with-atomic [conn pool]
- (files/check-edition-permissions! conn profile-id file-id)
- (when-not (db/read-only? conn)
- (let [media (-> cfg
- (update ::sto/storage media/configure-assets-storage)
- (assoc ::db/conn conn)
- (create-file-thumbnail! params))]
-
- {:uri (files/resolve-public-uri (:id media))}))))
+ [cfg {:keys [::rpc/profile-id file-id] :as params}]
+ (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
+ (files/check-edition-permissions! conn profile-id file-id)
+ (when-not (db/read-only? conn)
+ (let [cfg (-> cfg
+ (update ::sto/storage media/configure-assets-storage)
+ (assoc ::rtry/when rtry/conflict-exception?)
+ (assoc ::rtry/max-retries 5)
+ (assoc ::rtry/label "create-thumbnail"))
+ media (rtry/invoke cfg create-file-thumbnail! params)]
+ {:uri (files/resolve-public-uri (:id media))})))))
diff --git a/backend/src/app/rpc/commands/files_update.clj b/backend/src/app/rpc/commands/files_update.clj
index 7a27a834e8..03e1b04da4 100644
--- a/backend/src/app/rpc/commands/files_update.clj
+++ b/backend/src/app/rpc/commands/files_update.clj
@@ -250,7 +250,8 @@
:features (db/create-array conn "text" (:features file))
:data (when (take-snapshot? file)
(:data file))
- :changes (blob/encode changes)})
+ :changes (blob/encode changes)}
+ {::db/return-keys false})
(db/update! conn :file
{:revn (:revn file)
@@ -305,7 +306,7 @@
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)
pmap/*tracked* nil]
(-> (files/get-file cfg id :migrate? false)
- (feat.fdata/process-pointers deref) ; ensure all pointers resolved
+ (update :data feat.fdata/process-pointers deref) ; ensure all pointers resolved
(fmg/migrate-file))))))
(d/index-by :id)))
diff --git a/backend/src/app/rpc/commands/fonts.clj b/backend/src/app/rpc/commands/fonts.clj
index 4fc55a77f9..c19b8a2854 100644
--- a/backend/src/app/rpc/commands/fonts.clj
+++ b/backend/src/app/rpc/commands/fonts.clj
@@ -8,9 +8,10 @@
(:require
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
- [app.common.spec :as us]
+ [app.common.schema :as sm]
[app.common.uuid :as uuid]
[app.db :as db]
+ [app.db.sql :as-alias sql]
[app.loggers.audit :as-alias audit]
[app.loggers.webhooks :as-alias webhooks]
[app.media :as media]
@@ -25,39 +26,27 @@
[app.storage :as sto]
[app.util.services :as sv]
[app.util.time :as dt]
- [app.worker :as-alias wrk]
- [clojure.spec.alpha :as s]))
+ [app.worker :as-alias wrk]))
(def valid-weight #{100 200 300 400 500 600 700 800 900 950})
(def valid-style #{"normal" "italic"})
-(s/def ::data (s/map-of ::us/string any?))
-(s/def ::file-id ::us/uuid)
-(s/def ::font-id ::us/uuid)
-(s/def ::id ::us/uuid)
-(s/def ::name ::us/not-empty-string)
-(s/def ::project-id ::us/uuid)
-(s/def ::share-id ::us/uuid)
-(s/def ::style valid-style)
-(s/def ::team-id ::us/uuid)
-(s/def ::weight valid-weight)
-
;; --- QUERY: Get font variants
-(s/def ::get-font-variants
- (s/and
- (s/keys :req [::rpc/profile-id]
- :opt-un [::team-id
- ::file-id
- ::project-id
- ::share-id])
- (fn [o]
- (or (contains? o :team-id)
- (contains? o :file-id)
- (contains? o :project-id)))))
+(def ^:private
+ schema:get-font-variants
+ [:schema {:title "get-font-variants"}
+ [:and
+ [:map
+ [:team-id {:optional true} ::sm/uuid]
+ [:file-id {:optional true} ::sm/uuid]
+ [:project-id {:optional true} ::sm/uuid]
+ [:share-id {:optional true} ::sm/uuid]]
+ [::sm/contains-any #{:team-id :file-id :project-id}]]])
(sv/defmethod ::get-font-variants
- {::doc/added "1.18"}
+ {::doc/added "1.18"
+ ::sm/params schema:get-font-variants}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id file-id project-id share-id] :as params}]
(dm/with-open [conn (db/open pool)]
(cond
@@ -87,28 +76,31 @@
(declare create-font-variant)
-(s/def ::create-font-variant
- (s/keys :req [::rpc/profile-id]
- :req-un [::team-id
- ::data
- ::font-id
- ::font-family
- ::font-weight
- ::font-style]))
+(def ^:private schema:create-font-variant
+ [:map {:title "create-font-variant"}
+ [:team-id ::sm/uuid]
+ [:data [:map-of :string :any]]
+ [:font-id ::sm/uuid]
+ [:font-family :string]
+ [:font-weight [::sm/one-of {:format "number"} valid-weight]]
+ [:font-style [::sm/one-of {:format "string"} valid-style]]])
(sv/defmethod ::create-font-variant
{::doc/added "1.18"
- ::webhooks/event? true}
- [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id] :as params}]
- (let [cfg (update cfg ::sto/storage media/configure-assets-storage)]
- (teams/check-edition-permissions! pool profile-id team-id)
- (quotes/check-quote! pool {::quotes/id ::quotes/font-variants-per-team
- ::quotes/profile-id profile-id
- ::quotes/team-id team-id})
- (create-font-variant cfg (assoc params :profile-id profile-id))))
+ ::webhooks/event? true
+ ::sm/params schema:create-font-variant}
+ [cfg {:keys [::rpc/profile-id team-id] :as params}]
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn] :as cfg}]
+ (let [cfg (update cfg ::sto/storage media/configure-assets-storage)]
+ (teams/check-edition-permissions! conn profile-id team-id)
+ (quotes/check-quote! conn {::quotes/id ::quotes/font-variants-per-team
+ ::quotes/profile-id profile-id
+ ::quotes/team-id team-id})
+ (create-font-variant cfg (assoc params :profile-id profile-id))))))
(defn create-font-variant
- [{:keys [::sto/storage ::db/pool] :as cfg} {:keys [data] :as params}]
+ [{:keys [::sto/storage ::db/conn] :as cfg} {:keys [data] :as params}]
(letfn [(generate-missing! [data]
(let [data (media/run {:cmd :generate-fonts :input data})]
(when (and (not (contains? data "font/otf"))
@@ -136,6 +128,7 @@
ttf-params (prepare-font data "font/ttf")
wf1-params (prepare-font data "font/woff")
wf2-params (prepare-font data "font/woff2")]
+
(cond-> {}
(some? otf-params)
(assoc :otf (sto/put-object! storage otf-params))
@@ -147,7 +140,7 @@
(assoc :woff2 (sto/put-object! storage wf2-params)))))
(insert-font-variant! [{:keys [woff1 woff2 otf ttf]}]
- (db/insert! pool :team-font-variant
+ (db/insert! conn :team-font-variant
{:id (uuid/next)
:team-id (:team-id params)
:font-id (:font-id params)
@@ -168,63 +161,105 @@
;; --- UPDATE FONT FAMILY
-(s/def ::update-font
- (s/keys :req [::rpc/profile-id]
- :req-un [::team-id ::id ::name]))
+(def ^:private
+ schema:update-font
+ [:map {:title "update-font"}
+ [:team-id ::sm/uuid]
+ [:id ::sm/uuid]
+ [:name :string]])
(sv/defmethod ::update-font
{::doc/added "1.18"
- ::webhooks/event? true}
- [{:keys [::db/pool]} {:keys [::rpc/profile-id team-id id name]}]
- (db/with-atomic [conn pool]
- (teams/check-edition-permissions! conn profile-id team-id)
- (rph/with-meta
- (db/update! conn :team-font-variant
- {:font-family name}
- {:font-id id
- :team-id team-id})
- {::audit/replace-props {:id id
- :name name
- :team-id team-id
- :profile-id profile-id}})))
+ ::webhooks/event? true
+ ::sm/params schema:update-font}
+ [cfg {:keys [::rpc/profile-id team-id id name]}]
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn]}]
+ (teams/check-edition-permissions! conn profile-id team-id)
+
+ (db/update! conn :team-font-variant
+ {:font-family name}
+ {:font-id id
+ :team-id team-id})
+
+ (rph/with-meta (rph/wrap nil)
+ {::audit/replace-props {:id id
+ :name name
+ :team-id team-id
+ :profile-id profile-id}}))))
;; --- DELETE FONT
-(s/def ::delete-font
- (s/keys :req [::rpc/profile-id]
- :req-un [::team-id ::id]))
+(def ^:private
+ schema:delete-font
+ [:map {:title "delete-font"}
+ [:team-id ::sm/uuid]
+ [:id ::sm/uuid]])
(sv/defmethod ::delete-font
{::doc/added "1.18"
- ::webhooks/event? true}
- [{:keys [::db/pool]} {:keys [::rpc/profile-id id team-id]}]
- (db/with-atomic [conn pool]
- (teams/check-edition-permissions! conn profile-id team-id)
- (let [font (db/update! conn :team-font-variant
- {:deleted-at (dt/now)}
- {:font-id id :team-id team-id})]
- (rph/with-meta (rph/wrap)
- {::audit/props {:id id
- :team-id team-id
- :name (:font-family font)
- :profile-id profile-id}}))))
+ ::webhooks/event? true
+ ::sm/params schema:delete-font}
+ [cfg {:keys [::rpc/profile-id id team-id]}]
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn ::sto/storage] :as cfg}]
+ (teams/check-edition-permissions! conn profile-id team-id)
+ (let [fonts (db/query conn :team-font-variant
+ {:team-id team-id
+ :font-id id
+ :deleted-at nil}
+ {::sql/for-update true})
+ storage (media/configure-assets-storage storage conn)
+ tnow (dt/now)]
+
+ (when-not (seq fonts)
+ (ex/raise :type :not-found
+ :code :object-not-found))
+
+ (doseq [font fonts]
+ (db/update! conn :team-font-variant
+ {:deleted-at tnow}
+ {:id (:id font)})
+ (some->> (:woff1-file-id font) (sto/touch-object! storage))
+ (some->> (:woff2-file-id font) (sto/touch-object! storage))
+ (some->> (:ttf-file-id font) (sto/touch-object! storage))
+ (some->> (:otf-file-id font) (sto/touch-object! storage)))
+
+ (rph/with-meta (rph/wrap)
+ {::audit/props {:id id
+ :team-id team-id
+ :name (:font-family (peek fonts))
+ :profile-id profile-id}})))))
;; --- DELETE FONT VARIANT
-(s/def ::delete-font-variant
- (s/keys :req [::rpc/profile-id]
- :req-un [::team-id ::id]))
+(def ^:private schema:delete-font-variant
+ [:map {:title "delete-font-variant"}
+ [:team-id ::sm/uuid]
+ [:id ::sm/uuid]])
(sv/defmethod ::delete-font-variant
{::doc/added "1.18"
- ::webhooks/event? true}
- [{:keys [::db/pool]} {:keys [::rpc/profile-id id team-id]}]
- (db/with-atomic [conn pool]
- (teams/check-edition-permissions! conn profile-id team-id)
- (let [variant (db/update! conn :team-font-variant
- {:deleted-at (dt/now)}
- {:id id :team-id team-id})]
- (rph/with-meta (rph/wrap)
- {::audit/props {:font-family (:font-family variant)
- :font-id (:font-id variant)}}))))
+ ::webhooks/event? true
+ ::sm/params schema:delete-font-variant}
+ [cfg {:keys [::rpc/profile-id id team-id]}]
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn ::sto/storage] :as cfg}]
+ (teams/check-edition-permissions! conn profile-id team-id)
+ (let [variant (db/get conn :team-font-variant
+ {:id id :team-id team-id}
+ {::sql/for-update true})
+ storage (media/configure-assets-storage storage conn)]
+ (db/update! conn :team-font-variant
+ {:deleted-at (dt/now)}
+ {:id (:id variant)})
+
+ (some->> (:woff1-file-id variant) (sto/touch-object! storage))
+ (some->> (:woff2-file-id variant) (sto/touch-object! storage))
+ (some->> (:ttf-file-id variant) (sto/touch-object! storage))
+ (some->> (:otf-file-id variant) (sto/touch-object! storage))
+
+ (rph/with-meta (rph/wrap)
+ {::audit/props {:font-family (:font-family variant)
+ :font-id (:font-id variant)}})))))
diff --git a/backend/src/app/rpc/commands/management.clj b/backend/src/app/rpc/commands/management.clj
index 98f08a8672..aaf51c3a0c 100644
--- a/backend/src/app/rpc/commands/management.clj
+++ b/backend/src/app/rpc/commands/management.clj
@@ -215,7 +215,7 @@
(-> file
(update :features #(db/create-array conn "text" %))
(update :data blob/encode))
- {::db/return-keys? false})
+ {::db/return-keys false})
;; The file profile creation is optional, so when no profile is
;; present (when this function is called from profile less
@@ -231,10 +231,10 @@
{::db/return-keys? false}))
(doseq [params flibs]
- (db/insert! conn :file-library-rel params ::db/return-keys? false))
+ (db/insert! conn :file-library-rel params ::db/return-keys false))
(doseq [params fmeds]
- (db/insert! conn :file-media-object params ::db/return-keys? false))
+ (db/insert! conn :file-media-object params ::db/return-keys false))
file))
diff --git a/backend/src/app/rpc/commands/media.clj b/backend/src/app/rpc/commands/media.clj
index 04ad8bc9bc..a3dc357db5 100644
--- a/backend/src/app/rpc/commands/media.clj
+++ b/backend/src/app/rpc/commands/media.clj
@@ -23,6 +23,7 @@
[app.storage :as sto]
[app.storage.tmp :as tmp]
[app.util.services :as sv]
+ [app.util.time :as dt]
[app.worker :as-alias wrk]
[clojure.spec.alpha :as s]
[cuerdas.core :as str]
@@ -153,6 +154,11 @@
thumb (when-let [params (::thumb result)]
(sto/put-object! storage params))]
+ (db/update! conn :file
+ {:modified-at (dt/now)
+ :has-media-trimmed false}
+ {:id file-id})
+
(db/exec-one! conn [sql:create-file-media-object
(or id (uuid/next))
file-id is-local name
diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj
index 1deacf14ab..5b814abe62 100644
--- a/backend/src/app/rpc/commands/profile.clj
+++ b/backend/src/app/rpc/commands/profile.clj
@@ -13,6 +13,7 @@
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
+ [app.db.sql :as-alias sql]
[app.email :as eml]
[app.http.session :as session]
[app.loggers.audit :as audit]
@@ -99,7 +100,7 @@
;; NOTE: we need to retrieve the profile independently if we use
;; it or not for explicit locking and avoid concurrent updates of
;; the same row/object.
- (let [profile (-> (db/get-by-id conn :profile profile-id ::db/for-update? true)
+ (let [profile (-> (db/get-by-id conn :profile profile-id ::sql/for-update true)
(decode-row))
;; Update the profile map with direct params
@@ -164,7 +165,7 @@
(defn- validate-password!
[{:keys [::db/conn] :as cfg} {:keys [profile-id old-password] :as params}]
- (let [profile (db/get-by-id conn :profile profile-id ::db/for-update? true)]
+ (let [profile (db/get-by-id conn :profile profile-id ::sql/for-update true)]
(when (and (not= (:password profile) "!")
(not (:valid (verify-password cfg old-password (:password profile)))))
(ex/raise :type :validation
@@ -176,7 +177,8 @@
(when-not (db/read-only? conn)
(db/update! conn :profile
{:password (auth/derive-password password)}
- {:id id})))
+ {:id id})
+ nil))
;; --- MUTATION: Update Photo
@@ -202,7 +204,7 @@
(defn update-profile-photo
[{:keys [::db/pool ::sto/storage] :as cfg} {:keys [profile-id file] :as params}]
(let [photo (upload-photo cfg params)
- profile (db/get-by-id pool :profile profile-id ::db/for-update? true)]
+ profile (db/get-by-id pool :profile profile-id ::sql/for-update true)]
;; Schedule deletion of old photo
(when-let [id (:photo-id profile)]
@@ -329,7 +331,7 @@
::sm/params schema:update-profile-props}
[{:keys [::db/pool]} {:keys [::rpc/profile-id props]}]
(db/with-atomic [conn pool]
- (let [profile (get-profile conn profile-id ::db/for-update? true)
+ (let [profile (get-profile conn profile-id ::sql/for-update true)
props (reduce-kv (fn [props k v]
;; We don't accept namespaced keys
(if (simple-ident? k)
diff --git a/backend/src/app/rpc/commands/projects.clj b/backend/src/app/rpc/commands/projects.clj
index 6b4e72091a..b8a555f449 100644
--- a/backend/src/app/rpc/commands/projects.clj
+++ b/backend/src/app/rpc/commands/projects.clj
@@ -9,6 +9,7 @@
[app.common.data.macros :as dm]
[app.common.spec :as us]
[app.db :as db]
+ [app.db.sql :as-alias sql]
[app.loggers.audit :as-alias audit]
[app.loggers.webhooks :as webhooks]
[app.rpc :as-alias rpc]
@@ -233,7 +234,7 @@
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id name] :as params}]
(db/with-atomic [conn pool]
(check-edition-permissions! conn profile-id id)
- (let [project (db/get-by-id conn :project id ::db/for-update? true)]
+ (let [project (db/get-by-id conn :project id ::sql/for-update true)]
(db/update! conn :project
{:name name}
{:id id})
@@ -259,7 +260,8 @@
(check-edition-permissions! conn profile-id id)
(let [project (db/update! conn :project
{:deleted-at (dt/now)}
- {:id id :is-default false})]
+ {:id id :is-default false}
+ {::db/return-keys true})]
(rph/with-meta (rph/wrap)
{::audit/props {:team-id (:team-id project)
:name (:name project)
diff --git a/backend/src/app/rpc/commands/teams.clj b/backend/src/app/rpc/commands/teams.clj
index 791bce1d6e..264fca2a1e 100644
--- a/backend/src/app/rpc/commands/teams.clj
+++ b/backend/src/app/rpc/commands/teams.clj
@@ -963,5 +963,6 @@
(let [invitation (db/delete! conn :team-invitation
{:team-id team-id
- :email-to (str/lower email)})]
+ :email-to (str/lower email)}
+ {::db/return-keys true})]
(rph/wrap nil {::audit/props {:invitation-id (:id invitation)}})))))
diff --git a/backend/src/app/rpc/commands/webhooks.clj b/backend/src/app/rpc/commands/webhooks.clj
index 1c6b812c56..13a5d02101 100644
--- a/backend/src/app/rpc/commands/webhooks.clj
+++ b/backend/src/app/rpc/commands/webhooks.clj
@@ -95,7 +95,8 @@
:mtype mtype
:error-code nil
:error-count 0}
- {:id id})
+ {:id id}
+ {::db/return-keys true})
(decode-row)))
(sv/defmethod ::create-webhook
diff --git a/backend/src/app/rpc/retry.clj b/backend/src/app/rpc/retry.clj
index 9cb048ea91..bd9c3ea075 100644
--- a/backend/src/app/rpc/retry.clj
+++ b/backend/src/app/rpc/retry.clj
@@ -18,46 +18,47 @@
(and (instance? PSQLException e)
(= "23505" (.getSQLState ^PSQLException e))))
-(def ^:private always-false (constantly false))
+(def ^:private always-false
+ (constantly false))
(defn wrap-retry
- [_ f {:keys [::matches ::sv/name] :or {matches always-false} :as mdata}]
+ [_ f {:keys [::sv/name] :as mdata}]
- (when (::enabled mdata)
- (l/debug :hint "wrapping retry" :name name))
-
- (if-let [max-retries (::max-retries mdata)]
- (fn [cfg params]
- ((fn run [retry]
- (try
- (f cfg params)
- (catch Throwable cause
- (if (matches cause)
- (let [current-retry (inc retry)]
- (l/trace :hint "running retry algorithm" :retry current-retry)
- (if (<= current-retry max-retries)
- (run current-retry)
- (throw cause)))
- (throw cause))))) 1))
+ (if (::enabled mdata)
+ (let [max-retries (get mdata ::max-retries 3)
+ matches? (get mdata ::when always-false)]
+ (l/dbg :hint "wrapping retry" :name name :max-retries max-retries)
+ (fn [cfg params]
+ ((fn recursive-invoke [retry]
+ (try
+ (f cfg params)
+ (catch Throwable cause
+ (if (matches? cause)
+ (let [current-retry (inc retry)]
+ (l/wrn :hint "retrying operation" :retry current-retry :service name)
+ (if (<= current-retry max-retries)
+ (recursive-invoke current-retry)
+ (throw cause)))
+ (throw cause))))) 1)))
f))
-(defmacro with-retry
- [{:keys [::when ::max-retries ::label ::db/conn] :or {max-retries 3}} & body]
- `(let [conn# ~conn]
- (assert (or (nil? conn#) (db/connection? conn#)) "invalid database connection")
- (loop [tnum# 1]
- (let [result# (let [sp# (some-> conn# db/savepoint)]
- (try
- (let [result# (do ~@body)]
- (some->> sp# (db/release! conn#))
- result#)
- (catch Throwable cause#
- (some->> sp# (db/rollback! conn#))
- (if (and (~when cause#) (<= tnum# ~max-retries))
- ::retry
- (throw cause#)))))]
- (if (= ::retry result#)
- (do
- (l/warn :hint "retrying operation" :label ~label :retry tnum#)
- (recur (inc tnum#)))
- result#)))))
+(defn invoke
+ [{:keys [::db/conn ::max-retries] :or {max-retries 3} :as cfg} f & args]
+ (assert (db/connection? conn) "invalid database connection")
+ (loop [rnum 1]
+ (let [match? (get cfg ::when always-false)
+ result (let [spoint (db/savepoint conn)]
+ (try
+ (let [result (apply f cfg args)]
+ (db/release! conn spoint)
+ result)
+ (catch Throwable cause
+ (db/rollback! conn spoint)
+ (if (and (match? cause) (<= rnum max-retries))
+ ::retry
+ (throw cause)))))]
+ (if (= ::retry result)
+ (let [label (get cfg ::label "anonymous")]
+ (l/warn :hint "retrying operation" :label label :retry rnum)
+ (recur (inc rnum)))
+ result))))
diff --git a/backend/src/app/srepl/cli.clj b/backend/src/app/srepl/cli.clj
index c3a4bd0c12..9b4943bdcf 100644
--- a/backend/src/app/srepl/cli.clj
+++ b/backend/src/app/srepl/cli.clj
@@ -65,9 +65,8 @@
(let [res (db/update! conn :profile
params
{:email email
- :deleted-at nil}
- {::db/return-keys? false})]
- (pos? (:next.jdbc/update-count res))))))))
+ :deleted-at nil})]
+ (pos? (db/get-update-count res))))))))
(defmethod exec-command :delete-profile
[{:keys [email soft]}]
@@ -82,12 +81,10 @@
(let [res (if soft
(db/update! conn :profile
{:deleted-at (dt/now)}
- {:email email :deleted-at nil}
- {::db/return-keys? false})
+ {:email email :deleted-at nil})
(db/delete! conn :profile
- {:email email}
- {::db/return-keys? false}))]
- (pos? (:next.jdbc/update-count res))))))
+ {:email email}))]
+ (pos? (db/get-update-count res))))))
(defmethod exec-command :search-profile
[{:keys [email]}]
diff --git a/backend/src/app/srepl/components_v2.clj b/backend/src/app/srepl/components_v2.clj
index 598c13e6d5..049fc3574f 100644
--- a/backend/src/app/srepl/components_v2.clj
+++ b/backend/src/app/srepl/components_v2.clj
@@ -6,8 +6,6 @@
(ns app.srepl.components-v2
(:require
- [app.common.data :as d]
- [app.common.data.macros :as dm]
[app.common.logging :as l]
[app.common.pprint :as pp]
[app.db :as db]
@@ -19,6 +17,13 @@
[promesa.exec.semaphore :as ps]
[promesa.util :as pu]))
+(def ^:dynamic *scope* nil)
+(def ^:dynamic *semaphore* nil)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; PRIVATE HELPERS
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
(defn- print-stats!
[stats]
(->> stats
@@ -87,210 +92,228 @@
res (db/exec-one! pool [sql])]
(:count res)))
-(defn migrate-file!
- [system file-id & {:keys [rollback?] :or {rollback? true}}]
- (l/dbg :hint "migrate:start")
- (let [tpoint (dt/tpoint)]
- (try
- (binding [feat/*stats* (atom {})]
+(defn- mark-team-migration!
+ [{:keys [::db/pool]} team-id]
+ ;; We execute this out of transaction because we want this
+ ;; change to be visible to all other sessions before starting
+ ;; the migration
+ (let [sql (str "UPDATE team SET features = "
+ " array_append(features, 'ephimeral/v2-migration') "
+ " WHERE id = ?")]
+ (db/exec-one! pool [sql team-id])))
+
+(defn- unmark-team-migration!
+ [{:keys [::db/pool]} team-id]
+ ;; We execute this out of transaction because we want this
+ ;; change to be visible to all other sessions before starting
+ ;; the migration
+ (let [sql (str "UPDATE team SET features = "
+ " array_remove(features, 'ephimeral/v2-migration') "
+ " WHERE id = ?")]
+ (db/exec-one! pool [sql team-id])))
+
+(def ^:private sql:get-teams
+ "SELECT id, features
+ FROM team
+ WHERE deleted_at IS NULL
+ ORDER BY created_at ASC")
+
+(defn- get-teams
+ [conn]
+ (->> (db/cursor conn sql:get-teams)
+ (map feat/decode-row)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; PUBLIC API
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defn migrate-file!
+ [system file-id & {:keys [rollback? max-procs]
+ :or {rollback? true}}]
+
+ (l/dbg :hint "migrate:start" :rollback rollback?)
+ (let [tpoint (dt/tpoint)
+ file-id (if (string? file-id)
+ (parse-uuid file-id)
+ file-id)]
+ (binding [feat/*stats* (atom {})]
+ (try
(-> (assoc system ::db/rollback rollback?)
- (feat/migrate-file! file-id))
+ (feat/migrate-file! file-id :max-procs max-procs))
(-> (deref feat/*stats*)
- (assoc :elapsed (dt/format-duration (tpoint)))))
+ (assoc :elapsed (dt/format-duration (tpoint))))
- (catch Throwable cause
- (l/wrn :hint "migrate:error" :cause cause))
+ (catch Throwable cause
+ (l/wrn :hint "migrate:error" :cause cause))
- (finally
- (let [elapsed (dt/format-duration (tpoint))]
- (l/dbg :hint "migrate:end" :elapsed elapsed))))))
-
-(defn migrate-files!
- [{:keys [::db/pool] :as system}
- & {:keys [chunk-size max-jobs max-items start-at preset rollback? skip-on-error validate?]
- :or {chunk-size 10
- skip-on-error true
- max-jobs 10
- max-items Long/MAX_VALUE
- preset :shutdown-on-failure
- rollback? true
- validate? false}}]
- (letfn [(get-chunk [cursor]
- (let [sql (str/concat
- "SELECT id, created_at FROM file "
- " WHERE created_at < ? AND deleted_at IS NULL "
- " ORDER BY created_at desc LIMIT ?")
- rows (db/exec! pool [sql cursor chunk-size])]
- [(some->> rows peek :created-at) (seq rows)]))
-
- (get-candidates []
- (->> (d/iteration get-chunk
- :vf second
- :kf first
- :initk (or start-at (dt/now)))
- (take max-items)
- (map :id)))]
-
- (l/dbg :hint "migrate:start")
- (let [fsem (ps/create :permits max-jobs)
- total (get-total-files pool)
- stats (atom {:files/total total})
- tpoint (dt/tpoint)]
-
- (add-watch stats :progress-report (report-progress-files tpoint))
-
- (binding [feat/*stats* stats
- feat/*semaphore* fsem
- feat/*skip-on-error* skip-on-error]
- (try
- (pu/with-open [scope (px/structured-task-scope :preset preset :factory :virtual)]
-
- (run! (fn [file-id]
- (ps/acquire! feat/*semaphore*)
- (px/submit! scope (fn []
- (-> (assoc system ::db/rollback rollback?)
- (feat/migrate-file! file-id
- :validate? validate?
- :throw-on-validate? (not skip-on-error))))))
- (get-candidates))
-
- (p/await! scope))
-
- (-> (deref feat/*stats*)
- (assoc :elapsed (dt/format-duration (tpoint))))
-
- (catch Throwable cause
- (l/dbg :hint "migrate:error" :cause cause))
-
- (finally
- (let [elapsed (dt/format-duration (tpoint))]
- (l/dbg :hint "migrate:end" :elapsed elapsed))))))))
+ (finally
+ (let [elapsed (dt/format-duration (tpoint))]
+ (l/dbg :hint "migrate:end" :rollback rollback? :elapsed elapsed)))))))
(defn migrate-team!
- [{:keys [::db/pool] :as system} team-id
- & {:keys [rollback? skip-on-error validate?]
- :or {rollback? true skip-on-error true validate? false}}]
- (l/dbg :hint "migrate:start")
+ [{:keys [::db/pool] :as system} team-id & {:keys [rollback? skip-on-error validate? max-procs]
+ :or {rollback? true
+ skip-on-error true
+ validate? false
+ max-procs 1 }
+ :as opts}]
- (let [total (get-total-files pool :team-id team-id)
- stats (atom {:total/files total})
- tpoint (dt/tpoint)]
+ (l/dbg :hint "migrate:start" :rollback rollback?)
+
+ (let [team-id (if (string? team-id)
+ (parse-uuid team-id)
+ team-id)
+ total (get-total-files pool :team-id team-id)
+ stats (atom {:total/files total})
+ tpoint (dt/tpoint)]
(add-watch stats :progress-report (report-progress-files tpoint))
- (try
- (binding [feat/*stats* stats
- feat/*skip-on-error* skip-on-error]
+ (binding [feat/*stats* stats
+ feat/*skip-on-error* skip-on-error]
+
+ (try
+ (mark-team-migration! system team-id)
+
(-> (assoc system ::db/rollback rollback?)
(feat/migrate-team! team-id
+ :max-procs max-procs
:validate? validate?
:throw-on-validate? (not skip-on-error)))
(print-stats!
(-> (deref feat/*stats*)
(dissoc :total/files)
- (assoc :elapsed (dt/format-duration (tpoint))))))
+ (assoc :elapsed (dt/format-duration (tpoint)))))
- (catch Throwable cause
- (l/dbg :hint "migrate:error" :cause cause))
+ (catch Throwable cause
+ (l/dbg :hint "migrate:error" :cause cause))
- (finally
- (let [elapsed (dt/format-duration (tpoint))]
- (l/dbg :hint "migrate:end" :elapsed elapsed))))))
+ (finally
+ (unmark-team-migration! system team-id)
-(defn default-on-end
- [stats]
- (print-stats!
- (-> stats
- (update :elapsed/total dt/format-duration)
- (dissoc :total/teams))))
+ (let [elapsed (dt/format-duration (tpoint))]
+ (l/dbg :hint "migrate:end" :rollback rollback? :elapsed elapsed)))))))
(defn migrate-teams!
- [{:keys [::db/pool] :as system}
- & {:keys [chunk-size max-jobs max-items start-at
- rollback? validate? preset skip-on-error
- max-time on-start on-progress on-error on-end]
- :or {chunk-size 10000
- validate? false
- rollback? true
- skip-on-error true
- on-end default-on-end
- preset :shutdown-on-failure
- max-jobs Integer/MAX_VALUE
- max-items Long/MAX_VALUE}}]
+ "A REPL helper for migrate all teams.
- (letfn [(get-chunk [cursor]
- (let [sql (str/concat
- "SELECT id, created_at, features FROM team "
- " WHERE created_at < ? AND deleted_at IS NULL "
- " ORDER BY created_at desc LIMIT ?")
- rows (db/exec! pool [sql cursor chunk-size])]
- [(some->> rows peek :created-at) (seq rows)]))
+ This function starts multiple concurrent team migration processes
+ until thw maximum number of jobs is reached which by default has the
+ value of `1`. This is controled with the `:max-jobs` option.
- (get-candidates []
- (->> (d/iteration get-chunk
- :vf second
- :kf first
- :initk (or start-at (dt/now)))
- (map #(update % :features db/decode-pgarray #{}))
- (remove #(contains? (:features %) "ephimeral/v2-migration"))
- (take max-items)
- (map :id)))
+ Each tram migration process also can start multiple procs for
+ graphics migration, the total of that procs is controled with the
+ `:max-procs` option.
- (migrate-team [team-id]
- (try
- (-> (assoc system ::db/rollback rollback?)
- (feat/migrate-team! team-id
- :validate? validate?
- :throw-on-validate? (not skip-on-error)))
- (catch Throwable cause
- (l/err :hint "unexpected error on processing team" :team-id (dm/str team-id) :cause cause))))
+ Internally, the graphics migration process uses SVGO module which by
+ default has a limited number of maximum concurent
+ operations (globally), ensure setting up correct number with
+ PENPOT_SVGO_MAX_PROCS environment variable."
- (process-team [scope tpoint mtime team-id]
- (ps/acquire! feat/*semaphore*)
- (let [ts (tpoint)]
- (if (and mtime (neg? (compare mtime ts)))
- (l/inf :hint "max time constraint reached" :elapsed (dt/format-duration ts))
- (px/submit! scope (partial migrate-team team-id)))))]
+ [{:keys [::db/pool] :as system} & {:keys [max-jobs max-procs max-items
+ rollback? validate? preset
+ skip-on-error max-time
+ on-start on-progress on-error on-end]
+ :or {validate? false
+ rollback? true
+ skip-on-error true
+ preset :shutdown-on-failure
+ max-jobs 1
+ max-procs 10
+ max-items Long/MAX_VALUE}
+ :as opts}]
- (l/dbg :hint "migrate:start")
+ (let [total (get-total-teams pool)
+ stats (atom {:total/teams (min total max-items)})
- (let [sem (ps/create :permits max-jobs)
- total (get-total-teams pool)
- stats (atom {:total/teams (min total max-items)})
- tpoint (dt/tpoint)
- mtime (some-> max-time dt/duration)]
+ tpoint (dt/tpoint)
+ mtime (some-> max-time dt/duration)
- (when (fn? on-start)
- (on-start {:total total :rollback rollback?}))
+ scope (px/structured-task-scope :preset preset :factory :virtual)
+ sjobs (ps/create :permits max-jobs)
- (add-watch stats :progress-report (report-progress-teams tpoint on-progress))
+ migrate-team
+ (fn [{:keys [id features] :as team}]
+ (ps/acquire! sjobs)
+ (let [ts (tpoint)]
+ (cond
+ (and mtime (neg? (compare mtime ts)))
+ (do
+ (l/inf :hint "max time constraint reached"
+ :team-id (str id)
+ :elapsed (dt/format-duration ts))
+ (ps/release! sjobs)
+ (reduced nil))
- (binding [feat/*stats* stats
- feat/*semaphore* sem
- feat/*skip-on-error* skip-on-error]
+ (or (contains? features "ephimeral/v2-migration")
+ (contains? features "components/v2"))
+ (do
+ (l/dbg :hint "skip team" :team-id (str id))
+ (ps/release! sjobs))
+
+ :else
+ (px/submit! scope (fn []
+ (try
+ (mark-team-migration! system id)
+ (-> (assoc system ::db/rollback rollback?)
+ (feat/migrate-team! id
+ :max-procs max-procs
+ :validate? validate?
+ :throw-on-validate? (not skip-on-error)))
+ (catch Throwable cause
+ (l/err :hint "unexpected error on processing team"
+ :team-id (str id)
+ :cause cause))
+ (finally
+ (ps/release! sjobs)
+ (unmark-team-migration! system id))))))))]
+
+ (l/dbg :hint "migrate:start"
+ :rollback rollback?
+ :total total
+ :max-jobs max-jobs
+ :max-procs max-procs
+ :max-items max-items)
+
+ (add-watch stats :progress-report (report-progress-teams tpoint on-progress))
+
+ (binding [feat/*stats* stats
+ feat/*skip-on-error* skip-on-error]
+ (try
+ (when (fn? on-start)
+ (on-start {:total total :rollback rollback?}))
+
+ (db/tx-run! system
+ (fn [{:keys [::db/conn]}]
+ (run! (partial migrate-team)
+ (->> (get-teams conn)
+ (take max-items)))))
(try
- (pu/with-open [scope (px/structured-task-scope :preset preset
- :factory :virtual)]
- (loop [candidates (get-candidates)]
- (when-let [team-id (first candidates)]
- (when (process-team scope tpoint mtime team-id)
- (recur (rest candidates)))))
-
- (p/await! scope))
-
- (when (fn? on-end)
- (-> (deref stats)
- (assoc :elapsed/total (tpoint))
- (on-end)))
-
- (catch Throwable cause
- (l/dbg :hint "migrate:error" :cause cause)
- (when (fn? on-error)
- (on-error cause)))
-
+ (p/await! scope)
(finally
- (let [elapsed (dt/format-duration (tpoint))]
- (l/dbg :hint "migrate:end" :elapsed elapsed))))))))
+ (pu/close! scope)))
+
+
+ (if (fn? on-end)
+ (-> (deref stats)
+ (assoc :elapsed/total (tpoint))
+ (on-end))
+ (-> (deref stats)
+ (assoc :elapsed/total (tpoint))
+ (update :elapsed/total dt/format-duration)
+ (dissoc :total/teams)
+ (print-stats!)))
+
+ (catch Throwable cause
+ (l/dbg :hint "migrate:error" :cause cause)
+ (when (fn? on-error)
+ (on-error cause)))
+
+ (finally
+ (let [elapsed (dt/format-duration (tpoint))]
+ (l/dbg :hint "migrate:end"
+ :rollback rollback?
+ :elapsed elapsed)))))))
diff --git a/backend/src/app/srepl/helpers.clj b/backend/src/app/srepl/helpers.clj
index bc8caf6c17..c135d3e763 100644
--- a/backend/src/app/srepl/helpers.clj
+++ b/backend/src/app/srepl/helpers.clj
@@ -83,7 +83,7 @@
(into [file] (map (fn [{:keys [id]}]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer system id)]
(-> (files/get-file system id :migrate? false)
- (feat.fdata/process-pointers deref)
+ (update :data feat.fdata/process-pointers deref)
(pmg/migrate-file))))))
(d/index-by :id))]
(validate/validate-file file libs))))))
@@ -101,7 +101,7 @@
(into [file] (map (fn [{:keys [id]}]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer system id)]
(-> (files/get-file system id :migrate? false)
- (feat.fdata/process-pointers deref)
+ (update :data feat.fdata/process-pointers deref)
(pmg/migrate-file))))))
(d/index-by :id))
errors (validate/validate-file file libs)
diff --git a/backend/src/app/storage.clj b/backend/src/app/storage.clj
index 299fefcbb0..c27672e2a1 100644
--- a/backend/src/app/storage.clj
+++ b/backend/src/app/storage.clj
@@ -9,8 +9,6 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
- [app.common.exceptions :as ex]
- [app.common.logging :as l]
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.db :as db]
@@ -172,8 +170,7 @@
(let [id (if (impl/object? object-or-id) (:id object-or-id) object-or-id)
rs (db/update! pool-or-conn :storage-object
{:touched-at (dt/now)}
- {:id id}
- {::db/return-keys? false})]
+ {:id id})]
(pos? (db/get-update-count rs))))
(defn get-object-data
@@ -222,231 +219,8 @@
(let [id (if (impl/object? object-or-id) (:id object-or-id) object-or-id)
res (db/update! pool-or-conn :storage-object
{:deleted-at (dt/now)}
- {:id id}
- {::db/return-keys? false})]
+ {:id id})]
(pos? (db/get-update-count res))))
(dm/export impl/resolve-backend)
(dm/export impl/calculate-hash)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Garbage Collection: Permanently delete objects
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; A task responsible to permanently delete already marked as deleted
-;; storage files. The storage objects are practically never marked to
-;; be deleted directly by the api call. The touched-gc is responsible
-;; of collecting the usage of the object and mark it as deleted. Only
-;; the TMP files are are created with expiration date in future.
-
-(declare sql:retrieve-deleted-objects-chunk)
-
-(defmethod ig/pre-init-spec ::gc-deleted-task [_]
- (s/keys :req [::storage ::db/pool]))
-
-(defmethod ig/prep-key ::gc-deleted-task
- [_ cfg]
- (assoc cfg ::min-age (dt/duration {:hours 2})))
-
-(defmethod ig/init-key ::gc-deleted-task
- [_ {:keys [::db/pool ::storage ::min-age]}]
- (letfn [(get-to-delete-chunk [cursor]
- (let [sql (str "select s.* "
- " from storage_object as s "
- " where s.deleted_at is not null "
- " and s.deleted_at < ? "
- " order by s.deleted_at desc "
- " limit 25")
- rows (db/exec! pool [sql cursor])]
- [(some-> rows peek :deleted-at)
- (some->> (seq rows) (d/group-by #(-> % :backend keyword) :id #{}) seq)]))
-
- (get-to-delete-chunks [min-age]
- (d/iteration get-to-delete-chunk
- :initk (dt/minus (dt/now) min-age)
- :vf second
- :kf first))
-
- (delete-in-bulk! [backend-id ids]
- (try
- (db/with-atomic [conn pool]
- (let [sql "delete from storage_object where id = ANY(?)"
- ids' (db/create-array conn "uuid" ids)
-
- total (-> (db/exec-one! conn [sql ids'])
- (db/get-update-count))]
-
- (-> (impl/resolve-backend storage backend-id)
- (impl/del-objects-in-bulk ids))
-
- (doseq [id ids]
- (l/dbg :hint "gc-deleted: permanently delete storage object" :backend backend-id :id id))
-
- total))
-
- (catch Throwable cause
- (l/err :hint "gc-deleted: unexpected error on bulk deletion"
- :ids (vec ids)
- :cause cause)
- 0)))]
-
- (fn [params]
- (let [min-age (or (some-> params :min-age dt/duration) min-age)]
- (loop [total 0
- chunks (get-to-delete-chunks min-age)]
- (if-let [[backend-id ids] (first chunks)]
- (let [deleted (delete-in-bulk! backend-id ids)]
- (recur (+ total deleted)
- (rest chunks)))
- (do
- (l/inf :hint "gc-deleted: task finished"
- :min-age (dt/format-duration min-age)
- :total total)
- {:deleted total})))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Garbage Collection: Analyze touched objects
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; This task is part of the garbage collection process of storage
-;; objects and is responsible on analyzing the touched objects and
-;; mark them for deletion if corresponds.
-;;
-;; For example: when file_media_object is deleted, the depending
-;; storage_object are marked as touched. This means that some files
-;; that depend on a concrete storage_object are no longer exists and
-;; maybe this storage_object is no longer necessary and can be
-;; eligible for elimination. This task periodically analyzes touched
-;; objects and mark them as freeze (means that has other references
-;; and the object is still valid) or deleted (no more references to
-;; this object so is ready to be deleted).
-
-(declare sql:retrieve-file-media-object-nrefs)
-(declare sql:retrieve-file-object-thumbnail-nrefs)
-(declare sql:retrieve-profile-nrefs)
-(declare sql:retrieve-team-font-variant-nrefs)
-(declare sql:retrieve-touched-objects-chunk)
-
-(defmethod ig/pre-init-spec ::gc-touched-task [_]
- (s/keys :req [::db/pool]))
-
-(defmethod ig/init-key ::gc-touched-task
- [_ {:keys [::db/pool]}]
- (letfn [(get-team-font-variant-nrefs [conn id]
- (-> (db/exec-one! conn [sql:retrieve-team-font-variant-nrefs id id id id]) :nrefs))
-
- (get-file-media-object-nrefs [conn id]
- (-> (db/exec-one! conn [sql:retrieve-file-media-object-nrefs id id]) :nrefs))
-
- (get-profile-nrefs [conn id]
- (-> (db/exec-one! conn [sql:retrieve-profile-nrefs id id]) :nrefs))
-
- (get-file-object-thumbnails [conn id]
- (-> (db/exec-one! conn [sql:retrieve-file-object-thumbnail-nrefs id]) :nrefs))
-
- (mark-freeze-in-bulk [conn ids]
- (db/exec-one! conn ["update storage_object set touched_at=null where id = ANY(?)"
- (db/create-array conn "uuid" ids)]))
-
- (mark-delete-in-bulk [conn ids]
- (db/exec-one! conn ["update storage_object set deleted_at=now(), touched_at=null where id = ANY(?)"
- (db/create-array conn "uuid" ids)]))
-
- ;; NOTE: A getter that retrieves the key witch will be used
- ;; for group ids; previously we have no value, then we
- ;; introduced the `:reference` prop, and then it is renamed
- ;; to `:bucket` and now is string instead. This is
- ;; implemented in this way for backward comaptibilty.
-
- ;; NOTE: we use the "file-media-object" as default value for
- ;; backward compatibility because when we deploy it we can
- ;; have old backend instances running in the same time as
- ;; the new one and we can still have storage-objects created
- ;; without bucket value. And we know that if it does not
- ;; have value, it means :file-media-object.
-
- (get-bucket [{:keys [metadata]}]
- (or (some-> metadata :bucket)
- (some-> metadata :reference d/name)
- "file-media-object"))
-
- (retrieve-touched-chunk [conn cursor]
- (let [rows (->> (db/exec! conn [sql:retrieve-touched-objects-chunk cursor])
- (mapv #(d/update-when % :metadata db/decode-transit-pgobject)))]
- (when (seq rows)
- [(-> rows peek :created-at)
- (d/group-by get-bucket :id #{} rows)])))
-
- (retrieve-touched [conn]
- (d/iteration (partial retrieve-touched-chunk conn)
- :initk (dt/now)
- :vf second
- :kf first))
-
- (process-objects! [conn get-fn ids bucket]
- (loop [to-freeze #{}
- to-delete #{}
- ids (seq ids)]
- (if-let [id (first ids)]
- (let [nrefs (get-fn conn id)]
- (if (pos? nrefs)
- (do
- (l/debug :hint "gc-touched: processing storage object"
- :id id :status "freeze"
- :bucket bucket :refs nrefs)
- (recur (conj to-freeze id) to-delete (rest ids)))
- (do
- (l/debug :hint "gc-touched: processing storage object"
- :id id :status "delete"
- :bucket bucket :refs nrefs)
- (recur to-freeze (conj to-delete id) (rest ids)))))
- (do
- (some->> (seq to-freeze) (mark-freeze-in-bulk conn))
- (some->> (seq to-delete) (mark-delete-in-bulk conn))
- [(count to-freeze) (count to-delete)]))))]
-
- (fn [_]
- (db/with-atomic [conn pool]
- (loop [to-freeze 0
- to-delete 0
- groups (retrieve-touched conn)]
- (if-let [[bucket ids] (first groups)]
- (let [[f d] (case bucket
- "file-media-object" (process-objects! conn get-file-media-object-nrefs ids bucket)
- "team-font-variant" (process-objects! conn get-team-font-variant-nrefs ids bucket)
- "file-object-thumbnail" (process-objects! conn get-file-object-thumbnails ids bucket)
- "profile" (process-objects! conn get-profile-nrefs ids bucket)
- (ex/raise :type :internal
- :code :unexpected-unknown-reference
- :hint (dm/fmt "unknown reference %" bucket)))]
- (recur (+ to-freeze (long f))
- (+ to-delete (long d))
- (rest groups)))
- (do
- (l/info :hint "gc-touched: task finished" :to-freeze to-freeze :to-delete to-delete)
- {:freeze to-freeze :delete to-delete})))))))
-
-(def sql:retrieve-touched-objects-chunk
- "SELECT so.*
- FROM storage_object AS so
- WHERE so.touched_at IS NOT NULL
- AND so.created_at < ?
- ORDER by so.created_at DESC
- LIMIT 500;")
-
-(def sql:retrieve-file-media-object-nrefs
- "select ((select count(*) from file_media_object where media_id = ?) +
- (select count(*) from file_media_object where thumbnail_id = ?)) as nrefs")
-
-(def sql:retrieve-file-object-thumbnail-nrefs
- "select (select count(*) from file_tagged_object_thumbnail where media_id = ?) as nrefs")
-
-(def sql:retrieve-team-font-variant-nrefs
- "select ((select count(*) from team_font_variant where woff1_file_id = ?) +
- (select count(*) from team_font_variant where woff2_file_id = ?) +
- (select count(*) from team_font_variant where otf_file_id = ?) +
- (select count(*) from team_font_variant where ttf_file_id = ?)) as nrefs")
-
-(def sql:retrieve-profile-nrefs
- "select ((select count(*) from profile where photo_id = ?) +
- (select count(*) from team where photo_id = ?)) as nrefs")
diff --git a/backend/src/app/storage/gc_deleted.clj b/backend/src/app/storage/gc_deleted.clj
new file mode 100644
index 0000000000..2852c8fe6b
--- /dev/null
+++ b/backend/src/app/storage/gc_deleted.clj
@@ -0,0 +1,125 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; Copyright (c) KALEIDOS INC
+
+(ns app.storage.gc-deleted
+ "A task responsible to permanently delete already marked as deleted
+ storage files. The storage objects are practically never marked to
+ be deleted directly by the api call.
+
+ The touched-gc is responsible of collecting the usage of the object
+ and mark it as deleted. Only the TMP files are are created with
+ expiration date in future."
+ (:require
+ [app.common.data :as d]
+ [app.common.logging :as l]
+ [app.db :as db]
+ [app.storage :as-alias sto]
+ [app.storage.impl :as impl]
+ [app.util.time :as dt]
+ [clojure.spec.alpha :as s]
+ [integrant.core :as ig]))
+
+(def ^:private sql:lock-sobjects
+ "SELECT id FROM storage_object
+ WHERE id = ANY(?::uuid[])
+ FOR UPDATE
+ SKIP LOCKED")
+
+(defn- lock-ids
+ "Perform a select before delete for proper object locking and
+ prevent concurrent operations and we proceed only with successfully
+ locked objects."
+ [conn ids]
+ (let [ids (db/create-array conn "uuid" ids)]
+ (->> (db/exec! conn [sql:lock-sobjects ids])
+ (into #{} (map :id))
+ (not-empty))))
+
+
+(def ^:private sql:delete-sobjects
+ "DELETE FROM storage_object
+ WHERE id = ANY(?::uuid[])")
+
+(defn- delete-sobjects!
+ [conn ids]
+ (let [ids (db/create-array conn "uuid" ids)]
+ (-> (db/exec-one! conn [sql:delete-sobjects ids])
+ (db/get-update-count))))
+
+(defn- delete-in-bulk!
+ [cfg backend-id ids]
+ ;; We run the deletion on a separate transaction. This is
+ ;; because if some exception is raised inside procesing
+ ;; one chunk, it does not affects the rest of the chunks.
+ (try
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn ::sto/storage]}]
+ (when-let [ids (lock-ids conn ids)]
+ (let [total (delete-sobjects! conn ids)]
+ (-> (impl/resolve-backend storage backend-id)
+ (impl/del-objects-in-bulk ids))
+
+ (doseq [id ids]
+ (l/dbg :hint "permanently delete storage object"
+ :id (str id)
+ :backend (name backend-id)))
+ total))))
+ (catch Throwable cause
+ (l/err :hint "unexpected error on bulk deletion"
+ :ids ids
+ :cause cause))))
+
+
+(defn- group-by-backend
+ [items]
+ (d/group-by (comp keyword :backend) :id #{} items))
+
+(def ^:private sql:get-deleted-sobjects
+ "SELECT s.* FROM storage_object AS s
+ WHERE s.deleted_at IS NOT NULL
+ AND s.deleted_at < now() - ?::interval
+ ORDER BY s.deleted_at ASC")
+
+(defn- get-buckets
+ [conn min-age]
+ (let [age (db/interval min-age)]
+ (sequence
+ (comp (partition-all 25)
+ (mapcat group-by-backend))
+ (db/cursor conn [sql:get-deleted-sobjects age]))))
+
+
+(defn- clean-deleted!
+ [{:keys [::db/conn ::min-age] :as cfg}]
+ (reduce (fn [total [backend-id ids]]
+ (let [deleted (delete-in-bulk! cfg backend-id ids)]
+ (+ total (or deleted 0))))
+ 0
+ (get-buckets conn min-age)))
+
+
+(defmethod ig/pre-init-spec ::handler [_]
+ (s/keys :req [::sto/storage ::db/pool]))
+
+(defmethod ig/prep-key ::handler
+ [_ cfg]
+ (assoc cfg ::min-age (dt/duration {:hours 2})))
+
+(defmethod ig/init-key ::handler
+ [_ {:keys [::min-age] :as cfg}]
+ (fn [params]
+ (let [min-age (dt/duration (or (:min-age params) min-age))]
+ (db/tx-run! cfg (fn [cfg]
+ (let [cfg (assoc cfg ::min-age min-age)
+ total (clean-deleted! cfg)]
+
+ (l/inf :hint "task finished"
+ :min-age (dt/format-duration min-age)
+ :total total)
+
+ {:deleted total}))))))
+
+
diff --git a/backend/src/app/storage/gc_touched.clj b/backend/src/app/storage/gc_touched.clj
new file mode 100644
index 0000000000..bd499bb655
--- /dev/null
+++ b/backend/src/app/storage/gc_touched.clj
@@ -0,0 +1,208 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; Copyright (c) KALEIDOS INC
+
+(ns app.storage.gc-touched
+ "This task is part of the garbage collection process of storage
+ objects and is responsible on analyzing the touched objects and mark
+ them for deletion if corresponds.
+
+ For example: when file_media_object is deleted, the depending
+ storage_object are marked as touched. This means that some files
+ that depend on a concrete storage_object are no longer exists and
+ maybe this storage_object is no longer necessary and can be eligible
+ for elimination. This task periodically analyzes touched objects and
+ mark them as freeze (means that has other references and the object
+ is still valid) or deleted (no more references to this object so is
+ ready to be deleted)."
+ (:require
+ [app.common.data :as d]
+ [app.common.data.macros :as dm]
+ [app.common.exceptions :as ex]
+ [app.common.logging :as l]
+ [app.db :as db]
+ [app.storage :as-alias sto]
+ [app.storage.impl :as impl]
+ [clojure.spec.alpha :as s]
+ [integrant.core :as ig]))
+
+(def ^:private sql:get-team-font-variant-nrefs
+ "SELECT ((SELECT count(*) FROM team_font_variant WHERE woff1_file_id = ?) +
+ (SELECT count(*) FROM team_font_variant WHERE woff2_file_id = ?) +
+ (SELECT count(*) FROM team_font_variant WHERE otf_file_id = ?) +
+ (SELECT count(*) FROM team_font_variant WHERE ttf_file_id = ?)) AS nrefs")
+
+(defn- get-team-font-variant-nrefs
+ [conn id]
+ (-> (db/exec-one! conn [sql:get-team-font-variant-nrefs id id id id])
+ (get :nrefs)))
+
+
+(def ^:private
+ sql:get-file-media-object-nrefs
+ "SELECT ((SELECT count(*) FROM file_media_object WHERE media_id = ?) +
+ (SELECT count(*) FROM file_media_object WHERE thumbnail_id = ?)) AS nrefs")
+
+(defn- get-file-media-object-nrefs
+ [conn id]
+ (-> (db/exec-one! conn [sql:get-file-media-object-nrefs id id])
+ (get :nrefs)))
+
+
+(def ^:private sql:get-profile-nrefs
+ "SELECT ((SELECT count(*) FROM profile WHERE photo_id = ?) +
+ (SELECT count(*) FROM team WHERE photo_id = ?)) AS nrefs")
+
+(defn- get-profile-nrefs
+ [conn id]
+ (-> (db/exec-one! conn [sql:get-profile-nrefs id id])
+ (get :nrefs)))
+
+
+(def ^:private
+ sql:get-file-object-thumbnail-nrefs
+ "SELECT (SELECT count(*) FROM file_tagged_object_thumbnail WHERE media_id = ?) AS nrefs")
+
+(defn- get-file-object-thumbnails
+ [conn id]
+ (-> (db/exec-one! conn [sql:get-file-object-thumbnail-nrefs id])
+ (get :nrefs)))
+
+
+(def ^:private
+ sql:get-file-thumbnail-nrefs
+ "SELECT (SELECT count(*) FROM file_thumbnail WHERE media_id = ?) AS nrefs")
+
+(defn- get-file-thumbnails
+ [conn id]
+ (-> (db/exec-one! conn [sql:get-file-thumbnail-nrefs id])
+ (get :nrefs)))
+
+
+(def ^:private sql:mark-freeze-in-bulk
+ "UPDATE storage_object
+ SET touched_at = NULL
+ WHERE id = ANY(?::uuid[])")
+
+(defn- mark-freeze-in-bulk!
+ [conn ids]
+ (let [ids (db/create-array conn "uuid" ids)]
+ (db/exec-one! conn [sql:mark-freeze-in-bulk ids])))
+
+
+(def ^:private sql:mark-delete-in-bulk
+ "UPDATE storage_object
+ SET deleted_at = now(),
+ touched_at = NULL
+ WHERE id = ANY(?::uuid[])")
+
+(defn- mark-delete-in-bulk!
+ [conn ids]
+ (let [ids (db/create-array conn "uuid" ids)]
+ (db/exec-one! conn [sql:mark-delete-in-bulk ids])))
+
+;; NOTE: A getter that retrieves the key which will be used for group
+;; ids; previously we have no value, then we introduced the
+;; `:reference` prop, and then it is renamed to `:bucket` and now is
+;; string instead. This is implemented in this way for backward
+;; comaptibilty.
+
+;; NOTE: we use the "file-media-object" as default value for
+;; backward compatibility because when we deploy it we can
+;; have old backend instances running in the same time as
+;; the new one and we can still have storage-objects created
+;; without bucket value. And we know that if it does not
+;; have value, it means :file-media-object.
+
+(defn- lookup-bucket
+ [{:keys [metadata]}]
+ (or (some-> metadata :bucket)
+ (some-> metadata :reference d/name)
+ "file-media-object"))
+
+(defn- process-objects!
+ [conn get-fn ids bucket]
+ (loop [to-freeze #{}
+ to-delete #{}
+ ids (seq ids)]
+ (if-let [id (first ids)]
+ (let [nrefs (get-fn conn id)]
+ (if (pos? nrefs)
+ (do
+ (l/debug :hint "processing object"
+ :id (str id)
+ :status "freeze"
+ :bucket bucket :refs nrefs)
+ (recur (conj to-freeze id) to-delete (rest ids)))
+ (do
+ (l/debug :hint "processing object"
+ :id (str id)
+ :status "delete"
+ :bucket bucket :refs nrefs)
+ (recur to-freeze (conj to-delete id) (rest ids)))))
+ (do
+ (some->> (seq to-freeze) (mark-freeze-in-bulk! conn))
+ (some->> (seq to-delete) (mark-delete-in-bulk! conn))
+ [(count to-freeze) (count to-delete)]))))
+
+(defn- process-bucket!
+ [conn bucket ids]
+ (case bucket
+ "file-media-object" (process-objects! conn get-file-media-object-nrefs ids bucket)
+ "team-font-variant" (process-objects! conn get-team-font-variant-nrefs ids bucket)
+ "file-object-thumbnail" (process-objects! conn get-file-object-thumbnails ids bucket)
+ "file-thumbnail" (process-objects! conn get-file-thumbnails ids bucket)
+ "profile" (process-objects! conn get-profile-nrefs ids bucket)
+ (ex/raise :type :internal
+ :code :unexpected-unknown-reference
+ :hint (dm/fmt "unknown reference %" bucket))))
+
+
+(def ^:private
+ sql:get-touched-storage-objects
+ "SELECT so.*
+ FROM storage_object AS so
+ WHERE so.touched_at IS NOT NULL
+ ORDER BY touched_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
+
+(defn- group-by-bucket
+ [row]
+ (d/group-by lookup-bucket :id #{} row))
+
+(defn- get-buckets
+ [conn]
+ (sequence
+ (comp (map impl/decode-row)
+ (partition-all 25)
+ (mapcat group-by-bucket))
+ (db/cursor conn sql:get-touched-storage-objects)))
+
+(defn- process-touched!
+ [{:keys [::db/conn]}]
+ (loop [buckets (get-buckets conn)
+ freezed 0
+ deleted 0]
+ (if-let [[bucket ids] (first buckets)]
+ (let [[nfo ndo] (process-bucket! conn bucket ids)]
+ (recur (rest buckets)
+ (+ freezed nfo)
+ (+ deleted ndo)))
+ (do
+ (l/inf :hint "task finished"
+ :to-freeze freezed
+ :to-delete deleted)
+
+ {:freeze freezed :delete deleted}))))
+
+(defmethod ig/pre-init-spec ::handler [_]
+ (s/keys :req [::db/pool]))
+
+(defmethod ig/init-key ::handler
+ [_ cfg]
+ (fn [_]
+ (db/tx-run! cfg process-touched!)))
+
diff --git a/backend/src/app/storage/impl.clj b/backend/src/app/storage/impl.clj
index 9dc7facc14..156d86b872 100644
--- a/backend/src/app/storage/impl.clj
+++ b/backend/src/app/storage/impl.clj
@@ -9,7 +9,7 @@
(:require
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
- [app.db :as-alias db]
+ [app.db :as db]
[app.storage :as-alias sto]
[buddy.core.codecs :as bc]
[buddy.core.hash :as bh]
@@ -22,6 +22,13 @@
java.nio.file.Path
java.util.UUID))
+(defn decode-row
+ "Decode the storage-object row fields"
+ [{:keys [metadata] :as row}]
+ (cond-> row
+ (some? metadata)
+ (assoc :metadata (db/decode-transit-pgobject metadata))))
+
;; --- API Definition
(defmulti put-object (fn [cfg _ _] (::sto/type cfg)))
diff --git a/backend/src/app/storage/s3.clj b/backend/src/app/storage/s3.clj
index 3800be401d..e019ad2676 100644
--- a/backend/src/app/storage/s3.clj
+++ b/backend/src/app/storage/s3.clj
@@ -39,6 +39,7 @@
software.amazon.awssdk.core.async.AsyncRequestBody
software.amazon.awssdk.core.async.AsyncResponseTransformer
software.amazon.awssdk.core.client.config.ClientAsyncConfiguration
+ software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption
software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient
software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup
software.amazon.awssdk.regions.Region
@@ -169,32 +170,34 @@
(defn- build-s3-client
[{:keys [::region ::endpoint ::io-threads]}]
- (let [aconfig (-> (ClientAsyncConfiguration/builder)
- (.build))
+ (let [executor (px/resolve-executor :virtual)
+ aconfig (-> (ClientAsyncConfiguration/builder)
+ (.advancedOption SdkAdvancedAsyncClientOption/FUTURE_COMPLETION_EXECUTOR executor)
+ (.build))
- sconfig (-> (S3Configuration/builder)
- (cond-> (some? endpoint) (.pathStyleAccessEnabled true))
- (.build))
+ sconfig (-> (S3Configuration/builder)
+ (cond-> (some? endpoint) (.pathStyleAccessEnabled true))
+ (.build))
- thr-num (or io-threads (min 16 (px/get-available-processors)))
- hclient (-> (NettyNioAsyncHttpClient/builder)
- (.eventLoopGroupBuilder (-> (SdkEventLoopGroup/builder)
- (.numberOfThreads (int thr-num))))
- (.connectionAcquisitionTimeout default-timeout)
- (.connectionTimeout default-timeout)
- (.readTimeout default-timeout)
- (.writeTimeout default-timeout)
- (.build))
+ thr-num (or io-threads (min 16 (px/get-available-processors)))
+ hclient (-> (NettyNioAsyncHttpClient/builder)
+ (.eventLoopGroupBuilder (-> (SdkEventLoopGroup/builder)
+ (.numberOfThreads (int thr-num))))
+ (.connectionAcquisitionTimeout default-timeout)
+ (.connectionTimeout default-timeout)
+ (.readTimeout default-timeout)
+ (.writeTimeout default-timeout)
+ (.build))
- client (let [builder (S3AsyncClient/builder)
- builder (.serviceConfiguration ^S3AsyncClientBuilder builder ^S3Configuration sconfig)
- builder (.asyncConfiguration ^S3AsyncClientBuilder builder ^ClientAsyncConfiguration aconfig)
- builder (.httpClient ^S3AsyncClientBuilder builder ^NettyNioAsyncHttpClient hclient)
- builder (.region ^S3AsyncClientBuilder builder (lookup-region region))
- builder (cond-> ^S3AsyncClientBuilder builder
- (some? endpoint)
- (.endpointOverride (URI. endpoint)))]
- (.build ^S3AsyncClientBuilder builder))]
+ client (let [builder (S3AsyncClient/builder)
+ builder (.serviceConfiguration ^S3AsyncClientBuilder builder ^S3Configuration sconfig)
+ builder (.asyncConfiguration ^S3AsyncClientBuilder builder ^ClientAsyncConfiguration aconfig)
+ builder (.httpClient ^S3AsyncClientBuilder builder ^NettyNioAsyncHttpClient hclient)
+ builder (.region ^S3AsyncClientBuilder builder (lookup-region region))
+ builder (cond-> ^S3AsyncClientBuilder builder
+ (some? endpoint)
+ (.endpointOverride (URI. endpoint)))]
+ (.build ^S3AsyncClientBuilder builder))]
(reify
clojure.lang.IDeref
diff --git a/backend/src/app/svgo.clj b/backend/src/app/svgo.clj
new file mode 100644
index 0000000000..70d7c6b2b3
--- /dev/null
+++ b/backend/src/app/svgo.clj
@@ -0,0 +1,65 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; Copyright (c) KALEIDOS INC
+
+(ns app.svgo
+ "A SVG Optimizer service"
+ (:require
+ [app.common.data :as d]
+ [app.common.data.macros :as dm]
+ [app.common.jsrt :as jsrt]
+ [app.common.logging :as l]
+ [app.common.spec :as us]
+ [app.worker :as-alias wrk]
+ [clojure.spec.alpha :as s]
+ [integrant.core :as ig]
+ [promesa.exec :as px]
+ [promesa.exec.bulkhead :as bh]
+ [promesa.exec.semaphore :as ps]
+ [promesa.util :as pu]))
+
+(def ^:dynamic *semaphore*
+ "A dynamic variable that can optionally contain a traffic light to
+ appropriately delimit the use of resources, managed externally."
+ nil)
+
+(defn optimize
+ [system data]
+ (dm/assert! "expect data to be a string" (string? data))
+
+ (letfn [(optimize-fn [pool]
+ (jsrt/run! pool
+ (fn [context]
+ (jsrt/set! context "svgData" data)
+ (jsrt/eval! context "penpotSvgo.optimize(svgData, {plugins: ['safeAndFastPreset']})"))))]
+ (try
+ (some-> *semaphore* ps/acquire!)
+ (let [{:keys [::jsrt/pool ::wrk/executor]} (::optimizer system)]
+ (dm/assert! "expect optimizer instance" (jsrt/pool? pool))
+ (px/invoke! executor (partial optimize-fn pool)))
+ (finally
+ (some-> *semaphore* ps/release!)))))
+
+(s/def ::max-procs (s/nilable ::us/integer))
+
+(defmethod ig/pre-init-spec ::optimizer [_]
+ (s/keys :req [::wrk/executor ::max-procs]))
+
+(defmethod ig/prep-key ::optimizer
+ [_ cfg]
+ (merge {::max-procs 20} (d/without-nils cfg)))
+
+(defmethod ig/init-key ::optimizer
+ [_ {:keys [::wrk/executor ::max-procs]}]
+ (l/inf :hint "initializing svg optimizer pool" :max-procs max-procs)
+ (let [init (jsrt/resource->source "app/common/svg/optimizer.js")
+ executor (bh/create :type :executor :executor executor :permits max-procs)]
+ {::jsrt/pool (jsrt/pool :init init)
+ ::wrk/executor executor}))
+
+(defmethod ig/halt-key! ::optimizer
+ [_ {:keys [::jsrt/pool]}]
+ (l/info :hint "stopping svg optimizer pool")
+ (pu/close! pool))
diff --git a/backend/src/app/tasks/file_gc.clj b/backend/src/app/tasks/file_gc.clj
index 5e97bdabc0..dcb92a4570 100644
--- a/backend/src/app/tasks/file_gc.clj
+++ b/backend/src/app/tasks/file_gc.clj
@@ -10,7 +10,6 @@
file is eligible to be garbage collected after some period of
inactivity (the default threshold is 72h)."
(:require
- [app.common.data :as d]
[app.common.files.migrations :as pmg]
[app.common.logging :as l]
[app.common.thumbnails :as thc]
@@ -30,7 +29,7 @@
[integrant.core :as ig]))
(declare ^:private get-candidates)
-(declare ^:private process-file)
+(declare ^:private clean-file!)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HANDLER
@@ -44,67 +43,61 @@
(assoc cfg ::min-age cf/deletion-delay))
(defmethod ig/init-key ::handler
- [_ {:keys [::db/pool] :as cfg}]
+ [_ cfg]
(fn [{:keys [file-id] :as params}]
+ (db/tx-run! cfg
+ (fn [{:keys [::db/conn] :as cfg}]
+ (let [min-age (dt/duration (or (:min-age params) (::min-age cfg)))
+ cfg (-> cfg
+ (update ::sto/storage media/configure-assets-storage conn)
+ (assoc ::file-id file-id)
+ (assoc ::min-age min-age))
- (db/with-atomic [conn pool]
- (let [min-age (dt/duration (or (:min-age params) (::min-age cfg)))
- cfg (-> cfg
- (update ::sto/storage media/configure-assets-storage conn)
- (assoc ::db/conn conn)
- (assoc ::file-id file-id)
- (assoc ::min-age min-age))
+ total (reduce (fn [total file]
+ (clean-file! cfg file)
+ (inc total))
+ 0
+ (get-candidates cfg))]
- total (reduce (fn [total file]
- (process-file cfg file)
- (inc total))
- 0
- (get-candidates cfg))]
+ (l/inf :hint "task finished"
+ :min-age (dt/format-duration min-age)
+ :processed total)
- (l/info :hint "task finished" :min-age (dt/format-duration min-age) :processed total)
+ ;; Allow optional rollback passed by params
+ (when (:rollback? params)
+ (db/rollback! conn))
- ;; Allow optional rollback passed by params
- (when (:rollback? params)
- (db/rollback! conn))
-
- {:processed total}))))
+ {:processed total})))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IMPL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ^:private
- sql:get-candidates-chunk
- "select f.id,
+ sql:get-candidates
+ "SELECT f.id,
f.data,
f.revn,
f.features,
f.modified_at
- from file as f
- where f.has_media_trimmed is false
- and f.modified_at < now() - ?::interval
- and f.modified_at < ?
- order by f.modified_at desc
- limit 1
- for update skip locked")
+ FROM file AS f
+ WHERE f.has_media_trimmed IS false
+ AND f.modified_at < now() - ?::interval
+ ORDER BY f.modified_at DESC
+ FOR UPDATE
+ SKIP LOCKED")
(defn- get-candidates
[{:keys [::db/conn ::min-age ::file-id]}]
(if (uuid? file-id)
(do
- (l/warn :hint "explicit file id passed on params" :file-id file-id)
+ (l/warn :hint "explicit file id passed on params" :file-id (str file-id))
(->> (db/query conn :file {:id file-id})
(map #(update % :features db/decode-pgarray #{}))))
- (let [interval (db/interval min-age)
- get-chunk (fn [cursor]
- (let [rows (db/exec! conn [sql:get-candidates-chunk interval cursor])]
- [(some->> rows peek :modified-at)
- (map #(update % :features db/decode-pgarray #{}) rows)]))]
- (d/iteration get-chunk
- :vf second
- :kf first
- :initk (dt/now)))))
+ (let [min-age (db/interval min-age)]
+ (->> (db/cursor conn [sql:get-candidates min-age] {:chunk-size 1})
+ (map #(update % :features db/decode-pgarray #{}))))))
(defn collect-used-media
"Given a fdata (file data), returns all media references."
@@ -134,101 +127,93 @@
(into xform pages)
(into (keys (:media data))))))
+
+(def ^:private sql:mark-file-media-object-deleted
+ "UPDATE file_media_object
+ SET deleted_at = now()
+ WHERE file_id = ? AND id != ALL(?::uuid[])
+ RETURNING id")
+
(defn- clean-file-media!
"Performs the garbage collection of file media objects."
[conn file-id data]
(let [used (collect-used-media data)
- unused (->> (db/query conn :file-media-object {:file-id file-id})
- (remove #(contains? used (:id %))))]
+ ids (db/create-array conn "uuid" used)
+ unused (->> (db/exec! conn [sql:mark-file-media-object-deleted file-id ids])
+ (into #{} (map :id)))]
- (doseq [mobj unused]
- (l/dbg :hint "delete file media object"
- :id (:id mobj)
- :media-id (:media-id mobj)
- :thumbnail-id (:thumbnail-id mobj))
+ (doseq [id unused]
+ (l/trc :hint "mark deleted"
+ :rel "file-media-object"
+ :id (str id)
+ :file-id (str file-id)))
- ;; NOTE: deleting the file-media-object in the database
- ;; automatically marks as touched the referenced storage
- ;; objects. The touch mechanism is needed because many files can
- ;; point to the same storage objects and we can't just delete
- ;; them.
- (db/delete! conn :file-media-object {:id (:id mobj)}))))
+ (count unused)))
+
+
+(def ^:private sql:mark-file-object-thumbnails-deleted
+ "UPDATE file_tagged_object_thumbnail
+ SET deleted_at = now()
+ WHERE file_id = ? AND object_id != ALL(?::text[])
+ RETURNING object_id")
(defn- clean-file-object-thumbnails!
- [{:keys [::db/conn ::sto/storage]} file-id data]
- (let [stored (->> (db/query conn :file-tagged-object-thumbnail
- {:file-id file-id}
- {:columns [:object-id]})
- (into #{} (map :object-id)))
+ [{:keys [::db/conn]} file-id data]
+ (let [using (->> (vals (:pages-index data))
+ (into #{} (comp
+ (mapcat (fn [{:keys [id objects]}]
+ (->> (ctt/get-frames objects)
+ (map #(assoc % :page-id id)))))
+ (mapcat (fn [{:keys [id page-id]}]
+ (list
+ (thc/fmt-object-id file-id page-id id "frame")
+ (thc/fmt-object-id file-id page-id id "component")))))))
- using (into #{}
- (comp
- (mapcat (fn [{:keys [id objects]}]
- (->> (ctt/get-frames objects)
- (map #(assoc % :page-id id)))))
- (mapcat (fn [{:keys [id page-id]}]
- (list
- (thc/fmt-object-id file-id page-id id "frame")
- (thc/fmt-object-id file-id page-id id "component")))))
+ ids (db/create-array conn "text" using)
+ unused (->> (db/exec! conn [sql:mark-file-object-thumbnails-deleted file-id ids])
+ (into #{} (map :object-id)))]
- (vals (:pages-index data)))
+ (doseq [object-id unused]
+ (l/trc :hint "mark deleted"
+ :rel "file-tagged-object-thumbnail"
+ :object-id object-id
+ :file-id (str file-id)))
- unused (set/difference stored using)]
+ (count unused)))
- (when (seq unused)
- (let [sql (str "delete from file_tagged_object_thumbnail "
- " where file_id=? and object_id=ANY(?)"
- " returning media_id")
- res (db/exec! conn [sql file-id (db/create-array conn "text" unused)])]
- (l/dbg :hint "delete file object thumbnails"
- :file-id (str file-id)
- :total (count res))
-
- (doseq [media-id (into #{} (keep :media-id) res)]
- ;; Mark as deleted the storage object related with the
- ;; photo-id field.
- (l/trc :hint "touch file object thumbnail storage object" :id (str media-id))
- (sto/touch-object! storage media-id))))))
+(def ^:private sql:mark-file-thumbnails-deleted
+ "UPDATE file_thumbnail
+ SET deleted_at = now()
+ WHERE file_id = ? AND revn < ?
+ RETURNING revn")
(defn- clean-file-thumbnails!
- [{:keys [::db/conn ::sto/storage]} file-id revn]
- (let [sql (str "delete from file_thumbnail "
- " where file_id=? and revn < ? "
- " returning media_id")
- res (db/exec! conn [sql file-id revn])]
+ [{:keys [::db/conn]} file-id revn]
+ (let [unused (->> (db/exec! conn [sql:mark-file-thumbnails-deleted file-id revn])
+ (into #{} (map :revn)))]
- (when (seq res)
- (l/dbg :hint "delete file thumbnails"
- :file-id (str file-id)
- :total (count res))
+ (doseq [revn unused]
+ (l/trc :hint "mark deleted"
+ :rel "file-thumbnail"
+ :revn revn
+ :file-id (str file-id)))
- (doseq [media-id (into #{} (keep :media-id) res)]
- ;; Mark as deleted the storage object related with the
- ;; media-id field.
- (l/trc :hint "delete file thumbnail storage object" :id (str media-id))
- (sto/del-object! storage media-id)))))
+ (count unused)))
-(def ^:private
- sql:get-files-for-library
- "select f.data, f.modified_at
- from file as f
- left join file_library_rel as fl on (fl.file_id = f.id)
- where fl.library_file_id = ?
- and f.modified_at < ?
- and f.deleted_at is null
- order by f.modified_at desc
- limit 1")
+
+(def ^:private sql:get-files-for-library
+ "SELECT f.id, f.data, f.modified_at
+ FROM file AS f
+ LEFT JOIN file_library_rel AS fl ON (fl.file_id = f.id)
+ WHERE fl.library_file_id = ?
+ AND f.deleted_at IS null
+ ORDER BY f.modified_at ASC")
(defn- clean-deleted-components!
"Performs the garbage collection of unreferenced deleted components."
- [conn file-id data]
- (letfn [(get-files-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-files-for-library file-id cursor])]
- [(some-> rows peek :modified-at)
- (map (comp blob/decode :data) rows)]))
-
- (get-used-components [fdata components]
+ [{:keys [::db/conn] :as cfg} file-id data]
+ (letfn [(get-used-components [fdata components]
;; Find which of the components are used in the file.
(into #{}
(filter #(ctf/used-in? fdata file-id % :component))
@@ -246,65 +231,85 @@
files-data))]
(let [deleted (into #{} (ctkl/deleted-components-seq data))
- unused (->> (d/iteration get-files-chunk :vf second :kf first :initk (dt/now))
+ unused (->> (db/cursor conn [sql:get-files-for-library file-id] {:chunk-size 1})
+ (map (fn [{:keys [id data] :as file}]
+ (binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)]
+ (-> (blob/decode data)
+ (feat.fdata/process-pointers deref)))))
(cons data)
(get-unused-components deleted)
(mapv :id))]
- (when (seq unused)
- (l/dbg :hint "clean deleted components" :total (count unused))
+ (doseq [id unused]
+ (l/trc :hint "delete component" :component-id (str id) :file-id (str file-id)))
- (let [data (reduce ctkl/delete-component data unused)]
- (db/update! conn :file
- {:data (blob/encode data)}
- {:id file-id}))))))
+
+ (when-let [data (some->> (seq unused)
+ (reduce ctkl/delete-component data)
+ (blob/encode))]
+ (db/update! conn :file
+ {:data data}
+ {:id file-id}))
+
+ (count unused))))
+
+
+(def ^:private sql:get-changes
+ "SELECT id, data FROM file_change
+ WHERE file_id = ? AND data IS NOT NULL
+ ORDER BY created_at ASC")
+
+(def ^:private sql:mark-deleted-data-fragments
+ "UPDATE file_data_fragment
+ SET deleted_at = now()
+ WHERE file_id = ?
+ AND id != ALL(?::uuid[])
+ RETURNING id")
(defn- clean-data-fragments!
[conn file-id data]
- (letfn [(get-pointers-chunk [cursor]
- (let [sql (str "select id, data, created_at "
- " from file_change "
- " where file_id = ? "
- " and data is not null "
- " and created_at < ? "
- " order by created_at desc "
- " limit 1;")
- rows (db/exec! conn [sql file-id cursor])]
- [(some-> rows peek :created-at)
- (mapcat (comp feat.fdata/get-used-pointer-ids blob/decode :data) rows)]))]
+ (let [used (->> (db/cursor conn [sql:get-changes file-id])
+ (into (feat.fdata/get-used-pointer-ids data)
+ (comp (map :data)
+ (map blob/decode)
+ (mapcat feat.fdata/get-used-pointer-ids))))
- (let [used (into (feat.fdata/get-used-pointer-ids data)
- (d/iteration get-pointers-chunk
- :vf second
- :kf first
- :initk (dt/now)))
+ unused (let [ids (db/create-array conn "uuid" used)]
+ (->> (db/exec! conn [sql:mark-deleted-data-fragments file-id ids])
+ (into #{} (map :id))))]
- sql (str "select id from file_data_fragment "
- " where file_id = ? AND id != ALL(?::uuid[])")
- used (db/create-array conn "uuid" used)
- rows (db/exec! conn [sql file-id used])]
+ (doseq [id unused]
+ (l/trc :hint "mark deleted"
+ :rel "file-data-fragment"
+ :id (str id)
+ :file-id (str file-id)))
- (doseq [fragment-id (map :id rows)]
- (l/trc :hint "remove unused file data fragment" :id (str fragment-id))
- (db/delete! conn :file-data-fragment {:id fragment-id :file-id file-id})))))
+ (count unused)))
-(defn- process-file
- [{:keys [::db/conn] :as cfg} {:keys [id data revn modified-at features] :as file}]
- (l/dbg :hint "processing file" :file-id (str id) :modified-at modified-at)
+
+(defn- clean-file!
+ [{:keys [::db/conn] :as cfg} {:keys [id data revn modified-at] :as file}]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)
pmap/*tracked* (pmap/create-tracked)]
(let [data (-> (blob/decode data)
(assoc :id id)
- (pmg/migrate-data))]
+ (pmg/migrate-data))
- (clean-file-media! conn id data)
- (clean-file-object-thumbnails! cfg id data)
- (clean-file-thumbnails! cfg id revn)
- (clean-deleted-components! conn id data)
+ nfm (clean-file-media! conn id data)
+ nfot (clean-file-object-thumbnails! cfg id data)
+ nft (clean-file-thumbnails! cfg id revn)
+ nc (clean-deleted-components! cfg id data)
+ ndf (clean-data-fragments! conn id data)]
- (when (contains? features "fdata/pointer-map")
- (clean-data-fragments! conn id data))
+ (l/dbg :hint "file clened"
+ :file-id (str id)
+ :modified-at (dt/format-instant modified-at)
+ :media-objects nfm
+ :thumbnails nft
+ :object-thumbnails nfot
+ :components nc
+ :data-fragments ndf)
;; Mark file as trimmed
(db/update! conn :file
diff --git a/backend/src/app/tasks/objects_gc.clj b/backend/src/app/tasks/objects_gc.clj
index 83b86dcdea..c5e74ce3ac 100644
--- a/backend/src/app/tasks/objects_gc.clj
+++ b/backend/src/app/tasks/objects_gc.clj
@@ -8,7 +8,6 @@
"A maintenance task that performs a general purpose garbage collection
of deleted or unreachable objects."
(:require
- [app.common.data :as d]
[app.common.logging :as l]
[app.config :as cf]
[app.db :as db]
@@ -18,12 +17,15 @@
[clojure.spec.alpha :as s]
[integrant.core :as ig]))
-(declare ^:private delete-profiles!)
-(declare ^:private delete-teams!)
-(declare ^:private delete-fonts!)
-(declare ^:private delete-projects!)
+(declare ^:private delete-file-data-fragments!)
+(declare ^:private delete-file-media-objects!)
+(declare ^:private delete-file-object-thumbnails!)
+(declare ^:private delete-file-thumbnails!)
(declare ^:private delete-files!)
-(declare ^:private delete-orphan-teams!)
+(declare ^:private delete-fonts!)
+(declare ^:private delete-profiles!)
+(declare ^:private delete-projects!)
+(declare ^:private delete-teams!)
(defmethod ig/pre-init-spec ::handler [_]
(s/keys :req [::db/pool ::sto/storage]))
@@ -33,211 +35,306 @@
(assoc cfg ::min-age cf/deletion-delay))
(defmethod ig/init-key ::handler
- [_ {:keys [::db/pool ::sto/storage] :as cfg}]
+ [_ cfg]
(fn [params]
- (db/with-atomic [conn pool]
- (let [min-age (or (:min-age params) (::min-age cfg))
- _ (l/info :hint "gc started"
- :min-age (dt/format-duration min-age)
- :rollback? (boolean (:rollback? params)))
+ (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
+ ;; Disable deletion protection for the current transaction
+ (db/exec-one! conn ["SET LOCAL rules.deletion_protection TO off"])
+ (db/exec-one! conn ["SET CONSTRAINTS ALL DEFERRED"])
- storage (media/configure-assets-storage storage conn)
- cfg (-> cfg
- (assoc ::min-age (db/interval min-age))
- (assoc ::conn conn)
- (assoc ::storage storage))
+ (let [min-age (dt/duration (or (:min-age params) (::min-age cfg)))
+ cfg (-> cfg
+ (assoc ::min-age (db/interval min-age))
+ (update ::sto/storage media/configure-assets-storage conn))
- htotal (+ (delete-profiles! cfg)
- (delete-teams! cfg)
- (delete-projects! cfg)
- (delete-files! cfg)
- (delete-fonts! cfg))
- stotal (delete-orphan-teams! cfg)]
+ total (reduce + 0
+ [(delete-profiles! cfg)
+ (delete-teams! cfg)
+ (delete-fonts! cfg)
+ (delete-projects! cfg)
+ (delete-files! cfg)
+ (delete-file-thumbnails! cfg)
+ (delete-file-object-thumbnails! cfg)
+ (delete-file-data-fragments! cfg)
+ (delete-file-media-objects! cfg)])]
- (l/info :hint "gc finished"
- :deleted htotal
- :orphans stotal
- :rollback? (boolean (:rollback? params)))
+ (l/info :hint "task finished"
+ :deleted total
+ :rollback? (boolean (:rollback? params)))
- (when (:rollback? params)
- (db/rollback! conn))
+ (when (:rollback? params)
+ (db/rollback! conn))
- {:processed (+ stotal htotal)
- :orphans stotal}))))
+ {:processed total})))))
-(def ^:private sql:get-profiles-chunk
- "select id, photo_id, created_at from profile
- where deleted_at is not null
- and deleted_at < now() - ?::interval
- and created_at < ?
- order by created_at desc
- limit 10
- for update skip locked")
+(def ^:private sql:get-profiles
+ "SELECT id, photo_id FROM profile
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
(defn- delete-profiles!
- [{:keys [::conn ::min-age ::storage] :as cfg}]
- (letfn [(get-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-profiles-chunk min-age cursor])]
- [(some->> rows peek :created-at) rows]))
+ [{:keys [::db/conn ::min-age ::sto/storage] :as cfg}]
+ (->> (db/cursor conn [sql:get-profiles min-age])
+ (reduce (fn [total {:keys [id photo-id]}]
+ (l/trc :hint "permanently delete" :rel "profile" :id (str id))
- (process-profile [total {:keys [id photo-id]}]
- (l/debug :hint "permanently delete profile" :id (str id))
+ ;; Mark as deleted the storage object
+ (some->> photo-id (sto/touch-object! storage))
- ;; Mark as deleted the storage object related with the
- ;; photo-id field.
- (some->> photo-id (sto/touch-object! storage))
+ ;; And finally, permanently delete the profile. The
+ ;; relevant objects will be deleted using DELETE
+ ;; CASCADE database triggers. This may leave orphan
+ ;; teams, but there is a special task for deleting
+ ;; orphaned teams.
+ (db/delete! conn :profile {:id id})
- ;; And finally, permanently delete the profile.
- (db/delete! conn :profile {:id id})
+ (inc total))
+ 0)))
- (inc total))]
-
- (->> (d/iteration get-chunk :vf second :kf first :initk (dt/now))
- (reduce process-profile 0))))
-
-(def ^:private sql:get-teams-chunk
- "select id, photo_id, created_at from team
- where deleted_at is not null
- and deleted_at < now() - ?::interval
- and created_at < ?
- order by created_at desc
- limit 10
- for update skip locked")
+(def ^:private sql:get-teams
+ "SELECT deleted_at, id, photo_id FROM team
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
(defn- delete-teams!
- [{:keys [::conn ::min-age ::storage] :as cfg}]
- (letfn [(get-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-teams-chunk min-age cursor])]
- [(some->> rows peek :created-at) rows]))
+ [{:keys [::db/conn ::min-age ::sto/storage] :as cfg}]
- (process-team [total {:keys [id photo-id]}]
- (l/debug :hint "permanently delete team" :id (str id))
+ (->> (db/cursor conn [sql:get-teams min-age])
+ (reduce (fn [total {:keys [id photo-id deleted-at]}]
+ (l/trc :hint "permanently delete"
+ :rel "team"
+ :id (str id)
+ :deleted-at (dt/format-instant deleted-at))
- ;; Mark as deleted the storage object related with the
- ;; photo-id field.
- (some->> photo-id (sto/touch-object! storage))
+ ;; Mark as deleted the storage object
+ (some->> photo-id (sto/touch-object! storage))
- ;; And finally, permanently delete the team.
- (db/delete! conn :team {:id id})
+ ;; And finally, permanently delete the team.
+ (db/delete! conn :team {:id id})
- (inc total))]
+ ;; Mark for deletion in cascade
+ (db/update! conn :team-font-variant
+ {:deleted-at deleted-at}
+ {:team-id id})
- (->> (d/iteration get-chunk :vf second :kf first :initk (dt/now))
- (reduce process-team 0))))
+ (db/update! conn :project
+ {:deleted-at deleted-at}
+ {:team-id id})
-(def ^:private sql:get-orphan-teams-chunk
- "select t.id, t.created_at
- from team as t
- left join team_profile_rel as tpr
- on (t.id = tpr.team_id)
- where tpr.profile_id is null
- and t.created_at < ?
- order by t.created_at desc
- limit 10
- for update of t skip locked;")
+ (inc total))
+ 0)))
-(defn- delete-orphan-teams!
- "Find all orphan teams (with no members and mark them for
- deletion (soft delete)."
- [{:keys [::conn] :as cfg}]
- (letfn [(get-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-orphan-teams-chunk cursor])]
- [(some->> rows peek :created-at) rows]))
-
- (process-team [total {:keys [id]}]
- (let [result (db/update! conn :team
- {:deleted-at (dt/now)}
- {:id id :deleted-at nil}
- {::db/return-keys? false})
- count (db/get-update-count result)]
- (when (pos? count)
- (l/debug :hint "mark team for deletion" :id (str id)))
-
- (+ total count)))]
-
- (->> (d/iteration get-chunk :vf second :kf first :initk (dt/now))
- (reduce process-team 0))))
-
-(def ^:private sql:get-fonts-chunk
- "select id, created_at, woff1_file_id, woff2_file_id, otf_file_id, ttf_file_id
- from team_font_variant
- where deleted_at is not null
- and deleted_at < now() - ?::interval
- and created_at < ?
- order by created_at desc
- limit 10
- for update skip locked")
+(def ^:private sql:get-fonts
+ "SELECT id, team_id, deleted_at, woff1_file_id, woff2_file_id, otf_file_id, ttf_file_id
+ FROM team_font_variant
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
(defn- delete-fonts!
- [{:keys [::conn ::min-age ::storage] :as cfg}]
- (letfn [(get-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-fonts-chunk min-age cursor])]
- [(some->> rows peek :created-at) rows]))
+ [{:keys [::db/conn ::min-age ::sto/storage] :as cfg}]
+ (->> (db/cursor conn [sql:get-fonts min-age])
+ (reduce (fn [total {:keys [id team-id deleted-at] :as font}]
+ (l/trc :hint "permanently delete"
+ :rel "team-font-variant"
+ :id (str id)
+ :team-id (str team-id)
+ :deleted-at (dt/format-instant deleted-at))
- (process-font [total {:keys [id] :as font}]
- (l/debug :hint "permanently delete font variant" :id (str id))
+ ;; Mark as deleted the all related storage objects
+ (some->> (:woff1-file-id font) (sto/touch-object! storage))
+ (some->> (:woff2-file-id font) (sto/touch-object! storage))
+ (some->> (:otf-file-id font) (sto/touch-object! storage))
+ (some->> (:ttf-file-id font) (sto/touch-object! storage))
- ;; Mark as deleted the all related storage objects
- (some->> (:woff1-file-id font) (sto/touch-object! storage))
- (some->> (:woff2-file-id font) (sto/touch-object! storage))
- (some->> (:otf-file-id font) (sto/touch-object! storage))
- (some->> (:ttf-file-id font) (sto/touch-object! storage))
+ ;; And finally, permanently delete the team font variant
+ (db/delete! conn :team-font-variant {:id id})
- ;; And finally, permanently delete the team font variant
- (db/delete! conn :team-font-variant {:id id})
+ (inc total))
+ 0)))
- (inc total))]
-
- (->> (d/iteration get-chunk :vf second :kf first :initk (dt/now))
- (reduce process-font 0))))
-
-(def ^:private sql:get-projects-chunk
- "select id, created_at
- from project
- where deleted_at is not null
- and deleted_at < now() - ?::interval
- and created_at < ?
- order by created_at desc
- limit 10
- for update skip locked")
+(def ^:private sql:get-projects
+ "SELECT id, deleted_at, team_id
+ FROM project
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
(defn- delete-projects!
- [{:keys [::conn ::min-age] :as cfg}]
- (letfn [(get-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-projects-chunk min-age cursor])]
- [(some->> rows peek :created-at) rows]))
+ [{:keys [::db/conn ::min-age] :as cfg}]
+ (->> (db/cursor conn [sql:get-projects min-age])
+ (reduce (fn [total {:keys [id team-id deleted-at]}]
+ (l/trc :hint "permanently delete"
+ :rel "project"
+ :id (str id)
+ :team-id (str team-id)
+ :deleted-at (dt/format-instant deleted-at))
- (process-project [total {:keys [id]}]
- (l/debug :hint "permanently delete project" :id (str id))
- ;; And finally, permanently delete the project.
- (db/delete! conn :project {:id id})
+ ;; And finally, permanently delete the project.
+ (db/delete! conn :project {:id id})
- (inc total))]
+ ;; Mark files to be deleted
+ (db/update! conn :file
+ {:deleted-at deleted-at}
+ {:project-id id})
- (->> (d/iteration get-chunk :vf second :kf first :initk (dt/now))
- (reduce process-project 0))))
+ (inc total))
+ 0)))
-(def ^:private sql:get-files-chunk
- "select id, created_at
- from file
- where deleted_at is not null
- and deleted_at < now() - ?::interval
- and created_at < ?
- order by created_at desc
- limit 10
- for update skip locked")
+(def ^:private sql:get-files
+ "SELECT id, deleted_at, project_id
+ FROM file
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
(defn- delete-files!
- [{:keys [::conn ::min-age] :as cfg}]
- (letfn [(get-chunk [cursor]
- (let [rows (db/exec! conn [sql:get-files-chunk min-age cursor])]
- [(some->> rows peek :created-at) rows]))
+ [{:keys [::db/conn ::min-age] :as cfg}]
+ (->> (db/cursor conn [sql:get-files min-age])
+ (reduce (fn [total {:keys [id deleted-at project-id]}]
+ (l/trc :hint "permanently delete"
+ :rel "file"
+ :id (str id)
+ :project-id (str project-id)
+ :deleted-at (dt/format-instant deleted-at))
- (process-file [total {:keys [id]}]
- (l/debug :hint "permanently delete file" :id (str id))
- ;; And finally, permanently delete the file.
- (db/delete! conn :file {:id id})
- (inc total))]
+ ;; And finally, permanently delete the file.
+ (db/delete! conn :file {:id id})
- (->> (d/iteration get-chunk :vf second :kf first :initk (dt/now))
- (reduce process-file 0))))
+ ;; Mark file media objects to be deleted
+ (db/update! conn :file-media-object
+ {:deleted-at deleted-at}
+ {:file-id id})
+
+ ;; Mark thumbnails to be deleted
+ (db/update! conn :file-thumbnail
+ {:deleted-at deleted-at}
+ {:file-id id})
+
+ (db/update! conn :file-tagged-object-thumbnail
+ {:deleted-at deleted-at}
+ {:file-id id})
+
+ (inc total))
+ 0)))
+
+
+(def ^:private sql:get-file-thumbnails
+ "SELECT file_id, revn, media_id, deleted_at
+ FROM file_thumbnail
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
+
+(defn delete-file-thumbnails!
+ [{:keys [::db/conn ::min-age ::sto/storage] :as cfg}]
+ (->> (db/cursor conn [sql:get-file-thumbnails min-age])
+ (reduce (fn [total {:keys [file-id revn media-id deleted-at]}]
+ (l/trc :hint "permanently delete"
+ :rel "file-thumbnail"
+ :file-id (str file-id)
+ :revn revn
+ :deleted-at (dt/format-instant deleted-at))
+
+ ;; Mark as deleted the storage object
+ (some->> media-id (sto/touch-object! storage))
+
+ ;; And finally, permanently delete the object
+ (db/delete! conn :file-thumbnail {:file-id file-id :revn revn})
+
+ (inc total))
+ 0)))
+
+(def ^:private sql:get-file-object-thumbnails
+ "SELECT file_id, object_id, media_id, deleted_at
+ FROM file_tagged_object_thumbnail
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
+
+(defn delete-file-object-thumbnails!
+ [{:keys [::db/conn ::min-age ::sto/storage] :as cfg}]
+ (->> (db/cursor conn [sql:get-file-object-thumbnails min-age])
+ (reduce (fn [total {:keys [file-id object-id media-id deleted-at]}]
+ (l/trc :hint "permanently delete"
+ :rel "file-tagged-object-thumbnail"
+ :file-id (str file-id)
+ :object-id object-id
+ :deleted-at (dt/format-instant deleted-at))
+
+ ;; Mark as deleted the storage object
+ (some->> media-id (sto/touch-object! storage))
+
+ ;; And finally, permanently delete the object
+ (db/delete! conn :file-tagged-object-thumbnail {:file-id file-id :object-id object-id})
+
+ (inc total))
+ 0)))
+
+(def ^:private sql:get-file-data-fragments
+ "SELECT file_id, id, deleted_at
+ FROM file_data_fragment
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
+
+(defn- delete-file-data-fragments!
+ [{:keys [::db/conn ::min-age] :as cfg}]
+ (->> (db/cursor conn [sql:get-file-data-fragments min-age])
+ (reduce (fn [total {:keys [file-id id deleted-at]}]
+ (l/trc :hint "permanently delete"
+ :rel "file-data-fragment"
+ :id (str id)
+ :file-id (str file-id)
+ :deleted-at (dt/format-instant deleted-at))
+
+ (db/delete! conn :file-data-fragment {:file-id file-id :id id})
+
+ (inc total))
+ 0)))
+
+(def ^:private sql:get-file-media-objects
+ "SELECT id, file_id, media_id, thumbnail_id, deleted_at
+ FROM file_media_object
+ WHERE deleted_at IS NOT NULL
+ AND deleted_at < now() - ?::interval
+ ORDER BY deleted_at ASC
+ FOR UPDATE
+ SKIP LOCKED")
+
+(defn- delete-file-media-objects!
+ [{:keys [::db/conn ::min-age ::sto/storage] :as cfg}]
+ (->> (db/cursor conn [sql:get-file-media-objects min-age])
+ (reduce (fn [total {:keys [id file-id deleted-at] :as fmo}]
+ (l/trc :hint "permanently delete"
+ :rel "file-media-object"
+ :id (str id)
+ :file-id (str file-id)
+ :deleted-at (dt/format-instant deleted-at))
+
+ ;; Mark as deleted the all related storage objects
+ (some->> (:media-id fmo) (sto/touch-object! storage))
+ (some->> (:thumbnail-id fmo) (sto/touch-object! storage))
+
+ (db/delete! conn :file-media-object {:id id})
+
+ (inc total))
+ 0)))
diff --git a/backend/src/app/tasks/orphan_teams_gc.clj b/backend/src/app/tasks/orphan_teams_gc.clj
new file mode 100644
index 0000000000..c04123a831
--- /dev/null
+++ b/backend/src/app/tasks/orphan_teams_gc.clj
@@ -0,0 +1,59 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; Copyright (c) KALEIDOS INC
+
+(ns app.tasks.orphan-teams-gc
+ "A maintenance task that performs orphan teams GC."
+ (:require
+ [app.common.logging :as l]
+ [app.db :as db]
+ [app.util.time :as dt]
+ [clojure.spec.alpha :as s]
+ [integrant.core :as ig]))
+
+(declare ^:private delete-orphan-teams!)
+
+(defmethod ig/pre-init-spec ::handler [_]
+ (s/keys :req [::db/pool]))
+
+(defmethod ig/init-key ::handler
+ [_ cfg]
+ (fn [params]
+ (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
+ (l/inf :hint "gc started" :rollback? (boolean (:rollback? params)))
+ (let [total (delete-orphan-teams! cfg)]
+ (l/inf :hint "task finished"
+ :teams total
+ :rollback? (boolean (:rollback? params)))
+
+ (when (:rollback? params)
+ (db/rollback! conn))
+
+ {:processed total})))))
+
+(def ^:private sql:get-orphan-teams
+ "SELECT t.id
+ FROM team AS t
+ LEFT JOIN team_profile_rel AS tpr
+ ON (t.id = tpr.team_id)
+ WHERE tpr.profile_id IS NULL
+ AND t.deleted_at IS NULL
+ ORDER BY t.created_at ASC
+ FOR UPDATE OF t
+ SKIP LOCKED")
+
+(defn- delete-orphan-teams!
+ "Find all orphan teams (with no members) and mark them for
+ deletion (soft delete)."
+ [{:keys [::db/conn] :as cfg}]
+ (->> (db/cursor conn sql:get-orphan-teams)
+ (map :id)
+ (reduce (fn [total team-id]
+ (l/trc :hint "mark orphan team for deletion" :id (str team-id))
+ (db/update! conn :team
+ {:deleted-at (dt/now)}
+ {:id team-id})
+ (inc total))
+ 0)))
diff --git a/backend/src/app/worker.clj b/backend/src/app/worker.clj
index 0ab867971b..0e830ac9a3 100644
--- a/backend/src/app/worker.clj
+++ b/backend/src/app/worker.clj
@@ -42,8 +42,8 @@
(defmethod ig/init-key ::executor
[_ _]
- (let [factory (px/thread-factory :prefix "penpot/default/")
- executor (px/cached-executor :factory factory :keepalive 30000)]
+ (let [factory (px/thread-factory :prefix "penpot/default/")
+ executor (px/cached-executor :factory factory :keepalive 60000)]
(l/inf :hint "starting executor")
(reify
java.lang.AutoCloseable
diff --git a/backend/test/backend_tests/helpers.clj b/backend/test/backend_tests/helpers.clj
index 3fad161142..646905c515 100644
--- a/backend/test/backend_tests/helpers.clj
+++ b/backend/test/backend_tests/helpers.clj
@@ -175,12 +175,11 @@
" WHERE table_schema = 'public' "
" AND table_name != 'migrations';")]
(db/with-atomic [conn *pool*]
+ (db/exec-one! conn ["SET CONSTRAINTS ALL DEFERRED"])
+ (db/exec-one! conn ["SET LOCAL rules.deletion_protection TO off"])
(let [result (->> (db/exec! conn [sql])
(map :table-name)
- (remove #(= "task" %)))
- sql (str "TRUNCATE "
- (apply str (interpose ", " result))
- " CASCADE;")]
+ (remove #(= "task" %)))]
(doseq [table result]
(db/exec! conn [(str "delete from " table ";")]))))
@@ -433,11 +432,11 @@
(us/pretty-explain data))
(= :params-validation (:code data))
- (app.common.pprint/pprint
+ (println
(sm/humanize-explain (::sm/explain data)))
(= :data-validation (:code data))
- (app.common.pprint/pprint
+ (println
(sm/humanize-explain (::sm/explain data)))
(= :service-error (:type data))
@@ -512,6 +511,10 @@
[sql]
(db/exec! *pool* sql))
+(defn db-exec-one!
+ [sql]
+ (db/exec-one! *pool* sql))
+
(defn db-delete!
[& params]
(apply db/delete! *pool* params))
diff --git a/backend/test/backend_tests/rpc_file_test.clj b/backend/test/backend_tests/rpc_file_test.clj
index cbf96c2167..cbce720c56 100644
--- a/backend/test/backend_tests/rpc_file_test.clj
+++ b/backend/test/backend_tests/rpc_file_test.clj
@@ -149,7 +149,7 @@
shape-id (uuid/random)]
;; Preventive file-gc
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; Check the number of fragments before adding the page
@@ -175,7 +175,7 @@
(t/is (= 2 (count rows))))
;; The file-gc should remove unused fragments
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
@@ -203,7 +203,7 @@
(t/is (= 3 (count rows))))
;; The file-gc should remove unused fragments
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; Check the number of fragments; should be 3 because changes
@@ -220,12 +220,23 @@
;; The file-gc should remove fragments related to changes
;; snapshots previously deleted.
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; Check the number of fragments;
(let [rows (th/db-query :file-data-fragment {:file-id (:id file)})]
- (t/is (= 2 (count rows)))))))
+ ;; (pp/pprint rows)
+ (t/is (= 3 (count rows)))
+ (t/is (= 2 (count (remove (comp some? :deleted-at) rows)))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
+
+ (let [rows (th/db-query :file-data-fragment {:file-id (:id file)})]
+ (t/is (= 2 (count rows))))
+ )))
+
+
(t/deftest file-gc-task-with-thumbnails
(letfn [(add-file-media-object [& {:keys [profile-id file-id]}]
@@ -301,17 +312,16 @@
;; freeze because of the deduplication (we have uploaded 2 times
;; the same files).
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
(t/is (= 2 (:freeze res)))
(t/is (= 0 (:delete res))))
;; run the file-gc task immediately without forced min-age
- (let [res (th/run-task! "file-gc")]
+ (let [res (th/run-task! :file-gc)]
(t/is (= 0 (:processed res))))
;; run the task again
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; retrieve file and check trimmed attribute
@@ -319,8 +329,17 @@
(t/is (true? (:has-media-trimmed row))))
;; check file media objects
- (let [rows (th/db-exec! ["select * from file_media_object where file_id = ?" (:id file)])]
- (t/is (= 1 (count rows))))
+ (let [rows (th/db-query :file-media-object {:file-id (:id file)})]
+ (t/is (= 2 (count rows)))
+ (t/is (= 1 (count (remove (comp some? :deleted-at) rows)))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 2 (:processed res))))
+
+ ;; check file media objects
+ (let [rows (th/db-query :file-media-object {:file-id (:id file)})]
+ (t/is (= 1 (count rows)))
+ (t/is (= 1 (count (remove (comp some? :deleted-at) rows)))))
;; The underlying storage objects are still available.
(t/is (some? (sto/get-object storage (:media-id fmo2))))
@@ -340,15 +359,16 @@
;; Now, we have deleted the usage of pointers to the
;; file-media-objects, if we paste file-gc, they should be marked
;; as deleted.
- (let [task (:app.tasks.file-gc/handler th/*system*)
- res (task {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; Now that file-gc have deleted the file-media-object usage,
;; lets execute the touched-gc task, we should see that two of
;; them are marked to be deleted.
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
(t/is (= 0 (:freeze res)))
(t/is (= 2 (:delete res))))
@@ -457,11 +477,14 @@
:strokes [{:opacity 1 :stroke-image {:id (:id fmo5) :width 100 :height 100 :mtype "image/jpeg"}}]})}])
;; run the file-gc task immediately without forced min-age
- (let [res (th/run-task! "file-gc")]
+ (let [res (th/run-task! :file-gc)]
(t/is (= 0 (:processed res))))
;; run the task again
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; retrieve file and check trimmed attribute
@@ -494,15 +517,16 @@
;; Now, we have deleted the usage of pointers to the
;; file-media-objects, if we paste file-gc, they should be marked
;; as deleted.
- (let [task (:app.tasks.file-gc/handler th/*system*)
- res (task {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 5 (:processed res))))
+
;; Now that file-gc have deleted the file-media-object usage,
;; lets execute the touched-gc task, we should see that two of
;; them are marked to be deleted.
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
(t/is (= 0 (:freeze res)))
(t/is (= 2 (:delete res))))
@@ -515,7 +539,6 @@
(t/is (nil? (sto/get-object storage (:media-id fmo2))))
(t/is (nil? (sto/get-object storage (:media-id fmo1)))))))
-
(t/deftest file-gc-task-with-object-thumbnails
(letfn [(insert-file-object-thumbnail! [& {:keys [profile-id file-id page-id frame-id]}]
(let [object-id (thc/fmt-object-id file-id page-id frame-id "frame")
@@ -609,16 +632,16 @@
;; because of the deduplication (we have uploaded 2 times the
;; same files).
- (let [res (th/run-task! "storage-gc-touched" {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
(t/is (= 1 (:freeze res)))
(t/is (= 0 (:delete res))))
;; run the file-gc task immediately without forced min-age
- (let [res (th/run-task! "file-gc")]
+ (let [res (th/run-task! :file-gc)]
(t/is (= 0 (:processed res))))
;; run the task again
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; retrieve file and check trimmed attribute
@@ -648,22 +671,29 @@
:page-id page-id
:id frame-id-2}])
- (let [res (th/run-task! "file-gc" {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
- (let [rows (th/db-exec! ["select * from file_tagged_object_thumbnail where file_id = ?" file-id])]
- ;; (pp/pprint rows)
- (t/is (= 1 (count rows)))
+ (let [rows (th/db-query :file-tagged-object-thumbnail {:file-id file-id})]
+ (t/is (= 2 (count rows)))
+ (t/is (= 1 (count (remove (comp some? :deleted-at) rows))))
+
(t/is (= (thc/fmt-object-id file-id page-id frame-id-1 "frame")
(-> rows first :object-id))))
- ;; Now that file-gc have deleted the object thumbnail lets
+ ;; Now that file-gc have marked for deletion the object
+ ;; thumbnail lets execute the objects-gc task which remove
+ ;; the rows and mark as touched the storage object rows
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 2 (:processed res))))
+
+ ;; Now that objects-gc have deleted the object thumbnail lets
;; execute the touched-gc task
- (let [res (th/run-task! "storage-gc-touched" {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! "storage-gc-touched" {:min-age 0})]
(t/is (= 1 (:freeze res))))
;; check file media objects
- (let [rows (th/db-exec! ["select * from storage_object where deleted_at is null"])]
+ (let [rows (th/db-query :storage-object {:deleted-at nil})]
;; (pp/pprint rows)
(t/is (= 1 (count rows))))
@@ -676,31 +706,32 @@
:page-id page-id
:id frame-id-1}])
- (let [res (th/run-task! "file-gc" {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
- (let [rows (th/db-exec! ["select * from file_tagged_object_thumbnail where file_id = ?" file-id])]
- (t/is (= 0 (count rows))))
+ (let [rows (th/db-query :file-tagged-object-thumbnail {:file-id file-id})]
+ (t/is (= 1 (count rows)))
+ (t/is (= 0 (count (remove (comp some? :deleted-at) rows)))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ ;; (pp/pprint res)
+ (t/is (= 1 (:processed res))))
;; We still have th storage objects in the table
- (let [rows (th/db-exec! ["select * from storage_object where deleted_at is null"])]
+ (let [rows (th/db-query :storage-object {:deleted-at nil})]
;; (pp/pprint rows)
(t/is (= 1 (count rows))))
;; Now that file-gc have deleted the object thumbnail lets
;; execute the touched-gc task
- (let [res (th/run-task! "storage-gc-touched" {:min-age (dt/duration 0)})]
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
(t/is (= 1 (:delete res))))
;; check file media objects
- (let [rows (th/db-exec! ["select * from storage_object where deleted_at is null"])]
+ (let [rows (th/db-query :storage-object {:deleted-at nil})]
;; (pp/pprint rows)
(t/is (= 0 (count rows)))))))
-
-
-
-
(t/deftest permissions-checks-creating-file
(let [profile1 (th/create-profile* 1)
profile2 (th/create-profile* 2)
@@ -811,13 +842,12 @@
(t/is (th/ex-of-type? error :not-found))))
(t/deftest deletion
- (let [task (:app.tasks.objects-gc/handler th/*system*)
- profile1 (th/create-profile* 1)
+ (let [profile1 (th/create-profile* 1)
file (th/create-file* 1 {:project-id (:default-project-id profile1)
:profile-id (:id profile1)})]
;; file is not deleted because it does not meet all
;; conditions to be deleted.
- (let [result (task {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 0 (:processed result))))
;; query the list of files
@@ -848,7 +878,7 @@
(t/is (= 0 (count result)))))
;; run permanent deletion (should be noop)
- (let [result (task {:min-age (dt/duration {:minutes 1})})]
+ (let [result (th/run-task! :objects-gc {:min-age (dt/duration {:minutes 1})})]
(t/is (= 0 (:processed result))))
;; query the list of file libraries of a after hard deletion
@@ -862,7 +892,7 @@
(t/is (= 0 (count result)))))
;; run permanent deletion
- (let [result (task {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 1 (:processed result))))
;; query the list of file libraries of a after hard deletion
@@ -874,7 +904,8 @@
(let [error (:error out)
error-data (ex-data error)]
(t/is (th/ex-info? error))
- (t/is (= (:type error-data) :not-found))))))
+ (t/is (= (:type error-data) :not-found))))
+ ))
(t/deftest object-thumbnails-ops
@@ -1075,7 +1106,7 @@
(th/sleep 300)
;; run the task
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; check that object thumbnails are still here
@@ -1104,13 +1135,19 @@
(t/is (= 2 (count res))))
;; run the task again
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [res (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
;; check that the unknown frame thumbnail is deleted
- (let [res (th/db-exec! ["select * from file_tagged_object_thumbnail"])]
- (t/is (= 1 (count res)))))))
+ (let [rows (th/db-query :file-tagged-object-thumbnail {:file-id (:id file)})]
+ (t/is (= 2 (count rows)))
+ (t/is (= 1 (count (remove (comp some? :deleted-at) rows)))))
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 2 (:processed res))))
+
+ (let [rows (th/db-query :file-tagged-object-thumbnail {:file-id (:id file)})]
+ (t/is (= 1 (count rows)))))))
(t/deftest file-thumbnail-ops
(let [prof (th/create-profile* 1 {:is-active true})
@@ -1155,12 +1192,19 @@
(t/testing "gc task"
;; make the file eligible for GC waiting 300ms (configured
;; timeout for testing)
- (th/sleep 300)
+ (let [res (th/run-task! :file-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
- (let [res (th/run-task! "file-gc" {:min-age 0})]
+ (let [rows (th/db-query :file-thumbnail {:file-id (:id file)})]
+ (t/is (= 2 (count rows)))
+ (t/is (= 1 (count (remove (comp some? :deleted-at) rows)))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 1 (:processed res))))
(let [rows (th/db-query :file-thumbnail {:file-id (:id file)})]
(t/is (= 1 (count rows)))))))
+
+
diff --git a/backend/test/backend_tests/rpc_file_thumbnails_test.clj b/backend/test/backend_tests/rpc_file_thumbnails_test.clj
index b31e955569..12e5d71586 100644
--- a/backend/test/backend_tests/rpc_file_thumbnails_test.clj
+++ b/backend/test/backend_tests/rpc_file_thumbnails_test.clj
@@ -6,6 +6,7 @@
(ns backend-tests.rpc-file-thumbnails-test
(:require
+ [app.common.pprint :as pp]
[app.common.thumbnails :as thc]
[app.common.types.shape :as cts]
[app.common.uuid :as uuid]
@@ -114,9 +115,12 @@
;; Run the File GC task that should remove unused file object
;; thumbnails
- (let [result (th/run-task! :file-gc {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :file-gc {:min-age 0})]
(t/is (= 1 (:processed result))))
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 2 (:processed result))))
+
;; check if row2 related thumbnail row still exists
(let [[row :as rows] (th/db-query :file-tagged-object-thumbnail
{:file-id (:id file)}
@@ -136,19 +140,19 @@
(t/is (= 0 (:freeze res))))
;; check that storage object is still exists but is marked as deleted
- (let [row (th/db-get :storage-object {:id (:media-id row1)} {::db/remove-deleted? false})]
+ (let [row (th/db-get :storage-object {:id (:media-id row1)} {::db/remove-deleted false})]
(t/is (some? (:deleted-at row))))
;; Run the storage gc deleted task, it should permanently delete
;; all storage objects related to the deleted thumbnails
- (let [result (th/run-task! :storage-gc-deleted {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :storage-gc-deleted {:min-age 0})]
(t/is (= 1 (:deleted result))))
(t/is (nil? (sto/get-object storage (:media-id row1))))
(t/is (some? (sto/get-object storage (:media-id row2))))
;; check that storage object is still exists but is marked as deleted
- (let [row (th/db-get :storage-object {:id (:media-id row1)} {::db/remove-deleted? false})]
+ (let [row (th/db-get :storage-object {:id (:media-id row1)} {::db/remove-deleted false})]
(t/is (nil? row))))))
(t/deftest create-file-thumbnail
@@ -188,13 +192,12 @@
(let [[row1 row2 :as rows] (th/db-query :file-thumbnail
{:file-id (:id file)}
- {:order-by [[:created-at :asc]]})]
+ {:order-by [[:revn :asc]]})]
(t/is (= 2 (count rows)))
(t/is (= (:file-id data1) (:file-id row1)))
(t/is (= (:revn data1) (:revn row1)))
(t/is (uuid? (:media-id row1)))
-
(t/is (= (:file-id data2) (:file-id row2)))
(t/is (= (:revn data2) (:revn row2)))
(t/is (uuid? (:media-id row2)))
@@ -215,7 +218,10 @@
;; Run the File GC task that should remove unused file object
;; thumbnails
- (let [result (th/run-task! :file-gc {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :file-gc {:min-age 0})]
+ (t/is (= 1 (:processed result))))
+
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 1 (:processed result))))
;; check if row1 related thumbnail row still exists
@@ -227,19 +233,54 @@
(t/is (= (:object-id data1) (:object-id row)))
(t/is (uuid? (:media-id row1))))
+ (let [result (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 1 (:delete result))))
+
;; Check if storage objects still exists after file-gc
(t/is (nil? (sto/get-object storage (:media-id row1))))
(t/is (some? (sto/get-object storage (:media-id row2))))
- (let [row (th/db-get :storage-object {:id (:media-id row1)} {::db/remove-deleted? false})]
+ (let [row (th/db-get :storage-object {:id (:media-id row1)} {::db/remove-deleted false})]
(t/is (some? (:deleted-at row))))
;; Run the storage gc deleted task, it should permanently delete
;; all storage objects related to the deleted thumbnails
- (let [result (th/run-task! :storage-gc-deleted {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :storage-gc-deleted {:min-age 0})]
(t/is (= 1 (:deleted result))))
- (t/is (some? (sto/get-object storage (:media-id row2)))))))
+ (t/is (some? (sto/get-object storage (:media-id row2))))
+
+ )))
+
+(t/deftest error-on-direct-storage-obj-deletion
+ (let [storage (::sto/storage th/*system*)
+ profile (th/create-profile* 1)
+ file (th/create-file* 1 {:profile-id (:id profile)
+ :project-id (:default-project-id profile)
+ :is-shared false
+ :revn 3})
+
+ data1 {::th/type :create-file-thumbnail
+ ::rpc/profile-id (:id profile)
+ :file-id (:id file)
+ :revn 2
+ :media {:filename "sample.jpg"
+ :size 7923
+ :path (th/tempfile "backend_tests/test_files/sample2.jpg")
+ :mtype "image/jpeg"}}]
+
+ (let [out (th/command! data1)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out)))
+ (t/is (contains? (:result out) :uri)))
+
+ (let [[row1 :as rows] (th/db-query :file-thumbnail {:file-id (:id file)})]
+ (t/is (= 1 (count rows)))
+
+ (t/is (thrown? org.postgresql.util.PSQLException
+ (th/db-delete! :storage-object {:id (:media-id row1)}))))))
+
+
(t/deftest get-file-object-thumbnail
(let [storage (::sto/storage th/*system*)
@@ -279,6 +320,3 @@
(let [result (:result out)]
(t/is (contains? result "test-key-2"))))))
-
-
-
diff --git a/backend/test/backend_tests/rpc_font_test.clj b/backend/test/backend_tests/rpc_font_test.clj
index d1c3bdd60a..5d31f14b1f 100644
--- a/backend/test/backend_tests/rpc_font_test.clj
+++ b/backend/test/backend_tests/rpc_font_test.clj
@@ -92,3 +92,192 @@
:font-family
:font-weight
:font-style))))
+
+(t/deftest font-deletion-1
+ (let [prof (th/create-profile* 1 {:is-active true})
+ team-id (:default-team-id prof)
+ proj-id (:default-project-id prof)
+ font-id (uuid/custom 10 1)
+
+ data1 (-> (io/resource "backend_tests/test_files/font-1.woff")
+ io/input-stream
+ io/read-as-bytes)
+
+ data2 (-> (io/resource "backend_tests/test_files/font-2.woff")
+ io/input-stream
+ io/read-as-bytes)]
+
+ ;; Create front variant
+ (let [params {::th/type :create-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :font-id font-id
+ :font-family "somefont"
+ :font-weight 400
+ :font-style "normal"
+ :data {"font/woff" data1}}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out))))
+
+ (let [params {::th/type :create-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :font-id font-id
+ :font-family "somefont"
+ :font-weight 500
+ :font-style "normal"
+ :data {"font/woff" data2}}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 6 (:freeze res))))
+
+ (let [params {::th/type :delete-font
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :id font-id}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out)))
+ (t/is (nil? (:result out))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 6 (:freeze res)))
+ (t/is (= 0 (:delete res))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 2 (:processed res))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 0 (:freeze res)))
+ (t/is (= 6 (:delete res))))
+ ))
+
+(t/deftest font-deletion-2
+ (let [prof (th/create-profile* 1 {:is-active true})
+ team-id (:default-team-id prof)
+ proj-id (:default-project-id prof)
+ font-id (uuid/custom 10 1)
+
+ data1 (-> (io/resource "backend_tests/test_files/font-1.woff")
+ io/input-stream
+ io/read-as-bytes)
+
+ data2 (-> (io/resource "backend_tests/test_files/font-2.woff")
+ io/input-stream
+ io/read-as-bytes)]
+
+ ;; Create front variant
+ (let [params {::th/type :create-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :font-id font-id
+ :font-family "somefont"
+ :font-weight 400
+ :font-style "normal"
+ :data {"font/woff" data1}}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out))))
+
+ (let [params {::th/type :create-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :font-id (uuid/custom 10 2)
+ :font-family "somefont"
+ :font-weight 400
+ :font-style "normal"
+ :data {"font/woff" data2}}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 6 (:freeze res))))
+
+ (let [params {::th/type :delete-font
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :id font-id}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out)))
+ (t/is (nil? (:result out))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 3 (:freeze res)))
+ (t/is (= 0 (:delete res))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 0 (:freeze res)))
+ (t/is (= 3 (:delete res))))
+ ))
+
+(t/deftest font-deletion-3
+ (let [prof (th/create-profile* 1 {:is-active true})
+ team-id (:default-team-id prof)
+ proj-id (:default-project-id prof)
+ font-id (uuid/custom 10 1)
+
+ data1 (-> (io/resource "backend_tests/test_files/font-1.woff")
+ io/input-stream
+ io/read-as-bytes)
+
+ data2 (-> (io/resource "backend_tests/test_files/font-2.woff")
+ io/input-stream
+ io/read-as-bytes)
+ params1 {::th/type :create-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :font-id font-id
+ :font-family "somefont"
+ :font-weight 400
+ :font-style "normal"
+ :data {"font/woff" data1}}
+
+ params2 {::th/type :create-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :font-id font-id
+ :font-family "somefont"
+ :font-weight 500
+ :font-style "normal"
+ :data {"font/woff" data2}}
+
+ out1 (th/command! params1)
+ out2 (th/command! params2)]
+
+ ;; (th/print-result! out1)
+ (t/is (nil? (:error out1)))
+ (t/is (nil? (:error out2)))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 6 (:freeze res))))
+
+ (let [params {::th/type :delete-font-variant
+ ::rpc/profile-id (:id prof)
+ :team-id team-id
+ :id (-> out1 :result :id)}
+ out (th/command! params)]
+ ;; (th/print-result! out)
+ (t/is (nil? (:error out)))
+ (t/is (nil? (:result out))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 3 (:freeze res)))
+ (t/is (= 0 (:delete res))))
+
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
+
+ (let [res (th/run-task! :storage-gc-touched {:min-age 0})]
+ (t/is (= 0 (:freeze res)))
+ (t/is (= 3 (:delete res))))
+
+ ))
diff --git a/backend/test/backend_tests/rpc_profile_test.clj b/backend/test/backend_tests/rpc_profile_test.clj
index 64ccde95a3..f21dc17ecd 100644
--- a/backend/test/backend_tests/rpc_profile_test.clj
+++ b/backend/test/backend_tests/rpc_profile_test.clj
@@ -125,7 +125,7 @@
;; profile is not deleted because it does not meet all
;; conditions to be deleted.
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 0 (:processed result))))
;; Request profile to be deleted
@@ -144,12 +144,20 @@
(t/is (= 1 (count (:result out)))))
;; execute permanent deletion task
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration "-1m")})]
- (t/is (= 2 (:processed result))))
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 1 (:processed result))))
(let [row (th/db-get :team
{:id (:default-team-id prof)}
- {::db/remove-deleted? false})]
+ {::db/remove-deleted false})]
+ (t/is (nil? (:deleted-at row))))
+
+ (let [result (th/run-task! :orphan-teams-gc {:min-age 0})]
+ (t/is (= 1 (:processed result))))
+
+ (let [row (th/db-get :team
+ {:id (:default-team-id prof)}
+ {::db/remove-deleted false})]
(t/is (dt/instant? (:deleted-at row))))
;; query profile after delete
@@ -158,67 +166,9 @@
out (th/command! params)]
;; (th/print-result! out)
(let [result (:result out)]
- (t/is (= uuid/zero (:id result)))))))
+ (t/is (= uuid/zero (:id result)))))
-(t/deftest profile-immediate-deletion
- (let [prof1 (th/create-profile* 1)
- prof2 (th/create-profile* 2)
- file (th/create-file* 1 {:profile-id (:id prof1)
- :project-id (:default-project-id prof1)
- :is-shared false})
-
- team (th/create-team* 1 {:profile-id (:id prof1)})
- _ (th/create-team-role* {:team-id (:id team)
- :profile-id (:id prof2)
- :role :admin})]
-
- ;; profile is not deleted because it does not meet all
- ;; conditions to be deleted.
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration 0)})]
- (t/is (= 0 (:orphans result)))
- (t/is (= 0 (:processed result))))
-
- ;; just delete the profile
- (th/db-delete! :profile {:id (:id prof1)})
-
- ;; query files after profile deletion, expecting not found
- (let [params {::th/type :get-project-files
- ::rpc/profile-id (:id prof1)
- :project-id (:default-project-id prof1)}
- out (th/command! params)]
- ;; (th/print-result! out)
- (t/is (not (th/success? out)))
- (let [edata (-> out :error ex-data)]
- (t/is (= :not-found (:type edata)))))
-
- ;; the files and projects still exists on the database
- (let [files (th/db-query :file {:project-id (:default-project-id prof1)})
- projects (th/db-query :project {:team-id (:default-team-id prof1)})]
- (t/is (= 1 (count files)))
- (t/is (= 1 (count projects))))
-
- ;; execute the gc task
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration "-1m")})]
- (t/is (= 1 (:processed result)))
- (t/is (= 1 (:orphans result))))
-
- ;; Check the deletion flag on the default profile team
- (let [row (th/db-get :team
- {:id (:default-team-id prof1)}
- {::db/remove-deleted? false})]
- (t/is (dt/instant? (:deleted-at row))))
-
- ;; Check the deletion flag on the shared team
- (let [row (th/db-get :team
- {:id (:id team)}
- {::db/remove-deleted? false})]
- (t/is (nil? (:deleted-at row))))
-
- ;; Check the roles on the shared team
- (let [rows (th/db-query :team-profile-rel {:team-id (:id team)})]
- (t/is (= 1 (count rows)))
- (t/is (= (:id prof2) (get-in rows [0 :profile-id])))
- (t/is (= false (get-in rows [0 :is-owner]))))))
+ ))
(t/deftest registration-domain-whitelist
(let [whitelist #{"gmail.com" "hey.com" "ya.ru"}]
diff --git a/backend/test/backend_tests/rpc_project_test.clj b/backend/test/backend_tests/rpc_project_test.clj
index acfb6fdf21..f35105a97f 100644
--- a/backend/test/backend_tests/rpc_project_test.clj
+++ b/backend/test/backend_tests/rpc_project_test.clj
@@ -172,14 +172,13 @@
(t/deftest test-deletion
- (let [task (:app.tasks.objects-gc/handler th/*system*)
- profile1 (th/create-profile* 1)
+ (let [profile1 (th/create-profile* 1)
project (th/create-project* 1 {:team-id (:default-team-id profile1)
:profile-id (:id profile1)})]
;; project is not deleted because it does not meet all
;; conditions to be deleted.
- (let [result (task {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 0 (:processed result))))
;; query the list of projects
@@ -187,6 +186,7 @@
::rpc/profile-id (:id profile1)
:team-id (:default-team-id profile1)}
out (th/command! data)]
+
;; (th/print-result! out)
(t/is (nil? (:error out)))
(let [result (:result out)]
@@ -210,7 +210,7 @@
(t/is (= 1 (count result)))))
;; run permanent deletion (should be noop)
- (let [result (task {:min-age (dt/duration {:minutes 1})})]
+ (let [result (th/run-task! :objects-gc {:min-age (dt/duration {:minutes 1})})]
(t/is (= 0 (:processed result))))
;; query the list of files of a after soft deletion
@@ -224,7 +224,7 @@
(t/is (= 0 (count result)))))
;; run permanent deletion
- (let [result (task {:min-age (dt/duration 0)})]
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 1 (:processed result))))
;; query the list of files of a after hard deletion
diff --git a/backend/test/backend_tests/rpc_team_test.clj b/backend/test/backend_tests/rpc_team_test.clj
index 45e4c48071..8252e9aa30 100644
--- a/backend/test/backend_tests/rpc_team_test.clj
+++ b/backend/test/backend_tests/rpc_team_test.clj
@@ -269,76 +269,6 @@
(t/is (= 1 (count members)))
(t/is (true? (-> members first :can-edit))))))))
-(t/deftest team-deletion
- (let [profile1 (th/create-profile* 1 {:is-active true})
- team (th/create-team* 1 {:profile-id (:id profile1)})
- pool (:app.db/pool th/*system*)
- data {::th/type :delete-team
- ::rpc/profile-id (:id profile1)
- :team-id (:id team)}]
-
- ;; team is not deleted because it does not meet all
- ;; conditions to be deleted.
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration 0)})]
- (t/is (= 0 (:processed result))))
-
- ;; query the list of teams
- (let [data {::th/type :get-teams
- ::rpc/profile-id (:id profile1)}
- out (th/command! data)]
- ;; (th/print-result! out)
- (t/is (th/success? out))
- (let [result (:result out)]
- (t/is (= 2 (count result)))
- (t/is (= (:id team) (get-in result [1 :id])))
- (t/is (= (:default-team-id profile1) (get-in result [0 :id])))))
-
- ;; Request team to be deleted
- (let [params {::th/type :delete-team
- ::rpc/profile-id (:id profile1)
- :id (:id team)}
- out (th/command! params)]
- (t/is (th/success? out)))
-
- ;; query the list of teams after soft deletion
- (let [data {::th/type :get-teams
- ::rpc/profile-id (:id profile1)}
- out (th/command! data)]
- ;; (th/print-result! out)
- (t/is (th/success? out))
- (let [result (:result out)]
- (t/is (= 1 (count result)))
- (t/is (= (:default-team-id profile1) (get-in result [0 :id])))))
-
- ;; run permanent deletion (should be noop)
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration {:minutes 1})})]
- (t/is (= 0 (:processed result))))
-
- ;; query the list of projects after hard deletion
- (let [data {::th/type :get-projects
- ::rpc/profile-id (:id profile1)
- :team-id (:id team)}
- out (th/command! data)]
- ;; (th/print-result! out)
- (t/is (not (th/success? out)))
- (let [edata (-> out :error ex-data)]
- (t/is (= :not-found (:type edata)))))
-
- ;; run permanent deletion
- (let [result (th/run-task! :objects-gc {:min-age (dt/duration 0)})]
- (t/is (= 1 (:processed result))))
-
- ;; query the list of projects of a after hard deletion
- (let [data {::th/type :get-projects
- ::rpc/profile-id (:id profile1)
- :team-id (:id team)}
- out (th/command! data)]
- ;; (th/print-result! out)
-
- (t/is (not (th/success? out)))
- (let [edata (-> out :error ex-data)]
- (t/is (= :not-found (:type edata)))))))
-
(t/deftest query-team-invitations
(let [prof (th/create-profile* 1 {:is-active true})
team (th/create-team* 1 {:profile-id (:id prof)})
@@ -418,3 +348,119 @@
(t/is (th/success? out))
(t/is (nil? (:result out)))
(t/is (nil? res)))))
+
+
+(t/deftest team-deletion-1
+ (let [profile1 (th/create-profile* 1 {:is-active true})
+ team (th/create-team* 1 {:profile-id (:id profile1)})
+ pool (:app.db/pool th/*system*)
+ data {::th/type :delete-team
+ ::rpc/profile-id (:id profile1)
+ :team-id (:id team)}]
+
+ ;; team is not deleted because it does not meet all
+ ;; conditions to be deleted.
+ (let [result (th/run-task! :objects-gc {:min-age (dt/duration 0)})]
+ (t/is (= 0 (:processed result))))
+
+ ;; query the list of teams
+ (let [data {::th/type :get-teams
+ ::rpc/profile-id (:id profile1)}
+ out (th/command! data)]
+ ;; (th/print-result! out)
+ (t/is (th/success? out))
+ (let [result (:result out)]
+ (t/is (= 2 (count result)))
+ (t/is (= (:id team) (get-in result [1 :id])))
+ (t/is (= (:default-team-id profile1) (get-in result [0 :id])))))
+
+ ;; Request team to be deleted
+ (let [params {::th/type :delete-team
+ ::rpc/profile-id (:id profile1)
+ :id (:id team)}
+ out (th/command! params)]
+ (t/is (th/success? out)))
+
+ ;; query the list of teams after soft deletion
+ (let [data {::th/type :get-teams
+ ::rpc/profile-id (:id profile1)}
+ out (th/command! data)]
+ ;; (th/print-result! out)
+ (t/is (th/success? out))
+ (let [result (:result out)]
+ (t/is (= 1 (count result)))
+ (t/is (= (:default-team-id profile1) (get-in result [0 :id])))))
+
+ ;; run permanent deletion (should be noop)
+ (let [result (th/run-task! :objects-gc {:min-age (dt/duration {:minutes 1})})]
+ (t/is (= 0 (:processed result))))
+
+ ;; query the list of projects after hard deletion
+ (let [data {::th/type :get-projects
+ ::rpc/profile-id (:id profile1)
+ :team-id (:id team)}
+ out (th/command! data)]
+ ;; (th/print-result! out)
+ (t/is (not (th/success? out)))
+ (let [edata (-> out :error ex-data)]
+ (t/is (= :not-found (:type edata)))))
+
+ ;; run permanent deletion
+ (let [result (th/run-task! :objects-gc {:min-age (dt/duration 0)})]
+ (t/is (= 2 (:processed result))))
+
+ ;; query the list of projects of a after hard deletion
+ (let [data {::th/type :get-projects
+ ::rpc/profile-id (:id profile1)
+ :team-id (:id team)}
+ out (th/command! data)]
+ ;; (th/print-result! out)
+
+ (t/is (not (th/success? out)))
+ (let [edata (-> out :error ex-data)]
+ (t/is (= :not-found (:type edata)))))))
+
+
+(t/deftest team-deletion-2
+ (let [storage (-> (:app.storage/storage th/*system*)
+ (assoc ::sto/backend :assets-fs))
+ prof (th/create-profile* 1)
+
+ team (th/create-team* 1 {:profile-id (:id prof)})
+
+ proj (th/create-project* 1 {:profile-id (:id prof)
+ :team-id (:id team)})
+ file (th/create-file* 1 {:profile-id (:id prof)
+ :project-id (:default-project-id team)
+ :is-shared false})
+
+ mfile {:filename "sample.jpg"
+ :path (th/tempfile "backend_tests/test_files/sample.jpg")
+ :mtype "image/jpeg"
+ :size 312043}]
+
+
+ (let [params {::th/type :upload-file-media-object
+ ::rpc/profile-id (:id prof)
+ :file-id (:id file)
+ :is-local true
+ :name "testfile"
+ :content mfile}
+
+ out (th/command! params)]
+ (t/is (nil? (:error out))))
+
+ (let [params {::th/type :delete-team
+ ::rpc/profile-id (:id prof)
+ :id (:id team)}
+ out (th/command! params)]
+ #_(th/print-result! out)
+ (t/is (nil? (:error out))))
+
+ (let [rows (th/db-exec! ["select * from team where id = ?" (:id team)])]
+ (t/is (= 1 (count rows)))
+ (t/is (dt/instant? (:deleted-at (first rows)))))
+
+ (let [result (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 5 (:processed result))))
+ ))
diff --git a/backend/test/backend_tests/storage_test.clj b/backend/test/backend_tests/storage_test.clj
index 5277544204..ccc0d08630 100644
--- a/backend/test/backend_tests/storage_test.clj
+++ b/backend/test/backend_tests/storage_test.clj
@@ -113,7 +113,7 @@
(let [res (th/run-task! :storage-gc-deleted {})]
(t/is (= 1 (:deleted res))))
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object;"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object;"])]
(t/is (= 2 (:count res))))))
(t/deftest test-touched-gc-task-1
@@ -156,29 +156,33 @@
(t/is (= (:media-id result-1) (:media-id result-2)))
- ;; now we proceed to manually delete one file-media-object
- (db/exec-one! th/*pool* ["delete from file_media_object where id = ?" (:id result-1)])
+ (th/db-update! :file-media-object
+ {:deleted-at (dt/now)}
+ {:id (:id result-1)})
+
+ ;; run the objects gc task for permanent deletion
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
;; check that we still have all the storage objects
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object"])]
(t/is (= 2 (:count res))))
;; now check if the storage objects are touched
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where touched_at is not null"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object where touched_at is not null"])]
(t/is (= 2 (:count res))))
;; run the touched gc task
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {})]
+ (let [res (th/run-task! :storage-gc-touched {})]
(t/is (= 2 (:freeze res)))
(t/is (= 0 (:delete res))))
;; now check that there are no touched objects
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where touched_at is not null"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object where touched_at is not null"])]
(t/is (= 0 (:count res))))
;; now check that all objects are marked to be deleted
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where deleted_at is not null"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object where deleted_at is not null"])]
(t/is (= 0 (:count res)))))))
@@ -231,31 +235,35 @@
(t/is (nil? (:error out2)))
;; run the touched gc task
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {})]
+ (let [res (th/run-task! :storage-gc-touched {})]
(t/is (= 5 (:freeze res)))
(t/is (= 0 (:delete res)))
(let [result-1 (:result out1)
result-2 (:result out2)]
- ;; now we proceed to manually delete one team-font-variant
- (db/exec-one! th/*pool* ["delete from team_font_variant where id = ?" (:id result-2)])
+ (th/db-update! :team-font-variant
+ {:deleted-at (dt/now)}
+ {:id (:id result-2)})
+
+ ;; run the objects gc task for permanent deletion
+ (let [res (th/run-task! :objects-gc {:min-age 0})]
+ (t/is (= 1 (:processed res))))
;; revert touched state to all storage objects
- (db/exec-one! th/*pool* ["update storage_object set touched_at=now()"])
+ (th/db-exec-one! ["update storage_object set touched_at=now()"])
;; Run the task again
- (let [res (task {})]
+ (let [res (th/run-task! :storage-gc-touched {})]
(t/is (= 2 (:freeze res)))
(t/is (= 3 (:delete res))))
;; now check that there are no touched objects
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where touched_at is not null"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object where touched_at is not null"])]
(t/is (= 0 (:count res))))
;; now check that all objects are marked to be deleted
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where deleted_at is not null"])]
+ (let [res (th/db-exec-one! ["select count(*) from storage_object where deleted_at is not null"])]
(t/is (= 3 (:count res))))))))
(t/deftest test-touched-gc-task-3
@@ -289,28 +297,28 @@
result-2 (:result out2)]
;; now we proceed to manually mark all storage objects touched
- (db/exec-one! th/*pool* ["update storage_object set touched_at=now()"])
+ (th/db-exec! ["update storage_object set touched_at=now()"])
;; run the touched gc task
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {})]
+ (let [res (th/run-task! "storage-gc-touched" {:min-age 0})]
(t/is (= 2 (:freeze res)))
(t/is (= 0 (:delete res))))
;; check that we have all object in the db
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where deleted_at is null"])]
- (t/is (= 2 (:count res)))))
+ (let [rows (th/db-exec! ["select * from storage_object"])]
+ (t/is (= 2 (count rows)))))
;; now we proceed to manually delete all file_media_object
- (db/exec-one! th/*pool* ["delete from file_media_object"])
+ (th/db-exec! ["update file_media_object set deleted_at = now()"])
+
+ (let [res (th/run-task! "objects-gc" {:min-age 0})]
+ (t/is (= 2 (:processed res))))
;; run the touched gc task
- (let [task (:app.storage/gc-touched-task th/*system*)
- res (task {})]
+ (let [res (th/run-task! "storage-gc-touched" {:min-age 0})]
(t/is (= 0 (:freeze res)))
(t/is (= 2 (:delete res))))
;; check that we have all no objects
- (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where deleted_at is null"])]
- (t/is (= 0 (:count res))))))
-
+ (let [rows (th/db-exec! ["select * from storage_object where deleted_at is null"])]
+ (t/is (= 0 (count rows))))))
diff --git a/common/src/app/common/data.cljc b/common/src/app/common/data.cljc
index c997c05c0f..4068839865 100644
--- a/common/src/app/common/data.cljc
+++ b/common/src/app/common/data.cljc
@@ -517,6 +517,13 @@
(->> (apply c/iteration args)
(concat-all)))
+(defn add-at-index
+ "Insert an element in a vector at an arbitrary index"
+ [coll index element]
+ (assert (vector? coll))
+ (let [[before after] (split-at index coll)]
+ (concat-vec [] before [element] after)))
+
(defn insert-at-index
"Insert a list of elements at the given index of a previous list.
Replace all existing elems."
diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc
index 7efc11c311..6668f91af8 100644
--- a/common/src/app/common/files/changes_builder.cljc
+++ b/common/src/app/common/files/changes_builder.cljc
@@ -358,13 +358,15 @@
(defn changed-attrs
"Returns the list of attributes that will change when `update-fn` is applied"
- [object objects update-fn {:keys [attrs]}]
+ [object objects update-fn {:keys [attrs with-objects?]}]
(let [changed?
(fn [old new attr]
(let [old-val (get old attr)
new-val (get new attr)]
(not= old-val new-val)))
- new-obj (update-fn object objects)]
+ new-obj (if with-objects?
+ (update-fn object objects)
+ (update-fn object))]
(when-not (= object new-obj)
(let [attrs (or attrs (d/concat-set (keys object) (keys new-obj)))]
(filter (partial changed? object new-obj) attrs)))))
@@ -375,8 +377,8 @@
([changes ids update-fn]
(update-shapes changes ids update-fn nil))
- ([changes ids update-fn {:keys [attrs ignore-geometry? ignore-touched]
- :or {ignore-geometry? false ignore-touched false}}]
+ ([changes ids update-fn {:keys [attrs ignore-geometry? ignore-touched with-objects?]
+ :or {ignore-geometry? false ignore-touched false with-objects? false}}]
(assert-container-id! changes)
(assert-objects! changes)
(let [page-id (::page-id (meta changes))
@@ -412,7 +414,7 @@
update-shape
(fn [changes id]
(let [old-obj (get objects id)
- new-obj (update-fn old-obj objects)]
+ new-obj (if with-objects? (update-fn old-obj objects) (update-fn old-obj))]
(if (= old-obj new-obj)
changes
(let [[rops uops] (-> (or attrs (d/concat-set (keys old-obj) (keys new-obj)))
diff --git a/common/src/app/common/files/shapes_helpers.cljc b/common/src/app/common/files/shapes_helpers.cljc
index a36fadf916..8a656886f1 100644
--- a/common/src/app/common/files/shapes_helpers.cljc
+++ b/common/src/app/common/files/shapes_helpers.cljc
@@ -16,7 +16,7 @@
[app.common.uuid :as uuid]))
(defn prepare-add-shape
- [changes shape objects _selected]
+ [changes shape objects]
(let [index (:index (meta shape))
id (:id shape)
@@ -34,7 +34,7 @@
(cond-> (some? cell)
(pcb/update-shapes [(:parent-id shape)] #(ctl/push-into-cell % [id] row column)))
(cond-> (ctl/grid-layout? objects (:parent-id shape))
- (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells)))]
+ (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells {:with-objects? true})))]
[shape changes]))
(defn prepare-move-shapes-into-frame
@@ -50,58 +50,120 @@
(pcb/update-shapes ordered-indexes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))
(pcb/change-parent frame-id to-move-shapes 0)
(cond-> (ctl/grid-layout? objects frame-id)
- (pcb/update-shapes [frame-id] ctl/assign-cells))
- (pcb/reorder-grid-children [frame-id]))
+ (-> (pcb/update-shapes [frame-id] ctl/assign-cells {:with-objects? true})
+ (pcb/reorder-grid-children [frame-id]))))
changes)))
(defn prepare-create-artboard-from-selection
- [changes id parent-id objects selected index frame-name without-fill?]
- (let [selected-objs (map #(get objects %) selected)
- new-index (or index
- (cfh/get-index-replacement selected objects))]
- (when (d/not-empty? selected)
- (let [srect (gsh/shapes->rect selected-objs)
- selected-id (first selected)
+ ([changes id parent-id objects selected index frame-name without-fill?]
+ (prepare-create-artboard-from-selection
+ changes id parent-id objects selected index frame-name without-fill? nil))
- frame-id (dm/get-in objects [selected-id :frame-id])
- parent-id (or parent-id (dm/get-in objects [selected-id :parent-id]))
+ ([changes id parent-id objects selected index frame-name without-fill? target-cell-id]
+ (let [selected-objs (map #(get objects %) selected)
+ new-index (or index
+ (cfh/get-index-replacement selected objects))]
+ (when (d/not-empty? selected)
+ (let [srect (gsh/shapes->rect selected-objs)
+ selected-id (first selected)
- attrs {:type :frame
- :x (:x srect)
- :y (:y srect)
- :width (:width srect)
- :height (:height srect)}
+ frame-id (dm/get-in objects [selected-id :frame-id])
+ parent-id (or parent-id (dm/get-in objects [selected-id :parent-id]))
+ base-parent (get objects parent-id)
- shape (cts/setup-shape
- (cond-> attrs
- (some? id)
- (assoc :id id)
+ attrs {:type :frame
+ :x (:x srect)
+ :y (:y srect)
+ :width (:width srect)
+ :height (:height srect)}
- (some? frame-name)
- (assoc :name frame-name)
+ shape (cts/setup-shape
+ (cond-> attrs
+ (some? id)
+ (assoc :id id)
- :always
- (assoc :frame-id frame-id
- :parent-id parent-id
- :shapes (into [] selected))
+ (some? frame-name)
+ (assoc :name frame-name)
- :always
- (with-meta {:index new-index})
+ :always
+ (assoc :frame-id frame-id
+ :parent-id parent-id
+ :shapes (into [] selected))
- (or (not= frame-id uuid/zero) without-fill?)
- (assoc :fills [] :hide-in-viewer true)))
+ :always
+ (with-meta {:index new-index})
- [shape changes]
- (prepare-add-shape changes shape objects selected)
+ (or (not= frame-id uuid/zero) without-fill?)
+ (assoc :fills [] :hide-in-viewer true)))
- changes
- (prepare-move-shapes-into-frame changes (:id shape) selected objects)
+ [shape changes]
+ (prepare-add-shape changes shape objects)
- changes
- (cond-> changes
- (ctl/grid-layout? objects (:parent-id shape))
- (-> (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells)
- (pcb/reorder-grid-children [(:parent-id shape)])))]
+ changes
+ (prepare-move-shapes-into-frame changes (:id shape) selected objects)
- [shape changes]))))
+ changes
+ (cond-> changes
+ (ctl/grid-layout? objects (:parent-id shape))
+ (-> (cond-> (some? target-cell-id)
+ (pcb/update-shapes
+ [(:parent-id shape)]
+ (fn [parent]
+ (-> parent
+ (assoc :layout-grid-cells (:layout-grid-cells base-parent))
+ (assoc-in [:layout-grid-cells target-cell-id :shapes] [id])
+ (assoc :position :auto)))))
+ (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells {:with-objects? true})
+ (pcb/reorder-grid-children [(:parent-id shape)])))]
+ [shape changes])))))
+
+
+(defn prepare-create-empty-artboard
+ [changes frame-id parent-id objects index frame-name without-fill? target-cell-id]
+
+ (let [base-parent (get objects parent-id)
+
+ attrs {:type :frame
+ :x 0
+ :y 0
+ :width 0.01
+ :height 0.01}
+
+ shape (cts/setup-shape
+ (cond-> attrs
+ (some? frame-id)
+ (assoc :id frame-id)
+
+ (some? frame-name)
+ (assoc :name frame-name)
+
+ :always
+ (assoc :frame-id frame-id
+ :parent-id parent-id
+ :shapes [])
+
+ :always
+ (with-meta {:index index})
+
+ (or (not= frame-id uuid/zero) without-fill?)
+ (assoc :fills [] :hide-in-viewer true)))
+
+ [shape changes]
+ (prepare-add-shape changes shape objects)
+
+ changes
+ (cond-> changes
+ (ctl/grid-layout? objects (:parent-id shape))
+ (-> (cond-> (some? target-cell-id)
+ (pcb/update-shapes
+ [(:parent-id shape)]
+ (fn [parent]
+ (-> parent
+ (assoc :layout-grid-cells (:layout-grid-cells base-parent))
+ (assoc-in [:layout-grid-cells target-cell-id :shapes] [frame-id])
+ (assoc :position :auto)))))
+ (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells {:with-objects? true})
+ (pcb/reorder-grid-children [(:parent-id shape)])))]
+
+ [shape changes]))
diff --git a/common/src/app/common/geom/line.cljc b/common/src/app/common/geom/line.cljc
new file mode 100644
index 0000000000..6ab28d5fc1
--- /dev/null
+++ b/common/src/app/common/geom/line.cljc
@@ -0,0 +1,18 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; Copyright (c) KALEIDOS INC
+
+(ns app.common.geom.line)
+
+(defn line-value
+ [[{px :x py :y} {vx :x vy :y}] {:keys [x y]}]
+ (let [a vy
+ b (- vx)
+ c (+ (* (- vy) px) (* vx py))]
+ (+ (* a x) (* b y) c)))
+
+(defn is-inside-lines?
+ [line-1 line-2 pos]
+ (< (* (line-value line-1 pos) (line-value line-2 pos)) 0))
diff --git a/common/src/app/common/geom/shapes/grid_layout/params.cljc b/common/src/app/common/geom/shapes/grid_layout/params.cljc
index b50fbf4483..7c0dafc4ed 100644
--- a/common/src/app/common/geom/shapes/grid_layout/params.cljc
+++ b/common/src/app/common/geom/shapes/grid_layout/params.cljc
@@ -113,8 +113,8 @@
([_objects shapes parent]
(if (empty? shapes)
- (-> {:layout-grid-columns [{:type :auto} {:type :auto}]
- :layout-grid-rows [{:type :auto} {:type :auto}]}
+ (-> {:layout-grid-columns [ctl/default-track-value ctl/default-track-value]
+ :layout-grid-rows [ctl/default-track-value ctl/default-track-value]}
(ctl/create-cells [1 1 2 2]))
(let [all-shapes-rect (gco/shapes->rect shapes)
@@ -149,8 +149,8 @@
0
(/ (- (:height all-shapes-rect) total-rows-height) (dec num-rows)))
- layout-grid-rows (mapv (constantly (array-map :type :auto)) rows)
- layout-grid-columns (mapv (constantly (array-map :type :auto)) cols)
+ layout-grid-rows (mapv (constantly ctl/default-track-value) rows)
+ layout-grid-columns (mapv (constantly ctl/default-track-value) cols)
parent-childs-vector (gpt/to-vec (gpo/origin (:points parent)) (gpt/point all-shapes-rect))
p-left (:x parent-childs-vector)
diff --git a/common/src/app/common/geom/shapes/grid_layout/positions.cljc b/common/src/app/common/geom/shapes/grid_layout/positions.cljc
index e6504519f5..6ab0c0bb75 100644
--- a/common/src/app/common/geom/shapes/grid_layout/positions.cljc
+++ b/common/src/app/common/geom/shapes/grid_layout/positions.cljc
@@ -9,6 +9,7 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
+ [app.common.geom.line :as gl]
[app.common.geom.point :as gpt]
[app.common.geom.shapes.common :as gco]
[app.common.geom.shapes.grid-layout.layout-data :as ld]
@@ -182,18 +183,6 @@
(-> (ctm/add-modifiers fill-modifiers)
(ctm/move position-delta)))))
-
-(defn line-value
- [[{px :x py :y} {vx :x vy :y}] {:keys [x y]}]
- (let [a vy
- b (- vx)
- c (+ (* (- vy) px) (* vx py))]
- (+ (* a x) (* b y) c)))
-
-(defn is-inside-lines?
- [line-1 line-2 pos]
- (< (* (line-value line-1 pos) (line-value line-2 pos)) 0))
-
(defn get-position-grid-coord
[{:keys [layout-bounds row-tracks column-tracks]} position]
@@ -206,7 +195,7 @@
(fn is-inside-track? [{:keys [start-p size] :as track}]
(let [unit-v (vfn 1)
end-p (gpt/add start-p (ofn size))]
- (is-inside-lines? [start-p unit-v] [end-p unit-v] position)))))
+ (gl/is-inside-lines? [start-p unit-v] [end-p unit-v] position)))))
make-min-distance-track
(fn [type]
@@ -214,8 +203,8 @@
(fn [[selected selected-dist] [cur-idx {:keys [start-p size] :as track}]]
(let [unit-v (vfn 1)
end-p (gpt/add start-p (ofn size))
- dist-1 (mth/abs (line-value [start-p unit-v] position))
- dist-2 (mth/abs (line-value [end-p unit-v] position))]
+ dist-1 (mth/abs (gl/line-value [start-p unit-v] position))
+ dist-2 (mth/abs (gl/line-value [end-p unit-v] position))]
(if (or (< dist-1 selected-dist) (< dist-2 selected-dist))
[[cur-idx track] (min dist-1 dist-2)]
diff --git a/common/src/app/common/svg.cljc b/common/src/app/common/svg.cljc
index 39379028f3..bc4f79f19e 100644
--- a/common/src/app/common/svg.cljc
+++ b/common/src/app/common/svg.cljc
@@ -9,9 +9,6 @@
#?(:cljs ["./svg/optimizer.js" :as svgo])
#?(:clj [clojure.xml :as xml]
:cljs [tubax.core :as tubax])
- #?(:clj [integrant.core :as ig])
- #?(:clj [app.common.jsrt :as jsrt])
- #?(:clj [app.common.logging :as l])
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
@@ -1053,21 +1050,6 @@
:height (d/parse-integer (:height attrs) 0)})))]
(reduce-nodes redfn [] svg-data )))
-#?(:cljs
- (defn optimize
- ([input] (optimize input nil))
- ([input options]
- (svgo/optimize input (clj->js options))))
- :clj
- (defn optimize
- [pool data]
- (dm/assert! "expected a valid pool" (jsrt/pool? pool))
- (dm/assert! "expect data to be a string" (string? data))
- (jsrt/run! pool
- (fn [context]
- (jsrt/set! context "svgData" data)
- (jsrt/eval! context "penpotSvgo.optimize(svgData, {})")))))
-
#?(:clj
(defn- secure-parser-factory
[^InputStream input ^XMLHandler handler]
@@ -1091,15 +1073,9 @@
(dm/with-open [istream (IOUtils/toInputStream text "UTF-8")]
(xml/parse istream secure-parser-factory)))))
-#?(:clj
- (defmethod ig/init-key ::optimizer
- [_ _]
- (l/info :hint "initializing svg optimizer pool")
- (let [init (jsrt/resource->source "app/common/svg/optimizer.js")]
- (jsrt/pool :init init))))
-
-#?(:clj
- (defmethod ig/halt-key! ::optimizer
- [_ pool]
- (l/info :hint "stopping svg optimizer pool")
- (.close ^java.lang.AutoCloseable pool)))
+;; FIXME pass correct plugin set
+#?(:cljs
+ (defn optimize
+ ([input] (optimize input nil))
+ ([input options]
+ (svgo/optimize input (clj->js options)))))
diff --git a/common/src/app/common/svg/optimizer.js b/common/src/app/common/svg/optimizer.js
index 70826b8bdb..ccd19b6970 100644
--- a/common/src/app/common/svg/optimizer.js
+++ b/common/src/app/common/svg/optimizer.js
@@ -29431,12 +29431,13 @@ const optimize = (input, config) => {
exports.optimize = optimize;
-},{"./svgo/parser.js":322,"./svgo/plugins.js":324,"./svgo/stringifier.js":381,"./svgo/tools.js":383,"lodash/isPlainObject":308}],320:[function(require,module,exports){
+},{"./svgo/parser.js":322,"./svgo/plugins.js":324,"./svgo/stringifier.js":382,"./svgo/tools.js":384,"lodash/isPlainObject":308}],320:[function(require,module,exports){
'use strict';
exports.builtin = [
require('./plugins/default.js'),
require('./plugins/safe.js'),
+ require('./plugins/safeAndFast.js'),
require('./plugins/addAttributesToSVGElement.js'),
require('./plugins/addClassesToSVGElement.js'),
require('./plugins/cleanupAttrs.js'),
@@ -29489,7 +29490,7 @@ exports.builtin = [
require('./plugins/sortDefsChildren.js'),
];
-},{"./plugins/addAttributesToSVGElement.js":328,"./plugins/addClassesToSVGElement.js":329,"./plugins/cleanupAttrs.js":331,"./plugins/cleanupEnableBackground.js":332,"./plugins/cleanupIds.js":333,"./plugins/cleanupListOfValues.js":334,"./plugins/cleanupNumericValues.js":335,"./plugins/collapseGroups.js":336,"./plugins/convertColors.js":337,"./plugins/convertEllipseToCircle.js":338,"./plugins/convertPathData.js":339,"./plugins/convertShapeToPath.js":340,"./plugins/convertStyleToAttrs.js":341,"./plugins/convertTransform.js":342,"./plugins/default.js":343,"./plugins/inlineStyles.js":344,"./plugins/mergePaths.js":345,"./plugins/mergeStyles.js":346,"./plugins/minifyStyles.js":347,"./plugins/moveElemsAttrsToGroup.js":348,"./plugins/moveGroupAttrsToElems.js":349,"./plugins/prefixIds.js":350,"./plugins/removeAttributesBySelector.js":351,"./plugins/removeAttrs.js":352,"./plugins/removeComments.js":353,"./plugins/removeDesc.js":354,"./plugins/removeDimensions.js":355,"./plugins/removeDoctype.js":356,"./plugins/removeEditorsNSData.js":357,"./plugins/removeElementsByAttr.js":358,"./plugins/removeEmptyAttrs.js":359,"./plugins/removeEmptyContainers.js":360,"./plugins/removeEmptyText.js":361,"./plugins/removeHiddenElems.js":362,"./plugins/removeMetadata.js":363,"./plugins/removeNonInheritableGroupAttrs.js":364,"./plugins/removeOffCanvasPaths.js":365,"./plugins/removeRasterImages.js":366,"./plugins/removeScriptElement.js":367,"./plugins/removeStyleElement.js":368,"./plugins/removeTitle.js":369,"./plugins/removeUnknownsAndDefaults.js":370,"./plugins/removeUnusedNS.js":371,"./plugins/removeUselessDefs.js":372,"./plugins/removeUselessStrokeAndFill.js":373,"./plugins/removeViewBox.js":374,"./plugins/removeXMLNS.js":375,"./plugins/removeXMLProcInst.js":376,"./plugins/reusePaths.js":377,"./plugins/safe.js":378,"./plugins/sortAttrs.js":379,"./plugins/sortDefsChildren.js":380}],321:[function(require,module,exports){
+},{"./plugins/addAttributesToSVGElement.js":328,"./plugins/addClassesToSVGElement.js":329,"./plugins/cleanupAttrs.js":331,"./plugins/cleanupEnableBackground.js":332,"./plugins/cleanupIds.js":333,"./plugins/cleanupListOfValues.js":334,"./plugins/cleanupNumericValues.js":335,"./plugins/collapseGroups.js":336,"./plugins/convertColors.js":337,"./plugins/convertEllipseToCircle.js":338,"./plugins/convertPathData.js":339,"./plugins/convertShapeToPath.js":340,"./plugins/convertStyleToAttrs.js":341,"./plugins/convertTransform.js":342,"./plugins/default.js":343,"./plugins/inlineStyles.js":344,"./plugins/mergePaths.js":345,"./plugins/mergeStyles.js":346,"./plugins/minifyStyles.js":347,"./plugins/moveElemsAttrsToGroup.js":348,"./plugins/moveGroupAttrsToElems.js":349,"./plugins/prefixIds.js":350,"./plugins/removeAttributesBySelector.js":351,"./plugins/removeAttrs.js":352,"./plugins/removeComments.js":353,"./plugins/removeDesc.js":354,"./plugins/removeDimensions.js":355,"./plugins/removeDoctype.js":356,"./plugins/removeEditorsNSData.js":357,"./plugins/removeElementsByAttr.js":358,"./plugins/removeEmptyAttrs.js":359,"./plugins/removeEmptyContainers.js":360,"./plugins/removeEmptyText.js":361,"./plugins/removeHiddenElems.js":362,"./plugins/removeMetadata.js":363,"./plugins/removeNonInheritableGroupAttrs.js":364,"./plugins/removeOffCanvasPaths.js":365,"./plugins/removeRasterImages.js":366,"./plugins/removeScriptElement.js":367,"./plugins/removeStyleElement.js":368,"./plugins/removeTitle.js":369,"./plugins/removeUnknownsAndDefaults.js":370,"./plugins/removeUnusedNS.js":371,"./plugins/removeUselessDefs.js":372,"./plugins/removeUselessStrokeAndFill.js":373,"./plugins/removeViewBox.js":374,"./plugins/removeXMLNS.js":375,"./plugins/removeXMLProcInst.js":376,"./plugins/reusePaths.js":377,"./plugins/safe.js":378,"./plugins/safeAndFast.js":379,"./plugins/sortAttrs.js":380,"./plugins/sortDefsChildren.js":381}],321:[function(require,module,exports){
'use strict';
const isTag = (node) => {
@@ -30102,7 +30103,7 @@ const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => {
};
exports.stringifyPathData = stringifyPathData;
-},{"./tools.js":383}],324:[function(require,module,exports){
+},{"./tools.js":384}],324:[function(require,module,exports){
'use strict';
const { builtin } = require('./builtin.js');
@@ -33826,7 +33827,7 @@ const applyMatrixToPathData = (pathData, matrix) => {
}
};
-},{"../style.js":382,"../tools.js":383,"./_collections.js":325,"./_path.js":326,"./_transforms.js":327}],331:[function(require,module,exports){
+},{"../style.js":383,"../tools.js":384,"./_collections.js":325,"./_path.js":326,"./_transforms.js":327}],331:[function(require,module,exports){
'use strict';
exports.name = 'cleanupAttrs';
@@ -33948,7 +33949,7 @@ exports.fn = (root) => {
};
};
-},{"../xast.js":384}],333:[function(require,module,exports){
+},{"../xast.js":385}],333:[function(require,module,exports){
'use strict';
const { visitSkip } = require('../xast.js');
@@ -34207,7 +34208,7 @@ exports.fn = (_root, params) => {
};
};
-},{"../xast.js":384,"./_collections.js":325}],334:[function(require,module,exports){
+},{"../xast.js":385,"./_collections.js":325}],334:[function(require,module,exports){
'use strict';
const { removeLeadingZero } = require('../tools.js');
@@ -34345,7 +34346,7 @@ exports.fn = (_root, params) => {
};
};
-},{"../tools.js":383}],335:[function(require,module,exports){
+},{"../tools.js":384}],335:[function(require,module,exports){
'use strict';
const { removeLeadingZero } = require('../tools.js');
@@ -34451,7 +34452,7 @@ exports.fn = (_root, params) => {
};
};
-},{"../tools.js":383}],336:[function(require,module,exports){
+},{"../tools.js":384}],336:[function(require,module,exports){
'use strict';
const { inheritableAttrs, elemsGroups } = require('./_collections.js');
@@ -35838,7 +35839,7 @@ function data2Path(params, pathData) {
}, '');
}
-},{"../style.js":382,"../tools.js":383,"../xast.js":384,"./_collections.js":325,"./_path.js":326,"./applyTransforms.js":330}],340:[function(require,module,exports){
+},{"../style.js":383,"../tools.js":384,"../xast.js":385,"./_collections.js":325,"./_path.js":326,"./applyTransforms.js":330}],340:[function(require,module,exports){
'use strict';
const { stringifyPathData } = require('../path.js');
@@ -36004,7 +36005,7 @@ exports.fn = (root, params) => {
};
};
-},{"../path.js":323,"../xast.js":384}],341:[function(require,module,exports){
+},{"../path.js":323,"../xast.js":385}],341:[function(require,module,exports){
'use strict';
const { attrsGroups } = require('./_collections');
@@ -36506,7 +36507,7 @@ const smartRound = (precision, data) => {
return data;
};
-},{"../tools.js":383,"./_transforms.js":327}],343:[function(require,module,exports){
+},{"../tools.js":384,"./_transforms.js":327}],343:[function(require,module,exports){
'use strict';
const { createPreset } = require('../tools.js');
@@ -36590,7 +36591,7 @@ const presetDefault = createPreset({
module.exports = presetDefault;
-},{"../tools.js":383,"./cleanupAttrs.js":331,"./cleanupEnableBackground.js":332,"./cleanupIds.js":333,"./cleanupNumericValues.js":335,"./collapseGroups.js":336,"./convertColors.js":337,"./convertEllipseToCircle.js":338,"./convertPathData.js":339,"./convertShapeToPath.js":340,"./convertTransform.js":342,"./inlineStyles.js":344,"./mergePaths.js":345,"./mergeStyles.js":346,"./minifyStyles.js":347,"./moveElemsAttrsToGroup.js":348,"./moveGroupAttrsToElems.js":349,"./removeComments.js":353,"./removeDesc.js":354,"./removeDoctype.js":356,"./removeEditorsNSData.js":357,"./removeEmptyAttrs.js":359,"./removeEmptyContainers.js":360,"./removeEmptyText.js":361,"./removeHiddenElems.js":362,"./removeMetadata.js":363,"./removeNonInheritableGroupAttrs.js":364,"./removeTitle.js":369,"./removeUnknownsAndDefaults.js":370,"./removeUnusedNS.js":371,"./removeUselessDefs.js":372,"./removeUselessStrokeAndFill.js":373,"./removeViewBox.js":374,"./removeXMLProcInst.js":376,"./sortAttrs.js":379,"./sortDefsChildren.js":380}],344:[function(require,module,exports){
+},{"../tools.js":384,"./cleanupAttrs.js":331,"./cleanupEnableBackground.js":332,"./cleanupIds.js":333,"./cleanupNumericValues.js":335,"./collapseGroups.js":336,"./convertColors.js":337,"./convertEllipseToCircle.js":338,"./convertPathData.js":339,"./convertShapeToPath.js":340,"./convertTransform.js":342,"./inlineStyles.js":344,"./mergePaths.js":345,"./mergeStyles.js":346,"./minifyStyles.js":347,"./moveElemsAttrsToGroup.js":348,"./moveGroupAttrsToElems.js":349,"./removeComments.js":353,"./removeDesc.js":354,"./removeDoctype.js":356,"./removeEditorsNSData.js":357,"./removeEmptyAttrs.js":359,"./removeEmptyContainers.js":360,"./removeEmptyText.js":361,"./removeHiddenElems.js":362,"./removeMetadata.js":363,"./removeNonInheritableGroupAttrs.js":364,"./removeTitle.js":369,"./removeUnknownsAndDefaults.js":370,"./removeUnusedNS.js":371,"./removeUselessDefs.js":372,"./removeUselessStrokeAndFill.js":373,"./removeViewBox.js":374,"./removeXMLProcInst.js":376,"./sortAttrs.js":380,"./sortDefsChildren.js":381}],344:[function(require,module,exports){
'use strict';
const csstree = require('css-tree');
@@ -36937,7 +36938,7 @@ exports.fn = (root, params) => {
};
};
-},{"../xast.js":384,"css-tree":25,"csso":138}],345:[function(require,module,exports){
+},{"../xast.js":385,"css-tree":25,"csso":138}],345:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -37035,7 +37036,7 @@ exports.fn = (root, params) => {
};
};
-},{"../style.js":382,"../xast.js":384,"./_path.js":326}],346:[function(require,module,exports){
+},{"../style.js":383,"../xast.js":385,"./_path.js":326}],346:[function(require,module,exports){
'use strict';
const { visitSkip, detachNodeFromParent } = require('../xast.js');
@@ -37119,7 +37120,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],347:[function(require,module,exports){
+},{"../xast.js":385}],347:[function(require,module,exports){
'use strict';
const csso = require('csso');
@@ -37364,7 +37365,7 @@ exports.fn = (root) => {
};
};
-},{"../xast.js":384,"./_collections.js":325}],349:[function(require,module,exports){
+},{"../xast.js":385,"./_collections.js":325}],349:[function(require,module,exports){
'use strict';
const { pathElems, referencesProps } = require('./_collections.js');
@@ -37742,7 +37743,7 @@ exports.fn = (root, params) => {
return {};
};
-},{"../xast.js":384}],352:[function(require,module,exports){
+},{"../xast.js":385}],352:[function(require,module,exports){
'use strict';
exports.name = 'removeAttrs';
@@ -37924,7 +37925,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],354:[function(require,module,exports){
+},{"../xast.js":385}],354:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -37963,7 +37964,7 @@ exports.fn = (root, params) => {
};
};
-},{"../xast.js":384}],355:[function(require,module,exports){
+},{"../xast.js":385}],355:[function(require,module,exports){
'use strict';
exports.name = 'removeDimensions';
@@ -38046,7 +38047,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],357:[function(require,module,exports){
+},{"../xast.js":385}],357:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38110,7 +38111,7 @@ exports.fn = (_root, params) => {
};
};
-},{"../xast.js":384,"./_collections.js":325}],358:[function(require,module,exports){
+},{"../xast.js":385,"./_collections.js":325}],358:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38183,7 +38184,7 @@ exports.fn = (root, params) => {
};
};
-},{"../xast.js":384}],359:[function(require,module,exports){
+},{"../xast.js":385}],359:[function(require,module,exports){
'use strict';
const { attrsGroups } = require('./_collections.js');
@@ -38270,7 +38271,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384,"./_collections.js":325}],361:[function(require,module,exports){
+},{"../xast.js":385,"./_collections.js":325}],361:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38321,7 +38322,7 @@ exports.fn = (root, params) => {
};
};
-},{"../xast.js":384}],362:[function(require,module,exports){
+},{"../xast.js":385}],362:[function(require,module,exports){
'use strict';
const {
@@ -38631,7 +38632,7 @@ exports.fn = (root, params) => {
};
};
-},{"../path.js":323,"../style.js":382,"../xast.js":384}],363:[function(require,module,exports){
+},{"../path.js":323,"../style.js":383,"../xast.js":385}],363:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38658,7 +38659,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],364:[function(require,module,exports){
+},{"../xast.js":385}],364:[function(require,module,exports){
'use strict';
const {
@@ -38815,7 +38816,7 @@ exports.fn = () => {
};
};
-},{"../path.js":323,"../xast.js":384,"./_path.js":326}],366:[function(require,module,exports){
+},{"../path.js":323,"../xast.js":385,"./_path.js":326}],366:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38846,7 +38847,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],367:[function(require,module,exports){
+},{"../xast.js":385}],367:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38873,7 +38874,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],368:[function(require,module,exports){
+},{"../xast.js":385}],368:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38900,7 +38901,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],369:[function(require,module,exports){
+},{"../xast.js":385}],369:[function(require,module,exports){
'use strict';
const { detachNodeFromParent } = require('../xast.js');
@@ -38927,7 +38928,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],370:[function(require,module,exports){
+},{"../xast.js":385}],370:[function(require,module,exports){
'use strict';
const { visitSkip, detachNodeFromParent } = require('../xast.js');
@@ -39135,7 +39136,7 @@ exports.fn = (root, params) => {
};
};
-},{"../style.js":382,"../xast.js":384,"./_collections":325}],371:[function(require,module,exports){
+},{"../style.js":383,"../xast.js":385,"./_collections":325}],371:[function(require,module,exports){
'use strict';
exports.name = 'removeUnusedNS';
@@ -39252,7 +39253,7 @@ const collectUsefulNodes = (node, usefulNodes) => {
}
};
-},{"../xast.js":384,"./_collections.js":325}],373:[function(require,module,exports){
+},{"../xast.js":385,"./_collections.js":325}],373:[function(require,module,exports){
'use strict';
const { visit, visitSkip, detachNodeFromParent } = require('../xast.js');
@@ -39390,7 +39391,7 @@ exports.fn = (root, params) => {
};
};
-},{"../style.js":382,"../xast.js":384,"./_collections.js":325}],374:[function(require,module,exports){
+},{"../style.js":383,"../xast.js":385,"./_collections.js":325}],374:[function(require,module,exports){
'use strict';
exports.name = 'removeViewBox';
@@ -39497,7 +39498,7 @@ exports.fn = () => {
};
};
-},{"../xast.js":384}],377:[function(require,module,exports){
+},{"../xast.js":385}],377:[function(require,module,exports){
'use strict';
exports.name = 'reusePaths';
@@ -39678,7 +39679,72 @@ const presetSafe = createPreset({
module.exports = presetSafe;
-},{"../tools.js":383,"./cleanupAttrs.js":331,"./cleanupEnableBackground.js":332,"./cleanupIds.js":333,"./cleanupNumericValues.js":335,"./collapseGroups.js":336,"./convertColors.js":337,"./convertEllipseToCircle.js":338,"./convertPathData.js":339,"./convertTransform.js":342,"./inlineStyles.js":344,"./mergePaths.js":345,"./mergeStyles.js":346,"./minifyStyles.js":347,"./removeComments.js":353,"./removeDesc.js":354,"./removeDoctype.js":356,"./removeEditorsNSData.js":357,"./removeEmptyAttrs.js":359,"./removeEmptyContainers.js":360,"./removeEmptyText.js":361,"./removeHiddenElems.js":362,"./removeMetadata.js":363,"./removeNonInheritableGroupAttrs.js":364,"./removeTitle.js":369,"./removeUnknownsAndDefaults.js":370,"./removeUnusedNS.js":371,"./removeUselessDefs.js":372,"./removeUselessStrokeAndFill.js":373,"./removeViewBox.js":374,"./removeXMLProcInst.js":376,"./sortDefsChildren.js":380}],379:[function(require,module,exports){
+},{"../tools.js":384,"./cleanupAttrs.js":331,"./cleanupEnableBackground.js":332,"./cleanupIds.js":333,"./cleanupNumericValues.js":335,"./collapseGroups.js":336,"./convertColors.js":337,"./convertEllipseToCircle.js":338,"./convertPathData.js":339,"./convertTransform.js":342,"./inlineStyles.js":344,"./mergePaths.js":345,"./mergeStyles.js":346,"./minifyStyles.js":347,"./removeComments.js":353,"./removeDesc.js":354,"./removeDoctype.js":356,"./removeEditorsNSData.js":357,"./removeEmptyAttrs.js":359,"./removeEmptyContainers.js":360,"./removeEmptyText.js":361,"./removeHiddenElems.js":362,"./removeMetadata.js":363,"./removeNonInheritableGroupAttrs.js":364,"./removeTitle.js":369,"./removeUnknownsAndDefaults.js":370,"./removeUnusedNS.js":371,"./removeUselessDefs.js":372,"./removeUselessStrokeAndFill.js":373,"./removeViewBox.js":374,"./removeXMLProcInst.js":376,"./sortDefsChildren.js":381}],379:[function(require,module,exports){
+'use strict';
+
+const { createPreset } = require('../tools.js');
+
+const removeDoctype = require('./removeDoctype.js');
+const removeXMLProcInst = require('./removeXMLProcInst.js');
+const removeComments = require('./removeComments.js');
+const removeMetadata = require('./removeMetadata.js');
+const removeEditorsNSData = require('./removeEditorsNSData.js');
+const cleanupAttrs = require('./cleanupAttrs.js');
+const mergeStyles = require('./mergeStyles.js');
+const minifyStyles = require('./minifyStyles.js');
+const cleanupIds = require('./cleanupIds.js');
+const removeUselessDefs = require('./removeUselessDefs.js');
+const cleanupNumericValues = require('./cleanupNumericValues.js');
+const convertColors = require('./convertColors.js');
+const removeUnknownsAndDefaults = require('./removeUnknownsAndDefaults.js');
+const removeNonInheritableGroupAttrs = require('./removeNonInheritableGroupAttrs.js');
+const removeUselessStrokeAndFill = require('./removeUselessStrokeAndFill.js');
+const removeViewBox = require('./removeViewBox.js');
+const cleanupEnableBackground = require('./cleanupEnableBackground.js');
+const removeHiddenElems = require('./removeHiddenElems.js');
+const removeEmptyText = require('./removeEmptyText.js');
+const collapseGroups = require('./collapseGroups.js');
+const removeEmptyAttrs = require('./removeEmptyAttrs.js');
+const removeEmptyContainers = require('./removeEmptyContainers.js');
+const mergePaths = require('./mergePaths.js');
+const removeUnusedNS = require('./removeUnusedNS.js');
+const sortDefsChildren = require('./sortDefsChildren.js');
+const removeTitle = require('./removeTitle.js');
+const removeDesc = require('./removeDesc.js');
+
+const presetSafe = createPreset({
+ name: 'safeAndFastPreset',
+ plugins: [
+ removeDoctype,
+ removeXMLProcInst,
+ removeComments,
+ removeMetadata,
+ removeEditorsNSData,
+ cleanupAttrs,
+ mergeStyles,
+ cleanupIds,
+ removeUselessDefs,
+ cleanupNumericValues,
+ convertColors,
+ removeUnknownsAndDefaults,
+ removeNonInheritableGroupAttrs,
+ removeUselessStrokeAndFill,
+ removeViewBox,
+ cleanupEnableBackground,
+ removeHiddenElems,
+ removeEmptyText,
+ collapseGroups,
+ removeEmptyAttrs,
+ removeEmptyContainers,
+ removeUnusedNS,
+ removeTitle,
+ removeDesc,
+ ],
+});
+
+module.exports = presetSafe;
+
+},{"../tools.js":384,"./cleanupAttrs.js":331,"./cleanupEnableBackground.js":332,"./cleanupIds.js":333,"./cleanupNumericValues.js":335,"./collapseGroups.js":336,"./convertColors.js":337,"./mergePaths.js":345,"./mergeStyles.js":346,"./minifyStyles.js":347,"./removeComments.js":353,"./removeDesc.js":354,"./removeDoctype.js":356,"./removeEditorsNSData.js":357,"./removeEmptyAttrs.js":359,"./removeEmptyContainers.js":360,"./removeEmptyText.js":361,"./removeHiddenElems.js":362,"./removeMetadata.js":363,"./removeNonInheritableGroupAttrs.js":364,"./removeTitle.js":369,"./removeUnknownsAndDefaults.js":370,"./removeUnusedNS.js":371,"./removeUselessDefs.js":372,"./removeUselessStrokeAndFill.js":373,"./removeViewBox.js":374,"./removeXMLProcInst.js":376,"./sortDefsChildren.js":381}],380:[function(require,module,exports){
'use strict';
exports.name = 'sortAttrs';
@@ -39778,7 +39844,7 @@ exports.fn = (_root, params) => {
};
};
-},{}],380:[function(require,module,exports){
+},{}],381:[function(require,module,exports){
'use strict';
exports.name = 'sortDefsChildren';
@@ -39836,7 +39902,7 @@ exports.fn = () => {
};
};
-},{}],381:[function(require,module,exports){
+},{}],382:[function(require,module,exports){
'use strict';
const { textElems } = require('./plugins/_collections.js');
@@ -40070,7 +40136,7 @@ const stringifyText = (node, config, state) => {
);
};
-},{"./plugins/_collections.js":325}],382:[function(require,module,exports){
+},{"./plugins/_collections.js":325}],383:[function(require,module,exports){
'use strict';
const csstree = require('css-tree');
@@ -40300,7 +40366,7 @@ const computeStyle = (stylesheet, node) => {
};
exports.computeStyle = computeStyle;
-},{"./plugins/_collections.js":325,"./xast.js":384,"css-tree":25,"csso":138}],383:[function(require,module,exports){
+},{"./plugins/_collections.js":325,"./xast.js":385,"css-tree":25,"csso":138}],384:[function(require,module,exports){
(function (Buffer){(function (){
'use strict';
@@ -40455,7 +40521,7 @@ exports.invokePlugins = invokePlugins;
exports.createPreset = createPreset;
}).call(this)}).call(this,require("buffer").Buffer)
-},{"./xast.js":384,"buffer":4}],384:[function(require,module,exports){
+},{"./xast.js":385,"buffer":4}],385:[function(require,module,exports){
'use strict';
const { selectAll, selectOne, is } = require('css-select');
diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc
index a7f060391e..3d5cb31c43 100644
--- a/common/src/app/common/types/container.cljc
+++ b/common/src/app/common/types/container.cljc
@@ -255,7 +255,11 @@
(dissoc :component-root)))
[new-root-shape new-shapes updated-shapes]
- (ctst/clone-object shape nil objects update-new-shape update-original-shape)
+ (ctst/clone-shape shape
+ nil
+ objects
+ :update-new-shape update-new-shape
+ :update-original-shape update-original-shape)
;; If frame-id points to a shape inside the component, remap it to the
;; corresponding new frame shape. If not, set it to nil.
@@ -339,15 +343,14 @@
(dissoc :component-root))))
[new-shape new-shapes _]
- (ctst/clone-object component-shape
- frame-id
- (if components-v2 (:objects component-page) (:objects component))
- update-new-shape
- (fn [object _] object)
- force-id
- keep-ids?
- frame-id)
-
+ (ctst/clone-shape component-shape
+ frame-id
+ (if components-v2 (:objects component-page) (:objects component))
+ :update-new-shape update-new-shape
+ :force-id force-id
+ :keep-ids? keep-ids?
+ :frame-id frame-id
+ :dest-objects (:objects container))
;; Fix empty parent-id and remap all grid cells to the new ids.
remap-ids
diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc
index 30a866b76a..745cd941e4 100644
--- a/common/src/app/common/types/shape/layout.cljc
+++ b/common/src/app/common/types/shape/layout.cljc
@@ -327,6 +327,20 @@
[pad-top pad-right pad-top pad-right]
[pad-top pad-right pad-bottom pad-left])))
+(defn h-padding
+ [{:keys [layout-padding-type layout-padding]}]
+ (let [{pad-right :p2 pad-left :p4} layout-padding]
+ (if (= :simple layout-padding-type)
+ (+ pad-right pad-right)
+ (+ pad-right pad-left))))
+
+(defn v-padding
+ [{:keys [layout-padding-type layout-padding]}]
+ (let [{pad-top :p1 pad-bottom :p3} layout-padding]
+ (if (= :simple layout-padding-type)
+ (+ pad-top pad-top)
+ (+ pad-top pad-bottom))))
+
(defn child-min-width
[child]
(if (and (fill-width? child)
@@ -590,7 +604,8 @@
(declare assign-cells)
(def default-track-value
- {:type :auto})
+ {:type :flex
+ :value 1})
(def grid-cell-defaults
{:row-span 1
@@ -600,53 +615,225 @@
:justify-self :auto
:shapes []})
+(declare resize-cell-area)
+(declare cells-by-column)
+(declare cells-by-row)
+
+(defn remove-cell-areas
+ "Remove the areas in the given `index` before and after the index"
+ [parent prop index]
+ (let [prop-span (if (= prop :column) :column-span :row-span)
+ cells (if (= prop :column) (cells-by-column parent index) (cells-by-row parent index))]
+ (->> cells
+ (filter #(> (get % prop-span) 1))
+ (reduce
+ (fn [parent cell]
+ (let [area? (= :area (:position cell))
+ changed-cells
+ (cond
+ ;; New track at the beginning
+ (= (get cell prop) (inc index))
+ [(assoc cell prop-span 1)
+ (-> cell
+ (assoc :id (uuid/next) :shapes [] prop (inc (get cell prop)) prop-span (dec (get cell prop-span)))
+ (dissoc :area-name)
+ (cond-> area? (assoc :position :manual)))]
+
+ ;; New track at the middle
+ (< (get cell prop) (inc index) (+ (get cell prop) (dec (get cell prop-span))))
+ [(assoc cell prop-span (- (inc index) (get cell prop)))
+ (-> cell
+ (assoc :id (uuid/next) :shapes [] prop (inc index) prop-span 1)
+ (dissoc :area-name)
+ (cond-> area? (assoc :position :manual)))
+ (-> cell
+ (assoc :id (uuid/next) :shapes [] prop (+ index 2) prop-span (- (+ (get cell prop) (dec (get cell prop-span))) (inc index)))
+ (dissoc :area-name)
+ (cond-> area? (assoc :position :manual)))]
+
+ ;; New track at the end
+ (= (+ (get cell prop) (dec (get cell prop-span))) (inc index))
+ [(assoc cell prop-span (- (inc index) (get cell prop)))
+ (-> cell
+ (assoc :id (uuid/next) :shapes [] prop (inc index) prop-span 1)
+ (dissoc :area-name)
+ (cond-> area? (assoc :position :manual)))])]
+
+ (->> changed-cells
+ (reduce #(update %1 :layout-grid-cells assoc (:id %2) %2) parent))))
+ parent))))
+
+(defn remove-cell-areas-after
+ "Remove the areas in the given `index` but only after the index."
+ [parent prop index]
+ (let [prop-span (if (= prop :column) :column-span :row-span)
+ cells (if (= prop :column) (cells-by-column parent index) (cells-by-row parent index))]
+ (->> cells
+ (filter #(> (get % prop-span) 1))
+ (reduce
+ (fn [parent cell]
+ (let [area? (= :area (:position cell))
+ changed-cells
+ (cond
+ ;; New track at the beginning
+ (= (get cell prop) (inc index))
+ [(assoc cell prop-span 1)
+ (-> cell
+ (assoc :id (uuid/next) :shapes [] prop (inc (get cell prop)) prop-span (dec (get cell prop-span)))
+ (dissoc :area-name)
+ (cond-> area? (assoc :position :manual)))]
+
+ ;; New track at the middle
+ (< (get cell prop) (inc index) (+ (get cell prop) (dec (get cell prop-span))))
+ [(assoc cell prop-span (- (+ index 2) (get cell prop)))
+ (-> cell
+ (assoc :id (uuid/next) :shapes [] prop (+ index 2) prop-span (- (+ (get cell prop) (dec (get cell prop-span))) (inc index)))
+ (dissoc :area-name)
+ (cond-> area? (assoc :position :manual)))])]
+ (->> changed-cells
+ (reduce #(update %1 :layout-grid-cells assoc (:id %2) %2) parent))))
+ parent))))
+
;; Adding a track creates the cells. We should check the shapes that are not tracked (with default values) and assign to the correct tracked values
+
+(defn add-grid-track
+ ([type parent value]
+ (add-grid-track type parent value nil))
+ ([type parent value index]
+ (dm/assert!
+ "expected a valid grid definition for `value`"
+ (check-grid-track! value))
+
+ (let [[tracks-prop tracks-prop-other prop prop-other prop-span prop-span-other]
+ (if (= type :column)
+ [:layout-grid-columns :layout-grid-rows :column :row :column-span :row-span]
+ [:layout-grid-rows :layout-grid-columns :row :column :row-span :column-span])
+
+ new-index (d/nilv index (count (get parent tracks-prop)))
+ new-track-num (inc new-index)
+
+ ;; Increase the values for the existing cells
+ layout-grid-cells
+ (-> (:layout-grid-cells parent)
+ (update-vals
+ (fn [cell]
+ (cond-> cell
+ (>= (get cell prop) new-track-num)
+ (update prop inc)
+
+ (and (< (get cell prop) new-track-num)
+ (> (get cell prop-span) 1)
+ (>= (+ (get cell prop) (dec (get cell prop-span))) new-track-num))
+ (update prop-span inc)))))
+
+ ;; Search for the cells already created
+ exist-cells?
+ (into #{}
+ (comp (filter
+ (fn [cell]
+ (and (>= new-track-num (get cell prop))
+ (< new-track-num (+ (get cell prop) (get cell prop-span))))))
+ (mapcat #(range (get % prop-other) (+ (get % prop-other) (get % prop-span-other)))))
+ (vals layout-grid-cells))
+
+ ;; Create the new cells as necesary
+ layout-grid-cells
+ (->> (d/enumerate (get parent tracks-prop-other))
+ (remove (fn [[idx _]] (exist-cells? (inc idx))))
+ (reduce
+ (fn [result [idx _]]
+ (let [id (uuid/next)]
+ (assoc result id
+ (merge {:id id
+ prop-other (inc idx)
+ prop new-track-num}
+ grid-cell-defaults))))
+ layout-grid-cells))]
+
+ (-> parent
+ (update tracks-prop d/add-at-index new-index value)
+ (assoc :layout-grid-cells layout-grid-cells)))))
+
(defn add-grid-column
- [parent value]
- (dm/assert!
- "expected a valid grid definition for `value`"
- (check-grid-track! value))
-
- (let [rows (:layout-grid-rows parent)
- new-col-num (inc (count (:layout-grid-columns parent)))
-
- layout-grid-cells
- (->> (d/enumerate rows)
- (reduce (fn [result [row-idx _]]
- (let [id (uuid/next)]
- (assoc result id
- (merge {:id id
- :row (inc row-idx)
- :column new-col-num}
- grid-cell-defaults))))
- (:layout-grid-cells parent)))]
- (-> parent
- (update :layout-grid-columns (fnil conj []) value)
- (assoc :layout-grid-cells layout-grid-cells))))
+ ([parent value]
+ (add-grid-column parent value nil))
+ ([parent value index]
+ (add-grid-track :column parent value index)))
(defn add-grid-row
- [parent value]
- (dm/assert!
- "expected a valid grid definition for `value`"
- (check-grid-track! value))
+ ([parent value]
+ (add-grid-row parent value nil))
+ ([parent value index]
+ (add-grid-track :row parent value index)))
- (let [cols (:layout-grid-columns parent)
- new-row-num (inc (count (:layout-grid-rows parent)))
+(defn- duplicate-cells
+ [shape prop from-index to-index ids-map]
- layout-grid-cells
- (->> (d/enumerate cols)
- (reduce (fn [result [col-idx _]]
- (let [id (uuid/next)]
- (assoc result id
- (merge {:id id
- :column (inc col-idx)
- :row new-row-num}
- grid-cell-defaults))))
- (:layout-grid-cells parent)))]
- (-> parent
- (update :layout-grid-rows (fnil conj []) value)
- (assoc :layout-grid-cells layout-grid-cells))))
+ (let [[prop-span prop-other prop-other-span]
+ (if (= prop :column)
+ [:column-span :row :row-span]
+ [:row-span :column :column-span])
+ from-cells
+ (if (= prop :column)
+ (cells-by-column shape from-index)
+ (cells-by-row shape from-index))
+
+ to-cells
+ (if (= prop :column)
+ (cells-by-column shape to-index)
+ (cells-by-row shape to-index))
+
+ to-cells-idx (d/index-by prop-other to-cells)
+
+ ;; This loop will go throught the original cells and copy their data to the target cell
+ ;; After this some cells could have no correspondence and should be removed
+ [shape matched]
+ (loop [from-cells (seq from-cells)
+ matched #{}
+ result shape]
+ (if-let [cell (first from-cells)]
+ (let [match-cell
+ (-> (get to-cells-idx (get cell prop-other))
+ (d/patch-object (select-keys cell [prop-other-span :position :align-self :justify-self]))
+ (cond-> (= :area (:position cell))
+ (assoc :position :manual))
+ (cond-> (= (get cell prop-span) 1)
+ (assoc :shapes (mapv ids-map (:shapes cell)))))]
+ (recur (rest from-cells)
+ (conj matched (:id match-cell))
+ (assoc-in result [:layout-grid-cells (:id match-cell)] match-cell)))
+
+ [result matched]))
+
+ ;; Remove cells that haven't been matched
+ shape
+ (->> to-cells
+ (remove (fn [{:keys [id]}] (contains? matched id)))
+ (reduce (fn [shape cell]
+ (update shape :layout-grid-cells dissoc (:id cell)))
+ shape))]
+
+ shape))
+
+
+(defn duplicate-row
+ [shape objects index ids-map]
+ (let [value (dm/get-in shape [:layout-grid-rows index])]
+ (-> shape
+ (remove-cell-areas-after :row index)
+ (add-grid-row value (inc index))
+ (duplicate-cells :row index (inc index) ids-map)
+ (assign-cells objects))))
+
+(defn duplicate-column
+ [shape objects index ids-map]
+ (let [value (dm/get-in shape [:layout-grid-columns index])]
+ (-> shape
+ (remove-cell-areas-after :column index)
+ (add-grid-column value (inc index))
+ (duplicate-cells :column index (inc index) ids-map)
+ (assign-cells objects))))
(defn make-remove-cell
[attr span-attr track-num]
@@ -747,12 +934,9 @@
update-vals
(fn [cell] (update cell prop #(get remap-tracks % %)))))))
-(declare resize-cell-area)
-(declare cells-by-column)
-(declare cells-by-row)
(defn- reorder-grid-track
- [parent from-index to-index move-content? cells-by tracks-props prop prop-span]
+ [parent from-index to-index move-content? tracks-props prop]
(let [from-track (inc from-index)
to-track (if (< to-index from-index)
(+ to-index 2)
@@ -761,23 +945,10 @@
(and move-content? (not= from-track to-track))
parent
- (if move-content?
- (->> (concat (cells-by parent (dec from-track))
- (cells-by parent (dec to-track)))
- (reduce (fn [parent cell]
- (cond-> parent
- (and (> (get cell prop-span) 1)
- (or (> to-track from-track) (not (= to-track (get cell prop))))
- (or (< to-track from-track) (not (= to-track (+ (get cell prop) (dec (get cell prop-span)))))))
- (resize-cell-area
- (:row cell)
- (:column cell)
- (:row cell)
- (:column cell)
- (if (= prop :row) 1 (:row-span cell))
- (if (= prop :column) 1 (:column-span cell)))))
- parent))
- parent)
+ (cond-> parent
+ move-content?
+ (-> (remove-cell-areas prop from-index)
+ (remove-cell-areas-after prop to-index)))
parent
(reorder-grid-tracks parent tracks-props from-index to-index)]
@@ -788,11 +959,11 @@
(defn reorder-grid-column
[parent from-index to-index move-content?]
- (reorder-grid-track parent from-index to-index move-content? cells-by-column :layout-grid-columns :column :column-span))
+ (reorder-grid-track parent from-index to-index move-content? :layout-grid-columns :column))
(defn reorder-grid-row
[parent from-index to-index move-content?]
- (reorder-grid-track parent from-index to-index move-content? cells-by-row :layout-grid-rows :row :row-span))
+ (reorder-grid-track parent from-index to-index move-content? :layout-grid-rows :row))
(defn cells-seq
[{:keys [layout-grid-cells layout-grid-dir]} & {:keys [sort?] :or {sort? false}}]
@@ -877,6 +1048,41 @@
parent
overlaps))
+(defn reassign-positions
+ "Propagate the manual positioning to the following cells"
+ [parent]
+ (->> (cells-seq parent :sort? true)
+ (reduce
+ (fn [[parent auto?] cell]
+
+ (let [[cell auto?]
+ (cond
+ (and (empty? (:shapes cell))
+ (= :manual (:position cell))
+ (= (:row-span cell) 1)
+ (= (:column-span cell) 1))
+ [(assoc cell :position :auto) false]
+
+ (and (or (not= (:row-span cell) 1)
+ (not= (:column-span cell) 1))
+ (= :auto (:position cell)))
+ [(assoc cell :position :manual) false]
+
+ (empty? (:shapes cell))
+ [cell false]
+
+ (and (not auto?) (= :auto (:position cell)))
+ [(assoc cell :position :manual) false]
+
+ (= :manual (:position cell))
+ [cell false]
+
+ :else
+ [cell auto?])]
+ [(assoc-in parent [:layout-grid-cells (:id cell)] cell) auto?]))
+ [parent true])
+ (first)))
+
(defn position-auto-shapes
[parent]
;; Iterate through the cells. While auto and contains shape no changes.
@@ -903,6 +1109,14 @@
(rest shapes)))))]
parent))
+(defn assign-cell-positions
+ [parent objects]
+ (prn ">>>>assign-cell-positions" (:name parent))
+ (-> parent
+ (check-deassigned-cells objects)
+ (reassign-positions)
+ (position-auto-shapes)))
+
;; Assign cells takes the children and move them into the allotted cells. If there are not enough cells it creates
;; not-tracked rows/columns and put the shapes there
;; Non-tracked tracks need to be deleted when they are empty and there are no more shapes unallocated
@@ -914,13 +1128,10 @@
;; - (maybe) create group/frames. This case will assigna a cell that had one of its children
(defn assign-cells
[parent objects]
- (let [;; TODO: Remove this, shouldn't be happening
- ;;overlaps (overlapping-cells parent)
- ;;_ (when (not (empty? overlaps))
- ;; (.warn js/console "OVERLAPS" overlaps))
- parent (cond-> (check-deassigned-cells parent objects)
- #_(d/not-empty? overlaps)
- #_(fix-overlaps overlaps))
+ (prn ">assign-cells")
+ (let [
+
+ parent (assign-cell-positions parent objects)
shape-has-cell?
(into #{} (mapcat (comp :shapes second)) (:layout-grid-cells parent))
@@ -928,9 +1139,7 @@
no-cell-shapes
(->> (:shapes parent)
(remove shape-has-cell?)
- (remove (partial position-absolute? objects)))
-
- parent (position-auto-shapes parent)]
+ (remove (partial position-absolute? objects)))]
(if (empty? no-cell-shapes)
;; All shapes are within a cell. No need to assign
@@ -1080,6 +1289,7 @@
target-cell
(-> prev-cell
(assoc
+ :position :manual
:row new-row
:column new-column
:row-span new-row-span
@@ -1224,30 +1434,64 @@
(assoc parent :shapes (into [] (reverse new-shapes)))))
(defn cells-by-row
- [parent index]
- (->> (:layout-grid-cells parent)
- (filter (fn [[_ {:keys [row row-span]}]]
- (and (>= (inc index) row)
- (< (inc index) (+ row row-span)))))
- (map second)))
+ ([parent index]
+ (cells-by-row parent index true))
+ ([parent index check-span?]
+ (->> (:layout-grid-cells parent)
+ (vals)
+ (filter
+ (fn [{:keys [row row-span]}]
+ (if check-span?
+ (and (>= (inc index) row)
+ (< (inc index) (+ row row-span)))
+ (= (inc index) row)))))))
(defn cells-by-column
- [parent index]
+ ([parent index]
+ (cells-by-column parent index true))
+ ([parent index check-span?]
+ (->> (:layout-grid-cells parent)
+ (vals)
+ (filter
+ (fn [{:keys [column column-span] :as cell}]
+ (if check-span?
+ (and (>= (inc index) column)
+ (< (inc index) (+ column column-span)))
+ (= (inc index) column)))))))
+
+(defn cells-in-area
+ [parent first-row last-row first-column last-column]
(->> (:layout-grid-cells parent)
- (filter (fn [[_ {:keys [column column-span]}]]
- (and (>= (inc index) column)
- (< (inc index) (+ column column-span)))))
- (map second)))
+ (vals)
+ (filter
+ (fn [{:keys [row column row-span column-span] :as cell}]
+ (and
+ (or (<= row first-row (+ row row-span -1))
+ (<= row last-row (+ row row-span -1))
+ (<= first-row row last-row)
+ (<= first-row (+ row row-span -1) last-row))
+
+ (or (<= column first-column (+ column column-span -1))
+ (<= column last-column (+ column column-span -1))
+ (<= first-column column last-column)
+ (<= first-column (+ column column-span -1) last-column)))))))
(defn shapes-by-row
- [parent index]
- (->> (cells-by-row parent index)
- (mapcat :shapes)))
+ "Find all the shapes for a given row"
+ ([parent index]
+ (shapes-by-row parent index true))
+ ;; check-span? if false will only see if there is a coincidence in file&row
+ ([parent index check-span?]
+ (->> (cells-by-row parent index check-span?)
+ (mapcat :shapes))))
(defn shapes-by-column
- [parent index]
- (->> (cells-by-column parent index)
- (mapcat :shapes)))
+ "Find all the shapes for a given column"
+ ([parent index]
+ (shapes-by-column parent index true))
+ ([parent index check-span?]
+ (->> (cells-by-column parent index check-span?)
+ (mapcat :shapes))))
(defn cells-coordinates
"Given a group of cells returns the coordinates that define"
@@ -1300,7 +1544,6 @@
(defn valid-area-cells?
[cells]
-
(let [{:keys [first-row last-row first-column last-column cell-coords]} (cells-coordinates cells)]
(every?
#(contains? cell-coords %)
@@ -1309,7 +1552,7 @@
[r c]))))
(defn remap-grid-cells
- "Remaps the shapes inside the cells"
+ "Remaps the shapes ids inside the cells"
[shape ids-map]
(let [do-remap-cells
(fn [cell]
diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc
index 928a5ed664..ab6f08e41b 100644
--- a/common/src/app/common/types/shape_tree.cljc
+++ b/common/src/app/common/types/shape_tree.cljc
@@ -342,91 +342,89 @@
[frame]
(not (mth/almost-zero? (:rotation frame 0))))
-(defn clone-object
- "Gets a copy of the object and all its children, with new ids and with
+(defn clone-shape
+ "Gets a copy of the shape and all its children, with new ids and with
the parent-children links correctly set. Admits functions to make
- more transformations to the cloned objects and the original ones.
+ more transformations to the cloned shapes and the original ones.
- Returns the cloned object, the list of all new objects (including
- the cloned one), and possibly a list of original objects modified.
+ Returns the cloned shape, the list of all new shapes (including
+ the cloned one), and possibly a list of original shapes modified.
- The list of objects are returned in tree traversal order, respecting
+ The list of shapes are returned in tree traversal order, respecting
the order of the children of each parent."
-
- ([object parent-id objects]
- (clone-object object parent-id objects (fn [object _] object) (fn [object _] object) nil false nil))
-
- ([object parent-id objects update-new-object]
- (clone-object object parent-id objects update-new-object (fn [object _] object) nil false nil))
-
- ([object parent-id objects update-new-object update-original-object]
- (clone-object object parent-id objects update-new-object update-original-object nil false nil))
-
- ([object parent-id objects update-new-object update-original-object force-id]
- (clone-object object parent-id objects update-new-object update-original-object force-id false nil))
-
- ([object parent-id objects update-new-object update-original-object force-id keep-ids?]
- (clone-object object parent-id objects update-new-object update-original-object force-id keep-ids? nil))
-
- ([object parent-id objects update-new-object update-original-object force-id keep-ids? frame-id]
- (let [new-id (cond
- (some? force-id) force-id
- keep-ids? (:id object)
- :else (uuid/next))
+ [shape parent-id objects & {:keys [update-new-shape update-original-shape force-id keep-ids? frame-id dest-objects]
+ :or {update-new-shape (fn [shape _] shape)
+ update-original-shape (fn [shape _] shape)
+ force-id nil
+ keep-ids? false
+ frame-id nil
+ dest-objects objects}}]
+ (let [new-id (cond
+ (some? force-id) force-id
+ keep-ids? (:id shape)
+ :else (uuid/next))
;; Assign the correct frame-id for the given parent. It's the parent-id (if parent is frame)
;; or the parent's frame-id otherwise. Only for the first cloned shapes. In recursive calls
;; this is not needed.
- frame-id (cond
- (and (nil? frame-id) (cfh/frame-shape? objects parent-id))
- parent-id
+ frame-id (cond
+ (and (nil? frame-id) (cfh/frame-shape? dest-objects parent-id))
+ parent-id
- (nil? frame-id)
- (dm/get-in objects [parent-id :frame-id])
+ (nil? frame-id)
+ (dm/get-in dest-objects [parent-id :frame-id] uuid/zero)
- :else
- frame-id)]
+ :else
+ frame-id)]
- (loop [child-ids (seq (:shapes object))
- new-direct-children []
- new-children []
- updated-children []]
+ (loop [child-ids (seq (:shapes shape))
+ new-direct-children []
+ new-children []
+ updated-children []]
- (if (empty? child-ids)
- (let [new-object (cond-> object
- :always
- (assoc :id new-id
- :parent-id parent-id
- :frame-id frame-id)
+ (if (empty? child-ids)
+ (let [new-shape (cond-> shape
+ :always
+ (assoc :id new-id
+ :parent-id parent-id
+ :frame-id frame-id)
- (some? (:shapes object))
- (assoc :shapes (mapv :id new-direct-children)))
+ (some? (:shapes shape))
+ (assoc :shapes (mapv :id new-direct-children)))
- new-object (update-new-object new-object object)
- new-objects (into [new-object] new-children)
+ new-shape (update-new-shape new-shape shape)
+ new-shapes (into [new-shape] new-children)
- updated-object (update-original-object object new-object)
- updated-objects (if (identical? object updated-object)
- updated-children
- (into [updated-object] updated-children))]
+ updated-shape (update-original-shape shape new-shape)
+ updated-shapes (if (identical? shape updated-shape)
+ updated-children
+ (into [updated-shape] updated-children))]
- [new-object new-objects updated-objects])
+ [new-shape new-shapes updated-shapes])
- (let [child-id (first child-ids)
- child (get objects child-id)
- _ (dm/assert! (some? child))
- frame-id-child (if (cfh/frame-shape? object)
- new-id
- frame-id)
+ (let [child-id (first child-ids)
+ child (get objects child-id)
+ _ (dm/assert! (some? child))
+ frame-id-child (if (cfh/frame-shape? shape)
+ new-id
+ frame-id)
- [new-child new-child-objects updated-child-objects]
- (clone-object child new-id objects update-new-object update-original-object nil keep-ids? frame-id-child)]
+ [new-child new-child-shapes updated-child-shapes]
+ (clone-shape child
+ new-id
+ objects
+ :update-new-shape update-new-shape
+ :update-original-shape update-original-shape
+ :force-id nil
+ :keep-ids? keep-ids?
+ :frame-id frame-id-child
+ :dest-objects dest-objects)]
- (recur
- (next child-ids)
- (into new-direct-children [new-child])
- (into new-children new-child-objects)
- (into updated-children updated-child-objects))))))))
+ (recur
+ (next child-ids)
+ (into new-direct-children [new-child])
+ (into new-children new-child-shapes)
+ (into updated-children updated-child-shapes)))))))
(defn generate-shape-grid
"Generate a sequence of positions that lays out the list of
diff --git a/frontend/gulpfile.js b/frontend/gulpfile.js
index eee619276b..ce92a04e28 100644
--- a/frontend/gulpfile.js
+++ b/frontend/gulpfile.js
@@ -1,6 +1,6 @@
import fs from "fs";
import l from "lodash";
-import path from "path"
+import path from "path";
import gulp from "gulp";
import gulpConcat from "gulp-concat";
@@ -9,8 +9,8 @@ import gulpMustache from "gulp-mustache";
import gulpPostcss from "gulp-postcss";
import gulpRename from "gulp-rename";
-import * as sass from 'sass';
-import gsass from 'gulp-sass';
+import * as sass from "sass";
+import gsass from "gulp-sass";
const gulpSass = gsass(sass);
import svgSprite from "gulp-svg-sprite";
@@ -204,6 +204,7 @@ function templatePipeline(options) {
manifest: manifest,
translations: JSON.stringify(locales),
themes: JSON.stringify(themes),
+ isDebug: process.env.NODE_ENV !== "production",
});
return gulp.src(input).pipe(tmpl).pipe(gulpRename(name)).pipe(gulp.dest(output)).pipe(touch());
@@ -231,16 +232,16 @@ gulp.task("scss:modules", function () {
modules({
getJSON: function (cssFileName, json, outputFileName) {
// We do nothing because we don't want the generated JSON files
- },
+ },
// Calculates the whole css-module selector name.
// Should be the same as the one in the file `/src/app/main/style.clj`
generateScopedName: function (selector, filename, css) {
const dir = path.dirname(filename);
const name = path.basename(filename, ".css");
const parts = dir.split("/");
- const rootIdx = parts.findIndex(s => s === ROOT_NAME);
+ const rootIdx = parts.findIndex((s) => s === ROOT_NAME);
return parts.slice(rootIdx + 1).join("_") + "_" + name + "__" + selector;
- },
+ },
}),
autoprefixer(),
]),
@@ -249,13 +250,15 @@ gulp.task("scss:modules", function () {
});
gulp.task("scss:main", function () {
+ const sources = [`${paths.resources}styles/main-default.scss`, `${paths.resources}styles/debug.scss`];
+
return gulp
- .src(paths.resources + "styles/main-default.scss")
- .pipe(gulpSass.sync({
- includePaths: [
- "./node_modules/animate.css"
- ]
- }))
+ .src(sources)
+ .pipe(
+ gulpSass.sync({
+ includePaths: ["./node_modules/animate.css"],
+ }),
+ )
.pipe(gulpPostcss([autoprefixer]))
.pipe(gulp.dest(paths.output + "css/"));
});
diff --git a/frontend/resources/styles/common/base.scss b/frontend/resources/styles/common/base.scss
index 6654083ac6..fd1e4ecb0f 100644
--- a/frontend/resources/styles/common/base.scss
+++ b/frontend/resources/styles/common/base.scss
@@ -17,9 +17,6 @@ body {
width: 100vw;
height: 100vh;
overflow: hidden;
-
- background-color: red; //debugger colors
- color: yellow; //debugger colors
}
#app {
diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss
index 5ca389803e..25d70b6f66 100644
--- a/frontend/resources/styles/common/refactor/basic-rules.scss
+++ b/frontend/resources/styles/common/refactor/basic-rules.scss
@@ -216,6 +216,7 @@
.button-disabled {
@include buttonStyle;
@include flexCenter;
+ height: $s-32;
background-color: var(--button-background-color-disabled);
border: $s-1 solid var(--button-border-color-disabled);
color: var(--button-foreground-color-disabled);
@@ -738,7 +739,6 @@
@include titleTipography;
color: var(--color-foreground-primary);
text-align: left;
-
display: grid;
grid-template-columns: 1fr 22px;
grid-template-areas: "name button";
diff --git a/frontend/resources/styles/common/refactor/common-refactor.scss b/frontend/resources/styles/common/refactor/common-refactor.scss
index a200893e95..c1033735c8 100644
--- a/frontend/resources/styles/common/refactor/common-refactor.scss
+++ b/frontend/resources/styles/common/refactor/common-refactor.scss
@@ -34,7 +34,3 @@ $da-primary: var(--color-accent-primary);
$da-primary-muted: var(--color-accent-primary-muted);
$da-secondary: var(--color-accent-secondary);
$da-tertiary: var(--color-accent-tertiary);
-
-#app {
- background-color: var(--app-background);
-}
diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss
index a69026ba08..c9717d2e24 100644
--- a/frontend/resources/styles/common/refactor/design-tokens.scss
+++ b/frontend/resources/styles/common/refactor/design-tokens.scss
@@ -305,6 +305,11 @@
--resize-area-background-color: var(--color-background-primary);
--resize-area-border-color: var(--color-background-quaternary);
+ --flow-tag-background-color: var(--color-background-tertiary);
+ --flow-tag-foreground-color: var(--color-foreground-secondary);
+ --flow-tag-background-color-hover: var(--color-accent-primary);
+ --flow-tag-foreground-color-hover: var(--color-background-primary);
+
// VIEWER
--viewer-background-color: var(--color-background-secondary);
--viewer-paginator-background-color: var(--color-background-tertiary);
@@ -314,3 +319,7 @@
--viewer-thumbnail-border-color: var(--color-accent-primary);
--viewer-thumbnail-background-color-selected: var(--color-accent-primary-muted);
}
+
+#app {
+ background-color: var(--app-background);
+}
diff --git a/frontend/resources/styles/debug.scss b/frontend/resources/styles/debug.scss
new file mode 100644
index 0000000000..dda48e1fc0
--- /dev/null
+++ b/frontend/resources/styles/debug.scss
@@ -0,0 +1,15 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+// NOTE: This CSS only gets included when the NODE_ENV env var
+// is *not* set to `production`.
+// It is useful to have some styles that are useful in local dev, like
+// debugging.
+
+body {
+ background-color: red;
+ color: yellow;
+}
diff --git a/frontend/resources/styles/main-default.scss b/frontend/resources/styles/main-default.scss
index a961862db5..8690f68d52 100644
--- a/frontend/resources/styles/main-default.scss
+++ b/frontend/resources/styles/main-default.scss
@@ -44,7 +44,6 @@
//#################################################
@import "common/framework";
-@import "main/partials/modal";
@import "main/partials/forms";
@import "main/partials/texts";
@import "main/partials/context-menu";
@@ -58,31 +57,16 @@
@import "main/partials/viewer-header";
@import "main/partials/viewer-thumbnails";
@import "main/partials/activity-bar";
-@import "main/partials/colorpicker";
-@import "main/partials/dashboard";
-@import "main/partials/dashboard-header";
-@import "main/partials/dashboard-grid";
-@import "main/partials/dashboard-sidebar";
-@import "main/partials/dashboard-team";
-@import "main/partials/dashboard-settings";
-@import "main/partials/dashboard-fonts";
@import "main/partials/debug-icons-preview";
@import "main/partials/editable-label";
@import "main/partials/loader";
@import "main/partials/project-bar";
@import "main/partials/sidebar";
-@import "main/partials/sidebar-align-options";
-@import "main/partials/sidebar-assets";
-@import "main/partials/sidebar-document-history";
-@import "main/partials/sidebar-element-options";
-@import "main/partials/sidebar-interactions";
@import "main/partials/tab-container";
@import "main/partials/tool-bar";
@import "main/partials/user-settings";
@import "main/partials/workspace";
-@import "main/partials/comments";
@import "main/partials/color-bullet";
@import "main/partials/inspect";
@import "main/partials/exception-page";
-@import "main/partials/share-link";
@import "main/partials/signup-questions";
diff --git a/frontend/resources/styles/main/partials/colorpicker.scss b/frontend/resources/styles/main/partials/colorpicker.scss
deleted file mode 100644
index e70546d659..0000000000
--- a/frontend/resources/styles/main/partials/colorpicker.scss
+++ /dev/null
@@ -1,598 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.colorpicker {
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- background-color: $color-white;
-}
-
-.colorpicker-content {
- display: flex;
- flex-direction: column;
- padding: $size-2;
-
- & > * {
- width: 200px;
- }
-
- .top-actions {
- display: flex;
- margin-bottom: $size-1;
- flex-direction: row-reverse;
- justify-content: space-between;
-
- .picker-btn {
- background: none;
- border: none;
- cursor: pointer;
-
- &.active svg,
- &:hover svg {
- fill: $color-primary;
- }
-
- svg {
- width: 14px;
- height: 14px;
- }
- }
-
- .element-set-content {
- width: auto;
- padding: 0.25rem 0;
- .custom-select {
- border: none;
- &:hover {
- border: none;
- }
- .custom-select-dropdown {
- left: auto;
- right: 0;
- }
- }
- }
- }
-
- .select-image {
- .content {
- display: flex;
- justify-content: center;
- background-image: url("/images/colorpicker-no-image.png");
- background-position: center;
- background-size: auto 6.75rem;
- height: 6.75rem;
- img {
- height: fit-content;
- width: fit-content;
- max-height: 100%;
- max-width: 100%;
- margin: auto;
- }
- }
- button {
- width: 100%;
- margin-top: 10px;
- }
- }
- .gradients-buttons {
- .gradient {
- cursor: pointer;
- width: 15px;
- height: 15px;
- padding: 0;
- margin: 0;
- border: 1px solid $color-gray-20;
- border-radius: $br2;
- margin-left: $size-1;
- }
-
- .active {
- border-color: $color-primary;
- }
-
- .linear-gradient {
- background: linear-gradient(180deg, $color-gray-20, transparent);
- }
-
- .radial-gradient {
- background: radial-gradient(transparent, $color-gray-20);
- }
- }
-
- .gradient-stops {
- height: 10px;
- display: flex;
- margin-top: $size-2;
- margin-bottom: $size-4;
-
- .gradient-background-wrapper {
- height: 100%;
- width: 100%;
- border: 1px solid $color-gray-10;
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
- left center;
- }
-
- .gradient-background {
- height: 100%;
- width: 100%;
- }
-
- .gradient-stop-wrapper {
- position: absolute;
- width: calc(100% - 2rem);
- margin-left: 0.5rem;
- }
-
- .gradient-stop {
- display: grid;
- grid-template-columns: 50% 50%;
- position: absolute;
- width: 15px;
- height: 15px;
- border-radius: $br2;
- border: 1px solid $color-gray-20;
- margin-top: -2px;
- margin-left: -7px;
- box-shadow: 0 2px 2px rgb(0 0 0 / 15%);
-
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
- left center;
- background-color: $color-white;
-
- &.active {
- border-color: $color-primary;
- }
- }
- }
-
- .picker-detail-wrapper {
- position: relative;
-
- .center-circle {
- width: 14px;
- height: 14px;
- border: 2px solid $color-white;
- border-radius: $br8;
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-7px, -7px);
- filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));
- }
- }
-
- #picker-detail {
- border: 1px solid $color-gray-10;
- }
-
- .slider-selector {
- --gradient-direction: 90deg;
- --background-repeat: left;
-
- &.vertical {
- --gradient-direction: 0deg;
- --background-repeat: top;
- }
-
- border: 1px solid $color-gray-10;
-
- background: linear-gradient(
- var(--gradient-direction),
- rgba(var(--color), 0) 0%,
- rgba(var(--color), 1) 100%
- );
- align-self: center;
- position: relative;
- cursor: pointer;
-
- width: 100%;
- height: calc(0.5rem + 1px);
-
- &.vertical {
- width: calc(0.5rem + 1px);
- height: 100%;
- }
-
- &.hue {
- background: linear-gradient(
- var(--gradient-direction),
- #f00 0%,
- #ff0 17%,
- #0f0 33%,
- #0ff 50%,
- #00f 67%,
- #f0f 83%,
- #f00 100%
- );
- }
-
- &.saturation {
- background: linear-gradient(
- var(--gradient-direction),
- var(--saturation-grad-from) 0%,
- var(--saturation-grad-to) 100%
- );
- }
-
- &.opacity {
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
- var(--background-repeat) center;
-
- &::after {
- content: "";
- position: absolute;
- width: 100%;
- height: 100%;
- background: linear-gradient(
- var(--gradient-direction),
- rgba(var(--color), 0) 0%,
- rgba(var(--color), 1) 100%
- );
- }
- }
-
- &.value {
- background: linear-gradient(var(--gradient-direction), #000 0%, #fff 100%);
- }
-
- .handler {
- background-color: $color-white;
- box-shadow: rgba(0, 0, 0, 0.37) 0px 1px 4px 0px;
- transform: translate(-6px, -2px);
- left: 50%;
- position: absolute;
- width: 12px;
- height: 12px;
- border-radius: $br6;
- z-index: 1;
- }
-
- &.vertical .handler {
- transform: translate(-6px, 6px);
- }
- }
-
- .value-saturation-selector {
- background-color: rgba(var(--hue-rgb));
- position: relative;
- height: 6.75rem;
- cursor: pointer;
-
- .handler {
- position: absolute;
- width: 12px;
- height: 12px;
- border-radius: $br6;
- z-index: 1;
- border: 1px solid $color-white;
- box-shadow:
- rgb(255, 255, 255) 0px 0px 0px 1px inset,
- rgb(0 0 0 / 0.25) 0px 4px 4px inset,
- rgb(0 0 0 / 0.25) 0px 4px 4px;
- transform: translate(-6px, -6px);
- left: 50%;
- top: 50%;
- }
-
- &::before {
- content: "";
- position: absolute;
- width: 100%;
- height: 100%;
- background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
- }
-
- &::after {
- content: "";
- position: absolute;
- width: 100%;
- height: 100%;
- background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
- }
- }
-
- .shade-selector {
- display: grid;
- justify-items: center;
- align-items: center;
- grid-template-areas:
- "color hue"
- "color opacity";
- grid-template-columns: 2.5rem 1fr;
- height: 3.5rem;
- grid-row-gap: 0.5rem;
- cursor: pointer;
- margin-bottom: 0.25rem;
-
- .slider-selector.hue {
- grid-area: "hue";
- align-self: flex-end;
- }
-
- .slider-selector.opacity {
- grid-area: "opacity";
- align-self: flex-start;
- }
- }
-
- .color-values {
- display: grid;
- grid-template-columns: 3.5rem repeat(4, 1fr);
- grid-row-gap: 0.25rem;
- justify-items: center;
- grid-column-gap: 0.25rem;
-
- &.disable-opacity {
- grid-template-columns: 3.5rem repeat(3, 1fr);
- }
-
- input {
- width: 100%;
- margin: 0;
- border: 1px solid $color-gray-10;
- border-radius: $br2;
- font-size: $fs12;
- height: 1.5rem;
- padding: 0 $size-1;
- color: $color-gray-40;
- }
-
- label {
- font-size: $fs12;
- }
- }
-
- .libraries {
- border-top: 1px solid $color-gray-10;
- padding-top: 0.5rem;
- margin-top: 0.25rem;
- width: 200px;
-
- select {
- background-image: url(/images/icons/arrow-down.svg);
- background-repeat: no-repeat;
- background-position: 95% 48%;
- background-size: 10px;
- margin: 0;
- margin-bottom: $size-2;
- width: 100%;
- padding: $size-1 0.25rem;
- font-size: $fs12;
- color: $color-gray-40;
- cursor: pointer;
- border: 1px solid $color-gray-10;
- border-radius: $br2;
-
- option {
- padding: 0;
- }
- }
-
- .selected-colors {
- display: grid;
- grid-template-columns: repeat(8, 1fr);
- justify-content: space-between;
- margin-right: -8px;
- max-height: 5.5rem;
- overflow: auto;
- div {
- grid-area: unset;
- }
- }
-
- .selected-colors::after {
- content: "";
- flex: auto;
- }
- }
-
- .actions {
- margin-top: 0.5rem;
- display: flex;
- flex-direction: row;
- justify-content: center;
-
- .btn-primary {
- height: 1.5rem;
- font-size: $fs12;
- width: 100%;
- }
- }
-
- .harmony-selector {
- display: flex;
- flex-direction: row;
- margin-bottom: 0.5rem;
-
- .hue-wheel-wrapper {
- position: relative;
-
- .hue-wheel {
- width: 152px;
- height: 152px;
- }
-
- .handler {
- position: absolute;
- width: 12px;
- height: 12px;
- border-radius: $br6;
- z-index: 1;
- border: 1px solid $color-white;
- box-shadow:
- rgb(255, 255, 255) 0px 0px 0px 1px inset,
- rgb(0 0 0 / 0.25) 0px 4px 4px inset,
- rgb(0 0 0 / 0.25) 0px 4px 4px;
- transform: translate(-6px, -6px);
- left: 50%;
- top: 50%;
- }
-
- .handler.complement {
- background-color: $color-white;
- box-shadow: rgb(0 0 0 / 0.25) 0px 4px 4px;
- }
- }
-
- .handlers-wrapper {
- height: 152px;
- display: flex;
- flex-direction: row;
- flex-grow: 1;
- justify-content: space-around;
- padding-top: 0.5rem;
-
- & > * {
- height: 100%;
- }
- }
- }
-
- .hsva-selector {
- display: grid;
- padding: 0.25rem;
- grid-template-columns: 20px 1fr;
- grid-template-rows: repeat(4, 2rem);
- grid-row-gap: 0.5rem;
- margin-bottom: 0.5rem;
-
- .hue,
- .saturation,
- .value,
- .opacity {
- border-radius: $br10;
- }
-
- .hsva-selector-label {
- grid-column: 1;
- align-self: center;
- }
- }
-}
-
-.colorpicker-tooltip {
- border-radius: $br3;
- display: flex;
- flex-direction: column;
- left: 1400px;
- top: 100px;
- position: absolute;
- z-index: 11;
- width: auto;
-
- span {
- color: $color-gray-20;
- font-size: $fs12;
- }
-
- .inputs-area {
- .input-text {
- color: $color-gray-60;
- font-size: $fs12;
- margin: 5px;
- padding: 5px;
- width: 100%;
- }
- }
-
- .colorpicker-tabs {
- display: flex;
- margin-bottom: $size-2;
- border-radius: $br5;
- border: 1px solid $color-gray-10;
- height: 2rem;
-
- .colorpicker-tab {
- cursor: pointer;
- display: flex;
- flex-grow: 1;
- justify-content: center;
- align-items: center;
-
- svg {
- width: 16px;
- height: 16px;
- fill: $color-gray-20;
- }
- }
-
- .active {
- background-color: $color-gray-10;
- svg {
- fill: $color-gray-60;
- }
- }
-
- :hover svg {
- fill: $color-primary;
- }
- }
-}
-
-.color-data {
- align-items: center;
- display: flex;
- margin-bottom: $size-2;
- position: relative;
-
- &[draggable="true"] {
- cursor: pointer;
- }
-
- .color-name {
- font-size: $fs12;
- margin: 5px 6px 0px 6px;
- }
-
- .color-info {
- flex: 1 1 0;
-
- input {
- background-color: $color-gray-50;
- border: 1px solid $color-gray-30;
- border-radius: $br3;
- color: $color-white;
- height: 20px;
- margin: 5px 0 0 0;
- padding: 0 $size-1;
- width: 84px;
- font-size: $fs12;
-
- &:focus {
- border-color: $color-primary !important;
- color: $color-white;
- outline: none;
- }
-
- &:hover {
- border-color: $color-gray-20;
- }
-
- &:invalid {
- border-color: $color-danger;
- }
- }
- }
-
- ::placeholder {
- color: $color-gray-10;
- }
-
- .type {
- color: $color-gray-10;
- margin-right: $size-1;
- }
-
- .number {
- color: $color-gray-60;
- }
-
- .element-set-actions-button svg {
- width: 10px;
- height: 10px;
- }
-}
diff --git a/frontend/resources/styles/main/partials/comments.scss b/frontend/resources/styles/main/partials/comments.scss
deleted file mode 100644
index 7c2d4bf002..0000000000
--- a/frontend/resources/styles/main/partials/comments.scss
+++ /dev/null
@@ -1,467 +0,0 @@
-.comments-section {
- .thread-bubble {
- position: absolute;
- display: flex;
- transform: translate(-15px, -15px);
-
- cursor: pointer;
- pointer-events: auto;
- background-color: $color-gray-10;
- color: $color-gray-60;
- border: 1px solid #b1b2b5;
- box-sizing: border-box;
- box-shadow: 0px 4px 4px rgba($color-black, 0.25);
-
- font-size: $fs12;
- width: 30px;
- height: 30px;
- border-radius: 50%;
-
- display: flex;
- align-items: center;
- justify-content: center;
-
- &.resolved {
- color: $color-gray-10;
- background-color: $color-gray-50;
- }
-
- &.unread {
- background-color: $color-primary;
- }
- span {
- user-select: none;
- }
- }
-
- .thread-content {
- position: absolute;
- pointer-events: auto;
- margin-left: 10px;
- background: $color-white;
- border: 1px solid $color-gray-20;
- box-sizing: border-box;
- box-shadow: 0px 2px 8px rgba($color-black, 0.25);
- border-radius: $br2;
- min-width: 280px;
- max-width: 280px;
- user-select: text;
-
- .comments {
- max-height: 420px;
- min-height: 105px;
- overflow-y: auto;
- }
-
- hr {
- border: 0;
- height: 1px;
- background-color: $color-gray-20;
- margin: 0px 10px;
- }
- }
-
- .reply-form {
- display: flex;
- padding: 10px;
- flex-direction: column;
-
- &.edit-form {
- padding-bottom: 0px;
- }
-
- textarea {
- font-family: "worksans", sans-serif;
- font-size: $fs12;
- min-height: 32px;
- outline: none;
- overflow: hidden;
- padding: $size-2;
- resize: none;
- width: 100%;
- border-radius: $br2;
- border: 1px solid $color-gray-20;
- max-height: 4rem;
- }
-
- .buttons {
- margin-top: 10px;
- display: flex;
- justify-content: flex-end;
-
- input {
- margin: 0px;
- font-size: $fs14;
-
- &:not(:last-child) {
- margin-right: 6px;
- }
- }
- }
- }
-
- .comment-container {
- position: relative;
- }
-
- .comment {
- display: flex;
- flex-direction: column;
- padding: $size-4 $size-2;
-
- .author {
- display: flex;
- align-items: center;
- height: 26px;
- max-height: 26px;
- position: relative;
-
- .name {
- display: flex;
- flex-direction: column;
-
- .fullname {
- font-weight: $fw700;
- color: $color-gray-60;
- font-size: $fs12;
-
- @include text-ellipsis;
- width: 174px;
- }
- .timeago {
- margin-top: -2px;
- font-size: $fs12;
- color: $color-gray-30;
- }
- }
-
- .avatar {
- display: flex;
- align-items: center;
- padding-right: 6px;
-
- img {
- border-radius: 50%;
- flex-shrink: 0;
- height: 24px;
- width: 24px;
- }
- }
-
- .options-resolve {
- position: absolute;
- right: 20px;
- top: 0px;
- width: 16px;
- height: 16px;
-
- cursor: pointer;
-
- svg {
- width: 16px;
- height: 16px;
- fill: $color-gray-30;
- }
- }
-
- .options {
- position: absolute;
- right: -2px;
- top: 2px;
- height: 16px;
- display: flex;
- align-items: center;
- cursor: pointer;
-
- .options-icon {
- svg {
- width: 14px;
- height: 14px;
- fill: $color-black;
- }
- }
- }
- }
-
- .content {
- margin: $size-4 0;
- font-size: $fs14;
- color: $color-black;
- .text {
- margin: 0 $size-2 0 26px;
- white-space: pre-wrap;
- display: inline-block;
- word-break: break-word;
- }
- }
- }
-
- .comment-options-dropdown {
- top: 7px;
- right: 7px;
- width: 150px;
-
- border: 1px solid #b1b2b5;
- }
-}
-
-.workspace-comment-threads-sidebar-header {
- display: flex;
- background-color: $color-black;
- height: 34px;
- align-items: center;
- padding: 0px 9px;
- color: $color-gray-10;
- font-size: $fs12;
- justify-content: space-between;
-
- .options {
- display: flex;
- margin-right: 3px;
- cursor: pointer;
-
- .label {
- padding-right: 8px;
- }
-
- .icon {
- display: flex;
- align-items: center;
- }
-
- svg {
- fill: $color-gray-10;
- width: 10px;
- height: 10px;
- }
- }
-
- .dropdown {
- top: 80px;
- right: 7px;
- }
-}
-
-.comment-threads-section {
- pointer-events: auto;
-
- .thread-groups {
- height: calc(100% - 34px);
- overflow-y: scroll;
- hr {
- border: 0;
- height: 1px;
- background-color: $color-gray-30;
- margin: 0px 0px;
- }
- }
-
- .thread-group {
- display: flex;
- flex-direction: column;
- font-size: $fs12;
-
- .section-title {
- margin: 0px 10px;
- margin-top: 15px;
-
- .icon {
- margin-right: 4px;
- }
-
- .label {
- &.filename {
- font-weight: $fw700;
- }
- }
-
- svg {
- fill: $color-gray-10;
- height: 10px;
- width: 10px;
- }
- }
- }
-
- .thread-bubble {
- position: unset;
- transform: unset;
- width: 24px;
- height: 24px;
- margin-right: 6px;
- box-shadow: unset;
- }
-
- .comment {
- cursor: pointer;
- .author {
- margin-bottom: $size-4;
- .name {
- display: flex;
-
- .fullname {
- width: unset;
- max-width: 170px;
- color: $color-gray-20;
- padding-right: 3px;
- }
- .timeago {
- margin-top: unset;
- color: $color-gray-20;
- }
- }
- }
-
- .content {
- margin-top: 0px;
- color: $color-white;
-
- &.replies {
- margin: 0 $size-2 0 26px;
- display: flex;
- .total-replies {
- margin-right: 9px;
- color: $color-info;
- }
-
- .new-replies {
- color: $color-primary;
- }
- }
- }
- }
-}
-
-.viewer-comments-container {
- width: 100%;
- height: 100%;
- z-index: 1;
- position: absolute;
- top: 0px;
- left: 0px;
-}
-
-.workspace-comments-container {
- width: 100%;
- height: 100%;
- grid-column: 1 / span 2;
- grid-row: 1 / span 2;
- z-index: 1000;
- pointer-events: none;
- overflow: hidden;
- user-select: text;
-
- .threads {
- position: absolute;
- top: 0px;
- left: 0px;
- }
-}
-
-.dashboard-comments-section {
- width: 25px;
- height: 25px;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: $color-dashboard;
- border-radius: $br3;
- position: relative;
-
- .button {
- width: 25px;
- height: 25px;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: $color-dashboard;
- border-radius: $br3;
-
- svg {
- width: 15px;
- height: 15px;
- }
-
- &.unread {
- background-color: $color-warning;
- }
-
- &.open {
- background-color: $color-black;
- svg {
- fill: $color-primary;
- }
- }
- }
-
- .dropdown {
- width: 280px;
- bottom: 35px;
- left: 0px;
- border-radius: $br3;
- }
-
- .header {
- display: flex;
- height: 40px;
- align-items: center;
- padding: 0px 11px;
-
- h3 {
- font-weight: $fw400;
- color: $color-black;
- font-size: $fs14;
- line-height: $lh-128; // Original value was $fs18 => 1.125rem = 18px; 18px/14px = 128.571428571% => $lh-128 (rounded)
- flex-grow: 1;
- }
-
- .close {
- display: flex;
- align-items: center;
- }
-
- svg {
- width: 15px;
- height: 15px;
- transform: rotate(45deg);
- }
- }
-
- .thread-groups {
- max-height: calc(30rem - 40px);
- overflow: auto;
-
- hr {
- background-color: $color-gray-10;
- }
- }
-
- .thread-group .section-title {
- color: $color-black;
- }
-
- .comment {
- .author .name .fullname {
- color: $color-gray-40;
- }
- .content {
- color: $color-black;
- }
- }
-}
-
-.thread-groups-placeholder {
- align-items: center;
- display: flex;
- flex-direction: column;
- font-size: $fs12;
- padding: $size-5;
- text-align: center;
-
- svg {
- fill: $color-gray-20;
- height: 24px;
- margin-bottom: $size-5;
- width: 24px;
- }
-}
diff --git a/frontend/resources/styles/main/partials/dashboard-fonts.scss b/frontend/resources/styles/main/partials/dashboard-fonts.scss
deleted file mode 100644
index 544e50341e..0000000000
--- a/frontend/resources/styles/main/partials/dashboard-fonts.scss
+++ /dev/null
@@ -1,254 +0,0 @@
-.dashboard-fonts {
- display: flex;
- flex-direction: column;
- align-items: center;
-
- .dashboard-installed-fonts {
- max-width: 1000px;
- width: 100%;
- display: flex;
- margin-top: $size-5;
- flex-direction: column;
-
- h3 {
- font-size: $fs14;
- color: $color-gray-30;
- margin: $size-1;
- }
-
- .font-item {
- color: $color-black;
- }
- }
-
- .installed-fonts-header {
- color: $color-gray-40;
- display: flex;
- height: 40px;
- font-size: $fs12;
- background-color: $color-white;
- align-items: center;
- padding: 0px $size-5;
-
- > .family {
- min-width: 200px;
- width: 200px;
- }
-
- > .variants {
- padding-left: 12px;
- }
-
- .search-input {
- display: flex;
- flex-grow: 1;
- justify-content: flex-end;
-
- input {
- font-size: $fs12;
- border: 1px solid $color-gray-30;
- border-radius: $br3;
- width: 130px;
- padding: $size-1;
- margin: 0px;
- }
- }
- }
-
- .font-item {
- color: $color-gray-40;
- font-size: $fs14;
- background-color: $color-white;
- display: flex;
- max-width: 1000px;
- width: 100%;
- min-height: 97px;
- align-items: center;
- padding: $size-5;
- justify-content: space-between;
-
- &:not(:first-child) {
- border-top: 1px solid $color-gray-10;
- }
-
- input {
- border: 1px solid $color-gray-30;
- border-radius: $br3;
- margin: 0px;
- padding: $size-2;
- font-size: $fs12;
- }
-
- > .family {
- min-width: 200px;
- width: 200px;
- }
-
- > .filenames {
- min-width: 200px;
- }
-
- > .variants {
- font-size: $fs14;
- display: flex;
- flex-wrap: wrap;
- flex-grow: 1;
-
- .variant {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 8px 12px;
- cursor: pointer;
-
- .icon {
- display: flex;
- height: 16px;
- width: 16px;
- margin-left: 6px;
- align-items: center;
- svg {
- fill: transparent;
- width: 12px;
- height: 12px;
- transform: rotate(45deg);
- }
- }
-
- &:hover {
- .icon svg {
- fill: $color-gray-30;
- }
- }
- }
- }
-
- .filenames {
- display: flex;
- flex-direction: column;
- font-size: $fs12;
- }
-
- .options {
- display: flex;
- justify-content: flex-end;
- min-width: 180px;
-
- .icon {
- width: $size-5;
- cursor: pointer;
- display: flex;
- margin-left: 10px;
- justify-content: center;
- align-items: center;
- &.failure {
- margin-right: 10px;
- svg {
- fill: $color-warning;
- }
- }
- svg {
- width: 16px;
- height: 16px;
- }
-
- &.close {
- svg {
- transform: rotate(45deg);
- }
- }
- }
- }
- }
-
- .dashboard-fonts-upload {
- max-width: 1000px;
- width: 100%;
- display: flex;
- flex-direction: column;
-
- .upload-button {
- width: 100px;
- }
-
- .btn-secondary {
- margin-left: 10px;
- }
- }
-
- .dashboard-fonts-hero {
- font-size: $fs14;
- padding: $size-6;
- background-color: $color-white;
- margin-top: $size-6;
- display: flex;
- justify-content: space-between;
-
- .banner {
- background-color: $color-info-lighter;
- display: grid;
- grid-template-columns: 40px 1fr;
- &:not(:last-child) {
- margin-bottom: 10px;
- }
- .icon {
- display: flex;
- align-items: flex-start;
- justify-content: center;
- padding-top: 10px;
- background-color: $color-info;
- svg {
- fill: $color-white;
- }
- }
- .content {
- margin: 10px;
- }
- &.warning {
- background-color: $color-warning-lighter;
- .icon {
- background-color: $color-warning;
- }
- }
- }
-
- .desc {
- h2 {
- margin-bottom: $size-4;
- color: $color-black;
- }
- width: 80%;
- color: $color-gray-40;
- }
-
- .btn-primary {
- flex-shrink: 0;
- }
- }
-
- .fonts-placeholder {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- max-width: 1000px;
- width: 100%;
- height: 161px;
-
- border: 1px dashed $color-gray-20;
- margin-top: 16px;
-
- .icon {
- svg {
- fill: $color-gray-40;
- width: 32px;
- height: 32px;
- }
- }
-
- .label {
- color: $color-gray-40;
- font-size: $fs14;
- }
- }
-}
diff --git a/frontend/resources/styles/main/partials/dashboard-grid.scss b/frontend/resources/styles/main/partials/dashboard-grid.scss
deleted file mode 100644
index e5f14c116a..0000000000
--- a/frontend/resources/styles/main/partials/dashboard-grid.scss
+++ /dev/null
@@ -1,527 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.dashboard-grid {
- font-size: $fs14;
- height: 100%;
- overflow: hidden;
- overflow-y: auto;
- margin-bottom: 0;
-
- .grid-row {
- display: grid;
- width: 99%;
- margin-left: 13px;
- }
-
- .grid-item {
- align-items: center;
- cursor: pointer;
- display: flex;
- flex-direction: column;
- flex: 1 0 260px;
- height: 230px;
- margin: $size-3 $size-4 $size-4 $size-2;
- position: relative;
- text-align: center;
- a,
- button {
- width: 100%;
- font-weight: $fw400;
- }
- button {
- background-color: transparent;
- border: none;
- }
- @media #{$bp-max-1366} {
- height: 200px;
- flex: 1 0 230px;
- }
-
- &:hover {
- .grid-item-th {
- border: 2px solid $color-primary;
- }
- }
-
- .grid-item-th {
- border-radius: $br3;
- border: 2px solid lighten($color-gray-20, 15%);
- text-align: initial;
-
- img {
- object-fit: contain;
- }
- }
-
- &.dragged {
- border-radius: $br3;
- border: 2px solid lighten($color-gray-20, 15%);
- text-align: initial;
- max-height: 160px;
- }
-
- &.placeholder {
- min-width: 115px;
- max-width: 115px;
-
- display: flex;
- flex-direction: column;
- justify-content: center;
-
- .placeholder-icon {
- svg {
- transform: rotate(-90deg);
- width: 20px;
- height: 20px;
- fill: $color-gray-30;
- }
- }
-
- .placeholder-label {
- font-size: $fs14;
- }
- }
-
- &.overlay {
- border-radius: $br4;
- border: 2px solid $color-primary;
- height: 100%;
- opacity: 0;
- pointer-events: none;
- position: absolute;
- width: 100%;
- z-index: 1;
- }
-
- &:hover .overlay {
- display: block;
- opacity: 1;
- }
-
- &.small-item {
- max-width: 12%;
- min-width: 190px;
- padding: $size-4;
- justify-content: center;
- }
-
- .grid-item-icon {
- width: 90px;
- height: 90px;
- }
- .info-wrapper {
- display: grid;
- grid-template-columns: 1fr auto;
- }
-
- .item-info {
- display: grid;
- padding: $size-2;
- text-align: left;
- width: 100%;
- font-size: $fs12;
-
- h3 {
- border: 1px solid transparent;
- color: $color-gray-60;
- font-size: $fs14;
- font-weight: $fw500;
- overflow: hidden;
- padding: 0;
- height: 27px;
- padding-right: $size-2;
- text-overflow: ellipsis;
- width: 100%;
- white-space: nowrap;
- line-height: $lh-192; // Original value was 27px; 27px/14px = 192.857142857% => $lh-192 (rounded)
- max-width: 260px;
- @media #{$bp-max-1366} {
- max-width: 230px;
- }
- }
-
- span.date {
- color: $color-gray-30;
- overflow: hidden;
- text-overflow: ellipsis;
- width: 100%;
- white-space: nowrap;
- max-width: 260px;
- &::first-letter {
- text-transform: capitalize;
- }
- @media #{$bp-max-1366} {
- max-width: 230px;
- }
- }
-
- .edit-wrapper {
- .element-title {
- padding: 0px;
- height: 25px;
- color: $color-gray-60;
- font-size: $fs14;
- font-weight: $fw400;
- }
- }
- }
-
- .item-badge {
- background-color: $color-white;
- border: 1px solid $color-gray-20;
- border-radius: $br2;
- position: absolute;
- top: $size-2;
- right: $size-2;
- height: 32px;
- width: 32px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- svg {
- fill: $color-gray-30;
- height: 16px;
- width: 16px;
- }
- }
-
- &.add-file {
- border: 1px dashed $color-gray-20;
- justify-content: center;
- box-shadow: none;
-
- span {
- color: $color-gray-60;
- font-size: $fs14;
- }
-
- &:hover {
- background-color: $color-white;
- border: 2px solid $color-primary;
- }
- }
-
- // PROJECTS, ELEMENTS & ICONS GRID
- &.project-th {
- background-color: $color-white;
-
- &:hover,
- &:focus,
- &:focus-within {
- .project-th-actions {
- opacity: 1;
- }
- a {
- text-decoration: none;
- }
- }
-
- .selected {
- .grid-item-th {
- border: 2px solid $color-primary;
- }
- }
-
- .project-th-actions {
- align-items: center;
- opacity: 0;
- display: flex;
- right: 5px;
- justify-content: center;
- width: 30px;
- height: 100%;
-
- span {
- color: $color-black;
- }
-
- .project-th-icon {
- align-items: center;
- display: flex;
- margin-right: $size-2;
-
- &.menu {
- margin-right: 0;
- display: flex;
- justify-content: center;
- align-items: flex-end;
- flex-direction: column;
- width: 100%;
- height: 30px;
- margin-top: 20px;
-
- > svg {
- fill: $color-gray-60;
- margin-right: 0;
- height: 18px;
- width: 18px;
- }
-
- &:hover,
- &:focus {
- > svg {
- fill: $color-primary-dark;
- }
- }
- }
- }
- }
-
- .project-th-actions.force-display {
- opacity: 1;
- }
- }
-
- // IMAGES SECTION
- &.images-th {
- border: 1px dashed $color-gray-20;
- border-bottom: 2px solid lighten($color-gray-20, 12%);
-
- &:hover {
- border-color: $color-primary;
- }
- }
-
- .grid-item-image {
- svg {
- max-height: 100px;
- max-width: 100px;
- min-height: 40px;
- min-width: 40px;
- width: 8vw;
- }
- }
-
- .color-swatch {
- border-top-left-radius: $br5;
- border-top-right-radius: $br5;
- height: 25%;
- left: 0;
- position: absolute;
- top: 0;
- width: 100%;
- }
-
- .color-data {
- color: $color-gray-30;
- margin-top: 15px;
- }
-
- .drag-counter {
- position: absolute;
- top: 5px;
- left: 4px;
- width: 32px;
- height: 32px;
- background-color: $color-primary;
- border-radius: 50%;
- color: $color-black;
- font-size: $fs18;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- }
-
- .grid-item-th {
- background-position: center;
- background-size: auto 80%;
- background-repeat: no-repeat;
- border-top-left-radius: $br3;
- border-top-right-radius: $br3;
- height: 230px;
- max-height: 160px;
- overflow: hidden;
- position: relative;
- width: 100%;
-
- background-color: $color-canvas;
- display: flex;
- justify-content: center;
- flex-direction: row;
-
- .img-th {
- height: auto;
- width: 100%;
- }
-
- svg {
- height: 100%;
- width: 100%;
- }
-
- svg#loader-pencil {
- fill: $color-gray-20;
- }
- }
-
- // LIBRARY VIEW
- .grid-item {
- .library {
- height: 580px;
- }
-
- &.project-th.library {
- height: 610px;
- width: 300px;
- }
-
- .grid-item-th.library {
- background-color: $color-gray-50;
- flex-direction: column;
- height: 90%;
- justify-content: flex-start;
- max-height: 550px;
- padding: $size-6;
-
- .asset-section {
- font-size: $fs12;
- color: $color-gray-20;
-
- &:not(:first-child) {
- margin-top: $size-4;
- }
- }
-
- .asset-title {
- display: flex;
- font-size: $fs12;
- text-transform: uppercase;
-
- & .num-assets {
- color: $color-gray-30;
- }
- }
-
- .asset-list-item {
- display: flex;
- align-items: center;
- border: 1px solid transparent;
- border-radius: $br3;
- margin-top: $size-1;
- padding: 2px;
- font-size: $fs12;
- color: $color-white;
- position: relative;
-
- & .name-block {
- color: $color-gray-20;
- width: calc(100% - 24px - #{$size-2});
- }
-
- & .item-name {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- display: block;
- }
-
- & svg {
- background-color: $color-canvas;
- border-radius: $br4;
- border: 2px solid transparent;
- height: 24px;
- width: 24px;
- margin-right: $size-2;
- }
-
- & .color-name {
- color: $color-white;
- }
-
- & .color-value {
- margin-left: $size-1;
- color: $color-gray-30;
- text-transform: uppercase;
- }
-
- & .typography-sample {
- height: 20px;
- margin-right: $size-1;
- width: 20px;
- }
- }
- }
- }
-}
-
-.grid-empty-placeholder {
- border-radius: $br12;
- display: grid;
- background-color: rgba(227, 227, 227, 0.3);
- padding: 13px;
- margin-right: 13px;
- height: 230px;
- &.loader {
- justify-items: center;
- }
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- &.libs {
- background-image: url(/images/ph-left.svg), url(/images/ph-right.svg);
- background-position:
- 15% bottom,
- 85% top;
- background-repeat: no-repeat;
- align-items: center;
- border: 1px dashed #b1b2b5;
- border-radius: $br3;
- display: flex;
- flex-direction: column;
- height: 200px;
- margin: 1rem;
- padding: 3rem;
- justify-content: center;
- .text {
- p {
- max-width: 360px;
- text-align: center;
- font-size: $fs16;
- }
- }
- }
- .create-new {
- background-color: white;
- border: 2px solid $color-gray-10;
- border-radius: $br3;
- color: $color-black;
- cursor: pointer;
- height: 158px;
- font-family: "worksans", sans-serif;
- margin: 0.5rem;
- &:hover {
- border: 2px solid $color-primary;
- }
- }
-
- &.search {
- align-items: center;
- display: flex;
- justify-content: center;
- flex-direction: column;
- height: 200px;
- background: $color-white;
- border: 1px dashed #e3e3e3;
- border-radius: $br0;
- }
-
- svg {
- width: 36px;
- height: 36px;
- fill: $color-gray-20;
- }
-
- .text {
- margin-top: 10px;
- color: $color-gray-30;
- font-size: $fs16;
- }
-}
diff --git a/frontend/resources/styles/main/partials/dashboard-header.scss b/frontend/resources/styles/main/partials/dashboard-header.scss
deleted file mode 100644
index 157a440058..0000000000
--- a/frontend/resources/styles/main/partials/dashboard-header.scss
+++ /dev/null
@@ -1,139 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.dashboard-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- background-color: $color-white;
- height: 63px;
- padding: $size-1 $size-4 $size-1 $size-2;
- position: relative;
- z-index: 10;
- user-select: none;
- &.team {
- display: grid;
- grid-template-columns: 20% 1fr 20%;
- }
-
- .element-name {
- margin-right: $size-2;
- }
-
- .btn-secondary {
- flex-shrink: 0;
- z-index: 10;
- height: 32px;
- }
-
- svg {
- fill: $color-black;
- height: 14px;
- margin-right: $size-1;
- width: 14px;
- }
-
- nav {
- display: flex;
- align-items: flex-end;
- justify-content: center;
- z-index: 1;
-
- ul {
- display: flex;
- font-size: $fs14;
- justify-content: center;
- margin: 0;
- }
-
- li {
- a {
- display: flex;
- align-items: center;
- flex-basis: 140px;
- border-bottom: 3px solid transparent;
- color: $color-gray-30;
- height: 40px;
- padding: $size-1 $size-5;
- font-weight: $fw400;
- &:hover {
- color: $color-black;
- text-decoration: none;
- }
- }
-
- &.active {
- a {
- color: $color-black;
- border-color: $color-primary;
- }
- }
- }
- }
-
- .dashboard-title {
- display: flex;
- align-items: center;
- margin-left: 13px;
-
- h1 {
- color: $color-black;
- display: flex;
- flex-shrink: 0;
- font-size: $fs22;
- font-weight: $fw600;
- z-index: 10;
- user-select: all;
- }
-
- .context-menu.is-open {
- margin-top: 10px;
- }
- }
-
- .icon {
- display: flex;
- align-items: center;
- cursor: pointer;
- margin-left: $size-2;
- z-index: 10;
-
- svg {
- fill: $color-gray-40;
- width: 15px;
- height: 15px;
-
- &:hover {
- fill: $color-primary-dark;
- }
- }
- }
-
- .dashboard-buttons {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- }
-
- .dashboard-header-actions {
- display: flex;
- }
-
- .pin-icon {
- margin: 0 $size-2 0 $size-5;
- background-color: transparent;
- border: none;
- svg {
- fill: $color-gray-20;
- }
-
- &.active {
- svg {
- fill: $color-gray-50;
- }
- }
- }
-}
diff --git a/frontend/resources/styles/main/partials/dashboard-settings.scss b/frontend/resources/styles/main/partials/dashboard-settings.scss
deleted file mode 100644
index 0cd1146870..0000000000
--- a/frontend/resources/styles/main/partials/dashboard-settings.scss
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright (c) 2020 KALEIDOS INC
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.dashboard-sidebar {
- &.settings {
- .back-to-dashboard {
- padding: 12px 18px;
- font-size: $fs14;
- cursor: pointer;
- display: flex;
-
- .icon {
- display: flex;
- align-items: center;
- margin-right: 14px;
- }
-
- .text {
- color: $color-gray-60;
- }
-
- svg {
- fill: $color-gray-60;
- transform: rotate(90deg);
- width: 12px;
- height: 12px;
- }
- }
- }
-}
-
-.dashboard-settings {
- display: flex;
- width: 100%;
- justify-content: center;
- align-items: center;
-
- .form-container {
- margin-top: 50px;
- display: flex;
- max-width: 368px;
- margin-bottom: 2rem;
- width: 100%;
-
- &.two-columns {
- max-width: 536px;
- justify-content: space-between;
- flex-direction: row;
- }
-
- h2 {
- margin-bottom: 1rem;
- }
- }
-
- .avatar-form {
- display: flex;
- flex-direction: column;
- width: 120px;
- min-width: 120px;
-
- img {
- border-radius: 50%;
- flex-shrink: 0;
- height: 120px;
- margin-right: $size-4;
- width: 120px;
- }
-
- .image-change-field {
- position: relative;
- width: 120px;
- height: 120px;
-
- .update-overlay {
- opacity: 0;
- cursor: pointer;
- position: absolute;
- width: 121px;
- height: 121px;
- border-radius: 50%;
- font-size: $fs24;
- color: $color-white;
- line-height: $lh-500; // Original value was 120px; 120px/24px = 500% => $lh-500
- text-align: center;
- background: $color-primary-dark;
- z-index: 14;
- }
-
- input[type="file"] {
- width: 120px;
- height: 120px;
- position: absolute;
- opacity: 0;
- cursor: pointer;
- top: 0;
- z-index: 15;
- }
-
- &:hover {
- .update-overlay {
- opacity: 0.8;
- }
- }
- }
- }
-
- .profile-form {
- display: flex;
- flex-direction: column;
- max-width: 368px;
- width: 100%;
-
- .newsletter-subs {
- border-bottom: 1px solid $color-gray-20;
- border-top: 1px solid $color-gray-20;
- padding: 30px 0;
- margin-bottom: 31px;
-
- .newsletter-title {
- font-family: "worksans", sans-serif;
- color: $color-gray-30;
- font-size: $fs14;
- }
-
- label {
- font-family: "worksans", sans-serif;
- color: $color-gray-60;
- font-size: $fs12;
- margin-right: -17px;
- margin-bottom: 13px;
- }
-
- .info {
- font-family: "worksans", sans-serif;
- color: $color-gray-30;
- font-size: $fs12;
- margin-bottom: 8px;
- }
-
- .input-checkbox label {
- align-items: flex-start;
- }
- }
- }
-
- .options-form,
- .password-form {
- h2 {
- font-size: $fs14;
- margin-bottom: 20px;
- }
- }
-}
-
-.dashboard-access-tokens {
- display: flex;
- flex-direction: column;
- align-items: center;
-
- .access-tokens-hero-container {
- max-width: 1000px;
- width: 100%;
- display: flex;
- flex-direction: column;
- }
-
- .access-tokens-hero {
- font-size: $fs14;
- padding: $size-6;
- background-color: $color-white;
- margin-top: $size-6;
- display: flex;
- justify-content: space-between;
-
- .desc {
- width: 80%;
- color: $color-gray-40;
- h2 {
- margin-bottom: $size-4;
- color: $color-black;
- }
- p {
- font-size: $fs16;
- }
- }
-
- .btn-primary {
- flex-shrink: 0;
- }
- }
-
- .access-tokens-empty {
- text-align: center;
- max-width: 1000px;
- width: 100%;
- padding: $size-6;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- border: 1px dashed $color-gray-20;
- color: $color-gray-40;
- margin-top: 12px;
- min-height: 136px;
- }
-
- .table-row {
- background-color: $color-white;
- display: grid;
- grid-template-columns: 1fr 43% 12px;
- height: 63px;
- &:not(:first-child) {
- margin-top: 8px;
- }
- }
-
- .table-field {
- &.name {
- color: $color-gray-60;
- }
-
- &.expiration-date {
- color: $color-gray-40;
- font-size: $fs14;
- .content {
- padding: 2px 5px;
- &.expired {
- background-color: $color-warning-lighter;
- border-radius: $br4;
- color: $color-gray-40;
- }
- }
- }
-
- &.access-token-created {
- word-break: break-all;
- }
-
- &.actions {
- position: relative;
- }
- }
-}
-
-.access-tokens-modal {
- .action-buttons {
- gap: 10px;
-
- .cancel-button {
- border: 1px solid $color-gray-30;
- background: $color-canvas;
- border-radius: $br3;
- padding: 0.5rem 1rem;
- cursor: pointer;
- margin-right: 8px;
-
- &:hover {
- background: $color-gray-20;
- }
- }
- }
- .access-token-created {
- position: relative;
- word-break: break-all;
-
- .custom-input input {
- background-color: $color-success-lighter;
- border: 0;
- padding: 0 0 0 15px;
- }
- }
-
- .help-icon {
- border: none;
- height: 40px;
- width: 40px;
- position: absolute;
- top: 0;
- right: 0;
- cursor: pointer;
- background-color: $color-success-lighter;
-
- svg {
- fill: $color-gray-30;
- }
-
- &:hover {
- svg {
- fill: $color-gray-60;
- }
- }
- }
-
- .token-created-info {
- font-size: $fs12;
- color: $color-gray-40;
- }
-}
diff --git a/frontend/resources/styles/main/partials/dashboard-sidebar.scss b/frontend/resources/styles/main/partials/dashboard-sidebar.scss
deleted file mode 100644
index 646d53a303..0000000000
--- a/frontend/resources/styles/main/partials/dashboard-sidebar.scss
+++ /dev/null
@@ -1,476 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.dashboard-sidebar {
- background-color: $color-white;
- z-index: 1;
- display: flex;
- flex-direction: column;
- height: 100%;
- padding-top: $size-2;
-
- .sidebar-content {
- display: flex;
- flex-direction: column;
- height: 100%;
- overflow-y: auto;
- padding: 0;
-
- hr {
- border-color: $color-gray-10;
- margin: 1rem 15px;
- }
- }
-
- .sidebar-team-switch {
- position: relative;
- display: flex;
- margin: 5px 15px;
-
- .teams-dropdown {
- left: 0;
- top: 50px;
- z-index: 12;
- max-height: 30rem;
- min-width: 234px;
- overflow-y: auto;
- }
-
- .options-dropdown {
- right: 2px;
- top: 50px;
- z-index: 12;
- max-height: 30rem;
- min-width: 162px;
- }
-
- .switch-content {
- height: 40px;
- display: flex;
- width: 100%;
- border: 1px solid $color-gray-10;
- border-radius: $br5;
- align-items: center;
- }
-
- .switch-options {
- display: flex;
- max-width: 22px;
- min-width: 28px;
- border-left: 1px solid $color-gray-10;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- background-color: transparent;
- border: none;
- svg {
- width: 15px;
- height: 13px;
- fill: $color-gray-60;
- }
- }
-
- .current-team {
- cursor: pointer;
- display: flex;
- align-items: center;
- flex-grow: 1;
- font-size: $fs14;
- padding: 0px 10px;
- background-color: transparent;
- border: none;
- }
-
- .team-name {
- flex-grow: 1;
- display: flex;
- height: 40px;
- align-items: center;
-
- &.action {
- .team-icon {
- border-radius: 50%;
- background-color: $color-gray-10;
- height: 24px;
- margin-right: 10px;
- padding: 6px;
- width: 24px;
-
- svg {
- height: 12px;
- width: 12px;
- }
- }
-
- &:hover {
- .team-icon {
- background-color: $color-primary;
- }
- }
-
- .team-text {
- width: 150px;
- }
- }
-
- .team-icon {
- display: flex;
- align-items: center;
- padding-right: 10px;
-
- svg {
- width: 23px;
- height: 23px;
- fill: $color-gray-60;
- }
-
- img {
- border-radius: 50%;
- flex-shrink: 0;
- height: 23px;
- width: 23px;
- }
- }
-
- .team-text {
- color: $color-gray-60;
- @include text-ellipsis;
- width: 130px;
- text-align: left;
- }
-
- .icon {
- margin-left: auto;
- svg {
- fill: $color-gray-60;
- }
- }
- }
-
- .switch-icon {
- display: flex;
- align-items: center;
- justify-content: center;
- svg {
- width: 10px;
- height: 10px;
- fill: $color-gray-60;
- }
- }
- }
-
- .sidebar-empty-placeholder {
- padding: 10px 12px;
- color: $color-gray-30;
- display: flex;
- align-items: flex-start;
-
- .icon {
- padding: 0px 10px;
- svg {
- fill: $color-gray-30;
- width: 12px;
- height: 12px;
- }
- }
- .text {
- font-size: $fs12;
- }
- }
-
- .sidebar-nav {
- display: flex;
- flex-direction: column;
- overflow-y: auto;
- margin: 0;
- user-select: none;
-
- // TODO: should be deprecated / unclear name
- &.dashboard-common {
- overflow: unset;
- }
-
- &.no-overflow {
- overflow: unset;
- }
-
- & > li {
- align-items: center;
- cursor: pointer;
- display: flex;
- flex-shrink: 0;
- padding: $size-2;
- a {
- font-weight: $fw400;
- width: 100%;
- &:hover {
- text-decoration: none;
- }
- }
-
- svg {
- fill: $color-black;
- margin-right: 8px;
- height: $size-3;
- width: $size-3;
- }
-
- span.element-title {
- color: $color-gray-60;
- font-size: $fs14;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- &::before {
- background-color: transparent;
- border-radius: $br3;
- content: "";
- height: 26px;
- margin-right: $size-2;
- width: 4px;
- }
-
- &.recent-projects {
- svg {
- fill: $color-white;
- }
- }
-
- & .edit-wrapper {
- border: 1px solid $color-gray-10;
- border-radius: $br3;
- display: flex;
- width: 100%;
- }
-
- input.element-title {
- border: 0;
- height: 30px;
- padding: 5px;
- margin: 0;
- width: 100%;
- background-color: $color-white;
- }
-
- .close {
- background-color: $color-white;
- cursor: pointer;
- padding-left: 5px;
-
- svg {
- fill: $color-gray-30;
- height: 15px;
- transform: rotate(45deg) translateY(7px);
- width: 15px;
- margin: 0;
- }
- }
-
- .element-subtitle {
- color: $color-gray-20;
- font-style: italic;
- }
-
- &:hover {
- &::before {
- background-color: $color-gray-10;
- }
- }
-
- &.current {
- a {
- font-weight: $fw700;
- }
-
- &::before {
- background-color: $color-primary;
- }
- }
-
- &.dragging {
- background-color: color.adjust($color-primary, $alpha: -0.69);
- }
- }
- }
-
- .sidebar-search {
- align-items: center;
- background-color: $color-white;
- border: 1px solid $color-gray-10;
- border-radius: $br5;
- display: flex;
- margin: 5px 15px;
-
- .input-text {
- background: transparent;
- border: 0;
- color: $color-gray-60;
- font-size: $fs14;
- padding: 6px;
- margin: 0;
- max-width: 195px;
- width: 100%;
- height: 40px;
- }
-
- &:focus,
- &:focus-within {
- border-color: $color-black;
- }
-
- .search,
- .clear-search {
- align-items: center;
- cursor: pointer;
- display: flex;
- height: 22px;
- margin-left: auto;
- padding: 0 $size-2;
- width: 32px;
-
- svg {
- fill: $color-gray-30;
- height: 15px;
- width: 15px;
- }
- }
-
- .clear-search svg {
- transform: rotate(45deg);
-
- &:hover {
- fill: $color-danger;
- }
- }
- }
-
- &.profile-bar {
- background-color: $color-gray-10;
-
- .dashboard-sidebar-inside {
- display: none;
- }
- }
-}
-
-.projects-row {
- align-items: center;
- display: flex;
- margin-top: 1rem;
- padding: $size-2;
- position: relative;
-
- span {
- color: $color-gray-30;
- font-size: $fs14;
- }
-
- .btn-icon-light {
- margin-left: auto;
- }
-
- &::before {
- background-color: $color-gray-10;
- content: "";
- height: 1px;
- left: 4%;
- position: absolute;
- right: 4%;
- top: -5px;
- width: 92%;
- }
-}
-
-.team-form-modal {
- h2 {
- font-weight: $fw400;
- color: $color-gray-40;
- font-size: 28px;
- margin-bottom: 30px;
- }
-
- .buttons-row {
- margin-top: 20px;
- display: flex;
- justify-content: center;
- }
-
- input[type="submit"] {
- margin-bottom: 0px;
- }
-}
-
-.profile-section {
- align-items: center;
- cursor: pointer;
- display: flex;
- padding: 10px 15px;
- position: relative;
-
- .profile {
- align-items: center;
- cursor: pointer;
- display: flex;
- flex-grow: 1;
-
- span {
- @include text-ellipsis;
- color: $color-black;
- margin: 10px;
- font-size: $fs14;
- max-width: 160px;
- }
-
- img {
- border-radius: 50%;
- flex-shrink: 0;
- height: 25px;
- width: 25px;
- }
- svg {
- height: 10px;
- margin-left: auto;
- margin-right: $size-2;
- width: 10px;
- }
- }
-
- .dropdown {
- left: 15px;
- bottom: 45px;
- min-width: 189px;
-
- @include animation(0, 0.2s, fadeInUp);
-
- li {
- font-size: $fs14;
- padding: $size-2 $size-4;
-
- svg {
- fill: $color-gray-20;
- margin-right: $size-2;
-
- height: 12px;
- width: 12px;
- }
-
- &.separator {
- border-top: 1px solid $color-gray-10;
- }
- }
- }
-}
-
-.primary-badge {
- border: 1px solid $color-primary;
- border-radius: $br2;
- font-size: $fs9 !important;
- font-weight: $fw500;
- color: $color-primary !important;
- padding: 2px 4px;
-}
diff --git a/frontend/resources/styles/main/partials/dashboard-team.scss b/frontend/resources/styles/main/partials/dashboard-team.scss
deleted file mode 100644
index 5bdfcebda5..0000000000
--- a/frontend/resources/styles/main/partials/dashboard-team.scss
+++ /dev/null
@@ -1,605 +0,0 @@
-.dashboard-invite-modal {
- top: 72px;
- right: 13px;
- padding: 32px;
- box-shadow: 0px 4px 8px rgba($color-black, 0.25);
- border-radius: $br8;
- width: 400px;
- position: fixed;
- z-index: 16;
- &.hero {
- top: 218px;
- right: 35px;
- }
-
- form {
- width: 100%;
- }
-
- .form-row {
- display: flex;
- justify-content: space-between;
- margin: 4px 0px;
- .label {
- margin-bottom: 0;
- display: flex;
- align-items: center;
- }
- }
-
- .custom-input {
- width: 100%;
- min-height: 116px;
- max-height: 176px;
- overflow-y: hidden;
- input {
- &.no-padding {
- padding-top: 12px;
- height: 50px;
- }
- min-height: 40px;
- }
- .selected-items {
- gap: 8px;
- padding: 8px;
- max-height: 132px;
- overflow-y: scroll;
- .selected-item {
- .around {
- height: 24px;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: fit-content;
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- }
- }
- }
-
- .custom-select {
- width: 180px;
- overflow: hidden;
- justify-content: normal;
- select {
- height: auto;
- }
- }
-
- .action-buttons {
- display: flex;
- margin-top: 16px;
- input[type="submit"] {
- margin-bottom: 0px;
- }
- }
-
- .title {
- color: $color-black;
- font-weight: $fw700;
- margin-bottom: 16px;
- }
-
- .hint {
- font-size: $fs12;
-
- &.hidden {
- display: none;
- }
- }
-
- svg {
- width: 12px;
- height: 12px;
- fill: $color-gray-20;
- }
-
- .error,
- .warning {
- width: 100%;
- display: flex;
- .icon {
- text-align: center;
- padding: 5px;
- svg {
- fill: $color-white;
- width: 20px;
- height: 20px;
- margin: 5px;
- }
- }
- .text {
- color: $color-black;
- padding: 5px;
- font-size: $fs12;
- }
- }
-
- .error {
- background-color: #ffd9e0;
-
- .icon {
- background-color: $color-danger;
- }
- }
-
- .warning {
- background-color: #ffeaca;
-
- .icon {
- background-color: $color-warning;
- }
- }
-}
-
-.dashboard-team-members,
-.dashboard-team-invitations,
-.dashboard-team-webhooks {
- .empty-invitations {
- height: 156px;
- max-width: 1040px;
- width: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
- border: 1px dashed $color-gray-20;
- margin-top: 16px;
- }
- .table-header {
- user-select: none;
- }
-
- .table-row {
- background-color: $color-white;
- height: 63px;
- &:not(:first-child) {
- margin-top: 16px;
- }
- }
-
- .table-field {
- &.name {
- width: 43%;
- min-width: 300px;
- display: flex;
- .member-info {
- display: flex;
- flex-direction: column;
- margin-left: 16px;
- .member-name {
- font-size: $fs16;
- .you {
- color: $color-gray-30;
- margin-left: 5px;
- }
- }
- .member-email {
- color: $color-gray-30;
- font-size: $fs12;
- }
- }
-
- .member-image {
- height: 32px;
- width: 32px;
- img {
- border-radius: 50%;
- }
- }
- }
-
- &.roles {
- flex-grow: 1;
- cursor: default;
- position: relative;
- .rol-label {
- user-select: none;
- }
- .rol-selector {
- &.has-priv {
- border: 1px solid $color-gray-20;
- cursor: pointer;
- }
- min-width: 160px;
- height: 32px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-radius: $br2;
- padding: 3px 8px;
- font-size: $fs14;
- }
- }
-
- &.actions {
- position: relative;
- .actions-dropdown {
- max-height: 30rem;
- min-width: 180px;
- }
- }
-
- &.status {
- .status-badge {
- color: $color-white;
- border-radius: $br12;
- min-width: 74px;
- height: 24px;
- display: flex;
- justify-content: center;
- align-items: center;
-
- &.pending {
- background-color: $color-warning;
- }
-
- &.expired {
- background-color: $color-gray-20;
- }
-
- .status-label {
- font-size: $fs12;
- }
- }
- }
-
- &.uri {
- flex-grow: 1;
- }
-
- &.active {
- min-width: 100px;
- }
-
- &.last-delivery {
- display: flex;
- justify-content: center;
- width: 50px;
- position: relative;
- .success svg {
- fill: $color-primary;
- width: 16px;
- height: 16px;
- }
- .failure svg {
- fill: $color-warning;
- width: 16px;
- height: 16px;
- }
-
- .icon-container {
- width: 16px;
- height: 16px;
- overflow-x: visible;
- }
-
- .icon {
- padding: 0;
- }
- }
-
- .tooltip {
- display: none;
- position: absolute;
- top: -58px;
- left: 50%;
- transform: translate(-50%, 0);
- text-align: center;
-
- .label {
- border-radius: $br3;
- color: $color-white;
- background-color: $color-black;
- white-space: nowrap;
- padding: 12px 20px;
- }
-
- .arrow-down {
- margin: 0 auto;
- width: 0;
- height: 0;
- border-left: 8px solid transparent;
- border-right: 8px solid transparent;
- border-top: 8px solid $color-black;
- }
- }
-
- .last-delivery-icon:hover {
- .tooltip {
- display: block;
- }
- }
- }
-
- .dropdown {
- position: absolute;
- max-height: 30rem;
- overflow-y: auto;
- background-color: $color-white;
- border-radius: $br4;
- box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
- z-index: 12;
- top: 30px;
- left: -151px;
- width: 155px;
-
- hr {
- margin: 0;
- border-color: $color-gray-10;
- }
-
- li {
- display: flex;
- align-items: center;
- color: $color-gray-60;
- cursor: pointer;
- font-size: $fs14;
- height: 31px;
- padding: 5px 16px;
-
- &.title {
- font-weight: $fw600;
- cursor: default;
- }
-
- &:hover {
- background-color: $color-primary-lighter;
- }
- }
- }
-}
-
-.dashboard-team-settings {
- .team-settings {
- display: flex;
- justify-content: center;
- margin-top: 16px;
-
- svg {
- width: 20px;
- height: 20px;
- }
-
- .horizontal-blocks {
- display: flex;
- max-width: 1010px;
- justify-content: space-between;
- width: 100%;
- }
-
- .block {
- display: flex;
- max-width: 324px;
- width: 324px;
- background-color: $color-white;
- flex-direction: column;
- padding: 12px;
-
- .label {
- font-size: $fs13;
- color: $color-gray-30;
- }
- }
-
- .info-block {
- position: relative;
-
- .name {
- margin-top: 10px;
- font-size: $fs24;
- color: $color-black;
- @include text-ellipsis;
- margin-right: 90px;
- }
-
- .icon {
- position: absolute;
- padding: 15px;
- width: 100px;
- height: 100px;
- right: 0px;
- top: 0px;
-
- img {
- border-radius: 50%;
- width: 70px;
- height: 70px;
- }
-
- .update-overlay {
- opacity: 0;
- cursor: pointer;
- position: absolute;
- display: flex;
- justify-content: center;
- align-items: center;
- width: 71px;
- height: 71px;
- border-radius: 50%;
- color: $color-white;
- background: $color-primary-dark;
- z-index: 14;
-
- svg {
- fill: $color-white;
- }
- }
-
- &:hover {
- .update-overlay {
- opacity: 1;
- width: 72px;
- height: 72px;
- top: 14px;
- left: 14px;
- }
- }
- }
- }
-
- .owner-block {
- img {
- width: 30px;
- height: 30px;
- border-radius: 50%;
- }
-
- svg {
- width: 12px;
- height: 12px;
- fill: $color-black;
- }
-
- .owner {
- margin-top: 5px;
- display: flex;
- align-items: center;
- color: $color-black;
- .icon {
- margin-right: 12px;
- }
- }
-
- .summary {
- margin-top: 5px;
- color: $color-black;
- .icon {
- padding: 0px 10px;
- margin-right: 12px;
- }
- }
- }
-
- .stats-block {
- svg {
- fill: $color-black;
- }
-
- .projects,
- .files {
- margin-top: 7px;
- display: flex;
- align-items: center;
- color: $color-black;
-
- .icon {
- display: flex;
- align-items: center;
- padding: 0px 2px;
- margin-right: 14px;
- }
- }
- }
- }
-}
-
-.dashboard-team-webhooks {
- display: flex;
- flex-direction: column;
- align-items: center;
-
- .webhooks-hero-container {
- max-width: 1000px;
- width: 100%;
- display: flex;
- flex-direction: column;
-
- .upload-button {
- width: 100px;
- }
-
- .btn-secondary {
- margin-left: 10px;
- }
- }
-
- .webhooks-hero {
- font-size: $fs14;
-
- padding: $size-6;
- background-color: $color-white;
- margin-top: $size-6;
- display: flex;
- justify-content: space-between;
-
- .banner {
- background-color: unset;
-
- display: flex;
-
- .icon {
- display: flex;
- align-items: center;
- padding-left: 0px;
- padding-right: 10px;
- svg {
- fill: $color-info;
- }
- }
- }
-
- .desc {
- h2 {
- margin-bottom: $size-4;
- color: $color-black;
- }
- width: 80%;
- color: $color-gray-40;
- p {
- font-size: $fs16;
- }
- }
-
- .btn-primary {
- flex-shrink: 0;
- }
- }
-
- .webhooks-empty {
- text-align: center;
- max-width: 1000px;
- width: 100%;
- padding: $size-6;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- border: 1px dashed $color-gray-20;
- color: $color-gray-40;
- margin-top: 12px;
- min-height: 136px;
- }
-}
-
-.webhooks-modal {
- .action-buttons {
- gap: 10px;
-
- .cancel-button {
- border: 1px solid $color-gray-30;
- background: $color-canvas;
- border-radius: $br3;
- padding: 0.5rem 1rem;
- cursor: pointer;
- margin-right: 8px;
-
- &:hover {
- background: $color-gray-20;
- }
- }
- }
- .input-checkbox label {
- font-size: $fs14;
- color: $color-black;
- }
-
- .explain {
- font-size: $fs12;
- color: $color-gray-40;
- }
-}
diff --git a/frontend/resources/styles/main/partials/dashboard.scss b/frontend/resources/styles/main/partials/dashboard.scss
deleted file mode 100644
index f48e89e57d..0000000000
--- a/frontend/resources/styles/main/partials/dashboard.scss
+++ /dev/null
@@ -1,638 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.team-hero {
- display: flex;
- position: relative;
- border: 2px solid $color-gray-10;
- border-radius: $br8;
- padding: 20px;
- margin: 0 1rem 0 21px;
- height: 154px;
-
- .text {
- flex-grow: 1;
- padding-left: 20px;
- .title {
- font-size: $fs24;
- font-weight: $fw700;
- color: $color-black;
- }
- .info {
- span {
- color: $color-gray-30;
- display: block;
- }
- padding-top: 10px;
- }
- }
- .close {
- position: absolute;
- top: 20px;
- right: 20px;
- background-color: transparent;
- border: none;
- cursor: pointer;
- svg {
- transform: rotate(45deg);
- width: 16px;
- height: 16px;
- }
- }
- .invite {
- align-self: flex-end;
- height: 40px;
- font-family: "worksans", sans-serif;
- width: 180px;
- }
- img {
- width: 274px;
- margin-bottom: -19px;
- @media (max-width: 1200px) {
- display: none;
- width: 0;
- }
- }
-}
-
-.hero-projects {
- display: grid;
- grid-template-columns: 1fr 1fr;
- grid-gap: 30px;
- margin: 0 1rem 1rem 1.2rem;
- .tutorial,
- .walkthrough {
- display: grid;
- grid-template-columns: 1fr 1fr;
- position: relative;
- border: 2px solid $color-gray-10;
- border-radius: $br8;
- min-height: 211px;
-
- .thumbnail {
- border-top-left-radius: $br6;
- border-bottom-left-radius: $br6;
- padding: 30px;
- display: block;
- background-color: #e0e4e9;
- }
-
- .text {
- padding: 30px;
- .title {
- color: $color-black;
- font-size: $fs24;
- font-weight: $fw700;
- margin-bottom: 8px;
- }
- .info {
- color: $color-gray-50;
- margin-bottom: 20px;
- font-size: $fs14;
- }
- }
- .action {
- font-family: "worksans", sans-serif;
- width: 180px;
- height: 40px;
- }
- .close {
- position: absolute;
- top: 0;
- right: 0;
- width: $size-5;
- cursor: pointer;
- display: flex;
- margin: 20px;
- justify-content: center;
- align-items: center;
- background-color: transparent;
- border: none;
- .icon {
- svg {
- fill: $color-gray-30;
- height: 16px;
- width: 16px;
- transform: rotate(45deg);
- &:hover {
- fill: $color-primary;
- }
- }
- }
- }
-
- @media (max-width: 1846px) {
- grid-template-columns: 190px 1fr;
- }
- @media (max-width: 1526px) {
- grid-template-columns: 1fr;
- .img {
- display: none;
- width: 0;
- }
- }
- }
- .walkthrough {
- .thumbnail {
- background-image: url("/images/walkthrough-cover.png");
- background-position: center;
- background-repeat: no-repeat;
- background-size: cover;
- }
- }
- .tutorial {
- .thumbnail {
- background-image: url("/images/hands-on-tutorial.png");
- background-position: center;
- background-repeat: no-repeat;
- background-size: cover;
- }
- .loader {
- display: flex;
- svg#loader-pencil {
- width: 31px;
- }
- }
- }
-}
-
-.dashboard-container {
- background-color: $color-dashboard;
- flex: 1 0 0;
- margin-right: $size-4;
- overflow-y: auto;
- width: 100%;
- &.dashboard-projects {
- user-select: none;
- }
- &.no-bg {
- background-color: transparent;
- }
- &.dashboard-shared {
- width: calc(100vw - 320px);
- margin-right: 50px;
- }
-
- &.search {
- margin-top: 10px;
- }
-}
-
-.dashboard-project-row {
- margin-bottom: $size-5;
- position: relative;
-
- .project {
- align-items: center;
- background: $color-white;
- border-radius: $br3;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- margin-top: $size-4;
- padding: $size-2 $size-2 $size-2 $size-4;
- width: 99%;
- max-height: 40px;
- gap: $size-2;
- .project-name-wrapper {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- min-height: 32px;
- margin-left: $size-2;
- }
- .show-more {
- align-items: center;
- color: $color-gray-30;
- display: flex;
- font-size: $fs14;
- justify-content: space-between;
- cursor: pointer;
- background-color: transparent;
- border: none;
- .placeholder-icon {
- transform: rotate(-90deg);
- margin-left: 10px;
- svg {
- height: 14px;
- width: 14px;
- fill: $color-gray-30;
- }
- }
- &:hover {
- color: $color-primary-dark;
- svg {
- fill: $color-primary-dark;
- }
- }
- }
-
- .btn-secondary {
- border: none;
- padding: $size-2;
- }
-
- h2 {
- cursor: pointer;
- font-size: $fs18;
- line-height: $lh-088; // Original value was 1rem = 16px; 16px/18px = 88.88888% => $lh-088
- font-weight: $fw600;
- color: $color-black;
- margin-right: $size-1;
- }
-
- .edit-wrapper {
- margin-right: $size-4;
- }
-
- .info {
- font-size: $fs14;
- line-height: $lh-115; // Original value was 1rem = 16px; 16px/14px = 114.285714286% => $lh-115 (rounded)
- font-weight: $fw400;
- color: $color-gray-60;
- margin-left: 0.75rem;
- @media (max-width: 760px) {
- display: none;
- }
- }
-
- .project-actions {
- display: flex;
- opacity: 0;
- margin-left: $size-6;
-
- .btn-small {
- height: 32px;
- margin: 0 $size-2;
- width: 32px;
- }
- }
-
- .pin-icon {
- cursor: pointer;
- display: flex;
- align-items: center;
- margin-right: 14px;
- background-color: transparent;
- border: none;
- svg {
- width: 15px;
- height: 15px;
- fill: $color-gray-20;
- }
-
- &.active {
- svg {
- fill: $color-gray-50;
- }
- }
- }
- }
-
- &:hover,
- &:focus,
- &:focus-within {
- .project-actions {
- opacity: 1;
- }
- }
-
- .show-more {
- align-items: center;
- color: $color-gray-30;
- display: flex;
- font-size: $fs14;
- justify-content: space-between;
- cursor: pointer;
- background-color: transparent;
- border: none;
- position: absolute;
- top: 9px;
- right: 53px;
- .placeholder-icon {
- transform: rotate(-90deg);
- margin-left: 10px;
- svg {
- height: 14px;
- width: 14px;
- fill: $color-gray-30;
- }
- }
- &:hover {
- color: $color-primary-dark;
- svg {
- fill: $color-primary-dark;
- }
- }
- }
-}
-
-.recent-files-row-title-info {
- color: $color-gray-60;
- line-height: $lh-115; // Original value was 1rem = 16px; 16px/14px = 114.285714286% => $lh-115
- font-size: $fs14;
- font-weight: $fw400;
- @media (max-width: 880px) {
- display: none;
- }
-}
-
-.dashboard-table {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-top: 20px;
- font-size: $fs16;
-
- &.team-members {
- margin-bottom: 52px;
- }
-
- &.invitations {
- .table-row {
- display: grid;
- grid-template-columns: 43% 1fr 109px 12px;
- }
- }
-
- .table-header {
- display: grid;
- grid-template-columns: 43% 1fr 109px 12px;
- max-width: 1040px;
- background-color: $color-white;
- color: $color-gray-30;
- width: 100%;
- height: 40px;
- padding: 0px 16px;
- }
-
- .table-rows {
- display: flex;
- flex-direction: column;
- max-width: 1040px;
- width: 100%;
- margin-top: 16px;
- color: $color-black;
- }
-
- .table-row {
- display: flex;
- width: 100%;
- height: 45px;
- align-items: center;
- padding: 0px 16px;
- }
-
- .table-field {
- display: flex;
- align-items: center;
-
- .icon {
- padding-left: 10px;
- cursor: pointer;
- }
- }
-
- svg {
- width: 10px;
- height: 10px;
- fill: $color-black;
- }
-}
-
-.edit-wrapper {
- border: 1px solid $color-gray-10;
- border-radius: $br3;
- display: flex;
- padding-right: $size-5;
- position: relative;
-
- input.element-title {
- border: 0;
- height: 30px;
- padding: 5px;
- margin: 0;
- width: 100%;
- background-color: $color-white;
- }
-
- .close {
- cursor: pointer;
- position: absolute;
-
- top: 1px;
- right: 2px;
-
- svg {
- fill: $color-gray-30;
- height: 15px;
- transform: rotate(45deg) translateY(7px);
- width: 15px;
- margin: 0;
- }
- }
-}
-
-.import-file-btn {
- align-items: center;
- display: flex;
- flex-direction: column;
- height: 2rem;
- justify-content: center;
- overflow: hidden;
- padding: 4px;
- width: 2rem;
-
- background: none;
- border: 1px solid $color-gray-20;
- border-radius: $br2;
- cursor: pointer;
- transition: all 0.4s;
- margin-left: 1rem;
-
- &:hover {
- background: $color-primary;
- }
-
- svg {
- width: 16px;
- height: 16px;
- }
-}
-
-.dashboard-templates-section {
- position: absolute;
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
- bottom: 0;
- width: 100%;
- height: 228px;
- transition: bottom 300ms;
- pointer-events: none;
- &.collapsed {
- bottom: -228px;
- transition: bottom 300ms;
- }
-
- .title {
- pointer-events: all;
- width: fit-content;
- top: -56px;
- right: -28px;
- text-align: right;
- height: 56px;
- position: absolute;
- button {
- border: none;
- cursor: pointer;
- height: 58px;
- display: inline-flex;
- align-items: center;
- border-top: 2px solid #e4e4e4;
- border-left: 2px solid #e4e4e4;
- border-right: 2px solid #e4e4e4;
- border-top-left-radius: $br10;
- border-top-right-radius: $br10;
- margin-right: 30px;
- background-color: $color-white;
- position: relative;
- z-index: 1;
- span {
- display: inline-block;
- vertical-align: middle;
- line-height: $lh-normal;
- font-size: $fs18;
- font-weight: $fw600;
- color: $color-black;
- margin-left: 18px;
- margin-right: 10px;
- &.icon {
- margin-left: 10px;
- margin-right: 16px;
- }
- }
- svg {
- width: 12px;
- height: 12px;
- }
- }
- }
-
- .button {
- position: absolute;
- top: 133px;
- border: 2px solid #e0e4e9;
- border-radius: 50%;
- text-align: center;
- width: 35px;
- height: 35px;
- cursor: pointer;
- background-color: $color-white;
- display: flex;
- align-items: center;
- justify-content: center;
- pointer-events: all;
- svg {
- width: 12px;
- height: 12px;
- }
-
- &.left {
- left: 0;
- margin-left: 43px;
- }
-
- &.right {
- right: 0;
- margin-right: 43px;
- }
-
- &:hover {
- border: 2px solid $color-primary;
- }
- }
-
- .content {
- pointer-events: all;
- background-color: $color-white;
- width: 200%;
- height: 229px;
- border-top: 2px solid #e4e4e4;
- border-left: 2px solid #e4e4e4;
- margin-left: 5px;
- position: absolute;
-
- .card-container {
- width: 275px;
- margin-top: 20px;
- display: inline-block;
- text-align: center;
- vertical-align: top;
- background-color: transparent;
- border: none;
- padding: 0;
- }
-
- .template-card {
- display: inline-block;
- width: 255px;
- font-size: $fs16;
- color: #181a22;
- cursor: pointer;
- .img-container {
- width: 100%;
- height: 135px;
- margin-bottom: 15px;
- border-radius: $br5;
- border: 2px solid #e0e4e9;
- display: flex;
- justify-content: center;
- flex-direction: column;
- }
-
- .card-name {
- padding: 0 5px;
- display: flex;
- justify-content: space-between;
- height: 23px;
- svg {
- width: 16px;
- height: 16px;
- }
- span {
- font-weight: $fw500;
- font-size: $fs14;
- }
- }
-
- .template-link {
- border: 2px solid transparent;
- margin: 30px;
- padding: 32px 0;
- }
-
- .template-link-title {
- font-size: $fs14;
- font-weight: $fw600;
- color: $color-gray-60;
- }
-
- .template-link-text {
- font-size: $fs12;
- margin-top: $size-2;
- color: $color-gray-50;
- }
-
- &:hover {
- .img-container {
- border: 2px solid $color-primary;
- }
- }
- }
- }
-}
diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss
deleted file mode 100644
index f3ca1df159..0000000000
--- a/frontend/resources/styles/main/partials/modal.scss
+++ /dev/null
@@ -1,1930 +0,0 @@
-.modal-overlay {
- align-items: center;
- background-color: $color-dark-bg;
- display: flex;
- justify-content: center;
- position: fixed;
- height: 100%;
- left: 0;
- top: 0;
- width: 100%;
- z-index: 1000;
-
- &.transparent {
- background-color: rgba($color-white, 0);
- }
-}
-
-.modal,
-.generic-modal {
- background-color: $color-white;
- width: 565px;
- display: flex;
- position: relative;
-
- .close {
- cursor: pointer;
- position: absolute;
- right: 16px;
- top: 16px;
- svg {
- width: 16px;
- height: 16px;
- transform: rotate(45deg);
- }
- }
-
- .modal-content {
- display: flex;
- flex-grow: 1;
- flex-direction: column;
- padding: 60px 100px;
- }
-
- .button-row {
- display: flex;
- justify-content: space-between;
-
- > button {
- font-size: $fs12;
- }
- > button:not(:first-child) {
- margin-left: 25px;
- }
- }
-}
-
-// NEW GEN MODALS
-
-.modal-container {
- border-radius: $br5;
- display: flex;
- flex-direction: column;
- width: 448px;
- background-color: $color-white;
- max-height: 700px;
-
- .modal-header {
- align-items: center;
- background-color: $color-white;
- border-radius: $br8 $br8 0 0;
- color: $color-black;
- display: flex;
- height: 63px;
- justify-content: space-between;
- }
-
- .modal-header-title {
- display: flex;
- align-items: center;
- font-size: $fs18;
- padding-left: 16px;
-
- h2 {
- font-size: $fs18;
- font-weight: $fw400;
- margin: 0;
- }
- }
-
- .modal-close-button {
- align-items: center;
- cursor: pointer;
- display: flex;
- height: 30px;
- justify-content: center;
- margin-right: 16px;
-
- svg {
- transform: rotate(45deg);
- width: 16px;
- height: 16px;
- }
- }
-
- .component-list {
- max-height: 408px;
- overflow-y: scroll;
- }
-
- .modal-item-element {
- display: flex;
- padding-bottom: 3px;
- margin-left: 10px;
- font-size: $fs14;
- color: $color-info;
-
- .modal-component-icon {
- margin-right: 16px;
- display: flex;
- justify-content: center;
- align-items: center;
- svg {
- width: 16px;
- height: 16px;
- fill: $color-info;
- }
- }
- }
-
- .modal-content {
- display: flex;
- flex-direction: column;
- padding: 32px;
- border-top: 1px solid $color-gray-10;
- h3 {
- color: $color-gray-40;
- font-size: $fs16;
- font-weight: $fw400;
- }
- &.delete-shared {
- padding: 15px 32px;
- .modal-item-element {
- font-size: $fs16;
- }
- }
- }
-
- .modal-footer {
- display: flex;
- height: 63px;
- padding: 0px 18px;
- border-top: 1px solid $color-gray-10;
-
- .action-buttons {
- display: flex;
- width: 100%;
- height: 100%;
- justify-content: flex-end;
- // border: 1px solid red;
- align-items: center;
-
- input {
- margin-bottom: 0px;
- }
- }
- }
-
- .btn-disabled {
- opacity: 0.5;
- }
-}
-
-.change-email-modal {
- h2 {
- font-size: $fs18;
- }
-
- h3 {
- margin-bottom: 15px;
- }
-
- .modal-footer .action-buttons {
- justify-content: space-around;
- gap: 15px;
- }
-
- .fields-container {
- margin-top: 1rem;
- }
-}
-
-.confirm-dialog,
-.alert-dialog {
- background-color: $color-white;
-
- p {
- font-size: $fs14;
- color: $color-gray-40;
- }
-
- .action-buttons {
- display: flex;
- flex-direction: row;
- width: 100%;
- font-size: $fs14;
- }
-
- .cancel-button {
- border: 1px solid $color-gray-30;
- background: $color-canvas;
- border-radius: $br3;
- padding: 0.5rem 1rem;
- cursor: pointer;
- margin-right: 8px;
-
- &:hover {
- background: $color-gray-20;
- }
- }
-
- .accept-button {
- border-radius: $br3;
- cursor: pointer;
- padding: 0.5rem 1rem;
-
- &.danger {
- background: $color-danger;
- border: 1px solid $color-danger;
- color: $color-white;
- &:hover {
- background: $color-danger-dark;
- }
- }
-
- &.primary {
- background: $color-primary;
- border: 1px solid $color-primary;
- color: $color-black;
-
- &:hover {
- background: $color-primary-dark;
- }
- }
- }
-}
-
-.import-dialog,
-.export-dialog,
-.export-multiple-dialog {
- background-color: $color-white;
- border: 1px solid $color-gray-20;
- width: 30rem;
- min-height: 14rem;
-
- &.empty {
- width: 39rem;
- }
-
- p {
- font-size: $fs14;
- color: $color-black;
- }
-
- .detail {
- font-size: $fs12;
- }
-
- .detail,
- .explain {
- padding: 0 1rem;
- }
-
- .cancel-button {
- border: 1px solid $color-gray-20;
- background: $color-white;
- border-radius: $br3;
- padding: 0.5rem 2.25rem;
- cursor: pointer;
- margin-right: 18px;
-
- &:hover {
- background: $color-gray-20;
- }
- }
-
- .accept-button {
- background: $color-primary;
- border-radius: $br3;
- border: 1px solid $color-primary;
- color: $color-black;
- cursor: pointer;
- padding: 0.5rem 2.25rem;
-
- &[disabled] {
- border: 1px solid #e3e3e3;
- }
-
- &:hover {
- background: $color-primary-dark;
- }
- }
-
- .modal-content {
- flex: 1;
- overflow-y: auto;
- max-height: calc(65vh);
- }
-
- .modal-header-title {
- padding-left: 2rem;
-
- h2 {
- font-size: $fs18;
- }
- }
-
- .modal-content {
- padding: 1rem;
- }
-
- .file-entry {
- margin: 0.75rem 1rem;
- user-select: none;
-
- &.editable:hover {
- .file-name-label {
- background-color: $color-primary-lighter;
- }
- .edit-entry-buttons {
- display: flex;
- background-color: $color-primary-lighter;
- }
- }
- }
-
- .file-icon {
- width: 18px;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 1rem;
-
- svg {
- width: 18px;
- height: 18px;
- }
-
- #loader-pencil {
- fill: $color-black;
- }
-
- .icon-tick {
- fill: $color-success;
- }
-
- .icon-msg-warning {
- fill: $color-warning;
- }
-
- .icon-close {
- transform: rotate(45deg);
- fill: $color-danger;
- }
- }
-
- .file-name {
- display: flex;
- align-items: center;
- color: $color-black;
-
- .file-name-label {
- align-items: center;
- flex: 1;
- height: 2rem;
- margin-left: -0.25rem;
- overflow: hidden;
- padding-left: 0.25rem;
- padding-top: 0.25rem;
- text-overflow: ellipsis;
- white-space: nowrap;
-
- .icon-library {
- height: 14px;
- width: 14px;
- fill: $color-gray-20;
- margin-left: 0.5rem;
- padding-top: 1px;
- }
- }
-
- .file-name-edit {
- width: 100%;
-
- input {
- margin: 0;
- border: none;
- border-bottom: 1px solid $color-gray-20;
- height: 2rem;
- width: 100%;
- }
- }
- }
-
- .feedback-banner {
- color: $color-black;
- background: $color-success-lighter;
- height: 40px;
- display: flex;
- align-items: center;
- margin: 0 1rem;
-
- .message {
- padding: 0 1rem;
- font-size: $fs12;
- }
-
- .icon {
- background: $color-success;
- height: 40px;
- width: 40px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- svg {
- width: 20px;
- height: 20px;
- fill: $color-white;
- }
- }
-
- &.warning {
- background: $color-warning-lighter;
- .icon {
- background: $color-warning;
- }
- }
- }
-
- .error-message {
- margin: 0 2rem;
- color: $color-danger;
- font-size: $fs12;
- font-style: italic;
- }
-
- .progress-message {
- margin: 0 2rem;
- color: $color-info;
- font-size: $fs12;
- font-style: italic;
- }
-
- .linked-libraries {
- display: flex;
- flex-wrap: wrap;
- margin-left: 2rem;
-
- .icon-chain,
- .icon-unchain {
- width: 10px;
- height: 10px;
- margin-right: 2px;
- }
-
- .linked-library-tag {
- font-size: $fs10;
- color: $color-black;
- background: #d8f7fe;
- border-radius: $br3;
- padding: 2px 4px;
- display: flex;
- align-items: center;
- margin: 0.25rem;
-
- &.error {
- background-color: $color-danger-lighter;
- }
- }
- }
-
- .edit-entry-buttons {
- display: flex;
- flex-direction: row;
- font-size: $fs14;
- height: 2rem;
- display: none;
-
- button {
- border: none;
- background: none;
- display: block;
- cursor: pointer;
-
- svg {
- width: 14px;
- height: 14px;
- }
-
- &:hover svg {
- fill: $color-primary;
- }
- }
- }
-}
-
-.export-dialog {
- .export-option {
- border-radius: $br4;
- border: 1px solid $color-gray-10;
- margin-bottom: 0.5rem;
-
- h3 {
- font-weight: $fw700;
- }
-
- h3,
- p {
- font-size: $fs12;
- line-height: $lh-150;
- margin: 0;
- color: $color-black;
- padding: 0;
- }
-
- &.selected {
- border: 1px solid $color-primary;
- }
-
- &.table-row {
- align-items: center;
- display: flex;
- flex-wrap: wrap;
- height: 45px;
- justify-content: space-between;
- padding: 0px 0px;
- width: 100%;
- }
-
- .table-field {
- flex-grow: 0;
- padding: 0px 4px;
- overflow: hidden;
- text-overflow: ellipsis;
- width: 50px;
-
- &.check {
- width: 30px;
- }
-
- &.scale {
- flex-grow: 1;
- width: 15%;
- }
-
- &.name {
- flex-grow: 1;
- width: 40%;
- }
- }
- }
-
- .option-container {
- display: block;
- position: relative;
- padding-left: 40px;
- padding-right: 1rem;
- padding-top: 1rem;
- padding-bottom: 1rem;
- cursor: pointer;
- user-select: none;
-
- input {
- position: absolute;
- opacity: 0;
- cursor: pointer;
- height: 0;
- width: 0;
- }
-
- .option-radio-check {
- position: absolute;
- top: 1rem;
- left: 12px;
- height: 18px;
- width: 18px;
- background-color: $color-white;
- border: 1px solid $color-gray-10;
- border-radius: 50%;
- }
-
- &:hover input ~ .option-radio-check {
- border-color: $color-primary;
- }
-
- input:checked ~ .option-radio-check {
- border-color: $color-primary;
- background-color: $color-white;
- }
-
- .option-radio-check:after {
- content: "";
- position: absolute;
- display: none;
- }
-
- input:checked ~ .option-radio-check:after {
- display: block;
- background-color: $color-primary;
- }
-
- .option-radio-check:after {
- top: 3px;
- left: 3px;
- width: 10px;
- height: 10px;
- border-radius: 50%;
- background: white;
- }
- }
-}
-
-.libraries-dialog {
- border-radius: $br5;
- height: 664px;
- width: 920px;
- max-height: 100%;
-
- .modal-content {
- display: flex;
- flex-grow: 1;
- flex-direction: column;
- padding: 0;
- }
-
- .libraries-header {
- border-bottom: 1px solid $color-gray-20;
- padding: 2rem 1rem 0.5rem 1rem;
- display: flex;
- justify-content: center;
-
- .header-item {
- cursor: pointer;
- color: $color-gray-40;
- font-size: $fs14;
-
- &.active {
- color: $color-gray-60;
- border-bottom: 2px solid $color-primary;
- }
-
- &:not(:first-child) {
- margin-left: 3rem;
- }
- }
- }
-
- .libraries-content {
- display: flex;
- justify-content: stretch;
- align-items: stretch;
- flex-grow: 1;
- padding: 0 $size-4;
- color: $color-gray-40;
-
- .section {
- flex-basis: 0;
- flex-grow: 1;
- padding: $size-4 0;
- display: flex;
- flex-direction: column;
-
- &:not(:first-child) {
- border-left: 1px solid $color-gray-20;
- }
- }
-
- .section-title {
- color: $color-black;
- font-size: $fs14;
- padding: 0 $size-4;
- font-weight: $fw500;
- }
-
- .section-list {
- flex-basis: 0;
- flex-grow: 1;
- padding: 0 $size-4;
- overflow: auto;
-
- .section-list-item {
- padding: $size-4 0;
- border-bottom: 1px solid $color-gray-20;
- position: relative;
-
- .item-name {
- color: $color-gray-60;
- font-size: $fs14;
- margin-right: calc(4.5rem + 1rem);
- }
-
- .item-contents {
- color: $color-gray-40;
- font-size: $fs12;
- margin-right: calc(4.5rem + 1rem);
- }
-
- .item-button {
- cursor: pointer;
- top: $size-4;
- right: 0;
- border: 1px solid $color-primary;
- border-radius: $br2;
- min-width: 4.5rem;
- background: $color-primary;
- color: $color-black;
- padding: $size-2;
- margin-bottom: 0;
- position: absolute;
- top: 1rem;
-
- &:hover {
- color: $color-primary;
- background: $color-black;
- }
-
- &.item-update {
- background: $color-warning;
- border-color: $color-warning;
- color: $color-black;
-
- &.disabled {
- background: $color-gray-10;
- border-color: $color-gray-10;
- color: $color-black;
- cursor: unset;
- }
- }
- }
- }
- }
-
- .section-list-empty {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- padding: 0 $size-4;
- flex-grow: 1;
-
- & svg {
- fill: $color-gray-20;
- height: 50px;
- width: 50px;
- margin-bottom: $size-4;
- }
-
- & svg#loader-pencil {
- fill: $color-gray-20;
- height: 75px;
- width: 75px;
- margin-bottom: $size-4;
- }
- }
-
- .libraries-search {
- border: 1px solid $color-gray-20;
- margin: $size-4;
- padding: $size-1 $size-2;
- display: flex;
- align-items: center;
-
- &:focus-within {
- border-color: $color-primary;
- }
-
- & .search-input {
- border: none;
- color: $color-gray-60;
- font-size: $fs12;
- margin: 0;
- padding: 0;
- flex-grow: 1;
-
- &:hover,
- &:focus {
- outline: none;
- }
- }
-
- & .search-icon {
- display: flex;
- align-items: center;
-
- svg {
- fill: $color-gray-30;
- height: 16px;
- width: 16px;
- }
-
- &.search-close {
- transform: rotate(45deg);
- cursor: pointer;
- }
- }
- }
-
- .libraries-updates {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
- grid-gap: $size-5;
- font-size: $fs12;
- margin-top: $size-4;
-
- .libraries-updates-item {
- display: flex;
- align-items: center;
-
- &:not(:first-child) {
- margin-top: $size-2;
- }
-
- & svg {
- background-color: $color-canvas;
- border-radius: $br4;
- border: 2px solid transparent;
- height: 24px;
- width: 24px;
- min-height: 24px;
- min-width: 24px;
- margin-right: $size-2;
- }
-
- & .color-bullet {
- margin-right: $size-2;
- }
-
- & .typography-sample {
- margin-right: $size-2;
- }
-
- & .name-block {
- color: $color-gray-20;
- width: calc(100% - 24px - #{$size-2});
-
- &.ellipsis {
- padding-left: calc(24px + #{$size-2});
- }
- }
-
- & .item-name {
- display: block;
- margin: 0;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- }
- }
- }
-
- .libraries-updates-see-all {
- margin-top: $size-2;
- direction: rtl;
- & input {
- border: none;
- color: $color-info;
- cursor: pointer;
- margin-bottom: 0;
- text-decoration: underline;
- }
- }
- }
-}
-
-//- ONBOARDING
-.onboarding {
- background-color: $color-white;
- box-shadow: 0 10px 10px rgba(0, 0, 0, 0.2);
- display: flex;
- max-height: 710px;
- min-height: 420px;
- flex-direction: row;
- font-family: "sourcesanspro", sans-serif;
- min-width: 620px;
- position: relative;
-
- .modal-left {
- align-items: center;
- background-color: $color-pink;
- border-top-left-radius: $br5;
- border-bottom-left-radius: $br5;
- display: flex;
- flex-shrink: 0;
- justify-content: center;
- overflow: hidden;
- padding: $size-6;
- width: 230px;
-
- &.welcome {
- padding: 0;
- }
- }
-
- .modal-right {
- border-top-right-radius: $br5;
- border-bottom-right-radius: $br5;
- display: flex;
- flex-direction: column;
- padding: $size-6;
-
- .modal-title h2 {
- color: $color-black;
- font-size: $fs24;
- font-weight: $fw900;
- }
-
- .release {
- background-color: $color-primary;
- color: $color-black;
- font-size: $fs12;
- font-weight: $fw700;
- margin-top: $size-2;
- padding: 2px $size-1;
- width: max-content;
- }
-
- .modal-content {
- border: none;
- padding: $size-5 0;
-
- p {
- color: $color-black;
- font-size: $fs16;
- margin-top: $size-2;
- }
- }
-
- .modal-navigation {
- align-items: center;
- display: flex;
- margin-top: auto;
-
- .skip {
- cursor: pointer;
- font-family: "worksans", sans-serif;
- font-size: $fs12;
- margin-left: $size-5;
-
- &:hover {
- color: $color-black;
- }
- }
- }
-
- .step-dots {
- align-items: center;
- display: flex;
- margin-bottom: 0;
- margin-left: auto;
-
- li {
- background-color: $color-gray-10;
- border-radius: 50%;
- cursor: pointer;
- height: $size-2;
- margin-left: $size-2;
- width: $size-2;
-
- &.current {
- background-color: $color-primary;
- }
- }
- }
- }
-
- &.onboarding-v2 {
- min-height: unset;
- height: 100%;
- min-width: 752px;
- .modal-left {
- background-color: $color-gray-50;
- width: 297px;
- }
-
- .welcome img {
- width: 297px;
- height: 464px;
- position: absolute;
- bottom: 0;
- border-radius: $br5;
- }
-
- .modal-right {
- padding: 0;
- }
-
- .release-container {
- width: 100%;
- text-align: right;
- position: relative;
- height: 2rem;
- }
-
- .release {
- background-color: $color-primary;
- border-radius: $br4;
- color: #1f1f1f;
- padding: 4px $size-1;
- display: inline-block;
- margin-top: 1rem;
- margin-right: 1rem;
- }
-
- .right-content {
- padding: $size-6;
-
- .modal-content {
- padding: $size-1 0;
- p {
- margin-top: 0.4rem;
- }
- }
-
- .welcome-card {
- display: flex;
- color: $color-black;
- margin-top: $size-5;
- width: 90%;
-
- .title a {
- font-weight: $fw700;
- color: $color-black;
- text-decoration: none;
- &:hover {
- color: $color-primary-dark;
- }
- }
-
- .description {
- font-size: $fs12;
- text-decoration: none;
- text-transform: none;
- }
-
- img {
- width: 48px;
- height: 48px;
- margin-right: 6px;
- }
- }
- }
-
- .modal-navigation {
- width: 100%;
- padding: 0 2rem 2rem 0;
-
- button {
- margin-left: auto;
- padding: 0 0.5rem;
- }
- }
- }
-
- &.black {
- .modal-left {
- background-color: $color-black;
- }
- }
-
- button {
- font-family: "worksans", sans-serif;
- }
-
- &.feature {
- .modal-left {
- padding: 0;
-
- img {
- border-top-left-radius: $br5;
- border-bottom-left-radius: $br5;
- height: 100%;
- width: 115%;
- }
- }
- }
-
- &.final {
- // TODO: Juan revisa TODA esta parte
-
- padding: $size-5 0 0 0;
- flex-direction: column;
-
- .modal-top {
- padding: 40px 40px 0 40px;
- color: $color-gray-60;
- display: flex;
- flex-direction: column;
- align-items: center;
-
- h1 {
- font-family: "worksans", sans-serif;
- font-weight: $fw700;
- font-size: $fs26;
- margin-bottom: $size-3;
- text-align: center;
- }
- p {
- font-family: "worksans", sans-serif;
- font-weight: $fw500;
- font-size: $fs18;
- text-align: center;
- }
- }
-
- .modal-columns {
- display: flex;
- margin: 17px;
-
- .modal-left {
- background-image: url("/images/on-solo.svg");
- background-position: left top;
- background-size: 11%;
- }
-
- .modal-left:hover {
- background-image: url("/images/on-solo-hover.svg");
- background-size: 15%;
- }
-
- .modal-right {
- background-image: url("/images/on-teamup.svg");
- background-position: right top;
- background-size: 28%;
- }
-
- .modal-right:hover {
- background-image: url("/images/on-teamup-hover.svg");
- background-size: 32%;
- }
-
- .modal-right,
- .modal-left {
- background-repeat: no-repeat;
- border-radius: $br5;
- transition: all ease 0.3s;
- &:hover {
- background-color: $color-primary;
- }
- }
- }
-
- .modal-left {
- margin-right: 35px;
- }
-
- .modal-left,
- .modal-right {
- justify-content: center;
- align-items: center;
- background-color: $color-white;
- color: $color-black;
- flex: 1;
- flex-direction: column;
- // overflow: visible;
- // padding: $size-6 40px;
- text-align: center;
-
- border: 1px solid $color-gray-10;
- border-radius: $br2;
- min-height: 180px;
- width: 233px;
- cursor: pointer;
-
- h2 {
- font-weight: $fw700;
- margin-bottom: $size-5;
- font-size: $fs24;
- }
-
- p {
- font-size: $fs14;
- }
-
- img {
- box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.25);
- border-radius: $br5;
- margin-bottom: $size-6;
- margin-top: -90px;
- width: 150px;
- }
- }
- }
-
- &.newsletter {
- padding: $size-5 0 0 0;
- flex-direction: column;
- min-width: 623px;
- .modal-top {
- padding: 87px 40px 0 40px;
- color: $color-gray-60;
- display: flex;
- flex-direction: column;
-
- h1 {
- font-family: sourcesanspro;
- font-weight: $fw700;
- font-size: $fs36;
- margin-bottom: 0.75rem;
- }
-
- p {
- font-family: sourcesanspro;
- font-weight: $fw500;
- font-size: $fs16;
- margin-bottom: 1.5rem;
- }
- }
-
- .modal-bottom {
- margin: 0 32px;
- padding: 32px 0;
- color: $color-gray-60;
- display: flex;
- flex-direction: column;
- border-top: 1px solid $color-gray-10;
-
- .input-checkbox {
- margin-bottom: 23px;
-
- label {
- font-family: "worksans", sans-serif;
- text-align: left;
- color: $color-black;
- font-size: $fs12;
- }
- }
-
- p {
- font-family: "worksans", sans-serif;
- text-align: left;
- color: $color-gray-30;
- }
- }
-
- .modal-footer {
- padding: 17px;
- display: flex;
- justify-content: flex-end;
-
- .btn-secondary {
- margin-right: 16px;
- }
- }
-
- .deco.top {
- width: 183px;
- top: -106px;
- left: 213px;
- }
- }
-}
-
-.deco {
- left: -10px;
- position: absolute;
- top: -18px;
- width: 60px;
-
- &.left {
- left: -50px;
- top: 100px;
- color: $color-primary;
- }
-
- &.right {
- left: auto;
- color: $color-primary;
- top: 100px;
- right: -40px;
- }
-
- &.square {
- top: -18px;
- left: 631px;
- width: 24px;
- height: 24px;
- color: $color-primary;
- }
-
- &.circle {
- top: -16px;
- left: 21px;
- width: 24px;
- height: 24px;
- color: $color-primary;
- }
-
- &.line1 {
- top: 110px;
- left: -12px;
- width: 16px;
- height: 49px;
- color: $color-primary;
- }
-
- &.line2 {
- top: 440px;
- left: 733px;
- width: 46px;
- height: 43px;
- color: $color-primary;
- }
-
- &.top {
- width: 183px;
- top: -106px;
- left: 161px;
- }
-
- &.newsletter-right {
- left: 586px;
- top: 50px;
- }
-
- &.newsletter-left {
- width: 26px;
- left: -15px;
- top: -15px;
- }
-}
-
-.relnotes .onboarding {
- height: 420px;
-}
-
-.onboarding-templates {
- position: fixed;
- top: 0;
- right: 0;
- width: 348px;
- height: 100vh;
-
- .modal-close-button {
- width: 34px;
- height: 34px;
- margin-right: 13px;
- margin-top: 13px;
- svg {
- width: 24px;
- height: 24px;
- }
- }
-
- .modal-header {
- height: unset;
- border-radius: unset;
- justify-content: flex-end;
- }
-
- .modal-content {
- border: 0px;
- padding: 0px 25px;
- background-color: $color-white;
- flex-grow: 1;
-
- p,
- h3 {
- color: $color-gray-60;
- text-align: center;
- }
-
- h3 {
- font-size: $fs18;
- font-weight: $fw700;
- }
-
- p {
- font-size: $fs16;
- }
-
- .templates {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-top: 8%;
- }
-
- .template-item {
- width: 275px;
- border: 1px solid $color-gray-10;
-
- display: flex;
- flex-direction: column;
- text-align: left;
- border-radius: $br3;
-
- &:not(:last-child) {
- margin-bottom: 22px;
- }
- }
-
- .template-item-content {
- // height: 144px;
- flex-grow: 1;
-
- img {
- border-radius: $br3 $br3 0 0;
- }
- }
-
- .template-item-title {
- padding: 6px 12px;
- height: 64px;
- border-top: 1px solid $color-gray-10;
-
- .label {
- color: $color-black;
- padding: 0px 4px;
- font-size: $fs16;
- display: flex;
- }
-
- .action {
- color: $color-primary-dark;
- cursor: pointer;
- font-size: $fs14;
- font-weight: $fw600;
- display: flex;
- justify-content: flex-end;
- margin-top: $size-2;
- }
- }
- }
-}
-
-.onboarding-team,
-.onboarding-team-members {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- min-width: 620px;
- min-height: 420px;
- width: 816px;
- height: 488px;
- position: relative;
- .team-right {
- width: 361px;
- height: 100%;
- background-color: $color-gray-50;
- padding: 64px;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- border-radius: 0 $br5 $br5 0;
- .subtitle {
- font-weight: $fw700;
- font-size: $fs20;
- color: $color-gray-10;
- text-transform: uppercase;
- margin-bottom: 8px;
- }
- .info {
- font-size: $fs14;
- color: $color-gray-20;
- margin-bottom: 32px;
- }
- .team-features {
- flex-grow: 1;
- display: flex;
- justify-content: space-between;
- flex-direction: column;
- margin-bottom: 0;
- .feature {
- display: flex;
- align-items: center;
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- background: #31efb8;
- min-width: 28px;
- width: 28px;
- height: 28px;
- border-radius: 50%;
-
- svg {
- height: 16px;
- width: 16px;
- fill: $color-black;
- }
- }
- .feature-txt {
- margin: 0;
- margin-left: 13px;
- color: $color-white;
- font-size: $fs14;
- display: flex;
- align-items: center;
- }
- }
- }
- }
- .team-left {
- width: 455px;
- height: 100%;
- padding: 64px;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- .title {
- font-size: $fs26;
- font-weight: $fw700;
- color: $color-gray-60;
- margin-bottom: 8px;
- }
- .info {
- font-size: $fs14;
- color: $color-black;
- }
- form {
- flex-grow: 1;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: flex-start;
- row-gap: 1.5rem;
- .custom-input {
- width: 100%;
- }
- .btn-disabled {
- color: $color-gray-40;
- opacity: 100%;
- }
- .invite-row {
- width: 100%;
- .role-wrapper {
- display: flex;
- justify-content: space-between;
- width: 100%;
- margin-bottom: 8px;
- .rol {
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: $fs12;
- color: $color-gray-60;
- }
- }
- .custom-input {
- height: 96px;
- }
- .custom-select {
- width: 180px;
- overflow: hidden;
- justify-content: normal;
- select {
- height: auto;
- }
- }
-
- svg {
- width: 12px;
- height: 12px;
- fill: $color-gray-20;
- }
- }
- .buttons {
- margin-top: 32px;
- width: 100%;
- display: grid;
- grid-template-columns: 1fr auto;
- gap: 8px;
- .btn-primary {
- max-width: 250px;
- }
- }
- }
- .skip-action {
- background-color: transparent;
- border: none;
- text-align: left;
- font-size: $fs12;
- color: $color-gray-30;
- }
- }
-
- .paginator {
- width: 32px;
- height: 24px;
- background-color: $color-gray-60;
- position: absolute;
- top: 16px;
- right: 16px;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: $fs12;
- }
- .deco {
- &.line2 {
- top: 422px;
- left: 798px;
- }
- &.square {
- top: -14px;
- left: 483px;
- }
- &.line1 {
- top: 357px;
- }
- }
-}
-
-.onboarding-team-members {
- .team-left {
- form {
- align-items: stretch;
- margin-top: 24px;
- row-gap: normal;
- .invite-row {
- .custom-input {
- width: 100%;
- min-height: 80px;
- height: fit-content;
- max-height: 176px;
- overflow-y: hidden;
- input {
- &.no-padding {
- padding-top: 12px;
- }
- min-height: 40px;
- }
- .selected-items {
- gap: 7px;
- padding: 7px;
- max-height: 132px;
- overflow-y: scroll;
- .selected-item {
- .around {
- height: 24px;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: fit-content;
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- }
- }
- }
- }
- .buttons {
- margin: 32px 0 16px 0;
- button {
- height: auto;
- }
- input {
- white-space: break-spaces;
- word-break: break-word;
- height: fit-content;
- margin: 0;
- padding: 5px 10px;
- min-height: 40px;
- max-height: 90px;
- }
- }
- }
- }
-}
-
-.questions-form {
- .modal-overlay {
- z-index: 2001;
- }
-
- .modal-container {
- display: flex;
- flex-direction: row;
- justify-content: center;
-
- .af-form {
- --primary-color: #00c38b;
- --input-background-color: #ffffff;
- --label-font-size: $fs16;
- --field-error-font-color: #e65244;
- --message-success-font-color: #49d793;
- --message-fail-font-color: #e65244;
- --invalid-field-border-color: #e65244;
- --dropdown-background-color: #ffffff;
- --primary-font-color: #000;
- --input-border-color: rgb(224, 230, 240);
- --input-border-radius: $br3;
- --button-border-radius: $br3;
- --message-border-radius: $br3;
- --checkbox-border-radius: $br3;
- --dropdown-option-background-color: rgba(0, 195, 139, 1);
- --dropdown-option-active-background-color: rgba(0, 138, 98, 1);
- --invalid-field-background-color: rgba(238.51780000000002, 205.7178, 204.11780000000002, 1);
- --message-fail-background-color: rgba(238.51780000000002, 205.7178, 204.11780000000002, 1);
- --message-success-background-color: rgba(171, 232, 197, 1);
- }
- }
-}
-
-// Nudge modal
-
-.nudge-modal-overlay {
- display: flex;
- align-items: center;
- justify-content: center;
- position: fixed;
- left: calc(50vw - 107px);
- top: calc(50vh - 57px);
- height: 110px;
- width: 215px;
- padding: 8px 20px;
- background-color: $color-white;
- box-shadow: 0px 2px 8px 0px rgb(0 0 0 / 20%);
- z-index: 1000;
-
- &.transparent {
- background-color: rgba($color-white, 0);
- }
-
- .nudge-modal-container {
- display: flex;
- flex-direction: column;
- justify-content: space-around;
- height: 100%;
- width: 100%;
-
- .nudge-modal-header {
- display: flex;
- justify-content: space-between;
- margin-bottom: 7px;
-
- .modal-close-button {
- display: flex;
- justify-content: center;
- align-items: center;
- background-color: transparent;
- border: none;
- cursor: pointer;
-
- svg {
- height: 12px;
- width: 12px;
- transform: rotate(45deg);
- }
- }
-
- .nudge-modal-title {
- padding: 0;
- margin: 0;
- color: $color-black;
- font-size: $fs12;
- }
- }
-
- .nudge-modal-body {
- display: flex;
- justify-content: space-between;
-
- .nudge-subtitle {
- margin: 0;
- }
-
- input {
- width: 72px;
- background-color: transparent;
- border: none;
- border-bottom: 1px solid $color-black;
- margin-bottom: 12px;
-
- &:active,
- &:focus,
- &:hover {
- border-bottom: 1px solid $color-primary;
- }
- }
- }
- }
-}
-
-.remove-graphics-dialog {
- .modal-content {
- padding-top: 16px;
- }
-
- h2 {
- font-size: $fs18;
- }
-
- p {
- font-size: $fs12;
- color: $color-gray-30;
-
- &:last-child {
- margin-bottom: 0;
- }
-
- &.progress-message {
- color: $color-info;
- }
-
- &.error-message {
- color: $color-black;
-
- & svg {
- width: 16px;
- height: 16px;
- fill: $color-danger;
- margin-right: 0.5rem;
- position: relative;
- bottom: -4px;
- transform: rotate(45deg);
- }
- }
- }
-
- .close {
- border: 1px solid $color-gray-30;
- background: $color-canvas;
- border-radius: $br3;
- padding: 0.5rem 1rem;
- cursor: pointer;
- margin-right: 8px;
-
- &:hover {
- background: $color-gray-20;
- }
- }
-
- .button-primary {
- background: $color-primary;
- border: 1px solid $color-primary;
- border-radius: $br3;
- color: $color-black;
- cursor: pointer;
- padding: 0.5rem 1rem;
-
- &:hover {
- background: $color-primary-dark;
- }
- }
-
- .button-secondary {
- border: 1px solid $color-gray-30;
- background: $color-white;
- border-radius: $br3;
- padding: 0.5rem 1rem;
- cursor: pointer;
- margin-right: 8px;
-
- &:hover {
- background: $color-gray-20;
- }
- }
-}
-
-//- LOGIN
-.login-register {
- background-color: $color-white;
- box-shadow: 0 10px 10px rgba(0, 0, 0, 0.2);
- display: flex;
- font-family: "worksans", sans-serif;
- width: 472px;
- height: 100%;
- max-height: 700px;
- position: relative;
- overflow: auto;
- position: relative;
-
- .title {
- margin-left: 32px;
- h2 {
- font-size: $fs24;
- color: $color-black;
- line-height: $lh-150; // Original value was 2.25rem = 36px; 36px/24px = 150% => $lh-150
- letter-spacing: 0px;
- margin: 0 30px 20px 0;
- }
-
- .modal-close-button {
- margin-top: 7px;
- margin-right: 12px;
- justify-content: right;
- svg {
- fill: $color-black;
- }
- }
- }
-
- .modal-bottom {
- margin: 0 32px;
- color: #1f1f1f;
- display: flex;
- flex-direction: column;
-
- &.auth-content {
- align-items: initial;
- height: auto;
- .links {
- margin: 7px 0 0 0;
- text-align: left;
- }
- }
- }
-
- .modal-footer {
- justify-content: center;
- align-items: center;
-
- .terms-login {
- position: relative;
- bottom: 0;
- span {
- margin: 0 $size-2;
- }
- }
- }
-
- .hint {
- color: #b1b2b5;
- }
-}
diff --git a/frontend/resources/styles/main/partials/share-link.scss b/frontend/resources/styles/main/partials/share-link.scss
deleted file mode 100644
index 8b1d0225f0..0000000000
--- a/frontend/resources/styles/main/partials/share-link.scss
+++ /dev/null
@@ -1,243 +0,0 @@
-.share-modal {
- background: none;
- display: block;
- top: 50px;
- left: calc(100vw - 500px);
-
- .share-link-dialog {
- width: 480px;
- background-color: $color-white;
- box-shadow: 0px 2px 8px 0px rgb(0 0 0 / 20%);
-
- .modal-content {
- padding: 16px 32px;
- &:first-child {
- border-top: 0px;
- padding: 0;
- height: 50px;
- display: flex;
- justify-content: center;
- }
-
- .title {
- display: flex;
- justify-content: space-between;
- align-items: center;
- height: 100%;
- margin-left: 32px;
- h2 {
- font-size: $fs18;
- color: $color-black;
- }
-
- .modal-close-button {
- margin-right: 16px;
- }
- }
-
- .share-link-section {
- .custom-input {
- display: flex;
- flex-direction: row;
- margin-bottom: 15px;
- border: 1px solid $color-gray-20;
- input {
- padding: 0 0 0 15px;
- border: none;
- }
- }
- .hint-wrapper {
- display: flex;
- justify-content: space-between;
- align-items: center;
- .hint {
- font-size: $fs12;
- color: $color-gray-40;
- }
- .confirm-dialog {
- display: flex;
- flex-direction: column;
- background-color: unset;
- .actions {
- display: flex;
- justify-content: flex-end;
- gap: 16px;
- }
- .description {
- font-size: $fs12;
- margin-bottom: 16px;
- color: $color-black;
- }
- .btn-primary,
- .btn-secondary,
- .btn-warning,
- .btn-danger {
- width: 126px;
- margin-bottom: 0px;
-
- &:not(:last-child) {
- margin-right: 10px;
- }
- }
- }
- }
-
- label {
- font-size: $fs12;
- color: $color-black;
- }
-
- .help-icon {
- height: 40px;
- width: 40px;
- display: flex;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- position: relative;
- right: 0;
- top: 0;
- background-color: $color-gray-10;
- border-left: 1px solid $color-gray-20;
- svg {
- fill: $color-gray-30;
- }
- &:hover {
- background-color: $color-primary;
- svg {
- fill: $color-gray-60;
- }
- }
- }
- input {
- margin: 0;
- }
- }
-
- &.ops-section {
- .manage-permissions {
- display: flex;
- color: $color-primary-dark;
- font-size: $fs12;
- cursor: pointer;
- .icon {
- svg {
- height: 16px;
- width: 16px;
- fill: $color-primary-dark;
- }
- }
- .title {
- margin-left: 8px;
- }
- }
- .view-mode {
- min-height: 34px;
- .subtitle {
- height: 32px;
- }
- .row {
- display: flex;
- justify-content: space-between;
- align-items: center;
- .count-pages {
- font-size: $fs12;
- color: $color-gray-30;
- }
- }
- .current-tag {
- font-size: $fs12;
- color: $color-gray-30;
- }
- label {
- color: $color-black;
- }
- }
- .access-mode,
- .inspect-mode {
- display: grid;
- grid-template-columns: auto 1fr;
- .items {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- }
- }
- .view-mode,
- .access-mode,
- .inspect-mode {
- margin: 8px 0;
- .subtitle {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- color: $color-black;
- font-size: $fs16;
- .icon {
- display: flex;
- justify-content: center;
- align-items: center;
- margin-right: 10px;
- svg {
- height: 16px;
- width: 16px;
- }
- }
- }
- .items {
- .input-select {
- background-image: url("/images/icons/arrow-down.svg");
- margin: 0;
- padding-right: 28px;
- border: 1px solid $color-gray-10;
- max-width: 227px;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- }
- > .input-radio {
- display: flex;
- user-select: none;
- margin-top: 0;
- margin-bottom: 0;
- label {
- display: flex;
- align-items: center;
- color: $color-black;
- max-width: 115px;
-
- &::before {
- height: 16px;
- width: 16px;
- }
- .hint {
- margin-left: 5px;
- color: $color-gray-30;
- }
- }
-
- &.disabled {
- label {
- color: $color-gray-30;
- }
- }
- }
- }
- }
-
- .pages-selection {
- border-top: 1px solid $color-gray-10;
- border-bottom: 1px solid $color-gray-10;
- padding-left: 20px;
- max-height: 200px;
- overflow-y: scroll;
- user-select: none;
-
- label {
- color: $color-black;
- }
- }
- }
- }
- }
-}
diff --git a/frontend/resources/styles/main/partials/sidebar-align-options.scss b/frontend/resources/styles/main/partials/sidebar-align-options.scss
deleted file mode 100644
index b792e060c2..0000000000
--- a/frontend/resources/styles/main/partials/sidebar-align-options.scss
+++ /dev/null
@@ -1,62 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.align-options {
- display: flex;
- border-bottom: solid 1px $color-gray-60;
- height: 40px;
-
- .align-group {
- padding: 0 $size-1;
- display: flex;
- justify-content: flex-start;
- width: 50%;
-
- &:not(:last-child) {
- border-right: solid 1px $color-gray-60;
- }
- }
-
- .align-button {
- align-items: center;
- cursor: pointer;
- display: flex;
- height: 30px;
- justify-content: center;
- margin: 5px 0;
- padding: $size-2 $size-1;
- width: 25%;
-
- svg {
- height: 16px;
- width: 16px;
- fill: $color-gray-20;
- }
-
- &:hover {
- background-color: $color-primary;
- svg {
- fill: $color-gray-50;
- }
- }
-
- &.disabled {
- background-color: transparent;
- cursor: default;
- svg {
- fill: $color-gray-40;
- }
- }
-
- &.selected svg {
- fill: $color-primary;
- }
-
- &.selected:hover svg {
- fill: $color-white;
- }
- }
-}
diff --git a/frontend/resources/styles/main/partials/sidebar-assets.scss b/frontend/resources/styles/main/partials/sidebar-assets.scss
deleted file mode 100644
index aa1750b8dd..0000000000
--- a/frontend/resources/styles/main/partials/sidebar-assets.scss
+++ /dev/null
@@ -1,538 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.assets-bar {
- display: flex;
- flex-direction: column;
- overflow: hidden;
- height: 100%;
-
- .assets-bar-title {
- color: $color-gray-10;
- font-size: $fs14;
- margin: $size-2 $size-2 0 $size-2;
- display: flex;
- align-items: center;
- cursor: pointer;
-
- & .libraries-button {
- margin-left: auto;
- display: flex;
- align-items: center;
-
- svg {
- fill: $color-gray-30;
- height: 16px;
- width: 16px;
- padding-right: 6px;
- }
- }
-
- & .libraries-button:hover {
- color: $color-primary;
-
- & svg {
- fill: $color-primary;
- }
- }
- }
-
- .search-block {
- border: 1px solid $color-gray-30;
- margin: $size-2 $size-2 0 $size-2;
- padding: $size-1 $size-2;
- display: flex;
- align-items: center;
-
- &:hover {
- border-color: $color-gray-20;
- }
-
- &:focus-within {
- border-color: $color-primary;
- }
-
- & .search-input {
- background-color: $color-gray-50;
- border: none;
- color: $color-gray-10;
- font-size: $fs12;
- margin: 0;
- padding: 0;
- flex-grow: 1;
-
- &:focus {
- color: lighten($color-gray-10, 8%);
- outline: none;
- }
- }
-
- & .search-icon {
- display: flex;
- align-items: center;
-
- svg {
- fill: $color-gray-30;
- height: 16px;
- width: 16px;
- }
-
- &.close {
- transform: rotate(45deg);
- cursor: pointer;
- }
- }
- }
-
- .input-select {
- background-color: $color-gray-50;
- color: $color-gray-10;
- border: 1px solid transparent;
- border-bottom-color: $color-gray-40;
- padding: $size-1;
- margin: $size-2 $size-2 $size-4 $size-2;
-
- &:focus {
- color: lighten($color-gray-10, 8%);
- }
-
- &:active {
- border-color: $color-primary;
- }
-
- option {
- background: $color-white;
- color: $color-gray-60;
- font-size: $fs12;
- }
- }
-
- .collapse-library {
- margin-right: $size-2;
- flex-shrink: inherit; // Inheriting shrink behaviour
-
- &.open svg {
- transform: rotate(90deg);
- }
- }
-
- .library-bar {
- cursor: pointer;
- }
-
- .listing-options {
- background-color: $color-gray-60;
- display: flex;
- align-items: center;
- padding: $size-4 $size-2 0 $size-2;
-
- .selected-count {
- color: $color-primary;
- font-size: $fs12;
- }
-
- .listing-option-btn {
- cursor: pointer;
- margin-left: $size-2;
-
- &.first {
- margin-left: auto;
- }
-
- svg {
- fill: $color-gray-20;
- height: 16px;
- width: 16px;
- }
- }
- }
-
- .asset-section {
- background-color: $color-gray-60;
- padding: $size-2;
- font-size: $fs12;
- color: $color-gray-20;
- /* TODO: see if this is useful, or is better to leave only
- one scroll bar in the whole sidebar
- (also see .asset-list) */
- // max-height: 30rem;
- // overflow-y: scroll;
-
- // First child is the listing options buttons
- &:not(:nth-child(2)) {
- border-top: 1px solid $color-gray-50;
- }
-
- .asset-title {
- display: flex;
- cursor: pointer;
- font-size: $fs12;
- text-transform: uppercase;
-
- & .num-assets {
- color: $color-gray-30;
- }
-
- & svg {
- height: 8px;
- width: 8px;
- fill: $color-gray-30;
- margin-right: 4px;
- transform: rotate(90deg);
- }
-
- &.closed svg {
- transform: rotate(0deg);
- transition: transform 0.3s;
- }
- }
-
- .group-title {
- display: flex;
- cursor: pointer;
- margin-top: $size-2;
- margin-bottom: $size-1;
- color: $color-white;
-
- & svg {
- height: 8px;
- width: 8px;
- fill: $color-white;
- margin-right: 4px;
- transform: rotate(90deg);
- }
-
- &.closed svg {
- transform: rotate(0deg);
- transition: transform 0.3s;
- }
-
- & .dim {
- color: $color-gray-40;
- }
- }
-
- .assets-button {
- margin-left: auto;
- cursor: pointer;
-
- & svg {
- width: 0.7rem;
- height: 0.7rem;
- fill: #f0f0f0;
- }
-
- &:hover svg {
- fill: $color-primary;
- }
- }
-
- .asset-title + .asset-grid {
- margin-top: $size-2;
- }
-
- .asset-grid {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- grid-auto-rows: 6vh;
- column-gap: 0.5rem;
- row-gap: 0.5rem;
-
- &.big {
- grid-template-columns: repeat(2, 1fr);
- grid-auto-rows: 10vh;
-
- .three-row & {
- grid-template-columns: repeat(3, 1fr);
- }
-
- .four-row & {
- grid-template-columns: repeat(4, 1fr);
- }
-
- .grid-cell {
- padding: $size-1;
-
- & svg {
- height: 10vh;
- }
- }
- }
- }
-
- .grid-cell {
- background-color: $color-canvas;
- border-radius: $br4;
- border: 2px solid transparent;
- overflow: hidden;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: $size-2;
- position: relative;
- cursor: pointer;
-
- & img {
- max-height: 100%;
- max-width: 100%;
- height: auto;
- width: auto;
- pointer-events: none;
- }
- }
-
- .cell-name {
- background-color: $color-gray-60;
- font-size: $fs9;
- display: none;
- position: absolute;
- left: 0;
- bottom: 0;
- width: 100%;
- padding: 3px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-
- &.editing {
- display: block;
- }
-
- .editable-label-input {
- border: 1px solid $color-gray-20;
- border-radius: $br3;
- font-size: $fs12;
- padding: 2px;
- margin: 0;
- height: unset;
- width: 100%;
- }
-
- .editable-label-close {
- display: none;
- }
- }
-
- .grid-cell:hover {
- border: 2px solid $color-primary;
-
- & .cell-name {
- display: block;
- }
- }
-
- .grid-cell.selected {
- border: 2px solid $color-primary;
- }
-
- .grid-placeholder {
- border: 2px solid $color-gray-20;
- border-radius: $br4;
- }
-
- .drop-space {
- height: 10px;
- }
-
- .typography-container {
- position: relative;
-
- &:last-child {
- padding-bottom: 0.5em;
- }
- }
-
- .drag-counter {
- position: absolute;
- top: 5px;
- left: 4px;
- width: 16px;
- height: 16px;
- background-color: $color-primary;
- border-radius: 50%;
- color: $color-black;
- font-size: $fs12;
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .asset-title + .asset-enum {
- margin-top: $size-2;
- }
-
- .asset-enum {
- .enum-item {
- position: relative;
- display: flex;
- align-items: center;
- margin-bottom: $size-2;
- cursor: pointer;
-
- & > svg,
- & > img {
- background-color: $color-canvas;
- border-radius: $br4;
- border: 2px solid transparent;
- height: 24px;
- width: 24px;
- margin-right: $size-2;
- }
-
- .item-name {
- width: calc(100% - 24px - #{$size-2});
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- display: block;
-
- &.editing {
- display: flex;
- align-items: center;
-
- .editable-label-input {
- height: 24px;
- }
-
- .editable-label-close {
- display: none;
- }
- }
- }
- }
-
- .enum-item:hover,
- .enum-item.selected {
- color: $color-primary;
- }
-
- .grid-placeholder {
- margin-bottom: 5px;
- }
- }
-
- /* TODO: see if this is useful, or is better to leave only
- one scroll bar in the whole sidebar
- (also see .asset-section) */
- // .asset-list {
- // max-height: 30rem;
- // overflow-y: scroll;
- // }
-
- .asset-list-item {
- display: flex;
- align-items: center;
- border: 1px solid transparent;
- border-radius: $br3;
- margin-top: $size-1;
- padding: 2px;
- font-size: $fs12;
- color: $color-white;
- cursor: pointer;
- position: relative;
-
- .name-block {
- color: $color-gray-20;
- width: calc(100% - 24px - #{$size-2});
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- & span {
- margin-left: $size-1;
- color: $color-gray-30;
- text-transform: uppercase;
- }
-
- &.selected {
- border: 1px solid $color-primary;
- }
- }
-
- .context-menu {
- position: fixed;
- top: 10px;
- left: 10px;
- }
-
- .advanced-options {
- border-color: $color-black;
- background-color: $color-gray-60;
-
- .input-text,
- .input-select,
- .adv-typography-name {
- background-color: $color-gray-60;
- }
- }
-
- .dragging {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: color.adjust($color-primary, $alpha: -0.5);
- }
- }
-}
-
-.modal-create-color {
- position: relative;
- background-color: $color-white;
- padding: 4rem;
- display: flex;
- flex-direction: column;
- align-items: center;
-
- & .sketch-picker,
- .chrome-picker {
- box-shadow: none !important;
- border: 1px solid $color-gray-10 !important;
- border-radius: $br0 !important;
-
- & input {
- background-color: $color-white;
- }
- }
-
- & .close {
- position: absolute;
- right: 1rem;
- transform: rotate(45deg);
- top: 1rem;
-
- svg {
- fill: $color-black;
- height: 20px;
- width: 20px;
-
- &:hover {
- fill: $color-danger;
- }
- }
- }
-
- & .btn-primary {
- width: 10rem;
- padding: 0.5rem;
- margin-top: 1rem;
- }
-}
-
-.modal-create-color-title {
- color: $color-black;
- font-size: $fs24;
- font-weight: $fw400;
-}
-
-.libraries-wrapper {
- overflow: auto;
- display: flex;
- flex-direction: column;
- flex: 1;
-}
diff --git a/frontend/resources/styles/main/partials/sidebar-document-history.scss b/frontend/resources/styles/main/partials/sidebar-document-history.scss
deleted file mode 100644
index a8e00d41cc..0000000000
--- a/frontend/resources/styles/main/partials/sidebar-document-history.scss
+++ /dev/null
@@ -1,139 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.history-debug-overlay {
- background: $color-gray-50;
- bottom: 0;
- max-height: 500px;
- overflow-y: auto;
- position: absolute;
- width: 500px;
- z-index: 1000;
-}
-
-.history-toolbox {
- display: flex;
- flex-direction: column;
-}
-
-.history-toolbox-title {
- color: $color-gray-10;
- font-size: $fs14;
- padding: 0.5rem;
-}
-
-.history-entry-empty {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 1rem;
-
- .history-entry-empty-icon {
- margin-bottom: 1rem;
- svg {
- width: 32px;
- height: 32px;
- fill: $color-gray-40;
- }
- }
-
- .history-entry-empty-msg {
- color: $color-gray-30;
- font-size: $fs12;
- }
-}
-
-.history-entries {
- font-size: $fs12;
- color: $color-gray-20;
- fill: $color-gray-20;
- height: 100%;
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-.history-entry {
- border: 1px solid $color-gray-60;
- border-radius: $br4;
- margin: 0.5rem;
- display: flex;
- flex-direction: column;
- padding: 0.5rem;
- cursor: pointer;
-
- transition: border 0.2s;
-
- &.disabled {
- opacity: 0.5;
- }
-
- &.current {
- background-color: $color-gray-60;
- }
-
- &.hover {
- border-color: $color-primary;
- }
-}
-
-.history-entry-summary {
- display: flex;
- flex-direction: row;
- align-items: center;
-
- * {
- display: flex;
- }
-}
-
-.history-entry-summary-icon {
- svg {
- width: 16px;
- height: 16px;
- }
-}
-
-.history-entry-summary-text {
- flex: 1;
- margin: 0 0.5rem;
- margin-top: 2px;
-}
-
-.history-entry-summary-button {
- opacity: 0;
- transition: transform 0.2s;
-
- svg {
- width: 12px;
- height: 12px;
- }
-
- .show-detail &,
- .hover & {
- opacity: 1;
- }
-
- .show-detail & {
- transform: rotate(90deg);
- }
-}
-
-.history-entry-detail {
- display: none;
-
- .show-detail & {
- display: block;
- padding: 1rem 0 0.5rem 0;
- }
-
- .history-entry-details-list {
- margin: 0;
-
- li {
- margin-bottom: 0.5rem;
- }
- }
-}
diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss
deleted file mode 100644
index 5dab0ad90b..0000000000
--- a/frontend/resources/styles/main/partials/sidebar-element-options.scss
+++ /dev/null
@@ -1,2593 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.element-options {
- display: flex;
- flex-direction: column;
- width: 100%;
- height: 100%;
-
- .element-icons {
- background-color: $color-gray-60;
- border: 1px solid $color-gray-60;
- border-radius: $br3;
- display: flex;
- margin: $size-1;
-
- li {
- align-items: center;
- border-right: 1px solid $color-gray-60;
- border-radius: $br3;
- cursor: pointer;
- display: flex;
- flex: 1;
- justify-content: center;
- padding: $size-2;
-
- svg {
- fill: $color-gray-20;
- height: 15px;
- width: 15px;
- }
-
- &:hover {
- svg {
- fill: $color-primary;
- }
- }
-
- &.selected {
- background-color: $color-primary;
-
- svg {
- fill: $color-white;
- }
- }
-
- &:last-child {
- border: none;
- }
- }
- }
-
- &.inspect {
- & > :first-child {
- margin-top: 7px;
- }
- }
-
- .element-set {
- border-bottom: 1px solid $color-gray-60;
- color: $color-gray-20;
- padding: $size-2 $size-1;
-
- .element-set-title {
- height: 35px;
- color: $color-gray-20;
- display: flex;
- font-size: $fs14;
- padding: $size-1;
- width: 100%;
- align-items: center;
- justify-content: space-between;
- }
- }
-
- .element-list {
- margin-bottom: $size-2;
-
- li {
- align-items: center;
- border-bottom: 1px solid $color-gray-60;
- display: flex;
- flex-direction: row;
- padding: $size-2;
- width: 100%;
-
- .list-icon {
- svg {
- fill: $color-gray-30;
- height: 15px;
- margin-right: $size-1;
- width: 15px;
- }
- }
-
- span {
- color: $color-gray-20;
- font-size: $fs12;
- max-width: 75%;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .list-actions {
- align-items: center;
- cursor: pointer;
- display: none;
- margin-left: auto;
-
- a {
- svg {
- fill: $color-gray-60;
- height: 15px;
- margin-left: $size-1;
- width: 15px;
-
- &:hover {
- fill: $color-gray-20;
- }
- }
- }
- }
-
- &:hover {
- .list-icon {
- svg {
- fill: $color-primary;
- }
- }
-
- span {
- color: $color-primary;
- }
- }
-
- &.selected {
- .list-icon {
- svg {
- fill: $color-primary;
- }
- }
-
- span {
- color: $color-primary;
- font-weight: $fw700;
- }
- }
- }
-
- &:hover {
- .list-actions {
- display: flex;
- @include animation(0s, 0.3s, fadeIn);
- }
- }
- }
-}
-
-.element-set-content {
- display: flex;
- flex-direction: column;
- padding: $size-1;
- width: 100%;
-
- .input-text {
- background-color: $color-gray-50;
- border: 1px solid transparent;
- border-bottom-color: $color-gray-40;
- color: $color-white;
- font-size: $fs12;
- margin: $size-1;
- min-width: 0;
- padding: $size-1;
- width: 100%;
-
- &:focus {
- color: lighten($color-gray-10, 8%);
- border-color: $color-primary !important;
- }
-
- &:hover {
- border-color: $color-gray-40;
- }
-
- &.error {
- border-color: $color-danger;
- }
-
- &[disabled] {
- color: $color-gray-30;
- }
- }
-
- .input-select {
- /* This padding is so the text won't overlap the arrow*/
- padding-right: 1rem;
- overflow: hidden;
- text-overflow: ellipsis;
- color: $color-gray-10;
-
- &:focus {
- color: lighten($color-gray-10, 8%);
- border-color: $color-primary;
- }
-
- option {
- color: $color-gray-60;
- background: $color-white;
- font-size: $fs12;
-
- &:disabled {
- color: $color-gray-20;
- }
- }
- }
-
- .input-checkbox {
- label {
- color: $color-gray-20;
- }
-
- label::before {
- background-color: transparent;
- width: 16px;
- height: 16px;
- }
-
- label::after {
- width: 16px;
- height: 16px;
- }
-
- input:checked + label::before {
- border-width: 1px;
- }
-
- input:checked + label::after {
- font-size: $fs13;
- }
- }
-
- .element-set-subtitle {
- color: $color-gray-20;
- font-size: $fs12;
- width: 64px;
-
- &.wide {
- min-width: 75px;
- }
- }
-
- .lock-size {
- cursor: pointer;
- margin: auto;
-
- svg {
- fill: $color-gray-20;
- height: 14px;
- width: 14px;
-
- &:hover {
- fill: $color-primary;
- }
- }
-
- &.selected {
- svg {
- fill: $color-primary;
- }
- }
-
- &.disabled {
- cursor: unset;
- svg {
- fill: $color-gray-40;
- }
- }
- }
-
- .save-btn {
- width: 100%;
- }
-
- .cancel-btn {
- color: $color-danger;
- text-align: center;
- width: 100%;
- }
-
- .custom-select {
- border: 1px solid $color-gray-40;
- border-radius: $br3;
- cursor: pointer;
- padding: $size-1 $size-5 $size-1 $size-1;
- position: relative;
-
- .dropdown-button {
- position: absolute;
- right: $size-1;
- top: 7px;
-
- svg {
- fill: $color-gray-40;
- height: 10px;
- width: 10px;
- }
- }
-
- span {
- font-size: $fs12;
- }
-
- &:hover {
- border: 1px solid $color-gray-20;
- }
-
- &.no-check {
- .custom-select-dropdown {
- width: 100%;
- min-width: unset;
- .check-icon {
- display: none;
- }
- li.checked-element {
- padding-left: 0.5rem;
- &.is-selected {
- background-color: $color-primary;
- }
- }
- }
- }
- }
- .opened {
- border: 1px solid $color-primary;
- &:hover,
- &:focus {
- outline: none;
- border: 1px solid $color-primary;
- }
- }
-
- .custom-select-dropdown {
- background-color: $color-white;
- border-radius: $br3;
- box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
- left: 0;
- max-height: 30rem;
- min-width: 7rem;
- position: absolute;
- overflow-y: auto;
- top: 30px;
- z-index: 12;
-
- .presets {
- width: 200px;
- }
-
- hr {
- margin: 0;
- border-color: $color-gray-20;
- }
-
- li {
- color: $color-gray-60;
- cursor: pointer;
- font-size: $fs14;
- display: flex;
- gap: 0 10px;
- justify-content: flex-start;
- padding: $size-2;
-
- span {
- color: $color-gray-20;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- }
-
- .check-icon {
- min-width: 25px;
- color: $color-gray-20;
- justify-content: center;
- }
-
- &.dropdown-separator:not(:last-child) {
- border-bottom: 1px solid $color-gray-10;
- }
-
- &.dropdown-label:not(:first-child) {
- border-top: 1px solid $color-gray-10;
- }
-
- &.dropdown-label span {
- margin-left: 0;
- }
-
- &:hover {
- background-color: $color-primary-lighter;
- }
- }
- }
-
- & li.checked-element {
- padding-left: 0;
-
- & span {
- color: $color-black;
- }
-
- & svg {
- visibility: hidden;
- width: 8px;
- height: 8px;
- background: none;
- margin: 0.25rem;
- fill: $color-black;
- }
-
- &.is-selected {
- & svg {
- visibility: visible;
- }
- }
- }
-
- .editable-select {
- border: 1px solid transparent;
- position: relative;
- height: 38px;
- // margin-left: $size-2;
- max-height: 30px;
- position: relative;
- width: 60%;
-
- svg {
- fill: $color-gray-10;
- height: 10px;
- width: 10px;
- }
-
- .input-text {
- left: 0;
- position: absolute;
- top: -1px;
- width: 60%;
- }
-
- input.input-text {
- border: none;
- background: none;
- }
-
- .input-select {
- background-color: transparent;
- border: none;
- border-bottom: 1px solid $color-gray-40;
- color: transparent;
- left: 0;
- position: absolute;
- top: 0;
- width: 100%;
-
- option {
- color: $color-gray-60;
- background: $color-white;
- font-size: $fs12;
-
- &:disabled {
- color: $color-gray-20;
- }
- }
- }
-
- .dropdown-button {
- position: absolute;
- right: 0;
- padding-right: 4px;
- height: 100%;
- display: flex;
- align-items: center;
- }
-
- &.input-option {
- height: 26px;
- border-bottom: 1px solid #64666a;
- width: 100%;
- margin-left: 0.25rem;
-
- .input-text {
- border: none;
- margin: 0;
- width: calc(100% - 12px);
- height: 100%;
- top: auto;
- color: $color-white;
- }
- }
-
- .custom-select-dropdown {
- top: unset;
- margin-bottom: 0;
- }
-
- &:hover {
- border: 1px solid $color-gray-40;
- }
- }
-}
-
-.element-set-content .border-data {
- &[draggable="true"] {
- cursor: pointer;
- }
-}
-
-.element-set-content .grid-option-main {
- .editable-select {
- height: 2rem;
- }
- .editable-select svg {
- fill: $color-gray-40;
- }
- .editable-select.input-option .input-text {
- padding: 0;
- padding-top: 0.18rem;
- padding-left: 0.25rem;
- }
-
- .input-element {
- width: 55px;
- margin: 0 0.2rem;
- }
-
- .input-text {
- padding-left: 0;
- color: $color-white;
- background-color: transparent;
- height: 30px;
- }
-}
-
-.element-set-content .component-row {
- display: flex;
- align-items: center;
- font-size: $fs12;
- color: $color-gray-10;
-
- svg {
- fill: $color-gray-20;
- height: 16px;
- width: 16px;
- margin-right: $size-2;
- }
-
- .component-name {
- overflow: hidden;
- text-overflow: ellipsis;
- width: 100%;
- }
-
- .row-actions {
- margin-left: auto;
- cursor: pointer;
-
- svg {
- fill: $color-gray-20;
- height: 12px;
- margin-right: $size-1;
- width: 12px;
- }
-
- .context-menu-items {
- right: 0.5rem;
- left: unset;
- top: 0;
-
- .context-menu-action {
- overflow-wrap: break-word;
- min-width: 223px;
- white-space: break-spaces;
- }
- }
- }
-
- &.copy {
- flex-wrap: wrap;
- border-radius: 8px;
- border: 1px solid $color-gray-60;
- padding: 0.5rem;
- cursor: pointer;
-
- .component-name {
- width: 80%;
- color: $color-white;
- }
- .component-parent-name {
- overflow: hidden;
- text-overflow: ellipsis;
- width: 100%;
- padding-left: calc(0.5rem + 16px);
- color: $color-gray-40;
- }
- }
-}
-
-.grid-option .custom-select {
- margin-bottom: 0;
-}
-
-.presets {
- &:focus,
- &:focus-within {
- outline: none;
- border: 1px solid $color-primary;
- }
- .custom-select-dropdown {
- width: 237px;
-
- li {
- font-size: $fs12;
-
- span {
- font-size: $fs12;
- }
- }
- }
-}
-
-.row-flex.align-icons {
- margin-left: 0;
-}
-
-.align-icons {
- cursor: pointer;
- display: flex;
- flex: 1;
- justify-content: flex-end;
- margin: $size-2 0 $size-2 $size-2;
- padding: 0 $size-1;
-
- &:first-child {
- justify-content: flex-start;
- margin-left: 0;
- }
-
- span {
- align-items: center;
- display: flex;
- height: 20px;
- justify-content: center;
- margin-right: $size-2;
- position: relative;
- width: 20px;
-
- svg {
- fill: $color-gray-30;
- height: 14px;
- width: 14px;
- }
-
- &:hover,
- &.current {
- svg {
- fill: $color-primary;
- }
- }
-
- &:last-child {
- margin-right: 0;
- }
- }
-}
-
-.element-color-picker {
- align-items: center;
- display: flex;
- height: 100%;
- justify-content: center;
- margin: 0 4px;
-
- .color-picker-body {
- height: 100%;
- margin-right: 15px;
- }
-
- .color-picker-bar {
- height: 165px;
- position: relative;
- width: 15px;
-
- .color-bar-select {
- background-color: $color-gray-50;
- height: 3px;
- left: -4px;
- position: absolute;
- width: 23px;
- transition: none;
- top: 30%;
- }
- }
-}
-
-.radius-options,
-.padding-options,
-.margin-options {
- align-items: center;
- border: 1px solid $color-gray-60;
- border-radius: $br4;
- display: flex;
- justify-content: space-between;
- padding: 8px;
- width: 64px;
-
- .radius-icon,
- .padding-icon,
- .margin-icon {
- display: flex;
- align-items: center;
-
- svg {
- cursor: pointer;
- height: 16px;
- fill: $color-gray-30;
- width: 16px;
- }
-
- &:hover,
- &.selected {
- svg {
- fill: $color-primary;
- }
- }
- }
-}
-
-.orientation-icon {
- margin-left: $size-2;
- display: flex;
- align-items: center;
-
- svg {
- cursor: pointer;
- height: 20px;
- fill: $color-gray-40;
- width: 20px;
- }
-
- &:hover {
- svg {
- fill: $color-gray-10;
- }
- }
-}
-
-.navigate-icon {
- background-color: $color-gray-60;
- cursor: pointer;
- margin-left: $size-2;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 32px;
- height: 32px;
-
- svg {
- height: 16px;
- fill: $color-gray-30;
- width: 16px;
- }
-
- &:hover {
- svg {
- stroke: $color-gray-10;
- }
- }
-}
-
-.input-icon {
- align-items: center;
- display: flex;
- width: 100%;
-
- &:first-child {
- margin-right: $size-2;
- }
-
- .icon-before {
- align-items: center;
- display: flex;
- height: 18px;
- position: relative;
- width: 14px;
-
- svg {
- fill: $color-gray-30;
- height: 14px;
- width: 14px;
- }
- }
-}
-
-.custom-button {
- cursor: pointer;
- background: none;
- border: none;
-
- & svg {
- width: 12px;
- height: 12px;
- fill: $color-gray-20;
- }
-
- &:hover svg,
- &.is-active svg {
- fill: $color-primary;
- }
-}
-
-.element-set-content .input-row {
- & .element-set-subtitle {
- width: 5.5rem;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-}
-
-.grid-option,
-.shadow-option {
- margin-bottom: 0.5rem;
- .advanced-options {
- .row-flex {
- justify-content: flex-end;
- }
- .custom-button {
- left: 0;
- position: absolute;
- top: 12px;
- }
- .element-set-actions-button {
- min-width: auto;
- min-height: auto;
- padding-right: 10px;
- svg {
- width: 12px;
- height: 12px;
- }
- }
- }
-}
-
-.element-set-content .custom-select.input-option {
- border-top: none;
- border-left: none;
- border-right: none;
- margin-left: 0.25rem;
-}
-
-.element-set-content .grid-option-main,
-.element-set-content .shadow-option-main {
- align-items: center;
- display: flex;
- padding: 0.3rem 0;
- border: 1px solid $color-black;
- border-radius: $br4;
- height: 48px;
-
- &:hover {
- background: $color-gray-60;
-
- .custom-select,
- .editable-select,
- input {
- background-color: $color-gray-50;
- }
- }
-
- & .custom-select {
- min-width: 4.75rem;
- height: 2rem;
- border-color: transparent;
- border-bottom: 1px solid #65666a;
- max-height: 30px;
-
- &:hover {
- border: 1px solid $color-gray-40;
- }
- }
-
- & .input-element {
- width: 50px;
- overflow: hidden;
- }
-
- & .custom-select-dropdown {
- width: 96px;
- }
-
- & .input-option {
- margin-left: 0.5rem;
-
- & .custom-select-dropdown {
- width: 5rem;
- min-width: 5rem;
- max-height: 10rem;
- }
- }
-}
-
-.grid-option-main-actions,
-.shadow-option-main-actions {
- display: flex;
- visibility: hidden;
-
- .grid-option:hover &,
- .shadow-option:hover & {
- visibility: visible;
- }
-}
-
-.focus-overlay {
- background: $color-black;
- height: 100%;
- left: 0;
- position: absolute;
- top: 0;
- width: calc(100%);
- opacity: 0.4;
- z-index: 10;
- display: flex;
-}
-
-.advanced-options-wrapper {
- width: 100%;
-}
-
-.advanced-options {
- border: 1px solid $color-gray-60;
- background-color: $color-gray-50;
- border-radius: $br4;
- padding: 8px;
- position: relative;
- top: 2px;
- width: 100%;
-}
-
-.btn-options {
- cursor: pointer;
- border: 1px solid $color-black;
- background: $color-gray-60;
- border-radius: $br2;
- color: $color-gray-20;
- font-size: $fs11;
- line-height: $lh-145; // Original value was 16px; 16px/11px = 145.454545455% => $lh-145
- flex-grow: 1;
- padding: 0.25rem 0;
-
- &:first-child {
- margin-right: 0.5rem;
- }
-
- &:not([disabled]):hover {
- background: $color-primary;
- color: $color-black;
- }
-
- &[disabled] {
- opacity: 0.4;
- cursor: auto;
- }
-}
-
-.element-set-options-group {
- display: flex;
- justify-content: space-between;
- padding: 3px;
- border: 1px solid $color-black;
- border-radius: $br4;
-
- &:hover {
- background: #1f1f1f;
- }
-
- &.selected {
- border: 1px solid $color-primary;
- }
-
- &:not(:first-child) {
- margin-top: 7px;
- }
-
- &.open {
- &:hover {
- background: unset;
- }
- }
-}
-
-.interactions-options {
- &.element-set {
- border-bottom: 0;
- }
-
- .element-set-options-group {
- flex-wrap: wrap;
- }
-
- &:not(:first-child) {
- border-top: 1px solid $color-gray-60;
- }
-}
-
-.exports-options,
-.shadow-options {
- .element-set-options-group {
- .delete-icon {
- display: flex;
- min-width: 40px;
- min-height: 40px;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- svg {
- width: 12px;
- height: 12px;
- fill: $color-gray-20;
- }
- }
- }
-
- .download-button {
- margin-top: 10px;
- }
-
- .input-element {
- width: 100%;
- flex-shrink: initial;
- }
-
- .row-grid-2 {
- grid-column-gap: 1em;
- }
-
- .color-info {
- input {
- margin-right: 1em;
- width: 74px;
- &:focus {
- border-color: $color-primary !important;
- color: $color-white;
- outline: none;
- }
-
- &:hover {
- border-color: $color-gray-20;
- }
- }
- }
-}
-
-.shadow-options .color-row-wrap {
- margin-left: 6px;
- margin-top: 0.5rem;
-}
-
-.element-set-actions-button {
- display: flex;
- min-width: 30px;
- min-height: 30px;
- justify-content: center;
- align-items: center;
- cursor: pointer;
-
- svg {
- width: 12px;
- height: 12px;
- fill: $color-gray-20;
- stroke: $color-gray-20;
- }
-
- &.remove {
- min-width: 20px;
- min-height: 20px;
- }
-
- &:hover svg,
- &.active svg {
- fill: $color-primary;
- stroke: $color-primary;
- }
-
- &.actions-inside {
- position: absolute;
- right: 0;
- }
-}
-
-.element-set-label {
- font-size: $fs12;
- padding: 0.5rem;
- color: $color-gray-10;
-}
-
-.element-set-actions {
- display: flex;
- visibility: hidden;
-}
-
-.row-flex-removable:hover .element-set-actions,
-.element-set-options-group:hover .element-set-actions {
- visibility: visible;
-}
-
-.layer-actions {
- visibility: visible;
-}
-
-.typography-entry {
- margin: 0.5rem 0.3rem;
- display: flex;
- flex-direction: row;
- align-items: center;
-
- .typography-selection-wrapper {
- display: flex;
- flex-direction: row;
- align-items: center;
- flex: 1;
- height: 100%;
-
- &.is-selectable {
- cursor: pointer;
- }
- }
-
- .typography-sample {
- font-size: $fs17;
- color: $color-white;
- margin: 0 0.5rem;
-
- font-family: sourcesanspro;
- font-style: normal;
- font-weight: $fw400;
- }
-
- .typography-name {
- flex-grow: 1;
- font-size: $fs11;
- margin-top: 4px;
- max-width: calc(var(--width, 256px) - 100px);
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- .element-set-actions-button svg {
- width: 10px;
- height: 10px;
- }
-}
-
-.spacing-options {
- display: flex;
- width: 100%;
-}
-
-.asset-section {
- .typography-entry {
- margin: 0.25rem 0;
- }
-
- .element-set-content .font-option,
- .element-set-content .size-option {
- margin: 0.5rem 0;
- }
- .element-set-content .variant-option {
- margin-left: 0.5rem;
- }
-}
-
-.row-flex input.adv-typography-name {
- font-size: $fs14;
- color: $color-gray-10;
- width: 100%;
- max-width: none;
- margin: 0;
- background-color: #303236;
- border-top: none;
- border-left: none;
- border-right: none;
-}
-
-.size-option .custom-select-dropdown {
- cursor: pointer;
- max-height: 16rem;
- min-width: 6rem;
- left: initial;
- top: 0;
-}
-
-.typography-read-only-data {
- font-size: $fs12;
- color: $color-white;
-
- .typography-name {
- font-size: $fs14;
- }
-
- .row-flex {
- padding: 0.5rem 0;
- }
-
- .label {
- color: $color-gray-30;
-
- &::after {
- content: ":";
- margin-right: 0.25rem;
- }
- }
-
- .go-to-lib-button {
- color: $color-white;
- transition:
- border 0.3s,
- color 0.3s;
- text-align: center;
- background: $color-gray-50;
- padding: 0.5rem;
- border-radius: $br2;
- cursor: pointer;
- font-size: $fs14;
- margin-top: 1rem;
-
- &:hover {
- background: $color-primary;
- color: $color-black;
- }
- }
-}
-
-.multiple-typography {
- margin: 0.5rem;
- padding: 0.5rem;
- border: 1px dashed $color-gray-30;
- border-radius: $br4;
- display: flex;
- justify-content: space-between;
-
- .multiple-typography-text,
- .multiple-typography-button {
- font-size: $fs12;
- display: flex;
- align-items: center;
- }
-
- .multiple-typography-button {
- cursor: pointer;
- svg {
- transition: fill 0.3s;
- width: 16px;
- height: 16px;
- fill: $color-gray-10;
- }
-
- &:hover svg {
- fill: $color-primary;
- }
- }
-}
-
-.font-selector {
- background: $color-black;
- height: 100%;
- left: 0;
- position: absolute;
- top: 0;
- width: calc(100%);
- z-index: 10;
- display: flex;
- justify-content: center;
- align-items: center;
-
- .font-selector-dropdown {
- background: #303236;
- display: flex;
- flex-direction: column;
- flex-grow: 1;
- height: 100%;
- }
-
- header {
- display: flex;
- flex-direction: column;
- position: relative;
-
- .backend-filters {
- padding: $size-2 $size-4;
- // width: 220px;
- top: 40px;
- right: 20px;
- }
- .backend-filter {
- display: flex;
- align-items: center;
- padding: $size-2 0;
- cursor: pointer;
-
- .checkbox-icon {
- display: flex;
- justify-content: center;
- align-items: center;
- width: $size-4;
- height: $size-4;
- border: 1px solid $color-gray-30;
- border-radius: $br3;
-
- svg {
- width: 8px;
- display: none;
- height: 8px;
- fill: $color-black;
- }
- }
-
- .backend-name {
- margin-left: $size-2;
- color: $color-gray-50;
- }
-
- &.selected {
- .checkbox-icon {
- svg {
- display: inherit;
- }
- }
- }
- }
-
- input {
- display: flex;
- flex-grow: 1;
- padding: 4px;
- font-size: $fs12;
- background: $color-gray-50;
- border-radius: $br3;
- color: $color-gray-20;
- border: 1px solid $color-gray-30;
- width: 88%;
- margin: 15px 17px;
- }
-
- .title {
- font-size: $fs14;
- margin: 9px 17px;
- }
-
- .options {
- display: flex;
- justify-content: center;
- align-items: center;
- width: 24px;
- height: 24px;
- margin-left: $size-2;
-
- svg {
- width: 16px;
- height: 16px;
- fill: $color-gray-20;
- }
-
- &.active {
- svg {
- fill: $color-primary;
- }
- }
- }
- }
-
- .fonts-list {
- display: flex;
- flex-direction: column;
- height: 100%;
-
- position: relative;
- -webkit-box-flex: 1;
- flex: 1 1 auto;
- }
-
- hr {
- margin-bottom: 0px;
- margin-top: 0px;
- }
-
- .font-item {
- padding-left: $size-5;
- height: $size-6;
- max-height: $size-6;
- width: 100%;
- display: flex;
- align-items: center;
- cursor: pointer;
- color: $color-gray-10;
-
- &.selected {
- background-color: $color-black;
- color: $color-primary;
-
- .icon svg {
- fill: $color-primary;
- }
- }
-
- &:hover {
- background-color: $color-primary;
- color: $color-black;
- }
-
- .icon {
- display: flex;
- // justify-content: center;
- align-items: center;
- // border: 1px solid red;
- width: $size-5;
- }
-
- .label {
- font-size: $fs12;
- }
-
- svg {
- fill: $color-gray-10;
- width: 10px;
- height: 10px;
- }
- }
-}
-
-.row-flex.align-top {
- align-items: flex-start;
-}
-
-.constraints-widget {
- min-width: 72px;
- min-height: 72px;
- position: relative;
- background-color: $color-gray-60;
- flex-grow: 0;
-
- .constraints-box {
- width: 28px;
- height: 28px;
- position: absolute;
- top: 22px;
- left: 22px;
- border: 2px solid $color-gray-50;
- }
-
- .constraint-button {
- position: absolute;
- cursor: pointer;
- display: flex;
- justify-content: center;
- align-items: center;
-
- &::after {
- content: " ";
- background-color: $color-gray-30;
- }
-
- &.active,
- &:hover {
- &::after {
- background-color: $color-primary;
- }
- }
-
- &.top,
- &.bottom {
- width: 28px;
- height: 22px;
- left: calc(50% - 14px);
-
- &::after {
- width: 3px;
- height: 15px;
- }
- }
-
- &.top {
- top: 0;
- }
-
- &.bottom {
- bottom: 0;
- }
-
- &.left,
- &.right {
- width: 22px;
- height: 28px;
- top: calc(50% - 14px);
-
- &::after {
- width: 15px;
- height: 3px;
- }
- }
-
- &.left {
- left: 0;
- }
-
- &.right {
- right: 0;
- }
-
- &.centerv {
- width: 28px;
- height: 28px;
- left: calc(50% - 14px);
- top: calc(50% - 14px);
-
- &::after {
- width: 3px;
- height: 15px;
- }
- }
-
- &.centerh {
- width: 28px;
- height: 15px;
- left: calc(50% - 14px);
- top: calc(50% - 7px);
-
- &::after {
- width: 15px;
- height: 3px;
- }
- }
- }
-}
-
-.constraints-form {
- display: flex;
- flex-grow: 1;
- flex-direction: column;
- align-items: stretch;
- justify-content: flex-start;
-
- .input-select {
- font-size: $fs12;
- margin: 0 $size-1 $size-2 $size-1;
- padding: 0 $size-1;
- }
-
- svg {
- width: 15px;
- height: 15px;
- margin-left: $size-4;
- fill: $color-gray-20;
- }
-
- .left-right svg {
- transform: rotate(45deg);
- }
-
- .top-bottom svg {
- transform: rotate(-45deg);
- }
-
- .fix-when {
- font-size: $fs12;
- cursor: pointer;
- display: flex;
-
- span {
- margin-left: $size-2;
- }
-
- &:hover,
- &.active {
- color: $color-primary;
-
- svg {
- fill: $color-primary;
- }
- }
- }
-}
-
-.cap-select {
- background-color: transparent;
- border: 1px solid transparent;
- border-bottom-color: $color-gray-40;
- color: $color-gray-10;
- cursor: pointer;
- font-size: $fs12;
- margin: $size-1;
- overflow: hidden;
- padding: $size-1;
- padding-right: 20px;
- position: relative;
- text-overflow: ellipsis;
- white-space: nowrap;
- width: 100%;
-
- & .cap-select-button {
- svg {
- fill: $color-gray-10;
- height: 11px;
- position: absolute;
- right: 5px;
- top: 6px;
- width: 11px;
- }
- }
-
- &:hover {
- border-color: $color-gray-40;
- }
-
- &:focus {
- border-color: $color-primary;
- }
-}
-
-.cap-select-dropdown {
- right: 5px;
- top: 30px;
- z-index: 12;
- width: 200px;
- height: 320px;
- position: fixed;
-
- & li.separator {
- border-top: 1px solid $color-gray-10;
- }
-
- & li img {
- width: 16px;
- margin-right: $size-2;
- }
-}
-
-.expand-colors {
- cursor: pointer;
- display: flex;
-
- .text {
- color: $color-gray-30;
- font-size: $fs12;
- padding-left: 10px;
- }
-
- svg {
- width: 16px;
- height: 16px;
- fill: $color-gray-20;
- stroke: $color-gray-20;
- }
-}
-
-.selected-colors {
- .color-data {
- margin-bottom: 0;
- padding-bottom: 5px;
-
- svg {
- visibility: hidden;
- }
-
- .percentil {
- margin-bottom: 0;
- }
- }
-
- .color-data:hover {
- background-color: $color-gray-60;
-
- svg {
- visibility: visible;
- }
- }
-}
-
-.layout-menu,
-.layout-item-menu,
-.layout-grid-item-menu {
- font-family: "worksans", sans-serif;
- svg {
- height: 16px;
- width: 16px;
- fill: $color-gray-30;
- }
- .layout-row {
- display: grid;
- grid-template-columns: 60px 1fr;
- margin-bottom: 5px;
- .row-title {
- font-size: $fs12;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- margin-right: 5px;
- font-family: "worksans", sans-serif;
-
- &.justify-content,
- &.align-content,
- &.sizing {
- align-items: flex-start;
- margin-top: 4px;
- }
-
- &.align-items-grid,
- &.jusfiy-content-grid {
- align-items: flex-start;
- margin-top: 11px;
- }
- }
- .btn-wrapper {
- display: flex;
- width: 100%;
- max-width: 185px;
-
- &.wrap {
- flex-direction: column;
- gap: 5px;
- }
-
- &.justify-content,
- &.align-content {
- display: flex;
- flex-direction: column;
- gap: 5px;
- }
-
- .direction,
- .wrap-type,
- .align-items-style,
- .align-self-style,
- .justify-content-style,
- .align-content-style,
- .layout-behavior,
- .absolute {
- display: flex;
- border-radius: $br4;
- border: 1px solid $color-gray-60;
- height: 26px;
- margin-right: 5px;
- flex-grow: 1;
- &.horizontal {
- button svg {
- transform: rotate(90deg);
- }
- }
- button {
- display: flex;
- flex-grow: 1;
- justify-content: center;
- align-items: center;
- background: none;
- border: none;
- cursor: pointer;
- border-right: 1px solid $color-gray-60;
- color: $color-gray-20;
- &.active,
- &:hover {
- color: $color-primary;
- &.dir {
- color: $color-primary;
- }
- svg {
- fill: $color-primary;
- }
- }
- }
- .dir {
- display: flex;
- justify-content: center;
- align-items: center;
- background: none;
- border: none;
- cursor: pointer;
- border-right: 1px solid $color-gray-60;
- padding: 2px;
- &.row-reverse {
- svg {
- transform: rotate(180deg);
- }
- }
-
- &.column-reverse {
- svg {
- transform: rotate(-90deg);
- }
- }
- &.column {
- svg {
- transform: rotate(90deg);
- }
- }
- &.active,
- &:hover {
- svg {
- fill: $color-primary;
- }
- }
- }
- :last-child {
- border-right: none;
- }
- }
- .z-index {
- display: flex;
- align-items: center;
- margin-left: 2px;
- margin-top: -4px;
- svg {
- width: 30px;
- }
- }
-
- .edit-mode {
- align-items: center;
- border-radius: 4px;
- border: 1px solid $color-gray-60;
- display: flex;
- flex-direction: row;
- gap: 10px;
- justify-content: center;
- margin-left: 5px;
- padding: 0 8px;
- text-align: left;
- width: 120px;
-
- button {
- color: $color-gray-30;
- display: flex;
- justify-content: center;
- align-items: center;
- background: transparent;
- border: none;
- cursor: pointer;
- gap: 16px;
-
- &.active,
- &:hover {
- color: $color-primary;
- svg {
- fill: $color-primary;
- }
- }
- }
- }
-
- &.align-grid-items {
- flex-direction: row;
- gap: 0px;
- margin: 7px 0;
-
- .align-items-style {
- margin-right: 2px;
- }
- }
-
- &.align-grid-content {
- flex-direction: column;
- gap: 7px;
- margin: 7px 0;
- }
- }
- .position-wrapper {
- display: flex;
- width: 100%;
- max-width: 185px;
- height: 26px;
- border-radius: 4px;
- border: 1px solid $color-gray-60;
-
- .position-btn {
- display: flex;
- justify-content: center;
- align-items: center;
- background: transparent;
- border: none;
- cursor: pointer;
- color: $color-gray-20;
- border-right: 1px solid $color-gray-60;
- flex: 1;
-
- &:last-child {
- border-right: none;
- }
- &.active,
- &:hover {
- color: $color-primary;
- }
-
- &[disabled] {
- opacity: 0.5;
- &:hover {
- color: $color-gray-20;
- }
- }
- }
- }
-
- &.single-button {
- display: flex;
- justify-content: flex-end;
- height: 1.5rem;
-
- .btn-wrapper {
- width: initial;
- }
- }
- }
- .no-wrap {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 21px;
- width: 17px;
- svg {
- height: 0.7rem;
- width: 0.7rem;
- }
- }
-
- .wrap {
- padding: 1px;
- }
-
- .gap-group {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 7px;
- margin-top: 3px;
- margin-bottom: 8px;
- height: 26px;
- max-width: 166px;
- .gap-row {
- display: flex;
- justify-content: center;
- align-items: center;
- .icon {
- display: flex;
- justify-content: center;
- align-items: center;
- margin-right: 7px;
- svg {
- height: 14px;
- width: 14px;
- }
- &.rotated {
- transform: rotate(90deg);
- }
- &.activated {
- svg {
- fill: $color-primary;
- }
- }
- }
- input {
- font-size: $fs12;
- min-width: 0;
- padding: 0.25rem;
- height: 20px;
- margin: 0;
- }
- }
- button {
- display: flex;
- justify-content: center;
- align-items: center;
- background: none;
- border: none;
- cursor: pointer;
- border-radius: $br3;
-
- &.lock {
- border: 1px solid $color-gray-60;
- border-radius: $br3;
- width: 30px;
- height: 30px;
- }
- &.active {
- svg {
- fill: $color-primary;
- }
- }
- &:hover {
- background-color: $color-primary;
- svg {
- fill: $color-gray-60;
- }
- }
- }
- }
-
- .padding-row,
- .margin-row {
- display: grid;
- grid-template-columns: auto 30px;
- max-width: 226px;
- .padding-group,
- .margin-item-group {
- display: flex;
- margin-top: 3px;
- margin-bottom: 3px;
- height: 26px;
- .padding-item,
- .margin-item {
- display: flex;
- align-items: center;
- flex-grow: 1;
- .icon {
- display: flex;
- justify-content: center;
- align-items: center;
- margin-right: 7px;
- svg {
- height: 14px;
- width: 14px;
- }
- &.rotated {
- transform: rotate(90deg);
- }
- &.activated {
- svg {
- fill: $color-primary;
- }
- }
- }
- input {
- font-size: $fs12;
- min-width: 0;
- padding: 0.25rem;
- width: 70px;
- height: 20px;
- margin: 0;
- }
- }
- button {
- display: flex;
- justify-content: center;
- align-items: center;
- background: none;
- border: none;
- cursor: pointer;
- border-radius: $br3;
-
- &.lock {
- border: 1px solid $color-gray-60;
- border-radius: $br3;
- width: 30px;
- height: 30px;
- }
- &.active {
- svg {
- fill: $color-primary;
- }
- }
- &:hover {
- background-color: $color-primary;
- svg {
- fill: $color-gray-60;
- }
- }
- }
- }
- .padding-icons,
- .margin-item-icons {
- padding: 0;
- border: 1px solid $color-gray-60;
- border-radius: $br3;
- margin-bottom: 8px;
- margin-top: $br3;
- margin-right: 1px;
- height: 30px;
- width: 30px;
-
- .padding-icon,
- .margin-item-icon {
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 6px;
- flex-grow: 1;
- border-right: 1px solid $color-gray-60;
- cursor: pointer;
-
- &:hover,
- &.selected {
- svg {
- fill: $color-primary;
- }
- }
- svg {
- height: 14px;
- width: 14px;
- fill: $color-gray-30;
- }
- }
-
- :last-child {
- border: none;
- }
- }
-
- .wrapper {
- display: flex;
- height: 26px;
-
- .input-element {
- margin: 0;
- margin-top: 3px;
- height: 26px;
- }
- }
- }
-
- .layout-container {
- border: 1px solid $color-gray-60;
- border-radius: $br3;
- margin: 5px 0;
- .layout-entry {
- display: flex;
- align-items: center;
- color: $color-gray-20;
- height: 38px;
- cursor: pointer;
- &:hover {
- svg {
- fill: $color-primary;
- }
- }
- }
-
- .layout-info {
- font-size: $fs12;
- width: 100%;
- overflow-x: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- &::first-letter {
- text-transform: capitalize;
- }
- }
-
- .layout-body {
- display: flex;
- align-items: center;
- margin: 7px;
- .selects-wrapper {
- width: 100%;
- margin-left: 12px;
- select {
- text-transform: capitalize;
- }
- option {
- text-transform: capitalize;
- }
- }
-
- .orientation-grid {
- background-color: $color-gray-60;
- .button-wrapper {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- grid-template-rows: 1fr 1fr 1fr;
- width: 47px;
- height: 47px;
- border: 1px solid $color-gray-30;
- margin: 12px;
- .orientation {
- background: none;
- border: none;
- height: 14px;
- width: 14px;
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 2px;
- cursor: pointer;
-
- .icon {
- display: flex;
- justify-content: center;
- align-items: center;
- svg {
- fill: none;
- height: 10px;
- width: 10px;
- }
- &.rotated {
- transform: rotate(90deg);
- }
- }
-
- &.active {
- .icon {
- svg {
- fill: $color-primary;
- }
- }
- }
- &:hover {
- .icon {
- svg {
- fill: $color-gray-20;
- }
- }
- }
- }
- }
- &.col {
- .button-wrapper {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- grid-template-rows: 1fr;
- .orientation {
- height: 100%;
- justify-content: space-between;
- flex-direction: column;
- }
- }
- }
- &.row {
- .button-wrapper {
- display: grid;
- grid-template-rows: 1fr 1fr 1fr;
- grid-template-columns: 1fr;
- .orientation {
- width: 100%;
- justify-content: space-between;
- padding: 2px;
- }
- }
- }
- }
- }
- }
-
- .grid-columns {
- border: 1px solid $color-gray-60;
- padding: 5px;
- min-height: 38px;
- display: flex;
- flex-direction: column;
- align-items: center;
- &:not(:first-child) {
- margin-top: 5px;
- }
- .grid-columns-header {
- display: flex;
- justify-content: center;
- align-items: center;
- width: 100%;
- height: 100%;
- flex-grow: 1;
- min-height: 36px;
- .columns-info {
- flex-grow: 1;
- font-size: 12px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- .expand-icon,
- .add-column {
- cursor: pointer;
- background-color: transparent;
- border: none;
- display: flex;
- justify-content: center;
- align-items: center;
-
- &.active,
- &:hover {
- svg {
- fill: $color-primary;
- }
- }
- }
-
- .add-column svg {
- height: 12px;
- width: 12px;
- fill: $color-gray-20;
- }
- }
- .columns-info-wrapper {
- .column-info {
- display: grid;
- grid-template-columns: 35px 1fr 1fr auto;
- background-color: $color-gray-60;
- padding: 3px;
- border-radius: 3px;
- border: 1px solid transparent;
-
- &:hover {
- border: 1px solid $color-primary;
- }
-
- &:not(:first-child) {
- margin-top: 3px;
- }
- .direction-grid-icon {
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 5px;
- }
- input {
- background-color: $color-gray-60;
- }
- .grid-column-value,
- .grid-column-unit {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 30px;
- &.active,
- &:focus,
- &:focus-within {
- border-bottom: 1px solid $color-primary;
- }
- }
- .grid-column-unit-selector {
- border: none;
- border-bottom: 1px solid $color-gray-30;
- margin: 0.25rem 0;
- height: 23px;
- width: 100%;
- &:hover {
- border-bottom: 1px solid $color-gray-20;
- }
- }
-
- .remove-grid-column {
- cursor: pointer;
- background-color: transparent;
- border: none;
- display: flex;
- justify-content: center;
- align-items: center;
- margin-left: 40px;
- svg {
- height: 12px;
- width: 12px;
- fill: $color-gray-20;
- }
- &.active,
- &:hover {
- svg {
- fill: $color-primary;
- }
- }
- }
- }
- }
- }
- .manage-grid-columns {
- margin-left: 60px;
- margin-bottom: 10px;
- .grid-auto,
- .grid-manual {
- display: grid;
- grid-template-columns: 1fr 1fr;
- .grid-columns-auto,
- .grid-rows-auto {
- display: grid;
- grid-template-columns: 20px 1fr;
- .icon {
- display: flex;
- justify-content: center;
- align-items: center;
- }
- input {
- width: 80%;
- }
- }
- }
- .grid-manual {
- .input-wrapper {
- display: grid;
- grid-template-columns: 1fr 1fr;
- }
- }
- }
-}
-
-.advanced-ops {
- margin: 10px 0;
- display: flex;
- align-items: center;
- cursor: pointer;
- font-size: $fs12;
- color: $color-gray-30;
- border: none;
- background-color: transparent;
- padding: 0;
- .icon {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- margin-right: 10px;
- svg {
- fill: $color-gray-20;
- }
- }
-
- &:hover {
- svg {
- fill: $color-primary;
- }
- }
-}
-.advanced-ops-body {
- .input-wrapper {
- display: grid;
- grid-template-columns: 1fr 1fr;
- .input-element {
- width: 100%;
- &::after {
- content: attr(alt);
- width: 100px;
- }
- }
- }
-}
-
-.component-annotation {
- background-color: $color-gray-60;
- border: 1px solid $color-gray-60;
- border-radius: 2px;
-
- .title {
- display: flex;
- align-items: center;
- justify-content: space-between;
- border-bottom: 1px solid $color-gray-50;
- font-size: $fs12;
- color: $color-gray-20;
- padding: 0 10px;
-
- &.expandeable {
- cursor: pointer;
- }
-
- div {
- display: flex;
- align-items: center;
- line-height: 2.5;
- }
-
- .expand {
- svg {
- fill: $color-gray-20;
- width: $size-2;
- height: $size-2;
- margin-right: 10px;
- }
- }
-
- .icon {
- display: none;
- cursor: pointer;
- svg {
- fill: $color-gray-20;
- width: $size-4;
- height: $size-4;
- margin-left: 15px;
- &.icon-cross {
- width: $size-3;
- height: $size-3;
- }
- }
-
- .icon-tick:hover,
- .icon-pencil:hover {
- fill: $color-primary;
- }
-
- .icon-cross:hover,
- .icon-trash:hover {
- fill: $color-danger;
- }
- }
-
- &:hover {
- .icon {
- display: flex;
- }
- }
- }
-
- &.editing {
- border: 1px solid $color-primary;
- .title .icon {
- display: flex;
- }
-
- textarea {
- min-height: 250px;
- }
- }
-
- &.creating {
- textarea {
- min-height: 250px;
- }
- }
-
- .hidden {
- display: none;
- svg {
- display: none;
- }
- }
-
- .counter {
- text-align: right;
- font-size: $fs11;
- color: $color-gray-30;
- margin: 0 10px 10px 0;
- }
-
- // Auto growing text
- .grow-wrap {
- // easy way to plop the elements on top of each other and have them both sized based on the tallest one's height
- display: grid;
-
- &:after {
- // The space is needed to preventy jumpy behavior
- content: attr(data-replicated-value) " ";
- white-space: pre-wrap;
- visibility: hidden;
- }
-
- textarea {
- background-color: $color-gray-60;
- color: $color-white;
- padding: 10px;
-
- border: none;
- overflow: hidden;
- outline: none;
-
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
-
- resize: none; /*remove the resize handle on the bottom right*/
- }
-
- textarea,
- &:after {
- /* Identical styling required!! */
- font: inherit;
- font-size: $fs14;
- overflow-wrap: anywhere;
-
- padding: 10px;
-
- /* Place on top of each other */
- grid-area: 1 / 1 / 2 / 2;
- }
- }
-}
-
-.component-block-title {
- border: none;
- background: none;
-
- svg {
- height: 8px;
- width: 8px;
- fill: $color-gray-20;
- margin-right: 1rem;
- transform: rotate(180deg);
- }
-
- &.back {
- cursor: pointer;
- }
-}
diff --git a/frontend/resources/styles/main/partials/sidebar-interactions.scss b/frontend/resources/styles/main/partials/sidebar-interactions.scss
deleted file mode 100644
index 77c39c9a95..0000000000
--- a/frontend/resources/styles/main/partials/sidebar-interactions.scss
+++ /dev/null
@@ -1,215 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-.interactions-help {
- font-size: $fs12;
- padding: 7px $size-4;
- margin: 0 -7px;
- text-align: center;
-
- &.separator {
- padding-bottom: $size-4;
- border-bottom: 1px solid $color-black;
- }
-}
-
-.interactions-help-icon {
- height: 32px;
- width: 32px;
- margin: $size-4 auto;
-
- svg {
- fill: $color-gray-40;
- height: 32px;
- width: 32px;
- }
-}
-
-.interactions-summary {
- cursor: pointer;
- flex-basis: 0;
- flex-grow: 1;
-
- .trigger-name {
- font-size: $fs12;
- color: $color-white;
- }
-
- .action-summary {
- font-size: $fs12;
- color: $color-gray-20;
- }
-}
-
-.interactions-element {
- display: flex;
- align-items: center;
- margin: 0 -7px;
- padding: 0 7px;
-
- .element-label {
- color: $color-gray-20;
- font-size: $fs12;
- width: 64px;
- }
-
- &.separator {
- border-top: 1px solid $color-black;
- margin-top: $size-1;
- }
-}
-
-.interactions-pos-buttons {
- margin-top: $size-2;
- padding-top: $size-2;
- padding-bottom: $size-2;
- justify-content: space-between;
-
- .element-set-actions-button {
- min-width: 18px;
- min-height: 18px;
- }
-
- svg {
- height: 18px;
- width: 18px;
- }
-}
-
-.interactions-way-buttons {
- display: grid;
- grid-template-columns: 1fr 1fr;
-
- & .input-radio {
- margin-bottom: 0;
-
- & label {
- color: $color-gray-20;
-
- &:before {
- background-color: unset;
- }
- }
-
- & input[type="radio"]:checked {
- & + label {
- &:before {
- background-color: $color-primary;
- box-shadow: inset 0 0 0 5px $color-gray-50;
- }
- }
- }
- }
-}
-
-.interactions-direction-buttons {
- margin-top: $size-2;
- padding-top: $size-2;
- padding-bottom: $size-2;
- justify-content: space-around;
-
- .element-set-actions-button {
- min-width: 40px;
- min-height: 13px;
- }
-
- svg {
- height: 13px;
- width: 13px;
- }
-}
-
-.interactions-easing-icon {
- display: flex;
- justify-content: center;
- align-items: center;
- min-width: 30px;
- min-height: 30px;
-
- & svg {
- width: 12px;
- height: 12px;
- stroke: $color-gray-20;
- }
-}
-
-.flow-element {
- display: flex;
- align-items: center;
- padding: $size-1;
-
- .element-label {
- font-size: $fs11;
- }
-
- .flow-name {
- cursor: pointer;
- }
-
- & input.element-name {
- background: transparent;
- border-color: $color-primary;
- color: $color-white;
- font-size: $fs11;
- }
-}
-
-.flow-button {
- cursor: pointer;
- display: flex;
- justify-content: center;
- align-items: center;
- margin-right: $size-2;
-
- & svg {
- height: 12px;
- width: 12px;
- fill: $color-gray-20;
- }
-
- &:hover svg {
- fill: $color-primary;
- }
-}
-
-.flow-badge {
- cursor: pointer;
- display: flex;
-
- & .content {
- align-items: center;
- background-color: $color-gray-50;
- border-radius: $br4;
- display: flex;
- height: 24px;
-
- & svg {
- height: 12px;
- margin: 0 $size-2;
- width: 12px;
- fill: $color-gray-20;
- }
-
- & span {
- color: $color-gray-20;
- font-size: $fs12;
- margin-right: $size-4;
- }
- }
-
- &.selected .content,
- &:hover .content {
- background-color: $color-primary;
-
- & svg {
- fill: $color-gray-60;
- }
-
- & span {
- color: $color-gray-60;
- }
- }
-}
diff --git a/frontend/resources/templates/index.mustache b/frontend/resources/templates/index.mustache
index 14f26d76a8..77475d7e30 100644
--- a/frontend/resources/templates/index.mustache
+++ b/frontend/resources/templates/index.mustache
@@ -4,6 +4,7 @@
Penpot - Design Freedom for Teams
+
@@ -17,6 +18,9 @@
+ {{#isDebug}}
+
+ {{/isDebug}}
diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs
index b711b1ead4..6c72136001 100644
--- a/frontend/src/app/main/data/workspace.cljs
+++ b/frontend/src/app/main/data/workspace.cljs
@@ -855,7 +855,8 @@
(fn [parent objects]
(cond-> parent
(ctl/grid-layout? parent)
- (ctl/assign-cells objects))))
+ (ctl/assign-cells objects)))
+ {:with-objects? true})
(pcb/reorder-grid-children parents)
@@ -1490,6 +1491,30 @@
(rx/of (show-context-menu
(-> params (assoc :kind :page :selected (:id page))))))))
+(defn show-track-context-menu
+ [{:keys [grid-id type index] :as params}]
+ (ptk/reify ::show-track-context-menu
+ ptk/WatchEvent
+ (watch [_ _ _]
+ (rx/of (show-context-menu
+ (-> params (assoc :kind :grid-track
+ :grid-id grid-id
+ :type type
+ :index index)))))))
+
+(defn show-grid-cell-context-menu
+ [{:keys [grid-id] :as params}]
+ (ptk/reify ::show-grid-cell-context-menu
+ ptk/WatchEvent
+ (watch [_ state _]
+ (let [objects (wsh/lookup-page-objects state)
+ grid (get objects grid-id)
+ cells (->> (get-in state [:workspace-grid-edition grid-id :selected])
+ (map #(get-in grid [:layout-grid-cells %])))]
+ (rx/of (show-context-menu
+ (-> params (assoc :kind :grid-cells
+ :grid grid
+ :cells cells))))))))
(def hide-context-menu
(ptk/reify ::hide-context-menu
ptk/UpdateEvent
@@ -1497,6 +1522,8 @@
(assoc-in state [:workspace-local :context-menu] nil))))
+
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Clipboard
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs
index 9b7f1c54dc..061b3c5503 100644
--- a/frontend/src/app/main/data/workspace/changes.cljs
+++ b/frontend/src/app/main/data/workspace/changes.cljs
@@ -15,6 +15,7 @@
[app.common.logging :as log]
[app.common.schema :as sm]
[app.common.types.shape-tree :as ctst]
+ [app.common.types.shape.layout :as ctl]
[app.common.uuid :as uuid]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
@@ -51,8 +52,8 @@
(defn update-shapes
([ids update-fn] (update-shapes ids update-fn nil))
- ([ids update-fn {:keys [reg-objects? save-undo? stack-undo? attrs ignore-tree page-id ignore-remote? ignore-touched undo-group]
- :or {reg-objects? false save-undo? true stack-undo? false ignore-remote? false ignore-touched false}}]
+ ([ids update-fn {:keys [reg-objects? save-undo? stack-undo? attrs ignore-tree page-id ignore-remote? ignore-touched undo-group with-objects?]
+ :or {reg-objects? false save-undo? true stack-undo? false ignore-remote? false ignore-touched false with-objects? false}}]
(dm/assert!
"expected a valid coll of uuid's"
@@ -70,14 +71,15 @@
update-layout-ids
(->> ids
(map (d/getf objects))
- (filter #(some update-layout-attr? (pcb/changed-attrs % objects update-fn {:attrs attrs})))
+ (filter #(some update-layout-attr? (pcb/changed-attrs % objects update-fn {:attrs attrs :with-objects? with-objects?})))
(map :id))
changes (reduce
(fn [changes id]
(let [opts {:attrs attrs
:ignore-geometry? (get ignore-tree id)
- :ignore-touched ignore-touched}]
+ :ignore-touched ignore-touched
+ :with-objects? with-objects?}]
(pcb/update-shapes changes [id] update-fn (d/without-nils opts))))
(-> (pcb/empty-changes it page-id)
(pcb/set-save-undo? save-undo?)
@@ -86,6 +88,8 @@
(cond-> undo-group
(pcb/set-undo-group undo-group)))
ids)
+ grid-ids (->> ids (filter (partial ctl/grid-layout? objects)))
+ changes (pcb/update-shapes changes grid-ids ctl/assign-cell-positions {:with-objects? true})
changes (pcb/reorder-grid-children changes ids)
changes (add-undo-group changes state)]
(rx/concat
diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs
index ed0734e707..0c4850a404 100644
--- a/frontend/src/app/main/data/workspace/comments.cljs
+++ b/frontend/src/app/main/data/workspace/comments.cljs
@@ -13,7 +13,7 @@
[app.common.schema :as sm]
[app.common.types.shape-tree :as ctst]
[app.main.data.comments :as dcm]
- [app.main.data.workspace.changes :as dwc]
+ [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwco]
[app.main.data.workspace.drawing :as dwd]
[app.main.data.workspace.state-helpers :as wsh]
@@ -148,7 +148,7 @@
(pcb/update-page-option :comment-threads-position assoc thread-id (select-keys thread [:position :frame-id])))]
(rx/merge
- (rx/of (dwc/commit-changes changes))
+ (rx/of (dch/commit-changes changes))
(->> (rp/cmd! :update-comment-thread-position thread)
(rx/catch #(rx/throw {:type :update-comment-thread-position}))
(rx/ignore))))))))
diff --git a/frontend/src/app/main/data/workspace/grid_layout/editor.cljs b/frontend/src/app/main/data/workspace/grid_layout/editor.cljs
index dc6e99fa59..9af194119f 100644
--- a/frontend/src/app/main/data/workspace/grid_layout/editor.cljs
+++ b/frontend/src/app/main/data/workspace/grid_layout/editor.cljs
@@ -6,6 +6,7 @@
(ns app.main.data.workspace.grid-layout.editor
(:require
+ [app.common.data.macros :as dm]
[app.common.geom.rect :as grc]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.state-helpers :as wsh]
@@ -25,14 +26,34 @@
(conj hover-set cell-id)
(disj hover-set cell-id))))))))
-(defn select-grid-cell
- [grid-id cell-id add?]
- (ptk/reify ::select-grid-cell
+(defn add-to-selection
+ ([grid-id cell-id]
+ (add-to-selection grid-id cell-id false))
+ ([grid-id cell-id shift?]
+ (ptk/reify ::add-to-selection
+ ptk/UpdateEvent
+ (update [_ state]
+ (if shift?
+ (let [objects (wsh/lookup-page-objects state)
+ grid (get objects grid-id)
+ selected (or (dm/get-in state [:workspace-grid-edition grid-id :selected]) #{})
+ selected (into selected [cell-id])
+ cells (->> selected (map #(dm/get-in grid [:layout-grid-cells %])))
+
+ {:keys [first-row last-row first-column last-column]} (ctl/cells-coordinates cells)
+ new-selected
+ (into #{}
+ (map :id)
+ (ctl/cells-in-area grid first-row last-row first-column last-column))]
+ (assoc-in state [:workspace-grid-edition grid-id :selected] new-selected))
+ (update-in state [:workspace-grid-edition grid-id :selected] (fnil conj #{}) cell-id))))))
+
+(defn set-selection
+ [grid-id cell-id]
+ (ptk/reify ::set-selection
ptk/UpdateEvent
(update [_ state]
- (if add?
- (update-in state [:workspace-grid-edition grid-id :selected] (fnil conj #{}) cell-id)
- (assoc-in state [:workspace-grid-edition grid-id :selected] #{cell-id})))))
+ (assoc-in state [:workspace-grid-edition grid-id :selected] #{cell-id}))))
(defn remove-selection
[grid-id cell-id]
diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs
index 656173f5e4..ff477d3207 100644
--- a/frontend/src/app/main/data/workspace/groups.cljs
+++ b/frontend/src/app/main/data/workspace/groups.cljs
@@ -125,7 +125,7 @@
[parent-id]
(fn [parent]
(assoc-in parent [:layout-grid-cells (:id target-cell) :shapes] [(:id group)]))))
- (pcb/update-shapes grid-parents ctl/assign-cells)
+ (pcb/update-shapes grid-parents ctl/assign-cells {:with-objects? true})
(pcb/remove-objects ids-to-delete))]
[group changes]))
@@ -216,7 +216,7 @@
(cond-> changes
(ctl/grid-layout? objects (:parent-id shape))
- (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells))))
+ (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells {:with-objects? true}))))
selected (->> (wsh/lookup-selected state)
(remove #(ctn/has-any-copy-parent? objects (get objects %)))
diff --git a/frontend/src/app/main/data/workspace/guides.cljs b/frontend/src/app/main/data/workspace/guides.cljs
index 5df3d41a09..2229210103 100644
--- a/frontend/src/app/main/data/workspace/guides.cljs
+++ b/frontend/src/app/main/data/workspace/guides.cljs
@@ -11,7 +11,7 @@
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.types.page :as ctp]
- [app.main.data.workspace.changes :as dwc]
+ [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@@ -35,7 +35,7 @@
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/update-page-option :guides assoc (:id guide) guide))]
- (rx/of (dwc/commit-changes changes))))))
+ (rx/of (dch/commit-changes changes))))))
(defn remove-guide [guide]
(dm/assert!
@@ -56,7 +56,7 @@
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/update-page-option :guides dissoc (:id guide)))]
- (rx/of (dwc/commit-changes changes))))))
+ (rx/of (dch/commit-changes changes))))))
(defn remove-guides
[ids]
diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs
index 3037b9f893..f9854062fe 100644
--- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs
+++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs
@@ -98,11 +98,11 @@
(gsh/move delta)))
[new-instance-shape new-instance-shapes _]
- (ctst/clone-object main-instance-shape
- (:parent-id main-instance-shape)
- (:objects main-instance-page)
- update-new-shape
- update-original-shape)
+ (ctst/clone-shape main-instance-shape
+ (:parent-id main-instance-shape)
+ (:objects main-instance-page)
+ :update-new-shape update-new-shape
+ :update-original-shape update-original-shape)
remap-frame
(fn [shape]
@@ -134,10 +134,9 @@
(let [component-root (d/seek #(nil? (:parent-id %)) (vals (:objects component)))
[new-component-shape new-component-shapes _]
- (ctst/clone-object component-root
- nil
- (get component :objects)
- identity)]
+ (ctst/clone-shape component-root
+ nil
+ (get component :objects))]
[new-component-shape new-component-shapes nil nil]))))
@@ -185,7 +184,8 @@
(fn [shape objects]
(-> shape
(ctl/push-into-cell [(:id first-shape)] row column)
- (ctl/assign-cells objects))))
+ (ctl/assign-cells objects)))
+ {:with-objects? true})
(pcb/reorder-grid-children [(:parent-id first-shape)])))
changes)
@@ -975,11 +975,12 @@
original-shape)
[_ new-shapes _]
- (ctst/clone-object component-shape
+ (ctst/clone-shape component-shape
(:id parent-shape)
(get component-page :objects)
- update-new-shape
- update-original-shape)
+ :update-new-shape update-new-shape
+ :update-original-shape update-original-shape
+ :dest-objects (get container :objects))
add-obj-change (fn [changes shape']
(update changes :redo-changes conj
@@ -1037,11 +1038,11 @@
original-shape))
[_new-shape new-shapes updated-shapes]
- (ctst/clone-object shape
- (:id component-parent-shape)
- (get page :objects)
- update-new-shape
- update-original-shape)
+ (ctst/clone-shape shape
+ (:id component-parent-shape)
+ (get page :objects)
+ :update-new-shape update-new-shape
+ :update-original-shape update-original-shape)
add-obj-change (fn [changes shape']
(update changes :redo-changes conj
diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs
index 497202d7c4..b6828a1941 100644
--- a/frontend/src/app/main/data/workspace/selection.cljs
+++ b/frontend/src/app/main/data/workspace/selection.cljs
@@ -499,8 +499,7 @@
changes (-> (pcb/add-object changes new-obj {:ignore-touched (and duplicating-component? child?)})
(pcb/amend-last-change #(assoc % :old-id (:id obj)))
(cond-> (ctl/grid-layout? objects (:parent-id obj))
- (-> (pcb/update-shapes [(:parent-id obj)] ctl/assign-cells)
- (pcb/update-shapes [(:parent-id obj)] ctl/check-deassigned-cells)
+ (-> (pcb/update-shapes [(:parent-id obj)] ctl/assign-cells {:with-objects? true})
(pcb/reorder-grid-children [(:parent-id obj)]))))
changes (cond-> changes
diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs
index e89f415ea7..cc29ceca61 100644
--- a/frontend/src/app/main/data/workspace/shape_layout.cljs
+++ b/frontend/src/app/main/data/workspace/shape_layout.cljs
@@ -9,19 +9,22 @@
[app.common.colors :as clr]
[app.common.data :as d]
[app.common.data.macros :as dm]
+ [app.common.files.changes-builder :as pcb]
[app.common.files.helpers :as cfh]
+ [app.common.files.shapes-helpers :as cfsh]
+ [app.common.geom.point :as gpt]
[app.common.geom.shapes.flex-layout :as flex]
[app.common.geom.shapes.grid-layout :as grid]
[app.common.types.component :as ctc]
[app.common.types.modifiers :as ctm]
[app.common.types.shape.layout :as ctl]
[app.common.uuid :as uuid]
- [app.main.data.workspace.changes :as dwc]
+ [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.colors :as cl]
[app.main.data.workspace.grid-layout.editor :as dwge]
[app.main.data.workspace.modifiers :as dwm]
[app.main.data.workspace.selection :as dwse]
- [app.main.data.workspace.shapes :as dws]
+ [app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[beicon.v2.core :as rx]
@@ -68,13 +71,13 @@
:layout-grid-columns []})
(defn get-layout-initializer
- [type from-frame? objects]
+ [type from-frame?]
(let [[initial-layout-data calculate-params]
(case type
:flex [initial-flex-layout flex/calculate-params]
:grid [initial-grid-layout grid/calculate-params])]
- (fn [shape]
+ (fn [shape objects]
(let [shape
(-> shape
(merge initial-layout-data)
@@ -127,11 +130,11 @@
(let [objects (wsh/lookup-page-objects state)
parent (get objects id)
undo-id (js/Symbol)
- layout-initializer (get-layout-initializer type from-frame? objects)]
+ layout-initializer (get-layout-initializer type from-frame?)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes [id] layout-initializer)
- (dwc/update-shapes (dm/get-prop parent :shapes) #(dissoc % :constraints-h :constraints-v))
+ (dch/update-shapes [id] layout-initializer {:with-objects? true})
+ (dch/update-shapes (dm/get-prop parent :shapes) #(dissoc % :constraints-h :constraints-v))
(ptk/data-event :layout/update [id])
(dwu/commit-undo-transaction undo-id))))))
@@ -167,22 +170,22 @@
group-index (cfh/get-index-replacement selected objects)]
(rx/of
(dwse/select-shapes ordered-ids)
- (dws/create-artboard-from-selection new-shape-id parent-id group-index (:name (first selected-shapes)))
+ (dwsh/create-artboard-from-selection new-shape-id parent-id group-index (:name (first selected-shapes)))
(cl/remove-all-fills [new-shape-id] {:color clr/black :opacity 1})
(create-layout-from-id new-shape-id type false)
- (dwc/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto))
- (dwc/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix))
- (dws/delete-shapes page-id selected)
+ (dch/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto))
+ (dch/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix))
+ (dwsh/delete-shapes page-id selected)
(ptk/data-event :layout/update [new-shape-id])
(dwu/commit-undo-transaction undo-id)))
;; Create Layout from selection
(rx/of
- (dws/create-artboard-from-selection new-shape-id)
+ (dwsh/create-artboard-from-selection new-shape-id)
(cl/remove-all-fills [new-shape-id] {:color clr/black :opacity 1})
(create-layout-from-id new-shape-id type false)
- (dwc/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto))
- (dwc/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix))))
+ (dch/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto))
+ (dch/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix))))
(rx/of (ptk/data-event :layout/update [new-shape-id])
(dwu/commit-undo-transaction undo-id)))))))
@@ -195,7 +198,7 @@
(let [undo-id (js/Symbol)]
(rx/of
(dwu/start-undo-transaction undo-id)
- (dwc/update-shapes ids #(apply dissoc % layout-keys))
+ (dch/update-shapes ids #(apply dissoc % layout-keys))
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id))))))
@@ -242,42 +245,114 @@
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes ids (d/patch-object changes))
+ (dch/update-shapes ids (d/patch-object changes))
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id))))))
(defn add-layout-track
- [ids type value]
- (assert (#{:row :column} type))
- (ptk/reify ::add-layout-column
- ptk/WatchEvent
- (watch [_ _ _]
- (let [undo-id (js/Symbol)]
- (rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
- ids
- (fn [shape]
- (case type
- :row (ctl/add-grid-row shape value)
- :column (ctl/add-grid-column shape value))))
- (ptk/data-event :layout/update ids)
- (dwu/commit-undo-transaction undo-id))))))
+ ([ids type value]
+ (add-layout-track ids type value nil))
+ ([ids type value index]
+ (assert (#{:row :column} type))
+ (ptk/reify ::add-layout-track
+ ptk/WatchEvent
+ (watch [_ _ _]
+ (let [undo-id (js/Symbol)]
+ (rx/of (dwu/start-undo-transaction undo-id)
+ (dch/update-shapes
+ ids
+ (fn [shape]
+ (case type
+ :row (ctl/add-grid-row shape value index)
+ :column (ctl/add-grid-column shape value index))))
+ (ptk/data-event :layout/update ids)
+ (dwu/commit-undo-transaction undo-id)))))))
(defn remove-layout-track
+ [ids type index & {:keys [with-shapes?] :or {with-shapes? false}}]
+ (assert (#{:row :column} type))
+
+ (ptk/reify ::remove-layout-track
+ ptk/WatchEvent
+ (watch [_ state _]
+ (let [undo-id (js/Symbol)]
+ (let [objects (wsh/lookup-page-objects state)
+
+ shapes-to-delete
+ (when with-shapes?
+ (->> ids
+ (mapcat
+ (fn [id]
+ (let [shape (get objects id)]
+ (if (= type :column)
+ (ctl/shapes-by-column shape index)
+ (ctl/shapes-by-row shape index)))))
+ (into #{})))]
+ (rx/of (dwu/start-undo-transaction undo-id)
+ (if shapes-to-delete
+ (dwsh/delete-shapes shapes-to-delete)
+ (rx/empty))
+ (dch/update-shapes
+ ids
+ (fn [shape objects]
+ (case type
+ :row (ctl/remove-grid-row shape index objects)
+ :column (ctl/remove-grid-column shape index objects)))
+ {:with-objects? true})
+ (ptk/data-event :layout/update ids)
+ (dwu/commit-undo-transaction undo-id)))))))
+
+(defn duplicate-layout-track
[ids type index]
(assert (#{:row :column} type))
- (ptk/reify ::remove-layout-column
+ (ptk/reify ::duplicate-layout-track
ptk/WatchEvent
- (watch [_ _ _]
- (let [undo-id (js/Symbol)]
+ (watch [it state _]
+ (let [file-id (:current-file-id state)
+ page (wsh/lookup-page state)
+ objects (:objects page)
+ libraries (wsh/get-libraries state)
+ library-data (wsh/get-file state file-id)
+ shape-id (first ids)
+ base-shape (get objects shape-id)
+
+ shapes-by-track
+ (if (= type :column)
+ (ctl/shapes-by-column base-shape index false)
+ (ctl/shapes-by-row base-shape index false))
+
+ ;; Change to set in order to use auxiliary functions
+ selected (set shapes-by-track)
+
+ changes
+ (->> (dwse/prepare-duplicate-changes objects page selected (gpt/point 0 0) it libraries library-data file-id)
+ (dwse/duplicate-changes-update-indices objects selected))
+
+ ;; Creates a map with shape-id => duplicated-shape-id
+ ids-map
+ (->> changes
+ :redo-changes
+ (filter #(= (:type %) :add-obj))
+ (filter #(selected (:old-id %)))
+ (map #(vector (:old-id %) (get-in % [:obj :id])))
+ (into {}))
+
+ changes
+ (-> changes
+ (pcb/update-shapes
+ ids
+ (fn [shape objects]
+ ;; The duplication could have altered the grid so we restore the values, we'll calculate the good ones now
+ (let [shape (merge shape (select-keys base-shape [:layout-grid-cells :layout-grid-columns :layout-grid-rows]))]
+ (case type
+ :row (ctl/duplicate-row shape objects index ids-map)
+ :column (ctl/duplicate-column shape objects index ids-map))))
+ {:with-objects? true}))
+
+ undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
- ids
- (fn [shape objects]
- (case type
- :row (ctl/remove-grid-row shape index objects)
- :column (ctl/remove-grid-column shape index objects))))
+ (dch/commit-changes changes)
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id))))))
@@ -290,7 +365,7 @@
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
+ (dch/update-shapes
ids
(fn [shape]
(case type
@@ -336,7 +411,7 @@
:row :layout-grid-rows
:column :layout-grid-columns)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
+ (dch/update-shapes
ids
(fn [shape]
(-> shape
@@ -428,15 +503,16 @@
parent-ids (->> ids (map #(cfh/get-parent-id objects %)))
undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwc/update-shapes ids (d/patch-object changes))
- (dwc/update-shapes children-ids (partial fix-child-sizing objects changes))
- (dwc/update-shapes
+ (dch/update-shapes ids (d/patch-object changes))
+ (dch/update-shapes children-ids (partial fix-child-sizing objects changes))
+ (dch/update-shapes
parent-ids
(fn [parent objects]
(-> parent
(fix-parent-sizing objects (set ids) changes)
(cond-> (ctl/grid-layout? parent)
- (ctl/assign-cells objects)))))
+ (ctl/assign-cells objects))))
+ {:with-objects? true})
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id))))))
@@ -449,7 +525,7 @@
(rx/of
(dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
+ (dch/update-shapes
[layout-id]
(fn [shape]
(->> ids
@@ -472,7 +548,7 @@
(let [undo-id (js/Symbol)]
(rx/of
(dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
+ (dch/update-shapes
[layout-id]
(fn [shape objects]
(case mode
@@ -521,7 +597,40 @@
(ctl/assign-cells objects))]
(-> shape
- (d/update-in-when [:layout-grid-cells (:id target-cell)] assoc :position :area))))))
+ (d/update-in-when [:layout-grid-cells (:id target-cell)] assoc :position :area)))))
+ {:with-objects? true})
+ (dwge/clean-selection layout-id)
+ (ptk/data-event :layout/update [layout-id])
+ (dwu/commit-undo-transaction undo-id))))))
+
+(defn merge-cells
+ [layout-id ids]
+
+ (ptk/reify ::merge-cells
+ ptk/WatchEvent
+ (watch [_ _ _]
+ (let [undo-id (js/Symbol)]
+ (rx/of
+ (dwu/start-undo-transaction undo-id)
+ (dch/update-shapes
+ [layout-id]
+ (fn [shape objects]
+ (let [cells (->> ids (map #(get-in shape [:layout-grid-cells %])))
+
+ {:keys [first-row first-column last-row last-column]}
+ (ctl/cells-coordinates cells)
+
+ target-cell
+ (ctl/get-cell-by-position shape first-row first-column)]
+ (-> shape
+ (ctl/resize-cell-area
+ (:row target-cell) (:column target-cell)
+ first-row
+ first-column
+ (inc (- last-row first-row))
+ (inc (- last-column first-column)))
+ (ctl/assign-cells objects))))
+ {:with-objects? true})
(dwge/clean-selection layout-id)
(ptk/data-event :layout/update [layout-id])
(dwu/commit-undo-transaction undo-id))))))
@@ -531,14 +640,13 @@
(ptk/reify ::update-grid-cell-position
ptk/WatchEvent
- (watch [_ state _]
- (let [objects (wsh/lookup-page-objects state)
- undo-id (js/Symbol)]
+ (watch [_ _ _]
+ (let [undo-id (js/Symbol)]
(rx/of
(dwu/start-undo-transaction undo-id)
- (dwc/update-shapes
+ (dch/update-shapes
[layout-id]
- (fn [shape]
+ (fn [shape objects]
(let [prev-data (-> (dm/get-in shape [:layout-grid-cells cell-id])
(select-keys [:row :column :row-span :column-span]))
@@ -547,6 +655,62 @@
(ctl/resize-cell-area (:row prev-data) (:column prev-data)
(:row new-data) (:column new-data)
(:row-span new-data) (:column-span new-data))
- (ctl/assign-cells objects)))))
+ (ctl/assign-cells objects))))
+ {:with-objects? true})
+ (ptk/data-event :layout/update [layout-id])
+ (dwu/commit-undo-transaction undo-id))))))
+
+
+(defn create-cell-board
+ [layout-id cell-ids]
+ (ptk/reify ::create-cell-board
+ ptk/WatchEvent
+ (watch [it state _]
+ (let [page-id (:current-page-id state)
+ objects (wsh/lookup-page-objects state)
+ frame-id (uuid/next)
+
+ undo-id (js/Symbol)
+
+ shape (get objects layout-id)
+ cells (->> cell-ids (map #(get-in shape [:layout-grid-cells %])))
+ selected (into #{} (mapcat :shapes) cells)
+
+ {:keys [first-row first-column last-row last-column]} (ctl/cells-coordinates cells)
+
+ target-cell (ctl/get-cell-by-position shape first-row first-column)
+
+ [_ changes]
+ (-> (pcb/empty-changes it page-id)
+ (pcb/with-objects objects)
+ (cond-> (d/not-empty? selected)
+ (cfsh/prepare-create-artboard-from-selection
+ frame-id layout-id objects selected 0 nil true (:id target-cell)))
+
+ (cond-> (empty? (seq selected))
+ (cfsh/prepare-create-empty-artboard
+ frame-id layout-id objects 0 nil true (:id target-cell))))
+
+ changes
+ (-> changes
+ (pcb/update-shapes
+ [frame-id]
+ (fn [shape]
+ (-> shape
+ (assoc :layout-item-h-sizing :fill)
+ (assoc :layout-item-v-sizing :fill))))
+ (pcb/update-shapes
+ [layout-id]
+ (fn [shape]
+ (let [new-row-span (inc (- last-row first-row))
+ new-col-span (inc (- last-column first-column))]
+ (-> shape
+ (ctl/resize-cell-area
+ (:row target-cell) (:column target-cell)
+ first-row first-column new-row-span new-col-span))))))]
+
+ (rx/of
+ (dwu/start-undo-transaction undo-id)
+ (dch/commit-changes changes)
(ptk/data-event :layout/update [layout-id])
(dwu/commit-undo-transaction undo-id))))))
diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs
index 42422fa521..9a95a69791 100644
--- a/frontend/src/app/main/data/workspace/shapes.cljs
+++ b/frontend/src/app/main/data/workspace/shapes.cljs
@@ -41,12 +41,11 @@
(watch [it state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
- selected (wsh/lookup-selected state)
[shape changes]
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)
- (cfsh/prepare-add-shape shape objects selected))
+ (cfsh/prepare-add-shape shape objects))
changes (cond-> changes
(cfh/text-shape? shape)
diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs
index 5cc82e5b07..16904a1eee 100644
--- a/frontend/src/app/main/data/workspace/transforms.cljs
+++ b/frontend/src/app/main/data/workspace/transforms.cljs
@@ -559,8 +559,8 @@
(fn [[_ target-frame drop-index]]
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
- (dwm/apply-modifiers {:undo-transation? false})
(move-shapes-to-frame ids target-frame drop-index)
+ (dwm/apply-modifiers {:undo-transation? false})
(finish-transform)
(dwu/commit-undo-transaction undo-id))))))))))))))
@@ -628,9 +628,13 @@
(ctl/swap-shapes id (:id next-cell)))))
parent))]
(-> changes
- (pcb/update-shapes [(:id parent)] (fn [shape] (-> shape
- (assoc :layout-grid-cells layout-grid-cells)
- (ctl/assign-cells objects))))
+ (pcb/update-shapes
+ [(:id parent)]
+ (fn [shape]
+ (-> shape
+ (assoc :layout-grid-cells layout-grid-cells)
+ ;; We want the previous objects value
+ (ctl/assign-cells objects))))
(pcb/reorder-grid-children [(:id parent)]))))
changes
@@ -868,7 +872,9 @@
(pcb/update-shapes moving-shapes-ids #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))
(pcb/update-shapes shape-ids-to-detach ctk/detach-shape)
(pcb/change-parent frame-id moving-shapes drop-index)
- (pcb/reorder-grid-children [frame-id])
+ (cond-> (ctl/grid-layout? objects frame-id)
+ (-> (pcb/update-shapes [frame-id] ctl/assign-cell-positions {:with-objects? true})
+ (pcb/reorder-grid-children [frame-id])))
(pcb/remove-objects empty-parents))]
(when (and (some? frame-id) (d/not-empty? changes))
diff --git a/frontend/src/app/main/render.cljs b/frontend/src/app/main/render.cljs
index 5b8620b462..c6bf57e9ab 100644
--- a/frontend/src/app/main/render.cljs
+++ b/frontend/src/app/main/render.cljs
@@ -67,17 +67,24 @@
(defn- calculate-dimensions
[objects aspect-ratio]
- (let [bounds
- (->> (ctst/get-root-objects objects)
- (map (partial gsb/get-object-bounds objects))
- (grc/join-rects))]
- (-> bounds
- (update :x mth/finite 0)
- (update :y mth/finite 0)
- (update :width mth/finite 100000)
- (update :height mth/finite 100000)
- (grc/update-rect :position)
- (grc/fix-aspect-ratio aspect-ratio))))
+ (let [root-objects (ctst/get-root-objects objects)]
+ (if (empty? root-objects)
+ ;; Empty page, we create an arbitrary rect for the thumbnail
+ (-> (grc/make-rect {:x 0 :y 0 :width 100 :height 100})
+ (grc/update-rect :position)
+ (grc/fix-aspect-ratio aspect-ratio))
+
+ (let [bounds
+ (->> root-objects
+ (map (partial gsb/get-object-bounds objects))
+ (grc/join-rects))]
+ (-> bounds
+ (update :x mth/finite 0)
+ (update :y mth/finite 0)
+ (update :width mth/finite 100000)
+ (update :height mth/finite 100000)
+ (grc/update-rect :position)
+ (grc/fix-aspect-ratio aspect-ratio))))))
(declare shape-wrapper-factory)
@@ -201,6 +208,7 @@
(let [objects (:objects data)
shapes (cfh/get-immediate-children objects)
dim (calculate-dimensions objects aspect-ratio)
+ _ (prn ">>DIM" dim)
vbox (format-viewbox dim)
bgcolor (dm/get-in data [:options :background] default-color)
diff --git a/frontend/src/app/main/ui/alert.cljs b/frontend/src/app/main/ui/alert.cljs
index 7511c390b1..8c7ee4b020 100644
--- a/frontend/src/app/main/ui/alert.cljs
+++ b/frontend/src/app/main/ui/alert.cljs
@@ -9,7 +9,6 @@
(:require
[app.main.data.modal :as modal]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -27,8 +26,8 @@
hint
accept-label
accept-style] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-accept (or on-accept identity)
+
+ (let [on-accept (or on-accept identity)
message (or message (tr "ds.alert-title"))
accept-label (or accept-label (tr "ds.alert-ok"))
accept-style (or accept-style :danger)
@@ -50,54 +49,26 @@
(on-accept props)))]
(->> (events/listen js/document "keydown" on-keydown)
(partial events/unlistenByKey))))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} title]
- [:button {:class (stl/css :modal-close-btn)
- :on-click accept-fn} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} title]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click accept-fn} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- (when (and (string? message) (not= message ""))
- [:h3 {:class (stl/css :modal-msg)} message])
- (when (and (string? scd-message) (not= scd-message ""))
- [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
- (when (string? hint)
- [:p {:class (stl/css :modal-hint)} hint])]
+ [:div {:class (stl/css :modal-content)}
+ (when (and (string? message) (not= message ""))
+ [:h3 {:class (stl/css :modal-msg)} message])
+ (when (and (string? scd-message) (not= scd-message ""))
+ [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
+ (when (string? hint)
+ [:p {:class (stl/css :modal-hint)} hint])]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:input {:class (stl/css-case :accept-btn true
- :danger (= accept-style :danger)
- :primary (= accept-style :primary))
- :type "button"
- :value accept-label
- :on-click accept-fn}]]]]]
-
-
- [:div.modal-overlay
- [:div.modal-container.alert-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 title]]
- [:div.modal-close-button
- {:on-click accept-fn} i/close]]
-
- [:div.modal-content
- (when (and (string? message) (not= message ""))
- [:h3 message])
- (when (and (string? scd-message) (not= scd-message ""))
- [:h3 scd-message])
- (when (string? hint)
- [:p hint])]
-
- [:div.modal-footer
- [:div.action-buttons
- [:input.accept-button
- {:class (dom/classnames
- :danger (= accept-style :danger)
- :primary (= accept-style :primary))
- :type "button"
- :value accept-label
- :on-click accept-fn}]]]]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:input {:class (stl/css-case :accept-btn true
+ :danger (= accept-style :danger)
+ :primary (= accept-style :primary))
+ :type "button"
+ :value accept-label
+ :on-click accept-fn}]]]]]))
diff --git a/frontend/src/app/main/ui/alert.scss b/frontend/src/app/main/ui/alert.scss
index 066381d194..2d4a8b1d78 100644
--- a/frontend/src/app/main/ui/alert.scss
+++ b/frontend/src/app/main/ui/alert.scss
@@ -11,39 +11,45 @@
&.transparent {
background-color: transparent;
}
- .modal-container {
- @extend .modal-container-base;
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .modal-hint {
- @include titleTipography;
- }
- }
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+}
+.modal-container {
+ @extend .modal-container-base;
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.modal-hint {
+ @include titleTipography;
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
diff --git a/frontend/src/app/main/ui/auth.cljs b/frontend/src/app/main/ui/auth.cljs
index 37f5398722..fe84732526 100644
--- a/frontend/src/app/main/ui/auth.cljs
+++ b/frontend/src/app/main/ui/auth.cljs
@@ -12,7 +12,6 @@
[app.main.ui.auth.recovery :refer [recovery-page]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-page register-success-page register-validate-page]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -20,102 +19,57 @@
(mf/defc terms-login
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
+ (let [show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
show-terms? (some? cf/terms-of-service-uri)
show-privacy? (some? cf/privacy-policy-uri)]
- (if new-css-system
- (when show-all?
- [:div {:class (stl/css :terms-login)}
- (when show-terms?
- [:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
+ (when show-all?
+ [:div {:class (stl/css :terms-login)}
+ (when show-terms?
+ [:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
- (when show-all?
- [:span (tr "labels.and")])
+ (when show-all?
+ [:span (tr "labels.and")])
- (when show-privacy?
- [:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])])
-
- (when show-all?
- [:div.terms-login
- (when show-terms?
- [:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
-
- (when show-all?
- [:span (tr "labels.and")])
-
- (when show-privacy?
- [:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])]))))
+ (when show-privacy?
+ [:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])])))
(mf/defc auth
[{:keys [route] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- section (get-in route [:data :name])
+ (let [section (get-in route [:data :name])
params (:query-params route)
show-illustration? (contains? cf/flags :login-illustration)]
(mf/use-effect
#(dom/set-html-title (tr "title.default")))
- (if new-css-system
- [:main {:class (stl/css-case :auth-section true
- :no-illustration (not show-illustration?))}
- (when show-illustration?
- [:div {:class (stl/css :login-illustration)}
- i/login-illustration])
+ [:main {:class (stl/css-case :auth-section true
+ :no-illustration (not show-illustration?))}
+ (when show-illustration?
+ [:div {:class (stl/css :login-illustration)}
+ i/login-illustration])
- [:section {:class (stl/css :auth-content)}
- [:*
- [:a {:href "#/" :class (stl/css :logo-btn)}i/logo]
- (case section
- :auth-register
- [:& register-page {:params params}]
+ [:section {:class (stl/css :auth-content)}
+ [:*
+ [:a {:href "#/" :class (stl/css :logo-btn)} i/logo]
+ (case section
+ :auth-register
+ [:& register-page {:params params}]
- :auth-register-validate
- [:& register-validate-page {:params params}]
+ :auth-register-validate
+ [:& register-validate-page {:params params}]
- :auth-register-success
- [:& register-success-page {:params params}]
+ :auth-register-success
+ [:& register-success-page {:params params}]
- :auth-login
- [:& login-page {:params params}]
+ :auth-login
+ [:& login-page {:params params}]
- :auth-recovery-request
- [:& recovery-request-page]
+ :auth-recovery-request
+ [:& recovery-request-page]
- :auth-recovery
- [:& recovery-page {:params params}])]
+ :auth-recovery
+ [:& recovery-page {:params params}])]
- (when (contains? #{:auth-login :auth-register} section)
- [:& terms-login])]]
-
- ;; OLD
- [:main.auth
- [:section.auth-sidebar
- [:a.logo {:href "#/"}
- [:span {:aria-hidden true} i/logo]
- [:span.hidden-name "Home"]]
- [:span.tagline (tr "auth.sidebar-tagline")]]
-
- [:section.auth-content
- (case section
- :auth-register
- [:& register-page {:params params}]
-
- :auth-register-validate
- [:& register-validate-page {:params params}]
-
- :auth-register-success
- [:& register-success-page {:params params}]
-
- :auth-login
- [:& login-page {:params params}]
-
- :auth-recovery-request
- [:& recovery-request-page]
-
- :auth-recovery
- [:& recovery-page {:params params}])
-
- [:& terms-login {}]]])))
+ (when (contains? #{:auth-login :auth-register} section)
+ [:& terms-login])]]))
diff --git a/frontend/src/app/main/ui/auth/login.cljs b/frontend/src/app/main/ui/auth/login.cljs
index 249ed8e99e..abf47e0404 100644
--- a/frontend/src/app/main/ui/auth/login.cljs
+++ b/frontend/src/app/main/ui/auth/login.cljs
@@ -18,7 +18,6 @@
[app.main.ui.components.button-link :as bl]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.dom :as dom]
@@ -94,8 +93,7 @@
(mf/defc login-form
[{:keys [params on-success-callback origin] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo (mf/deps params) (constantly params))
+ (let [initial (mf/use-memo (mf/deps params) (constantly params))
error (mf/use-state false)
form (fm/use-form :spec ::login-form
:validators [handle-error-messages]
@@ -157,156 +155,86 @@
(mf/use-fn
#(st/emit! (rt/nav :auth-recovery-request)))]
- (if new-css-system
- [:*
- (when-let [message @error]
- [:& msgs/inline-banner
- {:type :warning
- :content message
- :on-close #(reset! error nil)
- :data-test "login-banner"
- :role "alert"}])
+ [:*
+ (when-let [message @error]
+ [:& msgs/inline-banner
+ {:type :warning
+ :content message
+ :on-close #(reset! error nil)
+ :data-test "login-banner"
+ :role "alert"}])
- [:& fm/form {:on-submit on-submit :form form}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input
- {:name :email
- :type "email"
- :label (tr "auth.email")
- :class (stl/css :form-field)}]]
+ [:& fm/form {:on-submit on-submit :form form}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input
+ {:name :email
+ :type "email"
+ :label (tr "auth.email")
+ :class (stl/css :form-field)}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input
- {:type "password"
- :name :password
- :label (tr "auth.password")
- :class (stl/css :form-field)}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input
+ {:type "password"
+ :name :password
+ :label (tr "auth.password")
+ :class (stl/css :form-field)}]]
- (when (and (not= origin :viewer)
- (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password)))
- [:div {:class (stl/css :fields-row :forgot-password)}
- [:& lk/link {:action on-recovery-request
- :data-test "forgot-password"}
- (tr "auth.forgot-password")]])
+ (when (and (not= origin :viewer)
+ (or (contains? cf/flags :login)
+ (contains? cf/flags :login-with-password)))
+ [:div {:class (stl/css :fields-row :forgot-password)}
+ [:& lk/link {:action on-recovery-request
+ :data-test "forgot-password"}
+ (tr "auth.forgot-password")]])
- [:div {:class (stl/css :buttons-stack)}
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password))
- [:> fm/submit-button*
- {:label (tr "auth.login-submit")
- :data-test "login-submit"
- :class (stl/css :login-button)}])
+ [:div {:class (stl/css :buttons-stack)}
+ (when (or (contains? cf/flags :login)
+ (contains? cf/flags :login-with-password))
+ [:> fm/submit-button*
+ {:label (tr "auth.login-submit")
+ :data-test "login-submit"
+ :class (stl/css :login-button)}])
- (when (contains? cf/flags :login-with-ldap)
- [:> fm/submit-button*
- {:label (tr "auth.login-with-ldap-submit")
- :on-click on-submit-ldap}])]]]
-
-
- ;; OLD
- [:*
- (when-let [message @error]
- [:& msgs/inline-banner
- {:type :warning
- :content message
- :on-close #(reset! error nil)
- :data-test "login-banner"
- :role "alert"}])
-
- [:& fm/form {:on-submit on-submit :form form}
- [:div.fields-row
- [:& fm/input
- {:name :email
- :type "email"
- :help-icon i/at
- :label (tr "auth.email")
- :class (stl/css :form-field)}]]
-
- [:div.fields-row
- [:& fm/input
- {:type "password"
- :name :password
- :help-icon i/eye
- :label (tr "auth.password")
- :class (stl/css :form-field)}]]
-
- [:div.buttons-stack
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password))
- [:> fm/submit-button*
- {:label (tr "auth.login-submit")
- :data-test "login-submit"}])
-
- (when (contains? cf/flags :login-with-ldap)
- [:> fm/submit-button*
- {:label (tr "auth.login-with-ldap-submit")
- :on-click on-submit-ldap}])]]])))
+ (when (contains? cf/flags :login-with-ldap)
+ [:> fm/submit-button*
+ {:label (tr "auth.login-with-ldap-submit")
+ :on-click on-submit-ldap}])]]]))
(mf/defc login-buttons
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- login-with-google (mf/use-fn (mf/deps params) #(login-with-oidc % :google params))
+ (let [login-with-google (mf/use-fn (mf/deps params) #(login-with-oidc % :google params))
login-with-github (mf/use-fn (mf/deps params) #(login-with-oidc % :github params))
login-with-gitlab (mf/use-fn (mf/deps params) #(login-with-oidc % :gitlab params))
login-with-oidc (mf/use-fn (mf/deps params) #(login-with-oidc % :oidc params))]
- (if new-css-system
- [:div {:class (stl/css :auth-buttons)}
- (when (contains? cf/flags :login-with-google)
- [:& bl/button-link {:on-click login-with-google
- :icon i/brand-google
- :label (tr "auth.login-with-google-submit")
- :class (stl/css :login-btn :btn-google-auth)}])
+ [:div {:class (stl/css :auth-buttons)}
+ (when (contains? cf/flags :login-with-google)
+ [:& bl/button-link {:on-click login-with-google
+ :icon i/brand-google
+ :label (tr "auth.login-with-google-submit")
+ :class (stl/css :login-btn :btn-google-auth)}])
- (when (contains? cf/flags :login-with-github)
- [:& bl/button-link {:on-click login-with-github
- :icon i/brand-github
- :label (tr "auth.login-with-github-submit")
- :class (stl/css :login-btn :btn-github-auth)}])
+ (when (contains? cf/flags :login-with-github)
+ [:& bl/button-link {:on-click login-with-github
+ :icon i/brand-github
+ :label (tr "auth.login-with-github-submit")
+ :class (stl/css :login-btn :btn-github-auth)}])
- (when (contains? cf/flags :login-with-gitlab)
- [:& bl/button-link {:on-click login-with-gitlab
- :icon i/brand-gitlab
- :label (tr "auth.login-with-gitlab-submit")
- :class (stl/css :login-btn :btn-gitlab-auth)}])
+ (when (contains? cf/flags :login-with-gitlab)
+ [:& bl/button-link {:on-click login-with-gitlab
+ :icon i/brand-gitlab
+ :label (tr "auth.login-with-gitlab-submit")
+ :class (stl/css :login-btn :btn-gitlab-auth)}])
- (when (contains? cf/flags :login-with-oidc)
- [:& bl/button-link {:on-click login-with-oidc
- :icon i/brand-openid
- :label (tr "auth.login-with-oidc-submit")
- :class (stl/css :login-btn :btn-oidc-auth)}])]
-
- [:div.auth-buttons
- (when (contains? cf/flags :login-with-google)
- [:& bl/button-link {:on-click login-with-google
- :icon i/brand-google
- :label (tr "auth.login-with-google-submit")
- :class "btn-google-auth"}])
-
- (when (contains? cf/flags :login-with-github)
- [:& bl/button-link {:on-click login-with-github
- :icon i/brand-github
- :label (tr "auth.login-with-github-submit")
- :class "btn-github-auth"}])
-
- (when (contains? cf/flags :login-with-gitlab)
- [:& bl/button-link {:on-click login-with-gitlab
- :icon i/brand-gitlab
- :label (tr "auth.login-with-gitlab-submit")
- :class "btn-gitlab-auth"}])
-
- (when (contains? cf/flags :login-with-oidc)
- [:& bl/button-link {:on-click login-with-oidc
- :icon i/brand-openid
- :label (tr "auth.login-with-oidc-submit")
- :class "btn-github-auth"}])])))
+ (when (contains? cf/flags :login-with-oidc)
+ [:& bl/button-link {:on-click login-with-oidc
+ :icon i/brand-openid
+ :label (tr "auth.login-with-oidc-submit")
+ :class (stl/css :login-btn :btn-oidc-auth)}])]))
(mf/defc login-button-oidc
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- login-oidc
+ (let [login-oidc
(mf/use-fn
(mf/deps params)
(fn [event]
@@ -317,69 +245,33 @@
(fn [event]
(when (k/enter? event)
(login-oidc event))))]
- (if new-css-system
- (when (contains? cf/flags :login-with-oidc)
- [:div {:class (stl/css :link-entry :link-oidc)}
- [:a {:tab-index "0"
- :on-key-down handle-key-down
- :on-click login-oidc}
- (tr "auth.login-with-oidc-submit")]])
-
- ;; OLD
- (when (contains? cf/flags :login-with-oidc)
- [:div.link-entry.link-oidc
- [:a {:tab-index "0"
- :on-key-down handle-key-down
- :on-click login-oidc}
- (tr "auth.login-with-oidc-submit")]]))))
+ (when (contains? cf/flags :login-with-oidc)
+ [:div {:class (stl/css :link-entry :link-oidc)}
+ [:a {:tab-index "0"
+ :on-key-down handle-key-down
+ :on-click login-oidc}
+ (tr "auth.login-with-oidc-submit")]])))
(mf/defc login-methods
[{:keys [params on-success-callback origin] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:*
- (when show-alt-login-buttons?
- [:*
- [:& login-buttons {:params params}]
+ [:*
+ (when show-alt-login-buttons?
+ [:*
+ [:& login-buttons {:params params}]
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password)
- (contains? cf/flags :login-with-ldap))
- [:hr {:class (stl/css :separator)}])])
+ (when (or (contains? cf/flags :login)
+ (contains? cf/flags :login-with-password)
+ (contains? cf/flags :login-with-ldap))
+ [:hr {:class (stl/css :separator)}])])
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password)
- (contains? cf/flags :login-with-ldap))
- [:& login-form {:params params :on-success-callback on-success-callback :origin origin}])]
-
- ;; OLD
- [:*
- (when show-alt-login-buttons?
- [:*
- [:span.separator
- [:span.line]
- [:span.text (tr "labels.continue-with")]
- [:span.line]]
-
- [:& login-buttons {:params params}]
-
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password)
- (contains? cf/flags :login-with-ldap))
- [:span.separator
- [:span.line]
- [:span.text (tr "labels.or")]
- [:span.line]])])
-
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password)
- (contains? cf/flags :login-with-ldap))
- [:& login-form {:params params :on-success-callback on-success-callback}])])))
+ (when (or (contains? cf/flags :login)
+ (contains? cf/flags :login-with-password)
+ (contains? cf/flags :login-with-ldap))
+ [:& login-form {:params params :on-success-callback on-success-callback :origin origin}])])
(mf/defc login-page
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- go-register
+ (let [go-register
(mf/use-fn
#(st/emit! (rt/nav :auth-register {} params)))
@@ -391,64 +283,33 @@
(mf/use-fn
#(st/emit! (du/create-demo-profile)))]
- (if new-css-system
- [:div {:class (stl/css :auth-form)}
- [:h1 {:class (stl/css :auth-title)
- :data-test "login-title"} (tr "auth.login-title")]
+ [:div {:class (stl/css :auth-form)}
+ [:h1 {:class (stl/css :auth-title)
+ :data-test "login-title"} (tr "auth.login-title")]
- [:hr {:class (stl/css :separator)}]
+ [:hr {:class (stl/css :separator)}]
- [:& login-methods {:params params}]
+ [:& login-methods {:params params}]
- [:div {:class (stl/css :links)}
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password))
- [:div {:class (stl/css :link-entry :register)}
- [:& lk/link {:action on-pass-recovery
- :data-test "forgot-password"}
- (tr "auth.forgot-password")]])
+ [:div {:class (stl/css :links)}
+ (when (or (contains? cf/flags :login)
+ (contains? cf/flags :login-with-password))
+ [:div {:class (stl/css :link-entry :register)}
+ [:& lk/link {:action on-pass-recovery
+ :data-test "forgot-password"}
+ (tr "auth.forgot-password")]])
- (when (contains? cf/flags :registration)
- [:div {:class (stl/css :link-entry :register)}
- [:span (tr "auth.register") " "]
- [:& lk/link {:action go-register
- :data-test "register-submit"}
- (tr "auth.register-submit")]])]
+ (when (contains? cf/flags :registration)
+ [:div {:class (stl/css :link-entry :register)}
+ [:span (tr "auth.register") " "]
+ [:& lk/link {:action go-register
+ :data-test "register-submit"}
+ (tr "auth.register-submit")]])]
- (when (contains? cf/flags :demo-users)
- [:div {:class (stl/css :link-entry :demo-account)}
- [:span (tr "auth.create-demo-profile") " "]
- [:& lk/link {:action on-create-demo-profile
- :data-test "demo-account-link"}
- (tr "auth.create-demo-account")]])]
-
- ;; OLD
- [:div.generic-form.login-form
- [:div.form-container
- [:h1 {:data-test "login-title"} (tr "auth.login-title")]
-
- [:& login-methods {:params params}]
-
- [:div.links
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-password))
- [:div.link-entry
- [:& lk/link {:action on-pass-recovery
- :data-test "forgot-password"}
- (tr "auth.forgot-password")]])
-
- (when (contains? cf/flags :registration)
- [:div.link-entry
- [:span (tr "auth.register") " "]
- [:& lk/link {:action go-register
- :data-test "register-submit"}
- (tr "auth.register-submit")]])]
-
- (when (contains? cf/flags :demo-users)
- [:div.links.demo
- [:div.link-entry
- [:span (tr "auth.create-demo-profile") " "]
- [:& lk/link {:action on-create-demo-profile
- :data-test "demo-account-link"}
- (tr "auth.create-demo-account")]]])]])))
+ (when (contains? cf/flags :demo-users)
+ [:div {:class (stl/css :link-entry :demo-account)}
+ [:span (tr "auth.create-demo-profile") " "]
+ [:& lk/link {:action on-create-demo-profile
+ :data-test "demo-account-link"}
+ (tr "auth.create-demo-account")]])]))
diff --git a/frontend/src/app/main/ui/auth/recovery.cljs b/frontend/src/app/main/ui/auth/recovery.cljs
index e8828c0031..f43b939bc4 100644
--- a/frontend/src/app/main/ui/auth/recovery.cljs
+++ b/frontend/src/app/main/ui/auth/recovery.cljs
@@ -12,7 +12,6 @@
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[cljs.spec.alpha :as s]
@@ -57,73 +56,41 @@
(mf/defc recovery-form
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (fm/use-form :spec ::recovery-form
+ (let [form (fm/use-form :spec ::recovery-form
:validators [password-equality
(fm/validate-not-empty :password-1 (tr "auth.password-not-empty"))
(fm/validate-not-empty :password-2 (tr "auth.password-not-empty"))]
:initial params)]
- (if new-css-system
- [:& fm/form {:on-submit on-submit :form form}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "password"
- :name :password-1
- :show-success? true
- :label (tr "auth.new-password")
- :class (stl/css :form-field)}]]
+ [:& fm/form {:on-submit on-submit :form form}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "password"
+ :name :password-1
+ :show-success? true
+ :label (tr "auth.new-password")
+ :class (stl/css :form-field)}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "password"
- :name :password-2
- :show-success? true
- :label (tr "auth.confirm-password")
- :class (stl/css :form-field)}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "password"
+ :name :password-2
+ :show-success? true
+ :label (tr "auth.confirm-password")
+ :class (stl/css :form-field)}]]
- [:> fm/submit-button*
- {:label (tr "auth.recovery-submit")
- :class (stl/css :submit-btn)}]]
-
- ;; OLD
- [:& fm/form {:on-submit on-submit
- :form form}
- [:div.fields-row
- [:& fm/input {:type "password"
- :name :password-1
- :label (tr "auth.new-password")}]]
-
- [:div.fields-row
- [:& fm/input {:type "password"
- :name :password-2
- :label (tr "auth.confirm-password")}]]
-
- [:> fm/submit-button*
- {:label (tr "auth.recovery-submit")}]])))
+ [:> fm/submit-button*
+ {:label (tr "auth.recovery-submit")
+ :class (stl/css :submit-btn)}]]))
;; --- Recovery Request Page
(mf/defc recovery-page
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :auth-form)}
- [:h1 {:class (stl/css :auth-title)} "Forgot your password?"]
- [:div {:class (stl/css :auth-subtitle)} "Please enter your new password"]
- [:hr {:class (stl/css :separator)}]
- [:& recovery-form {:params params}]
+ [:div {:class (stl/css :auth-form)}
+ [:h1 {:class (stl/css :auth-title)} "Forgot your password?"]
+ [:div {:class (stl/css :auth-subtitle)} "Please enter your new password"]
+ [:hr {:class (stl/css :separator)}]
+ [:& recovery-form {:params params}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-entry)}
- [:a {:on-click #(st/emit! (rt/nav :auth-login))}
- (tr "profile.recovery.go-to-login")]]]]
-
- ;; TODO
- [:section.generic-form
- [:div.form-container
- [:h1 "Forgot your password?"]
- [:div.subtitle "Please enter your new password"]
- [:& recovery-form {:params params}]
-
- [:div.links
- [:div.link-entry
- [:a {:on-click #(st/emit! (rt/nav :auth-login))}
- (tr "profile.recovery.go-to-login")]]]]])))
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-entry)}
+ [:a {:on-click #(st/emit! (rt/nav :auth-login))}
+ (tr "profile.recovery.go-to-login")]]]])
diff --git a/frontend/src/app/main/ui/auth/recovery_request.cljs b/frontend/src/app/main/ui/auth/recovery_request.cljs
index f9138025ff..d45720ea11 100644
--- a/frontend/src/app/main/ui/auth/recovery_request.cljs
+++ b/frontend/src/app/main/ui/auth/recovery_request.cljs
@@ -14,8 +14,6 @@
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk]
- [app.main.ui.context :as ctx]
- [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[beicon.v2.core :as rx]
@@ -34,8 +32,7 @@
(mf/defc recovery-form
[{:keys [on-success-callback] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (fm/use-form :spec ::recovery-request-form
+ (let [form (fm/use-form :spec ::recovery-request-form
:validators [handle-error-messages]
:initial {})
submitted (mf/use-state false)
@@ -77,62 +74,34 @@
(reset! form nil)
(st/emit! (du/request-profile-recovery params)))))]
- (if new-css-system
- [:& fm/form {:on-submit on-submit
- :form form}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:name :email
- :label (tr "auth.email")
- :type "text"
- :class (stl/css :form-field)}]]
+ [:& fm/form {:on-submit on-submit
+ :form form}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:name :email
+ :label (tr "auth.email")
+ :type "text"
+ :class (stl/css :form-field)}]]
- [:> fm/submit-button*
- {:label (tr "auth.recovery-request-submit")
- :data-test "recovery-resquest-submit"
- :class (stl/css :recover-btn)}]]
-
- ;; OLD
- [:& fm/form {:on-submit on-submit
- :form form}
- [:div.fields-row
- [:& fm/input {:name :email
- :label (tr "auth.email")
- :help-icon i/at
- :type "text"}]]
-
- [:> fm/submit-button*
- {:label (tr "auth.recovery-request-submit")
- :data-test "recovery-resquest-submit"}]])))
+ [:> fm/submit-button*
+ {:label (tr "auth.recovery-request-submit")
+ :data-test "recovery-resquest-submit"
+ :class (stl/css :recover-btn)}]]))
;; --- Recovery Request Page
(mf/defc recovery-request-page
[{:keys [params on-success-callback go-back-callback] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- default-go-back #(st/emit! (rt/nav :auth-login))
+ (let [default-go-back #(st/emit! (rt/nav :auth-login))
go-back (or go-back-callback default-go-back)]
- (if new-css-system
- [:div {:class (stl/css :auth-form)}
- [:h1 {:class (stl/css :auth-title)} (tr "auth.recovery-request-title")]
- [:div {:class (stl/css :auth-subtitle)} (tr "auth.recovery-request-subtitle")]
- [:hr {:class (stl/css :separator)}]
+ [:div {:class (stl/css :auth-form)}
+ [:h1 {:class (stl/css :auth-title)} (tr "auth.recovery-request-title")]
+ [:div {:class (stl/css :auth-subtitle)} (tr "auth.recovery-request-subtitle")]
+ [:hr {:class (stl/css :separator)}]
- [:& recovery-form {:params params :on-success-callback on-success-callback}]
+ [:& recovery-form {:params params :on-success-callback on-success-callback}]
- [:div {:class (stl/css :link-entry)}
- [:& lk/link {:action go-back
- :data-test "go-back-link"}
- (tr "labels.go-back")]]]
-
- ;; old
- [:section.generic-form
- [:div.form-container
- [:h1 (tr "auth.recovery-request-title")]
- [:div.subtitle (tr "auth.recovery-request-subtitle")]
- [:& recovery-form {:params params :on-success-callback on-success-callback}]
- [:div.links
- [:div.link-entry
- [:& lk/link {:action go-back
- :data-test "go-back-link"}
- (tr "labels.go-back")]]]]])))
+ [:div {:class (stl/css :link-entry)}
+ [:& lk/link {:action go-back
+ :data-test "go-back-link"}
+ (tr "labels.go-back")]]]))
diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs
index 432c852ae4..573c989209 100644
--- a/frontend/src/app/main/ui/auth/register.cljs
+++ b/frontend/src/app/main/ui/auth/register.cljs
@@ -17,7 +17,6 @@
[app.main.ui.auth.login :as login]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.i18n :refer [tr tr-html]]
@@ -88,8 +87,7 @@
(mf/defc register-form
[{:keys [params on-success-callback] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo (mf/deps params) (constantly params))
+ (let [initial (mf/use-memo (mf/deps params) (constantly params))
form (fm/use-form :spec ::register-form
:validators [validate
(fm/validate-not-empty :password (tr "auth.password-not-empty"))]
@@ -114,133 +112,64 @@
(partial handle-prepare-register-error form))))))]
- (if new-css-system
- [:& fm/form {:on-submit on-submit :form form}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "email"
- :name :email
- :label (tr "auth.email")
- :data-test "email-input"
- :show-success? true
- :class (stl/css :form-field)}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:name :password
- :hint (tr "auth.password-length-hint")
- :label (tr "auth.password")
- :show-success? true
- :type "password"
- :class (stl/css :form-field)}]]
+ [:& fm/form {:on-submit on-submit :form form}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "email"
+ :name :email
+ :label (tr "auth.email")
+ :data-test "email-input"
+ :show-success? true
+ :class (stl/css :form-field)}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:name :password
+ :hint (tr "auth.password-length-hint")
+ :label (tr "auth.password")
+ :show-success? true
+ :type "password"
+ :class (stl/css :form-field)}]]
- [:> fm/submit-button*
- {:label (tr "auth.register-submit")
- :disabled @submitted?
- :data-test "register-form-submit"
- :class (stl/css :register-btn)}]]
-
- ;; OLD
- [:& fm/form {:on-submit on-submit
- :form form}
- [:div.fields-row
- [:& fm/input {:type "email"
- :name :email
- :help-icon i/at
- :label (tr "auth.email")
- :data-test "email-input"}]]
- [:div.fields-row
- [:& fm/input {:name :password
- :hint (tr "auth.password-length-hint")
- :label (tr "auth.password")
- :type "password"}]]
-
- [:> fm/submit-button*
- {:label (tr "auth.register-submit")
- :disabled @submitted?
- :data-test "register-form-submit"}]])))
+ [:> fm/submit-button*
+ {:label (tr "auth.register-submit")
+ :disabled @submitted?
+ :data-test "register-form-submit"
+ :class (stl/css :register-btn)}]]))
(mf/defc register-methods
[{:keys [params on-success-callback] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:*
- (when login/show-alt-login-buttons?
- [:*
- [:hr {:class (stl/css :separator)}]
- [:& login/login-buttons {:params params}]])
- [:hr {:class (stl/css :separator)}]
- [:& register-form {:params params :on-success-callback on-success-callback}]]
-
- ;; OLD
- [:*
- (when login/show-alt-login-buttons?
- [:*
- [:span.separator
- [:span.line]
- [:span.text (tr "labels.continue-with")]
- [:span.line]]
-
- [:& login/login-buttons {:params params}]
-
- (when (or (contains? cf/flags :login)
- (contains? cf/flags :login-with-ldap))
- [:span.separator
- [:span.line]
- [:span.text (tr "labels.or")]
- [:span.line]])])
-
- [:& register-form {:params params :on-success-callback on-success-callback}]])))
+ [:*
+ (when login/show-alt-login-buttons?
+ [:*
+ [:hr {:class (stl/css :separator)}]
+ [:& login/login-buttons {:params params}]])
+ [:hr {:class (stl/css :separator)}]
+ [:& register-form {:params params :on-success-callback on-success-callback}]])
(mf/defc register-page
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :auth-form)}
- [:h1 {:class (stl/css :auth-title)
- :data-test "registration-title"} (tr "auth.register-title")]
- [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
+ [:div {:class (stl/css :auth-form)}
+ [:h1 {:class (stl/css :auth-title)
+ :data-test "registration-title"} (tr "auth.register-title")]
+ [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
- (when (contains? cf/flags :demo-warning)
- [:& demo-warning])
+ (when (contains? cf/flags :demo-warning)
+ [:& demo-warning])
- [:& register-methods {:params params}]
+ [:& register-methods {:params params}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-entry :account)}
- [:span (tr "auth.already-have-account") " "]
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-entry :account)}
+ [:span (tr "auth.already-have-account") " "]
- [:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
- :data-test "login-here-link"}
- (tr "auth.login-here")]]
+ [:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
+ :data-test "login-here-link"}
+ (tr "auth.login-here")]]
- (when (contains? cf/flags :demo-users)
- [:div {:class (stl/css :link-entry :demo-users)}
- [:span (tr "auth.create-demo-profile") " "]
- [:& lk/link {:action #(st/emit! (du/create-demo-profile))}
- (tr "auth.create-demo-account")]])]]
-
- ;; OLD
- [:div.form-container
- [:h1 {:data-test "registration-title"} (tr "auth.register-title")]
- [:div.subtitle (tr "auth.register-subtitle")]
-
- (when (contains? cf/flags :demo-warning)
- [:& demo-warning])
-
- [:& register-methods {:params params}]
-
- [:div.links
- [:div.link-entry
- [:span (tr "auth.already-have-account") " "]
-
- [:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
- :data-test "login-here-link"}
- (tr "auth.login-here")]]
-
- (when (contains? cf/flags :demo-users)
- [:div.link-entry
- [:span (tr "auth.create-demo-profile") " "]
- [:& lk/link {:action #(st/emit! (du/create-demo-profile))}
- (tr "auth.create-demo-account")]])]])))
+ (when (contains? cf/flags :demo-users)
+ [:div {:class (stl/css :link-entry :demo-users)}
+ [:span (tr "auth.create-demo-profile") " "]
+ [:& lk/link {:action #(st/emit! (du/create-demo-profile))}
+ (tr "auth.create-demo-account")]])]])
;; --- PAGE: register validation
@@ -284,8 +213,7 @@
(mf/defc register-validate-form
[{:keys [params on-success-callback] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (fm/use-form :spec ::register-validate-form
+ (let [form (fm/use-form :spec ::register-validate-form
:validators [(fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))
(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))]
:initial params)
@@ -306,103 +234,55 @@
(rx/subs! on-success
(partial handle-register-error form))))))]
- (if new-css-system
- [:& fm/form {:on-submit on-submit :form form}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:name :fullname
- :label (tr "auth.fullname")
- :type "text"
- :show-success? true
- :class (stl/css :form-field)}]]
+ [:& fm/form {:on-submit on-submit :form form}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:name :fullname
+ :label (tr "auth.fullname")
+ :type "text"
+ :show-success? true
+ :class (stl/css :form-field)}]]
- (when (contains? cf/flags :terms-and-privacy-checkbox)
- (let [terms-label
- (mf/html
- [:& tr-html
- {:tag-name "div"
- :label "auth.terms-privacy-agreement-md"
- :params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
- [:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
- [:& fm/input {:name :accept-terms-and-privacy
- :class "check-primary"
- :type "checkbox"
- :label terms-label}]]))
-
- [:> fm/submit-button*
- {:label (tr "auth.register-submit")
- :disabled @submitted?
- :class (stl/css :register-btn)}]]
-
- ;; OLD
- [:& fm/form {:on-submit on-submit
- :form form}
- [:div.fields-row
- [:& fm/input {:name :fullname
- :label (tr "auth.fullname")
- :type "text"}]]
-
- (when (contains? cf/flags :terms-and-privacy-checkbox)
- [:div.fields-row.input-visible.accept-terms-and-privacy-wrapper
+ (when (contains? cf/flags :terms-and-privacy-checkbox)
+ (let [terms-label
+ (mf/html
+ [:& tr-html
+ {:tag-name "div"
+ :label "auth.terms-privacy-agreement-md"
+ :params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
+ [:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class "check-primary"
- :type "checkbox"}
- [:span
- (tr "auth.terms-privacy-agreement")]]
- [:div.auth-links
- [:a {:href "https://penpot.app/terms" :target "_blank"} (tr "auth.terms-of-service")]
- [:span ",\u00A0"]
- [:a {:href "https://penpot.app/privacy" :target "_blank"} (tr "auth.privacy-policy")]]])
+ :type "checkbox"
+ :label terms-label}]]))
- [:> fm/submit-button*
- {:label (tr "auth.register-submit")
- :disabled @submitted?}]])))
+ [:> fm/submit-button*
+ {:label (tr "auth.register-submit")
+ :disabled @submitted?
+ :class (stl/css :register-btn)}]]))
(mf/defc register-validate-page
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :auth-form)}
- [:h1 {:class (stl/css :auth-title)
- :data-test "register-title"} (tr "auth.register-title")]
- [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
+ [:div {:class (stl/css :auth-form)}
+ [:h1 {:class (stl/css :auth-title)
+ :data-test "register-title"} (tr "auth.register-title")]
+ [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
- [:hr {:class (stl/css :separator)}]
+ [:hr {:class (stl/css :separator)}]
- [:& register-validate-form {:params params}]
+ [:& register-validate-form {:params params}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-entry :go-back)}
- [:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
- (tr "labels.go-back")]]]]
-
- ;; OLD
- [:div.form-container
- [:h1 {:data-test "register-title"} (tr "auth.register-title")]
- [:div.subtitle (tr "auth.register-subtitle")]
-
- [:& register-validate-form {:params params}]
-
- [:div.links
- [:div.link-entry
- [:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
- (tr "labels.go-back")]]]])))
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-entry :go-back)}
+ [:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
+ (tr "labels.go-back")]]]])
(mf/defc register-success-page
[{:keys [params] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :auth-form :register-success)}
- [:div {:class (stl/css :notification-icon)} i/icon-verify]
- [:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]
- [:div {:class (stl/css :notification-text-email)} (:email params "")]
- [:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]]
-
- ;; OLD
- [:div.form-container
- [:div.notification-icon i/icon-verify]
- [:div.notification-text (tr "auth.verification-email-sent")]
- [:div.notification-text-email (:email params "")]
- [:div.notification-text (tr "auth.check-your-email")]])))
+ [:div {:class (stl/css :auth-form :register-success)}
+ [:div {:class (stl/css :notification-icon)} i/icon-verify]
+ [:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]
+ [:div {:class (stl/css :notification-text-email)} (:email params "")]
+ [:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]])
diff --git a/frontend/src/app/main/ui/auth/verify_token.cljs b/frontend/src/app/main/ui/auth/verify_token.cljs
index db8f7745ac..e0dcd7cfed 100644
--- a/frontend/src/app/main/ui/auth/verify_token.cljs
+++ b/frontend/src/app/main/ui/auth/verify_token.cljs
@@ -11,7 +11,6 @@
[app.main.data.users :as du]
[app.main.repo :as rp]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.static :as static]
[app.util.dom :as dom]
@@ -62,8 +61,7 @@
(mf/defc verify-token
[{:keys [route] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- token (get-in route [:query-params :token])
+ (let [token (get-in route [:query-params :token])
bad-token (mf/use-state false)]
(mf/with-effect []
@@ -96,6 +94,5 @@
(if @bad-token
[:> static/invalid-token {}]
- [:div {:class (stl/css-case :verify-token new-css-system
- :global/verify-token (not new-css-system))}
+ [:div {:class (stl/css :verify-token)}
i/loader-pencil])))
diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs
index 7d053ab1eb..2e2c359b0b 100644
--- a/frontend/src/app/main/ui/comments.cljs
+++ b/frontend/src/app/main/ui/comments.cljs
@@ -18,7 +18,6 @@
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -81,20 +80,18 @@
(set! (.-height (.-style node)) "0")
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px")))))
- [:textarea
- {:ref local-ref
- :auto-focus autofocus?
- :on-key-down on-key-down
- :on-focus on-focus*
- :on-blur on-blur
- :value value
- :placeholder placeholder
- :on-change on-change*}]))
+ [:textarea {:ref local-ref
+ :auto-focus autofocus?
+ :on-key-down on-key-down
+ :on-focus on-focus*
+ :on-blur on-blur
+ :value value
+ :placeholder placeholder
+ :on-change on-change*}]))
(mf/defc reply-form
[{:keys [thread] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- show-buttons? (mf/use-state false)
+ (let [show-buttons? (mf/use-state false)
content (mf/use-state "")
disabled? (or (fm/all-spaces? @content)
@@ -123,54 +120,32 @@
(fn []
(st/emit! (dcm/add-comment thread @content))
(on-cancel)))]
- (if new-css-system
- [:div {:class (stl/css :reply-form)}
- [:& resizing-textarea {:value @content
- :placeholder "Reply"
- :on-blur on-blur
- :on-focus on-focus
- :select-on-focus? false
- :on-ctrl-enter on-submit
- :on-change on-change}]
- (when (or @show-buttons? (seq @content))
- [:div {:class (stl/css :buttons-wrapper)}
- [:input.btn-secondary
- {:type "button"
- :class (stl/css :cancel-btn)
- :value "Cancel"
- :on-click on-cancel}]
- [:input
- {:type "button"
- :class (stl/css-case :post-btn true
- :global/disabled disabled?)
- :value "Post"
- :on-click on-submit
- :disabled disabled?}]])]
-
-
- [:div.reply-form
- [:& resizing-textarea {:value @content
- :placeholder "Reply"
- :on-blur on-blur
- :on-focus on-focus
- :on-ctrl-enter on-submit
- :on-change on-change}]
- (when (or @show-buttons? (seq @content))
- [:div.buttons
- [:input.btn-primary
- {:type "button"
- :value "Post"
- :on-click on-submit
- :disabled disabled?}]
- [:input.btn-secondary
- {:type "button"
- :value "Cancel"
- :on-click on-cancel}]])])))
+ [:div {:class (stl/css :reply-form)}
+ [:& resizing-textarea {:value @content
+ :placeholder "Reply"
+ :on-blur on-blur
+ :on-focus on-focus
+ :select-on-focus? false
+ :on-ctrl-enter on-submit
+ :on-change on-change}]
+ (when (or @show-buttons? (seq @content))
+ [:div {:class (stl/css :buttons-wrapper)}
+ [:input.btn-secondary
+ {:type "button"
+ :class (stl/css :cancel-btn)
+ :value "Cancel"
+ :on-click on-cancel}]
+ [:input
+ {:type "button"
+ :class (stl/css-case :post-btn true
+ :global/disabled disabled?)
+ :value "Post"
+ :on-click on-submit
+ :disabled disabled?}]])]))
(mf/defc draft-thread
[{:keys [draft zoom on-cancel on-submit position-modifier]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- position (cond-> (:position draft)
+ (let [position (cond-> (:position draft)
(some? position-modifier)
(gpt/transform position-modifier))
content (:content draft)
@@ -201,73 +176,42 @@
(mf/deps draft)
(partial on-submit draft))]
+ [:*
+ [:div
+ {:class (stl/css :floating-thread-bubble)
+ :style {:top (str pos-y "px")
+ :left (str pos-x "px")}
+ :on-click dom/stop-propagation}
+ "?"]
+ [:div {:class (stl/css :thread-content)
+ :style {:top (str (- pos-y 24) "px")
+ :left (str (+ pos-x 28) "px")}
+ :on-click dom/stop-propagation}
+ [:div {:class (stl/css :reply-form)}
+ [:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
+ :value (or content "")
+ :autofocus true
+ :select-on-focus? false
+ :on-esc on-esc
+ :on-change on-change
+ :on-ctrl-enter on-submit}]
+ [:div {:class (stl/css :buttons-wrapper)}
- (if new-css-system
- [:*
- [:div
- {:class (stl/css :floating-thread-bubble)
- :style {:top (str pos-y "px")
- :left (str pos-x "px")}
- :on-click dom/stop-propagation}
- "?"]
- [:div {:class (stl/css :thread-content)
- :style {:top (str (- pos-y 24) "px")
- :left (str (+ pos-x 28) "px")}
- :on-click dom/stop-propagation}
- [:div {:class (stl/css :reply-form)}
- [:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
- :value (or content "")
- :autofocus true
- :select-on-focus? false
- :on-esc on-esc
- :on-change on-change
- :on-ctrl-enter on-submit}]
- [:div {:class (stl/css :buttons-wrapper)}
+ [:input {:on-click on-esc
+ :class (stl/css :cancel-btn)
+ :type "button"
+ :value "Cancel"}]
- [:input {:on-click on-esc
- :class (stl/css :cancel-btn)
- :type "button"
- :value "Cancel"}]
-
- [:input {:on-click on-submit
- :type "button"
- :value "Post"
- :class (stl/css-case :post-btn true
- :global/disabled disabled?)
- :disabled disabled?}]]]]]
-
- [:*
- [:div.thread-bubble
- {:style {:top (str pos-y "px")
- :left (str pos-x "px")}
- :on-click dom/stop-propagation}
- [:span "?"]]
- [:div.thread-content
- {:style {:top (str (- pos-y 14) "px")
- :left (str (+ pos-x 14) "px")}
- :on-click dom/stop-propagation}
- [:div.reply-form
- [:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
- :value (or content "")
- :autofocus true
- :on-esc on-esc
- :on-ctrl-enter on-submit
- :on-change on-change}]
- [:div.buttons
- [:input.btn-primary
- {:on-click on-submit
- :type "button"
- :value "Post"
- :disabled disabled?}]
- [:input.btn-secondary
- {:on-click on-esc
- :type "button"
- :value "Cancel"}]]]]])))
+ [:input {:on-click on-submit
+ :type "button"
+ :value "Post"
+ :class (stl/css-case :post-btn true
+ :global/disabled disabled?)
+ :disabled disabled?}]]]]]))
(mf/defc edit-form
[{:keys [content on-submit on-cancel] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- content (mf/use-state content)
+ (let [content (mf/use-state content)
on-change
(mf/use-fn
@@ -281,44 +225,28 @@
disabled? (or (fm/all-spaces? @content)
(str/empty-or-nil? @content))]
- (if new-css-system
- [:div {:class (stl/css :edit-form)}
- [:& resizing-textarea {:value @content
- :autofocus true
- :select-on-focus true
- :select-on-focus? false
- :on-ctrl-enter on-submit*
- :on-change on-change}]
- [:div {:class (stl/css :buttons-wrapper)}
- [:input {:type "button"
- :value "Cancel"
- :class (stl/css :cancel-btn)
- :on-click on-cancel}]
- [:input {:type "button"
- :class (stl/css-case :post-btn true
- :global/disabled disabled?)
- :value "Post"
- :on-click on-submit*
- :disabled disabled?}]]]
-
-
- [:div.reply-form.edit-form
- [:& resizing-textarea {:value @content
- :autofocus true
- :select-on-focus true
- :on-ctrl-enter on-submit*
- :on-change on-change}]
- [:div.buttons
- [:input.btn-primary {:type "button"
- :value "Post"
- :on-click on-submit*
- :disabled disabled?}]
- [:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]]])))
+ [:div {:class (stl/css :edit-form)}
+ [:& resizing-textarea {:value @content
+ :autofocus true
+ :select-on-focus true
+ :select-on-focus? false
+ :on-ctrl-enter on-submit*
+ :on-change on-change}]
+ [:div {:class (stl/css :buttons-wrapper)}
+ [:input {:type "button"
+ :value "Cancel"
+ :class (stl/css :cancel-btn)
+ :on-click on-cancel}]
+ [:input {:type "button"
+ :class (stl/css-case :post-btn true
+ :global/disabled disabled?)
+ :value "Post"
+ :on-click on-submit*
+ :disabled disabled?}]]]))
(mf/defc comment-item
[{:keys [comment thread users origin] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- owner (get users (:owner-id comment))
+ (let [owner (get users (:owner-id comment))
profile (mf/deref refs/profile)
options (mf/use-state false)
edition? (mf/use-state false)
@@ -382,82 +310,46 @@
(dom/stop-propagation event)
(st/emit! (dcm/update-comment-thread (update thread :is-resolved not)))))]
- (if new-css-system
- [:div {:class (stl/css :comment-container)}
- [:div {:class (stl/css :comment)}
- [:div {:class (stl/css :author)}
- [:div {:class (stl/css :avatar)}
- [:img {:src (cfg/resolve-profile-photo-url owner)}]]
- [:div {:class (stl/css :name)}
- [:div {:class (stl/css :fullname)} (:fullname owner)]
- [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]]
+ [:div {:class (stl/css :comment-container)}
+ [:div {:class (stl/css :comment)}
+ [:div {:class (stl/css :author)}
+ [:div {:class (stl/css :avatar)}
+ [:img {:src (cfg/resolve-profile-photo-url owner)}]]
+ [:div {:class (stl/css :name)}
+ [:div {:class (stl/css :fullname)} (:fullname owner)]
+ [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]]
- (when (some? thread)
- [:div {:class (stl/css :options-resolve-wrapper)
- :on-click toggle-resolved}
- [:span {:class (stl/css-case :options-resolve true
- :global/checked (:is-resolved thread))} i/tick-refactor]])
+ (when (some? thread)
+ [:div {:class (stl/css :options-resolve-wrapper)
+ :on-click toggle-resolved}
+ [:span {:class (stl/css-case :options-resolve true
+ :global/checked (:is-resolved thread))} i/tick-refactor]])
- (when (= (:id profile) (:id owner))
- [:div {:class (stl/css :options)
- :on-click on-toggle-options}
- i/menu-refactor])]
+ (when (= (:id profile) (:id owner))
+ [:div {:class (stl/css :options)
+ :on-click on-toggle-options}
+ i/menu-refactor])]
- [:div {:class (stl/css :content)}
- (if @edition?
- [:& edit-form {:content (:content comment)
- :on-submit on-submit
- :on-cancel on-cancel}]
- [:span {:class (stl/css :text)} (:content comment)])]]
+ [:div {:class (stl/css :content)}
+ (if @edition?
+ [:& edit-form {:content (:content comment)
+ :on-submit on-submit
+ :on-cancel on-cancel}]
+ [:span {:class (stl/css :text)} (:content comment)])]]
- [:& dropdown {:show @options
- :on-close on-hide-options}
- [:ul {:class (stl/css :comment-options-dropdown)}
+ [:& dropdown {:show @options
+ :on-close on-hide-options}
+ [:ul {:class (stl/css :comment-options-dropdown)}
+ [:li {:class (stl/css :context-menu-option)
+ :on-click on-edit-clicked}
+ (tr "labels.edit")]
+ (if thread
[:li {:class (stl/css :context-menu-option)
- :on-click on-edit-clicked}
- (tr "labels.edit")]
- (if thread
- [:li {:class (stl/css :context-menu-option)
- :on-click on-delete-thread}
- (tr "labels.delete-comment-thread")]
- [:li {:class (stl/css :context-menu-option)
- :on-click on-delete-comment}
- (tr "labels.delete-comment")])]]]
-
-
- [:div.comment-container
- [:div.comment
- [:div.author
- [:div.avatar
- [:img {:src (cfg/resolve-profile-photo-url owner)}]]
- [:div.name
- [:div.fullname (:fullname owner)]
- [:div.timeago (dt/timeago (:modified-at comment))]]
-
- (when (some? thread)
- [:div.options-resolve {:on-click toggle-resolved}
- (if (:is-resolved thread)
- [:span i/checkbox-checked]
- [:span i/checkbox-unchecked])])
-
- (when (= (:id profile) (:id owner))
- [:div.options
- [:div.options-icon {:on-click on-toggle-options} i/actions]])]
-
- [:div.content
- (if @edition?
- [:& edit-form {:content (:content comment)
- :on-submit on-submit
- :on-cancel on-cancel}]
- [:span.text (:content comment)])]]
-
- [:& dropdown {:show @options
- :on-close on-hide-options}
- [:ul.dropdown.comment-options-dropdown
- [:li {:on-click on-edit-clicked} (tr "labels.edit")]
- (if thread
- [:li {:on-click on-delete-thread} (tr "labels.delete-comment-thread")]
- [:li {:on-click on-delete-comment} (tr "labels.delete-comment")])]]])))
+ :on-click on-delete-thread}
+ (tr "labels.delete-comment-thread")]
+ [:li {:class (stl/css :context-menu-option)
+ :on-click on-delete-comment}
+ (tr "labels.delete-comment")])]]]))
(defn make-comments-ref
[thread-id]
@@ -466,8 +358,7 @@
(mf/defc thread-comments
{::mf/wrap [mf/memo]}
[{:keys [thread zoom users origin position-modifier]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- ref (mf/use-ref)
+ (let [ref (mf/use-ref)
thread-id (:id thread)
@@ -477,12 +368,8 @@
(some? position-modifier)
(gpt/transform position-modifier))
- pos-x (if new-css-system
- (+ (* (:x pos) zoom) 24)
- (+ (* (:x pos) zoom) 14))
- pos-y (if new-css-system
- (- (* (:y pos) zoom) 28)
- (- (* (:y pos) zoom) 14))
+ pos-x (+ (* (:x pos) zoom) 24)
+ pos-y (- (* (:y pos) zoom) 28)
comments-ref (mf/with-memo [thread-id]
@@ -504,46 +391,24 @@
(mf/with-layout-effect [thread-pos comments-map]
(when-let [node (mf/ref-val ref)]
(dom/scroll-into-view-if-needed! node)))
- (if new-css-system
- (when (some? comment)
- [:div {:class (stl/css :thread-content)
- :style {:top (str pos-y "px")
- :left (str pos-x "px")}
- :on-click dom/stop-propagation}
+ (when (some? comment)
+ [:div {:class (stl/css :thread-content)
+ :style {:top (str pos-y "px")
+ :left (str pos-x "px")}
+ :on-click dom/stop-propagation}
- [:div {:class (stl/css :comments)}
- [:& comment-item {:comment comment
- :users users
- :thread thread
- :origin origin}]
- (for [item (rest comments)]
- [:* {:key (dm/str (:id item))}
- [:& comment-item {:comment item
- :users users
- :origin origin}]])
- [:div {:ref ref}]]
- [:& reply-form {:thread thread}]])
-
-
- (when (some? comment)
- [:div.thread-content
- {:style {:top (str pos-y "px")
- :left (str pos-x "px")}
- :on-click dom/stop-propagation}
-
- [:div.comments
- [:& comment-item {:comment comment
- :users users
- :thread thread
- :origin origin}]
- (for [item (rest comments)]
- [:* {:key (dm/str (:id item))}
- [:hr]
- [:& comment-item {:comment item
- :users users
- :origin origin}]])
- [:div {:ref ref}]]
- [:& reply-form {:thread thread}]]))))
+ [:div {:class (stl/css :comments)}
+ [:& comment-item {:comment comment
+ :users users
+ :thread thread
+ :origin origin}]
+ (for [item (rest comments)]
+ [:* {:key (dm/str (:id item))}
+ [:& comment-item {:comment item
+ :users users
+ :origin origin}]])
+ [:div {:ref ref}]]
+ [:& reply-form {:thread thread}]])))
(defn use-buble
[zoom {:keys [position frame-id]}]
@@ -602,8 +467,7 @@
(mf/defc thread-bubble
{::mf/wrap [mf/memo]}
[{:keys [thread zoom open? on-click origin position-modifier]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- pos (cond-> (:position thread)
+ (let [pos (cond-> (:position thread)
(some? position-modifier)
(gpt/transform position-modifier))
@@ -658,37 +522,22 @@
(dom/stop-propagation event)
(when (= origin :viewer)
(on-click thread))))]
- (if new-css-system
- [:div {:style {:top (str pos-y "px")
- :left (str pos-x "px")}
- :on-pointer-down on-pointer-down*
- :on-pointer-up on-pointer-up*
- :on-pointer-move on-pointer-move*
- :on-click on-click*
- :on-lost-pointer-capture on-lost-pointer-capture
- :class (stl/css-case
- :floating-thread-bubble true
- :resolved (:is-resolved thread)
- :unread (pos? (:count-unread-comments thread)))}
- [:span (:seqn thread)]]
-
- [:div.thread-bubble
- {:style {:top (str pos-y "px")
- :left (str pos-x "px")}
- :on-pointer-down on-pointer-down*
- :on-pointer-up on-pointer-up*
- :on-pointer-move on-pointer-move*
- :on-click on-click*
- :on-lost-pointer-capture on-lost-pointer-capture
- :class (dom/classnames
- :resolved (:is-resolved thread)
- :unread (pos? (:count-unread-comments thread)))}
- [:span (:seqn thread)]])))
+ [:div {:style {:top (str pos-y "px")
+ :left (str pos-x "px")}
+ :on-pointer-down on-pointer-down*
+ :on-pointer-up on-pointer-up*
+ :on-pointer-move on-pointer-move*
+ :on-click on-click*
+ :on-lost-pointer-capture on-lost-pointer-capture
+ :class (stl/css-case
+ :floating-thread-bubble true
+ :resolved (:is-resolved thread)
+ :unread (pos? (:count-unread-comments thread)))}
+ [:span (:seqn thread)]]))
(mf/defc comment-thread
[{:keys [item users on-click]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- owner (get users (:owner-id item))
+ (let [owner (get users (:owner-id item))
on-click*
(mf/use-fn
(mf/deps item)
@@ -698,99 +547,50 @@
(when (fn? on-click)
(on-click item))))]
- (if new-css-system
- [:div {:class (stl/css :comment)
- :on-click on-click*}
- [:div {:class (stl/css :author)}
- [:div {:class (stl/css-case :thread-bubble true
- :resolved (:is-resolved item)
- :unread (pos? (:count-unread-comments item)))}
- (:seqn item)]
- [:div {:class (stl/css :avatar)}
- [:img {:src (cfg/resolve-profile-photo-url owner)}]]
- [:div {:class (stl/css :name)}
- [:div {:class (stl/css :fullname)} (:fullname owner)]
- [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]]
- [:div {:class (stl/css :content)}
- (:content item)]
- [:div {:class (stl/css :replies)}
- (let [unread (:count-unread-comments item ::none)
- total (:count-comments item 1)]
- [:*
- (when (> total 1)
- (if (= total 2)
- [:span {:class (stl/css :total-replies)} "1 reply"]
- [:span {:class (stl/css :total-replies)} (str (dec total) " replies")]))
+ [:div {:class (stl/css :comment)
+ :on-click on-click*}
+ [:div {:class (stl/css :author)}
+ [:div {:class (stl/css-case :thread-bubble true
+ :resolved (:is-resolved item)
+ :unread (pos? (:count-unread-comments item)))}
+ (:seqn item)]
+ [:div {:class (stl/css :avatar)}
+ [:img {:src (cfg/resolve-profile-photo-url owner)}]]
+ [:div {:class (stl/css :name)}
+ [:div {:class (stl/css :fullname)} (:fullname owner)]
+ [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]]
+ [:div {:class (stl/css :content)}
+ (:content item)]
+ [:div {:class (stl/css :replies)}
+ (let [unread (:count-unread-comments item ::none)
+ total (:count-comments item 1)]
+ [:*
+ (when (> total 1)
+ (if (= total 2)
+ [:span {:class (stl/css :total-replies)} "1 reply"]
+ [:span {:class (stl/css :total-replies)} (str (dec total) " replies")]))
- (when (and (> total 1) (> unread 0))
- (if (= unread 1)
- [:span {:class (stl/css :new-replies)} "1 new reply"]
- [:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]
-
-
- [:div.comment {:on-click on-click*}
- [:div.author
- [:div.thread-bubble
- {:class (dom/classnames
- :resolved (:is-resolved item)
- :unread (pos? (:count-unread-comments item)))}
- (:seqn item)]
- [:div.avatar
- [:img {:src (cfg/resolve-profile-photo-url owner)}]]
- [:div.name
- [:div.fullname (:fullname owner) ", "]
- [:div.timeago (dt/timeago (:modified-at item))]]]
- [:div.content
- [:span.text (:content item)]]
- [:div.content.replies
- (let [unread (:count-unread-comments item ::none)
- total (:count-comments item 1)]
- [:*
- (when (> total 1)
- (if (= total 2)
- [:span.total-replies "1 reply"]
- [:span.total-replies (str (dec total) " replies")]))
-
- (when (and (> total 1) (> unread 0))
- (if (= unread 1)
- [:span.new-replies "1 new reply"]
- [:span.new-replies (str unread " new replies")]))])]])))
+ (when (and (> total 1) (> unread 0))
+ (if (= unread 1)
+ [:span {:class (stl/css :new-replies)} "1 new reply"]
+ [:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]))
(mf/defc comment-thread-group
[{:keys [group users on-thread-click]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :thread-group)}
- (if (:file-name group)
- [:div {:class (stl/css :section-title)}
- [:span {:class (stl/css :file-name)} (:file-name group) ", "]
- [:span {:class (stl/css :page-name)} (:page-name group)]]
+ [:div {:class (stl/css :thread-group)}
+ (if (:file-name group)
+ [:div {:class (stl/css :section-title)}
+ [:span {:class (stl/css :file-name)} (:file-name group) ", "]
+ [:span {:class (stl/css :page-name)} (:page-name group)]]
- [:div {:class (stl/css :section-title)}
- [:span {:class (stl/css :icon)} i/document-refactor]
- [:span {:class (stl/css :page-name)} (:page-name group)]])
+ [:div {:class (stl/css :section-title)}
+ [:span {:class (stl/css :icon)} i/document-refactor]
+ [:span {:class (stl/css :page-name)} (:page-name group)]])
- [:div {:class (stl/css :threads)}
- (for [item (:items group)]
- [:& comment-thread
- {:item item
- :on-click on-thread-click
- :users users
- :key (:id item)}])]]
-
-
- [:div.thread-group
- (if (:file-name group)
- [:div.section-title
- [:span.label.filename (:file-name group) ", "]
- [:span.label (:page-name group)]]
- [:div.section-title
- [:span.icon i/file-html]
- [:span.label (:page-name group)]])
- [:div.threads
- (for [item (:items group)]
- [:& comment-thread
- {:item item
- :on-click on-thread-click
- :users users
- :key (:id item)}])]])))
+ [:div {:class (stl/css :threads)}
+ (for [item (:items group)]
+ [:& comment-thread
+ {:item item
+ :on-click on-thread-click
+ :users users
+ :key (:id item)}])]])
diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss
index 89fc247d70..874a229ad3 100644
--- a/frontend/src/app/main/ui/comments.scss
+++ b/frontend/src/app/main/ui/comments.scss
@@ -13,96 +13,106 @@
border-radius: $br-8;
padding: $s-8 $s-16;
- .section-title {
- @include titleTipography;
- height: $s-32;
- display: flex;
- align-items: center;
- margin-bottom: $s-8;
- .file-name {
- color: var(--comment-subtitle-color);
- }
- .page-name {
- color: var(--comment-subtitle-color);
- }
- .icon {
- display: flex;
- align-items: center;
- padding: 0 $s-6 0 $s-4;
- width: $s-24;
- height: $s-32;
- margin-left: $s-6;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
- }
- .threads {
- display: flex;
- flex-direction: column;
- gap: $s-24;
- }
-
&:hover {
background: $db-primary;
}
}
+.section-title {
+ @include titleTipography;
+ height: $s-32;
+ display: flex;
+ align-items: center;
+ margin-bottom: $s-8;
+}
+
+.file-name {
+ color: var(--comment-subtitle-color);
+}
+
+.page-name {
+ color: var(--comment-subtitle-color);
+}
+
+.icon {
+ display: flex;
+ align-items: center;
+ padding: 0 $s-6 0 $s-4;
+ width: $s-24;
+ height: $s-32;
+ margin-left: $s-6;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--icon-foreground);
+ }
+}
+
+.threads {
+ display: flex;
+ flex-direction: column;
+ gap: $s-24;
+}
+
// Comment-thread
.comment {
@include titleTipography;
display: flex;
flex-direction: column;
gap: $s-12;
- .author {
- display: flex;
- gap: $s-8;
- .thread-bubble {
- @extend .comment-bubbles;
- &.resolved {
- @extend .resolved-comment-bubble;
- }
- &.unread {
- @extend .unread-comment-bubble;
- }
- }
- .avatar {
- height: $s-32;
- width: $s-32;
- border-radius: $br-circle;
- img {
- border-radius: $br-circle;
- }
- }
- .name {
- flex-grow: 1;
- .fullname {
- @include textEllipsis;
- color: var(--comment-title-color);
- }
- .timeago {
- @include textEllipsis;
- color: var(--comment-subtitle-color);
- }
- }
+}
+
+.author {
+ display: flex;
+ gap: $s-8;
+}
+
+.thread-bubble {
+ @extend .comment-bubbles;
+ &.resolved {
+ @extend .resolved-comment-bubble;
}
- .content {
- @include titleTipography;
- color: var(--color-foreground-primary);
- }
- .replies {
- display: flex;
- gap: $s-8;
- .total-replies {
- color: var(--color-foreground-secondary);
- }
- .new-replies {
- color: var(--color-accent-primary);
- }
+ &.unread {
+ @extend .unread-comment-bubble;
}
}
+.avatar {
+ height: $s-32;
+ width: $s-32;
+ border-radius: $br-circle;
+ img {
+ border-radius: $br-circle;
+ }
+}
+
+.name {
+ flex-grow: 1;
+ .fullname {
+ @include textEllipsis;
+ color: var(--comment-title-color);
+ }
+ .timeago {
+ @include textEllipsis;
+ color: var(--comment-subtitle-color);
+ }
+}
+
+.content {
+ @include titleTipography;
+ color: var(--color-foreground-primary);
+}
+
+.replies {
+ display: flex;
+ gap: $s-8;
+}
+
+.total-replies {
+ color: var(--color-foreground-secondary);
+}
+.new-replies {
+ color: var(--color-accent-primary);
+}
// Thread-bubble
.floating-thread-bubble {
diff --git a/frontend/src/app/main/ui/components/code_block.cljs b/frontend/src/app/main/ui/components/code_block.cljs
index d6d81f8495..b766772344 100644
--- a/frontend/src/app/main/ui/components/code_block.cljs
+++ b/frontend/src/app/main/ui/components/code_block.cljs
@@ -8,7 +8,6 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
- [app.main.ui.context :as ctx]
[cuerdas.core :as str]
[promesa.core :as p]
[rumext.v2 :as mf]
@@ -20,8 +19,7 @@
(mf/defc code-block
{::mf/wrap-props false}
[{:keys [code type]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- block-ref (mf/use-ref)
+ (let [block-ref (mf/use-ref)
code (str/trim code)]
(mf/with-effect [code type]
@@ -29,7 +27,5 @@
(p/let [highlight-fn (lazy/load highlight-fn)]
(highlight-fn node))))
- (if new-css-system
- [:pre {:class (dm/str type " " (stl/css :code-display)) :ref block-ref} code]
- [:pre {:class (dm/str type " " "code-display") :ref block-ref} code])))
+ [:pre {:class (dm/str type " " (stl/css :code-display)) :ref block-ref} code]))
diff --git a/frontend/src/app/main/ui/components/color_bullet_new.cljs b/frontend/src/app/main/ui/components/color_bullet_new.cljs
index 6af3f502b4..f15f3549c8 100644
--- a/frontend/src/app/main/ui/components/color_bullet_new.cljs
+++ b/frontend/src/app/main/ui/components/color_bullet_new.cljs
@@ -75,5 +75,5 @@
:on-click on-click
:on-double-click on-double-click}
(if (some? image)
- (tr "media.image")
+ (or name (tr "media.image"))
(or name color (uc/gradient-type->string (:type gradient))))])))
diff --git a/frontend/src/app/main/ui/components/context_menu_a11y.cljs b/frontend/src/app/main/ui/components/context_menu_a11y.cljs
index 1b8bc1c610..e6a230bf58 100644
--- a/frontend/src/app/main/ui/components/context_menu_a11y.cljs
+++ b/frontend/src/app/main/ui/components/context_menu_a11y.cljs
@@ -11,7 +11,6 @@
[app.common.data.macros :as dm]
[app.main.refs :as refs]
[app.main.ui.components.dropdown :refer [dropdown']]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -68,7 +67,6 @@
min-width? (gobj/get props "min-width?" false)
origin (gobj/get props "origin")
route (mf/deref refs/route)
- new-css-system (mf/use-ctx ctx/new-css-system)
in-dashboard? (= :dashboard-projects (:name (:data route)))
local (mf/use-state {:offset-y 0
:offset-x 0
@@ -191,149 +189,79 @@
(tm/schedule-on-idle
#(dom/focus! (dom/get-element (first ids)))))
- (if new-css-system
- (when (and open? (some? (:levels @local)))
- [:> dropdown' props
- (let [level (-> @local :levels peek)
- original-options (:options level)
- parent-original (:parent-option level)]
- [:div {:class (stl/css-case :is-selectable is-selectable
- :context-menu true
- :is-open open?
- :fixed fixed?)
- :style {:top (+ top (:offset-y @local))
- :left (+ left (:offset-x @local))}
- :on-key-down (on-key-down original-options parent-original)}
- (let [level (-> @local :levels peek)]
- [:ul {:class (stl/css-case :min-width min-width?
- :context-menu-items true)
- :role "menu"
- :ref check-menu-offscreen}
- (when-let [parent-option (:parent-option level)]
- [:*
- [:& context-menu-a11y-item
- {:id "go-back-sub-option"
- :class (stl/css :context-menu-item)
- :tab-index "0"
- :on-key-down (fn [event]
- (dom/prevent-default event))}
- [:button {:class (stl/css :context-menu-action :submenu-back)
+ (when (and open? (some? (:levels @local)))
+ [:> dropdown' props
+ (let [level (-> @local :levels peek)
+ original-options (:options level)
+ parent-original (:parent-option level)]
+ [:div {:class (stl/css-case :is-selectable is-selectable
+ :context-menu true
+ :is-open open?
+ :fixed fixed?)
+ :style {:top (+ top (:offset-y @local))
+ :left (+ left (:offset-x @local))}
+ :on-key-down (on-key-down original-options parent-original)}
+ (let [level (-> @local :levels peek)]
+ [:ul {:class (stl/css-case :min-width min-width?
+ :context-menu-items true)
+ :role "menu"
+ :ref check-menu-offscreen}
+ (when-let [parent-option (:parent-option level)]
+ [:*
+ [:& context-menu-a11y-item
+ {:id "go-back-sub-option"
+ :class (stl/css :context-menu-item)
+ :tab-index "0"
+ :on-key-down (fn [event]
+ (dom/prevent-default event))}
+ [:button {:class (stl/css :context-menu-action :submenu-back)
+ :data-no-close true
+ :on-click exit-submenu}
+ [:span {:class (stl/css :submenu-icon-back)} i/arrow-refactor]
+ parent-option]]
+
+ [:li {:class (stl/css :separator)}]])
+
+ (for [[index option] (d/enumerate (:options level))]
+ (let [option-name (:option-name option)
+ id (:id option)
+ sub-options (:sub-options option)
+ option-handler (:option-handler option)
+ data-test (:data-test option)]
+ (when option-name
+ (if (= option-name :separator)
+ [:li {:key (dm/str "context-item-" index)
+ :class (stl/css :separator)}]
+ [:& context-menu-a11y-item
+ {:id id
+ :key id
+ :class (stl/css-case
+ :is-selected (and selected (= option-name selected))
+ :selected (and selected (= data-test selected))
+ :context-menu-item true)
+ :key-index (dm/str "context-item-" index)
+ :tab-index "0"
+ :on-key-down (fn [event]
+ (dom/prevent-default event))}
+ (if-not sub-options
+ [:a {:class (stl/css :context-menu-action)
+ :on-click #(do (dom/stop-propagation %)
+ (on-close)
+ (option-handler %))
+ :data-test data-test}
+ (if (and in-dashboard? (= option-name "Default"))
+ (tr "dashboard.default-team-name")
+ option-name)
+
+ (when (and selected (= data-test selected))
+ [:span {:class (stl/css :selected-icon)} i/tick-refactor])]
+
+ [:a {:class (stl/css :context-menu-action :submenu)
:data-no-close true
- :on-click exit-submenu}
- [:span {:class (stl/css :submenu-icon-back)} i/arrow-refactor]
- parent-option]]
-
- [:li {:class (stl/css :separator)}]])
-
- (for [[index option] (d/enumerate (:options level))]
- (let [option-name (:option-name option)
- id (:id option)
- sub-options (:sub-options option)
- option-handler (:option-handler option)
- data-test (:data-test option)]
- (when option-name
- (if (= option-name :separator)
- [:li {:key (dm/str "context-item-" index)
- :class (stl/css :separator)}]
- [:& context-menu-a11y-item
- {:id id
- :key id
- :class (stl/css-case
- :is-selected (and selected (= option-name selected))
- :selected (and selected (= data-test selected))
- :context-menu-item true)
- :key-index (dm/str "context-item-" index)
- :tab-index "0"
- :on-key-down (fn [event]
- (dom/prevent-default event))}
- (if-not sub-options
- [:a {:class (stl/css :context-menu-action)
- :on-click #(do (dom/stop-propagation %)
- (on-close)
- (option-handler %))
- :data-test data-test}
- (if (and in-dashboard? (= option-name "Default"))
- (tr "dashboard.default-team-name")
- option-name)
-
- (when (and selected (= data-test selected))
- [:span {:class (stl/css :selected-icon)} i/tick-refactor])]
-
- [:a {:class (stl/css :context-menu-action :submenu)
- :data-no-close true
- :on-click (enter-submenu option-name sub-options)
- :data-test data-test}
- option-name
- [:span {:class (stl/css :submenu-icon)} i/arrow-refactor]])]))))])])])
-
- ;; OLD
- (when (and open? (some? (:levels @local)))
- [:> dropdown' props
-
- (let [level (-> @local :levels peek)
- original-options (:options level)
- parent-original (:parent-option level)]
- [:div {:class (dom/classnames :is-selectable is-selectable
- :context-menu true
- :is-open open?
- :fixed fixed?)
- :style {:top (+ top (:offset-y @local))
- :left (+ left (:offset-x @local))}
- :on-key-down (on-key-down original-options parent-original)}
- (let [level (-> @local :levels peek)]
- [:ul {:class (dom/classnames :min-width min-width?
- :context-menu-items true)
- :role "menu"
- :ref check-menu-offscreen}
- (when-let [parent-option (:parent-option level)]
- [:*
- [:& context-menu-a11y-item
- {:id "go-back-sub-option"
- :tab-index "0"
- :on-key-down (fn [event]
- (dom/prevent-default event))}
- [:div {:class (dom/classnames :context-menu-action true
- :submenu-back true)
- :data-no-close true
- :on-click exit-submenu}
- [:span i/arrow-slide]
-
- parent-option]]
-
- [:li.separator]])
-
- (for [[index option] (d/enumerate (:options level))]
- (let [option-name (:option-name option)
- id (:id option)
- sub-options (:sub-options option)
- option-handler (:option-handler option)
- data-test (:data-test option)]
- (when option-name
- (if (= option-name :separator)
- [:li.separator {:key (dm/str "context-item-" index)}]
- [:& context-menu-a11y-item
- {:id id
- :key id
- :class (dom/classnames :is-selected (and selected (= option-name selected)))
- :key-index (dm/str "context-item-" index)
- :tab-index "0"
- :on-key-down (fn [event]
- (dom/prevent-default event))}
- (if-not sub-options
- [:a {:class (dom/classnames :context-menu-action true)
- :on-click #(do (dom/stop-propagation %)
- (on-close)
- (option-handler %))
- :data-test data-test}
- (if (and in-dashboard? (= option-name "Default"))
- (tr "dashboard.default-team-name")
- option-name)]
- [:a.context-menu-action.submenu
- {:data-no-close true
- :on-click (enter-submenu option-name sub-options)
- :data-test data-test}
- option-name
- [:span i/arrow-slide]])]))))])])]))))
+ :on-click (enter-submenu option-name sub-options)
+ :data-test data-test}
+ option-name
+ [:span {:class (stl/css :submenu-icon)} i/arrow-refactor]])]))))])])])))
(mf/defc context-menu-a11y
{::mf/wrap-props false}
diff --git a/frontend/src/app/main/ui/components/file_uploader.cljs b/frontend/src/app/main/ui/components/file_uploader.cljs
index 71af00d4ed..35429e09ee 100644
--- a/frontend/src/app/main/ui/components/file_uploader.cljs
+++ b/frontend/src/app/main/ui/components/file_uploader.cljs
@@ -30,15 +30,14 @@
(when label-text
[:label {:for input-id :class-name label-class} label-text])
- [:input
- {:style {:display "none"
- :width 0}
- :id input-id
- :multiple multi
- :accept accept
- :type "file"
- :ref input-ref
- :on-change on-files-selected
- :data-test data-test
- :aria-label "uploader"}]]))
+ [:input {:style {:display "none"
+ :width 0}
+ :id input-id
+ :multiple multi
+ :accept accept
+ :type "file"
+ :ref input-ref
+ :on-change on-files-selected
+ :data-test data-test
+ :aria-label "uploader"}]]))
diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs
index 11b633cc86..70469c23a1 100644
--- a/frontend/src/app/main/ui/components/forms.cljs
+++ b/frontend/src/app/main/ui/components/forms.cljs
@@ -386,21 +386,19 @@
(mf/defc submit-button*
{::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (or (unchecked-get props "form")
+ (let [form (or (unchecked-get props "form")
(mf/use-ctx form-ctx))
label (unchecked-get props "label")
on-click (unchecked-get props "onClick")
children (unchecked-get props "children")
- class (d/nilv (unchecked-get props "className") "btn-primary btn-large")
+ class (unchecked-get props "className")
name (d/nilv (unchecked-get props "name") "submit")
disabled? (or (and (some? form) (not (:valid @form)))
(true? (unchecked-get props "disabled")))
- klass (dm/str class " " (if disabled? "btn-disabled" ""))
new-klass (dm/str class " " (if disabled? (stl/css :btn-disabled) ""))
on-key-down
@@ -416,7 +414,7 @@
(obj/set! "onKeyDown" on-key-down)
(obj/set! "name" name)
(obj/set! "label" mf/undefined)
- (obj/set! "className" (if new-css-system new-klass klass))
+ (obj/set! "className" new-klass)
(obj/set! "type" "submit"))]
[:> "button" props
diff --git a/frontend/src/app/main/ui/components/forms.scss b/frontend/src/app/main/ui/components/forms.scss
index e0d10993b5..ec64c521c8 100644
--- a/frontend/src/app/main/ui/components/forms.scss
+++ b/frontend/src/app/main/ui/components/forms.scss
@@ -24,7 +24,7 @@
cursor: pointer;
color: var(--modal-title-foreground-color);
text-transform: uppercase;
-
+ margin-bottom: $s-8;
input {
@extend .input-element;
color: var(--input-foreground-color-active);
@@ -143,6 +143,7 @@
.hint {
@include titleTipography;
+ color: var(--modal-text-foreground-color);
width: 99%;
}
diff --git a/frontend/src/app/main/ui/components/search_bar.cljs b/frontend/src/app/main/ui/components/search_bar.cljs
index 507b68d1e7..705bb3b4d7 100644
--- a/frontend/src/app/main/ui/components/search_bar.cljs
+++ b/frontend/src/app/main/ui/components/search_bar.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.components.search-bar
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.main.ui.icons :as i]
[app.util.dom :as dom]
@@ -45,16 +45,16 @@
node (dom/get-target event)]
(when ^boolean enter? (dom/blur! node))
(when ^boolean esc? (dom/blur! node)))))]
- [:span {:class (dom/classnames (css :search-box) true
- (css :has-children) (some? children))}
+ [:span {:class (stl/css-case :search-box true
+ :has-children (some? children))}
children
- [:div {:class (dom/classnames (css :search-input-wrapper) true)}
+ [:div {:class (stl/css :search-input-wrapper)}
icon
[:input {:on-change handle-change
:value value
:placeholder placeholder
:on-key-down handle-key-down}]
(when (not= "" value)
- [:button {:class (dom/classnames (css :clear) true)
+ [:button {:class (stl/css :clear)
:on-click handle-clear}
i/delete-text-refactor])]]))
diff --git a/frontend/src/app/main/ui/components/search_bar.scss b/frontend/src/app/main/ui/components/search_bar.scss
index 9f568ea286..850b8af221 100644
--- a/frontend/src/app/main/ui/components/search_bar.scss
+++ b/frontend/src/app/main/ui/components/search_bar.scss
@@ -13,55 +13,56 @@
width: 100%;
border-radius: $br-8;
background-color: var(--search-bar-background-color);
+}
- .search-input-wrapper {
- @include flexCenter;
- height: $s-32;
+.search-input-wrapper {
+ @include flexCenter;
+ height: $s-32;
+ width: 100%;
+ border: $s-1 solid var(--search-bar-input-border-color);
+ border-radius: $br-8;
+ background-color: var(--search-bar-input-background-color);
+ input {
width: 100%;
- border: $s-1 solid var(--search-bar-input-border-color);
- border-radius: $br-8;
- background-color: var(--search-bar-input-background-color);
- input {
- width: 100%;
- height: 100%;
- margin: 0 $s-8 0 $s-4;
- border: 0;
- background-color: var(--input-background-color);
- font-size: $fs-12;
- color: var(--input-foreground-color);
- &:focus {
- outline: none;
- }
- }
- &:hover {
- border: $s-1 solid var(--input-background-color-hover);
- background-color: var(--input-background-color-hover);
- input {
- background-color: var(--input-background-color-hover);
- }
- }
- &:focus-within {
- background-color: var(--input-background-color-active);
- color: var(--input-foreground-color-active);
- border: $s-1 solid var(--input-border-color-focus);
- input {
- background-color: var(--input-background-color-active);
- }
- }
-
- .clear {
- @extend .button-tag;
- border-radius: $br-8;
- height: 100%;
- svg {
- @extend .button-icon-small;
- color: transparent;
- stroke: var(--icon-foreground);
- }
+ height: 100%;
+ margin: 0 $s-8 0 $s-4;
+ border: 0;
+ background-color: var(--input-background-color);
+ font-size: $fs-12;
+ color: var(--input-foreground-color);
+ &:focus {
+ outline: none;
}
}
- &.has-children .search-input-wrapper {
- border-radius: $br-2 $br-8 $br-8 $br-2;
- margin-left: 0;
+ &:hover {
+ border: $s-1 solid var(--input-background-color-hover);
+ background-color: var(--input-background-color-hover);
+ input {
+ background-color: var(--input-background-color-hover);
+ }
+ }
+ &:focus-within {
+ background-color: var(--input-background-color-active);
+ color: var(--input-foreground-color-active);
+ border: $s-1 solid var(--input-border-color-focus);
+ input {
+ background-color: var(--input-background-color-active);
+ }
}
}
+
+.clear {
+ @extend .button-tag;
+ border-radius: $br-8;
+ height: 100%;
+ svg {
+ @extend .button-icon-small;
+ color: transparent;
+ stroke: var(--icon-foreground);
+ }
+}
+
+.search-box.has-children .search-input-wrapper {
+ border-radius: $br-2 $br-8 $br-8 $br-2;
+ margin-left: 0;
+}
diff --git a/frontend/src/app/main/ui/components/tab_container.cljs b/frontend/src/app/main/ui/components/tab_container.cljs
index 9b52965a56..be104cfcf6 100644
--- a/frontend/src/app/main/ui/components/tab_container.cljs
+++ b/frontend/src/app/main/ui/components/tab_container.cljs
@@ -9,7 +9,6 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
@@ -19,9 +18,8 @@
(mf/defc tab-element
{::mf/wrap-props false}
[props]
- (let [children (unchecked-get props "children")
- new-css-system (mf/use-ctx ctx/new-css-system)]
- [:div {:class (stl/css new-css-system :tab-element)}
+ (let [children (unchecked-get props "children")]
+ [:div {:class (stl/css :tab-element)}
children]))
(mf/defc tab-container
diff --git a/frontend/src/app/main/ui/confirm.cljs b/frontend/src/app/main/ui/confirm.cljs
index d17cfaee91..cfce7c2c13 100644
--- a/frontend/src/app/main/ui/confirm.cljs
+++ b/frontend/src/app/main/ui/confirm.cljs
@@ -9,7 +9,6 @@
(:require
[app.main.data.modal :as modal]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr t]]
@@ -31,8 +30,7 @@
cancel-label
accept-label
accept-style] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- locale (mf/deref i18n/locale)
+ (let [locale (mf/deref i18n/locale)
on-accept (or on-accept identity)
on-cancel (or on-cancel identity)
@@ -67,87 +65,45 @@
(partial events/unlistenByKey))))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} title]
- [:button {:class (stl/css :modal-close-btn)
- :on-click cancel-fn} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} title]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click cancel-fn} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- (when (and (string? message) (not= message ""))
- [:h3 {:class (stl/css :modal-msg)} message])
- (when (and (string? scd-message) (not= scd-message ""))
- [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
- (when (string? hint)
- [:p {:class (stl/css :modal-hint)} hint])
- (when (> (count items) 0)
- [:*
- [:p {:class (stl/css :modal-subtitle)}
- (tr "ds.component-subtitle")]
- [:ul {:class (stl/css :component-list)}
- (for [item items]
- [:li {:class (stl/css :modal-item-element)}
- [:span {:class (stl/css :modal-component-icon)}
- i/component-refactor]
- [:span {:class (stl/css :modal-component-name)}
- (:name item)]])]])]
-
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- (when-not (= cancel-label :omit)
- [:input
- {:class (stl/css :cancel-button)
- :type "button"
- :value cancel-label
- :on-click cancel-fn}])
+ [:div {:class (stl/css :modal-content)}
+ (when (and (string? message) (not= message ""))
+ [:h3 {:class (stl/css :modal-msg)} message])
+ (when (and (string? scd-message) (not= scd-message ""))
+ [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
+ (when (string? hint)
+ [:p {:class (stl/css :modal-hint)} hint])
+ (when (> (count items) 0)
+ [:*
+ [:p {:class (stl/css :modal-subtitle)}
+ (tr "ds.component-subtitle")]
+ [:ul {:class (stl/css :component-list)}
+ (for [item items]
+ [:li {:class (stl/css :modal-item-element)}
+ [:span {:class (stl/css :modal-component-icon)}
+ i/component-refactor]
+ [:span {:class (stl/css :modal-component-name)}
+ (:name item)]])]])]
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ (when-not (= cancel-label :omit)
[:input
- {:class (stl/css-case :accept-btn true
- :danger (= accept-style :danger)
- :primary (= accept-style :primary))
+ {:class (stl/css :cancel-button)
:type "button"
- :value accept-label
- :on-click accept-fn}]]]]]
+ :value cancel-label
+ :on-click cancel-fn}])
-
- [:div.modal-overlay
- [:div.modal-container.confirm-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 title]]
- [:div.modal-close-button
- {:on-click cancel-fn} i/close]]
-
- [:div.modal-content
- (when (and (string? message) (not= message ""))
- [:h3 message])
- (when (and (string? scd-message) (not= scd-message ""))
- [:h3 scd-message])
- (when (string? hint)
- [:p hint])
- (when (> (count items) 0)
- [:*
- [:p (tr "ds.component-subtitle")]
- [:ul.component-list
- (for [item items]
- [:li.modal-item-element
- [:span.modal-component-icon i/component]
- [:span (:name item)]])]])]
-
- [:div.modal-footer
- [:div.action-buttons
- (when-not (= cancel-label :omit)
- [:input.cancel-button
- {:type "button"
- :value cancel-label
- :on-click cancel-fn}])
-
- [:input.accept-button
- {:class (dom/classnames
- :danger (= accept-style :danger)
- :primary (= accept-style :primary))
- :type "button"
- :value accept-label
- :on-click accept-fn}]]]]])))
+ [:input
+ {:class (stl/css-case :accept-btn true
+ :danger (= accept-style :danger)
+ :primary (= accept-style :primary))
+ :type "button"
+ :value accept-label
+ :on-click accept-fn}]]]]]))
diff --git a/frontend/src/app/main/ui/confirm.scss b/frontend/src/app/main/ui/confirm.scss
index 7d01aff684..ea944f3e5f 100644
--- a/frontend/src/app/main/ui/confirm.scss
+++ b/frontend/src/app/main/ui/confirm.scss
@@ -11,56 +11,63 @@
&.transparent {
background-color: transparent;
}
- .modal-container {
- @extend .modal-container-base;
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .component-list {
- .modal-item-element {
- @include flexRow;
- .modal-component-icon {
- @include flexCenter;
- height: $s-16;
- width: $s-16;
- svg {
- @extend .button-icon-small;
- stroke: var(--color);
- }
- }
- .modal-component-name {
- @include titleTipography;
- }
- }
- }
- .modal-hint {
- @extend .modal-hint-base;
- }
- }
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+}
+
+.modal-container {
+ @extend .modal-container-base;
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.modal-item-element {
+ @include flexRow;
+}
+
+.modal-component-icon {
+ @include flexCenter;
+ height: $s-16;
+ width: $s-16;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--color);
+ }
+}
+.modal-component-name {
+ @include titleTipography;
+}
+
+.modal-hint {
+ @extend .modal-hint-base;
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
diff --git a/frontend/src/app/main/ui/dashboard.cljs b/frontend/src/app/main/ui/dashboard.cljs
index 6905c68bc0..ec956fa08e 100644
--- a/frontend/src/app/main/ui/dashboard.cljs
+++ b/frontend/src/app/main/ui/dashboard.cljs
@@ -53,8 +53,7 @@
(mf/defc dashboard-content
[{:keys [team projects project section search-term profile] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- container (mf/use-ref)
+ (let [container (mf/use-ref)
content-width (mf/use-state 0)
project-id (:id project)
team-id (:id team)
@@ -82,123 +81,65 @@
(mf/use-effect on-resize)
- (if new-css-system
- [:div {:class (stl/css :dashboard-content)
- :on-click clear-selected-fn :ref container}
- (case section
- :dashboard-projects
- [:*
- [:& projects-section
- {:team team
- :projects projects
- :profile profile
- :default-project-id default-project-id}]
+ [:div {:class (stl/css :dashboard-content)
+ :on-click clear-selected-fn :ref container}
+ (case section
+ :dashboard-projects
+ [:*
+ [:& projects-section
+ {:team team
+ :projects projects
+ :profile profile
+ :default-project-id default-project-id}]
+ (when (contains? cf/flags :dashboard-templates-section)
+ [:& templates-section {:profile profile
+ :project-id project-id
+ :team-id team-id
+ :default-project-id default-project-id
+ :content-width @content-width}])]
+
+ :dashboard-fonts
+ [:& fonts-page {:team team}]
+
+ :dashboard-font-providers
+ [:& font-providers-page {:team team}]
+
+ :dashboard-files
+ (when project
+ [:*
+ [:& files-section {:team team :project project}]
(when (contains? cf/flags :dashboard-templates-section)
[:& templates-section {:profile profile
- :project-id project-id
:team-id team-id
- :default-project-id default-project-id
- :content-width @content-width}])]
-
- :dashboard-fonts
- [:& fonts-page {:team team}]
-
- :dashboard-font-providers
- [:& font-providers-page {:team team}]
-
- :dashboard-files
- (when project
- [:*
- [:& files-section {:team team :project project}]
- (when (contains? cf/flags :dashboard-templates-section)
- [:& templates-section {:profile profile
- :team-id team-id
- :project-id project-id
- :default-project-id default-project-id
- :content-width @content-width}])])
-
- :dashboard-search
- [:& search-page {:team team
- :search-term search-term}]
-
- :dashboard-libraries
- [:& libraries-page {:team team}]
-
- :dashboard-team-members
- [:& team-members-page {:team team :profile profile}]
-
- :dashboard-team-invitations
- [:& team-invitations-page {:team team}]
-
- :dashboard-team-webhooks
- [:& team-webhooks-page {:team team}]
-
- :dashboard-team-settings
- [:& team-settings-page {:team team :profile profile}]
-
- nil)]
-
- ;; OLD
- [:div.dashboard-content {:on-click clear-selected-fn :ref container}
- (case section
- :dashboard-projects
- [:*
- [:& projects-section
- {:team team
- :projects projects
- :profile profile
- :default-project-id default-project-id}]
-
- (when (contains? cf/flags :dashboard-templates-section)
- [:& templates-section {:profile profile
:project-id project-id
- :team-id team-id
:default-project-id default-project-id
- :content-width @content-width}])]
+ :content-width @content-width}])])
- :dashboard-fonts
- [:& fonts-page {:team team}]
+ :dashboard-search
+ [:& search-page {:team team
+ :search-term search-term}]
- :dashboard-font-providers
- [:& font-providers-page {:team team}]
+ :dashboard-libraries
+ [:& libraries-page {:team team}]
- :dashboard-files
- (when project
- [:*
- [:& files-section {:team team :project project}]
- (when (contains? cf/flags :dashboard-templates-section)
- [:& templates-section {:profile profile
- :team-id team-id
- :project-id project-id
- :default-project-id default-project-id
- :content-width @content-width}])])
+ :dashboard-team-members
+ [:& team-members-page {:team team :profile profile}]
- :dashboard-search
- [:& search-page {:team team
- :search-term search-term}]
+ :dashboard-team-invitations
+ [:& team-invitations-page {:team team}]
- :dashboard-libraries
- [:& libraries-page {:team team}]
+ :dashboard-team-webhooks
+ [:& team-webhooks-page {:team team}]
- :dashboard-team-members
- [:& team-members-page {:team team :profile profile}]
+ :dashboard-team-settings
+ [:& team-settings-page {:team team :profile profile}]
- :dashboard-team-invitations
- [:& team-invitations-page {:team team}]
-
- :dashboard-team-webhooks
- [:& team-webhooks-page {:team team}]
-
- :dashboard-team-settings
- [:& team-settings-page {:team team :profile profile}]
-
- nil)])))
+ nil)]))
(mf/defc dashboard
[{:keys [route profile] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- section (get-in route [:data :name])
+ (let [section (get-in route [:data :name])
params (parse-params route)
project-id (:project-id params)
@@ -227,59 +168,31 @@
(fn []
(events/unlistenByKey key))))
- (if new-css-system
- [:& (mf/provider ctx/current-team-id) {:value team-id}
- [:& (mf/provider ctx/current-project-id) {:value project-id}
- ;; NOTE: dashboard events and other related functions assumes
- ;; that the team is a implicit context variable that is
- ;; available using react context or accessing
- ;; the :current-team-id on the state. We set the key to the
- ;; team-id because we want to completely refresh all the
- ;; components on team change. Many components assumes that the
- ;; team is already set so don't put the team into mf/deps.
- (when team
- [:main {:class (stl/css :dashboard)
- :key (:id team)}
- [:& sidebar
- {:team team
- :projects projects
- :project project
+ [:& (mf/provider ctx/current-team-id) {:value team-id}
+ [:& (mf/provider ctx/current-project-id) {:value project-id}
+ ;; NOTE: dashboard events and other related functions assumes
+ ;; that the team is a implicit context variable that is
+ ;; available using react context or accessing
+ ;; the :current-team-id on the state. We set the key to the
+ ;; team-id because we want to completely refresh all the
+ ;; components on team change. Many components assumes that the
+ ;; team is already set so don't put the team into mf/deps.
+ (when team
+ [:main {:class (stl/css :dashboard)
+ :key (:id team)}
+ [:& sidebar
+ {:team team
+ :projects projects
+ :project project
+ :profile profile
+ :section section
+ :search-term search-term}]
+ (when (and team profile (seq projects))
+ [:& dashboard-content
+ {:projects projects
:profile profile
- :section section
- :search-term search-term}]
- (when (and team profile (seq projects))
- [:& dashboard-content
- {:projects projects
- :profile profile
- :project project
- :section section
- :search-term search-term
- :team team}])])]]
-
- [:& (mf/provider ctx/current-team-id) {:value team-id}
- [:& (mf/provider ctx/current-project-id) {:value project-id}
- ;; NOTE: dashboard events and other related functions assumes
- ;; that the team is a implicit context variable that is
- ;; available using react context or accessing
- ;; the :current-team-id on the state. We set the key to the
- ;; team-id because we want to completely refresh all the
- ;; components on team change. Many components assumes that the
- ;; team is already set so don't put the team into mf/deps.
- (when team
- [:main {:class (dom/classnames :dashboard-layout true) :key (:id team)}
- [:& sidebar
- {:team team
- :projects projects
:project project
- :profile profile
:section section
- :search-term search-term}]
- (when (and team profile (seq projects))
- [:& dashboard-content
- {:projects projects
- :profile profile
- :project project
- :section section
- :search-term search-term
- :team team}])])]])))
+ :search-term search-term
+ :team team}])])]]))
diff --git a/frontend/src/app/main/ui/dashboard/change_owner.cljs b/frontend/src/app/main/ui/dashboard/change_owner.cljs
index bb8eb1ea7d..cae033df37 100644
--- a/frontend/src/app/main/ui/dashboard/change_owner.cljs
+++ b/frontend/src/app/main/ui/dashboard/change_owner.cljs
@@ -12,7 +12,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s]
@@ -26,8 +25,7 @@
{::mf/register modal/components
::mf/register-as :leave-and-reassign}
[{:keys [profile team accept]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (fm/use-form :spec ::leave-modal-form :initial {})
+ (let [form (fm/use-form :spec ::leave-modal-form :initial {})
members-map (mf/deref refs/dashboard-team-members)
members (vals members-map)
@@ -42,71 +40,37 @@
(let [member-id (get-in @form [:clean-data :member-id])]
(accept member-id)))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} (tr "modals.leave-and-reassign.title")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-cancel} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} (tr "modals.leave-and-reassign.title")]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-cancel} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :modal-content)}
+ [:p {:class (stl/css :modal-msg)}
+ (tr "modals.leave-and-reassign.hint1" (:name team))]
+
+ (if (empty? members)
[:p {:class (stl/css :modal-msg)}
- (tr "modals.leave-and-reassign.hint1" (:name team))]
+ (tr "modals.leave-and-reassign.forbidden")]
+ [:*
+ [:& fm/form {:form form}
+ [:& fm/select {:name :member-id
+ :options options}]]])]
- (if (empty? members)
- [:p {:class (stl/css :modal-msg)}
- (tr "modals.leave-and-reassign.forbidden")]
- [:*
- [:& fm/form {:form form}
- [:& fm/select {:name :member-id
- :options options}]]])]
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:input {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.cancel")
+ :on-click on-cancel}]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.cancel")
- :on-click on-cancel}]
-
- [:input.accept-button
- {:type "button"
- :class (stl/css-case :accept-btn true
- :danger (:valid @form)
- :global/disabled (not (:valid @form)))
- :disabled (not (:valid @form))
- :value (tr "modals.leave-and-reassign.promote-and-leave")
- :on-click on-accept}]]]]]
-
-
- [:div.modal-overlay
- [:div.modal-container.confirm-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 (tr "modals.leave-and-reassign.title")]]
- [:div.modal-close-button
- {:on-click on-cancel} i/close]]
-
- [:div.modal-content.generic-form
- [:p (tr "modals.leave-and-reassign.hint1" (:name team))]
-
- (if (empty? members)
- [:p (tr "modals.leave-and-reassign.forbidden")]
- [:*
- [:& fm/form {:form form}
- [:& fm/select {:name :member-id
- :options options}]]])]
-
- [:div.modal-footer
- [:div.action-buttons
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.cancel")
- :on-click on-cancel}]
-
- [:input.accept-button
- {:type "button"
- :class (if (:valid @form) "danger" "btn-disabled")
- :disabled (not (:valid @form))
- :value (tr "modals.leave-and-reassign.promote-and-leave")
- :on-click on-accept}]]]]])))
+ [:input.accept-button
+ {:type "button"
+ :class (stl/css-case :accept-btn true
+ :danger (:valid @form)
+ :global/disabled (not (:valid @form)))
+ :disabled (not (:valid @form))
+ :value (tr "modals.leave-and-reassign.promote-and-leave")
+ :on-click on-accept}]]]]]))
diff --git a/frontend/src/app/main/ui/dashboard/change_owner.scss b/frontend/src/app/main/ui/dashboard/change_owner.scss
index 799d566c7c..3c91c1a92b 100644
--- a/frontend/src/app/main/ui/dashboard/change_owner.scss
+++ b/frontend/src/app/main/ui/dashboard/change_owner.scss
@@ -8,39 +8,46 @@
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .input-wrapper {
- @extend .input-with-label;
- }
- }
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+}
+
+.modal-container {
+ @extend .modal-container-base;
+ border: $s-1 solid var(--modal-border-color);
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.input-wrapper {
+ @extend .input-with-label;
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs
index 45c4d75d60..fcc5502517 100644
--- a/frontend/src/app/main/ui/dashboard/comments.cljs
+++ b/frontend/src/app/main/ui/dashboard/comments.cljs
@@ -14,9 +14,7 @@
[app.main.store :as st]
[app.main.ui.comments :as cmt]
[app.main.ui.components.dropdown :refer [dropdown]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[potok.v2.core :as ptk]
@@ -42,21 +40,18 @@
(on-show-comments event))))]
[:div {:class (stl/css :dashboard-comments-section)}
- [:button
- {:tab-index "0"
- :on-click on-show-comments
- :on-key-down handle-keydown
- :data-test "open-comments"
- :class (stl/css-case :button true
- :open show?
- :unread (boolean (seq tgroups)))}
- i/chat]]))
+ [:button {:tab-index "0"
+ :on-click on-show-comments
+ :on-key-down handle-keydown
+ :data-test "open-comments"
+ :class (stl/css-case :button true
+ :open show?
+ :unread (boolean (seq tgroups)))}
+ i/comments-refactor]]))
(mf/defc comments-section
- [{:keys [profile team show? on-show-comments on-hide-comments]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- threads-map (mf/deref refs/comment-threads)
+ [{:keys [profile team show? on-hide-comments]}]
+ (let [threads-map (mf/deref refs/comment-threads)
users (mf/deref refs/current-team-comments-users)
team-id (:id team)
@@ -91,79 +86,32 @@
(st/emit! (ptk/event ::ev/event {::ev/name "open-comment-notifications"
::ev/origin "dashboard"})))))
- (if new-css-system
- [:div {:class (stl/css :dashboard-comments-section)}
- [:& dropdown {:show show? :on-close on-hide-comments}
- [:div {:class (stl/css :dropdown :comments-section :comment-threads-section)}
- [:div {:class (stl/css :header)}
- [:h3 (tr "labels.comments")]
- [:button
- {:class (stl/css :close)
- :tab-index (if show? "0" "-1")
- :on-click on-hide-comments
- :on-key-down handle-keydown} i/close]]
+ [:div {:class (stl/css :dashboard-comments-section)}
+ [:& dropdown {:show show? :on-close on-hide-comments}
+ [:div {:class (stl/css :dropdown :comments-section :comment-threads-section)}
+ [:div {:class (stl/css :header)}
+ [:h3 (tr "labels.comments")]
+ [:button
+ {:class (stl/css :close)
+ :tab-index (if show? "0" "-1")
+ :on-click on-hide-comments
+ :on-key-down handle-keydown} i/close]]
- (if (seq tgroups)
- [:div {:class (stl/css :thread-groups)}
+ (if (seq tgroups)
+ [:div {:class (stl/css :thread-groups)}
+ [:& cmt/comment-thread-group
+ {:group (first tgroups)
+ :on-thread-click on-navigate
+ :show-file-name true
+ :users users}]
+ (for [tgroup (rest tgroups)]
[:& cmt/comment-thread-group
- {:group (first tgroups)
+ {:group tgroup
:on-thread-click on-navigate
:show-file-name true
- :users users}]
- (for [tgroup (rest tgroups)]
- [:& cmt/comment-thread-group
- {:group tgroup
- :on-thread-click on-navigate
- :show-file-name true
- :users users
- :key (:page-id tgroup)}])]
+ :users users
+ :key (:page-id tgroup)}])]
- [:div {:class (stl/css :thread-groups-placeholder)}
- i/chat
- (tr "labels.no-comments-available")])]]]
-
- ;; OLD
- [:div.dashboard-comments-section
- [:div.button
- {:tab-index "0"
- :on-click on-show-comments
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-show-comments event)))
- :data-test "open-comments"
- :class (dom/classnames :open show?
- :unread (boolean (seq tgroups)))}
- i/chat]
-
- [:& dropdown {:show show? :on-close on-hide-comments}
- [:div.dropdown.comments-section.comment-threads-section.
- [:div.header
- [:h3 (tr "labels.comments")]
- [:span.close {:tab-index (if show? "0" "-1")
- :on-click on-hide-comments
- :on-key-down handle-keydown}
- i/close]]
-
- [:hr]
-
- (if (seq tgroups)
- [:div.thread-groups
- [:& cmt/comment-thread-group
- {:group (first tgroups)
- :on-thread-click on-navigate
- :show-file-name true
- :users users}]
- (for [tgroup (rest tgroups)]
- [:*
- [:hr]
-
- [:& cmt/comment-thread-group
- {:group tgroup
- :on-thread-click on-navigate
- :show-file-name true
- :users users
- :key (:page-id tgroup)}]])]
-
- [:div.thread-groups-placeholder
- i/chat
- (tr "labels.no-comments-available")])]]])))
+ [:div {:class (stl/css :thread-groups-placeholder)}
+ i/comments-refactor
+ (tr "labels.no-comments-available")])]]]))
diff --git a/frontend/src/app/main/ui/dashboard/comments.scss b/frontend/src/app/main/ui/dashboard/comments.scss
index ed615fa73a..395d08005d 100644
--- a/frontend/src/app/main/ui/dashboard/comments.scss
+++ b/frontend/src/app/main/ui/dashboard/comments.scss
@@ -47,9 +47,11 @@
font-size: $fs-12;
padding: $s-24;
text-align: center;
+ color: $df-secondary;
svg {
- fill: $df-secondary;
+ stroke: $df-secondary;
+ fill: none;
height: $s-24;
margin-bottom: $s-24;
width: $s-24;
@@ -65,21 +67,22 @@
width: $s-32;
svg {
- width: $s-16;
- height: $s-16;
- fill: $df-secondary;
+ min-width: $s-16;
+ min-height: $s-16;
+ stroke: $df-secondary;
+ fill: none;
}
&.unread svg,
&.open svg {
- fill: $da-tertiary;
+ stroke: $da-tertiary;
}
&:hover {
background-color: $db-cuaternary;
svg {
- fill: $da-primary;
+ stroke: $da-primary;
}
}
}
diff --git a/frontend/src/app/main/ui/dashboard/export.cljs b/frontend/src/app/main/ui/dashboard/export.cljs
index d1ff72b124..3adee05946 100644
--- a/frontend/src/app/main/ui/dashboard/export.cljs
+++ b/frontend/src/app/main/ui/dashboard/export.cljs
@@ -11,7 +11,6 @@
[app.common.data.macros :as dm]
[app.main.data.modal :as modal]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.worker :as uw]
[app.util.dom :as dom]
@@ -24,36 +23,19 @@
(mf/defc export-entry
{::mf/wrap-props false}
[{:keys [file]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
+ [:div {:class (stl/css-case :file-entry true
+ :loading (:loading? file)
+ :success (:export-success? file)
+ :error (:export-error? file))}
- (if new-css-system
- [:div {:class (stl/css-case :file-entry true
- :loading (:loading? file)
- :success (:export-success? file)
- :error (:export-error? file))}
+ [:div {:class (stl/css :file-name)}
+ [:span {:class (stl/css :file-icon)}
+ (cond (:export-success? file) i/tick-refactor
+ (:export-error? file) i/close-refactor
+ (:loading? file) i/loader-pencil)]
- [:div {:class (stl/css :file-name)}
- [:span {:class (stl/css :file-icon)}
- (cond (:export-success? file) i/tick-refactor
- (:export-error? file) i/close-refactor
- (:loading? file) i/loader-pencil)]
-
- [:div {:class (stl/css :file-name-label)}
- (:name file)]]]
-
-
- [:div.file-entry
- {:class (dom/classnames
- :loading (:loading? file)
- :success (:export-success? file)
- :error (:export-error? file))}
- [:div.file-name
- [:div.file-icon
- (cond (:export-success? file) i/tick
- (:export-error? file) i/close
- (:loading? file) i/loader-pencil)]
-
- [:div.file-name-label (:name file)]]])))
+ [:div {:class (stl/css :file-name-label)}
+ (:name file)]]])
(defn- mark-file-error
[files file-id]
@@ -79,8 +61,7 @@
::mf/register-as :export
::mf/wrap-props false}
[{:keys [team-id files has-libraries? binary? features]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- state* (mf/use-state
+ (let [state* (mf/use-state
#(let [files (mapv (fn [file] (assoc file :loading? true)) files)]
{:status :prepare
:selected :all
@@ -140,136 +121,70 @@
(when-not has-libraries?
(start-export)))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)}
- (tr "dashboard.export.title")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-cancel} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)}
+ (tr "dashboard.export.title")]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-cancel} i/close-refactor]]
- (cond
- (= status :prepare)
- [:*
- [:div {:class (stl/css :modal-content)}
- [:p {:class (stl/css :modal-msg)} (tr "dashboard.export.explain")]
- [:p {:class (stl/css :modal-scd-msg)} (tr "dashboard.export.detail")]
+ (cond
+ (= status :prepare)
+ [:*
+ [:div {:class (stl/css :modal-content)}
+ [:p {:class (stl/css :modal-msg)} (tr "dashboard.export.explain")]
+ [:p {:class (stl/css :modal-scd-msg)} (tr "dashboard.export.detail")]
- (for [type export-types]
- [:div {:class (stl/css :export-option true)
- :key (name type)}
- [:label {:for (str "export-" type)
- :class (stl/css-case :global/checked (= selected type))}
- ;; Execution time translation strings:
- ;; dashboard.export.options.all.message
- ;; dashboard.export.options.all.title
- ;; dashboard.export.options.detach.message
- ;; dashboard.export.options.detach.title
- ;; dashboard.export.options.merge.message
- ;; dashboard.export.options.merge.title
- [:span {:class (stl/css-case :global/checked (= selected type))}
- (when (= selected type)
- i/status-tick-refactor)]
- [:div {:class (stl/css :option-content)}
- [:h3 {:class (stl/css :modal-subtitle)} (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
- [:p {:class (stl/css :modal-msg)} (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]]
+ (for [type export-types]
+ [:div {:class (stl/css :export-option true)
+ :key (name type)}
+ [:label {:for (str "export-" type)
+ :class (stl/css-case :global/checked (= selected type))}
+ ;; Execution time translation strings:
+ ;; dashboard.export.options.all.message
+ ;; dashboard.export.options.all.title
+ ;; dashboard.export.options.detach.message
+ ;; dashboard.export.options.detach.title
+ ;; dashboard.export.options.merge.message
+ ;; dashboard.export.options.merge.title
+ [:span {:class (stl/css-case :global/checked (= selected type))}
+ (when (= selected type)
+ i/status-tick-refactor)]
+ [:div {:class (stl/css :option-content)}
+ [:h3 {:class (stl/css :modal-subtitle)} (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
+ [:p {:class (stl/css :modal-msg)} (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]]
- [:input {:type "radio"
- :class (stl/css :option-input)
- :id (str "export-" type)
- :checked (= selected type)
- :name "export-option"
- :data-type (name type)
- :on-change on-change}]]])]
+ [:input {:type "radio"
+ :class (stl/css :option-input)
+ :id (str "export-" type)
+ :checked (= selected type)
+ :name "export-option"
+ :data-type (name type)
+ :on-change on-change}]]])]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.cancel")
- :on-click on-cancel}]
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:input {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.cancel")
+ :on-click on-cancel}]
- [:input {:class (stl/css :accept-btn)
- :type "button"
- :value (tr "labels.continue")
- :on-click on-accept}]]]]
+ [:input {:class (stl/css :accept-btn)
+ :type "button"
+ :value (tr "labels.continue")
+ :on-click on-accept}]]]]
- (= status :exporting)
- [:*
- [:div {:class (stl/css :modal-content)}
- (for [file (:files state)]
- [:& export-entry {:file file :key (dm/str (:id file))}])]
+ (= status :exporting)
+ [:*
+ [:div {:class (stl/css :modal-content)}
+ (for [file (:files state)]
+ [:& export-entry {:file file :key (dm/str (:id file))}])]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:input {:class (stl/css :accept-btn)
- :type "button"
- :value (tr "labels.close")
- :disabled (->> state :files (some :loading?))
- :on-click on-cancel}]]]])]]
-
-
- [:div.modal-overlay
- [:div.modal-container.export-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 (tr "dashboard.export.title")]]
-
- [:div.modal-close-button
- {:on-click on-cancel} i/close]]
-
- (cond
- (= status :prepare)
- [:*
- [:div.modal-content
- [:p.explain (tr "dashboard.export.explain")]
- [:p.detail (tr "dashboard.export.detail")]
-
- (for [type export-types]
- [:div.export-option {:class (when (= selected type) "selected")
- :key (name type)}
- [:label.option-container
- ;; Execution time translation strings:
- ;; dashboard.export.options.all.message
- ;; dashboard.export.options.all.title
- ;; dashboard.export.options.detach.message
- ;; dashboard.export.options.detach.title
- ;; dashboard.export.options.merge.message
- ;; dashboard.export.options.merge.title
- [:h3 (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
- [:p (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]
- [:input {:type "radio"
- :checked (= selected type)
- :data-type (name type)
- :on-change on-change
- :name "export-option"}]
- [:span {:class "option-radio-check"}]]])]
-
- [:div.modal-footer
- [:div.action-buttons
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.cancel")
- :on-click on-cancel}]
-
- [:input.accept-button
- {:class "primary"
- :type "button"
- :value (tr "labels.continue")
- :on-click on-accept}]]]]
-
- (= status :exporting)
- [:*
- [:div.modal-content
- (for [file (:files state)]
- [:& export-entry {:file file :key (dm/str (:id file))}])]
-
- [:div.modal-footer
- [:div.action-buttons
- [:input.accept-button
- {:class "primary"
- :type "button"
- :value (tr "labels.close")
- :disabled (->> state :files (some :loading?))
- :on-click on-cancel}]]]])]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:input {:class (stl/css :accept-btn)
+ :type "button"
+ :value (tr "labels.close")
+ :disabled (->> state :files (some :loading?))
+ :on-click on-cancel}]]]])]]))
diff --git a/frontend/src/app/main/ui/dashboard/export.scss b/frontend/src/app/main/ui/dashboard/export.scss
index 6d092f1679..98c9fd2516 100644
--- a/frontend/src/app/main/ui/dashboard/export.scss
+++ b/frontend/src/app/main/ui/dashboard/export.scss
@@ -8,59 +8,64 @@
.modal-overlay {
@extend .modal-overlay-base;
+}
- .modal-container {
- @extend .modal-container-base;
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
+.modal-container {
+ @extend .modal-container-base;
+}
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .export-option {
- @extend .input-checkbox;
- width: 100%;
- align-items: flex-start;
- label {
- align-items: flex-start;
- .modal-subtitle {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- }
- span {
- margin-top: $s-8;
- }
- .option-content {
- @include flexColumn;
- @include titleTipography;
- }
- }
- }
+.modal-header {
+ margin-bottom: $s-24;
+}
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.export-option {
+ @extend .input-checkbox;
+ width: 100%;
+ align-items: flex-start;
+ label {
+ align-items: flex-start;
+ .modal-subtitle {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
}
}
+ span {
+ margin-top: $s-8;
+ }
+}
+
+.option-content {
+ @include flexColumn;
+ @include titleTipography;
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
+ }
}
.modal-scd-msg,
diff --git a/frontend/src/app/main/ui/dashboard/files.cljs b/frontend/src/app/main/ui/dashboard/files.cljs
index 7faf96b97e..afbeb5afc4 100644
--- a/frontend/src/app/main/ui/dashboard/files.cljs
+++ b/frontend/src/app/main/ui/dashboard/files.cljs
@@ -11,7 +11,6 @@
[app.main.data.events :as ev]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [grid]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.project-menu :refer [project-menu]]
@@ -26,8 +25,7 @@
(mf/defc header
[{:keys [project create-fn] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- local (mf/use-state
+ (let [local (mf/use-state
{:menu-open false
:edition false})
@@ -64,137 +62,75 @@
(dd/clear-selected-files))))]
- (if new-css-system
- [:header {:class (stl/css :dashboard-header)}
- (if (:is-default project)
- [:div#dashboard-drafts-title {:class (stl/css :dashboard-title)}
- [:h1 (tr "labels.drafts")]]
+ [:header {:class (stl/css :dashboard-header)}
+ (if (:is-default project)
+ [:div#dashboard-drafts-title {:class (stl/css :dashboard-title)}
+ [:h1 (tr "labels.drafts")]]
- (if (:edition @local)
- [:& inline-edition
- {:content (:name project)
- :on-end (fn [name]
- (let [name (str/trim name)]
- (when-not (str/empty? name)
- (st/emit! (-> (dd/rename-project (assoc project :name name))
- (with-meta {::ev/origin "project"}))))
- (swap! local assoc :edition false)))}]
- [:div {:class (stl/css :dashboard-title)}
- [:h1 {:on-double-click on-edit
- :data-test "project-title"
- :id (:id project)}
- (:name project)]]))
+ (if (:edition @local)
+ [:& inline-edition
+ {:content (:name project)
+ :on-end (fn [name]
+ (let [name (str/trim name)]
+ (when-not (str/empty? name)
+ (st/emit! (-> (dd/rename-project (assoc project :name name))
+ (with-meta {::ev/origin "project"}))))
+ (swap! local assoc :edition false)))}]
+ [:div {:class (stl/css :dashboard-title)}
+ [:h1 {:on-double-click on-edit
+ :data-test "project-title"
+ :id (:id project)}
+ (:name project)]]))
- [:& project-menu {:project project
- :show? (:menu-open @local)
- :left (- (:x (:menu-pos @local)) 180)
- :top (:y (:menu-pos @local))
- :on-edit on-edit
- :on-menu-close on-menu-close
- :on-import on-import}]
+ [:& project-menu {:project project
+ :show? (:menu-open @local)
+ :left (- (:x (:menu-pos @local)) 180)
+ :top (:y (:menu-pos @local))
+ :on-edit on-edit
+ :on-menu-close on-menu-close
+ :on-import on-import}]
- [:div {:class (stl/css :dashboard-header-actions)}
- [:a
- {:class (stl/css :btn-secondary :btn-small)
+ [:div {:class (stl/css :dashboard-header-actions)}
+ [:a
+ {:class (stl/css :btn-secondary :btn-small)
+ :tab-index "0"
+ :on-click on-create-click
+ :data-test "new-file"
+ :on-key-down (fn [event]
+ (when (kbd/enter? event)
+ (on-create-click event)))}
+ (tr "dashboard.new-file")]
+
+ (when-not (:is-default project)
+ [:button
+ {:class (stl/css-case :icon true
+ :pin-icon true
+ :tooltip true
+ :tooltip-bottom true
+ :active (:is-pinned project))
:tab-index "0"
- :on-click on-create-click
- :data-test "new-file"
+ :on-click toggle-pin
+ :alt (tr "dashboard.pin-unpin")
:on-key-down (fn [event]
(when (kbd/enter? event)
- (on-create-click event)))}
- (tr "dashboard.new-file")]
+ (toggle-pin event)))}
+ (if (:is-pinned project)
+ i/pin-fill
+ i/pin)])
- (when-not (:is-default project)
- [:button
- {:class (stl/css-case :icon true
- :pin-icon true
- :tooltip true
- :tooltip-bottom true
- :active (:is-pinned project))
- :tab-index "0"
- :on-click toggle-pin
- :alt (tr "dashboard.pin-unpin")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (toggle-pin event)))}
- (if (:is-pinned project)
- i/pin-fill
- i/pin)])
-
- [:div
- {:class (stl/css :icon :tooltip :tooltip-bottom-left)
- :tab-index "0"
- :on-click on-menu-click
- :alt (tr "dashboard.options")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-menu-click event)))}
- i/actions]]]
-
- ;; OLD
- [:header.dashboard-header
- (if (:is-default project)
- [:div.dashboard-title#dashboard-drafts-title
- [:h1 (tr "labels.drafts")]]
-
- (if (:edition @local)
- [:& inline-edition {:content (:name project)
- :on-end (fn [name]
- (let [name (str/trim name)]
- (when-not (str/empty? name)
- (st/emit! (-> (dd/rename-project (assoc project :name name))
- (with-meta {::ev/origin "project"}))))
- (swap! local assoc :edition false)))}]
- [:div.dashboard-title
- [:h1 {:on-double-click on-edit
- :data-test "project-title"
- :id (:id project)}
- (:name project)]]))
-
- [:& project-menu {:project project
- :show? (:menu-open @local)
- :left (- (:x (:menu-pos @local)) 180)
- :top (:y (:menu-pos @local))
- :on-edit on-edit
- :on-menu-close on-menu-close
- :on-import on-import}]
-
- [:div.dashboard-header-actions
- [:a.btn-secondary.btn-small
- {:tab-index "0"
- :on-click on-create-click
- :data-test "new-file"
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-create-click event)))}
- (tr "dashboard.new-file")]
-
- (when-not (:is-default project)
- [:button.icon.pin-icon.tooltip.tooltip-bottom
- {:tab-index "0"
- :class (when (:is-pinned project) "active")
- :on-click toggle-pin
- :alt (tr "dashboard.pin-unpin")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (toggle-pin event)))}
- (if (:is-pinned project)
- i/pin-fill
- i/pin)])
-
- [:div.icon.tooltip.tooltip-bottom-left
- {:tab-index "0"
- :on-click on-menu-click
- :alt (tr "dashboard.options")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-menu-click event)))}
- i/actions]]])))
+ [:div
+ {:class (stl/css :icon :tooltip :tooltip-bottom-left)
+ :tab-index "0"
+ :on-click on-menu-click
+ :alt (tr "dashboard.options")
+ :on-key-down (fn [event]
+ (when (kbd/enter? event)
+ (on-menu-click event)))}
+ i/actions]]]))
(mf/defc files-section
[{:keys [project team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- files-map (mf/deref refs/dashboard-files)
+ (let [files-map (mf/deref refs/dashboard-files)
project-id (:id project)
[rowref limit] (hooks/use-dynamic-grid-item-width)
@@ -233,28 +169,15 @@
(st/emit! (dd/fetch-files {:project-id project-id})
(dd/clear-selected-files)))
- (if new-css-system
- [:*
- [:& header {:team team
- :project project
- :create-fn create-file}]
- [:section {:class (stl/css :dashboard-container :no-bg)
- :ref rowref}
- [:& grid {:project project
- :files files
- :origin :files
- :create-fn create-file
- :limit limit}]]]
-
- ;; OLD
- [:*
- [:& header {:team team
- :project project
- :create-fn create-file}]
- [:section.dashboard-container.no-bg {:ref rowref}
- [:& grid {:project project
- :files files
- :origin :files
- :create-fn create-file
- :limit limit}]]])))
+ [:*
+ [:& header {:team team
+ :project project
+ :create-fn create-file}]
+ [:section {:class (stl/css :dashboard-container :no-bg)
+ :ref rowref}
+ [:& grid {:project project
+ :files files
+ :origin :files
+ :create-fn create-file
+ :limit limit}]]]))
diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs
index 30cfa5f392..8a5d5a8591 100644
--- a/frontend/src/app/main/ui/dashboard/fonts.cljs
+++ b/frontend/src/app/main/ui/dashboard/fonts.cljs
@@ -15,7 +15,6 @@
[app.main.store :as st]
[app.main.ui.components.context-menu :refer [context-menu]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -40,17 +39,10 @@
(mf/defc header
{::mf/wrap [mf/memo]}
[{:keys [section team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (use-set-page-title team section)
- (if new-css-system
- [:header {:class (stl/css :dashboard-header)}
- [:div#dashboard-fonts-title {:class (stl/css :dashboard-title)}
- [:h1 (tr "labels.fonts")]]]
-
- ;; OLD
- [:header.dashboard-header
- [:div.dashboard-title#dashboard-fonts-title
- [:h1 (tr "labels.fonts")]]])))
+ (use-set-page-title team section)
+ [:header {:class (stl/css :dashboard-header)}
+ [:div#dashboard-fonts-title {:class (stl/css :dashboard-title)}
+ [:h1 (tr "labels.fonts")]]])
(mf/defc font-variant-display-name
[{:keys [variant]}]
@@ -61,8 +53,7 @@
(mf/defc fonts-upload
[{:keys [team installed-fonts] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- fonts (mf/use-state {})
+ (let [fonts (mf/use-state {})
input-ref (mf/use-ref)
uploading (mf/use-state #{})
@@ -121,151 +112,82 @@
handle-dismiss-all
(mf/use-callback (mf/deps @fonts) #(on-dismiss-all (vals @fonts)))]
- (if new-css-system
- [:div {:class (stl/css :dashboard-fonts-upload)}
- [:div {:class (stl/css :dashboard-fonts-hero)}
- [:div {:class (stl/css :desc)}
- [:h2 (tr "labels.upload-custom-fonts")]
- [:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}]
+ [:div {:class (stl/css :dashboard-fonts-upload)}
+ [:div {:class (stl/css :dashboard-fonts-hero)}
+ [:div {:class (stl/css :desc)}
+ [:h2 (tr "labels.upload-custom-fonts")]
+ [:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}]
- [:button
- {:class (stl/css :btn-primary)
- :on-click on-click
- :tab-index "0"}
- [:span (tr "labels.add-custom-font")]
- [:& file-uploader {:input-id "font-upload"
- :accept cm/str-font-types
- :multi true
- :ref input-ref
- :on-selected on-selected}]]
+ [:button
+ {:class (stl/css :btn-primary)
+ :on-click on-click
+ :tab-index "0"}
+ [:span (tr "labels.add-custom-font")]
+ [:& file-uploader {:input-id "font-upload"
+ :accept cm/str-font-types
+ :multi true
+ :ref input-ref
+ :on-selected on-selected}]]
- [:div {:class (stl/css :banner)}
- [:div {:class (stl/css :icon)} i/msg-info]
+ [:div {:class (stl/css :banner)}
+ [:div {:class (stl/css :icon)} i/msg-info]
+ [:div {:class (stl/css :content)}
+ [:& i18n/tr-html {:tag-name "span"
+ :label "dashboard.fonts.hero-text2"}]]]
+
+ (when problematic-fonts?
+ [:div {:class (stl/css :banner :warning)}
+ [:div {:class (stl/css :icon)} i/msg-warning]
[:div {:class (stl/css :content)}
[:& i18n/tr-html {:tag-name "span"
- :label "dashboard.fonts.hero-text2"}]]]
+ :label "dashboard.fonts.warning-text"}]]])]]
- (when problematic-fonts?
- [:div {:class (stl/css :banner :warning)}
- [:div {:class (stl/css :icon)} i/msg-warning]
- [:div {:class (stl/css :content)}
- [:& i18n/tr-html {:tag-name "span"
- :label "dashboard.fonts.warning-text"}]]])]]
+ [:*
+ (when (some? (vals @fonts))
+ [:div {:class (stl/css :font-item :table-row)}
+ [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
+ [:div {:class (stl/css :table-field :options)}
+ [:button {:class (stl/css :btn-primary)
+ :on-click handle-upload-all :data-test "upload-all"}
+ [:span (tr "dashboard.fonts.upload-all")]]
+ [:button {:class (stl/css :btn-secondary)
+ :on-click handle-dismiss-all :data-test "dismiss-all"}
+ [:span (tr "dashboard.fonts.dismiss-all")]]]])
+
+ (for [item (sort-by :font-family (vals @fonts))]
+ (let [uploading? (contains? @uploading (:id item))]
+ [:div {:class (stl/css :font-item :table-row) :key (:id item)}
+ [:div {:class (stl/css :table-field :family)}
+ [:input {:type "text"
+ :on-blur #(on-blur-name (:id item) %)
+ :default-value (:font-family item)}]]
+ [:div {:class (stl/css :table-field :variants)}
+ [:span {:class (stl/css :label)}
+ [:& font-variant-display-name {:variant item}]]]
+
+ [:div {:class (stl/css :table-field :filenames)}
+ (for [item (:names item)]
+ [:span item])]
- [:*
- (when (some? (vals @fonts))
- [:div {:class (stl/css :font-item :table-row)}
- [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
[:div {:class (stl/css :table-field :options)}
- [:button {:class (stl/css :btn-primary)
- :on-click handle-upload-all :data-test "upload-all"}
- [:span (tr "dashboard.fonts.upload-all")]]
- [:button {:class (stl/css :btn-secondary)
- :on-click handle-dismiss-all :data-test "dismiss-all"}
- [:span (tr "dashboard.fonts.dismiss-all")]]]])
+ (when (:height-warning? item)
+ [:span {:class (stl/css :icon :failure)} i/msg-warning])
- (for [item (sort-by :font-family (vals @fonts))]
- (let [uploading? (contains? @uploading (:id item))]
- [:div {:class (stl/css :font-item :table-row) :key (:id item)}
- [:div {:class (stl/css :table-field :family)}
- [:input {:type "text"
- :on-blur #(on-blur-name (:id item) %)
- :default-value (:font-family item)}]]
- [:div {:class (stl/css :table-field :variants)}
- [:span {:class (stl/css :label)}
- [:& font-variant-display-name {:variant item}]]]
-
- [:div {:class (stl/css :table-field :filenames)}
- (for [item (:names item)]
- [:span item])]
-
- [:div {:class (stl/css :table-field :options)}
- (when (:height-warning? item)
- [:span {:class (stl/css :icon :failure)} i/msg-warning])
-
- [:button
- {:on-click #(on-upload item)
- :class (stl/css-case :btn-primary true
- :upload-button true
- :disabled uploading?)
- :disabled uploading?}
- (if uploading?
- (tr "labels.uploading")
- (tr "labels.upload"))]
- [:span {:class (stl/css :icon :close)
- :on-click #(on-delete item)} i/close]]]))]]
- ;; OLD
- [:div.dashboard-fonts-upload
- [:div.dashboard-fonts-hero
- [:div.desc
- [:h2 (tr "labels.upload-custom-fonts")]
- [:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}]
-
- [:div.banner
- [:div.icon i/msg-info]
- [:div.content
- [:& i18n/tr-html {:tag-name "span"
- :label "dashboard.fonts.hero-text2"}]]]
-
- (when problematic-fonts?
- [:div.banner.warning
- [:div.icon i/msg-warning]
- [:div.content
- [:& i18n/tr-html {:tag-name "span"
- :label "dashboard.fonts.warning-text"}]]])]
-
- [:button.btn-primary
- {:on-click on-click
- :tab-index "0"}
- [:span (tr "labels.add-custom-font")]
- [:& file-uploader {:input-id "font-upload"
- :accept cm/str-font-types
- :multi true
- :ref input-ref
- :on-selected on-selected}]]]
-
- [:*
- (when (some? (vals @fonts))
- [:div.font-item.table-row
- [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
- [:div.table-field.options
- [:div.btn-primary
- {:on-click #(on-upload-all (vals @fonts)) :data-test "upload-all"}
- [:span (tr "dashboard.fonts.upload-all")]]
- [:div.btn-secondary
- {:on-click #(on-dismiss-all (vals @fonts)) :data-test "dismiss-all"}
- [:span (tr "dashboard.fonts.dismiss-all")]]]])
-
- (for [item (sort-by :font-family (vals @fonts))]
- (let [uploading? (contains? @uploading (:id item))]
- [:div.font-item.table-row {:key (:id item)}
- [:div.table-field.family
- [:input {:type "text"
- :on-blur #(on-blur-name (:id item) %)
- :default-value (:font-family item)}]]
- [:div.table-field.variants
- [:span.label
- [:& font-variant-display-name {:variant item}]]]
- [:div.table-field.filenames
- (for [item (:names item)]
- [:span item])]
-
- [:div.table-field.options
- (when (:height-warning? item)
- [:span.icon.failure i/msg-warning])
- [:button.btn-primary.upload-button
- {:on-click #(on-upload item)
- :class (dom/classnames :disabled uploading?)
- :disabled uploading?}
- (if uploading?
- (tr "labels.uploading")
- (tr "labels.upload"))]
- [:span.icon.close {:on-click #(on-delete item)} i/close]]]))]])))
+ [:button
+ {:on-click #(on-upload item)
+ :class (stl/css-case :btn-primary true
+ :upload-button true
+ :disabled uploading?)
+ :disabled uploading?}
+ (if uploading?
+ (tr "labels.uploading")
+ (tr "labels.upload"))]
+ [:span {:class (stl/css :icon :close)
+ :on-click #(on-delete item)} i/close]]]))]]))
(mf/defc installed-font
[{:keys [font-id variants] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- font (first variants)
+ (let [font (first variants)
variants (sort-by (fn [item]
[(:font-weight item)
@@ -324,94 +246,52 @@
:on-accept (fn [_props]
(delete-variant-fn id))})))]
- (if new-css-system
- [:div {:class (stl/css :font-item :table-row)}
- [:div {:class (stl/css :table-field :family)}
- (if @edit?
- [:input {:type "text"
- :default-value @state
- :on-key-down on-key-down
- :on-change on-change}]
- [:span (:font-family font)])]
+ [:div {:class (stl/css :font-item :table-row)}
+ [:div {:class (stl/css :table-field :family)}
+ (if @edit?
+ [:input {:type "text"
+ :default-value @state
+ :on-key-down on-key-down
+ :on-change on-change}]
+ [:span (:font-family font)])]
- [:div {:class (stl/css :table-field :variants)}
- (for [item variants]
- [:div {:class (stl/css :variant)}
- [:span {:class (stl/css :label)}
- [:& font-variant-display-name {:variant item}]]
- [:span
- {:class (stl/css :icon :close)
- :on-click #(on-delete-variant (:id item))}
- i/plus]])]
+ [:div {:class (stl/css :table-field :variants)}
+ (for [item variants]
+ [:div {:class (stl/css :variant)}
+ [:span {:class (stl/css :label)}
+ [:& font-variant-display-name {:variant item}]]
+ [:span
+ {:class (stl/css :icon :close)
+ :on-click #(on-delete-variant (:id item))}
+ i/plus]])]
- (if @edit?
- [:div {:class (stl/css :table-field :options)}
- [:button
- {:disabled (str/blank? @state)
- :on-click on-save
- :class (stl/css-case :btn-primary true
- :btn-disabled (str/blank? @state))}
- (tr "labels.save")]
- [:button {:class (stl/css :icon :close)
- :on-click on-cancel} i/close]]
+ (if @edit?
+ [:div {:class (stl/css :table-field :options)}
+ [:button
+ {:disabled (str/blank? @state)
+ :on-click on-save
+ :class (stl/css-case :btn-primary true
+ :btn-disabled (str/blank? @state))}
+ (tr "labels.save")]
+ [:button {:class (stl/css :icon :close)
+ :on-click on-cancel} i/close]]
- [:div {:class (stl/css :table-field :options)}
- [:span {:class (stl/css :icon)
- :on-click #(reset! open-menu? true)} i/actions]
- [:& context-menu
- {:on-close #(reset! open-menu? false)
- :show @open-menu?
- :fixed? false
- :top -15
- :left -115
- :options [[(tr "labels.edit") #(reset! edit? true) nil "font-edit"]
- [(tr "labels.delete") on-delete nil "font-delete"]]}]])]
- ;;OLD
- [:div.font-item.table-row
- [:div.table-field.family
- (if @edit?
- [:input {:type "text"
- :default-value @state
- :on-key-down on-key-down
- :on-change on-change}]
- [:span (:font-family font)])]
-
- [:div.table-field.variants
- (for [item variants]
- [:div.variant
- [:span.label
- [:& font-variant-display-name {:variant item}]]
- [:span.icon.close
- {:on-click #(on-delete-variant (:id item))}
- i/plus]])]
-
- [:div]
-
- (if @edit?
- [:div.table-field.options
- [:button.btn-primary
- {:disabled (str/blank? @state)
- :on-click on-save
- :class (dom/classnames :btn-disabled (str/blank? @state))}
- (tr "labels.save")]
- [:span.icon.close {:on-click on-cancel} i/close]]
-
- [:div.table-field.options
- [:span.icon {:on-click #(reset! open-menu? true)} i/actions]
- [:& context-menu
- {:on-close #(reset! open-menu? false)
- :show @open-menu?
- :fixed? false
- :top -15
- :left -115
- :options [[(tr "labels.edit") #(reset! edit? true) nil "font-edit"]
- [(tr "labels.delete") on-delete nil "font-delete"]]}]])])))
+ [:div {:class (stl/css :table-field :options)}
+ [:span {:class (stl/css :icon)
+ :on-click #(reset! open-menu? true)} i/actions]
+ [:& context-menu
+ {:on-close #(reset! open-menu? false)
+ :show @open-menu?
+ :fixed? false
+ :top -15
+ :left -115
+ :options [[(tr "labels.edit") #(reset! edit? true) nil "font-edit"]
+ [(tr "labels.delete") on-delete nil "font-delete"]]}]])]))
(mf/defc installed-fonts
[{:keys [fonts] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- sterm (mf/use-state "")
+ (let [sterm (mf/use-state "")
matches?
#(str/includes? (str/lower (:font-family %)) @sterm)
@@ -422,98 +302,49 @@
(let [val (dom/get-target-val event)]
(reset! sterm (str/lower val)))))]
- (if new-css-system
- [:div {:class (stl/css :dashboard-installed-fonts)}
- [:h3 (tr "labels.installed-fonts")]
- [:div {:class (stl/css :installed-fonts-header)}
- [:div {:class (stl/css :table-field :family)} (tr "labels.font-family")]
- [:div {:class (stl/css :table-field :variants)} (tr "labels.font-variants")]
- [:div {:class (stl/css :table-field :search-input)}
- [:input {:placeholder (tr "labels.search-font")
- :default-value ""
- :on-change on-change}]]]
+ [:div {:class (stl/css :dashboard-installed-fonts)}
+ [:h3 (tr "labels.installed-fonts")]
+ [:div {:class (stl/css :installed-fonts-header)}
+ [:div {:class (stl/css :table-field :family)} (tr "labels.font-family")]
+ [:div {:class (stl/css :table-field :variants)} (tr "labels.font-variants")]
+ [:div {:class (stl/css :table-field :search-input)}
+ [:input {:placeholder (tr "labels.search-font")
+ :default-value ""
+ :on-change on-change}]]]
- (cond
- (seq fonts)
- (for [[font-id variants] (->> (vals fonts)
- (filter matches?)
- (group-by :font-id))]
- [:& installed-font {:key (str font-id)
- :font-id font-id
- :variants variants}])
+ (cond
+ (seq fonts)
+ (for [[font-id variants] (->> (vals fonts)
+ (filter matches?)
+ (group-by :font-id))]
+ [:& installed-font {:key (str font-id)
+ :font-id font-id
+ :variants variants}])
- (nil? fonts)
- [:div {:class (stl/css :fonts-placeholder)}
- [:div {:class (stl/css :icon)} i/loader]
- [:div {:class (stl/css :label)} (tr "dashboard.loading-fonts")]]
+ (nil? fonts)
+ [:div {:class (stl/css :fonts-placeholder)}
+ [:div {:class (stl/css :icon)} i/loader]
+ [:div {:class (stl/css :label)} (tr "dashboard.loading-fonts")]]
- :else
- [:div {:class (stl/css :fonts-placeholder)}
- [:div {:class (stl/css :icon)} i/text]
- [:div {:class (stl/css :label)} (tr "dashboard.fonts.empty-placeholder")]])]
-
- ;; OLD
- [:div.dashboard-installed-fonts
- [:h3 (tr "labels.installed-fonts")]
- [:div.installed-fonts-header
- [:div.table-field.family (tr "labels.font-family")]
- [:div.table-field.variants (tr "labels.font-variants")]
- [:div]
- [:div.table-field.search-input
- [:input {:placeholder (tr "labels.search-font")
- :default-value ""
- :on-change on-change}]]]
-
- (cond
- (seq fonts)
- (for [[font-id variants] (->> (vals fonts)
- (filter matches?)
- (group-by :font-id))]
- [:& installed-font {:key (str font-id)
- :font-id font-id
- :variants variants}])
-
- (nil? fonts)
- [:div.fonts-placeholder
- [:div.icon i/loader]
- [:div.label (tr "dashboard.loading-fonts")]]
-
- :else
- [:div.fonts-placeholder
- [:div.icon i/text]
- [:div.label (tr "dashboard.fonts.empty-placeholder")]])])))
+ :else
+ [:div {:class (stl/css :fonts-placeholder)}
+ [:div {:class (stl/css :icon)} i/text]
+ [:div {:class (stl/css :label)} (tr "dashboard.fonts.empty-placeholder")]])]))
(mf/defc fonts-page
[{:keys [team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- fonts (mf/deref refs/dashboard-fonts)]
- (if new-css-system
- [:*
- [:& header {:team team :section :fonts}]
- [:section {:class (stl/css :dashboard-container :dashboard-fonts)}
- [:& fonts-upload {:team team :installed-fonts fonts}]
- [:& installed-fonts {:team team :fonts fonts}]]]
-
- ;; OLD
- [:*
- [:& header {:team team :section :fonts}]
- [:section.dashboard-container.dashboard-fonts
- [:& fonts-upload {:team team :installed-fonts fonts}]
- [:& installed-fonts {:team team :fonts fonts}]]])))
+ (let [fonts (mf/deref refs/dashboard-fonts)]
+ [:*
+ [:& header {:team team :section :fonts}]
+ [:section {:class (stl/css :dashboard-container :dashboard-fonts)}
+ [:& fonts-upload {:team team :installed-fonts fonts}]
+ [:& installed-fonts {:team team :fonts fonts}]]]))
(mf/defc font-providers-page
[{:keys [team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:*
- [:& header {:team team :section :providers}]
- [:section {:class (stl/css :dashboard-container)}
- [:span "font providers"]]]
-
- ;; OLD
- [:*
- [:& header {:team team :section :providers}]
- [:section.dashboard-container
- [:span "font providers"]]])))
+ [:*
+ [:& header {:team team :section :providers}]
+ [:section {:class (stl/css :dashboard-container)}
+ [:span "font providers"]]])
diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs
index 57108c88b2..67dac1f45f 100644
--- a/frontend/src/app/main/ui/dashboard/grid.cljs
+++ b/frontend/src/app/main/ui/dashboard/grid.cljs
@@ -20,7 +20,6 @@
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.components.color-bullet :as bc]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.file-menu :refer [file-menu]]
[app.main.ui.dashboard.import :refer [use-import-file]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
@@ -68,8 +67,7 @@
(mf/defc grid-item-thumbnail
{::mf/wrap-props false}
[{:keys [file-id revn thumbnail-uri background-color]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- container (mf/use-ref)
+ (let [container (mf/use-ref)
visible? (h/use-visible container :once? true)]
(mf/with-effect [file-id revn visible? thumbnail-uri]
@@ -83,28 +81,16 @@
:revn revn
:message (ex-message cause)))))))
- (if new-css-system
- [:div {:class (stl/css :grid-item-th)
- :style {:background-color background-color}
- :ref container}
- (when visible?
- (if thumbnail-uri
- [:img {:class (stl/css :grid-item-thumbnail-image)
- :src thumbnail-uri
- :loading "lazy"
- :decoding "async"}]
- i/loader-pencil))]
-
- ;; OLD
- [:div.grid-item-th
- {:style {:background-color background-color}
- :ref container}
- (when visible?
- (if thumbnail-uri
- [:img.grid-item-thumbnail-image {:src thumbnail-uri
- :loading "lazy"
- :decoding "async"}]
- i/loader-pencil))])))
+ [:div {:class (stl/css :grid-item-th)
+ :style {:background-color background-color}
+ :ref container}
+ (when visible?
+ (if thumbnail-uri
+ [:img {:class (stl/css :grid-item-thumbnail-image)
+ :src thumbnail-uri
+ :loading "lazy"
+ :decoding "async"}]
+ i/loader-pencil))]))
;; --- Grid Item Library
@@ -112,228 +98,125 @@
{::mf/wrap [mf/memo]}
[{:keys [file] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (mf/with-effect [file]
- (when file
- (let [font-ids (map :font-id (get-in file [:library-summary :typographies :sample] []))]
- (run! fonts/ensure-loaded! font-ids))))
+ (mf/with-effect [file]
+ (when file
+ (let [font-ids (map :font-id (get-in file [:library-summary :typographies :sample] []))]
+ (run! fonts/ensure-loaded! font-ids))))
- (if new-css-system
- [:div {:class (stl/css :grid-item-th :library)}
- (if (nil? file)
- i/loader-pencil
- (let [summary (:library-summary file)
- components (:components summary)
- colors (:colors summary)
- typographies (:typographies summary)]
- [:*
- (when (and (zero? (:count components)) (zero? (:count colors)) (zero? (:count typographies)))
- [:*
- [:div {:class (stl/css :asset-section)}
- [:div {:class (stl/css :asset-title)}
- [:span (tr "workspace.assets.components")]
- [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
- [:div {:class (stl/css :asset-section)}
- [:div {:class (stl/css :asset-title)}
- [:span (tr "workspace.assets.colors")]
- [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
- [:div {:class (stl/css :asset-section)}
- [:div {:class (stl/css :asset-title)}
- [:span (tr "workspace.assets.typography")]
- [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]]]) ;; Unicode 00A0 is non-breaking space
+ [:div {:class (stl/css :grid-item-th :library)}
+ (if (nil? file)
+ i/loader-pencil
+ (let [summary (:library-summary file)
+ components (:components summary)
+ colors (:colors summary)
+ typographies (:typographies summary)]
+ [:*
+ (when (and (zero? (:count components)) (zero? (:count colors)) (zero? (:count typographies)))
+ [:*
+ [:div {:class (stl/css :asset-section)}
+ [:div {:class (stl/css :asset-title)}
+ [:span (tr "workspace.assets.components")]
+ [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
+ [:div {:class (stl/css :asset-section)}
+ [:div {:class (stl/css :asset-title)}
+ [:span (tr "workspace.assets.colors")]
+ [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
+ [:div {:class (stl/css :asset-section)}
+ [:div {:class (stl/css :asset-title)}
+ [:span (tr "workspace.assets.typography")]
+ [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]]]) ;; Unicode 00A0 is non-breaking space
- (when (pos? (:count components))
- [:div {:class (stl/css :asset-section)}
- [:div {:class (stl/css :asset-title)}
- [:span (tr "workspace.assets.components")]
- [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
- [:div {:class (stl/css :asset-list)}
- (for [component (:sample components)]
- (let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
- [:div {:class (stl/css :asset-list-item)
- :key (str "assets-component-" (:id component))}
- [:& component-svg {:root-shape (get-in component [:objects root-id])
- :objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2
- [:div {:class (stl/css :name-block)}
- [:span {:class (stl/css :item-name)
- :title (:name component)}
- (:name component)]]]))
- (when (> (:count components) (count (:sample components)))
- [:div {:class (stl/css :asset-list-item)}
- [:div {:class (stl/css :name-block)}
- [:span {:class (stl/css :item-name)} "(...)"]]])]])
+ (when (pos? (:count components))
+ [:div {:class (stl/css :asset-section)}
+ [:div {:class (stl/css :asset-title)}
+ [:span (tr "workspace.assets.components")]
+ [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
+ [:div {:class (stl/css :asset-list)}
+ (for [component (:sample components)]
+ (let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
+ [:div {:class (stl/css :asset-list-item)
+ :key (str "assets-component-" (:id component))}
+ [:& component-svg {:root-shape (get-in component [:objects root-id])
+ :objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2
+ [:div {:class (stl/css :name-block)}
+ [:span {:class (stl/css :item-name)
+ :title (:name component)}
+ (:name component)]]]))
+ (when (> (:count components) (count (:sample components)))
+ [:div {:class (stl/css :asset-list-item)}
+ [:div {:class (stl/css :name-block)}
+ [:span {:class (stl/css :item-name)} "(...)"]]])]])
- (when (pos? (:count colors))
- [:div {:class (stl/css :asset-section)}
- [:div {:class (stl/css :asset-title)}
- [:span (tr "workspace.assets.colors")]
- [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count colors) ")"]] ;; Unicode 00A0 is non-breaking space
- [:div {:class (stl/css :asset-list)}
- (for [color (:sample colors)]
- (let [default-name (cond
- (:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
- (:color color) (:color color)
- :else (:value color))]
- [:div {:class (stl/css :asset-list-item)
- :key (str "assets-color-" (:id color))}
- [:& bc/color-bullet {:color {:color (:color color)
- :opacity (:opacity color)}}]
- [:div {:class (stl/css :name-block)}
- [:span {:class (stl/css :color-name)} (:name color)]
- (when-not (= (:name color) default-name)
- [:span {:class (stl/css :color-value)} (:color color)])]]))
+ (when (pos? (:count colors))
+ [:div {:class (stl/css :asset-section)}
+ [:div {:class (stl/css :asset-title)}
+ [:span (tr "workspace.assets.colors")]
+ [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count colors) ")"]] ;; Unicode 00A0 is non-breaking space
+ [:div {:class (stl/css :asset-list)}
+ (for [color (:sample colors)]
+ (let [default-name (cond
+ (:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
+ (:color color) (:color color)
+ :else (:value color))]
+ [:div {:class (stl/css :asset-list-item)
+ :key (str "assets-color-" (:id color))}
+ [:& bc/color-bullet {:color {:color (:color color)
+ :opacity (:opacity color)}}]
+ [:div {:class (stl/css :name-block)}
+ [:span {:class (stl/css :color-name)} (:name color)]
+ (when-not (= (:name color) default-name)
+ [:span {:class (stl/css :color-value)} (:color color)])]]))
- (when (> (:count colors) (count (:sample colors)))
- [:div {:class (stl/css :asset-list-item)}
- [:div {:class (stl/css :name-block)}
- [:span {:class (stl/css :item-name)} "(...)"]]])]])
+ (when (> (:count colors) (count (:sample colors)))
+ [:div {:class (stl/css :asset-list-item)}
+ [:div {:class (stl/css :name-block)}
+ [:span {:class (stl/css :item-name)} "(...)"]]])]])
- (when (pos? (:count typographies))
- [:div {:class (stl/css :asset-section)}
- [:div {:class (stl/css :asset-title)}
- [:span (tr "workspace.assets.typography")]
- [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count typographies) ")"]] ;; Unicode 00A0 is non-breaking space
- [:div {:class (stl/css :asset-list)}
- (for [typography (:sample typographies)]
- [:div {:class (stl/css :asset-list-item)
- :key (str "assets-typography-" (:id typography))}
- [:div {:class (stl/css :typography-sample)
- :style {:font-family (:font-family typography)
- :font-weight (:font-weight typography)
- :font-style (:font-style typography)}}
- (tr "workspace.assets.typography.sample")]
- [:div {:class (stl/css :name-block)}
- [:span {:class (stl/css :item-name)
- :title (:name typography)}
- (:name typography)]]])
+ (when (pos? (:count typographies))
+ [:div {:class (stl/css :asset-section)}
+ [:div {:class (stl/css :asset-title)}
+ [:span (tr "workspace.assets.typography")]
+ [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count typographies) ")"]] ;; Unicode 00A0 is non-breaking space
+ [:div {:class (stl/css :asset-list)}
+ (for [typography (:sample typographies)]
+ [:div {:class (stl/css :asset-list-item)
+ :key (str "assets-typography-" (:id typography))}
+ [:div {:class (stl/css :typography-sample)
+ :style {:font-family (:font-family typography)
+ :font-weight (:font-weight typography)
+ :font-style (:font-style typography)}}
+ (tr "workspace.assets.typography.sample")]
+ [:div {:class (stl/css :name-block)}
+ [:span {:class (stl/css :item-name)
+ :title (:name typography)}
+ (:name typography)]]])
- (when (> (:count typographies) (count (:sample typographies)))
- [:div {:class (stl/css :asset-list-item)}
- [:div {:class (stl/css :name-block)}
- [:span {:class (stl/css :item-name)} "(...)"]]])]])]))]
-
- ;; OLD
- [:div.grid-item-th.library
- (if (nil? file)
- i/loader-pencil
- (let [summary (:library-summary file)
- components (:components summary)
- colors (:colors summary)
- typographies (:typographies summary)]
- [:*
-
- (when (and (zero? (:count components)) (zero? (:count colors)) (zero? (:count typographies)))
- [:*
- [:div.asset-section
- [:div.asset-title
- [:span (tr "workspace.assets.components")]
- [:span.num-assets (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
- [:div.asset-section
- [:div.asset-title
- [:span (tr "workspace.assets.colors")]
- [:span.num-assets (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
- [:div.asset-section
- [:div.asset-title
- [:span (tr "workspace.assets.typography")]
- [:span.num-assets (str "\u00A0(") 0 ")"]]]]) ;; Unicode 00A0 is non-breaking space
-
-
- (when (pos? (:count components))
- [:div.asset-section
- [:div.asset-title
- [:span (tr "workspace.assets.components")]
- [:span.num-assets (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
- [:div.asset-list
- (for [component (:sample components)]
- (let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
- [:div.asset-list-item {:key (str "assets-component-" (:id component))}
- [:& component-svg {:root-shape (get-in component [:objects root-id])
- :objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2
- [:div.name-block
- [:span.item-name {:title (:name component)}
- (:name component)]]]))
- (when (> (:count components) (count (:sample components)))
- [:div.asset-list-item
- [:div.name-block
- [:span.item-name "(...)"]]])]])
-
- (when (pos? (:count colors))
- [:div.asset-section
- [:div.asset-title
- [:span (tr "workspace.assets.colors")]
- [:span.num-assets (str "\u00A0(") (:count colors) ")"]] ;; Unicode 00A0 is non-breaking space
- [:div.asset-list
- (for [color (:sample colors)]
- (let [default-name (cond
- (:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
- (:color color) (:color color)
- :else (:value color))]
- [:div.asset-list-item {:key (str "assets-color-" (:id color))}
- [:& bc/color-bullet {:color {:color (:color color)
- :opacity (:opacity color)}}]
- [:div.name-block
- [:span.color-name (:name color)]
- (when-not (= (:name color) default-name)
- [:span.color-value (:color color)])]]))
- (when (> (:count colors) (count (:sample colors)))
- [:div.asset-list-item
- [:div.name-block
- [:span.item-name "(...)"]]])]])
-
- (when (pos? (:count typographies))
- [:div.asset-section
- [:div.asset-title
- [:span (tr "workspace.assets.typography")]
- [:span.num-assets (str "\u00A0(") (:count typographies) ")"]] ;; Unicode 00A0 is non-breaking space
- [:div.asset-list
- (for [typography (:sample typographies)]
- [:div.asset-list-item {:key (str "assets-typography-" (:id typography))}
- [:div.typography-sample
- {:style {:font-family (:font-family typography)
- :font-weight (:font-weight typography)
- :font-style (:font-style typography)}}
- (tr "workspace.assets.typography.sample")]
- [:div.name-block
- [:span.item-name {:title (:name typography)}
- (:name typography)]]])
- (when (> (:count typographies) (count (:sample typographies)))
- [:div.asset-list-item
- [:div.name-block
- [:span.item-name "(...)"]]])]])]))])))
+ (when (> (:count typographies) (count (:sample typographies)))
+ [:div {:class (stl/css :asset-list-item)}
+ [:div {:class (stl/css :name-block)}
+ [:span {:class (stl/css :item-name)} "(...)"]]])]])]))])
;; --- Grid Item
(mf/defc grid-item-metadata
[{:keys [modified-at]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- locale (mf/deref i18n/locale)
+ (let [locale (mf/deref i18n/locale)
time (dt/timeago modified-at {:locale locale})]
- (if new-css-system
- [:span {:class (stl/css :date)} time]
-
- ;; OLD
- [:span.date time])))
+ [:span {:class (stl/css :date)} time]))
(defn create-counter-element
- [_element file-count new-css-system]
- (if new-css-system
- (let [counter-el (dom/create-element "div")]
- (dom/set-property! counter-el "class" (stl/css :drag-counter))
- (dom/set-text! counter-el (str file-count))
- counter-el)
-
- (let [counter-el (dom/create-element "div")]
- (dom/set-property! counter-el "class" "drag-counter")
- (dom/set-text! counter-el (str file-count))
- counter-el)))
+ [_element file-count]
+ (let [counter-el (dom/create-element "div")]
+ (dom/set-property! counter-el "class" (stl/css :drag-counter))
+ (dom/set-text! counter-el (str file-count))
+ counter-el))
(mf/defc grid-item
{:wrap [mf/memo]}
[{:keys [file navigate? origin library-view?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- file-id (:id file)
+ (let [file-id (:id file)
local (mf/use-state {:menu-open false
:menu-pos nil
:edition false})
@@ -380,8 +263,7 @@
item-el
(if select-current?
1
- (count selected-files))
- new-css-system)]
+ (count selected-files)))]
(when select-current?
(st/emit! (dd/clear-selected-files))
(st/emit! (dd/toggle-file-select file)))
@@ -453,132 +335,67 @@
(when (and (not selected?) (:menu-open @local))
(swap! local assoc :menu-open false)))
- (if new-css-system
- [:li
- {:class (stl/css-case :grid-item true :project-th true :library library-view?)}
- [:button
- {:class (stl/css-case :selected selected? :library library-view?)
- :ref node-ref
- :title (:name file)
- :draggable true
- :on-click on-select
- :on-key-down handle-key-down
- :on-double-click on-navigate
- :on-drag-start on-drag-start
- :on-context-menu on-menu-click}
+ [:li
+ {:class (stl/css-case :grid-item true :project-th true :library library-view?)}
+ [:button
+ {:class (stl/css-case :selected selected? :library library-view?)
+ :ref node-ref
+ :title (:name file)
+ :draggable true
+ :on-click on-select
+ :on-key-down handle-key-down
+ :on-double-click on-navigate
+ :on-drag-start on-drag-start
+ :on-context-menu on-menu-click}
- [:div {:class (stl/css :overlay)}]
+ [:div {:class (stl/css :overlay)}]
- (if library-view?
- [:& grid-item-library {:file file}]
- [:& grid-item-thumbnail
- {:file-id (:id file)
- :revn (:revn file)
- :thumbnail-uri (:thumbnail-uri file)
- :background-color (dm/get-in file [:data :options :background])}])
+ (if library-view?
+ [:& grid-item-library {:file file}]
+ [:& grid-item-thumbnail
+ {:file-id (:id file)
+ :revn (:revn file)
+ :thumbnail-uri (:thumbnail-uri file)
+ :background-color (dm/get-in file [:data :options :background])}])
- (when (and (:is-shared file) (not library-view?))
- [:div {:class (stl/css :item-badge)} i/library])
+ (when (and (:is-shared file) (not library-view?))
+ [:div {:class (stl/css :item-badge)} i/library])
- [:div {:class (stl/css :info-wrapper)}
- [:div {:class (stl/css :item-info)}
- (if (:edition @local)
- [:& inline-edition {:content (:name file)
- :on-end edit}]
- [:h3 (:name file)])
- [:& grid-item-metadata {:modified-at (:modified-at file)}]]
+ [:div {:class (stl/css :info-wrapper)}
+ [:div {:class (stl/css :item-info)}
+ (if (:edition @local)
+ [:& inline-edition {:content (:name file)
+ :on-end edit}]
+ [:h3 (:name file)])
+ [:& grid-item-metadata {:modified-at (:modified-at file)}]]
- [:div {:class (stl/css-case :project-th-actions true :force-display (:menu-open @local))}
- [:div
- {:class (stl/css :project-th-icon :menu)
- :tab-index "0"
- :ref menu-ref
- :id (str file-id "-action-menu")
- :on-click on-menu-click
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/stop-propagation event)
- (on-menu-click event)))}
- i/actions
- (when selected?
- [:& file-menu {:files (vals selected-files)
- :show? (:menu-open @local)
- :left (+ 24 (:x (:menu-pos @local)))
- :top (:y (:menu-pos @local))
- :navigate? navigate?
- :on-edit on-edit
- :on-menu-close on-menu-close
- :origin origin
- :dashboard-local dashboard-local
- :parent-id (str file-id "-action-menu")}])]]]]]
-
- ;; OLD
- [:li.grid-item.project-th {:class (dom/classnames :library library-view?)}
- [:button
- {:tab-index "0"
- :class (dom/classnames :selected selected?
- :library library-view?)
- :ref node-ref
- :draggable true
- :on-click on-select
- :on-key-down (fn [event]
- (dom/stop-propagation event)
- (when (kbd/enter? event)
- (on-navigate event))
- (when (kbd/shift? event)
- (when (or (kbd/down-arrow? event) (kbd/left-arrow? event) (kbd/up-arrow? event) (kbd/right-arrow? event))
- (on-select event)) ;; TODO Fix this
- ))
- :on-double-click on-navigate
- :on-drag-start on-drag-start
- :on-context-menu on-menu-click}
-
- [:div.overlay]
- (if library-view?
- [:& grid-item-library {:file file}]
- [:& grid-item-thumbnail
- {:file-id (:id file)
- :revn (:revn file)
- :thumbnail-uri (:thumbnail-uri file)
- :background-color (dm/get-in file [:data :options :background])}])
-
- (when (and (:is-shared file) (not library-view?))
- [:div.item-badge i/library])
- [:div.info-wrapper
- [:div.item-info
- (if (:edition @local)
- [:& inline-edition {:content (:name file)
- :on-end edit}]
- [:h3 (:name file)])
- [:& grid-item-metadata {:modified-at (:modified-at file)}]]
- [:div.project-th-actions {:class (dom/classnames
- :force-display (:menu-open @local))}
- [:div.project-th-icon.menu
- {:tab-index "0"
- :ref menu-ref
- :id (str file-id "-action-menu")
- :on-click on-menu-click
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/stop-propagation event)
- (on-menu-click event)))}
- i/actions
- (when selected?
- [:& file-menu {:files (vals selected-files)
- :show? (:menu-open @local)
- :left (+ 24 (:x (:menu-pos @local)))
- :top (:y (:menu-pos @local))
- :navigate? navigate?
- :on-edit on-edit
- :on-menu-close on-menu-close
- :origin origin
- :dashboard-local dashboard-local
- :parent-id (str file-id "-action-menu")}])]]]]])))
+ [:div {:class (stl/css-case :project-th-actions true :force-display (:menu-open @local))}
+ [:div
+ {:class (stl/css :project-th-icon :menu)
+ :tab-index "0"
+ :ref menu-ref
+ :id (str file-id "-action-menu")
+ :on-click on-menu-click
+ :on-key-down (fn [event]
+ (when (kbd/enter? event)
+ (dom/stop-propagation event)
+ (on-menu-click event)))}
+ i/actions
+ (when selected?
+ [:& file-menu {:files (vals selected-files)
+ :show? (:menu-open @local)
+ :left (+ 24 (:x (:menu-pos @local)))
+ :top (:y (:menu-pos @local))
+ :navigate? navigate?
+ :on-edit on-edit
+ :on-menu-close on-menu-close
+ :origin origin
+ :dashboard-local dashboard-local
+ :parent-id (str file-id "-action-menu")}])]]]]]))
(mf/defc grid
[{:keys [files project origin limit library-view? create-fn] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- dragging? (mf/use-state false)
+ (let [dragging? (mf/use-state false)
project-id (:id project)
node-ref (mf/use-var nil)
@@ -621,109 +438,58 @@
(reset! dragging? false)
(import-files (.-files (.-dataTransfer e))))))]
- (if new-css-system
- [:div
- {:class (stl/css :dashboard-grid)
- :on-drag-enter on-drag-enter
- :on-drag-over on-drag-over
- :on-drag-leave on-drag-leave
- :on-drop on-drop
- :ref node-ref}
+ [:div {:class (stl/css :dashboard-grid)
+ :on-drag-enter on-drag-enter
+ :on-drag-over on-drag-over
+ :on-drag-leave on-drag-leave
+ :on-drop on-drop
+ :ref node-ref}
- (cond
- (nil? files)
- [:& loading-placeholder]
-
- (seq files)
- (for [slice (partition-all limit files)]
- [:ul {:class (stl/css :grid-row)}
- (when @dragging?
- [:li {:class (stl/css :grid-item)}])
- (for [item slice]
- [:& grid-item
- {:file item
- :key (:id item)
- :navigate? true
- :origin origin
- :library-view? library-view?}])])
-
- :else
- [:& empty-placeholder
- {:limit limit
- :create-fn create-fn
- :origin origin}])]
-
- ;; OLD
- [:div.dashboard-grid
- {:on-drag-enter on-drag-enter
- :on-drag-over on-drag-over
- :on-drag-leave on-drag-leave
- :on-drop on-drop
- :ref node-ref}
- (cond
- (nil? files)
- [:& loading-placeholder]
-
- (seq files)
- [:ul.grid-row
- {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
+ (cond
+ (nil? files)
+ [:& loading-placeholder]
+ (seq files)
+ (for [slice (partition-all limit files)]
+ [:ul {:class (stl/css :grid-row)}
(when @dragging?
- [:li.grid-item])
-
- (for [item files]
+ [:li {:class (stl/css :grid-item)}])
+ (for [item slice]
[:& grid-item
{:file item
:key (:id item)
:navigate? true
:origin origin
- :library-view? library-view?}])]
+ :library-view? library-view?}])])
- :else
- [:& empty-placeholder
- {:limit limit
- :create-fn create-fn
- :origin origin}])])))
+ :else
+ [:& empty-placeholder
+ {:limit limit
+ :create-fn create-fn
+ :origin origin}])]))
(mf/defc line-grid-row
[{:keys [files selected-files dragging? limit] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- elements limit
+ (let [elements limit
limit (if dragging? (dec limit) limit)]
- (if new-css-system
- [:ul
- {:class (stl/css :grid-row :no-wrap)
- :style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
+ [:ul
+ {:class (stl/css :grid-row :no-wrap)
+ :style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
- (when dragging?
- [:li {:class (stl/css :grid-item :dragged)}])
+ (when dragging?
+ [:li {:class (stl/css :grid-item :dragged)}])
- (for [item (take limit files)]
- [:& grid-item
- {:id (:id item)
- :file item
- :selected-files selected-files
- :key (:id item)
- :navigate? false}])]
-
- ;; OLD
- [:ul.grid-row.no-wrap
- {:style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
-
- (when dragging?
- [:li.grid-item.dragged])
- (for [item (take limit files)]
- [:& grid-item
- {:id (:id item)
- :file item
- :selected-files selected-files
- :key (:id item)
- :navigate? false}])])))
+ (for [item (take limit files)]
+ [:& grid-item
+ {:id (:id item)
+ :file item
+ :selected-files selected-files
+ :key (:id item)
+ :navigate? false}])]))
(mf/defc line-grid
[{:keys [project team files limit create-fn] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- dragging? (mf/use-state false)
+ (let [dragging? (mf/use-state false)
project-id (:id project)
team-id (:id team)
@@ -799,47 +565,24 @@
(reset! dragging? false)
(import-files (.-files (.-dataTransfer e)))))))]
- (if new-css-system
- [:div {:class (stl/css :dashboard-grid)
- :on-drag-enter on-drag-enter
- :on-drag-over on-drag-over
- :on-drag-leave on-drag-leave
- :on-drop on-drop}
- (cond
- (nil? files)
- [:& loading-placeholder]
+ [:div {:class (stl/css :dashboard-grid)
+ :on-drag-enter on-drag-enter
+ :on-drag-over on-drag-over
+ :on-drag-leave on-drag-leave
+ :on-drop on-drop}
+ (cond
+ (nil? files)
+ [:& loading-placeholder]
- (seq files)
- [:& line-grid-row {:files files
- :team-id team-id
- :selected-files selected-files
- :dragging? @dragging?
- :limit limit}]
+ (seq files)
+ [:& line-grid-row {:files files
+ :team-id team-id
+ :selected-files selected-files
+ :dragging? @dragging?
+ :limit limit}]
- :else
- [:& empty-placeholder
- {:dragging? @dragging?
- :limit limit
- :create-fn create-fn}])]
-
- ;; OLD
- [:div.dashboard-grid {:on-drag-enter on-drag-enter
- :on-drag-over on-drag-over
- :on-drag-leave on-drag-leave
- :on-drop on-drop}
- (cond
- (nil? files)
- [:& loading-placeholder]
-
- (seq files)
- [:& line-grid-row {:files files
- :team-id team-id
- :selected-files selected-files
- :dragging? @dragging?
- :limit limit}]
-
- :else
- [:& empty-placeholder
- {:dragging? @dragging?
- :limit limit
- :create-fn create-fn}])])))
+ :else
+ [:& empty-placeholder
+ {:dragging? @dragging?
+ :limit limit
+ :create-fn create-fn}])]))
diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs
index d0d4b4d2c5..2ac73e4214 100644
--- a/frontend/src/app/main/ui/dashboard/import.cljs
+++ b/frontend/src/app/main/ui/dashboard/import.cljs
@@ -18,7 +18,6 @@
[app.main.features :as features]
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.worker :as uw]
[app.util.dom :as dom]
@@ -152,8 +151,7 @@
(mf/defc import-entry
[{:keys [state file editing? can-be-deleted?]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- loading? (or (= :analyzing (:status file))
+ (let [loading? (or (= :analyzing (:status file))
(= :importing (:status file)))
analyze-error? (= :analyze-error (:status file))
import-finish? (= :import-finish (:status file))
@@ -191,122 +189,66 @@
(fn []
(swap! state update :files remove-file (:file-id file))))]
- (if new-css-system
- [:div {:class (stl/css-case :file-entry true
- :loading loading?
- :success (and import-finish? (not import-warn?) (not import-error?))
- :warning (and import-finish? import-warn? (not import-error?))
- :error (or import-error? analyze-error?)
- :editable (and ready? (not editing?)))}
+ [:div {:class (stl/css-case :file-entry true
+ :loading loading?
+ :success (and import-finish? (not import-warn?) (not import-error?))
+ :warning (and import-finish? import-warn? (not import-error?))
+ :error (or import-error? analyze-error?)
+ :editable (and ready? (not editing?)))}
- [:div {:class (stl/css :file-name)}
- [:div {:class (stl/css-case :file-icon true
- :icon-fill ready?)}
- (cond loading? i/loader-pencil
- ready? i/logo-icon
- import-warn? i/msg-warning
- import-error? i/close-refactor
- import-finish? i/tick-refactor
- analyze-error? i/close-refactor)]
+ [:div {:class (stl/css :file-name)}
+ [:div {:class (stl/css-case :file-icon true
+ :icon-fill ready?)}
+ (cond loading? i/loader-pencil
+ ready? i/logo-icon
+ import-warn? i/msg-warning
+ import-error? i/close-refactor
+ import-finish? i/tick-refactor
+ analyze-error? i/close-refactor)]
- (if editing?
- [:div {:class (stl/css :file-name-edit)}
- [:input {:type "text"
- :auto-focus true
- :default-value (:name file)
- :on-key-press handle-edit-key-press
- :on-blur handle-edit-blur}]]
+ (if editing?
+ [:div {:class (stl/css :file-name-edit)}
+ [:input {:type "text"
+ :auto-focus true
+ :default-value (:name file)
+ :on-key-press handle-edit-key-press
+ :on-blur handle-edit-blur}]]
- [:div {:class (stl/css :file-name-label)}
- (:name file)
- (when is-shared? i/library-refactor)])
+ [:div {:class (stl/css :file-name-label)}
+ (:name file)
+ (when is-shared? i/library-refactor)])
- [:div {:class (stl/css :edit-entry-buttons)}
- (when (= "application/zip" (:type file))
- [:button {:on-click handle-edit-entry} i/curve-refactor])
- (when can-be-deleted?
- [:button {:on-click handle-remove-entry} i/delete-refactor])]]
- (cond
- analyze-error?
- [:div {:class (stl/css :error-message)}
- (tr "dashboard.import.analyze-error")]
+ [:div {:class (stl/css :edit-entry-buttons)}
+ (when (= "application/zip" (:type file))
+ [:button {:on-click handle-edit-entry} i/curve-refactor])
+ (when can-be-deleted?
+ [:button {:on-click handle-remove-entry} i/delete-refactor])]]
+ (cond
+ analyze-error?
+ [:div {:class (stl/css :error-message)}
+ (tr "dashboard.import.analyze-error")]
- import-error?
- [:div {:class (stl/css :error-message)}
- (tr "dashboard.import.import-error")]
+ import-error?
+ [:div {:class (stl/css :error-message)}
+ (tr "dashboard.import.import-error")]
- (and (not import-finish?) (some? progress))
- [:div {:class (stl/css :progress-message)} (parse-progress-message progress)])
+ (and (not import-finish?) (some? progress))
+ [:div {:class (stl/css :progress-message)} (parse-progress-message progress)])
- [:div {:class (stl/css :linked-libraries)}
- (for [library-id (:libraries file)]
- (let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
- error? (or (:deleted? library-data) (:import-error library-data))]
- (when (some? library-data)
- [:div {:class (stl/css-case :linked-library-tag true
- :error error?)}
- i/detach-refactor (:name library-data)])))]]
-
-
- [:div.file-entry
- {:class (dom/classnames
- :loading loading?
- :success (and import-finish? (not import-warn?) (not import-error?))
- :warning (and import-finish? import-warn? (not import-error?))
- :error (or import-error? analyze-error?)
- :editable (and ready? (not editing?)))}
-
- [:div.file-name
- [:div.file-icon
- (cond loading? i/loader-pencil
- ready? i/logo-icon
- import-warn? i/msg-warning
- import-error? i/close
- import-finish? i/tick
- analyze-error? i/close)]
-
- (if editing?
- [:div.file-name-edit
- [:input {:type "text"
- :auto-focus true
- :default-value (:name file)
- :on-key-press handle-edit-key-press
- :on-blur handle-edit-blur}]]
-
- [:div.file-name-label (:name file) (when is-shared? i/library)])
-
- [:div.edit-entry-buttons
- (when (= "application/zip" (:type file))
- [:button {:on-click handle-edit-entry} i/pencil])
- (when can-be-deleted?
- [:button {:on-click handle-remove-entry} i/trash])]]
-
- (cond
- analyze-error?
- [:div.error-message
- (tr "dashboard.import.analyze-error")]
-
- import-error?
- [:div.error-message
- (tr "dashboard.import.import-error")]
-
- (and (not import-finish?) (some? progress))
- [:div.progress-message (parse-progress-message progress)])
-
- [:div.linked-libraries
- (for [library-id (:libraries file)]
- (let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
- error? (or (:deleted? library-data) (:import-error library-data))]
- (when (some? library-data)
- [:div.linked-library-tag {:class (when error? "error")}
- (if error? i/unchain i/chain) (:name library-data)])))]])))
+ [:div {:class (stl/css :linked-libraries)}
+ (for [library-id (:libraries file)]
+ (let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
+ error? (or (:deleted? library-data) (:import-error library-data))]
+ (when (some? library-data)
+ [:div {:class (stl/css-case :linked-library-tag true
+ :error error?)}
+ i/detach-refactor (:name library-data)])))]]))
(mf/defc import-dialog
{::mf/register modal/components
::mf/register-as :import}
[{:keys [project-id files template on-finish-import]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- state (mf/use-state
+ (let [state (mf/use-state
{:status :analyzing
:editing nil
:importing-templates 0
@@ -425,122 +367,60 @@
#(doseq [file files]
(wapi/revoke-uri (:uri file)))))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click handle-cancel} i/close-refactor]]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click handle-cancel} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :modal-content)}
- (when (and (= :importing (:status @state)) (not pending-import?))
- (if (> warning-files 0)
- [:div {:class (stl/css-case :feedback-banner true
- :warning true)}
- [:div {:class (stl/css :icon)} i/msg-warning-refactor]
- [:div {:class (stl/css :message)} (tr "dashboard.import.import-warning" warning-files success-files)]]
+ (when (and (= :importing (:status @state)) (not pending-import?))
+ (if (> warning-files 0)
+ [:div {:class (stl/css-case :feedback-banner true
+ :warning true)}
+ [:div {:class (stl/css :icon)} i/msg-warning-refactor]
+ [:div {:class (stl/css :message)} (tr "dashboard.import.import-warning" warning-files success-files)]]
- [:div {:class (stl/css :feedback-banner)}
- [:div {:class (stl/css :icon)} i/msg-success-refactor]
- [:div {:class (stl/css :message)} (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
+ [:div {:class (stl/css :feedback-banner)}
+ [:div {:class (stl/css :icon)} i/msg-success-refactor]
+ [:div {:class (stl/css :message)} (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
- (for [file files]
- (let [editing? (and (some? (:file-id file))
- (= (:file-id file) (:editing @state)))]
- [:& import-entry {:state state
- :key (dm/str (:uri file))
- :file file
- :editing? editing?
- :can-be-deleted? (> (count files) 1)}]))
-
- (when (some? template)
+ (for [file files]
+ (let [editing? (and (some? (:file-id file))
+ (= (:file-id file) (:editing @state)))]
[:& import-entry {:state state
- :file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
- :editing? false
- :can-be-deleted? false}])]
+ :key (dm/str (:uri file))
+ :file file
+ :editing? editing?
+ :can-be-deleted? (> (count files) 1)}]))
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- (when (= :analyzing (:status @state))
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.cancel")
- :on-click handle-cancel}])
+ (when (some? template)
+ [:& import-entry {:state state
+ :file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
+ :editing? false
+ :can-be-deleted? false}])]
- (when (= :analyzing (:status @state))
- [:input {:class (stl/css :accept-btn)
- :type "button"
- :value (tr "labels.continue")
- :disabled (or pending-analysis? (not valid-files?))
- :on-click handle-continue}])
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ (when (= :analyzing (:status @state))
+ [:input {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.cancel")
+ :on-click handle-cancel}])
- (when (= :importing (:status @state))
- [:input {:class (stl/css :accept-btn)
- :type "button"
- :value (tr "labels.accept")
- :disabled (or pending-import? (not valid-files?))
- :on-click handle-accept}])]]]]
+ (when (= :analyzing (:status @state))
+ [:input {:class (stl/css :accept-btn)
+ :type "button"
+ :value (tr "labels.continue")
+ :disabled (or pending-analysis? (not valid-files?))
+ :on-click handle-continue}])
-
-
- [:div.modal-overlay
- [:div.modal-container.import-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 (tr "dashboard.import")]]
-
- [:div.modal-close-button
- {:on-click handle-cancel} i/close]]
-
- [:div.modal-content
- (when (and (= :importing (:status @state)) (not pending-import?))
- (if (> warning-files 0)
- [:div.feedback-banner.warning
- [:div.icon i/msg-warning]
- [:div.message (tr "dashboard.import.import-warning" warning-files success-files)]]
-
- [:div.feedback-banner
- [:div.icon i/checkbox-checked]
- [:div.message (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
-
- (for [file files]
- (let [editing? (and (some? (:file-id file))
- (= (:file-id file) (:editing @state)))]
- [:& import-entry {:state state
- :key (dm/str (:uri file))
- :file file
- :editing? editing?
- :can-be-deleted? (> (count files) 1)}]))
-
- (when (some? template)
- [:& import-entry {:state state
- :file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
- :editing? false
- :can-be-deleted? false}])]
-
- [:div.modal-footer
- [:div.action-buttons
- (when (= :analyzing (:status @state))
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.cancel")
- :on-click handle-cancel}])
-
- (when (= :analyzing (:status @state))
- [:input.accept-button
- {:class "primary"
- :type "button"
- :value (tr "labels.continue")
- :disabled (or pending-analysis? (not valid-files?))
- :on-click handle-continue}])
-
- (when (= :importing (:status @state))
- [:input.accept-button
- {:class "primary"
- :type "button"
- :value (tr "labels.accept")
- :disabled (or pending-import? (not valid-files?))
- :on-click handle-accept}])]]]])))
+ (when (= :importing (:status @state))
+ [:input {:class (stl/css :accept-btn)
+ :type "button"
+ :value (tr "labels.accept")
+ :disabled (or pending-import? (not valid-files?))
+ :on-click handle-accept}])]]]]))
diff --git a/frontend/src/app/main/ui/dashboard/import.scss b/frontend/src/app/main/ui/dashboard/import.scss
index 3ed738462e..4221530e0d 100644
--- a/frontend/src/app/main/ui/dashboard/import.scss
+++ b/frontend/src/app/main/ui/dashboard/import.scss
@@ -8,69 +8,72 @@
.modal-overlay {
@extend .modal-overlay-base;
+}
- .modal-container {
- @extend .modal-container-base;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
+.modal-container {
+ @extend .modal-container-base;
+ border: $s-1 solid var(--modal-border-color);
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.feedback-banner {
+ @include flexRow;
+ height: $s-32;
+ width: 100%;
+ margin-bottom: $s-24;
+ border-radius: $br-8;
+ background-color: var(--alert-background-color-ok);
+ color: var(--alert-foreground-color-ok);
+
+ .icon {
+ @include flexCenter;
+ height: $s-24;
+ width: $s-24;
+ svg {
+ @extend .button-icon;
+ stroke: var(--alert-foreground-color-ok);
}
-
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .feedback-banner {
- @include flexRow;
- height: $s-32;
- width: 100%;
- margin-bottom: $s-24;
- border-radius: $br-8;
- background-color: var(--alert-background-color-ok);
- color: var(--alert-foreground-color-ok);
-
- .icon {
- @include flexCenter;
- height: $s-24;
- width: $s-24;
- svg {
- @extend .button-icon;
- stroke: var(--alert-foreground-color-ok);
- }
- }
- .message {
- @include titleTipography;
- }
- &.warning {
- background-color: var(--alert-background-color-warning);
- color: var(--alert-foreground-color-warning);
- .icon svg {
- stroke: var(--alert-foreground-color-warning);
- }
- }
- }
+ }
+ .message {
+ @include titleTipography;
+ }
+ &.warning {
+ background-color: var(--alert-background-color-warning);
+ color: var(--alert-foreground-color-warning);
+ .icon svg {
+ stroke: var(--alert-foreground-color-warning);
}
+ }
+}
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
@@ -122,6 +125,7 @@
.error-message,
.progress-message {
height: $s-32;
+ color: var(--modal-text-foreground-color);
}
.linked-libraries {
diff --git a/frontend/src/app/main/ui/dashboard/inline_edition.cljs b/frontend/src/app/main/ui/dashboard/inline_edition.cljs
index 00d269066d..499f522143 100644
--- a/frontend/src/app/main/ui/dashboard/inline_edition.cljs
+++ b/frontend/src/app/main/ui/dashboard/inline_edition.cljs
@@ -7,7 +7,6 @@
(ns app.main.ui.dashboard.inline-edition
(:require-macros [app.main.style :as stl])
(:require
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
@@ -15,8 +14,7 @@
(mf/defc inline-edition
[{:keys [content on-end] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- name (mf/use-state content)
+ (let [name (mf/use-state content)
input-ref (mf/use-ref)
on-input
@@ -62,25 +60,14 @@
(dom/focus! node)
(dom/select-text! node))))
- (if new-css-system
- [:div {:class (stl/css :edit-wrapper)}
- [:input {:class (stl/css :element-title)
- :value @name
- :ref input-ref
- :on-click on-click
- :on-change on-input
- :on-key-down on-keyup
- :on-blur on-blur}]
- [:span {:class (stl/css :close)
- :on-click on-cancel} i/close]]
-
- ;; OLD
- [:div.edit-wrapper
- [:input.element-title {:value @name
- :ref input-ref
- :on-click on-click
- :on-change on-input
- :on-key-down on-keyup
- :on-blur on-blur}]
- [:span.close {:on-click on-cancel} i/close]])))
+ [:div {:class (stl/css :edit-wrapper)}
+ [:input {:class (stl/css :element-title)
+ :value @name
+ :ref input-ref
+ :on-click on-click
+ :on-change on-input
+ :on-key-down on-keyup
+ :on-blur on-blur}]
+ [:span {:class (stl/css :close)
+ :on-click on-cancel} i/close-refactor]]))
diff --git a/frontend/src/app/main/ui/dashboard/inline_edition.scss b/frontend/src/app/main/ui/dashboard/inline_edition.scss
index 8abb170cb0..0c84951f9c 100644
--- a/frontend/src/app/main/ui/dashboard/inline_edition.scss
+++ b/frontend/src/app/main/ui/dashboard/inline_edition.scss
@@ -12,42 +12,42 @@
padding-right: $s-24;
position: relative;
margin-right: $s-24;
+}
- input.element-title {
- background-color: $db-primary;
- border-radius: $br-8;
- color: $df-primary;
- font-size: $fs-16;
- height: $s-32;
- margin: 0;
- border: none;
- padding: $s-6;
- width: 100%;
+input.element-title {
+ background-color: $db-primary;
+ border-radius: $br-8;
+ color: $df-primary;
+ font-size: $fs-16;
+ height: $s-32;
+ margin: 0;
+ border: none;
+ padding: $s-6;
+ width: 100%;
- &:focus-visible {
- border: $s-1 solid $da-primary;
- outline: none;
- }
+ &:focus-visible {
+ border: $s-1 solid $da-primary;
+ outline: none;
}
+}
- .close {
- cursor: pointer;
- position: absolute;
+.close {
+ cursor: pointer;
+ position: absolute;
- top: $s-1;
- right: calc(-1 * $s-8);
+ top: $s-1;
+ right: calc(-1 * $s-8);
+ svg {
+ fill: $df-secondary;
+ height: $s-16;
+ transform: rotate(45deg) translateY(7px);
+ width: $s-16;
+ margin: 0;
+ }
+ &:hover {
svg {
- fill: $df-secondary;
- height: $s-16;
- transform: rotate(45deg) translateY(7px);
- width: $s-16;
- margin: 0;
- }
- &:hover {
- svg {
- fill: var(--warning-color);
- }
+ fill: var(--warning-color);
}
}
}
diff --git a/frontend/src/app/main/ui/dashboard/libraries.cljs b/frontend/src/app/main/ui/dashboard/libraries.cljs
index 2b80c8439b..dd543c154e 100644
--- a/frontend/src/app/main/ui/dashboard/libraries.cljs
+++ b/frontend/src/app/main/ui/dashboard/libraries.cljs
@@ -12,7 +12,6 @@
[app.main.features :as features]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [grid]]
[app.main.ui.hooks :as hooks]
[app.util.dom :as dom]
@@ -21,8 +20,7 @@
(mf/defc libraries-page
[{:keys [team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- files-map (mf/deref refs/dashboard-shared-files)
+ (let [files-map (mf/deref refs/dashboard-shared-files)
projects (mf/deref refs/dashboard-projects)
default-project (->> projects vals (d/seek :is-default))
@@ -49,27 +47,14 @@
(st/emit! (dd/fetch-shared-files (:id team))
(dd/clear-selected-files)))
- (if new-css-system
- [:*
- [:header {:class (stl/css :dashboard-header)}
- [:div#dashboard-libraries-title {:class (stl/css :dashboard-title)}
- [:h1 (tr "dashboard.libraries-title")]]]
- [:section {:class (stl/css :dashboard-container :no-bg :dashboard-shared) :ref rowref}
- [:& grid {:files files
- :project default-project
- :origin :libraries
- :limit limit
- :library-view? components-v2}]]]
-
- ;; OLD
- [:*
- [:header.dashboard-header {:ref rowref}
- [:div.dashboard-title#dashboard-libraries-title
- [:h1 (tr "dashboard.libraries-title")]]]
- [:section.dashboard-container.no-bg.dashboard-shared
- [:& grid {:files files
- :project default-project
- :origin :libraries
- :limit limit
- :library-view? components-v2}]]])))
+ [:*
+ [:header {:class (stl/css :dashboard-header)}
+ [:div#dashboard-libraries-title {:class (stl/css :dashboard-title)}
+ [:h1 (tr "dashboard.libraries-title")]]]
+ [:section {:class (stl/css :dashboard-container :no-bg :dashboard-shared) :ref rowref}
+ [:& grid {:files files
+ :project default-project
+ :origin :libraries
+ :limit limit
+ :library-view? components-v2}]]]))
diff --git a/frontend/src/app/main/ui/dashboard/placeholder.cljs b/frontend/src/app/main/ui/dashboard/placeholder.cljs
index 37fd949f35..ce8c5d81f3 100644
--- a/frontend/src/app/main/ui/dashboard/placeholder.cljs
+++ b/frontend/src/app/main/ui/dashboard/placeholder.cljs
@@ -7,65 +7,39 @@
(ns app.main.ui.dashboard.placeholder
(:require-macros [app.main.style :as stl])
(:require
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
(mf/defc empty-placeholder
[{:keys [dragging? limit origin create-fn] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-click
+ (let [on-click
(mf/use-fn
(mf/deps create-fn)
(fn [_]
(create-fn "dashboard:empty-folder-placeholder")))]
- (if new-css-system
- (cond
- (true? dragging?)
- [:ul
- {:class (stl/css :grid-row :no-wrap)
- :style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
- [:li {:class (stl/css :grid-item :grid-empty-placeholder :dragged)}]]
+ (cond
+ (true? dragging?)
+ [:ul
+ {:class (stl/css :grid-row :no-wrap)
+ :style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
+ [:li {:class (stl/css :grid-item :grid-empty-placeholder :dragged)}]]
- (= :libraries origin)
- [:div {:class (stl/css :grid-empty-placeholder :libs)
- :data-test "empty-placeholder"}
- [:div {:class (stl/css :text)}
- [:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]]
+ (= :libraries origin)
+ [:div {:class (stl/css :grid-empty-placeholder :libs)
+ :data-test "empty-placeholder"}
+ [:div {:class (stl/css :text)}
+ [:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]]
- :else
- [:div
- {:class (stl/css :grid-empty-placeholder)}
- [:button {:class (stl/css :create-new)
- :on-click on-click}
- i/add-refactor]])
-
- ;; OLD
- (cond
- (true? dragging?)
- [:ul.grid-row.no-wrap
- {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
- [:li.grid-item]]
-
- (= :libraries origin)
- [:div.grid-empty-placeholder.libs {:data-test "empty-placeholder"}
- [:div.text
- [:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]]
-
- :else
- [:div.grid-empty-placeholder
- {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
- [:button.create-new {:on-click on-click} (tr "dashboard.new-file")]]))))
+ :else
+ [:div
+ {:class (stl/css :grid-empty-placeholder)}
+ [:button {:class (stl/css :create-new)
+ :on-click on-click}
+ i/add-refactor]])))
(mf/defc loading-placeholder
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :grid-empty-placeholder :loader)}
- [:div {:class (stl/css :icon)} i/loader]
- [:div {:class (stl/css :text)} (tr "dashboard.loading-files")]]
-
- [:div.grid-empty-placeholder.loader
- [:div.icon i/loader]
- [:div.text (tr "dashboard.loading-files")]])))
+ [:div {:class (stl/css :grid-empty-placeholder :loader)}
+ [:div {:class (stl/css :icon)} i/loader]
+ [:div {:class (stl/css :text)} (tr "dashboard.loading-files")]])
diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs
index 572c72f778..035385bb49 100644
--- a/frontend/src/app/main/ui/dashboard/projects.cljs
+++ b/frontend/src/app/main/ui/dashboard/projects.cljs
@@ -18,7 +18,6 @@
[app.main.errors :as errors]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [line-grid]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.project-menu :refer [project-menu]]
@@ -37,32 +36,20 @@
(mf/defc header
{::mf/wrap [mf/memo]}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-click (mf/use-fn #(st/emit! (dd/create-project)))]
- (if new-css-system
- [:header {:class (stl/css :dashboard-header)}
- [:div#dashboard-projects-title {:class (stl/css :dashboard-title)}
- [:h1 (tr "dashboard.projects-title")]]
- [:button
- {:class (stl/css :btn-secondary :btn-small)
- :on-click on-click
- :data-test "new-project-button"}
- (tr "dashboard.new-project")]]
-
- ;; OLD
- [:header.dashboard-header
- [:div.dashboard-title#dashboard-projects-title
- [:h1 (tr "dashboard.projects-title")]]
- [:button.btn-secondary.btn-small
- {:on-click on-click
- :data-test "new-project-button"}
- (tr "dashboard.new-project")]])))
+ (let [on-click (mf/use-fn #(st/emit! (dd/create-project)))]
+ [:header {:class (stl/css :dashboard-header)}
+ [:div#dashboard-projects-title {:class (stl/css :dashboard-title)}
+ [:h1 (tr "dashboard.projects-title")]]
+ [:button
+ {:class (stl/css :btn-secondary :btn-small)
+ :on-click on-click
+ :data-test "new-project-button"}
+ (tr "dashboard.new-project")]]))
(mf/defc team-hero
{::mf/wrap [mf/memo]}
[{:keys [team close-fn] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-nav-members-click (mf/use-fn #(st/emit! (dd/go-to-team-members)))
+ (let [on-nav-members-click (mf/use-fn #(st/emit! (dd/go-to-team-members)))
on-invite-click
(mf/use-fn
@@ -78,52 +65,33 @@
(dom/prevent-default event)
(close-fn)))]
- (if new-css-system
- [:div {:class (stl/css :team-hero)}
- [:div {:class (stl/css :img-wrapper)}
- [:img {:src "images/deco-team-banner.png"
- :border "0"
- :role "presentation"}]]
- [:div {:class (stl/css :text)}
- [:div {:class (stl/css :title)} (tr "dasboard.team-hero.title")]
- [:div {:class (stl/css :info)}
- [:span (tr "dasboard.team-hero.text")]
- [:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]]
- [:button
- {:class (stl/css :btn-primary :invite)
- :on-click on-invite-click}
- (tr "onboarding.choice.team-up.invite-members")]]
+ [:div {:class (stl/css :team-hero)}
+ [:div {:class (stl/css :img-wrapper)}
+ [:img {:src "images/deco-team-banner.png"
+ :border "0"
+ :role "presentation"}]]
+ [:div {:class (stl/css :text)}
+ [:div {:class (stl/css :title)} (tr "dasboard.team-hero.title")]
+ [:div {:class (stl/css :info)}
+ [:span (tr "dasboard.team-hero.text")]
+ [:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]]
+ [:button
+ {:class (stl/css :btn-primary :invite)
+ :on-click on-invite-click}
+ (tr "onboarding.choice.team-up.invite-members")]]
- [:button
- {:class (stl/css :close)
- :on-click on-close-click
- :aria-label (tr "labels.close")}
- [:span i/close]]]
-
- ;; OLD
- [:div.team-hero
- [:img {:src "images/deco-team-banner.png" :border "0"
- :role "presentation"}]
- [:div.text
- [:div.title (tr "dasboard.team-hero.title")]
- [:div.info
- [:span (tr "dasboard.team-hero.text")]
- [:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]]]
- [:button.btn-primary.invite
- {:on-click on-invite-click}
- (tr "onboarding.choice.team-up.invite-members")]
- [:button.close
- {:on-click on-close-click
- :aria-label (tr "labels.close")}
- [:span i/close]]])))
+ [:button
+ {:class (stl/css :close)
+ :on-click on-close-click
+ :aria-label (tr "labels.close")}
+ [:span i/close]]]))
(def builtin-templates
(l/derived :builtin-templates st/state))
(mf/defc tutorial-project
[{:keys [close-tutorial default-project-id] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- state (mf/use-state {:status :waiting
+ (let [state (mf/use-state {:status :waiting
:file nil})
templates (mf/deref builtin-templates)
@@ -155,88 +123,51 @@
(swap! state #(assoc % :status :importing))
(st/emit! (with-meta (dd/clone-template (with-meta params mdata))
{::ev/origin "get-started-hero-block"})))))]
- (if new-css-system
- [:article {:class (stl/css :tutorial)}
- [:div {:class (stl/css :thumbnail)}]
- [:div {:class (stl/css :text)}
- [:h2 {:class (stl/css :title)} (tr "dasboard.tutorial-hero.title")]
- [:p {:class (stl/css :info)} (tr "dasboard.tutorial-hero.info")]
- [:button {:class (stl/css :btn-primary :action)
- :on-click download-tutorial}
- (case (:status @state)
- :waiting (tr "dasboard.tutorial-hero.start")
- :importing [:span.loader i/loader-pencil]
- :success "")]]
+ [:article {:class (stl/css :tutorial)}
+ [:div {:class (stl/css :thumbnail)}]
+ [:div {:class (stl/css :text)}
+ [:h2 {:class (stl/css :title)} (tr "dasboard.tutorial-hero.title")]
+ [:p {:class (stl/css :info)} (tr "dasboard.tutorial-hero.info")]
+ [:button {:class (stl/css :btn-primary :action)
+ :on-click download-tutorial}
+ (case (:status @state)
+ :waiting (tr "dasboard.tutorial-hero.start")
+ :importing [:span.loader i/loader-pencil]
+ :success "")]]
- [:button
- {:class (stl/css :close)
- :on-click close-tutorial
- :aria-label (tr "labels.close")}
- [:span {:class (stl/css :icon)} i/close]]]
-
- ;; OLD
- [:article.tutorial
- [:div.thumbnail]
- [:div.text
- [:h2.title (tr "dasboard.tutorial-hero.title")]
- [:p.info (tr "dasboard.tutorial-hero.info")]
- [:button.btn-primary.action {:on-click download-tutorial}
- (case (:status @state)
- :waiting (tr "dasboard.tutorial-hero.start")
- :importing [:span.loader i/loader-pencil]
- :success "")]]
-
- [:button.close
- {:on-click close-tutorial
- :aria-label (tr "labels.close")}
- [:span.icon i/close]]])))
+ [:button
+ {:class (stl/css :close)
+ :on-click close-tutorial
+ :aria-label (tr "labels.close")}
+ [:span {:class (stl/css :icon)} i/close]]]))
(mf/defc interface-walkthrough
{::mf/wrap [mf/memo]}
[{:keys [close-walkthrough] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- handle-walkthrough-link
+ (let [handle-walkthrough-link
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "show-walkthrough"
::ev/origin "get-started-hero-block"
:section "dashboard"})))]
- (if new-css-system
- [:article {:class (stl/css :walkthrough)}
- [:div {:class (stl/css :thumbnail)}]
- [:div {:class (stl/css :text)}
- [:h2 {:class (stl/css :title)} (tr "dasboard.walkthrough-hero.title")]
- [:p {:class (stl/css :info)} (tr "dasboard.walkthrough-hero.info")]
- [:a {:class (stl/css :btn-primary :action)
- :href " https://design.penpot.app/walkthrough"
- :target "_blank"
- :on-click handle-walkthrough-link}
- (tr "dasboard.walkthrough-hero.start")]]
- [:button
- {:class (stl/css :close)
- :on-click close-walkthrough
- :aria-label (tr "labels.close")}
- [:span {:class (stl/css :icon)} i/close]]]
-
- ;; OLD
- [:article.walkthrough
- [:div.thumbnail]
- [:div.text
- [:h2.title (tr "dasboard.walkthrough-hero.title")]
- [:p.info (tr "dasboard.walkthrough-hero.info")]
- [:a.btn-primary.action
- {:href " https://design.penpot.app/walkthrough"
- :target "_blank"
- :on-click handle-walkthrough-link}
- (tr "dasboard.walkthrough-hero.start")]]
- [:button.close
- {:on-click close-walkthrough
- :aria-label (tr "labels.close")}
- [:span.icon i/close]]])))
+ [:article {:class (stl/css :walkthrough)}
+ [:div {:class (stl/css :thumbnail)}]
+ [:div {:class (stl/css :text)}
+ [:h2 {:class (stl/css :title)} (tr "dasboard.walkthrough-hero.title")]
+ [:p {:class (stl/css :info)} (tr "dasboard.walkthrough-hero.info")]
+ [:a {:class (stl/css :btn-primary :action)
+ :href " https://design.penpot.app/walkthrough"
+ :target "_blank"
+ :on-click handle-walkthrough-link}
+ (tr "dasboard.walkthrough-hero.start")]]
+ [:button
+ {:class (stl/css :close)
+ :on-click close-walkthrough
+ :aria-label (tr "labels.close")}
+ [:span {:class (stl/css :icon)} i/close]]]))
(mf/defc project-item
[{:keys [project first? team files] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- locale (mf/deref i18n/locale)
+ (let [locale (mf/deref i18n/locale)
file-count (or (:count project) 0)
project-id (:id project)
team-id (:id team)
@@ -344,166 +275,85 @@
(dom/stop-propagation event)
(on-menu-click event))))]
- (if new-css-system
- [:article {:class (stl/css-case :dashboard-project-row true :first first?)}
- [:header {:class (stl/css :project)}
- [:div {:class (stl/css :project-name-wrapper)}
- (if (:edition? @local)
- [:& inline-edition {:content (:name project)
- :on-end on-edit}]
- [:h2 {:on-click on-nav
- :on-context-menu on-menu-click}
- (if (:is-default project)
- (tr "labels.drafts")
- (:name project))])
+ [:article {:class (stl/css-case :dashboard-project-row true :first first?)}
+ [:header {:class (stl/css :project)}
+ [:div {:class (stl/css :project-name-wrapper)}
+ (if (:edition? @local)
+ [:& inline-edition {:content (:name project)
+ :on-end on-edit}]
+ [:h2 {:on-click on-nav
+ :on-context-menu on-menu-click}
+ (if (:is-default project)
+ (tr "labels.drafts")
+ (:name project))])
- [:& project-menu
- {:project project
- :show? (:menu-open @local)
- :left (+ 24 (:x (:menu-pos @local)))
- :top (:y (:menu-pos @local))
- :on-edit on-edit-open
- :on-menu-close on-menu-close
- :on-import on-import}]
-
- [:span {:class (stl/css :info)} (str (tr "labels.num-of-files" (i18n/c file-count)))]
-
- (let [time (-> (:modified-at project)
- (dt/timeago {:locale locale}))]
- [:span {:class (stl/css :recent-files-row-title-info)} (str ", " time)])
-
- [:div {:class (stl/css :project-actions)}
- (when-not (:is-default project)
- [:button
- {:class (stl/css-case :pin-icon true
- :tooltip true
- :tooltip-bottom true
- :active (:is-pinned project))
- :on-click toggle-pin
- :alt (tr "dashboard.pin-unpin")
- :aria-label (tr "dashboard.pin-unpin")
- :tab-index "0"}
- (if (:is-pinned project)
- i/pin-fill
- i/pin)])
-
- [:button
- {:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
- :on-click on-create-click
- :alt (tr "dashboard.new-file")
- :aria-label (tr "dashboard.new-file")
- :data-test "project-new-file"
- :on-key-down handle-create-click}
- i/close]
-
- [:button
- {:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
- :on-click on-menu-click
- :alt (tr "dashboard.options")
- :aria-label (tr "dashboard.options")
- :data-test "project-options"
- :on-key-down handle-menu-click}
- i/actions]]]]
-
- [:div {:class (stl/css :grid-container) :ref rowref}
- [:& line-grid
- {:project project
- :team team
- :files files
- :create-fn create-file
- :limit limit}]]
-
- (when (and (> limit 0)
- (> file-count limit))
- [:button
- {:class (stl/css :show-more)
- :on-click on-nav
- :tab-index "0"
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-nav)))}
- [:div {:class (stl/css :placeholder-label)} (tr "dashboard.show-all-files")]
- [:div {:class (stl/css :placeholder-icon)} i/arrow-down]])]
-
- ;; OLD
- [:article.dashboard-project-row
- {:class (when first? "first")}
- [:header.project {:ref rowref}
- [:div.project-name-wrapper
- (if (:edition? @local)
- [:& inline-edition {:content (:name project)
- :on-end on-edit}]
- [:h2 {:on-click on-nav
- :on-context-menu on-menu-click}
- (if (:is-default project)
- (tr "labels.drafts")
- (:name project))])
-
- [:& project-menu
- {:project project
- :show? (:menu-open @local)
- :left (+ 24 (:x (:menu-pos @local)))
- :top (:y (:menu-pos @local))
- :on-edit on-edit-open
- :on-menu-close on-menu-close
- :on-import on-import}]
-
- [:span.info (str (tr "labels.num-of-files" (i18n/c file-count)))]
- (let [time (-> (:modified-at project)
- (dt/timeago {:locale locale}))]
- [:span.recent-files-row-title-info (str ", " time)])
- [:div.project-actions
- (when-not (:is-default project)
- [:button.pin-icon.tooltip.tooltip-bottom
- {:class (when (:is-pinned project) "active")
- :on-click toggle-pin
- :alt (tr "dashboard.pin-unpin")
- :aria-label (tr "dashboard.pin-unpin")
- :tab-index "0"}
- (if (:is-pinned project)
- i/pin-fill
- i/pin)])
-
- [:button.btn-secondary.btn-small.tooltip.tooltip-bottom
- {:on-click on-create-click
- :alt (tr "dashboard.new-file")
- :aria-label (tr "dashboard.new-file")
- :data-test "project-new-file"
- :tab-index "0"
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-create-click event)))}
- i/close]
-
- [:button.btn-secondary.btn-small.tooltip.tooltip-bottom
- {:on-click on-menu-click
- :alt (tr "dashboard.options")
- :aria-label (tr "dashboard.options")
- :data-test "project-options"
- :tab-index "0"
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/stop-propagation event)
- (on-menu-click event)))}
- i/actions]]]]
-
- [:& line-grid
+ [:& project-menu
{:project project
- :team team
- :files files
- :create-fn create-file
- :limit limit}]
+ :show? (:menu-open @local)
+ :left (+ 24 (:x (:menu-pos @local)))
+ :top (:y (:menu-pos @local))
+ :on-edit on-edit-open
+ :on-menu-close on-menu-close
+ :on-import on-import}]
- (when (and (> limit 0)
- (> file-count limit))
- [:button.show-more {:on-click on-nav
- :tab-index "0"
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-nav)))}
- [:div.placeholder-label
- (tr "dashboard.show-all-files")]
- [:div.placeholder-icon i/arrow-down]])])))
+ [:span {:class (stl/css :info)} (str (tr "labels.num-of-files" (i18n/c file-count)))]
+
+ (let [time (-> (:modified-at project)
+ (dt/timeago {:locale locale}))]
+ [:span {:class (stl/css :recent-files-row-title-info)} (str ", " time)])
+
+ [:div {:class (stl/css :project-actions)}
+ (when-not (:is-default project)
+ [:button
+ {:class (stl/css-case :pin-icon true
+ :tooltip true
+ :tooltip-bottom true
+ :active (:is-pinned project))
+ :on-click toggle-pin
+ :alt (tr "dashboard.pin-unpin")
+ :aria-label (tr "dashboard.pin-unpin")
+ :tab-index "0"}
+ (if (:is-pinned project)
+ i/pin-fill
+ i/pin)])
+
+ [:button
+ {:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
+ :on-click on-create-click
+ :alt (tr "dashboard.new-file")
+ :aria-label (tr "dashboard.new-file")
+ :data-test "project-new-file"
+ :on-key-down handle-create-click}
+ i/close]
+
+ [:button
+ {:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
+ :on-click on-menu-click
+ :alt (tr "dashboard.options")
+ :aria-label (tr "dashboard.options")
+ :data-test "project-options"
+ :on-key-down handle-menu-click}
+ i/actions]]]]
+
+ [:div {:class (stl/css :grid-container) :ref rowref}
+ [:& line-grid
+ {:project project
+ :team team
+ :files files
+ :create-fn create-file
+ :limit limit}]]
+
+ (when (and (> limit 0)
+ (> file-count limit))
+ [:button
+ {:class (stl/css :show-more)
+ :on-click on-nav
+ :tab-index "0"
+ :on-key-down (fn [event]
+ (when (kbd/enter? event)
+ (on-nav)))}
+ [:div {:class (stl/css :placeholder-label)} (tr "dashboard.show-all-files")]
+ [:div {:class (stl/css :placeholder-icon)} i/arrow-down]])]))
(def recent-files-ref
@@ -511,8 +361,7 @@
(mf/defc projects-section
[{:keys [team projects profile default-project-id] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- projects (->> (vals projects)
+ (let [projects (->> (vals projects)
(sort-by :modified-at)
(reverse))
recent-map (mf/deref recent-files-ref)
@@ -562,68 +411,34 @@
(st/emit! (dd/fetch-recent-files team-id)
(dd/clear-selected-files)))
- (if new-css-system
- (when (seq projects)
- [:*
- [:& header]
+ (when (seq projects)
+ [:*
+ [:& header]
- (when team-hero?
- [:& team-hero {:team team :close-fn close-banner}])
+ (when team-hero?
+ [:& team-hero {:team team :close-fn close-banner}])
- (when (and (contains? cf/flags :dashboard-templates-section)
- (or (not tutorial-viewed?)
- (not walkthrough-viewed?)))
- [:div {:class (stl/css :hero-projects)}
- (when (and (not tutorial-viewed?) (:is-default team))
- [:& tutorial-project
- {:close-tutorial close-tutorial
- :default-project-id default-project-id}])
+ (when (and (contains? cf/flags :dashboard-templates-section)
+ (or (not tutorial-viewed?)
+ (not walkthrough-viewed?)))
+ [:div {:class (stl/css :hero-projects)}
+ (when (and (not tutorial-viewed?) (:is-default team))
+ [:& tutorial-project
+ {:close-tutorial close-tutorial
+ :default-project-id default-project-id}])
- (when (and (not walkthrough-viewed?) (:is-default team))
- [:& interface-walkthrough
- {:close-walkthrough close-walkthrough}])])
+ (when (and (not walkthrough-viewed?) (:is-default team))
+ [:& interface-walkthrough
+ {:close-walkthrough close-walkthrough}])])
- [:div {:class (stl/css :dashboard-container :no-bg :dashboard-projects)}
- (for [{:keys [id] :as project} projects]
- (let [files (when recent-map
- (->> (vals recent-map)
- (filterv #(= id (:project-id %)))
- (sort-by :modified-at #(compare %2 %1))))]
- [:& project-item {:project project
- :team team
- :files files
- :first? (= project (first projects))
- :key id}]))]])
-
- ;; OLD
- (when (seq projects)
- [:*
- [:& header]
-
- (when team-hero?
- [:& team-hero {:team team :close-fn close-banner}])
-
- (when (and (contains? cf/flags :dashboard-templates-section)
- (or (not tutorial-viewed?)
- (not walkthrough-viewed?)))
- [:div.hero-projects
- (when (and (not tutorial-viewed?) (:is-default team))
- [:& tutorial-project
- {:close-tutorial close-tutorial
- :default-project-id default-project-id}])
-
- (when (and (not walkthrough-viewed?) (:is-default team))
- [:& interface-walkthrough
- {:close-walkthrough close-walkthrough}])])
-
- [:div.dashboard-container.no-bg.dashboard-projects
- (for [{:keys [id] :as project} projects]
- (let [files (when recent-map
- (->> (vals recent-map)
- (filterv #(= id (:project-id %)))
- (sort-by :modified-at #(compare %2 %1))))]
- [:& project-item {:project project
- :team team
- :files files
- :first? (= project (first projects))
- :key id}]))]]))))
+ [:div {:class (stl/css :dashboard-container :no-bg :dashboard-projects)}
+ (for [{:keys [id] :as project} projects]
+ (let [files (when recent-map
+ (->> (vals recent-map)
+ (filterv #(= id (:project-id %)))
+ (sort-by :modified-at #(compare %2 %1))))]
+ [:& project-item {:project project
+ :team team
+ :files files
+ :first? (= project (first projects))
+ :key id}]))]])))
diff --git a/frontend/src/app/main/ui/dashboard/search.cljs b/frontend/src/app/main/ui/dashboard/search.cljs
index 1f47edb4ed..3b4d090996 100644
--- a/frontend/src/app/main/ui/dashboard/search.cljs
+++ b/frontend/src/app/main/ui/dashboard/search.cljs
@@ -10,7 +10,6 @@
[app.main.data.dashboard :as dd]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [grid]]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
@@ -20,8 +19,7 @@
(mf/defc search-page
[{:keys [team search-term] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- result (mf/deref refs/dashboard-search-result)
+ (let [result (mf/deref refs/dashboard-search-result)
[rowref limit] (hooks/use-dynamic-grid-item-width)]
(mf/use-effect
@@ -38,61 +36,31 @@
(fn []
(st/emit! (dd/search {:search-term search-term})
(dd/clear-selected-files))))
- (if new-css-system
- [:*
- [:header {:class (stl/css :dashboard-header)}
- [:div#dashboard-search-title {:class (stl/css :dashboard-title)}
- [:h1 (tr "dashboard.title-search")]]]
+ [:*
+ [:header {:class (stl/css :dashboard-header)}
+ [:div#dashboard-search-title {:class (stl/css :dashboard-title)}
+ [:h1 (tr "dashboard.title-search")]]]
- [:section {:class (stl/css :dashboard-container :search :no-bg)
- :ref rowref}
- (cond
- (empty? search-term)
- [:div {:class (stl/css :grid-empty-placeholder :search)}
- [:div {:class (stl/css :icon)} i/search]
- [:div {:class (stl/css :text)} (tr "dashboard.type-something")]]
+ [:section {:class (stl/css :dashboard-container :search :no-bg)
+ :ref rowref}
+ (cond
+ (empty? search-term)
+ [:div {:class (stl/css :grid-empty-placeholder :search)}
+ [:div {:class (stl/css :icon)} i/search]
+ [:div {:class (stl/css :text)} (tr "dashboard.type-something")]]
- (nil? result)
- [:div {:class (stl/css :grid-empty-placeholder :search)}
- [:div {:class (stl/css :icon)} i/search]
- [:div {:class (stl/css :text)} (tr "dashboard.searching-for" search-term)]]
+ (nil? result)
+ [:div {:class (stl/css :grid-empty-placeholder :search)}
+ [:div {:class (stl/css :icon)} i/search]
+ [:div {:class (stl/css :text)} (tr "dashboard.searching-for" search-term)]]
- (empty? result)
- [:div {:class (stl/css :grid-empty-placeholder :search)}
- [:div {:class (stl/css :icon)} i/search]
- [:div {:class (stl/css :text)} (tr "dashboard.no-matches-for" search-term)]]
+ (empty? result)
+ [:div {:class (stl/css :grid-empty-placeholder :search)}
+ [:div {:class (stl/css :icon)} i/search]
+ [:div {:class (stl/css :text)} (tr "dashboard.no-matches-for" search-term)]]
- :else
- [:& grid {:files result
- :hide-new? true
- :origin :search
- :limit limit}])]]
-
- ;; OLD
- [:*
- [:header.dashboard-header
- [:div.dashboard-title#dashboard-search-title
- [:h1 (tr "dashboard.title-search")]]]
-
- [:section.dashboard-container.search.no-bg {:ref rowref}
- (cond
- (empty? search-term)
- [:div.grid-empty-placeholder.search
- [:div.icon i/search]
- [:div.text (tr "dashboard.type-something")]]
-
- (nil? result)
- [:div.grid-empty-placeholder.search
- [:div.icon i/search]
- [:div.text (tr "dashboard.searching-for" search-term)]]
-
- (empty? result)
- [:div.grid-empty-placeholder.search
- [:div.icon i/search]
- [:div.text (tr "dashboard.no-matches-for" search-term)]]
-
- :else
- [:& grid {:files result
- :hide-new? true
- :origin :search
- :limit limit}])]])))
+ :else
+ [:& grid {:files result
+ :hide-new? true
+ :origin :search
+ :limit limit}])]]))
diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs
index 4b61fb2bab..219883e931 100644
--- a/frontend/src/app/main/ui/dashboard/sidebar.cljs
+++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs
@@ -20,7 +20,6 @@
[app.main.store :as st]
[app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]]
[app.main.ui.components.link :refer [link]]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.comments :refer [comments-icon comments-section]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.project-menu :refer [project-menu]]
@@ -41,8 +40,7 @@
(mf/defc sidebar-project
[{:keys [item selected?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- dstate (mf/deref refs/dashboard-local)
+ (let [dstate (mf/deref refs/dashboard-local)
selected-files (:selected-files dstate)
selected-project (:selected-project dstate)
edit-id (:project-for-edit dstate)
@@ -136,59 +134,33 @@
mdata {:on-success on-drop-success}]
(st/emit! (dd/move-files (with-meta data mdata)))))))]
- (if new-css-system
- [:*
- [:li {:tab-index "0"
- :class (stl/css-case :project-element true
- :current selected?
- :dragging (:dragging? local))
- :on-click on-click
- :on-key-down on-key-down
- :on-double-click on-edit-open
- :on-context-menu on-menu-click
- :on-drag-enter on-drag-enter
- :on-drag-over on-drag-over
- :on-drag-leave on-drag-leave
- :on-drop on-drop}
- (if (:edition? local)
- [:& inline-edition {:content (:name item)
- :on-end on-edit}]
- [:span {:class (stl/css :element-title)} (:name item)])]
- [:& project-menu {:project item
- :show? (:menu-open local)
- :left (:x (:menu-pos local))
- :top (:y (:menu-pos local))
- :on-edit on-edit-open
- :on-menu-close on-menu-close}]]
-
- ;; OLD
- [:*
- [:li {:tab-index "0"
- :class (if selected? "current"
- (when (:dragging? local) "dragging"))
- :on-click on-click
- :on-key-down on-key-down
- :on-double-click on-edit-open
- :on-context-menu on-menu-click
- :on-drag-enter on-drag-enter
- :on-drag-over on-drag-over
- :on-drag-leave on-drag-leave
- :on-drop on-drop}
- (if (:edition? local)
- [:& inline-edition {:content (:name item)
- :on-end on-edit}]
- [:span.element-title (:name item)])]
- [:& project-menu {:project item
- :show? (:menu-open local)
- :left (:x (:menu-pos local))
- :top (:y (:menu-pos local))
- :on-edit on-edit-open
- :on-menu-close on-menu-close}]])))
+ [:*
+ [:li {:tab-index "0"
+ :class (stl/css-case :project-element true
+ :current selected?
+ :dragging (:dragging? local))
+ :on-click on-click
+ :on-key-down on-key-down
+ :on-double-click on-edit-open
+ :on-context-menu on-menu-click
+ :on-drag-enter on-drag-enter
+ :on-drag-over on-drag-over
+ :on-drag-leave on-drag-leave
+ :on-drop on-drop}
+ (if (:edition? local)
+ [:& inline-edition {:content (:name item)
+ :on-end on-edit}]
+ [:span {:class (stl/css :element-title)} (:name item)])]
+ [:& project-menu {:project item
+ :show? (:menu-open local)
+ :left (:x (:menu-pos local))
+ :top (:y (:menu-pos local))
+ :on-edit on-edit-open
+ :on-menu-close on-menu-close}]]))
(mf/defc sidebar-search
[{:keys [search-term team-id] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- search-term (or search-term "")
+ (let [search-term (or search-term "")
focused? (mf/use-state false)
emit! (mf/use-memo #(f/debounce st/emit! 500))
@@ -236,70 +208,39 @@
(when (kbd/enter? event)
(on-clear-click event))))]
- (if new-css-system
- [:form {:class (stl/css :sidebar-search)}
- [:input
- {:class (stl/css :input-text)
- :key "images-search-box"
- :id "search-input"
- :type "text"
- :aria-label (tr "dashboard.search-placeholder")
- :placeholder (tr "dashboard.search-placeholder")
- :default-value search-term
- :auto-complete "off"
- ;; :on-focus on-search-focus
- :on-blur on-search-blur
- :on-change on-search-change
- :on-key-press on-key-press
- :ref #(when % (set! (.-value %) search-term))}]
+ [:form {:class (stl/css :sidebar-search)}
+ [:input
+ {:class (stl/css :input-text)
+ :key "images-search-box"
+ :id "search-input"
+ :type "text"
+ :aria-label (tr "dashboard.search-placeholder")
+ :placeholder (tr "dashboard.search-placeholder")
+ :default-value search-term
+ :auto-complete "off"
+ ;; :on-focus on-search-focus
+ :on-blur on-search-blur
+ :on-change on-search-change
+ :on-key-press on-key-press
+ :ref #(when % (set! (.-value %) search-term))}]
- (if (or @focused? (seq search-term))
- [:div
- {:class (stl/css :clear-search)
- :tab-index "0"
- :on-click on-clear-click
- :on-key-down handle-clear-search}
- i/close]
+ (if (or @focused? (seq search-term))
+ [:div
+ {:class (stl/css :clear-search)
+ :tab-index "0"
+ :on-click on-clear-click
+ :on-key-down handle-clear-search}
+ i/close]
- [:div
- {:class (stl/css :search)
- :on-click on-clear-click}
- i/search])]
-
- ;; OLD
- [:form.sidebar-search
- [:input.input-text
- {:key "images-search-box"
- :id "search-input"
- :type "text"
- :aria-label (tr "dashboard.search-placeholder")
- :placeholder (tr "dashboard.search-placeholder")
- :default-value search-term
- :auto-complete "off"
- ;; :on-focus on-search-focus
- :on-blur on-search-blur
- :on-change on-search-change
- :on-key-press on-key-press
- :ref #(when % (set! (.-value %) search-term))}]
-
- (if (or @focused? (seq search-term))
- [:div.clear-search
- {:tab-index "0"
- :on-click on-clear-click
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-clear-click event)))}
- i/close]
-
- [:div.search
- {:on-click on-clear-click}
- i/search])])))
+ [:div
+ {:class (stl/css :search)
+ :on-click on-clear-click}
+ i/search])]))
(mf/defc teams-selector-dropdown-items
{::mf/wrap-props false}
[{:keys [team profile teams] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-create-clicked
+ (let [on-create-clicked
(mf/use-callback
#(st/emit! (modal/show :team-form {})))
@@ -318,76 +259,38 @@
(when (kbd/enter? event)
(team-selected id event)))]
- (if new-css-system
- [:*
- [:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
- :on-key-down handle-select-default
- :id "teams-selector-default-team"
- :class (stl/css :team-name)}
- [:span {:class (stl/css :team-icon)} i/logo-icon]
- [:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")]
- (when (= (:default-team-id profile) (:id team))
- [:span {:class (stl/css :icon)} i/tick])]
+ [:*
+ [:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
+ :on-key-down handle-select-default
+ :id "teams-selector-default-team"
+ :class (stl/css :team-name)}
+ [:span {:class (stl/css :team-icon)} i/logo-icon]
+ [:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")]
+ (when (= (:default-team-id profile) (:id team))
+ [:span {:class (stl/css :icon)} i/tick])]
- (for [team-item (remove :is-default (vals teams))]
- [:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
- :on-key-down (partial handle-select-team (:id team-item))
- :id (str "teams-selector-" (:id team-item))
- :class (stl/css :team-name)
- :key (str "teams-selector-" (:id team-item))}
- [:span {:class (stl/css :team-icon)}
- [:img {:src (cf/resolve-team-photo-url team-item)
- :alt (:name team-item)}]]
- [:span {:class (stl/css :team-text)
- :title (:name team-item)} (:name team-item)]
- (when (= (:id team-item) (:id team))
- [:span {:class (stl/css :icon)} i/tick])])
- [:hr {:role "separator"}]
- [:> dropdown-menu-item* {:on-click on-create-clicked
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-create-clicked event)))
- :id "teams-selector-create-team"
- :class (stl/css :team-name :action)}
- [:span {:class (stl/css :team-icon :new-team)} i/close]
- [:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]]
-
- ;; OLD
- [:*
- [:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (team-selected (:default-team-id profile) event)))
- :id "teams-selector-default-team"
- :class "team-name"}
- [:span.team-icon i/logo-icon]
- [:span.team-text (tr "dashboard.your-penpot")]
- (when (= (:default-team-id profile) (:id team))
- [:span.icon i/tick])]
-
- (for [team-item (remove :is-default (vals teams))]
- [:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (team-selected (:id team-item) event)))
- :id (str "teams-selector-" (:id team-item))
- :class "team-name"
- :key (str "teams-selector-" (:id team-item))}
- [:span.team-icon
- [:img {:src (cf/resolve-team-photo-url team-item)
- :alt (:name team-item)}]]
- [:span.team-text {:title (:name team-item)} (:name team-item)]
- (when (= (:id team-item) (:id team))
- [:span.icon i/tick])])
- [:hr {:role "separator"}]
- [:> dropdown-menu-item* {:on-click on-create-clicked
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-create-clicked event)))
- :id "teams-selector-create-team"
- :class "team-name action"}
- [:span.team-icon.new-team i/close]
- [:span.team-text (tr "dashboard.create-new-team")]]])))
+ (for [team-item (remove :is-default (vals teams))]
+ [:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
+ :on-key-down (partial handle-select-team (:id team-item))
+ :id (str "teams-selector-" (:id team-item))
+ :class (stl/css :team-name)
+ :key (str "teams-selector-" (:id team-item))}
+ [:span {:class (stl/css :team-icon)}
+ [:img {:src (cf/resolve-team-photo-url team-item)
+ :alt (:name team-item)}]]
+ [:span {:class (stl/css :team-text)
+ :title (:name team-item)} (:name team-item)]
+ (when (= (:id team-item) (:id team))
+ [:span {:class (stl/css :icon)} i/tick])])
+ [:hr {:role "separator"}]
+ [:> dropdown-menu-item* {:on-click on-create-clicked
+ :on-key-down (fn [event]
+ (when (kbd/enter? event)
+ (on-create-clicked event)))
+ :id "teams-selector-create-team"
+ :class (stl/css :team-name :action)}
+ [:span {:class (stl/css :team-icon :new-team)} i/close]
+ [:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]]))
(s/def ::member-id ::us/uuid)
(s/def ::leave-modal-form
@@ -395,8 +298,7 @@
(mf/defc team-options-dropdown
[{:keys [team profile] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- go-members #(st/emit! (dd/go-to-team-members))
+ (let [go-members #(st/emit! (dd/go-to-team-members))
go-invitations #(st/emit! (dd/go-to-team-invitations))
go-webhooks #(st/emit! (dd/go-to-team-webhooks))
go-settings #(st/emit! (dd/go-to-team-settings))
@@ -549,15 +451,13 @@
(when (kbd/enter? event)
(on-delete-clicked)))
:id "teams-options-delete-team"
- :class (if new-css-system (stl/css :warning) "warning")
+ :class (stl/css :warning)
:data-test "delete-team"}
(tr "dashboard.delete-team")])]))
-
(mf/defc sidebar-team-switch
[{:keys [team profile] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- teams (mf/deref refs/teams)
+ (let [teams (mf/deref refs/teams)
teams-without-default (into {} (filter (fn [[_ v]] (= false (:is-default v))) teams))
team-ids (map #(str "teams-selector-" %) (keys teams-without-default))
ids (concat ["teams-selector-default-team"] team-ids ["teams-selector-create-team"])
@@ -615,119 +515,55 @@
(fn []
(reset! show-teams-ddwn? false))]
- (if new-css-system
- [:div {:class (stl/css :sidebar-team-switch)}
- [:div {:class (stl/css :switch-content)}
+ [:div {:class (stl/css :sidebar-team-switch)}
+ [:div {:class (stl/css :switch-content)}
+ [:button
+ {:class (stl/css :current-team)
+ :tab-index "0"
+ :on-click handle-show-team-click
+ :on-key-down handle-show-team-keydown}
+
+
+ (if (:is-default team)
+ [:div {:class (stl/css :team-name)}
+ [:span {:class (stl/css :team-icon)} i/logo-icon]
+ [:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]]
+ [:div {:class (stl/css :team-name)}
+ [:span {:class (stl/css :team-icon)}
+ [:img {:src (cf/resolve-team-photo-url team)
+ :alt (:name team)}]]
+ [:span {:class (stl/css :team-text) :title (:name team)} (:name team)]])
+
+ [:span {:class (stl/css :switch-icon)} i/arrow-down]]
+
+ (when-not (:is-default team)
[:button
- {:class (stl/css :current-team)
+ {:class (stl/css :switch-options)
+ :on-click handle-show-opts-click
:tab-index "0"
- :on-click handle-show-team-click
- :on-key-down handle-show-team-keydown}
+ :on-key-down handle-show-opts-keydown}
+ i/actions])]
+ ;; Teams Dropdown
+ [:& dropdown-menu {:show @show-teams-ddwn?
+ :on-close handle-close-team
+ :ids ids
+ :list-class (stl/css :dropdown :teams-dropdown)}
+ [:& teams-selector-dropdown-items {:ids ids
+ :team team
+ :profile profile
+ :teams teams}]]
- (if (:is-default team)
- [:div {:class (stl/css :team-name)}
- [:span {:class (stl/css :team-icon)} i/logo-icon]
- [:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]]
- [:div {:class (stl/css :team-name)}
- [:span {:class (stl/css :team-icon)}
- [:img {:src (cf/resolve-team-photo-url team)
- :alt (:name team)}]]
- [:span {:class (stl/css :team-text) :title (:name team)} (:name team)]])
-
- [:span {:class (stl/css :switch-icon)} i/arrow-down]]
-
- (when-not (:is-default team)
- [:button
- {:class (stl/css :switch-options)
- :on-click handle-show-opts-click
- :tab-index "0"
- :on-key-down handle-show-opts-keydown}
- i/actions])]
-
- ;; Teams Dropdown
- [:& dropdown-menu {:show @show-teams-ddwn?
- :on-close handle-close-team
- :ids ids
- :list-class (stl/css :dropdown :teams-dropdown)}
- [:& teams-selector-dropdown-items {:ids ids
- :team team
- :profile profile
- :teams teams}]]
-
- [:& dropdown-menu {:show @show-team-opts-ddwn?
- :on-close #(reset! show-team-opts-ddwn? false)
- :ids options-ids
- :list-class (stl/css :dropdown :options-dropdown)}
- [:& team-options-dropdown {:team team
- :profile profile}]]]
-
- ;; Old css
- [:div.sidebar-team-switch
- [:div.switch-content
- [:button.current-team {:tab-index "0"
- :on-click (fn [event]
- (dom/stop-propagation event)
- (reset! show-teams-ddwn? true))
- :on-key-down (fn [event]
- (when (or (kbd/space? event) (kbd/enter? event))
- (dom/prevent-default event)
- (reset! show-teams-ddwn? true)
- (ts/schedule-on-idle
- (fn []
- (let [first-element (dom/get-element (first ids))]
- (when first-element
- (dom/focus! first-element)))))))}
- (if (:is-default team)
- [:div.team-name
- [:span.team-icon i/logo-icon]
- [:span.team-text (tr "dashboard.default-team-name")]]
- [:div.team-name
- [:span.team-icon
- [:img {:src (cf/resolve-team-photo-url team)
- :alt (:name team)}]]
- [:span.team-text {:title (:name team)} (:name team)]])
-
- [:span.switch-icon
- i/arrow-down]]
-
- (when-not (:is-default team)
- [:button.switch-options {:on-click (fn [event]
- (dom/stop-propagation event)
- (reset! show-team-opts-ddwn? true))
- :tab-index "0"
- :on-key-down (fn [event]
- (when (or (kbd/space? event) (kbd/enter? event))
- (dom/prevent-default event)
- (reset! show-team-opts-ddwn? true)
- (ts/schedule-on-idle
- (fn []
- (let [first-element (dom/get-element (first options-ids))]
- (when first-element
- (dom/focus! first-element)))))))}
- i/actions])]
-
- ;; Teams Dropdown
- [:& dropdown-menu {:show @show-teams-ddwn?
- :on-close #(reset! show-teams-ddwn? false)
- :ids ids
- :list-class "dropdown teams-dropdown"}
- [:& teams-selector-dropdown-items {:ids ids
- :team team
- :profile profile
- :teams teams}]]
-
- [:& dropdown-menu {:show @show-team-opts-ddwn?
- :on-close #(reset! show-team-opts-ddwn? false)
- :ids options-ids
- :list-class "dropdown options-dropdown"}
- [:& team-options-dropdown {:team team
- :profile profile}]]])))
+ [:& dropdown-menu {:show @show-team-opts-ddwn?
+ :on-close #(reset! show-team-opts-ddwn? false)
+ :ids options-ids
+ :list-class (stl/css :dropdown :options-dropdown)}
+ [:& team-options-dropdown {:team team
+ :profile profile}]]]))
(mf/defc sidebar-content
[{:keys [projects profile section team project search-term] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- default-project-id
+ (let [default-project-id
(->> (vals projects)
(d/seek :is-default)
(:id))
@@ -813,115 +649,61 @@
(remove :is-default)
(filter :is-pinned))]
- (if new-css-system
- [:div {:class (stl/css :sidebar-content)}
- [:& sidebar-team-switch {:team team :profile profile}]
- [:hr]
- [:& sidebar-search {:search-term search-term
- :team-id (:id team)}]
+ [:div {:class (stl/css :sidebar-content)}
+ [:& sidebar-team-switch {:team team :profile profile}]
+ [:hr]
+ [:& sidebar-search {:search-term search-term
+ :team-id (:id team)}]
- [:div {:class (stl/css :sidebar-content-section)}
- [:ul {:class (stl/css :sidebar-nav :no-overflow)}
- [:li
- {:class (stl/css :recent-projects)
- :class-name (when projects? (stl/css :current))}
- [:& link {:action go-projects
- :keyboard-action go-projects-with-key}
- [:span {:class (stl/css :element-title)} (tr "labels.projects")]]]
+ [:div {:class (stl/css :sidebar-content-section)}
+ [:ul {:class (stl/css :sidebar-nav :no-overflow)}
+ [:li
+ {:class (stl/css :recent-projects)
+ :class-name (when projects? (stl/css :current))}
+ [:& link {:action go-projects
+ :keyboard-action go-projects-with-key}
+ [:span {:class (stl/css :element-title)} (tr "labels.projects")]]]
- [:li {:class-name (when drafts? (stl/css :current))}
- [:& link {:action go-drafts
- :keyboard-action go-drafts-with-key}
- [:span {:class (stl/css :element-title)} (tr "labels.drafts")]]]
+ [:li {:class-name (when drafts? (stl/css :current))}
+ [:& link {:action go-drafts
+ :keyboard-action go-drafts-with-key}
+ [:span {:class (stl/css :element-title)} (tr "labels.drafts")]]]
- [:li {:class-name (when libs? (stl/css :current))}
- [:& link {:action go-libs
- :keyboard-action go-libs-with-key}
- [:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]]
+ [:li {:class-name (when libs? (stl/css :current))}
+ [:& link {:action go-libs
+ :keyboard-action go-libs-with-key}
+ [:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]]
- [:hr]
+ [:hr]
- [:div {:class (stl/css :sidebar-content-section)}
- [:ul {:class (stl/css :sidebar-nav :no-overflow)}
- [:li {:class-name (when fonts? (stl/css :current))}
- [:& link {:action go-fonts
- :keyboard-action go-fonts-with-key
- :data-test "fonts"}
- [:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]]
-
- [:hr]
- [:div {:class (stl/css :sidebar-content-section)
- :data-test "pinned-projects"}
- (if (seq pinned-projects)
- [:ul {:class (stl/css :sidebar-nav)}
- (for [item pinned-projects]
- [:& sidebar-project
- {:item item
- :key (dm/str (:id item))
- :id (:id item)
- :team-id (:id team)
- :selected? (= (:id item) (:id project))}])]
- [:div {:class (stl/css :sidebar-empty-placeholder)}
- [:span {:class (stl/css :icon)} i/pin]
- [:span {:class (stl/css :text)} (tr "dashboard.no-projects-placeholder")]])]]
-
- ;; OLD STYLES
- [:div.sidebar-content
- [:& sidebar-team-switch {:team team :profile profile}]
- [:hr]
- [:& sidebar-search {:search-term search-term
- :team-id (:id team)}]
- [:div.sidebar-content-section
- [:ul.sidebar-nav.no-overflow
- [:li.recent-projects
- {:class-name (when projects? "current")}
- [:& link {:action go-projects
- :keyboard-action go-projects-with-key}
- [:span.element-title (tr "labels.projects")]]]
-
- [:li {:class-name (when drafts? "current")}
- [:& link {:action go-drafts
- :keyboard-action go-drafts-with-key}
- [:span.element-title (tr "labels.drafts")]]]
-
-
- [:li {:class-name (when libs? "current")}
- [:& link {:action go-libs
- :keyboard-action go-libs-with-key}
- [:span.element-title (tr "labels.shared-libraries")]]]]]
-
- [:hr]
-
- [:div.sidebar-content-section
- [:ul.sidebar-nav.no-overflow
- [:li {:class-name (when fonts? "current")}
-
- [:& link {:action go-fonts
- :keyboard-action go-fonts-with-key
- :data-test "fonts"}
- [:span.element-title (tr "labels.fonts")]]]]]
-
- [:hr]
- [:div.sidebar-content-section {:data-test "pinned-projects"}
- (if (seq pinned-projects)
- [:ul.sidebar-nav
- (for [item pinned-projects]
- [:& sidebar-project
- {:item item
- :key (dm/str (:id item))
- :id (:id item)
- :team-id (:id team)
- :selected? (= (:id item) (:id project))}])]
- [:div.sidebar-empty-placeholder
- [:span.icon i/pin]
- [:span.text (tr "dashboard.no-projects-placeholder")]])]])))
+ [:div {:class (stl/css :sidebar-content-section)}
+ [:ul {:class (stl/css :sidebar-nav :no-overflow)}
+ [:li {:class-name (when fonts? (stl/css :current))}
+ [:& link {:action go-fonts
+ :keyboard-action go-fonts-with-key
+ :data-test "fonts"}
+ [:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]]
+ [:hr]
+ [:div {:class (stl/css :sidebar-content-section)
+ :data-test "pinned-projects"}
+ (if (seq pinned-projects)
+ [:ul {:class (stl/css :sidebar-nav)}
+ (for [item pinned-projects]
+ [:& sidebar-project
+ {:item item
+ :key (dm/str (:id item))
+ :id (:id item)
+ :team-id (:id team)
+ :selected? (= (:id item) (:id project))}])]
+ [:div {:class (stl/css :sidebar-empty-placeholder)}
+ [:span {:class (stl/css :icon)} i/pin]
+ [:span {:class (stl/css :text)} (tr "dashboard.no-projects-placeholder")]])]]))
(mf/defc profile-section
[{:keys [profile team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- show (mf/use-state false)
+ (let [show (mf/use-state false)
photo (cf/resolve-profile-photo-url profile)
on-click
@@ -1024,236 +806,110 @@
(fn [event]
(when (kbd/enter? event)
(on-click (du/logout) event))))]
- (if new-css-system
- [:*
- (when (and team profile)
- [:& comments-section
- {:profile profile
- :team team
- :show? show-comments?
- :on-show-comments handle-show-comments
- :on-hide-comments handle-hide-comments}])
- [:div {:class (stl/css :profile-section)}
- [:div {:class (stl/css :profile)
- :tab-index "0"
- :on-click handle-click
- :on-key-down handle-key-down
- :data-test "profile-btn"}
- [:img {:src photo
- :alt (:fullname profile)}]
- [:span (:fullname profile)]]
+ [:*
+ (when (and team profile)
+ [:& comments-section
+ {:profile profile
+ :team team
+ :show? show-comments?
+ :on-show-comments handle-show-comments
+ :on-hide-comments handle-hide-comments}])
- [:& dropdown-menu {:on-close handle-close :show @show}
- [:ul {:class (stl/css :dropdown)}
- [:li {:tab-index (if @show "0" "-1")
- :on-click (partial on-click :settings-profile)
- :on-key-down handle-key-down-profile
- :data-test "profile-profile-opt"}
- [:span {:class (stl/css :text)} (tr "labels.your-account")]]
+ [:div {:class (stl/css :profile-section)}
+ [:div {:class (stl/css :profile)
+ :tab-index "0"
+ :on-click handle-click
+ :on-key-down handle-key-down
+ :data-test "profile-btn"}
+ [:img {:src photo
+ :alt (:fullname profile)}]
+ [:span (:fullname profile)]]
+ [:& dropdown-menu {:on-close handle-close :show @show}
+ [:ul {:class (stl/css :dropdown)}
+ [:li {:tab-index (if @show "0" "-1")
+ :on-click (partial on-click :settings-profile)
+ :on-key-down handle-key-down-profile
+ :data-test "profile-profile-opt"}
+ [:span {:class (stl/css :text)} (tr "labels.your-account")]]
+
+ [:li {:class (stl/css :separator)
+ :tab-index (if @show "0" "-1")
+ :data-url "https://help.penpot.app"
+ :on-click handle-click-url
+ :on-key-down handle-keydown-url
+ :data-test "help-center-profile-opt"}
+ [:span {:class (stl/css :text)} (tr "labels.help-center")]]
+
+ [:li {:tab-index (if @show "0" "-1")
+ :data-url "https://community.penpot.app"
+ :on-click handle-click-url
+ :on-key-down handle-keydown-url}
+ [:span {:class (stl/css :text)} (tr "labels.community")]]
+
+ [:li {:tab-index (if @show "0" "-1")
+ :data-url "https://www.youtube.com/c/Penpot"
+ :on-click handle-click-url
+ :on-key-down handle-keydown-url}
+ [:span {:class (stl/css :text)} (tr "labels.tutorials")]]
+
+ [:li {:tab-index (if @show "0" "-1")
+ :on-click show-release-notes
+ :on-key-down handle-show-release-notes}
+ [:span {:class (stl/css :text)} (tr "labels.release-notes")]]
+
+ [:li {:class (stl/css :separator)
+ :tab-index (if @show "0" "-1")
+ :data-url "https://penpot.app/libraries-templates"
+ :on-click handle-click-url
+ :on-key-down handle-keydown-url
+ :data-test "libraries-templates-profile-opt"}
+ [:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]]
+
+ [:li {:tab-index (if @show "0" "-1")
+ :data-url "https://github.com/penpot/penpot"
+ :on-click handle-click-url
+ :on-key-down handle-keydown-url}
+ [:span {:class (stl/css :text)} (tr "labels.github-repo")]]
+
+ [:li {:tab-index (if @show "0" "-1")
+ :data-url "https://penpot.app/terms"
+ :on-click handle-click-url
+ :on-key-down handle-keydown-url}
+ [:span {:class (stl/css :text)} (tr "auth.terms-of-service")]]
+
+ (when (contains? cf/flags :user-feedback)
[:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1")
- :data-url "https://help.penpot.app"
- :on-click handle-click-url
- :on-key-down handle-keydown-url
- :data-test "help-center-profile-opt"}
- [:span {:class (stl/css :text)} (tr "labels.help-center")]]
+ :on-click handle-feedback-click
+ :on-key-down handle-feedback-keydown
+ :data-test "feedback-profile-opt"}
+ [:span {:class (stl/css :text)} (tr "labels.give-feedback")]])
- [:li {:tab-index (if @show "0" "-1")
- :data-url "https://community.penpot.app"
- :on-click handle-click-url
- :on-key-down handle-keydown-url}
- [:span {:class (stl/css :text)} (tr "labels.community")]]
+ [:li {:class (stl/css :separator)
+ :tab-index (if @show "0" "-1")
+ :on-click handle-logout-click
+ :on-key-down handle-logout-keydown
+ :data-test "logout-profile-opt"}
+ [:span {:class (stl/css :icon)} i/exit]
+ [:span {:class (stl/css :text)} (tr "labels.logout")]]]]
- [:li {:tab-index (if @show "0" "-1")
- :data-url "https://www.youtube.com/c/Penpot"
- :on-click handle-click-url
- :on-key-down handle-keydown-url}
- [:span {:class (stl/css :text)} (tr "labels.tutorials")]]
-
- [:li {:tab-index (if @show "0" "-1")
- :on-click show-release-notes
- :on-key-down handle-show-release-notes}
- [:span {:class (stl/css :text)} (tr "labels.release-notes")]]
-
- [:li {:class (stl/css :separator)
- :tab-index (if @show "0" "-1")
- :data-url "https://penpot.app/libraries-templates"
- :on-click handle-click-url
- :on-key-down handle-keydown-url
- :data-test "libraries-templates-profile-opt"}
- [:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]]
-
- [:li {:tab-index (if @show "0" "-1")
- :data-url "https://github.com/penpot/penpot"
- :on-click handle-click-url
- :on-key-down handle-keydown-url}
- [:span {:class (stl/css :text)} (tr "labels.github-repo")]]
-
- [:li {:tab-index (if @show "0" "-1")
- :data-url "https://penpot.app/terms"
- :on-click handle-click-url
- :on-key-down handle-keydown-url}
- [:span {:class (stl/css :text)} (tr "auth.terms-of-service")]]
-
- (when (contains? cf/flags :user-feedback)
- [:li {:class (stl/css :separator)
- :tab-index (if @show "0" "-1")
- :on-click handle-feedback-click
- :on-key-down handle-feedback-keydown
- :data-test "feedback-profile-opt"}
- [:span {:class (stl/css :text)} (tr "labels.give-feedback")]])
-
- [:li {:class (stl/css :separator)
- :tab-index (if @show "0" "-1")
- :on-click handle-logout-click
- :on-key-down handle-logout-keydown
- :data-test "logout-profile-opt"}
- [:span {:class (stl/css :icon)} i/exit]
- [:span {:class (stl/css :text)} (tr "labels.logout")]]]]
-
- (when (and team profile)
- [:& comments-icon
- {:profile profile
- :show? show-comments?
- :on-show-comments handle-show-comments}])]]
-
- ;; OLD
- [:div.profile-section
- [:div.profile {:tab-index "0"
- :on-click (fn [event]
- (dom/stop-propagation event)
- (reset! show true))
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (reset! show true)))
- :data-test "profile-btn"}
- [:img {:src photo
- :alt (:fullname profile)}]
- [:span (:fullname profile)]]
-
- [:& dropdown-menu {:on-close (fn [event]
- (dom/stop-propagation event)
- (reset! show false))
- :show @show}
- [:ul.dropdown
- [:li {:tab-index (if show
- "0"
- "-1")
- :on-click (partial on-click :settings-profile)
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-click :settings-profile event)))
- :data-test "profile-profile-opt"}
- [:span.text (tr "labels.your-account")]]
- [:li.separator {:tab-index (if show
- "0"
- "-1")
- :on-click #(dom/open-new-window "https://help.penpot.app")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/open-new-window "https://help.penpot.app")))
- :data-test "help-center-profile-opt"}
- [:span.text (tr "labels.help-center")]]
- [:li {:tab-index (if show
- "0"
- "-1")
- :on-click #(dom/open-new-window "https://community.penpot.app")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/open-new-window "https://community.penpot.app")))}
- [:span.text (tr "labels.community")]]
- [:li {:tab-index (if show
- "0"
- "-1")
- :on-click #(dom/open-new-window "https://www.youtube.com/c/Penpot")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/open-new-window "https://www.youtube.com/c/Penpot")))}
- [:span.text (tr "labels.tutorials")]]
- [:li {:tab-index (if show
- "0"
- "-1")
- :on-click show-release-notes
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (show-release-notes)))}
- [:span (tr "labels.release-notes")]]
-
- [:li.separator {:tab-index (if show
- "0"
- "-1")
- :on-click #(dom/open-new-window "https://penpot.app/libraries-templates")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/open-new-window "https://penpot.app/libraries-templates")))
- :data-test "libraries-templates-profile-opt"}
- [:span.text (tr "labels.libraries-and-templates")]]
- [:li {:tab-index (if show
- "0"
- "-1")
- :on-click #(dom/open-new-window "https://github.com/penpot/penpot")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/open-new-window "https://github.com/penpot/penpot")))}
- [:span (tr "labels.github-repo")]]
- [:li {:tab-index (if show
- "0"
- "-1")
- :on-click #(dom/open-new-window "https://penpot.app/terms")
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/open-new-window "https://penpot.app/terms")))}
- [:span (tr "auth.terms-of-service")]]
-
- (when (contains? cf/flags :user-feedback)
- [:li.separator {:tab-index (if show
- "0"
- "-1")
- :on-click (partial on-click :settings-feedback)
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-click :settings-feedback event)))
- :data-test "feedback-profile-opt"}
- [:span.text (tr "labels.give-feedback")]])
-
- [:li.separator {:tab-index (if show
- "0"
- "-1")
- :on-click #(on-click (du/logout) %)
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (on-click (du/logout) event)))
- :data-test "logout-profile-opt"}
- [:span.icon i/exit]
- [:span.text (tr "labels.logout")]]]]
-
- (when (and team profile)
- [:& comments-section
- {:profile profile
- :team team
- :show? show-comments?
- :on-show-comments handle-show-comments
- :on-hide-comments handle-hide-comments}])])))
+ (when (and team profile)
+ [:& comments-icon
+ {:profile profile
+ :show? show-comments?
+ :on-show-comments handle-show-comments}])]]))
(mf/defc sidebar
{::mf/wrap-props false
::mf/wrap [mf/memo]}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- team (obj/get props "team")
+ (let [team (obj/get props "team")
profile (obj/get props "profile")]
- (if new-css-system
- [:nav {:class (stl/css :dashboard-sidebar)}
- [:> sidebar-content props]
- [:& profile-section
- {:profile profile
- :team team}]]
-
- [:nav.dashboard-sidebar
- [:> sidebar-content props]
- [:& profile-section
- {:profile profile
- :team team}]])))
+ [:nav {:class (stl/css :dashboard-sidebar)}
+ [:> sidebar-content props]
+ [:& profile-section
+ {:profile profile
+ :team team}]]))
diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs
index 2f4f57a65d..8a2f958a3b 100644
--- a/frontend/src/app/main/ui/dashboard/team.cljs
+++ b/frontend/src/app/main/ui/dashboard/team.cljs
@@ -21,7 +21,6 @@
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.change-owner]
[app.main.ui.dashboard.team-form]
[app.main.ui.icons :as i]
@@ -36,8 +35,7 @@
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[{:keys [section team]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-nav-members (mf/use-fn #(st/emit! (dd/go-to-team-members)))
+ (let [on-nav-members (mf/use-fn #(st/emit! (dd/go-to-team-members)))
on-nav-settings (mf/use-fn #(st/emit! (dd/go-to-team-settings)))
on-nav-invitations (mf/use-fn #(st/emit! (dd/go-to-team-invitations)))
on-nav-webhooks (mf/use-fn #(st/emit! (dd/go-to-team-webhooks)))
@@ -56,62 +54,33 @@
:team team
:origin :team}))))]
- (if new-css-system
- [:header {:class (stl/css :dashboard-header :team)}
- [:div {:class (stl/css :dashboard-title)}
- [:h1 (cond
- members-section? (tr "labels.members")
- settings-section? (tr "labels.settings")
- invitations-section? (tr "labels.invitations")
- webhooks-section? (tr "labels.webhooks")
- :else nil)]]
- [:nav {:class (stl/css :dashboard-header-menu)}
- [:ul {:class (stl/css :dashboard-header-options)}
- [:li {:class (when members-section? (stl/css :active))}
- [:a {:on-click on-nav-members} (tr "labels.members")]]
- [:li {:class (when invitations-section? (stl/css :active))}
- [:a {:on-click on-nav-invitations} (tr "labels.invitations")]]
- (when (contains? cfg/flags :webhooks)
- [:li {:class (when webhooks-section? (stl/css :active))}
- [:a {:on-click on-nav-webhooks} (tr "labels.webhooks")]])
- [:li {:class (when settings-section? (stl/css :active))}
- [:a {:on-click on-nav-settings} (tr "labels.settings")]]]]
- [:div {:class (stl/css :dashboard-buttons)}
- (if (and (or invitations-section? members-section?) (:is-admin permissions))
- [:a
- {:class (stl/css :btn-secondary :btn-small)
- :on-click on-invite-member
- :data-test "invite-member"}
- (tr "dashboard.invite-profile")]
- [:div {:class (stl/css :blank-space)}])]]
-
- ;; OLD
- [:header.dashboard-header.team
- [:div.dashboard-title
- [:h1 (cond
- members-section? (tr "labels.members")
- settings-section? (tr "labels.settings")
- invitations-section? (tr "labels.invitations")
- webhooks-section? (tr "labels.webhooks")
- :else nil)]]
- [:nav.dashboard-header-menu
- [:ul.dashboard-header-options
- [:li {:class (when members-section? "active")}
- [:a {:on-click on-nav-members} (tr "labels.members")]]
- [:li {:class (when invitations-section? "active")}
- [:a {:on-click on-nav-invitations} (tr "labels.invitations")]]
- (when (contains? cfg/flags :webhooks)
- [:li {:class (when webhooks-section? "active")}
- [:a {:on-click on-nav-webhooks} (tr "labels.webhooks")]])
- [:li {:class (when settings-section? "active")}
- [:a {:on-click on-nav-settings} (tr "labels.settings")]]]]
- [:div.dashboard-buttons
- (if (and (or invitations-section? members-section?) (:is-admin permissions))
- [:a.btn-secondary.btn-small
- {:on-click on-invite-member
- :data-test "invite-member"}
- (tr "dashboard.invite-profile")]
- [:div.blank-space])]])))
+ [:header {:class (stl/css :dashboard-header :team)}
+ [:div {:class (stl/css :dashboard-title)}
+ [:h1 (cond
+ members-section? (tr "labels.members")
+ settings-section? (tr "labels.settings")
+ invitations-section? (tr "labels.invitations")
+ webhooks-section? (tr "labels.webhooks")
+ :else nil)]]
+ [:nav {:class (stl/css :dashboard-header-menu)}
+ [:ul {:class (stl/css :dashboard-header-options)}
+ [:li {:class (when members-section? (stl/css :active))}
+ [:a {:on-click on-nav-members} (tr "labels.members")]]
+ [:li {:class (when invitations-section? (stl/css :active))}
+ [:a {:on-click on-nav-invitations} (tr "labels.invitations")]]
+ (when (contains? cfg/flags :webhooks)
+ [:li {:class (when webhooks-section? (stl/css :active))}
+ [:a {:on-click on-nav-webhooks} (tr "labels.webhooks")]])
+ [:li {:class (when settings-section? (stl/css :active))}
+ [:a {:on-click on-nav-settings} (tr "labels.settings")]]]]
+ [:div {:class (stl/css :dashboard-buttons)}
+ (if (and (or invitations-section? members-section?) (:is-admin permissions))
+ [:a
+ {:class (stl/css :btn-secondary :btn-small)
+ :on-click on-invite-member
+ :data-test "invite-member"}
+ (tr "dashboard.invite-profile")]
+ [:div {:class (stl/css :blank-space)}])]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INVITATIONS MODAL
@@ -140,8 +109,7 @@
::mf/register-as :invite-members
::mf/wrap-props false}
[{:keys [team origin]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- members-map (mf/deref refs/dashboard-team-members)
+ (let [members-map (mf/deref refs/dashboard-team-members)
perms (:permissions team)
roles (mf/use-memo (mf/deps perms) #(get-available-roles perms))
@@ -188,80 +156,41 @@
(dd/fetch-team-invitations))))]
- (if new-css-system
- [:div {:class (stl/css-case :modal-team-container true
- :hero (= origin :hero))}
- [:& fm/form {:on-submit on-submit :form form}
- [:div {:class (stl/css :modal-title)}
- (tr "modals.invite-team-member.title")]
+ [:div {:class (stl/css-case :modal-team-container true
+ :hero (= origin :hero))}
+ [:& fm/form {:on-submit on-submit :form form}
+ [:div {:class (stl/css :modal-title)}
+ (tr "modals.invite-team-member.title")]
- (when-not (= "" @error-text)
- [:div {:class (stl/css :error-msg)}
- [:span {:class (stl/css :icon)} i/msg-error]
- [:span {:class (stl/css :message)} @error-text]])
+ (when-not (= "" @error-text)
+ [:div {:class (stl/css :error-msg)}
+ [:span {:class (stl/css :icon)} i/msg-error]
+ [:span {:class (stl/css :message)} @error-text]])
- (when (some current-data-emails current-members-emails)
- [:div {:class (stl/css :warning-msg)}
- [:span {:class (stl/css :icon)} i/msg-warning]
- [:span {:class (stl/css :message)} (tr "modals.invite-member.repeated-invitation")]])
+ (when (some current-data-emails current-members-emails)
+ [:div {:class (stl/css :warning-msg)}
+ [:span {:class (stl/css :icon)} i/msg-warning]
+ [:span {:class (stl/css :message)} (tr "modals.invite-member.repeated-invitation")]])
- [:div {:class (stl/css :role-select)}
- [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
- [:& fm/select {:name :role :options roles}]]
+ [:div {:class (stl/css :role-select)}
+ [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
+ [:& fm/select {:name :role :options roles}]]
- [:div {:class (stl/css :invitation-row)}
- [:& fm/multi-input {:type "email"
- :name :emails
- :auto-focus? true
- :trim true
- :valid-item-fn us/parse-email
- :caution-item-fn current-members-emails
- :label (tr "modals.invite-member.emails")
- :on-submit on-submit}]]
+ [:div {:class (stl/css :invitation-row)}
+ [:& fm/multi-input {:type "email"
+ :name :emails
+ :auto-focus? true
+ :trim true
+ :valid-item-fn us/parse-email
+ :caution-item-fn current-members-emails
+ :label (tr "modals.invite-member.emails")
+ :on-submit on-submit}]]
- [:div {:class (stl/css :action-buttons)}
- [:> fm/submit-button*
- {:label (tr "modals.invite-member-confirm.accept")
- :disabled (and (boolean (some current-data-emails current-members-emails))
- (empty? (remove current-members-emails current-data-emails)))}]]]]
-
-
- [:div.modal.dashboard-invite-modal.form-container
- {:class (dom/classnames
- :hero (= origin :hero))}
- [:& fm/form {:on-submit on-submit :form form}
- [:div.title
- [:span.text (tr "modals.invite-team-member.title")]]
-
- (when-not (= "" @error-text)
- [:div.error
- [:span.icon i/msg-error]
- [:span.text @error-text]])
-
- (when (some current-data-emails current-members-emails)
- [:div.warning
- [:span.icon i/msg-warning]
- [:span.text (tr "modals.invite-member.repeated-invitation")]])
-
- [:div.form-row
- [:p.label (tr "onboarding.choice.team-up.roles")]
- [:& fm/select {:name :role :options roles}]]
-
- [:div.form-row
- [:& fm/multi-input {:type "email"
- :name :emails
- :auto-focus? true
- :trim true
- :valid-item-fn us/parse-email
- :caution-item-fn current-members-emails
- :label (tr "modals.invite-member.emails")
- :on-submit on-submit}]]
-
- [:div.action-buttons
- [:> fm/submit-button*
- {:label (tr "modals.invite-member-confirm.accept")
- :disabled (and (boolean (some current-data-emails current-members-emails))
- (empty? (remove current-members-emails current-data-emails)))}]]]])))
+ [:div {:class (stl/css :action-buttons)}
+ [:> fm/submit-button*
+ {:label (tr "modals.invite-member-confirm.accept")
+ :disabled (and (boolean (some current-data-emails current-members-emails))
+ (empty? (remove current-members-emails current-data-emails)))}]]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MEMBERS SECTION
@@ -270,33 +199,20 @@
(mf/defc member-info
{::mf/wrap-props false}
[{:keys [member profile]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- is-you? (= (:id profile) (:id member))]
- (if new-css-system
- [:*
- [:div {:class (stl/css :member-image)}
- [:img {:src (cfg/resolve-profile-photo-url member)}]]
- [:div {:class (stl/css :member-info)}
- [:div {:class (stl/css :member-name)} (:name member)
- (when is-you?
- [:span {:class (stl/css :you)} (tr "labels.you")])]
- [:div {:class (stl/css :member-email)} (:email member)]]]
-
- ;; OLD
- [:*
- [:div.member-image
- [:img {:src (cfg/resolve-profile-photo-url member)}]]
- [:div.member-info
- [:div.member-name (:name member)
- (when is-you?
- [:span.you (tr "labels.you")])]
- [:div.member-email (:email member)]]])))
+ (let [is-you? (= (:id profile) (:id member))]
+ [:*
+ [:div {:class (stl/css :member-image)}
+ [:img {:src (cfg/resolve-profile-photo-url member)}]]
+ [:div {:class (stl/css :member-info)}
+ [:div {:class (stl/css :member-name)} (:name member)
+ (when is-you?
+ [:span {:class (stl/css :you)} (tr "labels.you")])]
+ [:div {:class (stl/css :member-email)} (:email member)]]]))
(mf/defc rol-info
{::mf/wrap-props false}
[{:keys [member team on-set-admin on-set-editor on-set-owner profile]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- member-is-owner? (:is-owner member)
+ (let [member-is-owner? (:is-owner member)
member-is-admin? (and (:is-admin member) (not member-is-owner?))
member-is-editor? (and (:can-edit member) (and (not member-is-admin?) (not member-is-owner?)))
show? (mf/use-state false)
@@ -316,50 +232,29 @@
on-show (mf/use-fn #(reset! show? true))
on-hide (mf/use-fn #(reset! show? false))]
- (if new-css-system
- [:*
- (if (and can-change-rol? not-superior? (not (and is-you? you-owner?)))
- [:div {:class (stl/css :rol-selector :has-priv)
- :on-click on-show}
- [:span {:class (stl/css :rol-label)} (tr role)]
- [:span {:class (stl/css :icon)} i/arrow-down]]
- [:div {:class (stl/css :rol-selector)}
- [:span {:class (stl/css :rol-label)} (tr role)]])
+ [:*
+ (if (and can-change-rol? not-superior? (not (and is-you? you-owner?)))
+ [:div {:class (stl/css :rol-selector :has-priv)
+ :on-click on-show}
+ [:span {:class (stl/css :rol-label)} (tr role)]
+ [:span {:class (stl/css :icon)} i/arrow-down]]
+ [:div {:class (stl/css :rol-selector)}
+ [:span {:class (stl/css :rol-label)} (tr role)]])
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul {:class (stl/css :dropdown :options-dropdown)}
- [:li {:on-click on-set-admin} (tr "labels.admin")]
- [:li {:on-click on-set-editor} (tr "labels.editor")]
- ;; Temporarily disabled viewer role
- ;; https://tree.taiga.io/project/penpot/issue/1083
- ;; [:li {:on-click set-viewer} (tr "labels.viewer")]
- (when you-owner?
- [:li {:on-click (partial on-set-owner member)} (tr "labels.owner")])]]]
-
- ;; OLD
- [:*
- (if (and can-change-rol? not-superior? (not (and is-you? you-owner?)))
- [:div.rol-selector.has-priv {:on-click on-show}
- [:span.rol-label (tr role)]
- [:span.icon i/arrow-down]]
- [:div.rol-selector
- [:span.rol-label (tr role)]])
-
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul.dropdown.options-dropdown
- [:li {:on-click on-set-admin} (tr "labels.admin")]
- [:li {:on-click on-set-editor} (tr "labels.editor")]
- ;; Temporarily disabled viewer role
- ;; https://tree.taiga.io/project/penpot/issue/1083
- ;; [:li {:on-click set-viewer} (tr "labels.viewer")]
- (when you-owner?
- [:li {:on-click (partial on-set-owner member)} (tr "labels.owner")])]]])))
+ [:& dropdown {:show @show? :on-close on-hide}
+ [:ul {:class (stl/css :dropdown :options-dropdown)}
+ [:li {:on-click on-set-admin} (tr "labels.admin")]
+ [:li {:on-click on-set-editor} (tr "labels.editor")]
+ ;; Temporarily disabled viewer role
+ ;; https://tree.taiga.io/project/penpot/issue/1083
+ ;; [:li {:on-click set-viewer} (tr "labels.viewer")]
+ (when you-owner?
+ [:li {:on-click (partial on-set-owner member)} (tr "labels.owner")])]]]))
(mf/defc member-actions
{::mf/wrap-props false}
[{:keys [member team on-delete on-leave profile]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- is-owner? (:is-owner member)
+ (let [is-owner? (:is-owner member)
owner? (dm/get-in team [:permissions :is-owner])
admin? (dm/get-in team [:permissions :is-admin])
show? (mf/use-state false)
@@ -369,30 +264,17 @@
on-show (mf/use-fn #(reset! show? true))
on-hide (mf/use-fn #(reset! show? false))]
- (if new-css-system
- [:*
- (when (or is-you? (and can-delete? (not (and is-owner? (not owner?)))))
- [:span {:class (stl/css :icon)
- :on-click on-show} [i/actions]])
+ [:*
+ (when (or is-you? (and can-delete? (not (and is-owner? (not owner?)))))
+ [:span {:class (stl/css :icon)
+ :on-click on-show} [i/actions]])
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul {:class (stl/css :dropdown :actions-dropdown)}
- (when is-you?
- [:li {:on-click on-leave} (tr "dashboard.leave-team")])
- (when (and can-delete? (not is-you?) (not (and is-owner? (not owner?))))
- [:li {:on-click on-delete} (tr "labels.remove-member")])]]]
-
- ;; OLD
- [:*
- (when (or is-you? (and can-delete? (not (and is-owner? (not owner?)))))
- [:span.icon {:on-click on-show} [i/actions]])
-
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul.dropdown.actions-dropdown
- (when is-you?
- [:li {:on-click on-leave} (tr "dashboard.leave-team")])
- (when (and can-delete? (not is-you?) (not (and is-owner? (not owner?))))
- [:li {:on-click on-delete} (tr "labels.remove-member")])]]])))
+ [:& dropdown {:show @show? :on-close on-hide}
+ [:ul {:class (stl/css :dropdown :actions-dropdown)}
+ (when is-you?
+ [:li {:on-click on-leave} (tr "dashboard.leave-team")])
+ (when (and can-delete? (not is-you?) (not (and is-owner? (not owner?))))
+ [:li {:on-click on-delete} (tr "labels.remove-member")])]]]))
(defn- set-role! [member-id role]
(let [params {:member-id member-id :role role}]
@@ -403,8 +285,7 @@
::mf/wrap-props false}
[{:keys [team member members profile]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- member-id (:id member)
+ (let [member-id (:id member)
on-set-admin (mf/use-fn (mf/deps member-id) (partial set-role! member-id :admin))
on-set-editor (mf/use-fn (mf/deps member-id) (partial set-role! member-id :editor))
owner? (dm/get-in team [:permissions :is-owner])
@@ -513,50 +394,29 @@
(= true owner?) on-change-owner-and-leave
:else on-leave)]
- (if new-css-system
- [:div {:class (stl/css :table-row)}
- [:div {:class (stl/css :table-field :name)}
- [:& member-info {:member member :profile profile}]]
+ [:div {:class (stl/css :table-row)}
+ [:div {:class (stl/css :table-field :name)}
+ [:& member-info {:member member :profile profile}]]
- [:div {:class (stl/css :table-field :roles)}
- [:& rol-info {:member member
- :team team
- :on-set-admin on-set-admin
- :on-set-editor on-set-editor
- :on-set-owner on-set-owner
- :profile profile}]]
+ [:div {:class (stl/css :table-field :roles)}
+ [:& rol-info {:member member
+ :team team
+ :on-set-admin on-set-admin
+ :on-set-editor on-set-editor
+ :on-set-owner on-set-owner
+ :profile profile}]]
- [:div {:class (stl/css :table-field :actions)}
- [:& member-actions {:member member
- :profile profile
- :team team
- :on-delete on-delete
- :on-leave on-leave'}]]]
- ;; OLD
- [:div.table-row
- [:div.table-field.name
- [:& member-info {:member member :profile profile}]]
-
- [:div.table-field.roles
- [:& rol-info {:member member
- :team team
- :on-set-admin on-set-admin
- :on-set-editor on-set-editor
- :on-set-owner on-set-owner
- :profile profile}]]
-
- [:div.table-field.actions
- [:& member-actions {:member member
- :profile profile
- :team team
- :on-delete on-delete
- :on-leave on-leave'}]]])))
+ [:div {:class (stl/css :table-field :actions)}
+ [:& member-actions {:member member
+ :profile profile
+ :team team
+ :on-delete on-delete
+ :on-leave on-leave'}]]]))
(mf/defc team-members
{::mf/wrap-props false}
[{:keys [members-map team profile]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- members (mf/with-memo [members-map]
+ (let [members (mf/with-memo [members-map]
(->> (vals members-map)
(sort-by :created-at)
(remove :is-owner)))
@@ -564,53 +424,30 @@
(->> (vals members-map)
(d/seek :is-owner)))]
- (if new-css-system
- [:div {:class (stl/css :dashboard-table :team-members)}
- [:div {:class (stl/css :table-header)}
- [:div {:class (stl/css :table-field :name)} (tr "labels.member")]
- [:div {:class (stl/css :table-field :role)} (tr "labels.role")]]
+ [:div {:class (stl/css :dashboard-table :team-members)}
+ [:div {:class (stl/css :table-header)}
+ [:div {:class (stl/css :table-field :name)} (tr "labels.member")]
+ [:div {:class (stl/css :table-field :role)} (tr "labels.role")]]
- [:div {:class (stl/css :table-rows)}
+ [:div {:class (stl/css :table-rows)}
+ [:& team-member
+ {:member owner
+ :team team
+ :profile profile
+ :members members-map}]
+
+ (for [item members]
[:& team-member
- {:member owner
+ {:member item
:team team
:profile profile
- :members members-map}]
-
- (for [item members]
- [:& team-member
- {:member item
- :team team
- :profile profile
- :key (:id item)
- :members members-map}])]]
-
- ;; OLD
- [:div.dashboard-table.team-members
- [:div.table-header
- [:div.table-field.name (tr "labels.member")]
- [:div.table-field.role (tr "labels.role")]]
-
- [:div.table-rows
- [:& team-member
- {:member owner
- :team team
- :profile profile
- :members members-map}]
-
- (for [item members]
- [:& team-member
- {:member item
- :team team
- :profile profile
- :key (:id item)
- :members members-map}])]])))
+ :key (:id item)
+ :members members-map}])]]))
(mf/defc team-members-page
{::mf/wrap-props false}
[{:keys [team profile]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- members-map (mf/deref refs/dashboard-team-members)]
+ (let [members-map (mf/deref refs/dashboard-team-members)]
(mf/with-effect [team]
(dom/set-html-title
@@ -622,23 +459,13 @@
(mf/with-effect [team]
(st/emit! (dd/fetch-team-members (:id team))))
- (if new-css-system
- [:*
- [:& header {:section :dashboard-team-members :team team}]
- [:section {:class (stl/css :dashboard-container :dashboard-team-members)}
- [:& team-members
- {:profile profile
- :team team
- :members-map members-map}]]]
-
- ;; OLD
- [:*
- [:& header {:section :dashboard-team-members :team team}]
- [:section.dashboard-container.dashboard-team-members
- [:& team-members
- {:profile profile
- :team team
- :members-map members-map}]]])))
+ [:*
+ [:& header {:section :dashboard-team-members :team team}]
+ [:section {:class (stl/css :dashboard-container :dashboard-team-members)}
+ [:& team-members
+ {:profile profile
+ :team team
+ :members-map members-map}]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INVITATIONS SECTION
@@ -647,8 +474,7 @@
(mf/defc invitation-role-selector
{::mf/wrap-props false}
[{:keys [can-invite? role status on-change]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- show? (mf/use-state false)
+ (let [show? (mf/use-state false)
label (cond
(= role :owner) (tr "labels.owner")
(= role :admin) (tr "labels.admin")
@@ -667,65 +493,37 @@
(keyword))]
(on-change role event))))]
- (if new-css-system
- [:*
- (if (and can-invite? (= status :pending))
- [:div {:class (stl/css :rol-selector :has-priv)
- :on-click on-show}
- [:span {:class (stl/css :rol-label)} label]
- [:span {:class (stl/css :icon)} i/arrow-down]]
- [:div {:class (stl/css :rol-selector)}
- [:span {:class (stl/css :rol-label)} label]])
+ [:*
+ (if (and can-invite? (= status :pending))
+ [:div {:class (stl/css :rol-selector :has-priv)
+ :on-click on-show}
+ [:span {:class (stl/css :rol-label)} label]
+ [:span {:class (stl/css :icon)} i/arrow-down]]
+ [:div {:class (stl/css :rol-selector)}
+ [:span {:class (stl/css :rol-label)} label]])
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul {:class (stl/css :dropdown :options-dropdown)}
- [:li {:data-role "admin" :on-click on-change'} (tr "labels.admin")]
- [:li {:data-role "editor" :on-click on-change'} (tr "labels.editor")]]]]
-
- ;; OLD
- [:*
- (if (and can-invite? (= status :pending))
- [:div.rol-selector.has-priv {:on-click on-show}
- [:span.rol-label label]
- [:span.icon i/arrow-down]]
- [:div.rol-selector
- [:span.rol-label label]])
-
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul.dropdown.options-dropdown
- [:li {:data-role "admin" :on-click on-change'} (tr "labels.admin")]
- [:li {:data-role "editor" :on-click on-change'} (tr "labels.editor")]]]])))
+ [:& dropdown {:show @show? :on-close on-hide}
+ [:ul {:class (stl/css :dropdown :options-dropdown)}
+ [:li {:data-role "admin" :on-click on-change'} (tr "labels.admin")]
+ [:li {:data-role "editor" :on-click on-change'} (tr "labels.editor")]]]]))
(mf/defc invitation-status-badge
{::mf/wrap-props false}
[{:keys [status]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div
- {:class (stl/css-case
- :status-badge true
- :expired (= status :expired)
- :pending (= status :pending))}
- [:span {:class (stl/css :status-label)}
- (if (= status :expired)
- (tr "labels.expired-invitation")
- (tr "labels.pending-invitation"))]]
-
- ;; OLD
- [:div.status-badge
- {:class (dom/classnames
- :expired (= status :expired)
- :pending (= status :pending))}
- [:span.status-label
- (if (= status :expired)
- (tr "labels.expired-invitation")
- (tr "labels.pending-invitation"))]])))
+ [:div
+ {:class (stl/css-case
+ :status-badge true
+ :expired (= status :expired)
+ :pending (= status :pending))}
+ [:span {:class (stl/css :status-label)}
+ (if (= status :expired)
+ (tr "labels.expired-invitation")
+ (tr "labels.pending-invitation"))]])
(mf/defc invitation-actions
{::mf/wrap-props false}
[{:keys [invitation team-id]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- show? (mf/use-state false)
+ (let [show? (mf/use-state false)
email (:email invitation)
role (:role invitation)
@@ -800,32 +598,21 @@
on-hide (mf/use-fn #(reset! show? false))
on-show (mf/use-fn #(reset! show? true))]
- (if new-css-system
- [:*
- [:span {:class (stl/css :icon)
- :on-click on-show} [i/actions]]
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul {:class (stl/css :dropdown :actions-dropdown)}
- [:li {:on-click on-copy} (tr "labels.copy-invitation-link")]
- [:li {:on-click on-resend} (tr "labels.resend-invitation")]
- [:li {:on-click on-delete} (tr "labels.delete-invitation")]]]]
-
- ;; OLD
- [:*
- [:span.icon {:on-click on-show} [i/actions]]
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul.dropdown.actions-dropdown
- [:li {:on-click on-copy} (tr "labels.copy-invitation-link")]
- [:li {:on-click on-resend} (tr "labels.resend-invitation")]
- [:li {:on-click on-delete} (tr "labels.delete-invitation")]]]])))
+ [:*
+ [:span {:class (stl/css :icon)
+ :on-click on-show} [i/actions]]
+ [:& dropdown {:show @show? :on-close on-hide}
+ [:ul {:class (stl/css :dropdown :actions-dropdown)}
+ [:li {:on-click on-copy} (tr "labels.copy-invitation-link")]
+ [:li {:on-click on-resend} (tr "labels.resend-invitation")]
+ [:li {:on-click on-delete} (tr "labels.delete-invitation")]]]]))
(mf/defc invitation-row
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[{:keys [invitation can-invite? team-id] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- expired? (:expired invitation)
+ (let [expired? (:expired invitation)
email (:email invitation)
role (:role invitation)
status (if expired? :expired :pending)
@@ -838,106 +625,58 @@
mdata {:on-success #(st/emit! (dd/fetch-team-invitations))}]
(st/emit! (dd/update-team-invitation-role (with-meta params mdata))))))]
- (if new-css-system
- [:div {:class (stl/css :table-row)}
- [:div {:class (stl/css :table-field :mail)} email]
+ [:div {:class (stl/css :table-row)}
+ [:div {:class (stl/css :table-field :mail)} email]
- [:div {:class (stl/css :table-field :roles)}
- [:& invitation-role-selector
- {:can-invite? can-invite?
- :role role
- :status status
- :on-change on-change-role}]]
+ [:div {:class (stl/css :table-field :roles)}
+ [:& invitation-role-selector
+ {:can-invite? can-invite?
+ :role role
+ :status status
+ :on-change on-change-role}]]
- [:div {:class (stl/css :table-field :status)}
- [:& invitation-status-badge {:status status}]]
+ [:div {:class (stl/css :table-field :status)}
+ [:& invitation-status-badge {:status status}]]
- [:div {:class (stl/css :table-field :actions)}
- (when can-invite?
- [:& invitation-actions
- {:invitation invitation
- :team-id team-id}])]]
-
- ;; OLD
- [:div.table-row
- [:div.table-field.mail email]
-
- [:div.table-field.roles
- [:& invitation-role-selector
- {:can-invite? can-invite?
- :role role
- :status status
- :on-change on-change-role}]]
-
- [:div.table-field.status
- [:& invitation-status-badge {:status status}]]
-
- [:div.table-field.actions
- (when can-invite?
- [:& invitation-actions
- {:invitation invitation
- :team-id team-id}])]])))
+ [:div {:class (stl/css :table-field :actions)}
+ (when can-invite?
+ [:& invitation-actions
+ {:invitation invitation
+ :team-id team-id}])]]))
(mf/defc empty-invitation-table
[{:keys [can-invite?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :empty-invitations)}
- [:span (tr "labels.no-invitations")]
- (when can-invite?
- [:& i18n/tr-html {:label "labels.no-invitations-hint"
- :tag-name "span"}])]
- ;; OLD
- [:div.empty-invitations
- [:span (tr "labels.no-invitations")]
- (when can-invite?
- [:& i18n/tr-html {:label "labels.no-invitations-hint"
- :tag-name "span"}])])))
+ [:div {:class (stl/css :empty-invitations)}
+ [:span (tr "labels.no-invitations")]
+ (when can-invite?
+ [:& i18n/tr-html {:label "labels.no-invitations-hint"
+ :tag-name "span"}])])
(mf/defc invitation-section
[{:keys [team invitations] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- owner? (dm/get-in team [:permissions :is-owner])
+ (let [owner? (dm/get-in team [:permissions :is-owner])
admin? (dm/get-in team [:permissions :is-admin])
can-invite? (or owner? admin?)
team-id (:id team)]
- (if new-css-system
- [:div {:class (stl/css :dashboard-table :invitations)}
- [:div {:class (stl/css :table-header)}
- [:div {:class (stl/css :table-field :name)} (tr "labels.invitations")]
- [:div {:class (stl/css :table-field :role)} (tr "labels.role")]
- [:div {:class (stl/css :table-field :status)} (tr "labels.status")]]
- (if (empty? invitations)
- [:& empty-invitation-table {:can-invite? can-invite?}]
- [:div {:class (stl/css :table-rows)}
- (for [invitation invitations]
- [:& invitation-row
- {:key (:email invitation)
- :invitation invitation
- :can-invite? can-invite?
- :team-id team-id}])])]
-
- ;; OLD
- [:div.dashboard-table.invitations
- [:div.table-header
- [:div.table-field.name (tr "labels.invitations")]
- [:div.table-field.role (tr "labels.role")]
- [:div.table-field.status (tr "labels.status")]]
- (if (empty? invitations)
- [:& empty-invitation-table {:can-invite? can-invite?}]
- [:div.table-rows
- (for [invitation invitations]
- [:& invitation-row
- {:key (:email invitation)
- :invitation invitation
- :can-invite? can-invite?
- :team-id team-id}])])])))
+ [:div {:class (stl/css :dashboard-table :invitations)}
+ [:div {:class (stl/css :table-header)}
+ [:div {:class (stl/css :table-field :name)} (tr "labels.invitations")]
+ [:div {:class (stl/css :table-field :role)} (tr "labels.role")]
+ [:div {:class (stl/css :table-field :status)} (tr "labels.status")]]
+ (if (empty? invitations)
+ [:& empty-invitation-table {:can-invite? can-invite?}]
+ [:div {:class (stl/css :table-rows)}
+ (for [invitation invitations]
+ [:& invitation-row
+ {:key (:email invitation)
+ :invitation invitation
+ :can-invite? can-invite?
+ :team-id team-id}])])]))
(mf/defc team-invitations-page
[{:keys [team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- invitations (mf/deref refs/dashboard-team-invitations)]
+ (let [invitations (mf/deref refs/dashboard-team-invitations)]
(mf/with-effect [team]
(dom/set-html-title
@@ -949,21 +688,12 @@
(mf/with-effect []
(st/emit! (dd/fetch-team-invitations)))
- (if new-css-system
- [:*
- [:& header {:section :dashboard-team-invitations
- :team team}]
- [:section {:class (stl/css :dashboard-container :dashboard-team-invitations)}
- [:& invitation-section {:team team
- :invitations invitations}]]]
-
- ;; OLD
- [:*
- [:& header {:section :dashboard-team-invitations
- :team team}]
- [:section.dashboard-container.dashboard-team-invitations
- [:& invitation-section {:team team
- :invitations invitations}]]])))
+ [:*
+ [:& header {:section :dashboard-team-invitations
+ :team team}]
+ [:section {:class (stl/css :dashboard-container :dashboard-team-invitations)}
+ [:& invitation-section {:team team
+ :invitations invitations}]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WEBHOOKS SECTION
@@ -987,8 +717,7 @@
::mf/register-as :webhook}
[{:keys [webhook] :as props}]
;; FIXME: this is a workaround because input fields do not support rendering hooks
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo (fn [] (or (some-> webhook (update :uri str))
+ (let [initial (mf/use-memo (fn [] (or (some-> webhook (update :uri str))
{:is-active false :mtype "application/json"})))
form (fm/use-form :spec ::webhook-form
:initial initial
@@ -1052,181 +781,95 @@
(on-create-submit form)))))
on-modal-close #(st/emit! (modal/hide))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:& fm/form {:form form :on-submit on-submit}
- [:div {:class (stl/css :modal-header)}
- (if webhook
- [:h2 {:class (stl/css :modal-title)} (tr "modals.edit-webhook.title")]
- [:h2 {:class (stl/css :modal-title)} (tr "modals.create-webhook.title")])
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:& fm/form {:form form :on-submit on-submit}
+ [:div {:class (stl/css :modal-header)}
+ (if webhook
+ [:h2 {:class (stl/css :modal-title)} (tr "modals.edit-webhook.title")]
+ [:h2 {:class (stl/css :modal-title)} (tr "modals.create-webhook.title")])
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-modal-close} i/close-refactor]]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-modal-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "text"
- :auto-focus? true
- :form form
- :name :uri
- :label (tr "modals.create-webhook.url.label")
- :placeholder (tr "modals.create-webhook.url.placeholder")}]]
- [:div {:class (stl/css :fields-row)}
- [:div {:class (stl/css :select-title)} (tr "dashboard.webhooks.content-type")]
- [:& fm/select {:options valid-webhook-mtypes
- :default "application/json"
- :name :mtype}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "checkbox"
- :class (stl/css :custom-input-checkbox)
- :form form
- :name :is-active
- :label (tr "dashboard.webhooks.active")}]
- [:div {:class (stl/css :hint)} (tr "dashboard.webhooks.active.explain")]]]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "text"
+ :auto-focus? true
+ :form form
+ :name :uri
+ :label (tr "modals.create-webhook.url.label")
+ :placeholder (tr "modals.create-webhook.url.placeholder")}]]
+ [:div {:class (stl/css :fields-row)}
+ [:div {:class (stl/css :select-title)} (tr "dashboard.webhooks.content-type")]
+ [:& fm/select {:options valid-webhook-mtypes
+ :default "application/json"
+ :name :mtype}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "checkbox"
+ :class (stl/css :custom-input-checkbox)
+ :form form
+ :name :is-active
+ :label (tr "dashboard.webhooks.active")}]
+ [:div {:class (stl/css :hint)} (tr "dashboard.webhooks.active.explain")]]]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.cancel")
- :on-click #(modal/hide!)}]
- [:> fm/submit-button*
- {:label (if webhook
- (tr "modals.edit-webhook.submit-label")
- (tr "modals.create-webhook.submit-label"))}]]]]]]
-
- ;; OLD
- [:div.modal-overlay
- [:div.modal-container.webhooks-modal
- [:& fm/form {:form form :on-submit on-submit}
-
- [:div.modal-header
- [:div.modal-header-title
- (if webhook
- [:h2 (tr "modals.edit-webhook.title")]
- [:h2 (tr "modals.create-webhook.title")])]
-
- [:div.modal-close-button
- {:on-click #(st/emit! (modal/hide))} i/close]]
-
- [:div.modal-content.generic-form
- [:div.fields-container
- [:div.fields-row
- [:& fm/input {:type "text"
- :auto-focus? true
- :form form
- :name :uri
- :label (tr "modals.create-webhook.url.label")
- :placeholder (tr "modals.create-webhook.url.placeholder")}]]
-
- [:div.fields-row
- [:& fm/select {:options valid-webhook-mtypes
- :label (tr "dashboard.webhooks.content-type")
- :default "application/json"
- :name :mtype}]]]
- [:div.fields-row
- [:div.input-checkbox.check-primary
- [:& fm/input {:type "checkbox"
- :form form
- :name :is-active
- :label (tr "dashboard.webhooks.active")}]]
- [:div.explain (tr "dashboard.webhooks.active.explain")]]]
-
- [:div.modal-footer
- [:div.action-buttons
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.cancel")
- :on-click #(modal/hide!)}]
- [:> fm/submit-button*
- {:label (if webhook
- (tr "modals.edit-webhook.submit-label")
- (tr "modals.create-webhook.submit-label"))}]]]]]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:input {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.cancel")
+ :on-click #(modal/hide!)}]
+ [:> fm/submit-button*
+ {:label (if webhook
+ (tr "modals.edit-webhook.submit-label")
+ (tr "modals.create-webhook.submit-label"))}]]]]]]))
(mf/defc webhooks-hero
{::mf/wrap-props false}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :webhooks-hero-container)}
- [:div {:class (stl/css :webhooks-hero)}
- [:div {:class (stl/css :desc)}
- [:h2 (tr "labels.webhooks")]
- [:& i18n/tr-html {:label "dashboard.webhooks.description"}]]
+ [:div {:class (stl/css :webhooks-hero-container)}
+ [:div {:class (stl/css :webhooks-hero)}
+ [:div {:class (stl/css :desc)}
+ [:h2 (tr "labels.webhooks")]
+ [:& i18n/tr-html {:label "dashboard.webhooks.description"}]]
- [:div
- {:class (stl/css :btn-primary)
- :on-click #(st/emit! (modal/show :webhook {}))}
- [:span (tr "dashboard.webhooks.create")]]]]
-
- ;; OLD
- [:div.webhooks-hero-container
- [:div.webhooks-hero
- [:div.desc
- [:h2 (tr "labels.webhooks")]
- [:& i18n/tr-html {:label "dashboard.webhooks.description"}]]
-
- [:div.btn-primary
- {:on-click #(st/emit! (modal/show :webhook {}))}
- [:span (tr "dashboard.webhooks.create")]]]])))
+ [:div
+ {:class (stl/css :btn-primary)
+ :on-click #(st/emit! (modal/show :webhook {}))}
+ [:span (tr "dashboard.webhooks.create")]]]])
(mf/defc webhook-actions
{::mf/wrap-props false}
[{:keys [on-edit on-delete]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- show? (mf/use-state false)
+ (let [show? (mf/use-state false)
on-show (mf/use-fn #(reset! show? true))
on-hide (mf/use-fn #(reset! show? false))]
-
- (if new-css-system
- [:*
- [:span {:class (stl/css :icon)
- :on-click on-show} [i/actions]]
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul {:class (stl/css :dropdown :actions-dropdown)}
- [:li {:on-click on-edit} (tr "labels.edit")]
- [:li {:on-click on-delete} (tr "labels.delete")]]]]
-
- ;; OLD
- [:*
- [:span.icon {:on-click on-show} [i/actions]]
- [:& dropdown {:show @show? :on-close on-hide}
- [:ul.dropdown.actions-dropdown
- [:li {:on-click on-edit} (tr "labels.edit")]
- [:li {:on-click on-delete} (tr "labels.delete")]]]])))
+
+ [:*
+ [:span {:class (stl/css :icon)
+ :on-click on-show} [i/actions]]
+ [:& dropdown {:show @show? :on-close on-hide}
+ [:ul {:class (stl/css :dropdown :actions-dropdown)}
+ [:li {:on-click on-edit} (tr "labels.edit")]
+ [:li {:on-click on-delete} (tr "labels.delete")]]]]))
(mf/defc last-delivery-icon
{::mf/wrap-props false}
[{:keys [success? text]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :last-delivery-icon)}
- [:div {:class (stl/css :tooltip)}
- [:div {:class (stl/css :label)} text]
- [:div {:class (stl/css :arrow-down)}]]
- (if success?
- [:span {:class (stl/css :icon :success)} i/msg-success]
- [:span {:class (stl/css :icon :failure)} i/msg-warning])]
-
- ;; OLD
- [:div.last-delivery-icon
- [:div.tooltip
- [:div.label text]
- [:div.arrow-down]]
- (if success?
- [:span.icon.success i/msg-success]
- [:span.icon.failure i/msg-warning])])))
+ [:div {:class (stl/css :last-delivery-icon)}
+ [:div {:class (stl/css :tooltip)}
+ [:div {:class (stl/css :label)} text]
+ [:div {:class (stl/css :arrow-down)}]]
+ (if success?
+ [:span {:class (stl/css :icon :success)} i/msg-success]
+ [:span {:class (stl/css :icon :failure)} i/msg-warning])])
(mf/defc webhook-item
{::mf/wrap [mf/memo]}
[{:keys [webhook] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- error-code (:error-code webhook)
+ (let [error-code (:error-code webhook)
id (:id webhook)
on-edit
@@ -1265,64 +908,36 @@
(str/starts-with? error-code "unexpected-status")
(dm/str " " (tr "errors.webhooks.unexpected-status" (extract-status error-code))))))]
-
- (if new-css-system
- [:div {:class (stl/css :table-row)}
- [:div {:class (stl/css :table-field :last-delivery)}
- [:div {:class (stl/css :icon-container)}
- [:& last-delivery-icon
- {:success? (nil? error-code)
- :text last-delivery-text}]]]
- [:div {:class (stl/css :table-field :uri)}
- [:div (dm/str (:uri webhook))]]
- [:div {:class (stl/css :table-field :active)}
- [:div (if (:is-active webhook)
- (tr "labels.active")
- (tr "labels.inactive"))]]
- [:div {:class (stl/css :table-field :actions)}
- [:& webhook-actions
- {:on-edit on-edit
- :on-delete on-delete}]]]
- ;; OLD
- [:div.table-row
- [:div.table-field.last-delivery
- [:div.icon-container
- [:& last-delivery-icon
- {:success? (nil? error-code)
- :text last-delivery-text}]]]
- [:div.table-field.uri
- [:div (dm/str (:uri webhook))]]
- [:div.table-field.active
- [:div (if (:is-active webhook)
- (tr "labels.active")
- (tr "labels.inactive"))]]
- [:div.table-field.actions
- [:& webhook-actions
- {:on-edit on-edit
- :on-delete on-delete}]]])))
+ [:div {:class (stl/css :table-row)}
+ [:div {:class (stl/css :table-field :last-delivery)}
+ [:div {:class (stl/css :icon-container)}
+ [:& last-delivery-icon
+ {:success? (nil? error-code)
+ :text last-delivery-text}]]]
+ [:div {:class (stl/css :table-field :uri)}
+ [:div (dm/str (:uri webhook))]]
+ [:div {:class (stl/css :table-field :active)}
+ [:div (if (:is-active webhook)
+ (tr "labels.active")
+ (tr "labels.inactive"))]]
+ [:div {:class (stl/css :table-field :actions)}
+ [:& webhook-actions
+ {:on-edit on-edit
+ :on-delete on-delete}]]]))
(mf/defc webhooks-list
{::mf/wrap-props false}
[{:keys [webhooks]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :dashboard-table)}
- [:div {:class (stl/css :table-rows)}
- (for [webhook webhooks]
- [:& webhook-item {:webhook webhook :key (:id webhook)}])]]
-
- ;; OLD
- [:div.dashboard-table
- [:div.table-rows
- (for [webhook webhooks]
- [:& webhook-item {:webhook webhook :key (:id webhook)}])]])))
+ [:div {:class (stl/css :dashboard-table)}
+ [:div {:class (stl/css :table-rows)}
+ (for [webhook webhooks]
+ [:& webhook-item {:webhook webhook :key (:id webhook)}])]])
(mf/defc team-webhooks-page
{::mf/wrap-props false}
[{:keys [team]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- webhooks (mf/deref refs/dashboard-team-webhooks)]
+ (let [webhooks (mf/deref refs/dashboard-team-webhooks)]
(mf/with-effect [team]
(dom/set-html-title
@@ -1334,29 +949,16 @@
(mf/with-effect [team]
(st/emit! (dd/fetch-team-webhooks)))
- (if new-css-system
+ [:*
+ [:& header {:team team :section :dashboard-team-webhooks}]
+ [:section {:class (stl/css :dashboard-container :dashboard-team-webhooks)}
[:*
- [:& header {:team team :section :dashboard-team-webhooks}]
- [:section {:class (stl/css :dashboard-container :dashboard-team-webhooks)}
- [:*
- [:& webhooks-hero]
- (if (empty? webhooks)
- [:div {:class (stl/css :webhooks-empty)}
- [:div (tr "dashboard.webhooks.empty.no-webhooks")]
- [:div (tr "dashboard.webhooks.empty.add-one")]]
- [:& webhooks-list {:webhooks webhooks}])]]]
-
- ;; OLD
- [:*
- [:& header {:team team :section :dashboard-team-webhooks}]
- [:section.dashboard-container.dashboard-team-webhooks
- [:*
- [:& webhooks-hero]
- (if (empty? webhooks)
- [:div.webhooks-empty
- [:div (tr "dashboard.webhooks.empty.no-webhooks")]
- [:div (tr "dashboard.webhooks.empty.add-one")]]
- [:& webhooks-list {:webhooks webhooks}])]]])))
+ [:& webhooks-hero]
+ (if (empty? webhooks)
+ [:div {:class (stl/css :webhooks-empty)}
+ [:div (tr "dashboard.webhooks.empty.no-webhooks")]
+ [:div (tr "dashboard.webhooks.empty.add-one")]]
+ [:& webhooks-list {:webhooks webhooks}])]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SETTINGS SECTION
@@ -1365,8 +967,7 @@
(mf/defc team-settings-page
{::mf/wrap-props false}
[{:keys [team]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- finput (mf/use-ref)
+ (let [finput (mf/use-ref)
members-map (mf/deref refs/dashboard-team-members)
owner (->> (vals members-map)
@@ -1398,77 +999,40 @@
(st/emit! (dd/fetch-team-members team-id)
(dd/fetch-team-stats team-id))))
- (if new-css-system
- [:*
- [:& header {:section :dashboard-team-settings :team team}]
- [:section {:class (stl/css :dashboard-container :dashboard-team-settings)}
- [:div {:class (stl/css :team-settings)}
- [:div {:class (stl/css :horizontal-blocks)}
- [:div {:class (stl/css :block :info-block)}
- [:div {:class (stl/css :label)} (tr "dashboard.team-info")]
- [:div {:class (stl/css :name)} (:name team)]
- [:div {:class (stl/css :icon)}
- (when can-edit?
- [:span {:class (stl/css :update-overlay)
- :on-click on-image-click} i/image])
- [:img {:src (cfg/resolve-team-photo-url team)}]
- (when can-edit?
- [:& file-uploader {:accept "image/jpeg,image/png"
- :multi false
- :ref finput
- :on-selected on-file-selected}])]]
+ [:*
+ [:& header {:section :dashboard-team-settings :team team}]
+ [:section {:class (stl/css :dashboard-container :dashboard-team-settings)}
+ [:div {:class (stl/css :team-settings)}
+ [:div {:class (stl/css :horizontal-blocks)}
+ [:div {:class (stl/css :block :info-block)}
+ [:div {:class (stl/css :label)} (tr "dashboard.team-info")]
+ [:div {:class (stl/css :name)} (:name team)]
+ [:div {:class (stl/css :icon)}
+ (when can-edit?
+ [:span {:class (stl/css :update-overlay)
+ :on-click on-image-click} i/image])
+ [:img {:src (cfg/resolve-team-photo-url team)}]
+ (when can-edit?
+ [:& file-uploader {:accept "image/jpeg,image/png"
+ :multi false
+ :ref finput
+ :on-selected on-file-selected}])]]
- [:div {:class (stl/css :block :owner-block)}
- [:div {:class (stl/css :label)} (tr "dashboard.team-members")]
- [:div {:class (stl/css :owner)}
- [:span {:class (stl/css :icon)} [:img {:src (cfg/resolve-profile-photo-url owner)}]]
- [:span {:class (stl/css :text)} (str (:name owner) " (" (tr "labels.owner") ")")]]
- [:div {:class (stl/css :summary)}
- [:span {:class (stl/css :icon)} i/user]
- [:span {:class (stl/css :text)} (tr "dashboard.num-of-members" (count members-map))]]]
+ [:div {:class (stl/css :block :owner-block)}
+ [:div {:class (stl/css :label)} (tr "dashboard.team-members")]
+ [:div {:class (stl/css :owner)}
+ [:span {:class (stl/css :icon)} [:img {:src (cfg/resolve-profile-photo-url owner)}]]
+ [:span {:class (stl/css :text)} (str (:name owner) " (" (tr "labels.owner") ")")]]
+ [:div {:class (stl/css :summary)}
+ [:span {:class (stl/css :icon)} i/user]
+ [:span {:class (stl/css :text)} (tr "dashboard.num-of-members" (count members-map))]]]
- [:div {:class (stl/css :block :stats-block)}
- [:div {:class (stl/css :label)} (tr "dashboard.team-projects")]
- [:div {:class (stl/css :projects)}
- [:span {:class (stl/css :icon)} i/folder]
- [:span {:class (stl/css :text)} (tr "labels.num-of-projects" (i18n/c (dec (:projects stats))))]]
- [:div {:class (stl/css :files)}
- [:span {:class (stl/css :icon)} i/file-html]
- [:span {:class (stl/css :text)} (tr "labels.num-of-files" (i18n/c (:files stats)))]]]]]]]
-
- [:*
- [:& header {:section :dashboard-team-settings :team team}]
- [:section.dashboard-container.dashboard-team-settings
- [:div.team-settings
- [:div.horizontal-blocks
- [:div.block.info-block
- [:div.label (tr "dashboard.team-info")]
- [:div.name (:name team)]
- [:div.icon
- (when can-edit?
- [:span.update-overlay {:on-click on-image-click} i/image])
- [:img {:src (cfg/resolve-team-photo-url team)}]
- (when can-edit?
- [:& file-uploader {:accept "image/jpeg,image/png"
- :multi false
- :ref finput
- :on-selected on-file-selected}])]]
-
- [:div.block.owner-block
- [:div.label (tr "dashboard.team-members")]
- [:div.owner
- [:span.icon [:img {:src (cfg/resolve-profile-photo-url owner)}]]
- [:span.text (str (:name owner) " (" (tr "labels.owner") ")")]]
- [:div.summary
- [:span.icon i/user]
- [:span.text (tr "dashboard.num-of-members" (count members-map))]]]
-
- [:div.block.stats-block
- [:div.label (tr "dashboard.team-projects")]
- [:div.projects
- [:span.icon i/folder]
- [:span.text (tr "labels.num-of-projects" (i18n/c (dec (:projects stats))))]]
- [:div.files
- [:span.icon i/file-html]
- [:span.text (tr "labels.num-of-files" (i18n/c (:files stats)))]]]]]]])))
+ [:div {:class (stl/css :block :stats-block)}
+ [:div {:class (stl/css :label)} (tr "dashboard.team-projects")]
+ [:div {:class (stl/css :projects)}
+ [:span {:class (stl/css :icon)} i/folder]
+ [:span {:class (stl/css :text)} (tr "labels.num-of-projects" (i18n/c (dec (:projects stats))))]]
+ [:div {:class (stl/css :files)}
+ [:span {:class (stl/css :icon)} i/file-html]
+ [:span {:class (stl/css :text)} (tr "labels.num-of-files" (i18n/c (:files stats)))]]]]]]]))
diff --git a/frontend/src/app/main/ui/dashboard/team.scss b/frontend/src/app/main/ui/dashboard/team.scss
index 83c5eff7ca..d593616b2d 100644
--- a/frontend/src/app/main/ui/dashboard/team.scss
+++ b/frontend/src/app/main/ui/dashboard/team.scss
@@ -102,7 +102,7 @@
}
}
.btn-primary {
- @extends .button-primary;
+ @extend .button-primary;
height: $s-32;
}
}
@@ -650,6 +650,7 @@
color: var(--modal-title-foreground-color);
}
}
+
.invitation-row {
margin-top: $s-8;
margin-bottom: $s-24;
@@ -671,48 +672,56 @@
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
+}
- .modal-content {
- @include flexColumn;
- gap: $s-24;
- @include titleTipography;
- margin-bottom: $s-24;
+.modal-container {
+ @extend .modal-container-base;
+ border: $s-1 solid var(--modal-border-color);
+}
- .fields-row {
- @include flexColumn;
- .select-title {
- @include titleTipography;
- color: var(--modal-title-foreground-color);
- }
- .custom-input-checkbox {
- align-items: flex-start;
- }
- }
- }
+.modal-header {
+ margin-bottom: $s-24;
+}
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- button {
- @extend .modal-accept-btn;
- }
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- }
- }
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include flexColumn;
+ gap: $s-24;
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.fields-row {
+ @include flexColumn;
+}
+
+.select-title {
+ @include titleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.custom-input-checkbox {
+ align-items: flex-start;
+}
+
+.hint {
+ color: var(--modal-text-foreground-color);
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+ button {
+ @extend .modal-accept-btn;
+ }
+ .cancel-button {
+ @extend .modal-cancel-btn;
}
}
diff --git a/frontend/src/app/main/ui/dashboard/team_form.cljs b/frontend/src/app/main/ui/dashboard/team_form.cljs
index 08a8d1df89..258459beea 100644
--- a/frontend/src/app/main/ui/dashboard/team_form.cljs
+++ b/frontend/src/app/main/ui/dashboard/team_form.cljs
@@ -13,7 +13,6 @@
[app.main.data.modal :as modal]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
@@ -70,73 +69,42 @@
(mf/defc team-form-modal {::mf/register modal/components
::mf/register-as :team-form}
[{:keys [team] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo (fn [] (or team {})))
+ (let [initial (mf/use-memo (fn [] (or team {})))
form (fm/use-form :spec ::team-form
:validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space"))
(fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))]
:initial initial)
on-close #(st/emit! (modal/hide))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:& fm/form {:form form :on-submit on-submit}
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:& fm/form {:form form :on-submit on-submit}
- [:div {:class (stl/css :modal-header)}
- (if team
- [:h2 {:class (stl/css :modal-title)}
- (tr "labels.rename-team")]
- [:h2 {:class (stl/css :modal-title)}
- (tr "labels.create-team")])
+ [:div {:class (stl/css :modal-header)}
+ (if team
+ [:h2 {:class (stl/css :modal-title)}
+ (tr "labels.rename-team")]
+ [:h2 {:class (stl/css :modal-title)}
+ (tr "labels.create-team")])
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-close} i/close-refactor]]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:& fm/input {:type "text"
- :auto-focus? true
- :class (stl/css :group-name-input)
- :form form
- :name :name
- :placeholder "E.g. Design"
- :label (tr "labels.create-team.placeholder")}]]
+ [:div {:class (stl/css :modal-content)}
+ [:& fm/input {:type "text"
+ :auto-focus? true
+ :class (stl/css :group-name-input)
+ :form form
+ :name :name
+ :placeholder "E.g. Design"
+ :label (tr "labels.create-team.placeholder")}]]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:> fm/submit-button*
- {:label (if team
- (tr "labels.update-team")
- (tr "labels.create-team"))
- :className (stl/css :accept-btn)}]]]]]]
-
-
-
- [:div.modal-overlay
- [:div.modal-container.team-form-modal
- [:& fm/form {:form form :on-submit on-submit}
-
- [:div.modal-header
- [:div.modal-header-title
- (if team
- [:h2 (tr "labels.rename-team")]
- [:h2 (tr "labels.create-team")])]
-
- [:div.modal-close-button
- {:on-click #(st/emit! (modal/hide))} i/close]]
-
- [:div.modal-content.generic-form
- [:& fm/input {:type "text"
- :auto-focus? true
- :form form
- :name :name
- :label (tr "labels.create-team.placeholder")}]]
-
- [:div.modal-footer
- [:div.action-buttons
- [:> fm/submit-button*
- {:label (if team
- (tr "labels.update-team")
- (tr "labels.create-team"))}]]]]]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:> fm/submit-button*
+ {:label (if team
+ (tr "labels.update-team")
+ (tr "labels.create-team"))
+ :className (stl/css :accept-btn)}]]]]]]))
diff --git a/frontend/src/app/main/ui/dashboard/templates.cljs b/frontend/src/app/main/ui/dashboard/templates.cljs
index c733d4f3e5..8b61fc95b8 100644
--- a/frontend/src/app/main/ui/dashboard/templates.cljs
+++ b/frontend/src/app/main/ui/dashboard/templates.cljs
@@ -16,7 +16,6 @@
[app.main.data.users :as du]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
@@ -59,8 +58,7 @@
(mf/defc title
{::mf/wrap-props false}
[{:keys [collapsed]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-click
+ (let [on-click
(mf/use-fn
(mf/deps collapsed)
(fn [_event]
@@ -76,27 +74,17 @@
(dom/prevent-default event)
(on-click event))))]
- (if new-css-system
- [:div {:class (stl/css :title)}
- [:button {:tab-index "0"
- :on-click on-click
- :on-key-down on-key-down}
- [:span (tr "dashboard.libraries-and-templates")]
- [:span {:class (stl/css :icon)} (if ^boolean collapsed i/arrow-up i/arrow-down)]]]
-
- ;; OLD
- [:div.title
- [:button {:tab-index "0"
- :on-click on-click
- :on-key-down on-key-down}
- [:span (tr "dashboard.libraries-and-templates")]
- [:span.icon (if ^boolean collapsed i/arrow-up i/arrow-down)]]])))
+ [:div {:class (stl/css :title)}
+ [:button {:tab-index "0"
+ :on-click on-click
+ :on-key-down on-key-down}
+ [:span (tr "dashboard.libraries-and-templates")]
+ [:span {:class (stl/css :icon)} (if ^boolean collapsed i/arrow-up i/arrow-down)]]]))
(mf/defc card-item
{::mf/wrap-props false}
[{:keys [item index is-visible collapsed on-import]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- id (dm/str "card-container-" index)
+ (let [id (dm/str "card-container-" index)
thb (assoc cf/public-uri :path (dm/str "/images/thumbnails/template-" (:id item) ".jpg"))
on-click
@@ -113,41 +101,24 @@
(dom/stop-propagation event)
(on-import item event))))]
- (if new-css-system
- [:a
- {:class (stl/css :card-container)
- :tab-index (if (or (not is-visible) collapsed) "-1" "0")
- :id id
- :data-index index
- :on-click on-click
- :on-key-down on-key-down}
- [:div {:class (stl/css :template-card)}
- [:div {:class (stl/css :img-container)}
- [:img {:src (dm/str thb)
- :alt (:name item)}]]
- [:div {:class (stl/css :card-name)}
- [:span (:name item)]
- [:span {:class (stl/css :icon)} i/download]]]]
-
- ;; OLD
- [:a.card-container
- {:tab-index (if (or (not is-visible) collapsed) "-1" "0")
- :id id
- :data-index index
- :on-click on-click
- :on-key-down on-key-down}
- [:div.template-card
- [:div.img-container
- [:img {:src (dm/str thb)
- :alt (:name item)}]]
- [:div.card-name [:span (:name item)]
- [:span.icon i/download]]]])))
+ [:a {:class (stl/css :card-container)
+ :tab-index (if (or (not is-visible) collapsed) "-1" "0")
+ :id id
+ :data-index index
+ :on-click on-click
+ :on-key-down on-key-down}
+ [:div {:class (stl/css :template-card)}
+ [:div {:class (stl/css :img-container)}
+ [:img {:src (dm/str thb)
+ :alt (:name item)}]]
+ [:div {:class (stl/css :card-name)}
+ [:span (:name item)]
+ [:span {:class (stl/css :icon)} i/download]]]]))
(mf/defc card-item-link
{::mf/wrap-props false}
[{:keys [total is-visible collapsed section]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- id (dm/str "card-container-" total)
+ (let [id (dm/str "card-container-" total)
on-click
(mf/use-fn
@@ -165,39 +136,23 @@
(dom/stop-propagation event)
(on-click event))))]
- (if new-css-system
- [:div {:class (stl/css :card-container)}
- [:div {:class (stl/css :template-card)}
- [:div {:class (stl/css :img-container)}
- [:a {:id id
- :tab-index (if (or (not is-visible) collapsed) "-1" "0")
- :href "https://penpot.app/libraries-templates.html"
- :target "_blank"
- :on-click on-click
- :on-key-down on-key-down}
- [:div {:class (stl/css :template-link)}
- [:div {:class (stl/css :template-link-title)} (tr "dashboard.libraries-and-templates")]
- [:div {:class (stl/css :template-link-text)} (tr "dashboard.libraries-and-templates.explore")]]]]]]
-
- ;; OLD
- [:div.card-container
- [:div.template-card
- [:div.img-container
- [:a {:id id
- :tab-index (if (or (not is-visible) collapsed) "-1" "0")
- :href "https://penpot.app/libraries-templates.html"
- :target "_blank"
- :on-click on-click
- :on-key-down on-key-down}
- [:div.template-link
- [:div.template-link-title (tr "dashboard.libraries-and-templates")]
- [:div.template-link-text (tr "dashboard.libraries-and-templates.explore")]]]]]])))
+ [:div {:class (stl/css :card-container)}
+ [:div {:class (stl/css :template-card)}
+ [:div {:class (stl/css :img-container)}
+ [:a {:id id
+ :tab-index (if (or (not is-visible) collapsed) "-1" "0")
+ :href "https://penpot.app/libraries-templates.html"
+ :target "_blank"
+ :on-click on-click
+ :on-key-down on-key-down}
+ [:div {:class (stl/css :template-link)}
+ [:div {:class (stl/css :template-link-title)} (tr "dashboard.libraries-and-templates")]
+ [:div {:class (stl/css :template-link-text)} (tr "dashboard.libraries-and-templates.explore")]]]]]]))
(mf/defc templates-section
{::mf/wrap-props false}
[{:keys [default-project-id profile project-id team-id content-width]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- templates (mf/deref builtin-templates)
+ (let [templates (mf/deref builtin-templates)
templates (mf/with-memo [templates]
(filterv #(not= (:id %) "tutorial-for-beginners") templates))
@@ -273,94 +228,50 @@
(mf/use-fn
(mf/deps default-project-id project-id section templates team-id)
(fn [template _event]
- (import-template! template team-id project-id default-project-id section)))
-
- ]
+ (import-template! template team-id project-id default-project-id section)))]
(mf/with-effect [profile collapsed]
(when (and profile (not collapsed))
(st/emit! (dd/fetch-builtin-templates))))
- (if new-css-system
- [:div
- {:class (stl/css-case :dashboard-templates-section true
- :collapsed collapsed)}
- [:& title {:collapsed collapsed}]
+ [:div {:class (stl/css-case :dashboard-templates-section true
+ :collapsed collapsed)}
+ [:& title {:collapsed collapsed}]
- [:div {:class (stl/css :content)
- :ref content-ref
- :style {:left card-offset
- :width (dm/str container-size "px")}}
+ [:div {:class (stl/css :content)
+ :ref content-ref
+ :style {:left card-offset
+ :width (dm/str container-size "px")}}
- (for [index (range (count templates))]
- [:& card-item
- {:on-import on-import-template
- :item (nth templates index)
- :index index
- :key index
- :is-visible (and (>= index first-card)
- (<= index last-card))
- :collapsed collapsed}])
+ (for [index (range (count templates))]
+ [:& card-item
+ {:on-import on-import-template
+ :item (nth templates index)
+ :index index
+ :key index
+ :is-visible (and (>= index first-card)
+ (<= index last-card))
+ :collapsed collapsed}])
- [:& card-item-link
- {:is-visible (and (>= total first-card) (<= total last-card))
- :collapsed collapsed
- :section section
- :total total}]]
+ [:& card-item-link
+ {:is-visible (and (>= total first-card) (<= total last-card))
+ :collapsed collapsed
+ :section section
+ :total total}]]
- (when (< card-offset 0)
- [:button
- {:class (stl/css :button :left)
- :tab-index (if ^boolean collapsed "-1" "0")
- :on-click on-move-left
- :on-key-down on-move-left-key-down}
- i/go-prev])
+ (when (< card-offset 0)
+ [:button
+ {:class (stl/css :button :left)
+ :tab-index (if ^boolean collapsed "-1" "0")
+ :on-click on-move-left
+ :on-key-down on-move-left-key-down}
+ i/go-prev])
- (when more-cards
- [:button
- {:class (stl/css :button :right)
- :tab-index (if collapsed "-1" "0")
- :on-click on-move-right
- :aria-label (tr "labels.next")
- :on-key-down on-move-right-key-down}
- i/go-next])]
-
- ;; OLD
- [:div.dashboard-templates-section
- {:class (when ^boolean collapsed "collapsed")}
- [:& title {:collapsed collapsed}]
-
- [:div.content {:ref content-ref
- :style {:left card-offset
- :width (dm/str container-size "px")}}
-
- (for [index (range (count templates))]
- [:& card-item
- {:on-import on-import-template
- :item (nth templates index)
- :index index
- :key index
- :is-visible (and (>= index first-card)
- (<= index last-card))
- :collapsed collapsed}])
-
- [:& card-item-link
- {:is-visible (and (>= total first-card) (<= total last-card))
- :collapsed collapsed
- :section section
- :total total}]]
-
- (when (< card-offset 0)
- [:button.button.left
- {:tab-index (if ^boolean collapsed "-1" "0")
- :on-click on-move-left
- :on-key-down on-move-left-key-down}
- i/go-prev])
-
- (when more-cards
- [:button.button.right
- {:tab-index (if collapsed "-1" "0")
- :on-click on-move-right
- :aria-label (tr "labels.next")
- :on-key-down on-move-right-key-down}
- i/go-next])])))
+ (when more-cards
+ [:button
+ {:class (stl/css :button :right)
+ :tab-index (if collapsed "-1" "0")
+ :on-click on-move-right
+ :aria-label (tr "labels.next")
+ :on-key-down on-move-right-key-down}
+ i/go-next])]))
diff --git a/frontend/src/app/main/ui/delete_shared.cljs b/frontend/src/app/main/ui/delete_shared.cljs
index a1e341f45a..f51f62df1e 100644
--- a/frontend/src/app/main/ui/delete_shared.cljs
+++ b/frontend/src/app/main/ui/delete_shared.cljs
@@ -11,7 +11,6 @@
[app.main.data.modal :as modal]
[app.main.repo :as rp]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -27,8 +26,7 @@
::mf/register-as :delete-shared-libraries
::mf/wrap-props false}
[{:keys [ids on-accept on-cancel accept-style origin count-libraries]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- references* (mf/use-state {})
+ (let [references* (mf/use-state {})
references (deref references*)
on-accept (or on-accept noop)
@@ -96,91 +94,43 @@
(let [key (events/listen js/document "keydown" on-keydown)]
(partial events/unlistenByKey key))))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} title]
- [:button {:class (stl/css :modal-close-btn)
- :on-click cancel-fn} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} title]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click cancel-fn} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- (when (and (string? subtitle) (not= subtitle ""))
- [:h3 {:class (stl/css :modal-subtitle)} subtitle])
- (when (not= 0 count-libraries)
- (if (pos? (count references))
- [:*
- [:div
- (when (and (string? scd-msg) (not= scd-msg ""))
- [:h3 {:class (stl/css :modal-scd-msg)} scd-msg])
- [:ul {:class (stl/css :element-list)}
- (for [[file-id file-name] references]
- [:li {:class (stl/css :list-item)
- :key (dm/str file-id)}
- [:span "- " file-name]])]]
- (when (and (string? hint) (not= hint ""))
- [:h3 {:class (stl/css :modal-hint)}hint])]
- [:*
- [:h3 {:class (stl/css :modal-msg)} no-files-msg]]))]
+ [:div {:class (stl/css :modal-content)}
+ (when (and (string? subtitle) (not= subtitle ""))
+ [:h3 {:class (stl/css :modal-subtitle)} subtitle])
+ (when (not= 0 count-libraries)
+ (if (pos? (count references))
+ [:*
+ [:div
+ (when (and (string? scd-msg) (not= scd-msg ""))
+ [:h3 {:class (stl/css :modal-scd-msg)} scd-msg])
+ [:ul {:class (stl/css :element-list)}
+ (for [[file-id file-name] references]
+ [:li {:class (stl/css :list-item)
+ :key (dm/str file-id)}
+ [:span "- " file-name]])]]
+ (when (and (string? hint) (not= hint ""))
+ [:h3 {:class (stl/css :modal-hint)} hint])]
+ [:*
+ [:h3 {:class (stl/css :modal-msg)} no-files-msg]]))]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- (when-not (= cancel-label :omit)
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value cancel-label
- :on-click cancel-fn}])
-
- [:input {:class (stl/css-case :accept-btn true
- :danger (= accept-style :danger)
- :primary (= accept-style :primary))
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ (when-not (= cancel-label :omit)
+ [:input {:class (stl/css :cancel-button)
:type "button"
- :value accept-label
- :on-click accept-fn}]]]]]
+ :value cancel-label
+ :on-click cancel-fn}])
-
- [:div.modal-overlay
- [:div.modal-container.confirm-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 title]]
- [:div.modal-close-button
- {:on-click cancel-fn} i/close]]
-
- [:div.modal-content.delete-shared
- (when (and (string? subtitle) (not= subtitle ""))
- [:h3 subtitle])
- (when (not= 0 count-libraries)
- (if (pos? (count references))
- [:*
- [:div
- (when (and (string? scd-msg) (not= scd-msg ""))
- [:h3 scd-msg])
- [:ul.file-list
- (for [[file-id file-name] references]
- [:li.modal-item-element
- {:key (dm/str file-id)}
- [:span "- " file-name]])]]
- (when (and (string? hint) (not= hint ""))
- [:h3 hint])]
- [:*
- [:h3 no-files-msg]]))]
-
- [:div.modal-footer
- [:div.action-buttons
- (when-not (= cancel-label :omit)
- [:input.cancel-button
- {:type "button"
- :value cancel-label
- :on-click cancel-fn}])
-
- [:input.accept-button
- {:class (dom/classnames
- :danger (= accept-style :danger)
- :primary (= accept-style :primary))
- :type "button"
- :value accept-label
- :on-click accept-fn}]]]]]
- )
-
- ))
+ [:input {:class (stl/css-case :accept-btn true
+ :danger (= accept-style :danger)
+ :primary (= accept-style :primary))
+ :type "button"
+ :value accept-label
+ :on-click accept-fn}]]]]]))
diff --git a/frontend/src/app/main/ui/delete_shared.scss b/frontend/src/app/main/ui/delete_shared.scss
index caa20bdcbb..84ec2e9b54 100644
--- a/frontend/src/app/main/ui/delete_shared.scss
+++ b/frontend/src/app/main/ui/delete_shared.scss
@@ -11,45 +11,53 @@
&.transparent {
background-color: transparent;
}
- .modal-container {
- @extend .modal-container-base;
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .modal-hint {
- @extend .modal-hint-base;
- }
- .element-list {
- @include titleTipography;
- .list-item {
- @include titleTipography;
- }
- }
- }
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+}
+
+.modal-container {
+ @extend .modal-container-base;
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.modal-hint {
+ @extend .modal-hint-base;
+}
+
+.element-list {
+ @include titleTipography;
+ .list-item {
+ @include titleTipography;
+ }
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
diff --git a/frontend/src/app/main/ui/messages.cljs b/frontend/src/app/main/ui/messages.cljs
index f04919fc67..489eae2a60 100644
--- a/frontend/src/app/main/ui/messages.cljs
+++ b/frontend/src/app/main/ui/messages.cljs
@@ -14,96 +14,52 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.link-button :as lb]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.util.dom :as dom]
[rumext.v2 :as mf]))
(mf/defc banner
[{:keys [type position status controls content links actions on-close data-test role] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css-case :banner true
- :warning (= type :warning)
- :error (= type :error)
- :success (= type :success)
- :info (= type :info)
- :fixed (= position :fixed)
- :floating (= position :floating)
- :inline (= position :inline)
- :hide (= status :hide))}
- [:div {:class (stl/css :wrapper)}
- [:div {:class (stl/css :icon)}
- (case type
- :warning i/msg-warning-refactor
- :error i/msg-error-refactor
- :success i/msg-success-refactor
- :info i/msg-neutral-refactor
- i/msg-error-refactor)]
+ [:div {:class (stl/css-case :banner true
+ :warning (= type :warning)
+ :error (= type :error)
+ :success (= type :success)
+ :info (= type :info)
+ :fixed (= position :fixed)
+ :floating (= position :floating)
+ :inline (= position :inline)
+ :hide (= status :hide))}
+ [:div {:class (stl/css :wrapper)}
+ [:div {:class (stl/css :icon)}
+ (case type
+ :warning i/msg-warning-refactor
+ :error i/msg-error-refactor
+ :success i/msg-success-refactor
+ :info i/msg-neutral-refactor
+ i/msg-error-refactor)]
- [:div {:class (stl/css-case :content true
- :inline-actions (= controls :inline-actions)
- :bottom-actions (= controls :bottom-actions))
- :data-test data-test
- :role role}
- [:span {:class (stl/css :text)}
- content
- (for [[index link] (d/enumerate links)]
- [:* {:key (dm/str "link-" index)}
- " " [:& lb/link-button {:class "link"
- :on-click (:callback link)
- :value (:label link)}]])]
+ [:div {:class (stl/css-case :content true
+ :inline-actions (= controls :inline-actions)
+ :bottom-actions (= controls :bottom-actions))
+ :data-test data-test
+ :role role}
+ [:span {:class (stl/css :text)}
+ content
+ (for [[index link] (d/enumerate links)]
+ [:* {:key (dm/str "link-" index)}
+ " " [:& lb/link-button {:class "link"
+ :on-click (:callback link)
+ :value (:label link)}]])]
- (when (or (= controls :bottom-actions) (= controls :inline-actions))
- [:div {:class (stl/css :actions)}
- (for [action actions]
- [:button {:key (uuid/next)
- :class (stl/css :action-bnt)
- :on-click (:callback action)}
- (:label action)])])]
- (when (= controls :close)
- [:button {:class (stl/css :btn-close)
- :on-click on-close} i/close-refactor])]]
-
-
-
- [:div.banner {:class (dom/classnames
- :warning (= type :warning)
- :error (= type :error)
- :success (= type :success)
- :info (= type :info)
- :fixed (= position :fixed)
- :floating (= position :floating)
- :inline (= position :inline)
- :hide (= status :hide))}
- [:div.wrapper
- [:div.icon (case type
- :warning i/msg-warning
- :error i/msg-error
- :success i/msg-success
- :info i/msg-info
- i/msg-error)]
- [:div.content {:class (dom/classnames
- :inline-actions (= controls :inline-actions)
- :bottom-actions (= controls :bottom-actions))
- :data-test data-test
- :role role}
- [:span
- content
- (for [[index link] (d/enumerate links)]
- [:* {:key (dm/str "link-" index)}
- " " [:& lb/link-button {:class "link"
- :on-click (:callback link)
- :value (:label link)}]])]
-
- (when (or (= controls :bottom-actions) (= controls :inline-actions))
- [:div.actions
- (for [action actions]
- [:div.btn-secondary.btn-small {:key (uuid/next)
- :on-click (:callback action)}
- (:label action)])])]
- (when (= controls :close)
- [:div.btn-close {:on-click on-close} i/close])]])))
+ (when (or (= controls :bottom-actions) (= controls :inline-actions))
+ [:div {:class (stl/css :actions)}
+ (for [action actions]
+ [:button {:key (uuid/next)
+ :class (stl/css :action-bnt)
+ :on-click (:callback action)}
+ (:label action)])])]
+ (when (= controls :close)
+ [:button {:class (stl/css :btn-close)
+ :on-click on-close} i/close-refactor])]])
(mf/defc notifications
[]
diff --git a/frontend/src/app/main/ui/messages.scss b/frontend/src/app/main/ui/messages.scss
index 1479f2f142..e2a571c8f7 100644
--- a/frontend/src/app/main/ui/messages.scss
+++ b/frontend/src/app/main/ui/messages.scss
@@ -100,15 +100,6 @@
@include titleTipography;
}
-.inline-actions {
-}
-
-.bottom-actions {
-}
-
-.actions {
-}
-
.action-btn {
@extend .button-tertiary;
height: $s-32;
diff --git a/frontend/src/app/main/ui/modal.cljs b/frontend/src/app/main/ui/modal.cljs
index 3ed224d1a3..a7eb37a45a 100644
--- a/frontend/src/app/main/ui/modal.cljs
+++ b/frontend/src/app/main/ui/modal.cljs
@@ -51,7 +51,6 @@
(let [data (unchecked-get props "data")
wrapper-ref (mf/use-ref nil)
components (mf/deref dm/components)
- new-css-system (mf/use-ctx ctx/new-css-system)
allow-click-outside (:allow-click-outside data)
@@ -78,9 +77,7 @@
(when-let [component (get components (:type data))]
[:div {:ref wrapper-ref
- :class (stl/css-case
- :modal-wrapper new-css-system
- :global/modal-wrapper (not new-css-system))}
+ :class (stl/css :modal-wrapper)}
(mf/element component (:props data))])))
(def modal-ref
diff --git a/frontend/src/app/main/ui/onboarding.cljs b/frontend/src/app/main/ui/onboarding.cljs
index 8b9801d8a1..b16589df32 100644
--- a/frontend/src/app/main/ui/onboarding.cljs
+++ b/frontend/src/app/main/ui/onboarding.cljs
@@ -13,7 +13,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.onboarding.newsletter]
[app.main.ui.onboarding.questions]
[app.main.ui.onboarding.team-choice]
@@ -33,178 +32,113 @@
(mf/defc onboarding-welcome
[{:keys [next] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- go-next
+ (let [go-next
(fn []
(send-event "onboarding-step1-continue")
(next))]
- (if new-css-system
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-left)}
- [:img {:src "images/onboarding-welcome.png"
- :border "0"
- :alt (tr "onboarding.welcome.alt")}]]
- [:div {:class (stl/css :modal-right)}
- [:div {:class (stl/css :release)}
- "Version " (:main cf/version)]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)
- :data-test "onboarding-welcome"}
- (tr "onboarding-v2.welcome.title")]]
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-left)}
+ [:img {:src "images/onboarding-welcome.png"
+ :border "0"
+ :alt (tr "onboarding.welcome.alt")}]]
+ [:div {:class (stl/css :modal-right)}
+ [:div {:class (stl/css :release)}
+ "Version " (:main cf/version)]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)
+ :data-test "onboarding-welcome"}
+ (tr "onboarding-v2.welcome.title")]]
- [:div {:class (stl/css :modal-info)}
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding-v2.welcome.desc1")]
- [:div {:class (stl/css :property-block)}
- [:img {:src "images/community.svg"
- :border "0"}]
- [:div {:class (stl/css :text-wrapper)}
- [:div {:class (stl/css :property-title)}
- [:a {:href "https://community.penpot.app/"
- :target "_blank"
- :on-click #(send-event "onboarding-community-link")}
- (tr "onboarding-v2.welcome.desc2.title")]]
- [:div {:class (stl/css :property-description)}
- (tr "onboarding-v2.welcome.desc2")]]]
+ [:div {:class (stl/css :modal-info)}
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding-v2.welcome.desc1")]
+ [:div {:class (stl/css :property-block)}
+ [:img {:src "images/community.svg"
+ :border "0"}]
+ [:div {:class (stl/css :text-wrapper)}
+ [:div {:class (stl/css :property-title)}
+ [:a {:href "https://community.penpot.app/"
+ :target "_blank"
+ :on-click #(send-event "onboarding-community-link")}
+ (tr "onboarding-v2.welcome.desc2.title")]]
+ [:div {:class (stl/css :property-description)}
+ (tr "onboarding-v2.welcome.desc2")]]]
- [:div {:class (stl/css :property-block)}
- [:img {:src "images/contributing.svg"
- :border "0"}]
- [:div {:class (stl/css :text-wrapper)}
- [:div {:class (stl/css :property-title)}
- [:a {:href "https://help.penpot.app/contributing-guide/"
- :target "_blank" :on-click #(send-event "onboarding-contributing-link")}
- (tr "onboarding-v2.welcome.desc3.title")]]
- [:div {:class (stl/css :property-description)}
- (tr "onboarding-v2.welcome.desc3")]]]]]
+ [:div {:class (stl/css :property-block)}
+ [:img {:src "images/contributing.svg"
+ :border "0"}]
+ [:div {:class (stl/css :text-wrapper)}
+ [:div {:class (stl/css :property-title)}
+ [:a {:href "https://help.penpot.app/contributing-guide/"
+ :target "_blank" :on-click #(send-event "onboarding-contributing-link")}
+ (tr "onboarding-v2.welcome.desc3.title")]]
+ [:div {:class (stl/css :property-description)}
+ (tr "onboarding-v2.welcome.desc3")]]]]]
- [:div {:class (stl/css :modal-footer)}
- [:button {:on-click go-next
- :data-test "onboarding-next-btn"}
- (tr "labels.continue")]]]]
-
-
- [:div.modal-container.onboarding.onboarding-v2
- [:div.modal-left.welcome
- [:img {:src "images/onboarding-welcome.png" :border "0" :alt (tr "onboarding.welcome.alt")}]]
- [:div.modal-right
- [:div.release-container [:span.release "Version " (:main cf/version)]]
- [:div.right-content
- [:div.modal-title
- [:h2 {:data-test "onboarding-welcome"} (tr "onboarding-v2.welcome.title")]]
-
- [:div.modal-content
- [:p (tr "onboarding-v2.welcome.desc1")]
- [:div.welcome-card
- [:img {:src "images/community.svg" :border "0"}]
- [:div
- [:div.title [:a {:href "https://community.penpot.app/" :target "_blank" :on-click #(send-event "onboarding-community-link")} (tr "onboarding-v2.welcome.desc2.title")]]
- [:div.description (tr "onboarding-v2.welcome.desc2")]]]
-
- [:div.welcome-card
- [:img {:src "images/contributing.svg" :border "0"}]
- [:div
- [:div.title [:a {:href "https://help.penpot.app/contributing-guide/" :target "_blank" :on-click #(send-event "onboarding-contributing-link")} (tr "onboarding-v2.welcome.desc3.title")]]
- [:div.description (tr "onboarding-v2.welcome.desc3")]]]]]
- [:div.modal-navigation
- [:button.btn-secondary {:on-click go-next :data-test "onboarding-next-btn"} (tr "labels.continue")]]
- [:img.deco.square {:src "images/deco-square.svg" :border "0"}]
- [:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
- [:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
- [:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:button {:on-click go-next
+ :data-test "onboarding-next-btn"}
+ (tr "labels.continue")]]]]))
(mf/defc onboarding-before-start
[{:keys [next] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- go-next
+ (let [go-next
(fn []
(send-event "onboarding-step2-continue")
(next))]
- (if new-css-system
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-left)}
- [:img {:src "images/onboarding-people.png"
- :border "0"
- :alt (tr "onboarding.welcome.alt")}]]
- [:div {:class (stl/css :modal-right)}
- [:div {:class (stl/css :release)}
- "Version " (:main cf/version)]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)
- :data-test "onboarding-welcome"}
- (tr "onboarding-v2.before-start.title")]]
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-left)}
+ [:img {:src "images/onboarding-people.png"
+ :border "0"
+ :alt (tr "onboarding.welcome.alt")}]]
+ [:div {:class (stl/css :modal-right)}
+ [:div {:class (stl/css :release)}
+ "Version " (:main cf/version)]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)
+ :data-test "onboarding-welcome"}
+ (tr "onboarding-v2.before-start.title")]]
- [:div {:class (stl/css :modal-info)}
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding-v2.before-start.desc1")]
- [:div {:class (stl/css :property-block)}
- [:img {:src "images/user-guide.svg" :border "0"}]
- [:div {:class (stl/css :text-wrapper)}
- [:div {:class (stl/css :property-title)}
- [:a {:class (stl/css :modal-link)
- :href "https://help.penpot.app/user-guide/"
- :target "_blank"
- :on-click #(send-event "onboarding-user-guide-link")}
- (tr "onboarding-v2.before-start.desc2.title")]]
- [:div {:class (stl/css :property-description)}
- (tr "onboarding-v2.before-start.desc2")]]]
+ [:div {:class (stl/css :modal-info)}
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding-v2.before-start.desc1")]
+ [:div {:class (stl/css :property-block)}
+ [:img {:src "images/user-guide.svg" :border "0"}]
+ [:div {:class (stl/css :text-wrapper)}
+ [:div {:class (stl/css :property-title)}
+ [:a {:class (stl/css :modal-link)
+ :href "https://help.penpot.app/user-guide/"
+ :target "_blank"
+ :on-click #(send-event "onboarding-user-guide-link")}
+ (tr "onboarding-v2.before-start.desc2.title")]]
+ [:div {:class (stl/css :property-description)}
+ (tr "onboarding-v2.before-start.desc2")]]]
- [:div {:class (stl/css :property-block)}
- [:img {:src "images/video-tutorials.svg" :border "0"}]
- [:div {:class (stl/css :text-wrapper)}
- [:div {:class (stl/css :property-title)}
- [:a {:class (stl/css :modal-link)
- :href "https://www.youtube.com/c/Penpot"
- :target "_blank"
- :on-click #(send-event "onboarding-video-tutorials-link")}
- (tr "onboarding-v2.before-start.desc3.title")]]
- [:div {:class (stl/css :property-description)}
- (tr "onboarding-v2.before-start.desc3")]]]]]
+ [:div {:class (stl/css :property-block)}
+ [:img {:src "images/video-tutorials.svg" :border "0"}]
+ [:div {:class (stl/css :text-wrapper)}
+ [:div {:class (stl/css :property-title)}
+ [:a {:class (stl/css :modal-link)
+ :href "https://www.youtube.com/c/Penpot"
+ :target "_blank"
+ :on-click #(send-event "onboarding-video-tutorials-link")}
+ (tr "onboarding-v2.before-start.desc3.title")]]
+ [:div {:class (stl/css :property-description)}
+ (tr "onboarding-v2.before-start.desc3")]]]]]
- [:div {:class (stl/css :modal-footer)}
- [:button {:on-click go-next
- :data-test "onboarding-next-btn"}
- (tr "labels.continue")]]]]
-
-
- [:div.modal-container.onboarding.onboarding-v2
- [:div.modal-left.welcome
- [:img {:src "images/onboarding-people.png" :border "0" :alt (tr "onboarding.welcome.alt")}]]
- [:div.modal-right
- [:div.release-container [:span.release "Version " (:main cf/version)]]
- [:div.right-content
- [:div.modal-title
- [:h2 {:data-test "onboarding-welcome"} (tr "onboarding-v2.before-start.title")]]
-
- [:div.modal-content
- [:p (tr "onboarding-v2.before-start.desc1")]
- [:div.welcome-card
- [:img {:src "images/user-guide.svg" :border "0"}]
- [:div
- [:div.title [:a {:href "https://help.penpot.app/user-guide/" :target "_blank" :on-click #(send-event "onboarding-user-guide-link")} (tr "onboarding-v2.before-start.desc2.title")]]
- [:div.description (tr "onboarding-v2.before-start.desc2")]]]
-
- [:div.welcome-card
- [:img {:src "images/video-tutorials.svg" :border "0"}]
- [:div
- [:div.title [:a {:href "https://www.youtube.com/c/Penpot" :target "_blank" :on-click #(send-event "onboarding-video-tutorials-link")} (tr "onboarding-v2.before-start.desc3.title")]]
- [:div.description (tr "onboarding-v2.before-start.desc3")]]]]]
- [:div.modal-navigation
- [:button.btn-secondary {:on-click go-next :data-test "onboarding-next-btn"} (tr "labels.continue")]]
- [:img.deco.square {:src "images/deco-square.svg" :border "0"}]
- [:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
- [:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
- [:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:button {:on-click go-next
+ :data-test "onboarding-next-btn"}
+ (tr "labels.continue")]]]]))
(mf/defc onboarding-modal
{::mf/register modal/components
::mf/register-as :onboarding}
[_]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- slide (mf/use-state :start)
+ (let [slide (mf/use-state :start)
klass (mf/use-state "fadeInDown")
navigate
@@ -230,15 +164,8 @@
(reset! klass nil)
(tm/dispose! sem))))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div.animated {:class(dm/str @klass " " (stl/css :animated))}
- (case @slide
- :start [:& onboarding-welcome {:next #(navigate :opensource)}]
- :opensource [:& onboarding-before-start {:next skip}])]]
-
- [:div.modal-overlay
- [:div.animated {:class @klass}
- (case @slide
- :start [:& onboarding-welcome {:next #(navigate :opensource)}]
- :opensource [:& onboarding-before-start {:next skip}])]])))
+ [:div {:class (stl/css :modal-overlay)}
+ [:div.animated {:class (dm/str @klass " " (stl/css :animated))}
+ (case @slide
+ :start [:& onboarding-welcome {:next #(navigate :opensource)}]
+ :opensource [:& onboarding-before-start {:next skip}])]]))
diff --git a/frontend/src/app/main/ui/onboarding/newsletter.cljs b/frontend/src/app/main/ui/onboarding/newsletter.cljs
index c147a7d5ec..e252452857 100644
--- a/frontend/src/app/main/ui/onboarding/newsletter.cljs
+++ b/frontend/src/app/main/ui/onboarding/newsletter.cljs
@@ -11,7 +11,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -20,8 +19,7 @@
{::mf/register modal/components
::mf/register-as :onboarding-newsletter-modal}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- message (tr "onboarding.newsletter.acceptance-message")
+ (let [message (tr "onboarding.newsletter.acceptance-message")
newsletter-updates (mf/use-state false)
newsletter-news (mf/use-state false)
toggle
@@ -39,78 +37,49 @@
(modal/show {:type :onboarding-team})
(du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div.animated.fadeInDown {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)
- :data-test "onboarding-newsletter-title"}
- (tr "onboarding.newsletter.title")]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding-v2.newsletter.desc")]]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :newsletter-options)}
- [:div {:class (stl/css :input-wrapper)}
- [:label {:for "newsletter-updates"}
- [:span {:class (stl/css-case :global/checked @newsletter-updates)}
- (when @newsletter-updates
- i/status-tick-refactor)]
- (tr "onboarding-v2.newsletter.updates")
- [:input {:type "checkbox"
- :id "newsletter-updates"
- :on-change #(toggle newsletter-updates)}]]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div.animated.fadeInDown {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)
+ :data-test "onboarding-newsletter-title"}
+ (tr "onboarding.newsletter.title")]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding-v2.newsletter.desc")]]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :newsletter-options)}
+ [:div {:class (stl/css :input-wrapper)}
+ [:label {:for "newsletter-updates"}
+ [:span {:class (stl/css-case :global/checked @newsletter-updates)}
+ (when @newsletter-updates
+ i/status-tick-refactor)]
+ (tr "onboarding-v2.newsletter.updates")
+ [:input {:type "checkbox"
+ :id "newsletter-updates"
+ :on-change #(toggle newsletter-updates)}]]]
- [:div {:class (stl/css :input-wrapper)}
- [:label {:for "newsletter-news"}
- [:span {:class (stl/css-case :global/checked @newsletter-news)}
- (when @newsletter-news
- i/status-tick-refactor)]
- (tr "onboarding-v2.newsletter.news")
- [:input {:type "checkbox"
- :id "newsletter-news"
- :on-change #(toggle newsletter-news)}]]]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:label {:for "newsletter-news"}
+ [:span {:class (stl/css-case :global/checked @newsletter-news)}
+ (when @newsletter-news
+ i/status-tick-refactor)]
+ (tr "onboarding-v2.newsletter.news")
+ [:input {:type "checkbox"
+ :id "newsletter-news"
+ :on-change #(toggle newsletter-news)}]]]]
- [:div {:class (stl/css :modal-info)}
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding-v2.newsletter.privacy1")
- [:a {:class (stl/css :modal-link)
- :target "_blank"
- :href "https://penpot.app/privacy"}
- (tr "onboarding.newsletter.policy")]]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding-v2.newsletter.privacy2")]]]
+ [:div {:class (stl/css :modal-info)}
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding-v2.newsletter.privacy1")
+ [:a {:class (stl/css :modal-link)
+ :target "_blank"
+ :href "https://penpot.app/privacy"}
+ (tr "onboarding.newsletter.policy")]]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding-v2.newsletter.privacy2")]]]
- [:div {:class (stl/css :modal-footer)}
- [:button {:on-click accept} (tr "labels.continue")]]
+ [:div {:class (stl/css :modal-footer)}
+ [:button {:on-click accept} (tr "labels.continue")]]
- [:img {:class (stl/css-case :deco true
- :top true)
- :src "images/deco-newsletter.png" :border "0"}]]]
-
-
-
- [:div.modal-overlay
- [:div.modal-container.onboarding.newsletter.animated.fadeInDown
- [:div.modal-top
- [:h1.newsletter-title {:data-test "onboarding-newsletter-title"} (tr "onboarding.newsletter.title")]
- [:p (tr "onboarding-v2.newsletter.desc")]]
- [:div.modal-bottom
- [:div.newsletter-options
- [:div.input-checkbox.check-primary
- [:input {:type "checkbox"
- :id "newsletter-updates"
- :on-change #(toggle newsletter-updates)}]
- [:label {:for "newsletter-updates"} (tr "onboarding-v2.newsletter.updates")]]
- [:div.input-checkbox.check-primary
- [:input {:type "checkbox"
- :id "newsletter-news"
- :on-change #(toggle newsletter-news)}]
- [:label {:for "newsletter-news"} (tr "onboarding-v2.newsletter.news")]]]
- [:p (tr "onboarding-v2.newsletter.privacy1") [:a {:target "_blank" :href "https://penpot.app/privacy"} (tr "onboarding.newsletter.policy")]]
- [:p (tr "onboarding-v2.newsletter.privacy2")]]
- [:div.modal-footer
- [:button.btn-primary {:on-click accept} (tr "labels.continue")]]
- [:img.deco.top {:src "images/deco-newsletter.png" :border "0"}]
- [:img.deco.newsletter-left {:src "images/deco-news-left.png" :border "0"}]
- [:img.deco.newsletter-right {:src "images/deco-news-right.png" :border "0"}]]])
- ))
+ [:img {:class (stl/css-case :deco true
+ :top true)
+ :src "images/deco-newsletter.png" :border "0"}]]]))
diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs
index 1f5d4b9f46..4f9a612158 100644
--- a/frontend/src/app/main/ui/onboarding/questions.cljs
+++ b/frontend/src/app/main/ui/onboarding/questions.cljs
@@ -13,7 +13,6 @@
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s]
[cuerdas.core :as str]
@@ -22,139 +21,75 @@
(mf/defc step-container
[{:keys [form step on-next on-prev children] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
+ [:& fm/form {:form form :on-submit on-next}
+ [:div {:class (stl/css :paginator)} (str/ffmt "%/4" step)]
- (if new-css-system
- [:& fm/form {:form form :on-submit on-next}
- [:div {:class (stl/css :paginator)} (str/ffmt "%/4" step)]
+ children
- children
+ [:div {:class (stl/css :action-buttons)}
- [:div {:class (stl/css :action-buttons)}
+ (when on-prev
+ [:button {:class (stl/css :prev-button)
+ :on-click on-prev} (tr "questions.previous")])
- (when on-prev
- [:button {:class (stl/css :prev-button)
- :on-click on-prev} (tr "questions.previous")])
-
- [:> fm/submit-button*
- {:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
- :class (stl/css :next-button)}]]]
-
-
-
- [:& fm/form {:form form :on-submit on-next}
- [:div.step-header
- [:div.step-number (str/ffmt "%/4" step)]]
-
- children
-
- [:div.buttons
- [:div.step-next
- [:> fm/submit-button*
- {:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
- :class "step-next"}]]
-
- (when on-prev
- [:div.step-prev
- [:button {:on-click on-prev} (tr "questions.previous")]])]])))
+ [:> fm/submit-button*
+ {:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
+ :class (stl/css :next-button)}]]])
(s/def ::questions-form-step-1
(s/keys :req-un [::planning]))
(mf/defc step-1
[{:keys [on-next form] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& step-container {:form form :step 1 :on-next on-next}
- [:img {:class (stl/css :header-image)
- :src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
- [:h1 {:class (stl/css :modal-title)} (tr "questions.lets-get-started")]
- [:p {:class (stl/css :modal-text)} (tr "questions.your-feedback-will-help-us")]
- [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.questions-how-are-you-planning-to-use-penpot")]
- [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true}
- {:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"}
- {:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"}
- {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"}
- {:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"}
- {:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"}
- {:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"}
- {:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}]
- :default ""
- :name :planning}]]
-
-
- [:& step-container {:form form :step 1 :on-next on-next}
- [:img.header-image {:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
- [:h1 (tr "questions.lets-get-started")]
- [:p.intro (tr "questions.your-feedback-will-help-us")]
- [:h3 (tr "questions.questions-how-are-you-planning-to-use-penpot")]
- [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true}
- {:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"}
- {:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"}
- {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"}
- {:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"}
- {:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"}
- {:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"}
- {:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}]
- :default ""
- :name :planning}]])))
+ [:& step-container {:form form :step 1 :on-next on-next}
+ [:img {:class (stl/css :header-image)
+ :src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
+ [:h1 {:class (stl/css :modal-title)} (tr "questions.lets-get-started")]
+ [:p {:class (stl/css :modal-text)} (tr "questions.your-feedback-will-help-us")]
+ [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.questions-how-are-you-planning-to-use-penpot")]
+ [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true}
+ {:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"}
+ {:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"}
+ {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"}
+ {:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"}
+ {:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"}
+ {:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"}
+ {:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}]
+ :default ""
+ :name :planning}]])
(s/def ::questions-form-step-2
(s/keys :req-un [::experience-branding-illustrations-marketing-pieces ::experience-interface-design-visual-assets-design-systems ::experience-interface-wireframes-user-journeys-flows-navigation-trees]))
(mf/defc step-2
[{:keys [on-next on-prev form] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev}
- [:h3 {:class (stl/css :modal-subtitle)}
- (tr "questions.describe-your-experience-working-on")]
+ [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev}
+ [:h3 {:class (stl/css :modal-subtitle)}
+ (tr "questions.describe-your-experience-working-on")]
- [:div {:class (stl/css :modal-question)}
- [:div {:class (stl/css :modal-text)}
- (tr "branding-illustrations-marketing-pieces")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
- {:label (tr "questions.some") :value "some"}
- {:label (tr "questions.a-lot") :value "a-lot"}]
- :name :experience-branding-illustrations-marketing-pieces}]]
+ [:div {:class (stl/css :modal-question)}
+ [:div {:class (stl/css :modal-text)}
+ (tr "branding-illustrations-marketing-pieces")]
+ [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
+ {:label (tr "questions.some") :value "some"}
+ {:label (tr "questions.a-lot") :value "a-lot"}]
+ :name :experience-branding-illustrations-marketing-pieces}]]
- [:div {:class (stl/css :modal-question)}
- [:div {:class (stl/css :modal-text)}
- (tr "questions.interface-design-visual-assets-design-systems")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
- {:label (tr "questions.some") :value "some"}
- {:label (tr "questions.a-lot") :value "a-lot"}]
- :name :experience-interface-design-visual-assets-design-systems}]]
+ [:div {:class (stl/css :modal-question)}
+ [:div {:class (stl/css :modal-text)}
+ (tr "questions.interface-design-visual-assets-design-systems")]
+ [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
+ {:label (tr "questions.some") :value "some"}
+ {:label (tr "questions.a-lot") :value "a-lot"}]
+ :name :experience-interface-design-visual-assets-design-systems}]]
- [:div {:class (stl/css :modal-question)}
- [:div {:class (stl/css :modal-text)}
- (tr "questions.wireframes-user-journeys-flows-navigation-trees")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
- {:label (tr "questions.some") :value "some"}
- {:label (tr "questions.a-lot") :value "a-lot"}]
- :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]]]
-
-
- [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev}
- [:h3 (tr "questions.describe-your-experience-working-on")]
-
- [:div.section (tr "branding-illustrations-marketing-pieces")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
- {:label (tr "questions.some") :value "some"}
- {:label (tr "questions.a-lot") :value "a-lot"}]
- :name :experience-branding-illustrations-marketing-pieces}]
-
- [:div.section (tr "questions.interface-design-visual-assets-design-systems")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
- {:label (tr "questions.some") :value "some"}
- {:label (tr "questions.a-lot") :value "a-lot"}]
- :name :experience-interface-design-visual-assets-design-systems}]
-
- [:div.section (tr "questions.wireframes-user-journeys-flows-navigation-trees")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
- {:label (tr "questions.some") :value "some"}
- {:label (tr "questions.a-lot") :value "a-lot"}]
- :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]])))
+ [:div {:class (stl/css :modal-question)}
+ [:div {:class (stl/css :modal-text)}
+ (tr "questions.wireframes-user-journeys-flows-navigation-trees")]
+ [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
+ {:label (tr "questions.some") :value "some"}
+ {:label (tr "questions.a-lot") :value "a-lot"}]
+ :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]]])
(s/def ::questions-form-step-3
(s/keys :req-un [::experience-design-tool]
@@ -170,8 +105,7 @@
(mf/defc step-3
[{:keys [on-next on-prev form] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])
+ (let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])
on-design-tool-change
(fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
@@ -180,40 +114,23 @@
(swap! form d/dissoc-in [:data :experience-design-tool-other])
(swap! form d/dissoc-in [:errors :experience-design-tool-other])))))]
- (if new-css-system
- [:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev}
- [:h3 {:class (stl/css :modal-subtitle)}
- (tr "question.design-tool-more-experienced-with")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"}
- {:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png"}
- {:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png"}
- {:label (tr "questions.canva") :value "canva" :image "images/form/canva.png"}
- {:label (tr "questions.invision") :value "invision" :image "images/form/invision.png"}
- {:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"}
- {:label (tr "questions.other") :value "other"}]
- :name :experience-design-tool
- :on-change on-design-tool-change}]
+ [:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev}
+ [:h3 {:class (stl/css :modal-subtitle)}
+ (tr "question.design-tool-more-experienced-with")]
+ [:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"}
+ {:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png"}
+ {:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png"}
+ {:label (tr "questions.canva") :value "canva" :image "images/form/canva.png"}
+ {:label (tr "questions.invision") :value "invision" :image "images/form/invision.png"}
+ {:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"}
+ {:label (tr "questions.other") :value "other"}]
+ :name :experience-design-tool
+ :on-change on-design-tool-change}]
- [:& fm/input {:name :experience-design-tool-other
- :placeholder (tr "questions.other")
- :label ""
- :disabled (not= experience-design-tool "other")}]]
-
-
- [:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev}
- [:h3 (tr "question.design-tool-more-experienced-with")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"}
- {:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png"}
- {:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png"}
- {:label (tr "questions.canva") :value "canva" :image "images/form/canva.png"}
- {:label (tr "questions.invision") :value "invision" :image "images/form/invision.png"}
- {:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"}
- {:label (tr "questions.other") :value "other"}]
- :name :experience-design-tool
- :on-change on-design-tool-change}]
- [:div.other
- [:label (tr "questions.other")]
- [:& fm/input {:name :experience-design-tool-other :label (tr "questions.other") :disabled (not= experience-design-tool "other")}]]])))
+ [:& fm/input {:name :experience-design-tool-other
+ :placeholder (tr "questions.other")
+ :label ""
+ :disabled (not= experience-design-tool "other")}]]))
(s/def ::questions-form-step-4
(s/keys :req-un [::team-size ::role]
@@ -229,8 +146,7 @@
(mf/defc step-4
[{:keys [on-next on-prev form] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- role (dm/get-in @form [:data :role])
+ (let [role (dm/get-in @form [:data :role])
on-role-change
(fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
@@ -239,63 +155,34 @@
(swap! form d/dissoc-in [:data :role-other])
(swap! form d/dissoc-in [:errors :role-other])))))]
- (if new-css-system
- [:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev}
- [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.role")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
- {:label (tr "questions.developer") :value "developer"}
- {:label (tr "questions.manager") :value "manager"}
- {:label (tr "questions.founder") :value "founder"}
- {:label (tr "questions.marketing") :value "marketing"}
- {:label (tr "questions.student-teacher") :value "student-teacher"}
- {:label (tr "questions.other") :value "other"}]
- :name :role
- :on-change on-role-change}]
- [:& fm/input {:name :role-other :label "" :placeholder (tr "questions.other") :disabled (not= role "other")}]
+ [:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev}
+ [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.role")]
+ [:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
+ {:label (tr "questions.developer") :value "developer"}
+ {:label (tr "questions.manager") :value "manager"}
+ {:label (tr "questions.founder") :value "founder"}
+ {:label (tr "questions.marketing") :value "marketing"}
+ {:label (tr "questions.student-teacher") :value "student-teacher"}
+ {:label (tr "questions.other") :value "other"}]
+ :name :role
+ :on-change on-role-change}]
+ [:& fm/input {:name :role-other :label "" :placeholder (tr "questions.other") :disabled (not= role "other")}]
- [:div {:class (stl/css :modal-question)}
- [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.team-size")]
- [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
- {:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"}
- {:label (tr "questions.31-50") :value "31-50" :key "31-50"}
- {:label (tr "questions.11-30") :value "11-30" :key "11-30"}
- {:label (tr "questions.2-10") :value "2-10" :key "2-10"}
- {:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
- {:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
- :default ""
- :name :team-size}]]]
-
-
- [:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev}
- [:h3 (tr "questions.role")]
- [:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
- {:label (tr "questions.developer") :value "developer"}
- {:label (tr "questions.manager") :value "manager"}
- {:label (tr "questions.founder") :value "founder"}
- {:label (tr "questions.marketing") :value "marketing"}
- {:label (tr "questions.student-teacher") :value "student-teacher"}
- {:label (tr "questions.other") :value "other"}]
- :name :role
- :on-change on-role-change}]
- [:div.other
- [:label (tr "questions.other")]
- [:& fm/input {:name :role-other :label (tr "questions.other") :disabled (not= role "other")}]]
-
- [:h3 (tr "questions.team-size")]
- [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
- {:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"}
- {:label (tr "questions.31-50") :value "31-50" :key "31-50"}
- {:label (tr "questions.11-30") :value "11-30" :key "11-30"}
- {:label (tr "questions.2-10") :value "2-10" :key "2-10"}
- {:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
- {:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
- :default ""
- :name :team-size}]])))
+ [:div {:class (stl/css :modal-question)}
+ [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.team-size")]
+ [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
+ {:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"}
+ {:label (tr "questions.31-50") :value "31-50" :key "31-50"}
+ {:label (tr "questions.11-30") :value "11-30" :key "11-30"}
+ {:label (tr "questions.2-10") :value "2-10" :key "2-10"}
+ {:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
+ {:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
+ :default ""
+ :name :team-size}]]]))
(mf/defc questions
[{:keys []}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- container (mf/use-ref)
+ (let [container (mf/use-ref)
step (mf/use-state 1)
clean-data (mf/use-state {})
@@ -336,25 +223,11 @@
(reset! clean-data questionnaire)
(st/emit! (du/mark-questions-as-answered questionnaire)))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)
- :ref container}
- (case @step
- 1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}]
- 2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}]
- 3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}]
- 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]
-
-
- [:div.modal-wrapper.questions-form
- [:div.modal-overlay
- [:div.modal-container.onboarding.onboarding-v2 {:ref container}
- [:img.deco.left {:src "images/deco-left.png" :border 0}]
- [:img.deco.right {:src "images/deco-right.png" :border 0}]
- [:div.signup-questions
- (case @step
- 1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}]
- 2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}]
- 3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}]
- 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]]])))
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)
+ :ref container}
+ (case @step
+ 1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}]
+ 2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}]
+ 3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}]
+ 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]))
diff --git a/frontend/src/app/main/ui/onboarding/team_choice.cljs b/frontend/src/app/main/ui/onboarding/team_choice.cljs
index bb2d5c977c..f850128ac6 100644
--- a/frontend/src/app/main/ui/onboarding/team_choice.cljs
+++ b/frontend/src/app/main/ui/onboarding/team_choice.cljs
@@ -15,7 +15,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
@@ -30,64 +29,38 @@
(mf/defc team-modal-right
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
-
- [:div {:class (stl/css :modal-right)}
- [:h2 {:class (stl/css :modal-subtitle)}
- (tr "onboarding.team-modal.create-team")]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.team-modal.create-team-desc")]
- [:ul {:class (stl/css :team-features)}
- [:li {:class (stl/css :feature)}
- [:span {:class (stl/css :icon)} i/document-refactor]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.team-modal.create-team-feature-1")]]
- [:li {:class (stl/css :feature)}
- [:span {:class (stl/css :icon)} i/move-refactor]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.team-modal.create-team-feature-2")]]
- [:li {:class (stl/css :feature)}
- [:span {:class (stl/css :icon)} i/tree-refactor]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.team-modal.create-team-feature-3")]]
- [:li {:class (stl/css :feature)}
- [:span {:class (stl/css :icon)} i/user-refactor]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.team-modal.create-team-feature-4")]]
- [:li {:class (stl/css :feature)}
- [:span {:class (stl/css :icon)} i/tick-refactor]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.team-modal.create-team-feature-5")]]]]
-
-
-
- [:div.team-right
- [:h2.subtitle (tr "onboarding.team-modal.create-team")]
- [:p.info (tr "onboarding.team-modal.create-team-desc")]
- [:ul.team-features
- [:li.feature
- [:span.icon i/file-html]
- [:p.feature-txt (tr "onboarding.team-modal.create-team-feature-1")]]
- [:li.feature
- [:span.icon i/pointer-inner]
- [:p.feature-txt (tr "onboarding.team-modal.create-team-feature-2")]]
- [:li.feature
- [:span.icon i/tree]
- [:p.feature-txt (tr "onboarding.team-modal.create-team-feature-3")]]
- [:li.feature
- [:span.icon i/user]
- [:p.feature-txt (tr "onboarding.team-modal.create-team-feature-4")]]
- [:li.feature
- [:span.icon i/tick]
- [:p.feature-txt (tr "onboarding.team-modal.create-team-feature-5")]]]])))
+ [:div {:class (stl/css :modal-right)}
+ [:h2 {:class (stl/css :modal-subtitle)}
+ (tr "onboarding.team-modal.create-team")]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.team-modal.create-team-desc")]
+ [:ul {:class (stl/css :team-features)}
+ [:li {:class (stl/css :feature)}
+ [:span {:class (stl/css :icon)} i/document-refactor]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.team-modal.create-team-feature-1")]]
+ [:li {:class (stl/css :feature)}
+ [:span {:class (stl/css :icon)} i/move-refactor]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.team-modal.create-team-feature-2")]]
+ [:li {:class (stl/css :feature)}
+ [:span {:class (stl/css :icon)} i/tree-refactor]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.team-modal.create-team-feature-3")]]
+ [:li {:class (stl/css :feature)}
+ [:span {:class (stl/css :icon)} i/user-refactor]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.team-modal.create-team-feature-4")]]
+ [:li {:class (stl/css :feature)}
+ [:span {:class (stl/css :icon)} i/tick-refactor]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.team-modal.create-team-feature-5")]]]])
(mf/defc onboarding-team-modal
{::mf/register modal/components
::mf/register-as :onboarding-team}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (fm/use-form :spec ::team-form
+ (let [form (fm/use-form :spec ::team-form
:initial {}
:validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space"))
(fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))])
@@ -109,76 +82,43 @@
teams (mf/deref refs/teams)]
- (if new-css-system
- (if (< (count teams) 2)
- [:div {:class (stl/css :modal-overlay)}
- [:div.animated.fadeIn {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-left)}
- [:div {:class (stl/css :first-block)}
- [:h2 {:class (stl/css :modal-title)}
- (tr "onboarding.team-modal.create-team")]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.choice.team-up.create-team-desc")]
- [:& fm/form {:form form
- :class (stl/css :modal-form)
- :on-submit on-submit}
+ (if (< (count teams) 2)
+ [:div {:class (stl/css :modal-overlay)}
+ [:div.animated.fadeIn {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-left)}
+ [:div {:class (stl/css :first-block)}
+ [:h2 {:class (stl/css :modal-title)}
+ (tr "onboarding.team-modal.create-team")]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.choice.team-up.create-team-desc")]
+ [:& fm/form {:form form
+ :class (stl/css :modal-form)
+ :on-submit on-submit}
- [:& fm/input {:type "text"
- :class (stl/css :team-name-input)
- :name :name
- :placeholder "Team name"
- :label (tr "onboarding.choice.team-up.create-team-placeholder")}]
-
- [:div {:class (stl/css :action-buttons)}
- [:& fm/submit-button*
- {:className (stl/css :accept-button)
- :label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
- [:div {:class (stl/css :second-block)}
- [:h2 {:class (stl/css :modal-title)}
- (tr "onboarding.choice.team-up.start-without-a-team")]
- [:p {:class (stl/css :modal-text)}
- (tr "onboarding.choice.team-up.start-without-a-team-description")]
-
- [:div {:class (stl/css :action-buttons)}
- [:button {:class (stl/css :accept-button)
- :on-click on-skip}
- (tr "onboarding.choice.team-up.continue-without-a-team")]]]]
- [:& team-modal-right]
- [:div {:class (stl/css :paginator)} "1/2"]]]
-
- (st/emit! (modal/hide)))
-
-
- (if (< (count teams) 2)
-
- [:div.modal-overlay
- [:div.modal-container.onboarding-team.animated.fadeIn
- [:div.team-left
- [:h2.title (tr "onboarding.team-modal.create-team")]
- [:p.info (tr "onboarding.choice.team-up.create-team-desc")]
- [:& fm/form {:form form
- :on-submit on-submit}
- [:& fm/input {:type "text"
- :name :name
- :label (tr "onboarding.choice.team-up.create-team-placeholder")}]
+ [:& fm/input {:type "text"
+ :class (stl/css :team-name-input)
+ :name :name
+ :placeholder "Team name"
+ :label (tr "onboarding.choice.team-up.create-team-placeholder")}]
+ [:div {:class (stl/css :action-buttons)}
[:& fm/submit-button*
- {:label (tr "onboarding.choice.team-up.continue-creating-team")}]]
+ {:className (stl/css :accept-button)
+ :label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
+ [:div {:class (stl/css :second-block)}
+ [:h2 {:class (stl/css :modal-title)}
+ (tr "onboarding.choice.team-up.start-without-a-team")]
+ [:p {:class (stl/css :modal-text)}
+ (tr "onboarding.choice.team-up.start-without-a-team-description")]
- [:h2.title (tr "onboarding.choice.team-up.start-without-a-team")]
- [:p.info (tr "onboarding.choice.team-up.start-without-a-team-description")]
+ [:div {:class (stl/css :action-buttons)}
+ [:button {:class (stl/css :accept-button)
+ :on-click on-skip}
+ (tr "onboarding.choice.team-up.continue-without-a-team")]]]]
+ [:& team-modal-right]
+ [:div {:class (stl/css :paginator)} "1/2"]]]
- [:div
- [:button.btn-primary.btn-large {:on-click on-skip} (tr "onboarding.choice.team-up.continue-without-a-team")]]]
- [:& team-modal-right]
- [:div.paginator "1/2"]
-
- [:img.deco.square {:src "images/deco-square.svg" :border "0"}]
- [:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
- [:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
- [:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]]
-
- (st/emit! (modal/hide))))))
+ (st/emit! (modal/hide)))))
(defn get-available-roles
[]
@@ -197,8 +137,7 @@
{::mf/register modal/components
::mf/register-as :onboarding-team-invitations}
[{:keys [name] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo (constantly
+ (let [initial (mf/use-memo (constantly
{:role "editor"
:name name}))
form (fm/use-form :spec ::invite-form
@@ -265,96 +204,48 @@
(on-invite-now form)
(on-invite-later form)))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div.animated.fadeIn {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-left)}
- [:h2 {:class (stl/css :modal-title)} (tr "onboarding.choice.team-up.invite-members")]
- [:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div.animated.fadeIn {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-left)}
+ [:h2 {:class (stl/css :modal-title)} (tr "onboarding.choice.team-up.invite-members")]
+ [:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
- [:div {:class (stl/css :modal-form)}
- [:& fm/form {:form form
- :on-submit on-submit}
- [:div {:class (stl/css :role-select)}
- [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
- [:& fm/select {:name :role :options roles}]]
+ [:div {:class (stl/css :modal-form)}
+ [:& fm/form {:form form
+ :on-submit on-submit}
+ [:div {:class (stl/css :role-select)}
+ [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
+ [:& fm/select {:name :role :options roles}]]
- [:div {:class (stl/css :invitation-row)}
- [:& fm/multi-input {:type "email"
- :name :emails
- :auto-focus? true
- :trim true
- :valid-item-fn us/parse-email
- :caution-item-fn #{}
- :label (tr "modals.invite-member.emails")
- :on-submit on-submit}]]]
+ [:div {:class (stl/css :invitation-row)}
+ [:& fm/multi-input {:type "email"
+ :name :emails
+ :auto-focus? true
+ :trim true
+ :valid-item-fn us/parse-email
+ :caution-item-fn #{}
+ :label (tr "modals.invite-member.emails")
+ :on-submit on-submit}]]]
- [:div {:class (stl/css :action-buttons)}
- [:button {:class (stl/css :back-button)
- :on-click #(st/emit! (modal/show {:type :onboarding-team})
- (ptk/event ::ev/event {::ev/name "invite-members-back"
- ::ev/origin "onboarding"
- :name name
- :step 2}))}
- (tr "labels.back")]
+ [:div {:class (stl/css :action-buttons)}
+ [:button {:class (stl/css :back-button)
+ :on-click #(st/emit! (modal/show {:type :onboarding-team})
+ (ptk/event ::ev/event {::ev/name "invite-members-back"
+ ::ev/origin "onboarding"
+ :name name
+ :step 2}))}
+ (tr "labels.back")]
- [:& fm/submit-button*
- {:className (stl/css :accept-button)
- :label
- (if (> (count emails) 0)
- (tr "onboarding.choice.team-up.create-team-and-invite")
- (tr "onboarding.choice.team-up.create-team-without-invite"))}]]
- [:div {:class (stl/css :modal-hint)}
- (tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
+ [:& fm/submit-button*
+ {:className (stl/css :accept-button)
+ :label
+ (if (> (count emails) 0)
+ (tr "onboarding.choice.team-up.create-team-and-invite")
+ (tr "onboarding.choice.team-up.create-team-without-invite"))}]]
+ [:div {:class (stl/css :modal-hint)}
+ (tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
- [:& team-modal-right]
- [:div {:class (stl/css :paginator)} "2/2"]]]
-
-
-
- [:div.modal-overlay
- [:div.modal-container.onboarding-team-members.animated.fadeIn
- [:div.team-left
- [:h2.title (tr "onboarding.choice.team-up.invite-members")]
- [:p.info (tr "onboarding.choice.team-up.invite-members-info")]
-
- [:& fm/form {:form form
- :on-submit on-submit}
- [:div.invite-row
- [:div.role-wrapper
- [:span.rol (tr "onboarding.choice.team-up.roles")]
- [:& fm/select {:name :role :options roles}]]
-
- [:& fm/multi-input {:type "email"
- :name :emails
- :auto-focus? true
- :trim true
- :valid-item-fn us/parse-email
- :caution-item-fn #{}
- :on-submit on-submit
- :label (tr "modals.invite-member.emails")}]]
-
- [:div.buttons
- [:button.btn-secondary.btn-large
- {:on-click #(st/emit! (modal/show {:type :onboarding-team})
- (ptk/event ::ev/event {::ev/name "invite-members-back"
- ::ev/origin "onboarding"
- :name name
- :step 2}))}
- (tr "labels.back")]
- [:& fm/submit-button*
- {:label
- (if (> (count emails) 0)
- (tr "onboarding.choice.team-up.create-team-and-send-invites")
- (tr "onboarding.choice.team-up.create-team-without-inviting"))}]]
- [:div.skip-action
- (tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
- [:& team-modal-right]
- [:div.paginator "2/2"]
-
- [:img.deco.square {:src "images/deco-square.svg" :border "0"}]
- [:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
- [:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
- [:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
+ [:& team-modal-right]
+ [:div {:class (stl/css :paginator)} "2/2"]]]))
diff --git a/frontend/src/app/main/ui/settings.cljs b/frontend/src/app/main/ui/settings.cljs
index 946f6f1c6c..8b024332d5 100644
--- a/frontend/src/app/main/ui/settings.cljs
+++ b/frontend/src/app/main/ui/settings.cljs
@@ -10,7 +10,6 @@
[app.main.data.dashboard.shortcuts :as sc]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.settings.access-tokens :refer [access-tokens-page]]
[app.main.ui.settings.change-email]
@@ -20,7 +19,6 @@
[app.main.ui.settings.password :refer [password-page]]
[app.main.ui.settings.profile :refer [profile-page]]
[app.main.ui.settings.sidebar :refer [sidebar]]
- [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[rumext.v2 :as mf]))
@@ -28,21 +26,13 @@
(mf/defc header
{::mf/wrap [mf/memo]}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:header {:class (stl/css :dashboard-header)}
- [:div {:class (stl/css :dashboard-title)}
- [:h1 {:data-test "account-title"} (tr "dashboard.your-account-title")]]]
-
- ;; OLD
- [:header.dashboard-header
- [:div.dashboard-title
- [:h1 {:data-test "account-title"} (tr "dashboard.your-account-title")]]])))
+ [:header {:class (stl/css :dashboard-header)}
+ [:div {:class (stl/css :dashboard-title)}
+ [:h1 {:data-test "account-title"} (tr "dashboard.your-account-title")]]])
(mf/defc settings
[{:keys [route] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- section (get-in route [:data :name])
+ (let [section (get-in route [:data :name])
profile (mf/deref refs/profile)
locale (mf/deref i18n/locale)]
@@ -52,53 +42,26 @@
#(when (nil? profile)
(st/emit! (rt/nav :auth-login))))
- (if new-css-system
- [:section {:class (stl/css :dashboard-layout-refactor :dashboard)}
- [:& sidebar {:profile profile
- :locale locale
- :section section}]
+ [:section {:class (stl/css :dashboard-layout-refactor :dashboard)}
+ [:& sidebar {:profile profile
+ :locale locale
+ :section section}]
- [:div {:class (stl/css :dashboard-content)}
- [:& header]
- [:section {:class (stl/css :dashboard-container)}
- (case section
- :settings-profile
- [:& profile-page {:locale locale}]
+ [:div {:class (stl/css :dashboard-content)}
+ [:& header]
+ [:section {:class (stl/css :dashboard-container)}
+ (case section
+ :settings-profile
+ [:& profile-page {:locale locale}]
- :settings-feedback
- [:& feedback-page]
+ :settings-feedback
+ [:& feedback-page]
- :settings-password
- [:& password-page {:locale locale}]
+ :settings-password
+ [:& password-page {:locale locale}]
- :settings-options
- [:& options-page {:locale locale}]
+ :settings-options
+ [:& options-page {:locale locale}]
- :settings-access-tokens
- [:& access-tokens-page])]]]
-
- ;; OLD
- [:section {:class (dom/classnames :dashboard-layout (not new-css-system)
- :dashboard-layout-refactor new-css-system)}
- [:& sidebar {:profile profile
- :locale locale
- :section section}]
-
- [:div.dashboard-content
- [:& header]
- [:section.dashboard-container
- (case section
- :settings-profile
- [:& profile-page {:locale locale}]
-
- :settings-feedback
- [:& feedback-page]
-
- :settings-password
- [:& password-page {:locale locale}]
-
- :settings-options
- [:& options-page {:locale locale}]
-
- :settings-access-tokens
- [:& access-tokens-page])]]])))
+ :settings-access-tokens
+ [:& access-tokens-page])]]]))
diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs
index a044455aed..cb71674f34 100644
--- a/frontend/src/app/main/ui/settings/access_tokens.cljs
+++ b/frontend/src/app/main/ui/settings/access_tokens.cljs
@@ -14,7 +14,6 @@
[app.main.store :as st]
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -51,8 +50,7 @@
{::mf/register modal/components
::mf/register-as :access-token}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- form (fm/use-form
+ (let [form (fm/use-form
:initial initial-data
:spec ::access-token-form
:validators [name-validator
@@ -107,176 +105,96 @@
:content (tr "dashboard.access-tokens.copied-success")
:timeout 1000}))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:& fm/form {:form form :on-submit on-submit}
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:& fm/form {:form form :on-submit on-submit}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} (tr "modals.create-access-token.title")]
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} (tr "modals.create-access-token.title")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-close} i/close-refactor]]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "text"
- :auto-focus? true
- :form form
- :name :name
- :disabled @created?
- :label (tr "modals.create-access-token.name.label")
- :show-success? true
- :placeholder (tr "modals.create-access-token.name.placeholder")}]]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "text"
+ :auto-focus? true
+ :form form
+ :name :name
+ :disabled @created?
+ :label (tr "modals.create-access-token.name.label")
+ :show-success? true
+ :placeholder (tr "modals.create-access-token.name.placeholder")}]]
- [:div {:class (stl/css :fields-row)}
- [:div {:class (stl/css :select-title)} (tr "modals.create-access-token.expiration-date.label")]
- [:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
- {:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
- {:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
- {:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
- {:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
- :default "never"
- :disabled @created?
- :name :expiration-date}]
- (when @created?
- [:span.token-created-info
- (if (:expires-at created)
- (tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
- (tr "dashboard.access-tokens.token-will-not-expire"))])]
+ [:div {:class (stl/css :fields-row)}
+ [:div {:class (stl/css :select-title)} (tr "modals.create-access-token.expiration-date.label")]
+ [:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
+ {:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
+ {:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
+ {:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
+ {:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
+ :default "never"
+ :disabled @created?
+ :name :expiration-date}]
+ (when @created?
+ [:span {:class (stl/css :token-created-info)}
+ (if (:expires-at created)
+ (tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
+ (tr "dashboard.access-tokens.token-will-not-expire"))])]
- [:div {:class (stl/css :fields-row)}
- (when @created?
- [:div {:class (stl/css :custon-input-wrapper)}
- [:input {:type "text"
- :value (:token created "")
- :class (stl/css :custom-input-token)
- :placeholder (tr "modals.create-access-token.token")
- :read-only true}]
- [:button {:title (tr "modals.create-access-token.copy-token")
- :class (stl/css :copy-btn)
- :on-click copy-token}
- i/clipboard-refactor]])
- #_(when @created?
+ [:div {:class (stl/css :fields-row)}
+ (when @created?
+ [:div {:class (stl/css :custon-input-wrapper)}
+ [:input {:type "text"
+ :value (:token created "")
+ :class (stl/css :custom-input-token)
+ :placeholder (tr "modals.create-access-token.token")
+ :read-only true}]
+ [:button {:title (tr "modals.create-access-token.copy-token")
+ :class (stl/css :copy-btn)
+ :on-click copy-token}
+ i/clipboard-refactor]])
+ #_(when @created?
[:button {:class (stl/css :copy-btn)
:title (tr "modals.create-access-token.copy-token")
:on-click copy-token}
- [:span {:class (stl/css :token-value)}(:token created "")]
+ [:span {:class (stl/css :token-value)} (:token created "")]
[:span {:class (stl/css :icon)}
i/clipboard-refactor]])]]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
- (if @created?
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.close")
- :on-click #(modal/hide!)}]
- [:*
- [:input {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.cancel")
- :on-click #(modal/hide!)}]
- [:> fm/submit-button*
- {:label (tr "modals.create-access-token.submit-label")}]])]]]]]
-
-
- [:div.modal-overlay
- [:div.modal-container.access-tokens-modal
- [:& fm/form {:form form :on-submit on-submit}
-
- [:div.modal-header
- [:div.modal-header-title
- [:h2 (tr "modals.create-access-token.title")]]
-
- [:div.modal-close-button
- {:on-click on-close} i/close]]
-
- [:div.modal-content.generic-form
- [:div.fields-container
- [:div.fields-row
- [:& fm/input {:type "text"
- :auto-focus? true
- :form form
- :name :name
- :disabled @created?
- :label (tr "modals.create-access-token.name.label")
- :placeholder (tr "modals.create-access-token.name.placeholder")}]]
-
- [:div.fields-row
- [:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
- {:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
- {:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
- {:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
- {:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
- :label (tr "modals.create-access-token.expiration-date.label")
- :default "never"
- :disabled @created?
- :name :expiration-date}]
- (when @created?
- [:span.token-created-info
- (if (:expires-at created)
- (tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
- (tr "dashboard.access-tokens.token-will-not-expire"))])]
-
- [:div.fields-row.access-token-created
- (when @created?
- [:div.custom-input.with-icon
- [:input {:type "text"
- :value (:token created "")
- :placeholder (tr "modals.create-access-token.token")
- :read-only true}]
- [:button.help-icon {:title (tr "modals.create-access-token.copy-token")
- :on-click copy-token}
- i/copy]])]]]
-
- [:div.modal-footer
- [:div.action-buttons
- (if @created?
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.close")
- :on-click #(modal/hide!)}]
- [:*
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.cancel")
- :on-click #(modal/hide!)}]
- [:> fm/submit-button*
- {:label (tr "modals.create-access-token.submit-label")}]])]]]]])))
+ (if @created?
+ [:input {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.close")
+ :on-click #(modal/hide!)}]
+ [:*
+ [:input {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.cancel")
+ :on-click #(modal/hide!)}]
+ [:> fm/submit-button*
+ {:label (tr "modals.create-access-token.submit-label")}]])]]]]]))
(mf/defc access-tokens-hero
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-click (mf/use-fn #(st/emit! (modal/show :access-token {})))]
- (if new-css-system
- [:div {:class (stl/css :access-tokens-hero-container)}
- [:div {:class (stl/css :access-tokens-hero)}
- [:div {:class (stl/css :desc)}
- [:h2 (tr "dashboard.access-tokens.personal")]
- [:p (tr "dashboard.access-tokens.personal.description")]]
+ (let [on-click (mf/use-fn #(st/emit! (modal/show :access-token {})))]
+ [:div {:class (stl/css :access-tokens-hero-container)}
+ [:div {:class (stl/css :access-tokens-hero)}
+ [:div {:class (stl/css :desc)}
+ [:h2 (tr "dashboard.access-tokens.personal")]
+ [:p (tr "dashboard.access-tokens.personal.description")]]
- [:button
- {:class (stl/css :btn-primary)
- :on-click on-click}
- [:span (tr "dashboard.access-tokens.create")]]]]
-
- ;; OLD
- [:div.access-tokens-hero-container
- [:div.access-tokens-hero
- [:div.desc
- [:h2 (tr "dashboard.access-tokens.personal")]
- [:p (tr "dashboard.access-tokens.personal.description")]]
-
- [:button.btn-primary
- {:on-click on-click}
- [:span (tr "dashboard.access-tokens.create")]]]])))
+ [:button
+ {:class (stl/css :btn-primary)
+ :on-click on-click}
+ [:span (tr "dashboard.access-tokens.create")]]]]))
(mf/defc access-token-actions
[{:keys [on-delete]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- local (mf/use-state {:menu-open false})
+ (let [local (mf/use-state {:menu-open false})
show? (:menu-open @local)
options (mf/with-memo [on-delete]
[{:option-name (tr "labels.delete")
@@ -302,47 +220,25 @@
(dom/stop-propagation event)
(on-menu-click event))))]
- (if new-css-system
- [:div
- {:class (stl/css :icon)
- :tab-index "0"
- :ref menu-ref
- :on-click on-menu-click
- :on-key-down on-keydown}
- i/actions
- [:& context-menu-a11y
- {:on-close on-menu-close
- :show show?
- :fixed? true
- :min-width? true
- :top "auto"
- :left "auto"
- :options options}]]
-
- ;; OLD
- [:div.icon
- {:tab-index "0"
- :ref menu-ref
- :on-click on-menu-click
- :on-key-down (fn [event]
- (when (kbd/enter? event)
- (dom/stop-propagation event)
- (on-menu-click event)))}
- i/actions
- [:& context-menu-a11y
- {:on-close on-menu-close
- :show show?
- :fixed? true
- :min-width? true
- :top "auto"
- :left "auto"
- :options options}]])))
+ [:div {:class (stl/css :icon)
+ :tab-index "0"
+ :ref menu-ref
+ :on-click on-menu-click
+ :on-key-down on-keydown}
+ i/actions
+ [:& context-menu-a11y
+ {:on-close on-menu-close
+ :show show?
+ :fixed? true
+ :min-width? true
+ :top "auto"
+ :left "auto"
+ :options options}]]))
(mf/defc access-token-item
{::mf/wrap [mf/memo]}
[{:keys [token] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- locale (mf/deref i18n/locale)
+ (let [locale (mf/deref i18n/locale)
expires-at (:expires-at token)
expires-txt (some-> expires-at (dt/format-date-locale {:locale locale}))
expired? (and (some? expires-at) (> (dt/now) expires-at))
@@ -366,66 +262,36 @@
:accept-label (tr "modals.delete-acces-token.accept")
:on-accept delete-fn}))))]
- (if new-css-system
- [:div {:class (stl/css :table-row)}
- [:div {:class (stl/css :table-field :name)}
- (str (:name token))]
+ [:div {:class (stl/css :table-row)}
+ [:div {:class (stl/css :table-field :name)}
+ (str (:name token))]
- [:div {:class (stl/css :table-field :expiration-date)}
- [:span {:class (stl/css-case :expired expired? :content true)}
- (cond
- (nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
- expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
- :else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
- [:div {:class (stl/css :table-field :actions)}
- [:& access-token-actions
- {:on-delete on-delete}]]]
-
- ;; OLD
- [:div.table-row
- [:div.table-field.name
- (str (:name token))]
- [:div.table-field.expiration-date
- [:span.content {:class (when expired? "expired")}
- (cond
- (nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
- expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
- :else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
- [:div.table-field.actions
- [:& access-token-actions
- {:on-delete on-delete}]]])))
+ [:div {:class (stl/css :table-field :expiration-date)}
+ [:span {:class (stl/css-case :expired expired? :content true)}
+ (cond
+ (nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
+ expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
+ :else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
+ [:div {:class (stl/css :table-field :actions)}
+ [:& access-token-actions
+ {:on-delete on-delete}]]]))
(mf/defc access-tokens-page
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- tokens (mf/deref tokens-ref)]
+ (let [tokens (mf/deref tokens-ref)]
(mf/with-effect []
(dom/set-html-title (tr "title.settings.access-tokens"))
(st/emit! (du/fetch-access-tokens)))
- (if new-css-system
- [:div {:class (stl/css :dashboard-access-tokens)}
- [:div
- [:& access-tokens-hero]
- (if (empty? tokens)
- [:div {:class (stl/css :access-tokens-empty)}
- [:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
- [:div (tr "dashboard.access-tokens.empty.add-one")]]
- [:div {:class (stl/css :dashboard-table)}
- [:div {:class (stl/css :table-rows)}
- (for [token tokens]
- [:& access-token-item {:token token :key (:id token)}])]])]]
-
- ;; OLD
- [:div.dashboard-access-tokens
- [:div
- [:& access-tokens-hero]
- (if (empty? tokens)
- [:div.access-tokens-empty
- [:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
- [:div (tr "dashboard.access-tokens.empty.add-one")]]
- [:div.dashboard-table
- [:div.table-rows
- (for [token tokens]
- [:& access-token-item {:token token :key (:id token)}])]])]])))
+ [:div {:class (stl/css :dashboard-access-tokens)}
+ [:div
+ [:& access-tokens-hero]
+ (if (empty? tokens)
+ [:div {:class (stl/css :access-tokens-empty)}
+ [:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
+ [:div (tr "dashboard.access-tokens.empty.add-one")]]
+ [:div {:class (stl/css :dashboard-table)}
+ [:div {:class (stl/css :table-rows)}
+ (for [token tokens]
+ [:& access-token-item {:token token :key (:id token)}])]])]]))
diff --git a/frontend/src/app/main/ui/settings/access_tokens.scss b/frontend/src/app/main/ui/settings/access_tokens.scss
index 2e9b8ef178..50bdef0af3 100644
--- a/frontend/src/app/main/ui/settings/access_tokens.scss
+++ b/frontend/src/app/main/ui/settings/access_tokens.scss
@@ -12,88 +12,6 @@
font-size: $fs-16;
margin-top: $s-20;
width: $s-800;
-
- .table-header {
- color: $df-secondary;
- display: grid;
- font-size: $fs-12;
- grid-template-columns: 43% 1fr $s-108 $s-12;
- height: $s-40;
- max-width: $s-1000;
- padding: 0 $s-16;
- text-transform: uppercase;
- width: 100%;
- }
-
- .table-rows {
- color: $db-secondary;
- display: flex;
- flex-direction: column;
- margin-top: $s-16;
- max-width: $s-1000;
- padding-top: 0;
- width: 100%;
- }
-
- .table-row {
- align-items: center;
- background-color: $db-tertiary;
- border-radius: $br-8;
- color: $df-primary;
- display: grid;
- font-size: $fs-14;
- grid-template-columns: 1fr 43% $s-12;
- height: fit-content;
- min-height: $s-40;
- padding: 0 $s-16;
- width: 100%;
-
- &:not(:first-child) {
- margin-top: $s-8;
- }
- }
-
- .table-field {
- display: flex;
- align-items: center;
-
- .icon {
- padding-left: $s-12;
- cursor: pointer;
- }
-
- &.name {
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 2;
- color: $df-primary;
- display: -webkit-box;
- max-width: $s-480;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- &.expiration-date {
- color: $df-secondary;
- font-size: $fs-14;
-
- .content {
- padding: $s-2 $s-6;
- &.expired {
- background-color: var(--warning-color);
- border-radius: $br-4;
- color: $db-secondary;
- }
- }
- }
- &.access-token-created {
- word-break: break-all;
- }
-
- &.actions {
- position: relative;
- }
- }
-
svg {
width: $s-12;
height: $s-12;
@@ -101,6 +19,87 @@
}
}
+.table-header {
+ color: $df-secondary;
+ display: grid;
+ font-size: $fs-12;
+ grid-template-columns: 43% 1fr $s-108 $s-12;
+ height: $s-40;
+ max-width: $s-1000;
+ padding: 0 $s-16;
+ text-transform: uppercase;
+ width: 100%;
+}
+
+.table-rows {
+ color: $db-secondary;
+ display: flex;
+ flex-direction: column;
+ margin-top: $s-16;
+ max-width: $s-1000;
+ padding-top: 0;
+ width: 100%;
+}
+
+.table-row {
+ align-items: center;
+ background-color: $db-tertiary;
+ border-radius: $br-8;
+ color: $df-primary;
+ display: grid;
+ font-size: $fs-14;
+ grid-template-columns: 1fr 43% $s-12;
+ height: fit-content;
+ min-height: $s-40;
+ padding: 0 $s-16;
+ width: 100%;
+
+ &:not(:first-child) {
+ margin-top: $s-8;
+ }
+}
+
+.table-field {
+ display: flex;
+ align-items: center;
+
+ .icon {
+ padding-left: $s-12;
+ cursor: pointer;
+ }
+
+ &.name {
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ color: $df-primary;
+ display: -webkit-box;
+ max-width: $s-480;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &.expiration-date {
+ color: $df-secondary;
+ font-size: $fs-14;
+
+ .content {
+ padding: $s-2 $s-6;
+ &.expired {
+ background-color: var(--warning-color);
+ border-radius: $br-4;
+ color: $db-secondary;
+ }
+ }
+ }
+ &.access-token-created {
+ word-break: break-all;
+ }
+
+ &.actions {
+ position: relative;
+ }
+}
+
.dashboard-access-tokens {
display: flex;
flex-direction: column;
@@ -171,75 +170,85 @@
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- min-width: $s-408;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
+}
- .modal-content {
- @include flexColumn;
- gap: $s-24;
- @include titleTipography;
- margin-bottom: $s-24;
+.modal-container {
+ @extend .modal-container-base;
+ min-width: $s-408;
+ border: $s-1 solid var(--modal-border-color);
+}
- .fields-row {
- @include flexColumn;
- .select-title {
- @include titleTipography;
- color: var(--modal-title-foreground-color);
- }
- .custon-input-wrapper {
- @include flexRow;
- border-radius: $br-8;
- height: $s-32;
- background-color: var(--input-background-color);
- }
- .custom-input-token {
- @extend .input-element;
- margin: 0;
- flex-grow: 1;
- &:focus {
- outline: none;
- border: $s-1 solid var(--input-border-color-active);
- }
- }
- .token-value {
- @include textEllipsis;
- @include titleTipography;
- flex-grow: 1;
- }
- .copy-btn {
- @include flexCenter;
- @extend .button-secondary;
- height: $s-28;
- width: $s-28;
- svg {
- @extend .button-icon-small;
- }
- }
- }
- }
-
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- button {
- @extend .modal-accept-btn;
- }
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- }
- }
+.modal-header {
+ margin-bottom: $s-24;
+ .modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+ }
+ .modal-close-btn {
+ @extend .modal-close-btn-base;
}
}
+
+.modal-content {
+ @include flexColumn;
+ gap: $s-24;
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.fields-row {
+ @include flexColumn;
+}
+
+.select-title {
+ @include titleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.custon-input-wrapper {
+ @include flexRow;
+ border-radius: $br-8;
+ height: $s-32;
+ background-color: var(--input-background-color);
+}
+
+.custom-input-token {
+ @extend .input-element;
+ margin: 0;
+ flex-grow: 1;
+ &:focus {
+ outline: none;
+ border: $s-1 solid var(--input-border-color-active);
+ }
+}
+
+.token-value {
+ @include textEllipsis;
+ @include titleTipography;
+ flex-grow: 1;
+}
+
+.copy-btn {
+ @include flexCenter;
+ @extend .button-secondary;
+ height: $s-28;
+ width: $s-28;
+ svg {
+ @extend .button-icon-small;
+ }
+}
+
+.token-created-info {
+ color: var(--modal-text-foreground-color);
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+ button {
+ @extend .modal-accept-btn;
+ }
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
diff --git a/frontend/src/app/main/ui/settings/change_email.cljs b/frontend/src/app/main/ui/settings/change_email.cljs
index 08ab6ea6f7..37d4f54c7f 100644
--- a/frontend/src/app/main/ui/settings/change_email.cljs
+++ b/frontend/src/app/main/ui/settings/change_email.cljs
@@ -16,7 +16,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr]]
@@ -76,8 +75,7 @@
{::mf/register modal/components
::mf/register-as :change-email}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- profile (mf/deref refs/profile)
+ (let [profile (mf/deref refs/profile)
form (fm/use-form :spec ::email-change-form
:validators [email-equality]
:initial profile)
@@ -99,82 +97,44 @@
(when (and different-emails-error? (= email-1 email-2))
(swap! form d/dissoc-in [:errors :email-2])))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:& fm/form {:form form
- :on-submit on-submit}
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:& fm/form {:form form
+ :on-submit on-submit}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)
- :data-test "change-email-title"}
- (tr "modals.change-email.title")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-close} i/close-refactor]]
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)
+ :data-test "change-email-title"}
+ (tr "modals.change-email.title")]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:& msgs/inline-banner
- {:type :info
- :content (tr "modals.change-email.info" (:email profile))}]
+ [:div {:class (stl/css :modal-content)}
+ [:& msgs/inline-banner
+ {:type :info
+ :content (tr "modals.change-email.info" (:email profile))}]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "email"
- :name :email-1
- :label (tr "modals.change-email.new-email")
- :trim true
- :show-success? true
- :on-change-value on-email-change}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "email"
+ :name :email-1
+ :label (tr "modals.change-email.new-email")
+ :trim true
+ :show-success? true
+ :on-change-value on-email-change}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:type "email"
- :name :email-2
- :label (tr "modals.change-email.confirm-email")
- :trim true
- :show-success? true
- :on-change-value on-email-change}]]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:type "email"
+ :name :email-2
+ :label (tr "modals.change-email.confirm-email")
+ :trim true
+ :show-success? true
+ :on-change-value on-email-change}]]]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)
- :data-test "change-email-submit"}
- [:> fm/submit-button*
- {:label (tr "modals.change-email.submit")}]]]]]]
-
-
- [:div.modal-overlay
- [:div.modal-container.change-email-modal.form-container
- [:& fm/form {:form form
- :on-submit on-submit}
-
- [:div.modal-header
- [:div.modal-header-title
- [:h2 {:data-test "change-email-title"}
- (tr "modals.change-email.title")]]
- [:div.modal-close-button
- {:on-click on-close} i/close]]
-
- [:div.modal-content
- [:& msgs/inline-banner
- {:type :info
- :content (tr "modals.change-email.info" (:email profile))}]
-
- [:div.fields-container
- [:div.fields-row
- [:& fm/input {:type "email"
- :name :email-1
- :label (tr "modals.change-email.new-email")
- :trim true
- :on-change-value on-email-change}]]
- [:div.fields-row
- [:& fm/input {:type "email"
- :name :email-2
- :label (tr "modals.change-email.confirm-email")
- :trim true
- :on-change-value on-email-change}]]]]
-
- [:div.modal-footer
- [:div.action-buttons {:data-test "change-email-submit"}
- [:> fm/submit-button*
- {:label (tr "modals.change-email.submit")}]]]]]])
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)
+ :data-test "change-email-submit"}
+ [:> fm/submit-button*
+ {:label (tr "modals.change-email.submit")}]]]]]]
))
diff --git a/frontend/src/app/main/ui/settings/change_email.scss b/frontend/src/app/main/ui/settings/change_email.scss
index 6b6b760c99..97da12aeca 100644
--- a/frontend/src/app/main/ui/settings/change_email.scss
+++ b/frontend/src/app/main/ui/settings/change_email.scss
@@ -8,46 +8,50 @@
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- min-width: $s-408;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
+}
- .modal-content {
- @include flexColumn;
- @include titleTipography;
- gap: $s-24;
- margin-bottom: $s-24;
+.modal-container {
+ @extend .modal-container-base;
+ min-width: $s-408;
+ border: $s-1 solid var(--modal-border-color);
+}
- .fields-row {
- @include flexColumn;
- .select-title {
- @include titleTipography;
- color: var(--modal-title-foreground-color);
- }
- }
- }
+.modal-header {
+ margin-bottom: $s-24;
+}
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- button {
- @extend .modal-accept-btn;
- }
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- }
- }
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include flexColumn;
+ @include titleTipography;
+ gap: $s-24;
+ margin-bottom: $s-24;
+}
+
+.fields-row {
+ @include flexColumn;
+}
+
+.select-title {
+ @include titleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+ button {
+ @extend .modal-accept-btn;
}
}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
diff --git a/frontend/src/app/main/ui/settings/delete_account.cljs b/frontend/src/app/main/ui/settings/delete_account.cljs
index a9c26b7305..2eddcca231 100644
--- a/frontend/src/app/main/ui/settings/delete_account.cljs
+++ b/frontend/src/app/main/ui/settings/delete_account.cljs
@@ -11,7 +11,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr]]
@@ -29,8 +28,7 @@
{::mf/register modal/components
::mf/register-as :delete-account}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-close
+ (let [on-close
(mf/use-callback #(st/emit! (modal/hide)))
on-accept
@@ -39,52 +37,28 @@
(du/request-account-deletion
(with-meta {} {:on-error on-error}))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
+ [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} (tr "modals.delete-account.title")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-close} i/close-refactor]]
+ [:h2 {:class (stl/css :modal-title)} (tr "modals.delete-account.title")]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:& msgs/inline-banner
- {:type :warning
- :content (tr "modals.delete-account.info")}]]
+ [:div {:class (stl/css :modal-content)}
+ [:& msgs/inline-banner
+ {:type :warning
+ :content (tr "modals.delete-account.info")}]]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:button {:class (stl/css :cancel-button)
- :on-click on-close}
- (tr "modals.delete-account.cancel")]
- [:button {:class (stl/css-case :accept-button true
- :danger true)
- :on-click on-accept
- :data-test "delete-account-btn"}
- (tr "modals.delete-account.confirm")]]]]]
-
-
-
- [:div.modal-overlay
- [:div.modal-container.change-email-modal
- [:div.modal-header
- [:div.modal-header-title
- [:h2 (tr "modals.delete-account.title")]]
- [:div.modal-close-button
- {:on-click on-close} i/close]]
-
- [:div.modal-content
- [:& msgs/inline-banner
- {:type :warning
- :content (tr "modals.delete-account.info")}]]
-
- [:div.modal-footer
- [:div.action-buttons
- [:button.btn-danger.btn-large {:on-click on-accept
- :data-test "delete-account-btn"}
- (tr "modals.delete-account.confirm")]
- [:button.btn-secondary.btn-large {:on-click on-close}
- (tr "modals.delete-account.cancel")]]]]])))
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:button {:class (stl/css :cancel-button)
+ :on-click on-close}
+ (tr "modals.delete-account.cancel")]
+ [:button {:class (stl/css-case :accept-button true
+ :danger true)
+ :on-click on-accept
+ :data-test "delete-account-btn"}
+ (tr "modals.delete-account.confirm")]]]]]))
diff --git a/frontend/src/app/main/ui/settings/delete_account.scss b/frontend/src/app/main/ui/settings/delete_account.scss
index e12ff29a8f..33e72dd4ac 100644
--- a/frontend/src/app/main/ui/settings/delete_account.scss
+++ b/frontend/src/app/main/ui/settings/delete_account.scss
@@ -8,50 +8,54 @@
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- min-width: $s-408;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
+}
- .modal-content {
- @include flexColumn;
- @include titleTipography;
- gap: $s-24;
- margin-bottom: $s-24;
+.modal-container {
+ @extend .modal-container-base;
+ min-width: $s-408;
+ border: $s-1 solid var(--modal-border-color);
+}
- .fields-row {
- @include flexColumn;
- .select-title {
- @include titleTipography;
- color: var(--modal-title-foreground-color);
- }
- }
- }
+.modal-header {
+ margin-bottom: $s-24;
+}
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-button {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include flexColumn;
+ @include titleTipography;
+ gap: $s-24;
+ margin-bottom: $s-24;
+}
+
+.fields-row {
+ @include flexColumn;
+}
+
+.select-title {
+ @include titleTipography;
+ color: var(--modal-title-foreground-color);
+}
+
+.action-buttons {
+ @extend .modal-action-btns;
+}
+
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-button {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
diff --git a/frontend/src/app/main/ui/settings/feedback.cljs b/frontend/src/app/main/ui/settings/feedback.cljs
index 46bbc1e1bf..82daf3c5b4 100644
--- a/frontend/src/app/main/ui/settings/feedback.cljs
+++ b/frontend/src/app/main/ui/settings/feedback.cljs
@@ -14,7 +14,6 @@
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[beicon.v2.core :as rx]
@@ -29,8 +28,7 @@
(mf/defc feedback-form
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- profile (mf/deref refs/profile)
+ (let [profile (mf/deref refs/profile)
form (fm/use-form :spec ::feedback-form
:validators [(fm/validate-length :subject fm/max-length-allowed (tr "auth.name.too-long"))
(fm/validate-not-empty :subject (tr "auth.name.not-all-space"))])
@@ -62,101 +60,54 @@
(->> (rp/cmd! :send-user-feedback data)
(rx/subs! on-succes on-error)))))]
- (if new-css-system
- [:& fm/form {:class (stl/css :feedback-form)
- :on-submit on-submit
- :form form}
+ [:& fm/form {:class (stl/css :feedback-form)
+ :on-submit on-submit
+ :form form}
;; --- Feedback section
- [:h2 {:class (stl/css :field-title)} (tr "feedback.title")]
- [:p {:class (stl/css :field-text)} (tr "feedback.subtitle")]
+ [:h2 {:class (stl/css :field-title)} (tr "feedback.title")]
+ [:p {:class (stl/css :field-text)} (tr "feedback.subtitle")]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input {:label (tr "feedback.subject")
- :name :subject
- :show-success? true}]]
- [:div {:class (stl/css :fields-row :description)}
- [:& fm/textarea
- {:label (tr "feedback.description")
- :name :content
- :rows 5}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input {:label (tr "feedback.subject")
+ :name :subject
+ :show-success? true}]]
+ [:div {:class (stl/css :fields-row :description)}
+ [:& fm/textarea
+ {:label (tr "feedback.description")
+ :name :content
+ :rows 5}]]
- [:> fm/submit-button*
- {:label (if @loading (tr "labels.sending") (tr "labels.send"))
- :disabled @loading}]
+ [:> fm/submit-button*
+ {:label (if @loading (tr "labels.sending") (tr "labels.send"))
+ :disabled @loading}]
- [:hr]
+ [:hr]
- [:h2 {:class (stl/css :field-title)} (tr "feedback.discourse-title")]
- [:p {:class (stl/css :field-text)} (tr "feedback.discourse-subtitle1")]
+ [:h2 {:class (stl/css :field-title)} (tr "feedback.discourse-title")]
+ [:p {:class (stl/css :field-text)} (tr "feedback.discourse-subtitle1")]
- [:a
- {:class (stl/css :btn-secondary :btn-large)
- :href "https://community.penpot.app"
- :target "_blank"}
- (tr "feedback.discourse-go-to")]
- [:hr]
+ [:a
+ {:class (stl/css :btn-secondary :btn-large)
+ :href "https://community.penpot.app"
+ :target "_blank"}
+ (tr "feedback.discourse-go-to")]
+ [:hr]
- [:h2 {:class (stl/css :field-title)} (tr "feedback.twitter-title")]
- [:p {:class (stl/css :field-text)} (tr "feedback.twitter-subtitle1")]
+ [:h2 {:class (stl/css :field-title)} (tr "feedback.twitter-title")]
+ [:p {:class (stl/css :field-text)} (tr "feedback.twitter-subtitle1")]
- [:a
- {:class (stl/css :btn-secondary :btn-large)
- :href "https://twitter.com/penpotapp"
- :target "_blank"}
- (tr "feedback.twitter-go-to")]]
-
- ;; OLD
- [:& fm/form {:class "feedback-form"
- :on-submit on-submit
- :form form}
-
- ;; --- Feedback section
- [:h2.field-title (tr "feedback.title")]
- [:p.field-text (tr "feedback.subtitle")]
-
- [:div.fields-row
- [:& fm/input {:label (tr "feedback.subject")
- :name :subject}]]
- [:div.fields-row
- [:& fm/textarea
- {:label (tr "feedback.description")
- :name :content
- :rows 5}]]
-
- [:> fm/submit-button*
- {:label (if @loading (tr "labels.sending") (tr "labels.send"))
- :disabled @loading}]
-
- [:hr]
-
- [:h2.field-title (tr "feedback.discourse-title")]
- [:p.field-text (tr "feedback.discourse-subtitle1")]
-
- [:a.btn-secondary.btn-large
- {:href "https://community.penpot.app" :target "_blank"}
- (tr "feedback.discourse-go-to")]
- [:hr]
-
- [:h2.field-title (tr "feedback.twitter-title")]
- [:p.field-text (tr "feedback.twitter-subtitle1")]
-
- [:a.btn-secondary.btn-large
- {:href "https://twitter.com/penpotapp" :target "_blank"}
- (tr "feedback.twitter-go-to")]])))
+ [:a
+ {:class (stl/css :btn-secondary :btn-large)
+ :href "https://twitter.com/penpotapp"
+ :target "_blank"}
+ (tr "feedback.twitter-go-to")]]))
(mf/defc feedback-page
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (mf/use-effect
- #(dom/set-html-title (tr "title.settings.feedback")))
+ (mf/use-effect
+ #(dom/set-html-title (tr "title.settings.feedback")))
- (if new-css-system
- [:div {:class (stl/css :dashboard-settings)}
- [:div {:class (stl/css :form-container)}
- [:& feedback-form]]]
-
- ;; OLD
- [:div.dashboard-settings
- [:div.form-container
- [:& feedback-form]]])))
+ [:div {:class (stl/css :dashboard-settings)}
+ [:div {:class (stl/css :form-container)}
+ [:& feedback-form]]])
diff --git a/frontend/src/app/main/ui/settings/options.cljs b/frontend/src/app/main/ui/settings/options.cljs
index 2ec2476590..34b539a84f 100644
--- a/frontend/src/app/main/ui/settings/options.cljs
+++ b/frontend/src/app/main/ui/settings/options.cljs
@@ -13,7 +13,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s]
@@ -38,78 +37,49 @@
(mf/defc options-form
{::mf/wrap-props false}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- profile (mf/deref refs/profile)
+ (let [profile (mf/deref refs/profile)
initial (mf/with-memo [profile]
(update profile :lang #(or % "")))
form (fm/use-form :spec ::options-form
:initial initial)]
- (if new-css-system
- [:& fm/form {:class (stl/css :options-form)
- :on-submit on-submit
- :form form}
+ [:& fm/form {:class (stl/css :options-form)
+ :on-submit on-submit
+ :form form}
- [:h3 (tr "labels.language")]
+ [:h3 (tr "labels.language")]
- [:div {:class (stl/css :fields-row)}
- [:& fm/select {:options (into [{:label "Auto (browser)" :value ""}]
- i18n/supported-locales)
- :label (tr "dashboard.select-ui-language")
- :default ""
- :name :lang
- :data-test "setting-lang"}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/select {:options (into [{:label "Auto (browser)" :value ""}]
+ i18n/supported-locales)
+ :label (tr "dashboard.select-ui-language")
+ :default ""
+ :name :lang
+ :data-test "setting-lang"}]]
- [:h3 (tr "dashboard.theme-change")]
- [:div {:class (stl/css :fields-row)}
- [:& fm/select {:label (tr "dashboard.select-ui-theme")
- :name :theme
- :default "default"
- :options [{:label "Penpot Dark (default)" :value "default"}
- {:label "Penpot Light" :value "light"}]
- :data-test "setting-theme"}]]
+ [:h3 (tr "dashboard.theme-change")]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/select {:label (tr "dashboard.select-ui-theme")
+ :name :theme
+ :default "default"
+ :options [{:label "Penpot Dark (default)" :value "default"}
+ {:label "Penpot Light" :value "light"}]
+ :data-test "setting-theme"}]]
- [:> fm/submit-button*
- {:label (tr "dashboard.update-settings")
- :data-test "submit-lang-change"
- :class (stl/css :btn-primary)}]]
-
- ;; OLD
- [:& fm/form {:class "options-form"
- :on-submit on-submit
- :form form}
-
- [:h2 (tr "labels.language")]
-
- [:div.fields-row
- [:& fm/select {:options (into [{:label "Auto (browser)" :value ""}]
- i18n/supported-locales)
- :label (tr "dashboard.select-ui-language")
- :default ""
- :name :lang
- :data-test "setting-lang"}]]
-
- [:> fm/submit-button*
- {:label (tr "dashboard.update-settings")
- :data-test "submit-lang-change"}]])))
+ [:> fm/submit-button*
+ {:label (tr "dashboard.update-settings")
+ :data-test "submit-lang-change"
+ :class (stl/css :btn-primary)}]]))
;; --- Password Page
(mf/defc options-page
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (mf/use-effect
- #(dom/set-html-title (tr "title.settings.options")))
+ (mf/use-effect
+ #(dom/set-html-title (tr "title.settings.options")))
- (if new-css-system
- [:div {:class (stl/css :dashboard-settings)}
- [:div {:class (stl/css :form-container) :data-test "settings-form"}
- [:h2 (tr "labels.settings")]
- [:& options-form {}]]]
-
- ;; OLD
- [:div.dashboard-settings
- [:div.form-container
- {:data-test "settings-form"}
- [:& options-form {}]]])))
+ [:div {:class (stl/css :dashboard-settings)}
+ [:div {:class (stl/css :form-container) :data-test "settings-form"}
+ [:h2 (tr "labels.settings")]
+ [:& options-form {}]]])
diff --git a/frontend/src/app/main/ui/settings/password.cljs b/frontend/src/app/main/ui/settings/password.cljs
index 0b9b1b5a0a..f96edbc306 100644
--- a/frontend/src/app/main/ui/settings/password.cljs
+++ b/frontend/src/app/main/ui/settings/password.cljs
@@ -12,7 +12,6 @@
[app.main.data.users :as udu]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [t tr]]
[cljs.spec.alpha :as s]
@@ -71,88 +70,51 @@
(mf/defc password-form
[{:keys [locale] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo (constantly {:password-old nil}))
+ (let [initial (mf/use-memo (constantly {:password-old nil}))
form (fm/use-form :spec ::password-form
:validators [(fm/validate-not-all-spaces :password-old (tr "auth.password-not-empty"))
(fm/validate-not-empty :password-1 (tr "auth.password-not-empty"))
(fm/validate-not-empty :password-2 (tr "auth.password-not-empty"))
password-equality]
:initial initial)]
- (if new-css-system
- [:& fm/form {:class (stl/css :password-form)
- :on-submit on-submit
- :form form}
+ [:& fm/form {:class (stl/css :password-form)
+ :on-submit on-submit
+ :form form}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input
- {:type "password"
- :name :password-old
- :auto-focus? true
- :label (t locale "labels.old-password")}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input
+ {:type "password"
+ :name :password-old
+ :auto-focus? true
+ :label (t locale "labels.old-password")}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input
- {:type "password"
- :name :password-1
- :show-success? true
- :label (t locale "labels.new-password")}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input
+ {:type "password"
+ :name :password-1
+ :show-success? true
+ :label (t locale "labels.new-password")}]]
- [:div {:class (stl/css :fields-row)}
- [:& fm/input
- {:type "password"
- :name :password-2
- :show-success? true
- :label (t locale "labels.confirm-password")}]]
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input
+ {:type "password"
+ :name :password-2
+ :show-success? true
+ :label (t locale "labels.confirm-password")}]]
- [:> fm/submit-button*
- {:label (t locale "dashboard.update-settings")
- :data-test "submit-password"
- :class (stl/css :update-btn)}]]
-
- ;; OLD
- [:& fm/form {:class "password-form"
- :on-submit on-submit
- :form form}
- [:h2 (t locale "dashboard.password-change")]
- [:div.fields-row
- [:& fm/input
- {:type "password"
- :name :password-old
- :auto-focus? true
- :label (t locale "labels.old-password")}]]
-
- [:div.fields-row
- [:& fm/input
- {:type "password"
- :name :password-1
- :label (t locale "labels.new-password")}]]
-
- [:div.fields-row
- [:& fm/input
- {:type "password"
- :name :password-2
- :label (t locale "labels.confirm-password")}]]
-
- [:> fm/submit-button*
- {:label (t locale "dashboard.update-settings")
- :data-test "submit-password"}]])))
+ [:> fm/submit-button*
+ {:label (t locale "dashboard.update-settings")
+ :data-test "submit-password"
+ :class (stl/css :update-btn)}]]))
;; --- Password Page
(mf/defc password-page
[{:keys [locale]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (mf/use-effect
- #(dom/set-html-title (tr "title.settings.password")))
+ (mf/use-effect
+ #(dom/set-html-title (tr "title.settings.password")))
- (if new-css-system
- [:section {:class (stl/css :dashboard-settings)}
- [:div {:class (stl/css :form-container)}
- [:h2 (t locale "dashboard.password-change")]
- [:& password-form {:locale locale}]]]
-
- ;; old
- [:section.dashboard-settings.form-container
- [:div.form-container
- [:& password-form {:locale locale}]]])))
+ [:section {:class (stl/css :dashboard-settings)}
+ [:div {:class (stl/css :form-container)}
+ [:h2 (t locale "dashboard.password-change")]
+ [:& password-form {:locale locale}]]])
diff --git a/frontend/src/app/main/ui/settings/profile.cljs b/frontend/src/app/main/ui/settings/profile.cljs
index b946b68462..c3bd7fe5bd 100644
--- a/frontend/src/app/main/ui/settings/profile.cljs
+++ b/frontend/src/app/main/ui/settings/profile.cljs
@@ -16,8 +16,6 @@
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.forms :as fm]
- [app.main.ui.context :as ctx]
- [app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s]
@@ -43,9 +41,7 @@
(mf/defc profile-form
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- profile (mf/deref refs/profile)
+ (let [profile (mf/deref refs/profile)
form (fm/use-form :spec ::profile-form
:initial profile
:validators [(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))
@@ -59,78 +55,43 @@
(mf/use-callback
#(modal/show! :delete-account {}))]
- (if new-css-system
- [:& fm/form {:on-submit on-submit
- :form form
- :class (stl/css :profile-form)}
- [:div {:class (stl/css :fields-row)}
- [:& fm/input
- {:type "text"
- :name :fullname
- :label (tr "dashboard.your-name")}]]
+ [:& fm/form {:on-submit on-submit
+ :form form
+ :class (stl/css :profile-form)}
+ [:div {:class (stl/css :fields-row)}
+ [:& fm/input
+ {:type "text"
+ :name :fullname
+ :label (tr "dashboard.your-name")}]]
- [:div {:class (stl/css :fields-row)
- :on-click handle-show-change-email}
- [:& fm/input
- {:type "email"
- :name :email
- :disabled true
- :label (tr "dashboard.your-email")}]
+ [:div {:class (stl/css :fields-row)
+ :on-click handle-show-change-email}
+ [:& fm/input
+ {:type "email"
+ :name :email
+ :disabled true
+ :label (tr "dashboard.your-email")}]
- [:div {:class (stl/css :options)}
- [:div.change-email
- [:a {:on-click handle-show-change-email}
- (tr "dashboard.change-email")]]]]
+ [:div {:class (stl/css :options)}
+ [:div.change-email
+ [:a {:on-click handle-show-change-email}
+ (tr "dashboard.change-email")]]]]
- [:> fm/submit-button*
- {:label (tr "dashboard.save-settings")
- :disabled (empty? (:touched @form))
- :className (stl/css :btn-primary)}]
+ [:> fm/submit-button*
+ {:label (tr "dashboard.save-settings")
+ :disabled (empty? (:touched @form))
+ :className (stl/css :btn-primary)}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-item)}
- [:a {:on-click handle-show-delete-account
- :data-test "remove-acount-btn"}
- (tr "dashboard.remove-account")]]]]
-
- ;; OLD
- [:& fm/form {:on-submit on-submit
- :form form
- :class "profile-form"}
- [:div.fields-row
- [:& fm/input
- {:type "text"
- :name :fullname
- :label (tr "dashboard.your-name")}]]
-
- [:div.fields-row
- [:& fm/input
- {:type "email"
- :name :email
- :disabled true
- :help-icon i/at
- :label (tr "dashboard.your-email")}]
-
- [:div.options
- [:div.change-email
- [:a {:on-click #(modal/show! :change-email {})}
- (tr "dashboard.change-email")]]]]
-
- [:> fm/submit-button*
- {:label (tr "dashboard.save-settings")
- :disabled (empty? (:touched @form))}]
-
- [:div.links
- [:div.link-item
- [:a {:on-click #(modal/show! :delete-account {})
- :data-test "remove-acount-btn"}
- (tr "dashboard.remove-account")]]]])))
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-item)}
+ [:a {:on-click handle-show-delete-account
+ :data-test "remove-acount-btn"}
+ (tr "dashboard.remove-account")]]]]))
;; --- Profile Photo Form
(mf/defc profile-photo-form []
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- file-input (mf/use-ref nil)
+ (let [file-input (mf/use-ref nil)
profile (mf/deref refs/profile)
photo (cf/resolve-profile-photo-url profile)
on-image-click #(dom/click (mf/ref-val file-input))
@@ -139,44 +100,25 @@
(fn [file]
(st/emit! (du/update-photo file)))]
- (if new-css-system
- [:form {:class (stl/css :avatar-form)}
- [:div {:class (stl/css :image-change-field)}
- [:span {:class (stl/css :update-overlay)
- :on-click on-image-click} (tr "labels.update")]
- [:img {:src photo}]
- [:& file-uploader {:accept "image/jpeg,image/png"
- :multi false
- :ref file-input
- :on-selected on-file-selected
- :data-test "profile-image-input"}]]]
- ;; OLD
- [:form.avatar-form
- [:div.image-change-field
- [:span.update-overlay {:on-click on-image-click} (tr "labels.update")]
- [:img {:src photo}]
- [:& file-uploader {:accept "image/jpeg,image/png"
- :multi false
- :ref file-input
- :on-selected on-file-selected
- :data-test "profile-image-input"}]]])))
+ [:form {:class (stl/css :avatar-form)}
+ [:div {:class (stl/css :image-change-field)}
+ [:span {:class (stl/css :update-overlay)
+ :on-click on-image-click} (tr "labels.update")]
+ [:img {:src photo}]
+ [:& file-uploader {:accept "image/jpeg,image/png"
+ :multi false
+ :ref file-input
+ :on-selected on-file-selected
+ :data-test "profile-image-input"}]]]))
;; --- Profile Page
(mf/defc profile-page []
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (mf/with-effect []
- (dom/set-html-title (tr "title.settings.profile")))
- (if new-css-system
- [:div {:class (stl/css :dashboard-settings)}
- [:div {:class (stl/css :form-container)}
- [:h2 (tr "labels.profile")]
- [:& profile-photo-form]
- [:& profile-form]]]
-
- ;; OLD
- [:div.dashboard-settings
- [:div.form-container.two-columns
- [:& profile-photo-form]
- [:& profile-form]]])))
+ (mf/with-effect []
+ (dom/set-html-title (tr "title.settings.profile")))
+ [:div {:class (stl/css :dashboard-settings)}
+ [:div {:class (stl/css :form-container)}
+ [:h2 (tr "labels.profile")]
+ [:& profile-photo-form]
+ [:& profile-form]]])
diff --git a/frontend/src/app/main/ui/settings/sidebar.cljs b/frontend/src/app/main/ui/settings/sidebar.cljs
index 5d3fc8c8b7..c82664b115 100644
--- a/frontend/src/app/main/ui/settings/sidebar.cljs
+++ b/frontend/src/app/main/ui/settings/sidebar.cljs
@@ -12,7 +12,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.dashboard.sidebar :refer [profile-section]]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
@@ -23,8 +22,7 @@
(mf/defc sidebar-content
[{:keys [profile section] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- profile? (= section :settings-profile)
+ (let [profile? (= section :settings-profile)
password? (= section :settings-password)
options? (= section :settings-options)
feedback? (= section :settings-feedback)
@@ -69,107 +67,52 @@
(st/emit! (modal/show {:type :onboarding}))
(st/emit! (modal/show {:type :release-notes :version version}))))))]
- (if new-css-system
- [:div {:class (stl/css :sidebar-content)}
- [:div {:class (stl/css :sidebar-content-section)}
- [:div {:class (stl/css :back-to-dashboard)
- :on-click go-dashboard}
- [:span {:class (stl/css :icon)} i/arrow-down]
- [:span {:class (stl/css :text)} (tr "labels.dashboard")]]]
+ [:div {:class (stl/css :sidebar-content)}
+ [:div {:class (stl/css :sidebar-content-section)}
+ [:div {:class (stl/css :back-to-dashboard)
+ :on-click go-dashboard}
+ [:span {:class (stl/css :icon)} i/arrow-down]
+ [:span {:class (stl/css :text)} (tr "labels.dashboard")]]]
+ [:hr]
+
+ [:div {:class (stl/css :sidebar-content-section)}
+ [:ul {:class (stl/css :sidebar-nav :no-overflow)}
+ [:li {:class (when profile? (stl/css :current))
+ :on-click go-settings-profile}
+ [:span {:class (stl/css :element-title)} (tr "labels.profile")]]
+
+ [:li {:class (when password? (stl/css :current))
+ :on-click go-settings-password}
+ [:span {:class (stl/css :element-title)} (tr "labels.password")]]
+
+ [:li {:class (when options? (stl/css :current))
+ :on-click go-settings-options
+ :data-test "settings-profile"}
+ [:span {:class (stl/css :element-title)} (tr "labels.settings")]]
+
+ (when (contains? cf/flags :access-tokens)
+ [:li {:class (when access-tokens? (stl/css :current))
+ :on-click go-settings-access-tokens
+ :data-test "settings-access-tokens"}
+ [:span {:class (stl/css :element-title)} (tr "labels.access-tokens")]])
+
[:hr]
- [:div {:class (stl/css :sidebar-content-section)}
- [:ul {:class (stl/css :sidebar-nav :no-overflow)}
- [:li {:class (when profile? (stl/css :current))
- :on-click go-settings-profile}
- [:span {:class (stl/css :element-title)} (tr "labels.profile")]]
+ [:li {:on-click show-release-notes :data-test "release-notes"}
+ [:span {:class (stl/css :element-title)} (tr "labels.release-notes")]]
- [:li {:class (when password? (stl/css :current))
- :on-click go-settings-password}
- [:span {:class (stl/css :element-title)} (tr "labels.password")]]
-
- [:li {:class (when options? (stl/css :current))
- :on-click go-settings-options
- :data-test "settings-profile"}
- [:span {:class (stl/css :element-title)} (tr "labels.settings")]]
-
- (when (contains? cf/flags :access-tokens)
- [:li {:class (when access-tokens? (stl/css :current))
- :on-click go-settings-access-tokens
- :data-test "settings-access-tokens"}
- [:span {:class (stl/css :element-title)} (tr "labels.access-tokens")]])
-
- [:hr]
-
- [:li {:on-click show-release-notes :data-test "release-notes"}
- [:span {:class (stl/css :element-title)} (tr "labels.release-notes")]]
-
- (when (contains? cf/flags :user-feedback)
- [:li {:class (when feedback? (stl/css :current))
- :on-click go-settings-feedback}
- i/msg-info
- [:span {:class (stl/css :element-title)} (tr "labels.give-feedback")]])]]]
-
- ;; OLD
- [:div.sidebar-content
- [:div.sidebar-content-section
- [:div.back-to-dashboard {:on-click go-dashboard}
- [:span.icon i/arrow-down]
- [:span.text (tr "labels.dashboard")]]]
- [:hr]
-
- [:div.sidebar-content-section
- [:ul.sidebar-nav.no-overflow
- [:li {:class (when profile? "current")
- :on-click go-settings-profile}
- i/user
- [:span.element-title (tr "labels.profile")]]
-
- [:li {:class (when password? "current")
- :on-click go-settings-password}
- i/lock
- [:span.element-title (tr "labels.password")]]
-
- [:li {:class (when options? "current")
- :on-click go-settings-options
- :data-test "settings-profile"}
- i/tree
- [:span.element-title (tr "labels.settings")]]
-
- (when (contains? cf/flags :access-tokens)
- [:li {:class (when access-tokens? "current")
- :on-click go-settings-access-tokens
- :data-test "settings-access-tokens"}
- i/icon-key
- [:span.element-title (tr "labels.access-tokens")]])
-
- [:hr]
-
- [:li {:on-click show-release-notes :data-test "release-notes"}
- i/pencil
- [:span.element-title (tr "labels.release-notes")]]
-
- (when (contains? cf/flags :user-feedback)
- [:li {:class (when feedback? "current")
- :on-click go-settings-feedback}
- i/msg-info
- [:span.element-title (tr "labels.give-feedback")]])]]])))
+ (when (contains? cf/flags :user-feedback)
+ [:li {:class (when feedback? (stl/css :current))
+ :on-click go-settings-feedback}
+ i/msg-info
+ [:span {:class (stl/css :element-title)} (tr "labels.give-feedback")]])]]]))
(mf/defc sidebar
{::mf/wrap [mf/memo]}
[{:keys [profile locale section]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :dashboard-sidebar :settings)}
- [:& sidebar-content {:profile profile
- :section section}]
- [:& profile-section {:profile profile
- :locale locale}]]
-
- ;; OLD
- [:div.dashboard-sidebar.settings
- [:& sidebar-content {:profile profile
- :section section}]
- [:& profile-section {:profile profile
- :locale locale}]])))
+ [:div {:class (stl/css :dashboard-sidebar :settings)}
+ [:& sidebar-content {:profile profile
+ :section section}]
+ [:& profile-section {:profile profile
+ :locale locale}]])
diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs
index 14bee97258..e2bcf1156b 100644
--- a/frontend/src/app/main/ui/shapes/attrs.cljs
+++ b/frontend/src/app/main/ui/shapes/attrs.cljs
@@ -124,7 +124,7 @@
(not= :inner alignment)
(not= :outer alignment)
(not= :dotted style))
- (obj/set! attrs "strokeLinecap" caps-start)
+ (obj/set! attrs "strokeLinecap" (name caps-start))
(= :dotted style)
(obj/set! attrs "strokeLinecap" "round"))
diff --git a/frontend/src/app/main/ui/static.cljs b/frontend/src/app/main/ui/static.cljs
index 916d2fa38d..04ae734912 100644
--- a/frontend/src/app/main/ui/static.cljs
+++ b/frontend/src/app/main/ui/static.cljs
@@ -20,112 +20,64 @@
(mf/defc static-header
{::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- children (obj/get props "children")
+ (let [children (obj/get props "children")
on-click (mf/use-callback #(set! (.-href globals/location) "/"))]
- (if new-css-system
- [:section {:class (stl/css :exception-layout)}
- [:button
- {:class (stl/css :exception-header)
- :on-click on-click}
- i/logo-icon]
- [:div {:class (stl/css :deco-before)} i/logo-error-screen]
+ [:section {:class (stl/css :exception-layout)}
+ [:button
+ {:class (stl/css :exception-header)
+ :on-click on-click}
+ i/logo-icon]
+ [:div {:class (stl/css :deco-before)} i/logo-error-screen]
- [:div {:class (stl/css :exception-content)}
- [:div {:class (stl/css :container)} children]]
+ [:div {:class (stl/css :exception-content)}
+ [:div {:class (stl/css :container)} children]]
- [:div {:class (stl/css :deco-after)} i/logo-error-screen]]
- [:section.exception-layout
- [:div.exception-header
- {:on-click on-click}
- i/logo]
- [:div.exception-content
- [:div.container children]]])))
+ [:div {:class (stl/css :deco-after)} i/logo-error-screen]]))
(mf/defc invalid-token
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:> static-header {}
- [:div {:class (stl/css :main-message)} (tr "errors.invite-invalid")]
- [:div {:class (stl/css :desc-message)} (tr "errors.invite-invalid.info")]]
-
- [:> static-header {}
- [:div.image i/unchain]
- [:div.main-message (tr "errors.invite-invalid")]
- [:div.desc-message (tr "errors.invite-invalid.info")]])))
+ [:> static-header {}
+ [:div {:class (stl/css :main-message)} (tr "errors.invite-invalid")]
+ [:div {:class (stl/css :desc-message)} (tr "errors.invite-invalid.info")]])
(mf/defc not-found
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:> static-header {}
- [:div {:class (stl/css :main-message)} (tr "labels.not-found.main-message")]
- [:div {:class (stl/css :desc-message)} (tr "labels.not-found.desc-message")]]
-
- [:> static-header {}
- [:div.image i/icon-empty]
- [:div.main-message (tr "labels.not-found.main-message")]
- [:div.desc-message (tr "labels.not-found.desc-message")]])))
+ [:> static-header {}
+ [:div {:class (stl/css :main-message)} (tr "labels.not-found.main-message")]
+ [:div {:class (stl/css :desc-message)} (tr "labels.not-found.desc-message")]])
(mf/defc bad-gateway
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- handle-retry
+ (let [handle-retry
(mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))]
- (if new-css-system
- [:> static-header {}
- [:div {:class (stl/css :main-message)} (tr "labels.bad-gateway.main-message")]
- [:div {:class (stl/css :desc-message)} (tr "labels.bad-gateway.desc-message")]
- [:div {:class (stl/css :sign-info)}
- [:button {:on-click handle-retry} (tr "labels.retry")]]]
-
- [:> static-header {}
- [:div.image i/icon-empty]
- [:div.main-message (tr "labels.bad-gateway.main-message")]
- [:div.desc-message (tr "labels.bad-gateway.desc-message")]
- [:div.sign-info
- [:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
+ [:> static-header {}
+ [:div {:class (stl/css :main-message)} (tr "labels.bad-gateway.main-message")]
+ [:div {:class (stl/css :desc-message)} (tr "labels.bad-gateway.desc-message")]
+ [:div {:class (stl/css :sign-info)}
+ [:button {:on-click handle-retry} (tr "labels.retry")]]]))
(mf/defc service-unavailable
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- handle-retry
+ (let [handle-retry
(mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))]
- (if new-css-system
- [:> static-header {}
- [:div {:class (stl/css :main-message)} (tr "labels.service-unavailable.main-message")]
- [:div {:class (stl/css :desc-message)} (tr "labels.service-unavailable.desc-message")]
- [:div {:class (stl/css :sign-info)}
- [:button {:on-click handle-retry} (tr "labels.retry")]]]
-
- [:> static-header {}
- [:div.main-message (tr "labels.service-unavailable.main-message")]
- [:div.desc-message (tr "labels.service-unavailable.desc-message")]
- [:div.sign-info
- [:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
+ [:> static-header {}
+ [:div {:class (stl/css :main-message)} (tr "labels.service-unavailable.main-message")]
+ [:div {:class (stl/css :desc-message)} (tr "labels.service-unavailable.desc-message")]
+ [:div {:class (stl/css :sign-info)}
+ [:button {:on-click handle-retry} (tr "labels.retry")]]]))
(mf/defc internal-error
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- handle-retry
+ (let [handle-retry
(mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))]
- (if new-css-system
- [:> static-header {}
- [:div {:class (stl/css :main-message)} (tr "labels.internal-error.main-message")]
- [:div {:class (stl/css :desc-message)} (tr "labels.internal-error.desc-message")]
- [:div {:class (stl/css :sign-info)}
- [:button {:on-click handle-retry} (tr "labels.retry")]]]
-
- [:> static-header {}
- [:div.image i/icon-empty]
- [:div.main-message (tr "labels.internal-error.main-message")]
- [:div.desc-message (tr "labels.internal-error.desc-message")]
- [:div.sign-info
- [:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
+ [:> static-header {}
+ [:div {:class (stl/css :main-message)} (tr "labels.internal-error.main-message")]
+ [:div {:class (stl/css :desc-message)} (tr "labels.internal-error.desc-message")]
+ [:div {:class (stl/css :sign-info)}
+ [:button {:on-click handle-retry} (tr "labels.retry")]]]))
(mf/defc exception-page
[{:keys [data] :as props}]
diff --git a/frontend/src/app/main/ui/viewer/inspect/attributes.cljs b/frontend/src/app/main/ui/viewer/inspect/attributes.cljs
index 74bf4bcf98..9798af6777 100644
--- a/frontend/src/app/main/ui/viewer/inspect/attributes.cljs
+++ b/frontend/src/app/main/ui/viewer/inspect/attributes.cljs
@@ -8,7 +8,6 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.types.components-list :as ctkl]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.viewer.inspect.annotation :refer [annotation]]
[app.main.ui.viewer.inspect.attributes.blur :refer [blur-panel]]
@@ -36,65 +35,35 @@
(mf/defc attributes
[{:keys [page-id file-id shapes frame from libraries share-id objects]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- shapes (hooks/use-equal-memo shapes)
+ (let [shapes (hooks/use-equal-memo shapes)
type (if (= (count shapes) 1) (-> shapes first :type) :multiple)
options (type->options type)
content (when (= (count shapes) 1)
(ctkl/get-component-annotation (first shapes) libraries))]
- (if new-css-system
- [:div {:class (stl/css :element-options)}
- (for [[idx option] (map-indexed vector options)]
- [:> (case option
- :geometry geometry-panel
- :layout layout-panel
- :layout-element layout-element-panel
- :fill fill-panel
- :stroke stroke-panel
- :shadow shadow-panel
- :blur blur-panel
- :image image-panel
- :text text-panel
- :svg svg-panel)
- {:key idx
- :shapes shapes
- :objects objects
- :frame frame
- :from from}])
- (when content
- [:& annotation {:content content}])
- [:& exports
- {:shapes shapes
- :type type
- :page-id page-id
- :file-id file-id
- :share-id share-id}]]
-
-
- [:div.element-options
- (for [[idx option] (map-indexed vector options)]
- [:> (case option
- :geometry geometry-panel
- :layout layout-panel
- :layout-element layout-element-panel
- :fill fill-panel
- :stroke stroke-panel
- :shadow shadow-panel
- :blur blur-panel
- :image image-panel
- :text text-panel
- :svg svg-panel)
- {:key idx
- :shapes shapes
- :objects objects
- :frame frame
- :from from}])
- (when content
- [:& annotation {:content content}])
- [:& exports
- {:shapes shapes
- :type type
- :page-id page-id
- :file-id file-id
- :share-id share-id}]])))
+ [:div {:class (stl/css :element-options)}
+ (for [[idx option] (map-indexed vector options)]
+ [:> (case option
+ :geometry geometry-panel
+ :layout layout-panel
+ :layout-element layout-element-panel
+ :fill fill-panel
+ :stroke stroke-panel
+ :shadow shadow-panel
+ :blur blur-panel
+ :image image-panel
+ :text text-panel
+ :svg svg-panel)
+ {:key idx
+ :shapes shapes
+ :objects objects
+ :frame frame
+ :from from}])
+ (when content
+ [:& annotation {:content content}])
+ [:& exports
+ {:shapes shapes
+ :type type
+ :page-id page-id
+ :file-id file-id
+ :share-id share-id}]]))
diff --git a/frontend/src/app/main/ui/viewer/inspect/code.cljs b/frontend/src/app/main/ui/viewer/inspect/code.cljs
index b80df099dd..205ff04f32 100644
--- a/frontend/src/app/main/ui/viewer/inspect/code.cljs
+++ b/frontend/src/app/main/ui/viewer/inspect/code.cljs
@@ -20,7 +20,6 @@
[app.main.ui.components.code-block :refer [code-block]]
[app.main.ui.components.copy-button :refer [copy-button]]
[app.main.ui.components.select :refer [select]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
[app.main.ui.icons :as i]
@@ -100,8 +99,7 @@
(mf/defc code
[{:keys [shapes frame on-expand from]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- style-type* (mf/use-state "css")
+ (let [style-type* (mf/use-state "css")
markup-type* (mf/use-state "html")
fontfaces-css* (mf/use-state nil)
images-data* (mf/use-state nil)
@@ -232,135 +230,80 @@
(fn [result]
(reset! images-data* result)))))
- (if new-css-system
- [:div {:class (stl/css :element-options)}
- [:div {:class (stl/css :attributes-block)}
- [:button {:class (stl/css :download-button)
- :on-click handle-copy-all-code}
- "Copy all code"]]
+ [:div {:class (stl/css :element-options)}
+ [:div {:class (stl/css :attributes-block)}
+ [:button {:class (stl/css :download-button)
+ :on-click handle-copy-all-code}
+ "Copy all code"]]
- #_[:div.attributes-block
- [:button.download-button {:on-click handle-open-review}
- "Preview"]]
+ #_[:div.attributes-block
+ [:button.download-button {:on-click handle-open-review}
+ "Preview"]]
- [:div {:class (stl/css :code-block)}
- [:div {:class (stl/css :code-row-lang)}
- [:button {:class (stl/css :toggle-btn)
- :data-type "css"
- :on-click handle-collapse}
- [:span {:class (stl/css-case
- :collapsabled-icon true
- :rotated collapsed-css?)}
- i/arrow-refactor]]
+ [:div {:class (stl/css :code-block)}
+ [:div {:class (stl/css :code-row-lang)}
+ [:button {:class (stl/css :toggle-btn)
+ :data-type "css"
+ :on-click handle-collapse}
+ [:span {:class (stl/css-case
+ :collapsabled-icon true
+ :rotated collapsed-css?)}
+ i/arrow-refactor]]
- [:& select {:default-value style-type
- :class (stl/css :code-lang-select)
- :options [{:label "CSS" :value "css"}]}]
+ [:& select {:default-value style-type
+ :class (stl/css :code-lang-select)
+ :on-change set-style
+ :options [{:label "CSS" :value "css"}]}]
- [:div {:class (stl/css :action-btns)}
- [:button {:class (stl/css :expand-button)
- :on-click on-expand}
- i/code-refactor]
+ [:div {:class (stl/css :action-btns)}
+ [:button {:class (stl/css :expand-button)
+ :on-click on-expand}
+ i/code-refactor]
- [:& copy-button {:data #(replace-map style-code images-data)
- :on-copied on-style-copied}]]]
+ [:& copy-button {:data #(replace-map style-code images-data)
+ :on-copied on-style-copied}]]]
- (when-not collapsed-css?
- [:div {:class (stl/css :code-row-display)
- :style #js {"--code-height" (str (or style-size 400) "px")}}
- [:& code-block {:type style-type
- :code style-code}]])
-
- [:div {:class (stl/css :resize-area)
- :on-pointer-down on-style-pointer-down
- :on-lost-pointer-capture on-style-lost-pointer-capture
- :on-pointer-move on-style-pointer-move}]]
-
- [:div {:class (stl/css :code-block)}
- [:div {:class (stl/css :code-row-lang)}
- [:button {:class (stl/css :toggle-btn)
- :data-type "markup"
- :on-click handle-collapse}
- [:span {:class (stl/css-case
- :collapsabled-icon true
- :rotated collapsed-markup?)}
- i/arrow-refactor]]
- [:& select {:default-value markup-type
- :class (stl/css :code-lang-select)
- :options [{:label "HTML" :value "html"}
- {:label "SVG" :value "svg"}]
- :on-change set-markup}]
-
- [:div {:class (stl/css :action-btns)}
- [:button {:class (stl/css :expand-button)
- :on-click on-expand}
- i/code-refactor]
-
- [:& copy-button {:data #(replace-map markup-code images-data)
- :on-copied on-markup-copied}]]]
-
- (when-not collapsed-markup?
- [:div {:class (stl/css :code-row-display)
- :style #js {"--code-height" (str (or markup-size 400) "px")}}
- [:& code-block {:type markup-type
- :code markup-code}]])
-
- [:div {:class (stl/css :resize-area)
- :on-pointer-down on-markup-pointer-down
- :on-lost-pointer-capture on-markup-lost-pointer-capture
- :on-pointer-move on-markup-pointer-move}]]]
-
-
-
- [:div.element-options
- [:div.attributes-block
- [:button.download-button {:on-click handle-copy-all-code}
- "Copy all code"]]
-
- #_[:div.attributes-block
- [:button.download-button {:on-click handle-open-review}
- "Preview"]]
-
- [:div.code-block
- [:div.code-row-lang
- [:& select {:default-value style-type
- :class "custom-select"
- :options [{:label "CSS" :value "css"}]
- :on-change set-style}]
- [:button.expand-button
- {:on-click on-expand}
- i/full-screen]
-
- [:& copy-button {:data #(replace-map style-code images-data)
- :on-copied on-style-copied}]]
-
- [:div.code-row-display {:style #js {"--code-height" (str (or style-size 400) "px")}}
+ (when-not collapsed-css?
+ [:div {:class (stl/css :code-row-display)
+ :style #js {"--code-height" (str (or style-size 400) "px")}}
[:& code-block {:type style-type
- :code style-code}]]
+ :code style-code}]])
- [:div.resize-area {:on-pointer-down on-style-pointer-down
- :on-lost-pointer-capture on-style-lost-pointer-capture
- :on-pointer-move on-style-pointer-move}]]
+ [:div {:class (stl/css :resize-area)
+ :on-pointer-down on-style-pointer-down
+ :on-lost-pointer-capture on-style-lost-pointer-capture
+ :on-pointer-move on-style-pointer-move}]]
- [:div.code-block
- [:div.code-row-lang
- [:& select {:default-value markup-type
- :class "input-option"
- :options [{:label "HTML" :value "html"}
- {:label "SVG" :value "svg"}]
- :on-change set-markup}]
+ [:div {:class (stl/css :code-block)}
+ [:div {:class (stl/css :code-row-lang)}
+ [:button {:class (stl/css :toggle-btn)
+ :data-type "markup"
+ :on-click handle-collapse}
+ [:span {:class (stl/css-case
+ :collapsabled-icon true
+ :rotated collapsed-markup?)}
+ i/arrow-refactor]]
+ [:& select {:default-value markup-type
+ :class (stl/css :code-lang-select)
+ :options [{:label "HTML" :value "html"}
+ {:label "SVG" :value "svg"}]
+ :on-change set-markup}]
- [:button.expand-button
- {:on-click on-expand}
- i/full-screen]
+ [:div {:class (stl/css :action-btns)}
+ [:button {:class (stl/css :expand-button)
+ :on-click on-expand}
+ i/code-refactor]
- [:& copy-button {:data #(replace-map markup-code images-data)
- :on-copied on-markup-copied}]]
+ [:& copy-button {:data #(replace-map markup-code images-data)
+ :on-copied on-markup-copied}]]]
- [:div.code-row-display {:style #js {"--code-height" (str (or markup-size 400) "px")}}
+ (when-not collapsed-markup?
+ [:div {:class (stl/css :code-row-display)
+ :style #js {"--code-height" (str (or markup-size 400) "px")}}
[:& code-block {:type markup-type
- :code markup-code}]]
+ :code markup-code}]])
- [:div.resize-area {:on-pointer-down on-markup-pointer-down
- :on-lost-pointer-capture on-markup-lost-pointer-capture
- :on-pointer-move on-markup-pointer-move}]]])))
+ [:div {:class (stl/css :resize-area)
+ :on-pointer-down on-markup-pointer-down
+ :on-lost-pointer-capture on-markup-lost-pointer-capture
+ :on-pointer-move on-markup-pointer-move}]]]))
diff --git a/frontend/src/app/main/ui/viewer/inspect/code.scss b/frontend/src/app/main/ui/viewer/inspect/code.scss
index 3524f40a03..9f7c37b5e7 100644
--- a/frontend/src/app/main/ui/viewer/inspect/code.scss
+++ b/frontend/src/app/main/ui/viewer/inspect/code.scss
@@ -12,80 +12,85 @@
height: 100%;
overflow: hidden;
padding-bottom: $s-16;
+}
- .attributes-block {
- .download-button {
- @extend .button-secondary;
- @include tabTitleTipography;
- height: $s-32;
- width: 100%;
- margin: $s-8 0;
- }
- }
- .code-block {
- @include codeTypography;
- display: flex;
- flex-direction: column;
- flex: 1;
+.download-button {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ height: $s-32;
+ width: 100%;
+ margin: $s-8 0;
+}
+
+.code-block {
+ @include codeTypography;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ height: 100%;
+ min-height: 0;
+ overflow: hidden;
+ padding: 0 $s-4 $s-8 0;
+
+ pre {
+ border-radius: $br-8;
+ padding: $s-16;
+ max-height: var(--code-height);
+ overflow: auto;
height: 100%;
- min-height: 0;
- overflow: hidden;
- padding: 0 $s-4 $s-8 0;
+ }
- pre {
- border-radius: $br-8;
- padding: $s-16;
- max-height: var(--code-height);
- overflow: auto;
- height: 100%;
- }
+ // Overrides background setted in the theme
+ :global(.hljs) {
+ background: $db-tertiary;
+ }
+}
- // Overrides background setted in the theme
- :global(.hljs) {
- background: $db-tertiary;
- }
- }
- .code-row-lang {
- display: flex;
- justify-content: space-between;
- gap: $s-4;
- width: 100%;
- }
- .code-lang {
- @include tabTitleTipography;
- display: flex;
- align-items: center;
- }
- .action-btns {
- display: flex;
- gap: $s-4;
- flex: 1;
- justify-content: end;
- .expand-button {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- }
- }
- .code-lang-select {
- @include tabTitleTipography;
- width: $s-72;
- border: $s-1 solid transparent;
- background-color: transparent;
- color: var(--menu-foreground-color-disabled);
- }
- .code-row-display {
- flex: 1;
- min-height: 0;
- overflow: hidden;
- padding-bottom: $s-8;
+.code-row-lang {
+ display: flex;
+ justify-content: space-between;
+ gap: $s-4;
+ width: 100%;
+}
+
+.code-lang {
+ @include tabTitleTipography;
+ display: flex;
+ align-items: center;
+}
+
+.action-btns {
+ display: flex;
+ gap: $s-4;
+ flex: 1;
+ justify-content: end;
+}
+
+.expand-button {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
}
}
+.code-lang-select {
+ @include tabTitleTipography;
+ width: $s-72;
+ border: $s-1 solid transparent;
+ background-color: transparent;
+ color: var(--menu-foreground-color-disabled);
+}
+
+.code-row-display {
+ flex: 1;
+ min-height: 0;
+ overflow: hidden;
+ padding-bottom: $s-8;
+}
+
.toggle-btn {
@include buttonStyle;
display: flex;
diff --git a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs
index d5fe584b74..ea62c3111b 100644
--- a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs
+++ b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs
@@ -10,11 +10,8 @@
[app.common.data.macros :as dm]
[app.common.types.component :as ctk]
[app.main.refs :as refs]
- [app.main.ui.components.shape-icon :as si]
[app.main.ui.components.shape-icon-refactor :as sir]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
- [app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.viewer.inspect.attributes :refer [attributes]]
[app.main.ui.viewer.inspect.code :refer [code]]
@@ -44,8 +41,7 @@
(mf/defc right-sidebar
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
:or {from :inspect}}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- section (mf/use-state :info #_:code)
+ (let [section (mf/use-state :info #_:code)
objects (or objects (:objects page))
shapes (or shapes
(resolve-shapes objects selected))
@@ -86,113 +82,60 @@
(when-not (seq shapes)
(handle-change-tab :info))))
- (if new-css-system
- [:aside {:class (stl/css-case :settings-bar-right true
- :viewer-code (= from :inspect))}
- (if (seq shapes)
- [:div {:class (stl/css :tool-windows)}
- [:div {:class (stl/css :shape-row)}
- (if (> (count shapes) 1)
- [:*
- [:span {:class (stl/css :layers-icon)} i/layers-refactor]
- [:span {:class (stl/css :layer-title)} (tr "inspect.tabs.code.selected.multiple" (count shapes))]]
- [:*
- [:span {:class (stl/css :shape-icon)}
- [:& sir/element-icon-refactor {:shape first-shape :main-instance? main-instance?}]]
- ;; Execution time translation strings:
- ;; inspect.tabs.code.selected.circle
- ;; inspect.tabs.code.selected.component
- ;; inspect.tabs.code.selected.curve
- ;; inspect.tabs.code.selected.frame
- ;; inspect.tabs.code.selected.group
- ;; inspect.tabs.code.selected.image
- ;; inspect.tabs.code.selected.mask
- ;; inspect.tabs.code.selected.path
- ;; inspect.tabs.code.selected.rect
- ;; inspect.tabs.code.selected.svg-raw
- ;; inspect.tabs.code.selected.text
- [:span {:class (stl/css :layer-title)} (:name first-shape)]])]
- [:div {:class (stl/css :inspect-content)}
- [:& tab-container {:on-change-tab handle-change-tab
- :selected @section}
- [:& tab-element {:id :info :title (tr "inspect.tabs.info")}
- [:& attributes {:page-id page-id
- :objects objects
- :file-id file-id
- :frame frame
- :shapes shapes
- :from from
- :libraries libraries
- :share-id share-id}]]
+ [:aside {:class (stl/css-case :settings-bar-right true
+ :viewer-code (= from :inspect))}
+ (if (seq shapes)
+ [:div {:class (stl/css :tool-windows)}
+ [:div {:class (stl/css :shape-row)}
+ (if (> (count shapes) 1)
+ [:*
+ [:span {:class (stl/css :layers-icon)} i/layers-refactor]
+ [:span {:class (stl/css :layer-title)} (tr "inspect.tabs.code.selected.multiple" (count shapes))]]
+ [:*
+ [:span {:class (stl/css :shape-icon)}
+ [:& sir/element-icon-refactor {:shape first-shape :main-instance? main-instance?}]]
+ ;; Execution time translation strings:
+ ;; inspect.tabs.code.selected.circle
+ ;; inspect.tabs.code.selected.component
+ ;; inspect.tabs.code.selected.curve
+ ;; inspect.tabs.code.selected.frame
+ ;; inspect.tabs.code.selected.group
+ ;; inspect.tabs.code.selected.image
+ ;; inspect.tabs.code.selected.mask
+ ;; inspect.tabs.code.selected.path
+ ;; inspect.tabs.code.selected.rect
+ ;; inspect.tabs.code.selected.svg-raw
+ ;; inspect.tabs.code.selected.text
+ [:span {:class (stl/css :layer-title)} (:name first-shape)]])]
+ [:div {:class (stl/css :inspect-content)}
+ [:& tab-container {:on-change-tab handle-change-tab
+ :selected @section}
+ [:& tab-element {:id :info :title (tr "inspect.tabs.info")}
+ [:& attributes {:page-id page-id
+ :objects objects
+ :file-id file-id
+ :frame frame
+ :shapes shapes
+ :from from
+ :libraries libraries
+ :share-id share-id}]]
- [:& tab-element {:id :code :title (tr "inspect.tabs.code")}
- [:& code {:frame frame
- :shapes shapes
- :on-expand handle-expand
- :from from}]]]]]
- [:div {:class (stl/css :empty)}
- [:div {:class (stl/css :code-info)}
- [:span {:class (stl/css :placeholder-icon)}
- i/code-refactor]
- [:span {:class (stl/css :placeholder-label)}
- (tr "inspect.empty.select")]]
- [:div {:class (stl/css :help-info)}
- [:span {:class (stl/css :placeholder-icon)}
- i/help-refactor]
- [:span {:class (stl/css :placeholder-label)}
- (tr "inspect.empty.help")]]
- [:button {:class (stl/css :more-info-btn)
- :on-click navigate-to-help}
- (tr "inspect.empty.more-info")]])]
-
-
- [:aside.settings-bar.settings-bar-right
- [:div.settings-bar-inside
- (if (seq shapes)
- [:div.tool-window
- [:div.tool-window-bar.big
- (if (> (count shapes) 1)
- [:*
- [:span.tool-window-bar-icon i/layers]
- [:span.tool-window-bar-title (tr "inspect.tabs.code.selected.multiple" (count shapes))]]
- [:*
- [:span.tool-window-bar-icon
- [:& si/element-icon {:shape first-shape :main-instance? main-instance?}]]
- ;; Execution time translation strings:
- ;; inspect.tabs.code.selected.circle
- ;; inspect.tabs.code.selected.component
- ;; inspect.tabs.code.selected.curve
- ;; inspect.tabs.code.selected.frame
- ;; inspect.tabs.code.selected.group
- ;; inspect.tabs.code.selected.image
- ;; inspect.tabs.code.selected.mask
- ;; inspect.tabs.code.selected.path
- ;; inspect.tabs.code.selected.rect
- ;; inspect.tabs.code.selected.svg-raw
- ;; inspect.tabs.code.selected.text
- [:span.tool-window-bar-title (:name first-shape)]])]
- [:div.tool-window-content.inspect
- [:& tabs-container {:on-change-tab handle-change-tab
- :selected @section}
- [:& tabs-element {:id :info :title (tr "inspect.tabs.info")}
- [:& attributes {:page-id page-id
- :objects objects
- :file-id file-id
- :frame frame
- :shapes shapes
- :from from
- :libraries libraries
- :share-id share-id}]]
-
- [:& tabs-element {:id :code :title (tr "inspect.tabs.code")}
- [:& code {:frame frame
- :shapes shapes
- :on-expand handle-expand
- :from from}]]]]]
- [:div.empty
- [:span.tool-window-bar-icon i/code]
- [:div (tr "inspect.empty.select")]
- [:span.tool-window-bar-icon i/help]
- [:div (tr "inspect.empty.help")]
- [:button.btn-primary.action {:on-click navigate-to-help} (tr "inspect.empty.more-info")]])]])
- ))
+ [:& tab-element {:id :code :title (tr "inspect.tabs.code")}
+ [:& code {:frame frame
+ :shapes shapes
+ :on-expand handle-expand
+ :from from}]]]]]
+ [:div {:class (stl/css :empty)}
+ [:div {:class (stl/css :code-info)}
+ [:span {:class (stl/css :placeholder-icon)}
+ i/code-refactor]
+ [:span {:class (stl/css :placeholder-label)}
+ (tr "inspect.empty.select")]]
+ [:div {:class (stl/css :help-info)}
+ [:span {:class (stl/css :placeholder-icon)}
+ i/help-refactor]
+ [:span {:class (stl/css :placeholder-label)}
+ (tr "inspect.empty.help")]]
+ [:button {:class (stl/css :more-info-btn)
+ :on-click navigate-to-help}
+ (tr "inspect.empty.more-info")]])]))
diff --git a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss
index 13bf37facb..c5267edbfc 100644
--- a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss
+++ b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss
@@ -16,61 +16,73 @@
grid-area: right-sidebar;
padding-top: $s-8;
padding-left: $s-12;
- .tool-windows {
- height: 100%;
- display: flex;
- flex-direction: column;
- .shape-row {
- display: flex;
- gap: $s-8;
- align-items: center;
- margin-bottom: $s-16;
- .layers-icon,
- .shape-icon {
- @include flexCenter;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
- .layer-title {
- @include titleTipography;
- }
- }
- }
- .empty {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: $s-40;
- padding-top: $s-24;
- .code-info,
- .help-info {
- @include flexColumn;
- align-items: center;
- justify-content: flex-start;
- gap: $s-8;
- .placeholder-icon {
- @extend .empty-icon;
- }
- .placeholder-label {
- @include titleTipography;
- text-align: center;
- width: $s-200;
- }
- }
- .more-info-btn {
- @extend .button-secondary;
- @include tabTitleTipography;
- height: $s-32;
- padding: $s-8 $s-24;
- }
- }
- .inspect-content {
- flex: 1;
- overflow: hidden;
- }
&.viewer-code {
height: calc(100vh - $s-48);
}
}
+
+.tool-windows {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.shape-row {
+ display: flex;
+ gap: $s-8;
+ align-items: center;
+ margin-bottom: $s-16;
+}
+
+.layers-icon,
+.shape-icon {
+ @include flexCenter;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--icon-foreground);
+ }
+}
+
+.layer-title {
+ @include titleTipography;
+ color: $df-primary;
+}
+
+.empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: $s-40;
+ padding-top: $s-24;
+}
+
+.code-info,
+.help-info {
+ @include flexColumn;
+ align-items: center;
+ justify-content: flex-start;
+ gap: $s-8;
+}
+
+.placeholder-icon {
+ @extend .empty-icon;
+}
+
+.placeholder-label {
+ @include titleTipography;
+ text-align: center;
+ width: $s-200;
+ color: var(--empty-message-foreground-color);
+}
+
+.more-info-btn {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ height: $s-32;
+ padding: $s-8 $s-24;
+}
+
+.inspect-content {
+ flex: 1;
+ overflow: hidden;
+}
diff --git a/frontend/src/app/main/ui/viewer/login.cljs b/frontend/src/app/main/ui/viewer/login.cljs
index 375066e137..3341fac27c 100644
--- a/frontend/src/app/main/ui/viewer/login.cljs
+++ b/frontend/src/app/main/ui/viewer/login.cljs
@@ -14,7 +14,6 @@
[app.main.ui.auth.login :refer [login-methods]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-methods register-validate-form register-success-page]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -27,8 +26,7 @@
{::mf/register modal/components
::mf/register-as :login-register}
[_]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- uri (. (. js/document -location) -href)
+ (let [uri (. (. js/document -location) -href)
user-email (mf/use-state "")
register-token (mf/use-state "")
@@ -71,114 +69,58 @@
(mf/with-effect []
(swap! storage assoc :redirect-url uri))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} (tr "labels.continue-with-penpot")]
- [:button {:class (stl/css :modal-close-btn)
- :title (tr "labels.close")
- :on-click close} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} (tr "labels.continue-with-penpot")]
+ [:button {:class (stl/css :modal-close-btn)
+ :title (tr "labels.close")
+ :on-click close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :modal-content)}
- (case current-section
- :login
- [:div {:class (stl/css :form-container)}
- [:& login-methods {:on-success-callback success-login :origin :viewer}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-entry)}
- [:a {:on-click set-section
- :data-value :recovery-request}
- (tr "auth.forgot-password")]]
- [:div {:class (stl/css :link-entry)}
- [:span (tr "auth.register") " "]
- [:a {:on-click set-section
- :data-value :register}
- (tr "auth.register-submit")]]]]
+ (case current-section
+ :login
+ [:div {:class (stl/css :form-container)}
+ [:& login-methods {:on-success-callback success-login :origin :viewer}]
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-entry)}
+ [:a {:on-click set-section
+ :data-value :recovery-request}
+ (tr "auth.forgot-password")]]
+ [:div {:class (stl/css :link-entry)}
+ [:span (tr "auth.register") " "]
+ [:a {:on-click set-section
+ :data-value :register}
+ (tr "auth.register-submit")]]]]
- :register
- [:div {:class (stl/css :form-container)}
- [:& register-methods {:on-success-callback success-register}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-entry)}
- [:span (tr "auth.already-have-account") " "]
- [:a {:on-click set-section
- :data-value :login}
- (tr "auth.login-here")]]]]
+ :register
+ [:div {:class (stl/css :form-container)}
+ [:& register-methods {:on-success-callback success-register}]
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-entry)}
+ [:span (tr "auth.already-have-account") " "]
+ [:a {:on-click set-section
+ :data-value :login}
+ (tr "auth.login-here")]]]]
- :register-validate
- [:div {:class (stl/css :form-container)}
- [:& register-validate-form {:params {:token @register-token}
- :on-success-callback success-email-sent}]
- [:div {:class (stl/css :links)}
- [:div {:class (stl/css :link-entry)}
- [:a {:on-click set-section
- :data-value :register}
- (tr "labels.go-back")]]]]
-
- :recovery-request
- [:& recovery-request-page {:go-back-callback go-back-to-login
+ :register-validate
+ [:div {:class (stl/css :form-container)}
+ [:& register-validate-form {:params {:token @register-token}
:on-success-callback success-email-sent}]
- :email-sent
- [:div {:class (stl/css :form-container)}
- [:& register-success-page {:params {:email @user-email}}]])
+ [:div {:class (stl/css :links)}
+ [:div {:class (stl/css :link-entry)}
+ [:a {:on-click set-section
+ :data-value :register}
+ (tr "labels.go-back")]]]]
- (when main-section
- [:div {:class (stl/css :links)}
- [:& terms-login]])]]]
+ :recovery-request
+ [:& recovery-request-page {:go-back-callback go-back-to-login
+ :on-success-callback success-email-sent}]
+ :email-sent
+ [:div {:class (stl/css :form-container)}
+ [:& register-success-page {:params {:email @user-email}}]])
-
- ;;OLD
- [:div.modal-overlay
- [:div.modal-container.login-register
- [:div.title
- [:div.modal-close-button {:on-click close :title (tr "labels.close")}
- i/close]
- (when main-section
- [:h2 (tr "labels.continue-with-penpot")])]
-
- [:div.modal-bottom.auth-content
-
- (case current-section
- :login
- [:div.generic-form.login-form
- [:div.form-container
- [:& login-methods {:on-success-callback success-login}]
- [:div.links
- [:div.link-entry
- [:a {:on-click #(set-current-section :recovery-request)}
- (tr "auth.forgot-password")]]
- [:div.link-entry
- [:span (tr "auth.register") " "]
- [:a {:on-click #(set-current-section :register)}
- (tr "auth.register-submit")]]]]]
-
- :register
- [:div.form-container
- [:& register-methods {:on-success-callback success-register}]
- [:div.links
- [:div.link-entry
- [:span (tr "auth.already-have-account") " "]
- [:a {:on-click #(set-current-section :login)}
- (tr "auth.login-here")]]]]
-
- :register-validate
- [:div.form-container
- [:& register-validate-form {:params {:token @register-token}
- :on-success-callback success-email-sent}]
- [:div.links
- [:div.link-entry
- [:a {:on-click #(set-current-section :register)}
- (tr "labels.go-back")]]]]
-
- :recovery-request
- [:& recovery-request-page {:go-back-callback #(set-current-section :login)
- :on-success-callback success-email-sent}]
- :email-sent
- [:div.form-container
- [:& register-success-page {:params {:email @user-email}}]])]
-
- (when main-section
- [:div.modal-footer.links
- [:& terms-login]])]])))
+ (when main-section
+ [:div {:class (stl/css :links)}
+ [:& terms-login]])]]]))
diff --git a/frontend/src/app/main/ui/viewer/share_link.cljs b/frontend/src/app/main/ui/viewer/share_link.cljs
index 41bd3ed204..0c2769cc90 100644
--- a/frontend/src/app/main/ui/viewer/share_link.cljs
+++ b/frontend/src/app/main/ui/viewer/share_link.cljs
@@ -18,7 +18,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.select :refer [select]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -40,8 +39,7 @@
::mf/register-as :share-link
::mf/wrap-props false}
[{:keys [file page]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- current-page page
+ (let [current-page page
current-page-id (:id page)
slinks (mf/deref refs/share-links)
router (mf/deref refs/router)
@@ -165,274 +163,151 @@
(reset! confirm* false)
(swap! options* assoc :who-comment value))]
- (if new-css-system
- [:div {:class (stl/css :share-modal)}
- [:div {:class (stl/css :share-link-dialog)}
- [:div {:class (stl/css :share-link-header)}
- [:h2 {:class (stl/css :share-link-title)}
- (tr "common.share-link.title")]
- [:button {:class (stl/css :modal-close-button)
- :on-click on-close
- :title (tr "labels.close")}
- i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :share-link-section)}
- (when (and (not confirm?) (some? current-link))
- [:div {:class (stl/css :custon-input-wrapper)}
- [:input {:class (stl/css :input-text)
- :type "text"
- :value (or current-link "")
- :placeholder (tr "common.share-link.placeholder")
- :read-only true}]
-
- [:button {:class (stl/css :copy-button)
- :title (tr "viewer.header.share.copy-link")
- :on-click copy-link}
- i/clipboard-refactor]])
-
- [:div {:class (stl/css :hint-wrapper)}
- (when (not ^boolean confirm?)
- [:div {:class (stl/css :hint)} (tr "common.share-link.permissions-hint")])
- (cond
- (true? confirm?)
- [:div {:class (stl/css :confirm-dialog)}
- [:div {:class (stl/css :description)}
- (tr "common.share-link.confirm-deletion-link-description")]
- [:div {:class (stl/css :actions)}
- [:input {:type "button"
- :class (stl/css :button-cancel)
- :on-click #(reset! confirm* false)
- :value (tr "labels.cancel")}]
- [:input {:type "button"
- :class (stl/css :button-danger)
- :on-click delete-link
- :value (tr "common.share-link.destroy-link")}]]]
-
- (some? current-link)
- [:input
- {:type "button"
- :class (stl/css :button-danger)
- :on-click try-delete-link
- :value (tr "common.share-link.destroy-link")}]
-
- :else
- [:input
- {:type "button"
- :class (stl/css :button-active)
- :on-click create-link
- :value (tr "common.share-link.get-link")}])]]
+ [:div {:class (stl/css :share-modal)}
+ [:div {:class (stl/css :share-link-dialog)}
+ [:div {:class (stl/css :share-link-header)}
+ [:h2 {:class (stl/css :share-link-title)}
+ (tr "common.share-link.title")]
+ [:button {:class (stl/css :modal-close-button)
+ :on-click on-close
+ :title (tr "labels.close")}
+ i/close-refactor]]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :share-link-section)}
+ (when (and (not confirm?) (some? current-link))
+ [:div {:class (stl/css :custon-input-wrapper)}
+ [:input {:class (stl/css :input-text)
+ :type "text"
+ :value (or current-link "")
+ :placeholder (tr "common.share-link.placeholder")
+ :read-only true}]
+ [:button {:class (stl/css :copy-button)
+ :title (tr "viewer.header.share.copy-link")
+ :on-click copy-link}
+ i/clipboard-refactor]])
+ [:div {:class (stl/css :hint-wrapper)}
(when (not ^boolean confirm?)
- [:div {:class (stl/css :permissions-section)}
- [:button {:class (stl/css :manage-permissions)
- :on-click toggle-perms-visibility}
- [:span {:class (stl/css-case :icon true
- :rotated perms-visible?)}
- i/arrow-refactor]
- (tr "common.share-link.manage-ops")]
+ [:div {:class (stl/css :hint)} (tr "common.share-link.permissions-hint")])
+ (cond
+ (true? confirm?)
+ [:div {:class (stl/css :confirm-dialog)}
+ [:div {:class (stl/css :description)}
+ (tr "common.share-link.confirm-deletion-link-description")]
+ [:div {:class (stl/css :actions)}
+ [:input {:type "button"
+ :class (stl/css :button-cancel)
+ :on-click #(reset! confirm* false)
+ :value (tr "labels.cancel")}]
+ [:input {:type "button"
+ :class (stl/css :button-danger)
+ :on-click delete-link
+ :value (tr "common.share-link.destroy-link")}]]]
- (when ^boolean perms-visible?
- [:*
- (let [all-selected? (:all-pages options)
- pages (->> (get-in file [:data :pages])
- (map #(get-in file [:data :pages-index %])))
- selected (:pages options)]
- [:div {:class (stl/css :view-mode)}
- [:div {:class (stl/css :subtitle)}
- (tr "common.share-link.permissions-pages")]
- [:div {:class (stl/css :items)}
- (if (= 1 (count pages))
+ (some? current-link)
+ [:input
+ {:type "button"
+ :class (stl/css :button-danger)
+ :on-click try-delete-link
+ :value (tr "common.share-link.destroy-link")}]
- [:div {:class (stl/css :checkbox-wrapper)}
- [:input {:type "checkbox"
- :id (dm/str "page-" current-page-id)
- :data-page-id (dm/str current-page-id)
- :on-change on-mark-checked-page
- :checked true}]
- [:label {:for (str "page-" current-page-id)} (:name current-page)]
- [:span {:class (stl/css-case :checkobox-tick true
- :global/checked true)}
- i/status-tick-refactor]
- [:span (str " " (tr "common.share-link.current-tag"))]]
+ :else
+ [:input
+ {:type "button"
+ :class (stl/css :button-active)
+ :on-click create-link
+ :value (tr "common.share-link.get-link")}])]]
- [:*
- [:div {:class (stl/css :select-all-row)}
- [:div {:class (stl/css :checkbox-wrapper)}
- [:label {:for "view-all"
- :class (stl/css :select-all-label)}
- [:span {:class (stl/css-case :global/checked all-selected?)}
- (when all-selected?
- i/status-tick-refactor)]
- (tr "common.share-link.view-all")
- [:input {:type "checkbox"
- :id "view-all"
- :checked all-selected?
- :name "pages-mode"
- :on-change on-toggle-all}]]]
- [:span {:class (stl/css :count-pages)}
- (tr "common.share-link.page-shared" (i18n/c (count selected)))]]
+ (when (not ^boolean confirm?)
+ [:div {:class (stl/css :permissions-section)}
+ [:button {:class (stl/css :manage-permissions)
+ :on-click toggle-perms-visibility}
+ [:span {:class (stl/css-case :icon true
+ :rotated perms-visible?)}
+ i/arrow-refactor]
+ (tr "common.share-link.manage-ops")]
- [:ul {:class (stl/css :pages-selection)}
- (for [{:keys [id name]} pages]
- [:li {:class (stl/css :checkbox-wrapper)
- :key (dm/str id)}
- [:label {:for (dm/str "page-" id)}
- [:span {:class (stl/css-case :global/checked (contains? selected id))}
- (when (contains? selected id)
- i/status-tick-refactor)]
- name
- (when (= current-page-id id)
- [:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))])
- [:input {:type "checkbox"
- :id (dm/str "page-" id)
- :data-page-id (dm/str id)
- :on-change on-mark-checked-page
- :checked (contains? selected id)}]]])]])]])
-
- [:div {:class (stl/css :access-mode)}
+ (when ^boolean perms-visible?
+ [:*
+ (let [all-selected? (:all-pages options)
+ pages (->> (get-in file [:data :pages])
+ (map #(get-in file [:data :pages-index %])))
+ selected (:pages options)]
+ [:div {:class (stl/css :view-mode)}
[:div {:class (stl/css :subtitle)}
- (tr "common.share-link.permissions-can-comment")]
- [:div {:class (stl/css :items)}
- [:& select
- {:class (stl/css :who-comment-select)
- :default-value (dm/str (:who-comment options))
- :options [{:value "team" :label (tr "common.share-link.team-members")}
- {:value "all" :label (tr "common.share-link.all-users")}]
- :on-change on-comment-change}]]]
- [:div {:class (stl/css :inspect-mode)}
- [:div {:class (stl/css :subtitle)}
- (tr "common.share-link.permissions-can-inspect")]
- [:div {:class (stl/css :items)}
- [:& select
- {:class (stl/css :who-inspect-select)
- :default-value (dm/str (:who-inspect options))
- :options [{:value "team" :label (tr "common.share-link.team-members")}
- {:value "all" :label (tr "common.share-link.all-users")}]
- :on-change on-inspect-change}]]]])])]]]
-
-
- ;;OLD
- [:div.modal-overlay.transparent.share-modal
- [:div.modal-container.share-link-dialog
- [:div.modal-content.initial
- [:div.title
- [:h2 (tr "common.share-link.title")]
- [:div.modal-close-button
- {:on-click on-close
- :title (tr "labels.close")}
- i/close]]]
- [:div.modal-content
- [:div.share-link-section
- (when (and (not confirm?) (some? current-link))
- [:div.custom-input.with-icon
- [:input {:type "text"
- :value (or current-link "")
- :placeholder (tr "common.share-link.placeholder")
- :read-only true}]
- [:div.help-icon {:title (tr "viewer.header.share.copy-link")
- :on-click copy-link}
- i/copy]])
- [:div.hint-wrapper
- (when (not ^boolean confirm?)
- [:div.hint (tr "common.share-link.permissions-hint")])
- (cond
- (true? confirm?)
- [:div.confirm-dialog
- [:div.description (tr "common.share-link.confirm-deletion-link-description")]
- [:div.actions
- [:input.btn-secondary
- {:type "button"
- :on-click #(reset! confirm* false)
- :value (tr "labels.cancel")}]
- [:input.btn-danger
- {:type "button"
- :on-click delete-link
- :value (tr "common.share-link.destroy-link")}]]]
-
- (some? current-link)
- [:input.btn-secondary
- {:type "button"
- :class "primary"
- :on-click try-delete-link
- :value (tr "common.share-link.destroy-link")}]
-
- :else
- [:input.btn-primary
- {:type "button"
- :class "primary"
- :on-click create-link
- :value (tr "common.share-link.get-link")}])]]]
- [:div.modal-content.ops-section
- [:div.manage-permissions
- {:on-click toggle-perms-visibility}
- [:span.icon i/picker-hsv]
- [:div.title (tr "common.share-link.manage-ops")]]
- (when ^boolean perms-visible?
- [:*
- (let [all-selected? (:all-pages options)
- pages (->> (get-in file [:data :pages])
- (map #(get-in file [:data :pages-index %])))
- selected (:pages options)]
- [:*
- [:div.view-mode
- [:div.subtitle
- [:span.icon i/play]
(tr "common.share-link.permissions-pages")]
- [:div.items
+ [:div {:class (stl/css :items)}
(if (= 1 (count pages))
- [:div.input-checkbox.check-primary
+
+ [:div {:class (stl/css :checkbox-wrapper)}
[:input {:type "checkbox"
:id (dm/str "page-" current-page-id)
:data-page-id (dm/str current-page-id)
:on-change on-mark-checked-page
:checked true}]
[:label {:for (str "page-" current-page-id)} (:name current-page)]
+ [:span {:class (stl/css-case :checkobox-tick true
+ :global/checked true)}
+ i/status-tick-refactor]
[:span (str " " (tr "common.share-link.current-tag"))]]
[:*
- [:div.row
- [:div.input-checkbox.check-primary
- [:input {:type "checkbox"
- :id "view-all"
- :checked all-selected?
- :name "pages-mode"
- :on-change on-toggle-all}]
- [:label {:for "view-all"} (tr "common.share-link.view-all")]]
- [:span.count-pages (tr "common.share-link.page-shared" (i18n/c (count selected)))]]
+ [:div {:class (stl/css :select-all-row)}
+ [:div {:class (stl/css :checkbox-wrapper)}
+ [:label {:for "view-all"
+ :class (stl/css :select-all-label)}
+ [:span {:class (stl/css-case :global/checked all-selected?)}
+ (when all-selected?
+ i/status-tick-refactor)]
+ (tr "common.share-link.view-all")
+ [:input {:type "checkbox"
+ :id "view-all"
+ :checked all-selected?
+ :name "pages-mode"
+ :on-change on-toggle-all}]]]
- [:ul.pages-selection
+ [:span {:class (stl/css :count-pages)}
+ (tr "common.share-link.page-shared" (i18n/c (count selected)))]]
+
+ [:ul {:class (stl/css :pages-selection)}
(for [{:keys [id name]} pages]
- [:li.input-checkbox.check-primary {:key (dm/str id)}
- [:input {:type "checkbox"
- :id (dm/str "page-" id)
- :data-page-id (dm/str id)
- :on-change on-mark-checked-page
- :checked (contains? selected id)}]
- (if (= current-page-id id)
- [:*
- [:label {:for (dm/str "page-" id)} name]
- [:span.current-tag (dm/str " " (tr "common.share-link.current-tag"))]]
- [:label {:for (dm/str "page-" id)} name])])]])]]])
- [:div.access-mode
- [:div.subtitle
- [:span.icon i/chat]
- (tr "common.share-link.permissions-can-comment")]
- [:div.items
- [:select.input-select {:on-change on-comment-change
- :value (:who-comment options)}
- [:option {:value "team"} (tr "common.share-link.team-members")]
- [:option {:value "all"} (tr "common.share-link.all-users")]]]]
- [:div.inspect-mode
- [:div.subtitle
- [:span.icon i/code]
- (tr "common.share-link.permissions-can-inspect")]
- [:div.items
- [:select.input-select {:on-change on-inspect-change
- :value (:who-inspect options)}
- [:option {:value "team"} (tr "common.share-link.team-members")]
- [:option {:value "all"} (tr "common.share-link.all-users")]]]]])]]])))
+ [:li {:class (stl/css :checkbox-wrapper)
+ :key (dm/str id)}
+ [:label {:for (dm/str "page-" id)}
+ [:span {:class (stl/css-case :global/checked (contains? selected id))}
+ (when (contains? selected id)
+ i/status-tick-refactor)]
+ name
+ (when (= current-page-id id)
+ [:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))])
+ [:input {:type "checkbox"
+ :id (dm/str "page-" id)
+ :data-page-id (dm/str id)
+ :on-change on-mark-checked-page
+ :checked (contains? selected id)}]]])]])]])
+
+ [:div {:class (stl/css :access-mode)}
+ [:div {:class (stl/css :subtitle)}
+ (tr "common.share-link.permissions-can-comment")]
+ [:div {:class (stl/css :items)}
+ [:& select
+ {:class (stl/css :who-comment-select)
+ :default-value (dm/str (:who-comment options))
+ :options [{:value "team" :label (tr "common.share-link.team-members")}
+ {:value "all" :label (tr "common.share-link.all-users")}]
+ :on-change on-comment-change}]]]
+ [:div {:class (stl/css :inspect-mode)}
+ [:div {:class (stl/css :subtitle)}
+ (tr "common.share-link.permissions-can-inspect")]
+ [:div {:class (stl/css :items)}
+ [:& select
+ {:class (stl/css :who-inspect-select)
+ :default-value (dm/str (:who-inspect options))
+ :options [{:value "team" :label (tr "common.share-link.team-members")}
+ {:value "all" :label (tr "common.share-link.all-users")}]
+ :on-change on-inspect-change}]]]])])]]]))
diff --git a/frontend/src/app/main/ui/viewer/share_link.scss b/frontend/src/app/main/ui/viewer/share_link.scss
index dc0fbc7b4e..da9ce16d71 100644
--- a/frontend/src/app/main/ui/viewer/share_link.scss
+++ b/frontend/src/app/main/ui/viewer/share_link.scss
@@ -48,6 +48,7 @@
}
.hint {
flex-grow: 1;
+ color: var(--modal-text-foreground-color);
}
.custon-input-wrapper {
@include flexRow;
@@ -68,6 +69,7 @@
border: $s-1 solid var(--input-border-color-active);
}
}
+
.copy-button {
@extend .button-secondary;
@include flexRow;
@@ -93,9 +95,11 @@
.button-active {
@extend .modal-accept-btn;
}
+
.button-cancel {
@extend .modal-cancel-btn;
}
+
.button-danger {
@extend .modal-danger-btn;
}
@@ -126,12 +130,20 @@
transform: rotate(90deg);
}
}
+
.view-mode,
.access-mode,
.inspect-mode {
display: flex;
width: 100%;
}
+
+.view-mode {
+ max-height: $s-248;
+ overflow: hidden auto;
+ scrollbar-gutter: stable;
+}
+
.subtitle {
color: var(--modal-text-foreground-color);
display: flex;
diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs
index 045d1d533c..ff447eb017 100644
--- a/frontend/src/app/main/ui/workspace.cljs
+++ b/frontend/src/app/main/ui/workspace.cljs
@@ -90,12 +90,12 @@
{:key (dm/str "workspace-" page-id)
:ref node-ref}
- [:section.workspace-viewport
+ [:section {:class (stl/css :workspace-viewport)}
(when (dbg/enabled? :coordinates)
[:& coordinates/coordinates {:colorpalette? colorpalette?}])
(when (dbg/enabled? :history-overlay)
- [:div.history-debug-overlay
+ [:div {:class (stl/css :history-debug-overlay)}
[:button {:on-click #(st/emit! dw/reinitialize-undo)} "CLEAR"]
[:& history-toolbox]])
diff --git a/frontend/src/app/main/ui/workspace.scss b/frontend/src/app/main/ui/workspace.scss
index 72633f95ce..410c831862 100644
--- a/frontend/src/app/main/ui/workspace.scss
+++ b/frontend/src/app/main/ui/workspace.scss
@@ -40,3 +40,25 @@
}
}
}
+
+.workspace-content {
+ grid-area: viewport;
+}
+
+.history-debug-overlay {
+ bottom: 0;
+ max-height: $s-500;
+ width: $s-500;
+ overflow-y: auto;
+ position: absolute;
+ z-index: $z-index-modal;
+}
+
+.workspace-viewport {
+ overflow: hidden;
+ transition: none;
+ display: grid;
+ grid-template-rows: $s-20 1fr;
+ grid-template-columns: $s-20 1fr;
+ flex: 1;
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs
index c4e1f8b3e2..4972589ed6 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs
@@ -20,7 +20,6 @@
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.colorpicker.color-inputs :refer [color-inputs]]
[app.main.ui.workspace.colorpicker.gradients :refer [gradients]]
@@ -52,8 +51,7 @@
(mf/defc colorpicker
[{:keys [data disable-gradient disable-opacity disable-image on-change on-accept]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- state (mf/deref refs/colorpicker)
+ (let [state (mf/deref refs/colorpicker)
node-ref (mf/use-ref)
;; TODO: I think we need to put all this picking state under
@@ -267,235 +265,123 @@
:h h :s s :v v
:alpha (/ alpha 255)}))))
- (if new-css-system
- [:div {:class (stl/css :colorpicker)
- :ref node-ref
- :style {:touch-action "none"}}
- [:div {:class (stl/css :top-actions)}
- (when (or (not disable-gradient) (not disable-image))
- [:div {:class (stl/css :select)}
- [:& select
- {:default-value selected-mode
- :options options
- :on-change handle-change-mode}]])
- (when (not= selected-mode :image)
- [:button {:class (stl/css-case :picker-btn true
- :selected picking-color?)
- :on-click handle-click-picker}
- i/picker-refactor])]
+ [:div {:class (stl/css :colorpicker)
+ :ref node-ref
+ :style {:touch-action "none"}}
+ [:div {:class (stl/css :top-actions)}
+ (when (or (not disable-gradient) (not disable-image))
+ [:div {:class (stl/css :select)}
+ [:& select
+ {:default-value selected-mode
+ :options options
+ :on-change handle-change-mode}]])
+ (when (not= selected-mode :image)
+ [:button {:class (stl/css-case :picker-btn true
+ :selected picking-color?)
+ :on-click handle-click-picker}
+ i/picker-refactor])]
- (when (or (= selected-mode :linear-gradient)
+ (when (or (= selected-mode :linear-gradient)
(= selected-mode :radial-gradient))
- [:& gradients
- {:stops (:stops state)
- :editing-stop (:editing-stop state)
- :on-select-stop handle-change-stop}])
+ [:& gradients
+ {:stops (:stops state)
+ :editing-stop (:editing-stop state)
+ :on-select-stop handle-change-stop}])
- (if (= selected-mode :image)
- (let [uri (cfg/resolve-file-media (:image current-color))]
- [:div {:class (stl/css :select-image)}
- [:div {:class (stl/css :content)}
- (when (:image current-color)
- [:img {:src uri}])]
- [:button
- {:class (stl/css :choose-image)
- :title (tr "media.choose-image")
- :aria-label (tr "media.choose-image")
- :on-click on-fill-image-click}
- (tr "media.choose-image")
- [:& file-uploader
- {:input-id "fill-image-upload"
- :accept "image/jpeg,image/png"
- :multi false
- :ref fill-image-ref
- :on-selected on-fill-image-selected}]]])
- [:*
- [:div {:class (stl/css :colorpicker-tabs)}
- [:& tab-container
- {:on-change-tab set-tab!
- :selected @active-color-tab
- :collapsable? false}
-
- [:& tab-element {:id :ramp :title i/rgba-refactor}
- (if picking-color?
- [:div {:class (stl/css :picker-detail-wrapper)}
- [:div {:class (stl/css :center-circle)}]
- [:canvas#picker-detail {:width 256 :height 140}]]
- [:& ramp-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]
-
- [:& tab-element {:id :harmony :title i/rgba-complementary-refactor}
- (if picking-color?
- [:div {:class (stl/css :picker-detail-wrapper)}
- [:div {:class (stl/css :center-circle)}]
- [:canvas#picker-detail {:width 256 :height 140}]]
- [:& harmony-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]
-
- [:& tab-element {:id :hsva :title i/hsva-refactor}
- (if picking-color?
- [:div {:class (stl/css :picker-detail-wrapper)}
- [:div {:class (stl/css :center-circle)}]
- [:canvas#picker-detail {:width 256 :height 140}]]
- [:& hsva-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]]]
-
- [:& color-inputs
- {:type (if (= @active-color-tab :hsva) :hsv :rgb)
- :disable-opacity disable-opacity
- :color current-color
- :on-change handle-change-color}]
-
- [:& libraries
- {:state state
- :current-color current-color
- :disable-gradient disable-gradient
- :disable-opacity disable-opacity
- :disable-image disable-image
- :on-select-color on-select-library-color
- :on-add-library-color on-add-library-color}]])
-
- (when on-accept
- [:div {:class (stl/css :actions)}
- [:button {:class (stl/css-case
- :accept-color true
- :btn-disabled disabled-color-accept?)
- :on-click on-color-accept
- :disabled disabled-color-accept?}
- (tr "workspace.libraries.colors.save-color")]])]
-
- [:div.colorpicker {:ref node-ref
- :style {:touch-action "none"}}
- [:div.colorpicker-content
- [:div.top-actions
- (when (or (not disable-gradient) (not disable-image))
- [:div.element-set-content
- [:& select
- {:default-value selected-mode
- :options options
- :on-change handle-change-mode}]])
- (when (not= selected-mode :image)
- [:button.picker-btn
- {:class (when picking-color? "active")
- :on-click handle-click-picker}
- i/picker])]
-
- (when (or (= (:type state) :linear-gradient)
- (= (:type state) :radial-gradient))
-
- [:& gradients
- {:stops (:stops state)
- :editing-stop (:editing-stop state)
- :on-select-stop handle-change-stop}])
-
- (if (= selected-mode :image)
- (let [uri (cfg/resolve-file-media (:image current-color))]
- [:div.select-image
- [:div.content
- (when (:image current-color)
- [:img {:src uri}])]
- [:button.btn-secondary
- {:title (tr "media.choose-image")
- :aria-label (tr "media.choose-image")
- :on-click on-fill-image-click}
- (tr "media.choose-image")
- [:& file-uploader
- {:input-id "fill-image-upload"
- :accept "image/jpeg,image/png"
- :multi false
- :ref fill-image-ref
- :on-selected on-fill-image-selected}]]])
- [:*
- [:div.colorpicker-tabs
- [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
- {:class (when (= @active-color-tab :ramp) "active")
- :alt (tr "workspace.libraries.colors.rgba")
- :on-click set-tab!
- :data-tab "ramp"} i/picker-ramp]
- [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
- {:class (when (= @active-color-tab :harmony) "active")
- :alt (tr "workspace.libraries.colors.rgb-complementary")
- :on-click set-tab!
- :data-tab "harmony"} i/picker-harmony]
- [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
- {:class (when (= @active-color-tab :hsva) "active")
- :alt (tr "workspace.libraries.colors.hsv")
- :on-click set-tab!
- :data-tab "hsva"} i/picker-hsv]]
+ (if (= selected-mode :image)
+ (let [uri (cfg/resolve-file-media (:image current-color))]
+ [:div {:class (stl/css :select-image)}
+ [:div {:class (stl/css :content)}
+ (when (:image current-color)
+ [:img {:src uri}])]
+ [:button
+ {:class (stl/css :choose-image)
+ :title (tr "media.choose-image")
+ :aria-label (tr "media.choose-image")
+ :on-click on-fill-image-click}
+ (tr "media.choose-image")
+ [:& file-uploader
+ {:input-id "fill-image-upload"
+ :accept "image/jpeg,image/png"
+ :multi false
+ :ref fill-image-ref
+ :on-selected on-fill-image-selected}]]])
+ [:*
+ [:div {:class (stl/css :colorpicker-tabs)}
+ [:& tab-container
+ {:on-change-tab set-tab!
+ :selected @active-color-tab
+ :collapsable? false}
+ [:& tab-element {:id :ramp :title i/rgba-refactor}
(if picking-color?
- [:div.picker-detail-wrapper
- [:div.center-circle]
- [:canvas#picker-detail {:width 200 :height 160}]]
- (case @active-color-tab
- :ramp
- [:& ramp-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- :harmony
- [:& harmony-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- :hsva
- [:& hsva-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- nil))
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:width 256 :height 140}]]
+ [:& ramp-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]
- [:& color-inputs
- {:type (if (= @active-color-tab :hsva) :hsv :rgb)
- :disable-opacity disable-opacity
- :color current-color
- :on-change handle-change-color}]
+ [:& tab-element {:id :harmony :title i/rgba-complementary-refactor}
+ (if picking-color?
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:width 256 :height 140}]]
+ [:& harmony-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]
- [:& libraries
- {:state state
- :current-color current-color
- :disable-gradient disable-gradient
- :disable-opacity disable-opacity
- :disable-image disable-image
- :on-select-color on-select-library-color
- :on-add-library-color on-add-library-color}]])
+ [:& tab-element {:id :hsva :title i/hsva-refactor}
+ (if picking-color?
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:width 256 :height 140}]]
+ [:& hsva-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]]]
- (when on-accept
- [:div.actions
- [:button.btn-primary.btn-large
- {:on-click on-color-accept
- :disabled disabled-color-accept?
- :class (dom/classnames
- :btn-disabled disabled-color-accept?)}
- (tr "workspace.libraries.colors.save-color")]])]])))
+ [:& color-inputs
+ {:type (if (= @active-color-tab :hsva) :hsv :rgb)
+ :disable-opacity disable-opacity
+ :color current-color
+ :on-change handle-change-color}]
+
+ [:& libraries
+ {:state state
+ :current-color current-color
+ :disable-gradient disable-gradient
+ :disable-opacity disable-opacity
+ :disable-image disable-image
+ :on-select-color on-select-library-color
+ :on-add-library-color on-add-library-color}]])
+
+ (when on-accept
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css-case
+ :accept-color true
+ :btn-disabled disabled-color-accept?)
+ :on-click on-color-accept
+ :disabled disabled-color-accept?}
+ (tr "workspace.libraries.colors.save-color")]])]))
(defn calculate-position
"Calculates the style properties for the given coordinates and position"
- [{vh :height} position x y new-css-system]
+ [{vh :height} position x y]
(let [;; picker height in pixels
- h(if new-css-system 510 430)
+ h 510
;; Checks for overflow outside the viewport height
overflow-fix (max 0 (+ y (- 50) h (- vh)))
- x-pos (if new-css-system 325 250)]
+ x-pos 325]
(cond
(or (nil? x) (nil? y)) {:left "auto" :right "16rem" :top "4rem"}
(= position :left) {:left (str (- x x-pos) "px")
@@ -512,12 +398,11 @@
disable-opacity
disable-image
on-change on-close on-accept] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- vport (mf/deref viewport)
+ (let [vport (mf/deref viewport)
dirty? (mf/use-var false)
last-change (mf/use-var nil)
position (or position :left)
- style (calculate-position vport position x y new-css-system)
+ style (calculate-position vport position x y)
handle-change
(fn [new-data]
@@ -531,7 +416,7 @@
#(when (and @dirty? @last-change on-close)
(on-close @last-change))))
- [:div {:class (stl/css new-css-system :colorpicker-tooltip)
+ [:div {:class (stl/css :colorpicker-tooltip)
:style (clj->js style)}
[:& colorpicker {:data data
:disable-gradient disable-gradient
diff --git a/frontend/src/app/main/ui/workspace/colorpicker.scss b/frontend/src/app/main/ui/workspace/colorpicker.scss
index ae18f6abd6..4abe58b463 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker.scss
+++ b/frontend/src/app/main/ui/workspace/colorpicker.scss
@@ -11,118 +11,126 @@
top: $s-100;
left: calc(10 * $s-140);
width: auto;
- .colorpicker {
- border-radius: $br-8;
- width: $s-260;
- & > * {
- width: $s-260;
- }
- .top-actions {
- display: flex;
- align-items: flex-start;
- flex-direction: row-reverse;
- justify-content: space-between;
- height: $s-40;
- .picker-btn {
- @include buttonStyle;
- @include flexCenter;
- border-radius: $br-8;
- background-color: transparent;
- border: $s-1 solid transparent;
- height: $s-20;
- width: $s-20;
- border-radius: $br-4;
- padding: 0;
- margin-top: $s-4;
- svg {
- @extend .button-icon;
- stroke: var(--button-tertiary-foreground-color-rest);
- }
- &:hover {
- svg {
- stroke: var(--button-tertiary-foreground-color-focus);
- }
- }
- &:focus,
- &:focus-visible {
- outline: none;
- svg {
- stroke: var(--button-secondary-foreground-color-hover);
- }
- }
- &:active {
- outline: none;
- border: $s-1 solid transparent;
- svg {
- stroke: var(--button-tertiary-foreground-color-active);
- }
- }
- &.selected {
- svg {
- stroke: var(--button-tertiary-foreground-color-active);
- }
- }
- }
- .gradient-buttons {
- display: flex;
- align-items: center;
- gap: $s-8;
- .gradient-btn {
- @extend .button-tertiary;
- height: $s-20;
- width: $s-20;
- border-radius: $br-4;
- border: $s-2 solid transparent;
- &:hover {
- border: $s-2 solid var(--colorpicker-details-color-selected);
- }
- }
- .linear-gradient-btn {
- background: linear-gradient(180deg, var(--color-foreground-secondary), transparent);
- &.selected {
- background: linear-gradient(to bottom, rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
- border: $s-2 solid var(--colorpicker-details-color-selected);
- }
- }
+}
- .radial-gradient-btn {
- background: radial-gradient(transparent, var(--color-foreground-secondary));
- &.selected {
- background: radial-gradient(rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
- border: $s-2 solid var(--colorpicker-details-color-selected);
- }
- }
- }
- }
- .actions {
- display: flex;
- gap: $s-4;
- .accept-color {
- @include tabTitleTipography;
- @extend .button-secondary;
- width: 100%;
- height: $s-32;
- margin-top: $s-8;
- }
+.colorpicker {
+ border-radius: $br-8;
+ width: $s-260;
+ & > * {
+ width: $s-260;
+ }
+}
+
+.top-actions {
+ display: flex;
+ align-items: flex-start;
+ flex-direction: row-reverse;
+ justify-content: space-between;
+ height: $s-40;
+}
+
+.picker-btn {
+ @include buttonStyle;
+ @include flexCenter;
+ border-radius: $br-8;
+ background-color: transparent;
+ border: $s-1 solid transparent;
+ height: $s-20;
+ width: $s-20;
+ border-radius: $br-4;
+ padding: 0;
+ margin-top: $s-4;
+ svg {
+ @extend .button-icon;
+ stroke: var(--button-tertiary-foreground-color-rest);
+ }
+ &:hover {
+ svg {
+ stroke: var(--button-tertiary-foreground-color-focus);
}
}
- .colorpicker-tabs {
- .picker-detail-wrapper {
- @include flexCenter;
- position: relative;
- margin: $s-12 0 $s-8 0;
- .center-circle {
- width: $s-24;
- height: $s-24;
- border: $s-2 solid var(--colorpicker-details-color);
- border-radius: $br-circle;
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(calc(-1 * $s-12), calc(-1 * $s-12));
- }
+ &:focus,
+ &:focus-visible {
+ outline: none;
+ svg {
+ stroke: var(--button-secondary-foreground-color-hover);
}
}
+ &:active {
+ outline: none;
+ border: $s-1 solid transparent;
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
+ }
+ }
+ &.selected {
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
+ }
+ }
+}
+
+.gradient-buttons {
+ display: flex;
+ align-items: center;
+ gap: $s-8;
+}
+
+.gradient-btn {
+ @extend .button-tertiary;
+ height: $s-20;
+ width: $s-20;
+ border-radius: $br-4;
+ border: $s-2 solid transparent;
+ &:hover {
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+}
+
+.linear-gradient-btn {
+ background: linear-gradient(180deg, var(--color-foreground-secondary), transparent);
+ &.selected {
+ background: linear-gradient(to bottom, rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+}
+
+.radial-gradient-btn {
+ background: radial-gradient(transparent, var(--color-foreground-secondary));
+ &.selected {
+ background: radial-gradient(rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+}
+
+.actions {
+ display: flex;
+ gap: $s-4;
+}
+
+.accept-color {
+ @include tabTitleTipography;
+ @extend .button-secondary;
+ width: 100%;
+ height: $s-32;
+ margin-top: $s-8;
+}
+
+.picker-detail-wrapper {
+ @include flexCenter;
+ position: relative;
+ margin: $s-12 0 $s-8 0;
+}
+
+.center-circle {
+ width: $s-24;
+ height: $s-24;
+ border: $s-2 solid var(--colorpicker-details-color);
+ border-radius: $br-circle;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(calc(-1 * $s-12), calc(-1 * $s-12));
}
.select {
@@ -131,29 +139,31 @@
.select-image {
margin-top: $s-4;
- .content {
- border-radius: $br-8;
- display: flex;
- justify-content: center;
- background-image: url("/images/colorpicker-no-image.png");
- background-position: center;
- background-size: auto $s-140;
- height: $s-140;
- margin-bottom: $s-6;
- margin-right: $s-1;
- img {
- height: fit-content;
- width: fit-content;
- max-height: 100%;
- max-width: 100%;
- margin: auto;
- }
- }
- .choose-image {
- @extend .button-secondary;
- @include tabTitleTipography;
- width: 100%;
- margin-top: $s-12;
- height: $s-32;
+}
+
+.content {
+ border-radius: $br-8;
+ display: flex;
+ justify-content: center;
+ background-image: url("/images/colorpicker-no-image.png");
+ background-position: center;
+ background-size: auto $s-140;
+ height: $s-140;
+ margin-bottom: $s-6;
+ margin-right: $s-1;
+ img {
+ height: fit-content;
+ width: fit-content;
+ max-height: 100%;
+ max-width: 100%;
+ margin: auto;
}
}
+
+.choose-image {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ width: 100%;
+ margin-top: $s-12;
+ height: $s-32;
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs
index 531b67ccbf..53fb08dfd0 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs
@@ -10,7 +10,6 @@
[app.common.colors :as cc]
[app.common.data :as d]
[app.common.math :as mth]
- [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
@@ -29,8 +28,7 @@
(* (/ val 255) 100))
(mf/defc color-inputs [{:keys [type color disable-opacity on-change]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- {red :r green :g blue :b
+ (let [{red :r green :g blue :b
hue :h saturation :s value :v
hex :hex alpha :alpha} color
@@ -115,133 +113,52 @@
property-val)]
(dom/set-value! node new-val))))))))
- (if new-css-system
- [:div {:class (stl/css-case :color-values true
- :disable-opacity disable-opacity)}
+ [:div {:class (stl/css-case :color-values true
+ :disable-opacity disable-opacity)}
- [:div {:class (stl/css :colors-row)}
- (if (= type :rgb)
- [:*
- [:div {:class (stl/css :input-wrapper)}
- [:span {:class (stl/css :input-label)} "R"]
- [:input {:id "red-value"
- :ref (:r refs)
- :type "number"
- :min 0
- :max 255
- :default-value red
- :on-change (on-change-property :r 255)}]]
- [:div {:class (stl/css :input-wrapper)}
- [:span {:class (stl/css :input-label)} "G"]
- [:input {:id "green-value"
- :ref (:g refs)
- :type "number"
- :min 0
- :max 255
- :default-value green
- :on-change (on-change-property :g 255)}]]
- [:div {:class (stl/css :input-wrapper)}
- [:span {:class (stl/css :input-label)} "B"]
- [:input {:id "blue-value"
- :ref (:b refs)
- :type "number"
- :min 0
- :max 255
- :default-value blue
- :on-change (on-change-property :b 255)}]]]
-
- [:*
- [:div {:class (stl/css :input-wrapper)}
- [:span {:class (stl/css :input-label)} "H"]
- [:input {:id "hue-value"
- :ref (:h refs)
- :type "number"
- :min 0
- :max 360
- :default-value hue
- :on-change (on-change-property :h 360)}]]
- [:div {:class (stl/css :input-wrapper)}
- [:span {:class (stl/css :input-label)} "S"]
- [:input {:id "saturation-value"
- :ref (:s refs)
- :type "number"
- :min 0
- :max 100
- :step 1
- :default-value saturation
- :on-change (on-change-property :s 100)}]]
- [:div {:class (stl/css :input-wrapper)}
- [:span {:class (stl/css :input-label)} "V"]
- [:input {:id "value-value"
- :ref (:v refs)
- :type "number"
- :min 0
- :max 100
- :default-value value
- :on-change (on-change-property :v 100)}]]])]
- [:div {:class (stl/css :hex-alpha-wrapper)}
- [:div {:class (stl/css-case :input-wrapper true
- :hex true)}
- [:span {:class (stl/css :input-label)} "HEX"]
- [:input {:id "hex-value"
- :ref (:hex refs)
- :default-value hex
- :on-change on-change-hex
- :on-blur on-blur-hex}]]
- (when (not disable-opacity)
- [:div {:class (stl/css-case :input-wrapper true)}
- [:span {:class (stl/css :input-label)} "A"]
- [:input {:id "alpha-value"
- :ref (:alpha refs)
- :type "number"
- :min 0
- :step 1
- :max 100
- :default-value (if (= alpha :multiple) "" alpha)
- :on-change on-change-opacity}]])]]
-
- [:div.color-values
- {:class (when disable-opacity "disable-opacity")}
- [:input {:id "hex-value"
- :ref (:hex refs)
- :default-value hex
- :on-change on-change-hex
- :on-blur on-blur-hex}]
-
- (if (= type :rgb)
- [:*
+ [:div {:class (stl/css :colors-row)}
+ (if (= type :rgb)
+ [:*
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "R"]
[:input {:id "red-value"
:ref (:r refs)
:type "number"
:min 0
:max 255
:default-value red
- :on-change (on-change-property :r 255)}]
-
+ :on-change (on-change-property :r 255)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "G"]
[:input {:id "green-value"
:ref (:g refs)
:type "number"
:min 0
:max 255
:default-value green
- :on-change (on-change-property :g 255)}]
-
+ :on-change (on-change-property :g 255)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "B"]
[:input {:id "blue-value"
:ref (:b refs)
:type "number"
:min 0
:max 255
:default-value blue
- :on-change (on-change-property :b 255)}]]
- [:*
+ :on-change (on-change-property :b 255)}]]]
+
+ [:*
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "H"]
[:input {:id "hue-value"
:ref (:h refs)
:type "number"
:min 0
:max 360
:default-value hue
- :on-change (on-change-property :h 360)}]
-
+ :on-change (on-change-property :h 360)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "S"]
[:input {:id "saturation-value"
:ref (:s refs)
:type "number"
@@ -249,35 +166,33 @@
:max 100
:step 1
:default-value saturation
- :on-change (on-change-property :s 100)}]
-
+ :on-change (on-change-property :s 100)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "V"]
[:input {:id "value-value"
:ref (:v refs)
:type "number"
:min 0
:max 100
:default-value value
- :on-change (on-change-property :v 100)}]])
-
- (when (not disable-opacity)
- [:input.alpha-value {:id "alpha-value"
- :ref (:alpha refs)
- :type "number"
- :min 0
- :step 1
- :max 100
- :default-value (if (= alpha :multiple) "" alpha)
- :on-change on-change-opacity}])
-
- [:label.hex-label {:for "hex-value"} "HEX"]
- (if (= type :rgb)
- [:*
- [:label.red-label {:for "red-value"} "R"]
- [:label.green-label {:for "green-value"} "G"]
- [:label.blue-label {:for "blue-value"} "B"]]
- [:*
- [:label.red-label {:for "hue-value"} "H"]
- [:label.green-label {:for "saturation-value"} "S"]
- [:label.blue-label {:for "value-value"} "V"]])
- (when (not disable-opacity)
- [:label.alpha-label {:for "alpha-value"} "A"])])))
+ :on-change (on-change-property :v 100)}]]])]
+ [:div {:class (stl/css :hex-alpha-wrapper)}
+ [:div {:class (stl/css-case :input-wrapper true
+ :hex true)}
+ [:span {:class (stl/css :input-label)} "HEX"]
+ [:input {:id "hex-value"
+ :ref (:hex refs)
+ :default-value hex
+ :on-change on-change-hex
+ :on-blur on-blur-hex}]]
+ (when (not disable-opacity)
+ [:div {:class (stl/css-case :input-wrapper true)}
+ [:span {:class (stl/css :input-label)} "A"]
+ [:input {:id "alpha-value"
+ :ref (:alpha refs)
+ :type "number"
+ :min 0
+ :step 1
+ :max 100
+ :default-value (if (= alpha :multiple) "" alpha)
+ :on-change on-change-opacity}]])]]))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs b/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
index 4242861de6..9764b4eaec 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
@@ -8,7 +8,6 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
- [app.main.ui.context :as ctx]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@@ -22,40 +21,22 @@
(mf/defc gradients
[{:keys [stops editing-stop on-select-stop]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :gradient-stops)}
- [:div {:class (stl/css :gradient-background-wrapper)}
- [:div {:class (stl/css :gradient-background)
- :style {:background (gradient->string stops)}}]]
+ [:div {:class (stl/css :gradient-stops)}
+ [:div {:class (stl/css :gradient-background-wrapper)}
+ [:div {:class (stl/css :gradient-background)
+ :style {:background (gradient->string stops)}}]]
- [:div {:class (stl/css :gradient-stop-wrapper)}
- (for [{:keys [offset hex r g b alpha] :as value} stops]
- [:button {:class (stl/css-case :gradient-stop true
- :selected (= editing-stop offset))
- :data-value offset
- :on-click on-select-stop
- :style {:left (dm/str (* offset 100) "%")
- :backgroundColor hex}
- :key (dm/str offset)}
+ [:div {:class (stl/css :gradient-stop-wrapper)}
+ (for [{:keys [offset hex r g b alpha] :as value} stops]
+ [:button {:class (stl/css-case :gradient-stop true
+ :selected (= editing-stop offset))
+ :data-value offset
+ :on-click on-select-stop
+ :style {:left (dm/str (* offset 100) "%")
+ :backgroundColor hex}
+ :key (dm/str offset)}
- [:div {:class (stl/css :gradient-stop-color)
- :style {:background-color hex}}]
- [:div {:class (stl/css :gradient-stop-alpha)
- :style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]]
-
- [:div.gradient-stops
- [:div.gradient-background-wrapper
- [:div.gradient-background {:style {:background (gradient->string stops)}}]]
-
- [:div.gradient-stop-wrapper
- (for [{:keys [offset hex r g b alpha] :as value} stops]
- [:div.gradient-stop
- {:class (when (= editing-stop offset) "active")
- :data-value offset
- :on-click on-select-stop
- :style {:left (dm/str (* offset 100) "%")}
- :key (dm/str offset)}
-
- [:div.gradient-stop-color {:style {:background-color hex}}]
- [:div.gradient-stop-alpha {:style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]])))
+ [:div {:class (stl/css :gradient-stop-color)
+ :style {:background-color hex}}]
+ [:div {:class (stl/css :gradient-stop-alpha)
+ :style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]])
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss b/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss
index 78932650dd..a9b4107eeb 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss
+++ b/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss
@@ -13,39 +13,41 @@
margin: $s-12 0;
background-color: var(--colorpicker-handlers-color);
border-radius: $br-6;
+}
- .gradient-background-wrapper {
- height: 100%;
- width: 100%;
- border-radius: $br-6;
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
- left center;
+.gradient-background-wrapper {
+ height: 100%;
+ width: 100%;
+ border-radius: $br-6;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
+ left center;
+}
- .gradient-background {
- height: 100%;
- width: 100%;
- border-radius: $br-6;
- border: $s-2 solid var(--colorpicker-details-color);
- }
- }
- .gradient-stop-wrapper {
- position: absolute;
- width: calc(100% - 2rem);
- .gradient-stop {
- position: absolute;
- display: grid;
- grid-template-columns: 50% 50%;
- width: $s-16;
- height: $s-24;
- border-radius: $br-4;
- margin-top: calc(-1 * $s-2);
- margin-left: calc(-1 * $s-8);
- border: $s-2 solid var(--colorpicker-handlers-color);
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
- left center;
- &.selected {
- border: $s-2 solid var(--colorpicker-details-color-selected);
- }
- }
+.gradient-background {
+ height: 100%;
+ width: 100%;
+ border-radius: $br-6;
+ border: $s-2 solid var(--colorpicker-details-color);
+}
+
+.gradient-stop-wrapper {
+ position: absolute;
+ width: calc(100% - 2rem);
+}
+
+.gradient-stop {
+ position: absolute;
+ display: grid;
+ grid-template-columns: 50% 50%;
+ width: $s-16;
+ height: $s-24;
+ border-radius: $br-4;
+ margin-top: calc(-1 * $s-2);
+ margin-left: calc(-1 * $s-8);
+ border: $s-2 solid var(--colorpicker-handlers-color);
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
+ left center;
+ &.selected {
+ border: $s-2 solid var(--colorpicker-details-color-selected);
}
}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs
index 2bc19b28bc..7ca720bd2a 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs
@@ -10,7 +10,6 @@
[app.common.colors :as cc]
[app.common.geom.point :as gpt]
[app.common.math :as mth]
- [app.main.ui.context :as ctx]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
[app.util.dom :as dom]
[app.util.object :as obj]
@@ -59,11 +58,8 @@
(gpt/point x y)))
(mf/defc harmony-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- canvas-ref (mf/use-ref nil)
- canvas-side (if new-css-system
- 192
- 152)
+ (let [canvas-ref (mf/use-ref nil)
+ canvas-side 192
{hue :h saturation :s value :v alpha :alpha} color
pos-current (color->point canvas-side hue saturation)
@@ -128,83 +124,44 @@
(mf/deps canvas-ref)
(fn [] (when canvas-ref
(create-color-wheel (mf/ref-val canvas-ref)))))
- (if new-css-system
- [:div {:class (stl/css :harmony-selector)}
- [:div {:class (stl/css :handlers-wrapper)}
- [:& slider-selector {:type :value
- :vertical? true
- :reverse? true
- :value value
- :max-value 255
- :vertical true
- :on-change on-change-value
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- (when (not disable-opacity)
- [[:& slider-selector {:type :opacity
- :vertical? true
- :value alpha
- :max-value 1
- :vertical true
- :on-change on-change-opacity
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]])]
+ [:div {:class (stl/css :harmony-selector)}
+ [:div {:class (stl/css :handlers-wrapper)}
+ [:& slider-selector {:type :value
+ :vertical? true
+ :reverse? true
+ :value value
+ :max-value 255
+ :vertical true
+ :on-change on-change-value
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+ (when (not disable-opacity)
+ [[:& slider-selector {:type :opacity
+ :vertical? true
+ :value alpha
+ :max-value 1
+ :vertical true
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]])]
- [:div {:class (stl/css :hue-wheel-wrapper)}
- [:canvas {:class (stl/css :hue-wheel)
- :ref canvas-ref
- :width canvas-side
- :height canvas-side
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}]
- [:div {:class (stl/css :handler)
- :style {:pointer-events "none"
- :left (:x pos-current)
- :top (:y pos-current)}}]
- [:div {:class (stl/css-case :handler true
- :complement true)
- :style {:left (:x pos-complement)
- :top (:y pos-complement)
- :cursor "pointer"}
- :on-click on-complement-click}]]]
-
- [:div.harmony-selector
- [:div.hue-wheel-wrapper
- [:canvas.hue-wheel
- {:ref canvas-ref
- :width canvas-side
- :height canvas-side
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}]
- [:div.handler {:style {:pointer-events "none"
- :left (:x pos-current)
- :top (:y pos-current)}}]
- [:div.handler.complement {:style {:left (:x pos-complement)
- :top (:y pos-complement)
- :cursor "pointer"}
- :on-click on-complement-click}]]
- [:div.handlers-wrapper
- [:& slider-selector {:class "value"
- :vertical? true
- :reverse? true
- :value value
- :max-value 255
- :vertical true
- :on-change on-change-value
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- (when (not disable-opacity)
- [:& slider-selector {:class "opacity"
- :vertical? true
- :value alpha
- :max-value 1
- :vertical true
- :on-change on-change-opacity
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]])))
+ [:div {:class (stl/css :hue-wheel-wrapper)}
+ [:canvas {:class (stl/css :hue-wheel)
+ :ref canvas-ref
+ :width canvas-side
+ :height canvas-side
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}]
+ [:div {:class (stl/css :handler)
+ :style {:pointer-events "none"
+ :left (:x pos-current)
+ :top (:y pos-current)}}]
+ [:div {:class (stl/css-case :handler true
+ :complement true)
+ :style {:left (:x pos-complement)
+ :top (:y pos-complement)
+ :cursor "pointer"}
+ :on-click on-complement-click}]]]))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss b/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
index 15b9f54d5e..04bc1d46ac 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
+++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
@@ -12,32 +12,33 @@
gap: $s-8;
margin-top: $s-12;
margin-bottom: $s-8;
- .hue-wheel-wrapper {
- @include flexCenter;
- position: relative;
-
- .hue-wheel {
- width: $s-196;
- height: $s-196;
- }
-
- .handler {
- @extend .colorpicker-handler;
- height: $s-16;
- width: $s-16;
- border: $s-2 solid var(--colorpicker-handlers-color);
- }
-
- .handler.complement {
- background-color: var(--colorpicker-handlers-color);
- border: $s-2 solid var(--colorpicker-handlers-color);
- }
- }
-
- .handlers-wrapper {
- @include flexRow;
- height: $s-200;
- width: $s-52;
- flex-grow: 1;
- }
+}
+
+.hue-wheel-wrapper {
+ @include flexCenter;
+ position: relative;
+}
+
+.hue-wheel {
+ width: $s-196;
+ height: $s-196;
+}
+
+.handler {
+ @extend .colorpicker-handler;
+ height: $s-16;
+ width: $s-16;
+ border: $s-2 solid var(--colorpicker-handlers-color);
+}
+
+.handler.complement {
+ background-color: var(--colorpicker-handlers-color);
+ border: $s-2 solid var(--colorpicker-handlers-color);
+}
+
+.handlers-wrapper {
+ @include flexRow;
+ height: $s-200;
+ width: $s-52;
+ flex-grow: 1;
}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs b/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs
index 9236371144..cf4554b6e3 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs
@@ -8,13 +8,11 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.colors :as cc]
- [app.main.ui.context :as ctx]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
[rumext.v2 :as mf]))
(mf/defc hsva-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- {hue :h saturation :s value :v alpha :alpha} color
+ (let [{hue :h saturation :s value :v alpha :alpha} color
handle-change-slider (fn [key]
(fn [new-value]
(let [change (hash-map key new-value)
@@ -25,87 +23,46 @@
{:hex hex
:r r :g g :b b})))))
on-change-opacity (fn [new-alpha] (on-change {:alpha new-alpha}))]
- (if new-css-system
- [:div {:class (stl/css :hsva-selector)}
+ [:div {:class (stl/css :hsva-selector)}
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "H"]
+ [:& slider-selector
+ {:class (stl/css :hsva-bar)
+ :type :hue
+ :max-value 360
+ :value hue
+ :on-change (handle-change-slider :h)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]]
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "S"]
+ [:& slider-selector
+ {:class (stl/css :hsva-bar)
+ :type :saturation
+ :max-value 1
+ :value saturation
+ :on-change (handle-change-slider :s)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]]
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "V"]
+ [:& slider-selector
+ {:class (stl/css :hsva-bar)
+ :type :value
+ :reverse? false
+ :max-value 255
+ :value value
+ :on-change (handle-change-slider :v)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]]
+ (when (not disable-opacity)
[:div {:class (stl/css :hsva-row)}
- [:span {:class (stl/css :hsva-selector-label)} "H"]
+ [:span {:class (stl/css :hsva-selector-label)} "A"]
[:& slider-selector
{:class (stl/css :hsva-bar)
- :type :hue
- :max-value 360
- :value hue
- :on-change (handle-change-slider :h)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]]
- [:div {:class (stl/css :hsva-row)}
- [:span {:class (stl/css :hsva-selector-label)} "S"]
- [:& slider-selector
- {:class (stl/css :hsva-bar)
- :type :saturation
+ :type :opacity
:max-value 1
- :value saturation
- :on-change (handle-change-slider :s)
+ :value alpha
+ :on-change on-change-opacity
:on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]]
- [:div {:class (stl/css :hsva-row)}
- [:span {:class (stl/css :hsva-selector-label)} "V"]
- [:& slider-selector
- {:class (stl/css :hsva-bar)
- :type :value
- :reverse? false
- :max-value 255
- :value value
- :on-change (handle-change-slider :v)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]]
- (when (not disable-opacity)
- [:div {:class (stl/css :hsva-row)}
- [:span {:class (stl/css :hsva-selector-label)} "A"]
- [:& slider-selector
- {:class (stl/css :hsva-bar)
- :type :opacity
- :max-value 1
- :value alpha
- :on-change on-change-opacity
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]])]
-
- [:div.hsva-selector
- [:span.hsva-selector-label "H"]
- [:& slider-selector
- {:class "hue"
- :max-value 360
- :value hue
- :on-change (handle-change-slider :h)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- [:span.hsva-selector-label "S"]
- [:& slider-selector
- {:class "saturation"
- :max-value 1
- :value saturation
- :on-change (handle-change-slider :s)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- [:span.hsva-selector-label "V"]
- [:& slider-selector
- {:class "value"
- :reverse? false
- :max-value 255
- :value value
- :on-change (handle-change-slider :v)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- (when (not disable-opacity)
- [:*
- [:span.hsva-selector-label "A"]
- [:& slider-selector
- {:class "opacity"
- :max-value 1
- :value alpha
- :on-change on-change-opacity
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]])])
- ))
+ :on-finish-drag on-finish-drag}]])]))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss b/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
index 03e2d66b68..be13a492b5 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
+++ b/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
@@ -11,18 +11,21 @@
padding: $s-4;
grid-row-gap: $s-8;
margin-bottom: $s-8;
- .hsva-row {
- display: flex;
- align-items: center;
- .hsva-selector-label {
- @include tabTitleTipography;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: $s-32;
- }
- .hsva-bar {
- width: $s-228;
- }
- }
+}
+
+.hsva-row {
+ display: flex;
+ align-items: center;
+}
+
+.hsva-selector-label {
+ @include tabTitleTipography;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ width: $s-32;
+}
+
+.hsva-bar {
+ width: $s-228;
}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs
index d184ba8b4e..5970835a0b 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs
@@ -14,10 +14,8 @@
[app.main.data.workspace.colors :as mdc]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.components.color-bullet :refer [color-bullet]]
[app.main.ui.components.color-bullet-new :as cb]
[app.main.ui.components.select :refer [select]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :as r]
[app.main.ui.icons :as i]
@@ -28,8 +26,7 @@
(mf/defc libraries
[{:keys [state on-select-color on-add-library-color disable-gradient disable-opacity disable-image]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
+ (let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
current-colors (mf/use-state [])
shared-libs (mf/deref refs/workspace-libraries)
@@ -40,14 +37,11 @@
on-library-change
(mf/use-fn
(fn [event]
- (let [val (if new-css-system
- event
- (dom/get-target-val event))]
- (reset! selected
- (if (or (= val "recent")
- (= val "file"))
- (keyword val)
- (parse-uuid val))))))
+ (reset! selected
+ (if (or (= event "recent")
+ (= event "file"))
+ (keyword event)
+ (parse-uuid event)))))
check-valid-color?
(fn [color]
@@ -103,59 +97,26 @@
(let [colors (vals file-colors)]
(reset! current-colors (into [] (filter check-valid-color?) colors)))))
- (if new-css-system
- [:div {:class (stl/css :libraries)}
- [:div {:class (stl/css :select-wrapper)}
- [:& select
- {:class (stl/css :shadow-type-select)
- :default-value (or (name @selected) "recent")
- :options options
- :on-change on-library-change}]]
+ [:div {:class (stl/css :libraries)}
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select
+ {:class (stl/css :shadow-type-select)
+ :default-value (or (name @selected) "recent")
+ :options options
+ :on-change on-library-change}]]
- [:div {:class (stl/css :selected-colors)}
- (when (= @selected :file)
- [:button {:class (stl/css :add-color-btn)
- :on-click on-add-library-color}
- i/add-refactor])
+ [:div {:class (stl/css :selected-colors)}
+ (when (= @selected :file)
+ [:button {:class (stl/css :add-color-btn)
+ :on-click on-add-library-color}
+ i/add-refactor])
- [:button {:class (stl/css :palette-btn)
- :on-click toggle-palette}
- i/swatches-refactor]
+ [:button {:class (stl/css :palette-btn)
+ :on-click toggle-palette}
+ i/swatches-refactor]
- (for [[idx color] (map-indexed vector @current-colors)]
- [:& cb/color-bullet
- {:key (dm/str "color-" idx)
- :color color
- :on-click on-color-click}])]]
-
-
- [:div.libraries
- [:select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :on-change on-library-change
- :value (name @selected)}
- [:option {:value "recent"} (tr "workspace.libraries.colors.recent-colors")]
- [:option {:value "file"} (tr "workspace.libraries.colors.file-library")]
-
- (for [[_ {:keys [name id]}] shared-libs]
- [:option {:key id :value id} name])]
-
- [:div.selected-colors
- (when (= @selected :file)
- [:div.color-bullet.button.plus-button {:style {:background-color "var(--color-white)"}
- :on-click on-add-library-color}
- i/plus])
-
- [:div.color-bullet.button {:style {:background-color "var(--color-white)"}
- :on-click (fn []
- (r/set-resize-type! :bottom)
- (dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
- (ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
- (-> (dw/toggle-layout-flag :colorpalette)
- (vary-meta assoc ::ev/origin "workspace-colorpicker")))))}
- i/palette]
-
- (for [[idx color] (map-indexed vector @current-colors)]
- [:& color-bullet
- {:key (dm/str "color-" idx)
- :color color
- :on-click on-color-click}])]])))
+ (for [[idx color] (map-indexed vector @current-colors)]
+ [:& cb/color-bullet
+ {:key (dm/str "color-" idx)
+ :color color
+ :on-click on-color-click}])]]))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss b/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss
index 483aa2bae8..63a0f83987 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss
+++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss
@@ -9,32 +9,34 @@
.libraries {
margin-top: $s-8;
width: 100%;
+}
- .selected-colors {
- display: grid;
- grid-template-columns: repeat(8, 1fr);
- gap: $s-4;
- justify-content: space-between;
- overflow: auto;
- margin-top: $s-8;
- .add-color-btn,
- .palette-btn {
- @extend .button-secondary;
- height: $s-24;
- width: $s-24;
- border-radius: $br-circle;
- padding: 0;
- svg {
- @extend .button-icon;
- }
- }
- }
- .selected-colors::after {
- content: "";
- flex: auto;
- }
+.selected-colors {
+ display: grid;
+ grid-template-columns: repeat(8, 1fr);
+ gap: $s-4;
+ justify-content: space-between;
+ overflow: auto;
+ margin-top: $s-8;
+}
- .select-wrapper {
- overflow: initial;
+.add-color-btn,
+.palette-btn {
+ @extend .button-secondary;
+ height: $s-24;
+ width: $s-24;
+ border-radius: $br-circle;
+ padding: 0;
+ svg {
+ @extend .button-icon;
}
}
+
+.selected-colors::after {
+ content: "";
+ flex: auto;
+}
+
+.select-wrapper {
+ overflow: initial;
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs
index 4063c40158..8b5ee82a30 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs
@@ -9,16 +9,13 @@
(:require
[app.common.colors :as cc]
[app.common.math :as mth]
- [app.main.ui.components.color-bullet :refer [color-bullet]]
[app.main.ui.components.color-bullet-new :as cb]
- [app.main.ui.context :as ctx]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
(mf/defc value-saturation-selector [{:keys [saturation value on-change on-start-drag on-finish-drag]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- dragging? (mf/use-state false)
+ (let [dragging? (mf/use-state false)
calculate-pos
(fn [ev]
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
@@ -42,32 +39,20 @@
(dom/release-pointer event)
(reset! dragging? false)
(on-finish-drag)))]
- (if new-css-system
- [:div {:class (stl/css :value-saturation-selector)
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}
- [:div {:class (stl/css :handler)
- :style {:pointer-events "none"
- :left (str (* 100 saturation) "%")
- :top (str (* 100 (- 1 (/ value 255))) "%")}}]]
-
- [:div.value-saturation-selector
- {:on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}
- [:div.handler {:style {:pointer-events "none"
- :left (str (* 100 saturation) "%")
- :top (str (* 100 (- 1 (/ value 255))) "%")}}]])))
+ [:div {:class (stl/css :value-saturation-selector)
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}
+ [:div {:class (stl/css :handler)
+ :style {:pointer-events "none"
+ :left (str (* 100 saturation) "%")
+ :top (str (* 100 (- 1 (/ value 255))) "%")}}]]))
(mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- {hex :hex
+ (let [{hex :hex
hue :h saturation :s value :v alpha :alpha} color
on-change-value-saturation
@@ -90,60 +75,32 @@
on-change-opacity
(fn [new-opacity]
(on-change {:alpha new-opacity}))]
- (if new-css-system
- [:*
- [:& value-saturation-selector
- {:hue hue
- :saturation saturation
- :value value
- :on-change on-change-value-saturation
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
+ [:*
+ [:& value-saturation-selector
+ {:hue hue
+ :saturation saturation
+ :value value
+ :on-change on-change-value-saturation
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
- [:div {:class (stl/css new-css-system :shade-selector)
- :style #js {"--bullet-size" "52px"}}
- [:& cb/color-bullet {:color {:color hex
- :opacity alpha}
- :area true}]
- [:div {:class (stl/css :sliders-wrapper)}
- [:& slider-selector {:type :hue
- :max-value 360
- :value hue
- :on-change on-change-hue
+ [:div {:class (stl/css :shade-selector)
+ :style #js {"--bullet-size" "52px"}}
+ [:& cb/color-bullet {:color {:color hex
+ :opacity alpha}
+ :area true}]
+ [:div {:class (stl/css :sliders-wrapper)}
+ [:& slider-selector {:type :hue
+ :max-value 360
+ :value hue
+ :on-change on-change-hue
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+
+ (when (not disable-opacity)
+ [:& slider-selector {:type :opacity
+ :max-value 1
+ :value alpha
+ :on-change on-change-opacity
:on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- (when (not disable-opacity)
- [:& slider-selector {:type :opacity
- :max-value 1
- :value alpha
- :on-change on-change-opacity
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]]]
-
- [:*
- [:& value-saturation-selector
- {:hue hue
- :saturation saturation
- :value value
- :on-change on-change-value-saturation
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- [:div.shade-selector
- [:& color-bullet {:color {:color hex
- :opacity alpha}}]
- [:& slider-selector {:class "hue"
- :max-value 360
- :value hue
- :on-change on-change-hue
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- (when (not disable-opacity)
- [:& slider-selector {:class "opacity"
- :max-value 1
- :value alpha
- :on-change on-change-opacity
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]])))
+ :on-finish-drag on-finish-drag}])]]]))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss b/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
index 450dcd9e57..512739d8fd 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
+++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
@@ -15,13 +15,6 @@
margin-bottom: $s-12;
cursor: pointer;
- .handler {
- @extend .colorpicker-handler;
- height: $s-16;
- width: $s-16;
- border: $s-2 solid var(--colorpicker-handlers-color);
- }
-
&::before {
content: "";
position: absolute;
@@ -38,12 +31,21 @@
background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
}
}
+
+.handler {
+ @extend .colorpicker-handler;
+ height: $s-16;
+ width: $s-16;
+ border: $s-2 solid var(--colorpicker-handlers-color);
+}
+
.shade-selector {
display: flex;
gap: $s-4;
height: $s-52;
cursor: pointer;
}
+
.sliders-wrapper {
@include flexColumn;
}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs
index ddf475744d..1fa07db8a4 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs
@@ -9,15 +9,13 @@
(:require
[app.common.data.macros :as dm]
[app.common.math :as mth]
- [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[app.util.object :as obj]
[rumext.v2 :as mf]))
(mf/defc slider-selector
[{:keys [value class min-value max-value vertical? reverse? on-change on-start-drag on-finish-drag type]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- min-value (or min-value 0)
+ (let [min-value (or min-value 0)
max-value (or max-value 1)
dragging? (mf/use-state false)
@@ -53,49 +51,27 @@
value (+ min-value (* unit-value (- max-value min-value)))]
(on-change value))))]
- (if new-css-system
- [:div {:class (stl/css-case :opacity-wrapper (= type :opacity))}
- [:div {:class (dm/str class (stl/css-case :vertical vertical?
- :slider-selector true
- :hue (= type :hue)
- :opacity (= type :opacity)
- :value (= type :value)))
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}
- (let [value-percent (* (/ (- value min-value)
- (- max-value min-value)) 100)
+ [:div {:class (stl/css-case :opacity-wrapper (= type :opacity))}
+ [:div {:class (dm/str class (stl/css-case :vertical vertical?
+ :slider-selector true
+ :hue (= type :hue)
+ :opacity (= type :opacity)
+ :value (= type :value)))
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}
+ (let [value-percent (* (/ (- value min-value)
+ (- max-value min-value)) 100)
- value-percent (if reverse?
- (mth/abs (- value-percent 100))
- value-percent)
- value-percent-str (str value-percent "%")
+ value-percent (if reverse?
+ (mth/abs (- value-percent 100))
+ value-percent)
+ value-percent-str (str value-percent "%")
- style-common #js {:pointerEvents "none"}
- style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
- style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
- [:div {:class (stl/css :handler)
- :style (if vertical? style-vertical style-horizontal)}])]]
-
- [:div.slider-selector
- {:class (str (if vertical? "vertical " "") class)
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}
-
- (let [value-percent (* (/ (- value min-value)
- (- max-value min-value)) 100)
-
- value-percent (if reverse?
- (mth/abs (- value-percent 100))
- value-percent)
- value-percent-str (str value-percent "%")
-
- style-common #js {:pointerEvents "none"}
- style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
- style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
- [:div.handler {:style (if vertical? style-vertical style-horizontal)}])])))
+ style-common #js {:pointerEvents "none"}
+ style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
+ style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
+ [:div {:class (stl/css :handler)
+ :style (if vertical? style-vertical style-horizontal)}])]]))
diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs
index 121ca11d98..35df73bdd8 100644
--- a/frontend/src/app/main/ui/workspace/comments.cljs
+++ b/frontend/src/app/main/ui/workspace/comments.cljs
@@ -28,8 +28,7 @@
(mf/defc sidebar-options
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- {cmode :mode cshow :show} (mf/deref refs/comments-local)
+ (let [{cmode :mode cshow :show} (mf/deref refs/comments-local)
update-mode
(mf/use-fn
(fn [event]
@@ -45,53 +44,30 @@
(let [mode (if (= :pending cshow) :all :pending)]
(st/emit! (dcm/update-filters {:show mode})))))]
- (if new-css-system
- [:ul {:class (stl/css :comment-mode-dropdown)}
- [:li {:class (stl/css-case :dropdown-item true
- :selected (or (= :all cmode) (nil? cmode)))
- :data-value "all"
- :on-click update-mode}
+ [:ul {:class (stl/css :comment-mode-dropdown)}
+ [:li {:class (stl/css-case :dropdown-item true
+ :selected (or (= :all cmode) (nil? cmode)))
+ :data-value "all"
+ :on-click update-mode}
- [:span {:class (stl/css :label)} (tr "labels.show-all-comments")]
- [:span {:class (stl/css :icon)} i/tick-refactor]]
- [:li {:class (stl/css-case :dropdown-item true
- :selected (= :yours cmode))
- :data-value "yours"
- :on-click update-mode}
- [:span {:class (stl/css :label)} (tr "labels.show-your-comments")]
- [:span {:class (stl/css :icon)} i/tick-refactor]]
- [:li {:class (stl/css :separator)}]
- [:li {:class (stl/css-case :dropdown-item true
- :selected (= :pending cshow))
- :on-click update-show}
- [:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")]
- [:span {:class (stl/css :icon)} i/tick-refactor]]]
-
-
- [:ul.dropdown.with-check
- [:li {:class (dom/classnames :selected (or (= :all cmode) (nil? cmode)))
- :data-value "all"
- :on-click update-mode}
- [:span.icon i/tick]
- [:span.label (tr "labels.show-all-comments")]]
-
- [:li {:class (dom/classnames :selected (= :yours cmode))
- :data-value "yours"
- :on-click update-mode}
- [:span.icon i/tick]
- [:span.label (tr "labels.show-your-comments")]]
-
- [:hr]
-
- [:li {:class (dom/classnames :selected (= :pending cshow))
- :on-click update-show}
- [:span.icon i/tick]
- [:span.label (tr "labels.hide-resolved-comments")]]])))
+ [:span {:class (stl/css :label)} (tr "labels.show-all-comments")]
+ [:span {:class (stl/css :icon)} i/tick-refactor]]
+ [:li {:class (stl/css-case :dropdown-item true
+ :selected (= :yours cmode))
+ :data-value "yours"
+ :on-click update-mode}
+ [:span {:class (stl/css :label)} (tr "labels.show-your-comments")]
+ [:span {:class (stl/css :icon)} i/tick-refactor]]
+ [:li {:class (stl/css :separator)}]
+ [:li {:class (stl/css-case :dropdown-item true
+ :selected (= :pending cshow))
+ :on-click update-show}
+ [:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")]
+ [:span {:class (stl/css :icon)} i/tick-refactor]]]))
(mf/defc comments-sidebar
[{:keys [users threads page-id from-viewer]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- threads-map (mf/deref refs/threads-ref)
+ (let [threads-map (mf/deref refs/threads-ref)
profile (mf/deref refs/profile)
users-refs (mf/deref refs/current-file-comments-users)
users (or users users-refs)
@@ -139,75 +115,41 @@
(dwcm/center-to-comment-thread thread)
(-> (dcm/open-thread thread)
(with-meta {::ev/origin "workspace"})))))))]
- (if new-css-system
- [:div {:class (stl/css :comments-section)}
- [:div {:class (stl/css :comments-section-title)}
- [:span (tr "labels.comments")]
- [:button {:class (stl/css :close-button)
- :on-click close-section}
- i/close-refactor]]
+ [:div {:class (stl/css :comments-section)}
+ [:div {:class (stl/css :comments-section-title)}
+ [:span (tr "labels.comments")]
+ [:button {:class (stl/css :close-button)
+ :on-click close-section}
+ i/close-refactor]]
- [:button {:class (stl/css :mode-dropdown-wrapper)
- :on-click toggle-mode-selector}
+ [:button {:class (stl/css :mode-dropdown-wrapper)
+ :on-click toggle-mode-selector}
- [:span {:class (stl/css :mode-label)} (case (:mode local)
- (nil :all) (tr "labels.show-all-comments")
- :yours (tr "labels.show-your-comments"))]
- [:div {:class (stl/css :icon)} i/arrow-refactor]]
+ [:span {:class (stl/css :mode-label)} (case (:mode local)
+ (nil :all) (tr "labels.show-all-comments")
+ :yours (tr "labels.show-your-comments"))]
+ [:div {:class (stl/css :icon)} i/arrow-refactor]]
- [:& dropdown {:show options?
- :on-close #(reset! state* false)}
- [:& sidebar-options {:local local}]]
+ [:& dropdown {:show options?
+ :on-close #(reset! state* false)}
+ [:& sidebar-options {:local local}]]
- [:div {:class (stl/css :comments-section-content)}
+ [:div {:class (stl/css :comments-section-content)}
- (if (seq tgroups)
- [:div {:class (stl/css :thread-groups)}
+ (if (seq tgroups)
+ [:div {:class (stl/css :thread-groups)}
+ [:& cmt/comment-thread-group
+ {:group (first tgroups)
+ :on-thread-click on-thread-click
+ :users users}]
+ (for [tgroup (rest tgroups)]
[:& cmt/comment-thread-group
- {:group (first tgroups)
+ {:group tgroup
:on-thread-click on-thread-click
- :users users}]
- (for [tgroup (rest tgroups)]
- [:& cmt/comment-thread-group
- {:group tgroup
- :on-thread-click on-thread-click
- :users users
- :key (:page-id tgroup)}])]
+ :users users
+ :key (:page-id tgroup)}])]
- [:div {:class (stl/css :thread-group-placeholder)}
- [:span {:class (stl/css :placeholder-icon)} i/comments-refactor]
- [:span {:class (stl/css :placeholder-label)}
- (tr "labels.no-comments-available")]])]]
-
-
- [:div.comments-section.comment-threads-section
- [:div.workspace-comment-threads-sidebar-header
- [:div.label (tr "labels.comments")]
- [:div.options {:on-click toggle-mode-selector}
- [:div.label (case (:mode local)
- (nil :all) (tr "labels.all")
- :yours (tr "labels.only-yours"))]
- [:div.icon i/arrow-down]]
-
- [:& dropdown {:show options?
- :on-close #(reset! state* false)}
- [:& sidebar-options {:local local}]]]
-
- (if (seq tgroups)
- [:div.thread-groups
- [:& cmt/comment-thread-group
- {:group (first tgroups)
- :on-thread-click on-thread-click
- :users users}]
- (for [tgroup (rest tgroups)]
- [:*
- [:hr]
- [:& cmt/comment-thread-group
- {:group tgroup
- :on-thread-click on-thread-click
- :users users
- :key (:page-id tgroup)}]])]
-
- [:div.thread-groups-placeholder
- i/chat
- (tr "labels.no-comments-available")])])))
+ [:div {:class (stl/css :thread-group-placeholder)}
+ [:span {:class (stl/css :placeholder-icon)} i/comments-refactor]
+ [:span {:class (stl/css :placeholder-label)}
+ (tr "labels.no-comments-available")]])]]))
diff --git a/frontend/src/app/main/ui/workspace/comments.scss b/frontend/src/app/main/ui/workspace/comments.scss
index 7c45491e67..b742ea5890 100644
--- a/frontend/src/app/main/ui/workspace/comments.scss
+++ b/frontend/src/app/main/ui/workspace/comments.scss
@@ -133,6 +133,7 @@
@include titleTipography;
text-align: center;
width: $s-184;
+ color: var(--empty-message-foreground-color);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs
index b028ad0014..af84fffa69 100644
--- a/frontend/src/app/main/ui/workspace/context_menu.cljs
+++ b/frontend/src/app/main/ui/workspace/context_menu.cljs
@@ -6,7 +6,7 @@
(ns app.main.ui.workspace.context-menu
"A workspace specific context menu (mouse right click)."
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -14,6 +14,7 @@
[app.common.types.component :as ctk]
[app.common.types.container :as ctn]
[app.common.types.page :as ctp]
+ [app.common.types.shape.layout :as ctl]
[app.common.uuid :as uuid]
[app.main.data.events :as ev]
[app.main.data.modal :as modal]
@@ -30,7 +31,6 @@
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.shape-icon-refactor :as sic]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.util.dom :as dom]
@@ -48,10 +48,9 @@
(dom/stop-propagation event))
(mf/defc menu-entry
- [{:keys [title shortcut on-click on-pointer-enter on-pointer-leave on-unmount children selected? icon] :as props}]
+ [{:keys [title shortcut on-click on-pointer-enter on-pointer-leave on-unmount children selected? icon disabled] :as props}]
(let [submenu-ref (mf/use-ref nil)
hovering? (mf/use-ref false)
- new-css-system (mf/use-ctx ctx/new-css-system)
on-pointer-enter
(mf/use-callback
(fn []
@@ -85,69 +84,44 @@
(constantly on-unmount))
(if icon
- [:li {:class (if new-css-system
- (dom/classnames (css :icon-menu-item) true)
- (dom/classnames :icon-menu-item true))
+ [:li {:class (stl/css :icon-menu-item)
+ :disabled disabled
:ref set-dom-node
:on-click on-click
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave}
[:span
- {:class (if new-css-system
- (dom/classnames (css :icon-wrapper) true)
- (dom/classnames :icon-wrapper true))}
- (if selected? [:span {:class (if new-css-system
- (dom/classnames (css :selected-icon) true)
- (dom/classnames :selected-icon true))}
- (if new-css-system
- i/tick-refactor
- i/tick)]
- [:span {:class (if new-css-system
- (dom/classnames (css :selected-icon) true)
- (dom/classnames :selected-icon true))}])
- [:span {:class (if new-css-system
- (dom/classnames (css :shape-icon) true)
- (dom/classnames :shape-icon true))} icon]]
- [:span {:class (if new-css-system
- (dom/classnames (css :title) true)
- (dom/classnames :title true))} title]]
- [:li {:class (dom/classnames (css :context-menu-item) new-css-system)
+ {:class (stl/css :icon-wrapper)}
+ (if selected? [:span {:class (stl/css :selected-icon)}
+ i/tick-refactor]
+ [:span {:class (stl/css :selected-icon)}])
+ [:span {:class (stl/css :shape-icon)} icon]]
+ [:span {:class (stl/css :title)} title]]
+ [:li {:class (stl/css :context-menu-item)
+ :disabled disabled
:ref set-dom-node
:on-click on-click
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave}
- [:span {:class (if new-css-system
- (dom/classnames (css :title) true)
- (dom/classnames :title true))} title]
+ [:span {:class (stl/css :title)} title]
(when shortcut
- [:span {:class (if new-css-system
- (dom/classnames (css :shortcut) true)
- (dom/classnames :shortcut true))}
- (if new-css-system
- (for [sc (scd/split-sc shortcut)]
- [:span {:class (dom/classnames (css :shortcut-key) true)} sc])
- (or shortcut ""))])
+ [:span {:class (stl/css :shortcut)}
+ (for [sc (scd/split-sc shortcut)]
+ [:span {:class (stl/css :shortcut-key)} sc])])
(when (> (count children) 1)
- (if new-css-system
- [:span {:class (dom/classnames (css :submenu-icon) true)} i/arrow-refactor]
- [:span.submenu-icon i/arrow-slide]))
+ [:span {:class (stl/css :submenu-icon)} i/arrow-refactor])
(when (> (count children) 1)
- [:ul
- {:class (if new-css-system
- (dom/classnames (css :workspace-context-submenu) true)
- (dom/classnames :workspace-context-menu true))
- :ref submenu-ref
- :style {:display "none" :left 250}
- :on-context-menu prevent-default}
+ [:ul {:class (stl/css :workspace-context-submenu)
+ :ref submenu-ref
+ :style {:display "none" :left 250}
+ :on-context-menu prevent-default}
children])])))
+
(mf/defc menu-separator
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- [:li {:class (if new-css-system
- (dom/classnames (css :separator) true)
- (dom/classnames :separator true))}]))
+ [:li {:class (stl/css :separator)}])
(mf/defc context-menu-edit
[_]
@@ -479,8 +453,8 @@
[:*
[:& menu-separator]
[:& menu-entry {:title (tr "workspace.shape.menu.delete")
- :shortcut (sc/get-tooltip :delete)
- :on-click do-delete}]]))
+ :shortcut (sc/get-tooltip :delete)
+ :on-click do-delete}]]))
(mf/defc shape-context-menu
{::mf/wrap [mf/memo]}
@@ -549,13 +523,97 @@
:shortcut (sc/get-tooltip :toggle-focus-mode)
:on-click do-toggle-focus-mode}])]))
+(mf/defc grid-track-context-menu
+ [{:keys [mdata] :as props}]
+ (let [{:keys [type index grid-id]} mdata
+ do-delete-track
+ (mf/use-callback
+ (mf/deps grid-id type index)
+ (fn []
+ (st/emit! (dwsl/remove-layout-track [grid-id] type index))))
+
+ do-add-track-before
+ (mf/use-callback
+ (mf/deps grid-id type index)
+ (fn []
+ (st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value index))))
+
+ do-add-track-after
+ (mf/use-callback
+ (mf/deps grid-id type index)
+ (fn []
+ (st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value (inc index)))))
+
+ do-duplicate-track
+ (mf/use-callback
+ (mf/deps grid-id type index)
+ (fn []
+ (st/emit! (dwsl/duplicate-layout-track [grid-id] type index))))
+
+ do-delete-track-shapes
+ (mf/use-callback
+ (mf/deps grid-id type index)
+ (fn []
+ (st/emit! (dwsl/remove-layout-track [grid-id] type index {:with-shapes? true}))))]
+
+ (if (= type :column)
+ [:*
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.duplicate") :on-click do-duplicate-track}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.add-before") :on-click do-add-track-before}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.add-after") :on-click do-add-track-after}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete") :on-click do-delete-track}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete-shapes") :on-click do-delete-track-shapes}]]
+
+ [:*
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.duplicate") :on-click do-duplicate-track}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.add-before") :on-click do-add-track-before}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.add-after") :on-click do-add-track-after}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete") :on-click do-delete-track}]
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete-shapes") :on-click do-delete-track-shapes}]])))
+
+(mf/defc grid-cells-context-menu
+ [{:keys [mdata] :as props}]
+ (let [{:keys [grid cells]} mdata
+
+ single? (= (count cells) 1)
+
+ can-merge?
+ (mf/use-memo
+ (mf/deps cells)
+ #(ctl/valid-area-cells? cells))
+
+ do-merge-cells
+ (mf/use-callback
+ (mf/deps grid cells)
+ (fn []
+ (st/emit! (dwsl/merge-cells (:id grid) (map :id cells)))))
+
+ do-create-board
+ (mf/use-callback
+ (mf/deps grid cells)
+ (fn []
+ (st/emit! (dwsl/create-cell-board (:id grid) (map :id cells)))))]
+ [:*
+ (when (not single?)
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-cells.merge")
+ :on-click do-merge-cells
+ :disabled (not can-merge?)}])
+
+ (when single?
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-cells.area")
+ :on-click do-merge-cells}])
+
+ [:& menu-entry {:title (tr "workspace.context-menu.grid-cells.create-board")
+ :on-click do-create-board
+ :disabled (and (not single?) (not can-merge?))}]]))
+
+
(mf/defc context-menu
[]
(let [mdata (mf/deref menu-ref)
top (- (get-in mdata [:position :y]) 20)
left (get-in mdata [:position :x])
- dropdown-ref (mf/use-ref)
- new-css-system (mf/use-ctx ctx/new-css-system)]
+ dropdown-ref (mf/use-ref)]
(mf/use-effect
(mf/deps mdata)
@@ -573,9 +631,7 @@
[:& dropdown {:show (boolean mdata)
:on-close #(st/emit! dw/hide-context-menu)}
[:ul
- {:class (if new-css-system
- (dom/classnames (css :workspace-context-menu) true)
- (dom/classnames :workspace-context-menu true))
+ {:class (stl/css :workspace-context-menu)
:ref dropdown-ref
:style {:top top :left left}
:on-context-menu prevent-default}
@@ -583,6 +639,8 @@
(case (:kind mdata)
:shape [:& shape-context-menu {:mdata mdata}]
:page [:& page-item-context-menu {:mdata mdata}]
+ :grid-track [:& grid-track-context-menu {:mdata mdata}]
+ :grid-cells [:& grid-cells-context-menu {:mdata mdata}]
[:& viewport-context-menu {:mdata mdata}])]]))
diff --git a/frontend/src/app/main/ui/workspace/context_menu.scss b/frontend/src/app/main/ui/workspace/context_menu.scss
index 94f73018ef..4a178c88f8 100644
--- a/frontend/src/app/main/ui/workspace/context_menu.scss
+++ b/frontend/src/app/main/ui/workspace/context_menu.scss
@@ -19,94 +19,102 @@
border-radius: $br-8;
background-color: var(--menu-background-color);
z-index: $z-index-3;
- .separator {
- height: $s-12;
- }
- .context-menu-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- height: $s-28;
- width: 100%;
- padding: $s-6;
- border-radius: $br-8;
- cursor: pointer;
+}
- .title {
+.separator {
+ height: $s-12;
+}
+
+.context-menu-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: $s-28;
+ width: 100%;
+ padding: $s-6;
+ border-radius: $br-8;
+ cursor: pointer;
+
+ .title {
+ @include titleTipography;
+ color: var(--menu-foreground-color);
+ }
+ .shortcut {
+ @include flexCenter;
+ gap: $s-2;
+ color: var(--menu-shortcut-foreground-color);
+ .shortcut-key {
@include titleTipography;
- color: var(--menu-foreground-color);
+ @include flexCenter;
+ height: $s-20;
+ padding: $s-2 $s-6;
+ border-radius: $br-6;
+ background-color: var(--menu-shortcut-background-color);
+ }
+ }
+
+ .submenu-icon {
+ position: absolute;
+ right: $s-16;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--menu-foreground-color);
+ }
+ }
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ .title {
+ color: var(--menu-foreground-color-hover);
}
.shortcut {
- @include flexCenter;
- gap: $s-2;
- color: var(--menu-shortcut-foreground-color);
- .shortcut-key {
- @include titleTipography;
- @include flexCenter;
- height: $s-20;
- padding: $s-2 $s-6;
- border-radius: $br-6;
- background-color: var(--menu-shortcut-background-color);
- }
- }
-
- .submenu-icon {
- position: absolute;
- right: $s-16;
- svg {
- @extend .button-icon-small;
- stroke: var(--menu-foreground-color);
- }
- }
- &:hover {
- background-color: var(--menu-background-color-hover);
- .title {
- color: var(--menu-foreground-color-hover);
- }
- .shortcut {
- color: var(--menu-shortcut-foreground-color-hover);
- }
- }
- &:focus {
- border: 1px solid var(--menu-border-color-focus);
- background-color: var(--menu-background-color-focus);
+ color: var(--menu-shortcut-foreground-color-hover);
}
}
-
- .icon-menu-item {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- height: $s-28;
- padding: $s-6;
- border-radius: $br-8;
- &:hover {
- background-color: var(--menu-background-color-hover);
- }
-
- span.title {
- margin-left: $s-6;
- }
-
- .selected-icon {
- svg {
- @extend .button-icon-small;
- stroke: var(--menu-foreground-color);
- }
- }
-
- .shape-icon {
- margin-left: $s-2;
- svg {
- @extend .button-icon-small;
- stroke: var(--menu-foreground-color);
- }
- }
-
- .icon-wrapper {
- display: grid;
- grid-template-columns: 1fr 1fr;
- margin: 0;
- }
+ &:focus {
+ border: 1px solid var(--menu-border-color-focus);
+ background-color: var(--menu-background-color-focus);
}
}
+
+.icon-menu-item {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ height: $s-28;
+ padding: $s-6;
+ border-radius: $br-8;
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ }
+
+ span.title {
+ margin-left: $s-6;
+ }
+
+ .selected-icon {
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--menu-foreground-color);
+ }
+ }
+
+ .shape-icon {
+ margin-left: $s-2;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--menu-foreground-color);
+ }
+ }
+
+ .icon-wrapper {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ margin: 0;
+ }
+}
+
+.icon-menu-item[disabled],
+.context-menu-item[disabled] {
+ pointer-events: none;
+ opacity: 0.6;
+}
diff --git a/frontend/src/app/main/ui/workspace/left_header.scss b/frontend/src/app/main/ui/workspace/left_header.scss
index 7b34ccb0aa..d527a04e9c 100644
--- a/frontend/src/app/main/ui/workspace/left_header.scss
+++ b/frontend/src/app/main/ui/workspace/left_header.scss
@@ -19,7 +19,8 @@
height: $s-32;
margin-right: $s-4;
svg {
- height: $s-32;
+ min-height: $s-32;
+ width: $s-32;
fill: var(--icon-foreground-hover);
}
}
diff --git a/frontend/src/app/main/ui/workspace/libraries.scss b/frontend/src/app/main/ui/workspace/libraries.scss
index 6b7825bf6c..8ebf89b741 100644
--- a/frontend/src/app/main/ui/workspace/libraries.scss
+++ b/frontend/src/app/main/ui/workspace/libraries.scss
@@ -39,9 +39,11 @@
stroke: var(--icon-foreground);
}
}
+
.modal-title {
@include tabTitleTipography;
margin-bottom: $s-16;
+ color: var(--modal-title-foreground-color);
}
.modal-content {
@@ -161,6 +163,7 @@
.section-list-empty {
@include titleTipography;
@include flexCenter;
+ color: var(--empty-message-foreground-color);
svg {
@extend .button-icon-small;
diff --git a/frontend/src/app/main/ui/workspace/nudge.cljs b/frontend/src/app/main/ui/workspace/nudge.cljs
index 6e59f46188..868e294fdd 100644
--- a/frontend/src/app/main/ui/workspace/nudge.cljs
+++ b/frontend/src/app/main/ui/workspace/nudge.cljs
@@ -12,7 +12,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -32,8 +31,7 @@
{::mf/register modal/components
::mf/register-as :nudge-option}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- profile (mf/deref refs/profile)
+ (let [profile (mf/deref refs/profile)
nudge (or (get-in profile [:props :nudge]) {:big 10 :small 1})
update-big (mf/use-fn #(st/emit! (dw/update-nudge {:big %})))
update-small (mf/use-fn #(st/emit! (dw/update-nudge {:small %})))
@@ -43,45 +41,24 @@
(->> (events/listen js/document EventType.KEYDOWN on-keydown)
(partial events/unlistenByKey)))
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:div {:class (stl/css :input-wrapper)}
- [:label {:class (stl/css :modal-msg)
- :for "nudge-small"} (tr "modals.small-nudge")]
- [:> numeric-input* {:min 0.01
- :id "nudge-small"
- :value (:small nudge)
- :on-change update-small}]]
- [:div {:class (stl/css :input-wrapper)}
- [:label {:class (stl/css :modal-msg)
- :for "nudge-big"} (tr "modals.big-nudge")]
- [:> numeric-input* {:min 0.01
- :id "nudge-big"
- :value (:big nudge)
- :on-change update-big}]]]]]
-
-
- [:div.nudge-modal-overlay
- [:div.nudge-modal-container
- [:div.nudge-modal-header
- [:p.nudge-modal-title (tr "modals.nudge-title")]
- [:button.modal-close-button {:on-click on-close} i/close]]
- [:div.nudge-modal-body
- [:div.input-wrapper
- [:span
- [:p.nudge-subtitle (tr "modals.small-nudge")]
- [:> numeric-input* {:min 0.01
- :value (:small nudge)
- :on-change update-small}]]]
- [:div.input-wrapper
- [:span
- [:p.nudge-subtitle (tr "modals.big-nudge")]
- [:> numeric-input* {:min 0.01
- :value (:big nudge)
- :on-change update-big}]]]]]])))
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-close} i/close-refactor]]
+ [:div {:class (stl/css :modal-content)}
+ [:div {:class (stl/css :input-wrapper)}
+ [:label {:class (stl/css :modal-msg)
+ :for "nudge-small"} (tr "modals.small-nudge")]
+ [:> numeric-input* {:min 0.01
+ :id "nudge-small"
+ :value (:small nudge)
+ :on-change update-small}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:label {:class (stl/css :modal-msg)
+ :for "nudge-big"} (tr "modals.big-nudge")]
+ [:> numeric-input* {:min 0.01
+ :id "nudge-big"
+ :value (:big nudge)
+ :on-change update-big}]]]]]))
diff --git a/frontend/src/app/main/ui/workspace/nudge.scss b/frontend/src/app/main/ui/workspace/nudge.scss
index ff8f775a28..28d4985791 100644
--- a/frontend/src/app/main/ui/workspace/nudge.scss
+++ b/frontend/src/app/main/ui/workspace/nudge.scss
@@ -8,33 +8,37 @@
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- min-width: $s-408;
- border: $s-1 solid var(--modal-border-color);
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
+}
- .modal-content {
- @include flexColumn;
- gap: $s-24;
- @include titleTipography;
- margin-bottom: $s-24;
- .input-wrapper {
- @extend .input-with-label;
- label {
- text-transform: none;
- }
- }
- }
+.modal-container {
+ @extend .modal-container-base;
+ min-width: $s-408;
+ border: $s-1 solid var(--modal-border-color);
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include flexColumn;
+ gap: $s-24;
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+
+.input-wrapper {
+ @extend .input-with-label;
+ label {
+ text-transform: none;
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar.cljs b/frontend/src/app/main/ui/workspace/sidebar.cljs
index e0433a1762..ddda4cf013 100644
--- a/frontend/src/app/main/ui/workspace/sidebar.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar.cljs
@@ -12,10 +12,7 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
- [app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
- [app.main.ui.icons :as i]
[app.main.ui.workspace.comments :refer [comments-sidebar]]
[app.main.ui.workspace.left-header :refer [left-header]]
[app.main.ui.workspace.right-header :refer [right-header]]
@@ -26,7 +23,6 @@
[app.main.ui.workspace.sidebar.options :refer [options-toolbox]]
[app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]]
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
- [app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.object :as obj]
[rumext.v2 :as mf]))
@@ -47,7 +43,6 @@
(contains? layout :assets) :assets)
shortcuts? (contains? layout :shortcuts)
show-debug? (contains? layout :debug-panel)
- new-css-system (mf/use-ctx ctx/new-css-system)
{on-pointer-down :on-pointer-down on-lost-pointer-capture :on-lost-pointer-capture on-pointer-move :on-pointer-move parent-ref :parent-ref size :size}
(use-resize-hook :left-sidebar 275 275 500 :x false :left)
@@ -65,25 +60,17 @@
[:aside {:ref parent-ref
:id "left-sidebar-aside"
:data-size size
- :class (stl/css-case new-css-system
- :global/settings-bar (not new-css-system)
- :global/settings-bar-left (not new-css-system)
- :left-settings-bar true
+ :class (stl/css-case :left-settings-bar true
:global/two-row (<= size 300)
:global/three-row (and (> size 300) (<= size 400))
:global/four-row (> size 400))
:style #js {"--width" (dm/str size "px")}}
- (when new-css-system
- [:& left-header {:file file :layout layout :project project :page-id page-id}])
+ [:& left-header {:file file :layout layout :project project :page-id page-id}]
[:div {:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move
- :class (if ^boolean new-css-system
- (stl/css :resize-area)
- (dom/classnames :resize-area true))}]
- [:div {:class (if ^boolean new-css-system
- (stl/css :settings-bar-inside)
- (dom/classnames :settings-bar-inside true))}
+ :class (stl/css :resize-area)}]
+ [:div {:class (stl/css :settings-bar-inside)}
(cond
(true? shortcuts?)
[:& shortcuts-container]
@@ -92,64 +79,32 @@
[:& debug-panel]
:else
- (if ^boolean new-css-system
- [:div {:class (stl/css :tabs-wrapper)}
- [:& tab-container
- {:on-change-tab on-tab-change
- :selected section
- :shortcuts? shortcuts?
- :collapsable? true
- :handle-collapse handle-collapse
- :class (stl/css :tab-spacing)}
- [:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
- [:div {:class (stl/css :layers-tab)
- :style #js {"--height" (str size-pages "px")}}
- [:& sitemap {:layout layout
- :toggle-pages toggle-pages
- :show-pages? @show-pages?
- :size size-pages}]
- (when @show-pages?
- [:div {:class (stl/css :resize-area-horiz)
- :on-pointer-down on-pointer-down-pages
- :on-lost-pointer-capture on-lost-pointer-capture-pages
- :on-pointer-move on-pointer-move-pages}])
- [:& layers-toolbox {:size-parent size
- :size size-pages}]]]
+ [:div {:class (stl/css :tabs-wrapper)}
+ [:& tab-container
+ {:on-change-tab on-tab-change
+ :selected section
+ :shortcuts? shortcuts?
+ :collapsable? true
+ :handle-collapse handle-collapse
+ :class (stl/css :tab-spacing)}
+ [:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
+ [:div {:class (stl/css :layers-tab)
+ :style #js {"--height" (str size-pages "px")}}
+ [:& sitemap {:layout layout
+ :toggle-pages toggle-pages
+ :show-pages? @show-pages?
+ :size size-pages}]
+ (when @show-pages?
+ [:div {:class (stl/css :resize-area-horiz)
+ :on-pointer-down on-pointer-down-pages
+ :on-lost-pointer-capture on-lost-pointer-capture-pages
+ :on-pointer-move on-pointer-move-pages}])
+ [:& layers-toolbox {:size-parent size
+ :size size-pages}]]]
- (when-not ^boolean mode-inspect?
- [:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
- [:& assets-toolbox]])]]
-
- [:*
- [:button.collapse-sidebar
- {:on-click handle-collapse
- :aria-label (tr "workspace.sidebar.collapse")}
- i/arrow-slide]
-
- [:& tabs-container
- {:on-change-tab on-tab-change
- :selected section
- :shortcuts? shortcuts?
- :collapsable? true
- :handle-collapse handle-collapse}
-
- [:& tabs-element {:id :layers :title (tr "workspace.sidebar.layers")}
- [:div {:class :layers-tab
- :style #js {"--height" (str size-pages "px")}}
- [:& sitemap {:layout layout
- :toggle-pages toggle-pages
- :show-pages? @show-pages?
- :size size-pages}]
- (when @show-pages?
- [:div.resize-area-horiz
- {:on-pointer-down on-pointer-down-pages
- :on-lost-pointer-capture on-lost-pointer-capture-pages
- :on-pointer-move on-pointer-move-pages}])
- [:& layers-toolbox {:size-parent size}]]]
-
- (when-not ^boolean mode-inspect?
- [:& tabs-element {:id :assets :title (tr "workspace.toolbar.assets")}
- [:& assets-toolbox]])]]))]]))
+ (when-not ^boolean mode-inspect?
+ [:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
+ [:& assets-toolbox]])]])]]))
;; --- Right Sidebar (Component)
@@ -158,7 +113,6 @@
::mf/wrap [mf/memo]}
[{:keys [layout section file page-id ] :as props}]
(let [drawing-tool (:tool (mf/deref refs/workspace-drawing))
- new-css-system (mf/use-ctx ctx/new-css-system)
is-comments? (= drawing-tool :comments)
is-history? (contains? layout :document-history)
@@ -195,10 +149,7 @@
(obj/set! "on-change-section" handle-change-section)
(obj/set! "on-expand" handle-expand))]
- [:aside {:class (stl/css-case new-css-system
- :global/settings-bar (not new-css-system)
- :global/settings-bar-right (not new-css-system)
- :right-settings-bar true
+ [:aside {:class (stl/css-case :right-settings-bar true
:not-expand (not can-be-expanded?)
:expanded (> size 276))
@@ -206,14 +157,13 @@
:data-size size
:style #js {"--width" (when can-be-expanded? (dm/str size "px"))}}
(when can-be-expanded?
- [:div {:class (stl/css new-css-system :resize-area)
+ [:div {:class (stl/css :resize-area)
:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move}])
- (when new-css-system
- [:& right-header {:file file :layout layout :page-id page-id}])
+ [:& right-header {:file file :layout layout :page-id page-id}]
- [:div {:class (stl/css new-css-system :settings-bar-inside)}
+ [:div {:class (stl/css :settings-bar-inside)}
(cond
(true? is-comments?)
[:& comments-sidebar]
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs
index f82f6bb8d3..cb67bf83df 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs
@@ -19,7 +19,6 @@
[app.main.ui.workspace.sidebar.assets.file-library :refer [file-library]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
- [app.util.keyboard :as kbd]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@@ -71,7 +70,6 @@
[]
(let [components-v2 (mf/use-ctx ctx/components-v2)
read-only? (mf/use-ctx ctx/workspace-read-only?)
- new-css-system (mf/use-ctx ctx/new-css-system)
filters* (mf/use-state
{:term ""
:section "all"
@@ -104,17 +102,8 @@
on-search-term-change
(mf/use-fn
- (mf/deps new-css-system)
(fn [event]
- ;; NOTE: When old-css-system is removed this function will recibe value and event
- ;; Let won't be necessary any more
- (let [value (if ^boolean new-css-system
- event
- (dom/get-target-val event))]
- (swap! filters* assoc :term value))))
-
- on-search-clear-click
- (mf/use-fn #(swap! filters* assoc :term ""))
+ (swap! filters* assoc :term event)))
on-section-filter-change
(mf/use-fn
@@ -125,23 +114,12 @@
(dom/get-attribute $ "data-test")))]
(swap! filters* assoc :section value :open-menu false))))
- handle-key-down
- (mf/use-fn
- (fn [event]
- (let [enter? (kbd/enter? event)
- esc? (kbd/esc? event)
- node (dom/get-target event)]
-
- (when ^boolean enter? (dom/blur! node))
- (when ^boolean esc? (dom/blur! node)))))
-
show-libraries-dialog
(mf/use-fn
(fn []
(modal/show! :libraries-dialog {})
(modal/allow-click-outside!)))
-
on-open-menu
(mf/use-fn #(swap! filters* update :open-menu not))
@@ -175,86 +153,43 @@
:option-handler on-section-filter-change
:data-test "typographies"}]))]
- (if ^boolean new-css-system
- [:div {:class (stl/css :assets-bar)}
- [:div {:class (stl/css :assets-header)}
- (when-not ^boolean read-only?
- [:button {:class (stl/css :libraries-button)
- :on-click show-libraries-dialog}
- [:span {:class (stl/css :libraries-icon)}
- i/library-refactor]
- (tr "workspace.assets.libraries")])
+ [:div {:class (stl/css :assets-bar)}
+ [:div {:class (stl/css :assets-header)}
+ (when-not ^boolean read-only?
+ [:button {:class (stl/css :libraries-button)
+ :on-click show-libraries-dialog}
+ [:span {:class (stl/css :libraries-icon)}
+ i/library-refactor]
+ (tr "workspace.assets.libraries")])
- [:div {:class (stl/css :search-wrapper)}
- [:& search-bar {:on-change on-search-term-change
- :value term
- :placeholder (tr "workspace.assets.search")}
- [:button
- {:on-click on-open-menu
- :class (stl/css :section-button)}
- i/filter-refactor]]
- [:& context-menu-a11y
- {:on-close on-menu-close
- :selectable true
- :selected section
- :show menu-open?
- :fixed? true
- :min-width? true
- :top 152
- :left 64
- :options options
- :workspace? true}]
- [:button {:class (stl/css :sort-button)
- :on-click toggle-ordering}
- (if reverse-sort?
- i/asc-sort-refactor
- i/desc-sort-refactor)]]]
+ [:div {:class (stl/css :search-wrapper)}
+ [:& search-bar {:on-change on-search-term-change
+ :value term
+ :placeholder (tr "workspace.assets.search")}
+ [:button
+ {:on-click on-open-menu
+ :class (stl/css :section-button)}
+ i/filter-refactor]]
+ [:& context-menu-a11y
+ {:on-close on-menu-close
+ :selectable true
+ :selected section
+ :show menu-open?
+ :fixed? true
+ :min-width? true
+ :top 152
+ :left 64
+ :options options
+ :workspace? true}]
+ [:button {:class (stl/css :sort-button)
+ :on-click toggle-ordering}
+ (if reverse-sort?
+ i/asc-sort-refactor
+ i/desc-sort-refactor)]]]
- [:& (mf/provider cmm/assets-filters) {:value filters}
- [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering}
- [:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style}
- [:div {:class (stl/css :libraries-wrapper)}
- [:& assets-local-library {:filters filters}]
- [:& assets-libraries {:filters filters}]]]]]]
-
- [:div.assets-bar
- [:div.tool-window
- [:div.tool-window-content
- [:div.assets-bar-title
- (tr "workspace.assets.assets")
-
- (when-not ^boolean read-only?
- [:div.libraries-button {:on-click show-libraries-dialog}
- i/text-align-justify
- (tr "workspace.assets.libraries")])]
- [:div.search-block
- [:input.search-input
- {:placeholder (tr "workspace.assets.search")
- :type "text"
- :value term
- :on-change on-search-term-change
- :on-key-down handle-key-down}]
-
- (if ^boolean (str/empty? term)
- [:div.search-icon
- i/search]
- [:div.search-icon.close
- {:on-click on-search-clear-click}
- i/close])]
-
- [:select.input-select {:value (:section filters)
- :data-mousetrap-dont-stop true
- :on-change on-section-filter-change}
- [:option {:value "all"} (tr "workspace.assets.box-filter-all")]
- [:option {:value "components"} (tr "workspace.assets.components")]
- (when-not components-v2
- [:option {:value "graphics"} (tr "workspace.assets.graphics")])
- [:option {:value "colors"} (tr "workspace.assets.colors")]
- [:option {:value "typographies"} (tr "workspace.assets.typography")]]]]
-
- [:& (mf/provider cmm/assets-filters) {:value filters}
- [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering}
- [:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style}
- [:div.libraries-wrapper
- [:& assets-local-library {:filters filters}]
- [:& assets-libraries {:filters filters}]]]]]])))
+ [:& (mf/provider cmm/assets-filters) {:value filters}
+ [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering}
+ [:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style}
+ [:div {:class (stl/css :libraries-wrapper)}
+ [:& assets-local-library {:filters filters}]
+ [:& assets-libraries {:filters filters}]]]]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.scss b/frontend/src/app/main/ui/workspace/sidebar/assets.scss
index 82f81a7ac5..dd8ebf217a 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets.scss
@@ -10,121 +10,129 @@
position: relative;
height: 100%;
overflow: hidden;
+}
- .libraries-button {
- @include tabTitleTipography;
- @extend .button-secondary;
- gap: $s-2;
- height: $s-32;
- width: 100%;
- border-radius: $s-8;
- margin-bottom: $s-4;
- .libraries-icon {
- @include flexCenter;
- width: $s-24;
- height: 100%;
- svg {
- @include flexCenter;
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- }
- &:hover {
- background-color: var(--button-secondary-background-color-hover);
- color: var(--button-secondary-foreground-color-hover);
- border: $s-1 solid var(--button-secondary-border-color-hover);
- svg {
- stroke: var(--button-secondary-foreground-color-hover);
- }
- }
- &:focus {
- background-color: var(--button-secondary-background-color-focus);
- color: var(--button-secondary-foreground-color-focus);
- border: $s-1 solid var(--button-secondary-border-color-focus);
- svg {
- stroke: var(--button-secondary-foreground-color-focus);
- }
- }
- }
- .section-button {
+.libraries-button {
+ @include tabTitleTipography;
+ @extend .button-secondary;
+ gap: $s-2;
+ height: $s-32;
+ width: 100%;
+ border-radius: $s-8;
+ margin-bottom: $s-4;
+ .libraries-icon {
@include flexCenter;
- @include buttonStyle;
- height: $s-32;
- width: $s-32;
- margin: 0;
- border: 1px solid var(--color-background-tertiary);
- border-radius: $br-8 $br-2 $br-2 $br-8;
- background-color: var(--color-background-tertiary);
+ width: $s-24;
+ height: 100%;
svg {
- height: $s-16;
- width: $s-16;
+ @include flexCenter;
+ @extend .button-icon;
stroke: var(--icon-foreground);
}
- &:focus {
- border: 1px solid var(--input-border-color-focus);
- outline: 0;
- background-color: var(--input-background-color-active);
- color: var(--input-foreground-color-active);
- svg {
- background-color: var(--input-background-color-active);
- }
- }
- &:hover {
- border: 1px solid var(--input-background-color-hover);
- background-color: var(--input-background-color-hover);
- svg {
- background-color: var(--input-background-color-hover);
- stroke: var(--button-foreground-hover);
- }
+ }
+ &:hover {
+ background-color: var(--button-secondary-background-color-hover);
+ color: var(--button-secondary-foreground-color-hover);
+ border: $s-1 solid var(--button-secondary-border-color-hover);
+ svg {
+ stroke: var(--button-secondary-foreground-color-hover);
}
}
- .sections-container {
- @include menuShadow;
- @include flexColumn;
- position: absolute;
- top: $s-84;
- left: $s-12;
- width: $s-192;
- padding: $s-4;
- border-radius: $br-8;
- background-color: var(--menu-background-color);
- z-index: $z-index-2;
- .section-item {
- @include titleTipography;
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- padding: $s-6;
- border-radius: $br-8;
- .section-btn {
- @include buttonStyle;
- }
- }
- }
- .libraries-wrapper {
- overflow-x: hidden;
- overflow-y: auto;
- scrollbar-gutter: stable;
- display: flex;
- flex-direction: column;
- padding-left: $s-8;
- height: calc(100vh - $s-180);
- }
- .assets-header {
- padding: $s-8 $s-12 $s-12 $s-12;
- .search-wrapper {
- display: flex;
- gap: $s-4;
- .sort-button {
- @extend .button-secondary;
- width: $s-32;
- border-radius: $br-8;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
+ &:focus {
+ background-color: var(--button-secondary-background-color-focus);
+ color: var(--button-secondary-foreground-color-focus);
+ border: $s-1 solid var(--button-secondary-border-color-focus);
+ svg {
+ stroke: var(--button-secondary-foreground-color-focus);
}
}
}
+
+.section-button {
+ @include flexCenter;
+ @include buttonStyle;
+ height: $s-32;
+ width: $s-32;
+ margin: 0;
+ border: 1px solid var(--color-background-tertiary);
+ border-radius: $br-8 $br-2 $br-2 $br-8;
+ background-color: var(--color-background-tertiary);
+ svg {
+ height: $s-16;
+ width: $s-16;
+ stroke: var(--icon-foreground);
+ }
+ &:focus {
+ border: 1px solid var(--input-border-color-focus);
+ outline: 0;
+ background-color: var(--input-background-color-active);
+ color: var(--input-foreground-color-active);
+ svg {
+ background-color: var(--input-background-color-active);
+ }
+ }
+ &:hover {
+ border: 1px solid var(--input-background-color-hover);
+ background-color: var(--input-background-color-hover);
+ svg {
+ background-color: var(--input-background-color-hover);
+ stroke: var(--button-foreground-hover);
+ }
+ }
+}
+
+.sections-container {
+ @include menuShadow;
+ @include flexColumn;
+ position: absolute;
+ top: $s-84;
+ left: $s-12;
+ width: $s-192;
+ padding: $s-4;
+ border-radius: $br-8;
+ background-color: var(--menu-background-color);
+ z-index: $z-index-2;
+}
+
+.section-item {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ padding: $s-6;
+ border-radius: $br-8;
+}
+
+.section-btn {
+ @include buttonStyle;
+}
+
+.libraries-wrapper {
+ overflow-x: hidden;
+ overflow-y: auto;
+ scrollbar-gutter: stable;
+ display: flex;
+ flex-direction: column;
+ padding-left: $s-8;
+ height: calc(100vh - $s-180);
+}
+
+.assets-header {
+ padding: $s-8 $s-12 $s-12 $s-12;
+}
+
+.search-wrapper {
+ display: flex;
+ gap: $s-4;
+}
+
+.sort-button {
+ @extend .button-secondary;
+ width: $s-32;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--icon-foreground);
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
index 9ea7a1f6c8..d819943033 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.assets.colors
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -18,7 +18,6 @@
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.components.color-bullet :as bc]
[app.main.ui.components.color-bullet-new :as cb]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
@@ -59,7 +58,6 @@
menu-state (mf/use-state cmm/initial-context-menu-state)
read-only? (mf/use-ctx ctx/workspace-read-only?)
- new-css-system (mf/use-ctx ctx/new-css-system)
default-name (cond
(:gradient color) (uc/gradient-type->string (dm/get-in color [:gradient :type]))
@@ -193,113 +191,67 @@
(dom/select-text! input)
nil)))
- (if ^boolean new-css-system
- [:div {:class (dom/classnames (css :asset-list-item) true
- (css :selected) (contains? selected (:id color))
- (css :editing) editing?)
- :style #js {"--bullet-size" "16px"}
- :on-context-menu on-context-menu
- :on-click (when-not editing? on-click)
- :ref item-ref
- :draggable (and (not read-only?) (not editing?))
- :on-drag-start on-color-drag-start
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
+ [:div {:class (stl/css-case :asset-list-item true
+ :selected (contains? selected (:id color))
+ :editing editing?)
+ :style #js {"--bullet-size" "16px"}
+ :on-context-menu on-context-menu
+ :on-click (when-not editing? on-click)
+ :ref item-ref
+ :draggable (and (not read-only?) (not editing?))
+ :on-drag-start on-color-drag-start
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
- [:div {:class (dom/classnames (css :bullet-block) true)}
- [:& cb/color-bullet {:color color
- :mini? true}]]
+ [:div {:class (stl/css :bullet-block)}
+ [:& cb/color-bullet {:color color
+ :mini? true}]]
- (if ^boolean editing?
- [:input
- {:type "text"
- :class (dom/classnames (css :element-name) true)
- :ref input-ref
- :on-blur input-blur
- :on-key-down input-key-down
- :auto-focus true
- :default-value (cfh/merge-path-item (:path color) (:name color))}]
+ (if ^boolean editing?
+ [:input
+ {:type "text"
+ :class (stl/css :element-name)
+ :ref input-ref
+ :on-blur input-blur
+ :on-key-down input-key-down
+ :auto-focus true
+ :default-value (cfh/merge-path-item (:path color) (:name color))}]
- [:div {:title (:name color)
- :class (dom/classnames (css :name-block) true)
- :on-double-click rename-color-clicked}
+ [:div {:title (:name color)
+ :class (stl/css :name-block)
+ :on-double-click rename-color-clicked}
- (if (= (:name color) default-name)
- [:span {:class (dom/classnames (css :default-name-only) true)} default-name]
- [:*
- [:span {:class (dom/classnames (css :name) true)} (:name color)]
- [:span {:class (dom/classnames (css :default-name) true)} default-name]])])
+ (if (= (:name color) default-name)
+ [:span {:class (stl/css :default-name-only)} default-name]
+ [:*
+ [:span {:class (stl/css :name)} (:name color)]
+ [:span {:class (stl/css :default-name)} default-name]])])
- (when local?
- [:& cmm/assets-context-menu
- {:on-close on-close-menu
- :state @menu-state
- :options [(when-not (or multi-colors? multi-assets?)
- {:option-name (tr "workspace.assets.rename")
- :id "assets-rename-color"
- :option-handler rename-color-clicked})
- (when-not (or multi-colors? multi-assets?)
- {:option-name (tr "workspace.assets.edit")
- :id "assets-edit-color"
- :option-handler edit-color-clicked})
+ (when local?
+ [:& cmm/assets-context-menu
+ {:on-close on-close-menu
+ :state @menu-state
+ :options [(when-not (or multi-colors? multi-assets?)
+ {:option-name (tr "workspace.assets.rename")
+ :id "assets-rename-color"
+ :option-handler rename-color-clicked})
+ (when-not (or multi-colors? multi-assets?)
+ {:option-name (tr "workspace.assets.edit")
+ :id "assets-edit-color"
+ :option-handler edit-color-clicked})
- {:option-name (tr "workspace.assets.delete")
- :id "assets-delete-color"
- :option-handler delete-color}
- (when-not multi-assets?
- {:option-name (tr "workspace.assets.group")
- :id "assets-group-color"
- :option-handler (on-group (:id color))})]}])
+ {:option-name (tr "workspace.assets.delete")
+ :id "assets-delete-color"
+ :option-handler delete-color}
+ (when-not multi-assets?
+ {:option-name (tr "workspace.assets.group")
+ :id "assets-group-color"
+ :option-handler (on-group (:id color))})]}])
- (when ^boolean dragging?
- [:div {:class (dom/classnames (css :dragging) true)}])]
-
- [:div.asset-list-item
- {:class-name (dom/classnames
- :selected (contains? selected (:id color)))
- :on-context-menu on-context-menu
- :on-click (when-not editing? on-click)
- :ref item-ref
- :draggable (and (not read-only?) (not editing?))
- :on-drag-start on-color-drag-start
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
-
- [:& bc/color-bullet {:color color}]
-
- (if ^boolean editing?
- [:input.element-name
- {:type "text"
- :ref input-ref
- :on-blur input-blur
- :on-key-down input-key-down
- :auto-focus true
- :default-value (cfh/merge-path-item (:path color) (:name color))}]
-
- [:div.name-block {:title (:name color)
- :on-double-click rename-color-clicked}
- (:name color)
- (when-not (= (:name color) default-name)
- [:span default-name])])
-
- (when local?
- [:& cmm/assets-context-menu
- {:on-close on-close-menu
- :state @menu-state
- :options [(when-not (or multi-colors? multi-assets?)
- [(tr "workspace.assets.rename") rename-color-clicked])
- (when-not (or multi-colors? multi-assets?)
- [(tr "workspace.assets.edit") edit-color-clicked])
- [(tr "workspace.assets.delete") delete-color]
- (when-not multi-assets?
- [(tr "workspace.assets.group") (on-group (:id color))])]}])
-
- (when ^boolean dragging?
- [:div.dragging])])))
+ (when ^boolean dragging?
+ [:div {:class (stl/css :dragging)}])]))
(mf/defc colors-group
[{:keys [file-id prefix groups open-groups force-open? local? selected
@@ -308,7 +260,6 @@
selected-full]}]
(let [group-open? (or ^boolean force-open?
^boolean (get open-groups prefix (if (= prefix "") true false)))
- new-css-system (mf/use-ctx ctx/new-css-system)
dragging* (mf/use-state false)
dragging? (deref dragging*)
@@ -338,136 +289,71 @@
(fn [event]
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full move-color)))]
- (if ^boolean new-css-system
- [:div {:class (dom/classnames (css :colors-group) true)
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- [:& grp/asset-group-title {:file-id file-id
- :section :colors
- :path prefix
- :group-open? group-open?
- :on-rename on-rename-group
- :on-ungroup on-ungroup}]
- (when group-open?
- [:*
- (let [colors (get groups "" [])]
- [:div {:class (dom/classnames (css :asset-list) true)
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
+ [:div {:class (stl/css :colors-group)
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
+ [:& grp/asset-group-title {:file-id file-id
+ :section :colors
+ :path prefix
+ :group-open? group-open?
+ :on-rename on-rename-group
+ :on-ungroup on-ungroup}]
+ (when group-open?
+ [:*
+ (let [colors (get groups "" [])]
+ [:div {:class (stl/css :asset-list)
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
- (when ^boolean dragging?
- [:div {:class (dom/classnames (css :grid-placeholder) true)}
- "\u00A0"])
+ (when ^boolean dragging?
+ [:div {:class (stl/css :grid-placeholder)}
+ "\u00A0"])
- (when (and (empty? colors)
- (some? groups))
- [:div {:class (dom/classnames (css :drop-space) true)}])
+ (when (and (empty? colors)
+ (some? groups))
+ [:div {:class (stl/css :drop-space)}])
- (for [color colors]
- [:& color-item {:key (dm/str (:id color))
- :color color
- :file-id file-id
- :local? local?
- :selected selected
- :multi-colors? multi-colors?
- :multi-assets? multi-assets?
- :on-asset-click on-asset-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection
- :on-group on-group
- :colors colors
- :selected-full selected-full
- :selected-paths selected-paths
- :move-color move-color}])])
+ (for [color colors]
+ [:& color-item {:key (dm/str (:id color))
+ :color color
+ :file-id file-id
+ :local? local?
+ :selected selected
+ :multi-colors? multi-colors?
+ :multi-assets? multi-assets?
+ :on-asset-click on-asset-click
+ :on-assets-delete on-assets-delete
+ :on-clear-selection on-clear-selection
+ :on-group on-group
+ :colors colors
+ :selected-full selected-full
+ :selected-paths selected-paths
+ :move-color move-color}])])
- (for [[path-item content] groups]
- (when-not (empty? path-item)
- [:& colors-group {:file-id file-id
- :prefix (cfh/merge-path-item prefix path-item)
- :key (dm/str "group-" path-item)
- :groups content
- :open-groups open-groups
- :force-open? force-open?
- :local? local?
- :selected selected
- :multi-colors? multi-colors?
- :multi-assets? multi-assets?
- :on-asset-click on-asset-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection
- :on-group on-group
- :on-rename-group on-rename-group
- :on-ungroup on-ungroup
- :colors colors
- :selected-full selected-full}]))])]
-
-
- [:div {:on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- [:& grp/asset-group-title {:file-id file-id
- :section :colors
- :path prefix
- :group-open? group-open?
- :on-rename on-rename-group
- :on-ungroup on-ungroup}]
- (when group-open?
- [:*
- (let [colors (get groups "" [])]
- [:div.asset-list {:on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
-
- (when ^boolean dragging?
- [:div.grid-placeholder "\u00A0"])
-
- (when (and (empty? colors)
- (some? groups))
- [:div.drop-space])
-
- (for [color colors]
- [:& color-item {:key (dm/str (:id color))
- :color color
- :file-id file-id
- :local? local?
- :selected selected
- :multi-colors? multi-colors?
- :multi-assets? multi-assets?
- :on-asset-click on-asset-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection
- :on-group on-group
- :colors colors
- :selected-full selected-full
- :selected-paths selected-paths
- :move-color move-color}])])
-
- (for [[path-item content] groups]
- (when-not (empty? path-item)
- [:& colors-group {:file-id file-id
- :prefix (cfh/merge-path-item prefix path-item)
- :key (dm/str "group-" path-item)
- :groups content
- :open-groups open-groups
- :force-open? force-open?
- :local? local?
- :selected selected
- :multi-colors? multi-colors?
- :multi-assets? multi-assets?
- :on-asset-click on-asset-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection
- :on-group on-group
- :on-rename-group on-rename-group
- :on-ungroup on-ungroup
- :colors colors
- :selected-full selected-full}]))])])))
+ (for [[path-item content] groups]
+ (when-not (empty? path-item)
+ [:& colors-group {:file-id file-id
+ :prefix (cfh/merge-path-item prefix path-item)
+ :key (dm/str "group-" path-item)
+ :groups content
+ :open-groups open-groups
+ :force-open? force-open?
+ :local? local?
+ :selected selected
+ :multi-colors? multi-colors?
+ :multi-assets? multi-assets?
+ :on-asset-click on-asset-click
+ :on-assets-delete on-assets-delete
+ :on-clear-selection on-clear-selection
+ :on-group on-group
+ :on-rename-group on-rename-group
+ :on-ungroup on-ungroup
+ :colors colors
+ :selected-full selected-full}]))])]))
(mf/defc colors-section
[{:keys [file-id local? colors open? force-open? open-status-ref selected reverse-sort?
@@ -491,7 +377,6 @@
(grp/group-assets colors reverse-sort?))
read-only? (mf/use-ctx ctx/workspace-read-only?)
- new-css-system (mf/use-ctx ctx/new-css-system)
add-color
(mf/use-fn
(fn [value _]
@@ -589,19 +474,12 @@
:section :colors
:assets-count (count colors)
:open? open?}
- (if ^boolean new-css-system
- (when local?
- [:& cmm/asset-section-block {:role :title-button}
- (when-not read-only?
- [:button {:class (dom/classnames (css :assets-btn) true)
- :on-click add-color-clicked}
- i/add-refactor])])
-
- (when local?
- [:& cmm/asset-section-block {:role :title-button}
- (when-not read-only?
- [:div.assets-button {:on-click add-color-clicked}
- i/plus])]))
+ (when local?
+ [:& cmm/asset-section-block {:role :title-button}
+ (when-not read-only?
+ [:button {:class (stl/css :assets-btn)
+ :on-click add-color-clicked}
+ i/add-refactor])])
[:& cmm/asset-section-block {:role :content}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.scss
index aed7ab1197..28dced5b49 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.scss
@@ -9,7 +9,7 @@
.assets-btn {
@extend .button-tertiary;
height: $s-32;
- width: calc($s-24 + $s-4);
+ width: $s-28;
padding: 0;
border-radius: $br-8;
svg {
@@ -20,83 +20,92 @@
.colors-group {
margin-top: $s-4;
- .asset-list {
- padding: 0 0 0 $s-4;
- .asset-list-item {
- position: relative;
- display: flex;
- align-items: center;
- height: $s-32;
- padding: $s-8;
- margin-bottom: $s-4;
- border-radius: $br-8;
- background-color: var(--assets-item-background-color);
- cursor: pointer;
- .bullet-block {
- @include flexCenter;
- height: 100%;
- justify-content: flex-start;
- margin-right: $s-4;
- }
- .name-block {
- @include titleTipography;
- display: grid;
- grid-template-columns: auto 1fr;
- margin: 0;
- overflow: hidden;
- .default-name-only,
- .name {
- color: var(--assets-item-name-foreground-color-hover);
- margin-right: $s-6;
- @include textEllipsis;
- }
- .default-name {
- min-width: 0;
- color: var(--assets-item-name-foreground-color);
- }
- }
- .element-name {
- @include textEllipsis;
- color: var(--color-foreground-primary);
- }
- &.selected {
- border: $s-1 solid var(--assets-item-border-color);
- }
+}
- &.editing {
- border: $s-1 solid var(--input-border-color-focus);
- input.element-name {
- @include textEllipsis;
- @include titleTipography;
- @include removeInputStyle;
- flex-grow: 1;
- height: $s-28;
- max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
- margin: 0;
- color: var(--layer-row-foreground-color);
- }
- }
- &:hover {
- background-color: var(--assets-item-background-color-hover);
- }
+.asset-list {
+ padding: 0 0 0 $s-4;
+}
+
+.asset-list-item {
+ position: relative;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ padding: $s-8;
+ margin-bottom: $s-4;
+ border-radius: $br-8;
+ background-color: var(--assets-item-background-color);
+ cursor: pointer;
+
+ &.selected {
+ border: $s-1 solid var(--assets-item-border-color);
+ }
+
+ &.editing {
+ border: $s-1 solid var(--input-border-color-focus);
+ input.element-name {
+ @include textEllipsis;
+ @include titleTipography;
+ @include removeInputStyle;
+ flex-grow: 1;
+ height: $s-28;
+ max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
+ margin: 0;
+ color: var(--layer-row-foreground-color);
}
}
- .grid-placeholder {
- height: $s-2;
- margin-bottom: $s-2;
- background-color: var(--color-accent-primary);
- }
- .drop-space {
- height: $s-12;
- }
- .dragging {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- border-radius: $s-8;
- background-color: var(--assets-item-background-color-drag);
- border: $s-2 solid var(--assets-item-border-color-drag);
+ &:hover {
+ background-color: var(--assets-item-background-color-hover);
}
}
+
+.bullet-block {
+ @include flexCenter;
+ height: 100%;
+ justify-content: flex-start;
+ margin-right: $s-4;
+}
+
+.name-block {
+ @include titleTipography;
+ display: grid;
+ grid-template-columns: auto 1fr;
+ margin: 0;
+ overflow: hidden;
+ .default-name-only,
+ .name {
+ color: var(--assets-item-name-foreground-color-hover);
+ margin-right: $s-6;
+ @include textEllipsis;
+ }
+ .default-name {
+ min-width: 0;
+ color: var(--assets-item-name-foreground-color);
+ }
+}
+
+.element-name {
+ @include textEllipsis;
+ color: var(--color-foreground-primary);
+}
+
+.grid-placeholder {
+ height: $s-2;
+ margin-bottom: $s-2;
+ background-color: var(--color-accent-primary);
+}
+
+.drop-space {
+ height: $s-12;
+}
+
+.dragging {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border-radius: $s-8;
+ background-color: var(--assets-item-background-color-drag);
+ border: $s-2 solid var(--assets-item-border-color-drag);
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
index 141a83a68f..c6d63c7d3e 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
@@ -6,7 +6,7 @@
(ns app.main.ui.workspace.sidebar.assets.common
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
@@ -22,7 +22,6 @@
[app.main.refs :as refs]
[app.main.render :refer [component-svg component-svg-thumbnail]]
[app.main.store :as st]
- [app.main.ui.components.context-menu :refer [context-menu]]
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
[app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
@@ -111,24 +110,14 @@
(mf/defc assets-context-menu
{::mf/wrap-props false}
[{:keys [options state on-close]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& context-menu-a11y
- {:show (:open? state)
- :fixed? (or (not= (:top state) 0) (not= (:left state) 0))
- :on-close on-close
- :top (:top state)
- :left (:left state)
- :options options
- :workspace? true}]
-
- [:& context-menu
- {:selectable false
- :show (:open? state)
- :on-close on-close
- :top (:top state)
- :left (:left state)
- :options options}])))
+ [:& context-menu-a11y
+ {:show (:open? state)
+ :fixed? (or (not= (:top state) 0) (not= (:left state) 0))
+ :on-close on-close
+ :top (:top state)
+ :left (:left state)
+ :options options
+ :workspace? true}])
(mf/defc section-icon
[{:keys [section] :as props}]
@@ -145,34 +134,24 @@
(filter some?))
get-role #(.. % -props -role)
title-buttons (filter #(= (get-role %) :title-button) children)
- content (filter #(= (get-role %) :content) children)
- new-css-system (mf/use-ctx ctx/new-css-system)]
- (if ^boolean new-css-system
- [:div {:class (dom/classnames (css :asset-section) true)}
- [:& title-bar {:collapsable? true
- :collapsed? (not open?)
- :clickable-all? true
- :on-collapsed #(st/emit! (dw/set-assets-section-open file-id section (not open?)))
- :class (css :title-spacing)
- :title (mf/html [:span {:class (dom/classnames (css :title-name) true)}
- [:span {:class (dom/classnames (css :section-icon) true)}
- [:& section-icon {:section section}]]
- [:span {:class (dom/classnames (css :section-name) true)}
- title]
+ content (filter #(= (get-role %) :content) children)]
+ [:div {:class (stl/css :asset-section)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :clickable-all? true
+ :on-collapsed #(st/emit! (dw/set-assets-section-open file-id section (not open?)))
+ :class (stl/css :title-spacing)
+ :title (mf/html [:span {:class (stl/css :title-name)}
+ [:span {:class (stl/css :section-icon)}
+ [:& section-icon {:section section}]]
+ [:span {:class (stl/css :section-name)}
+ title]
- [:span {:class (dom/classnames (css :num-assets) true)}
- assets-count]])}
- title-buttons]
- (when ^boolean open?
- content)]
- [:div.asset-section
- [:div.asset-title {:class (when (not ^boolean open?) "closed")}
- [:span {:on-click #(st/emit! (dw/set-assets-section-open file-id section (not open?)))}
- i/arrow-slide title]
- [:span.num-assets (dm/str "\u00A0(") assets-count ")"] ;; Unicode 00A0 is non-breaking space
- title-buttons]
- (when ^boolean open?
- content)])))
+ [:span {:class (stl/css :num-assets)}
+ assets-count]])}
+ title-buttons]
+ (when ^boolean open?
+ content)]))
(mf/defc asset-section-block
[{:keys [children]}]
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss
index 21da5c603c..a546e71a7d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss
@@ -6,36 +6,38 @@
@import "refactor/common-refactor.scss";
-.asset-section {
- .title-name {
- @include tabTitleTipography;
- display: flex;
- align-items: center;
- flex-grow: 1;
- width: 100%;
- .section-icon {
- @include flexCenter;
- padding-right: $s-2;
- svg {
- @include flexCenter;
- height: $s-16;
- width: $s-16;
- color: transparent;
- fill: none;
- }
- }
- .section-name {
- display: flex;
- align-items: center;
- margin: 0 $s-2;
- }
- .num-assets {
- @include flexCenter;
- height: 100%;
- padding-left: $s-8;
- }
+.title-name {
+ @include tabTitleTipography;
+ display: flex;
+ align-items: center;
+ flex-grow: 1;
+ width: 100%;
+}
+
+.section-icon {
+ @include flexCenter;
+ padding-right: $s-2;
+ svg {
+ @include flexCenter;
+ height: $s-16;
+ width: $s-16;
+ color: transparent;
+ fill: none;
}
}
+
+.section-name {
+ display: flex;
+ align-items: center;
+ margin: 0 $s-2;
+}
+
+.num-assets {
+ @include flexCenter;
+ height: 100%;
+ padding-left: $s-8;
+}
+
.title-spacing {
margin-bottom: $s-4;
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
index 964b403802..833c573f7a 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.assets.components
- (:require-macros [app.main.style :as stl :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -77,7 +77,6 @@
read-only? (mf/use-ctx ctx/workspace-read-only?)
components-v2 (mf/use-ctx ctx/components-v2)
- new-css-system (mf/use-ctx ctx/new-css-system)
component-id (:id component)
visible? (h/use-visible item-ref :once? true)
@@ -144,89 +143,45 @@
(mf/deps on-context-menu component-id)
(partial on-context-menu component-id))]
- (if ^boolean new-css-system
- [:div {:ref item-ref
- :class (dom/classnames
- (css :selected) (contains? selected (:id component))
- (css :grid-cell) listing-thumbs?
- (css :enum-item) (not listing-thumbs?))
- :id (dm/str "component-shape-id-" (:id component))
- :draggable (not read-only?)
- :on-click on-component-click
- :on-double-click on-component-double-click
- :on-context-menu on-context-menu
- :on-drag-start on-component-drag-start
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- (when (and (some? root-shape)
- (some? container))
- [:*
+ [:div {:ref item-ref
+ :class (stl/css-case :selected (contains? selected (:id component))
+ :grid-cell listing-thumbs?
+ :enum-item (not listing-thumbs?))
+ :id (dm/str "component-shape-id-" (:id component))
+ :draggable (not read-only?)
+ :on-click on-component-click
+ :on-double-click on-component-double-click
+ :on-context-menu on-context-menu
+ :on-drag-start on-component-drag-start
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
+ (when (and (some? root-shape)
+ (some? container))
+ [:*
+ (let [renaming? (= renaming (:id component))]
+ [:*
+ [:& editable-label
+ {:class (stl/css-case :cell-name listing-thumbs?
+ :item-name (not listing-thumbs?)
+ :editing renaming?)
+ :value (cfh/merge-path-item (:path component) (:name component))
+ :tooltip (cfh/merge-path-item (:path component) (:name component))
+ :display-value (:name component)
+ :editing renaming?
+ :disable-dbl-click true
+ :on-change do-rename
+ :on-cancel cancel-rename}]
- (let [renaming? (= renaming (:id component))]
- [:*
- [:& editable-label
- {:class (dom/classnames
- (css :cell-name) listing-thumbs?
- (css :item-name) (not listing-thumbs?)
- (css :editing) renaming?)
- :value (cfh/merge-path-item (:path component) (:name component))
- :tooltip (cfh/merge-path-item (:path component) (:name component))
- :display-value (:name component)
- :editing renaming?
- :disable-dbl-click true
- :on-change do-rename
- :on-cancel cancel-rename}]
+ (when ^boolean dragging?
+ [:div {:class (stl/css :dragging)}])])
- (when ^boolean dragging?
- [:div {:class (dom/classnames (css :dragging) true)}])])
+ (when visible?
[:& cmm/component-item-thumbnail {:file-id file-id
:root-shape root-shape
:component component
- :container container}]])]
-
- [:div {:ref item-ref
- :class (dom/classnames
- :selected (contains? selected (:id component))
- :grid-cell listing-thumbs?
- :enum-item (not listing-thumbs?))
- :id (dm/str "component-shape-id-" (:id component))
- :draggable (not read-only?)
- :on-click on-component-click
- :on-double-click on-component-double-click
- :on-context-menu on-context-menu
- :on-drag-start on-component-drag-start
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
-
- (when (and (some? root-shape)
- (some? container))
- [:*
- (when visible?
- [:& cmm/component-item-thumbnail {:file-id file-id
- :root-shape root-shape
- :component component
- :container container}])
- (let [renaming? (= renaming (:id component))]
- [:*
- [:& editable-label
- {:class (dom/classnames
- :cell-name listing-thumbs?
- :item-name (not listing-thumbs?)
- :editing renaming?)
- :value (cfh/merge-path-item (:path component) (:name component))
- :tooltip (cfh/merge-path-item (:path component) (:name component))
- :display-value (:name component)
- :editing renaming?
- :disable-dbl-click true
- :on-change do-rename
- :on-cancel cancel-rename}]
-
- (when ^boolean dragging?
- [:div.dragging])])])])))
+ :container container}])])]))
(mf/defc components-group
{::mf/wrap-props false}
@@ -236,7 +191,6 @@
(let [group-open? (or ^boolean force-open?
^boolean (get open-groups prefix (if (= prefix "") true false)))
- new-css-system (mf/use-ctx ctx/new-css-system)
dragging* (mf/use-state false)
dragging? (deref dragging*)
@@ -266,162 +220,82 @@
(when (and local (:local? @drag-data*))
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-component-and-main-instance))))]
- (if ^boolean new-css-system
- [:div {:class (dom/classnames (css :component-group) true)
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- [:& grp/asset-group-title
- {:file-id file-id
- :section :components
- :path prefix
- :group-open? group-open?
- :on-rename on-rename-group
- :on-ungroup on-ungroup}]
+ [:div {:class (stl/css :component-group)
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
+ [:& grp/asset-group-title
+ {:file-id file-id
+ :section :components
+ :path prefix
+ :group-open? group-open?
+ :on-rename on-rename-group
+ :on-ungroup on-ungroup}]
- (when group-open?
- [:*
- (let [components (get groups "" [])]
- [:div {:class-name (dom/classnames
- (css :asset-grid) listing-thumbs?
- (css :asset-enum) (not listing-thumbs?)
- (css :drop-space) (and
- (empty? components)
- (some? groups)
- (not dragging?)
- local))
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
+ (when group-open?
+ [:*
+ (let [components (get groups "" [])]
+ [:div {:class-name (stl/css-case :asset-grid listing-thumbs?
+ :asset-enum (not listing-thumbs?)
+ :drop-space (and
+ (empty? components)
+ (some? groups)
+ (not dragging?)
+ local))
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
- (when ^boolean dragging?
- [:div {:class (dom/classnames (css :grid-placeholder) true)} "\u00A0"])
+ (when ^boolean dragging?
+ [:div {:class (stl/css :grid-placeholder)} "\u00A0"])
- (when (and (empty? components)
- (some? groups)
- local)
- [:div {:class (dom/classnames (css :drop-space) true)}])
+ (when (and (empty? components)
+ (some? groups)
+ local)
+ [:div {:class (stl/css :drop-space)}])
- (for [component components]
- [:& components-item
- {:component component
- :key (dm/str "component-" (:id component))
- :renaming renaming
- :listing-thumbs? listing-thumbs?
- :file-id file-id
- :selected selected
- :selected-full selected-full
- :selected-paths selected-paths
- :on-asset-click on-asset-click
- :on-context-menu on-context-menu
- :on-drag-start on-drag-start
- :on-group on-group
- :do-rename do-rename
- :cancel-rename cancel-rename
- :local local}])])
+ (for [component components]
+ [:& components-item
+ {:component component
+ :key (dm/str "component-" (:id component))
+ :renaming renaming
+ :listing-thumbs? listing-thumbs?
+ :file-id file-id
+ :selected selected
+ :selected-full selected-full
+ :selected-paths selected-paths
+ :on-asset-click on-asset-click
+ :on-context-menu on-context-menu
+ :on-drag-start on-drag-start
+ :on-group on-group
+ :do-rename do-rename
+ :cancel-rename cancel-rename
+ :local local}])])
- (for [[path-item content] groups]
- (when-not (empty? path-item)
- [:& components-group {:file-id file-id
- :key path-item
- :prefix (cfh/merge-path-item prefix path-item)
- :groups content
- :open-groups open-groups
- :force-open? force-open?
- :renaming renaming
- :listing-thumbs? listing-thumbs?
- :selected selected
- :on-asset-click on-asset-click
- :on-drag-start on-drag-start
- :do-rename do-rename
- :cancel-rename cancel-rename
- :on-rename-group on-rename-group
- :on-ungroup on-ungroup
- :on-context-menu on-context-menu
- :selected-full selected-full
- :local local}]))])]
-
-
- [:div {:on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
-
- [:& grp/asset-group-title
- {:file-id file-id
- :section :components
- :path prefix
- :group-open? group-open?
- :on-rename on-rename-group
- :on-ungroup on-ungroup}]
-
- (when group-open?
- [:*
- (let [components (get groups "" [])]
- [:div {:class-name (dom/classnames
- :asset-grid listing-thumbs?
- :big listing-thumbs?
- :asset-enum (not listing-thumbs?)
- :drop-space (and
- (empty? components)
- (some? groups)
- (not dragging?)
- local))
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
-
- (when ^boolean dragging?
- [:div.grid-placeholder "\u00A0"])
-
- (when (and (empty? components)
- (some? groups)
- local)
- [:div.drop-space])
-
- (for [component components]
- [:& components-item
- {:component component
- :key (dm/str "component-" (:id component))
- :renaming renaming
- :listing-thumbs? listing-thumbs?
- :file-id file-id
- :selected selected
- :selected-full selected-full
- :selected-paths selected-paths
- :on-asset-click on-asset-click
- :on-context-menu on-context-menu
- :on-drag-start on-drag-start
- :on-group on-group
- :do-rename do-rename
- :cancel-rename cancel-rename
- :local local}])])
-
- (for [[path-item content] groups]
- (when-not (empty? path-item)
- [:& components-group {:file-id file-id
- :key path-item
- :prefix (cfh/merge-path-item prefix path-item)
- :groups content
- :open-groups open-groups
- :force-open? force-open?
- :renaming renaming
- :listing-thumbs? listing-thumbs?
- :selected selected
- :on-asset-click on-asset-click
- :on-drag-start on-drag-start
- :do-rename do-rename
- :cancel-rename cancel-rename
- :on-rename-group on-rename-group
- :on-ungroup on-ungroup
- :on-context-menu on-context-menu
- :selected-full selected-full
- :local local}]))])])))
+ (for [[path-item content] groups]
+ (when-not (empty? path-item)
+ [:& components-group {:file-id file-id
+ :key path-item
+ :prefix (cfh/merge-path-item prefix path-item)
+ :groups content
+ :open-groups open-groups
+ :force-open? force-open?
+ :renaming renaming
+ :listing-thumbs? listing-thumbs?
+ :selected selected
+ :on-asset-click on-asset-click
+ :on-drag-start on-drag-start
+ :do-rename do-rename
+ :cancel-rename cancel-rename
+ :on-rename-group on-rename-group
+ :on-ungroup on-ungroup
+ :on-context-menu on-context-menu
+ :selected-full selected-full
+ :local local}]))])]))
(mf/defc components-section
{::mf/wrap-props false}
@@ -446,7 +320,6 @@
menu-state (mf/use-state cmm/initial-context-menu-state)
read-only? (mf/use-ctx ctx/workspace-read-only?)
components-v2 (mf/use-ctx ctx/components-v2)
- new-css-system (mf/use-ctx ctx/new-css-system)
toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
selected (:components selected)
@@ -623,38 +496,28 @@
:section :components
:assets-count (count components)
:open? open?}
- (if ^boolean new-css-system
- [:& cmm/asset-section-block {:role :title-button}
- [:*
- (when open?
- [:div {:class (stl/css :listing-options)}
- [:& radio-buttons {:selected (if listing-thumbs? "grid" "list")
- :on-change toggle-list-style
- :name "listing-style"}
- [:& radio-button {:icon i/view-as-list-refactor
- :value "list"
- :id "opt-list"}]
- [:& radio-button {:icon i/flex-grid-refactor
- :value "grid"
- :id "opt-grid"}]]])
+ [:& cmm/asset-section-block {:role :title-button}
+ [:*
+ (when open?
+ [:div {:class (stl/css :listing-options)}
+ [:& radio-buttons {:selected (if listing-thumbs? "grid" "list")
+ :on-change toggle-list-style
+ :name "listing-style"}
+ [:& radio-button {:icon i/view-as-list-refactor
+ :value "list"
+ :id "opt-list"}]
+ [:& radio-button {:icon i/flex-grid-refactor
+ :value "grid"
+ :id "opt-grid"}]]])
- (when (and components-v2 (not read-only?) local?)
- [:div {:on-click add-component
- :class (dom/classnames (css :add-component) true)}
- i/add-refactor
- [:& file-uploader {:accept cm/str-image-types
- :multi true
- :ref input-ref
- :on-selected on-file-selected}]])]]
- (when local?
- [:& cmm/asset-section-block {:role :title-button}
- (when (and components-v2 (not read-only?))
- [:div.assets-button {:on-click add-component}
- i/plus
- [:& file-uploader {:accept cm/str-image-types
- :multi true
- :ref input-ref
- :on-selected on-file-selected}]])]))
+ (when (and components-v2 (not read-only?) local?)
+ [:div {:on-click add-component
+ :class (stl/css :add-component)}
+ i/add-refactor
+ [:& file-uploader {:accept cm/str-image-types
+ :multi true
+ :ref input-ref
+ :on-selected on-file-selected}]])]]
[:& cmm/asset-section-block {:role :content}
(when ^boolean open?
@@ -680,42 +543,28 @@
[:& cmm/assets-context-menu
{:on-close on-close-menu
:state @menu-state
- :options (if new-css-system
- [(when (and local? (not (or multi-components? multi-assets? read-only?)))
- {:option-name (tr "workspace.assets.rename")
- :id "assets-rename-component"
- :option-handler on-rename})
- (when (and local? (not (or multi-assets? read-only?)))
- {:option-name (if components-v2
- (tr "workspace.assets.duplicate-main")
- (tr "workspace.assets.duplicate"))
- :id "assets-duplicate-component"
- :option-handler on-duplicate})
+ :options [(when (and local? (not (or multi-components? multi-assets? read-only?)))
+ {:option-name (tr "workspace.assets.rename")
+ :id "assets-rename-component"
+ :option-handler on-rename})
+ (when (and local? (not (or multi-assets? read-only?)))
+ {:option-name (if components-v2
+ (tr "workspace.assets.duplicate-main")
+ (tr "workspace.assets.duplicate"))
+ :id "assets-duplicate-component"
+ :option-handler on-duplicate})
- (when (and local? (not read-only?))
- {:option-name (tr "workspace.assets.delete")
- :id "assets-delete-component"
- :option-handler on-delete})
- (when (and local? (not (or multi-assets? read-only?)))
- {:option-name (tr "workspace.assets.group")
- :id "assets-group-component"
- :option-handler on-group})
+ (when (and local? (not read-only?))
+ {:option-name (tr "workspace.assets.delete")
+ :id "assets-delete-component"
+ :option-handler on-delete})
+ (when (and local? (not (or multi-assets? read-only?)))
+ {:option-name (tr "workspace.assets.group")
+ :id "assets-group-component"
+ :option-handler on-group})
- (when (and components-v2 (not multi-assets?))
- {:option-name (tr "workspace.shape.menu.show-main")
- :id "assets-show-main-component"
- :option-handler on-show-main})]
-
- [(when (and local? (not (or multi-components? multi-assets? read-only?)))
- [(tr "workspace.assets.rename") on-rename])
- (when (and local? (not (or multi-assets? read-only?)))
- [(if components-v2
- (tr "workspace.assets.duplicate-main")
- (tr "workspace.assets.duplicate")) on-duplicate])
- (when (and local? (not read-only?))
- [(tr "workspace.assets.delete") on-delete])
- (when (and local? (not (or multi-assets? read-only?)))
- [(tr "workspace.assets.group") on-group])
- (when (and components-v2 (not multi-assets?))
- [(tr "workspace.shape.menu.show-main") on-show-main])])}]]]))
+ (when (and components-v2 (not multi-assets?))
+ {:option-name (tr "workspace.shape.menu.show-main")
+ :id "assets-show-main-component"
+ :option-handler on-show-main})]}]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/components.scss
index 82fa009bc6..6496b917eb 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.scss
@@ -6,213 +6,217 @@
@import "refactor/common-refactor.scss";
-.component-group {
- .drop-space {
- height: $s-12;
- }
- .asset-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- grid-auto-rows: calc(10vh + $s-16);
- gap: $s-4;
- margin-left: $s-8;
- .grid-cell {
- @include flexCenter;
- position: relative;
- padding: $s-8;
- border: $s-4 solid transparent;
- border-radius: $br-8;
- background-color: var(--assets-component-background-color);
- overflow: hidden;
- cursor: pointer;
- img {
- height: auto;
- width: auto;
- max-height: 100%;
- max-width: 100%;
- pointer-events: none;
- }
- svg {
- height: 10vh;
- }
- .cell-name {
- @include titleTipography;
- @include textEllipsis;
- display: none;
- position: absolute;
- left: 0;
- bottom: 0;
- width: 100%;
- padding: $s-2;
- &.editing {
- display: flex;
- align-items: center;
- height: $s-32;
- border: $s-1 solid var(--input-border-color-focus);
- border-radius: $br-8;
- background-color: var(--input-background-color);
- input {
- @include textEllipsis;
- @include titleTipography;
- @include removeInputStyle;
- flex-grow: 1;
- height: $s-28;
- max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
- padding-left: $s-6;
- margin: 0;
- border-radius: $br-8;
- color: var(--input-foreground-color);
- }
- span {
- @include flexCenter;
- height: $s-28;
- background-color: transparent;
- border-radius: $br-8;
- svg {
- @extend .button-icon-small;
- stroke: var(--input-foreground-color);
- transform: rotate(90deg);
- }
- }
- }
- }
+.drop-space {
+ height: $s-12;
+}
+.asset-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ grid-auto-rows: calc(10vh + $s-16);
+ gap: $s-4;
+ margin-left: $s-8;
+}
- &:hover {
- background-color: var(--assets-item-background-color-hover);
- .cell-name {
- display: block;
- color: var(--assets-item-name-foreground-color-hover);
- background: linear-gradient(to top, rgba(52, 57, 59, 1) 0%, rgba(52, 57, 59, 0) 100%);
- &.editing {
- display: flex;
- background: var(--input-background-color);
- input {
- color: var(--input-foreground-color-active);
- }
- span svg {
- stroke: var(--input-foreground-color-active);
- }
- }
- }
- }
-
- &.selected {
- border: $s-4 solid var(--assets-item-border-color);
- }
- }
- .grid-placeholder {
- width: 100%;
- border-radius: $br-8;
- background-color: var(--assets-item-background-color-drag);
- border: $s-2 solid var(--assets-item-border-color-drag);
- }
+.grid-cell {
+ @include flexCenter;
+ position: relative;
+ padding: $s-8;
+ border: $s-4 solid transparent;
+ border-radius: $br-8;
+ background-color: var(--assets-component-background-color);
+ overflow: hidden;
+ cursor: pointer;
+ img {
+ height: auto;
+ width: auto;
+ max-height: 100%;
+ max-width: 100%;
+ pointer-events: none;
}
- .asset-enum {
- margin: 0 $s-12;
- .enum-item {
- position: relative;
+ svg {
+ height: 10vh;
+ }
+ .cell-name {
+ @include titleTipography;
+ @include textEllipsis;
+ display: none;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ padding: $s-2;
+ &.editing {
display: flex;
align-items: center;
- height: $s-36;
- margin-bottom: $s-4;
- padding: $s-2;
+ height: $s-32;
+ border: $s-1 solid var(--input-border-color-focus);
border-radius: $br-8;
- background-color: var(--assets-item-background-color);
- cursor: pointer;
-
- svg,
- img {
- @include flexCenter;
- flex-shrink: 0;
- padding: $s-2;
- height: $s-32;
- width: $s-32;
- border-radius: $br-6;
- background-color: var(--color-foreground-secondary);
- }
-
- .item-name {
- @include titleTipography;
+ background-color: var(--input-background-color);
+ input {
@include textEllipsis;
- padding-left: $s-8;
- color: var(--assets-item-name-foreground-color);
- &.editing {
- display: flex;
- align-items: center;
- height: $s-32;
- border: $s-1 solid var(--input-border-color-focus);
- border-radius: $br-8;
- background-color: var(--input-background-color);
- input {
- @include textEllipsis;
- @include titleTipography;
- @include removeInputStyle;
- flex-grow: 1;
- height: $s-28;
- max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
- padding-left: $s-6;
- margin: 0;
- border-radius: $br-8;
- color: var(--input-foreground-color);
- }
- span {
- @include flexCenter;
- height: $s-28;
- background-color: transparent;
- border-radius: $br-8;
- svg {
- @extend .button-icon-small;
- stroke: var(--input-foreground-color);
- transform: rotate(90deg);
- }
- }
+ @include titleTipography;
+ @include removeInputStyle;
+ flex-grow: 1;
+ height: $s-28;
+ max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
+ padding-left: $s-6;
+ margin: 0;
+ border-radius: $br-8;
+ color: var(--input-foreground-color);
+ }
+ span {
+ @include flexCenter;
+ height: $s-28;
+ background-color: transparent;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-foreground-color);
+ transform: rotate(90deg);
}
}
-
- &:hover {
- background-color: var(--assets-item-background-color-hover);
- .item-name {
- color: var(--assets-item-name-foreground-color-hover);
- &.editing {
- background: var(--input-background-color);
- input {
- color: var(--input-foreground-color-active);
- }
- span svg {
- stroke: var(--input-foreground-color-active);
- }
- }
- }
- }
- &.selected {
- border: $s-1 solid var(--assets-item-border-color);
- }
- }
- .grid-placeholder {
- height: $s-2;
- width: 100%;
- background-color: var(--color-accent-primary);
}
}
+
+ &:hover {
+ background-color: var(--assets-item-background-color-hover);
+ .cell-name {
+ display: block;
+ color: var(--assets-item-name-foreground-color-hover);
+ background: linear-gradient(to top, rgba(52, 57, 59, 1) 0%, rgba(52, 57, 59, 0) 100%);
+ &.editing {
+ display: flex;
+ background: var(--input-background-color);
+ input {
+ color: var(--input-foreground-color-active);
+ }
+ span svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+ }
+ }
+
+ &.selected {
+ border: $s-4 solid var(--assets-item-border-color);
+ }
}
+
+.grid-placeholder {
+ width: 100%;
+ border-radius: $br-8;
+ background-color: var(--assets-item-background-color-drag);
+ border: $s-2 solid var(--assets-item-border-color-drag);
+}
+
+.asset-enum {
+ margin: 0 $s-12;
+}
+.enum-item {
+ position: relative;
+ display: flex;
+ align-items: center;
+ height: $s-36;
+ margin-bottom: $s-4;
+ padding: $s-2;
+ border-radius: $br-8;
+ background-color: var(--assets-item-background-color);
+ cursor: pointer;
+
+ svg,
+ img {
+ @include flexCenter;
+ flex-shrink: 0;
+ padding: $s-2;
+ height: $s-32;
+ width: $s-32;
+ border-radius: $br-6;
+ background-color: var(--color-foreground-secondary);
+ }
+
+ .item-name {
+ @include titleTipography;
+ @include textEllipsis;
+ padding-left: $s-8;
+ color: var(--assets-item-name-foreground-color);
+ &.editing {
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ border: $s-1 solid var(--input-border-color-focus);
+ border-radius: $br-8;
+ background-color: var(--input-background-color);
+ input {
+ @include textEllipsis;
+ @include titleTipography;
+ @include removeInputStyle;
+ flex-grow: 1;
+ height: $s-28;
+ max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
+ padding-left: $s-6;
+ margin: 0;
+ border-radius: $br-8;
+ color: var(--input-foreground-color);
+ }
+ span {
+ @include flexCenter;
+ height: $s-28;
+ background-color: transparent;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-foreground-color);
+ transform: rotate(90deg);
+ }
+ }
+ }
+ }
+
+ &:hover {
+ background-color: var(--assets-item-background-color-hover);
+ .item-name {
+ color: var(--assets-item-name-foreground-color-hover);
+ &.editing {
+ background: var(--input-background-color);
+ input {
+ color: var(--input-foreground-color-active);
+ }
+ span svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+ }
+ }
+ &.selected {
+ border: $s-1 solid var(--assets-item-border-color);
+ }
+}
+
+.grid-placeholder {
+ height: $s-2;
+ width: 100%;
+ background-color: var(--color-accent-primary);
+}
+
.listing-options {
display: flex;
align-items: center;
+}
- .listing-option-btn {
- @include flexCenter;
- cursor: pointer;
- background-color: var(--button-radio-background-color-rest);
+.listing-option-btn {
+ @include flexCenter;
+ cursor: pointer;
+ background-color: var(--button-radio-background-color-rest);
- &.first {
- margin-left: auto;
- }
+ &.first {
+ margin-left: auto;
+ }
- svg {
- @extend .button-icon;
- }
+ svg {
+ @extend .button-icon;
}
}
+
.add-component {
@extend .button-tertiary;
height: $s-32;
@@ -224,6 +228,7 @@
stroke: var(--icon-foreground);
}
}
+
:global(.three-row) {
.asset-grid {
grid-template-columns: repeat(3, 1fr);
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs
index 116ebd2abb..f9fcbc82a3 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.assets.file-library
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -40,62 +40,41 @@
(mf/defc file-library-title
{::mf/wrap-props false}
- [{:keys [open? local? shared? project-id file-id page-id file-name]}]
+ [{:keys [open? local? project-id file-id page-id file-name]}]
(let [router (mf/deref refs/router)
url (rt/resolve router :workspace
{:project-id project-id
:file-id file-id}
{:page-id page-id})
- new-css-system (mf/use-ctx ctx/new-css-system)
toggle-open
(mf/use-fn
(mf/deps file-id open?)
(fn []
(st/emit! (dw/set-assets-section-open file-id :library (not open?)))))]
- (if ^boolean new-css-system
- [:div {:class (dom/classnames (css :library-title) true)}
- [:& title-bar {:collapsable? true
- :collapsed? (not open?)
- :clickable-all? true
- :on-collapsed toggle-open
- :title (if local?
- (mf/html [:div {:class (dom/classnames (css :special-title) true)} (tr "workspace.assets.local-library")])
+ [:div {:class (stl/css :library-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :clickable-all? true
+ :on-collapsed toggle-open
+ :title (if local?
+ (mf/html [:div {:class (stl/css :special-title)}
+ (tr "workspace.assets.local-library")])
+ ;; Do we need to add shared info here?
- (mf/html [:div {:class (dom/classnames (css :special-title) true)} file-name]))}
- (when-not local?
- [:span.tool-link.tooltip.tooltip-left {:alt "Open library file"}
- [:a {:class (dom/classnames (css :file-link) true)
- :href (str "#" url)
- :target "_blank"
- :on-click dom/stop-propagation}
- i/open-link-refactor]])]]
-
- [:div.tool-window-bar.library-bar
- {:on-click toggle-open}
- [:div.collapse-library
- {:class (dom/classnames :open open?)}
- i/arrow-slide]
-
- (if local?
- [:*
- [:span.library-title (tr "workspace.assets.local-library")]
- (when shared?
- [:span.shared-library {:alt (tr "workspace.assets.shared-library") :title (tr "workspace.assets.shared-library")}
- i/library]
- )]
- [:*
- [:span.library-title {:title file-name} file-name]
- [:span.tool-link {:alt (tr "workspace.assets.open-library") :title (tr "workspace.assets.open-library")}
- [:a {:href (str "#" url)
- :target "_blank"
- :on-click dom/stop-propagation}
- i/chain]]])])))
+ (mf/html [:div {:class (stl/css :special-title)}
+ file-name]))}
+ (when-not local?
+ [:span {:title "Open library file"}
+ [:a {:class (stl/css :file-link)
+ :href (str "#" url)
+ :target "_blank"
+ :on-click dom/stop-propagation}
+ i/open-link-refactor]])]]))
(mf/defc file-library-content
{::mf/wrap-props false}
[{:keys [file local? open-status-ref on-clear-selection]}]
(let [components-v2 (mf/use-ctx ctx/components-v2)
- new-css-system (mf/use-ctx ctx/new-css-system)
open-status (mf/deref open-status-ref)
file-id (:id file)
@@ -111,9 +90,6 @@
reverse-sort? (= :desc filters-ordering)
listing-thumbs? (= :thumbs filters-list-style)
- toggle-ordering (mf/use-ctx cmm/assets-toggle-ordering)
- toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
-
library-ref (mf/with-memo [file-id]
(create-file-library-ref file-id))
@@ -155,10 +131,6 @@
(l/derived lens:selected)))
selected (mf/deref selected-lens)
- selected-count (+ (count (get selected :components))
- (count (get selected :graphics))
- (count (get selected :colors))
- (count (get selected :typographies)))
has-term? (not ^boolean (str/empty? filters-term))
force-open-components? (when ^boolean has-term? (> 60 (count components)))
@@ -246,166 +218,80 @@
(st/emit! (dwu/commit-undo-transaction undo-id)))))]
- (if ^boolean new-css-system
- [:div {:class (dom/classnames (css :library-content) true)}
- (when ^boolean show-components?
- [:& components-section
- {:file-id file-id
- :local? local?
- :components components
- :listing-thumbs? listing-thumbs?
- :open? (or ^boolean force-open-components?
- ^boolean (get open-status :components false))
- :force-open? force-open-components?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-component-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
+ [:div {:class (stl/css :library-content)}
+ (when ^boolean show-components?
+ [:& components-section
+ {:file-id file-id
+ :local? local?
+ :components components
+ :listing-thumbs? listing-thumbs?
+ :open? (or ^boolean force-open-components?
+ ^boolean (get open-status :components false))
+ :force-open? force-open-components?
+ :open-status-ref open-status-ref
+ :reverse-sort? reverse-sort?
+ :selected selected
+ :on-asset-click on-component-click
+ :on-assets-delete on-assets-delete
+ :on-clear-selection on-clear-selection}])
- (when ^boolean show-graphics?
- [:& graphics-section
- {:file-id file-id
- :project-id project-id
- :local? local?
- :objects media
- :listing-thumbs? listing-thumbs?
- :open? (or ^boolean force-open-graphics?
- ^boolean (get open-status :graphics false))
- :force-open? force-open-graphics?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-graphics-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
+ (when ^boolean show-graphics?
+ [:& graphics-section
+ {:file-id file-id
+ :project-id project-id
+ :local? local?
+ :objects media
+ :listing-thumbs? listing-thumbs?
+ :open? (or ^boolean force-open-graphics?
+ ^boolean (get open-status :graphics false))
+ :force-open? force-open-graphics?
+ :open-status-ref open-status-ref
+ :reverse-sort? reverse-sort?
+ :selected selected
+ :on-asset-click on-graphics-click
+ :on-assets-delete on-assets-delete
+ :on-clear-selection on-clear-selection}])
- (when ^boolean show-colors?
- [:& colors-section
- {:file-id file-id
- :local? local?
- :colors colors
- :open? (or ^boolean force-open-colors?
- ^boolean (get open-status :colors false))
- :force-open? force-open-colors?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-colors-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
+ (when ^boolean show-colors?
+ [:& colors-section
+ {:file-id file-id
+ :local? local?
+ :colors colors
+ :open? (or ^boolean force-open-colors?
+ ^boolean (get open-status :colors false))
+ :force-open? force-open-colors?
+ :open-status-ref open-status-ref
+ :reverse-sort? reverse-sort?
+ :selected selected
+ :on-asset-click on-colors-click
+ :on-assets-delete on-assets-delete
+ :on-clear-selection on-clear-selection}])
- (when ^boolean show-typography?
- [:& typographies-section
- {:file file
- :file-id (:id file)
- :local? local?
- :typographies typographies
- :open? (or ^boolean force-open-typographies?
- ^boolean (get open-status :typographies false))
- :force-open? force-open-typographies?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-typography-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
+ (when ^boolean show-typography?
+ [:& typographies-section
+ {:file file
+ :file-id (:id file)
+ :local? local?
+ :typographies typographies
+ :open? (or ^boolean force-open-typographies?
+ ^boolean (get open-status :typographies false))
+ :force-open? force-open-typographies?
+ :open-status-ref open-status-ref
+ :reverse-sort? reverse-sort?
+ :selected selected
+ :on-asset-click on-typography-click
+ :on-assets-delete on-assets-delete
+ :on-clear-selection on-clear-selection}])
- (when (and (not ^boolean show-components?)
- (not ^boolean show-graphics?)
- (not ^boolean show-colors?)
- (not ^boolean show-typography?))
- [:div {:class (css :asset-title)}
- [:span {:class (css :no-found-icon)}
- i/search-refactor]
- [:span {:class (css :no-found-text)}
- (tr "workspace.assets.not-found")]])]
- [:div.tool-window-content
- [:div.listing-options
- (when (> selected-count 0)
- [:span.selected-count
- (tr "workspace.assets.selected-count" (i18n/c selected-count))])
- [:div.listing-option-btn.first {:on-click toggle-ordering}
- (if reverse-sort?
- i/sort-ascending
- i/sort-descending)]
- [:div.listing-option-btn {:on-click toggle-list-style}
- (if listing-thumbs?
- i/listing-enum
- i/listing-thumbs)]]
-
- (when ^boolean show-components?
- [:& components-section
- {:file-id file-id
- :local? local?
- :components components
- :listing-thumbs? listing-thumbs?
- :open? (or ^boolean force-open-components?
- ^boolean (get open-status :components false))
- :force-open? force-open-components?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-component-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
-
- (when ^boolean show-graphics?
- [:& graphics-section
- {:file-id file-id
- :project-id project-id
- :local? local?
- :objects media
- :listing-thumbs? listing-thumbs?
- :open? (or ^boolean force-open-graphics?
- ^boolean (get open-status :graphics false))
- :force-open? force-open-graphics?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-graphics-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
-
- (when ^boolean show-colors?
- [:& colors-section
- {:file-id file-id
- :local? local?
- :colors colors
- :open? (or ^boolean force-open-colors?
- ^boolean (get open-status :colors false))
- :force-open? force-open-colors?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-colors-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
-
- (when ^boolean show-typography?
- [:& typographies-section
- {:file file
- :file-id (:id file)
- :local? local?
- :typographies typographies
- :open? (or ^boolean force-open-typographies?
- ^boolean (get open-status :typographies false))
- :force-open? force-open-typographies?
- :open-status-ref open-status-ref
- :reverse-sort? reverse-sort?
- :selected selected
- :on-asset-click on-typography-click
- :on-assets-delete on-assets-delete
- :on-clear-selection on-clear-selection}])
-
- (when (and (not ^boolean show-components?)
- (not ^boolean show-graphics?)
- (not ^boolean show-colors?)
- (not ^boolean show-typography?))
- [:div.asset-section
- [:div.asset-title
- (tr "workspace.assets.not-found")]])])))
+ (when (and (not ^boolean show-components?)
+ (not ^boolean show-graphics?)
+ (not ^boolean show-colors?)
+ (not ^boolean show-typography?))
+ [:div {:class (stl/css :asset-title)}
+ [:span {:class (stl/css :no-found-icon)}
+ i/search-refactor]
+ [:span {:class (stl/css :no-found-text)}
+ (tr "workspace.assets.not-found")]])]))
(mf/defc file-library
@@ -416,7 +302,6 @@
shared? (:is-shared file)
project-id (:project-id file)
page-id (dm/get-in file [:data :pages 0])
- new-css-system (mf/use-ctx ctx/new-css-system)
open-status-ref (mf/with-memo [file-id]
(-> (l/key file-id)
@@ -429,8 +314,7 @@
(mf/deps file-id)
(fn []
(st/emit! (dw/unselect-all-assets file-id))))]
- [:div {:class (dom/classnames (css :tool-window) new-css-system
- :tool-window (not new-css-system))
+ [:div {:class (stl/css :tool-window)
:on-context-menu dom/prevent-default
:on-click unselect-all}
[:& file-library-title
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.scss
index 68b50d27c0..0044dbcd18 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.scss
@@ -8,35 +8,35 @@
.tool-window {
margin-bottom: $s-24;
}
-.library-title {
- .file-name {
- @include titleTipography;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- flex-grow: 100;
- height: 100%;
- }
- .special-title {
- @include textEllipsis;
- color: var(--title-foreground-color-hover);
- margin-left: $s-2;
- text-align: left;
- }
+.file-name {
+ @include titleTipography;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ flex-grow: 100;
+ height: 100%;
+}
- .file-link {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- border-radius: $br-8;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- fill: var(--title-foreground-color-hover);
- }
+.special-title {
+ @include textEllipsis;
+ color: var(--title-foreground-color-hover);
+ margin-left: $s-2;
+ text-align: left;
+}
+
+.file-link {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ fill: var(--title-foreground-color-hover);
}
}
+
.library-content {
display: flex;
flex-direction: column;
@@ -53,22 +53,23 @@
flex-direction: column;
align-items: center;
gap: $s-8;
- .no-found-icon {
- @include flexCenter;
- background-color: var(--not-found-background-color);
- border-radius: $br-circle;
- height: $s-48;
- width: $s-48;
- svg {
- @extend .button-icon;
- height: $s-24;
- width: $s-24;
- stroke: var(--not-found-foreground-color);
- }
- }
+}
- .no-found-text {
- @include titleTipography;
- color: var(--not-found-foreground-color);
+.no-found-icon {
+ @include flexCenter;
+ background-color: var(--not-found-background-color);
+ border-radius: $br-circle;
+ height: $s-48;
+ width: $s-48;
+ svg {
+ @extend .button-icon;
+ height: $s-24;
+ width: $s-24;
+ stroke: var(--not-found-foreground-color);
}
}
+
+.no-found-text {
+ @include titleTipography;
+ color: var(--not-found-foreground-color);
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs
index 0dd0b0b47e..2705c891cb 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs
@@ -14,7 +14,6 @@
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.util.dom :as dom]
@@ -27,7 +26,6 @@
(when-not (empty? path)
(let [[other-path last-path truncated] (cfh/compact-path path 35 true)
menu-state (mf/use-state cmm/initial-context-menu-state)
- new-css-system (mf/use-ctx ctx/new-css-system)
on-fold-group
(mf/use-fn
(mf/deps file-id section path group-open?)
@@ -46,45 +44,28 @@
on-close-menu
(mf/use-fn #(swap! menu-state cmm/close-context-menu))]
- (if new-css-system
- [:div {:class (stl/css :group-title)
- :on-context-menu on-context-menu}
- [:& title-bar {:collapsable? true
- :collapsed? (not group-open?)
- :clickable-all? true
- :on-collapsed on-fold-group
- :title (mf/html [:* (when-not (empty? other-path)
- [:span {:class (stl/css :pre-path)
- :title (when truncated path)}
- other-path "\u00A0\u2022\u00A0"])
- [:span {:class (stl/css :path)
- :title (when truncated path)}
- last-path]])}]
- [:& cmm/assets-context-menu
- {:on-close on-close-menu
- :state @menu-state
- :options [{:option-name (tr "workspace.assets.rename")
- :id "assets-rename-group"
- :option-handler #(on-rename % path last-path)}
- {:option-name (tr "workspace.assets.ungroup")
- :id "assets-ungroup-group"
- :option-handler #(on-ungroup path)}]}]]
-
-
- [:div.group-title {:class (when-not group-open? "closed")
- :on-click on-fold-group
- :on-context-menu on-context-menu}
- [:span i/arrow-slide]
- (when-not (empty? other-path)
- [:span.dim {:title (when truncated path)}
- other-path "\u00A0/\u00A0"])
- [:span {:title (when truncated path)}
- last-path]
- [:& cmm/assets-context-menu
- {:on-close on-close-menu
- :state @menu-state
- :options [[(tr "workspace.assets.rename") #(on-rename % path last-path)]
- [(tr "workspace.assets.ungroup") #(on-ungroup path)]]}]]))))
+ [:div {:class (stl/css :group-title)
+ :on-context-menu on-context-menu}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not group-open?)
+ :clickable-all? true
+ :on-collapsed on-fold-group
+ :title (mf/html [:* (when-not (empty? other-path)
+ [:span {:class (stl/css :pre-path)
+ :title (when truncated path)}
+ other-path "\u00A0\u2022\u00A0"])
+ [:span {:class (stl/css :path)
+ :title (when truncated path)}
+ last-path]])}]
+ [:& cmm/assets-context-menu
+ {:on-close on-close-menu
+ :state @menu-state
+ :options [{:option-name (tr "workspace.assets.rename")
+ :id "assets-rename-group"
+ :option-handler #(on-rename % path last-path)}
+ {:option-name (tr "workspace.assets.ungroup")
+ :id "assets-ungroup-group"
+ :option-handler #(on-ungroup path)}]}]])))
(defn group-assets
"Convert a list of assets in a nested structure like this:
@@ -120,8 +101,7 @@
::mf/register-as :name-group-dialog}
[{:keys [path last-path accept] :as ctx
:or {path "" last-path ""}}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- initial (mf/use-memo
+ (let [initial (mf/use-memo
(mf/deps last-path)
(constantly {:asset-name last-path}))
form (fm/use-form :spec ::name-group-form
@@ -142,69 +122,36 @@
(accept asset-name)
(accept path asset-name))
(modal/hide!))))]
- (if new-css-system
- [:div {:class (stl/css :modal-overlay)}
- [:div {:class (stl/css :modal-container)}
- [:div {:class (stl/css :modal-header)}
- [:h2 {:class (stl/css :modal-title)}
- (if create?
- (tr "workspace.assets.create-group")
- (tr "workspace.assets.rename-group"))]
- [:button {:class (stl/css :modal-close-btn)
- :on-click on-close} i/close-refactor]]
+ [:div {:class (stl/css :modal-overlay)}
+ [:div {:class (stl/css :modal-container)}
+ [:div {:class (stl/css :modal-header)}
+ [:h2 {:class (stl/css :modal-title)}
+ (if create?
+ (tr "workspace.assets.create-group")
+ (tr "workspace.assets.rename-group"))]
+ [:button {:class (stl/css :modal-close-btn)
+ :on-click on-close} i/close-refactor]]
- [:div {:class (stl/css :modal-content)}
- [:& fm/form {:form form :on-submit on-accept}
- [:& fm/input {:name :asset-name
- :class (stl/css :input-wrapper)
- :auto-focus? true
- :label (tr "workspace.assets.group-name")
- :hint (tr "workspace.assets.create-group-hint")}]]]
+ [:div {:class (stl/css :modal-content)}
+ [:& fm/form {:form form :on-submit on-accept}
+ [:& fm/input {:name :asset-name
+ :class (stl/css :input-wrapper)
+ :auto-focus? true
+ :label (tr "workspace.assets.group-name")
+ :hint (tr "workspace.assets.create-group-hint")}]]]
- [:div {:class (stl/css :modal-footer)}
- [:div {:class (stl/css :action-buttons)}
- [:input
- {:class (stl/css :cancel-button)
- :type "button"
- :value (tr "labels.cancel")
- :on-click on-close}]
+ [:div {:class (stl/css :modal-footer)}
+ [:div {:class (stl/css :action-buttons)}
+ [:input
+ {:class (stl/css :cancel-button)
+ :type "button"
+ :value (tr "labels.cancel")
+ :on-click on-close}]
- [:input
- {:type "button"
- :class (stl/css-case :accept-btn true
- :global/disabled (not (:valid @form) ))
- :disabled (not (:valid @form))
- :value (if create? (tr "labels.create") (tr "labels.rename"))
- :on-click on-accept}]]]]]
-
-
- [:div.modal-overlay
- [:div.modal-container.confirm-dialog
- [:div.modal-header
- [:div.modal-header-title
- [:h2 (if create?
- (tr "workspace.assets.create-group")
- (tr "workspace.assets.rename-group"))]]
- [:div.modal-close-button
- {:on-click on-close} i/close]]
-
- [:div.modal-content.generic-form
- [:& fm/form {:form form :on-submit on-accept}
- [:& fm/input {:name :asset-name
- :auto-focus? true
- :label (tr "workspace.assets.group-name")
- :hint (tr "workspace.assets.create-group-hint")}]]]
-
- [:div.modal-footer
- [:div.action-buttons
- [:input.cancel-button
- {:type "button"
- :value (tr "labels.cancel")
- :on-click on-close}]
-
- [:input.accept-button.primary
- {:type "button"
- :class (when-not (:valid @form) "btn-disabled")
- :disabled (not (:valid @form))
- :value (if create? (tr "labels.create") (tr "labels.rename"))
- :on-click on-accept}]]]]])))
+ [:input
+ {:type "button"
+ :class (stl/css-case :accept-btn true
+ :global/disabled (not (:valid @form)))
+ :disabled (not (:valid @form))
+ :value (if create? (tr "labels.create") (tr "labels.rename"))
+ :on-click on-accept}]]]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss
index 93235d3bae..c3091a7cb2 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss
@@ -8,52 +8,57 @@
.group-title {
padding-left: $s-4;
- .pre-path {
- margin-left: $s-2;
- text-transform: initial;
- color: var(--title-foreground-color);
- }
- .path {
- margin-left: $s-2;
- text-transform: initial;
- color: var(--title-foreground-color-hover);
- }
+}
+
+.pre-path {
+ margin-left: $s-2;
+ text-transform: initial;
+ color: var(--title-foreground-color);
+}
+
+.path {
+ margin-left: $s-2;
+ text-transform: initial;
+ color: var(--title-foreground-color-hover);
}
.modal-overlay {
@extend .modal-overlay-base;
- .modal-container {
- @extend .modal-container-base;
- .modal-header {
- margin-bottom: $s-24;
- .modal-title {
- @include tabTitleTipography;
- color: var(--modal-title-foreground-color);
- }
- .modal-close-btn {
- @extend .modal-close-btn-base;
- }
- }
- .modal-content {
- @include titleTipography;
- margin-bottom: $s-24;
- .input-wrapper {
- @extend .input-with-label;
- }
- }
- .modal-footer {
- .action-buttons {
- @extend .modal-action-btns;
- .cancel-button {
- @extend .modal-cancel-btn;
- }
- .accept-btn {
- @extend .modal-accept-btn;
- &.danger {
- @extend .modal-danger-btn;
- }
- }
- }
- }
+}
+
+.modal-container {
+ @extend .modal-container-base;
+}
+
+.modal-header {
+ margin-bottom: $s-24;
+}
+
+.modal-title {
+ @include tabTitleTipography;
+ color: var(--modal-title-foreground-color);
+}
+.modal-close-btn {
+ @extend .modal-close-btn-base;
+}
+
+.modal-content {
+ @include titleTipography;
+ margin-bottom: $s-24;
+}
+.input-wrapper {
+ @extend .input-with-label;
+}
+.action-buttons {
+ @extend .modal-action-btns;
+}
+.cancel-button {
+ @extend .modal-cancel-btn;
+}
+
+.accept-btn {
+ @extend .modal-accept-btn;
+ &.danger {
+ @extend .modal-danger-btn;
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs
index 5708709d33..d85b1979cb 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs
@@ -46,7 +46,6 @@
dragging? (deref dragging*)
read-only? (mf/use-ctx ctx/workspace-read-only?)
- new-css-system (mf/use-ctx ctx/new-css-system)
editing? (= editing-id (:id typography))
renaming? (= renaming-id (:id typography))
@@ -100,52 +99,29 @@
(mf/deps typography apply-typography on-asset-click)
(partial on-asset-click typography-id apply-typography))]
- (if ^boolean new-css-system
- [:div {:class (stl/css :typography-item)
- :ref item-ref
- :draggable (and (not read-only?) (not open?))
- :on-drag-start on-typography-drag-start
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
+ [:div {:class (stl/css :typography-item)
+ :ref item-ref
+ :draggable (and (not read-only?) (not open?))
+ :on-drag-start on-typography-drag-start
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
- [:& typography-entry
- {:typography typography
- :local? local?
- :on-context-menu on-context-menu
- :on-change handle-change
- :selected? (contains? selected typography-id)
- :on-click on-asset-click
- :editing? editing?
- :renaming? renaming?
- :focus-name? rename?
- :external-open* open*
- :file-id file-id}]
- (when ^boolean dragging?
- [:div {:class (stl/css :dragging)}])]
-
- [:div.typography-container {:ref item-ref
- :draggable (and (not read-only?) (not open?))
- :on-drag-start on-typography-drag-start
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- [:& typography-entry
- {:typography typography
- :local? local?
- :on-context-menu on-context-menu
- :on-change handle-change
- :selected? (contains? selected typography-id)
- :on-click on-asset-click
- :editing? editing?
- :focus-name? rename?
- :external-open* open*
- :file-id file-id}]
-
- (when ^boolean dragging?
- [:div.dragging])])))
+ [:& typography-entry
+ {:typography typography
+ :local? local?
+ :on-context-menu on-context-menu
+ :on-change handle-change
+ :selected? (contains? selected typography-id)
+ :on-click on-asset-click
+ :editing? editing?
+ :renaming? renaming?
+ :focus-name? rename?
+ :external-open* open*
+ :file-id file-id}]
+ (when ^boolean dragging?
+ [:div {:class (stl/css :dragging)}])]))
(mf/defc typographies-group
{::mf/wrap-props false}
@@ -155,7 +131,6 @@
(let [group-open? (get open-groups prefix true)
dragging* (mf/use-state false)
dragging? (deref dragging*)
- new-css-system (mf/use-ctx ctx/new-css-system)
selected-paths (mf/with-memo [selected-full]
(into #{}
(comp (map :path) (d/nilv ""))
@@ -183,134 +158,72 @@
(fn [event]
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full move-typography)))]
- (if ^boolean new-css-system
- [:div {:class (stl/css :typographies-group)
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- [:& grp/asset-group-title {:file-id file-id
- :section :typographies
- :path prefix
- :group-open? group-open?
- :on-rename on-rename-group
- :on-ungroup on-ungroup}]
+ [:div {:class (stl/css :typographies-group)
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
+ [:& grp/asset-group-title {:file-id file-id
+ :section :typographies
+ :path prefix
+ :group-open? group-open?
+ :on-rename on-rename-group
+ :on-ungroup on-ungroup}]
- (when group-open?
- [:*
- (let [typographies (get groups "" [])]
- [:div {:class (stl/css :assets-list)
- :on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
+ (when group-open?
+ [:*
+ (let [typographies (get groups "" [])]
+ [:div {:class (stl/css :assets-list)
+ :on-drag-enter on-drag-enter
+ :on-drag-leave on-drag-leave
+ :on-drag-over dom/prevent-default
+ :on-drop on-drop}
- (when ^boolean dragging?
- [:div {:class (stl/css :grid-placeholder)} "\u00A0"])
+ (when ^boolean dragging?
+ [:div {:class (stl/css :grid-placeholder)} "\u00A0"])
- (when (and
- (empty? typographies)
- (some? groups))
- [:div {:class (stl/css :drop-space)}])
- (for [{:keys [id] :as typography} typographies]
- [:& typography-item {:typography typography
- :key (dm/str "typography-" id)
- :file-id file-id
+ (when (and
+ (empty? typographies)
+ (some? groups))
+ [:div {:class (stl/css :drop-space)}])
+ (for [{:keys [id] :as typography} typographies]
+ [:& typography-item {:typography typography
+ :key (dm/str "typography-" id)
+ :file-id file-id
+ :local? local?
+ :handle-change handle-change
+ :selected selected
+ :apply-typography apply-typography
+ :editing-id editing-id
+ :renaming-id renaming-id
+ :rename? (= (:rename-typography local-data) id)
+ :on-asset-click on-asset-click
+ :on-context-menu on-context-menu
+ :selected-full selected-full
+ :selected-paths selected-paths
+ :move-typography move-typography}])])
+
+ (for [[path-item content] groups]
+ (when-not (empty? path-item)
+ [:& typographies-group {:file-id file-id
+ :prefix (cfh/merge-path-item prefix path-item)
+ :key (dm/str "group-" path-item)
+ :groups content
+ :open-groups open-groups
+ :force-open? force-open?
+ :file file
:local? local?
- :handle-change handle-change
:selected selected
- :apply-typography apply-typography
:editing-id editing-id
:renaming-id renaming-id
- :rename? (= (:rename-typography local-data) id)
+ :local-data local-data
:on-asset-click on-asset-click
- :on-context-menu on-context-menu
- :selected-full selected-full
- :selected-paths selected-paths
- :move-typography move-typography}])])
-
- (for [[path-item content] groups]
- (when-not (empty? path-item)
- [:& typographies-group {:file-id file-id
- :prefix (cfh/merge-path-item prefix path-item)
- :key (dm/str "group-" path-item)
- :groups content
- :open-groups open-groups
- :force-open? force-open?
- :file file
- :local? local?
- :selected selected
- :editing-id editing-id
- :renaming-id renaming-id
- :local-data local-data
- :on-asset-click on-asset-click
- :handle-change handle-change
- :apply-typography apply-typography
- :on-rename-group on-rename-group
- :on-ungroup on-ungroup
- :on-context-menu on-context-menu
- :selected-full selected-full}]))])]
- [:div {:on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
- [:& grp/asset-group-title {:file-id file-id
- :section :typographies
- :path prefix
- :group-open? group-open?
- :on-rename on-rename-group
- :on-ungroup on-ungroup}]
- (when group-open?
- [:*
- (let [typographies (get groups "" [])]
- [:div.asset-list {:on-drag-enter on-drag-enter
- :on-drag-leave on-drag-leave
- :on-drag-over dom/prevent-default
- :on-drop on-drop}
-
- (when ^boolean dragging?
- [:div.grid-placeholder "\u00A0"])
-
- (when (and
- (empty? typographies)
- (some? groups))
- [:div.drop-space])
- (for [{:keys [id] :as typography} typographies]
- [:& typography-item {:typography typography
- :key (dm/str "typography-" id)
- :file-id file-id
- :local? local?
:handle-change handle-change
- :selected selected
:apply-typography apply-typography
- :editing-id editing-id
- :rename? (= (:rename-typography local-data) id)
- :on-asset-click on-asset-click
+ :on-rename-group on-rename-group
+ :on-ungroup on-ungroup
:on-context-menu on-context-menu
- :selected-full selected-full
- :selected-paths selected-paths
- :move-typography move-typography}])])
-
- (for [[path-item content] groups]
- (when-not (empty? path-item)
- [:& typographies-group {:file-id file-id
- :prefix (cfh/merge-path-item prefix path-item)
- :key (dm/str "group-" path-item)
- :groups content
- :open-groups open-groups
- :force-open? force-open?
- :file file
- :local? local?
- :selected selected
- :editing-id editing-id
- :local-data local-data
- :on-asset-click on-asset-click
- :handle-change handle-change
- :apply-typography apply-typography
- :on-rename-group on-rename-group
- :on-ungroup on-ungroup
- :on-context-menu on-context-menu
- :selected-full selected-full}]))])])))
+ :selected-full selected-full}]))])]))
(mf/defc typographies-section
{::mf/wrap-props false}
@@ -320,7 +233,6 @@
local-data (mf/deref lens:typography-section-state)
read-only? (mf/use-ctx ctx/workspace-read-only?)
- new-css-system (mf/use-ctx ctx/new-css-system)
menu-state (mf/use-state cmm/initial-context-menu-state)
typographies (mf/with-memo [typographies]
(mapv dwl/extract-path-if-missing typographies))
@@ -465,10 +377,7 @@
(dwl/sync-file file-id file-id :typographies (:id @state))
(dwu/commit-undo-transaction undo-id))))))
- editing-id (if new-css-system
- (:edit-typography local-data)
- (or (:rename-typography local-data)
- (:edit-typography local-data)))
+ editing-id (:edit-typography local-data)
renaming-id (:rename-typography local-data)
@@ -478,10 +387,8 @@
(partial on-asset-click groups))]
(mf/use-effect
- (mf/deps local-data new-css-system)
+ (mf/deps local-data )
(fn []
- (when (and (not new-css-system)(:rename-typography local-data))
- (st/emit! #(update % :workspace-global dissoc :rename-typography)))
(when (:edit-typography local-data)
(st/emit! #(update % :workspace-global dissoc :edit-typography)))))
@@ -491,19 +398,12 @@
:section :typographies
:assets-count (count typographies)
:open? open?}
- (if ^boolean new-css-system
- (when local?
- [:& cmm/asset-section-block {:role :title-button}
- (when-not read-only?
- [:button {:class (stl/css :assets-btn)
- :on-click add-typography}
- i/add-refactor])])
-
- (when local?
- [:& cmm/asset-section-block {:role :title-button}
- (when-not read-only?
- [:div.assets-button {:on-click add-typography}
- i/plus])]))
+ (when local?
+ [:& cmm/asset-section-block {:role :title-button}
+ (when-not read-only?
+ [:button {:class (stl/css :assets-btn)
+ :on-click add-typography}
+ i/add-refactor])])
[:& cmm/asset-section-block {:role :content}
[:& typographies-group {:file-id file-id
@@ -530,38 +430,28 @@
[:& cmm/assets-context-menu
{:on-close on-close-menu
:state @menu-state
- :options (if new-css-system
- [(when-not (or multi-typographies? multi-assets?)
- {:option-name (tr "workspace.assets.rename")
- :id "assets-rename-typography"
- :option-handler handle-rename-typography-clicked})
-
- (when-not (or multi-typographies? multi-assets?)
- {:option-name (tr "workspace.assets.edit")
- :id "assets-edit-typography"
- :option-handler handle-edit-typography-clicked})
-
- {:option-name (tr "workspace.assets.delete")
- :id "assets-delete-typography"
- :option-handler handle-delete-typography}
-
- (when-not multi-assets?
- {:option-name (tr "workspace.assets.group")
- :id "assets-group-typography"
- :option-handler on-group})]
-
- [(when-not (or multi-typographies? multi-assets?)
- [(tr "workspace.assets.rename") handle-rename-typography-clicked])
- (when-not (or multi-typographies? multi-assets?)
- [(tr "workspace.assets.edit") handle-edit-typography-clicked])
- [(tr "workspace.assets.delete") handle-delete-typography]
- (when-not multi-assets?
- [(tr "workspace.assets.group") on-group])])}]
-
- (when new-css-system
- [:& cmm/assets-context-menu
- {:on-close on-close-menu
- :state @menu-state
- :options [{:option-name "show info"
+ :options [(when-not (or multi-typographies? multi-assets?)
+ {:option-name (tr "workspace.assets.rename")
:id "assets-rename-typography"
- :option-handler handle-edit-typography-clicked}]}]))]]]))
+ :option-handler handle-rename-typography-clicked})
+
+ (when-not (or multi-typographies? multi-assets?)
+ {:option-name (tr "workspace.assets.edit")
+ :id "assets-edit-typography"
+ :option-handler handle-edit-typography-clicked})
+
+ {:option-name (tr "workspace.assets.delete")
+ :id "assets-delete-typography"
+ :option-handler handle-delete-typography}
+
+ (when-not multi-assets?
+ {:option-name (tr "workspace.assets.group")
+ :id "assets-group-typography"
+ :option-handler on-group})]}]
+
+ [:& cmm/assets-context-menu
+ {:on-close on-close-menu
+ :state @menu-state
+ :options [{:option-name "show info"
+ :id "assets-rename-typography"
+ :option-handler handle-edit-typography-clicked}]}])]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.scss
index 01a0bb172d..e0ad31a23a 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.scss
@@ -17,34 +17,37 @@
stroke: var(--icon-foreground);
}
}
-.typographies-group {
- .assets-list {
- padding: 0 0 0 $s-4;
- .drop-space {
- height: $s-12;
- }
- .grid-placeholder {
- height: $s-2;
- width: 100%;
- background-color: var(--color-accent-primary);
- }
- .typography-item {
- position: relative;
- display: flex;
- align-items: center;
- margin-bottom: $s-4;
- border-radius: $br-8;
- background-color: var(--assets-item-background-color);
- }
- .dragging {
- position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- width: 100%;
- border: $s-2 solid var(--assets-item-border-color-drag);
- border-radius: $s-8;
- background-color: var(--assets-item-background-color-drag);
- }
- }
+
+.assets-list {
+ padding: 0 0 0 $s-4;
+}
+
+.drop-space {
+ height: $s-12;
+}
+
+.grid-placeholder {
+ height: $s-2;
+ width: 100%;
+ background-color: var(--color-accent-primary);
+}
+
+.typography-item {
+ position: relative;
+ display: flex;
+ align-items: center;
+ margin-bottom: $s-4;
+ border-radius: $br-8;
+ background-color: var(--assets-item-background-color);
+}
+
+.dragging {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ border: $s-2 solid var(--assets-item-border-color-drag);
+ border-radius: $s-8;
+ background-color: var(--assets-item-background-color-drag);
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs b/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs
index f292e9ad4c..643114f07f 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs
@@ -5,31 +5,23 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.collapsable-button
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.main.data.workspace :as dw]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[rumext.v2 :as mf]))
(mf/defc collapsed-button
{::mf/wrap-props false}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
- (if ^boolean new-css-system
- [:div {:id "left-sidebar-aside"
- :data-size 0
- :class (dom/classnames (css :collapsed-sidebar) true)}
- [:div {:class (dom/classnames (css :collapsed-title) true)}
- [:button {:class (dom/classnames (css :collapsed-button) true)
- :on-click on-click
- :aria-label (tr "workspace.sidebar.expand")}
- i/arrow-refactor]]]
- [:button.collapse-sidebar.collapsed
- {:on-click on-click
- :aria-label (tr "workspace.sidebar.expand")}
- i/arrow-slide])))
+ (let [on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
+ [:div {:id "left-sidebar-aside"
+ :data-size 0
+ :class (stl/css :collapsed-sidebar)}
+ [:div {:class (stl/css :collapsed-title)}
+ [:button {:class (stl/css :collapsed-button)
+ :on-click on-click
+ :aria-label (tr "workspace.sidebar.expand")}
+ i/arrow-refactor]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs
index 5d7932a898..71adc0d998 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.debug
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.main.data.workspace :as dw]
@@ -24,26 +25,27 @@
(dbg/toggle! option)
(js* "app.main.reinit()")))
- on-close
+ handle-close
(mf/use-fn
(fn []
(st/emit! (dw/remove-layout-flag :debug-panel))))]
- [:div.debug-panel
- [:div.debug-panel-header
- [:div.debug-panel-close-button
- {:on-click on-close} i/close]
- [:div.debug-panel-title "Debugging tools"]]
- [:div.debug-panel-inner
+ [:div {:class (stl/css :debug-panel)}
+ [:div {:class (stl/css :panel-title)}
+ [:span "Debugging tools"]
+ [:div {:class (stl/css :close-button) :on-click handle-close}
+ i/close-refactor]]
+
+ [:div {:class (stl/css :debug-panel-inner)}
(for [option (sort-by d/name dbg/options)]
- [:div.debug-option {:key (d/name option)
- :on-click #(on-toggle-enabled % option)}
+ [:div {:class (stl/css :checkbox-wrapper)}
+ [:span {:class (stl/css-case :checkbox-icon true :global/checked (dbg/enabled? option))
+ :on-click #(on-toggle-enabled % option)}
+ (when (dbg/enabled? option) i/status-tick-refactor)]
+
[:input {:type "checkbox"
:id (d/name option)
+ :key (d/name option)
:on-change #(on-toggle-enabled % option)
:checked (dbg/enabled? option)}]
- [:div.field.check
- (if (dbg/enabled? option)
- [:span.checked i/checkbox-checked]
- [:span.unchecked i/checkbox-unchecked])]
[:label {:for (d/name option)} (d/name option)]])]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug.scss b/frontend/src/app/main/ui/workspace/sidebar/debug.scss
new file mode 100644
index 0000000000..96364d88ee
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/debug.scss
@@ -0,0 +1,59 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@use "common/refactor/common-refactor.scss" as *;
+
+.debug-panel {
+ display: flex;
+ flex-direction: column;
+ background-color: var(--panel-background-color);
+}
+
+.panel-title {
+ @include flexCenter;
+ @include tabTitleTipography;
+ position: relative;
+ height: $s-32;
+ min-height: $s-32;
+ margin: $s-8 $s-8 0 $s-8;
+ border-radius: $br-8;
+ background-color: var(--panel-title-background-color);
+
+ span {
+ @include flexCenter;
+ flex-grow: 1;
+ color: var(--title-foreground-color-hover);
+ }
+}
+
+.close-button {
+ @extend .button-tertiary;
+ position: absolute;
+ right: $s-2;
+ top: $s-2;
+ height: $s-28;
+ width: $s-28;
+ border-radius: $br-6;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+}
+
+.checkbox-wrapper {
+ @extend .input-checkbox;
+ height: $s-32;
+ padding: 0;
+}
+
+.checkbox-icon {
+ @extend .checkbox-icon;
+ cursor: pointer;
+}
+
+.debug-panel-inner {
+ padding: $s-16 $s-8;
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/history.cljs b/frontend/src/app/main/ui/workspace/sidebar/history.cljs
index 67cb6075d8..4c292d905d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/history.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/history.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.history
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.main.data.events :as ev]
@@ -13,9 +13,7 @@
[app.main.data.workspace.common :as dwc]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.util.dom :as dom]
[app.util.i18n :refer [t] :as i18n]
[cuerdas.core :as str]
[okulary.core :as l]
@@ -149,23 +147,6 @@
(t locale "workspace.undo.entry.unknown" value))))
(defn entry->icon [{:keys [type]}]
- (case type
- :page i/file-html
- :shape i/layers
- :rect i/box
- :circle i/circle
- :text i/text
- :path i/curve
- :frame i/artboard
- :group i/folder
- :color i/palette
- :typography i/titlecase
- :component i/component
- :media i/image
- :image i/image
- i/layers))
-
-(defn entry->icon-refactor [{:keys [type]}]
(case type
:page i/document-refactor
:shape i/svg-refactor
@@ -277,103 +258,58 @@
(mf/defc history-entry-details [{:keys [entry]}]
(let [{entries :items} (mf/deref workspace-undo)
- new-css-system (mf/use-ctx ctx/new-css-system)
objects (mf/deref refs/workspace-page-objects)]
- (if new-css-system
- [:div {:class (css :history-entry-detail)}
- (case (:operation entry)
- :new
- (:name (get-object (:detail entry) entries objects))
+ [:div {:class (stl/css :history-entry-detail)}
+ (case (:operation entry)
+ :new
+ (:name (get-object (:detail entry) entries objects))
- :delete
- [:ul {:class (css :ul.history-entry-details-list)}
- (for [id (:detail entry)]
- (let [shape-name (:name (get-object id entries objects))]
- [:li {:key id} shape-name]))]
+ :delete
+ [:ul {:class (stl/css :history-entry-details-list)}
+ (for [id (:detail entry)]
+ (let [shape-name (:name (get-object id entries objects))]
+ [:li {:key id} shape-name]))]
- :modify
- [:ul {:class (css :ul.history-entry-details-list)}
- (for [[id attributes] (:detail entry)]
- (let [shape-name (:name (get-object id entries objects))]
- [:li {:key id}
- [:div shape-name]
- [:div (str/join ", " attributes)]]))]
+ :modify
+ [:ul {:class (stl/css :history-entry-details-list)}
+ (for [[id attributes] (:detail entry)]
+ (let [shape-name (:name (get-object id entries objects))]
+ [:li {:key id}
+ [:div shape-name]
+ [:div (str/join ", " attributes)]]))]
- nil)]
-
- [:div.history-entry-detail
- (case (:operation entry)
- :new
- (:name (get-object (:detail entry) entries objects))
-
- :delete
- [:ul.history-entry-details-list
- (for [id (:detail entry)]
- (let [shape-name (:name (get-object id entries objects))]
- [:li {:key id} shape-name]))]
-
-
- :modify
- [:ul.history-entry-details-list
- (for [[id attributes] (:detail entry)]
- (let [shape-name (:name (get-object id entries objects))]
- [:li {:key id}
- [:div shape-name]
- [:div (str/join ", " attributes)]]))]
-
- nil)]
- )))
+ nil)]))
(mf/defc history-entry [{:keys [locale entry idx-entry disabled? current?]}]
(let [hover? (mf/use-state false)
- new-css-system (mf/use-ctx ctx/new-css-system)
show-detail? (mf/use-state false)]
- (if new-css-system
- [:div {:class (dom/classnames (css :history-entry) true
- (css :disabled) disabled?
- (css :current) current?
- (css :hover) @hover?
- (css :show-detail) @show-detail?)
- :on-pointer-enter #(reset! hover? true)
- :on-pointer-leave #(reset! hover? false)
- :on-click #(st/emit! (dwc/undo-to-index idx-entry))}
- [:div {:class (dom/classnames (css :history-entry-summary) true)}
- [:div {:class (dom/classnames (css :history-entry-summary-icon) true)} (entry->icon-refactor entry)]
- [:div {:class (dom/classnames (css :history-entry-summary-text) true)} (entry->message locale entry)]
- (when (:detail entry)
- [:div {:class (dom/classnames (css :history-entry-summary-button) true
- (css :button-opened) @show-detail?)
- :on-click #(when (:detail entry)
- (swap! show-detail? not))}
- i/arrow-refactor])]
+ [:div {:class (stl/css-case :history-entry true
+ :disabled disabled?
+ :current current?
+ :hover @hover?
+ :show-detail @show-detail?)
+ :on-pointer-enter #(reset! hover? true)
+ :on-pointer-leave #(reset! hover? false)
+ :on-click #(st/emit! (dwc/undo-to-index idx-entry))}
- (when @show-detail?
- [:& history-entry-details {:entry entry}])]
+ [:div {:class (stl/css :history-entry-summary)}
+ [:div {:class (stl/css :history-entry-summary-icon)}
+ (entry->icon entry)]
+ [:div {:class (stl/css :history-entry-summary-text)} (entry->message locale entry)]
+ (when (:detail entry)
+ [:div {:class (stl/css-case :history-entry-summary-button true
+ :button-opened @show-detail?)
+ :on-click #(when (:detail entry)
+ (swap! show-detail? not))}
+ i/arrow-refactor])]
- [:div.history-entry {:class (dom/classnames
- :disabled disabled?
- :current current?
- :hover @hover?
- :show-detail @show-detail?)
- :on-pointer-enter #(reset! hover? true)
- :on-pointer-leave #(reset! hover? false)
- :on-click #(st/emit! (dwc/undo-to-index idx-entry))}
- [:div.history-entry-summary
- [:div.history-entry-summary-icon (entry->icon entry)]
- [:div.history-entry-summary-text (entry->message locale entry)]
- (when (:detail entry)
- [:div.history-entry-summary-button {:on-click #(when (:detail entry)
- (swap! show-detail? not))}
- i/arrow-slide])]
-
- (when show-detail?
- [:& history-entry-details {:entry entry}])])))
+ (when @show-detail?
+ [:& history-entry-details {:entry entry}])]))
(mf/defc history-toolbox []
(let [locale (mf/deref i18n/locale)
- new-css-system (mf/use-ctx ctx/new-css-system)
objects (mf/deref refs/workspace-page-objects)
{:keys [items index]} (mf/deref workspace-undo)
entries (parse-entries items objects)
@@ -381,40 +317,24 @@
(mf/use-fn
#(st/emit! (-> (dw/toggle-layout-flag :document-history)
(vary-meta assoc ::ev/origin "history-toolbox"))))]
- (if new-css-system
- [:div {:class (css :history-toolbox)}
- [:div {:class (css :history-toolbox-title)}
- [:span (t locale "workspace.undo.title")]
- [:div {:class (css :close-button)
- :on-click toggle-history}
- i/close-refactor]]
- (if (empty? entries)
- [:div {:class (css :history-entry-empty)}
- [:div {:class (css :history-entry-empty-icon)} i/history-refactor]
- [:div {:class (css :history-entry-empty-msg)} (t locale "workspace.undo.empty")]]
- [:ul {:class (css :history-entries)}
- (for [[idx-entry entry] (->> entries (map-indexed vector) reverse)] #_[i (range 0 10)]
- [:& history-entry {:key (str "entry-" idx-entry)
- :locale locale
- :entry entry
- :idx-entry idx-entry
- :current? (= idx-entry index)
- :disabled? (> idx-entry index)}])])]
-
- [:div.history-toolbox
- [:div.history-toolbox-title (t locale "workspace.undo.title")]
- (if (empty? entries)
- [:div.history-entry-empty
- [:div.history-entry-empty-icon i/recent]
- [:div.history-entry-empty-msg (t locale "workspace.undo.empty")]]
- [:ul.history-entries
- (for [[idx-entry entry] (->> entries (map-indexed vector) reverse)] #_[i (range 0 10)]
- [:& history-entry {:key (str "entry-" idx-entry)
- :locale locale
- :entry entry
- :idx-entry idx-entry
- :current? (= idx-entry index)
- :disabled? (> idx-entry index)}])])])))
+ [:div {:class (stl/css :history-toolbox)}
+ [:div {:class (stl/css :history-toolbox-title)}
+ [:span (t locale "workspace.undo.title")]
+ [:div {:class (stl/css :close-button)
+ :on-click toggle-history}
+ i/close-refactor]]
+ (if (empty? entries)
+ [:div {:class (stl/css :history-entry-empty)}
+ [:div {:class (stl/css :history-entry-empty-icon)} i/history-refactor]
+ [:div {:class (stl/css :history-entry-empty-msg)} (t locale "workspace.undo.empty")]]
+ [:ul {:class (stl/css :history-entries)}
+ (for [[idx-entry entry] (->> entries (map-indexed vector) reverse)] #_[i (range 0 10)]
+ [:& history-entry {:key (str "entry-" idx-entry)
+ :locale locale
+ :entry entry
+ :idx-entry idx-entry
+ :current? (= idx-entry index)
+ :disabled? (> idx-entry index)}])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/history.scss b/frontend/src/app/main/ui/workspace/sidebar/history.scss
index 1870531c2f..5cebfbcb0d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/history.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/history.scss
@@ -10,138 +10,139 @@
display: flex;
flex-direction: column;
background-color: var(--panel-background-color);
+}
- .history-toolbox-title {
+.history-toolbox-title {
+ @include flexCenter;
+ @include tabTitleTipography;
+ position: relative;
+ height: $s-32;
+ min-height: $s-32;
+ margin: $s-8 $s-8 0 $s-8;
+ border-radius: $br-8;
+ background-color: var(--panel-title-background-color);
+
+ span {
@include flexCenter;
- @include tabTitleTipography;
- position: relative;
- height: $s-32;
- min-height: $s-32;
- margin: $s-8 $s-8 0 $s-8;
- border-radius: $br-8;
- background-color: var(--panel-title-background-color);
+ flex-grow: 1;
+ color: var(--title-foreground-color-hover);
+ }
+}
- span {
- @include flexCenter;
- flex-grow: 1;
- color: var(--title-foreground-color-hover);
- }
+.close-button {
+ @extend .button-tertiary;
+ position: absolute;
+ right: $s-2;
+ top: $s-2;
+ height: $s-28;
+ width: $s-28;
+ border-radius: $br-6;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+}
- .close-button {
- @extend .button-tertiary;
- position: absolute;
- right: $s-2;
- top: $s-2;
- height: $s-28;
- width: $s-28;
- border-radius: $br-6;
+.history-entry-empty {
+ @include flexCenter;
+ flex-direction: column;
+ gap: $s-16;
+ padding: $s-28 $s-16;
+ text-align: center;
+}
+
+.history-entry-empty-icon {
+ @extend .empty-icon;
+ svg {
+ margin-left: calc(-1 * $s-2);
+ }
+}
+
+.history-entry-empty-msg {
+ @include titleTipography;
+ color: var(--empty-message-foreground-color);
+}
+
+.history-entries {
+ height: 100%;
+ padding: $s-12;
+ overflow-x: hidden;
+ overflow-y: auto;
+ font-size: $fs-12;
+}
+
+.history-entry {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ min-height: $s-32;
+ margin: $s-4;
+ padding: $s-4 $s-8;
+ border: $s-2 solid transparent;
+ border-radius: $s-8;
+ background-color: var(--entry-background-color);
+ cursor: pointer;
+ transition: border 0.2s;
+
+ .history-entry-summary {
+ display: flex;
+ align-items: center;
+ .history-entry-summary-icon {
svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
+ @extend .button-icon-small;
+ stroke: var(--entry-foreground-color);
+ }
+ }
+ .history-entry-summary-text {
+ margin: 0 $s-8;
+ color: $df-primary;
+ }
+ .history-entry-summary-button {
+ opacity: $op-0;
+ margin-left: auto;
+ &.button-opened {
+ svg {
+ transform: rotate(90deg);
+ }
+ }
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--entry-foreground-color);
}
}
}
- .history-entry-empty {
- @include flexCenter;
- flex-direction: column;
- gap: $s-16;
- padding: $s-28 $s-16;
- text-align: center;
-
- .history-entry-empty-icon {
- @extend .empty-icon;
- svg {
- margin-left: calc(-1 * $s-2);
- }
- }
-
- .history-entry-empty-msg {
- @include titleTipography;
- color: var(--title-foreground-secondary);
+ .history-entry-detail {
+ display: block;
+ padding-top: $s-16;
+ color: var(--modal-text-foreground-color);
+ .history-entry-details-list {
+ margin: 0;
}
}
- ul.history-entries {
- height: 100%;
- padding: $s-12;
- overflow-x: hidden;
- overflow-y: auto;
- font-size: $fs-12;
+ &.disabled {
+ border-color: var(--entry-border-color-disabled);
+ background-color: var(--entry-background-color-disabled);
+ }
- .history-entry {
- display: flex;
- justify-content: center;
- flex-direction: column;
- min-height: $s-32;
- margin: $s-4;
- padding: $s-4 $s-8;
- border: $s-2 solid transparent;
- border-radius: $s-8;
- background-color: var(--entry-background-color);
- cursor: pointer;
- transition: border 0.2s;
-
- &.disabled {
- border-color: var(--entry-border-color-disabled);
- background-color: var(--entry-background-color-disabled);
- }
-
- &.hover,
- &:hover {
- background-color: var(--entry-background-color-hover);
- color: var(--entry-foreground-color-hover);
- .history-entry-summary {
- .history-entry-summary-icon {
- svg {
- stroke: var(--entry-foreground-color-hover);
- }
- }
- .history-entry-summary-button {
- opacity: $op-10;
- &.button-opened {
- svg {
- transform: rotate(90deg);
- }
- }
- }
+ &.hover,
+ &:hover {
+ background-color: var(--entry-background-color-hover);
+ color: var(--entry-foreground-color-hover);
+ .history-entry-summary {
+ .history-entry-summary-icon {
+ svg {
+ stroke: var(--entry-foreground-color-hover);
}
}
-
- .history-entry-summary {
- display: flex;
- align-items: center;
- .history-entry-summary-icon {
+ .history-entry-summary-button {
+ opacity: $op-10;
+ &.button-opened {
svg {
- @extend .button-icon-small;
- stroke: var(--entry-foreground-color);
+ transform: rotate(90deg);
}
}
- .history-entry-summary-text {
- margin: 0 $s-8;
- }
- .history-entry-summary-button {
- opacity: $op-0;
- margin-left: auto;
- &.button-opened {
- svg {
- transform: rotate(90deg);
- }
- }
- svg {
- @extend .button-icon-small;
- stroke: var(--entry-foreground-color);
- }
- }
- }
-
- .history-entry-detail {
- display: block;
- padding-top: $s-16;
-
- ul.history-entry-details-list {
- margin: 0;
- }
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs
index 76886baa48..763adb7fbb 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs
@@ -16,7 +16,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
- [app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
[app.main.ui.context :as ctx]
[app.main.ui.viewer.inspect.right-sidebar :as hrs]
[app.main.ui.workspace.sidebar.options.menus.align :refer [align-options]]
@@ -78,8 +77,7 @@
(mf/defc options-content
{::mf/wrap [mf/memo]}
[{:keys [selected section shapes shapes-with-children page-id file-id on-change-section on-expand]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- drawing (mf/deref refs/workspace-drawing)
+ (let [drawing (mf/deref refs/workspace-drawing)
objects (mf/deref refs/workspace-page-objects)
shared-libs (mf/deref refs/workspace-libraries)
edition (mf/deref refs/selected-edition)
@@ -100,144 +98,74 @@
(if (= options-mode :inspect)
(st/emit! :interrupt (udw/set-workspace-read-only true))
(st/emit! :interrupt (udw/set-workspace-read-only false))))]
- (if ^boolean new-css-system
- [:div {:class (stl/css :tool-window)}
- [:& tab-container
- {:on-change-tab on-change-tab
- :selected section
- :collapsable? false
- :content-class (stl/css :content-class)
- :class (stl/css :tab-spacing)}
- [:& tab-element {:id :design
- :title (tr "workspace.options.design")}
- [:div {:class (stl/css :element-options)}
- [:& align-options]
- [:& bool-options]
- (cond
- (and edit-grid? (d/not-empty? selected-cells))
- [:& grid-cell/options
- {:shape (get objects edition)
- :cells selected-cells}]
+ [:div {:class (stl/css :tool-window)}
+ [:& tab-container
+ {:on-change-tab on-change-tab
+ :selected section
+ :collapsable? false
+ :content-class (stl/css :content-class)
+ :class (stl/css :tab-spacing)}
+ [:& tab-element {:id :design
+ :title (tr "workspace.options.design")}
+ [:div {:class (stl/css :element-options)}
+ [:& align-options]
+ [:& bool-options]
- edit-grid?
- [:& layout-container/grid-layout-edition
- {:ids [edition]
- :values (get objects edition)}]
+ (cond
+ (and edit-grid? (d/not-empty? selected-cells))
+ [:& grid-cell/options
+ {:shape (get objects edition)
+ :cells selected-cells}]
- (not (nil? sp-panel))
- [:& specialized-panel {:panel sp-panel}]
+ edit-grid?
+ [:& layout-container/grid-layout-edition
+ {:ids [edition]
+ :values (get objects edition)}]
- (d/not-empty? drawing)
- [:& shape-options
- {:shape (:object drawing)
- :page-id page-id
- :file-id file-id
- :shared-libs shared-libs}]
+ (not (nil? sp-panel))
+ [:& specialized-panel {:panel sp-panel}]
- (= 0 (count selected))
- [:& page/options]
+ (d/not-empty? drawing)
+ [:& shape-options
+ {:shape (:object drawing)
+ :page-id page-id
+ :file-id file-id
+ :shared-libs shared-libs}]
- (= 1 (count selected))
- [:& shape-options
- {:shape (first selected-shapes)
- :page-id page-id
- :file-id file-id
- :shared-libs shared-libs
- :shapes-with-children shapes-with-children}]
+ (= 0 (count selected))
+ [:& page/options]
- :else
- [:& multiple/options
- {:shapes-with-children shapes-with-children
- :shapes selected-shapes
- :page-id page-id
- :file-id file-id
- :shared-libs shared-libs}])]]
- [:& tab-element {:id :prototype
- :title (tr "workspace.options.prototype")}
- [:div {:class (stl/css :element-options)}
- [:& interactions-menu {:shape (first shapes)}]]]
- [:& tab-element {:id :inspect
- :title (tr "workspace.options.inspect")}
- [:div {:class (stl/css :element-options)}
- [:& hrs/right-sidebar {:page-id page-id
- :objects objects
- :file-id file-id
- :frame shape-parent-frame
- :shapes selected-shapes
- :on-change-section on-change-section
- :on-expand on-expand
- :from :workspace}]]]]]
+ (= 1 (count selected))
+ [:& shape-options
+ {:shape (first selected-shapes)
+ :page-id page-id
+ :file-id file-id
+ :shared-libs shared-libs
+ :shapes-with-children shapes-with-children}]
- [:div.tool-window
- [:div.tool-window-content
- [:& tabs-container {:on-change-tab on-change-tab
- :selected section}
- [:& tabs-element {:id :design
- :title (tr "workspace.options.design")}
- [:div.element-options
- [:& align-options]
- [:& bool-options]
- (cond
- (d/not-empty? selected-cells)
- [:& grid-cell/options
- {:shape (get objects edition)
- :cells selected-cells}]
-
- edit-grid?
- [:& layout-container/grid-layout-edition
- {:ids [edition]
- :values (get objects edition)}]
-
- sp-panel
- [:& specialized-panel {:panel sp-panel}]
-
-
- (d/not-empty? drawing)
- [:& shape-options
- {:shape (:object drawing)
- :page-id page-id
- :file-id file-id
- :shared-libs shared-libs}]
-
- (= 0 (count selected))
- [:& page/options]
-
- (= 1 (count selected))
- [:& shape-options
- {:shape (first selected-shapes)
- :page-id page-id
- :file-id file-id
- :shared-libs shared-libs
- :shapes-with-children shapes-with-children}]
-
- :else
- [:& multiple/options
- {:shapes-with-children shapes-with-children
- :shapes selected-shapes
- :page-id page-id
- :file-id file-id
- :shared-libs shared-libs}])]]
-
- [:& tabs-element
- {:id :prototype
- :title (tr "workspace.options.prototype")}
-
- [:div.element-options
- [:& interactions-menu {:shape (first shapes)}]]]
-
- [:& tabs-element {:id :inspect
- :title (tr "workspace.options.inspect")}
-
- [:div.element-options.element-options-inspect
- [:& hrs/right-sidebar {:page-id page-id
- :objects objects
- :file-id file-id
- :frame shape-parent-frame
- :shapes selected-shapes
- :on-change-section on-change-section
- :on-expand on-expand
- :from :workspace}]]]]]])))
+ :else
+ [:& multiple/options
+ {:shapes-with-children shapes-with-children
+ :shapes selected-shapes
+ :page-id page-id
+ :file-id file-id
+ :shared-libs shared-libs}])]]
+ [:& tab-element {:id :prototype
+ :title (tr "workspace.options.prototype")}
+ [:div {:class (stl/css :element-options)}
+ [:& interactions-menu {:shape (first shapes)}]]]
+ [:& tab-element {:id :inspect
+ :title (tr "workspace.options.inspect")}
+ [:div {:class (stl/css :element-options)}
+ [:& hrs/right-sidebar {:page-id page-id
+ :objects objects
+ :file-id file-id
+ :frame shape-parent-frame
+ :shapes selected-shapes
+ :on-change-section on-change-section
+ :on-expand on-expand
+ :from :workspace}]]]]]))
;; TODO: this need optimizations, selected-objects and
;; selected-objects-with-children are derefed always but they only
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.scss b/frontend/src/app/main/ui/workspace/sidebar/options.scss
index 46aeb77458..7b67bcf8c6 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options.scss
@@ -13,24 +13,24 @@
width: 100%;
height: 100%;
padding-left: $s-12;
-
- .tab-spacing {
- margin-right: $s-12;
- margin-bottom: $s-8;
- }
-
- .content-class {
- overflow-y: auto;
- overflow-x: hidden;
- height: calc(100vh - $s-96);
- scrollbar-gutter: stable;
- }
-
- .element-options {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- gap: $s-8;
- }
+}
+
+.tab-spacing {
+ margin-right: $s-12;
+ margin-bottom: $s-8;
+}
+
+.content-class {
+ overflow-y: auto;
+ overflow-x: hidden;
+ height: calc(100vh - $s-96);
+ scrollbar-gutter: stable;
+}
+
+.element-options {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: $s-8;
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs
index dbe756c224..1efb38e5a0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs
@@ -8,27 +8,19 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
- [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
(mf/defc advanced-options [{:keys [visible? class children]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- ref (mf/use-ref nil)]
+ (let [ref (mf/use-ref nil)]
(mf/use-effect
(mf/deps visible?)
(fn []
(when-let [node (mf/ref-val ref)]
(when visible?
(dom/scroll-into-view-if-needed! node)))))
- (if new-css-system
- (when visible?
- [:div {:class (dm/str class " " (stl/css :advanced-options-wrapper))
- :ref ref}
- children])
-
- (when visible?
- [:div.advanced-options-wrapper {:ref ref}
- [:div.advanced-options {}
- children]]))))
+ (when visible?
+ [:div {:class (dm/str class " " (stl/css :advanced-options-wrapper))
+ :ref ref}
+ children])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.cljs
index 1632e7b51a..fc7758d99f 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.cljs
@@ -11,7 +11,6 @@
[app.main.data.workspace.shortcuts :as sc]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -19,9 +18,8 @@
(mf/defc align-options
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- selected (mf/deref refs/selected-shapes)
- ;; don't need to watch objects, only read the value
+ (let [selected (mf/deref refs/selected-shapes)
+ ;; don't need to watch objects, only read the value
objects (deref refs/workspace-page-objects)
disabled-align (not (dw/can-align? selected objects))
@@ -44,130 +42,70 @@
(st/emit! (dw/distribute-objects value)))))]
(when (not (and disabled-align disabled-distribute))
- (if new-css-system
- [:div {:class (stl/css :align-options)}
- [:div {:class (stl/css :align-group)}
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-align)
- :disabled disabled-align
- :title (tr "workspace.align.hleft" (sc/get-tooltip :align-left))
- :data-value :hleft
- :on-click align-objects}
- i/align-left-refactor]
+ [:div {:class (stl/css :align-options)}
+ [:div {:class (stl/css :align-group)}
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-align)
+ :disabled disabled-align
+ :title (tr "workspace.align.hleft" (sc/get-tooltip :align-left))
+ :data-value :hleft
+ :on-click align-objects}
+ i/align-left-refactor]
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-align)
- :disabled disabled-align
- :title (tr "workspace.align.hcenter" (sc/get-tooltip :align-hcenter))
- :data-value :hcenter
- :on-click align-objects}
- i/align-horizontal-center-refactor]
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-align)
+ :disabled disabled-align
+ :title (tr "workspace.align.hcenter" (sc/get-tooltip :align-hcenter))
+ :data-value :hcenter
+ :on-click align-objects}
+ i/align-horizontal-center-refactor]
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-align)
- :disabled disabled-align
- :title (tr "workspace.align.hright" (sc/get-tooltip :align-right))
- :data-value :hright
- :on-click align-objects}
- i/align-right-refactor]
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-align)
+ :disabled disabled-align
+ :title (tr "workspace.align.hright" (sc/get-tooltip :align-right))
+ :data-value :hright
+ :on-click align-objects}
+ i/align-right-refactor]
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-distribute)
- :disabled disabled-distribute
- :title (tr "workspace.align.hdistribute" (sc/get-tooltip :h-distribute))
- :data-value :horizontal
- :on-click distribute-objects}
- i/distribute-horizontally-refactor]]
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-distribute)
+ :disabled disabled-distribute
+ :title (tr "workspace.align.hdistribute" (sc/get-tooltip :h-distribute))
+ :data-value :horizontal
+ :on-click distribute-objects}
+ i/distribute-horizontally-refactor]]
- [:div {:class (stl/css :align-group)}
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-align)
- :disabled disabled-align
- :title (tr "workspace.align.vtop" (sc/get-tooltip :align-top))
- :data-value :vtop
- :on-click align-objects}
- i/align-top-refactor]
+ [:div {:class (stl/css :align-group)}
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-align)
+ :disabled disabled-align
+ :title (tr "workspace.align.vtop" (sc/get-tooltip :align-top))
+ :data-value :vtop
+ :on-click align-objects}
+ i/align-top-refactor]
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-align)
- :disabled disabled-align
- :title (tr "workspace.align.vcenter" (sc/get-tooltip :align-vcenter))
- :data-value :vcenter
- :on-click align-objects}
- i/align-vertical-center-refactor]
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-align)
+ :disabled disabled-align
+ :title (tr "workspace.align.vcenter" (sc/get-tooltip :align-vcenter))
+ :data-value :vcenter
+ :on-click align-objects}
+ i/align-vertical-center-refactor]
- [:button {:class (stl/css-case :align-button true
- :disabled disabled-align)
- :disabled disabled-align
- :title (tr "workspace.align.vbottom" (sc/get-tooltip :align-bottom))
- :data-value :vbottom
- :on-click align-objects}
- i/align-bottom-refactor]
+ [:button {:class (stl/css-case :align-button true
+ :disabled disabled-align)
+ :disabled disabled-align
+ :title (tr "workspace.align.vbottom" (sc/get-tooltip :align-bottom))
+ :data-value :vbottom
+ :on-click align-objects}
+ i/align-bottom-refactor]
- [:button {:title (tr "workspace.align.vdistribute" (sc/get-tooltip :v-distribute))
- :class (stl/css-case :align-button true
- :disabled disabled-distribute)
- :disabled disabled-distribute
- :data-value :vertical
- :on-click distribute-objects}
- i/distribute-vertical-spacing-refactor]]]
-
- [:div.align-options
- [:div.align-group
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (tr "workspace.align.hleft" (sc/get-tooltip :align-left))
- :class (when disabled-align "disabled")
- :data-value :hleft
- :on-click align-objects}
- i/shape-halign-left]
-
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (tr "workspace.align.hcenter" (sc/get-tooltip :align-hcenter))
- :class (when disabled-align "disabled")
- :data-value :hcenter
- :on-click align-objects}
- i/shape-halign-center]
-
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (tr "workspace.align.hright" (sc/get-tooltip :align-right))
- :class (when disabled-align "disabled")
- :data-value :hright
- :on-click align-objects}
- i/shape-halign-right]
-
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (tr "workspace.align.hdistribute" (sc/get-tooltip :h-distribute))
- :class (when disabled-distribute "disabled")
- :data-value :horizontal
- :on-click distribute-objects}
- i/shape-hdistribute]]
-
- [:div.align-group
- [:div.align-button.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.align.vtop" (sc/get-tooltip :align-top))
- :class (when disabled-align "disabled")
- :data-value :vtop
- :on-click align-objects}
- i/shape-valign-top]
-
- [:div.align-button.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.align.vcenter" (sc/get-tooltip :align-vcenter))
- :class (when disabled-align "disabled")
- :data-value :vcenter
- :on-click align-objects}
- i/shape-valign-center]
-
- [:div.align-button.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.align.vbottom" (sc/get-tooltip :align-bottom))
- :class (when disabled-align "disabled")
- :data-value :vbottom
- :on-click align-objects}
- i/shape-valign-bottom]
-
- [:div.align-button.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.align.vdistribute" (sc/get-tooltip :v-distribute))
- :class (when disabled-distribute "disabled")
- :data-value :vertical
- :on-click distribute-objects}
- i/shape-vdistribute]]]))))
+ [:button {:title (tr "workspace.align.vdistribute" (sc/get-tooltip :v-distribute))
+ :class (stl/css-case :align-button true
+ :disabled disabled-distribute)
+ :disabled disabled-distribute
+ :data-value :vertical
+ :on-click distribute-objects}
+ i/distribute-vertical-spacing-refactor]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.scss
index d141e7fd59..8294f1d8b7 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/align.scss
@@ -11,29 +11,30 @@
gap: $s-4;
height: $s-32;
margin: 0 calc(-1 * $s-2);
- .align-group {
- @include flexRow;
- .align-button {
- @extend .button-tertiary;
- height: $s-28;
- width: $s-28;
- padding: 0;
- border-radius: $br-8;
+}
+.align-group {
+ @include flexRow;
+}
+
+.align-button {
+ @extend .button-tertiary;
+ height: $s-28;
+ width: $s-28;
+ padding: 0;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ &.disabled {
+ cursor: default;
+ svg {
+ stroke: var(--button-background-color-disabled);
+ }
+ &:hover {
+ background-color: var(--panel-background-color);
svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- &.disabled {
- cursor: default;
- svg {
- stroke: var(--button-background-color-disabled);
- }
- &:hover {
- background-color: var(--panel-background-color);
- svg {
- stroke: var(--button-background-color-disabled);
- }
- }
+ stroke: var(--button-background-color-disabled);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs
index d24bce38a2..989d262b11 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs
@@ -12,9 +12,7 @@
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -28,10 +26,8 @@
:hidden false}))
(mf/defc blur-menu [{:keys [ids type values]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- blur (:blur values)
+ (let [blur (:blur values)
has-value? (not (nil? blur))
- multiple? (= blur :multiple)
state* (mf/use-state {:show-content true
:show-more-options false})
@@ -79,76 +75,47 @@
(fn []
(change! #(update-in % [:blur :hidden] not))))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-value?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title (case type
- :multiple (tr "workspace.options.blur-options.title.multiple")
- :group (tr "workspace.options.blur-options.title.group")
- (tr "workspace.options.blur-options.title"))
- :class (stl/css-case :title-spacing-blur (not has-value?))}
- (when-not has-value?
- [:button {:class (stl/css :add-blur)
- :on-click handle-add} i/add-refactor])]]
- (when (and open? has-value?)
- [:div {:class (stl/css :element-set-content)}
- [:div {:class (stl/css-case :first-row true
- :hidden hidden?)}
- [:div {:class (stl/css :blur-info)}
- [:button {:class (stl/css-case :show-more true
- :selected more-options?)
- :on-click toggle-more-options}
- i/menu-refactor]
- [:span {:class (stl/css :label)}
- (tr "workspace.options.blur-options.title")]]
- [:div {:class (stl/css :actions)}
- [:button {:class (stl/css :action-btn)
- :on-click handle-toggle-visibility}
- (if hidden?
- i/hide-refactor
- i/shown-refactor)]
- [:button {:class (stl/css :action-btn)
- :on-click handle-delete} i/remove-refactor]]]
- (when more-options?
- [:div {:class (stl/css :second-row)}
- [:label {:class (stl/css :label)
- :for "blur-input-sidebar"}
- (tr "inspect.attributes.blur.value")]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :id "blur-input-sidebar"
- :min "0"
- :on-change handle-change
- :value (:value blur)}]])])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span
- (case type
- :multiple (tr "workspace.options.blur-options.title.multiple")
- :group (tr "workspace.options.blur-options.title.group")
- (tr "workspace.options.blur-options.title"))]
-
- [:div.element-set-title-actions
- (when (and has-value? (not multiple?))
- [:div.add-page {:on-click handle-toggle-visibility}
- (if hidden? i/eye-closed i/eye)])
-
- (if has-value?
- [:div.add-page {:on-click handle-delete} i/minus]
- [:div.add-page {:on-click handle-add} i/close])]]
-
- (cond
- has-value?
- [:div.element-set-content
- [:& input-row {:label "Value"
- :class "pixels"
- :min "0"
- :value (:value blur)
- :placeholder (tr "settings.multiple")
- :on-change handle-change}]])])))
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-value?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (case type
+ :multiple (tr "workspace.options.blur-options.title.multiple")
+ :group (tr "workspace.options.blur-options.title.group")
+ (tr "workspace.options.blur-options.title"))
+ :class (stl/css-case :title-spacing-blur (not has-value?))}
+ (when-not has-value?
+ [:button {:class (stl/css :add-blur)
+ :on-click handle-add} i/add-refactor])]]
+ (when (and open? has-value?)
+ [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css-case :first-row true
+ :hidden hidden?)}
+ [:div {:class (stl/css :blur-info)}
+ [:button {:class (stl/css-case :show-more true
+ :selected more-options?)
+ :on-click toggle-more-options}
+ i/menu-refactor]
+ [:span {:class (stl/css :label)}
+ (tr "workspace.options.blur-options.title")]]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click handle-toggle-visibility}
+ (if hidden?
+ i/hide-refactor
+ i/shown-refactor)]
+ [:button {:class (stl/css :action-btn)
+ :on-click handle-delete} i/remove-refactor]]]
+ (when more-options?
+ [:div {:class (stl/css :second-row)}
+ [:label {:class (stl/css :label)
+ :for "blur-input-sidebar"}
+ (tr "inspect.attributes.blur.value")]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :id "blur-input-sidebar"
+ :min "0"
+ :on-change handle-change
+ :value (:value blur)}]])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss
index 6559fdd1d4..6bed44856a 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss
@@ -8,13 +8,73 @@
.element-set {
margin: 0;
- .element-title {
- .title-spacing-blur {
- padding-left: $s-2;
- margin: 0;
+}
+
+.title-spacing-blur {
+ padding-left: $s-2;
+ margin: 0;
+}
+
+.add-blur {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.element-set-content {
+ @include flexColumn;
+ margin-bottom: $s-8;
+}
+
+.first-row {
+ @include flexRow;
+ width: 100%;
+ .blur-info {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ flex-grow: 1;
+ border-radius: $br-8;
+ background-color: var(--input-details-color);
+ .show-more {
+ @extend .button-secondary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8 0 0 $br-8;
+ box-sizing: border-box;
+ border: $s-1 solid var(--button-secondary-background-color-rest);
+ svg {
+ @extend .button-icon;
+ }
+ &.selected {
+ background-color: var(--button-radio-background-color-active);
+ svg {
+ stroke: var(--button-radio-foreground-color-active);
+ }
+ }
}
- .add-blur {
+ .label {
+ @include titleTipography;
+ flex-grow: 1;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ padding: 0 $s-8;
+ border-radius: 0 $br-8 $br-8 0;
+ background-color: var(--input-background-color);
+ color: var(--menu-foreground-color);
+ box-sizing: border-box;
+ border: $s-1 solid var(--input-background-color);
+ }
+ }
+ .actions {
+ @include flexRow;
+ .action-btn {
@extend .button-tertiary;
+ box-sizing: border-box;
height: $s-32;
width: $s-28;
svg {
@@ -22,85 +82,27 @@
}
}
}
- .element-set-content {
- @include flexColumn;
- margin-bottom: $s-8;
- .first-row {
- @include flexRow;
- width: 100%;
- .blur-info {
- display: flex;
- align-items: center;
- gap: $s-1;
- flex-grow: 1;
- border-radius: $br-8;
- background-color: var(--input-details-color);
- .show-more {
- @extend .button-secondary;
- height: $s-32;
- width: $s-28;
- border-radius: $br-8 0 0 $br-8;
- box-sizing: border-box;
- border: $s-1 solid var(--button-secondary-background-color-rest);
- svg {
- @extend .button-icon;
- }
- &.selected {
- background-color: var(--button-radio-background-color-active);
- svg {
- stroke: var(--button-radio-foreground-color-active);
- }
- }
- }
- .label {
- @include titleTipography;
- flex-grow: 1;
- display: flex;
- align-items: center;
- height: $s-32;
- padding: 0 $s-8;
- border-radius: 0 $br-8 $br-8 0;
- background-color: var(--input-background-color);
- color: var(--menu-foreground-color);
- box-sizing: border-box;
- border: $s-1 solid var(--input-background-color);
- }
- }
- .actions {
- @include flexRow;
- .action-btn {
- @extend .button-tertiary;
- box-sizing: border-box;
- border: $s-1 solid var(--button-tertiary-background-color-rest);
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- &.hidden {
- .blur-info {
- @include hiddenElement;
- .show-more {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- .label {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- }
+ &.hidden {
+ .blur-info {
+ @include hiddenElement;
+ .show-more {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
}
- }
- .second-row {
- @extend .input-element;
- width: $s-92;
.label {
- padding-left: $s-8;
- width: $s-60;
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
}
}
}
}
+
+.second-row {
+ @extend .input-element;
+ width: $s-92;
+ .label {
+ padding-left: $s-8;
+ width: $s-60;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs
index bae6919402..7a25e1bf55 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs
@@ -13,19 +13,13 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
-
-
(mf/defc bool-options
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- selected (mf/deref refs/selected-objects)
+ (let [selected (mf/deref refs/selected-objects)
head (first selected)
selected-with-children (mf/deref refs/selected-shapes-with-children)
has-invalid-shapes? (->> selected-with-children
@@ -42,39 +36,10 @@
disabled-flatten (or (empty? selected) has-invalid-shapes?)
set-bool
- (mf/use-fn
- (mf/deps head head-bool-type selected)
- (fn [event]
- (let [bool-type (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))]
- (cond
- (> (count selected) 1)
- (st/emit! (dw/create-bool (if new-css-system
- (keyword bool-type)
- bool-type)))
-
- (and (= (count selected) 1) is-group?)
- (st/emit! (dw/group-to-bool (:id head) (if new-css-system
- (keyword bool-type)
- bool-type)))
-
- (and (= (count selected) 1) is-bool?)
- (if (= head-bool-type (if new-css-system
- (keyword bool-type)
- bool-type))
- (st/emit! (dw/bool-to-group (:id head)))
- (st/emit! (dw/change-bool-type (:id head) (if new-css-system
- (keyword bool-type)
- bool-type))))))))
-
- set-bool-refactor
(mf/use-fn
(mf/deps selected is-group? is-bool?)
(fn [bool-type]
- (let [bool-type (if new-css-system
- (keyword bool-type)
- bool-type)]
+ (let [bool-type (keyword bool-type)]
(cond
(> (count selected) 1)
(st/emit! (dw/create-bool bool-type))
@@ -90,82 +55,40 @@
flatten-objects (mf/use-fn #(st/emit! (dw/convert-selected-to-path)))]
(when (not (and disabled-bool-btns disabled-flatten))
- (if new-css-system
- [:div {:class (stl/css :boolean-options)}
- [:div {:class (stl/css :bool-group)}
- [:& radio-buttons {:selected (d/name head-bool-type)
- :class (stl/css :boolean-radio-btn)
- :on-change set-bool-refactor
- :name "bool-options"}
- [:& radio-button {:icon i/boolean-union-refactor
- :value "union"
- :disabled disabled-bool-btns
- :title (str (tr "workspace.shape.menu.union") " (" (sc/get-tooltip :bool-union) ")")
- :id "bool-opt-union"}]
- [:& radio-button {:icon i/boolean-difference-refactor
- :value "difference"
- :disabled disabled-bool-btns
- :title (str (tr "workspace.shape.menu.difference") " (" (sc/get-tooltip :bool-difference) ")")
- :id "bool-opt-differente"}]
- [:& radio-button {:icon i/boolean-intersection-refactor
- :value "intersection"
- :disabled disabled-bool-btns
- :title (str (tr "intersection") " (" (sc/get-tooltip :bool-intersection) ")")
- :id "bool-opt-intersection"}]
- [:& radio-button {:icon i/boolean-exclude-refactor
- :value "exclude"
- :disabled disabled-bool-btns
- :title (str (tr "exclude") " (" (sc/get-tooltip :bool-exclude) ")")
- :id "bool-opt-exclude"}]]]
+ [:div {:class (stl/css :boolean-options)}
+ [:div {:class (stl/css :bool-group)}
+ [:& radio-buttons {:selected (d/name head-bool-type)
+ :class (stl/css :boolean-radio-btn)
+ :on-change set-bool
+ :name "bool-options"}
+ [:& radio-button {:icon i/boolean-union-refactor
+ :value "union"
+ :disabled disabled-bool-btns
+ :title (str (tr "workspace.shape.menu.union") " (" (sc/get-tooltip :bool-union) ")")
+ :id "bool-opt-union"}]
+ [:& radio-button {:icon i/boolean-difference-refactor
+ :value "difference"
+ :disabled disabled-bool-btns
+ :title (str (tr "workspace.shape.menu.difference") " (" (sc/get-tooltip :bool-difference) ")")
+ :id "bool-opt-differente"}]
+ [:& radio-button {:icon i/boolean-intersection-refactor
+ :value "intersection"
+ :disabled disabled-bool-btns
+ :title (str (tr "intersection") " (" (sc/get-tooltip :bool-intersection) ")")
+ :id "bool-opt-intersection"}]
+ [:& radio-button {:icon i/boolean-exclude-refactor
+ :value "exclude"
+ :disabled disabled-bool-btns
+ :title (str (tr "exclude") " (" (sc/get-tooltip :bool-exclude) ")")
+ :id "bool-opt-exclude"}]]]
- [:div {:class (stl/css :bool-group)}
- [:button
- {:title (tr "workspace.shape.menu.flatten")
- :class (stl/css-case
- :flatten true
- :disabled disabled-flatten)
- :disabled disabled-flatten
- :on-click flatten-objects}
- i/boolean-flatten-refactor]]]
-
- [:div.align-options
- [:div.align-group
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (str (tr "workspace.shape.menu.union") " (" (sc/get-tooltip :bool-union) ")")
- :class (dom/classnames :disabled disabled-bool-btns
- :selected (= head-bool-type :union))
- :data-value :union
- :on-click set-bool}
- i/bool-union]
-
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (str (tr "workspace.shape.menu.difference") " (" (sc/get-tooltip :bool-difference) ")")
- :class (dom/classnames :disabled disabled-bool-btns
- :selected (= head-bool-type :difference))
- :data-value :difference
- :on-click set-bool}
- i/bool-difference]
-
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (str (tr "workspace.shape.menu.intersection") " (" (sc/get-tooltip :bool-intersection) ")")
- :class (dom/classnames :disabled disabled-bool-btns
- :selected (= head-bool-type :intersection))
- :data-value :intersection
- :on-click set-bool}
- i/bool-intersection]
-
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (str (tr "workspace.shape.menu.exclude") " (" (sc/get-tooltip :bool-exclude) ")")
- :class (dom/classnames :disabled disabled-bool-btns
- :selected (= head-bool-type :exclude))
- :data-value :exclude
- :on-click set-bool}
- i/bool-exclude]]
-
- [:div.align-group
- [:div.align-button.tooltip.tooltip-bottom
- {:alt (tr "workspace.shape.menu.flatten")
- :class (dom/classnames :disabled disabled-flatten)
- :on-click flatten-objects}
- i/bool-flatten]]]))))
+ [:div {:class (stl/css :bool-group)}
+ [:button
+ {:title (tr "workspace.shape.menu.flatten")
+ :class (stl/css-case
+ :flatten true
+ :disabled disabled-flatten)
+ :disabled disabled-flatten
+ :on-click flatten-objects}
+ i/boolean-flatten-refactor]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.scss
index bf08806f5e..3cf1fa8fe6 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.scss
@@ -11,33 +11,36 @@
gap: $s-4;
height: $s-32;
margin: 0 calc(-1 * $s-2);
- .bool-group {
- display: flex;
- align-items: center;
- .flatten {
- @extend .button-tertiary;
- height: $s-28;
- width: $s-28;
- border-radius: $br-8;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- &.disabled {
- cursor: default;
- svg {
- stroke: var(--button-background-color-disabled);
- }
- &:hover {
- background-color: var(--panel-background-color);
- svg {
- stroke: var(--button-background-color-disabled);
- }
- }
- }
+}
+
+.bool-group {
+ display: flex;
+ align-items: center;
+}
+
+.flatten {
+ @extend .button-tertiary;
+ height: $s-28;
+ width: $s-28;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ &.disabled {
+ cursor: default;
+ svg {
+ stroke: var(--button-background-color-disabled);
}
- .boolean-radio-btn {
- background-color: transparent;
+ &:hover {
+ background-color: var(--panel-background-color);
+ svg {
+ stroke: var(--button-background-color-disabled);
+ }
}
}
}
+
+.boolean-radio-btn {
+ background-color: transparent;
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
index 47aac34fb4..6dce1cc000 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
@@ -14,8 +14,6 @@
[app.main.data.workspace.selection :as dws]
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
- [app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.util.i18n :as i18n :refer [tr]]
[cuerdas.core :as str]
@@ -158,7 +156,6 @@
[{:keys [shapes file-id shared-libs] :as props}]
(let [{:keys [grouped-colors library-colors colors]} (mf/with-memo [shapes file-id shared-libs]
(prepare-colors shapes file-id shared-libs))
- new-css-system (mf/use-ctx ctx/new-css-system)
state* (mf/use-state true)
open? (deref state*)
@@ -216,71 +213,17 @@
(mf/with-effect [grouped-colors]
(reset! grouped-colors* grouped-colors))
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-colors?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title (tr "workspace.options.selection-color")
- :class (stl/css-case :title-spacing-selected-colors (not has-colors?))}]]
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-colors?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.options.selection-color")
+ :class (stl/css-case :title-spacing-selected-colors (not has-colors?))}]]
- (when open?
- [:div {:class (stl/css :element-content)}
- [:div {:class (stl/css :selected-color-group)}
- (for [[index color] (d/enumerate (take 3 library-colors))]
- [:& color-row {:key (dm/str "library-color-" (:color color))
- :color color
- :index index
- :on-detach on-detach
- :select-only select-only
- :on-change #(on-change %1 color %2)
- :on-open on-open
- :on-close on-close}])
- (when (and (false? @expand-lib-color) (< 3 (count library-colors)))
- [:button {:class (stl/css :more-colors-btn)
- :on-click #(reset! expand-lib-color true)}
- (tr "workspace.options.more-lib-colors")])
- (when @expand-lib-color
- (for [[index color] (d/enumerate (drop 3 library-colors))]
- [:& color-row {:key (dm/str "library-color-" (:color color))
- :color color
- :index index
- :on-detach on-detach
- :select-only select-only
- :on-change #(on-change %1 color %2)
- :on-open on-open
- :on-close on-close}]))]
- [:div {:class (stl/css :selected-color-group)}
- (for [[index color] (d/enumerate (take 3 colors))]
- [:& color-row {:key (dm/str "color-" index)
- :color color
- :index index
- :select-only select-only
- :on-change #(on-change %1 color %2)
- :on-open on-open
- :on-close on-close}])
- (when (and (false? @expand-color) (< 3 (count colors)))
- [:button {:class (stl/css :more-colors-btn)
- :on-click #(reset! expand-color true)}
- (tr "workspace.options.more-colors")])
-
- (when @expand-color
- (for [[index color] (d/enumerate (drop 3 colors))]
- [:& color-row {:key (dm/str "color-" (:color color))
- :color color
- :index index
- :select-only select-only
- :on-change #(on-change %1 color %2)
- :on-open on-open
- :on-close on-close}]))]])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.selection-color")]]
- [:div.element-set-content
- [:div.selected-colors
+ (when open?
+ [:div {:class (stl/css :element-content)}
+ [:div {:class (stl/css :selected-color-group)}
(for [[index color] (d/enumerate (take 3 library-colors))]
[:& color-row {:key (dm/str "library-color-" (:color color))
:color color
@@ -291,9 +234,9 @@
:on-open on-open
:on-close on-close}])
(when (and (false? @expand-lib-color) (< 3 (count library-colors)))
- [:div.expand-colors {:on-click #(reset! expand-lib-color true)}
- [:span i/actions]
- [:span.text (tr "workspace.options.more-lib-colors")]])
+ [:button {:class (stl/css :more-colors-btn)
+ :on-click #(reset! expand-lib-color true)}
+ (tr "workspace.options.more-lib-colors")])
(when @expand-lib-color
(for [[index color] (d/enumerate (drop 3 library-colors))]
[:& color-row {:key (dm/str "library-color-" (:color color))
@@ -304,8 +247,7 @@
:on-change #(on-change %1 color %2)
:on-open on-open
:on-close on-close}]))]
-
- [:div.selected-colors
+ [:div {:class (stl/css :selected-color-group)}
(for [[index color] (d/enumerate (take 3 colors))]
[:& color-row {:key (dm/str "color-" index)
:color color
@@ -315,9 +257,10 @@
:on-open on-open
:on-close on-close}])
(when (and (false? @expand-color) (< 3 (count colors)))
- [:div.expand-colors {:on-click #(reset! expand-color true)}
- [:span i/actions]
- [:span.text (tr "workspace.options.more-colors")]])
+ [:button {:class (stl/css :more-colors-btn)
+ :on-click #(reset! expand-color true)}
+ (tr "workspace.options.more-colors")])
+
(when @expand-color
(for [[index color] (d/enumerate (drop 3 colors))]
[:& color-row {:key (dm/str "color-" (:color color))
@@ -326,4 +269,4 @@
:select-only select-only
:on-change #(on-change %1 color %2)
:on-open on-open
- :on-close on-close}]))]]])))
+ :on-close on-close}]))]])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss
index eb8ca850c3..56e096768f 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss
@@ -8,30 +8,33 @@
.element-set {
margin: 0;
- .element-title {
- .title-spacing-selected-colors {
- padding-left: $s-2;
- margin: 0;
- }
- .add-fill {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- .element-content {
- @include flexColumn;
- margin-bottom: $s-8;
- .selected-color-group {
- @include flexColumn;
- .more-colors-btn {
- @extend .button-secondary;
- @include tabTitleTipography;
- height: $s-32;
- }
- }
+}
+
+.title-spacing-selected-colors {
+ padding-left: $s-2;
+ margin: 0;
+}
+
+.add-fill {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
}
+
+.element-content {
+ @include flexColumn;
+ margin-bottom: $s-8;
+}
+
+.selected-color-group {
+ @include flexColumn;
+}
+
+.more-colors-btn {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ height: $s-32;
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs
index c000ac90c8..40cef86426 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs
@@ -147,7 +147,6 @@
(when (or @editing? creating?)
[:div.counter (str @size "/300")])]])))
-
(mf/defc component-swap-item
{::mf/wrap-props false}
[{:keys [item loop shapes file-id root-shape container component-id is-search listing-thumbs] :as props}]
@@ -190,7 +189,6 @@
[:span {:class (stl/css :component-group-name)} (cfh/last-path group-name)]]
[:span i/arrow-slide]]))
-
(mf/defc component-swap
[{:keys [shapes] :as props}]
(let [single? (= 1 (count shapes))
@@ -405,7 +403,6 @@
[:span {:class (stl/css :dropdown-label)}
(tr (:msg entry))]])]]))
-
(mf/defc component-menu
[{:keys [shapes swap-opened?] :as props}]
(let [current-file-id (mf/use-ctx ctx/current-file-id)
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs
index a61c6314a3..35b72810ef 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs
@@ -16,7 +16,6 @@
[app.main.store :as st]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -31,9 +30,7 @@
(mf/defc constraints-menu
[{:keys [ids values] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- state* (mf/use-state true)
+ (let [state* (mf/use-state true)
open? (deref state*)
toggle-content (mf/use-fn #(swap! state* not))
@@ -109,19 +106,6 @@
ids
#(assoc % constraint new-value))))))
- on-constraint-select-changed
- (mf/use-fn
- (mf/deps ids)
- (fn [event]
- (let [constraint (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))
- value (-> (dom/get-target-val event) (keyword))]
- (when-not (str/empty? value)
- (st/emit! (dch/update-shapes
- ids
- #(assoc % constraint value)))))))
-
on-constraint-h-select-changed
(mf/use-fn
(mf/deps ids)
@@ -171,154 +155,79 @@
;; CONSTRAINTS
(when in-frame?
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? true
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title (tr "workspace.options.constraints")}]]
- (when open?
- [:div {:class (stl/css :element-set-content)}
- [:div {:class (stl/css :constraints-widget)}
- [:div {:class (stl/css :constraints-top)}
- [:button {:class (stl/css-case :constraint-btn true
- :active (or (= constraints-v :top)
- (= constraints-v :topbottom)))
- :data-value :top
- :on-click on-constraint-button-clicked}
- [:span {:class (stl/css :resalted-area)}]]]
- [:div {:class (stl/css :constraints-left)}
- [:button {:class (stl/css-case :constraint-btn true
- :constraint-btn-rotated true
- :active (or (= constraints-h :left)
- (= constraints-h :leftright)))
- :data-value :left
- :on-click on-constraint-button-clicked}
- [:span {:class (stl/css :resalted-area)}]]]
- [:div {:class (stl/css :constraints-center)}
- [:button {:class (stl/css-case :constraint-btn true
- :active (= constraints-h :center))
- :data-value :centerh
- :on-click on-constraint-button-clicked}
- [:span {:class (stl/css :resalted-area)}]]
- [:button {:class (stl/css-case :constraint-btn-special true
- :constraint-btn-rotated true
- :active (= constraints-v :center))
- :data-value :centerv
- :on-click on-constraint-button-clicked}
- [:span {:class (stl/css :resalted-area)}]]]
- [:div {:class (stl/css :constraints-right)}
- [:button {:class (stl/css-case :constraint-btn true
- :constraint-btn-rotated true
- :active (or (= constraints-h :right)
- (= constraints-h :leftright)))
- :data-value :right
- :on-click on-constraint-button-clicked}
- [:span {:class (stl/css :resalted-area)}]]]
- [:div {:class (stl/css :constraints-bottom)}
- [:button {:class (stl/css-case :constraint-btn true
- :active (or (= constraints-v :bottom)
- (= constraints-v :topbottom)))
- :data-value :bottom
- :on-click on-constraint-button-clicked}
- [:span {:class (stl/css :resalted-area)}]]]]
- [:div {:class (stl/css :contraints-selects)}
- [:div {:class (stl/css :horizontal-select)}
- [:& select
- {:default-value (d/name constraints-h "scale")
- :options options-h
- :on-change on-constraint-h-select-changed}]]
- [:div {:class (stl/css :vertical-select)}
- [:& select
- {:default-value (d/name constraints-v "scale")
- :options options-v
- :on-change on-constraint-v-select-changed}]]
- (when first-level?
- [:div {:class (stl/css :checkbox)}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.options.constraints")}]]
+ (when open?
+ [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :constraints-widget)}
+ [:div {:class (stl/css :constraints-top)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :active (or (= constraints-v :top)
+ (= constraints-v :topbottom)))
+ :data-value :top
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-left)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :constraint-btn-rotated true
+ :active (or (= constraints-h :left)
+ (= constraints-h :leftright)))
+ :data-value :left
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-center)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :active (= constraints-h :center))
+ :data-value :centerh
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]
+ [:button {:class (stl/css-case :constraint-btn-special true
+ :constraint-btn-rotated true
+ :active (= constraints-v :center))
+ :data-value :centerv
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-right)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :constraint-btn-rotated true
+ :active (or (= constraints-h :right)
+ (= constraints-h :leftright)))
+ :data-value :right
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-bottom)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :active (or (= constraints-v :bottom)
+ (= constraints-v :topbottom)))
+ :data-value :bottom
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]]
+ [:div {:class (stl/css :contraints-selects)}
+ [:div {:class (stl/css :horizontal-select)}
+ [:& select
+ {:default-value (d/name constraints-h "scale")
+ :options options-h
+ :on-change on-constraint-h-select-changed}]]
+ [:div {:class (stl/css :vertical-select)}
+ [:& select
+ {:default-value (d/name constraints-v "scale")
+ :options options-v
+ :on-change on-constraint-v-select-changed}]]
+ (when first-level?
+ [:div {:class (stl/css :checkbox)}
- [:label {:for "fixed-on-scroll"
- :class (stl/css-case :checked (:fixed-scroll values))}
- [:span {:class (stl/css-case :check-mark true
- :checked (:fixed-scroll values))}
- (when (:fixed-scroll values)
- i/status-tick-refactor)]
- (tr "workspace.options.constraints.fix-when-scrolling")
- [:input {:type "checkbox"
- :id "fixed-on-scroll"
- :checked (:fixed-scroll values)
- :on-change on-fixed-scroll-clicked}]]])]])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.constraints")]]
-
- [:div.element-set-content
- [:div.row-flex.align-top
- [:div.constraints-widget
- [:div.constraints-box]
- [:div.constraint-button.top
- {:class (dom/classnames :active (or (= constraints-v :top)
- (= constraints-v :topbottom)))
- :data-value :top
- :on-click on-constraint-button-clicked}]
- [:div.constraint-button.bottom
- {:class (dom/classnames :active (or (= constraints-v :bottom)
- (= constraints-v :topbottom)))
- :data-value :bottom
- :on-click on-constraint-button-clicked}]
- [:div.constraint-button.left
- {:class (dom/classnames :active (or (= constraints-h :left)
- (= constraints-h :leftright)))
- :data-value :left
- :on-click on-constraint-button-clicked}]
- [:div.constraint-button.right
- {:class (dom/classnames :active (or (= constraints-h :right)
- (= constraints-h :leftright)))
- :data-value :right
- :on-click on-constraint-button-clicked}]
- [:div.constraint-button.centerv
- {:class (dom/classnames :active (= constraints-v :center))
- :data-value :centerv
- :on-click on-constraint-button-clicked}]
- [:div.constraint-button.centerh
- {:class (dom/classnames :active (= constraints-h :center))
- :data-value :centerh
- :on-click on-constraint-button-clicked}]]
-
- [:div.constraints-form
- [:div.row-flex
- [:span.left-right i/full-screen]
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :data-value :constraints-h
- :on-change on-constraint-select-changed
- :value (d/name constraints-h "scale")}
- (when (= constraints-h :multiple)
- [:option {:value ""} (tr "settings.multiple")])
- [:option {:value "left"} (tr "workspace.options.constraints.left")]
- [:option {:value "right"} (tr "workspace.options.constraints.right")]
- [:option {:value "leftright"} (tr "workspace.options.constraints.leftright")]
- [:option {:value "center"} (tr "workspace.options.constraints.center")]
- [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
- [:div.row-flex
- [:span.top-bottom i/full-screen]
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :data-value :constraints-v
- :on-change on-constraint-select-changed
- :value (d/name constraints-v "scale")}
- (when (= constraints-v :multiple)
- [:option {:value ""} (tr "settings.multiple")])
- [:option {:value "top"} (tr "workspace.options.constraints.top")]
- [:option {:value "bottom"} (tr "workspace.options.constraints.bottom")]
- [:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")]
- [:option {:value "center"} (tr "workspace.options.constraints.center")]
- [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
- (when first-level?
- [:div.row-flex
- [:div.fix-when {:class (dom/classnames :active (:fixed-scroll values))
- :on-click on-fixed-scroll-clicked}
- (if (:fixed-scroll values)
- i/pin-fill
- i/pin)
- [:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]]))))
+ [:label {:for "fixed-on-scroll"
+ :class (stl/css-case :checked (:fixed-scroll values))}
+ [:span {:class (stl/css-case :check-mark true
+ :checked (:fixed-scroll values))}
+ (when (:fixed-scroll values)
+ i/status-tick-refactor)]
+ (tr "workspace.options.constraints.fix-when-scrolling")
+ [:input {:type "checkbox"
+ :id "fixed-on-scroll"
+ :checked (:fixed-scroll values)
+ :on-change on-fixed-scroll-clicked}]]])]])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss
index 736bde4e40..cf275fba93 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss
@@ -8,149 +8,156 @@
.element-set {
margin: 0;
- .element-set-content {
- display: flex;
- gap: $s-4;
- .constraints-widget {
- background-color: var(--constraint-widget-background-color);
- display: grid;
- grid-template-columns: $s-24 $s-60 $s-24;
- grid-template-rows: $s-24 $s-60 $s-24;
- grid-template-areas:
- "top top top"
- "left center right"
- "bottom bottom bottom";
- height: $s-108;
- width: $s-108;
+}
+
+.element-set-content {
+ display: flex;
+ gap: $s-4;
+}
+
+.constraints-widget {
+ background-color: var(--constraint-widget-background-color);
+ display: grid;
+ grid-template-columns: $s-24 $s-60 $s-24;
+ grid-template-rows: $s-24 $s-60 $s-24;
+ grid-template-areas:
+ "top top top"
+ "left center right"
+ "bottom bottom bottom";
+ height: $s-108;
+ width: $s-108;
+ border-radius: $br-8;
+}
+
+.constraints-top,
+.constraints-left,
+.constraints-center,
+.constraints-right,
+.constraints-bottom {
+ @include flexCenter;
+ grid-area: top;
+ .constraint-btn,
+ .constraint-btn-special,
+ .constraint-btn-rotated {
+ @include buttonStyle;
+ @include flexCenter;
+ width: 100%;
+ height: 100%;
+ .resalted-area {
+ width: $s-32;
+ height: $s-3;
border-radius: $br-8;
- .constraints-top,
- .constraints-left,
- .constraints-center,
- .constraints-right,
- .constraints-bottom {
- @include flexCenter;
- grid-area: top;
- .constraint-btn,
- .constraint-btn-special,
- .constraint-btn-rotated {
- @include buttonStyle;
- @include flexCenter;
- width: 100%;
- height: 100%;
- .resalted-area {
- width: $s-32;
- height: $s-3;
- border-radius: $br-8;
- background-color: var(--button-constraint-background-color-rest);
- padding: 0;
- margin: 0;
- }
- &.active .resalted-area {
- outline: $s-4 solid var(--button-constraint-border-color-hover);
- background-color: var(--button-constraint-background-color-hover);
- }
- &:hover .resalted-area,
- &:focus .resalted-area {
- outline: $s-4 solid var(--button-constraint-border-color-hover);
- background-color: var(--button-constraint-background-color-hover);
- }
- }
- }
- .constraints-left {
- grid-area: left;
- .constraint-btn-rotated {
- height: $s-60;
- width: $s-24;
- .resalted-area {
- height: $s-32;
- width: $s-3;
- }
- }
- }
- .constraints-center {
- grid-area: center;
- position: relative;
- background-color: var(--constraint-center-area-background-color);
- border-radius: $br-8;
- .constraint-btn {
- width: $s-60;
- height: $s-24;
- .resalted-area {
- width: $s-32;
- height: $s-3;
- }
- }
- .constraint-btn-special {
- position: absolute;
- height: $s-60;
- width: $s-24;
- .resalted-area {
- height: $s-32;
- width: $s-3;
- }
- }
- }
- .constraints-right {
- grid-area: right;
- .constraint-btn-rotated {
- height: $s-72;
- width: $s-24;
- .resalted-area {
- height: $s-32;
- width: $s-3;
- }
- }
- }
- .constraints-bottom {
- grid-area: bottom;
- }
+ background-color: var(--button-constraint-background-color-rest);
+ padding: 0;
+ margin: 0;
}
- .contraints-selects {
- @include flexColumn;
+ &.active .resalted-area {
+ outline: $s-4 solid var(--button-constraint-border-color-hover);
+ background-color: var(--button-constraint-background-color-hover);
+ }
+ &:hover .resalted-area,
+ &:focus .resalted-area {
+ outline: $s-4 solid var(--button-constraint-border-color-hover);
+ background-color: var(--button-constraint-background-color-hover);
+ }
+ }
+}
+.constraints-left {
+ grid-area: left;
+ .constraint-btn-rotated {
+ height: $s-60;
+ width: $s-24;
+ .resalted-area {
+ height: $s-32;
+ width: $s-3;
+ }
+ }
+}
+.constraints-center {
+ grid-area: center;
+ position: relative;
+ background-color: var(--constraint-center-area-background-color);
+ border-radius: $br-8;
+ .constraint-btn {
+ width: $s-60;
+ height: $s-24;
+ .resalted-area {
+ width: $s-32;
+ height: $s-3;
+ }
+ }
+ .constraint-btn-special {
+ position: absolute;
+ height: $s-60;
+ width: $s-24;
+ .resalted-area {
+ height: $s-32;
+ width: $s-3;
+ }
+ }
+}
- .horizontal-select,
- .vertical-select {
- width: $s-124;
- padding: 0;
+.constraints-right {
+ grid-area: right;
+ .constraint-btn-rotated {
+ height: $s-72;
+ width: $s-24;
+ .resalted-area {
+ height: $s-32;
+ width: $s-3;
+ }
+ }
+}
+
+.constraints-bottom {
+ grid-area: bottom;
+}
+
+.contraints-selects {
+ @include flexColumn;
+}
+
+.horizontal-select,
+.vertical-select {
+ width: $s-124;
+ padding: 0;
+}
+
+.checkbox {
+ display: flex;
+ align-items: center;
+ margin-bottom: $s-8;
+ margin-top: $s-8;
+ padding-left: 0;
+ input {
+ margin: 0;
+ }
+
+ label {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ gap: $s-2;
+ cursor: pointer;
+ color: var(--input-checkbox-text-foreground-color);
+ .check-mark {
+ @include flexCenter;
+ width: $s-16;
+ height: $s-16;
+ border-radius: $br-6;
+ background-color: var(--input-checkbox-inactive-background-color);
+ &.checked {
+ background-color: var(--input-checkbox-active-background-color);
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-details-color);
+ }
}
-
- .checkbox {
- display: flex;
- align-items: center;
- margin-bottom: $s-8;
- margin-top: $s-8;
- padding-left: 0;
- input {
- margin: 0;
- }
- label {
- @include titleTipography;
- display: flex;
- align-items: center;
- gap: $s-2;
- cursor: pointer;
- color: var(--input-checkbox-text-foreground-color);
- .check-mark {
- @include flexCenter;
- width: $s-16;
- height: $s-16;
- border-radius: $br-6;
- background-color: var(--input-checkbox-inactive-background-color);
- &.checked {
- background-color: var(--input-checkbox-active-background-color);
- svg {
- @extend .button-icon-small;
- stroke: var(--input-details-color);
- }
- }
- &:hover {
- border-color: var(--input-checkbox-border-color-hover);
- }
- &:focus {
- border-color: var(--input-checkbox-border-color-focus);
- }
- }
- }
+ &:hover {
+ border-color: var(--input-checkbox-border-color-hover);
+ }
+ &:focus {
+ border-color: var(--input-checkbox-border-color-focus);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
index f45dffb83e..72556669d0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
@@ -15,7 +15,6 @@
[app.main.store :as st]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.export]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
@@ -30,8 +29,7 @@
(mf/defc exports-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "page-id" "file-id"]))]}
[{:keys [ids type values page-id file-id] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- exports (:exports values [])
+ (let [exports (:exports values [])
has-exports? (or (= :multiple exports) (some? (seq exports)))
comp-state* (mf/use-state true)
@@ -118,11 +116,7 @@
(mf/use-fn
(mf/deps ids)
(fn [index event]
- (let [scale (if new-css-system
- (d/parse-double event)
- (-> event
- (dom/get-target-val)
- (d/parse-double)))]
+ (let [scale (d/parse-double event)]
(st/emit! (dch/update-shapes ids
(fn [shape]
(assoc-in shape [:exports index :scale] scale)))))))
@@ -143,11 +137,7 @@
(mf/use-fn
(mf/deps ids)
(fn [index event]
- (let [type (if new-css-system
- (keyword event)
- (-> event
- (dom/get-target-val)
- (keyword)))]
+ (let [type (keyword event)]
(st/emit! (dch/update-shapes ids
(fn [shape]
(assoc-in shape [:exports index :type] type)))))))
@@ -179,125 +169,68 @@
{:value "svg" :label "SVG"}
{:value "pdf" :label "PDF"}]]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-exports?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))
- :class (stl/css-case :title-spacing-export (not has-exports?))}
- [:button {:class (stl/css :add-export)
- :on-click add-export} i/add-refactor]]]
- (when open?
- [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-exports?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))
+ :class (stl/css-case :title-spacing-export (not has-exports?))}
+ [:button {:class (stl/css :add-export)
+ :on-click add-export} i/add-refactor]]]
+ (when open?
+ [:div {:class (stl/css :element-set-content)}
- (cond
- (= :multiple exports)
- [:div {:class (stl/css :multiple-exports)}
- [:div {:class (stl/css :label)} (tr "settings.multiple")]
- [:div {:class (stl/css :actions)}
- [:button {:class (stl/css :action-btn)
- :on-click on-remove-all}
- i/remove-refactor]]]
+ (cond
+ (= :multiple exports)
+ [:div {:class (stl/css :multiple-exports)}
+ [:div {:class (stl/css :label)} (tr "settings.multiple")]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove-all}
+ i/remove-refactor]]]
- (seq exports)
- [:*
- (for [[index export] (d/enumerate exports)]
- [:div {:class (stl/css :element-group)
- :key index}
- [:div {:class (stl/css :input-wrapper)}
- [:div {:class (stl/css :format-select)}
+ (seq exports)
+ [:*
+ (for [[index export] (d/enumerate exports)]
+ [:div {:class (stl/css :element-group)
+ :key index}
+ [:div {:class (stl/css :input-wrapper)}
+ [:div {:class (stl/css :format-select)}
+ [:& select
+ {:default-value (d/name (:type export))
+ :options format-options
+ :dropdown-class (stl/css :dropdown-upwards)
+ :on-change (partial on-type-change index)}]]
+ (when (scale-enabled? export)
+ [:div {:class (stl/css :size-select)}
[:& select
- {:default-value (d/name (:type export))
- :options format-options
+ {:default-value (str (:scale export))
+ :options size-options
:dropdown-class (stl/css :dropdown-upwards)
- :on-change (partial on-type-change index)}]]
- (when (scale-enabled? export)
- [:div {:class (stl/css :size-select)}
- [:& select
- {:default-value (str (:scale export))
- :options size-options
- :dropdown-class (stl/css :dropdown-upwards)
- :on-change (partial on-scale-change index)}]])
- [:label {:class (stl/css :suffix-input)
- :for "suffix-export-input"}
- [:input {:class (stl/css :type-input)
- :id "suffix-export-input"
- :type "text"
- :value (:suffix export)
- :placeholder (tr "workspace.options.export.suffix")
- :data-value index
- :on-change on-suffix-change
- :on-key-down manage-key-down}]]]
+ :on-change (partial on-scale-change index)}]])
+ [:label {:class (stl/css :suffix-input)
+ :for "suffix-export-input"}
+ [:input {:class (stl/css :type-input)
+ :id "suffix-export-input"
+ :type "text"
+ :value (:suffix export)
+ :placeholder (tr "workspace.options.export.suffix")
+ :data-value index
+ :on-change on-suffix-change
+ :on-key-down manage-key-down}]]]
- [:button {:class (stl/css :action-btn)
- :on-click (partial delete-export index)}
- i/remove-refactor]])])
+ [:button {:class (stl/css :action-btn)
+ :on-click (partial delete-export index)}
+ i/remove-refactor]])])
- (when (or (= :multiple exports) (seq exports))
- [:button
- {:on-click (when-not in-progress? on-download)
- :class (stl/css-case
- :export-btn true
- :btn-disabled in-progress?)
- :disabled in-progress?}
- (if in-progress?
- (tr "workspace.options.exporting-object")
- (tr "workspace.options.export-object" (c (count shapes-with-exports))))])])]
-
-
- [:div.element-set.exports-options
- [:div.element-set-title
- [:span (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))]
- (when (not (= :multiple exports))
- [:div.add-page {:on-click add-export} i/close])]
-
- (cond
- (= :multiple exports)
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click on-remove-all}
- i/minus]]]
-
- (seq exports)
- [:div.element-set-content
- (for [[index export] (d/enumerate exports)]
- [:div.element-set-options-group
- {:key index}
- (when (scale-enabled? export)
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :on-change (partial on-scale-change index)
- :value (:scale export)}
- [:option {:value "0.5"} "0.5x"]
- [:option {:value "0.75"} "0.75x"]
- [:option {:value "1"} "1x"]
- [:option {:value "1.5"} "1.5x"]
- [:option {:value "2"} "2x"]
- [:option {:value "4"} "4x"]
- [:option {:value "6"} "6x"]])
- [:input.input-text {:value (:suffix export)
- :placeholder (tr "workspace.options.export.suffix")
- :data-value index
- :on-change on-suffix-change
- :on-key-down manage-key-down}]
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (d/name (:type export))
- :on-change (partial on-type-change index)}
- [:option {:value "png"} "PNG"]
- [:option {:value "jpeg"} "JPEG"]
- [:option {:value "svg"} "SVG"]
- [:option {:value "pdf"} "PDF"]]
- [:div.delete-icon {:on-click (partial delete-export index)}
- i/minus]])])
-
- (when (or (= :multiple exports) (seq exports))
- [:div.btn-icon-dark.download-button
- {:on-click (when-not in-progress? on-download)
- :class (dom/classnames
- :btn-disabled in-progress?)
- :disabled in-progress?}
- (if in-progress?
- (tr "workspace.options.exporting-object")
- (tr "workspace.options.export-object" (c (count shapes-with-exports))))])])))
+ (when (or (= :multiple exports) (seq exports))
+ [:button
+ {:on-click (when-not in-progress? on-download)
+ :class (stl/css-case
+ :export-btn true
+ :btn-disabled in-progress?)
+ :disabled in-progress?}
+ (if in-progress?
+ (tr "workspace.options.exporting-object")
+ (tr "workspace.options.export-object" (c (count shapes-with-exports))))])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
index 414d9f7cbc..6bbb39afd9 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
@@ -8,12 +8,35 @@
.element-set {
margin: 0;
- .element-title {
- .title-spacing-export {
- padding-left: $s-2;
- margin: 0;
- }
- .add-export {
+}
+
+.title-spacing-export {
+ padding-left: $s-2;
+ margin: 0;
+}
+
+.add-export {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.element-set-content {
+ @include flexColumn;
+ margin: $s-4 0 $s-8 0;
+}
+
+.multiple-exports {
+ @include flexRow;
+ .label {
+ @extend .mixed-bar;
+ }
+ .actions {
+ @include flexRow;
+ .action-btn {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
@@ -22,68 +45,58 @@
}
}
}
- .element-set-content {
- @include flexColumn;
- margin: $s-4 0 $s-8 0;
- .multiple-exports {
- @include flexRow;
- .label {
- @extend .mixed-bar;
- }
- .actions {
- @include flexRow;
- .action-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- }
- .element-group {
- @include flexRow;
- .input-wrapper {
- @include flexRow;
- .format-select {
- width: $s-60;
- padding: 0;
- .dropdown-upwards {
- bottom: $s-36;
- width: $s-80;
- top: unset;
- }
- }
- .size-select {
- width: $s-60;
- padding: 0;
- .dropdown-upwards {
- bottom: $s-36;
- top: unset;
- width: $s-80;
- }
- }
- .suffix-input {
- @extend .input-element;
- min-width: $s-92;
- flex-grow: 1;
- }
- }
- .action-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- .export-btn {
- @extend .button-secondary;
- @include tabTitleTipography;
- height: $s-32;
- width: $s-252;
+}
+
+.element-group {
+ display: grid;
+ grid-template-columns: repeat(8, 1fr);
+ column-gap: $s-4;
+
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
}
}
+
+.input-wrapper {
+ grid-column: span 7;
+ display: grid;
+ grid-template-columns: subgrid;
+}
+
+.format-select {
+ grid-column: span 2;
+ padding: 0;
+
+ .dropdown-upwards {
+ bottom: $s-36;
+ width: $s-80;
+ top: unset;
+ }
+}
+
+.size-select {
+ grid-column: span 2;
+ padding: 0;
+ .dropdown-upwards {
+ bottom: $s-36;
+ top: unset;
+ width: $s-80;
+ }
+}
+
+.suffix-input {
+ grid-column: span 3;
+ @extend .input-element;
+}
+
+.export-btn {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ height: $s-32;
+ width: $s-252;
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
index 948c5228f4..58fe4f1e92 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
@@ -13,7 +13,6 @@
[app.main.data.workspace.colors :as dc]
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
@@ -44,8 +43,7 @@
(mf/defc fill-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
[{:keys [ids type values disable-remove?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- label (case type
+ (let [label (case type
:multiple (tr "workspace.options.selection-fill")
:group (tr "workspace.options.group-fill")
(tr "workspace.options.fill"))
@@ -137,83 +135,28 @@
(dom/set-attribute! checkbox "indeterminate" true)
(dom/remove-attribute! checkbox "indeterminate")))))
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-fills?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title label
- :class (stl/css-case :title-spacing-fill (not has-fills?))}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-fills?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title label
+ :class (stl/css-case :title-spacing-fill (not has-fills?))}
- (when (and (not disable-remove?) (not (= :multiple fills)))
- [:button {:class (stl/css :add-fill)
- :on-click on-add} i/add-refactor])]]
-
- (when open?
- [:div {:class (stl/css :element-content)}
- (cond
- (= :multiple fills)
- [:div {:class (stl/css :element-set-options-group)}
- [:div {:class (stl/css :group-label)}
- (tr "settings.multiple")]
- [:button {:on-click on-remove-all
- :class (stl/css :remove-btn)}
- i/remove-refactor]]
-
- (seq fills)
- [:& h/sortable-container {}
- (for [[index value] (d/enumerate (:fills values []))]
- [:& color-row {:color {:color (:fill-color value)
- :opacity (:fill-opacity value)
- :id (:fill-color-ref-id value)
- :file-id (:fill-color-ref-file value)
- :gradient (:fill-color-gradient value)
- :image (:fill-image value)}
- :key index
- :index index
- :title (tr "workspace.options.fill")
- :on-change (on-change index)
- :on-reorder (on-reorder index)
- :on-detach (on-detach index)
- :on-remove (on-remove index)
- :disable-drag disable-drag
- :on-focus on-focus
- :select-on-focus (not @disable-drag)
- :on-blur on-blur}])])
-
- (when (or (= type :frame)
- (and (= type :multiple) (some? (:hide-fill-on-export values))))
- [:div {:class (stl/css :checkbox)}
- [:label {:for "show-fill-on-export"
- :class (stl/css-case :global/checked (not hide-fill-on-export?))}
- [:span {:class (stl/css-case :check-mark true
- :checked (not hide-fill-on-export?))}
- (when (not hide-fill-on-export?)
- i/status-tick-refactor)]
- (tr "workspace.options.show-fill-on-export")
- [:input {:type "checkbox"
- :id "show-fill-on-export"
- :ref checkbox-ref
- :checked (not hide-fill-on-export?)
- :on-change on-change-show-fill-on-export}]]])])]
-
- ;; OLD
- [:div.element-set
- [:div.element-set-title
- [:span label]
- (when (and (not disable-remove?) (not (= :multiple fills)))
- [:div.add-page {:on-click on-add} i/close])]
-
- [:div.element-set-content
+ (when (and (not disable-remove?) (not (= :multiple fills)))
+ [:button {:class (stl/css :add-fill)
+ :on-click on-add} i/add-refactor])]]
+ (when open?
+ [:div {:class (stl/css :element-content)}
(cond
(= :multiple fills)
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click on-remove-all}
- i/minus]]]
+ [:div {:class (stl/css :element-set-options-group)}
+ [:div {:class (stl/css :group-label)}
+ (tr "settings.multiple")]
+ [:button {:on-click on-remove-all
+ :class (stl/css :remove-btn)}
+ i/remove-refactor]]
(seq fills)
[:& h/sortable-container {}
@@ -238,12 +181,16 @@
(when (or (= type :frame)
(and (= type :multiple) (some? (:hide-fill-on-export values))))
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id "show-fill-on-export"
- :ref checkbox-ref
- :checked (not hide-fill-on-export?)
- :on-change on-change-show-fill-on-export}]
-
- [:label {:for "show-fill-on-export"}
- (tr "workspace.options.show-fill-on-export")]])]])))
+ [:div {:class (stl/css :checkbox)}
+ [:label {:for "show-fill-on-export"
+ :class (stl/css-case :global/checked (not hide-fill-on-export?))}
+ [:span {:class (stl/css-case :check-mark true
+ :checked (not hide-fill-on-export?))}
+ (when (not hide-fill-on-export?)
+ i/status-tick-refactor)]
+ (tr "workspace.options.show-fill-on-export")
+ [:input {:type "checkbox"
+ :id "show-fill-on-export"
+ :ref checkbox-ref
+ :checked (not hide-fill-on-export?)
+ :on-change on-change-show-fill-on-export}]]])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
index 7bcc45db94..08b5581dbd 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
@@ -8,50 +8,58 @@
.element-set {
margin: 0;
- .element-title {
- margin: 0;
- .title-spacing-fill {
- padding-left: $s-2;
- margin: 0;
- }
- .add-fill {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
+}
+
+.element-title {
+ margin: 0;
+}
+
+.title-spacing-fill {
+ padding-left: $s-2;
+ margin: 0;
+}
+
+.add-fill {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
- .element-content {
- display: flex;
- flex-direction: column;
- gap: $s-12;
- margin: $s-4 0 $s-8 0;
- .element-set-options-group {
- @include flexRow;
- .group-label {
- @extend .mixed-bar;
- }
- .remove-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- .checkbox {
- @extend .input-checkbox;
- padding-left: $s-8;
- span.checked {
- background-color: var(--input-border-color-active);
- svg {
- @extend .button-icon-small;
- stroke: var(--input-details-color);
- }
- }
+}
+
+.element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-12;
+ margin: $s-4 0 $s-8 0;
+}
+
+.element-set-options-group {
+ @include flexRow;
+}
+
+.group-label {
+ @extend .mixed-bar;
+}
+
+.remove-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.checkbox {
+ @extend .input-checkbox;
+ padding-left: $s-8;
+ span.checked {
+ background-color: var(--input-border-color-active);
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-details-color);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs
index 2f326dddfb..8191cf0908 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs
@@ -15,11 +15,9 @@
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
- [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row input-row-v2]]
[app.util.i18n :as i18n :refer [tr]]
[okulary.core :as l]
[rumext.v2 :as mf]))
@@ -35,8 +33,7 @@
(mf/defc grid-options
{::mf/wrap [mf/memo]}
[{:keys [shape-id index grid frame-width frame-height default-grid-params]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
+ (let [on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
on-remove (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/remove-frame-grid shape-id index)))
on-save-default (mf/use-fn #(st/emit! (dw/set-default-grid (:type %) (:params %))))
@@ -136,215 +133,87 @@
is-default (= (->> grid :params)
(->> grid :type default-grid-params))]
- (if new-css-system
- [:div {:class (stl/css :grid-option)}
- [:div {:class (stl/css :grid-title)}
- [:div {:class (stl/css-case :option-row true
- :hidden is-hidden?)}
- [:button {:class (stl/css-case :show-options true
- :selected open?)
- :on-click toggle-advanced-options}
- i/menu-refactor]
- [:div {:class (stl/css :type-select-wrapper)}
- [:& select
- {:class (stl/css :grid-type-select)
- :default-value type
- :options [{:value :square :label (tr "workspace.options.grid.square")}
- {:value :column :label (tr "workspace.options.grid.column")}
- {:value :row :label (tr "workspace.options.grid.row")}]
- :on-change handle-change-type}]]
- (if (= type :square)
- [:div {:class (stl/css :grid-size)
- :title (tr "workspace.options.size")}
- [:> numeric-input* {:min 0.01
- :value (or (:size params) "")
- :no-validate true
- :className (stl/css :numeric-input)
- :on-change (handle-change :params :size)}]]
-
- [:div {:class (stl/css :editable-select-wrapper)}
- [:& editable-select {:value (:size params)
- :type "number"
- :class (stl/css :column-select)
- :input-class (stl/css :numeric-input)
- :min 1
- :options size-options
- :placeholder "Auto"
- :on-change handle-change-size}]])]
-
- [:div {:class (stl/css :actions)}
- [:button {:class (stl/css :action-btn)
- :on-click handle-toggle-visibility}
- (if display i/shown-refactor i/hide-refactor)]
- [:button {:class (stl/css :action-btn)
- :on-click on-remove}
- i/remove-refactor]]]
-
- (when (:display grid)
- [:& advanced-options {:class (stl/css :grid-advanced-options)
- :visible? open?
- :on-close toggle-advanced-options}
- ;; square
- (when (= :square type)
- [:div {:class (stl/css :square-row)}
- [:div {:class (stl/css :advanced-row)}
- [:& color-row {:color (:color params)
- :title (tr "workspace.options.grid.params.color")
- :disable-gradient true
- :disable-image true
- :on-change handle-change-color
- :on-detach handle-detach-color}]
- [:button {:class (stl/css-case :show-more-options true
- :selected show-more-options?)
- :on-click toggle-more-options}
- i/menu-refactor]]
- (when show-more-options?
- [:div {:class (stl/css :second-row)}
- [:button {:class (stl/css-case :btn-options true
- :disabled is-default)
- :disabled is-default
- :on-click handle-use-default}
- [:span (tr "workspace.options.grid.params.use-default")]]
- [:button {:class (stl/css-case :btn-options true
- :disabled is-default)
- :disabled is-default
- :on-click handle-set-as-default}
- [:span (tr "workspace.options.grid.params.set-default")]]])])
-
- (when (or (= :column type) (= :row type))
- [:div {:class (stl/css :column-row)}
- [:div {:class (stl/css :advanced-row)}
- [:div {:class (stl/css :orientation-select-wrapper)}
- [:& select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :default-value (:type params)
- :class (stl/css :orientation-select)
- :options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
- {:value :left :label (if (= type :row)
- (tr "workspace.options.grid.params.type.top")
- (tr "workspace.options.grid.params.type.left"))}
- {:value :center :label (tr "workspace.options.grid.params.type.center")}
- {:value :right :label (if (= type :row)
- (tr "workspace.options.grid.params.type.bottom")
- (tr "workspace.options.grid.params.type.right"))}]
- :on-change (handle-change :params :type)}]]
-
- [:div {:class (stl/css :color-wrapper)}
- [:& color-row {:color (:color params)
- :title (tr "workspace.options.grid.params.color")
- :disable-gradient true
- :disable-image true
- :on-change handle-change-color
- :on-detach handle-detach-color}]]]
-
- [:div {:class (stl/css :advanced-row)}
- [:div {:class (stl/css :height)
- :title (if (= :row type)
- (tr "workspace.options.grid.params.height")
- (tr "workspace.options.grid.params.width"))}
- [:span {:class (stl/css :icon-text)}
- (if (= :row type)
- "H"
- "W")]
- [:> numeric-input* {:placeholder "Auto"
- :on-change handle-change-item-length
- :nillable true
- :className (stl/css :numeric-input)
- :value (or (:item-length params) "")}]]
-
- [:div {:class (stl/css :gutter)
- :title (tr "workspace.options.grid.params.gutter")}
- [:span {:class (stl/css-case :icon true
- :rotated (= type :row))} i/gap-horizontal-refactor]
- [:> numeric-input* {:placeholder "0"
- :on-change (handle-change :params :gutter)
- :nillable true
- :className (stl/css :numeric-input)
- :value (or (:gutter params) 0)}]]
-
- [:div {:class (stl/css :margin)
- :title (tr "workspace.options.grid.params.margin")}
- [:span {:class (stl/css-case :icon true
- :rotated (= type :column))} i/grid-margin-refactor]
- [:> numeric-input* {:placeholder "0"
- :on-change (handle-change :params :margin)
- :nillable true
- :className (stl/css :numeric-input)
- :value (or (:margin params) 0)}]]
-
- [:button {:class (stl/css-case :show-more-options true
- :selected show-more-options?)
- :on-click toggle-more-options}
- i/menu-refactor]
- (when show-more-options?
- [:div {:class (stl/css :more-options)}
- [:button {:disabled is-default
- :class (stl/css :option-btn)
- :on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
- [:button {:disabled is-default
- :class (stl/css :option-btn)
- :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]])]])])]
-
- [:div.grid-option
- [:div.grid-option-main {:style {:display (when open? "none")}}
- [:button.custom-button {:class (when open? "is-active")
- :on-click toggle-advanced-options} i/actions]
+ [:div {:class (stl/css :grid-option)}
+ [:div {:class (stl/css :grid-title)}
+ [:div {:class (stl/css-case :option-row true
+ :hidden is-hidden?)}
+ [:button {:class (stl/css-case :show-options true
+ :selected open?)
+ :on-click toggle-advanced-options}
+ i/menu-refactor]
+ [:div {:class (stl/css :type-select-wrapper)}
[:& select
- {:class "flex-grow"
+ {:class (stl/css :grid-type-select)
:default-value type
:options [{:value :square :label (tr "workspace.options.grid.square")}
{:value :column :label (tr "workspace.options.grid.column")}
{:value :row :label (tr "workspace.options.grid.row")}]
- :on-change handle-change-type}]
-
- (if (= type :square)
- [:div.input-element.pixels {:title (tr "workspace.options.size")}
- [:> numeric-input* {:min 0.01
- :value (or (:size params) "")
- :no-validate true
- :on-change (handle-change :params :size)}]]
+ :on-change handle-change-type}]]
+ (if (= type :square)
+ [:div {:class (stl/css :grid-size)
+ :title (tr "workspace.options.size")}
+ [:> numeric-input* {:min 0.01
+ :value (or (:size params) "")
+ :no-validate true
+ :className (stl/css :numeric-input)
+ :on-change (handle-change :params :size)}]]
+ [:div {:class (stl/css :editable-select-wrapper)}
[:& editable-select {:value (:size params)
:type "number"
- :class "input-option"
+ :class (stl/css :column-select)
+ :input-class (stl/css :numeric-input)
:min 1
:options size-options
:placeholder "Auto"
- :on-change handle-change-size}])
+ :on-change handle-change-size}]])]
- [:div.grid-option-main-actions
- [:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)]
- [:button.custom-button {:on-click on-remove} i/minus]]]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click handle-toggle-visibility}
+ (if display i/shown-refactor i/hide-refactor)]
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove}
+ i/remove-refactor]]]
- [:& advanced-options {:visible? open? :on-close toggle-advanced-options}
- [:button.custom-button {:on-click toggle-advanced-options} i/actions]
+ (when (:display grid)
+ [:& advanced-options {:class (stl/css :grid-advanced-options)
+ :visible? open?
+ :on-close toggle-advanced-options}
+ ;; square
(when (= :square type)
- [:& input-row {:label (tr "workspace.options.grid.params.size")
- :class "pixels"
- :min 0.01
- :value (:size params)
- :on-change (handle-change :params :size)}])
+ [:div {:class (stl/css :square-row)}
+ [:div {:class (stl/css :advanced-row)}
+ [:& color-row {:color (:color params)
+ :title (tr "workspace.options.grid.params.color")
+ :disable-gradient true
+ :disable-image true
+ :on-change handle-change-color
+ :on-detach handle-detach-color}]
+ [:button {:class (stl/css-case :show-more-options true
+ :selected show-more-options?)
+ :on-click toggle-more-options}
+ i/menu-refactor]]
+ (when show-more-options?
+ [:div {:class (stl/css :second-row)}
+ [:button {:class (stl/css-case :btn-options true
+ :disabled is-default)
+ :disabled is-default
+ :on-click handle-use-default}
+ [:span (tr "workspace.options.grid.params.use-default")]]
+ [:button {:class (stl/css-case :btn-options true
+ :disabled is-default)
+ :disabled is-default
+ :on-click handle-set-as-default}
+ [:span (tr "workspace.options.grid.params.set-default")]]])])
- (when (= :row type)
- [:& input-row {:label (tr "workspace.options.grid.params.rows")
- :type :editable-select
- :options size-options
- :value (:size params)
- :min 1
- :placeholder "Auto"
- :on-change handle-change-size}])
-
- (when (= :column type)
- [:& input-row {:label (tr "workspace.options.grid.params.columns")
- :type :editable-select
- :options size-options
- :value (:size params)
- :min 1
- :placeholder "Auto"
- :on-change handle-change-size}])
-
- (when (#{:row :column} type)
- [:& input-row {:label (tr "workspace.options.grid.params.type")
- :type :select
+ (when (or (= :column type) (= :row type))
+ [:div {:class (stl/css :column-row)}
+ [:div {:class (stl/css :advanced-row)}
+ [:div {:class (stl/css :orientation-select-wrapper)}
+ [:& select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :default-value (:type params)
+ :class (stl/css :orientation-select)
:options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
{:value :left :label (if (= type :row)
(tr "workspace.options.grid.params.type.top")
@@ -353,56 +222,67 @@
{:value :right :label (if (= type :row)
(tr "workspace.options.grid.params.type.bottom")
(tr "workspace.options.grid.params.type.right"))}]
- :value (:type params)
- :on-change (handle-change :params :type)}])
+ :on-change (handle-change :params :type)}]]
- (when (#{:row :column} type)
- [:& input-row-v2
- {:class "pixels"
- :label (if (= :row type)
- (tr "workspace.options.grid.params.height")
- (tr "workspace.options.grid.params.width"))}
- [:> numeric-input*
- {:placeholder "Auto"
- :value (or (:item-length params) "")
- :nillable true
- :on-change handle-change-item-length}]])
+ [:div {:class (stl/css :color-wrapper)}
+ [:& color-row {:color (:color params)
+ :title (tr "workspace.options.grid.params.color")
+ :disable-gradient true
+ :disable-image true
+ :on-change handle-change-color
+ :on-detach handle-detach-color}]]]
- (when (#{:row :column} type)
- [:*
- [:& input-row {:label (tr "workspace.options.grid.params.gutter")
- :class "pixels"
- :value (:gutter params)
- :min 0
- :nillable true
- :default 0
- :placeholder "0"
- :on-change (handle-change :params :gutter)}]
- [:& input-row {:label (tr "workspace.options.grid.params.margin")
- :class "pixels"
- :min 0
- :nillable true
- :default 0
- :placeholder "0"
- :value (:margin params)
- :on-change (handle-change :params :margin)}]])
+ [:div {:class (stl/css :advanced-row)}
+ [:div {:class (stl/css :height)
+ :title (if (= :row type)
+ (tr "workspace.options.grid.params.height")
+ (tr "workspace.options.grid.params.width"))}
+ [:span {:class (stl/css :icon-text)}
+ (if (= :row type)
+ "H"
+ "W")]
+ [:> numeric-input* {:placeholder "Auto"
+ :on-change handle-change-item-length
+ :nillable true
+ :className (stl/css :numeric-input)
+ :value (or (:item-length params) "")}]]
- [:& color-row {:color (:color params)
- :title (tr "workspace.options.grid.params.color")
- :disable-gradient true
- :disable-image true
- :on-change handle-change-color
- :on-detach handle-detach-color}]
- [:div.row-flex
- [:button.btn-options {:disabled is-default
- :on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
- [:button.btn-options {:disabled is-default
- :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]]]])))
+ [:div {:class (stl/css :gutter)
+ :title (tr "workspace.options.grid.params.gutter")}
+ [:span {:class (stl/css-case :icon true
+ :rotated (= type :row))} i/gap-horizontal-refactor]
+ [:> numeric-input* {:placeholder "0"
+ :on-change (handle-change :params :gutter)
+ :nillable true
+ :className (stl/css :numeric-input)
+ :value (or (:gutter params) 0)}]]
+
+ [:div {:class (stl/css :margin)
+ :title (tr "workspace.options.grid.params.margin")}
+ [:span {:class (stl/css-case :icon true
+ :rotated (= type :column))} i/grid-margin-refactor]
+ [:> numeric-input* {:placeholder "0"
+ :on-change (handle-change :params :margin)
+ :nillable true
+ :className (stl/css :numeric-input)
+ :value (or (:margin params) 0)}]]
+
+ [:button {:class (stl/css-case :show-more-options true
+ :selected show-more-options?)
+ :on-click toggle-more-options}
+ i/menu-refactor]
+ (when show-more-options?
+ [:div {:class (stl/css :more-options)}
+ [:button {:disabled is-default
+ :class (stl/css :option-btn)
+ :on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
+ [:button {:disabled is-default
+ :class (stl/css :option-btn)
+ :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]])]])])]))
(mf/defc frame-grid
[{:keys [shape]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- state* (mf/use-state true)
+ (let [state* (mf/use-state true)
open? (deref state*)
frame-grids (:grids shape)
has-frame-grids? (or (= :multiple frame-grids) (some? (seq frame-grids)))
@@ -413,44 +293,26 @@
default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids))
handle-create-grid (mf/use-fn (mf/deps id) #(st/emit! (dw/add-frame-grid id)))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:& title-bar {:collapsable? has-frame-grids?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :class (stl/css-case :title-spacing-board-grid (not has-frame-grids?))
- :title (tr "workspace.options.guides.title")}
+ [:div {:class (stl/css :element-set)}
+ [:& title-bar {:collapsable? has-frame-grids?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :class (stl/css-case :title-spacing-board-grid (not has-frame-grids?))
+ :title (tr "workspace.options.guides.title")}
- [:button {:on-click handle-create-grid
- :class (stl/css :add-grid)}
- i/add-refactor]]
+ [:button {:on-click handle-create-grid
+ :class (stl/css :add-grid)}
+ i/add-refactor]]
- (when (and open? (seq frame-grids))
- [:div {:class (stl/css :element-set-content)}
- (for [[index grid] (map-indexed vector frame-grids)]
- [:& grid-options {:key (str id "-" index)
- :shape-id id
- :grid grid
- :index index
- :frame-width (:width shape)
- :frame-height (:height shape)
- :default-grid-params default-grid-params}])])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.grid.grid-title")]
- [:div.add-page {:on-click handle-create-grid} i/close]]
-
- (when (seq frame-grids)
- [:div.element-set-content
- (for [[index grid] (map-indexed vector frame-grids)]
- [:& grid-options {:key (str id "-" index)
- :shape-id id
- :grid grid
- :index index
- :frame-width (:width shape)
- :frame-height (:height shape)
- :default-grid-params default-grid-params}])])])))
+ (when (and open? (seq frame-grids))
+ [:div {:class (stl/css :element-set-content)}
+ (for [[index grid] (map-indexed vector frame-grids)]
+ [:& grid-options {:key (str id "-" index)
+ :shape-id id
+ :grid grid
+ :index index
+ :frame-width (:width shape)
+ :frame-height (:height shape)
+ :default-grid-params default-grid-params}])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss
index 0435242e82..4a23132e71 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss
@@ -8,241 +8,250 @@
.element-set {
margin: 0;
- .title-spacing-board-grid {
- padding-left: $s-2;
- margin: 0;
+}
+
+.title-spacing-board-grid {
+ padding-left: $s-2;
+ margin: 0;
+}
+
+.add-grid {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
- .add-grid {
- @extend .button-tertiary;
+}
+
+.element-set-content {
+ @include flexColumn;
+ margin: $s-4 0 $s-8 0;
+}
+
+.grid-title {
+ @include flexRow;
+}
+
+.option-row {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ border-radius: $br-8;
+ background-color: var(--input-details-color);
+ .show-options {
+ @extend .button-secondary;
height: $s-32;
width: $s-28;
+ border-radius: $br-8 0 0 $br-8;
+ box-sizing: border-box;
+ border: $s-1 solid var(--input-background-color);
svg {
@extend .button-icon;
}
+ &.selected {
+ @extend .button-icon-selected;
+ }
}
- .element-set-content {
- @include flexColumn;
- margin: $s-4 0 $s-8 0;
- .grid-option {
- .grid-title {
- @include flexRow;
- .option-row {
- display: flex;
- align-items: center;
- gap: $s-1;
- border-radius: $br-8;
- background-color: var(--input-details-color);
- .show-options {
- @extend .button-secondary;
- height: $s-32;
- width: $s-28;
- border-radius: $br-8 0 0 $br-8;
- box-sizing: border-box;
- border: $s-1 solid var(--input-background-color);
- svg {
- @extend .button-icon;
- }
- &.selected {
- @extend .button-icon-selected;
- }
- }
- .type-select-wrapper {
- width: $s-96;
- padding: 0;
- border-radius: 0;
- height: $s-32;
- .grid-type-select {
- border-radius: 0;
- height: 100%;
- box-sizing: border-box;
- border: $s-1 solid var(--input-background-color);
- &:hover {
- border: $s-1 solid var(--input-background-color-hover);
- }
- }
- }
- .grid-size {
- @extend .asset-element;
- width: $s-60;
- margin: 0;
- padding: 0;
- padding-left: $s-8;
- border-radius: 0 $br-8 $br-8 0;
- .numeric-input {
- @extend .input-base;
- }
- }
- .editable-select-wrapper {
- @extend .asset-element;
- width: $s-60;
- margin: 0;
- padding: 0;
- position: relative;
- border-radius: 0 $br-8 $br-8 0;
- .column-select {
- height: $s-32;
- border-radius: 0 $br-8 $br-8 0;
- box-sizing: border-box;
- border: $s-1 solid var(--input-background-color);
- .numeric-input {
- @extend .input-base;
- margin: 0;
- padding: 0;
- }
- span {
- @include flexCenter;
- svg {
- @extend .button-icon;
- }
- }
- }
- }
-
- &.hidden {
- .show-options {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- .type-select-wrapper,
- .editable-select-wrapper {
- @include hiddenElement;
- .column-select,
- .grid-type-select {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- .column-select {
- @include hiddenElement;
- border-radius: 0 $br-8 $br-8 0;
- .numeric-input {
- @include hiddenElement;
- }
- }
- }
- .grid-size {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- .icon {
- stroke: var(--input-foreground-color-disabled);
- }
- .numeric-input {
- color: var(--input-foreground-color-disabled);
- }
- }
- .actions {
- .hidden-btn,
- .lock-btn {
- background-color: transparent;
- svg {
- stroke: var(--input-foreground-color-disabled);
- }
- }
- }
- }
- }
-
- .actions {
- @include flexRow;
- .action-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
+ .type-select-wrapper {
+ width: $s-96;
+ padding: 0;
+ border-radius: 0;
+ height: $s-32;
+ .grid-type-select {
+ border-radius: 0;
+ height: 100%;
+ box-sizing: border-box;
+ border: $s-1 solid var(--input-background-color);
+ &:hover {
+ border: $s-1 solid var(--input-background-color-hover);
+ }
+ }
+ }
+ .grid-size {
+ @extend .asset-element;
+ width: $s-60;
+ margin: 0;
+ padding: 0;
+ padding-left: $s-8;
+ border-radius: 0 $br-8 $br-8 0;
+ .numeric-input {
+ @extend .input-base;
+ }
+ }
+ .editable-select-wrapper {
+ @extend .asset-element;
+ width: $s-60;
+ margin: 0;
+ padding: 0;
+ position: relative;
+ border-radius: 0 $br-8 $br-8 0;
+ .column-select {
+ height: $s-32;
+ border-radius: 0 $br-8 $br-8 0;
+ box-sizing: border-box;
+ border: $s-1 solid var(--input-background-color);
+ .numeric-input {
+ @extend .input-base;
+ margin: 0;
+ padding: 0;
+ }
+ span {
+ @include flexCenter;
+ svg {
+ @extend .button-icon;
}
}
}
- .grid-advanced-options {
- @include flexColumn;
- margin-top: $s-4;
- .column-row,
- .square-row {
- @include flexColumn;
- position: relative;
- .advanced-row {
- position: relative;
- display: flex;
- gap: $s-4;
- .orientation-select-wrapper {
- width: $s-92;
- padding: 0;
- }
- .color-wrapper {
- width: $s-156;
- }
- .show-more-options {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-32;
- svg {
- @extend .button-icon;
- }
- &.selected {
- @extend .button-icon-selected;
- }
- }
- .height {
- @extend .input-element;
- width: $s-108;
- .icon-text {
- padding-top: $s-1;
- }
- }
- .gutter,
- .margin {
- @extend .input-element;
- width: $s-108;
- .icon {
- &.rotated svg {
- transform: rotate(90deg);
- }
- }
- }
- .more-options {
- @include menuShadow;
- @include flexColumn;
- position: absolute;
- top: calc($s-2 + $s-28);
- right: 0;
- width: $s-156;
- max-height: $s-300;
- padding: $s-2;
- margin: 0 0 $s-40 0;
- margin-top: $s-4;
- border-radius: $br-8;
- z-index: $z-index-3;
- overflow-y: auto;
- background-color: var(--menu-background-color);
- .option-btn {
- @include buttonStyle;
- display: flex;
- align-items: center;
- height: $s-32;
- padding: 0 $s-8;
- border-radius: $br-6;
- color: var(--menu-foreground-color);
+ }
- &:hover {
- background-color: var(--menu-background-color-hover);
- color: var(--menu-foreground-color-hover);
- }
- }
- }
+ &.hidden {
+ .show-options {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
+ }
+ .type-select-wrapper,
+ .editable-select-wrapper {
+ @include hiddenElement;
+ .column-select,
+ .grid-type-select {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
+ }
+ .column-select {
+ @include hiddenElement;
+ border-radius: 0 $br-8 $br-8 0;
+ .numeric-input {
+ @include hiddenElement;
}
- .second-row {
- @extend .dropdown-wrapper;
- left: unset;
- right: 0;
- width: $s-108;
- .btn-options {
- @include buttonStyle;
- @extend .dropdown-element-base;
- width: 100%;
- }
+ }
+ }
+ .grid-size {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
+ .icon {
+ stroke: var(--input-foreground-color-disabled);
+ }
+ .numeric-input {
+ color: var(--input-foreground-color-disabled);
+ }
+ }
+ .actions {
+ .hidden-btn,
+ .lock-btn {
+ background-color: transparent;
+ svg {
+ stroke: var(--input-foreground-color-disabled);
}
}
}
}
}
+
+.actions {
+ @include flexRow;
+}
+
+.action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.grid-advanced-options {
+ @include flexColumn;
+ margin-top: $s-4;
+}
+
+.column-row,
+.square-row {
+ @include flexColumn;
+ position: relative;
+}
+
+.advanced-row {
+ position: relative;
+ display: flex;
+ gap: $s-4;
+ .orientation-select-wrapper {
+ width: $s-92;
+ padding: 0;
+ }
+ .color-wrapper {
+ width: $s-156;
+ }
+ .show-more-options {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-32;
+ svg {
+ @extend .button-icon;
+ }
+ &.selected {
+ @extend .button-icon-selected;
+ }
+ }
+ .height {
+ @extend .input-element;
+ width: $s-108;
+ .icon-text {
+ padding-top: $s-1;
+ }
+ }
+ .gutter,
+ .margin {
+ @extend .input-element;
+ width: $s-108;
+ .icon {
+ &.rotated svg {
+ transform: rotate(90deg);
+ }
+ }
+ }
+
+ .more-options {
+ @include menuShadow;
+ @include flexColumn;
+ position: absolute;
+ top: calc($s-2 + $s-28);
+ right: 0;
+ width: $s-156;
+ max-height: $s-300;
+ padding: $s-2;
+ margin: 0 0 $s-40 0;
+ margin-top: $s-4;
+ border-radius: $br-8;
+ z-index: $z-index-3;
+ overflow-y: auto;
+ background-color: var(--menu-background-color);
+ .option-btn {
+ @include buttonStyle;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ padding: 0 $s-8;
+ border-radius: $br-6;
+ color: var(--menu-foreground-color);
+
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ color: var(--menu-foreground-color-hover);
+ }
+ }
+ }
+}
+
+.second-row {
+ @extend .dropdown-wrapper;
+ left: unset;
+ right: 0;
+ width: $s-108;
+ .btn-options {
+ @include buttonStyle;
+ @extend .dropdown-element-base;
+ width: 100%;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.cljs
index ffd4f82d6f..7d9da91219 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.cljs
@@ -18,10 +18,8 @@
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
- [app.main.ui.workspace.sidebar.options.menus.layout-container :as lyc]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -38,9 +36,7 @@
(mf/defc set-self-alignment
[{:keys [is-col? alignment set-alignment] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- dir-v [:auto :start :center :end :stretch #_:baseline]
- alignment (or alignment :auto)
+ (let [alignment (or alignment :auto)
type (if is-col? "col" "row")
handle-set-alignment
@@ -49,8 +45,7 @@
(fn [value]
(set-alignment (-> value keyword))))]
- (if new-css-system
- [:div {:class (stl/css :self-align-menu)}
+ [:div {:class (stl/css :self-align-menu)}
[:& radio-buttons {:selected (d/name alignment)
:on-change handle-set-alignment
:name (dm/str "flex-align-items-" type)}
@@ -72,27 +67,14 @@
[:& radio-button {:value "stretch"
:icon (if is-col? i/align-self-row-strech i/align-self-column-strech)
:title "Align self stretch"
- :id (dm/str "align-self-stretch-" type)}]]]
-
- [:div.align-self-style
- (for [align dir-v]
- [:button.align-self.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= alignment align)
- :tooltip-bottom-left (not= align :start)
- :tooltip-bottom (= align :start))
- :alt (dm/str "Align self " (d/name align)) ;; TODO fix this tooltip
- :on-click #(set-alignment align)
- :key (str "align-self" align)}
- (lyc/get-layout-flex-icon :align-self align is-col?)])])))
+ :id (dm/str "align-self-stretch-" type)}]]]))
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [shape cell cells] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- state* (mf/use-state {:open true})
+ (let [state* (mf/use-state {:open true})
open? (:open @state*)
cells (hooks/use-equal-memo cells)
@@ -181,208 +163,104 @@
(dwge/clear-selection (:id shape)))))]
- (if new-css-system
- [:div {:class (stl/css :grid-cell-menu)}
- [:div {:class (stl/css :grid-cell-menu-title)}
- [:& title-bar {:collapsable? true
- :collapsed? (not open?)
- :on-collapsed #(swap! state* update :open not)
- :title "Grid cell"}]]
+ [:div {:class (stl/css :grid-cell-menu)}
+ [:div {:class (stl/css :grid-cell-menu-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed #(swap! state* update :open not)
+ :title "Grid cell"}]]
- (when open?
- [:div {:class (stl/css :grid-cell-menu-container)}
- [:div {:class (stl/css :cell-mode :row)}
- [:& radio-buttons {:selected (d/name cell-mode)
- :on-change set-cell-mode
- :name "cell-mode"
- :wide true}
- [:& radio-button {:value "auto" :id :auto}]
- [:& radio-button {:value "manual" :id :manual}]
- [:& radio-button {:value "area" :id :area}]]]
-
- (when (= :area cell-mode)
- [:div {:class (stl/css :row)}
- [:input
- {:class (stl/css :area-input)
- :key (dm/str "name-" (:id cell))
- :id "grid-area-name"
- :type "text"
- :aria-label "grid-area-name"
- :placeholder "Area name"
- :default-value area-name
- :auto-complete "off"
- :on-change on-area-name-change}]])
-
- (when (and (not multiple?) (= :auto cell-mode))
- [:div {:class (stl/css :row)}
- [:div {:class (stl/css :grid-coord-group)}
- [:span {:class (stl/css :icon)} i/flex-vertical-refactor]
- [:div {:class (stl/css :coord-input)}
- [:> numeric-input*
- {:placeholder "--"
- :title "Column"
- :on-click #(dom/select-target %)
- :on-change (partial on-grid-coordinates :all :column)
- :value column}]]]
-
- [:div {:class (stl/css :grid-coord-group)}
- [:span {:class (stl/css :icon)} i/flex-horizontal-refactor]
- [:div {:class (stl/css :coord-input)}
- [:> numeric-input*
- {:placeholder "--"
- :title "Row"
- :on-click #(dom/select-target %)
- :on-change (partial on-grid-coordinates :all :row)
- :value row}]]]])
-
- (when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
- [:div {:class (stl/css :row)}
- [:div {:class (stl/css :grid-coord-group)}
- [:span {:class (stl/css :icon)} i/layout-rows]
- [:div {:class (stl/css :coord-input)}
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :start :column)
- :value column}]]
- [:div {:class (stl/css :coord-input)}
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :end :column)
- :value column-end}]]]
-
- [:div {:class (stl/css :grid-coord-group)}
- [:span {:class (stl/css :icon)} i/layout-columns]
- [:div {:class (stl/css :coord-input :double)}
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :start :row)
- :value row}]]
- [:div {:class (stl/css :coord-input)}
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :end :row)
- :value row-end}]]]])
+ (when open?
+ [:div {:class (stl/css :grid-cell-menu-container)}
+ [:div {:class (stl/css :cell-mode :row)}
+ [:& radio-buttons {:selected (d/name cell-mode)
+ :on-change set-cell-mode
+ :name "cell-mode"
+ :wide true}
+ [:& radio-button {:value "auto" :id :auto}]
+ [:& radio-button {:value "manual" :id :manual}]
+ [:& radio-button {:value "area"
+ :id :area
+ :disabled (not valid-area-cells?)}]]]
+ (when (= :area cell-mode)
[:div {:class (stl/css :row)}
- [:& set-self-alignment {:is-col? false
- :alignment align-self
- :set-alignment set-alignment}]
- [:& set-self-alignment {:is-col? true
- :alignment justify-self
- :set-alignment set-justify-self}]]
+ [:input
+ {:class (stl/css :area-input)
+ :key (dm/str "name-" (:id cell))
+ :id "grid-area-name"
+ :type "text"
+ :aria-label "grid-area-name"
+ :placeholder "Area name"
+ :default-value area-name
+ :auto-complete "off"
+ :on-change on-area-name-change}]])
+ (when (and (not multiple?) (= :auto cell-mode))
[:div {:class (stl/css :row)}
- [:button
- {:class (stl/css :edit-grid-btn)
- :alt (tr "workspace.layout_grid.editor.options.edit-grid")
- :on-click toggle-edit-mode}
- (tr "workspace.layout_grid.editor.options.edit-grid")]]])]
+ [:div {:class (stl/css :grid-coord-group)}
+ [:span {:class (stl/css :icon)} i/flex-vertical-refactor]
+ [:div {:class (stl/css :coord-input)}
+ [:> numeric-input*
+ {:placeholder "--"
+ :title "Column"
+ :on-click #(dom/select-target %)
+ :on-change (partial on-grid-coordinates :all :column)
+ :value column}]]]
+ [:div {:class (stl/css :grid-coord-group)}
+ [:span {:class (stl/css :icon)} i/flex-horizontal-refactor]
+ [:div {:class (stl/css :coord-input)}
+ [:> numeric-input*
+ {:placeholder "--"
+ :title "Row"
+ :on-click #(dom/select-target %)
+ :on-change (partial on-grid-coordinates :all :row)
+ :value row}]]]])
- [:div.element-set
- [:div.element-set-title
- [:span "Grid Cell"]]
+ (when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
+ [:div {:class (stl/css :row)}
+ [:div {:class (stl/css :grid-coord-group)}
+ [:span {:class (stl/css :icon)} i/layout-rows]
+ [:div {:class (stl/css :coord-input)}
+ [:> numeric-input*
+ {:placeholder "--"
+ :on-pointer-down #(dom/select-target %)
+ :on-change (partial on-grid-coordinates :start :column)
+ :value column}]]
+ [:div {:class (stl/css :coord-input)}
+ [:> numeric-input*
+ {:placeholder "--"
+ :on-pointer-down #(dom/select-target %)
+ :on-change (partial on-grid-coordinates :end :column)
+ :value column-end}]]]
- [:div.element-set-content.layout-grid-item-menu
- [:div.layout-row
- [:div.row-title.sizing "Position"]
- [:div.position-wrapper
- [:button.position-btn
- {:on-click #(set-cell-mode :auto)
- :class (dom/classnames :active (= :auto cell-mode))} "Auto"]
- (when-not multiple?
- [:button.position-btn
- {:on-click #(set-cell-mode :manual)
- :class (dom/classnames :active (= :manual cell-mode))} "Manual"])
- [:button.position-btn
- {:on-click #(set-cell-mode :area)
- :disabled (not valid-area-cells?)
- :class (dom/classnames :active (= :area cell-mode))} "Area"]]]
+ [:div {:class (stl/css :grid-coord-group)}
+ [:span {:class (stl/css :icon)} i/layout-columns]
+ [:div {:class (stl/css :coord-input :double)}
+ [:> numeric-input*
+ {:placeholder "--"
+ :on-pointer-down #(dom/select-target %)
+ :on-change (partial on-grid-coordinates :start :row)
+ :value row}]]
+ [:div {:class (stl/css :coord-input)}
+ [:> numeric-input*
+ {:placeholder "--"
+ :on-pointer-down #(dom/select-target %)
+ :on-change (partial on-grid-coordinates :end :row)
+ :value row-end}]]]])
- [:div.manage-grid-columns
- (when (and (not multiple?) (= :auto cell-mode))
- [:div.grid-auto
- [:div.grid-columns-auto
- [:span.icon i/layout-rows]
- [:div.input-wrapper
- [:> numeric-input*
- {:placeholder "--"
- :on-click #(dom/select-target %)
- :on-change (partial on-grid-coordinates :all :column)
- :value column}]]]
- [:div.grid-rows-auto
- [:span.icon i/layout-columns]
- [:div.input-wrapper
- [:> numeric-input*
- {:placeholder "--"
- :on-click #(dom/select-target %)
- :on-change (partial on-grid-coordinates :all :row)
- :value row}]]]])
+ [:div {:class (stl/css :row)}
+ [:& set-self-alignment {:is-col? false
+ :alignment align-self
+ :set-alignment set-alignment}]
+ [:& set-self-alignment {:is-col? true
+ :alignment justify-self
+ :set-alignment set-justify-self}]]
- (when (= :area cell-mode)
- [:div.input-wrapper
- [:input.input-text
- {:key (dm/str "name-" (:id cell))
- :id "grid-area-name"
- :type "text"
- :aria-label "grid-area-name"
- :placeholder "--"
- :default-value area-name
- :auto-complete "off"
- :on-change on-area-name-change}]])
-
- (when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
- [:div.grid-manual
- [:div.grid-columns-auto
- [:span.icon i/layout-rows]
- [:div.input-wrapper
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :start :column)
- :value column}]
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :end :column)
- :value column-end}]]]
- [:div.grid-rows-auto
- [:span.icon i/layout-columns]
- [:div.input-wrapper
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :start :row)
- :value row}]
- [:> numeric-input*
- {:placeholder "--"
- :on-pointer-down #(dom/select-target %)
- :on-change (partial on-grid-coordinates :end :row)
- :value row-end}]]]])]
-
- [:div.layout-row
- [:div.row-title "Align"]
- [:div.btn-wrapper
- [:& set-self-alignment {:is-col? false
- :alignment align-self
- :set-alignment set-alignment}]]]
- [:div.layout-row
- [:div.row-title "Justify"]
- [:div.btn-wrapper
- [:& set-self-alignment {:is-col? true
- :alignment justify-self
- :set-alignment set-justify-self}]]]
-
- [:div.layout-row.single-button
- [:div.btn-wrapper
- [:div.edit-mode
- [:button.tooltip.tooltip-bottom-left
- {:alt "Grid edit mode"
- :on-click toggle-edit-mode
- :style {:padding 0}}
- "Edit grid"
- i/grid-layout-mode]]]]]])))
+ [:div {:class (stl/css :row)}
+ [:button
+ {:class (stl/css :edit-grid-btn)
+ :alt (tr "workspace.layout_grid.editor.options.edit-grid")
+ :on-click toggle-edit-mode}
+ (tr "workspace.layout_grid.editor.options.edit-grid")]]])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.scss
index 66fa82d4e6..a2a3449f4e 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/grid_cell.scss
@@ -6,53 +6,51 @@
@import "refactor/common-refactor.scss";
-.grid-cell-menu {
- .grid-cell-menu-container {
- @include flexColumn;
- margin-top: $s-8;
- gap: $s-16;
- }
+.grid-cell-menu-container {
+ @include flexColumn;
+ margin-top: $s-8;
+ gap: $s-16;
+}
- .grid-cell-menu-title {
- font-size: $fs-11;
- }
+.grid-cell-menu-title {
+ font-size: $fs-11;
+}
- .row {
- @include flexRow;
- }
+.row {
+ @include flexRow;
+}
- .cell-mode :global(label) {
- padding: 0 $s-12;
- }
+.cell-mode :global(label) {
+ padding: 0 $s-12;
+}
- .edit-grid-btn {
- @extend .button-secondary;
- @include tabTitleTipography;
- width: 100%;
- padding: $s-8;
- }
+.edit-grid-btn {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ width: 100%;
+ padding: $s-8;
+}
- .area-input {
- @extend .input-element;
- width: 100%;
- padding: $s-8;
- }
+.area-input {
+ @extend .input-element;
+ width: 100%;
+ padding: $s-8;
}
.grid-coord-group {
@include flexRow;
-
border-radius: $br-8;
padding-left: $s-4;
background-color: var(--input-background-color);
-
- .icon svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- .coord-input {
- @extend .input-element;
- border-radius: 0 $br-8 $br-8 0;
- border-left: 1px solid var(--panel-background-color);
- }
+}
+
+.icon svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+}
+
+.coord-input {
+ @extend .input-element;
+ border-radius: 0 $br-8 $br-8 0;
+ border-left: 1px solid var(--panel-background-color);
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
index d99ca6ba1b..67138d85e0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
@@ -22,7 +22,6 @@
[app.main.ui.components.radio-buttons :refer [radio-buttons radio-button]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -45,15 +44,6 @@
[interaction]
(get (event-type-names) (:event-type interaction) "--"))
-(defn- action-type-names
- []
- {:navigate (tr "workspace.options.interaction-navigate-to")
- :open-overlay (tr "workspace.options.interaction-open-overlay")
- :toggle-overlay (tr "workspace.options.interaction-toggle-overlay")
- :close-overlay (tr "workspace.options.interaction-close-overlay")
- :prev-screen (tr "workspace.options.interaction-prev-screen")
- :open-url (tr "workspace.options.interaction-open-url")})
-
(defn- action-summary
[interaction destination]
(case (:action-type interaction)
@@ -69,34 +59,6 @@
:open-url (tr "workspace.options.interaction-open-url")
"--"))
-(defn- overlay-pos-type-names
- []
- {:manual (tr "workspace.options.interaction-pos-manual")
- :center (tr "workspace.options.interaction-pos-center")
- :top-left (tr "workspace.options.interaction-pos-top-left")
- :top-right (tr "workspace.options.interaction-pos-top-right")
- :top-center (tr "workspace.options.interaction-pos-top-center")
- :bottom-left (tr "workspace.options.interaction-pos-bottom-left")
- :bottom-right (tr "workspace.options.interaction-pos-bottom-right")
- :bottom-center (tr "workspace.options.interaction-pos-bottom-center")})
-
-(defn- animation-type-names
- [interaction]
- (cond->
- {:dissolve (tr "workspace.options.interaction-animation-dissolve")
- :slide (tr "workspace.options.interaction-animation-slide")}
-
- (ctsi/allow-push? (:action-type interaction))
- (assoc :push (tr "workspace.options.interaction-animation-push"))))
-
-(defn- easing-names
- []
- {:linear (tr "workspace.options.interaction-easing-linear")
- :ease (tr "workspace.options.interaction-easing-ease")
- :ease-in (tr "workspace.options.interaction-easing-ease-in")
- :ease-out (tr "workspace.options.interaction-easing-ease-out")
- :ease-in-out (tr "workspace.options.interaction-easing-ease-in-out")})
-
(defn- get-frames-options
[frames shape]
(->> frames
@@ -115,8 +77,7 @@
(mf/defc flow-item
[{:keys [flow]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- editing? (mf/use-state false)
+ (let [editing? (mf/use-state false)
flow-for-rename (mf/deref flow-for-rename-ref)
name-ref (mf/use-ref)
@@ -144,10 +105,10 @@
(mf/deps flow)
#(st/emit! (dw/select-shape (:starting-frame flow))))
- rename-flow
- (mf/use-fn
- (mf/deps flow)
- #(st/emit! (dwi/start-rename-flow (:id flow))))
+ ;; rename-flow
+ ;; (mf/use-fn
+ ;; (mf/deps flow)
+ ;; #(st/emit! (dwi/start-rename-flow (:id flow))))
remove-flow
(mf/use-fn
@@ -171,95 +132,59 @@
(let [name-input (mf/ref-val name-ref)]
(dom/select-text! name-input))
nil))
- (if new-css-system
- [:div {:class (stl/css :flow-element)}
- [:span {:class (stl/css :flow-info)}
- [:span {:class (stl/css :flow-name-wrapper)}
- [:button {:class (stl/css :start-flow-btn)
- :on-click start-flow}
- [:span {:class (stl/css :button-icon)}
- i/play-refactor]]
- [:span {:class (stl/css :flow-input-wrapper)}
- [:input
- {:class (stl/css :flow-input)
- :type "text"
- :ref name-ref
- :on-blur accept-edit
- :on-key-down on-key-down
- :default-value (:name flow "")}]]]]
- [:button {:class (stl/css :remove-flow-btn)
- :on-click remove-flow}
- i/remove-refactor]]
+ [:div {:class (stl/css :flow-element)}
+ [:span {:class (stl/css :flow-info)}
+ [:span {:class (stl/css :flow-name-wrapper)}
+ [:button {:class (stl/css :start-flow-btn)
+ :on-click start-flow}
+ [:span {:class (stl/css :button-icon)}
+ i/play-refactor]]
+ [:span {:class (stl/css :flow-input-wrapper)}
+ [:input
+ {:class (stl/css :flow-input)
+ :type "text"
+ :ref name-ref
+ :on-blur accept-edit
+ :on-key-down on-key-down
+ :default-value (:name flow "")}]]]]
- [:div.flow-element
- [:div.flow-button {:on-click start-flow} i/play]
- (if @editing?
- [:input.element-name
- {:type "text"
- :ref name-ref
- :on-blur accept-edit
- :on-key-down on-key-down
- :auto-focus true
- :default-value (:name flow "")}]
- [:span.element-label.flow-name
- {:on-double-click rename-flow}
- (:name flow)])
- [:div.add-page {:on-click remove-flow} i/minus]])))
+ [:button {:class (stl/css :remove-flow-btn)
+ :on-click remove-flow}
+ i/remove-refactor]]))
(mf/defc page-flows
[{:keys [flows]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- (when (seq flows)
- [:div {:class (stl/css :interaction-options)}
- [:& title-bar {:collapsable? false
- :title (tr "workspace.options.flows.flow-starts")
- :class (stl/css :title-spacing-layout-flow)}]
- (for [flow flows]
- [:& flow-item {:flow flow :key (str (:id flow))}])])
-
- (when (seq flows)
- [:div.element-set.interactions-options
- [:div.element-set-title
- [:span (tr "workspace.options.flows.flow-starts")]]
- (for [flow flows]
- [:& flow-item {:flow flow :key (str (:id flow))}])]))))
+ (when (seq flows)
+ [:div {:class (stl/css :interaction-options)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.flows.flow-starts")
+ :class (stl/css :title-spacing-layout-flow)}]
+ (for [flow flows]
+ [:& flow-item {:flow flow :key (str (:id flow))}])]))
(mf/defc shape-flows
[{:keys [flows shape]}]
(when (= (:type shape) :frame)
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- flow (ctp/get-frame-flow flows (:id shape))
+ (let [flow (ctp/get-frame-flow flows (:id shape))
add-flow (mf/use-fn #(st/emit! (dwi/add-flow-selected-frame)))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:& title-bar {:collapsable? false
- :title (tr "workspace.options.flows.flow")
- :class (stl/css :title-spacing-layout-flow)}
- (when (nil? flow)
- [:button {:class (stl/css :add-flow-btn)
- :title (tr "workspace.options.flows.add-flow-start")
- :on-click add-flow}
- i/add-refactor])]
- (when flow
- [:& flow-item {:flow flow :key (str (:id flow))}])]
+ [:div {:class (stl/css :element-set)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.flows.flow")
+ :class (stl/css :title-spacing-layout-flow)}
+ (when (nil? flow)
+ [:button {:class (stl/css :add-flow-btn)
+ :title (tr "workspace.options.flows.add-flow-start")
+ :on-click add-flow}
+ i/add-refactor])]
- [:div.element-set.interactions-options
- [:div.element-set-title
- [:span (tr "workspace.options.flows.flow-start")]]
- (if (nil? flow)
- [:div.flow-element
- [:span.element-label (tr "workspace.options.flows.add-flow-start")]
- [:div.add-page {:on-click add-flow}
- i/plus]]
- [:& flow-item {:flow flow :key (str (:id flow))}])]))))
+ (when flow
+ [:& flow-item {:flow flow :key (str (:id flow))}])])))
(mf/defc interaction-entry
[{:keys [index shape interaction update-interaction remove-interaction]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- objects (deref refs/workspace-page-objects)
+ (let [objects (deref refs/workspace-page-objects)
destination (get objects (:destination interaction))
frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? true}))
@@ -286,18 +211,14 @@
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (keyword event)
- (-> event dom/get-target dom/get-value d/read-string))]
+ (let [value (keyword event)]
(update-interaction index #(ctsi/set-event-type % value shape)))))
change-action-type
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (keyword event)
- (-> event dom/get-target dom/get-value d/read-string))]
+ (let [value (keyword event)]
(update-interaction index #(ctsi/set-action-type % value)))))
change-delay
@@ -310,9 +231,7 @@
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- event
- (-> event dom/get-target dom/get-value))
+ (let [value event
value (when (not= value "") (uuid/uuid value))]
(update-interaction index #(ctsi/set-destination % value)))))
@@ -320,12 +239,7 @@
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (uuid/uuid event)
- (-> event
- dom/get-target
- dom/get-value
- uuid/uuid))]
+ (let [value (uuid/uuid event)]
(update-interaction index #(ctsi/set-position-relative-to % value)))))
change-preserve-scroll
@@ -357,11 +271,8 @@
change-overlay-pos-type
(mf/use-fn
(mf/deps shape)
- (fn [event]
- (let [shape-id (:id shape)
- value (if new-css-system
- event
- (-> event dom/get-target dom/get-value d/read-string))]
+ (fn [value]
+ (let [shape-id (:id shape)]
(update-interaction index #(ctsi/set-overlay-pos-type % value shape objects))
(when (= value :manual)
(update-interaction index #(ctsi/set-position-relative-to % shape-id))))))
@@ -393,11 +304,9 @@
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (if (= "" event)
- nil
- (keyword event))
- (-> event dom/get-target dom/get-value d/read-string))]
+ (let [value (if (= "" event)
+ nil
+ (keyword event))]
(update-interaction index #(ctsi/set-animation-type % value)))))
change-duration
@@ -408,30 +317,21 @@
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (keyword event)
- (-> event dom/get-target dom/get-value d/read-string))]
+ (let [value (keyword event)]
(update-interaction index #(ctsi/set-easing % value)))))
change-way
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (keyword event)
- (-> event dom/get-target dom/get-value d/read-string))]
+ (let [value (keyword event)]
(update-interaction index #(ctsi/set-way % value)))))
change-direction
(mf/use-fn
(mf/deps index)
(fn [event]
- (let [value (if new-css-system
- (keyword event)
- (-> event
- dom/get-target
- (dom/get-data "value")
- keyword))]
+ (let [value (keyword event)]
(update-interaction index #(ctsi/set-direction % value)))))
change-offset-effect
@@ -502,565 +402,293 @@
{:icon :easing-ease-in-out-refactor :value :ease-in-out :label (tr "workspace.options.interaction-easing-ease-in-out")}]]
- (if new-css-system
- [:div {:class (stl/css-case :element-set-options-group true
- :open extended-open?)}
- ; Summary
- [:div {:class (stl/css :interactions-summary)}
- [:div {:class (stl/css-case :extend-btn true
- :extended extended-open?)
- :on-click toggle-extended}
- i/menu-refactor]
+ [:div {:class (stl/css-case :element-set-options-group true
+ :open extended-open?)}
+ ; Summary
+ [:div {:class (stl/css :interactions-summary)}
+ [:div {:class (stl/css-case :extend-btn true
+ :extended extended-open?)
+ :on-click toggle-extended}
+ i/menu-refactor]
- [:div {:class (stl/css :interactions-info)
- :on-click toggle-extended}
- [:div {:class (stl/css :trigger-name)} (event-type-name interaction)]
- [:div {:class (stl/css :action-summary)} (action-summary interaction destination)]]
- [:button {:class (stl/css :remove-btn)
- :data-value index
- :on-click #(remove-interaction index)}
- i/remove-refactor]]
+ [:div {:class (stl/css :interactions-info)
+ :on-click toggle-extended}
+ [:div {:class (stl/css :trigger-name)} (event-type-name interaction)]
+ [:div {:class (stl/css :action-summary)} (action-summary interaction destination)]]
+ [:button {:class (stl/css :remove-btn)
+ :data-value index
+ :on-click #(remove-interaction index)}
+ i/remove-refactor]]
- (when extended-open?
- [:div {:class (stl/css :extended-options)}
- ;; Trigger select
+ (when extended-open?
+ [:div {:class (stl/css :extended-options)}
+ ;; Trigger select
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)}
+ (tr "workspace.options.interaction-trigger")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (:event-type interaction)
+ :options event-type-options
+ :on-change change-event-type}]]]
+
+ ;; Delay
+ (when (ctsi/has-delay interaction)
[:div {:class (stl/css :property-row)}
[:span {:class (stl/css :interaction-name)}
- (tr "workspace.options.interaction-trigger")]
- [:div {:class (stl/css :select-wrapper)}
- [:& select {:class (stl/css :interaction-type-select)
- :default-value (:event-type interaction)
- :options event-type-options
- :on-change change-event-type}]]]
+ (tr "workspace.options.interaction-delay")]
+ [:div {:class (stl/css :input-element-wrapper)
+ :title (tr "workspace.options.interaction-ms")}
+ [:span.after (tr "workspace.options.interaction-ms")]
+ [:> numeric-input* {:ref ext-delay-ref
+ :className (stl/css :numeric-input)
+ :on-change change-delay
+ :value (:delay interaction)
+ :title (tr "workspace.options.interaction-ms")}]]])
- ;; Delay
- (when (ctsi/has-delay interaction)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)}
- (tr "workspace.options.interaction-delay")]
- [:div {:class (stl/css :input-element-wrapper)
- :title (tr "workspace.options.interaction-ms")}
- [:span.after (tr "workspace.options.interaction-ms")]
- [:> numeric-input* {:ref ext-delay-ref
- :className (stl/css :numeric-input)
- :on-change change-delay
- :value (:delay interaction)
- :title (tr "workspace.options.interaction-ms")}]]])
+ ;; Action select
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-action")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (:action-type interaction)
+ :options action-type-options
+ :on-change change-action-type}]]]
- ;; Action select
+ ;; Destination
+ (when (ctsi/has-destination interaction)
[:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-action")]
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-destination")]
[:div {:class (stl/css :select-wrapper)}
[:& select {:class (stl/css :interaction-type-select)
- :default-value (:action-type interaction)
- :options action-type-options
- :on-change change-action-type}]]]
+ :default-value (str (:destination interaction))
+ :options destination-options
+ :on-change change-destination}]]])
- ;; Destination
- (when (ctsi/has-destination interaction)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-destination")]
- [:div {:class (stl/css :select-wrapper)}
- [:& select {:class (stl/css :interaction-type-select)
- :default-value (str (:destination interaction))
- :options destination-options
- :on-change change-destination}]]])
+ ;; Preserve scroll
+ (when (ctsi/has-preserve-scroll interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "preserve-" index)
+ :class (stl/css-case :global/checked preserve-scroll?)}
+ [:span {:class (stl/css-case :global/checked preserve-scroll?)}
+ (when preserve-scroll?
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-preserve-scroll")
+ [:input {:type "checkbox"
+ :id (str "preserve-" index)
+ :checked preserve-scroll?
+ :on-change change-preserve-scroll}]]]])
- ;; Preserve scroll
- (when (ctsi/has-preserve-scroll interaction)
- [:div {:class (stl/css :property-row)}
- [:div {:class (stl/css :checkbox-option)}
- [:label {:for (str "preserve-" index)
- :class (stl/css-case :global/checked preserve-scroll?)}
- [:span {:class (stl/css-case :global/checked preserve-scroll?)}
- (when preserve-scroll?
- i/status-tick-refactor)]
- (tr "workspace.options.interaction-preserve-scroll")
- [:input {:type "checkbox"
- :id (str "preserve-" index)
- :checked preserve-scroll?
- :on-change change-preserve-scroll}]]]])
+ ;; URL
+ (when (ctsi/has-url interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-url")]
+ [:div {:class (stl/css :input-element-wrapper)}
+ [:input {:class (stl/css :input-text)
+ :type "url"
+ :placeholder "http://example.com"
+ :default-value (str (:url interaction))
+ :on-blur change-url}]]])
- ;; URL
- (when (ctsi/has-url interaction)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-url")]
- [:div {:class (stl/css :input-element-wrapper)}
- [:input {:class (stl/css :input-text)
- :type "url"
- :placeholder "http://example.com"
- :default-value (str (:url interaction))
- :on-blur change-url}]]])
+ (when (ctsi/has-overlay-opts interaction)
+ [:*
+ ;; Overlay position relative-to (select)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-relative-to")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (str (:position-relative-to interaction))
+ :options relative-to-opts
+ :on-change change-position-relative-to}]]]
- (when (ctsi/has-overlay-opts interaction)
- [:*
- ;; Overlay position relative-to (select)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-relative-to")]
- [:div {:class (stl/css :select-wrapper)}
- [:& select {:class (stl/css :interaction-type-select)
- :default-value (str (:position-relative-to interaction))
- :options relative-to-opts
- :on-change change-position-relative-to}]]]
+ ;; Overlay position (select)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-position")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (:overlay-pos-type interaction)
+ :options overlay-position-opts
+ :on-change change-overlay-pos-type}]]]
- ;; Overlay position (select)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-position")]
- [:div {:class (stl/css :select-wrapper)}
- [:& select {:class (stl/css :interaction-type-select)
- :default-value (:overlay-pos-type interaction)
- :options overlay-position-opts
- :on-change change-overlay-pos-type}]]]
+ ;; Overlay position (buttons)
+ [:div {:class (stl/css-case :property-row true
+ :big-row true)}
+ [:div {:class (stl/css :position-btns-wrapper)}
+ [:button {:class (stl/css-case :direction-btn true
+ :center-btn true
+ :active (= overlay-pos-type :center))
+ :data-value :center
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :top-left-btn true
+ :active (= overlay-pos-type :top-left))
+ :data-value :top-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :top-right-btn true
+ :active (= overlay-pos-type :top-right))
+ :data-value :top-right
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
- ;; Overlay position (buttons)
- [:div {:class (stl/css-case :property-row true
- :big-row true)}
- [:div {:class (stl/css :position-btns-wrapper)}
- [:button {:class (stl/css-case :direction-btn true
- :center-btn true
- :active (= overlay-pos-type :center))
- :data-value :center
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :top-left-btn true
- :active (= overlay-pos-type :top-left))
- :data-value :top-left
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :top-right-btn true
- :active (= overlay-pos-type :top-right))
- :data-value :top-right
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :top-center-btn true
+ :active (= overlay-pos-type :top-center))
+ :data-value :top-center
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-left-btn true
+ :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-left-btn true
+ :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :top-center-btn true
- :active (= overlay-pos-type :top-center))
- :data-value :top-center
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :bottom-left-btn true
- :active (= overlay-pos-type :bottom-left))
- :data-value :bottom-left
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :bottom-left-btn true
- :active (= overlay-pos-type :bottom-left))
- :data-value :bottom-left
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-left-btn true
+ :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-right-btn true
+ :active (= overlay-pos-type :bottom-right))
+ :data-value :bottom-right
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-center-btn true
+ :active (= overlay-pos-type :bottom-center))
+ :data-value :bottom-center
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]]]
- [:button {:class (stl/css-case :direction-btn true
- :bottom-left-btn true
- :active (= overlay-pos-type :bottom-left))
- :data-value :bottom-left
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :bottom-right-btn true
- :active (= overlay-pos-type :bottom-right))
- :data-value :bottom-right
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]
- [:button {:class (stl/css-case :direction-btn true
- :bottom-center-btn true
- :active (= overlay-pos-type :bottom-center))
- :data-value :bottom-center
- :on-click toggle-overlay-pos-type}
- [:span {:class (stl/css :rectangle)}]]]]
-
- ;; Overlay click outside
- [:div {:class (stl/css :property-row)}
- [:div {:class (stl/css :checkbox-option)}
- [:label {:for (str "close-" index)
- :class (stl/css-case :global/checked close-click-outside?)}
- [:span {:class (stl/css-case :global/checked close-click-outside?)}
- (when close-click-outside?
- i/status-tick-refactor)]
- (tr "workspace.options.interaction-close-outside")
- [:input {:type "checkbox"
- :id (str "close-" index)
- :checked close-click-outside?
- :on-change change-close-click-outside}]]]]
-
- ;; Overlay background
- [:div {:class (stl/css :property-row)}
- [:div {:class (stl/css :checkbox-option)}
- [:label {:for (str "background-" index)
- :class (stl/css-case :global/checked background-overlay?)}
- [:span {:class (stl/css-case :global/checked background-overlay?)}
- (when background-overlay?
- i/status-tick-refactor)]
- (tr "workspace.options.interaction-background")
- [:input {:type "checkbox"
- :id (str "background-" index)
- :checked background-overlay?
- :on-change change-background-overlay}]]]]])
-
- (when (ctsi/has-animation? interaction)
- [:*
- ;; Animation select
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-animation")]
- [:div {:class (stl/css :select-wrapper)}
- [:& select {:class (stl/css :animation-select)
- :default-value (or (-> interaction :animation :animation-type) "")
- :options animation-opts
- :on-change change-animation-type}]]]
-
- ;; Direction
- (when (ctsi/has-way? interaction)
- [:div {:class (stl/css :property-row)}
- [:div {:class (stl/css :inputs-wrapper)}
-
- [:& radio-buttons {:selected (d/name way)
- :on-change change-way
- :name "animation-way"}
- [:& radio-button {:value "in"
- :id "animation-way-in"}]
- [:& radio-button {:id "animation-way-out"
- :value "out"}]]]])
-
- ;; Direction
- (when (ctsi/has-direction? interaction)
- [:div {:class (stl/css :property-row)}
- [:div {:class (stl/css :buttons-wrapper)}
- [:& radio-buttons {:selected (d/name direction)
- :on-change change-direction
- :name "animation-direction"}
- [:& radio-button {:icon i/column-refactor
- :icon-class (stl/css :right)
- :value "right"
- :id "animation-right"}]
- [:& radio-button {:icon i/column-refactor
- :icon-class (stl/css :left)
- :id "animation-left"
- :value "left"}]
- [:& radio-button {:icon i/column-refactor
- :icon-class (stl/css :down)
- :id "animation-down"
- :value "down"}]
- [:& radio-button {:icon i/column-refactor
- :icon-class (stl/css :up)
- :id "animation-up"
- :value "up"}]]]])
-
- ;; Duration
- (when (ctsi/has-duration? interaction)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-duration")]
- [:div {:class (stl/css :input-element-wrapper)
- :title (tr "workspace.options.interaction-ms")}
- [:span.after (tr "workspace.options.interaction-ms")]
- [:> numeric-input* {:ref ext-duration-ref
- :on-change change-duration
- :value (-> interaction :animation :duration)
- :title (tr "workspace.options.interaction-ms")}]]])
-
- ;; Easing
- (when (ctsi/has-easing? interaction)
- [:div {:class (stl/css :property-row)}
- [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-easing")]
- [:div {:class (stl/css :select-wrapper)}
- [:& select {:class (stl/css :easing-select)
- :dropdown-class (stl/css :dropdown-upwards)
- :default-value (-> interaction :animation :easing)
- :options easing-options
- :on-change change-easing}]]])
-
- ;; Offset effect
- (when (ctsi/has-offset-effect? interaction)
- [:div {:class (stl/css :property-row)}
- [:div {:class (stl/css :checkbox-option)}
- [:label {:for (str "offset-effect-" index)
- :class (stl/css-case :global/checked (-> interaction :animation :offset-effect))}
- [:span {:class (stl/css-case :global/checked (-> interaction :animation :offset-effect))}
- (when (-> interaction :animation :offset-effect)
- i/status-tick-refactor)]
- (tr "workspace.options.interaction-offset-effect")
- [:input {:type "checkbox"
- :id (str "offset-effect-" index)
- :checked (-> interaction :animation :offset-effect)
- :on-change change-offset-effect}]]]])])])]
-
-
- [:div.element-set-options-group {:class (dom/classnames
- :open extended-open?)}
- ; Summary
- [:div.element-set-actions-button {:on-click toggle-extended}
- i/actions]
- [:div.interactions-summary {:on-click toggle-extended}
- [:div.trigger-name (event-type-name interaction)]
- [:div.action-summary (action-summary interaction destination)]]
- [:div.element-set-actions {:on-click #(remove-interaction index)}
- [:div.element-set-actions-button i/minus]]
-
- (when extended-open?
- [:div.element-set-content
-
- ;; Trigger select
- [:div.interactions-element.separator
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-trigger")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:event-type interaction))
- :on-change change-event-type}
- (for [[value name] (event-type-names)]
- (when-not (and (= value :after-delay)
- (not= (:type shape) :frame))
- [:option {:key (dm/str value)
- :value (dm/str value)} name]))]]
-
- ;; Delay
- (when (ctsi/has-delay interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-delay")]
- [:div.input-element {:title (tr "workspace.options.interaction-ms")}
- [:> numeric-input* {:ref ext-delay-ref
- :on-change change-delay
- :value (:delay interaction)
- :title (tr "workspace.options.interaction-ms")}]
- [:span.after (tr "workspace.options.interaction-ms")]]])
-
- ;; Action select
- [:div.interactions-element.separator
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-action")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:action-type interaction))
- :on-change change-action-type}
- (for [[value name] (action-type-names)]
- [:option {:key (dm/str "action-" value)
- :value (str value)} name])]]
-
- ;; Destination
- (when (ctsi/has-destination interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:destination interaction))
- :on-change change-destination}
- (if (= (:action-type interaction) :close-overlay)
- [:option {:value ""} (tr "workspace.options.interaction-self")]
- [:option {:value ""} (tr "workspace.options.interaction-none")])
- (for [frame frames]
- (when (and (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
- (not= (:id frame) (:frame-id shape))) ; nor a shape to its container frame
- [:option {:key (dm/str "destination-" (:id frame))
- :value (str (:id frame))} (:name frame)]))]])
-
- ;; Preserve scroll
- (when (ctsi/has-preserve-scroll interaction)
- [:div.interactions-element
- [:div.input-checkbox
+ ;; Overlay click outside
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "close-" index)
+ :class (stl/css-case :global/checked close-click-outside?)}
+ [:span {:class (stl/css-case :global/checked close-click-outside?)}
+ (when close-click-outside?
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-close-outside")
[:input {:type "checkbox"
- :id (str "preserve-" index)
- :checked preserve-scroll?
- :on-change change-preserve-scroll}]
- [:label {:for (str "preserve-" index)}
- (tr "workspace.options.interaction-preserve-scroll")]]])
+ :id (str "close-" index)
+ :checked close-click-outside?
+ :on-change change-close-click-outside}]]]]
- ;; URL
- (when (ctsi/has-url interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-url")]
- [:input.input-text {:type "url"
- :placeholder "http://example.com"
- :default-value (str (:url interaction))
- :on-blur change-url}]])
+ ;; Overlay background
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "background-" index)
+ :class (stl/css-case :global/checked background-overlay?)}
+ [:span {:class (stl/css-case :global/checked background-overlay?)}
+ (when background-overlay?
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-background")
+ [:input {:type "checkbox"
+ :id (str "background-" index)
+ :checked background-overlay?
+ :on-change change-background-overlay}]]]]])
- (when (ctsi/has-overlay-opts interaction)
- [:*
- ;; Overlay position relative-to (select)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-relative-to")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:position-relative-to interaction))
- :on-change change-position-relative-to}
- (when (not= (:overlay-pos-type interaction) :manual)
- [:*
- [:option {:value ""} (tr "workspace.options.interaction-auto")]
- (for [frame shape-parents]
- [:option {:key (dm/str "position-relative-to-" (:id frame))
- :value (str (:id frame))} (:name frame)])])
- [:option {:key (dm/str "position-relative-to-" (:id shape))
- :value (str (:id shape))} (:name shape) " (" (tr "workspace.options.interaction-self") ")"]]]
+ (when (ctsi/has-animation? interaction)
+ [:*
+ ;; Animation select
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-animation")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :animation-select)
+ :default-value (or (-> interaction :animation :animation-type) "")
+ :options animation-opts
+ :on-change change-animation-type}]]]
- ;; Overlay position (select)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-position")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:overlay-pos-type interaction))
- :on-change change-overlay-pos-type}
- (for [[value name] (overlay-pos-type-names)]
- [:option {:value (str value)} name])]]
+ ;; Direction
+ (when (ctsi/has-way? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :inputs-wrapper)}
- ;; Overlay position (buttons)
- [:div.interactions-element.interactions-pos-buttons
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :center))
- :data-value :center
- :on-click toggle-overlay-pos-type}
- i/position-center]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :top-left))
- :data-value :top-left
- :on-click toggle-overlay-pos-type}
- i/position-top-left]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :top-right))
- :data-value :top-right
- :on-click toggle-overlay-pos-type}
- i/position-top-right]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :top-center))
- :data-value :top-center
- :on-click toggle-overlay-pos-type}
- i/position-top-center]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :bottom-left))
- :data-value :bottom-center
- :on-click toggle-overlay-pos-type}
- i/position-bottom-left]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :bottom-right))
- :data-value :bottom-right
- :on-click toggle-overlay-pos-type}
- i/position-bottom-right]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :bottom-center))
- :data-value :bottom-center
- :on-click toggle-overlay-pos-type}
- i/position-bottom-center]]
+ [:& radio-buttons {:selected (d/name way)
+ :on-change change-way
+ :name "animation-way"}
+ [:& radio-button {:value "in"
+ :id "animation-way-in"}]
+ [:& radio-button {:id "animation-way-out"
+ :value "out"}]]]])
- ;; Overlay click outside
- [:div.interactions-element
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id (str "close-" index)
- :checked close-click-outside?
- :on-change change-close-click-outside}]
- [:label {:for (str "close-" index)}
- (tr "workspace.options.interaction-close-outside")]]]
+ ;; Direction
+ (when (ctsi/has-direction? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :buttons-wrapper)}
+ [:& radio-buttons {:selected (d/name direction)
+ :on-change change-direction
+ :name "animation-direction"}
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :right)
+ :value "right"
+ :id "animation-right"}]
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :left)
+ :id "animation-left"
+ :value "left"}]
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :down)
+ :id "animation-down"
+ :value "down"}]
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :up)
+ :id "animation-up"
+ :value "up"}]]]])
- ;; Overlay background
- [:div.interactions-element
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id (str "background-" index)
- :checked background-overlay?
- :on-change change-background-overlay}]
- [:label {:for (str "background-" index)}
- (tr "workspace.options.interaction-background")]]]])
+ ;; Duration
+ (when (ctsi/has-duration? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-duration")]
+ [:div {:class (stl/css :input-element-wrapper)
+ :title (tr "workspace.options.interaction-ms")}
+ [:span.after (tr "workspace.options.interaction-ms")]
+ [:> numeric-input* {:ref ext-duration-ref
+ :on-change change-duration
+ :value (-> interaction :animation :duration)
+ :title (tr "workspace.options.interaction-ms")}]]])
- (when (ctsi/has-animation? interaction)
- [:*
- ;; Animation select
- [:div.interactions-element.separator
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-animation")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (-> interaction :animation :animation-type))
- :on-change change-animation-type}
- [:option {:value ""} (tr "workspace.options.interaction-animation-none")]
- (for [[value name] (animation-type-names interaction)]
- [:option {:value (str value)} name])]]
+ ;; Easing
+ (when (ctsi/has-easing? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-easing")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :easing-select)
+ :dropdown-class (stl/css :dropdown-upwards)
+ :default-value (-> interaction :animation :easing)
+ :options easing-options
+ :on-change change-easing}]]])
- ;; Direction
- (when (ctsi/has-way? interaction)
- [:div.interactions-element.interactions-way-buttons
- [:div.input-radio
- [:input {:type "radio"
- :id "way-in"
- :checked (= :in way)
- :name "animation-way"
- :value ":in"
- :on-change change-way}]
- [:label {:for "way-in"} (tr "workspace.options.interaction-in")]]
- [:div.input-radio
- [:input {:type "radio"
- :id "way-out"
- :checked (= :out way)
- :name "animation-way"
- :value ":out"
- :on-change change-way}]
- [:label {:for "way-out"} (tr "workspace.options.interaction-out")]]])
-
- ;; Direction
- (when (ctsi/has-direction? interaction)
- [:div.interactions-element.interactions-direction-buttons
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :right))
- :data-value :right
- :on-click change-direction}
- i/animate-right]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :down))
- :data-value :up
- :on-click change-direction}
- i/animate-down]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :left))
- :data-value :left
- :on-click change-direction}
- i/animate-left]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :up))
- :data-value :down
- :on-click change-direction}
- i/animate-up]])
-
- ;; Duration
- (when (ctsi/has-duration? interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-duration")]
- [:div.input-element {:title (tr "workspace.options.interaction-ms")}
- [:> numeric-input* {:ref ext-duration-ref
- :on-change change-duration
- :value (-> interaction :animation :duration)
- :title (tr "workspace.options.interaction-ms")}]
- [:span.after (tr "workspace.options.interaction-ms")]]])
-
- ;; Easing
- (when (ctsi/has-easing? interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-easing")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (-> interaction :animation :easing))
- :on-change change-easing}
- (for [[value name] (easing-names)]
- [:option {:value (str value)} name])]
- [:div.interactions-easing-icon
- (case (-> interaction :animation :easing)
- :linear i/easing-linear
- :ease i/easing-ease
- :ease-in i/easing-ease-in
- :ease-out i/easing-ease-out
- :ease-in-out i/easing-ease-in-out)]])
-
- ;; Offset effect
- (when (ctsi/has-offset-effect? interaction)
- [:div.interactions-element
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id (str "offset-effect-" index)
- :checked (-> interaction :animation :offset-effect)
- :on-change change-offset-effect}]
- [:label {:for (str "offset-effect-" index)}
- (tr "workspace.options.interaction-offset-effect")]]])])])])))
+ ;; Offset effect
+ (when (ctsi/has-offset-effect? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "offset-effect-" index)
+ :class (stl/css-case :global/checked (-> interaction :animation :offset-effect))}
+ [:span {:class (stl/css-case :global/checked (-> interaction :animation :offset-effect))}
+ (when (-> interaction :animation :offset-effect)
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-offset-effect")
+ [:input {:type "checkbox"
+ :id (str "offset-effect-" index)
+ :checked (-> interaction :animation :offset-effect)
+ :on-change change-offset-effect}]]]])])])]))
(mf/defc interactions-menu
[{:keys [shape] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- interactions (get shape :interactions [])
+ (let [interactions (get shape :interactions [])
options (mf/deref refs/workspace-page-options)
flows (:flows options)
@@ -1076,76 +704,43 @@
update-interaction
(fn [index update-fn]
(st/emit! (dwi/update-interaction shape index update-fn)))]
- (if new-css-system
- [:div {:class (stl/css :interactions-content)}
- (if shape
- [:& shape-flows {:flows flows
- :shape shape}]
- [:& page-flows {:flows flows}])
- [:div {:class (stl/css :interaction-options)}
- (when (and shape (not (cfh/unframed-shape? shape)))
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? false
- :title (tr "workspace.options.interactions")
- :class (stl/css :title-spacing-layout-interactions)}
+ [:div {:class (stl/css :interactions-content)}
+ (if shape
+ [:& shape-flows {:flows flows
+ :shape shape}]
+ [:& page-flows {:flows flows}])
+ [:div {:class (stl/css :interaction-options)}
+ (when (and shape (not (cfh/unframed-shape? shape)))
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.interactions")
+ :class (stl/css :title-spacing-layout-interactions)}
- [:button {:class (stl/css :add-interaction-btn)
- :on-click add-interaction}
- i/add-refactor]]])
- [:div {:class (stl/css :help-content)}
- (when (= (count interactions) 0)
- [:*
- (when (and shape (not (cfh/unframed-shape? shape)))
- [:div {:class (stl/css :help-group)}
- [:div {:class (stl/css :interactions-help-icon)} i/add-refactor]
- [:div {:class (stl/css :interactions-help)}
- (tr "workspace.options.add-interaction")]])
+ [:button {:class (stl/css :add-interaction-btn)
+ :on-click add-interaction}
+ i/add-refactor]]])
+ [:div {:class (stl/css :help-content)}
+ (when (= (count interactions) 0)
+ [:*
+ (when (and shape (not (cfh/unframed-shape? shape)))
[:div {:class (stl/css :help-group)}
- [:div {:class (stl/css :interactions-help-icon)} i/interaction-refactor]
+ [:div {:class (stl/css :interactions-help-icon)} i/add-refactor]
[:div {:class (stl/css :interactions-help)}
- (tr "workspace.options.select-a-shape")]]
- [:div {:class (stl/css :help-group)}
- [:div {:class (stl/css :interactions-help-icon)} i/play-refactor]
- [:div {:class (stl/css :interactions-help)}
- (tr "workspace.options.use-play-button")]]])]
- [:div {:class (stl/css :groups)}
- (for [[index interaction] (d/enumerate interactions)]
- [:& interaction-entry {:key (dm/str (:id shape) "-" index)
- :index index
- :shape shape
- :interaction interaction
- :update-interaction update-interaction
- :remove-interaction remove-interaction}])]]]
-
- [:*
- (if shape
- [:& shape-flows {:flows flows
- :shape shape}]
- [:& page-flows {:flows flows}])
-
- [:div.element-set.interactions-options
- (when (and shape (not (cfh/unframed-shape? shape)))
- [:div.element-set-title
- [:span (tr "workspace.options.interactions")]
- [:div.add-page {:on-click add-interaction}
- i/plus]])
- [:div.element-set-content
- (when (= (count interactions) 0)
- [:*
- (when (and shape (not (cfh/unframed-shape? shape)))
- [:*
- [:div.interactions-help-icon i/plus]
- [:div.interactions-help.separator (tr "workspace.options.add-interaction")]])
- [:div.interactions-help-icon i/interaction]
- [:div.interactions-help (tr "workspace.options.select-a-shape")]
- [:div.interactions-help-icon i/play]
- [:div.interactions-help (tr "workspace.options.use-play-button")]])]
- [:div.groups
- (for [[index interaction] (d/enumerate interactions)]
- [:& interaction-entry {:key (dm/str (:id shape) "-" index)
- :index index
- :shape shape
- :interaction interaction
- :update-interaction update-interaction
- :remove-interaction remove-interaction}])]]])))
+ (tr "workspace.options.add-interaction")]])
+ [:div {:class (stl/css :help-group)}
+ [:div {:class (stl/css :interactions-help-icon)} i/interaction-refactor]
+ [:div {:class (stl/css :interactions-help)}
+ (tr "workspace.options.select-a-shape")]]
+ [:div {:class (stl/css :help-group)}
+ [:div {:class (stl/css :interactions-help-icon)} i/play-refactor]
+ [:div {:class (stl/css :interactions-help)}
+ (tr "workspace.options.use-play-button")]]])]
+ [:div {:class (stl/css :groups)}
+ (for [[index interaction] (d/enumerate interactions)]
+ [:& interaction-entry {:key (dm/str (:id shape) "-" index)
+ :index index
+ :shape shape
+ :interaction interaction
+ :update-interaction update-interaction
+ :remove-interaction remove-interaction}])]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss
index 87eb4017a9..9ab6a9d811 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss
@@ -10,69 +10,76 @@
display: flex;
flex-direction: column;
gap: $s-8;
- .interaction-options {
- @include flexColumn;
- .element-title {
- .add-interaction-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- }
- }
+}
- .help-content {
- padding: $s-20;
- .help-group {
- margin-bottom: $s-40;
- .interactions-help-icon {
- @include flexCenter;
- width: $s-48;
- height: $s-48;
- border-radius: $br-circle;
- background-color: var(--pill-background-color);
- margin: 0 auto $s-12 auto;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- height: $s-32;
- width: $s-32;
- }
- }
- .interactions-help {
- @include titleTipography;
- text-align: center;
- }
- }
- }
+.interaction-options {
+ @include flexColumn;
+}
+
+.add-interaction-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
}
- .element-set {
- @include flexColumn;
- .add-flow-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
+}
+
+.help-content {
+ padding: $s-20;
+}
+
+.help-group {
+ margin-bottom: $s-40;
+}
+
+.interactions-help-icon {
+ @include flexCenter;
+ width: $s-48;
+ height: $s-48;
+ border-radius: $br-circle;
+ background-color: var(--pill-background-color);
+ margin: 0 auto $s-12 auto;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ height: $s-32;
+ width: $s-32;
+ }
+}
+
+.interactions-help {
+ @include titleTipography;
+ text-align: center;
+ color: var(--title-foreground-color);
+}
+
+.element-set {
+ @include flexColumn;
+}
+
+.add-flow-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
}
.interactions-info {
flex-grow: 1;
display: grid;
+}
- .trigger-name {
- color: var(--color-foreground-primary);
- }
- .action-summary {
- color: var(--color-foreground-secondary);
- @include textEllipsis;
- }
+.trigger-name {
+ color: var(--color-foreground-primary);
+}
+
+.action-summary {
+ color: var(--color-foreground-secondary);
+ @include textEllipsis;
}
.groups {
@@ -96,6 +103,7 @@
width: $s-92;
margin: auto 0;
grid-area: name;
+ color: var(--title-foreground-color);
}
.select-wrapper {
display: flex;
@@ -231,91 +239,97 @@
.flow-element {
@include flexRow;
- .flow-info {
- display: flex;
- align-items: center;
- gap: $s-2;
- border-radius: $s-8;
- background-color: var(--input-details-color);
- height: $s-32;
- width: 100%;
- flex-grow: 1;
- .flow-name-wrapper {
- @include titleTipography;
- @include focusInput;
- display: flex;
- align-items: center;
- gap: $s-4;
- flex-grow: 1;
- height: $s-32;
- width: 100%;
- border-radius: $br-8;
- padding: 0;
- margin-right: 0;
- background-color: var(--input-background-color);
- border: $s-1 solid var(--input-background-color);
- color: var(--input-foreground-color);
- .start-flow-btn {
- @include buttonStyle;
- height: $s-32;
- width: $s-28;
- padding: 0 $s-2 0 $s-8;
- border-radius: $br-8 0 0 $br-8;
- background-color: transparent;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- &:hover {
- stroke: var(--input-foreground-color-active);
- }
- }
- }
- .flow-input {
- @extend .input-base;
- background-color: transparent;
- height: $s-28;
- }
- .flow-input-wrapper {
- @include titleTipography;
- display: flex;
- align-items: center;
- height: $s-28;
- padding: 0;
- width: 100%;
- margin: 0;
- flex-grow: 1;
- background-color: transparent;
- color: var(--input-foreground-color);
- border-radius: $br-8;
- }
- &:hover {
- background-color: var(--input-background-color-hover);
- border: $s-1 solid var(--input-background-color-hover);
- &:active {
- background-color: var(--input-background-color-active);
- .flow-input-wrapper {
- background-color: var(--input-background-color-active);
- }
- }
- }
- &:focus,
- &:focus-within {
- background-color: var(--input-background-color-active);
- }
+}
- &.editing {
- background-color: var(--input-background-color-active);
- }
- }
- }
+.flow-info {
+ display: flex;
+ align-items: center;
+ gap: $s-2;
+ border-radius: $s-8;
+ background-color: var(--input-details-color);
+ height: $s-32;
+ width: 100%;
+ flex-grow: 1;
+}
- .remove-flow-btn {
- @extend .button-tertiary;
+.flow-name-wrapper {
+ @include titleTipography;
+ @include focusInput;
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ flex-grow: 1;
+ height: $s-32;
+ width: 100%;
+ border-radius: $br-8;
+ padding: 0;
+ margin-right: 0;
+ background-color: var(--input-background-color);
+ border: $s-1 solid var(--input-background-color);
+ color: var(--input-foreground-color);
+ .start-flow-btn {
+ @include buttonStyle;
height: $s-32;
width: $s-28;
- min-width: $s-28;
+ padding: 0 $s-2 0 $s-8;
+ border-radius: $br-8 0 0 $br-8;
+ background-color: transparent;
svg {
@extend .button-icon;
+ stroke: var(--icon-foreground);
+ &:hover {
+ stroke: var(--input-foreground-color-active);
+ }
}
}
+
+ .flow-input {
+ @extend .input-base;
+ background-color: transparent;
+ height: $s-28;
+ }
+
+ .flow-input-wrapper {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ height: $s-28;
+ padding: 0;
+ width: 100%;
+ margin: 0;
+ flex-grow: 1;
+ background-color: transparent;
+ color: var(--input-foreground-color);
+ border-radius: $br-8;
+ }
+
+ &:hover {
+ background-color: var(--input-background-color-hover);
+ border: $s-1 solid var(--input-background-color-hover);
+ &:active {
+ background-color: var(--input-background-color-active);
+ .flow-input-wrapper {
+ background-color: var(--input-background-color-active);
+ }
+ }
+ }
+
+ &:focus,
+ &:focus-within {
+ background-color: var(--input-background-color-active);
+ }
+
+ &.editing {
+ background-color: var(--input-background-color-active);
+ }
+}
+
+.remove-flow-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ min-width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs
index 7dedfd571d..bdfec509f4 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs
@@ -14,7 +14,6 @@
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.select :refer [select]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -33,9 +32,7 @@
(mf/defc layer-menu
{::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- ids (unchecked-get props "ids")
- type (unchecked-get props "type")
+ (let [ids (unchecked-get props "ids")
values (unchecked-get props "values")
hidden? (:hidden values)
@@ -148,90 +145,46 @@
preview-complete?))
(swap! state* assoc :selected-blend-mode current-blend-mode)))
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css-case :element-set-content true
- :hidden hidden?)}
- [:div {:class (stl/css :select)}
- [:& select
- {:default-value selected-blend-mode
- :options options
- :on-change handle-change-blend-mode
- :is-open? option-highlighted?
- :class (stl/css-case :hidden-select hidden?)
- :on-pointer-enter-option handle-blend-mode-enter
- :on-pointer-leave-option handle-blend-mode-leave}]]
- [:div {:class (stl/css :input)
- :title (tr "workspace.options.opacity")}
- [:span {:class (stl/css :icon)} "%"]
- [:> numeric-input*
- {:value (opacity->string current-opacity)
- :placeholder (tr "settings.multiple")
- :on-change handle-opacity-change
- :min 0
- :max 100
- :className (stl/css :numeric-input)}]]
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css-case :element-set-content true
+ :hidden hidden?)}
+ [:div {:class (stl/css :select)}
+ [:& select
+ {:default-value selected-blend-mode
+ :options options
+ :on-change handle-change-blend-mode
+ :is-open? option-highlighted?
+ :class (stl/css-case :hidden-select hidden?)
+ :on-pointer-enter-option handle-blend-mode-enter
+ :on-pointer-leave-option handle-blend-mode-leave}]]
+ [:div {:class (stl/css :input)
+ :title (tr "workspace.options.opacity")}
+ [:span {:class (stl/css :icon)} "%"]
+ [:> numeric-input*
+ {:value (opacity->string current-opacity)
+ :placeholder (tr "settings.multiple")
+ :on-change handle-opacity-change
+ :min 0
+ :max 100
+ :className (stl/css :numeric-input)}]]
- [:div {:class (stl/css :actions)}
- (cond
- (or (= :multiple hidden?) (not hidden?))
- [:button {:on-click handle-set-hidden
- :class (stl/css :hidden-btn)} i/shown-refactor]
+ [:div {:class (stl/css :actions)}
+ (cond
+ (or (= :multiple hidden?) (not hidden?))
+ [:button {:on-click handle-set-hidden
+ :class (stl/css :hidden-btn)} i/shown-refactor]
- :else
- [:button {:on-click handle-set-visible
- :class (stl/css :hidden-btn)} i/hide-refactor])
+ :else
+ [:button {:on-click handle-set-visible
+ :class (stl/css :hidden-btn)} i/hide-refactor])
- (cond
- (or (= :multiple blocked?) (not blocked?))
- [:button {:on-click handle-set-blocked
- :class (stl/css :lock-btn)} i/unlock-refactor]
+ (cond
+ (or (= :multiple blocked?) (not blocked?))
+ [:button {:on-click handle-set-blocked
+ :class (stl/css :lock-btn)} i/unlock-refactor]
- :else
- [:button {:on-click handle-set-unblocked
- :class (stl/css-case :lock-btn true
- :locked blocked?)} i/lock-refactor])]]]
-
- [:div.element-set
- [:div.element-set-title
- [:span
- (case type
- :multiple (tr "workspace.options.layer-options.title.multiple")
- :group (tr "workspace.options.layer-options.title.group")
- (tr "workspace.options.layer-options.title"))]]
-
- [:div.element-set-content
- [:div.row-flex
- [:& select
- {:class "flex-grow no-check"
- :default-value selected-blend-mode
- :options options
- :on-change handle-change-blend-mode
- :is-open? option-highlighted?
- :on-pointer-enter-option handle-blend-mode-enter
- :on-pointer-leave-option handle-blend-mode-leave}]
-
- [:div.input-element {:title (tr "workspace.options.opacity")
- :class "percentail"}
- [:> numeric-input*
- {:value (opacity->string current-opacity)
- :placeholder (tr "settings.multiple")
- :on-change handle-opacity-change
- :min 0
- :max 100}]]
-
- [:div.element-set-actions.layer-actions
- (cond
- (or (= :multiple hidden?) (not hidden?))
- [:div.element-set-actions-button {:on-click handle-set-hidden} i/eye]
-
- :else
- [:div.element-set-actions-button {:on-click handle-set-visible} i/eye-closed])
-
- (cond
- (or (= :multiple blocked?) (not blocked?))
- [:div.element-set-actions-button {:on-click handle-set-blocked} i/unlock]
-
- :else
- [:div.element-set-actions-button {:on-click handle-set-unblocked} i/lock])]]]])))
+ :else
+ [:button {:on-click handle-set-unblocked
+ :class (stl/css-case :lock-btn true
+ :locked blocked?)} i/lock-refactor])]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
index 7d8f31d768..93be5aa25c 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
@@ -8,48 +8,48 @@
.element-set {
margin-bottom: $s-8;
- .element-set-content {
+}
+.element-set-content {
+ display: flex;
+ height: $s-32;
+ gap: $s-4;
+ .select {
+ width: $s-124;
+ padding: 0;
+ }
+ .input {
+ @extend .input-element;
+ width: $s-60;
+ }
+ .actions {
display: flex;
- height: $s-32;
gap: $s-4;
- .select {
- width: $s-124;
- padding: 0;
+ .hidden-btn,
+ .lock-btn {
+ @extend .button-tertiary;
+ border-radius: $br-8;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ }
+ }
+
+ &.hidden {
+ .hidden-select {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
}
.input {
- @extend .input-element;
- width: $s-60;
- }
- .actions {
- display: flex;
- gap: $s-4;
- .hidden-btn,
- .lock-btn {
- @extend .button-tertiary;
- border-radius: $br-8;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
+ .icon {
+ stroke: var(--input-foreground-color-disabled);
}
- }
-
- &.hidden {
- .hidden-select {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- .input {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- .icon {
- stroke: var(--input-foreground-color-disabled);
- }
- .numeric-input {
- color: var(--input-foreground-color-disabled);
- }
+ .numeric-input {
+ color: var(--input-foreground-color-disabled);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs
index 8138f0a3e4..c9069edbbf 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs
@@ -23,7 +23,6 @@
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
@@ -41,29 +40,6 @@
:column i/column-refactor
:column-reverse i/column-reverse-refactor))
-(mf/defc direction-btn
- [{:keys [dir saved-dir on-click icon?] :as props}]
- (let [handle-on-click
- (mf/use-fn
- (mf/deps on-click dir)
- (fn []
- (when (some? on-click)
- (on-click dir))))]
-
- [:button.dir.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= saved-dir dir)
- :row (= :row dir)
- :row-reverse (= :row-reverse dir)
- :column-reverse (= :column-reverse dir)
- :column (= :column dir))
- :key (dm/str "direction-" dir)
- :alt (str/replace (str/capital (d/name dir)) "-" " ")
- :on-click handle-on-click}
- (if icon?
- i/auto-direction
- (str/replace (str/capital (d/name dir)) "-" " "))]))
-
-
;; FLEX COMPONENTS
(def layout-container-flex-attrs
@@ -85,86 +61,6 @@
:layout-grid-rows])
(defn get-layout-flex-icon
- [type val is-col?]
- (case type
- :align-items
- (if is-col?
- (case val
- :start i/align-items-column-start
- :end i/align-items-column-end
- :center i/align-items-column-center
- :stretch i/align-items-column-strech
- :baseline i/align-items-column-baseline)
- (case val
- :start i/align-items-row-start
- :end i/align-items-row-end
- :center i/align-items-row-center
- :stretch i/align-items-row-strech
- :baseline i/align-items-row-baseline))
-
- :justify-content
- (if is-col?
- (case val
- :start i/justify-content-column-start
- :end i/justify-content-column-end
- :center i/justify-content-column-center
- :space-around i/justify-content-column-around
- :space-evenly i/justify-content-column-evenly
- :space-between i/justify-content-column-between)
- (case val
- :start i/justify-content-row-start
- :end i/justify-content-row-end
- :center i/justify-content-row-center
- :space-around i/justify-content-row-around
- :space-evenly i/justify-content-row-evenly
- :space-between i/justify-content-row-between))
-
- :align-content
- (if is-col?
- (case val
- :start i/align-content-column-start
- :end i/align-content-column-end
- :center i/align-content-column-center
- :space-around i/align-content-column-around
- :space-evenly i/align-content-column-evenly
- :space-between i/align-content-column-between
- :stretch nil)
-
- (case val
- :start i/align-content-row-start
- :end i/align-content-row-end
- :center i/align-content-row-center
- :space-around i/align-content-row-around
- :space-evenly i/align-content-row-evenly
- :space-between i/align-content-row-between
- :stretch nil))
-
- (case val
- :start i/align-content-row-start
- :end i/align-content-row-end
- :center i/align-content-row-center
- :space-around i/align-content-row-around
- :space-between i/align-content-row-between
- :stretch nil)
-
- :align-self
- (if is-col?
- (case val
- :auto i/minus
- :start i/align-self-row-left
- :end i/align-self-row-right
- :center i/align-self-row-center
- :stretch i/align-self-row-strech
- :baseline i/align-self-row-baseline)
- (case val
- :auto i/minus
- :start i/align-self-column-top
- :end i/align-self-column-bottom
- :center i/align-self-column-center
- :stretch i/align-self-column-strech
- :baseline i/align-self-column-baseline))))
-
-(defn get-layout-flex-icon-refactor
[type val is-col?]
(case type
:align-items
@@ -276,249 +172,118 @@
(mf/defc direction-row-flex
[{:keys [saved-dir on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name saved-dir)
- :on-change on-change
- :name "flex-direction"}
- [:& radio-button {:value "row"
- :id "flex-direction-row"
- :title "Row"
- :icon (dir-icons-refactor :row)}]
- [:& radio-button {:value "row-reverse"
- :id "flex-direction-row-reverse"
- :title "Row reverse"
- :icon (dir-icons-refactor :row-reverse)}]
- [:& radio-button {:value "column"
- :id "flex-direction-column"
- :title "Column"
- :icon (dir-icons-refactor :column)}]
- [:& radio-button {:value "column-reverse"
- :id "flex-direction-column-reverse"
- :title "Column reverse"
- :icon (dir-icons-refactor :column-reverse)}]]
- [:*
- (for [dir [:row :row-reverse :column :column-reverse]]
- [:& direction-btn {:key (d/name dir)
- :dir dir
- :saved-dir saved-dir
- :on-click on-change
- :icon? true}])])))
+ [:& radio-buttons {:selected (d/name saved-dir)
+ :on-change on-change
+ :name "flex-direction"}
+ [:& radio-button {:value "row"
+ :id "flex-direction-row"
+ :title "Row"
+ :icon (dir-icons-refactor :row)}]
+ [:& radio-button {:value "row-reverse"
+ :id "flex-direction-row-reverse"
+ :title "Row reverse"
+ :icon (dir-icons-refactor :row-reverse)}]
+ [:& radio-button {:value "column"
+ :id "flex-direction-column"
+ :title "Column"
+ :icon (dir-icons-refactor :column)}]
+ [:& radio-button {:value "column-reverse"
+ :id "flex-direction-column-reverse"
+ :title "Column reverse"
+ :icon (dir-icons-refactor :column-reverse)}]])
(mf/defc wrap-row
[{:keys [wrap-type on-click] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:button {:class (stl/css-case :wrap-button true
- :selected (= wrap-type :wrap))
- :title (if (= :wrap wrap-type)
- "No wrap"
- "Wrap")
- :on-click on-click}
- i/wrap-refactor]
-
- [:*
- [:button.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= wrap-type :nowrap))
- :alt "No wrap"
- :data-value :nowrap
- :on-click on-click
- :style {:padding 0}}
- [:span.no-wrap i/minus]]
- [:button.wrap.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= wrap-type :wrap))
- :alt "Wrap"
- :data-value :wrap
- :on-click on-click}
- i/auto-wrap]])))
+ [:button {:class (stl/css-case :wrap-button true
+ :selected (= wrap-type :wrap))
+ :title (if (= :wrap wrap-type)
+ "No wrap"
+ "Wrap")
+ :on-click on-click}
+ i/wrap-refactor])
(mf/defc align-row
[{:keys [is-col? align-items on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name align-items)
- :on-change on-change
- :name "flex-align-items"}
- [:& radio-button {:value "start"
- :icon (get-layout-flex-icon-refactor :align-items :start is-col?)
- :title "Align items start"
- :id "align-items-start"}]
- [:& radio-button {:value "center"
- :icon (get-layout-flex-icon-refactor :align-items :center is-col?)
- :title "Align items center"
- :id "align-items-center"}]
- [:& radio-button {:value "end"
- :icon (get-layout-flex-icon-refactor :align-items :end is-col?)
- :title "Align items end"
- :id "align-items-end"}]]
-
- [:div.align-items-style
- [:button.align-start.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= align-items :start))
- :alt "Align items start"
- :data-value :start
- :on-click on-change}
- (get-layout-flex-icon :align-items :start is-col?)]
- [:button.align-start.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= align-items :center))
- :alt "Align items center"
- :data-value :center
- :on-click on-change}
- (get-layout-flex-icon :align-items :center is-col?)]
- [:button.align-start.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= align-items :end))
- :alt "Align items end"
- :data-value :end
- :on-click on-change}
- (get-layout-flex-icon :align-items :end is-col?)]])))
+ [:& radio-buttons {:selected (d/name align-items)
+ :on-change on-change
+ :name "flex-align-items"}
+ [:& radio-button {:value "start"
+ :icon (get-layout-flex-icon :align-items :start is-col?)
+ :title "Align items start"
+ :id "align-items-start"}]
+ [:& radio-button {:value "center"
+ :icon (get-layout-flex-icon :align-items :center is-col?)
+ :title "Align items center"
+ :id "align-items-center"}]
+ [:& radio-button {:value "end"
+ :icon (get-layout-flex-icon :align-items :end is-col?)
+ :title "Align items end"
+ :id "align-items-end"}]])
(mf/defc align-content-row
[{:keys [is-col? align-content on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name align-content)
- :on-change on-change
- :name "flex-align-content"}
- [:& radio-button {:value "start"
- :icon (get-layout-flex-icon-refactor :align-content :start is-col?)
- :title "Align content start"
- :id "align-content-start"}]
- [:& radio-button {:value "center"
- :icon (get-layout-flex-icon-refactor :align-content :center is-col?)
- :title "Align content center"
- :id "align-content-center"}]
- [:& radio-button {:value "end"
- :icon (get-layout-flex-icon-refactor :align-content :end is-col?)
- :title "Align content end"
- :id "align-content-end"}]
- [:& radio-button {:value "space-between"
- :icon (get-layout-flex-icon-refactor :align-content :space-between is-col?)
- :title "Align content space-between"
- :id "align-content-space-between"}]
- [:& radio-button {:value "space-around"
- :icon (get-layout-flex-icon-refactor :align-content :space-around is-col?)
- :title "Align content space-around"
- :id "align-content-space-around"}]
- [:& radio-button {:value "space-evenly"
- :icon (get-layout-flex-icon-refactor :align-content :space-evenly is-col?)
- :title "Align content space-evenly"
- :id "align-content-space-evenly"}]]
- [:*
- [:div.align-content-style
- [:button.align-content.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= align-content :start))
- :alt "Align content start"
- :data-value :start
- :on-click on-change}
- (get-layout-flex-icon :align-content :start is-col?)]
- [:button.align-content.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= align-content :center))
- :alt "Align content center"
- :data-value :center
- :on-click on-change}
- (get-layout-flex-icon :align-content :center is-col?)]
- [:button.align-content.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= align-content :end))
- :alt "Align content end"
- :data-value :end
- :on-click on-change}
- (get-layout-flex-icon :align-content :end is-col?)]]
- [:div.align-content-style
- [:button.align-content.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= align-content :space-between))
- :alt "Align content space-between"
- :data-value :space-between
- :on-click on-change}
- (get-layout-flex-icon :align-content :space-between is-col?)]
- [:button.align-content.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= align-content :space-around))
- :alt "Align content space-around"
- :data-value :space-around
- :on-click on-change}
- (get-layout-flex-icon :align-content :space-around is-col?)]
- [:button.align-content.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= align-content :space-evenly))
- :alt "Align content space-evenly"
- :data-value :space-evenly
- :on-click on-change}
- (get-layout-flex-icon :align-content :space-evenly is-col?)]]])))
+ [:& radio-buttons {:selected (d/name align-content)
+ :on-change on-change
+ :name "flex-align-content"}
+ [:& radio-button {:value "start"
+ :icon (get-layout-flex-icon :align-content :start is-col?)
+ :title "Align content start"
+ :id "align-content-start"}]
+ [:& radio-button {:value "center"
+ :icon (get-layout-flex-icon :align-content :center is-col?)
+ :title "Align content center"
+ :id "align-content-center"}]
+ [:& radio-button {:value "end"
+ :icon (get-layout-flex-icon :align-content :end is-col?)
+ :title "Align content end"
+ :id "align-content-end"}]
+ [:& radio-button {:value "space-between"
+ :icon (get-layout-flex-icon :align-content :space-between is-col?)
+ :title "Align content space-between"
+ :id "align-content-space-between"}]
+ [:& radio-button {:value "space-around"
+ :icon (get-layout-flex-icon :align-content :space-around is-col?)
+ :title "Align content space-around"
+ :id "align-content-space-around"}]
+ [:& radio-button {:value "space-evenly"
+ :icon (get-layout-flex-icon :align-content :space-evenly is-col?)
+ :title "Align content space-evenly"
+ :id "align-content-space-evenly"}]])
(mf/defc justify-content-row
[{:keys [is-col? justify-content on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name justify-content)
- :on-change on-change
- :name "flex-justify"}
- [:& radio-button {:value "start"
- :icon (get-layout-flex-icon-refactor :justify-content :start is-col?)
- :title "Justify content start"
- :id "justify-content-start"}]
- [:& radio-button {:value "center"
- :icon (get-layout-flex-icon-refactor :justify-content :center is-col?)
- :title "Justify content center"
- :id "justify-content-center"}]
- [:& radio-button {:value "end"
- :icon (get-layout-flex-icon-refactor :justify-content :end is-col?)
- :title "Justify content end"
- :id "justify-content-end"}]
- [:& radio-button {:value "space-between"
- :icon (get-layout-flex-icon-refactor :justify-content :space-between is-col?)
- :title "Justify content space-between"
- :id "justify-content-space-between"}]
- [:& radio-button {:value "space-around"
- :icon (get-layout-flex-icon-refactor :justify-content :space-around is-col?)
- :title "Justify content space-around"
- :id "justify-content-space-around"}]
- [:& radio-button {:value "space-evenly"
- :icon (get-layout-flex-icon-refactor :justify-content :space-evenly is-col?)
- :title "Justify content space-evenly"
- :id "justify-content-space-evenly"}]]
- [:*
- [:div.justify-content-style
- [:button.justify.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= justify-content :start))
- :alt "Justify content start"
- :data-value :start
- :on-click on-change}
- (get-layout-flex-icon :justify-content :start is-col?)]
- [:button.justify.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= justify-content :center))
- :data-value :center
- :alt "Justify content center"
- :on-click on-change}
- (get-layout-flex-icon :justify-content :center is-col?)]
- [:button.justify.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= justify-content :end))
- :alt "Justify content end"
- :data-value :end
- :on-click on-change}
- (get-layout-flex-icon :justify-content :end is-col?)]]
- [:div.justify-content-style
- [:button.justify.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= justify-content :space-between))
- :alt "Justify content space-between"
- :data-value :space-between
- :on-click on-change}
- (get-layout-flex-icon :justify-content :space-between is-col?)]
- [:button.justify.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= justify-content :space-around))
- :alt "Justify content space-around"
- :data-value :space-around
- :on-click on-change}
- (get-layout-flex-icon :justify-content :space-around is-col?)]
- [:button.justify.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active (= justify-content :space-evenly))
- :alt "Justify content space-evenly"
- :data-value :space-evenly
- :on-click on-change}
- (get-layout-flex-icon :justify-content :space-evenly is-col?)]]])))
+ [:& radio-buttons {:selected (d/name justify-content)
+ :on-change on-change
+ :name "flex-justify"}
+ [:& radio-button {:value "start"
+ :icon (get-layout-flex-icon :justify-content :start is-col?)
+ :title "Justify content start"
+ :id "justify-content-start"}]
+ [:& radio-button {:value "center"
+ :icon (get-layout-flex-icon :justify-content :center is-col?)
+ :title "Justify content center"
+ :id "justify-content-center"}]
+ [:& radio-button {:value "end"
+ :icon (get-layout-flex-icon :justify-content :end is-col?)
+ :title "Justify content end"
+ :id "justify-content-end"}]
+ [:& radio-button {:value "space-between"
+ :icon (get-layout-flex-icon :justify-content :space-between is-col?)
+ :title "Justify content space-between"
+ :id "justify-content-space-between"}]
+ [:& radio-button {:value "space-around"
+ :icon (get-layout-flex-icon :justify-content :space-around is-col?)
+ :title "Justify content space-around"
+ :id "justify-content-space-around"}]
+ [:& radio-button {:value "space-evenly"
+ :icon (get-layout-flex-icon :justify-content :space-evenly is-col?)
+ :title "Justify content space-evenly"
+ :id "justify-content-space-evenly"}]])
(mf/defc padding-section
[{:keys [values on-change-style on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- padding-type (:layout-padding-type values)
+ (let [padding-type (:layout-padding-type values)
toggle-padding-mode
(mf/use-fn
@@ -551,171 +316,110 @@
;;on destroy component
(select-paddings false false false false))))
- (if new-css-system
- [:div {:class (stl/css :padding-group)}
- [:div {:class (stl/css :padding-inputs)}
- (cond
- (= padding-type :simple)
- [:div {:class (stl/css :paddings-simple)}
- [:div {:class (stl/css :padding-simple)
- :title "Vertical padding"}
- [:span {:class (stl/css :icon)}
- i/padding-top-bottom-refactor]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-change (partial on-change :simple :p1)
- :on-focus #(do
- (dom/select-target %)
- (select-paddings true false true false))
- :nillable true
- :min 0
- :value p1}]]
- [:div {:class (stl/css :padding-simple)
- :title "Horizontal padding"}
+ [:div {:class (stl/css :padding-group)}
+ [:div {:class (stl/css :padding-inputs)}
+ (cond
+ (= padding-type :simple)
+ [:div {:class (stl/css :paddings-simple)}
+ [:div {:class (stl/css :padding-simple)
+ :title "Vertical padding"}
+ [:span {:class (stl/css :icon)}
+ i/padding-top-bottom-refactor]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-change (partial on-change :simple :p1)
+ :on-focus #(do
+ (dom/select-target %)
+ (select-paddings true false true false))
+ :nillable true
+ :min 0
+ :value p1}]]
+ [:div {:class (stl/css :padding-simple)
+ :title "Horizontal padding"}
- [:span {:class (stl/css :icon)}
- i/padding-left-right-refactor]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-change (partial on-change :simple :p2)
- :on-focus #(do (dom/select-target %)
- (select-paddings false true false true))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value p2}]]]
- (= padding-type :multiple)
- [:div {:class (stl/css :paddings-multiple)}
+ [:span {:class (stl/css :icon)}
+ i/padding-left-right-refactor]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-change (partial on-change :simple :p2)
+ :on-focus #(do (dom/select-target %)
+ (select-paddings false true false true))
+ :on-blur #(select-paddings false false false false)
+ :nillable true
+ :min 0
+ :value p2}]]]
+ (= padding-type :multiple)
+ [:div {:class (stl/css :paddings-multiple)}
- [:div {:class (stl/css :padding-multiple)
- :title "Top padding"}
- [:span {:class (stl/css :icon)}
- i/padding-top-refactor]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-change (partial on-change :multiple :p1)
- :on-focus #(do (dom/select-target %)
- (select-padding :p1))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value (:p1 (:layout-padding values))}]]
+ [:div {:class (stl/css :padding-multiple)
+ :title "Top padding"}
+ [:span {:class (stl/css :icon)}
+ i/padding-top-refactor]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-change (partial on-change :multiple :p1)
+ :on-focus #(do (dom/select-target %)
+ (select-padding :p1))
+ :on-blur #(select-paddings false false false false)
+ :nillable true
+ :min 0
+ :value (:p1 (:layout-padding values))}]]
- [:div {:class (stl/css :padding-multiple)
- :title "Right padding"}
- [:span {:class (stl/css :icon)}
- i/padding-right-refactor]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-change (partial on-change :multiple :p2)
- :on-focus #(do (dom/select-target %)
- (select-padding :p2))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value (:p2 (:layout-padding values))}]]
+ [:div {:class (stl/css :padding-multiple)
+ :title "Right padding"}
+ [:span {:class (stl/css :icon)}
+ i/padding-right-refactor]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-change (partial on-change :multiple :p2)
+ :on-focus #(do (dom/select-target %)
+ (select-padding :p2))
+ :on-blur #(select-paddings false false false false)
+ :nillable true
+ :min 0
+ :value (:p2 (:layout-padding values))}]]
- [:div {:class (stl/css :padding-multiple)
- :title "Bottom padding"}
- [:span {:class (stl/css :icon)}
- i/padding-bottom-refactor]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-change (partial on-change :multiple :p3)
- :on-focus #(do (dom/select-target %)
- (select-padding :p3))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value (:p3 (:layout-padding values))}]]
+ [:div {:class (stl/css :padding-multiple)
+ :title "Bottom padding"}
+ [:span {:class (stl/css :icon)}
+ i/padding-bottom-refactor]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-change (partial on-change :multiple :p3)
+ :on-focus #(do (dom/select-target %)
+ (select-padding :p3))
+ :on-blur #(select-paddings false false false false)
+ :nillable true
+ :min 0
+ :value (:p3 (:layout-padding values))}]]
- [:div {:class (stl/css :padding-multiple)
- :title "Left padding"}
- [:span {:class (stl/css :icon)}
- i/padding-left-refactor]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-change (partial on-change :multiple :p4)
- :on-focus #(do (dom/select-target %)
- (select-padding :p4))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value (:p4 (:layout-padding values))}]]])]
- [:button {:class (stl/css-case :padding-toggle true
- :selected (= padding-type :multiple))
- :on-click toggle-padding-mode}
- i/padding-extended-refactor]]
-
- [:div.padding-row
- (cond
- (= padding-type :simple)
-
- [:div.padding-group
- [:div.padding-item.tooltip.tooltip-bottom-left
- {:alt "Vertical padding"}
- [:span.icon.rotated i/auto-padding-both-sides]
- [:> numeric-input*
- {:placeholder "--"
- :on-change (partial on-change :simple :p1)
- :on-focus #(do
- (dom/select-target %)
- (select-paddings true false true false))
- :nillable true
- :min 0
- :value p1}]]
-
- [:div.padding-item.tooltip.tooltip-bottom-left
- {:alt "Horizontal padding"}
- [:span.icon i/auto-padding-both-sides]
- [:> numeric-input*
- {:placeholder "--"
- :on-change (partial on-change :simple :p2)
- :on-focus #(do (dom/select-target %)
- (select-paddings false true false true))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value p2}]]]
-
- (= padding-type :multiple)
- [:div.wrapper
- (for [num [:p1 :p2 :p3 :p4]]
- [:div.tooltip.tooltip-bottom
- {:key (dm/str "padding-" (d/name num))
- :alt (case num
- :p1 "Top"
- :p2 "Right"
- :p3 "Bottom"
- :p4 "Left")}
- [:div.input-element.auto
- [:> numeric-input*
- {:placeholder "--"
- :on-change (partial on-change :multiple num)
- :on-focus #(do (dom/select-target %)
- (select-padding num))
- :on-blur #(select-paddings false false false false)
- :nillable true
- :min 0
- :value (num (:layout-padding values))}]]])])
-
- [:div.padding-icons
- [:div.padding-icon.tooltip.tooltip-bottom-left
- {:class (dom/classnames :selected (= padding-type :multiple))
- :alt "Independent paddings"
- :on-click toggle-padding-mode}
- i/auto-padding-side]]])))
+ [:div {:class (stl/css :padding-multiple)
+ :title "Left padding"}
+ [:span {:class (stl/css :icon)}
+ i/padding-left-refactor]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-change (partial on-change :multiple :p4)
+ :on-focus #(do (dom/select-target %)
+ (select-padding :p4))
+ :on-blur #(select-paddings false false false false)
+ :nillable true
+ :min 0
+ :value (:p4 (:layout-padding values))}]]])]
+ [:button {:class (stl/css-case :padding-toggle true
+ :selected (= padding-type :multiple))
+ :on-click toggle-padding-mode}
+ i/padding-extended-refactor]]))
(mf/defc gap-section
[{:keys [is-col? wrap-type gap-selected? on-change gap-value]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- select-gap
+ (let [select-gap
(fn [gap]
(st/emit! (udw/set-gap-selected gap)))]
@@ -725,89 +429,47 @@
;;on destroy component
(select-gap nil))))
- (if new-css-system
- [:div {:class (stl/css :gap-group)}
- [:div {:class (stl/css-case :row-gap true
- :disabled (and (= :nowrap wrap-type) (not is-col?)))
- :title "Row gap"}
- [:span {:class (stl/css :icon)} i/gap-vertical-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input true)
- :no-validate true
- :placeholder "--"
- :on-focus (fn [event]
- (select-gap :row-gap)
- (reset! gap-selected? :row-gap)
- (dom/select-target event))
- :on-change (partial on-change (= :nowrap wrap-type) :row-gap)
- :on-blur (fn [_]
- (select-gap nil)
- (reset! gap-selected? :none))
- :nillable true
- :min 0
- :value (:row-gap gap-value)
- :disabled (and (= :nowrap wrap-type) (not is-col?))}]]
+ [:div {:class (stl/css :gap-group)}
+ [:div {:class (stl/css-case :row-gap true
+ :disabled (and (= :nowrap wrap-type) (not is-col?)))
+ :title "Row gap"}
+ [:span {:class (stl/css :icon)} i/gap-vertical-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input true)
+ :no-validate true
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-gap :row-gap)
+ (reset! gap-selected? :row-gap)
+ (dom/select-target event))
+ :on-change (partial on-change (= :nowrap wrap-type) :row-gap)
+ :on-blur (fn [_]
+ (select-gap nil)
+ (reset! gap-selected? :none))
+ :nillable true
+ :min 0
+ :value (:row-gap gap-value)
+ :disabled (and (= :nowrap wrap-type) (not is-col?))}]]
- [:div {:class (stl/css-case :column-gap true
- :disabled (and (= :nowrap wrap-type) is-col?))
- :title "Column gap"}
- [:span {:class (stl/css :icon)}
- i/gap-horizontal-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :no-validate true
- :placeholder "--"
- :on-focus (fn [event]
- (select-gap :column-gap)
- (reset! gap-selected? :column-gap)
- (dom/select-target event))
- :on-change (partial on-change (= :nowrap wrap-type) :column-gap)
- :on-blur (fn [_]
- (select-gap nil)
- (reset! gap-selected? :none))
- :nillable true
- :min 0
- :value (:column-gap gap-value)
- :disabled (and (= :nowrap wrap-type) is-col?)}]]]
-
- [:div.layout-row
- [:div.gap.row-title "Gap"]
- [:div.gap-group
- [:div.gap-row.tooltip.tooltip-bottom-left
- {:alt "Column gap"}
- [:span.icon
- i/auto-gap]
- [:> numeric-input* {:no-validate true
- :placeholder "--"
- :on-focus (fn [event]
- (select-gap :column-gap)
- (reset! gap-selected? :column-gap)
- (dom/select-target event))
- :on-change (partial on-change (= :nowrap wrap-type) :column-gap)
- :on-blur (fn [_]
- (select-gap nil)
- (reset! gap-selected? :none))
- :nillable true
- :min 0
- :value (:column-gap gap-value)
- :disabled (and (= :nowrap wrap-type) is-col?)}]]
-
- [:div.gap-row.tooltip.tooltip-bottom-left
- {:alt "Row gap"}
- [:span.icon.rotated
- i/auto-gap]
- [:> numeric-input* {:no-validate true
- :placeholder "--"
- :on-focus (fn [event]
- (select-gap :row-gap)
- (reset! gap-selected? :row-gap)
- (dom/select-target event))
- :on-change (partial on-change (= :nowrap wrap-type) :row-gap)
- :on-blur (fn [_]
- (select-gap nil)
- (reset! gap-selected? :none))
- :nillable true
- :min 0
- :value (:row-gap gap-value)
- :disabled (and (= :nowrap wrap-type) (not is-col?))}]]]])))
+ [:div {:class (stl/css-case :column-gap true
+ :disabled (and (= :nowrap wrap-type) is-col?))
+ :title "Column gap"}
+ [:span {:class (stl/css :icon)}
+ i/gap-horizontal-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :no-validate true
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-gap :column-gap)
+ (reset! gap-selected? :column-gap)
+ (dom/select-target event))
+ :on-change (partial on-change (= :nowrap wrap-type) :column-gap)
+ :on-blur (fn [_]
+ (select-gap nil)
+ (reset! gap-selected? :none))
+ :nillable true
+ :min 0
+ :value (:column-gap gap-value)
+ :disabled (and (= :nowrap wrap-type) is-col?)}]]]))
;; GRID COMPONENTS
@@ -835,36 +497,22 @@
:space-evenly i/grid-justify-content-row-between))))
(mf/defc direction-row-grid
- [{:keys [saved-dir on-change on-click] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name saved-dir)
- :on-change on-change
- :name "grid-direction"}
- [:& radio-button {:value "row"
- :id "grid-direction-row"
- :title "Row"
- :icon (dir-icons-refactor :row)}]
- [:& radio-button {:value "column"
- :id "grid-direction-column"
- :title "Column"
- :icon (dir-icons-refactor :column)}]]
- [:*
- [:& direction-btn {:key "grid-direction-row"
- :dir :row
- :saved-dir saved-dir
- :on-click on-click
- :icon? true}]
- [:& direction-btn {:key "grid-direction-column"
- :dir :column
- :saved-dir saved-dir
- :on-click on-click
- :icon? true}]])))
+ [{:keys [saved-dir on-change] :as props}]
+ [:& radio-buttons {:selected (d/name saved-dir)
+ :on-change on-change
+ :name "grid-direction"}
+ [:& radio-button {:value "row"
+ :id "grid-direction-row"
+ :title "Row"
+ :icon (dir-icons-refactor :row)}]
+ [:& radio-button {:value "column"
+ :id "grid-direction-column"
+ :title "Column"
+ :icon (dir-icons-refactor :column)}]])
(mf/defc grid-edit-mode
[{:keys [id] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- edition (mf/deref refs/selected-edition)
+ (let [edition (mf/deref refs/selected-edition)
active? (= id edition)
toggle-edit-mode
@@ -874,81 +522,43 @@
(if-not active?
(st/emit! (udw/start-edition-mode id))
(st/emit! :interrupt))))]
- (if new-css-system
- [:button
- {:class (stl/css :edit-mode-btn)
- :alt "Grid edit mode"
- :on-click toggle-edit-mode}
- (tr "workspace.layout_grid.editor.options.edit-grid")]
-
- [:button.tooltip.tooltip-bottom-left
- {:class (dom/classnames :active active?)
- :alt "Grid edit mode"
- :on-click toggle-edit-mode
- :style {:padding 0}}
- (tr "workspace.layout_grid.editor.options.edit-grid")
- i/grid-layout-mode])))
+ [:button
+ {:class (stl/css :edit-mode-btn)
+ :alt "Grid edit mode"
+ :on-click toggle-edit-mode}
+ (tr "workspace.layout_grid.editor.options.edit-grid")]))
(mf/defc align-grid-row
[{:keys [is-col? align-items set-align] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- type (if is-col? :column :row)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name align-items)
- :on-change #(set-align % type)
- :name (dm/str "flex-align-items-" (d/name type))}
- [:& radio-button {:value "start"
- :icon (get-layout-grid-icon-refactor :align-items :start is-col?)
- :title "Align items start"
- :id (dm/str "align-items-start-" (d/name type))}]
- [:& radio-button {:value "center"
- :icon (get-layout-grid-icon-refactor :align-items :center is-col?)
- :title "Align items center"
- :id (dm/str "align-items-center-" (d/name type))}]
- [:& radio-button {:value "end"
- :icon (get-layout-grid-icon-refactor :align-items :end is-col?)
- :title "Align items end"
- :id (dm/str "align-items-end-" (d/name type))}]]
- [:div.align-items-style
- (for [align [:start :center :end]]
- [:button.align-start.tooltip
- {:class (dom/classnames :active (= align-items align)
- :tooltip-bottom-left (not= align :start)
- :tooltip-bottom (= align :start))
- :alt (if is-col?
- (dm/str "justify-items: " (d/name align))
- (dm/str "align-items: " (d/name align)))
- :on-click #(set-align align type)
- :key (dm/str "align-items" (d/name align))}
- (get-layout-flex-icon :align-items align is-col?)])])))
+ (let [type (if is-col? :column :row)]
+ [:& radio-buttons {:selected (d/name align-items)
+ :on-change #(set-align % type)
+ :name (dm/str "flex-align-items-" (d/name type))}
+ [:& radio-button {:value "start"
+ :icon (get-layout-grid-icon-refactor :align-items :start is-col?)
+ :title "Align items start"
+ :id (dm/str "align-items-start-" (d/name type))}]
+ [:& radio-button {:value "center"
+ :icon (get-layout-grid-icon-refactor :align-items :center is-col?)
+ :title "Align items center"
+ :id (dm/str "align-items-center-" (d/name type))}]
+ [:& radio-button {:value "end"
+ :icon (get-layout-grid-icon-refactor :align-items :end is-col?)
+ :title "Align items end"
+ :id (dm/str "align-items-end-" (d/name type))}]]))
(mf/defc justify-grid-row
[{:keys [is-col? justify-items set-justify] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- type (if is-col? :column :row)]
+ (let [type (if is-col? :column :row)]
- (if new-css-system
- [:& radio-buttons {:selected (d/name justify-items)
- :on-change #(set-justify % type)
- :name (dm/str "grid-justify-items-" (d/name type))}
- (for [justify [:start :center :end :space-around :space-between :stretch]]
- [:& radio-button {:value (d/name justify)
- :icon (get-layout-grid-icon-refactor :justify-items justify is-col?)
- :title (dm/str "Justify items " (d/name justify))
- :id (dm/str "justify-items-" (d/name justify) "-" (d/name type))}])]
-
- [:div.justify-content-style
- (for [align [:start :center :end :space-around :space-between :stretch]]
- [:button.align-start.tooltip
- {:class (dom/classnames :active (= justify-items align)
- :tooltip-bottom-left (not= align :start)
- :tooltip-bottom (= align :start))
- :alt (if is-col?
- (dm/str "align-content: " (d/name align))
- (dm/str "justify-content: " (d/name align)))
- :on-click #(set-justify align type)
- :key (dm/str "justify-content" (d/name align))}
- (get-layout-grid-icon :justify-items align is-col?)])])))
+ [:& radio-buttons {:selected (d/name justify-items)
+ :on-change #(set-justify % type)
+ :name (dm/str "grid-justify-items-" (d/name type))}
+ (for [justify [:start :center :end :space-around :space-between :stretch]]
+ [:& radio-button {:value (d/name justify)
+ :icon (get-layout-grid-icon-refactor :justify-items justify is-col?)
+ :title (dm/str "Justify items " (d/name justify))
+ :id (dm/str "justify-items-" (d/name justify) "-" (d/name type))}])]))
(defn manage-values [{:keys [value type]}]
(case type
@@ -959,14 +569,22 @@
value))
(mf/defc grid-track-info
- [{:keys [is-col? type index column set-column-value set-column-type remove-element reorder-track hover-track on-select-track]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ [{:keys [is-col?
+ type
+ index
+ column
+ set-column-value
+ set-column-type
+ remove-element
+ reorder-track
+ hover-track
+ on-select-track]}]
- drop-track
+ (let [drop-track
(mf/use-fn
(mf/deps type reorder-track index)
(fn [drop-position data event]
- (reorder-track type (:index data) (if (= :top drop-position) (dec index) index) (kbd/mod? event))))
+ (reorder-track type (:index data) (if (= :top drop-position) (dec index) index) (not (kbd/mod? event)))))
pointer-enter
(mf/use-fn
@@ -996,89 +614,50 @@
:column column}
:draggable? true)]
- (if new-css-system
- [:div {:class
- (stl/css-case :track-info true
- :dnd-over-top (or (= (:over dprops) :top)
- (= (:over dprops) :center))
- :dnd-over-bot (= (:over dprops) :bot))
- :ref dref
- :on-pointer-enter pointer-enter
- :on-pointer-leave pointer-leave}
+ [:div {:class (stl/css-case :track-info true
+ :dnd-over-top (or (= (:over dprops) :top)
+ (= (:over dprops) :center))
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref
+ :on-pointer-enter pointer-enter
+ :on-pointer-leave pointer-leave}
- [:div {:class (stl/css :track-info-container)}
- [:div {:class (stl/css :track-info-dir-icon)
- :on-click handle-select-track}
- (if is-col? i/flex-vertical-refactor i/flex-horizontal-refactor)]
+ [:div {:class (stl/css :track-info-container)}
+ [:div {:class (stl/css :track-info-dir-icon)
+ :on-click handle-select-track}
+ (if is-col? i/flex-vertical-refactor i/flex-horizontal-refactor)]
- [:div {:class (stl/css :track-info-value)}
- [:> numeric-input* {:no-validate true
- :value (:value column)
- :on-change #(set-column-value type index %)
- :placeholder "--"
- :min 0
- :disabled (= :auto (:type column))}]]
+ [:div {:class (stl/css :track-info-value)}
+ [:> numeric-input* {:no-validate true
+ :value (:value column)
+ :on-change #(set-column-value type index %)
+ :placeholder "--"
+ :min 0
+ :disabled (= :auto (:type column))}]]
- [:div {:class (stl/css :track-info-unit)}
- [:& select
- {:class (stl/css :track-info-unit-selector)
- :default-value (:type column)
- :options [{:value :flex :label "FR"}
- {:value :auto :label "AUTO"}
- {:value :fixed :label "PX"}
- {:value :percent :label "%"}]
- :on-change #(set-column-type type index %)}]]]
+ [:div {:class (stl/css :track-info-unit)}
+ [:& select {:class (stl/css :track-info-unit-selector)
+ :default-value (:type column)
+ :options [{:value :flex :label "FR"}
+ {:value :auto :label "AUTO"}
+ {:value :fixed :label "PX"}
+ {:value :percent :label "%"}]
+ :on-change #(set-column-type type index %)}]]]
- [:button
- {:class (stl/css :remove-track-btn)
- :on-click #(remove-element type index)}
- i/remove-refactor]]
-
- [:div.column-info
- {:ref dref
- :class (dom/classnames
- :dnd-over-top (or (= (:over dprops) :top)
- (= (:over dprops) :center))
- :dnd-over-bot (= (:over dprops) :bot))
- :on-pointer-enter pointer-enter
- :on-pointer-leave pointer-leave}
- [:div.direction-grid-icon
- (if is-col?
- i/layout-rows
- i/layout-columns)]
-
- [:div.grid-column-value
- [:> numeric-input* {:no-validate true
- :value (:value column)
- :on-change #(set-column-value type index %)
- :placeholder "--"
- :disabled (= :auto (:type column))}]]
- [:div.grid-column-unit
- [:& select
- {:class "grid-column-unit-selector"
- :default-value (:type column)
- :options [{:value :flex :label "FR"}
- {:value :auto :label "AUTO"}
- {:value :fixed :label "PX"}
- {:value :percent :label "%"}]
- :on-change #(set-column-type type index %)}]]
- [:button.remove-grid-column
- {:on-click #(remove-element type index)}
- i/minus]])))
+ [:button {:class (stl/css :remove-track-btn)
+ :on-click #(remove-element type index)}
+ i/remove-refactor]]))
(mf/defc grid-columns-row
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type
remove-element reorder-track hover-track on-select-track] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- column-num (count column-values)
+ (let [column-num (count column-values)
direction (if (> column-num 1)
(if is-col? "Columns " "Rows ")
(if is-col? "Column " "Row "))
track-name (dm/str direction (if (= column-num 0) " - empty" column-num))
track-detail (str/join ", " (map manage-values column-values))
- generated-name (dm/str direction (if (= column-num 0) " - empty" (dm/str column-num " (" track-detail ")")))
type (if is-col? :column :row)
@@ -1087,61 +666,36 @@
(when-not expanded? (toggle))
(add-new-element type ctl/default-track-value))]
- (if new-css-system
- [:div {:class (stl/css :grid-tracks)}
- [:div {:class (stl/css :grid-track-header)}
- [:button {:class (stl/css :expand-icon) :on-click toggle} i/menu-refactor]
- [:div {:class (stl/css :track-title) :on-click toggle}
- [:div {:class (stl/css :track-name) :title track-name} track-name]
- [:div {:class (stl/css :track-detail) :title track-detail} track-detail]]
- [:button {:class (stl/css :add-column) :on-click add-track} i/add-refactor]]
+ [:div {:class (stl/css :grid-tracks)}
+ [:div {:class (stl/css :grid-track-header)}
+ [:button {:class (stl/css :expand-icon) :on-click toggle} i/menu-refactor]
+ [:div {:class (stl/css :track-title) :on-click toggle}
+ [:div {:class (stl/css :track-name) :title track-name} track-name]
+ [:div {:class (stl/css :track-detail) :title track-detail} track-detail]]
+ [:button {:class (stl/css :add-column) :on-click add-track} i/add-refactor]]
- (when expanded?
- [:& h/sortable-container {}
- [:div {:class (stl/css :grid-tracks-info-container)}
- (for [[index column] (d/enumerate column-values)]
- [:& grid-track-info {:key (dm/str index "-" (name type))
- :type type
- :is-col? is-col?
- :index index
- :column column
- :set-column-value set-column-value
- :set-column-type set-column-type
- :remove-element remove-element
- :reorder-track reorder-track
- :hover-track hover-track
- :on-select-track on-select-track}])]])]
-
- [:div.grid-columns
- [:div.grid-columns-header
- [:button.expand-icon {:on-click toggle} i/actions]
- [:div.columns-info {:title generated-name :on-click toggle} generated-name]
- [:button.add-column {:on-click add-track} i/plus]]
-
- (when expanded?
- [:& h/sortable-container {}
- [:div.columns-info-wrapper
- (for [[index column] (d/enumerate column-values)]
- [:& grid-track-info {:key (dm/str index "-" (name type))
- :type type
- :is-col? is-col?
- :index index
- :column column
- :set-column-value set-column-value
- :set-column-type set-column-type
- :remove-element remove-element
- :reorder-track reorder-track
- :hover-track hover-track
- :on-select-track on-select-track}])]])])))
+ (when expanded?
+ [:& h/sortable-container {}
+ [:div {:class (stl/css :grid-tracks-info-container)}
+ (for [[index column] (d/enumerate column-values)]
+ [:& grid-track-info {:key (dm/str index "-" (name type))
+ :type type
+ :is-col? is-col?
+ :index index
+ :column column
+ :set-column-value set-column-value
+ :set-column-type set-column-type
+ :remove-element remove-element
+ :reorder-track reorder-track
+ :hover-track hover-track
+ :on-select-track on-select-track}])]])]))
;; LAYOUT COMPONENT
(mf/defc layout-container-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "multiple"]))]}
[{:keys [ids values multiple] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- ;; Display
+ (let [;; Display
layout-type (:layout values)
has-layout? (some? layout-type)
@@ -1194,9 +748,9 @@
set-direction-refactor
(mf/use-fn
- (mf/deps new-css-system layout-type ids)
+ (mf/deps layout-type ids)
(fn [dir]
- (let [dir (if new-css-system (keyword dir) dir)]
+ (let [dir (keyword dir)]
(if (= :flex layout-type)
(st/emit! (dwsl/update-layout ids {:layout-flex-dir dir}))
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))))))
@@ -1205,7 +759,7 @@
wrap-type (:layout-wrap-type values)
- toggle-wrap-refactor
+ toggle-wrap
(mf/use-fn
(mf/deps wrap-type ids)
(fn []
@@ -1214,30 +768,12 @@
:wrap)]
(st/emit! (dwsl/update-layout ids {:layout-wrap-type type})))))
- set-wrap
- (mf/use-fn
- (mf/deps ids)
- (fn [event]
- (let [type (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))]
- (st/emit! (dwsl/update-layout ids {:layout-wrap-type type})))))
-
;; Align items
align-items (:layout-align-items values)
set-align-items
- (mf/use-fn
- (mf/deps ids)
- (fn [event]
- (let [value (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))]
- (st/emit! (dwsl/update-layout ids {:layout-align-items value})))))
-
- set-align-items-refactor
(mf/use-fn
(mf/deps ids)
(fn [value]
@@ -1248,15 +784,6 @@
justify-content (:layout-justify-content values)
set-justify-content
- (mf/use-fn
- (mf/deps ids)
- (fn [event]
- (let [value (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))]
- (st/emit! (dwsl/update-layout ids {:layout-justify-content value})))))
-
- set-justify-content-refactor
(mf/use-fn
(mf/deps ids)
(fn [value]
@@ -1267,17 +794,6 @@
align-content (:layout-align-content values)
set-align-content
- (mf/use-fn
- (mf/deps ids align-content)
- (fn [event]
- (let [value (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))]
- (if (= align-content value)
- (st/emit! (dwsl/update-layout ids {:layout-align-content :stretch}))
- (st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))
-
- set-align-content-refactor
(mf/use-fn
(mf/deps ids)
(fn [value align-content]
@@ -1324,9 +840,9 @@
set-direction
(mf/use-fn
- (mf/deps layout-type ids new-css-system)
+ (mf/deps layout-type ids)
(fn [dir]
- (let [dir (cond-> dir new-css-system keyword)]
+ (let [dir (keyword dir)]
(if (= :flex layout-type)
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))))))
@@ -1337,9 +853,9 @@
set-align-grid
(mf/use-fn
- (mf/deps ids new-css-system)
+ (mf/deps ids)
(fn [value type]
- (let [value (cond-> value new-css-system keyword)]
+ (let [value (keyword value)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-items value}))))))
@@ -1352,9 +868,9 @@
set-justify-grid
(mf/use-fn
- (mf/deps ids new-css-system)
+ (mf/deps ids)
(fn [value type]
- (let [value (cond-> value new-css-system keyword)]
+ (let [value (keyword value)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-justify-content value}))
(st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))
@@ -1379,246 +895,127 @@
(fn []
(st/emit! (dom/open-new-window cf/grid-help-uri))))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-layout?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title "Layout"
- :class (stl/css-case :title-spacing-layout (not has-layout?))}
- (if (and (not multiple) (:layout values))
- [:div {:class (stl/css :title-actions)}
- (when ^boolean grid-enabled?
- [:*
- [:button {:class (stl/css :add-layout)
- :on-click handle-show-layout-dropdown}
- i/menu-refactor]
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-layout?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title "Layout"
+ :class (stl/css-case :title-spacing-layout (not has-layout?))}
+ (if (and (not multiple) (:layout values))
+ [:div {:class (stl/css :title-actions)}
+ (when ^boolean grid-enabled?
+ [:*
+ [:button {:class (stl/css :add-layout)
+ :on-click handle-show-layout-dropdown}
+ i/menu-refactor]
- [:& dropdown {:show show-layout-dropdown? :on-close handle-close-layout-options}
- [:div {:class (stl/css :layout-options)}
- [:button {:class (stl/css :layout-option) :on-click set-flex} "Flex layout"]
- [:button {:class (stl/css :layout-option) :on-click set-grid} "Grid layout"]]]])
+ [:& dropdown {:show show-layout-dropdown? :on-close handle-close-layout-options}
+ [:div {:class (stl/css :layout-options)}
+ [:button {:class (stl/css :layout-option) :on-click set-flex} "Flex layout"]
+ [:button {:class (stl/css :layout-option) :on-click set-grid} "Grid layout"]]]])
- [:button {:class (stl/css :remove-layout)
- :on-click on-remove-layout}
- i/remove-refactor]]
+ [:button {:class (stl/css :remove-layout)
+ :on-click on-remove-layout}
+ i/remove-refactor]]
- [:div {:class (stl/css :title-actions)}
- (if ^boolean grid-enabled?
- [:*
- [:button {:class (stl/css :add-layout)
- :on-click handle-show-layout-dropdown}
- i/add-refactor]
+ [:div {:class (stl/css :title-actions)}
+ (if ^boolean grid-enabled?
+ [:*
+ [:button {:class (stl/css :add-layout)
+ :on-click handle-show-layout-dropdown}
+ i/add-refactor]
- [:& dropdown {:show show-layout-dropdown? :on-close handle-close-layout-options}
- [:div {:class (stl/css :layout-options)}
- [:button {:class (stl/css :layout-option) :on-click set-flex} "Flex layout"]
- [:button {:class (stl/css :layout-option) :on-click set-grid} "Grid layout"]]]]
+ [:& dropdown {:show show-layout-dropdown? :on-close handle-close-layout-options}
+ [:div {:class (stl/css :layout-options)}
+ [:button {:class (stl/css :layout-option) :on-click set-flex} "Flex layout"]
+ [:button {:class (stl/css :layout-option) :on-click set-grid} "Grid layout"]]]]
- [:button {:class (stl/css :add-layout)
- :data-value :flex
- :on-click on-set-layout}
- i/add-refactor])])]]
+ [:button {:class (stl/css :add-layout)
+ :data-value :flex
+ :on-click on-set-layout}
+ i/add-refactor])])]]
- (when (and open? has-layout?)
- (when (not= :multiple layout-type)
- (case layout-type
- :flex
- [:div {:class (stl/css :flex-layout-menu)}
- [:div {:class (stl/css :first-row)}
- [:& align-row {:is-col? is-col?
- :align-items align-items
- :on-change set-align-items-refactor}]
+ (when (and open? has-layout?)
+ (when (not= :multiple layout-type)
+ (case layout-type
+ :flex
+ [:div {:class (stl/css :flex-layout-menu)}
+ [:div {:class (stl/css :first-row)}
+ [:& align-row {:is-col? is-col?
+ :align-items align-items
+ :on-change set-align-items}]
- [:& direction-row-flex {:on-change set-direction-refactor
- :saved-dir saved-dir}]
+ [:& direction-row-flex {:on-change set-direction-refactor
+ :saved-dir saved-dir}]
- [:& wrap-row {:wrap-type wrap-type
- :on-click toggle-wrap-refactor}]]
+ [:& wrap-row {:wrap-type wrap-type
+ :on-click toggle-wrap}]]
- [:div {:class (stl/css :second-row :help-button-wrapper)}
- [:& justify-content-row {:is-col? is-col?
- :justify-content justify-content
- :on-change set-justify-content-refactor}]
+ [:div {:class (stl/css :second-row :help-button-wrapper)}
+ [:& justify-content-row {:is-col? is-col?
+ :justify-content justify-content
+ :on-change set-justify-content}]
- [:button {:on-click handle-open-flex-help
- :class (stl/css :help-button)} i/help-refactor]]
- (when (= :wrap wrap-type)
- [:div {:class (stl/css :third-row)}
- [:& align-content-row {:is-col? is-col?
- :align-content align-content
- :on-change set-align-content-refactor}]])
- [:div {:class (stl/css :forth-row)}
- [:& gap-section {:is-col? is-col?
- :wrap-type wrap-type
- :gap-selected? gap-selected?
- :on-change set-gap
- :gap-value (:layout-gap values)}]
+ [:button {:on-click handle-open-flex-help
+ :class (stl/css :help-button)} i/help-refactor]]
+ (when (= :wrap wrap-type)
+ [:div {:class (stl/css :third-row)}
+ [:& align-content-row {:is-col? is-col?
+ :align-content align-content
+ :on-change set-align-content}]])
+ [:div {:class (stl/css :forth-row)}
+ [:& gap-section {:is-col? is-col?
+ :wrap-type wrap-type
+ :gap-selected? gap-selected?
+ :on-change set-gap
+ :gap-value (:layout-gap values)}]
- [:& padding-section {:values values
- :on-change-style change-padding-type
- :on-change on-padding-change}]]]
+ [:& padding-section {:values values
+ :on-change-style change-padding-type
+ :on-change on-padding-change}]]]
- :grid
- [:div {:class (stl/css :grid-layout-menu)}
- (when (= 1 (count ids))
- [:div {:class (stl/css :edit-grid-wrapper)}
- [:& grid-edit-mode {:id (first ids)}]
- [:button {:on-click handle-open-grid-help
- :class (stl/css :help-button)} i/help-refactor]])
- [:div {:class (stl/css :row :first-row)}
- [:div {:class (stl/css :direction-edit)}
- [:div {:class (stl/css :direction)}
- [:& direction-row-grid {:saved-dir saved-grid-dir
- :on-change set-direction}]]]
+ :grid
+ [:div {:class (stl/css :grid-layout-menu)}
+ (when (= 1 (count ids))
+ [:div {:class (stl/css :edit-grid-wrapper)}
+ [:& grid-edit-mode {:id (first ids)}]
+ [:button {:on-click handle-open-grid-help
+ :class (stl/css :help-button)} i/help-refactor]])
+ [:div {:class (stl/css :row :first-row)}
+ [:div {:class (stl/css :direction-edit)}
+ [:div {:class (stl/css :direction)}
+ [:& direction-row-grid {:saved-dir saved-grid-dir
+ :on-change set-direction}]]]
- [:& align-grid-row {:is-col? false
- :align-items align-items-row
- :set-align set-align-grid}]
+ [:& align-grid-row {:is-col? false
+ :align-items align-items-row
+ :set-align set-align-grid}]
- [:& align-grid-row {:is-col? true
- :align-items align-items-column
- :set-align set-align-grid}]]
+ [:& align-grid-row {:is-col? true
+ :align-items align-items-column
+ :set-align set-align-grid}]]
- [:div {:class (stl/css :row :grid-layout-align)}
- [:& justify-grid-row {:is-col? true
- :justify-items grid-justify-content-column
- :set-justify set-justify-grid}]
- [:& justify-grid-row {:is-col? false
- :justify-items grid-justify-content-row
- :set-justify set-justify-grid}]]]
- nil)))]
-
- [:div.element-set
- [:div.element-set-title
- [:*
- [:span "Layout"]
-
- (if ^boolean grid-enabled?
- [:div.title-actions
- [:div.layout-btns
- [:button {:on-click set-flex
- :class (dom/classnames
- :active (= :flex layout-type))} "Flex"]
- [:button {:on-click set-grid
- :class (dom/classnames
- :active (= :grid layout-type))} "Grid"]]
-
- (when (and (not multiple) (:layout values))
- [:button.remove-layout {:on-click on-remove-layout} i/minus])]
-
- [:div.title-actions
- (if (and (not multiple) (:layout values))
- [:button.remove-layout {:on-click on-remove-layout} i/minus]
- [:button.add-page {:data-value :flex
- :on-click on-set-layout} i/close])])]]
-
- (when (:layout values)
- (when (not= :multiple layout-type)
- (case layout-type
- :flex
-
- [:div.element-set-content.layout-menu
- [:div.layout-row
- [:div.direction-wrap.row-title "Direction"]
- [:div.btn-wrapper
- [:div.direction
- [:& direction-row-flex {:on-change set-direction
- :saved-dir saved-dir}]]
-
- [:div.wrap-type
- [:& wrap-row {:wrap-type wrap-type
- :on-click set-wrap}]]]]
-
- (when (= :wrap wrap-type)
- [:div.layout-row
- [:div.align-content.row-title "Content"]
- [:div.btn-wrapper.align-content
- [:& align-content-row {:is-col? is-col?
- :align-content align-content
- :on-change set-align-content}]]])
-
- [:div.layout-row
- [:div.align-items.row-title "Align"]
- [:div.btn-wrapper
- [:& align-row {:is-col? is-col?
- :align-items align-items
- :on-change set-align-items}]]]
-
- [:div.layout-row
- [:div.justify-content.row-title "Justify"]
- [:div.btn-wrapper.justify-content
- [:& justify-content-row {:is-col? is-col?
- :justify-content justify-content
- :on-change set-justify-content}]]]
-
- [:& gap-section {:is-col? is-col?
- :wrap-type wrap-type
- :gap-selected? gap-selected?
- :on-change set-gap
- :gap-value (:layout-gap values)}]
-
- [:& padding-section {:values values
- :on-change-style change-padding-type
- :on-change on-padding-change}]]
-
- :grid
-
- [:div.element-set-content.layout-menu
- [:div.layout-row
- [:div.direction-wrap.row-title "Direction"]
- [:div.btn-wrapper
- [:div.direction
- [:*
- (for [dir [:row :column]]
- [:& direction-btn {:key (d/name dir)
- :dir dir
- :saved-dir saved-grid-dir
- :on-click set-direction
- :icon? true}])]]
-
- (when (= 1 (count ids))
- [:div.edit-mode
- [:& grid-edit-mode {:id (first ids)}]])]]
-
- [:div.layout-row
- [:div.align-items-grid.row-title "Items"]
- [:div.btn-wrapper.align-grid-items
- [:& align-grid-row {:is-col? false
- :align-items align-items-row
- :set-align set-align-grid}]
-
- [:& align-grid-row {:is-col? true
- :align-items align-items-column
- :set-align set-align-grid}]]]
-
- [:div.layout-row
- [:div.jusfiy-content-grid.row-title "Content"]
- [:div.btn-wrapper.align-grid-content
- [:& justify-grid-row {:is-col? true
- :justify-items grid-justify-content-column
- :set-justify set-justify-grid}]
- [:& justify-grid-row {:is-col? false
- :justify-items grid-justify-content-row
- :set-justify set-justify-grid}]]]]
-
- ;; Default if not grid or flex
- nil)))])))
+ [:div {:class (stl/css :row :grid-layout-align)}
+ [:& justify-grid-row {:is-col? true
+ :justify-items grid-justify-content-column
+ :set-justify set-justify-grid}]
+ [:& justify-grid-row {:is-col? false
+ :justify-items grid-justify-content-row
+ :set-justify set-justify-grid}]]]
+ nil)))]))
(mf/defc grid-layout-edition
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
[{:keys [ids values] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
-
- ;; Gap
+ (let [;; Gap
gap-selected? (mf/use-state :none)
saved-grid-dir (:layout-grid-dir values)
set-direction
(fn [dir]
- (let [dir (if new-css-system (keyword dir) dir)]
+ (let [dir (keyword dir)]
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))))
set-gap
@@ -1650,9 +1047,9 @@
set-align-grid
(mf/use-fn
- (mf/deps ids new-css-system)
+ (mf/deps ids)
(fn [value type]
- (let [value (cond-> value new-css-system keyword)]
+ (let [value (keyword value)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-items value}))))))
@@ -1664,9 +1061,9 @@
set-justify-grid
(mf/use-fn
- (mf/deps ids new-css-system)
+ (mf/deps ids)
(fn [value type]
- (let [value (cond-> value new-css-system keyword)]
+ (let [value (keyword value)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-justify-content value}))
(st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))
@@ -1743,141 +1140,70 @@
(fn []
(st/emit! (dwge/locate-board (first ids)))))]
- (if new-css-system
- [:div {:class (stl/css :grid-layout-menu)}
- [:div {:class (stl/css :row)}
- [:div {:class (stl/css :grid-layout-menu-title)} "GRID LAYOUT"]
- [:button {:on-click handle-open-grid-help
- :class (stl/css :help-button)} i/help-refactor]
- [:button {:class (stl/css :exit-btn)
- :on-click #(st/emit! udw/clear-edition-mode)}
- (tr "workspace.layout_grid.editor.options.exit")]]
+ [:div {:class (stl/css :grid-layout-menu)}
+ [:div {:class (stl/css :row)}
+ [:div {:class (stl/css :grid-layout-menu-title)} "GRID LAYOUT"]
+ [:button {:on-click handle-open-grid-help
+ :class (stl/css :help-button)} i/help-refactor]
+ [:button {:class (stl/css :exit-btn)
+ :on-click #(st/emit! udw/clear-edition-mode)}
+ (tr "workspace.layout_grid.editor.options.exit")]]
- [:div {:class (stl/css :row :first-row)}
- [:div {:class (stl/css :direction-edit)}
- [:div {:class (stl/css :direction)}
- [:& direction-row-grid {:saved-dir saved-grid-dir
- :on-change set-direction}]]]
+ [:div {:class (stl/css :row :first-row)}
+ [:div {:class (stl/css :direction-edit)}
+ [:div {:class (stl/css :direction)}
+ [:& direction-row-grid {:saved-dir saved-grid-dir
+ :on-change set-direction}]]]
- [:& align-grid-row {:is-col? false
- :align-items align-items-row
- :set-align set-align-grid}]
+ [:& align-grid-row {:is-col? false
+ :align-items align-items-row
+ :set-align set-align-grid}]
- [:& align-grid-row {:is-col? true
- :align-items align-items-column
- :set-align set-align-grid}]]
+ [:& align-grid-row {:is-col? true
+ :align-items align-items-column
+ :set-align set-align-grid}]]
- [:div {:class (stl/css :row :grid-layout-align)}
- [:& justify-grid-row {:is-col? true
- :justify-items grid-justify-content-column
- :set-justify set-justify-grid}]
- [:& justify-grid-row {:is-col? false
- :justify-items grid-justify-content-row
- :set-justify set-justify-grid}]
+ [:div {:class (stl/css :row :grid-layout-align)}
+ [:& justify-grid-row {:is-col? true
+ :justify-items grid-justify-content-column
+ :set-justify set-justify-grid}]
+ [:& justify-grid-row {:is-col? false
+ :justify-items grid-justify-content-row
+ :set-justify set-justify-grid}]
- [:button {:on-click handle-locate-grid
- :class (stl/css :locate-button)}
- i/locate-refactor]]
- [:div {:class (stl/css :row :grid-tracks-row)}
- [:& grid-columns-row {:is-col? true
- :expanded? @grid-columns-open?
- :toggle toggle-columns-info
- :column-values column-grid-values
- :add-new-element add-new-element
- :set-column-value set-column-value
- :set-column-type set-column-type
- :remove-element remove-element
- :reorder-track reorder-track
- :hover-track hover-track
- :on-select-track handle-select-track}]
+ [:button {:on-click handle-locate-grid
+ :class (stl/css :locate-button)}
+ i/locate-refactor]]
+ [:div {:class (stl/css :row :grid-tracks-row)}
+ [:& grid-columns-row {:is-col? true
+ :expanded? @grid-columns-open?
+ :toggle toggle-columns-info
+ :column-values column-grid-values
+ :add-new-element add-new-element
+ :set-column-value set-column-value
+ :set-column-type set-column-type
+ :remove-element remove-element
+ :reorder-track reorder-track
+ :hover-track hover-track
+ :on-select-track handle-select-track}]
- [:& grid-columns-row {:is-col? false
- :expanded? @grid-rows-open?
- :toggle toggle-rows-info
- :column-values rows-grid-values
- :add-new-element add-new-element
- :set-column-value set-column-value
- :set-column-type set-column-type
- :remove-element remove-element
- :reorder-track reorder-track
- :hover-track hover-track
- :on-select-track handle-select-track}]]
- [:div {:class (stl/css :row)}
- [:& gap-section {:gap-selected? gap-selected?
- :on-change set-gap
- :gap-value (:layout-gap values)}]]
+ [:& grid-columns-row {:is-col? false
+ :expanded? @grid-rows-open?
+ :toggle toggle-rows-info
+ :column-values rows-grid-values
+ :add-new-element add-new-element
+ :set-column-value set-column-value
+ :set-column-type set-column-type
+ :remove-element remove-element
+ :reorder-track reorder-track
+ :hover-track hover-track
+ :on-select-track handle-select-track}]]
+ [:div {:class (stl/css :row)}
+ [:& gap-section {:gap-selected? gap-selected?
+ :on-change set-gap
+ :gap-value (:layout-gap values)}]]
- [:div {:class (stl/css :row :padding-section)}
- [:& padding-section {:values values
- :on-change-style change-padding-type
- :on-change on-padding-change}]]]
-
- [:div.element-set
- [:div.element-set-title
- [:span "Grid Layout"]]
-
- [:div.element-set-content.layout-menu
- [:div.layout-row
- [:div.direction-wrap.row-title "Direction"]
- [:div.btn-wrapper
- [:div.direction
- (for [dir [:row :column]]
- [:& direction-btn {:key (d/name dir)
- :dir dir
- :saved-dir saved-grid-dir
- :on-click set-direction
- :icon? true}])]
-
- (when (= 1 (count ids))
- [:div.edit-mode
- [:& grid-edit-mode {:id (first ids)}]])]]
-
- [:div.layout-row
- [:div.align-items-grid.row-title "Items"]
- [:div.btn-wrapper.align-grid
- [:& align-grid-row {:is-col? false
- :align-items align-items-row
- :set-align set-align-grid}]
-
- [:& align-grid-row {:is-col? true
- :align-items align-items-column
- :set-align set-align-grid}]]]
-
- [:div.layout-row
- [:div.jusfiy-content-grid.row-title "Content"]
- [:div.btn-wrapper.align-grid-content
- [:& justify-grid-row {:is-col? true
- :justify-items grid-justify-content-row
- :set-justify set-justify-grid}]
- [:& justify-grid-row {:is-col? false
- :justify-items grid-justify-content-column
- :set-justify set-justify-grid}]]]
- [:& grid-columns-row {:is-col? true
- :expanded? @grid-columns-open?
- :toggle toggle-columns-info
- :column-values column-grid-values
- :add-new-element add-new-element
- :set-column-value set-column-value
- :set-column-type set-column-type
- :remove-element remove-element
- :reorder-track reorder-track
- :hover-track hover-track}]
-
- [:& grid-columns-row {:is-col? false
- :expanded? @grid-rows-open?
- :toggle toggle-rows-info
- :column-values rows-grid-values
- :add-new-element add-new-element
- :set-column-value set-column-value
- :set-column-type set-column-type
- :remove-element remove-element
- :reorder-track reorder-track
- :hover-track hover-track}]
-
- [:& gap-section {:gap-selected? gap-selected?
- :on-change set-gap
- :gap-value (:layout-gap values)}]
-
- [:& padding-section {:values values
- :on-change-style change-padding-type
- :on-change on-padding-change}]]])))
+ [:div {:class (stl/css :row :padding-section)}
+ [:& padding-section {:values values
+ :on-change-style change-padding-type
+ :on-change on-padding-change}]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss
index 4c66d2c375..cc51a740bd 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss
@@ -174,6 +174,7 @@
.grid-layout-menu-title {
flex: 1;
font-size: $fs-11;
+ color: var(--title-foreground-color-hover);
}
.edit-mode-btn {
@@ -245,9 +246,6 @@
border-right: $s-1 solid var(--panel-background-color);
}
- .track-info-unit {
- }
-
.track-info-unit-selector {
border-radius: 0 $br-8 $br-8 0;
width: $s-96;
@@ -289,7 +287,7 @@
}
.track-name {
- color: var(--color-foreground-secondary);
+ color: $df-primary;
}
.track-detail {
@@ -297,6 +295,7 @@
white-space: nowrap;
text-overflow: ellipsis;
width: 100%;
+ color: $df-secondary;
}
.expand-icon {
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
index 4162175b7a..8a028b2ff0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
@@ -17,9 +17,8 @@
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [get-layout-flex-icon get-layout-flex-icon-refactor]]
+ [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [get-layout-flex-icon]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -40,8 +39,7 @@
(mf/defc margin-section
[{:keys [values change-margin-style on-margin-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- margin-type (or (:layout-item-margin-type values) :simple)
+ (let [margin-type (or (:layout-item-margin-type values) :simple)
m1 (when (and (not (= :multiple (:layout-item-margin values)))
(= (dm/get-in values [:layout-item-margin :m1])
(dm/get-in values [:layout-item-margin :m3])))
@@ -63,158 +61,99 @@
;;on destroy component
(select-margins false false false false))))
- (if new-css-system
- [:div {:class (stl/css :margin-row)}
- [:div {:class (stl/css :inputs-wrapper)}
- (cond
- (= margin-type :simple)
- [:div {:class (stl/css :margin-simple)}
- [:div {:class (stl/css :vertical-margin)
- :title "Vertical margin"}
- [:span {:class (stl/css :icon)}
- i/margin-top-bottom-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :placeholder "--"
- :nillable true
- :value m1
- :on-focus (fn [event]
- (select-margins true false true false)
- (dom/select-target event))
- :on-change (partial on-margin-change :simple :m1)
- :on-blur #(select-margins false false false false)}]]
+ [:div {:class (stl/css :margin-row)}
+ [:div {:class (stl/css :inputs-wrapper)}
+ (cond
+ (= margin-type :simple)
+ [:div {:class (stl/css :margin-simple)}
+ [:div {:class (stl/css :vertical-margin)
+ :title "Vertical margin"}
+ [:span {:class (stl/css :icon)}
+ i/margin-top-bottom-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :nillable true
+ :value m1
+ :on-focus (fn [event]
+ (select-margins true false true false)
+ (dom/select-target event))
+ :on-change (partial on-margin-change :simple :m1)
+ :on-blur #(select-margins false false false false)}]]
- [:div {:class (stl/css :horizontal-margin)
- :title "Horizontal margin"}
- [:span {:class (stl/css :icon)}
- i/margin-left-right-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-focus (fn [event]
- (select-margins false true false true)
- (dom/select-target event))
- :on-change (partial on-margin-change :simple :m2)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value m2}]]]
+ [:div {:class (stl/css :horizontal-margin)
+ :title "Horizontal margin"}
+ [:span {:class (stl/css :icon)}
+ i/margin-left-right-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-margins false true false true)
+ (dom/select-target event))
+ :on-change (partial on-margin-change :simple :m2)
+ :on-blur #(select-margins false false false false)
+ :nillable true
+ :value m2}]]]
- (= margin-type :multiple)
- [:div {:class (stl/css :margin-multiple)}
- [:div {:class (stl/css :top-margin)
- :title "Top margin"}
- [:span {:class (stl/css :icon)}
- i/margin-top-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-focus (fn [event]
- (select-margin :m1)
- (dom/select-target event))
- :on-change (partial on-margin-change :multiple :m1)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value (:m1 (:layout-item-margin values))}]]
- [:div {:class (stl/css :right-margin)
- :title "Right margin"}
- [:span {:class (stl/css :icon)}
- i/margin-right-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-focus (fn [event]
- (select-margin :m2)
- (dom/select-target event))
- :on-change (partial on-margin-change :multiple :m2)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value (:m2 (:layout-item-margin values))}]]
+ (= margin-type :multiple)
+ [:div {:class (stl/css :margin-multiple)}
+ [:div {:class (stl/css :top-margin)
+ :title "Top margin"}
+ [:span {:class (stl/css :icon)}
+ i/margin-top-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-margin :m1)
+ (dom/select-target event))
+ :on-change (partial on-margin-change :multiple :m1)
+ :on-blur #(select-margins false false false false)
+ :nillable true
+ :value (:m1 (:layout-item-margin values))}]]
+ [:div {:class (stl/css :right-margin)
+ :title "Right margin"}
+ [:span {:class (stl/css :icon)}
+ i/margin-right-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-margin :m2)
+ (dom/select-target event))
+ :on-change (partial on-margin-change :multiple :m2)
+ :on-blur #(select-margins false false false false)
+ :nillable true
+ :value (:m2 (:layout-item-margin values))}]]
- [:div {:class (stl/css :bottom-margin)
- :title "Bottom margin"}
- [:span {:class (stl/css :icon)}
- i/margin-bottom-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-focus (fn [event]
- (select-margin :m3)
- (dom/select-target event))
- :on-change (partial on-margin-change :multiple :m3)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value (:m3 (:layout-item-margin values))}]]
- [:div {:class (stl/css :left-margin)
- :title "Left margin"}
- [:span {:class (stl/css :icon)}
- i/margin-left-refactor]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-focus (fn [event]
- (select-margin :m4)
- (dom/select-target event))
- :on-change (partial on-margin-change :multiple :m4)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value (:m4 (:layout-item-margin values))}]]])]
- [:button {:class (stl/css-case :margin-mode true
- :selected (= margin-type :multiple))
- :title "Margin - multiple"
- :on-click #(change-margin-style (if (= margin-type :multiple) :simple :multiple))}
- i/margin-refactor]]
- [:div.margin-row
- (cond
- (= margin-type :simple)
-
- [:div.margin-item-group
- [:div.margin-item.tooltip.tooltip-bottom-left
- {:alt "Vertical margin"}
- [:span.icon i/auto-margin-both-sides]
- [:> numeric-input*
- {:placeholder "--"
- :on-focus (fn [event]
- (select-margins true false true false)
- (dom/select-target event))
- :on-change (partial on-margin-change :simple :m1)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value m1}]]
-
- [:div.margin-item.tooltip.tooltip-bottom-left
- {:alt "Horizontal margin"}
- [:span.icon.rotated i/auto-margin-both-sides]
- [:> numeric-input*
- {:placeholder "--"
- :on-focus (fn [event]
- (select-margins false true false true)
- (dom/select-target event))
- :on-change (partial on-margin-change :simple :m2)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value m2}]]]
-
- (= margin-type :multiple)
- [:div.wrapper
- (for [num [:m1 :m2 :m3 :m4]]
- [:div.tooltip.tooltip-bottom
- {:key (dm/str "margin-" (d/name num))
- :alt (case num
- :m1 "Top"
- :m2 "Right"
- :m3 "Bottom"
- :m4 "Left")}
- [:div.input-element.auto
- [:> numeric-input*
- {:placeholder "--"
- :on-focus (fn [event]
- (select-margin num)
- (dom/select-target event))
- :on-change (partial on-margin-change :multiple num)
- :on-blur #(select-margins false false false false)
- :nillable true
- :value (num (:layout-item-margin values))}]]])])
-
- [:div.margin-item-icons
- [:div.margin-item-icon.tooltip.tooltip-bottom-left
- {:class (dom/classnames :selected (= margin-type :multiple))
- :alt "Margin - multiple"
- :on-click #(change-margin-style (if (= margin-type :multiple) :simple :multiple))}
- i/auto-margin]]])))
+ [:div {:class (stl/css :bottom-margin)
+ :title "Bottom margin"}
+ [:span {:class (stl/css :icon)}
+ i/margin-bottom-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-margin :m3)
+ (dom/select-target event))
+ :on-change (partial on-margin-change :multiple :m3)
+ :on-blur #(select-margins false false false false)
+ :nillable true
+ :value (:m3 (:layout-item-margin values))}]]
+ [:div {:class (stl/css :left-margin)
+ :title "Left margin"}
+ [:span {:class (stl/css :icon)}
+ i/margin-left-refactor]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :on-focus (fn [event]
+ (select-margin :m4)
+ (dom/select-target event))
+ :on-change (partial on-margin-change :multiple :m4)
+ :on-blur #(select-margins false false false false)
+ :nillable true
+ :value (:m4 (:layout-item-margin values))}]]])]
+ [:button {:class (stl/css-case :margin-mode true
+ :selected (= margin-type :multiple))
+ :title "Margin - multiple"
+ :on-click #(change-margin-style (if (= margin-type :multiple) :simple :multiple))}
+ i/margin-refactor]]))
(mf/defc element-behaviour-horizontal
[{:keys [auto? fill? layout-item-sizing on-change] :as props}]
@@ -270,112 +209,46 @@
:id "behaviour-v-auto"}])]])
(mf/defc element-behaviour
- [{:keys [auto? fill? layout-item-h-sizing layout-item-v-sizing on-change-behaviour-h-refactor on-change-behaviour-v-refactor on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
-
- (if new-css-system
- [:div {:class (stl/css-case :behaviour-menu true
- :wrap (and fill? auto?))}
- [:& element-behaviour-horizontal {:auto? auto?
- :fill? fill?
- :layout-item-sizing layout-item-h-sizing
- :on-change on-change-behaviour-h-refactor}]
- [:& element-behaviour-vertical {:auto? auto?
- :fill? fill?
- :layout-item-sizing layout-item-v-sizing
- :on-change on-change-behaviour-v-refactor}]]
-
- [:div.btn-wrapper
- {:class (when (and fill? auto?) "wrap")}
- [:div.layout-behavior.horizontal
- [:button.behavior-btn.tooltip.tooltip-bottom
- {:alt "Fix width"
- :class (dom/classnames :active (= layout-item-h-sizing :fix))
- :data-direction :h
- :data-value :fix
- :on-click on-change}
- i/auto-fix-layout]
- (when fill?
- [:button.behavior-btn.tooltip.tooltip-bottom
- {:alt "Width 100%"
- :class (dom/classnames :active (= layout-item-h-sizing :fill))
- :data-direction :h
- :data-value :fill
- :on-click on-change}
- i/auto-fill])
- (when auto?
- [:button.behavior-btn.tooltip.tooltip-bottom
- {:alt "Fit content"
- :class (dom/classnames :active (= layout-item-h-sizing :auto))
- :data-direction :h
- :data-value :auto
- :on-click on-change}
- i/auto-hug])]
-
- [:div.layout-behavior
- [:button.behavior-btn.tooltip.tooltip-bottom
- {:alt "Fix height"
- :class (dom/classnames :active (= layout-item-v-sizing :fix))
- :data-direction :v
- :data-value :fix
- :on-click on-change}
- i/auto-fix-layout]
- (when fill?
- [:button.behavior-btn.tooltip.tooltip-bottom-left
- {:alt "Height 100%"
- :class (dom/classnames :active (= layout-item-v-sizing :fill))
- :data-direction :v
- :data-value :fill
- :on-click on-change}
- i/auto-fill])
- (when auto?
- [:button.behavior-btn.tooltip.tooltip-bottom-left
- {:alt "Fit content"
- :class (dom/classnames :active (= layout-item-v-sizing :auto))
- :data-direction :v
- :data-value :auto
- :on-click on-change}
- i/auto-hug])]])))
+ [{:keys [auto?
+ fill?
+ layout-item-h-sizing
+ layout-item-v-sizing
+ on-change-behaviour-h-refactor
+ on-change-behaviour-v-refactor] :as props}]
+ [:div {:class (stl/css-case :behaviour-menu true
+ :wrap (and fill? auto?))}
+ [:& element-behaviour-horizontal {:auto? auto?
+ :fill? fill?
+ :layout-item-sizing layout-item-h-sizing
+ :on-change on-change-behaviour-h-refactor}]
+ [:& element-behaviour-vertical {:auto? auto?
+ :fill? fill?
+ :layout-item-sizing layout-item-v-sizing
+ :on-change on-change-behaviour-v-refactor}]])
(mf/defc align-self-row
[{:keys [is-col? align-self on-change] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- dir-v [:start :center :end #_:stretch #_:baseline]]
- (if new-css-system
- [:& radio-buttons {:selected (d/name align-self)
- :on-change on-change
- :name "flex-align-self"}
- [:& radio-button {:value "start"
- :icon (get-layout-flex-icon-refactor :align-self :start is-col?)
- :title "Align self start"
- :id "align-self-start"}]
- [:& radio-button {:value "center"
- :icon (get-layout-flex-icon-refactor :align-self :center is-col?)
- :title "Align self center"
- :id "align-self-center"}]
- [:& radio-button {:value "end"
- :icon (get-layout-flex-icon-refactor :align-self :end is-col?)
- :title "Align self end"
- :id "align-self-end"}]]
-
- [:div.align-self-style
- (for [align dir-v]
- [:button.align-self.tooltip.tooltip-bottom
- {:class (dom/classnames :active (= align-self align)
- :tooltip-bottom-left (not= align :start)
- :tooltip-bottom (= align :start))
- :alt (dm/str "Align self " (d/name align))
- :data-value align
- :on-click on-change
- :key (str "align-self" align)}
- (get-layout-flex-icon :align-self align is-col?)])])))
+ [:& radio-buttons {:selected (d/name align-self)
+ :on-change on-change
+ :name "flex-align-self"}
+ [:& radio-button {:value "start"
+ :icon (get-layout-flex-icon :align-self :start is-col?)
+ :title "Align self start"
+ :id "align-self-start"}]
+ [:& radio-button {:value "center"
+ :icon (get-layout-flex-icon :align-self :center is-col?)
+ :title "Align self center"
+ :id "align-self-center"}]
+ [:& radio-button {:value "end"
+ :icon (get-layout-flex-icon :align-self :end is-col?)
+ :title "Align self end"
+ :id "align-self-end"}]])
(mf/defc layout-item-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "is-layout-child?" "is-grid-parent?" "is-flex-parent?"]))]}
[{:keys [ids values is-layout-child? is-layout-container? is-grid-parent? is-flex-parent?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
+ (let [selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
selection-parents (mf/deref selection-parents-ref)
is-absolute? (:layout-item-absolute values)
@@ -408,17 +281,6 @@
"Layout element")
set-align-self
- (mf/use-fn
- (mf/deps ids align-self)
- (fn [event]
- (let [value (-> (dom/get-current-target event)
- (dom/get-data "value")
- (d/read-string))]
- (if (= align-self value)
- (st/emit! (dwsl/update-layout-child ids {:layout-item-align-self nil}))
- (st/emit! (dwsl/update-layout-child ids {:layout-item-align-self value}))))))
-
- set-align-self-refactor
(mf/use-fn
(mf/deps ids align-self)
(fn [value]
@@ -464,7 +326,7 @@
(mf/use-fn
(mf/deps ids)
(fn [value]
- (let [value (if new-css-system (keyword value) value)]
+ (let [value (keyword value)]
(st/emit! (dwsl/update-layout-child ids {:layout-item-h-sizing value})))))
@@ -472,7 +334,7 @@
(mf/use-fn
(mf/deps ids)
(fn [value]
- (let [value (if new-css-system (keyword value) value)]
+ (let [value (keyword value)]
(st/emit! (dwsl/update-layout-child ids {:layout-item-v-sizing value})))))
;; Size and position
@@ -485,7 +347,7 @@
(mf/use-fn
(mf/deps ids)
(fn [value]
- (let [value (if new-css-system (keyword value) value)]
+ (let [value (keyword value)]
(when (= value :static)
(st/emit! (dwsl/update-layout-child ids {:layout-item-z-index nil})))
(st/emit! (dwsl/update-layout-child ids {:layout-item-absolute (= value :absolute)})))))
@@ -498,19 +360,18 @@
(fn [value]
(st/emit! (dwsl/update-layout-child ids {:layout-item-z-index value}))))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-content?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title title
- :class (stl/css-case :title-spacing-layout-element true
- :title-spacing-empty (not has-content?))}]]
- (when open?
- [:div {:class (stl/css :flex-element-menu)}
- (when (or is-layout-child? is-absolute?)
- [:div {:class (stl/css :row)}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-content?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title title
+ :class (stl/css-case :title-spacing-layout-element true
+ :title-spacing-empty (not has-content?))}]]
+ (when open?
+ [:div {:class (stl/css :flex-element-menu)}
+ (when (or is-layout-child? is-absolute?)
+ [:div {:class (stl/css :row)}
[:div {:class (stl/css :position-options)}
[:& radio-buttons {:selected (if is-absolute? "absolute" "static")
:on-change on-change-position
@@ -535,187 +396,93 @@
:nillable true
:value (:layout-item-z-index values)}]])])
+ [:div {:class (stl/css :row)}
+ [:& element-behaviour {:fill? is-layout-child?
+ :auto? is-layout-container?
+ :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
+ :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
+ :on-change-behaviour-h-refactor on-change-behaviour-h
+ :on-change-behaviour-v-refactor on-change-behaviour-v
+ :on-change on-change-behaviour}]]
+
+ (when (and is-layout-child? is-flex-parent?)
[:div {:class (stl/css :row)}
- [:& element-behaviour {:fill? is-layout-child?
- :auto? is-layout-container?
- :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
- :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
- :on-change-behaviour-h-refactor on-change-behaviour-h
- :on-change-behaviour-v-refactor on-change-behaviour-v
- :on-change on-change-behaviour}]]
+ [:& align-self-row {:is-col? is-col?
+ :align-self align-self
+ :on-changer set-align-self}]])
- (when (and is-layout-child? is-flex-parent?)
- [:div {:class (stl/css :row)}
- [:& align-self-row {:is-col? is-col?
- :align-self align-self
- :on-changer set-align-self-refactor}]])
-
- (when is-layout-child?
- [:div {:class (stl/css :row)}
- [:& margin-section {:values values
- :change-margin-style change-margin-style
- :on-margin-change on-margin-change}]])
-
- (when (or (= (:layout-item-h-sizing values) :fill)
- (= (:layout-item-v-sizing values) :fill))
- [:div {:class (stl/css :row)}
- [:div {:class (stl/css :advanced-options)}
- (when (= (:layout-item-h-sizing values) :fill)
- [:div {:class (stl/css :horizontal-fill)}
- [:div {:class (stl/css :layout-item-min-w)
- :title (tr "workspace.options.layout-item.layout-item-min-w")}
-
- [:span {:class (stl/css :icon-text)}
- "MIN W"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-min-w)
- :value (get values :layout-item-min-w)
- :nillable true}]]
-
- [:div {:class (stl/css :layout-item-max-w)
- :title (tr "workspace.options.layout-item.layout-item-max-w")}
- [:span {:class (stl/css :icon-text)}
- "MAX W"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-max-w)
- :value (get values :layout-item-max-w)
- :nillable true}]]])
- (when (= (:layout-item-v-sizing values) :fill)
- [:div {:class (stl/css :vertical-fill)}
- [:div {:class (stl/css :layout-item-min-h)
- :title (tr "workspace.options.layout-item.layout-item-min-h")}
-
- [:span {:class (stl/css :icon-text)}
- "MIN H"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-min-h)
- :value (get values :layout-item-min-h)
- :nillable true}]]
-
- [:div {:class (stl/css :layout-item-max-h)
- :title (tr "workspace.options.layout-item.layout-item-max-h")}
-
- [:span {:class (stl/css :icon-text)}
- "MAX H"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-max-h)
- :value (get values :layout-item-max-h)
- :nillable true}]]])]])])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span (cond
- (and is-layout-container? (not is-layout-child?))
- "Flex board"
-
- is-flex-parent?
- "Flex element"
-
- is-grid-parent?
- "Grid element"
-
- :else
- "Layout element")]]
-
- [:div.element-set-content.layout-item-menu
- (when (or is-layout-child? is-absolute?)
- [:div.layout-row
- [:div.row-title.sizing "Position"]
- [:div.btn-wrapper
- [:div.absolute
- [:button.behavior-btn.tooltip.tooltip-bottom
- {:alt "Static"
- :class (dom/classnames :active (not (:layout-item-absolute values)))
- :on-click #(on-change-position :static)}
- "Static"]
- [:button.behavior-btn.tooltip.tooltip-bottom
- {:alt "Absolute"
- :class (dom/classnames :active (and (:layout-item-absolute values) (not= :multiple (:layout-item-absolute values))))
- :on-click #(on-change-position :absolute)}
- "Absolute"]]
-
- [:div.tooltip.tooltip-bottom-left.z-index {:alt "z-index"}
- i/layers
- [:> numeric-input*
- {:placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change #(on-change-z-index %)
- :nillable true
- :value (:layout-item-z-index values)}]]]])
-
- [:*
- [:div.layout-row
- [:div.row-title.sizing "Sizing"]
- [:& element-behaviour {:fill? is-layout-child?
- :auto? is-layout-container?
- :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
- :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
- :on-change-behaviour-h-refactor on-change-behaviour-h
- :on-change-behaviour-v-refactor on-change-behaviour-v
- :on-change on-change-behaviour}]]
-
- (when (and is-layout-child? is-flex-parent?)
- [:div.layout-row
- [:div.row-title "Align"]
- [:div.btn-wrapper
- [:& align-self-row {:is-col? is-col?
- :align-self align-self
- :on-change set-align-self}]]])
-
- (when is-layout-child?
+ (when is-layout-child?
+ [:div {:class (stl/css :row)}
[:& margin-section {:values values
:change-margin-style change-margin-style
- :on-margin-change on-margin-change}])
+ :on-margin-change on-margin-change}]])
- [:div.advanced-ops-body
- [:div.input-wrapper
- (for [item (cond-> []
- (= (:layout-item-h-sizing values) :fill)
- (conj :layout-item-min-w :layout-item-max-w)
+ (when (or (= (:layout-item-h-sizing values) :fill)
+ (= (:layout-item-v-sizing values) :fill))
+ [:div {:class (stl/css :row)}
+ [:div {:class (stl/css :advanced-options)}
+ (when (= (:layout-item-h-sizing values) :fill)
+ [:div {:class (stl/css :horizontal-fill)}
+ [:div {:class (stl/css :layout-item-min-w)
+ :title (tr "workspace.options.layout-item.layout-item-min-w")}
- (= (:layout-item-v-sizing values) :fill)
- (conj :layout-item-min-h :layout-item-max-h))]
+ [:span {:class (stl/css :icon-text)}
+ "MIN W"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-min-w)
+ :value (get values :layout-item-min-w)
+ :nillable true}]]
- [:div.tooltip.tooltip-bottom
- {:key (d/name item)
- :alt (tr (dm/str "workspace.options.layout-item.title." (d/name item)))
- :class (dom/classnames "maxH" (= item :layout-item-max-h)
- "minH" (= item :layout-item-min-h)
- "maxW" (= item :layout-item-max-w)
- "minW" (= item :layout-item-min-w))}
- [:div.input-element
- {:alt (tr (dm/str "workspace.options.layout-item." (d/name item)))}
- [:> numeric-input*
- {:no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change item)
- :value (get values item)
- :nillable true}]]])]]]]])))
+ [:div {:class (stl/css :layout-item-max-w)
+ :title (tr "workspace.options.layout-item.layout-item-max-w")}
+ [:span {:class (stl/css :icon-text)}
+ "MAX W"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-max-w)
+ :value (get values :layout-item-max-w)
+ :nillable true}]]])
+ (when (= (:layout-item-v-sizing values) :fill)
+ [:div {:class (stl/css :vertical-fill)}
+ [:div {:class (stl/css :layout-item-min-h)
+ :title (tr "workspace.options.layout-item.layout-item-min-h")}
+
+ [:span {:class (stl/css :icon-text)}
+ "MIN H"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-min-h)
+ :value (get values :layout-item-min-h)
+ :nillable true}]]
+
+ [:div {:class (stl/css :layout-item-max-h)
+ :title (tr "workspace.options.layout-item.layout-item-max-h")}
+
+ [:span {:class (stl/css :icon-text)}
+ "MAX H"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-max-h)
+ :value (get values :layout-item-max-h)
+ :nillable true}]]])]])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss
index 6899664041..a88b10213d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss
@@ -8,125 +8,132 @@
.element-set {
margin: 0;
- .element-title {
- .title-spacing-layout-element {
- margin: 0 0 $s-4 0;
- }
- .title-spacing-empty {
- padding-left: $s-2;
- }
+}
+
+.title-spacing-layout-element {
+ margin: 0 0 $s-4 0;
+}
+
+.title-spacing-empty {
+ padding-left: $s-2;
+}
+
+.flex-element-menu {
+ @include flexColumn;
+ gap: $s-12;
+}
+
+.behaviour-menu {
+ display: flex;
+ gap: $s-4;
+}
+
+.horizontal-behaviour {
+ &.one-element {
+ width: $s-28;
}
- .flex-element-menu {
- @include flexColumn;
- gap: $s-12;
+ &.two-element {
+ width: $s-60;
+ }
+ &.three-element {
+ width: $s-92;
+ }
+}
- .behaviour-menu {
- display: flex;
- gap: $s-4;
- .horizontal-behaviour {
- &.one-element {
- width: $s-28;
- }
- &.two-element {
- width: $s-60;
- }
- &.three-element {
- width: $s-92;
- }
- }
- .vertical-behaviour {
- .rotated {
- transform: rotate(90deg);
- }
- &.one-element {
- width: $s-28;
- }
- &.two-element {
- width: $s-60;
- }
- &.three-element {
- width: $s-92;
- }
- }
- }
+.vertical-behaviour {
+ .rotated {
+ transform: rotate(90deg);
+ }
+ &.one-element {
+ width: $s-28;
+ }
+ &.two-element {
+ width: $s-60;
+ }
+ &.three-element {
+ width: $s-92;
+ }
+}
- .z-index-wrapper {
- @extend .input-element;
- width: $s-60;
- }
+.z-index-wrapper {
+ @extend .input-element;
+ width: $s-60;
+}
- .row {
- display: flex;
- gap: $s-4;
- }
+.row {
+ display: flex;
+ gap: $s-4;
+}
- .position-options {
- width: $s-188;
- }
+.position-options {
+ width: $s-188;
+}
- .margin-row {
- display: flex;
- align-items: flex-start;
- gap: $s-4;
- .margin-mode {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- &.selected {
- background-color: var(--button-tertiary-background-color-active);
- color: var(--button-tertiary-foreground-color-active);
- svg {
- stroke: var(--button-tertiary-foreground-color-active);
- }
- }
- }
- .inputs-wrapper {
- .margin-simple {
- display: flex;
- gap: $s-4;
- .vertical-margin,
- .horizontal-margin {
- @extend .input-element;
- width: $s-108;
- }
- }
- .margin-multiple {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: $s-4;
- .top-margin,
- .bottom-margin,
- .left-margin,
- .right-margin {
- @extend .input-element;
- width: $s-108;
- }
- }
- }
- }
+.margin-row {
+ display: flex;
+ align-items: flex-start;
+ gap: $s-4;
+}
- .advanced-options {
- @include flexColumn;
- .horizontal-fill,
- .vertical-fill {
- display: flex;
- gap: $s-4;
- .layout-item-min-w,
- .layout-item-min-h,
- .layout-item-max-w,
- .layout-item-max-h {
- @extend .input-element;
- width: $s-108;
- .icon-text {
- justify-content: flex-start;
- width: $s-80;
- padding-top: $s-2;
- }
- }
- }
+.margin-mode {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ &.selected {
+ background-color: var(--button-tertiary-background-color-active);
+ color: var(--button-tertiary-foreground-color-active);
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
}
}
}
+
+.margin-simple {
+ display: flex;
+ gap: $s-4;
+ .vertical-margin,
+ .horizontal-margin {
+ @extend .input-element;
+ width: $s-108;
+ }
+}
+
+.margin-multiple {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: $s-4;
+}
+
+.top-margin,
+.bottom-margin,
+.left-margin,
+.right-margin {
+ @extend .input-element;
+ width: $s-108;
+}
+
+.advanced-options {
+ @include flexColumn;
+}
+
+.horizontal-fill,
+.vertical-fill {
+ display: flex;
+ gap: $s-4;
+}
+
+.layout-item-min-w,
+.layout-item-min-h,
+.layout-item-max-w,
+.layout-item-max-h {
+ @extend .input-element;
+ width: $s-108;
+ .icon-text {
+ justify-content: flex-start;
+ width: $s-80;
+ padding-top: $s-2;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
index fc408f592e..0cc61833c6 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
@@ -21,7 +21,6 @@
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
@@ -75,8 +74,7 @@
{::mf/wrap-props false
::mf/wrap [mf/memo]}
[{:keys [ids ids-with-children values type all-types shape]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- options (if (= type :multiple)
+ (let [options (if (= type :multiple)
(reduce #(union %1 %2) (map #(get type->options %) all-types))
(get type->options type))
@@ -193,16 +191,7 @@
:else
:vert))
- on-orientation-clicked
- (mf/use-fn
- (mf/deps ids)
- (fn [event]
- (let [orientation (-> (dom/get-current-target event)
- (dom/get-data "value")
- (keyword))]
- (st/emit! (udw/change-orientation ids orientation)))))
-
- on-orientation-change-refactor
+ on-orientation-change
(mf/use-fn
(mf/deps ids)
(fn [orientation]
@@ -348,30 +337,29 @@
;; restore focus to the newly created numeric-input
(let [radius-input (mf/ref-val radius-input-ref)]
(dom/focus! radius-input)))))
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- (when (and (options :presets)
- (or (nil? all-types) (= (count all-types) 1)))
- [:div {:class (stl/css :presets)}
- [:div {:class (stl/css-case :presets-wrapper true
- :opened show-presets-dropdown?)
- :on-click open-presets}
- [:span {:class (stl/css :select-name)}(tr "workspace.options.size-presets")]
- [:span {:class (stl/css :collapsed-icon)} i/arrow-refactor]
+ [:div {:class (stl/css :element-set)}
+ (when (and (options :presets)
+ (or (nil? all-types) (= (count all-types) 1)))
+ [:div {:class (stl/css :presets)}
+ [:div {:class (stl/css-case :presets-wrapper true
+ :opened show-presets-dropdown?)
+ :on-click open-presets}
+ [:span {:class (stl/css :select-name)} (tr "workspace.options.size-presets")]
+ [:span {:class (stl/css :collapsed-icon)} i/arrow-refactor]
- [:& dropdown {:show show-presets-dropdown?
- :on-close close-presets}
- [:ul {:class (stl/css :custom-select-dropdown)}
- (for [size-preset size-presets]
- (if-not (:width size-preset)
+ [:& dropdown {:show show-presets-dropdown?
+ :on-close close-presets}
+ [:ul {:class (stl/css :custom-select-dropdown)}
+ (for [size-preset size-presets]
+ (if-not (:width size-preset)
+ [:li {:key (:name size-preset)
+ :class (stl/css-case :dropdown-element true
+ :disabled true)}
+ [:span {:class (stl/css :preset-name)} (:name size-preset)]]
+
+ (let [preset-match (and (= (:width size-preset) (d/parse-integer (:width values) 0))
+ (= (:height size-preset) (d/parse-integer (:height values) 0)))]
[:li {:key (:name size-preset)
- :class (stl/css-case :dropdown-element true
- :disabled true)}
- [:span {:class (stl/css :preset-name)} (:name size-preset)]]
-
- (let [preset-match (and (= (:width size-preset) (d/parse-integer (:width values) 0))
- (= (:height size-preset) (d/parse-integer (:height values) 0)))]
- [:li {:key (:name size-preset)
:class (stl/css-case :dropdown-element true
:match preset-match)
:data-width (:width size-preset)
@@ -383,366 +371,189 @@
(when preset-match
[:span {:class (stl/css :check-icon)} i/tick-refactor])])))]]]
- [:& radio-buttons {:selected (or (d/name orientation) "")
- :on-change on-orientation-change-refactor
- :name "frame-otientation"}
- [:& radio-button {:icon i/size-vertical-refactor
- :value "vert"
- :id "size-vertical"}]
- [:& radio-button {:icon i/size-horizontal-refactor
- :value "horiz"
- :id "size-horizontal"}]]])
- (when (options :size)
- [:div {:class (stl/css :size)}
- [:div {:class (stl/css-case :width true
- :disabled disabled-width-sizing?)
- :title (tr "workspace.options.width")}
- [:span {:class (stl/css :icon-text)} "W"]
- [:> numeric-input* {:min 0.01
- :no-validate true
- :placeholder "--"
- :on-change on-width-change
- :disabled disabled-width-sizing?
- :className (stl/css :numeric-input)
- :value (:width values)}]]
- [:div {:class (stl/css-case :height true
- :disabled disabled-height-sizing?)
- :title (tr "workspace.options.height")}
- [:span {:class (stl/css :icon-text)} "H"]
- [:> numeric-input* {:min 0.01
- :no-validate true
- :placeholder "--"
- :on-change on-height-change
- :disabled disabled-height-sizing?
- :className (stl/css :numeric-input)
- :value (:height values)}]]
- [:button {:class (stl/css-case
- :lock-size-btn true
- :selected (true? proportion-lock)
- :disabled (= proportion-lock :multiple))
- :on-click on-proportion-lock-change}
- (if proportion-lock
- i/lock-refactor
- i/unlock-refactor)]])
- (when (options :position)
- [:div {:class (stl/css :position)}
- [:div {:class (stl/css-case :x-position true
- :disabled disabled-position-x?)
- :title (tr "workspace.options.x")}
- [:span {:class (stl/css :icon-text)} "X"]
- [:> numeric-input* {:no-validate true
- :placeholder "--"
- :on-change on-pos-x-change
- :disabled disabled-position-x?
- :className (stl/css :numeric-input)
- :value (:x values)}]]
+ [:& radio-buttons {:selected (or (d/name orientation) "")
+ :on-change on-orientation-change
+ :name "frame-otientation"}
+ [:& radio-button {:icon i/size-vertical-refactor
+ :value "vert"
+ :id "size-vertical"}]
+ [:& radio-button {:icon i/size-horizontal-refactor
+ :value "horiz"
+ :id "size-horizontal"}]]])
+ (when (options :size)
+ [:div {:class (stl/css :size)}
+ [:div {:class (stl/css-case :width true
+ :disabled disabled-width-sizing?)
+ :title (tr "workspace.options.width")}
+ [:span {:class (stl/css :icon-text)} "W"]
+ [:> numeric-input* {:min 0.01
+ :no-validate true
+ :placeholder "--"
+ :on-change on-width-change
+ :disabled disabled-width-sizing?
+ :className (stl/css :numeric-input)
+ :value (:width values)}]]
+ [:div {:class (stl/css-case :height true
+ :disabled disabled-height-sizing?)
+ :title (tr "workspace.options.height")}
+ [:span {:class (stl/css :icon-text)} "H"]
+ [:> numeric-input* {:min 0.01
+ :no-validate true
+ :placeholder "--"
+ :on-change on-height-change
+ :disabled disabled-height-sizing?
+ :className (stl/css :numeric-input)
+ :value (:height values)}]]
+ [:button {:class (stl/css-case
+ :lock-size-btn true
+ :selected (true? proportion-lock)
+ :disabled (= proportion-lock :multiple))
+ :on-click on-proportion-lock-change}
+ (if proportion-lock
+ i/lock-refactor
+ i/unlock-refactor)]])
+ (when (options :position)
+ [:div {:class (stl/css :position)}
+ [:div {:class (stl/css-case :x-position true
+ :disabled disabled-position-x?)
+ :title (tr "workspace.options.x")}
+ [:span {:class (stl/css :icon-text)} "X"]
+ [:> numeric-input* {:no-validate true
+ :placeholder "--"
+ :on-change on-pos-x-change
+ :disabled disabled-position-x?
+ :className (stl/css :numeric-input)
+ :value (:x values)}]]
- [:div {:class (stl/css-case :y-position true
- :disabled disabled-position-y?)
- :title (tr "workspace.options.y")}
- [:span {:class (stl/css :icon-text)} "Y"]
- [:> numeric-input* {:no-validate true
- :placeholder "--"
- :disabled disabled-position-y?
- :on-change on-pos-y-change
- :className (stl/css :numeric-input)
- :value (:y values)}]]])
- (when (or (options :rotation) (options :radius))
- [:div {:class (stl/css :rotation-radius)}
+ [:div {:class (stl/css-case :y-position true
+ :disabled disabled-position-y?)
+ :title (tr "workspace.options.y")}
+ [:span {:class (stl/css :icon-text)} "Y"]
+ [:> numeric-input* {:no-validate true
+ :placeholder "--"
+ :disabled disabled-position-y?
+ :on-change on-pos-y-change
+ :className (stl/css :numeric-input)
+ :value (:y values)}]]])
+ (when (or (options :rotation) (options :radius))
+ [:div {:class (stl/css :rotation-radius)}
- (when (options :rotation)
- [:div {:class (stl/css :rotation)
- :title (tr "workspace.options.rotation")}
- [:span {:class (stl/css :icon)} i/rotation-refactor]
- [:> numeric-input*
- {:no-validate true
- :min 0
- :max 359
- :data-wrap true
- :placeholder "--"
- :on-change on-rotation-change
- :className (stl/css :numeric-input)
- :value (:rotation values)}]])
-
- (when (options :radius)
- [:div {:class (stl/css :radius)}
- [:div {:class (stl/css :radius-inputs)}
- (cond
- (= radius-mode :radius-1)
- [:div {:class (stl/css :radius-1)
- :title (tr "workspace.options.radius")}
- [:span {:class (stl/css :icon)} i/corner-radius-refactor]
- [:> numeric-input*
- {:placeholder "Mixed"
- :ref radius-input-ref
- :min 0
- :on-change on-radius-1-change
- :className (stl/css :numeric-input)
- :value (:rx values)}]]
-
- @radius-multi?
- [:div {:class (stl/css :radius-1)
- :title (tr "workspace.options.radius")}
- [:span {:class (stl/css :icon)} i/corner-radius-refactor]
- [:input.input-text
- {:type "number"
- :placeholder "Mixed"
- :min 0
- :on-change on-radius-multi-change
- :className (stl/css :numeric-input)
- :value (if all-equal? (:rx values) nil)}]]
-
-
- (= radius-mode :radius-4)
- [:div {:class (stl/css :radius-4)}
- [:div {:class (stl/css :small-input)
- :title (tr "workspace.options.radius-top-left")}
- [:> numeric-input*
- {:placeholder "--"
- :min 0
- :on-change on-radius-r1-change
- :className (stl/css :numeric-input)
- :value (:r1 values)}]]
-
- [:div {:class (stl/css :small-input)
- :title (tr "workspace.options.radius-top-right")}
- [:> numeric-input*
- {:placeholder "--"
- :min 0
- :on-change on-radius-r2-change
- :className (stl/css :numeric-input)
- :value (:r2 values)}]]
-
- [:div {:class (stl/css :small-input)
- :title (tr "workspace.options.radius-bottom-left")}
- [:> numeric-input*
- {:placeholder "--"
- :min 0
- :on-change on-radius-r4-change
- :className (stl/css :numeric-input)
- :value (:r4 values)}]]
-
- [:div {:class (stl/css :small-input)
- :title (tr "workspace.options.radius-bottom-right")}
- [:> numeric-input*
- {:placeholder "--"
- :min 0
- :on-change on-radius-r3-change
- :className (stl/css :numeric-input)
- :value (:r3 values)}]]
- ])]
- [:button {:class (stl/css-case :radius-mode true
- :selected (= radius-mode :radius-4))
- :title (if(= radius-mode :radius-4)
- (tr "workspace.options.radius.all-corners")
- (tr "workspace.options.radius.single-corners"))
- :on-click toggle-radius-mode}
- i/corner-radius-refactor]])])
- (when (or (options :clip-content) (options :show-in-viewer))
- [:div {:class (stl/css :clip-show)}
- (when (options :clip-content)
- [:div {:class (stl/css :clip-content)}
- [:input {:type "checkbox"
- :id "clip-content"
- :ref clip-content-ref
- :class (stl/css :clip-content-input)
- :checked (not (:show-content values))
- :on-change on-change-clip-content}]
-
- [:label {:for "clip-content"
- :title (tr "workspace.options.clip-content")
- :class (stl/css-case :clip-content-label true
- :selected (not (:show-content values)))}
- [:span {:class (stl/css :icon)}
- i/clip-content-refactor]
- ]])
- (when (options :show-in-viewer)
- [:div {:class (stl/css :clip-content)}
- [:input {:type "checkbox"
- :id "show-in-viewer"
- :ref show-in-viewer-ref
- :class (stl/css :clip-content-input)
- :checked (not (:hide-in-viewer values))
- :on-change on-change-show-in-viewer}]
-
- [:label {:for "show-in-viewer"
- :title (tr "workspace.options.show-in-viewer")
- :class (stl/css-case :clip-content-label true
- :selected (not (:hide-in-viewer values)))}
- [:span {:class (stl/css :icon)}
- i/play-refactor]]])])]
-
- [:*
- [:div.element-set
- [:div.element-set-content
-
- ;; FRAME PRESETS
- (when (and (options :presets)
- (or (nil? all-types) (= (count all-types) 1))) ;; Don't show presets if multi selected
- [:div.row-flex ;; some frames and some non frames
- [:div.presets.custom-select.flex-grow {:class (when show-presets-dropdown? "opened")
- :on-click open-presets}
- [:span (tr "workspace.options.size-presets")]
- [:span.dropdown-button i/arrow-down]
- [:& dropdown {:show show-presets-dropdown?
- :on-close close-presets}
- [:ul.custom-select-dropdown
- (for [size-preset size-presets]
- (if-not (:width size-preset)
- [:li.dropdown-label {:key (:name size-preset)}
- [:span (:name size-preset)]]
- [:li {:key (:name size-preset)
- :data-width (:width size-preset)
- :data-height (:height size-preset)
- :on-click on-preset-selected}
- (:name size-preset)
- [:span (:width size-preset) " x " (:height size-preset)]]))]]]
- [:span.orientation-icon {:data-value :vert
- :on-click on-orientation-clicked} i/size-vert]
- [:span.orientation-icon {:data-value :horiz
- :on-click on-orientation-clicked} i/size-horiz]])
-
- ;; WIDTH & HEIGHT
- (when (options :size)
- [:div.row-flex
- [:span.element-set-subtitle (tr "workspace.options.size")]
- [:div.input-element.width {:title (tr "workspace.options.width")}
- [:> numeric-input* {:min 0.01
- :no-validate true
- :placeholder "--"
- :on-change on-width-change
- :disabled disabled-width-sizing?
- :value (:width values)}]]
-
- [:div.input-element.height {:title (tr "workspace.options.height")}
- [:> numeric-input* {:min 0.01
- :no-validate true
- :placeholder "--"
- :on-change on-height-change
- :disabled disabled-height-sizing?
- :value (:height values)}]]
-
- [:div.lock-size {:class (dom/classnames
- :selected (true? proportion-lock)
- :disabled (= proportion-lock :multiple))
- :on-click on-proportion-lock-change}
- (if proportion-lock
- i/lock
- i/unlock)]])
-
- ;; POSITION
- (when (options :position)
- [:div.row-flex
- [:span.element-set-subtitle (tr "workspace.options.position")]
- [:div.input-element.Xaxis {:title (tr "workspace.options.x")}
- [:> numeric-input* {:no-validate true
- :placeholder "--"
- :on-change on-pos-x-change
- :disabled disabled-position-x?
- :value (:x values)}]]
- [:div.input-element.Yaxis {:title (tr "workspace.options.y")}
- [:> numeric-input* {:no-validate true
- :placeholder "--"
- :disabled disabled-position-y?
- :on-change on-pos-y-change
- :value (:y values)}]]])
-
- ;; ROTATION
- (when (options :rotation)
- [:div.row-flex
- [:span.element-set-subtitle (tr "workspace.options.rotation")]
- [:div.input-element.degrees {:title (tr "workspace.options.rotation")}
- [:> numeric-input*
- {:no-validate true
- :min 0
- :max 359
- :data-wrap true
- :placeholder "--"
- :on-change on-rotation-change
- :value (:rotation values)}]]])
-
- ;; RADIUS
- (when (options :radius)
- [:div.row-flex
- [:div.radius-options
- [:div.radius-icon.tooltip.tooltip-bottom
- {:class (dom/classnames
- :selected (or (= radius-mode :radius-1) @radius-multi?))
- :alt (tr "workspace.options.radius.all-corners")
- :on-click on-switch-to-radius-1}
- i/radius-1]
- [:div.radius-icon.tooltip.tooltip-bottom
- {:class (dom/classnames
- :selected (and (= radius-mode :radius-4) (not @radius-multi?)))
- :alt (tr "workspace.options.radius.single-corners")
- :on-click on-switch-to-radius-4}
- i/radius-4]]
+ (when (options :rotation)
+ [:div {:class (stl/css :rotation)
+ :title (tr "workspace.options.rotation")}
+ [:span {:class (stl/css :icon)} i/rotation-refactor]
+ [:> numeric-input*
+ {:no-validate true
+ :min 0
+ :max 359
+ :data-wrap true
+ :placeholder "--"
+ :on-change on-rotation-change
+ :className (stl/css :numeric-input)
+ :value (:rotation values)}]])
+ (when (options :radius)
+ [:div {:class (stl/css :radius)}
+ [:div {:class (stl/css :radius-inputs)}
(cond
(= radius-mode :radius-1)
- [:div.input-element.mini {:title (tr "workspace.options.radius")}
+ [:div {:class (stl/css :radius-1)
+ :title (tr "workspace.options.radius")}
+ [:span {:class (stl/css :icon)} i/corner-radius-refactor]
[:> numeric-input*
- {:placeholder "--"
+ {:placeholder "Mixed"
:ref radius-input-ref
:min 0
:on-change on-radius-1-change
+ :className (stl/css :numeric-input)
:value (:rx values)}]]
@radius-multi?
- [:div.input-element.mini {:title (tr "workspace.options.radius")}
+ [:div {:class (stl/css :radius-1)
+ :title (tr "workspace.options.radius")}
+ [:span {:class (stl/css :icon)} i/corner-radius-refactor]
[:input.input-text
{:type "number"
- :placeholder "--"
+ :placeholder "Mixed"
:min 0
:on-change on-radius-multi-change
- :value ""}]]
+ :className (stl/css :numeric-input)
+ :value (if all-equal? (:rx values) nil)}]]
+
(= radius-mode :radius-4)
- [:*
- [:div.input-element.mini {:title (tr "workspace.options.radius-top-left")}
+ [:div {:class (stl/css :radius-4)}
+ [:div {:class (stl/css :small-input)
+ :title (tr "workspace.options.radius-top-left")}
[:> numeric-input*
{:placeholder "--"
:min 0
:on-change on-radius-r1-change
+ :className (stl/css :numeric-input)
:value (:r1 values)}]]
- [:div.input-element.mini {:title (tr "workspace.options.radius-top-right")}
+ [:div {:class (stl/css :small-input)
+ :title (tr "workspace.options.radius-top-right")}
[:> numeric-input*
{:placeholder "--"
:min 0
:on-change on-radius-r2-change
+ :className (stl/css :numeric-input)
:value (:r2 values)}]]
- [:div.input-element.mini {:title (tr "workspace.options.radius-bottom-right")}
- [:> numeric-input*
- {:placeholder "--"
- :min 0
- :on-change on-radius-r3-change
- :value (:r3 values)}]]
-
- [:div.input-element.mini {:title (tr "workspace.options.radius-bottom-left")}
+ [:div {:class (stl/css :small-input)
+ :title (tr "workspace.options.radius-bottom-left")}
[:> numeric-input*
{:placeholder "--"
:min 0
:on-change on-radius-r4-change
- :value (:r4 values)}]]])])
- (when (options :clip-content)
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id "clip-content"
- :ref clip-content-ref
- :checked (not (:show-content values))
- :on-change on-change-clip-content}]
+ :className (stl/css :numeric-input)
+ :value (:r4 values)}]]
- [:label {:for "clip-content"}
- (tr "workspace.options.clip-content")]])
- (when (options :show-in-viewer)
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id "show-in-viewer"
- :ref show-in-viewer-ref
- :checked (not (:hide-in-viewer values))
- :on-change on-change-show-in-viewer}]
+ [:div {:class (stl/css :small-input)
+ :title (tr "workspace.options.radius-bottom-right")}
+ [:> numeric-input*
+ {:placeholder "--"
+ :min 0
+ :on-change on-radius-r3-change
+ :className (stl/css :numeric-input)
+ :value (:r3 values)}]]])]
+ [:button {:class (stl/css-case :radius-mode true
+ :selected (= radius-mode :radius-4))
+ :title (if (= radius-mode :radius-4)
+ (tr "workspace.options.radius.all-corners")
+ (tr "workspace.options.radius.single-corners"))
+ :on-click toggle-radius-mode}
+ i/corner-radius-refactor]])])
+ (when (or (options :clip-content) (options :show-in-viewer))
+ [:div {:class (stl/css :clip-show)}
+ (when (options :clip-content)
+ [:div {:class (stl/css :clip-content)}
+ [:input {:type "checkbox"
+ :id "clip-content"
+ :ref clip-content-ref
+ :class (stl/css :clip-content-input)
+ :checked (not (:show-content values))
+ :on-change on-change-clip-content}]
- [:label {:for "show-in-viewer"}
- (tr "workspace.options.show-in-viewer")]])]]])))
+ [:label {:for "clip-content"
+ :title (tr "workspace.options.clip-content")
+ :class (stl/css-case :clip-content-label true
+ :selected (not (:show-content values)))}
+ [:span {:class (stl/css :icon)}
+ i/clip-content-refactor]]])
+ (when (options :show-in-viewer)
+ [:div {:class (stl/css :clip-content)}
+ [:input {:type "checkbox"
+ :id "show-in-viewer"
+ :ref show-in-viewer-ref
+ :class (stl/css :clip-content-input)
+ :checked (not (:hide-in-viewer values))
+ :on-change on-change-show-in-viewer}]
+
+ [:label {:for "show-in-viewer"
+ :title (tr "workspace.options.show-in-viewer")
+ :class (stl/css-case :clip-content-label true
+ :selected (not (:hide-in-viewer values)))}
+ [:span {:class (stl/css :icon)}
+ i/play-refactor]]])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss
index b0a5cb1a65..f05c3e555e 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss
@@ -9,216 +9,235 @@
.element-set {
@include flexColumn;
margin-bottom: $s-8;
- .presets {
- display: flex;
- align-items: flex-start;
- gap: $s-4;
- .presets-wrapper {
- @extend .asset-element;
- position: relative;
- display: flex;
- height: $s-32;
- width: $s-188;
- padding: $s-8;
- border-radius: $br-8;
- .select-name {
- @include titleTipography;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- flex-grow: 1;
- cursor: pointer;
- }
- .collapsed-icon {
- @include flexCenter;
- cursor: pointer;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- transform: rotate(90deg);
- }
- }
- .custom-select-dropdown {
- @extend .dropdown-wrapper;
- margin-top: $s-2;
- width: $s-252;
- .dropdown-element {
- @extend .dropdown-element-base;
- .name-wrapper {
- display: flex;
- gap: $s-8;
- flex-grow: 1;
- .preset-name {
- color: var(--menu-foreground-color-rest);
- }
- .preset-size {
- color: var(--menu-foreground-color-rest);
- }
- }
+}
- .check-icon {
- @include flexCenter;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
+.presets {
+ display: flex;
+ align-items: flex-start;
+ gap: $s-4;
+}
- &.disabled {
- pointer-events: none;
- cursor: default;
- .preset-name {
- color: var(--menu-foreground-color);
- }
- }
+.presets-wrapper {
+ @extend .asset-element;
+ position: relative;
+ display: flex;
+ height: $s-32;
+ width: $s-188;
+ padding: $s-8;
+ border-radius: $br-8;
- &.match {
- .name-wrapper .preset-name {
- color: var(--menu-foreground-color-hover);
- }
- .check-icon svg {
- stroke: var(--menu-foreground-color-hover);
- }
- }
-
- &:hover {
- background-color: var(--menu-background-color-hover);
- .name-wrapper .preset-name {
- color: var(--menu-foreground-color-hover);
- }
- .check-icon svg {
- stroke: var(--menu-foreground-color-hover);
- }
- }
- }
- }
- &:hover {
- .collapsed-icon svg {
- stroke: var(--input-foreground-color-active);
- }
- }
+ .collapsed-icon {
+ @include flexCenter;
+ cursor: pointer;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--icon-foreground);
+ transform: rotate(90deg);
}
}
- .size {
- @include flexRow;
- .height,
- .width {
- @extend .input-element;
- width: $s-108;
- .icon-text {
- padding-top: $s-1;
+
+ &:hover {
+ .collapsed-icon svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+}
+
+.select-name {
+ @include titleTipography;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ flex-grow: 1;
+ cursor: pointer;
+}
+
+.custom-select-dropdown {
+ @extend .dropdown-wrapper;
+ margin-top: $s-2;
+ width: $s-252;
+ .dropdown-element {
+ @extend .dropdown-element-base;
+ .name-wrapper {
+ display: flex;
+ gap: $s-8;
+ flex-grow: 1;
+ .preset-name {
+ color: var(--menu-foreground-color-rest);
}
- &.disabled {
- @extend .disabled-input;
+ .preset-size {
+ color: var(--menu-foreground-color-rest);
}
}
- .lock-size-btn {
- @extend .button-tertiary;
- border-radius: $br-8;
- height: $s-32;
- width: $s-28;
+
+ .check-icon {
+ @include flexCenter;
svg {
- @extend .button-icon;
+ @extend .button-icon-small;
stroke: var(--icon-foreground);
}
- &.selected {
- @extend .button-icon-selected;
+ }
+
+ &.disabled {
+ pointer-events: none;
+ cursor: default;
+ .preset-name {
+ color: var(--menu-foreground-color);
}
}
- }
- .position {
- @include flexRow;
- .x-position,
- .y-position {
- @extend .input-element;
- width: $s-108;
- .icon-text {
- padding-top: $s-1;
+
+ &.match {
+ .name-wrapper .preset-name {
+ color: var(--menu-foreground-color-hover);
}
- &.disabled {
- @extend .disabled-input;
+ .check-icon svg {
+ stroke: var(--menu-foreground-color-hover);
}
}
- }
- .rotation-radius {
- display: flex;
- align-items: flex-start;
- justify-content: flex-start;
- gap: $s-4;
- .rotation {
- @extend .input-element;
- width: $s-108;
- .icon-text {
- padding-top: $s-1;
+
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ .name-wrapper .preset-name {
+ color: var(--menu-foreground-color-hover);
}
- }
- .radius {
- display: flex;
- align-items: flex-start;
- justify-content: flex-start;
- gap: $s-4;
- .radius-inputs {
- display: flex;
- .radius-1 {
- @extend .input-element;
- width: $s-108;
- }
- .radius-4 {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: $s-4;
- .small-input {
- @extend .input-element;
- width: $s-52;
- }
- }
- }
- .radius-mode {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- border-radius: $br-8;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- &.selected {
- background-color: var(--button-tertiary-background-color-hover);
- svg {
- stroke: var(--button-tertiary-foreground-color-active);
- }
- }
- }
- }
- }
- .clip-show {
- display: flex;
- align-items: flex-start;
- justify-content: flex-start;
- gap: $s-4;
- .clip-content,
- .show-in-viewer {
- .clip-content-input {
- display: none;
- }
- .clip-content-label {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- border-radius: $br-8;
- .icon {
- @include flexCenter;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- }
- }
- &.selected {
- background-color: var(--button-tertiary-background-color-hover);
- svg {
- stroke: var(--button-tertiary-foreground-color-active);
- }
- }
+ .check-icon svg {
+ stroke: var(--menu-foreground-color-hover);
+ }
+ }
+ }
+}
+
+.size {
+ @include flexRow;
+}
+
+.height,
+.width {
+ @extend .input-element;
+ width: $s-108;
+ .icon-text {
+ padding-top: $s-1;
+ }
+ &.disabled {
+ @extend .disabled-input;
+ }
+}
+
+.lock-size-btn {
+ @extend .button-tertiary;
+ border-radius: $br-8;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ &.selected {
+ @extend .button-icon-selected;
+ }
+}
+
+.position {
+ @include flexRow;
+}
+
+.x-position,
+.y-position {
+ @extend .input-element;
+ width: $s-108;
+ .icon-text {
+ padding-top: $s-1;
+ }
+ &.disabled {
+ @extend .disabled-input;
+ }
+}
+
+.rotation-radius {
+ display: flex;
+ align-items: flex-start;
+ justify-content: flex-start;
+ gap: $s-4;
+}
+
+.rotation {
+ @extend .input-element;
+ width: $s-108;
+ .icon-text {
+ padding-top: $s-1;
+ }
+}
+.radius {
+ display: flex;
+ align-items: flex-start;
+ justify-content: flex-start;
+ gap: $s-4;
+}
+
+.radius-inputs {
+ display: flex;
+}
+
+.radius-1 {
+ @extend .input-element;
+ width: $s-108;
+}
+
+.radius-4 {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: $s-4;
+ .small-input {
+ @extend .input-element;
+ width: $s-52;
+ }
+}
+
+.radius-mode {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ &.selected {
+ background-color: var(--button-tertiary-background-color-hover);
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
+ }
+ }
+}
+
+.clip-show {
+ display: flex;
+ align-items: flex-start;
+ justify-content: flex-start;
+ gap: $s-4;
+}
+
+.clip-content,
+.show-in-viewer {
+ .clip-content-input {
+ display: none;
+ }
+ .clip-content-label {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8;
+ .icon {
+ @include flexCenter;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ }
+ &.selected {
+ background-color: var(--button-tertiary-background-color-hover);
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs
index a7246b2494..874e4628a5 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs
@@ -19,7 +19,6 @@
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
@@ -51,8 +50,7 @@
(mf/defc shadow-entry
[{:keys [ids index value on-reorder disable-drag? on-blur open-state-ref]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- basic-offset-x-ref (mf/use-ref nil)
+ (let [basic-offset-x-ref (mf/use-ref nil)
basic-offset-y-ref (mf/use-ref nil)
basic-blur-ref (mf/use-ref nil)
@@ -61,9 +59,7 @@
adv-blur-ref (mf/use-ref nil)
adv-spread-ref (mf/use-ref nil)
- shadow-style (if new-css-system
- (:style value)
- (dm/str (:style value)))
+ shadow-style (:style value)
shadow-id (:id value)
@@ -143,9 +139,7 @@
(mf/use-fn
(mf/deps ids index)
(fn [event]
- (let [value (if new-css-system
- (keyword event)
- (-> event dom/get-target-val d/read-string))]
+ (let [value (keyword event)]
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value))))))
type-options [{:value "drop-shadow" :label (tr "workspace.options.shadow-options.drop-shadow")}
@@ -155,187 +149,91 @@
manage-on-close #(st/emit! (dwu/commit-undo-transaction :color-row))]
- [:div.shadow-option {:class (stl/css-case new-css-system
- :global/shadow-option true
- :shadow-element true
- :dnd-over-top (= (:over dprops) :top)
- :dnd-over-bot (= (:over dprops) :bot))
- :ref dref}
- (if new-css-system
- [:*
- [:div {:class (stl/css :basic-options)}
- [:div {:class (stl/css-case :shadow-info true
- :hidden hidden?)}
- [:button {:class (stl/css-case :more-options true
- :selected open-shadow)
- :on-click on-toggle-open-shadow}
- i/menu-refactor]
- [:div {:class (stl/css :type-select)}
- [:& select
- {:class (stl/css :shadow-type-select)
- :default-value (d/name shadow-style)
- :options type-options
- :on-change on-type-change}]]]
- [:div {:class (stl/css :actions)}
- [:button {:class (stl/css :action-btn)
- :on-click toggle-visibility}
- (if hidden?
- i/hide-refactor
- i/shown-refactor)]
- [:button {:class (stl/css :action-btn)
- :on-click on-remove-shadow}
- i/remove-refactor]]]
- (when open-shadow
- [:& advanced-options {:class (stl/css :shadow-advanced-options)
- :visible? open-shadow
- :on-close on-toggle-open-shadow}
-
- [:div {:class (stl/css :first-row)}
- [:div {:class (stl/css :offset-x-input)
- :title (tr "workspace.options.shadow-options.offsetx")}
- [:span {:class (stl/css :input-label)}
- "X"]
- [:> numeric-input* {:className (stl/css :numeric-input)
- :ref adv-offset-x-ref
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :offset-x basic-offset-x-ref)
- :on-blur on-blur
- :value (:offset-x value)}]]
-
- [:div {:class (stl/css :blur-input)
- :title (tr "workspace.options.shadow-options.blur")}
- [:span {:class (stl/css :input-label)}
- (tr "workspace.options.shadow-options.blur")]
- [:> numeric-input* {:ref adv-blur-ref
- :className (stl/css :numeric-input)
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :blur basic-blur-ref)
- :on-blur on-blur
- :min 0
- :value (:blur value)}]]
-
- [:div {:class (stl/css :spread-input)
- :title (tr "workspace.options.shadow-options.spread")}
- [:span {:class (stl/css :input-label)}
- (tr "workspace.options.shadow-options.spread")]
- [:> numeric-input* {:ref adv-spread-ref
- :className (stl/css :numeric-input)
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :spread)
- :on-blur on-blur
- :value (:spread value)}]]]
-
- [:div {:class (stl/css :second-row)}
- [:div {:class (stl/css :offset-y-input)
- :title (tr "workspace.options.shadow-options.offsety")}
- [:span {:class (stl/css :input-label)}
- "Y"]
- [:> numeric-input* {:ref adv-offset-y-ref
- :className (stl/css :numeric-input)
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :offset-y basic-offset-y-ref)
- :on-blur on-blur
- :value (:offset-y value)}]]
- [:& color-row {:color (if (string? (:color value))
- ;; Support for old format colors
- {:color (:color value) :opacity (:opacity value)}
- (:color value))
- :title (tr "workspace.options.shadow-options.color")
- :disable-gradient true
- :disable-image true
- :on-change update-color
- :on-detach detach-color
- :on-open manage-on-open
- :on-close manage-on-close}]]])]
-
- [:*
- [:div.shadow-option-main {:style {:display (when open-shadow "none")}}
- [:div.element-set-actions-button
- {:on-click on-toggle-open-shadow}
- i/actions]
-
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :default-value shadow-style
- :on-change on-type-change}
- [:option {:value ":drop-shadow"
- :selected (when (= shadow-style ":drop-shadow") "selected")}
- (tr "workspace.options.shadow-options.drop-shadow")]
- [:option {:value ":inner-shadow"
- :selected (when (= shadow-style ":inner-shadow") "selected")}
- (tr "workspace.options.shadow-options.inner-shadow")]]
-
- [:div.shadow-option-main-actions
- [:div.element-set-actions-button {:on-click toggle-visibility}
- (if hidden? i/eye-closed i/eye)]
- [:div.element-set-actions-button
- {:data-index index
- :on-click on-remove-shadow}
- i/minus]]]
-
- [:& advanced-options {:visible? open-shadow
+ [:div {:class (stl/css-case :global/shadow-option true
+ :shadow-element true
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ [:*
+ [:div {:class (stl/css :basic-options)}
+ [:div {:class (stl/css-case :shadow-info true
+ :hidden hidden?)}
+ [:button {:class (stl/css-case :more-options true
+ :selected open-shadow)
+ :on-click on-toggle-open-shadow}
+ i/menu-refactor]
+ [:div {:class (stl/css :type-select)}
+ [:& select
+ {:class (stl/css :shadow-type-select)
+ :default-value (d/name shadow-style)
+ :options type-options
+ :on-change on-type-change}]]]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click toggle-visibility}
+ (if hidden?
+ i/hide-refactor
+ i/shown-refactor)]
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove-shadow}
+ i/remove-refactor]]]
+ (when open-shadow
+ [:& advanced-options {:class (stl/css :shadow-advanced-options)
+ :visible? open-shadow
:on-close on-toggle-open-shadow}
- [:div.color-data
- [:div.element-set-actions-button
- {:on-click on-toggle-open-shadow}
- i/actions]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :default-value shadow-style
- :on-change on-type-change}
- [:option {:value ":drop-shadow"
- :selected (when (= shadow-style ":drop-shadow") "selected")}
- (tr "workspace.options.shadow-options.drop-shadow")]
- [:option {:value ":inner-shadow"
- :selected (when (= shadow-style ":inner-shadow") "selected")}
- (tr "workspace.options.shadow-options.inner-shadow")]]]
- [:div.row-grid-2
- [:div.input-element {:title (tr "workspace.options.shadow-options.offsetx")}
- [:> numeric-input* {:ref adv-offset-x-ref
+ [:div {:class (stl/css :first-row)}
+ [:div {:class (stl/css :offset-x-input)
+ :title (tr "workspace.options.shadow-options.offsetx")}
+ [:span {:class (stl/css :input-label)}
+ "X"]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :ref adv-offset-x-ref
:no-validate true
:placeholder "--"
:on-change (update-attr index :offset-x basic-offset-x-ref)
:on-blur on-blur
- :value (:offset-x value)}]
- [:span.after (tr "workspace.options.shadow-options.offsetx")]]
+ :value (:offset-x value)}]]
- [:div.input-element {:title (tr "workspace.options.shadow-options.offsety")}
- [:> numeric-input* {:ref adv-offset-y-ref
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :offset-y basic-offset-y-ref)
- :on-blur on-blur
- :value (:offset-y value)}]
- [:span.after (tr "workspace.options.shadow-options.offsety")]]]
-
- [:div.row-grid-2
- [:div.input-element {:title (tr "workspace.options.shadow-options.blur")}
+ [:div {:class (stl/css :blur-input)
+ :title (tr "workspace.options.shadow-options.blur")}
+ [:span {:class (stl/css :input-label)}
+ (tr "workspace.options.shadow-options.blur")]
[:> numeric-input* {:ref adv-blur-ref
+ :className (stl/css :numeric-input)
:no-validate true
:placeholder "--"
:on-change (update-attr index :blur basic-blur-ref)
:on-blur on-blur
:min 0
- :value (:blur value)}]
- [:span.after (tr "workspace.options.shadow-options.blur")]]
+ :value (:blur value)}]]
- [:div.input-element {:title (tr "workspace.options.shadow-options.spread")}
+ [:div {:class (stl/css :spread-input)
+ :title (tr "workspace.options.shadow-options.spread")}
+ [:span {:class (stl/css :input-label)}
+ (tr "workspace.options.shadow-options.spread")]
[:> numeric-input* {:ref adv-spread-ref
+ :className (stl/css :numeric-input)
:no-validate true
:placeholder "--"
:on-change (update-attr index :spread)
:on-blur on-blur
- :value (:spread value)}]
- [:span.after (tr "workspace.options.shadow-options.spread")]]]
+ :value (:spread value)}]]]
- [:div.color-row-wrap
+ [:div {:class (stl/css :second-row)}
+ [:div {:class (stl/css :offset-y-input)
+ :title (tr "workspace.options.shadow-options.offsety")}
+ [:span {:class (stl/css :input-label)}
+ "Y"]
+ [:> numeric-input* {:ref adv-offset-y-ref
+ :className (stl/css :numeric-input)
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :offset-y basic-offset-y-ref)
+ :on-blur on-blur
+ :value (:offset-y value)}]]
[:& color-row {:color (if (string? (:color value))
- ;; Support for old format colors
+ ;; Support for old format colors
{:color (:color value) :opacity (:opacity value)}
(:color value))
:title (tr "workspace.options.shadow-options.color")
@@ -344,13 +242,12 @@
:on-change update-color
:on-detach detach-color
:on-open manage-on-open
- :on-close manage-on-close}]]]])]))
+ :on-close manage-on-close}]]])]]))
(mf/defc shadow-menu
{::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- ids (unchecked-get props "ids")
+ (let [ids (unchecked-get props "ids")
type (unchecked-get props "type")
values (unchecked-get props "values")
@@ -389,70 +286,35 @@
(mf/deps ids)
#(st/emit! (dc/add-shadow ids (create-shadow))))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-shadows?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title (case type
- :multiple (tr "workspace.options.shadow-options.title.multiple")
- :group (tr "workspace.options.shadow-options.title.group")
- (tr "workspace.options.shadow-options.title"))
- :class (stl/css-case :title-spacing-shadow (not has-shadows?))}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-shadows?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (case type
+ :multiple (tr "workspace.options.shadow-options.title.multiple")
+ :group (tr "workspace.options.shadow-options.title.group")
+ (tr "workspace.options.shadow-options.title"))
+ :class (stl/css-case :title-spacing-shadow (not has-shadows?))}
- (when-not (= :multiple shadows)
- [:button {:class (stl/css :add-shadow)
- :on-click on-add-shadow} i/add-refactor])]]
-
- (when open?
- (cond
- (= :multiple shadows)
- [:div {:class (stl/css :element-set-content)}
- [:div {:class (stl/css :multiple-shadows)}
- [:div {:class (stl/css :label)} (tr "settings.multiple")]
- [:div {:class (stl/css :actions)}
- [:button {:class (stl/css :action-btn)
- :on-click on-remove-all}
- i/remove-refactor]]]]
-
- (seq shadows)
- [:& h/sortable-container {}
- [:div {:class (stl/css :element-set-content)}
- (for [[index value] (d/enumerate shadows)]
- [:& shadow-entry
- {:key (dm/str "shadow-" index)
- :ids ids
- :value value
- :on-reorder handle-reorder
- :disable-drag? disable-drag?
- :on-blur on-blur
- :index index
- :open-state-ref open-state-ref}])]]))]
-
- [:div.element-set.shadow-options
- [:div.element-set-title
- [:span
- (case type
- :multiple (tr "workspace.options.shadow-options.title.multiple")
- :group (tr "workspace.options.shadow-options.title.group")
- (tr "workspace.options.shadow-options.title"))]
-
- (when-not (= :multiple shadows)
- [:div.add-page {:on-click on-add-shadow} i/close])]
+ (when-not (= :multiple shadows)
+ [:button {:class (stl/css :add-shadow)
+ :on-click on-add-shadow} i/add-refactor])]]
+ (when open?
(cond
(= :multiple shadows)
- [:div.element-set-content
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click on-remove-all}
- i/minus]]]]
+ [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :multiple-shadows)}
+ [:div {:class (stl/css :label)} (tr "settings.multiple")]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove-all}
+ i/remove-refactor]]]]
(seq shadows)
[:& h/sortable-container {}
- [:div.element-set-content
+ [:div {:class (stl/css :element-set-content)}
(for [[index value] (d/enumerate shadows)]
[:& shadow-entry
{:key (dm/str "shadow-" index)
@@ -462,4 +324,4 @@
:disable-drag? disable-drag?
:on-blur on-blur
:index index
- :open-state-ref open-state-ref}])]])])))
+ :open-state-ref open-state-ref}])]]))]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss
index e5c27782a3..a9ef8ebd20 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss
@@ -8,129 +8,127 @@
.element-set {
margin: 0;
- .element-title {
- .title-spacing-shadow {
- margin: 0;
- padding-left: $s-2;
+}
+
+.title-spacing-shadow {
+ margin: 0;
+ padding-left: $s-2;
+}
+.add-shadow {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.element-set-content {
+ margin-top: $s-4;
+ @include flexColumn;
+}
+
+.multiple-shadows {
+ @include flexRow;
+}
+
+.label {
+ @extend .mixed-bar;
+}
+
+.actions {
+ @include flexRow;
+}
+
+.action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.shadow-element {
+ @include flexColumn;
+}
+
+.basic-options {
+ @include flexRow;
+}
+
+.shadow-info {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ width: $s-188;
+ .more-options {
+ @extend .button-secondary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8 0 0 $br-8;
+ svg {
+ @extend .button-icon;
}
- .add-shadow {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
+ &.selected {
+ background-color: var(--button-radio-background-color-active);
svg {
- @extend .button-icon;
+ stroke: var(--button-radio-foreground-color-active);
}
}
}
- .element-set-content {
- margin-top: $s-4;
- @include flexColumn;
- .multiple-shadows {
- @include flexRow;
- .label {
- @extend .mixed-bar;
- }
- .actions {
- @include flexRow;
- .action-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
+ .type-select {
+ padding: 0;
+ border-radius: 0 $br-8 $br-8 0;
+ flex-grow: 1;
+ .shadow-type-select {
+ flex-grow: 1;
+ border-radius: 0 $br-8 $br-8 0;
}
- .shadow-element {
- @include flexColumn;
- .basic-options {
- @include flexRow;
- .shadow-info {
- display: flex;
- align-items: center;
- gap: $s-1;
- width: $s-188;
- .more-options {
- @extend .button-secondary;
- height: $s-32;
- width: $s-28;
- border-radius: $br-8 0 0 $br-8;
- svg {
- @extend .button-icon;
- }
- &.selected {
- background-color: var(--button-radio-background-color-active);
- svg {
- stroke: var(--button-radio-foreground-color-active);
- }
- }
- }
- .type-select {
- padding: 0;
- border-radius: 0 $br-8 $br-8 0;
- flex-grow: 1;
- .shadow-type-select {
- flex-grow: 1;
- border-radius: 0 $br-8 $br-8 0;
- }
- }
+ }
- &.hidden {
- .more-options {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- .type-select {
- @include hiddenElement;
- .shadow-type-select {
- @include hiddenElement;
- border: $s-1 solid var(--input-border-color-disabled);
- }
- }
- }
- }
- .actions {
- @include flexRow;
- .action-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- }
- .shadow-advanced-options {
- @include flexColumn;
- .first-row,
- .second-row {
- @include flexRow;
- .offset-x-input,
- .blur-input,
- .spread-input,
- .offset-y-input {
- @extend .input-element;
- width: $s-60;
- min-width: $s-60;
- align-items: baseline;
- input {
- width: $s-32;
- }
- }
- .blur-input,
- .spread-input {
- width: $s-92;
- .input-label {
- width: $s-44;
- }
- }
- .spread-input {
- gap: $s-8;
- }
- }
+ &.hidden {
+ .more-options {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
+ }
+ .type-select {
+ @include hiddenElement;
+ .shadow-type-select {
+ @include hiddenElement;
+ border: $s-1 solid var(--input-border-color-disabled);
}
}
}
}
+
+.shadow-advanced-options {
+ @include flexColumn;
+}
+
+.first-row,
+.second-row {
+ @include flexRow;
+ .offset-x-input,
+ .blur-input,
+ .spread-input,
+ .offset-y-input {
+ @extend .input-element;
+ width: $s-60;
+ min-width: $s-60;
+ align-items: baseline;
+ input {
+ width: $s-32;
+ }
+ }
+ .blur-input,
+ .spread-input {
+ width: $s-92;
+ .input-label {
+ width: $s-44;
+ }
+ }
+ .spread-input {
+ gap: $s-8;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
index 90d4d9ac33..093434da9b 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
@@ -13,7 +13,6 @@
[app.main.data.workspace.colors :as dc]
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.stroke-row :refer [stroke-row]]
@@ -38,8 +37,7 @@
(mf/defc stroke-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps"]))]}
[{:keys [ids type values show-caps disable-stroke-style] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- label (case type
+ (let [label (case type
:multiple (tr "workspace.options.selection-stroke")
:group (tr "workspace.options.group-stroke")
(tr "workspace.options.stroke"))
@@ -53,27 +51,15 @@
strokes (:strokes values)
has-strokes? (or (= :multiple strokes) (some? (seq strokes)))
- handle-change-stroke-color
- (mf/use-fn
- (mf/deps ids)
- (fn [index]
- (fn [color]
- (st/emit! (dc/change-stroke ids color index)))))
- on-color-change-refactor
+ on-color-change
(mf/use-fn
(mf/deps ids)
(fn [index color]
(st/emit! (dc/change-stroke ids color index))))
- handle-remove
- (mf/use-fn
- (mf/deps ids)
- (fn [index]
- (fn []
- (st/emit! (dc/remove-stroke ids index)))))
- on-remove-refactor
+ on-remove
(mf/use-fn
(mf/deps ids)
(fn [index]
@@ -85,16 +71,7 @@
(fn [_]
(st/emit! (dc/remove-all-strokes ids))))
- handle-detach
- (mf/use-fn
- (mf/deps ids)
- (fn [index]
- (fn [color]
- (let [color (-> color
- (assoc :id nil :file-id nil))]
- (st/emit! (dc/change-stroke ids color index))))))
-
- on-color-detach-refactor
+ on-color-detach
(mf/use-fn
(mf/deps ids)
(fn [index color]
@@ -110,42 +87,19 @@
(st/emit! (dc/reorder-strokes ids index new-index)))))
on-stroke-style-change
- (fn [index]
- (fn [event]
- (let [value (-> (dom/get-target event)
- (dom/get-value)
- (d/read-string))]
- (st/emit! (dc/change-stroke ids {:stroke-style value} index)))))
-
- on-stroke-style-change-refactor
(mf/use-fn
(mf/deps ids)
(fn [index value]
(st/emit! (dc/change-stroke ids {:stroke-style value} index))))
-
on-stroke-alignment-change
- (fn [index]
- (fn [event]
- (let [value (-> (dom/get-target event)
- (dom/get-value)
- (d/read-string))]
- (when-not (str/empty? value)
- (st/emit! (dc/change-stroke ids {:stroke-alignment value} index))))))
-
- on-stroke-alignment-change-refactor
(fn [index value]
(when-not (str/empty? value)
(st/emit! (dc/change-stroke ids {:stroke-alignment value} index))))
- on-stroke-width-change
- (fn [index]
- (fn [value]
- (when-not (str/empty? value)
- (st/emit! (dc/change-stroke ids {:stroke-width value} index)))))
- on-stroke-width-change-refactor
+ on-stroke-width-change
(fn [index value]
(when-not (str/empty? value)
(st/emit! (dc/change-stroke ids {:stroke-width value} index))))
@@ -207,70 +161,27 @@
on-blur (fn [_]
(reset! disable-drag false))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? has-strokes?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title label
- :class (stl/css-case :title-spacing-stroke (not has-strokes?))}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? has-strokes?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title label
+ :class (stl/css-case :title-spacing-stroke (not has-strokes?))}
- [:button {:class (stl/css :add-stroke)
- :on-click on-add-stroke} i/add-refactor]]]
- (when open?
- [:div {:class (stl/css-case :element-content true
- :empty-content (not has-strokes?))}
- (cond
- (= :multiple strokes)
- [:div {:class (stl/css :element-set-options-group)}
- [:div {:class (stl/css :group-label)}
- (tr "settings.multiple")]
- [:button {:on-click handle-remove-all
- :class (stl/css :remove-btn)}
- i/remove-refactor]]
- (seq strokes)
- [:& h/sortable-container {}
- (for [[index value] (d/enumerate (:strokes values []))]
- [:& stroke-row {:key (dm/str "stroke-" index)
- :stroke value
- :title (tr "workspace.options.stroke-color")
- :index index
- :show-caps show-caps
- :on-color-change on-color-change-refactor
- :on-color-detach on-color-detach-refactor
- :on-stroke-width-change on-stroke-width-change-refactor
- :on-stroke-style-change on-stroke-style-change-refactor
- :on-stroke-alignment-change on-stroke-alignment-change-refactor
- :open-caps-select open-caps-select
- :close-caps-select close-caps-select
- :on-stroke-cap-start-change on-stroke-cap-start-change
- :on-stroke-cap-end-change on-stroke-cap-end-change
- :on-stroke-cap-switch on-stroke-cap-switch
- :on-remove on-remove-refactor
- :on-reorder (handle-reorder index)
- :disable-drag disable-drag
- :on-focus on-focus
- :select-on-focus (not @disable-drag)
- :on-blur on-blur
- :disable-stroke-style disable-stroke-style}])])])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span label]
- [:div.add-page {:on-click on-add-stroke} i/close]]
-
- [:div.element-set-content
+ [:button {:class (stl/css :add-stroke)
+ :on-click on-add-stroke} i/add-refactor]]]
+ (when open?
+ [:div {:class (stl/css-case :element-content true
+ :empty-content (not has-strokes?))}
(cond
(= :multiple strokes)
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click handle-remove-all}
- i/minus]]]
-
-
+ [:div {:class (stl/css :element-set-options-group)}
+ [:div {:class (stl/css :group-label)}
+ (tr "settings.multiple")]
+ [:button {:on-click handle-remove-all
+ :class (stl/css :remove-btn)}
+ i/remove-refactor]]
(seq strokes)
[:& h/sortable-container {}
(for [[index value] (d/enumerate (:strokes values []))]
@@ -279,8 +190,8 @@
:title (tr "workspace.options.stroke-color")
:index index
:show-caps show-caps
- :on-color-change handle-change-stroke-color
- :on-color-detach handle-detach
+ :on-color-change on-color-change
+ :on-color-detach on-color-detach
:on-stroke-width-change on-stroke-width-change
:on-stroke-style-change on-stroke-style-change
:on-stroke-alignment-change on-stroke-alignment-change
@@ -289,10 +200,10 @@
:on-stroke-cap-start-change on-stroke-cap-start-change
:on-stroke-cap-end-change on-stroke-cap-end-change
:on-stroke-cap-switch on-stroke-cap-switch
- :on-remove handle-remove
+ :on-remove on-remove
:on-reorder (handle-reorder index)
:disable-drag disable-drag
:on-focus on-focus
:select-on-focus (not @disable-drag)
:on-blur on-blur
- :disable-stroke-style disable-stroke-style}])])]])))
+ :disable-stroke-style disable-stroke-style}])])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss
index 252334692e..53f6af64e0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss
@@ -8,43 +8,48 @@
.element-set {
margin: 0;
- .element-title {
- margin: 0;
- .title-spacing-stroke {
- padding-left: $s-2;
- margin: 0;
- }
- .add-stroke {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
+}
- .element-content {
- display: flex;
- flex-direction: column;
- gap: $s-12;
- margin: $s-4 0 $s-8 0;
- .element-set-options-group {
- @include flexRow;
- .group-label {
- @extend .mixed-bar;
- }
- .remove-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- &.empty-content {
- margin: 0;
- }
+.element-title {
+ margin: 0;
+}
+
+.title-spacing-stroke {
+ padding-left: $s-2;
+ margin: 0;
+}
+.add-stroke {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-12;
+ margin: $s-4 0 $s-8 0;
+ &.empty-content {
+ margin: 0;
+ }
+}
+
+.element-set-options-group {
+ @include flexRow;
+}
+
+.group-label {
+ @extend .mixed-bar;
+}
+
+.remove-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs
index 792b83f943..2092e55101 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs
@@ -11,16 +11,13 @@
[app.main.data.workspace.changes :as dch]
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[rumext.v2 :as mf]))
(mf/defc attribute-value [{:keys [attr value on-change on-delete] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- handle-change
+ (let [handle-change
(mf/use-fn
(mf/deps attr on-change)
(fn [event]
@@ -33,56 +30,31 @@
(on-delete attr)))
label (->> attr last d/name)]
- (if new-css-system
- [:*
- (if (string? value)
- [:div {:class (stl/css :attr-content)}
- [:span {:class (stl/css :attr-name)} label]
- [:div {:class (stl/css :attr-input)}
- [:input {:value value
- :class "input-text"
- :on-change handle-change}]]
- [:div {:class (stl/css :attr-actions)}
- [:button {:class (stl/css :attr-action-btn)
- :on-click handle-delete}
- i/remove-refactor]]]
- [:div {:class (stl/css :attr-nested-content)}
- [:div {:class (stl/css :attr-title)}
- (str (d/name (last attr)))]
- (for [[key value] value]
- [:div {:class (stl/css :attr-row) :key key}
- [:& attribute-value {:key key
- :attr (conj attr key)
- :value value
- :on-change on-change
- :on-delete on-delete}]])])]
- [:div.element-set-content
- (if (string? value)
- [:div.row-flex.row-flex-removable
- [:& input-row {:label label
- :type :text
- :class "large"
- :value (str value)
- :on-change handle-change}]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click handle-delete}
- i/minus]]]
-
- [:*
- [:div.element-set-title
- {:style {:border-bottom "1px solid #444" :margin-bottom "0.5rem"}}
- [:span (str (d/name (last attr)))]]
-
- (for [[key value] value]
- [:& attribute-value {:key key
- :attr (conj attr key)
- :value value
- :on-change on-change
- :on-delete on-delete}])])])))
+ [:*
+ (if (string? value)
+ [:div {:class (stl/css :attr-content)}
+ [:span {:class (stl/css :attr-name)} label]
+ [:div {:class (stl/css :attr-input)}
+ [:input {:value value
+ :class "input-text"
+ :on-change handle-change}]]
+ [:div {:class (stl/css :attr-actions)}
+ [:button {:class (stl/css :attr-action-btn)
+ :on-click handle-delete}
+ i/remove-refactor]]]
+ [:div {:class (stl/css :attr-nested-content)}
+ [:div {:class (stl/css :attr-title)}
+ (str (d/name (last attr)))]
+ (for [[key value] value]
+ [:div {:class (stl/css :attr-row) :key key}
+ [:& attribute-value {:key key
+ :attr (conj attr key)
+ :value value
+ :on-change on-change
+ :on-delete on-delete}]])])]))
(mf/defc svg-attrs-menu [{:keys [ids values]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- state* (mf/use-state true)
+ (let [state* (mf/use-state true)
open? (deref state*)
attrs (:svg-attrs values)
has-attributes? (or (= :multiple attrs) (some? (seq attrs)))
@@ -112,30 +84,18 @@
(st/emit! (dch/update-shapes ids update-fn)))))]
(when-not (empty? attrs)
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-set-title)}
- [:& title-bar {:collapsable? has-attributes?
- :collapsed? (not open?)
- :on-collapsed toggle-content
- :title (tr "workspace.sidebar.options.svg-attrs.title")
- :class (stl/css-case :title-spacing-svg-attrs (not has-attributes?))}]]
- (when open?
- [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-set-title)}
+ [:& title-bar {:collapsable? has-attributes?
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.sidebar.options.svg-attrs.title")
+ :class (stl/css-case :title-spacing-svg-attrs (not has-attributes?))}]]
+ (when open?
+ [:div {:class (stl/css :element-set-content)}
(for [[attr-key attr-value] attrs]
[:& attribute-value {:key attr-key
:attr [attr-key]
:value attr-value
:on-change handle-change
- :on-delete handle-delete}])])]
-
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.sidebar.options.svg-attrs.title")]]
-
- (for [[attr-key attr-value] attrs]
- [:& attribute-value {:key attr-key
- :attr [attr-key]
- :value attr-value
- :on-change handle-change
- :on-delete handle-delete}])]))))
+ :on-delete handle-delete}])])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss
index 5926c782b8..536f589c99 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss
@@ -8,41 +8,49 @@
.element-set {
margin: 0;
- .title-spacing-svg-attrs {
- padding-left: $s-2;
- margin: 0;
- }
- .element-set-content {
- @include flexColumn;
- margin: $s-4 0 0 0;
- .attr-content {
- display: flex;
- gap: $s-4;
- .attr-name {
- @include titleTipography;
- @include twoLineTextEllipsis;
- width: $s-88;
- margin: auto $s-4;
- margin-right: 0;
- display: inline-block;
- }
- .attr-input {
- @extend .input-element;
- width: $s-124;
- }
- .attr-actions {
- display: flex;
- gap: $s-4;
- .attr-action-btn {
- @extend .button-tertiary;
- width: $s-28;
- height: $s-32;
- svg {
- @extend .button-icon;
- }
- }
- }
- }
+}
+
+.title-spacing-svg-attrs {
+ padding-left: $s-2;
+ margin: 0;
+}
+
+.element-set-content {
+ @include flexColumn;
+ margin: $s-4 0 0 0;
+}
+
+.attr-content {
+ display: flex;
+ gap: $s-4;
+}
+
+.attr-name {
+ @include titleTipography;
+ @include twoLineTextEllipsis;
+ width: $s-88;
+ margin: auto $s-4;
+ margin-right: 0;
+ display: inline-block;
+ color: var(--title-foreground-color);
+}
+
+.attr-input {
+ @extend .input-element;
+ width: $s-124;
+}
+
+.attr-actions {
+ display: flex;
+ gap: $s-4;
+}
+
+.attr-action-btn {
+ @extend .button-tertiary;
+ width: $s-28;
+ height: $s-32;
+ svg {
+ @extend .button-icon;
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs
index 8e393ae2de..913630f049 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs
@@ -30,181 +30,101 @@
(mf/defc text-align-options
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [text-align]} values
- new-css-system (mf/use-ctx ctx/new-css-system)
-
handle-change
(mf/use-fn
+ (mf/deps on-blur)
(fn [value]
- (let [new-align (if new-css-system
- value
- (-> (dom/get-current-target value)
- (dom/get-data "value")))]
- (on-change {:text-align new-align})
- (when (some? on-blur) (on-blur)))))]
+ (on-change {:text-align value})
+ (when (some? on-blur) (on-blur))))]
;; --- Align
- (if new-css-system
- [:div {:class (stl/css :align-options)}
- [:& radio-buttons {:selected text-align
- :on-change handle-change
- :name "align-text-options"}
- [:& radio-button {:value "left"
- :id "text-align-left"
- :title (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
- :icon i/text-align-left-refactor}]
- [:& radio-button {:value "center"
- :id "text-align-center"
- :title (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
- :icon i/text-align-center-refactor}]
- [:& radio-button {:value "right"
- :id "text-align-right"
- :title (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
- :icon i/text-align-right-refactor}]
- [:& radio-button {:value "justify"
- :id "text-align-justify"
- :title (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
- :icon i/text-justify-refactor}]]]
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
- :class (dom/classnames :current (= "left" text-align))
- :data-value "left"
- :on-click handle-change}
- i/text-align-left]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
- :class (dom/classnames :current (= "center" text-align))
- :data-value "center"
- :on-click handle-change}
- i/text-align-center]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
- :class (dom/classnames :current (= "right" text-align))
- :data-value "right"
- :on-click handle-change}
- i/text-align-right]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
- :class (dom/classnames :current (= "justify" text-align))
- :data-value "justify"
- :on-click handle-change}
- i/text-align-justify]])))
+ [:div {:class (stl/css :align-options)}
+ [:& radio-buttons {:selected text-align
+ :on-change handle-change
+ :name "align-text-options"}
+ [:& radio-button {:value "left"
+ :id "text-align-left"
+ :title (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
+ :icon i/text-align-left-refactor}]
+ [:& radio-button {:value "center"
+ :id "text-align-center"
+ :title (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
+ :icon i/text-align-center-refactor}]
+ [:& radio-button {:value "right"
+ :id "text-align-right"
+ :title (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
+ :icon i/text-align-right-refactor}]
+ [:& radio-button {:value "justify"
+ :id "text-align-justify"
+ :title (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
+ :icon i/text-justify-refactor}]]]))
(mf/defc text-direction-options
[{:keys [values on-change on-blur] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- direction (:text-direction values)
+ (let [direction (:text-direction values)
handle-change
(mf/use-fn
(mf/deps direction)
(fn [value]
- (let [val (if new-css-system
- value
- (-> (dom/get-current-target value)
- (dom/get-data "value")))
- dir (if (= val direction)
+ (let [dir (if (= value direction)
"none"
- val)]
+ value)]
(on-change {:text-direction dir})
(when (some? on-blur) (on-blur)))))]
- (if new-css-system
- [:div {:class (stl/css :text-direction-options)}
- [:& radio-buttons {:selected direction
- :on-change handle-change
- :name "text-direction-options"}
- [:& radio-button {:value "ltr"
- :type "checkbox"
- :id "ltr-text-direction"
- :title (tr "workspace.options.text-options.direction-ltr")
- :icon i/text-ltr-refactor}]
- [:& radio-button {:value "rtl"
- :type "checkbox"
- :id "rtl-text-direction"
- :title (tr "workspace.options.text-options.direction-rtl")
- :icon i/text-rtl-refactor}]]]
- ;; --- Align
- [:div.align-icons
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.direction-ltr")
- :class (dom/classnames :current (= "ltr" direction))
- :data-value "ltr"
- :on-click handle-change}
- i/text-direction-ltr]
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.direction-rtl")
- :class (dom/classnames :current (= "rtl" direction))
- :data-value "rtl"
- :on-click handle-change}
- i/text-direction-rtl]])))
+ [:div {:class (stl/css :text-direction-options)}
+ [:& radio-buttons {:selected direction
+ :on-change handle-change
+ :name "text-direction-options"}
+ [:& radio-button {:value "ltr"
+ :type "checkbox"
+ :id "ltr-text-direction"
+ :title (tr "workspace.options.text-options.direction-ltr")
+ :icon i/text-ltr-refactor}]
+ [:& radio-button {:value "rtl"
+ :type "checkbox"
+ :id "rtl-text-direction"
+ :title (tr "workspace.options.text-options.direction-rtl")
+ :icon i/text-rtl-refactor}]]]))
(mf/defc vertical-align
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [vertical-align]} values
- new-css-system (mf/use-ctx ctx/new-css-system)
vertical-align (or vertical-align "top")
handle-change
(mf/use-fn
+ (mf/deps on-blur)
(fn [value]
- (let [new-align (if new-css-system
- value
- (-> (dom/get-current-target value)
- (dom/get-data "value")))]
- (on-change {:vertical-align new-align})
- (when (some? on-blur) (on-blur)))))]
+ (on-change {:vertical-align value})
+ (when (some? on-blur) (on-blur))))]
- (if new-css-system
- [:div {:class (stl/css :vertical-align-options)}
- [:& radio-buttons {:selected vertical-align
- :on-change handle-change
- :name "vertical-align-text-options"}
- [:& radio-button {:value "top"
- :id "vertical-text-align-top"
- :title (tr "workspace.options.text-options.align-top")
- :icon i/text-top-refactor}]
- [:& radio-button {:value "center"
- :id "vertical-text-align-center"
- :title (tr "workspace.options.text-options.align-middle")
- :icon i/text-middle-refactor}]
- [:& radio-button {:value "bottom"
- :id "vertical-text-align-bottom"
- :title (tr "workspace.options.text-options.align-bottom")
- :icon i/text-bottom-refactor}]]]
- [:div.align-icons
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.align-top")
- :class (dom/classnames :current (= "top" vertical-align))
- :data-value "top"
- :on-click handle-change}
- i/align-top]
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.align-middle")
- :class (dom/classnames :current (= "center" vertical-align))
- :data-value "center"
- :on-click handle-change}
- i/align-middle]
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.align-bottom")
- :class (dom/classnames :current (= "bottom" vertical-align))
- :data-value "bottom"
- :on-click handle-change}
- i/align-bottom]])))
+ [:div {:class (stl/css :vertical-align-options)}
+ [:& radio-buttons {:selected vertical-align
+ :on-change handle-change
+ :name "vertical-align-text-options"}
+ [:& radio-button {:value "top"
+ :id "vertical-text-align-top"
+ :title (tr "workspace.options.text-options.align-top")
+ :icon i/text-top-refactor}]
+ [:& radio-button {:value "center"
+ :id "vertical-text-align-center"
+ :title (tr "workspace.options.text-options.align-middle")
+ :icon i/text-middle-refactor}]
+ [:& radio-button {:value "bottom"
+ :id "vertical-text-align-bottom"
+ :title (tr "workspace.options.text-options.align-bottom")
+ :icon i/text-bottom-refactor}]]]))
(mf/defc grow-options
[{:keys [ids values on-blur] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- grow-type (:grow-type values)
+ (let [grow-type (:grow-type values)
handle-change-grow
(mf/use-fn
- (mf/deps ids new-css-system)
+ (mf/deps ids on-blur)
(fn [value]
(let [uid (js/Symbol)
- grow-type (if new-css-system
- (keyword value)
- (-> (dom/get-current-target value)
- (dom/get-data "value")
- (keyword)))]
+ grow-type (keyword value)]
(st/emit!
(dwu/start-undo-transaction uid)
(dch/update-shapes ids #(assoc % :grow-type grow-type)))
@@ -212,105 +132,55 @@
(ts/schedule #(st/emit! (dwu/commit-undo-transaction uid))))
(when (some? on-blur) (on-blur))))]
- (if new-css-system
- [:div {:class (stl/css :grow-options)}
- [:& radio-buttons {:selected (d/name grow-type)
- :on-change handle-change-grow
- :name "grow-text-options"}
- [:& radio-button {:value "fixed"
- :id "text-fixed-grow"
- :title (tr "workspace.options.text-options.grow-fixed")
- :icon i/text-fixed-refactor}]
- [:& radio-button {:value "auto-width"
- :id "text-auto-width-grow"
- :title (tr "workspace.options.text-options.grow-auto-width")
- :icon i/text-auto-width-refactor}]
- [:& radio-button {:value "auto-height"
- :id "text-auto-height-grow"
- :title (tr "workspace.options.text-options.grow-auto-height")
- :icon i/text-auto-height-refactor}]]]
-
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.grow-fixed")
- :class (dom/classnames :current (= :fixed grow-type))
- :data-value "fixed"
- :on-click handle-change-grow}
- i/auto-fix]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.grow-auto-width")
- :data-value "auto-width"
- :class (dom/classnames :current (= :auto-width grow-type))
- :on-click handle-change-grow}
- i/auto-width]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.grow-auto-height")
- :class (dom/classnames :current (= :auto-height grow-type))
- :data-value "auto-height"
- :on-click handle-change-grow}
- i/auto-height]])))
+ [:div {:class (stl/css :grow-options)}
+ [:& radio-buttons {:selected (d/name grow-type)
+ :on-change handle-change-grow
+ :name "grow-text-options"}
+ [:& radio-button {:value "fixed"
+ :id "text-fixed-grow"
+ :title (tr "workspace.options.text-options.grow-fixed")
+ :icon i/text-fixed-refactor}]
+ [:& radio-button {:value "auto-width"
+ :id "text-auto-width-grow"
+ :title (tr "workspace.options.text-options.grow-auto-width")
+ :icon i/text-auto-width-refactor}]
+ [:& radio-button {:value "auto-height"
+ :id "text-auto-height-grow"
+ :title (tr "workspace.options.text-options.grow-auto-height")
+ :icon i/text-auto-height-refactor}]]]))
(mf/defc text-decoration-options
[{:keys [values on-change on-blur] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- text-decoration (or (:text-decoration values) "none")
+ (let [text-decoration (or (:text-decoration values) "none")
handle-change
(mf/use-fn
(mf/deps text-decoration)
(fn [value]
- (let [val (if new-css-system
- value
- (-> (dom/get-current-target value)
- (dom/get-data "value")))
- decoration (if (= val text-decoration)
+ (let [decoration (if (= value text-decoration)
"none"
- val)]
+ value)]
(on-change {:text-decoration decoration})
(when (some? on-blur) (on-blur)))))]
- (if new-css-system
- [:div {:class (stl/css :text-decoration-options)}
- [:& radio-buttons {:selected text-decoration
- :on-change handle-change
- :name "text-decoration-options"}
- [:& radio-button {:value "underline"
- :type "checkbox"
- :id "underline-text-decoration"
- :title (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
- :icon i/text-underlined-refactor}]
- [:& radio-button {:value "line-through"
- :type "checkbox"
- :id "line-through-text-decoration"
- :title (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
- :icon i/text-stroked-refactor}]]]
-
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.none")
- :class (dom/classnames :current (= "none" text-decoration))
- :data-value "none"
- :on-click handle-change}
- i/minus]
-
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
- :class (dom/classnames :current (= "underline" text-decoration))
- :data-value "underline"
- :on-click handle-change}
- i/underline]
-
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
- :class (dom/classnames :current (= "line-through" text-decoration))
- :data-value "line-through"
- :on-click handle-change}
- i/strikethrough]])))
+ [:div {:class (stl/css :text-decoration-options)}
+ [:& radio-buttons {:selected text-decoration
+ :on-change handle-change
+ :name "text-decoration-options"}
+ [:& radio-button {:value "underline"
+ :type "checkbox"
+ :id "underline-text-decoration"
+ :title (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
+ :icon i/text-underlined-refactor}]
+ [:& radio-button {:value "line-through"
+ :type "checkbox"
+ :id "line-through-text-decoration"
+ :title (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
+ :icon i/text-stroked-refactor}]]]))
(mf/defc text-menu
{::mf/wrap [mf/memo]}
[{:keys [ids type values] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- file-id (mf/use-ctx ctx/current-file-id)
+ (let [file-id (mf/use-ctx ctx/current-file-id)
typographies (mf/deref refs/workspace-file-typography)
shared-libs (mf/deref refs/workspace-libraries)
label (case type
@@ -411,87 +281,48 @@
(let [node (dom/get-element-by-class "public-DraftEditor-content")]
(dom/focus! node))))))}]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? true
- :collapsed? (not main-menu-open?)
- :on-collapsed toggle-main-menu
- :title label
- :class (stl/css :title-spacing-text)}
- (when (and (not typography) (not multiple?))
- [:button {:class (stl/css :add-typography)
- :on-click on-convert-to-typography}
- i/add-refactor])]]
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not main-menu-open?)
+ :on-collapsed toggle-main-menu
+ :title label
+ :class (stl/css :title-spacing-text)}
+ (when (and (not typography) (not multiple?))
+ [:button {:class (stl/css :add-typography)
+ :on-click on-convert-to-typography}
+ i/add-refactor])]]
- (when main-menu-open?
- [:div {:class (stl/css :element-content)}
- (cond
- typography
- [:& typography-entry {:typography typography
- :local? (= typography-file file-id)
- :file (get shared-libs typography-file)
- :on-detach handle-detach-typography
- :on-change handle-change-typography}]
+ (when main-menu-open?
+ [:div {:class (stl/css :element-content)}
+ (cond
+ typography
+ [:& typography-entry {:typography typography
+ :local? (= typography-file file-id)
+ :file (get shared-libs typography-file)
+ :on-detach handle-detach-typography
+ :on-change handle-change-typography}]
- (= typography-id :multiple)
- [:div {:class (stl/css :multiple-typography)}
- [:span {:class (stl/css :multiple-text)} (tr "workspace.libraries.text.multiple-typography")]
- [:div {:class (stl/css :multiple-typography-button)
- :on-click handle-detach-typography
- :title (tr "workspace.libraries.text.multiple-typography-tooltip")}
- i/detach-refactor]]
+ (= typography-id :multiple)
+ [:div {:class (stl/css :multiple-typography)}
+ [:span {:class (stl/css :multiple-text)} (tr "workspace.libraries.text.multiple-typography")]
+ [:div {:class (stl/css :multiple-typography-button)
+ :on-click handle-detach-typography
+ :title (tr "workspace.libraries.text.multiple-typography-tooltip")}
+ i/detach-refactor]]
- :else
- [:> text-options opts])
+ :else
+ [:> text-options opts])
- [:div {:class (stl/css :text-align-options)}
- [:> text-align-options opts]
- [:> grow-options opts]
- [:button {:class (stl/css :more-options)
- :on-click toggle-more-options}
- i/menu-refactor]]
-
- (when more-options-open?
- [:div {:class (stl/css :text-decoration-options)}
- [:> vertical-align opts]
- [:> text-decoration-options opts]
- [:> text-direction-options opts]])])]
-
-
- [:div.element-set
- [:div.element-set-title
- [:span label]
- (when (and (not typography) (not multiple?))
- [:div.add-page {:on-click on-convert-to-typography} i/close])]
-
- (cond
- typography
- [:& typography-entry {:typography typography
- :local? (= typography-file file-id)
- :file (get shared-libs typography-file)
- :on-detach handle-detach-typography
- :on-change handle-change-typography}]
-
- (= typography-id :multiple)
- [:div.multiple-typography
- [:div.multiple-typography-text (tr "workspace.libraries.text.multiple-typography")]
- [:div.multiple-typography-button {:on-click handle-detach-typography
- :title (tr "workspace.libraries.text.multiple-typography-tooltip")} i/unchain]]
-
- :else
- [:> text-options opts])
-
- [:div.element-set-content
-
- [:div.row-flex
+ [:div {:class (stl/css :text-align-options)}
[:> text-align-options opts]
- [:> vertical-align opts]]
-
- [:div.row-flex
- [:> text-decoration-options opts]
- [:> text-direction-options opts]]
-
- [:div.row-flex
[:> grow-options opts]
- [:div.align-icons]]]])))
+ [:button {:class (stl/css :more-options)
+ :on-click toggle-more-options}
+ i/menu-refactor]]
+
+ (when more-options-open?
+ [:div {:class (stl/css :text-decoration-options)}
+ [:> vertical-align opts]
+ [:> text-decoration-options opts]
+ [:> text-direction-options opts]])])]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss
index 2504fa5e78..2e0c982989 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss
@@ -8,58 +8,68 @@
.element-set {
margin: 0;
- .element-title {
- margin: 0;
- .add-typography {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- .element-content {
- @include flexColumn;
- margin-top: $s-4;
- .multiple-typography {
- @extend .mixed-bar;
- .multiple-text {
- @include titleTipography;
- flex-grow: 1;
- color: var(--input-foreground-color-active);
- }
- .multiple-typography-button {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- .text-align-options {
- display: flex;
- gap: $s-4;
- .align-options,
- .text-direction-options,
- .vertical-align-options,
- .grow-options,
- .text-decoration-options {
- height: $s-32;
- }
- .more-options {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
- }
- .text-decoration-options {
- display: flex;
- gap: $s-4;
- }
+}
+
+.element-title {
+ margin: 0;
+}
+
+.add-typography {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
}
}
+
+.element-content {
+ @include flexColumn;
+ margin-top: $s-4;
+}
+
+.multiple-typography {
+ @extend .mixed-bar;
+}
+
+.multiple-text {
+ @include titleTipography;
+ flex-grow: 1;
+ color: var(--input-foreground-color-active);
+}
+
+.multiple-typography-button {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.text-align-options {
+ display: flex;
+ gap: $s-4;
+}
+
+.align-options,
+.text-direction-options,
+.vertical-align-options,
+.grow-options,
+.text-decoration-options {
+ height: $s-32;
+}
+
+.more-options {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.text-decoration-options {
+ display: flex;
+ gap: $s-4;
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
index 122c32ea8a..c54d3a13d5 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
@@ -25,7 +25,6 @@
[app.main.ui.components.select :refer [select]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
- [app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
@@ -61,8 +60,7 @@
{::mf/wrap [mf/memo]}
[{:keys [font current? on-click style]}]
(let [item-ref (mf/use-ref)
- on-click (mf/use-fn (mf/deps font) #(on-click font))
- new-css-system (mf/use-ctx ctx/new-css-system)]
+ on-click (mf/use-fn (mf/deps font) #(on-click font))]
(mf/use-effect
(mf/deps current?)
@@ -72,22 +70,14 @@
(when-not (dom/is-in-viewport? element)
(dom/scroll-into-view! element))))))
- (if new-css-system
- [:div {:class (stl/css :font-wrapper)
- :style style
- :ref item-ref
- :on-click on-click}
- [:div {:class (stl/css-case :font-item true
- :selected current?)}
- [:span {:class (stl/css :label)} (:name font)]
- [:span {:class (stl/css :icon)} (when current? i/tick-refactor)]]]
-
- [:div.font-item {:ref item-ref
- :style style
- :class (when current? "selected")
- :on-click on-click}
- [:span.icon (when current? i/tick)]
- [:span.label (:name font)]])))
+ [:div {:class (stl/css :font-wrapper)
+ :style style
+ :ref item-ref
+ :on-click on-click}
+ [:div {:class (stl/css-case :font-item true
+ :selected current?)}
+ [:span {:class (stl/css :label)} (:name font)]
+ [:span {:class (stl/css :icon)} (when current? i/tick-refactor)]]]))
(declare row-renderer)
@@ -104,8 +94,7 @@
(mf/defc font-selector
[{:keys [on-select on-close current-font show-recent] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- selected (mf/use-state current-font)
+ (let [selected (mf/use-state current-font)
state (mf/use-state {:term "" :backends #{}})
flist (mf/use-ref)
@@ -143,12 +132,8 @@
on-filter-change
(mf/use-fn
- (mf/deps new-css-system)
(fn [event]
- (let [value (if new-css-system
- event
- (dom/get-target-val event))]
- (swap! state assoc :term value))))
+ (swap! state assoc :term event)))
on-select-and-close
(mf/use-fn
@@ -184,72 +169,35 @@
#(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})]
(.scrollToPosition ^js inst offset)))))
+ [:div {:class (stl/css :font-selector)}
+ [:div {:class (stl/css :font-selector-dropdown)}
+ [:div {:class (stl/css :header)}
+ [:& search-bar {:on-change on-filter-change
+ :value (:term @state)
+ :placeholder (tr "workspace.options.search-font")}]
+ (when (and recent-fonts show-recent)
+ [*
+ [:p {:class (stl/css :title)} (tr "workspace.options.recent-fonts")]
+ (for [[idx font] (d/enumerate recent-fonts)]
+ [:& font-item {:key (dm/str "font-" idx)
+ :font font
+ :style {}
+ :on-click on-select-and-close
+ :current? (= (:id font) (:id @selected))}])])]
- (if new-css-system
- [:div {:class (stl/css :font-selector)}
- [:div {:class (stl/css :font-selector-dropdown)}
- [:div {:class (stl/css :header)}
- [:& search-bar {:on-change on-filter-change
- :value (:term @state)
- :placeholder (tr "workspace.options.search-font")}]
- (when (and recent-fonts show-recent)
- [*
- [:p {:class (stl/css :title)} (tr "workspace.options.recent-fonts")]
- (for [[idx font] (d/enumerate recent-fonts)]
- [:& font-item {:key (dm/str "font-" idx)
- :font font
- :style {}
- :on-click on-select-and-close
- :current? (= (:id font) (:id @selected))}])])]
-
- [:div {:class (stl/css :fonts-list)}
- [:> rvt/AutoSizer {}
- (fn [props]
- (let [width (unchecked-get props "width")
- height (unchecked-get props "height")
- render #(row-renderer fonts @selected on-select-and-close %)]
- (mf/html
- [:> rvt/List #js {:height height
- :ref flist
- :width width
- :rowCount (count fonts)
- :rowHeight 36
- :rowRenderer render}])))]]]]
-
- [:div.font-selector
- [:div.font-selector-dropdown
- [:header
- [:input {:placeholder (tr "workspace.options.search-font")
- :value (:term @state)
- :ref input
- :spell-check false
- :on-change on-filter-change}]
- (when (and recent-fonts show-recent)
- [:*
- [:hr]
- [:p.title (tr "workspace.options.recent-fonts")]
- (for [[idx font] (d/enumerate recent-fonts)]
- [:& font-item {:key (dm/str "font-" idx)
- :font font
- :style {}
- :on-click on-select-and-close
- :current? (= (:id font) (:id @selected))}])])]
-
- [:hr]
-
- [:div.fonts-list
- [:> rvt/AutoSizer {}
- (fn [props]
- (let [width (unchecked-get props "width")
- height (unchecked-get props "height")
- render #(row-renderer fonts @selected on-select-and-close %)]
- (mf/html
- [:> rvt/List #js {:height height
- :ref flist
- :width width
- :rowCount (count fonts)
- :rowHeight 32
- :rowRenderer render}])))]]]])))
+ [:div {:class (stl/css :fonts-list)}
+ [:> rvt/AutoSizer {}
+ (fn [props]
+ (let [width (unchecked-get props "width")
+ height (unchecked-get props "height")
+ render #(row-renderer fonts @selected on-select-and-close %)]
+ (mf/html
+ [:> rvt/List #js {:height height
+ :ref flist
+ :width width
+ :rowCount (count fonts)
+ :rowHeight 36
+ :rowRenderer render}])))]]]]))
(defn row-renderer
[fonts selected on-select props]
@@ -272,7 +220,6 @@
font-id (or font-id (:font-id txt/default-text-attrs))
font-size (or font-size (:font-size txt/default-text-attrs))
font-variant-id (or font-variant-id (:font-variant-id txt/default-text-attrs))
- new-css-system (mf/use-ctx ctx/new-css-system)
fonts (mf/deref fonts/fontsdb)
font (get fonts font-id)
@@ -304,17 +251,14 @@
on-font-variant-change
(mf/use-fn
(mf/deps font on-change)
- (fn [event]
- (let [new-variant-id (if new-css-system
- event
- (dom/get-target-val event))
- variant (d/seek #(= new-variant-id (:id %)) (:variants font))]
+ (fn [new-variant-id]
+ (let [variant (d/seek #(= new-variant-id (:id %)) (:variants font))]
(on-change {:font-id (:id font)
:font-family (:family font)
:font-variant-id new-variant-id
:font-weight (:weight variant)
:font-style (:style variant)})
- (dom/blur! (dom/get-target event)))))
+ (dom/blur! (dom/get-target new-variant-id)))))
on-font-select
(mf/use-fn
@@ -335,114 +279,65 @@
(when (mf/ref-val last-font)
(st/emit! (fts/add-recent-font (mf/ref-val last-font))))))]
- (if new-css-system
- [:*
- (when @open-selector?
- [:& font-selector
- {:current-font font
- :on-close on-font-selector-close
- :on-select on-font-select
- :show-recent show-recent}])
+ [:*
+ (when @open-selector?
+ [:& font-selector
+ {:current-font font
+ :on-close on-font-selector-close
+ :on-select on-font-select
+ :show-recent show-recent}])
- [:div {:class (stl/css :font-option)
- :on-click #(reset! open-selector? true)}
- (cond
- (= :multiple font-id)
- "--"
+ [:div {:class (stl/css :font-option)
+ :on-click #(reset! open-selector? true)}
+ (cond
+ (= :multiple font-id)
+ "--"
- (some? font)
- [:*
- [:span {:class (stl/css :name)}
- (:name font)]
- [:span {:class (stl/css :icon)}
- i/arrow-refactor]]
+ (some? font)
+ [:*
+ [:span {:class (stl/css :name)}
+ (:name font)]
+ [:span {:class (stl/css :icon)}
+ i/arrow-refactor]]
- :else
- (tr "dashboard.fonts.deleted-placeholder"))]
+ :else
+ (tr "dashboard.fonts.deleted-placeholder"))]
- [:div {:class (stl/css :font-modifiers)}
- [:div {:class (stl/css :font-size-options)}
- (let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
- size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
- [:& editable-select
- {:value (attr->string font-size)
- :class (stl/css :font-size-select)
- :input-class (stl/css :numeric-input)
- :options size-options
- :type "number"
- :placeholder "--"
- :min 3
- :max 1000
- :on-change on-font-size-change
- :on-blur on-blur}])]
+ [:div {:class (stl/css :font-modifiers)}
+ [:div {:class (stl/css :font-size-options)}
+ (let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
+ size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
+ [:& editable-select
+ {:value (attr->string font-size)
+ :class (stl/css :font-size-select)
+ :input-class (stl/css :numeric-input)
+ :options size-options
+ :type "number"
+ :placeholder "--"
+ :min 3
+ :max 1000
+ :on-change on-font-size-change
+ :on-blur on-blur}])]
- [:div {:class (stl/css :font-variant-options)}
- (let [basic-variant-options (->> (:variants font)
- (map (fn [variant]
- {:value (:id variant)
- :key (pr-str variant)
- :label (:name variant)}) ))
- variant-options (if (= font-size :multiple)
- (conj basic-variant-options
- {:value :multiple
- :key :multiple-variants
- :label "--"} )
- basic-variant-options)]
- ;; TODO Add disabled mode
- [:& select
- {:class (stl/css :font-variant-select)
- :default-value (attr->string font-variant-id)
- :options variant-options
- :on-change on-font-variant-change
- :on-blur on-blur}])]]]
-
- [:*
- (when @open-selector?
- [:& font-selector
- {:current-font font
- :on-close on-font-selector-close
- :on-select on-font-select
- :show-recent show-recent}])
-
- [:div.row-flex
- [:div.input-select.font-option
- {:on-click #(reset! open-selector? true)}
- (cond
- (= :multiple font-id)
- "--"
-
- (some? font)
- (:name font)
-
- :else
- (tr "dashboard.fonts.deleted-placeholder"))]]
-
- [:div.row-flex
- (let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
- size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
- [:& editable-select
- {:value (attr->string font-size)
- :class "input-option size-option"
- :options size-options
- :type "number"
- :placeholder "--"
- :min 3
- :max 1000
- :on-change on-font-size-change
- :on-blur on-blur}])
-
- [:select.input-select.variant-option
- {:disabled (= font-id :multiple)
- :data-mousetrap-dont-stop true
- :value (attr->string font-variant-id)
- :on-change on-font-variant-change
- :on-blur on-blur}
- (when (or (= font-id :multiple) (= font-variant-id :multiple))
- [:option {:value ""} "--"])
- (for [variant (:variants font)]
- [:option {:value (:id variant)
- :key (pr-str variant)}
- (:name variant)])]]])))
+ [:div {:class (stl/css :font-variant-options)}
+ (let [basic-variant-options (->> (:variants font)
+ (map (fn [variant]
+ {:value (:id variant)
+ :key (pr-str variant)
+ :label (:name variant)})))
+ variant-options (if (= font-size :multiple)
+ (conj basic-variant-options
+ {:value :multiple
+ :key :multiple-variants
+ :label "--"})
+ basic-variant-options)]
+ ;; TODO Add disabled mode
+ [:& select
+ {:class (stl/css :font-variant-select)
+ :default-value (attr->string font-variant-id)
+ :options variant-options
+ :on-change on-font-variant-change
+ :on-blur on-blur}])]]]))
(mf/defc spacing-options
{::mf/wrap-props false}
@@ -452,152 +347,87 @@
line-height (or line-height "1.2")
letter-spacing (or letter-spacing "0")
- new-css-system (mf/use-ctx ctx/new-css-system)
line-height-nillable (if (= (str line-height) "1.2") false true)
handle-change
(fn [value attr]
(on-change {attr (str value)}))]
- (if new-css-system
- [:div {:class (stl/css :spacing-options)}
- [:div {:class (stl/css :line-height)}
- [:span {:class (stl/css :icon)
- :alt (tr "workspace.options.text-options.line-height")}
- i/text-lineheight-refactor]
- [:> numeric-input*
- {:min -200
- :max 200
- :step 0.1
- :default "1.2"
- :class (stl/css :line-height-input)
- :value (attr->string line-height)
- :placeholder (tr "settings.multiple")
- :nillable line-height-nillable
- :on-change #(handle-change % :line-height)
- :on-blur on-blur}]]
- [:div {:class (stl/css :letter-spacing)}
- [:span
- {:class (stl/css :icon)
- :alt (tr "workspace.options.text-options.letter-spacing")}
- i/text-letterspacing-refactor]
- [:> numeric-input*
- {:min -200
- :max 200
- :step 0.1
- :class (stl/css :letter-spacing-input)
- :value (attr->string letter-spacing)
- :placeholder (tr "settings.multiple")
- :on-change #(handle-change % :letter-spacing)
- :on-blur on-blur}]]]
+ [:div {:class (stl/css :spacing-options)}
+ [:div {:class (stl/css :line-height)}
+ [:span {:class (stl/css :icon)
+ :alt (tr "workspace.options.text-options.line-height")}
+ i/text-lineheight-refactor]
+ [:> numeric-input*
+ {:min -200
+ :max 200
+ :step 0.1
+ :default "1.2"
+ :class (stl/css :line-height-input)
+ :value (attr->string line-height)
+ :placeholder (tr "settings.multiple")
+ :nillable line-height-nillable
+ :on-change #(handle-change % :line-height)
+ :on-blur on-blur}]]
-
- [:div.spacing-options
- [:div.input-icon
- [:span.icon-before.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.line-height")}
- i/line-height]
- [:> numeric-input*
- {:min -200
- :max 200
- :step 0.1
- :default "1.2"
- :value (attr->string line-height)
- :placeholder (tr "settings.multiple")
- :nillable line-height-nillable
- :on-change #(handle-change % :line-height)
- :on-blur on-blur}]]
-
- [:div.input-icon
- [:span.icon-before.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.letter-spacing")}
- i/letter-spacing]
- [:> numeric-input*
- {:min -200
- :max 200
- :step 0.1
- :value (attr->string letter-spacing)
- :placeholder (tr "settings.multiple")
- :on-change #(handle-change % :letter-spacing)
- :on-blur on-blur}]]])))
+ [:div {:class (stl/css :letter-spacing)}
+ [:span
+ {:class (stl/css :icon)
+ :alt (tr "workspace.options.text-options.letter-spacing")}
+ i/text-letterspacing-refactor]
+ [:> numeric-input*
+ {:min -200
+ :max 200
+ :step 0.1
+ :class (stl/css :letter-spacing-input)
+ :value (attr->string letter-spacing)
+ :placeholder (tr "settings.multiple")
+ :on-change #(handle-change % :letter-spacing)
+ :on-blur on-blur}]]]))
(mf/defc text-transform-options
{::mf/wrap-props false}
[{:keys [values on-change on-blur]}]
(let [text-transform (or (:text-transform values) "none")
- new-css-system (mf/use-ctx ctx/new-css-system)
handle-change
(fn [type]
(if (= text-transform type)
(on-change {:text-transform "unset"})
(on-change {:text-transform type}))
(when (some? on-blur) (on-blur)))]
- (if new-css-system
- [:div {:class (stl/css :text-transform)}
- [:& radio-buttons {:selected text-transform
- :on-change handle-change
- :name "text-transform"}
- [:& radio-button {:icon i/text-uppercase-refactor
- :type "checkbox"
- :value "uppercase"
- :id "text-transform-uppercase"}]
- [:& radio-button {:icon i/text-lowercase-refactor
- :type "checkbox"
- :value "lowercase"
- :id "text-transform-lowercase"}]
- [:& radio-button {:icon i/text-mixed-refactor
- :type "checkbox"
- :value "capitalize"
- :id "text-transform-capitalize"}]]]
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.none")
- :class (dom/classnames :current (= "none" text-transform))
- :on-focus #(dom/prevent-default %)
- :on-click #(handle-change "none")}
- i/minus]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.uppercase")
- :class (dom/classnames :current (= "uppercase" text-transform))
- :on-click #(handle-change "uppercase")}
- i/uppercase]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.lowercase")
- :class (dom/classnames :current (= "lowercase" text-transform))
- :on-click #(handle-change "lowercase")}
- i/lowercase]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.titlecase")
- :class (dom/classnames :current (= "capitalize" text-transform))
- :on-click #(handle-change "capitalize")}
- i/titlecase]])))
+ [:div {:class (stl/css :text-transform)}
+ [:& radio-buttons {:selected text-transform
+ :on-change handle-change
+ :name "text-transform"}
+ [:& radio-button {:icon i/text-uppercase-refactor
+ :type "checkbox"
+ :value "uppercase"
+ :id "text-transform-uppercase"}]
+ [:& radio-button {:icon i/text-lowercase-refactor
+ :type "checkbox"
+ :value "lowercase"
+ :id "text-transform-lowercase"}]
+ [:& radio-button {:icon i/text-mixed-refactor
+ :type "checkbox"
+ :value "capitalize"
+ :id "text-transform-capitalize"}]]]))
(mf/defc text-options
{::mf/wrap-props false}
[{:keys [ids editor values on-change on-blur show-recent]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- opts #js {:editor editor
+ (let [opts #js {:editor editor
:ids ids
:values values
:on-change on-change
:on-blur on-blur
:show-recent show-recent}]
- (if new-css-system
- [:div {:class (stl/css :text-options)}
- [:> font-options opts]
- [:div {:class (stl/css :typography-variations)}
- [:> spacing-options opts]
- [:> text-transform-options opts]]]
-
- [:div.element-set-content
- [:> font-options opts]
- [:div.row-flex
- [:> spacing-options opts]]
- [:div.row-flex
- [:> text-transform-options opts]]])))
-
+ [:div {:class (stl/css :text-options)}
+ [:> font-options opts]
+ [:div {:class (stl/css :typography-variations)}
+ [:> spacing-options opts]
+ [:> text-transform-options opts]]]))
(mf/defc typography-advanced-options
{::mf/wrap [mf/memo]}
@@ -684,16 +514,11 @@
:on-click navigate-to-library}
(tr "workspace.assets.typography.go-to-edit")])])])))
-
(mf/defc typography-entry
{::mf/wrap-props false}
[{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? renaming? focus-name? external-open*]}]
- (let [hover-detach* (mf/use-state false)
- hover-detach? (deref hover-detach*)
-
- name-input-ref (mf/use-ref)
+ (let [name-input-ref (mf/use-ref)
read-only? (mf/use-ctx ctx/workspace-read-only?)
- new-css-system (mf/use-ctx ctx/new-css-system)
editable? (and local? (not read-only?))
open* (mf/use-state editing?)
@@ -710,12 +535,6 @@
(on-change {:name name})
(st/emit! #(update % :workspace-global dissoc :rename-typography))))))
- on-pointer-enter
- (mf/use-fn #(reset! hover-detach* true))
-
- on-pointer-leave
- (mf/use-fn #(reset! hover-detach* false))
-
on-open
(mf/use-fn #(reset! open* true))
@@ -755,147 +574,62 @@
(dom/focus! node)
(dom/select-text! node)))))
- (if new-css-system
- [:*
- [:div {:class (stl/css-case :typography-entry true
- :selected ^boolean selected?)
- :style {:display (when ^boolean open? "none")}}
- (if renaming?
- [:div {:class (stl/css :font-name-wrapper)}
- [:div
- {:class (stl/css :typography-sample-input)
- :style {:font-family (:font-family typography)
- :font-weight (:font-weight typography)
- :font-style (:font-style typography)}}
- (tr "workspace.assets.typography.sample")]
-
- [:input
- {:class (stl/css :adv-typography-name)
- :type "text"
- :ref name-input-ref
- :default-value (:name typography)
- :on-key-down on-key-down
- :on-blur on-name-blur}]]
- [:div
- {:class (stl/css-case :typography-selection-wrapper true
- :is-selectable ^boolean on-click)
- :on-click on-click
- :on-context-menu on-context-menu}
- [:div
- {:class (stl/css :typography-sample)
- :style {:font-family (:font-family typography)
- :font-weight (:font-weight typography)
- :font-style (:font-style typography)}}
- (tr "workspace.assets.typography.sample")]
-
- [:div {:class (stl/css :typography-name)
- :title (:name typography)} (:name typography)]
-
- (when-not name-only?
- [:div {:class (stl/css :typography-font)
- :title (:name font-data)}
- (:name font-data)])])
- [:div {:class (stl/css :element-set-actions)}
- (when ^boolean on-detach
- [:button {:class (stl/css :element-set-actions-button)
- :on-click on-detach}
- i/detach-refactor])
- [:button {:class (stl/css :menu-btn)
- :on-click on-open}
- i/menu-refactor]]]
-
- [:& typography-advanced-options
- {:visible? open?
- :on-close on-close
- :typography typography
- :editable? editable?
- :name-input-ref name-input-ref
- :on-change on-change
- :on-name-blur on-name-blur
- :on-key-down on-key-down
- :local? local?
- :navigate-to-library navigate-to-library}]]
-
-
- [:*
- [:div.element-set-options-group.typography-entry
- {:class (when ^boolean selected? "selected")
- :style {:display (when ^boolean open? "none")}}
- [:div.typography-selection-wrapper
- {:class (when ^boolean on-click "is-selectable")
- :on-click on-click
- :on-context-menu on-context-menu}
- [:div.typography-sample
- {:style {:font-family (:font-family typography)
+ [:*
+ [:div {:class (stl/css-case :typography-entry true
+ :selected ^boolean selected?)
+ :style {:display (when ^boolean open? "none")}}
+ (if renaming?
+ [:div {:class (stl/css :font-name-wrapper)}
+ [:div
+ {:class (stl/css :typography-sample-input)
+ :style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
- [:div.typography-name {:title (:name typography)} (:name typography)]]
- [:div.element-set-actions
- (when ^boolean on-detach
- [:div.element-set-actions-button
- {:on-pointer-enter on-pointer-enter
- :on-pointer-leave on-pointer-leave
- :on-click on-detach}
- (if ^boolean hover-detach? i/unchain i/chain)])
- [:div.element-set-actions-button
- {:on-click on-open}
- i/actions]]]
+ [:input
+ {:class (stl/css :adv-typography-name)
+ :type "text"
+ :ref name-input-ref
+ :default-value (:name typography)
+ :on-key-down on-key-down
+ :on-blur on-name-blur}]]
+ [:div
+ {:class (stl/css-case :typography-selection-wrapper true
+ :is-selectable ^boolean on-click)
+ :on-click on-click
+ :on-context-menu on-context-menu}
+ [:div
+ {:class (stl/css :typography-sample)
+ :style {:font-family (:font-family typography)
+ :font-weight (:font-weight typography)
+ :font-style (:font-style typography)}}
+ (tr "workspace.assets.typography.sample")]
- [:& advanced-options {:visible? open? :on-close on-close}
- (if ^boolean editable?
- [:*
- [:div.element-set-content
- [:div.row-flex
- [:input.element-name.adv-typography-name
- {:type "text"
- :ref name-input-ref
- :default-value (:name typography)
- :on-blur on-name-blur}]
+ [:div {:class (stl/css :typography-name)
+ :title (:name typography)} (:name typography)]
- [:div.element-set-actions-button
- {:on-click on-close}
- i/actions]]]
+ (when-not name-only?
+ [:div {:class (stl/css :typography-font)
+ :title (:name font-data)}
+ (:name font-data)])])
+ [:div {:class (stl/css :element-set-actions)}
+ (when ^boolean on-detach
+ [:button {:class (stl/css :element-set-actions-button)
+ :on-click on-detach}
+ i/detach-refactor])
+ [:button {:class (stl/css :menu-btn)
+ :on-click on-open}
+ i/menu-refactor]]]
- [:& text-options {:values typography
- :on-change on-change
- :show-recent false}]]
-
- [:div.element-set-content.typography-read-only-data
- [:div.row-flex.typography-name
- [:span {:title (:name typography)} (:name typography)]]
-
- [:div.row-flex
- [:span.label (tr "workspace.assets.typography.font-id")]
- [:span (:font-id typography)]]
-
- [:div.element-set-actions-button.actions-inside
- {:on-click on-close}
- i/actions]
-
- [:div.row-flex
- [:span.label (tr "workspace.assets.typography.font-variant-id")]
- [:span (:font-variant-id typography)]]
-
- [:div.row-flex
- [:span.label (tr "workspace.assets.typography.font-size")]
- [:span (:font-size typography)]]
-
- [:div.row-flex
- [:span.label (tr "workspace.assets.typography.line-height")]
- [:span (:line-height typography)]]
-
- [:div.row-flex
- [:span.label (tr "workspace.assets.typography.letter-spacing")]
- [:span (:letter-spacing typography)]]
-
- [:div.row-flex
- [:span.label (tr "workspace.assets.typography.text-transform")]
- [:span (:text-transform typography)]]
-
- (when-not local?
- [:div.row-flex
- [:a.go-to-lib-button
- {:on-click navigate-to-library}
- (tr "workspace.assets.typography.go-to-edit")]])])]])))
+ [:& typography-advanced-options
+ {:visible? open?
+ :on-close on-close
+ :typography typography
+ :editable? editable?
+ :name-input-ref name-input-ref
+ :on-change on-change
+ :on-name-blur on-name-blur
+ :on-key-down on-key-down
+ :local? local?
+ :navigate-to-library navigate-to-library}]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
index 305fc6e83e..6f7aab290d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
@@ -142,103 +142,104 @@
height: 100%;
width: 100%;
background-color: var(--assets-title-background-color);
- .typography-info-wrapper {
- @include flexColumn;
- margin-bottom: $s-12;
- .typography-name-wrapper {
- @extend .asset-element;
- display: grid;
- grid-template-columns: $s-24 auto 1fr $s-28;
- flex: 1;
+}
+
+.typography-info-wrapper {
+ @include flexColumn;
+ margin-bottom: $s-12;
+ .typography-name-wrapper {
+ @extend .asset-element;
+ display: grid;
+ grid-template-columns: $s-24 auto 1fr $s-28;
+ flex: 1;
+ height: $s-32;
+ width: 100%;
+ padding: 0 0 0 $s-12;
+ background-color: var(--assets-item-background-color-hover);
+ margin-bottom: $s-4;
+ .typography-sample {
+ @include flexCenter;
+ min-width: $s-24;
+ font-size: $fs-16;
height: $s-32;
- width: 100%;
- padding: 0 0 0 $s-12;
- background-color: var(--assets-item-background-color-hover);
- margin-bottom: $s-4;
- .typography-sample {
- @include flexCenter;
- min-width: $s-24;
- font-size: $fs-16;
- height: $s-32;
- padding: 0;
- color: var(--assets-item-name-foreground-color-hover);
+ padding: 0;
+ color: var(--assets-item-name-foreground-color-hover);
+ }
+ .typography-name {
+ @include titleTipography;
+ @include textEllipsis;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ margin-left: $s-6;
+ color: var(--assets-item-name-foreground-color-hover);
+ }
+ .typography-font {
+ @include titleTipography;
+ @include textEllipsis;
+ margin-left: $s-6;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ min-width: 0;
+ color: var(--assets-item-name-foreground-color);
+ }
+ .action-btn {
+ @extend .button-tertiary;
+ width: $s-28;
+ height: $s-32;
+ svg {
+ @extend .button-icon;
}
- .typography-name {
- @include titleTipography;
- @include textEllipsis;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- margin-left: $s-6;
- color: var(--assets-item-name-foreground-color-hover);
- }
- .typography-font {
- @include titleTipography;
- @include textEllipsis;
- margin-left: $s-6;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- min-width: 0;
- color: var(--assets-item-name-foreground-color);
- }
- .action-btn {
- @extend .button-tertiary;
- width: $s-28;
- height: $s-32;
- svg {
- @extend .button-icon;
- }
- &:active {
- background-color: transparent;
- }
+ &:active {
+ background-color: transparent;
}
}
+ }
- .info-row {
- display: grid;
- grid-template-columns: 50% 50%;
- height: $s-32;
- --calcualted-width: calc(var(--width) - $s-48);
- padding-left: $s-2;
- .info-label {
- @include titleTipography;
- @include textEllipsis;
- width: calc(var(--calcualted-width) / 2);
- padding-top: $s-8;
- color: var(--assets-item-name-foreground-color);
- }
- .info-content {
- @include titleTipography;
- @include textEllipsis;
- padding-top: $s-8;
- width: calc(var(--calcualted-width) / 2);
- color: var(--assets-item-name-foreground-color-hover);
+ .info-row {
+ display: grid;
+ grid-template-columns: 50% 50%;
+ height: $s-32;
+ --calcualted-width: calc(var(--width) - $s-48);
+ padding-left: $s-2;
+ .info-label {
+ @include titleTipography;
+ @include textEllipsis;
+ width: calc(var(--calcualted-width) / 2);
+ padding-top: $s-8;
+ color: var(--assets-item-name-foreground-color);
+ }
+ .info-content {
+ @include titleTipography;
+ @include textEllipsis;
+ padding-top: $s-8;
+ width: calc(var(--calcualted-width) / 2);
+ color: var(--assets-item-name-foreground-color-hover);
+ }
+ }
+
+ .link-btn {
+ @include tabTitleTipography;
+ @extend .button-secondary;
+ width: 100%;
+ height: $s-32;
+ border-radius: $br-8;
+ &:hover {
+ background-color: var(--button-secondary-background-color-hover);
+ color: var(--button-secondary-foreground-color-hover);
+ border: $s-1 solid var(--button-secondary-border-color-hover);
+ text-decoration: none;
+ svg {
+ stroke: var(--button-secondary-foreground-color-hover);
}
}
-
- .link-btn {
- @include tabTitleTipography;
- @extend .button-secondary;
- width: 100%;
- height: $s-32;
- border-radius: $br-8;
- &:hover {
- background-color: var(--button-secondary-background-color-hover);
- color: var(--button-secondary-foreground-color-hover);
- border: $s-1 solid var(--button-secondary-border-color-hover);
- text-decoration: none;
- svg {
- stroke: var(--button-secondary-foreground-color-hover);
- }
- }
- &:focus {
- background-color: var(--button-secondary-background-color-focus);
- color: var(--button-secondary-foreground-color-focus);
- border: $s-1 solid var(--button-secondary-border-color-focus);
- svg {
- stroke: var(--button-secondary-foreground-color-focus);
- }
+ &:focus {
+ background-color: var(--button-secondary-background-color-focus);
+ color: var(--button-secondary-foreground-color-focus);
+ border: $s-1 solid var(--button-secondary-border-color-focus);
+ svg {
+ stroke: var(--button-secondary-foreground-color-focus);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs
index dbdd285075..9a99b7dbfd 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs
@@ -14,7 +14,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -23,40 +22,24 @@
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- options (mf/deref refs/workspace-page-options)
+ (let [options (mf/deref refs/workspace-page-options)
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
- (if new-css-system
- [:div {:class (stl/css :element-set)}
- [:div {:class (stl/css :element-title)}
- [:& title-bar {:collapsable? false
- :title (tr "workspace.options.canvas-background")
- :class (stl/css :title-spacing-page)}]]
- [:div {:class (stl/css :element-content)}
- [:& color-row
- {:disable-gradient true
- :disable-opacity true
- :disable-image true
- :title (tr "workspace.options.canvas-background")
- :color {:color (get options :background clr/canvas)
- :opacity 1}
- :on-change on-change
- :on-open on-open
- :on-close on-close}]]]
-
- [:div.element-set
- [:div.element-set-title (tr "workspace.options.canvas-background")]
- [:div.element-set-content
- [:& color-row
- {:disable-gradient true
- :disable-opacity true
- :disable-image true
- :title (tr "workspace.options.canvas-background")
- :color {:color (get options :background clr/canvas)
- :opacity 1}
- :on-change on-change
- :on-open on-open
- :on-close on-close}]]])))
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.canvas-background")
+ :class (stl/css :title-spacing-page)}]]
+ [:div {:class (stl/css :element-content)}
+ [:& color-row
+ {:disable-gradient true
+ :disable-opacity true
+ :disable-image true
+ :title (tr "workspace.options.canvas-background")
+ :color {:color (get options :background clr/canvas)
+ :opacity 1}
+ :on-change on-change
+ :on-open on-open
+ :on-close on-close}]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
index cad09c56ac..15be74946d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
@@ -15,7 +15,6 @@
[app.main.data.workspace.libraries :as dwl]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.components.color-bullet :as cb]
[app.main.ui.components.color-bullet-new :as cbn]
[app.main.ui.components.color-input :refer [color-input*]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
@@ -43,10 +42,9 @@
(mf/defc color-row
[{:keys [index color disable-gradient disable-opacity disable-image on-change
- on-reorder on-detach on-open on-close title on-remove
+ on-reorder on-detach on-open on-close on-remove
disable-drag on-focus on-blur select-only select-on-focus]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- current-file-id (mf/use-ctx ctx/current-file-id)
+ (let [current-file-id (mf/use-ctx ctx/current-file-id)
file-colors (mf/deref refs/workspace-file-colors)
shared-libs (mf/deref refs/workspace-libraries)
hover-detach (mf/use-state false)
@@ -186,152 +184,87 @@
(when (not= prev-color color)
(modal/update-props! :colorpicker {:data (parse-color color)})))
- (if new-css-system
- [:div {:class (stl/css-case
- :color-data true
- :dnd-over-top (= (:over dprops) :top)
- :dnd-over-bot (= (:over dprops) :bot))
- :ref dref}
- [:span {:class (stl/css :color-info)}
- [:span {:class (stl/css-case :color-name-wrapper true
- :no-opacity (or disable-opacity
- (not opacity?))
- :library-name-wrapper library-color?
- :editing editing-text?
- :gradient-name-wrapper gradient-color?)}
- [:span {:class (stl/css :color-bullet-wrapper)}
- [:& cbn/color-bullet {:color (cond-> color
- (nil? color-name) (assoc
- :id nil
- :file-id nil))
- :mini? true
- :on-click handle-click-color}]]
- (cond
- ;; Rendering a color with ID
- library-color?
- [:*
- [:div {:class (stl/css :color-name)
- :title (str color-name)}
-
- (str color-name)]
- (when on-detach
- [:button
- {:class (stl/css :detach-btn)
- :title (tr "settings.detach")
- :on-pointer-enter #(reset! hover-detach true)
- :on-pointer-leave #(reset! hover-detach false)
- :on-click detach-value}
- i/detach-refactor])]
-
- ;; Rendering a gradient
- gradient-color?
- [:*
- [:div {:class (stl/css :color-name)}
- (uc/gradient-type->string (get-in color [:gradient :type]))]]
-
- ;; Rendering an image
- image-color?
- [:*
- [:div {:class (stl/css :color-name)}
- (tr "media.image")]]
-
- ;; Rendering a plain color
- :else
- [:span {:class (stl/css :color-input-wrapper)}
- [:> color-input* {:value (if multiple-colors?
- ""
- (-> color :color cc/remove-hash))
- :placeholder (tr "settings.multiple")
- :className (stl/css :color-input)
- :on-focus on-focus
- :on-blur on-blur
- :on-change handle-value-change}]])]
-
- (when opacity?
- [:div {:class (stl/css :opacity-element-wrapper)}
- [:span {:class (stl/css :icon-text)}
- "%"]
- [:> numeric-input* {:value (-> color :opacity opacity->string)
- :className (stl/css :opacity-input)
- :placeholder "--"
- :select-on-focus select-on-focus
- :on-focus on-focus
- :on-blur on-blur
- :on-change handle-opacity-change
- :min 0
- :max 100}]])]
-
- (when (some? on-remove)
- [:button {:class (stl/css :remove-btn)
- :on-click on-remove} i/remove-refactor])
- (when select-only
- [:button {:class (stl/css :select-btn)
- :on-click handle-select}
- i/move-refactor])]
-
- ;; OLD CSS
- [:div.row-flex.color-data {:title title
- :class (dom/classnames
- :dnd-over-top (= (:over dprops) :top)
- :dnd-over-bot (= (:over dprops) :bot))
- :ref dref}
- [:& cb/color-bullet {:color (cond-> color
- (nil? color-name) (assoc
- :id nil
- :file-id nil))
- :on-click handle-click-color}]
-
+ [:div {:class (stl/css-case
+ :color-data true
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ [:span {:class (stl/css :color-info)}
+ [:span {:class (stl/css-case :color-name-wrapper true
+ :no-opacity (or disable-opacity
+ (not opacity?))
+ :library-name-wrapper library-color?
+ :editing editing-text?
+ :gradient-name-wrapper gradient-color?)}
+ [:span {:class (stl/css :color-bullet-wrapper)}
+ [:& cbn/color-bullet {:color (cond-> color
+ (nil? color-name) (assoc
+ :id nil
+ :file-id nil))
+ :mini? true
+ :on-click handle-click-color}]]
(cond
- ;; Rendering a color with ID
+ ;; Rendering a color with ID
library-color?
[:*
- [:div.color-info
- [:div.color-name (str color-name)]]
+ [:div {:class (stl/css :color-name)
+ :title (str color-name)}
+
+ (str color-name)]
(when on-detach
- [:div.element-set-actions-button
- {:on-pointer-enter #(reset! hover-detach true)
+ [:button
+ {:class (stl/css :detach-btn)
+ :title (tr "settings.detach")
+ :on-pointer-enter #(reset! hover-detach true)
:on-pointer-leave #(reset! hover-detach false)
:on-click detach-value}
- (if @hover-detach i/unchain i/chain)])]
+ i/detach-refactor])]
- ;; Rendering a gradient
+ ;; Rendering a gradient
gradient-color?
[:*
- [:div.color-info
- [:div.color-name (uc/gradient-type->string (get-in color [:gradient :type]))]]
- (when select-only
- [:div.element-set-actions-button {:on-click handle-select}
- i/pointer-inner])]
+ [:div {:class (stl/css :color-name)}
+ (uc/gradient-type->string (get-in color [:gradient :type]))]]
- ;; Rendering a plain color/opacity
- :else
+ ;; Rendering an image
+ image-color?
[:*
- [:div.color-info
- [:> color-input* {:value (if multiple-colors?
- ""
- (-> color :color cc/remove-hash))
- :placeholder (tr "settings.multiple")
+ [:div {:class (stl/css :color-name)}
+ (tr "media.image")]]
+
+ ;; Rendering a plain color
+ :else
+ [:span {:class (stl/css :color-input-wrapper)}
+ [:> color-input* {:value (if multiple-colors?
+ ""
+ (-> color :color cc/remove-hash))
+ :placeholder (tr "settings.multiple")
+ :className (stl/css :color-input)
+ :on-focus on-focus
+ :on-blur on-blur
+ :on-change handle-value-change}]])]
+
+ (when opacity?
+ [:div {:class (stl/css :opacity-element-wrapper)}
+ [:span {:class (stl/css :icon-text)}
+ "%"]
+ [:> numeric-input* {:value (-> color :opacity opacity->string)
+ :className (stl/css :opacity-input)
+ :placeholder "--"
+ :select-on-focus select-on-focus
:on-focus on-focus
:on-blur on-blur
- :on-change handle-value-change}]]
+ :on-change handle-opacity-change
+ :min 0
+ :max 100}]])]
- (when (and (not disable-opacity)
- (not (:gradient color)))
- [:div.input-element
- {:class (dom/classnames :percentail (not= (:opacity color) :multiple))}
- [:> numeric-input* {:value (-> color :opacity opacity->string)
- :placeholder (tr "settings.multiple")
- :select-on-focus select-on-focus
- :on-focus on-focus
- :on-blur on-blur
- :on-change handle-opacity-change
- :min 0
- :max 100}]])
- (when select-only
- [:div.element-set-actions-button {:on-click handle-select}
- i/pointer-inner])])
- (when (some? on-remove)
- [:div.element-set-actions-button.remove {:on-click on-remove} i/minus])])
+ (when (some? on-remove)
+ [:button {:class (stl/css :remove-btn)
+ :on-click on-remove} i/remove-refactor])
+ (when select-only
+ [:button {:class (stl/css :select-btn)
+ :on-click handle-select}
+ i/move-refactor])]
))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss
index 83f32b627a..5285303c5f 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss
@@ -8,155 +8,6 @@
.color-data {
@include flexRow;
- .color-info {
- display: flex;
- align-items: center;
- gap: $s-2;
- border-radius: $s-8;
- background-color: var(--input-details-color);
- height: $s-32;
- width: 100%;
- flex-grow: 1;
- .color-name-wrapper {
- @extend .input-element;
- flex-grow: 1;
- width: 100%;
- border-radius: $br-8 0 0 $br-8;
- padding: 0;
- margin-right: 0;
- gap: $s-4;
- input {
- padding: 0;
- }
- .color-bullet-wrapper {
- height: $s-28;
- padding: 0 $s-2 0 $s-8;
- border-radius: $br-8 0 0 $br-8;
- background-color: transparent;
- &:hover {
- background-color: transparent;
- }
- }
- .color-name {
- @include titleTipography;
- display: flex;
- align-items: center;
- height: $s-28;
- padding-left: $s-6;
- border-radius: $br-8;
- width: 100%;
- flex-grow: 1;
- color: var(--input-foreground-color-active);
- }
- .detach-btn {
- @extend .button-tertiary;
- height: $s-28;
- width: $s-28;
- border-radius: 0 $br-8 $br-8 0;
- display: none;
- svg {
- @extend .button-icon;
- }
- }
- .color-input-wrapper {
- @include titleTipography;
- display: flex;
- align-items: center;
- height: $s-28;
- padding: 0 $s-0;
- width: 100%;
- margin: 0;
- flex-grow: 1;
- background-color: var(--input-background-color);
- color: var(--input-foreground-color);
- border-radius: $br-0;
- }
- &.no-opacity {
- border-radius: $br-8;
- .color-input-wrapper {
- border-radius: $br-8;
- }
- }
- &:hover {
- background-color: var(--input-background-color-hover);
- border: $s-1 solid var(--input-background-color-hover);
- .color-bullet-wrapper,
- .color-name,
- .detach-btn,
- .color-input-wrapper {
- background-color: var(--input-background-color-hover);
- }
- .detach-btn {
- display: flex;
- svg {
- stroke: var(--input-foreground-color-active);
- }
- }
- &.editing {
- background-color: var(--input-background-color-active);
- .color-bullet-wrapper,
- .color-name,
- .detach-btn,
- .color-input-wrapper {
- background-color: var(--input-background-color-active);
- }
- }
- }
- &:focus,
- &:focus-within {
- background-color: var(--input-background-color-active);
- }
-
- &.editing {
- background-color: var(--input-background-color-active);
- }
- }
- .gradient-name-wrapper {
- border-radius: 0 $br-8 $br-8 0;
- .color-name {
- @include flexRow;
- border-radius: 0 $br-8 $br-8 0;
- }
- }
- .library-name-wrapper {
- border-radius: $br-8;
- }
- .opacity-element-wrapper {
- @extend .input-element;
- width: $s-60;
- border-radius: 0 $br-8 $br-8 0;
- .opacity-input {
- padding: 0;
- border-radius: 0 $br-8 $br-8 0;
- min-width: $s-28;
- }
- .icon-text {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- padding-top: $s-2;
- }
- }
-
- &:hover {
- .detach-btn,
- .select-btn {
- background-color: transparent;
- svg {
- stroke: var(--input-foreground-color-active);
- }
- }
- }
- }
- .remove-btn,
- .select-btn {
- @extend .button-tertiary;
- height: $s-32;
- width: $s-28;
- svg {
- @extend .button-icon;
- }
- }
&.dnd-over-top {
border-top: $s-1 solid var(--layer-row-foreground-color-drag);
@@ -165,3 +16,155 @@
border-bottom: $s-1 solid var(--layer-row-foreground-color-drag);
}
}
+
+.color-info {
+ display: flex;
+ align-items: center;
+ gap: $s-2;
+ border-radius: $s-8;
+ background-color: var(--input-details-color);
+ height: $s-32;
+ width: 100%;
+ flex-grow: 1;
+
+ .color-name-wrapper {
+ @extend .input-element;
+ flex-grow: 1;
+ width: 100%;
+ border-radius: $br-8 0 0 $br-8;
+ padding: 0;
+ margin-right: 0;
+ gap: $s-4;
+ input {
+ padding: 0;
+ }
+ .color-bullet-wrapper {
+ height: $s-28;
+ padding: 0 $s-2 0 $s-8;
+ border-radius: $br-8 0 0 $br-8;
+ background-color: transparent;
+ &:hover {
+ background-color: transparent;
+ }
+ }
+ .color-name {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ height: $s-28;
+ padding-left: $s-6;
+ border-radius: $br-8;
+ width: 100%;
+ flex-grow: 1;
+ color: var(--input-foreground-color-active);
+ }
+ .detach-btn {
+ @extend .button-tertiary;
+ height: $s-28;
+ width: $s-28;
+ border-radius: 0 $br-8 $br-8 0;
+ display: none;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ .color-input-wrapper {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ height: $s-28;
+ padding: 0 $s-0;
+ width: 100%;
+ margin: 0;
+ flex-grow: 1;
+ background-color: var(--input-background-color);
+ color: var(--input-foreground-color);
+ border-radius: $br-0;
+ }
+ &.no-opacity {
+ border-radius: $br-8;
+ .color-input-wrapper {
+ border-radius: $br-8;
+ }
+ }
+ &:hover {
+ background-color: var(--input-background-color-hover);
+ border: $s-1 solid var(--input-background-color-hover);
+ .color-bullet-wrapper,
+ .color-name,
+ .detach-btn,
+ .color-input-wrapper {
+ background-color: var(--input-background-color-hover);
+ }
+ .detach-btn {
+ display: flex;
+ svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+ &.editing {
+ background-color: var(--input-background-color-active);
+ .color-bullet-wrapper,
+ .color-name,
+ .detach-btn,
+ .color-input-wrapper {
+ background-color: var(--input-background-color-active);
+ }
+ }
+ }
+ &:focus,
+ &:focus-within {
+ background-color: var(--input-background-color-active);
+ }
+
+ &.editing {
+ background-color: var(--input-background-color-active);
+ }
+ }
+ .gradient-name-wrapper {
+ border-radius: 0 $br-8 $br-8 0;
+ .color-name {
+ @include flexRow;
+ border-radius: 0 $br-8 $br-8 0;
+ }
+ }
+ .library-name-wrapper {
+ border-radius: $br-8;
+ }
+ .opacity-element-wrapper {
+ @extend .input-element;
+ width: $s-60;
+ border-radius: 0 $br-8 $br-8 0;
+ .opacity-input {
+ padding: 0;
+ border-radius: 0 $br-8 $br-8 0;
+ min-width: $s-28;
+ }
+ .icon-text {
+ @include flexCenter;
+ height: $s-32;
+ margin-right: $s-4;
+ padding-top: $s-2;
+ }
+ }
+
+ &:hover {
+ .detach-btn,
+ .select-btn {
+ background-color: transparent;
+ svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+ }
+}
+
+.remove-btn,
+.select-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs
deleted file mode 100644
index f0aca9d255..0000000000
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs
+++ /dev/null
@@ -1,72 +0,0 @@
-;; This Source Code Form is subject to the terms of the Mozilla Public
-;; License, v. 2.0. If a copy of the MPL was not distributed with this
-;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-;;
-;; Copyright (c) KALEIDOS INC
-
-(ns app.main.ui.workspace.sidebar.options.rows.input-row
- (:require
- [app.main.ui.components.editable-select :refer [editable-select]]
- [app.main.ui.components.numeric-input :refer [numeric-input*]]
- [app.main.ui.components.select :refer [select]]
- [app.util.object :as obj]
- [rumext.v2 :as mf]))
-
-(mf/defc input-row
- [{:keys [label options value class min max on-change type placeholder default nillable on-focus select-on-focus]}]
- [:div.row-flex.input-row
- [:span.element-set-subtitle label]
- [:div.input-element {:class class}
-
- (case type
- :select
- [:& select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :default-value value
- :class "input-option"
- :options options
- :on-change on-change}]
-
- :editable-select
- [:& editable-select {:value value
- :class "input-option"
- :options options
- :type "number"
- :min min
- :max max
- :placeholder placeholder
- :on-change on-change}]
-
- :text
- [:input {:value value
- :class "input-text"
- :on-change on-change} ]
-
- [:> numeric-input*
- {:placeholder placeholder
- :min min
- :max max
- :default default
- :nillable nillable
- :on-change on-change
- :on-focus on-focus
- :select-on-focus select-on-focus
- :value (or value "")}])]])
-
-
-;; NOTE: (by niwinz) this is a new version of input-row, I didn't
-;; touched the original one because it is used in many sites and I
-;; don't have intention to refactor all the code right now. We should
-;; consider to use the new one and once we have migrated all to the
-;; new component, we can proceed to rename it and delete the old one.
-
-(mf/defc input-row-v2
- {::mf/wrap-props false}
- [props]
- (let [label (obj/get props "label")
- class (obj/get props "class")
- children (obj/get props "children")]
- [:div.row-flex.input-row
- [:span.element-set-subtitle label]
- [:div.input-element {:class class}
- children]]))
-
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs
index 2b661b1096..558e86b416 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs
@@ -10,7 +10,6 @@
[app.common.data :as d]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu]]
@@ -33,8 +32,7 @@
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- shape (unchecked-get props "shape")
+ (let [shape (unchecked-get props "shape")
shape-with-children (unchecked-get props "shape-with-children")
shared-libs (unchecked-get props "shared-libs")
objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
@@ -69,8 +67,7 @@
[layout-item-ids layout-item-values] (get-attrs [shape] objects :layout-item)]
- [:div {:class (stl/css-case new-css-system
- :options true)}
+ [:div {:class (stl/css :options)}
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
[:& measures-menu {:type type :ids measure-ids :values measure-values :shape shape}]
[:& component-menu {:shapes [shape]}] ;;remove this in components-v2
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs
index 8309844a76..a562269aec 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs
@@ -16,7 +16,6 @@
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.texts :as dwt]
[app.main.refs :as refs]
- [app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu]]
@@ -268,8 +267,7 @@
{::mf/wrap [#(mf/memo' % (mf/check-props ["shapes" "shapes-with-children" "page-id" "file-id"]))]
::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- shapes (unchecked-get props "shapes")
+ (let [shapes (unchecked-get props "shapes")
shapes-with-children (unchecked-get props "shapes-with-children")
;; remove children from bool shapes
@@ -348,8 +346,7 @@
components (filter ctk/instance-head? shapes)]
- [:div {:class (stl/css-case new-css-system
- :options true)}
+ [:div {:class (stl/css :options)}
(when-not (empty? layer-ids)
[:& layer-menu {:type type :ids layer-ids :values layer-values}])
diff --git a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs
index 65b37b1e10..04748ef406 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs
@@ -5,13 +5,12 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.shortcuts
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.config :as cf]
[app.main.data.dashboard.shortcuts]
- [app.main.data.events :as ev]
[app.main.data.shortcuts :as ds]
[app.main.data.viewer.shortcuts]
[app.main.data.workspace :as dw]
@@ -19,21 +18,17 @@
[app.main.data.workspace.shortcuts]
[app.main.store :as st]
[app.main.ui.components.search-bar :refer [search-bar]]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
- [app.util.keyboard :as kbd]
[app.util.strings :refer [matches-search]]
[clojure.set :as set]
[clojure.string]
- [cuerdas.core :as str]
[rumext.v2 :as mf]))
(mf/defc converted-chars
[{:keys [char command] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- modified-keys {:up ds/up-arrow
+ (let [modified-keys {:up ds/up-arrow
:down ds/down-arrow
:left ds/left-arrow
:right ds/right-arrow
@@ -51,10 +46,8 @@
char (if (contains? modified-keys (keyword char)) ((keyword char) modified-keys) char)
char (if (and is-macos? (contains? macos-keys (keyword char))) ((keyword char) macos-keys) char)
unique-key (str (d/name command) "-" char)]
- (if new-css-system
- [:span {:class (css :key)
- :key unique-key} char]
- [:span.char-box {:key unique-key} char])))
+ [:span {:class (stl/css :key)
+ :key unique-key} char]))
(defn translation-keyname
[type keyname]
@@ -222,8 +215,7 @@
(mf/defc shortcuts-keys
[{:keys [content command] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- managed-list (if (coll? content)
+ (let [managed-list (if (coll? content)
content
(conj () content))
chars-list (map ds/split-sc managed-list)
@@ -232,43 +224,25 @@
chars-list
(drop-last chars-list))
penultimate (last short-char-list)]
- (if new-css-system
- [:span {:class (css :keys)}
- (for [chars short-char-list]
- [:*
- (for [char chars]
- [:& converted-chars {:key (dm/str char "-" (name command))
- :char char
- :command command}])
- (when (not= chars penultimate) [:span {:class (css :space)} ","])])
- (when (not= last-element penultimate)
- [:*
- [:span {:class (css :space)} (tr "shortcuts.or")]
- (for [char last-element]
- [:& converted-chars {:key (dm/str char "-" (name command))
- :char char
- :command command}])])]
-
- [:span.keys
- (for [chars short-char-list]
- [:*
- (for [char chars]
- [:& converted-chars {:key (dm/str char "-" (name command))
- :char char
- :command command}])
- (when (not= chars penultimate) [:span.space ","])])
- (when (not= last-element penultimate)
- [:*
- [:span.space (tr "shortcuts.or")]
- (for [char last-element]
- [:& converted-chars {:key (dm/str char "-" (name command))
- :char char
- :command command}])])])))
+ [:span {:class (stl/css :keys)}
+ (for [chars short-char-list]
+ [:*
+ (for [char chars]
+ [:& converted-chars {:key (dm/str char "-" (name command))
+ :char char
+ :command command}])
+ (when (not= chars penultimate) [:span {:class (stl/css :space)} ","])])
+ (when (not= last-element penultimate)
+ [:*
+ [:span {:class (stl/css :space)} (tr "shortcuts.or")]
+ (for [char last-element]
+ [:& converted-chars {:key (dm/str char "-" (name command))
+ :char char
+ :command command}])])]))
(mf/defc shortcut-row
[{:keys [elements filter-term match-section? match-subsection?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- shortcut-name (keys elements)
+ (let [shortcut-name (keys elements)
shortcut-translations (map #(translation-keyname :sc %) shortcut-name)
match-shortcut? (some #(matches-search % @filter-term) shortcut-translations)
filtered (if (and (or match-section? match-subsection?) (not match-shortcut?))
@@ -276,46 +250,32 @@
(filter #(matches-search % @filter-term) shortcut-translations))
sorted-filtered (sort filtered)]
- (if new-css-system
- [:ul {:class (css :sub-menu)}
- (for [command-translate sorted-filtered]
- (let [sc-by-translate (first (filter #(= (:translation (second %)) command-translate) elements))
- [command comand-info] sc-by-translate
- content (or (:show-command comand-info) (:command comand-info))]
- [:li {:class (css :shortcuts-name)
- :key command-translate}
- [:span {:class (css :command-name)}
- command-translate]
- [:& shortcuts-keys {:content content
- :command command}]]))]
-
- [:ul.sub-menu
- (for [command-translate sorted-filtered]
- (let [sc-by-translate (first (filter #(= (:translation (second %)) command-translate) elements))
- [command comand-info] sc-by-translate
- content (or (:show-command comand-info) (:command comand-info))]
- [:li.shortcut-name {:key command-translate}
- [:span.command-name command-translate]
- [:& shortcuts-keys {:content content
- :command command}]]))])))
+ [:ul {:class (stl/css :sub-menu)}
+ (for [command-translate sorted-filtered]
+ (let [sc-by-translate (first (filter #(= (:translation (second %)) command-translate) elements))
+ [command comand-info] sc-by-translate
+ content (or (:show-command comand-info) (:command comand-info))]
+ [:li {:class (stl/css :shortcuts-name)
+ :key command-translate}
+ [:span {:class (stl/css :command-name)}
+ command-translate]
+ [:& shortcuts-keys {:content content
+ :command command}]]))]))
(mf/defc section-title
[{:keys [is-visible? name is-sub?] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (if is-sub? (css :subsection-title) (css :section-title))}
- [:span {:class (dom/classnames (css :open) is-visible?
- (css :collapsed-shortcuts) true)} i/arrow-refactor]
- [:span {:class (if is-sub? (css :subsection-name) (css :section-name))} name]]
-
- [:div {:class (if is-sub? "subsection-title" "section-title")}
- [:span.collapesed-shortcuts {:class (when is-visible? "open")} i/arrow-slide]
- [:span {:class (if is-sub? "subsection-name" "section-name")} name]])))
+ [:div {:class (if is-sub?
+ (stl/css :subsection-title)
+ (stl/css :section-title))}
+ [:span {:class (stl/css-case :open is-visible?
+ :collapsed-shortcuts true)} i/arrow-refactor]
+ [:span {:class (if is-sub?
+ (stl/css :subsection-name)
+ (stl/css :section-name))} name]])
(mf/defc shortcut-subsection
[{:keys [subsections manage-sections filter-term match-section? open-sections] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- subsections-names (keys subsections)
+ (let [subsections-names (keys subsections)
subsection-translations (if (= :none (first subsections-names))
(map #(translation-keyname :sc %) subsections-names)
(map #(translation-keyname :sub-sec %) subsections-names))
@@ -328,8 +288,7 @@
:match-section? match-section?
:match-subsection? true}])
- [:ul {:class (dom/classnames (css :subsection-menu) new-css-system
- :subsection-menu (not new-css-system))}
+ [:ul {:class (stl/css :subsection-menu)}
(for [sub-translated sorted-translations]
(let [sub-by-translate (first (filter #(= (:translation (second %)) sub-translated) subsections))
[sub-name sub-info] sub-by-translate
@@ -368,7 +327,7 @@
visible? (some #(= % section-id) @open-sections)]
(when (or match-section? match-subsection? match-shortcut?)
- [:div {:class (css :section)
+ [:div {:class (stl/css :section)
:on-click (manage-sections section-id)}
[:& section-title {:is-visible? visible?
:is-sub? false
@@ -383,8 +342,7 @@
(mf/defc shortcuts-container
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- workspace-shortcuts app.main.data.workspace.shortcuts/shortcuts
+ (let [workspace-shortcuts app.main.data.workspace.shortcuts/shortcuts
path-shortcuts app.main.data.workspace.path.shortcuts/shortcuts
all-workspace-shortcuts (->> (d/deep-merge path-shortcuts workspace-shortcuts)
(add-translation :sc)
@@ -496,13 +454,6 @@
(manage-section-on-search :viewer term))]
(reset! open-sections ids))))
- on-search-term-change
- (mf/use-callback
- (fn [event]
- (let [value (dom/get-target-val event)]
- (manage-sections-on-search value)
- (reset! filter-term value))))
-
on-search-term-change-2
(mf/use-callback
(fn [value]
@@ -512,80 +463,31 @@
(mf/use-callback
(fn [_]
(reset! open-sections [[1]])
- (reset! filter-term "")))
-
- manage-key-down
- (mf/use-callback
- (fn [event]
- (when (kbd/esc? event)
- (st/emit! (-> (dw/toggle-layout-flag :shortcuts)
- (vary-meta assoc ::ev/origin "shortcuts-panel"))))))
-
- on-key-down
- (mf/use-callback
- (fn [event]
- (when (kbd/enter? event)
- (on-search-clear-click)
- (dom/focus! (dom/get-element "shortcut-search")))))]
+ (reset! filter-term "")))]
(mf/with-effect []
(dom/focus! (dom/get-element "shortcut-search")))
- (if new-css-system
- [:div {:class (css :shortcuts)}
- [:div {:class (css :shortcuts-header)}
- [:div {:class (css :shortcuts-title)} (tr "shortcuts.title")]
- [:div {:class (css :shortcuts-close-button)
- :on-click close-fn}
- i/close-refactor]]
- [:div {:class (css :search-field)}
+ [:div {:class (stl/css :shortcuts)}
+ [:div {:class (stl/css :shortcuts-header)}
+ [:div {:class (stl/css :shortcuts-title)} (tr "shortcuts.title")]
+ [:div {:class (stl/css :shortcuts-close-button)
+ :on-click close-fn}
+ i/close-refactor]]
+ [:div {:class (stl/css :search-field)}
- [:& search-bar {:on-change on-search-term-change-2
- :clear-action on-search-clear-click
- :value @filter-term
- :placeholder (tr "shortcuts.title")
- :icon (mf/html [:span {:class (css :search-icon)} i/search-refactor])}]]
+ [:& search-bar {:on-change on-search-term-change-2
+ :clear-action on-search-clear-click
+ :value @filter-term
+ :placeholder (tr "shortcuts.title")
+ :icon (mf/html [:span {:class (stl/css :search-icon)} i/search-refactor])}]]
- (if match-any?
- [:div {:class (dom/classnames (css :shortcuts-list) true)}
- (for [section all-shortcuts]
- [:& shortcut-section
- {:section section
- :manage-sections manage-sections
- :open-sections open-sections
- :filter-term filter-term}])]
- [:div {:class (css :not-found)} (tr "shortcuts.not-found")])]
-
- [:div.shortcuts
- [:div.shortcuts-header
- [:div.shortcuts-close-button
- {:on-click close-fn} i/close]
- [:div.shortcuts-title (tr "shortcuts.title")]]
- [:div.search-field
- [:div.search-box
- [:input.input-text
- {:id "shortcut-search"
- :placeholder (tr "shortcuts.search-placeholder")
- :type "text"
- :value @filter-term
- :on-change on-search-term-change
- :auto-complete "off"
- :on-key-down manage-key-down}]
- (if (str/empty? @filter-term)
- [:span.icon-wrapper
- i/search]
- [:button.icon-wrapper
- {:on-click on-search-clear-click
- :on-key-down on-key-down}
- [:span.icon.close
- i/close]])]]
- (if match-any?
- [:div.shortcut-list
- (for [section all-shortcuts]
- [:& shortcut-section
- {:section section
- :manage-sections manage-sections
- :open-sections open-sections
- :filter-term filter-term}])]
-
- [:div.not-found (tr "shortcuts.not-found")])])))
+ (if match-any?
+ [:div {:class (stl/css :shortcuts-list)}
+ (for [section all-shortcuts]
+ [:& shortcut-section
+ {:section section
+ :manage-sections manage-sections
+ :open-sections open-sections
+ :filter-term filter-term}])]
+ [:div {:class (stl/css :not-found)} (tr "shortcuts.not-found")])]))
diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs
index 6933fb1c85..8374386cf4 100644
--- a/frontend/src/app/main/ui/workspace/viewport.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport.cljs
@@ -229,7 +229,7 @@
show-rules? (and (contains? layout :rules) (not hide-ui?))
- disabled-guides? (or drawing-tool transform)
+ disabled-guides? (or drawing-tool transform drawing-path? node-editing?)
one-selected-shape? (= (count selected-shapes) 1)
diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs
index f036cbde96..aa59d9e91f 100644
--- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs
@@ -12,15 +12,13 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.comments :as cmt]
- [app.main.ui.context :as ctx]
[cuerdas.core :as str]
[okulary.core :as l]
[rumext.v2 :as mf]))
(mf/defc comments-layer
[{:keys [vbox vport zoom file-id page-id drawing] :as props}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- pos-x (* (- (:x vbox)) zoom)
+ (let [pos-x (* (- (:x vbox)) zoom)
pos-y (* (- (:y vbox)) zoom)
profile (mf/deref refs/profile)
@@ -57,54 +55,29 @@
(st/emit! (dwcm/initialize-comments file-id))
(fn []
(st/emit! ::dwcm/finalize))))
- (if new-css-system
- [:div {:class (stl/css :comments-section)}
- [:div
- {:class (stl/css :workspace-comments-container)
- :style {:width (str (:width vport) "px")
- :height (str (:height vport) "px")}}
- [:div {:class (stl/css :threads)
- :style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}}
- (for [item threads]
- [:& cmt/thread-bubble {:thread item
- :zoom zoom
- :open? (= (:id item) (:open local))
- :key (:seqn item)}])
+ [:div {:class (stl/css :comments-section)}
+ [:div
+ {:class (stl/css :workspace-comments-container)
+ :style {:width (str (:width vport) "px")
+ :height (str (:height vport) "px")}}
+ [:div {:class (stl/css :threads)
+ :style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}}
+ (for [item threads]
+ [:& cmt/thread-bubble {:thread item
+ :zoom zoom
+ :open? (= (:id item) (:open local))
+ :key (:seqn item)}])
- (when-let [id (:open local)]
- (when-let [thread (get threads-map id)]
- [:& cmt/thread-comments {:thread (update-thread-position thread)
- :users users
- :zoom zoom}]))
+ (when-let [id (:open local)]
+ (when-let [thread (get threads-map id)]
+ [:& cmt/thread-comments {:thread (update-thread-position thread)
+ :users users
+ :zoom zoom}]))
- (when-let [draft (:comment drawing)]
- [:& cmt/draft-thread {:draft draft
- :on-cancel on-draft-cancel
- :on-submit on-draft-submit
- :zoom zoom}])]]]
-
- ;; OLD
- [:div.comments-section
- [:div.workspace-comments-container
- {:style {:width (str (:width vport) "px")
- :height (str (:height vport) "px")}}
- [:div.threads {:style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}}
- (for [item threads]
- [:& cmt/thread-bubble {:thread item
- :zoom zoom
- :open? (= (:id item) (:open local))
- :key (:seqn item)}])
-
- (when-let [id (:open local)]
- (when-let [thread (get threads-map id)]
- [:& cmt/thread-comments {:thread (update-thread-position thread)
- :users users
- :zoom zoom}]))
-
- (when-let [draft (:comment drawing)]
- [:& cmt/draft-thread {:draft draft
- :on-cancel on-draft-cancel
- :on-submit on-draft-submit
- :zoom zoom}])]]])
+ (when-let [draft (:comment drawing)]
+ [:& cmt/draft-thread {:draft draft
+ :on-cancel on-draft-cancel
+ :on-submit on-draft-submit
+ :zoom zoom}])]]]
))
diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs
index 8066696b00..fcac73c07b 100644
--- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs
@@ -10,6 +10,7 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
+ [app.common.geom.line :as gl]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
@@ -24,12 +25,12 @@
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.css-cursors :as cur]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.workspace.viewport.viewport-ref :as uwvv]
+ [app.util.debug :as dbg]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
@@ -53,28 +54,16 @@
(mf/defc grid-edition-actions
{::mf/wrap-props false}
[{:keys [shape]}]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)]
- (if new-css-system
- [:div {:class (stl/css :grid-actions)}
- [:div {:class (stl/css :grid-actions-container)}
- [:div {:class (stl/css :grid-actions-title)}
- (tr "workspace.layout_grid.editor.title") " " [:span {:stl/css :board-name} (:name shape)]]
- [:button {:class (stl/css :locate-btn)
- :on-click #(st/emit! (dwge/locate-board (:id shape)))}
- (tr "workspace.layout_grid.editor.top-bar.locate")]
- [:button {:class (stl/css :done-btn)
- :on-click #(st/emit! dw/clear-edition-mode)}
- (tr "workspace.layout_grid.editor.top-bar.done")]]]
-
- [:div.viewport-actions
- [:div.viewport-actions-container
- [:div.viewport-actions-title
- (tr "workspace.layout_grid.editor.title") " " [:span.grid-edit-board-name (:name shape)]]
- [:button.btn-secondary {:on-click #(st/emit! (dwge/locate-board (:id shape)))}
- (tr "workspace.layout_grid.editor.top-bar.locate")]
- [:button.btn-primary {:on-click #(st/emit! dw/clear-edition-mode)}
- (tr "workspace.layout_grid.editor.top-bar.done")]
- [:button.btn-icon-basic {:on-click #(st/emit! dw/clear-edition-mode)} i/close]]])))
+ [:div {:class (stl/css :grid-actions)}
+ [:div {:class (stl/css :grid-actions-container)}
+ [:div {:class (stl/css :grid-actions-title)}
+ (tr "workspace.layout_grid.editor.title") " " [:span {:stl/css :board-name} (:name shape)]]
+ [:button {:class (stl/css :locate-btn)
+ :on-click #(st/emit! (dwge/locate-board (:id shape)))}
+ (tr "workspace.layout_grid.editor.top-bar.locate")]
+ [:button {:class (stl/css :done-btn)
+ :on-click #(st/emit! dw/clear-edition-mode)}
+ (tr "workspace.layout_grid.editor.top-bar.done")]]])
(mf/defc grid-editor-frame
{::mf/wrap-props false}
@@ -163,7 +152,7 @@
(mf/set-ref-val! dragging-ref true)
(mf/set-ref-val! start-pos-ref raw-pt)
(mf/set-ref-val! current-pos-ref raw-pt)
- (when on-drag-start (on-drag-start position)))))
+ (when on-drag-start (on-drag-start event position)))))
handle-lost-pointer-capture
(mf/use-callback
@@ -174,7 +163,7 @@
(dom/release-pointer event)
(mf/set-ref-val! dragging-ref false)
(mf/set-ref-val! start-pos-ref nil)
- (when on-drag-end (on-drag-end position)))))
+ (when on-drag-end (on-drag-end event position)))))
handle-pointer-move
(mf/use-callback
@@ -185,8 +174,8 @@
pos (dom/get-client-position event)
pt (uwvv/point->viewport pos)]
(mf/set-ref-val! current-pos-ref pos)
- (when on-drag-delta (on-drag-delta (gpt/to-vec start pos)))
- (when on-drag-position (on-drag-position pt))))))]
+ (when on-drag-delta (on-drag-delta event (gpt/to-vec start pos)))
+ (when on-drag-position (on-drag-position event pt))))))]
{:handle-pointer-down handle-pointer-down
:handle-lost-pointer-capture handle-lost-pointer-capture
@@ -212,7 +201,7 @@
handle-drag-position
(mf/use-callback
(mf/deps shape row column row-span column-span)
- (fn [position]
+ (fn [_ position]
(let [[drag-row drag-column] (gsg/get-position-grid-coord layout-data position)
[new-row new-column new-row-span new-column-span]
@@ -336,11 +325,52 @@
(mf/use-callback
(mf/deps (:id shape) (:id cell) selected?)
(fn [event]
- (if (and (kbd/shift? event) selected?)
- (st/emit! (dwge/remove-selection (:id shape) (:id cell)))
- (st/emit! (dwge/select-grid-cell (:id shape) (:id cell) (kbd/shift? event)) ))))]
+ (when (dom/left-mouse? event)
+ (cond
+ (and selected? (or (kbd/mod? event) (kbd/shift? event)))
+ (st/emit! (dwge/remove-selection (:id shape) (:id cell)))
+
+ (and (not selected?) (kbd/mod? event))
+ (st/emit! (dwge/add-to-selection (:id shape) (:id cell)))
+
+ (and (not selected?) (kbd/shift? event))
+ (st/emit! (dwge/add-to-selection (:id shape) (:id cell) true))
+
+ :else
+ (st/emit! (dwge/set-selection (:id shape) (:id cell)))))))
+
+ handle-context-menu
+ (mf/use-callback
+ (fn [event]
+ (dom/prevent-default event)
+ (dom/stop-propagation event)
+ (let [position (dom/get-client-position event)]
+ (st/emit! (dw/show-grid-cell-context-menu {:position position :grid-id (:id shape)})))))]
[:g.cell-editor
+ ;; DEBUG OVERLAY
+ (when (dbg/enabled? :grid-cells)
+ [:g.debug-cell {:pointer-events "none"
+ :transform (dm/str (gmt/transform-in cell-center (:transform shape)))}
+
+ [:rect
+ {:x (:x cell-origin)
+ :y (:y cell-origin)
+ :width cell-width
+ :height cell-height
+ :fill (cond
+ (= (:position cell) :auto) "green"
+ (= (:position cell) :manual) "red"
+ (= (:position cell) :area) "yellow"
+ :else "black")
+ :fill-opacity 0.2}]
+
+ (when (seq (:shapes cell))
+ [:circle
+ {:cx (+ (:x cell-origin) cell-width (- (/ 7 zoom)))
+ :cy (+ (:y cell-origin) (/ 7 zoom))
+ :r (/ 5 zoom)
+ :fill "red"}])])
[:rect
{:transform (dm/str (gmt/transform-in cell-center (:transform shape)))
:class (dom/classnames (stl/css :grid-cell-outline) true
@@ -351,6 +381,7 @@
:width cell-width
:height cell-height
+ :on-context-menu handle-context-menu
:on-pointer-enter handle-pointer-enter
:on-pointer-leave handle-pointer-leave
:on-pointer-down handle-pointer-down}]
@@ -410,7 +441,7 @@
handle-drag-position
(mf/use-callback
(mf/deps shape track-before track-after)
- (fn [position]
+ (fn [_ position]
(let [[tracks-prop axis]
(if (= :column type) [:layout-grid-columns :x] [:layout-grid-rows :y])
@@ -451,11 +482,14 @@
(let [shape (unchecked-get props "shape")
index (unchecked-get props "index")
last? (unchecked-get props "last?")
+ drop? (unchecked-get props "drop?")
track-before (unchecked-get props "track-before")
track-after (unchecked-get props "track-after")
snap-pixel? (unchecked-get props "snap-pixel?")
- {:keys [column-total-size column-total-gap row-total-size row-total-gap]} (unchecked-get props "layout-data")
+ {:keys [column-total-size column-total-gap row-total-size row-total-gap] :as layout-data}
+ (unchecked-get props "layout-data")
+
start-p (unchecked-get props "start-p")
type (unchecked-get props "type")
zoom (unchecked-get props "zoom")
@@ -477,7 +511,7 @@
[(+ column-total-size column-total-gap)
(max 0 (- layout-gap-row (/ 10 zoom)) (/ 8 zoom))])
- start-p
+ start-p-resize
(cond-> start-p
(and (= type :column) (= index 0))
(gpt/subtract (hv (/ width 2)))
@@ -491,22 +525,52 @@
(and (= type :row) (not= index 0) (not last?))
(-> (gpt/subtract (vv (/ layout-gap-row 2)))
- (gpt/subtract (vv (/ height 2)))))]
+ (gpt/subtract (vv (/ height 2)))))
- [:rect.resize-track-handler
- {:x (:x start-p)
- :y (:y start-p)
- :height height
- :width width
- :on-pointer-down handle-pointer-down
- :on-lost-pointer-capture handle-lost-pointer-capture
- :on-pointer-move handle-pointer-move
- :transform (dm/str (gmt/transform-in start-p (:transform shape)))
- :class (if (= type :column)
- (cur/get-dynamic "resize-ew" (:rotation shape))
- (cur/get-dynamic "resize-ns" (:rotation shape)))
- :style {:fill "transparent"
- :stroke-width 0}}]))
+ start-p-drop
+ (cond-> start-p
+ (and (= type :column) (= index 0))
+ (gpt/subtract (hv (/ width 2)))
+
+ (and (= type :row) (= index 0))
+ (gpt/subtract (vv (/ height 2)))
+
+ (and (= type :column) last?)
+ (gpt/add (hv (/ width 2)))
+
+ (and (= type :row) last?)
+ (gpt/add (vv (/ height 2)))
+
+ (and (= type :column) (not= index 0) (not last?))
+ (-> (gpt/subtract (hv (/ layout-gap-col 2)))
+ (gpt/subtract (hv (/ 5 zoom))))
+
+ (and (= type :row) (not= index 0) (not last?))
+ (-> (gpt/subtract (vv (/ layout-gap-row 2)))
+ (gpt/subtract (vv (/ 5 zoom)))))]
+ [:*
+ (when drop?
+ [:rect.drop
+ {:x (:x start-p-drop)
+ :y (:y start-p-drop)
+ :width (if (= type :column)(/ 10 zoom) width)
+ :height (if (= type :row) (/ 10 zoom) height)
+ :fill "var(--grid-editor-area-background)"}])
+
+ [:rect.resize-track-handler
+ {:x (:x start-p-resize)
+ :y (:y start-p-resize)
+ :height height
+ :width width
+ :on-pointer-down handle-pointer-down
+ :on-lost-pointer-capture handle-lost-pointer-capture
+ :on-pointer-move handle-pointer-move
+ :transform (dm/str (gmt/transform-in start-p (:transform shape)))
+ :class (if (= type :column)
+ (cur/get-dynamic "resize-ew" (:rotation shape))
+ (cur/get-dynamic "resize-ns" (:rotation shape)))
+ :style {:fill "transparent"
+ :stroke-width 0}}]]))
(def marker-width 24)
(def marker-h1 20)
@@ -620,7 +684,7 @@
(dm/str value)]]))
(mf/defc track
- {::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "zoom" "index" "type" "track-data" "layout-data" "hovering?"]))]
+ {::mf/wrap [mf/memo]
::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
@@ -631,6 +695,11 @@
track-data (unchecked-get props "track-data")
layout-data (unchecked-get props "layout-data")
hovering? (unchecked-get props "hovering?")
+ drop? (unchecked-get props "drop?")
+
+ on-start-reorder-track (unchecked-get props "on-start-reorder-track")
+ on-move-reorder-track (unchecked-get props "on-move-reorder-track")
+ on-end-reorder-track (unchecked-get props "on-end-reorder-track")
track-input-ref (mf/use-ref)
[layout-gap-row layout-gap-col] (ctl/gaps shape)
@@ -707,29 +776,60 @@
(fn []
(st/emit! (dwsl/hover-layout-track [(:id shape)] type index false))))
- handle-remove-track
- (mf/use-callback
- (mf/deps (:id shape) type index)
- (fn []
- (st/emit! (dwsl/remove-layout-track [(:id shape)] type index))))
-
track-list-prop (if (= type :column) :column-tracks :row-tracks)
[text-x text-y text-width text-height]
(if (= type :column)
[(:x text-p) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)]
[(- (:x text-p) (max 0 (:size track-data))) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)])
+ handle-drag-start
+ (mf/use-callback
+ (mf/deps on-start-reorder-track type index)
+ (fn []
+ (on-start-reorder-track type index)))
+
+ handle-drag-end
+ (mf/use-callback
+ (mf/deps on-end-reorder-track type index)
+ (fn [event position]
+ (on-end-reorder-track type index position (not (kbd/mod? event)))))
+
+ handle-drag-position
+ (mf/use-callback
+ (mf/deps on-move-reorder-track type index)
+ (fn [_ position]
+ (on-move-reorder-track type index position)))
+
+ handle-show-track-menu
+ (mf/use-callback
+ (fn [event]
+ (dom/stop-propagation event)
+ (dom/prevent-default event)
+ (let [position (cond-> (dom/get-client-position event)
+ (= type :column) (update :y + 40)
+ (= type :row) (update :x + 30))]
+ (st/emit! (dw/show-track-context-menu {:position position
+ :grid-id (:id shape)
+ :type type
+ :index index})))))
+
trackwidth (* text-width zoom)
medium? (and (>= trackwidth small-size-limit) (< trackwidth medium-size-limit))
small? (< trackwidth small-size-limit)
- track-before (get-in layout-data [track-list-prop (dec index)])]
+ track-before (get-in layout-data [track-list-prop (dec index)])
+
+ {:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
+ (use-drag {:on-drag-start handle-drag-start
+ :on-drag-end handle-drag-end
+ :on-drag-position handle-drag-position})]
(mf/use-effect
(mf/deps track-data)
(fn []
(dom/set-value! (mf/ref-val track-input-ref) (format-size track-data))))
+
[:g.track
[:g {:on-pointer-enter handle-pointer-enter
:on-pointer-leave handle-pointer-leave
@@ -737,17 +837,21 @@
(dm/str (gmt/transform-in text-p (:transform shape)))
(dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))}
- (when (and hovering? (not small?))
- [:rect {:x (+ text-x (/ 18 zoom))
- :y text-y
- :width (- text-width (/ 36 zoom))
- :height (- text-height (/ 5 zoom))
- :rx (/ 3 zoom)
- :fill "var(--grid-editor-marker-color)"
- :opacity 0.2}])
+ [:rect {:class (stl/css :grid-editor-header-hover)
+ :x (+ text-x (/ 18 zoom))
+ :y text-y
+ :width (- text-width (/ 36 zoom))
+ :height (- text-height (/ 5 zoom))
+ :rx (/ 3 zoom)
+ :style {:cursor "pointer"}
+ :opacity (if (and hovering? (not small?)) 0.2 0)}]
(when (not small?)
[:foreignObject {:x text-x :y text-y :width text-width :height text-height}
- [:div {:class (stl/css :grid-editor-wrapper)}
+ [:div {:class (stl/css :grid-editor-wrapper)
+ :on-context-menu handle-show-track-menu
+ :on-pointer-down handle-pointer-down
+ :on-lost-pointer-capture handle-lost-pointer-capture
+ :on-pointer-move handle-pointer-move}
[:input
{:ref track-input-ref
:style {}
@@ -759,7 +863,7 @@
:on-blur handle-blur-track-input}]
(when (and hovering? (not medium?) (not small?))
[:button {:class (stl/css :grid-editor-button)
- :on-click handle-remove-track} i/delete-refactor])]])]
+ :on-click handle-show-track-menu} i/menu-refactor])]])]
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))}
[:& track-marker
@@ -778,6 +882,7 @@
:layout-data layout-data
:shape shape
:snap-pixel? snap-pixel?
+ :drop? drop?
:start-p start-p
:track-after track-data
:track-before track-before
@@ -855,8 +960,8 @@
(mf/deps shape children)
#(gsg/calc-layout-data shape bounds children all-bounds objects))
- width (max (gpo/width-points bounds) (+ column-total-size column-total-gap))
- height (max (gpo/height-points bounds) (+ row-total-size row-total-gap))
+ width (max (gpo/width-points bounds) (+ column-total-size column-total-gap (ctl/h-padding shape)))
+ height (max (gpo/height-points bounds) (+ row-total-size row-total-gap (ctl/v-padding shape)))
handle-pointer-down
(mf/use-callback
@@ -875,7 +980,68 @@
(mf/use-callback
(mf/deps (:id shape))
(fn []
- (st/emit! (st/emit! (dwsl/add-layout-track [(:id shape)] :row ctl/default-track-value)))))]
+ (st/emit! (st/emit! (dwsl/add-layout-track [(:id shape)] :row ctl/default-track-value)))))
+
+
+ target-tracks* (mf/use-ref nil)
+ drop-track-type* (mf/use-state nil)
+ drop-track-target* (mf/use-state nil)
+
+ handle-start-reorder-track
+ (mf/use-callback
+ (mf/deps layout-data)
+ (fn [type _from-idx]
+ ;; Initialize target-tracks
+ (let [line-vec (if (= type :column) (vv 1) (hv 1))
+
+ first-point origin
+ last-point (if (= type :column) (nth bounds 1) (nth bounds 3))
+ mid-points
+ (if (= type :column)
+ (->> (:column-tracks layout-data)
+ (mapv #(gpt/add (:start-p %) (hv (/ (:size %) 2)))))
+
+ (->> (:row-tracks layout-data)
+ (mapv #(gpt/add (:start-p %) (vv (/ (:size %) 2))))))
+
+ tracks
+ (->> (d/with-prev (d/concat-vec [first-point] mid-points [last-point]))
+ (d/enumerate)
+ (keep
+ (fn [[index [current prev]]]
+ (when (some? prev)
+ [[prev current line-vec] (dec index)]))))]
+
+ (mf/set-ref-val! target-tracks* tracks)
+ (reset! drop-track-type* type))))
+
+ handle-move-reorder-track
+ (mf/use-callback
+ (fn [_type _from-idx position]
+ (let [index
+ (->> (mf/ref-val target-tracks*)
+ (d/seek (fn [[[p1 p2 v] _]]
+ (gl/is-inside-lines? [p1 v] [p2 v] position)))
+ (second))]
+ (when (some? index)
+ (reset! drop-track-target* index)))))
+
+ handle-end-reorder-track
+ (mf/use-callback
+ (mf/deps base-shape @drop-track-target*)
+ (fn [type from-index _position move-content?]
+ (when-let [to-index @drop-track-target*]
+ (let [ids [(:id base-shape)]]
+ (cond
+ (< from-index to-index)
+ (st/emit! (dwsl/reorder-layout-track ids type from-index (dec to-index) move-content?))
+
+ (> from-index to-index)
+ (st/emit! (dwsl/reorder-layout-track ids type from-index (dec to-index) move-content?)))))
+
+ (mf/set-ref-val! target-tracks* nil)
+ (reset! drop-track-type* nil)
+ (reset! drop-track-target* nil)))]
(mf/use-effect
(fn []
@@ -914,15 +1080,21 @@
:on-click handle-add-row}]])
(for [[idx column-data] (d/enumerate column-tracks)]
- [:& track {:key (dm/str "column-track-" idx)
- :shape shape
- :zoom zoom
- :type :column
- :index idx
- :layout-data layout-data
- :snap-pixel? snap-pixel?
- :track-data column-data
- :hovering? (contains? hover-columns idx)}])
+ (let [drop? (and (= :column @drop-track-type*)
+ (= idx @drop-track-target*))]
+ [:& track {:key (dm/str "column-track-" idx)
+ :shape shape
+ :zoom zoom
+ :type :column
+ :index idx
+ :layout-data layout-data
+ :snap-pixel? snap-pixel?
+ :drop? drop?
+ :track-data column-data
+ :hovering? (contains? hover-columns idx)
+ :on-start-reorder-track handle-start-reorder-track
+ :on-move-reorder-track handle-move-reorder-track
+ :on-end-reorder-track handle-end-reorder-track}]))
;; Last track resize handler
(when-not (empty? column-tracks)
@@ -940,27 +1112,36 @@
:type :column
:value (dm/str (inc (count column-tracks)))
:zoom zoom}]
- [:& resize-track-handler
- {:index (count column-tracks)
- :last? true
- :shape shape
- :layout-data layout-data
- :snap-pixel? snap-pixel?
- :start-p end-p
- :type :column
- :track-before (last column-tracks)
- :zoom zoom}]]))
+ (let [drop? (and (= :column @drop-track-type*)
+ (= (count column-tracks) @drop-track-target*))]
+ [:& resize-track-handler
+ {:index (count column-tracks)
+ :last? true
+ :drop? drop?
+ :shape shape
+ :layout-data layout-data
+ :snap-pixel? snap-pixel?
+ :start-p end-p
+ :type :column
+ :track-before (last column-tracks)
+ :zoom zoom}])]))
(for [[idx row-data] (d/enumerate row-tracks)]
- [:& track {:index idx
- :key (dm/str "row-track-" idx)
- :layout-data layout-data
- :shape shape
- :snap-pixel? snap-pixel?
- :track-data row-data
- :type :row
- :zoom zoom
- :hovering? (contains? hover-rows idx)}])
+ (let [drop? (and (= :row @drop-track-type*)
+ (= idx @drop-track-target*))]
+ [:& track {:index idx
+ :key (dm/str "row-track-" idx)
+ :layout-data layout-data
+ :shape shape
+ :snap-pixel? snap-pixel?
+ :drop? drop?
+ :track-data row-data
+ :type :row
+ :zoom zoom
+ :hovering? (contains? hover-rows idx)
+ :on-start-reorder-track handle-start-reorder-track
+ :on-move-reorder-track handle-move-reorder-track
+ :on-end-reorder-track handle-end-reorder-track}]))
(when-not (empty? row-tracks)
(let [last-track (last row-tracks)
start-p (:start-p last-track)
@@ -977,13 +1158,16 @@
:type :row
:value (dm/str (inc (count row-tracks)))
:zoom zoom}]]
- [:& resize-track-handler
- {:index (count row-tracks)
- :last? true
- :shape shape
- :layout-data layout-data
- :start-p end-p
- :type :row
- :track-before (last row-tracks)
- :snap-pixel? snap-pixel?
- :zoom zoom}]]))])])))
+ (let [drop? (and (= :row @drop-track-type*)
+ (= (count row-tracks) @drop-track-target*))]
+ [:& resize-track-handler
+ {:index (count row-tracks)
+ :last? true
+ :drop? drop?
+ :shape shape
+ :layout-data layout-data
+ :start-p end-p
+ :type :row
+ :track-before (last row-tracks)
+ :snap-pixel? snap-pixel?
+ :zoom zoom}])]))])])))
diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss
index c519a0356d..497bc2e879 100644
--- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss
+++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss
@@ -18,30 +18,35 @@
}
.grid-editor-wrapper {
+ cursor: grab;
width: 100%;
height: 80%;
display: flex;
+ flex-direction: column;
justify-content: center;
align-items: center;
}
+.grid-editor-header-hover {
+ fill: var(--grid-editor-marker-color);
+}
+
.grid-editor-label {
+ flex: 1;
background: none;
- border-bottom: calc($s-1 / var(--zoom)) solid transparent;
border: 0;
color: var(--grid-editor-marker-text);
font-family: worksans;
font-size: calc($fs-12 / var(--zoom));
font-weight: 400;
margin: 0;
- max-width: calc($s-80 / var(--zoom));
+ max-width: calc($s-60 / var(--zoom));
padding: 0;
- padding: $s-4;
+ padding: calc($s-4 / var(--zoom));
text-align: center;
&:focus {
outline: none;
- border-bottom: calc($s-1 / var(--zoom)) solid var(--grid-editor-marker-text);
}
}
diff --git a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs
index 5dcb1b6d39..3f2c7558b3 100644
--- a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs
@@ -10,7 +10,6 @@
[app.main.data.workspace.path :as drp]
[app.main.data.workspace.path.shortcuts :as sc]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.shapes.path.common :as pc]
[app.util.i18n :as i18n :refer [tr]]
@@ -40,7 +39,6 @@
(mf/defc path-actions [{:keys [shape]}]
(let [{:keys [edit-mode selected-points snap-toggled] :as all} (mf/deref pc/current-edit-path-ref)
content (:content shape)
- new-css-system (mf/use-ctx ctx/new-css-system)
enabled-buttons
(mf/use-memo
@@ -111,160 +109,80 @@
(fn [_]
(st/emit! (drp/toggle-snap))))]
- (if new-css-system
- [:div {:class (stl/css :sub-actions)}
- [:div {:class (stl/css :sub-actions-group)}
+ [:div {:class (stl/css :sub-actions)}
+ [:div {:class (stl/css :sub-actions-group)}
- ;; Draw Mode
- [:button
- {:class (stl/css-case :is-toggled (= edit-mode :draw))
- :title (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes))
- :on-click on-select-draw-mode}
- i/pentool-refactor]
+ ;; Draw Mode
+ [:button
+ {:class (stl/css-case :is-toggled (= edit-mode :draw))
+ :title (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes))
+ :on-click on-select-draw-mode}
+ i/pentool-refactor]
- ;; Edit mode
- [:button
- {:class (stl/css-case :is-toggled (= edit-mode :move))
- :title (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes))
- :on-click on-select-edit-mode}
- i/move-refactor]]
+ ;; Edit mode
+ [:button
+ {:class (stl/css-case :is-toggled (= edit-mode :move))
+ :title (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes))
+ :on-click on-select-edit-mode}
+ i/move-refactor]]
- [:div {:class (stl/css :sub-actions-group)}
- ;; Add Node
- [:button
- {:disabled (not (:add-node enabled-buttons))
- :title (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node))
- :on-click on-add-node}
- i/add-refactor]
+ [:div {:class (stl/css :sub-actions-group)}
+ ;; Add Node
+ [:button
+ {:disabled (not (:add-node enabled-buttons))
+ :title (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node))
+ :on-click on-add-node}
+ i/add-refactor]
- ;; Remove node
- [:button
- {:disabled (not (:remove-node enabled-buttons))
- :title (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node))
- :on-click on-remove-node}
- i/remove-refactor]]
+ ;; Remove node
+ [:button
+ {:disabled (not (:remove-node enabled-buttons))
+ :title (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node))
+ :on-click on-remove-node}
+ i/remove-refactor]]
- [:div {:class (stl/css :sub-actions-group)}
- ;; Merge Nodes
- [:button
- {:disabled (not (:merge-nodes enabled-buttons))
- :title (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes))
- :on-click on-merge-nodes}
- i/merge-nodes-refactor]
+ [:div {:class (stl/css :sub-actions-group)}
+ ;; Merge Nodes
+ [:button
+ {:disabled (not (:merge-nodes enabled-buttons))
+ :title (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes))
+ :on-click on-merge-nodes}
+ i/merge-nodes-refactor]
- ;; Join Nodes
- [:button
- {:disabled (not (:join-nodes enabled-buttons))
- :title (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes))
- :on-click on-join-nodes}
- i/join-nodes-refactor]
+ ;; Join Nodes
+ [:button
+ {:disabled (not (:join-nodes enabled-buttons))
+ :title (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes))
+ :on-click on-join-nodes}
+ i/join-nodes-refactor]
- ;; Separate Nodes
- [:button
- {:disabled (not (:separate-nodes enabled-buttons))
- :title (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes))
- :on-click on-separate-nodes}
- i/separate-nodes-refactor]]
+ ;; Separate Nodes
+ [:button
+ {:disabled (not (:separate-nodes enabled-buttons))
+ :title (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes))
+ :on-click on-separate-nodes}
+ i/separate-nodes-refactor]]
- ;; Make Corner
- [:div {:class (stl/css :sub-actions-group)}
- [:button
- {:disabled (not (:make-corner enabled-buttons))
- :title (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner))
- :on-click on-make-corner}
- i/to-corner-refactor]
+ ;; Make Corner
+ [:div {:class (stl/css :sub-actions-group)}
+ [:button
+ {:disabled (not (:make-corner enabled-buttons))
+ :title (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner))
+ :on-click on-make-corner}
+ i/to-corner-refactor]
- ;; Make Curve
- [:button
- {:disabled (not (:make-curve enabled-buttons))
- :title (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve))
- :on-click on-make-curve}
- i/to-curve-refactor]]
+ ;; Make Curve
+ [:button
+ {:disabled (not (:make-curve enabled-buttons))
+ :title (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve))
+ :on-click on-make-curve}
+ i/to-curve-refactor]]
- ;; Toggle snap
- [:div {:class (stl/css :sub-actions-group)}
- [:button
- {:class (stl/css-case :is-toggled snap-toggled)
- :title (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes))
- :on-click on-toggle-snap}
- i/snap-nodes-refactor]]]
-
-
-
- [:div.path-actions
- [:div.viewport-actions-group
-
- ;; Draw Mode
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when (= edit-mode :draw) "is-toggled")
- :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes))
- :on-click on-select-draw-mode}
- i/pen]
-
- ;; Edit mode
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when (= edit-mode :move) "is-toggled")
- :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes))
- :on-click on-select-edit-mode}
- i/pointer-inner]]
-
- [:div.viewport-actions-group
- ;; Add Node
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:add-node enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node))
- :on-click on-add-node}
- i/nodes-add]
-
- ;; Remove node
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:remove-node enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node))
- :on-click on-remove-node}
- i/nodes-remove]]
-
- [:div.viewport-actions-group
- ;; Merge Nodes
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:merge-nodes enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes))
- :on-click on-merge-nodes}
- i/nodes-merge]
-
- ;; Join Nodes
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:join-nodes enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes))
- :on-click on-join-nodes}
- i/nodes-join]
-
- ;; Separate Nodes
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:separate-nodes enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes))
- :on-click on-separate-nodes}
- i/nodes-separate]]
-
- ;; Make Corner
- [:div.viewport-actions-group
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:make-corner enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner))
- :on-click on-make-corner}
- i/nodes-corner]
-
- ;; Make Curve
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when-not (:make-curve enabled-buttons) "is-disabled")
- :alt (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve))
- :on-click on-make-curve}
- i/nodes-curve]]
-
- ;; Toggle snap
- [:div.viewport-actions-group
- [:div.viewport-actions-entry.tooltip.tooltip-bottom
- {:class (when snap-toggled "is-toggled")
- :alt (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes))
- :on-click on-toggle-snap}
- i/nodes-snap]]])))
+ ;; Toggle snap
+ [:div {:class (stl/css :sub-actions-group)}
+ [:button
+ {:class (stl/css-case :is-toggled snap-toggled)
+ :title (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes))
+ :on-click on-toggle-snap}
+ i/snap-nodes-refactor]]]))
diff --git a/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs b/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs
index fb295276f0..babee74956 100644
--- a/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs
@@ -13,7 +13,6 @@
[app.main.fonts :as fonts]
[app.main.rasterizer :as thr]
[app.main.store :as st]
- [app.main.ui.context :as ctx]
[app.main.ui.css-cursors :as cur]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
@@ -51,8 +50,7 @@
(mf/defc pixel-overlay
{::mf/wrap-props false}
[props]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- vport (unchecked-get props "vport")
+ (let [vport (unchecked-get props "vport")
viewport-ref (unchecked-get props "viewport-ref")
viewport-node (mf/ref-val viewport-ref)
@@ -81,8 +79,8 @@
(when-let [zoom-view-node (dom/get-element "picker-detail")]
(when-not (mf/ref-val zoom-view-context)
(mf/set-ref-val! zoom-view-context (.getContext zoom-view-node "2d")))
- (let [canvas-width (if new-css-system 260 200)
- canvas-height (if new-css-system 140 160)
+ (let [canvas-width 260
+ canvas-height 140
{brx :left bry :top} (dom/get-bounding-rect viewport-node)
x (mth/floor (- (.-clientX event) brx))
@@ -100,10 +98,10 @@
;; I don't know why, but the zoom view is offset by 24px
;; instead of 25.
- sx (- x (if new-css-system 32 24))
- sy (- y (if new-css-system 17 20))
- sw (if new-css-system 65 50)
- sh (if new-css-system 35 40)
+ sx (- x 32)
+ sy (- y 17)
+ sw 65
+ sh 35
dx 0
dy 0
dw canvas-width
diff --git a/frontend/src/app/main/ui/workspace/viewport/rules.cljs b/frontend/src/app/main/ui/workspace/viewport/rules.cljs
index 87ec78766f..af978fef0f 100644
--- a/frontend/src/app/main/ui/workspace/viewport/rules.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/rules.cljs
@@ -6,12 +6,10 @@
(ns app.main.ui.workspace.viewport.rules
(:require
- [app.common.colors :as colors]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
- [app.main.ui.context :as ctx]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as hooks]
[app.util.object :as obj]
@@ -22,8 +20,7 @@
(def rules-width 1)
(def rule-area-size 22)
(def rule-area-half-size (/ rule-area-size 2))
-(def rules-background "var(--color-gray-50)")
-(def new-css-rules-background "var(--panel-background-color)")
+(def rules-background "var(--panel-background-color)")
(def selection-area-color "var(--color-primary)")
(def selection-area-opacity 0.3)
(def over-number-size 50)
@@ -31,9 +28,8 @@
(def font-size 12)
(def font-family "worksans")
-(def font-color colors/gray-30)
-(def new-css-font-color "var(--layer-row-foreground-color)")
-(def new-css-canvas-border-radius 12)
+(def font-color "var(--layer-row-foreground-color)")
+(def canvas-border-radius 12)
;; ----------------
;; RULES
@@ -156,9 +152,8 @@
(let [rules-width (* rules-width zoom-inverse)
step (calculate-step-size zoom)
clip-id (str "clip-rule-" (d/name axis))
- new-css-system (mf/use-ctx ctx/new-css-system)
- font-color (if new-css-system new-css-font-color font-color)
- rules-background (if new-css-system new-css-rules-background rules-background)]
+ font-color font-color
+ rules-background rules-background]
[:*
(let [{:keys [x y width height]} (get-background-area vbox zoom-inverse axis)]
@@ -207,8 +202,7 @@
(mf/defc selection-area
[{:keys [vbox zoom-inverse selection-rect offset-x offset-y]}]
;; When using the format-number callls we consider if the guide is associated to a frame and we show the position relative to it with the offset
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- rules-background (if new-css-system new-css-rules-background rules-background)]
+ (let [rules-background rules-background]
[:g.selection-area
[:g
[:rect {:x (:x selection-rect)
@@ -306,9 +300,8 @@
(hooks/use-equal-memo))
show-rules? (obj/get props "show-rules?")
- new-css-system (mf/use-ctx ctx/new-css-system)
- rules-background (if new-css-system new-css-rules-background rules-background)
- border-radius (/ new-css-canvas-border-radius zoom)
+ rules-background rules-background
+ border-radius (/ canvas-border-radius zoom)
selection-rect
(mf/use-memo
@@ -324,21 +317,20 @@
[:& rules-axis {:zoom zoom :zoom-inverse zoom-inverse :vbox vbox :axis :y :offset offset-y}]])
;; Draw the rules' rounded corners in the viewport corners
- (when new-css-system
- (let [{:keys [x y width height]} vbox
- rule-area-size (if show-rules? (/ rule-area-size zoom) 0)]
- [:*
- [:path {:d (round-corner-path-tl (+ x rule-area-size) (+ y rule-area-size) border-radius)
- :style {:fill rules-background}}]
+ (let [{:keys [x y width height]} vbox
+ rule-area-size (if show-rules? (/ rule-area-size zoom) 0)]
+ [:*
+ [:path {:d (round-corner-path-tl (+ x rule-area-size) (+ y rule-area-size) border-radius)
+ :style {:fill rules-background}}]
- [:path {:d (round-corner-path-tr (+ x width (- border-radius)) (+ y rule-area-size) border-radius)
- :style {:fill rules-background}}]
+ [:path {:d (round-corner-path-tr (+ x width (- border-radius)) (+ y rule-area-size) border-radius)
+ :style {:fill rules-background}}]
- [:path {:d (round-corner-path-bl (+ x rule-area-size) (+ y height (- border-radius)) border-radius)
- :style {:fill rules-background}}]
+ [:path {:d (round-corner-path-bl (+ x rule-area-size) (+ y height (- border-radius)) border-radius)
+ :style {:fill rules-background}}]
- [:path {:d (round-corner-path-br (+ x (:width vbox) (- border-radius)) (+ y height (- border-radius)) border-radius)
- :style {:fill rules-background}}]]))
+ [:path {:d (round-corner-path-br (+ x (:width vbox) (- border-radius)) (+ y height (- border-radius)) border-radius)
+ :style {:fill rules-background}}]])
(when (and show-rules? (some? selection-rect))
[:& selection-area {:zoom zoom
diff --git a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs
index c3efb32784..04eeb79d1f 100644
--- a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs
@@ -13,7 +13,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
- [app.main.ui.icons :as i]
[app.main.ui.workspace.viewport.grid-layout-editor :refer [grid-edition-actions]]
[app.main.ui.workspace.viewport.path-actions :refer [path-actions]]
[app.util.i18n :as i18n :refer [tr]]
@@ -21,30 +20,19 @@
(mf/defc view-only-actions
[]
- (let [new-css-system (mf/use-ctx ctx/new-css-system)
- handle-close-view-mode
+ (let [handle-close-view-mode
(mf/use-callback
(fn []
(st/emit! :interrupt
(dw/set-options-mode :design)
(dw/set-workspace-read-only false))))]
- (if new-css-system
- [:div {:class (stl/css :viewport-actions)}
- [:div {:class (stl/css :viewport-actions-container)}
- [:div {:class (stl/css :viewport-actions-title)}
- [:& i18n/tr-html {:tag-name "span"
- :label "workspace.top-bar.read-only"}]]
- [:button {:class (stl/css :done-btn)
- :on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]]]
-
- ;; OLD
- [:div.viewport-actions
- [:div.viewport-actions-container
- [:div.viewport-actions-title
- [:& i18n/tr-html {:tag-name "span"
- :label "workspace.top-bar.read-only"}]]
- [:button.btn-primary {:on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]
- [:button.btn-icon-basic {:on-click handle-close-view-mode} i/close]]])))
+ [:div {:class (stl/css :viewport-actions)}
+ [:div {:class (stl/css :viewport-actions-container)}
+ [:div {:class (stl/css :viewport-actions-title)}
+ [:& i18n/tr-html {:tag-name "span"
+ :label "workspace.top-bar.read-only"}]]
+ [:button {:class (stl/css :done-btn)
+ :on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]]]))
(mf/defc top-bar
{::mf/wrap [mf/memo]}
diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs
index 58fde157b7..ec646a9665 100644
--- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.viewport.widgets
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -251,12 +252,14 @@
:width 100000
:height 24
:transform (vwu/text-transform flow-pos zoom)}
- [:div.flow-badge {:class (dom/classnames :selected selected?)}
- [:div.content {:on-pointer-down on-pointer-down
+ [:div {:class (stl/css-case :flow-badge true
+ :selected selected?)}
+ [:div {:class (stl/css :content)
+ :on-pointer-down on-pointer-down
:on-double-click on-double-click
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave}
- i/play
+ i/play-refactor
[:span (:name flow)]]]]))
(mf/defc frame-flows
diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.scss b/frontend/src/app/main/ui/workspace/viewport/widgets.scss
new file mode 100644
index 0000000000..2fc2a81daf
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/viewport/widgets.scss
@@ -0,0 +1,64 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.flow-element {
+ display: flex;
+ align-items: center;
+
+ .element-label {
+ }
+
+ .flow-name {
+ cursor: pointer;
+ }
+
+ & input.element-name {
+ background: transparent;
+ }
+}
+
+.flow-badge {
+ cursor: pointer;
+ display: flex;
+ .content {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ height: $s-24;
+ border-radius: $br-6;
+ background-color: var(--flow-tag-background-color);
+ svg {
+ @extend .button-icon;
+ height: $s-24;
+ width: $s-12;
+ stroke: var(--icon-foreground);
+ margin: 0 $s-8;
+ }
+
+ span {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: $s-8;
+ color: var(--flow-tag-foreground-color);
+ }
+ }
+
+ &.selected .content,
+ &:hover .content {
+ background-color: var(--flow-tag-background-color-hover);
+ svg {
+ stroke: var(--flow-tag-foreground-color-hover);
+ }
+
+ span {
+ color: var(--flow-tag-foreground-color-hover);
+ }
+ }
+}
diff --git a/frontend/src/app/rasterizer.cljs b/frontend/src/app/rasterizer.cljs
index d6eeb474ca..157b57a653 100644
--- a/frontend/src/app/rasterizer.cljs
+++ b/frontend/src/app/rasterizer.cljs
@@ -96,10 +96,16 @@
:method :get
:mode :cors
:omit-default-headers true})
- (rx/map :body)
- (rx/mapcat wapi/read-file-as-data-url)
- (rx/tap (fn [data-uri]
- (.set data-uri-cache uri (wapi/create-blob data-uri "text/plain")))))))
+ (rx/catch (fn [cause]
+ (log/error :hint "fetching data uri"
+ :cause cause)
+ (rx/of nil)))
+ (rx/mapcat (fn [response]
+ (if (nil? response)
+ (rx/of uri)
+ (->> (rx/of (:body response))
+ (rx/mapcat wapi/read-file-as-data-url)
+ (rx/tap (fn [data-uri] (.set data-uri-cache uri (wapi/create-blob data-uri "text/plain")))))))))))
(defn- svg-update-image!
"Updates an image in an SVG to a Data URI."
@@ -128,27 +134,53 @@
(dom/append-child! style (dom/create-text svg styles))
(dom/append-child! doc style)))
-(defn- svg-resolve-styles!
- "Resolves all fonts in an SVG to Data URIs."
- [svg styles]
+(defn- svg-resolve-external-resources
+ "Resolves all external resources in an SVG to Data URIs."
+ [styles]
(->> (rx/from (re-seq #"url\((https?://[^)]+)\)" styles))
(rx/map second)
(rx/mapcat (fn [url]
- (->> (fetch-as-data-uri url)
- (rx/map (fn [uri] [url uri])))))
-
+ (->> (fetch-as-data-uri url)
+ (rx/map (fn [uri] [url uri])))))
(rx/reduce (fn [styles [url uri]]
(str/replace styles url uri))
- styles)
+ styles)))
+
+(defn- svg-resolve-styles!
+ "Resolves all fonts in an SVG to Data URIs."
+ [svg styles]
+ (->> (svg-resolve-external-resources styles)
(rx/tap (partial svg-add-style! svg))
(rx/ignore)))
+(defn- svg-resolve-inline-styles!
+ "Resolves all inline styles in an SVG to Data URIs."
+ [svg]
+ (->> (rx/from (dom/query-all svg "[style]"))
+ (rx/mapcat (fn [node]
+ (let [styles (dom/get-attribute node "style")]
+ (->> (svg-resolve-external-resources styles)
+ (rx/tap (fn [styles] (dom/set-attribute! node "style" styles)))))))
+ (rx/ignore)))
+
+(defn- svg-resolve-style-elements!
+ "Resolves all style elements in an SVG to Data URIs."
+ [svg]
+ (->> (rx/from (dom/query-all svg "style"))
+ (rx/mapcat (fn [node]
+ (let [styles (dom/get-text node)]
+ (->> (svg-resolve-external-resources styles)
+ (rx/tap (fn [styles] (dom/set-text! node styles)))))))
+ (rx/ignore)))
+
(defn- svg-resolve-all!
"Resolves all images and fonts in an SVG to Data URIs."
[svg styles]
(rx/concat
(svg-resolve-images! svg)
(svg-resolve-styles! svg styles)
+ (svg-resolve-inline-styles! svg)
+ (svg-resolve-style-elements! svg)
(rx/of svg)))
(defn- svg-parse
diff --git a/frontend/src/app/util/debug.cljs b/frontend/src/app/util/debug.cljs
index 7fecae2192..7bf6304bde 100644
--- a/frontend/src/app/util/debug.cljs
+++ b/frontend/src/app/util/debug.cljs
@@ -75,6 +75,9 @@
;;
:grid-layout
+
+ ;; Show an overlay to the grid cells to know its properties
+ :grid-cells
})
(defn enable!
diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs
index 8b04784789..998a581ebc 100644
--- a/frontend/src/app/util/dom.cljs
+++ b/frontend/src/app/util/dom.cljs
@@ -504,6 +504,10 @@
(.setAttribute node property value))
node)
+(defn get-text [^js node]
+ (when (some? node)
+ (.-textContent node)))
+
(defn set-text! [^js node text]
(when (some? node)
(set! (.-textContent node) text))
diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs
index 4b1058f618..02964dcabe 100644
--- a/frontend/src/debug.cljs
+++ b/frontend/src/debug.cljs
@@ -21,7 +21,7 @@
[app.main.data.preview :as dp]
[app.main.data.viewer.shortcuts]
[app.main.data.workspace :as dw]
- [app.main.data.workspace.changes :as dwc]
+ [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.path.shortcuts]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shortcuts]
@@ -297,7 +297,7 @@
(let [file-id (:current-file-id @st/state)
changes (t/decode-str changes*)]
- (st/emit! (dwc/commit-changes {:redo-changes changes
+ (st/emit! (dch/commit-changes {:redo-changes changes
:undo-changes []
:save-undo? true
:file-id file-id}))))
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index f1206c084c..1d1addfc4a 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -5057,3 +5057,43 @@ msgstr "Choose image"
msgid "workspace.options.guides.title"
msgstr "Guides"
+
+msgid "workspace.context-menu.grid-track.column.duplicate"
+msgstr "Duplicate column"
+
+msgid "workspace.context-menu.grid-track.column.add-before"
+msgstr "Add 1 column to the left"
+
+msgid "workspace.context-menu.grid-track.column.add-after"
+msgstr "Add 1 column to the right"
+
+msgid "workspace.context-menu.grid-track.column.delete"
+msgstr "Delete column"
+
+msgid "workspace.context-menu.grid-track.column.delete-shapes"
+msgstr "Delete column and shapes"
+
+msgid "workspace.context-menu.grid-track.row.duplicate"
+msgstr "Duplicate row"
+
+msgid "workspace.context-menu.grid-track.row.add-before"
+msgstr "Add 1 row above"
+
+msgid "workspace.context-menu.grid-track.row.add-after"
+msgstr "Add 1 row below"
+
+msgid "workspace.context-menu.grid-track.row.delete"
+msgstr "Delete row"
+
+msgid "workspace.context-menu.grid-track.row.delete-shapes"
+msgstr "Delete row and shapes"
+
+msgid "workspace.context-menu.grid-cells.merge"
+msgstr "Merge cells"
+
+msgid "workspace.context-menu.grid-cells.area"
+msgstr "Create area"
+
+msgid "workspace.context-menu.grid-cells.create-board"
+msgstr "Create board"
+
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 7b4e5b85ed..8845dc4848 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -5146,3 +5146,43 @@ msgstr "Elegir imagen"
msgid "workspace.options.guides.title"
msgstr "Guías"
+
+msgid "workspace.context-menu.grid-track.column.duplicate"
+msgstr "Duplicar columna"
+
+msgid "workspace.context-menu.grid-track.column.add-before"
+msgstr "Añadir 1 columna a la izquierda"
+
+msgid "workspace.context-menu.grid-track.column.add-after"
+msgstr "Añadir 1 columna a la derecha"
+
+msgid "workspace.context-menu.grid-track.column.delete"
+msgstr "Borrar columna"
+
+msgid "workspace.context-menu.grid-track.column.delete-shapes"
+msgstr "Borrar columna con el contenido"
+
+msgid "workspace.context-menu.grid-track.row.duplicate"
+msgstr "Duplicar fila"
+
+msgid "workspace.context-menu.grid-track.row.add-before"
+msgstr "Añadir 1 fila encima"
+
+msgid "workspace.context-menu.grid-track.row.add-after"
+msgstr "Añadir 1 fila debajo"
+
+msgid "workspace.context-menu.grid-track.row.delete"
+msgstr "Borrar fila"
+
+msgid "workspace.context-menu.grid-track.row.delete-shapes"
+msgstr "Borrar fila con el contenido"
+
+msgid "workspace.context-menu.grid-cells.merge"
+msgstr "Fusionar celdas"
+
+msgid "workspace.context-menu.grid-cells.area"
+msgstr "Crear area"
+
+msgid "workspace.context-menu.grid-cells.create-board"
+msgstr "Crear tablero"
+