From 638cf6daff07e26fd4785ceb577ea04bc1293ef5 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Mar 2024 14:13:50 +0100 Subject: [PATCH 001/136] :lipstick: Add cosmetic enhancements to viewport comments layer That also improves performance --- frontend/src/app/main/ui/comments.cljs | 1 + .../main/ui/workspace/viewport/comments.cljs | 70 ++++++++++--------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 1147cf99a..938d108a1 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -391,6 +391,7 @@ (mf/with-layout-effect [thread-pos comments-map] (when-let [node (mf/ref-val ref)] (dom/scroll-into-view-if-needed! node))) + (when (some? comment) [:div {:class (stl/css :thread-content) :style {:top (str pos-y "px") diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs index ce44c0292..6a54a8e26 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs @@ -7,61 +7,67 @@ (ns app.main.ui.workspace.viewport.comments (:require-macros [app.main.style :as stl]) (:require + [app.common.data.macros :as dm] [app.main.data.comments :as dcm] [app.main.data.workspace.comments :as dwcm] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.comments :as cmt] - [cuerdas.core :as str] [okulary.core :as l] [rumext.v2 :as mf])) +(defn- update-position + [positions {:keys [id] :as thread}] + (if (contains? positions id) + (-> thread + (assoc :position (dm/get-in positions [id :position])) + (assoc :frame-id (dm/get-in positions [id :frame-id]))) + thread)) + (mf/defc comments-layer + {::mf/props :obj} [{:keys [vbox vport zoom file-id page-id drawing] :as props}] - (let [pos-x (* (- (:x vbox)) zoom) - pos-y (* (- (:y vbox)) zoom) + (let [pos-x (* (- (:x vbox)) zoom) + pos-y (* (- (:y vbox)) zoom) - profile (mf/deref refs/profile) - users (mf/deref refs/current-file-comments-users) - local (mf/deref refs/comments-local) - threads-position-ref (l/derived (l/in [:workspace-data :pages-index page-id :options :comment-threads-position]) st/state) - threads-position-map (mf/deref threads-position-ref) - threads-map (mf/deref refs/threads-ref) + profile (mf/deref refs/profile) + users (mf/deref refs/current-file-comments-users) + local (mf/deref refs/comments-local) - update-thread-position (fn update-thread-position [thread] - (if (contains? threads-position-map (:id thread)) - (-> thread - (assoc :position (get-in threads-position-map [(:id thread) :position])) - (assoc :frame-id (get-in threads-position-map [(:id thread) :frame-id]))) - thread)) + positions-ref + (mf/with-memo [page-id] + (-> (l/in [:workspace-data :pages-index page-id :options :comment-threads-position]) + (l/derived st/state))) - threads (->> (vals threads-map) - (filter #(= (:page-id %) page-id)) - (mapv update-thread-position) - (dcm/apply-filters local profile)) + positions (mf/deref positions-ref) + threads-map (mf/deref refs/threads-ref) + + threads + (mf/with-memo [threads-map positions local profile] + (->> (vals threads-map) + (filter #(= (:page-id %) page-id)) + (mapv (partial update-position positions)) + (dcm/apply-filters local profile))) on-draft-cancel - (mf/use-callback - #(st/emit! :interrupt)) + (mf/use-fn #(st/emit! :interrupt)) on-draft-submit - (mf/use-callback + (mf/use-fn (fn [draft] (st/emit! (dcm/create-thread-on-workspace draft))))] - (mf/use-effect - (mf/deps file-id) - (fn [] - (st/emit! (dwcm/initialize-comments file-id)) - (fn [] - (st/emit! ::dwcm/finalize)))) + (mf/with-effect [file-id] + (st/emit! (dwcm/initialize-comments file-id)) + (fn [] (st/emit! ::dwcm/finalize))) + [:div {:class (stl/css :comments-section)} [:div {:class (stl/css :workspace-comments-container) - :style {:width (str (:width vport) "px") - :height (str (:height vport) "px")}} + :style {:width (dm/str (:width vport) "px") + :height (dm/str (:height vport) "px")}} [:div {:class (stl/css :threads) - :style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}} + :style {:transform (dm/fmt "translate(%px, %px)" pos-x pos-y)}} (for [item threads] [:& cmt/thread-bubble {:thread item :zoom zoom @@ -70,7 +76,7 @@ (when-let [id (:open local)] (when-let [thread (get threads-map id)] - [:& cmt/thread-comments {:thread (update-thread-position thread) + [:& cmt/thread-comments {:thread (update-position positions thread) :users users :zoom zoom}])) From 4106e8da56814bf101fb7d7afcea5c09dc7f681f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Mar 2024 14:16:57 +0100 Subject: [PATCH 002/136] :zap: Add performance enhancements to viewport comments layer --- .../app/main/ui/workspace/viewport/comments.cljs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs index 6a54a8e26..8adbce9cd 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs @@ -27,8 +27,13 @@ (mf/defc comments-layer {::mf/props :obj} [{:keys [vbox vport zoom file-id page-id drawing] :as props}] - (let [pos-x (* (- (:x vbox)) zoom) - pos-y (* (- (:y vbox)) zoom) + (let [vbox-x (dm/get-prop vbox :x) + vbox-y (dm/get-prop vbox :y) + vport-w (dm/get-prop vport :width) + vport-h (dm/get-prop vport :height) + + pos-x (* (- vbox-x) zoom) + pos-y (* (- vbox-y) zoom) profile (mf/deref refs/profile) users (mf/deref refs/current-file-comments-users) @@ -64,8 +69,8 @@ [:div {:class (stl/css :comments-section)} [:div {:class (stl/css :workspace-comments-container) - :style {:width (dm/str (:width vport) "px") - :height (dm/str (:height vport) "px")}} + :style {:width (dm/str vport-w "px") + :height (dm/str vport-h "px")}} [:div {:class (stl/css :threads) :style {:transform (dm/fmt "translate(%px, %px)" pos-x pos-y)}} (for [item threads] From 43cd4656b4e4e2c8d2bd926b78a5846f4f06e0b0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Mar 2024 15:57:26 +0100 Subject: [PATCH 003/136] :zap: Remove props wrapping on workspace comment react components --- frontend/src/app/main/ui/workspace/comments.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index d74fa287b..19fce235f 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -27,6 +27,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (mf/defc sidebar-options + {::mf/props :obj} [{:keys [from-viewer]}] (let [{cmode :mode cshow :show} (mf/deref refs/comments-local) update-mode @@ -67,6 +68,7 @@ [:span {:class (stl/css :icon)} i/tick-refactor]]])) (mf/defc comments-sidebar + {::mf/props :obj} [{:keys [users threads page-id from-viewer]}] (let [threads-map (mf/deref refs/threads-ref) profile (mf/deref refs/profile) From ee91ab5dadcc61a506f4a398ee95fa3ea5eeb7f7 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Mar 2024 16:11:50 +0100 Subject: [PATCH 004/136] :zap: Add nano optimizations to fo_text react component --- .../src/app/main/ui/shapes/text/fo_text.cljs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/text/fo_text.cljs b/frontend/src/app/main/ui/shapes/text/fo_text.cljs index 8e2b1e528..7e2ebc504 100644 --- a/frontend/src/app/main/ui/shapes/text/fo_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/fo_text.cljs @@ -8,6 +8,7 @@ (:require [app.common.colors :as cc] [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.geom.shapes :as gsh] [app.main.ui.shapes.attrs :as attrs] [app.main.ui.shapes.text.styles :as sts] @@ -169,16 +170,16 @@ [colors color-mapping color-mapping-inverse])) (mf/defc text-shape - {::mf/wrap-props false + {::mf/props :obj ::mf/forward-ref true} - [props ref] - (let [shape (obj/get props "shape") - transform (gsh/transform-str shape) - - {:keys [id x y width height content]} shape - grow-type (obj/get props "grow-type") ;; This is only needed in workspace - ;; We add 8px to add a padding for the exporter - ;; width (+ width 8) + [{:keys [shape grow-type]} ref] + (let [transform (gsh/transform-str shape) + id (dm/get-prop shape :id) + x (dm/get-prop shape :x) + y (dm/get-prop shape :y) + width (dm/get-prop shape :width) + height (dm/get-prop shape :height) + content (get shape :content) [colors _color-mapping color-mapping-inverse] (retrieve-colors shape)] @@ -186,7 +187,7 @@ {:x x :y y :id id - :data-colors (->> colors (str/join ",")) + :data-colors (str/join "," colors) :data-mapping (-> color-mapping-inverse clj->js js/JSON.stringify) :transform transform :width (if (#{:auto-width} grow-type) 100000 width) From 85d06b10c2cf84c679000f93aa8c590655635af2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Mar 2024 16:18:57 +0100 Subject: [PATCH 005/136] :bug: Fix incorrect event handling on component annotation creation --- .../main/ui/workspace/sidebar/options/menus/component.cljs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 a016f99f3..84a888fba 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 @@ -110,9 +110,10 @@ (let [text (dom/get-value textarea)] (when-not (str/blank? text) (reset! editing* false) + (st/emit! (dw/update-component-annotation component-id text)) (when ^boolean creating? - (st/emit! (dw/set-annotations-id-for-create nil))) - (dw/update-component-annotation component-id text)))))) + (st/emit! (dw/set-annotations-id-for-create nil)))))))) + on-delete-annotation (mf/use-fn From 34126582864ae0016551ebf63c235333a965c124 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 08:46:41 +0100 Subject: [PATCH 006/136] :sparkles: Move some functions from file helpers to types.shape.layout --- common/src/app/common/files/helpers.cljc | 17 ----------------- common/src/app/common/types/shape/layout.cljc | 16 ++++++++++++++++ frontend/src/app/main/ui/shapes/frame.cljs | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/common/src/app/common/files/helpers.cljc b/common/src/app/common/files/helpers.cljc index 296d4da83..5b31328e6 100644 --- a/common/src/app/common/files/helpers.cljc +++ b/common/src/app/common/files/helpers.cljc @@ -12,7 +12,6 @@ [app.common.schema :as sm] [app.common.types.components-list :as ctkl] [app.common.types.pages-list :as ctpl] - [app.common.types.shape.layout :as ctl] [app.common.uuid :as uuid] [clojure.set :as set] [cuerdas.core :as str])) @@ -741,22 +740,6 @@ (d/seek root-frame?) :id)) -(defn comparator-layout-z-index - [[idx-a child-a] [idx-b child-b]] - (cond - (> (ctl/layout-z-index child-a) (ctl/layout-z-index child-b)) 1 - (< (ctl/layout-z-index child-a) (ctl/layout-z-index child-b)) -1 - (< idx-a idx-b) 1 - (> idx-a idx-b) -1 - :else 0)) - -(defn sort-layout-children-z-index - [children] - (->> children - (d/enumerate) - (sort comparator-layout-z-index) - (mapv second))) - (defn common-parent-frame "Search for the common frame for the selected shapes. Otherwise returns the root frame" [objects selected] diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 7c60ad412..b65f7b83b 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -536,6 +536,22 @@ ([shape] (or (:layout-item-z-index shape) 0))) +(defn- comparator-layout-z-index + [[idx-a child-a] [idx-b child-b]] + (cond + (> (layout-z-index child-a) (layout-z-index child-b)) 1 + (< (layout-z-index child-a) (layout-z-index child-b)) -1 + (< idx-a idx-b) 1 + (> idx-a idx-b) -1 + :else 0)) + +(defn sort-layout-children-z-index + [children] + (->> children + (d/enumerate) + (sort comparator-layout-z-index) + (mapv second))) + (defn change-h-sizing? [frame-id objects children-ids] (and (flex-layout? objects frame-id) diff --git a/frontend/src/app/main/ui/shapes/frame.cljs b/frontend/src/app/main/ui/shapes/frame.cljs index 705ce3233..64bd709f9 100644 --- a/frontend/src/app/main/ui/shapes/frame.cljs +++ b/frontend/src/app/main/ui/shapes/frame.cljs @@ -168,7 +168,7 @@ childs (unchecked-get props "childs") childs (cond-> childs (ctl/any-layout? shape) - (cfh/sort-layout-children-z-index))] + (ctl/sort-layout-children-z-index))] [:> frame-container props [:g.frame-children {:opacity (:opacity shape)} From 6fe85465a12ac263ab371afc2b7573359428d838 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 08:51:15 +0100 Subject: [PATCH 007/136] :zap: Add minor performance enhacement on shape layout functions --- common/src/app/common/types/shape/layout.cljc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index b65f7b83b..ea2f69dae 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -8,6 +8,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.files.helpers :as cfh] [app.common.geom.shapes.grid-layout.areas :as sga] [app.common.math :as mth] [app.common.schema :as sm] @@ -47,7 +48,8 @@ #{:flex :grid}) (def flex-direction-types - #{:row :reverse-row :row-reverse :column :reverse-column :column-reverse}) ;;TODO remove reverse-column and reverse-row after script + ;;TODO remove reverse-column and reverse-row after script + #{:row :reverse-row :row-reverse :column :reverse-column :column-reverse}) (def grid-direction-types #{:row :column}) @@ -128,7 +130,7 @@ (def grid-cell-justify-self-types #{:auto :start :center :end :stretch}) -(sm/define! ::grid-cell +(sm/def! ::grid-cell [:map {:title "GridCell"} [:id ::sm/uuid] [:area-name {:optional true} :string] @@ -142,7 +144,7 @@ [:shapes [:vector {:gen/max 1} ::sm/uuid]]]) -(sm/define! ::grid-track +(sm/def! ::grid-track [:map {:title "GridTrack"} [:type [::sm/one-of grid-track-types]] [:value {:optional true} [:maybe ::sm/safe-number]]]) @@ -197,14 +199,14 @@ ([objects id] (flex-layout? (get objects id))) ([shape] - (and (= :frame (:type shape)) + (and (cfh/frame-shape? shape) (= :flex (:layout shape))))) (defn grid-layout? ([objects id] (grid-layout? (get objects id))) ([shape] - (and (= :frame (:type shape)) + (and (cfh/frame-shape? shape) (= :grid (:layout shape))))) (defn any-layout? @@ -212,7 +214,10 @@ (any-layout? (get objects id))) ([shape] - (or (flex-layout? shape) (grid-layout? shape)))) + (and (cfh/frame-shape? shape) + (let [layout (:layout shape)] + (or (= :flex layout) + (= :grid layout)))))) (defn flex-layout-immediate-child? [objects shape] (let [parent-id (:parent-id shape) From d2059475f00bbb8c6c597613606f31a8c8ea852d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 10:58:10 +0100 Subject: [PATCH 008/136] :zap: Add minor performance enhancement for `inside-layout?` helper --- common/src/app/common/types/shape/layout.cljc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index ea2f69dae..c39545041 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -267,20 +267,21 @@ (defn inside-layout? "Check if the shape is inside a layout" [objects shape] - - (loop [current-id (:id shape)] - (let [current (get objects current-id)] + (loop [current-id (dm/get-prop shape :id)] + (let [current (get objects current-id) + parent-id (dm/get-prop current :parent-id)] (cond - (or (nil? current) (= current-id (:parent-id current))) + (or (nil? current) (= current-id parent-id)) false - (= :frame (:type current)) + (cfh/frame-shape? current-id) (:layout current) :else - (recur (:parent-id current)))))) + (recur parent-id))))) -(defn wrap? [{:keys [layout-wrap-type]}] +(defn wrap? + [{:keys [layout-wrap-type]}] (= layout-wrap-type :wrap)) (defn fill-width? From cac785f3e14bb98244ffea0dc483d9565d83b8dc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 11:05:32 +0100 Subject: [PATCH 009/136] :lipstick: Add cosmetic improvements to dashboard import modal code --- .../src/app/main/ui/dashboard/import.cljs | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index 8bca69f80..2d218e06c 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -36,7 +36,7 @@ (defn use-import-file [project-id on-finish-import] - (mf/use-callback + (mf/use-fn (mf/deps project-id on-finish-import) (fn [files] (when files @@ -52,7 +52,9 @@ :on-finish-import on-finish-import}))))))) (mf/defc import-form - {::mf/forward-ref true} + {::mf/forward-ref true + ::mf/props :obj} + [{:keys [project-id on-finish-import]} external-ref] (let [on-file-selected (use-import-file project-id on-finish-import)] @@ -62,23 +64,25 @@ :ref external-ref :on-selected on-file-selected}]])) -(defn update-file [files file-id new-name] - (->> files - (mapv - (fn [file] - (let [new-name (str/trim new-name)] - (cond-> file - (and (= (:file-id file) file-id) - (not= "" new-name)) - (assoc :name new-name))))))) +(defn update-file + [files file-id new-name] + (mapv + (fn [file] + (let [new-name (str/trim new-name)] + (cond-> file + (and (= (:file-id file) file-id) + (not= "" new-name)) + (assoc :name new-name)))) + files)) -(defn remove-file [files file-id] - (->> files - (mapv - (fn [file] - (cond-> file - (= (:file-id file) file-id) - (assoc :deleted? true)))))) +(defn remove-file + [files file-id] + (mapv + (fn [file] + (cond-> file + (= (:file-id file) file-id) + (assoc :deleted? true))) + files)) (defn set-analyze-error [files uri error] @@ -89,7 +93,8 @@ (-> (assoc :status :analyze-error) (assoc :error error))))))) -(defn set-analyze-result [files uri type data] +(defn set-analyze-result + [files uri type data] (let [existing-files? (into #{} (->> files (map :file-id) (filter some?))) replace-file (fn [file] @@ -106,12 +111,14 @@ [file]))] (into [] (mapcat replace-file) files))) -(defn mark-files-importing [files] +(defn mark-files-importing + [files] (->> files (filter #(= :ready (:status %))) (mapv #(assoc % :status :importing)))) -(defn update-status [files file-id status progress errors] +(defn update-status + [files file-id status progress errors] (->> files (mapv (fn [file] (cond-> file @@ -124,7 +131,7 @@ (= file-id (:file-id file)) (assoc :errors errors)))))) -(defn parse-progress-message +(defn- parse-progress-message [message] (case (:type message) :upload-data @@ -151,7 +158,8 @@ (str message))) (mf/defc import-entry - [{:keys [state file editing? can-be-deleted?]}] + {::mf/props :obj} + [{:keys [state file editing? can-be-deleted]}] (let [loading? (or (= :analyzing (:status file)) (= :importing (:status file))) analyze-error? (= :analyze-error (:status file)) @@ -163,7 +171,7 @@ progress (:progress file) handle-edit-key-press - (mf/use-callback + (mf/use-fn (fn [e] (when (or (kbd/enter? e) (kbd/esc? e)) (dom/prevent-default e) @@ -171,7 +179,7 @@ (dom/blur! (dom/get-target e))))) handle-edit-blur - (mf/use-callback + (mf/use-fn (mf/deps file) (fn [e] (let [value (dom/get-target-val e)] @@ -179,13 +187,13 @@ (update :files update-file (:file-id file) value)))))) handle-edit-entry - (mf/use-callback + (mf/use-fn (mf/deps file) (fn [] (swap! state assoc :editing (:file-id file)))) handle-remove-entry - (mf/use-callback + (mf/use-fn (mf/deps file) (fn [] (swap! state update :files remove-file (:file-id file))))] @@ -224,7 +232,7 @@ [: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? + (when can-be-deleted [:button {:on-click handle-remove-entry} i/delete-refactor])]] (cond analyze-error? @@ -252,7 +260,8 @@ (mf/defc import-dialog {::mf/register modal/components - ::mf/register-as :import} + ::mf/register-as :import + ::mf/props :obj} [{:keys [project-id files template on-finish-import]}] (let [state (mf/use-state {:status :analyzing @@ -262,7 +271,7 @@ (mapv #(assoc % :status :analyzing)))}) analyze-import - (mf/use-callback + (mf/use-fn (fn [files] (->> (uw/ask-many! {:cmd :analyze-import @@ -277,7 +286,7 @@ (swap! state update :files set-analyze-result uri type data))))))) import-files - (mf/use-callback + (mf/use-fn (fn [project-id files] (st/emit! (ptk/event ::ev/event {::ev/name "import-files" :num-files (count files)})) @@ -291,7 +300,7 @@ (swap! state update :files update-status file-id status message errors)))))) handle-cancel - (mf/use-callback + (mf/use-fn (mf/deps (:editing @state)) (fn [event] (when (nil? (:editing @state)) @@ -334,7 +343,7 @@ handle-continue - (mf/use-callback + (mf/use-fn (mf/deps project-id (:files @state)) (fn [event] (dom/prevent-default event) @@ -343,7 +352,7 @@ (continue-files)))) handle-accept - (mf/use-callback + (mf/use-fn (fn [event] (dom/prevent-default event) (st/emit! (modal/hide)) @@ -400,13 +409,13 @@ :key (dm/str (:uri file)) :file file :editing? editing? - :can-be-deleted? (> (count files) 1)}])) + :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}])] + :can-be-deleted false}])] [:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :action-buttons)} From afd373ffeefaf6b8992b449d8ab54d4e6b3a46ec Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 17:07:41 +0100 Subject: [PATCH 010/136] :sparkles: Simplify implementation of d/name --- common/src/app/common/data.cljc | 21 +++++++++---------- .../sidebar/options/menus/constraints.cljs | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/common/src/app/common/data.cljc b/common/src/app/common/data.cljc index 0dcf23e7e..736803631 100644 --- a/common/src/app/common/data.cljc +++ b/common/src/app/common/data.cljc @@ -716,20 +716,19 @@ (defn name "Improved version of name that won't fail if the input is not a keyword" - ([maybe-keyword] (name maybe-keyword nil)) - ([maybe-keyword default-value] - (cond - (keyword? maybe-keyword) - (c/name maybe-keyword) + [maybe-keyword] + (cond + (nil? maybe-keyword) + nil - (string? maybe-keyword) - maybe-keyword + (keyword? maybe-keyword) + (c/name maybe-keyword) - (nil? maybe-keyword) default-value + (string? maybe-keyword) + maybe-keyword - :else - (or default-value - (str maybe-keyword))))) + :else + (str maybe-keyword))) (defn prefix-keyword "Given a keyword and a prefix will return a new keyword with the prefix attached 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 44d5182ec..538b4f960 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 @@ -209,12 +209,12 @@ [:div {:class (stl/css :contraints-selects)} [:div {:class (stl/css :horizontal-select)} [:& select - {:default-value (d/name constraints-h "scale") + {:default-value (d/nilv (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") + {:default-value (d/nilv (d/name constraints-v) "scale") :options options-v :on-change on-constraint-v-select-changed}]] (when first-level? From c3f37fb8a363adc244f6af0497e7fc1a1155b4c1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 13:08:55 +0100 Subject: [PATCH 011/136] :recycle: Refactor import dialog on dashboard --- .../src/app/main/ui/dashboard/import.cljs | 546 ++++++++++-------- .../src/app/main/ui/dashboard/import.scss | 1 + 2 files changed, 310 insertions(+), 237 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index 2d218e06c..2d079a778 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -38,17 +38,17 @@ [project-id on-finish-import] (mf/use-fn (mf/deps project-id on-finish-import) - (fn [files] - (when files - (let [files (->> files - (mapv - (fn [file] - {:name (.-name file) - :uri (wapi/create-uri file)})))] + (fn [entries] + (let [entries (->> entries + (mapv (fn [file] + {:name (.-name file) + :uri (wapi/create-uri file)})) + (not-empty))] + (when entries (st/emit! (modal/show {:type :import :project-id project-id - :files files + :entries entries :on-finish-import on-finish-import}))))))) (mf/defc import-form @@ -56,7 +56,6 @@ ::mf/props :obj} [{:keys [project-id on-finish-import]} external-ref] - (let [on-file-selected (use-import-file project-id on-finish-import)] [:form.import-file {:aria-hidden "true"} [:& file-uploader {:accept ".penpot,.zip" @@ -64,72 +63,70 @@ :ref external-ref :on-selected on-file-selected}]])) -(defn update-file - [files file-id new-name] - (mapv - (fn [file] - (let [new-name (str/trim new-name)] - (cond-> file - (and (= (:file-id file) file-id) - (not= "" new-name)) - (assoc :name new-name)))) - files)) +(defn- update-entry-name + [entries file-id new-name] + (mapv (fn [entry] + (let [new-name (str/trim new-name)] + (cond-> entry + (and (= (:file-id entry) file-id) + (not= "" new-name)) + (assoc :name new-name)))) + entries)) -(defn remove-file - [files file-id] - (mapv - (fn [file] - (cond-> file - (= (:file-id file) file-id) - (assoc :deleted? true))) - files)) +(defn- remove-entry + [entries file-id] + (mapv (fn [entry] + (cond-> entry + (= (:file-id entry) file-id) + (assoc :deleted true))) + entries)) -(defn set-analyze-error - [files uri error] - (->> files - (mapv (fn [file] - (cond-> file - (= uri (:uri file)) +(defn- update-with-analyze-error + [entries uri error] + (->> entries + (mapv (fn [entry] + (cond-> entry + (= uri (:uri entry)) (-> (assoc :status :analyze-error) (assoc :error error))))))) -(defn set-analyze-result - [files uri type data] - (let [existing-files? (into #{} (->> files (map :file-id) (filter some?))) - replace-file - (fn [file] - (if (and (= uri (:uri file)) - (= (:status file) :analyzing)) - (->> (:files data) - (remove (comp existing-files? first)) - (mapv (fn [[file-id file-data]] - (-> file-data - (assoc :file-id file-id - :status :ready - :uri uri - :type type))))) - [file]))] - (into [] (mapcat replace-file) files))) +(defn- update-with-analyze-result + [entries uri type result] + (let [existing-entries? (into #{} (keep :file-id) entries) + replace-entry + (fn [entry] + (if (and (= uri (:uri entry)) + (= (:status entry) :analyzing)) + (->> (:files result) + (remove (comp existing-entries? first)) + (map (fn [[file-id file-data]] + (-> file-data + (assoc :file-id file-id) + (assoc :status :ready) + (assoc :uri uri) + (assoc :type type))))) + [entry]))] + (into [] (mapcat replace-entry) entries))) -(defn mark-files-importing - [files] - (->> files +(defn- mark-entries-importing + [entries] + (->> entries (filter #(= :ready (:status %))) (mapv #(assoc % :status :importing)))) -(defn update-status - [files file-id status progress errors] - (->> files - (mapv (fn [file] - (cond-> file - (and (= file-id (:file-id file)) (not= status :import-progress)) - (assoc :status status) +(defn- update-entry-status + [entries file-id status progress errors] + (mapv (fn [entry] + (cond-> entry + (and (= file-id (:file-id entry)) (not= status :import-progress)) + (assoc :status status) - (and (= file-id (:file-id file)) (= status :import-progress)) - (assoc :progress progress) + (and (= file-id (:file-id entry)) (= status :import-progress)) + (assoc :progress progress) - (= file-id (:file-id file)) - (assoc :errors errors)))))) + (= file-id (:file-id entry)) + (assoc :errors errors))) + entries)) (defn- parse-progress-message [message] @@ -157,53 +154,116 @@ (str message))) +(defn- has-status-importing? + [item] + (= (:status item) :importing)) + +(defn- has-status-analyzing? + [item] + (= (:status item) :analyzing)) + +(defn- has-status-analyze-error? + [item] + (= (:status item) :analyzing)) + +(defn- has-status-success? + [item] + (and (= (:status item) :import-finish) + (empty? (:errors item)))) + +(defn- has-status-error? + [item] + (and (= (:status item) :import-finish) + (d/not-empty? (:errors item)))) + +(defn- has-status-ready? + [item] + (and (= :ready (:status item)) + (not (:deleted item)))) + +(defn- analyze-entries + [state entries] + (->> (uw/ask-many! + {:cmd :analyze-import + :files entries + :features @features/features-ref}) + (rx/mapcat #(rx/delay emit-delay (rx/of %))) + (rx/filter some?) + (rx/subs! + (fn [{:keys [uri data error type] :as msg}] + (if (some? error) + (swap! state update-with-analyze-error uri error) + (swap! state update-with-analyze-result uri type data)))))) + +(defn- import-files! + [state project-id entries] + (st/emit! (ptk/data-event ::ev/event {::ev/name "import-files" + :num-files (count entries)})) + (->> (uw/ask-many! + {:cmd :import-files + :project-id project-id + :files entries + :features @features/features-ref}) + (rx/subs! + (fn [{:keys [file-id status message errors] :as msg}] + (swap! state update-entry-status file-id status message errors))))) + (mf/defc import-entry - {::mf/props :obj} - [{:keys [state file editing? can-be-deleted]}] - (let [loading? (or (= :analyzing (:status file)) - (= :importing (:status file))) - analyze-error? (= :analyze-error (:status file)) - import-finish? (= :import-finish (:status file)) - import-error? (= :import-error (:status file)) - import-warn? (d/not-empty? (:errors file)) - ready? (= :ready (:status file)) - is-shared? (:shared file) - progress (:progress file) + {::mf/props :obj + ::mf/memo true + ::mf/private true} + [{:keys [entries entry edition can-be-deleted on-edit on-change on-delete]}] + (let [status (:status entry) + loading? (or (= :analyzing status) + (= :importing status)) + analyze-error? (= :analyze-error status) + import-finish? (= :import-finish status) + import-error? (= :import-error status) + import-warn? (d/not-empty? (:errors entry)) + ready? (= :ready status) + is-shared? (:shared entry) + progress (:progress entry) - handle-edit-key-press + file-id (:file-id entry) + editing? (and (some? file-id) (= edition file-id)) + + on-edit-key-press (mf/use-fn - (fn [e] - (when (or (kbd/enter? e) (kbd/esc? e)) - (dom/prevent-default e) - (dom/stop-propagation e) - (dom/blur! (dom/get-target e))))) + (fn [event] + (when (or (kbd/enter? event) + (kbd/esc? event)) + (dom/prevent-default event) + (dom/stop-propagation event) + (dom/blur! (dom/get-target event))))) - handle-edit-blur + on-edit-blur (mf/use-fn - (mf/deps file) - (fn [e] - (let [value (dom/get-target-val e)] - (swap! state #(-> (assoc % :editing nil) - (update :files update-file (:file-id file) value)))))) + (mf/deps file-id on-change) + (fn [event] + (let [value (dom/get-target-val event)] + (on-change file-id value event)))) - handle-edit-entry + on-edit' (mf/use-fn - (mf/deps file) - (fn [] - (swap! state assoc :editing (:file-id file)))) + (mf/deps file-id on-change) + (fn [event] + (when (fn? on-edit) + (on-edit file-id event)))) - handle-remove-entry + on-delete' (mf/use-fn - (mf/deps file) - (fn [] - (swap! state update :files remove-file (:file-id file))))] + (mf/deps file-id on-delete) + (fn [event] + (when (fn? on-delete) + (on-delete file-id event))))] - [: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 @@ -219,26 +279,28 @@ [: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}]] + :default-value (:name entry) + :on-key-press on-edit-key-press + :on-blur on-edit-blur}]] [:div {:class (stl/css :file-name-label)} - (:name file) - (when is-shared? + (:name entry) + (when ^boolean is-shared? [:span {:class (stl/css :icon)} 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 (and (= "application/zip" (:type entry)) + (= status :ready)) + [:button {:on-click on-edit'} i/curve-refactor]) (when can-be-deleted - [:button {:on-click handle-remove-entry} i/delete-refactor])]] + [:button {:on-click on-delete'} i/delete-refactor])]] + (cond analyze-error? [:div {:class (stl/css :error-message)} - (if (some? (:error file)) - (tr (:error file)) + (if (some? (:error entry)) + (tr (:error entry)) (tr "dashboard.import.analyze-error"))] import-error? @@ -249,139 +311,143 @@ [: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))] + (for [library-id (:libraries entry)] + (let [library-data (d/seek #(= library-id (:file-id %)) entries) + error? (or (:deleted library-data) + (:import-error library-data))] (when (some? library-data) - [:div {:class (stl/css :linked-library)} + [:div {:class (stl/css :linked-library) + :key (dm/str library-id)} (:name library-data) - [:span {:class (stl/css-case :linked-library-tag true - :error error?)} i/detach-refactor]])))]])) + [:span {:class (stl/css-case + :linked-library-tag true + :error error?)} + i/detach-refactor]])))]])) (mf/defc import-dialog {::mf/register modal/components ::mf/register-as :import ::mf/props :obj} - [{:keys [project-id files template on-finish-import]}] - (let [state (mf/use-state - {:status :analyzing - :editing nil - :importing-templates 0 - :files (->> files - (mapv #(assoc % :status :analyzing)))}) - analyze-import - (mf/use-fn - (fn [files] - (->> (uw/ask-many! - {:cmd :analyze-import - :files files - :features @features/features-ref}) - (rx/mapcat #(rx/delay emit-delay (rx/of %))) - (rx/filter some?) - (rx/subs! - (fn [{:keys [uri data error type] :as msg}] - (if (some? error) - (swap! state update :files set-analyze-error uri error) - (swap! state update :files set-analyze-result uri type data))))))) + [{:keys [project-id entries template on-finish-import]}] - import-files - (mf/use-fn - (fn [project-id files] - (st/emit! (ptk/event ::ev/event {::ev/name "import-files" - :num-files (count files)})) - (->> (uw/ask-many! - {:cmd :import-files - :project-id project-id - :files files - :features @features/features-ref}) - (rx/subs! - (fn [{:keys [file-id status message errors] :as msg}] - (swap! state update :files update-status file-id status message errors)))))) + (mf/with-effect [] + ;; dispose uris when the component is umount + (fn [] (run! wapi/revoke-uri (map :uri entries)))) - handle-cancel + (let [entries* (mf/use-state + (fn [] (mapv #(assoc % :status :analyzing) entries))) + entries (deref entries*) + + status* (mf/use-state :analyzing) + status (deref status*) + + edition* (mf/use-state nil) + edition (deref edition*) + + on-template-cloned-success (mf/use-fn - (mf/deps (:editing @state)) + (fn [] + (swap! status* (constantly :importing)) + ;; (swap! state assoc :status :importing :importing-templates 0) + (st/emit! (dd/fetch-recent-files)))) + + on-template-cloned-error + (mf/use-fn + (fn [cause] + (swap! status* (constantly :error)) + ;; (swap! state assoc :status :error :importing-templates 0) + (errors/print-error! cause) + (rx/of (modal/hide) + (msg/error (tr "dashboard.libraries-and-templates.import-error"))))) + + continue-entries + (mf/use-fn + (mf/deps entries) + (fn [] + (let [entries (filterv has-status-ready? entries)] + (swap! status* (constantly :importing)) + (swap! entries* mark-entries-importing) + (import-files! entries* project-id entries)))) + + continue-template + (mf/use-fn + (mf/deps on-template-cloned-success + on-template-cloned-error + template) + (fn [] + (let [mdata {:on-success on-template-cloned-success + :on-error on-template-cloned-error} + params {:project-id project-id :template-id (:id template)}] + (swap! status* (constantly :importing)) + (st/emit! (dd/clone-template (with-meta params mdata)))))) + + on-edit + (mf/use-fn + (fn [file-id _event] + (swap! edition* (constantly file-id)))) + + on-entry-change + (mf/use-fn + (fn [file-id value] + (swap! edition* (constantly nil)) + (swap! entries* update-entry-name file-id value))) + + on-entry-delete + (mf/use-fn + (fn [file-id] + (swap! entries* remove-entry file-id))) + + on-cancel + (mf/use-fn + (mf/deps edition) (fn [event] - (when (nil? (:editing @state)) + (when (nil? edition) (dom/prevent-default event) (st/emit! (modal/hide))))) - on-template-cloned-success - (fn [] - (swap! state assoc :status :importing :importing-templates 0) - (st/emit! (dd/fetch-recent-files))) - - on-template-cloned-error - (fn [cause] - (swap! state assoc :status :error :importing-templates 0) - (errors/print-error! cause) - (rx/of (modal/hide) - (msg/error (tr "dashboard.libraries-and-templates.import-error")))) - - continue-files - (fn [] - (let [files (->> @state :files (filterv #(and (= :ready (:status %)) (not (:deleted? %)))))] - (import-files project-id files)) - - (swap! state - (fn [state] - (-> state - (assoc :status :importing) - (update :files mark-files-importing))))) - - continue-template - (fn [] - (let [mdata {:on-success on-template-cloned-success - :on-error on-template-cloned-error} - params {:project-id project-id :template-id (:id template)}] - (swap! state - (fn [state] - (-> state - (assoc :status :importing :importing-templates 1)))) - (st/emit! (dd/clone-template (with-meta params mdata))))) - - - handle-continue + on-continue (mf/use-fn - (mf/deps project-id (:files @state)) + (mf/deps template + continue-template + continue-entries) (fn [event] (dom/prevent-default event) (if (some? template) (continue-template) - (continue-files)))) + (continue-entries)))) - handle-accept + on-accept (mf/use-fn + (mf/deps on-finish-import) (fn [event] (dom/prevent-default event) (st/emit! (modal/hide)) - (when on-finish-import (on-finish-import)))) + (when (fn? on-finish-import) + (on-finish-import)))) - files (->> (:files @state) (filterv (comp not :deleted?))) + entries (filterv (comp not :deleted) entries) + num-importing (+ (count (filterv has-status-importing? entries)) + (if (some? template) 1 0)) - num-importing (+ - (->> files (filter #(= (:status %) :importing)) count) - (:importing-templates @state)) + success-num (if (some? template) + 1 + (count (filterv has-status-success? entries))) - warning-files (->> files (filter #(and (= (:status %) :import-finish) (d/not-empty? (:errors %)))) count) - success-files (->> files (filter #(and (= (:status %) :import-finish) (empty? (:errors %)))) count) - pending-analysis? (> (->> files (filter #(= (:status %) :analyzing)) count) 0) - pending-import? (> num-importing 0) + errors? (or (some has-status-error? entries) + (zero? (count entries))) - valid-files? (or (some? template) - (> (+ (->> files (filterv (fn [x] (not= (:status x) :analyze-error))) count)) 0))] - (mf/use-effect - (fn [] - (let [sub (analyze-import files)] - #(rx/dispose! sub)))) + pending-analysis? (some has-status-analyzing? entries) + pending-import? (pos? num-importing) + valid-all-entries? (or (some? template) + (not (some has-status-analyze-error? entries)))] - (mf/use-effect - (fn [] - ;; dispose uris when the component is umount - #(doseq [file files] - (wapi/revoke-uri (:uri file))))) + + ;; Run analyze operation on component mount + (mf/with-effect [] + (let [sub (analyze-entries entries* entries)] + (partial rx/dispose! sub))) [:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)} @@ -389,52 +455,58 @@ [:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")] [:button {:class (stl/css :modal-close-btn) - :on-click handle-cancel} i/close-refactor]] + :on-click on-cancel} i/close-refactor]] [:div {:class (stl/css :modal-content)} + (when (and (= :analyzing status) errors?) + [:& context-notification + {:type :warning + :content (tr "dashboard.import.import-warning")}]) - (when (and (= :importing (:status @state)) (not pending-import?)) - (if (> warning-files 0) + (when (and (= :importing status) (not ^boolean pending-import?)) + (cond + errors? [:& context-notification {:type :warning - :content (tr "dashboard.import.import-warning" warning-files success-files)}] + :content (tr "dashboard.import.import-warning")}] + + :else [:& context-notification {:type :success - :content (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))}])) + :content (tr "dashboard.import.import-message" (i18n/c success-num))}])) - (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)}])) + (for [entry entries] + [:& import-entry {:edition edition + :key (dm/str (:uri entry)) + :entry entry + :entries entries + :on-edit on-edit + :on-change on-entry-change + :on-delete on-entry-delete + :can-be-deleted (> (count entries) 1)}]) (when (some? template) - [:& import-entry {:state state - :file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready)) - :editing? false + [:& import-entry {:entry (assoc template :status :ready) :can-be-deleted false}])] [:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :action-buttons)} - (when (= :analyzing (:status @state)) + (when (= :analyzing status) [:input {:class (stl/css :cancel-button) :type "button" :value (tr "labels.cancel") - :on-click handle-cancel}]) + :on-click on-cancel}]) - (when (= :analyzing (:status @state)) + (when (and (= :analyzing status) (not errors?)) [:input {:class (stl/css :accept-btn) :type "button" :value (tr "labels.continue") - :disabled (or pending-analysis? (not valid-files?)) - :on-click handle-continue}]) + :disabled (or pending-analysis? (not valid-all-entries?)) + :on-click on-continue}]) - (when (= :importing (:status @state)) + (when (and (= :importing status) (not errors?)) [:input {:class (stl/css :accept-btn) :type "button" :value (tr "labels.accept") - :disabled (or pending-import? (not valid-files?)) - :on-click handle-accept}])]]]])) + :disabled (or pending-import? (not valid-all-entries?)) + :on-click on-accept}])]]]])) diff --git a/frontend/src/app/main/ui/dashboard/import.scss b/frontend/src/app/main/ui/dashboard/import.scss index 0fc0c620f..a89dda6da 100644 --- a/frontend/src/app/main/ui/dashboard/import.scss +++ b/frontend/src/app/main/ui/dashboard/import.scss @@ -33,6 +33,7 @@ grid-template-columns: 1fr; gap: $s-16; margin-bottom: $s-24; + min-height: 40px; } .action-buttons { From 07b8a2a6e6c9e414e8923094297089937d33a747 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 19:06:29 +0100 Subject: [PATCH 012/136] :sparkles: Restrict http methods on RPC handlers --- backend/src/app/http/errors.clj | 8 ++++++-- backend/src/app/rpc.clj | 36 ++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/backend/src/app/http/errors.clj b/backend/src/app/http/errors.clj index 580cd6703..18350d21d 100644 --- a/backend/src/app/http/errors.clj +++ b/backend/src/app/http/errors.clj @@ -60,8 +60,12 @@ (defmethod handle-error :restriction [err _ _] - {::rres/status 400 - ::rres/body (ex-data err)}) + (let [{:keys [code] :as data} (ex-data err)] + (if (= code :method-not-allowed) + {::rres/status 405 + ::rres/body data} + {::rres/status 400 + ::rres/body data}))) (defmethod handle-error :rate-limit [err _ _] diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 2f999a08e..8ae7a38d6 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -31,6 +31,7 @@ [app.util.services :as sv] [app.util.time :as dt] [clojure.spec.alpha :as s] + [cuerdas.core :as str] [integrant.core :as ig] [promesa.core :as p] [ring.request :as rreq] @@ -71,24 +72,31 @@ (defn- rpc-handler "Ring handler that dispatches cmd requests and convert between internal async flow into ring async flow." - [methods {:keys [params path-params] :as request}] - (let [type (keyword (:type path-params)) - etag (rreq/get-header request "if-none-match") - profile-id (or (::session/profile-id request) - (::actoken/profile-id request)) + [methods {:keys [params path-params method] :as request}] + (let [handler-name (:type path-params) + etag (rreq/get-header request "if-none-match") + profile-id (or (::session/profile-id request) + (::actoken/profile-id request)) - data (-> params - (assoc ::request-at (dt/now)) - (assoc ::session/id (::session/id request)) - (assoc ::cond/key etag) - (cond-> (uuid? profile-id) - (assoc ::profile-id profile-id))) + data (-> params + (assoc ::request-at (dt/now)) + (assoc ::session/id (::session/id request)) + (assoc ::cond/key etag) + (cond-> (uuid? profile-id) + (assoc ::profile-id profile-id))) - data (vary-meta data assoc ::http/request request) - method (get methods type default-handler)] + data (vary-meta data assoc ::http/request request) + handler-fn (get methods (keyword handler-name) default-handler)] + + (when (and (or (= method :get) + (= method :head)) + (not (str/starts-with? handler-name "get-"))) + (ex/raise :type :restriction + :code :method-not-allowed + :hint "method not allowed for this request")) (binding [cond/*enabled* true] - (let [response (method data)] + (let [response (handler-fn data)] (handle-response request response))))) (defn- wrap-metrics From 1bc4001e70c9bc4ea72019bd261de17e48f1dc14 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 5 Mar 2024 19:44:09 +0100 Subject: [PATCH 013/136] :sparkles: Add the ability to set :string for cookie same-site By configuration. The default is :lax (unchanged) --- backend/src/app/http/session.clj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/app/http/session.clj b/backend/src/app/http/session.clj index 696cc6a3a..7ff6dfa01 100644 --- a/backend/src/app/http/session.clj +++ b/backend/src/app/http/session.clj @@ -248,6 +248,7 @@ renewal (dt/plus created-at default-renewal-max-age) expires (dt/plus created-at max-age) secure? (contains? cf/flags :secure-session-cookies) + strict? (contains? cf/flags :strict-session-cookies) cors? (contains? cf/flags :cors) name (cf/get :auth-token-cookie-name default-auth-token-cookie-name) comment (str "Renewal at: " (dt/format-instant renewal :rfc1123)) @@ -256,7 +257,7 @@ :expires expires :value token :comment comment - :same-site (if cors? :none :lax) + :same-site (if cors? :none (if strict? :strict :lax)) :secure secure?}] (update response :cookies assoc name cookie))) From 8cb550120ac878048880a584c24018e841ec6cfc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 09:16:45 +0100 Subject: [PATCH 014/136] :bug: Fix error handling on recovery request page --- .../app/main/ui/auth/recovery_request.cljs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/main/ui/auth/recovery_request.cljs b/frontend/src/app/main/ui/auth/recovery_request.cljs index e90eec477..d1d72ed2d 100644 --- a/frontend/src/app/main/ui/auth/recovery_request.cljs +++ b/frontend/src/app/main/ui/auth/recovery_request.cljs @@ -49,19 +49,20 @@ on-error (mf/use-callback - (fn [data {:keys [code] :as error}] + (fn [data cause] (reset! submitted false) - (case code - :profile-not-verified - (rx/of (msg/error (tr "auth.notifications.profile-not-verified"))) + (let [code (-> cause ex-data :code)] + (case code + :profile-not-verified + (rx/of (msg/error (tr "auth.notifications.profile-not-verified"))) - :profile-is-muted - (rx/of (msg/error (tr "errors.profile-is-muted"))) + :profile-is-muted + (rx/of (msg/error (tr "errors.profile-is-muted"))) - :email-has-permanent-bounces - (rx/of (msg/error (tr "errors.email-has-permanent-bounces" (:email data)))) + :email-has-permanent-bounces + (rx/of (msg/error (tr "errors.email-has-permanent-bounces" (:email data)))) - (rx/throw error)))) + (rx/throw cause))))) on-submit (mf/use-callback From 5b722a86086c8374d7390c596c44852aec8b38b2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 09:17:04 +0100 Subject: [PATCH 015/136] :bug: Fix error handling on register page --- frontend/src/app/main/ui/auth/register.cljs | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index cda4f878d..0c1a0e70c 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -58,33 +58,33 @@ :opt-un [::invitation-token])) (defn- handle-prepare-register-error - [form {:keys [type code] :as cause}] - (condp = [type code] - [:restriction :registration-disabled] - (st/emit! (msg/error (tr "errors.registration-disabled"))) + [form cause] + (let [{:keys [type code]} (ex-data cause)] + (condp = [type code] + [:restriction :registration-disabled] + (st/emit! (msg/error (tr "errors.registration-disabled"))) - [:restriction :profile-blocked] - (st/emit! (msg/error (tr "errors.profile-blocked"))) + [:restriction :profile-blocked] + (st/emit! (msg/error (tr "errors.profile-blocked"))) - [:validation :email-has-permanent-bounces] - (let [email (get @form [:data :email])] - (st/emit! (msg/error (tr "errors.email-has-permanent-bounces" email)))) + [:validation :email-has-permanent-bounces] + (let [email (get @form [:data :email])] + (st/emit! (msg/error (tr "errors.email-has-permanent-bounces" email)))) - [:validation :email-already-exists] - (swap! form assoc-in [:errors :email] - {:message "errors.email-already-exists"}) + [:validation :email-already-exists] + (swap! form assoc-in [:errors :email] + {:message "errors.email-already-exists"}) - [:validation :email-as-password] - (swap! form assoc-in [:errors :password] - {:message "errors.email-as-password"}) + [:validation :email-as-password] + (swap! form assoc-in [:errors :password] + {:message "errors.email-as-password"}) - (st/emit! (msg/error (tr "errors.generic"))))) + (st/emit! (msg/error (tr "errors.generic")))))) (defn- handle-prepare-register-success [params] (st/emit! (rt/nav :auth-register-validate {} params))) - (mf/defc register-form [{:keys [params on-success-callback] :as props}] (let [initial (mf/use-memo (mf/deps params) (constantly params)) From 88f49cfbc932272c5bf7e9cd789a5d1ba1f462d3 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 09:17:39 +0100 Subject: [PATCH 016/136] :bug: Fix email field intrusive autocomplete on firefox Firefox has a strange behavior because it ignores the autocomplete attribute and just does not allow submit a form when an email type field has invalid email (valid but surrounded with whitespace). This fix is a workaround, setting up the input field as simple text instead of semantic type 'email'. --- frontend/src/app/main/ui/auth/register.cljs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index 0c1a0e70c..6789b99dc 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -100,7 +100,7 @@ (on-success-callback p))) on-submit - (mf/use-callback + (mf/use-fn (fn [form _event] (reset! submitted? true) (let [cdata (:clean-data @form)] @@ -114,7 +114,7 @@ [:& fm/form {:on-submit on-submit :form form} [:div {:class (stl/css :fields-row)} - [:& fm/input {:type "email" + [:& fm/input {:type "text" :name :email :label (tr "auth.email") :data-test "email-input" @@ -225,7 +225,7 @@ (on-success-callback (:email p)))) on-submit - (mf/use-callback + (mf/use-fn (fn [form _event] (reset! submitted? true) (let [params (:clean-data @form)] From 7eecd50c50d12ce5b37ecd6e5f178e052af3eea8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 09:24:37 +0100 Subject: [PATCH 017/136] :books: Add http methods documentation to the API doc page --- backend/resources/app/templates/api-doc.tmpl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/resources/app/templates/api-doc.tmpl b/backend/resources/app/templates/api-doc.tmpl index aa0b2a7d9..8c67fdeee 100644 --- a/backend/resources/app/templates/api-doc.tmpl +++ b/backend/resources/app/templates/api-doc.tmpl @@ -37,6 +37,13 @@

GENERAL NOTES

+

HTTP Transport & Methods

+

The HTTP is the transport method for accesing this API; all + functions can be called using POST HTTP method; the functions + that starts with get- in the name, can use GET HTTP + method which in many cases benefits from the HTTP cache.

+ +

Authentication

The penpot backend right now offers two way for authenticate the request: cookies (the same mechanism that we use ourselves on accessing the API from the From 131fc95ab0d2b0025eae92d16abd011cf81e805a Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 10:01:57 +0100 Subject: [PATCH 018/136] :bug: Fix release notes not showing on release build --- frontend/src/app/main/ui/releases.cljs | 2 +- frontend/src/app/main/ui/releases/v2_0.cljs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/releases.cljs b/frontend/src/app/main/ui/releases.cljs index 562c1eab2..50f87648f 100644 --- a/frontend/src/app/main/ui/releases.cljs +++ b/frontend/src/app/main/ui/releases.cljs @@ -91,4 +91,4 @@ (defmethod rc/render-release-notes "0.0" [params] - (rc/render-release-notes (assoc params :version "2.0"))) + (rc/render-release-notes (assoc params :version "1.21"))) diff --git a/frontend/src/app/main/ui/releases/v2_0.cljs b/frontend/src/app/main/ui/releases/v2_0.cljs index 67ae75e17..53ce83ee1 100644 --- a/frontend/src/app/main/ui/releases/v2_0.cljs +++ b/frontend/src/app/main/ui/releases/v2_0.cljs @@ -11,6 +11,10 @@ [app.main.ui.releases.common :as c] [rumext.v2 :as mf])) +(defmethod c/render-release-notes "1.21" + [data] + (c/render-release-notes (assoc data :verstion "2.0"))) + ;; TODO: Review all copies and alt text (defmethod c/render-release-notes "2.0" [{:keys [slide klass next finish navigate version]}] From 1134f16ffac65bb00b9d7ccaf845c9410867d433 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 12:46:30 +0100 Subject: [PATCH 019/136] :lipstick: Add cosmetic refactor to dashboard fonts react components --- frontend/src/app/main/ui/dashboard/fonts.cljs | 352 +++++++++++------- 1 file changed, 208 insertions(+), 144 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index bdd8e5ede..a444236ce 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -25,108 +25,143 @@ [cuerdas.core :as str] [rumext.v2 :as mf])) -(defn- use-set-page-title +(defn- use-page-title [team section] - (mf/use-effect - (mf/deps team) - (fn [] - (when team - (let [tname (if (:is-default team) - (tr "dashboard.your-penpot") - (:name team))] - (case section - :fonts (dom/set-html-title (tr "title.dashboard.fonts" tname)) - :providers (dom/set-html-title (tr "title.dashboard.font-providers" tname)))))))) + (mf/with-effect [team] + (when team + (let [tname (if (:is-default team) + (tr "dashboard.your-penpot") + (:name team))] + (case section + :fonts (dom/set-html-title (tr "title.dashboard.fonts" tname)) + :providers (dom/set-html-title (tr "title.dashboard.font-providers" tname))))))) + +(defn- bad-font-family-tmp? + [font] + (and (contains? font :font-family-tmp) + (str/blank? (:font-family-tmp font)))) (mf/defc header - {::mf/wrap [mf/memo]} - [{:keys [section team] :as props}] - (use-set-page-title team section) + {::mf/props :obj + ::mf/memo true + ::mf/private true} + [{:keys [section team]}] + (use-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 + {::mf/props :obj + ::mf/private true} [{:keys [variant]}] [:* [:span (cm/font-weight->name (:font-weight variant))] (when (not= "normal" (:font-style variant)) [:span " " (str/capital (:font-style variant))])]) -(mf/defc fonts-upload +(mf/defc uploaded-fonts + {::mf/props :obj + ::mf/private true} [{:keys [team installed-fonts] :as props}] - (let [fonts* (mf/use-state {}) - fonts (deref fonts*) - input-ref (mf/use-ref) - uploading (mf/use-state #{}) + (let [fonts* (mf/use-state {}) + fonts (deref fonts*) + font-vals (mf/with-memo [fonts] + (->> fonts + (into [] (map val)) + (not-empty))) - bad-font-family-tmp? - (mf/use-fn - (fn [font] - (and (contains? font :font-family-tmp) - (str/blank? (:font-family-tmp font))))) + team-id (:id team) - disable-upload-all? (some bad-font-family-tmp? (vals fonts)) + input-ref (mf/use-ref) - handle-click + uploading* (mf/use-state #{}) + uploading (deref uploading*) + + disable-upload-all? + (some bad-font-family-tmp? fonts) + + problematic-fonts? + (some :height-warning? (vals fonts)) + + on-click (mf/use-fn #(dom/click (mf/ref-val input-ref))) - handle-selected + on-selected (mf/use-fn - (mf/deps team installed-fonts) + (mf/deps team-id installed-fonts) (fn [blobs] - (->> (df/process-upload blobs (:id team)) + (->> (df/process-upload blobs team-id) (rx/subs! (fn [result] (swap! fonts* df/merge-and-group-fonts installed-fonts result)) (fn [error] (js/console.error "error" error)))))) - on-upload + on-upload* (mf/use-fn - (mf/deps team) - (fn [item] - (swap! uploading conj (:id item)) + (fn [{:keys [id] :as item}] + (swap! uploading* conj id) (->> (rp/cmd! :create-font-variant item) (rx/delay-at-least 2000) (rx/subs! (fn [font] - (swap! fonts* dissoc (:id item)) - (swap! uploading disj (:id item)) + (swap! fonts* dissoc id) + (swap! uploading* disj id) (st/emit! (df/add-font font))) (fn [error] (js/console.log "error" error)))))) - on-upload-all - (fn [items] - (run! on-upload items)) + on-upload + (mf/use-fn + (mf/deps fonts on-upload*) + (fn [event] + (let [id (-> (dom/get-current-target event) + (dom/get-data "id") + (parse-uuid)) + item (get fonts id)] + (on-upload* item)))) on-blur-name - (fn [id event] - (let [name (dom/get-target-val event)] - (when-not (str/blank? name) - (swap! fonts* df/rename-and-regroup id name installed-fonts)))) + (mf/use-fn + (mf/deps installed-fonts) + (fn [event] + (let [target (dom/get-current-target event) + id (-> target + (dom/get-data "id") + (parse-uuid)) + name (dom/get-value target)] + (when-not (str/blank? name) + (swap! fonts* df/rename-and-regroup id name installed-fonts))))) on-change-name - (fn [id event] - (let [name (dom/get-target-val event)] - (swap! fonts* update-in [id] #(assoc % :font-family-tmp name)))) + (mf/use-fn + (fn [event] + (let [target (dom/get-current-target event) + id (-> target + (dom/get-data "id") + (parse-uuid)) + name (dom/get-value target)] + (swap! fonts* update id assoc :font-family-tmp name)))) on-delete (mf/use-fn (mf/deps team) - (fn [{:keys [id] :as item}] - (swap! fonts* dissoc id))) + (fn [event] + (let [id (-> (dom/get-current-target event) + (dom/get-data "id") + (parse-uuid))] + (swap! fonts* dissoc id)))) - on-dismiss-all - (fn [items] - (run! on-delete items)) + on-upload-all + (mf/use-fn + (mf/deps font-vals) + (fn [_] + (run! on-upload* font-vals))) - problematic-fonts? (some :height-warning? (vals fonts)) - - handle-upload-all - (mf/use-fn (mf/deps fonts) #(on-upload-all (vals fonts))) - - handle-dismiss-all - (mf/use-fn (mf/deps fonts) #(on-dismiss-all (vals fonts)))] + on-dismis-all + (mf/use-fn + (mf/deps fonts) + (fn [_] + (run! on-delete (vals fonts))))] [:div {:class (stl/css :dashboard-fonts-upload)} [:div {:class (stl/css :dashboard-fonts-hero)} @@ -135,14 +170,14 @@ [:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}] [:button {:class (stl/css :btn-primary) - :on-click handle-click + :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 handle-selected}]] + :on-selected on-selected}]] [:& context-notification {:content (tr "dashboard.fonts.hero-text2") :type :default @@ -154,31 +189,32 @@ :is-html true}])]] [:* - (when (some? (vals fonts)) + (when (seq fonts) [:div {:class (stl/css :font-item :table-row)} - [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals fonts))))] + [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count fonts)))] [:div {:class (stl/css :table-field :options)} - [:button {:class (stl/css-case :btn-primary true - :disabled disable-upload-all?) - :on-click handle-upload-all + [:button {:class (stl/css-case + :btn-primary true + :disabled disable-upload-all?) + :on-click on-upload-all :data-test "upload-all" :disabled disable-upload-all?} [:span (tr "dashboard.fonts.upload-all")]] [:button {:class (stl/css :btn-secondary) - :on-click handle-dismiss-all + :on-click on-dismis-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)) - disable-upload? (or uploading? - (bad-font-family-tmp? item))] + (for [{:keys [id] :as item} (sort-by :font-family font-vals)] + (let [uploading? (contains? uploading id) + disable-upload? (or uploading? (bad-font-family-tmp? item))] [:div {:class (stl/css :font-item :table-row) - :key (:id item)} + :key (dm/str id)} [:div {:class (stl/css :table-field :family)} [:input {:type "text" - :on-blur #(on-blur-name (:id item) %) - :on-change #(on-change-name (:id item) %) + :data-id (dm/str id) + :on-blur on-blur-name + :on-change on-change-name :default-value (:font-family item)}]] [:div {:class (stl/css :table-field :variants)} [:span {:class (stl/css :label)} @@ -190,115 +226,151 @@ [:div {:class (stl/css :table-field :options)} (when (:height-warning? item) - [:span {:class (stl/css :icon :failure)} i/msg-neutral-refactor]) + [:span {:class (stl/css :icon :failure)} + i/msg-neutral-refactor]) - [:button {:on-click #(on-upload item) - :class (stl/css-case :btn-primary true - :upload-button true - :disabled disable-upload?) + [:button {:on-click on-upload + :data-id (dm/str id) + :class (stl/css-case + :btn-primary true + :upload-button true + :disabled disable-upload?) :disabled disable-upload?} - (if uploading? + (if ^boolean uploading? (tr "labels.uploading") (tr "labels.upload"))] [:span {:class (stl/css :icon :close) - :on-click #(on-delete item)} i/close-refactor]]]))]])) + :data-id (dm/str id) + :on-click on-delete} + i/close-refactor]]]))]])) + +(mf/defc installed-font-context-menu + {::mf/props :obj + ::mf/private true} + [{:keys [is-open on-close on-edit on-delete]}] + (let [options (mf/with-memo [on-edit on-delete] + [{:option-name (tr "labels.edit") + :id "font-edit" + :option-handler on-edit} + {:option-name (tr "labels.delete") + :id "font-delete" + :option-handler on-delete}])] + [:& context-menu-a11y + {:on-close on-close + :show is-open + :fixed? false + :min-width? true + :top -15 + :left -115 + :options options + :workspace? false}])) (mf/defc installed-font - [{:keys [font-id variants] :as props}] + {::mf/props :obj + ::mf/private true + ::mf/memo true} + [{:keys [font-id variants]}] (let [font (first variants) - variants (sort-by (fn [item] - [(:font-weight item) - (if (= "normal" (:font-style item)) 1 2)]) - variants) + menu-open* (mf/use-state false) + menu-open? (deref menu-open*) + edition* (mf/use-state false) + edition? (deref edition*) - open-menu? (mf/use-state false) - edit? (mf/use-state false) state* (mf/use-state (:font-family font)) font-family (deref state*) + variants + (mf/with-memo [variants] + (sort-by (fn [item] + [(:font-weight item) + (if (= "normal" (:font-style item)) 1 2)]) + variants)) on-change - (mf/use-callback + (mf/use-fn (fn [event] (reset! state* (dom/get-target-val event)))) + on-edit + (mf/use-fn #(reset! edition* true)) + + on-menu-open + (mf/use-fn #(reset! menu-open* true)) + + on-menu-close + (mf/use-fn #(reset! menu-open* false)) + on-save - (mf/use-callback + (mf/use-fn (mf/deps font-family) (fn [_] + (reset! edition* false) (when-not (str/blank? font-family) - (st/emit! (df/update-font {:id font-id :name font-family}))) - (reset! edit? false))) + (st/emit! (df/update-font {:id font-id :name font-family}))))) on-key-down - (mf/use-callback + (mf/use-fn (mf/deps on-save) (fn [event] (when (kbd/enter? event) (on-save event)))) on-cancel - (mf/use-callback + (mf/use-fn (fn [_] - (reset! edit? false) + (reset! edition* false) (reset! state* (:font-family font)))) - delete-font-fn - (mf/use-callback + on-delete-font + (mf/use-fn (mf/deps font-id) (fn [] - (st/emit! (df/delete-font font-id)))) - - delete-variant-fn - (mf/use-callback - (fn [id] - (st/emit! (df/delete-font-variant id)))) - - on-delete - (mf/use-callback - (mf/deps delete-font-fn) - (fn [] - (st/emit! (modal/show - {:type :confirm - :title (tr "modals.delete-font.title") - :message (tr "modals.delete-font.message") - :accept-label (tr "labels.delete") - :on-accept (fn [_props] (delete-font-fn))})))) + (let [options {:type :confirm + :title (tr "modals.delete-font.title") + :message (tr "modals.delete-font.message") + :accept-label (tr "labels.delete") + :on-accept (fn [_props] + (st/emit! (df/delete-font font-id)))}] + (st/emit! (modal/show options))))) on-delete-variant - (mf/use-callback - (mf/deps delete-variant-fn) - (fn [id] - (st/emit! (modal/show - {:type :confirm - :title (tr "modals.delete-font-variant.title") - :message (tr "modals.delete-font-variant.message") - :accept-label (tr "labels.delete") - :on-accept (fn [_props] - (delete-variant-fn id))}))))] + (mf/use-fn + (fn [event] + (let [id (-> (dom/get-current-target event) + (dom/get-data "id") + (parse-uuid)) + options {:type :confirm + :title (tr "modals.delete-font-variant.title") + :message (tr "modals.delete-font-variant.message") + :accept-label (tr "labels.delete") + :on-accept (fn [_props] + (st/emit! (df/delete-font-variant id)))}] + (st/emit! (modal/show options)))))] [:div {:class (stl/css :font-item :table-row)} [:div {:class (stl/css :table-field :family)} - (if @edit? + (if ^boolean edition? [:input {:type "text" + :auto-focus true :default-value font-family :on-key-down on-key-down :on-change on-change}] [:span (:font-family font)])] [:div {:class (stl/css :table-field :variants)} - (for [item variants] + (for [{:keys [id] :as item} variants] [:div {:class (stl/css :variant) - :key (dm/str (:id item) "-variant")} + :key (dm/str id)} [:span {:class (stl/css :label)} [:& font-variant-display-name {:variant item}]] [:span {:class (stl/css :icon :close) - :on-click #(on-delete-variant (:id item))} + :data-id (dm/str id) + :on-click on-delete-variant} i/add-refactor]])] - (if @edit? + (if ^boolean edition? [:div {:class (stl/css :table-field :options)} [:button {:disabled (str/blank? font-family) @@ -307,27 +379,19 @@ :btn-disabled (str/blank? font-family))} (tr "labels.save")] [:button {:class (stl/css :icon :close) - :on-click on-cancel} i/close-refactor]] + :on-click on-cancel} + i/close-refactor]] [:div {:class (stl/css :table-field :options)} [:span {:class (stl/css :icon) - :on-click #(reset! open-menu? true)} + :on-click on-menu-open} i/menu-refactor] - [:& context-menu-a11y {:on-close #(reset! open-menu? false) - :show @open-menu? - :fixed? false - :min-width? true - :top -15 - :left -115 - :options [{:option-name (tr "labels.edit") - :id "font-edit" - :option-handler #(reset! edit? true)} - {:option-name (tr "labels.delete") - :id "font-delete" - :option-handler on-delete}] - :workspace? false}]])])) - + [:& installed-font-context-menu + {:on-close on-menu-close + :is-open menu-open? + :on-delete on-delete-font + :on-edit on-edit}]])])) (mf/defc installed-fonts [{:keys [fonts] :as props}] @@ -377,7 +441,7 @@ [:* [:& header {:team team :section :fonts}] [:section {:class (stl/css :dashboard-container :dashboard-fonts)} - [:& fonts-upload {:team team :installed-fonts fonts}] + [:& uploaded-fonts {:team team :installed-fonts fonts}] [:& installed-fonts {:team team :fonts fonts}]]])) (mf/defc font-providers-page From 92425fcbaf1d7f3ea189d84b2112b55884a4eb4e Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 6 Mar 2024 11:42:31 +0100 Subject: [PATCH 020/136] :recycle: Update dashboard hero and template icons --- frontend/src/app/main/ui/dashboard/files.cljs | 35 +- frontend/src/app/main/ui/dashboard/files.scss | 5 + .../src/app/main/ui/dashboard/projects.cljs | 50 ++- .../src/app/main/ui/dashboard/projects.scss | 145 ++++---- .../src/app/main/ui/dashboard/templates.cljs | 44 ++- .../src/app/main/ui/dashboard/templates.scss | 322 +++++++++--------- 6 files changed, 301 insertions(+), 300 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/files.cljs b/frontend/src/app/main/ui/dashboard/files.cljs index 049688c2b..50d776e62 100644 --- a/frontend/src/app/main/ui/dashboard/files.cljs +++ b/frontend/src/app/main/ui/dashboard/files.cljs @@ -24,6 +24,9 @@ [cuerdas.core :as str] [rumext.v2 :as mf])) +(def ^:private menu-icon + (i/icon-xref :menu-refactor (stl/css :menu-icon))) + (mf/defc header [{:keys [project create-fn] :as props}] (let [local (mf/use-state @@ -92,14 +95,13 @@ :on-import on-import}] [:div {:class (stl/css :dashboard-header-actions)} - [:a - {:class (stl/css :btn-secondary :btn-small :new-file) - :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)))} + [:a {:class (stl/css :btn-secondary :btn-small :new-file) + :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) @@ -109,15 +111,14 @@ :on-click toggle-pin :on-key-down (fn [event] (when (kbd/enter? event) (toggle-pin event)))}]) - [: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]]])) + [:div {:class (stl/css :icon) + :tab-index "0" + :on-click on-menu-click + :title (tr "dashboard.options") + :on-key-down (fn [event] + (when (kbd/enter? event) + (on-menu-click event)))} + menu-icon]]])) (mf/defc files-section [{:keys [project team] :as props}] diff --git a/frontend/src/app/main/ui/dashboard/files.scss b/frontend/src/app/main/ui/dashboard/files.scss index 4473dab6a..98cf1733e 100644 --- a/frontend/src/app/main/ui/dashboard/files.scss +++ b/frontend/src/app/main/ui/dashboard/files.scss @@ -30,3 +30,8 @@ .new-file { margin-inline-end: $s-8; } + +.menu-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 179f66d32..883e5bb8a 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -37,6 +37,9 @@ (def ^:private show-more-icon (i/icon-xref :arrow-refactor (stl/css :show-more-icon))) +(def ^:private close-icon + (i/icon-xref :close-refactor (stl/css :close-icon))) + (mf/defc header {::mf/wrap [mf/memo]} [] @@ -44,10 +47,9 @@ [: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"} + [: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 @@ -84,11 +86,10 @@ :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]]])) + [:button {:class (stl/css :close) + :on-click on-close-click + :aria-label (tr "labels.close")} + close-icon]])) (def builtin-templates (l/derived :builtin-templates st/state)) @@ -139,11 +140,10 @@ :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]]])) + [:button {:class (stl/css :close) + :on-click close-tutorial + :aria-label (tr "labels.close")} + close-icon]])) (mf/defc interface-walkthrough {::mf/wrap [mf/memo]} @@ -163,11 +163,10 @@ :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]]])) + [:button {:class (stl/css :close) + :on-click close-walkthrough + :aria-label (tr "labels.close")} + close-icon]])) (mf/defc project-item [{:keys [project first? team files] :as props}] @@ -310,13 +309,12 @@ (when-not (:is-default project) [:> pin-button* {:class (stl/css :pin-button) :is-pinned (:is-pinned project) :on-click toggle-pin :tab-index 0}]) - [: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} + [: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/add-refactor] [:button diff --git a/frontend/src/app/main/ui/dashboard/projects.scss b/frontend/src/app/main/ui/dashboard/projects.scss index b950bd48e..13204f3d5 100644 --- a/frontend/src/app/main/ui/dashboard/projects.scss +++ b/frontend/src/app/main/ui/dashboard/projects.scss @@ -141,6 +141,7 @@ stroke: currentColor; } +// Team hero .team-hero { background-color: $db-tertiary; border-radius: $br-8; @@ -150,60 +151,6 @@ padding: $s-8; position: relative; - .text { - display: flex; - flex-direction: column; - align-items: flex-start; - flex-grow: 1; - padding: $s-20 $s-20; - } - .title { - font-size: $fs-24; - color: $df-primary; - font-weight: $fw400; - } - .info { - flex: 1; - font-size: $fs-16; - span { - color: $df-secondary; - display: block; - } - a { - color: $da-primary; - } - padding: $s-8 0; - } - .close { - position: absolute; - top: $s-20; - right: $s-20; - background-color: transparent; - border: none; - cursor: pointer; - svg { - transform: rotate(45deg); - width: $s-16; - height: $s-16; - } - } - .invite { - height: $s-32; - width: $s-180; - } - .img-wrapper { - display: flex; - align-items: center; - justify-content: center; - width: $s-200; - height: $s-200; - overflow: hidden; - border-radius: $br-4; - @media (max-width: 1200px) { - display: none; - width: 0; - } - } img { border-radius: $br-4; height: $s-200; @@ -214,8 +161,70 @@ width: 0; } } - svg { - fill: $df-secondary; +} + +.text { + display: flex; + flex-direction: column; + align-items: flex-start; + flex-grow: 1; + padding: $s-20 $s-20; +} + +.title { + font-size: $fs-24; + color: $df-primary; + font-weight: $fw400; +} + +.info { + flex: 1; + font-size: $fs-16; + span { + color: $df-secondary; + display: block; + } + a { + color: $da-primary; + } + padding: $s-8 0; +} + +.close { + --close-icon-foreground-color: var(--icon-foreground); + position: absolute; + top: $s-20; + right: $s-24; + width: $s-24; + background-color: transparent; + border: none; + cursor: pointer; + &:hover { + --close-icon-foreground-color: var(--button-icon-foreground-color-selected); + } +} + +.close-icon { + @extend .button-icon; + stroke: var(--close-icon-foreground-color); +} + +.invite { + height: $s-32; + width: $s-180; +} + +.img-wrapper { + display: flex; + align-items: center; + justify-content: center; + width: $s-200; + height: $s-200; + overflow: hidden; + border-radius: $br-4; + @media (max-width: 1200px) { + display: none; + width: 0; } } @@ -279,30 +288,6 @@ width: $s-180; height: $s-40; } - .close { - position: absolute; - top: 0; - right: 0; - width: $s-24; - cursor: pointer; - display: flex; - margin: $s-20; - justify-content: center; - align-items: center; - background-color: transparent; - border: none; - .icon { - svg { - fill: $df-secondary; - height: $s-16; - width: $s-16; - transform: rotate(45deg); - &:hover { - fill: $da-tertiary; - } - } - } - } } .walkthrough { .thumbnail { diff --git a/frontend/src/app/main/ui/dashboard/templates.cljs b/frontend/src/app/main/ui/dashboard/templates.cljs index 953f9b4b3..182345dc1 100644 --- a/frontend/src/app/main/ui/dashboard/templates.cljs +++ b/frontend/src/app/main/ui/dashboard/templates.cljs @@ -25,6 +25,12 @@ [potok.v2.core :as ptk] [rumext.v2 :as mf])) +(def ^:private arrow-icon + (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) + +(def ^:private download-icon + (i/icon-xref :download-refactor (stl/css :download-icon))) + (def builtin-templates (l/derived :builtin-templates st/state)) @@ -76,10 +82,16 @@ [:div {:class (stl/css :title)} [:button {:tab-index "0" + :class (stl/css :title-btn) :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)]]])) + [:span {:class (stl/css :title-text)} + (tr "dashboard.libraries-and-templates")] + (if ^boolean collapsed + [:span {:class (stl/css :title-icon :title-icon-collapsed)} + arrow-icon] + [:span {:class (stl/css :title-icon)} + arrow-icon])]])) (mf/defc card-item {::mf/wrap-props false} @@ -112,8 +124,8 @@ [:img {:src (dm/str thb) :alt (:name item)}]] [:div {:class (stl/css :card-name)} - [:span (:name item)] - [:span {:class (stl/css :icon)} i/download-refactor]]]])) + [:span {:class (stl/css :card-text)} (:name item)] + download-icon]]])) (mf/defc card-item-link {::mf/wrap-props false} @@ -260,18 +272,16 @@ :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]) + [:button {:class (stl/css :move-button :move-left) + :tab-index (if ^boolean collapsed "-1" "0") + :on-click on-move-left + :on-key-down on-move-left-key-down} + arrow-icon]) (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])])) + [:button {:class (stl/css :move-button :move-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} + arrow-icon])])) diff --git a/frontend/src/app/main/ui/dashboard/templates.scss b/frontend/src/app/main/ui/dashboard/templates.scss index f70618c45..2fa508411 100644 --- a/frontend/src/app/main/ui/dashboard/templates.scss +++ b/frontend/src/app/main/ui/dashboard/templates.scss @@ -20,173 +20,175 @@ bottom: calc(-1 * $s-228); transition: bottom 300ms; } +} - .title { - pointer-events: all; - width: fit-content; - top: calc(-1 * $s-56); - text-align: right; - height: $s-56; - position: absolute; - right: calc(-1 * $s-24); +.title { + pointer-events: all; + width: fit-content; + top: calc(-1 * $s-56); + text-align: right; + height: $s-56; + position: absolute; + right: calc(-1 * $s-24); +} - button { - border: none; - cursor: pointer; - height: $s-56; - display: inline-flex; - align-items: center; - border-top-left-radius: $br-10; - border-top-right-radius: $br-10; - margin-right: $s-32; - position: relative; - z-index: 1; - background-color: $db-quaternary; +.title-btn { + border: none; + cursor: pointer; + height: $s-56; + display: inline-flex; + align-items: center; + border-top-left-radius: $br-10; + border-top-right-radius: $br-10; + margin-right: $s-32; + position: relative; + z-index: 1; + background-color: $db-quaternary; +} - span { - display: inline-block; - vertical-align: middle; - line-height: 1.2; - font-size: $fs-16; - margin-left: $s-16; - margin-right: $s-8; - color: $df-primary; - font-weight: $fw400; - &.icon { - margin-left: $s-16; - margin-right: $s-16; - } - } - svg { - width: $s-12; - height: $s-12; - fill: $df-secondary; - } - } - } +.title-text { + display: inline-block; + vertical-align: middle; + line-height: 1.2; + font-size: $fs-16; + margin-left: $s-16; + margin-right: $s-8; + color: $df-primary; + font-weight: $fw400; +} - .button { - position: absolute; - top: $s-136; - border: $s-2 solid $df-secondary; - border-radius: 50%; - text-align: center; - width: $s-36; - height: $s-36; - cursor: pointer; - background-color: $df-primary; - display: flex; - align-items: center; - justify-content: center; - pointer-events: all; - svg { - width: $s-12; - height: $s-12; - fill: $df-secondary; - } +.title-icon { + display: inline-block; + vertical-align: middle; + margin-left: $s-16; + margin-right: $s-8; + color: $df-primary; + margin-left: $s-16; + margin-right: $s-16; + transform: rotate(90deg); +} - &.left { - left: 0; - margin-left: $s-44; - } +.title-icon-collapsed { + transform: rotate(-90deg); +} - &.right { - right: 0; - margin-right: $s-44; - } +.arrow-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} - &:hover { - border: $s-2 solid $da-tertiary; - } - } +.move-button { + position: absolute; + top: $s-136; + border: $s-2 solid $df-secondary; + border-radius: 50%; + text-align: center; + width: $s-36; + height: $s-36; + cursor: pointer; + background-color: $df-primary; + display: flex; + align-items: center; + justify-content: center; + pointer-events: all; - .content { - pointer-events: all; - width: 200%; - height: $s-228; - margin-left: $s-6; - position: absolute; - border-top-left-radius: $s-8; - background-color: $db-quaternary; - - .card-container { - width: $s-276; - margin-top: $s-20; - display: inline-block; - text-align: center; - vertical-align: top; - background-color: transparent; - border: none; - padding: 0; - } - - .template-card { - display: inline-block; - width: $s-256; - font-size: $fs-16; - cursor: pointer; - color: $df-primary; - padding: $s-3 $s-6 $s-16 $s-6; - border-radius: $br-8; - - .img-container { - width: 100%; - height: $s-136; - margin-bottom: $s-16; - border-radius: $br-5; - display: flex; - justify-content: center; - flex-direction: column; - - img { - border-radius: $br-4; - } - } - - .card-name { - padding: 0 $s-6; - display: flex; - justify-content: space-between; - height: $s-24; - align-items: center; - - .icon { - width: $s-16; - height: $s-16; - } - svg { - width: $s-16; - height: $s-16; - fill: none; - stroke: currentColor; - } - span { - font-weight: $fw500; - font-size: $fs-16; - } - } - - .template-link { - border: $s-2 solid transparent; - margin: $s-32; - padding: $s-32 0; - } - - .template-link-title { - font-size: $fs-14; - color: $df-primary; - font-weight: $fw400; - } - - .template-link-text { - font-size: $fs-12; - margin-top: $s-8; - color: $df-secondary; - } - - &:hover { - background-color: $db-tertiary; - } - } + &:hover { + border: $s-2 solid $da-tertiary; } } + +.move-left { + left: 0; + margin-left: $s-44; + transform: rotate(180deg); +} + +.move-right { + right: 0; + margin-right: $s-44; +} + +.content { + pointer-events: all; + width: 200%; + height: $s-228; + margin-left: $s-6; + position: absolute; + border-top-left-radius: $s-8; + background-color: $db-quaternary; +} + +.card-container { + width: $s-276; + margin-top: $s-20; + display: inline-block; + text-align: center; + vertical-align: top; + background-color: transparent; + border: none; + padding: 0; +} + +.template-card { + display: inline-block; + width: $s-256; + font-size: $fs-16; + cursor: pointer; + color: $df-primary; + padding: $s-3 $s-6 $s-16 $s-6; + border-radius: $br-8; + + &:hover { + background-color: $db-tertiary; + } +} + +.img-container { + width: 100%; + height: $s-136; + margin-bottom: $s-16; + border-radius: $br-5; + display: flex; + justify-content: center; + flex-direction: column; + + img { + border-radius: $br-4; + } +} + +.card-name { + padding: 0 $s-6; + display: flex; + justify-content: space-between; + height: $s-24; + align-items: center; +} + +.card-text { + font-weight: $fw500; + font-size: $fs-16; +} + +.download-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} + +.template-link { + border: $s-2 solid transparent; + margin: $s-32; + padding: $s-32 0; +} + +.template-link-title { + font-size: $fs-14; + color: $df-primary; + font-weight: $fw400; +} + +.template-link-text { + font-size: $fs-12; + margin-top: $s-8; + color: $df-secondary; +} From 4f69ff7124d8f5bb9b4597f5bf6e082a5b04a7d2 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 6 Mar 2024 16:07:31 +0100 Subject: [PATCH 021/136] :books: Update changelog --- CHANGES.md | 133 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7e1a1760b..9f87f4c9a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,36 +1,131 @@ # CHANGELOG -## :rocket: Next +## 2.0.0 - I Just Can't Get Enough + +### :rocket: Epics and highlights +- Grid CSS layout [Taiga #4915](https://tree.taiga.io/project/penpot/epic/4915) +- UI redesign [Taiga #4958](https://tree.taiga.io/project/penpot/epic/4958) +- New components System [Taiga #2662](https://tree.taiga.io/project/penpot/epic/2662) +- Swap components [Taiga #1331](https://tree.taiga.io/project/penpot/us/1331) +- Images as fill [Taiga #2983](https://tree.taiga.io/project/penpot/us/2983) +- HTML code generation [Taiga #5277](https://tree.taiga.io/project/penpot/us/5277) +- Light and dark themes [Taiga #2287](https://tree.taiga.io/project/penpot/us/2287) ### :boom: Breaking changes & Deprecations -### :sparkles: New features +- New strokes default to inside border [Taiga #6847](https://tree.taiga.io/project/penpot/issue/6847) -### :bug: Bugs fixed - -### :arrow_up: Deps updates - -### :heart: Community contributions by (Thank you!) - -## 1.20.0 - -### :boom: Breaking changes & Deprecations +### :heart: Community contributions (Thank you!) +- New Hausa, Yoruba and Igbo translations and update translation files (by All For Tech Empowerment Foundation) [Taiga #6950](https://tree.taiga.io/project/penpot/us/6950), [Taiga #6534](https://tree.taiga.io/project/penpot/us/6534) +- Hide bounding-box when editing shape (by @VasilevsVV) [#3930](https://github.com/penpot/penpot/pull/3930) +- CTRL + "+" to zoom into canvas instead of browser (by @audriu) [#3848](https://github.com/penpot/penpot/pull/3848) +- Add dev deps.edn in the project root (by @PEZ) [#3794](https://github.com/penpot/penpot/pull/3794) +- Allow passing overrides to frontend nginx config (by @m90) [#3602](https://github.com/penpot/penpot/pull/3602) +- Update index.njk to remove typo (by @fdvmoreira) [#155](https://github.com/penpot/penpot-docs/pull/155) +- Typo (by StephanEggermont) [#157](https://github.com/penpot/penpot-docs/pull/157) ### :sparkles: New features - +- Send comments with Ctrl+Enter / Cmd + Enter [Taiga #6085](https://tree.taiga.io/project/penpot/issue/6085) - Select through stroke only rectangle [Taiga #5484](https://tree.taiga.io/project/penpot/issue/5484) +- Stroke default position [Taiga #6847](https://tree.taiga.io/project/penpot/issue/6847) - Override browser Ctrl+ and Ctrl- zoom with Penpot Zoom [Taiga #3200](https://tree.taiga.io/project/penpot/us/3200) -- Reduce handlers for the flex layout gaps and paddings +- Improve the way handlers work on flex layouts [Taiga #6598](https://tree.taiga.io/project/penpot/us/6598) +- Add menu entry for toggle between light/dark theme [Taiga #6829](https://tree.taiga.io/project/penpot/issue/6829) +- Switch themes shortcut [Taiga #6644](https://tree.taiga.io/project/penpot/us/6644) +- Constraints section at design tab new position [Taiga #6830](https://tree.taiga.io/project/penpot/issue/6830) +- [PICKER] File library colors order [Taiga #5399](https://tree.taiga.io/project/penpot/us/5399) +- Onboarding invitations improvements [Taiga #5974](https://tree.taiga.io/project/penpot/us/5974) +- [PERFORMANCE] Workspace thumbnails refactor [Taiga #5828](https://tree.taiga.io/project/penpot/us/5828) +- [PERFORMANCE] Add performance optimizations to shape rendering [Taiga #5835](https://tree.taiga.io/project/penpot/us/5835) +- [PERFORMANCE] Optimize SVG output [Taiga #4134](https://tree.taiga.io/project/penpot/us/4134) +- [PERFORMANCE] Optimize svg on importation [Taiga #5879](https://tree.taiga.io/project/penpot/us/5879) +- [PERFORMANCE] Optimization tasks related to design tab file [Taiga #5760](https://tree.taiga.io/project/penpot/us/5760) +- [INSTALL] Ability to setup features by team [Taiga #6108](https://tree.taiga.io/project/penpot/us/6108) +- [IMAGES] Keep aspect ratio option [Taiga #6933](https://tree.taiga.io/project/penpot/us/6933) +- [INSPECT] UI review [Taiga #5687](https://tree.taiga.io/project/penpot/us/5687) +- [GRID LAYOUT] Phase 1 [Taiga #4303](https://tree.taiga.io/project/penpot/us/4303) +- [GRID LAYOUT] Inspect code for Grid [Taiga #5277](https://tree.taiga.io/project/penpot/us/5277) +- [GRID LAYOUT] Phase 1 polishing [Taiga #5612](https://tree.taiga.io/project/penpot/us/5612) +- [GRID LAYOUT] Improvements & Feedback [Taiga #6047](https://tree.taiga.io/project/penpot/us/6047) +- [COMPONENTS] Naming of the main component [Taiga #5291](https://tree.taiga.io/project/penpot/us/5291) +- [COMPONENTS] Rework inside of components - Library page [Taiga #2918](https://tree.taiga.io/project/penpot/us/2918) +- [COMPONENTS] Update component when updating main instance [Taiga #3794](https://tree.taiga.io/project/penpot/us/3794) +- [COMPONENTS] Main component new behavior [Taiga #3796](https://tree.taiga.io/project/penpot/us/3796) +- [COMPONENTS] Main component look & feel [Taiga #5290](https://tree.taiga.io/project/penpot/us/5290) +- [COMPONENTS] Library view [Taiga #2880](https://tree.taiga.io/project/penpot/us/2880) +- [COMPONENTS] Positioning inside a component should relative, as in boards [Taiga #2826](https://tree.taiga.io/project/penpot/us/2826) +- [COMPONENTS] Update message should show only if affecting at components that are being used at a file [Taiga #1397](https://tree.taiga.io/project/penpot/us/1397) +- [COMPONENTS] Annotations [Taiga #4957](https://tree.taiga.io/project/penpot/us/4957) +- [COMPONENTS] Synchronization order for nested components [Taiga #5439](https://tree.taiga.io/project/penpot/us/5439) +- [COMPONENTS] Libraries modal zero case [Taiga #5294](https://tree.taiga.io/project/penpot/us/5294) +- [COMPONENTS] Contextual menu casuistics [Taiga #5292](https://tree.taiga.io/project/penpot/us/5292) +- [COMPONENTS] Libraries publishing flow review [Taiga #5293](https://tree.taiga.io/project/penpot/us/5293) +- [COMPONENTS] Add loading text to Libraries modal [Taiga #6702](https://tree.taiga.io/project/penpot/us/6702) +- [COMPONENTS] Components rename and organization in bulk [Taiga #2877](https://tree.taiga.io/project/penpot/us/2877) +- [COMPONENTS] Info overlay about components V2 [Taiga #6276](https://tree.taiga.io/project/penpot/us/6276) +- [REDESIGN] New styles basics [Taiga #4967](https://tree.taiga.io/project/penpot/us/4967) +- [REDESIGN] Layers tab redesign [Taiga #4966](https://tree.taiga.io/project/penpot/us/4966) +- [REDESIGN] Design tab phase 1 [Taiga #4982](https://tree.taiga.io/project/penpot/us/4966) +- [REDESIGN] Assets tab redesign [Taiga #4984](https://tree.taiga.io/project/penpot/us/4984) +- [REDESIGN] Palette panels (colors, typographies...) [Taiga #4983](https://tree.taiga.io/project/penpot/us/4983) +- [REDESIGN] Workspace structure [Taiga #4988](https://tree.taiga.io/project/penpot/us/4988) +- [REDESIGN] Shortcut tab [Taiga #4989](https://tree.taiga.io/project/penpot/us/4989) +- [REDESIGN] Toolbar [Taiga #5500](https://tree.taiga.io/project/penpot/us/5500) +- [REDESIGN] History tab [Taiga #5481](https://tree.taiga.io/project/penpot/us/5481) +- [REDESIGN] Path options/toolbar [Taiga #5815](https://tree.taiga.io/project/penpot/us/5815) +- [REDESIGN] Design tab phase 2 [Taiga #5814](https://tree.taiga.io/project/penpot/us/5814) +- [REDESIGN] Design tab phase 3 and dashboard details [Taiga #5920](https://tree.taiga.io/project/penpot/us/5920) +- [REDESIGN] Dashboard [Taiga #5164](https://tree.taiga.io/project/penpot/us/5164) +- [REDESIGN] New Dashboard UI [Taiga #5869](https://tree.taiga.io/project/penpot/us/5869) +- [REDESIGN] Prototype tab [Taiga #4985](https://tree.taiga.io/project/penpot/us/4985) +- [REDESIGN] Code tab [Taiga #4986](https://tree.taiga.io/project/penpot/us/4986) +- [REDESIGN] Modals and alert messages [Taiga #5915](https://tree.taiga.io/project/penpot/us/5915) +- [REDESIGN] Comments page [Taiga #5917](https://tree.taiga.io/project/penpot/us/5917) +- [REDESIGN] View Mode [Taiga #5163](https://tree.taiga.io/project/penpot/us/5163) +- [REDESIGN] Miscellaneous tasks [Taiga #6050](https://tree.taiga.io/project/penpot/us/6050) +- [REDESIGN] Swap components [Taiga #6739](https://tree.taiga.io/project/penpot/us/6739) +- [REDESIGN] Font selector [Taiga #6677](https://tree.taiga.io/project/penpot/us/6677) +- [REDESIGN] Colour system of alerts and notifications [Taiga #6746](https://tree.taiga.io/project/penpot/us/6746) +- [REDESIGN] Review text in paragraphs for accessibility [Taiga #6703](https://tree.taiga.io/project/penpot/us/6703) +- [REDESIGN] Interaction icons [Taiga #6880](https://tree.taiga.io/project/penpot/us/6880) +- [REDESIGN] Panels visual separations [Taiga #6692](https://tree.taiga.io/project/penpot/us/6692) +- [REDESIGN] Onboarding slides [Taiga #6678](https://tree.taiga.io/project/penpot/us/6678) -### :bug: Bugs fixed - -- Fix pixelated thumbnails [Github #3681](https://github.com/penpot/penpot/issues/3681) [Github #3661](https://github.com/penpot/penpot/issues/3661) +### :bug Bugs fixed +- Fix pixelated thumbnails [Github #3681](https://github.com/penpot/penpot/issues/3681), [Github #3661](https://github.com/penpot/penpot/issues/3661) - Fix problem with not applying colors to boards [Github #3941](https://github.com/penpot/penpot/issues/3941) - Fix problem with path editor undoing changes [Github #3998](https://github.com/penpot/penpot/issues/3998) +- [View mode] Open overlay places frame in the wrong position when paired with a fixed element [Taiga #6385](https://tree.taiga.io/project/penpot/issue/6385) +- Flex Layout: Fit-content not recalculated after deleting an element [Taiga #5968](https://tree.taiga.io/project/penpot/issue/5968) +- Selecting from Color Palette does not work for board when there is no existing fill [Taiga #6464](https://tree.taiga.io/project/penpot/issue/6464) +- Color thumbnails are consistently rounded in the inspect code mode [Taiga #5886](https://tree.taiga.io/project/penpot/issue/5886) +- Adding vector path points before first point of existing open path not working [Taiga #6593](https://tree.taiga.io/project/penpot/issue/6593) +- Some image formats include the extension when importing [Taiga #5485](https://tree.taiga.io/project/penpot/issue/5485) +- Gradient color tool doesn't work properly with flipped items [Taiga #6485](https://tree.taiga.io/project/penpot/issue/6485) +- [TEXT] Align options are not shown when several text are selected [Taiga #5948](https://tree.taiga.io/project/penpot/issue/5948) +- [VIEW MODE] Comments not working properly on multiple pages [Taiga #6281](https://tree.taiga.io/project/penpot/issue/6281) +- [PERFORMANCE] Alignments are slow [Taiga #5865](https://tree.taiga.io/project/penpot/issue/5865) +- [EXPORT] Exporting an element with a non-visible drop shadow displays the shadow either way [Taiga #6768](https://tree.taiga.io/project/penpot/issue/6768) +- [SAFARI] Color picker cursor is not pointing correctly [Taiga #6733](https://tree.taiga.io/project/penpot/issue/6733) +- [Import Files] When user has imported .penpot file with new file name of previously downloaded library file the default library file name is set for it [Taiga #5596](https://tree.taiga.io/project/penpot/issue/5596) +- Issue when resizing a duotone FA icon [Taiga #5935](https://tree.taiga.io/project/penpot/issue/5935) +- "Hide grid" keyboard shortcut broken [Taiga #5102](https://tree.taiga.io/project/penpot/issue/5102) +- Picking a gradient color in recent colors for a new color in the assets tab crashes Penpot [Taiga #5601](https://tree.taiga.io/project/penpot/issue/5601) +- Thumbnails not loading [Taiga #6012](https://tree.taiga.io/project/penpot/issue/6012) +- Don't show signup link/form when registration is disabled. [Taiga #1196](https://tree.taiga.io/project/penpot/issue/1196) +- Registration Page UI UX issue with small resolutions [Taiga #1693](https://tree.taiga.io/project/penpot/issue/1693) +- [LOGIN] "E-Mail-Adress" input field is set to type 'text' instead of 'eMail [Taiga #1921](https://tree.taiga.io/project/penpot/issue/1921) +- Handling correctly slashes "/" in emails [Taiga #4906](https://tree.taiga.io/project/penpot/issue/4906) +- Tab character in texts crashes the app [Taiga #4418](https://tree.taiga.io/project/penpot/issue/4418) +- Text does not match export [Taiga #4129](https://tree.taiga.io/project/penpot/issue/4129) +- Scrollbars cover the layers carets [Taiga #4431](https://tree.taiga.io/project/penpot/issue/4431) +- Horizontal ruler disappear when overlapping a board [Taiga #4138](https://tree.taiga.io/project/penpot/issue/4138) +- Resize shape + Alt key is not working [Taiga #3447](https://tree.taiga.io/project/penpot/issue/3447) +- Libraries images broken on premise [Taiga #4573](https://tree.taiga.io/project/penpot/issue/4573) +- [VIEWER] Cannot scroll down in code mode [Taiga #4655](https://tree.taiga.io/project/penpot/issue/4655) +- Strange cursor behavior after clicking viewport with text tool [Taiga #4363](https://tree.taiga.io/project/penpot/issue/4363) +- Selected color affects all of them [Taiga #5285](https://tree.taiga.io/project/penpot/issue/5285) -### :arrow_up: Deps updates - -### :heart: Community contributions by (Thank you!) ## 1.19.5 From b3f97fe456901bcc31dc421d4b0396e7ba636e44 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 7 Mar 2024 10:54:03 +0100 Subject: [PATCH 022/136] :bug: Fix concat changes --- common/src/app/common/files/changes_builder.cljc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc index f868cbd2a..d219fc365 100644 --- a/common/src/app/common/files/changes_builder.cljc +++ b/common/src/app/common/files/changes_builder.cljc @@ -109,11 +109,12 @@ [changes f] (update changes :redo-changes #(mapv f %))) +;; redo-changes is a vector and :undo-changes is a list (defn concat-changes [changes1 changes2] (-> changes1 (update :redo-changes d/concat-vec (:redo-changes changes2)) - (update :undo-changes d/concat-vec (:undo-changes changes2)))) + (update :undo-changes #(concat (:undo-changes changes2) %)))) ; TODO: remove this when not needed (defn- assert-page-id! From 899093dd5563d4bff1f018f2e17706887bf18aff Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 6 Mar 2024 18:10:07 +0100 Subject: [PATCH 023/136] :recycle: Update team icons --- .../common/refactor/common-dashboard.scss | 4 +- .../styles/common/refactor/design-tokens.scss | 5 +- .../src/app/main/ui/components/forms.scss | 2 +- frontend/src/app/main/ui/dashboard.scss | 4 +- frontend/src/app/main/ui/dashboard/team.cljs | 285 +++-- frontend/src/app/main/ui/dashboard/team.scss | 1068 +++++++---------- frontend/src/app/util/i18n.cljs | 4 +- 7 files changed, 636 insertions(+), 736 deletions(-) diff --git a/frontend/resources/styles/common/refactor/common-dashboard.scss b/frontend/resources/styles/common/refactor/common-dashboard.scss index 7e1830ab7..5404d5630 100644 --- a/frontend/resources/styles/common/refactor/common-dashboard.scss +++ b/frontend/resources/styles/common/refactor/common-dashboard.scss @@ -4,12 +4,13 @@ // // Copyright (c) KALEIDOS INC -@use "common/refactor/common-refactor" as *; +@use "refactor/common-refactor" as *; .dashboard-header { align-items: center; display: flex; height: $s-64; + max-height: $s-64; justify-content: space-between; padding: $s-4 $s-16 $s-4 $s-8; position: relative; @@ -18,6 +19,7 @@ &.team { display: grid; grid-template-columns: 20% 1fr 20%; + max-height: $s-64; } .element-name { diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss index eb1116b7f..bd18e57fe 100644 --- a/frontend/resources/styles/common/refactor/design-tokens.scss +++ b/frontend/resources/styles/common/refactor/design-tokens.scss @@ -370,6 +370,7 @@ --pill-foreground-color: var(--color-foreground-primary); --tag-background-color: var(--color-accent-primary); + --tag-background-color-disabled: var(--color-foreground-primary); --link-foreground-color: var(--color-accent-primary); @@ -377,7 +378,9 @@ --resize-area-border-color: var(--color-background-quaternary); --profile-section-background-color: var(--color-background-tertiary); - + --dashboard-list-background-color: var(--color-background-tertiary); + --dashboard-list-foreground-color: var(--color-foreground-primary); + --dashboard-list-text-foreground-color: var(--color-foreground-secondary); --flow-tag-background-color: var(--color-background-tertiary); --flow-tag-foreground-color: var(--color-foreground-secondary); --flow-tag-background-color-hover: var(--color-background-quaternary); diff --git a/frontend/src/app/main/ui/components/forms.scss b/frontend/src/app/main/ui/components/forms.scss index c9e09ec19..d77fce23b 100644 --- a/frontend/src/app/main/ui/components/forms.scss +++ b/frontend/src/app/main/ui/components/forms.scss @@ -336,7 +336,7 @@ color: var(--alert-text-foreground-color-error); } .icon svg { - stroke: var(--alert-icon-foreground-color-error); + stroke: var(--alert-text-foreground-color-error); } } } diff --git a/frontend/src/app/main/ui/dashboard.scss b/frontend/src/app/main/ui/dashboard.scss index fdf2d0d69..064694ec9 100644 --- a/frontend/src/app/main/ui/dashboard.scss +++ b/frontend/src/app/main/ui/dashboard.scss @@ -20,8 +20,8 @@ } .dashboard-content { - display: flex; - flex-direction: column; + display: grid; + grid-template-rows: $s-64 1fr; position: relative; grid-row: 1 / span 2; padding: $s-16 $s-16 0 0; diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index cbbbb421e..a2f80d058 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -24,6 +24,7 @@ [app.main.ui.dashboard.change-owner] [app.main.ui.dashboard.team-form] [app.main.ui.icons :as i] + [app.main.ui.notifications.context-notification :refer [context-notification]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] [beicon.v2.core :as rx] @@ -31,6 +32,31 @@ [cuerdas.core :as str] [rumext.v2 :as mf])) + +(def ^:private arrow-icon + (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) + +(def ^:private menu-icon + (i/icon-xref :menu-refactor (stl/css :menu-icon))) + +(def ^:private warning-icon + (i/icon-xref :msg-warning-refactor (stl/css :warning-icon))) + +(def ^:private success-icon + (i/icon-xref :msg-success-refactor (stl/css :success-icon))) + +(def ^:private image-icon + (i/icon-xref :img-refactor (stl/css :image-icon))) + +(def ^:private user-icon + (i/icon-xref :user-refactor (stl/css :user-icon))) + +(def ^:private document-icon + (i/icon-xref :document-refactor (stl/css :document-icon))) + +(def ^:private group-icon + (i/icon-xref :group-refactor (stl/css :group-icon))) + (mf/defc header {::mf/wrap [mf/memo] ::mf/wrap-props false} @@ -163,17 +189,16 @@ (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]]) + [:& context-notification {:content @error-text + :type :error}]) (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")]]) + [:& context-notification {:content (tr "modals.invite-member.repeated-invitation") + :type :warning}]) [:div {:class (stl/css :role-select)} - [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")] + [:p {:class (stl/css :role-title)} + (tr "onboarding.choice.team-up.roles")] [:& fm/select {:name :role :options roles}]] [:div {:class (stl/css :invitation-row)} @@ -190,6 +215,7 @@ [:div {:class (stl/css :action-buttons)} [:> fm/submit-button* {:label (tr "modals.invite-member-confirm.accept") + :class (stl/css :accept-btn) :disabled (and (boolean (some current-data-emails current-members-emails)) (empty? (remove current-members-emails current-data-emails)))}]]]])) @@ -202,8 +228,8 @@ [{:keys [member profile]}] (let [is-you? (= (:id profile) (:id member))] [:* - [:div {:class (stl/css :member-image)} - [:img {:src (cfg/resolve-profile-photo-url member)}]] + [:img {:class (stl/css :member-image) + :src (cfg/resolve-profile-photo-url member)}] [:div {:class (stl/css :member-info)} [:div {:class (stl/css :member-name)} (:name member) (when is-you? @@ -238,19 +264,25 @@ [: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]] + arrow-icon] [: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")] + [:ul {:class (stl/css :roles-dropdown)} + [:li {:on-click on-set-admin + :class (stl/css :rol-dropdown-item)} + (tr "labels.admin")] + [:li {:on-click on-set-editor + :class (stl/css :rol-dropdown-item)} + (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")])]]])) + [:li {:on-click (partial on-set-owner member) + :class (:stl/css :rol-dropdown-item)} + (tr "labels.owner")])]]])) (mf/defc member-actions {::mf/wrap-props false} @@ -267,15 +299,20 @@ [:* (when (or is-you? (and can-delete? (not (and is-owner? (not owner?))))) - [:span {:class (stl/css :icon) - :on-click on-show} [i/actions]]) + [:button {:class (stl/css :menu-btn) + :on-click on-show} + menu-icon]) [:& dropdown {:show @show? :on-close on-hide} - [:ul {:class (stl/css :dropdown :actions-dropdown)} + [:ul {:class (stl/css :actions-dropdown)} (when is-you? - [:li {:on-click on-leave} (tr "dashboard.leave-team")]) + [:li {:on-click on-leave + :class (stl/css :action-dropdown-item) + :key "is-you-option"} (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")])]]])) + [:li {:on-click on-delete + :class (stl/css :action-dropdown-item) + :key "is-not-you-option"} (tr "labels.remove-member")])]]])) (defn- set-role! [member-id role] (let [params {:member-id member-id :role role}] @@ -396,10 +433,10 @@ :else on-leave)] [:div {:class (stl/css :table-row)} - [:div {:class (stl/css :table-field :name)} + [:div {:class (stl/css :table-field :field-name)} [:& member-info {:member member :profile profile}]] - [:div {:class (stl/css :table-field :roles)} + [:div {:class (stl/css :table-field :field-roles)} [:& rol-info {:member member :team team :on-set-admin on-set-admin @@ -407,7 +444,7 @@ :on-set-owner on-set-owner :profile profile}]] - [:div {:class (stl/css :table-field :actions)} + [:div {:class (stl/css :table-field :field-actions)} [:& member-actions {:member member :profile profile :team team @@ -427,8 +464,8 @@ [: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-field :title-field-name)} (tr "labels.member")] + [:div {:class (stl/css :table-field :title-field-role)} (tr "labels.role")]] [:div {:class (stl/css :table-rows)} [:& team-member @@ -499,14 +536,20 @@ [: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]] + arrow-icon] [: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")]]]])) + [:ul {:class (stl/css :roles-dropdown)} + [:li {:data-role "admin" + :class (stl/css :rol-dropdown-item) + :on-click on-change'} + (tr "labels.admin")] + [:li {:data-role "editor" + :class (stl/css :rol-dropdown-item) + :on-click on-change'} + (tr "labels.editor")]]]])) (mf/defc invitation-status-badge {::mf/wrap-props false} @@ -514,8 +557,8 @@ [:div {:class (stl/css-case :status-badge true - :expired (= status :expired) - :pending (= status :pending))} + :badge-expired (= status :expired) + :badge-pending (= status :pending))} [:span {:class (stl/css :status-label)} (if (= status :expired) (tr "labels.expired-invitation") @@ -600,13 +643,21 @@ on-show (mf/use-fn #(reset! show? true))] [:* - [:span {:class (stl/css :icon) - :on-click on-show} [i/actions]] + [:button {:class (stl/css :menu-btn) + :on-click on-show} + menu-icon] + [:& 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")]]]])) + [:ul {:class (stl/css :actions-dropdown :invitations-dropdown)} + [:li {:on-click on-copy + :class (stl/css :action-dropdown-item)} + (tr "labels.copy-invitation-link")] + [:li {:on-click on-resend + :class (stl/css :action-dropdown-item)} + (tr "labels.resend-invitation")] + [:li {:on-click on-delete + :class (stl/css :action-dropdown-item)} + (tr "labels.delete-invitation")]]]])) (mf/defc invitation-row {::mf/wrap [mf/memo] @@ -626,20 +677,20 @@ mdata {:on-success #(st/emit! (dd/fetch-team-invitations))}] (st/emit! (dd/update-team-invitation-role (with-meta params mdata))))))] - [:div {:class (stl/css :table-row)} - [:div {:class (stl/css :table-field :mail)} email] + [:div {:class (stl/css :table-row :table-row-invitations)} + [:div {:class (stl/css :table-field :field-email)} email] - [:div {:class (stl/css :table-field :roles)} + [:div {:class (stl/css :table-field :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)} + [:div {:class (stl/css :table-field :field-status)} [:& invitation-status-badge {:status status}]] - [:div {:class (stl/css :table-field :actions)} + [:div {:class (stl/css :table-field :field-actions)} (when can-invite? [:& invitation-actions {:invitation invitation @@ -660,11 +711,11 @@ can-invite? (or owner? admin?) team-id (:id team)] - [:div {:class (stl/css :dashboard-table :invitations)} + [:div {:class (stl/css :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")]] + [:div {:class (stl/css :title-field-name)} (tr "labels.invitations")] + [:div {:class (stl/css :title-field-role)} (tr "labels.role")] + [:div {:class (stl/css :title-field-status)} (tr "labels.status")]] (if (empty? invitations) [:& empty-invitation-table {:can-invite? can-invite?}] [:div {:class (stl/css :table-rows)} @@ -692,7 +743,7 @@ [:* [:& header {:section :dashboard-team-invitations :team team}] - [:section {:class (stl/css :dashboard-container :dashboard-team-invitations)} + [:section {:class (stl/css :dashboard-team-invitations)} ;; TODO: We should consider adding a "loading state" here ;; with an (if (nil? invitations) [:& loading-state] [:& invitations]) (when-not (nil? invitations) @@ -828,20 +879,17 @@ (tr "modals.edit-webhook.submit-label") (tr "modals.create-webhook.submit-label"))}]]]]]])) - (mf/defc webhooks-hero {::mf/wrap-props false} [] [: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")]]]]) + [:h2 {:class (stl/css :hero-title)} + (tr "labels.webhooks")] + [:& i18n/tr-html {:class (stl/css :hero-desc) + :label "dashboard.webhooks.description"}] + [:button {:class (stl/css :hero-btn) + :on-click #(st/emit! (modal/show :webhook {}))} + (tr "dashboard.webhooks.create")]]) (mf/defc webhook-actions {::mf/wrap-props false} @@ -852,23 +900,24 @@ [:* - [:span {:class (stl/css :icon) - :on-click on-show} [i/actions]] + [:button {:class (stl/css :menu-btn) + :on-click on-show} + menu-icon] [:& 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")]]]])) + [:ul {:class (stl/css :webhook-actions-dropdown)} + [:li {:on-click on-edit + :class (stl/css :webhook-dropdown-item)} (tr "labels.edit")] + [:li {:on-click on-delete + :class (stl/css :webhook-dropdown-item)} (tr "labels.delete")]]]])) (mf/defc last-delivery-icon {::mf/wrap-props false} [{:keys [success? text]}] - [:div {:class (stl/css :last-delivery-icon)} - [:div {:class (stl/css :tooltip)} - [:div {:class (stl/css :label)} text] - [:div {:class (stl/css :arrow-down)}]] + [:div {:class (stl/css :last-delivery-icon) + :title text} (if success? - [:span {:class (stl/css :icon :success)} i/msg-success] - [:span {:class (stl/css :icon :failure)} i/msg-warning])]) + success-icon + warning-icon)]) (mf/defc webhook-item {::mf/wrap [mf/memo]} @@ -913,12 +962,12 @@ (dm/str " " (tr "errors.webhooks.unexpected-status" (extract-status error-code))))))] - [: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-row :webhook-row)} + [:div {:class (stl/css :table-field :last-delivery) + :title last-delivery-text} + (if (nil? error-code) + success-icon + warning-icon)] [:div {:class (stl/css :table-field :uri)} [:div (dm/str (:uri webhook))]] [:div {:class (stl/css :table-field :active)} @@ -933,10 +982,9 @@ (mf/defc webhooks-list {::mf/wrap-props false} [{:keys [webhooks]}] - [:div {:class (stl/css :dashboard-table)} - [:div {:class (stl/css :table-rows)} - (for [webhook webhooks] - [:& webhook-item {:webhook webhook :key (:id webhook)}])]]) + [:div {:class (stl/css :table-rows :webhook-table)} + (for [webhook webhooks] + [:& webhook-item {:webhook webhook :key (:id webhook)}])]) (mf/defc team-webhooks-page {::mf/wrap-props false} @@ -1005,38 +1053,51 @@ [:* [:& 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}])]] + [:section {:class (stl/css :dashboard-team-settings)} + [:div {:class (stl/css :block :info-block)} + [:div {:class (stl/css :block-label)} + (tr "dashboard.team-info")] + [:div {:class (stl/css :block-text)} + (:name team)] + [:div {:class (stl/css :team-icon)} + (when can-edit? + [:button {:class (stl/css :update-overlay) + :on-click on-image-click} + image-icon]) + [:img {:class (stl/css :team-image) + :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)} + [:div {:class (stl/css :block-label)} + (tr "dashboard.team-members")] - [: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)))]]]]]]])) + [:div {:class (stl/css :block-content)} + [:img {:class (stl/css :owner-icon) + :src (cfg/resolve-profile-photo-url owner)}] + [:span {:class (stl/css :block-text)} + (str (:name owner) " (" (tr "labels.owner") ")")]] + + [:div {:class (stl/css :block-content)} + user-icon + [:span {:class (stl/css :block-text)} + (tr "dashboard.num-of-members" (count members-map))]]] + + [:div {:class (stl/css :block)} + [:div {:class (stl/css :block-label)} + (tr "dashboard.team-projects")] + + [:div {:class (stl/css :block-content)} + group-icon + [:span {:class (stl/css :block-text)} + (tr "labels.num-of-projects" (i18n/c (dec (:projects stats))))]] + + [:div {:class (stl/css :block-content)} + document-icon + [:span {:class (stl/css :block-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 2f1b8840e..c5d67a027 100644 --- a/frontend/src/app/main/ui/dashboard/team.scss +++ b/frontend/src/app/main/ui/dashboard/team.scss @@ -7,577 +7,446 @@ @use "common/refactor/common-refactor.scss" as *; @use "common/refactor/common-dashboard"; -.dashboard-container { - flex: 1 0 0; - margin-right: $s-16; - overflow-y: auto; +// Dashboard team settings +.dashboard-team-settings { + display: grid; + grid-template-rows: auto auto 1fr; + justify-items: center; + gap: $s-24; width: 100%; - border-top: $s-1 solid $db-quaternary; - - &.dashboard-projects { - user-select: none; - } - &.dashboard-shared { - width: calc(100vw - $s-320); - margin-right: $s-52; - } - - &.search { - margin-top: $s-12; - } + border-top: $s-1 solid var(--panel-border-color); + overflow-y: auto; } -.dashboard-team-webhooks { - display: flex; - flex-direction: column; - width: $s-800; - margin-left: $s-120; - margin-top: $s-80; - border: none; - align-items: flex-start; -} - -.webhooks-empty { - align-items: center; - background-color: transparent; - border-radius: $br-8; - border: $s-1 solid $db-quaternary; - color: $df-secondary; - display: flex; - flex-direction: column; - font-size: $fs-12; - justify-content: center; - margin-top: $s-32; +.block { + display: grid; + grid-auto-rows: min-content; + gap: $s-8; max-width: $s-1000; - min-height: $s-136; - padding: $s-32; - text-align: center; - width: $s-468; + width: $s-1000; +} + +.info-block { + position: relative; + padding-top: $s-180; +} + +.block-label { + @include headlineSmallTypography; + color: var(--title-foreground-color); +} + +.block-text { + color: var(--title-foreground-color-hover); +} + +.block-content { + display: grid; + grid-template-columns: $s-32 1fr; + align-items: center; + gap: $s-12; +} + +.owner-icon { + width: $s-32; + height: $s-32; + border-radius: 50%; +} + +.user-icon, +.document-icon, +.group-icon { + @extend .button-icon; + margin: 0 auto; + stroke: var(--icon-foreground); +} + +.team-icon { + --update-button-opacity: 0; + position: absolute; + top: 0; + left: 0; + height: $s-120; + width: $s-120; + padding: $s-16; + + &:hover { + --update-button-opacity: 1; + } +} + +.team-image { + border-radius: 50%; + width: $s-120; + height: $s-120; +} + +.update-overlay { + opacity: var(--update-button-opacity); + @include buttonStyle; + @include flexCenter; + position: absolute; + top: $s-16; + left: $s-16; + height: 100%; + width: 100%; + z-index: $z-index-modal; + border-radius: $br-circle; + background-color: $da-primary; +} + +.image-icon { + @extend .button-icon; + min-width: $s-24; + min-height: $s-24; + stroke: var(--icon-foreground-hover); +} + +// TEAM MEMBERS PAGE +.dashboard-team-members { + display: grid; + justify-items: center; + width: 100%; + height: 100%; + padding-top: $s-20; + border-top: $s-1 solid var(--panel-border-color); + overflow-y: auto; + scrollbar-gutter: stable; +} + +.team-members { + display: grid; + grid-template-rows: auto 1fr; + height: fit-content; + max-width: $s-1000; + width: $s-1000; +} + +.table-header { + @include headlineSmallTypography; + display: grid; + align-items: center; + grid-template-columns: 43% 1fr $s-108 $s-12; + height: $s-40; + width: 100%; + max-width: $s-1000; + padding: 0 $s-16; + user-select: none; + color: var(--title-foreground-color); +} + +.table-rows { + display: grid; + grid-auto-rows: $s-64; + gap: $s-16; + width: 100%; + height: 100%; + max-width: $s-1000; + margin-top: $s-16; + color: var(--title-foreground-color); +} + +.table-row { + display: grid; + grid-template-columns: 43% 1fr auto; + align-items: center; + height: $s-64; + width: 100%; + padding: 0 $s-16; + border-radius: $br-8; + background-color: var(--dashboard-list-background-color); + color: var(--dashboard-list-foreground-color); +} + +.title-field-name { + width: 43%; + min-width: $s-300; +} + +.title-field-roles { + position: relative; + cursor: default; +} + +.field-name { + display: grid; + grid-template-columns: auto 1fr; + gap: $s-16; + width: 43%; + min-width: $s-300; +} + +.field-roles { + position: relative; + cursor: default; +} + +.field-actions { + position: relative; +} + +// MEMBER INFO +.member-image { + height: $s-32; + width: $s-32; + border-radius: $br-circle; +} + +.member-info { + display: grid; + grid-template-rows: 1fr 1fr; + width: 100%; +} + +.member-name, +.member-email { + @include textEllipsis; + @include bodyLargeTypography; +} + +.member-email { + @include bodySmallTypography; + color: var(--dashboard-list-text-foreground-color); +} + +.you { + color: var(--dashboard-list-text-foreground-color); + margin-left: $s-6; +} + +// ROL INFO +.rol-selector { + position: relative; + display: grid; + grid-template-columns: 1fr auto; + align-items: center; + height: $s-32; + min-width: $s-160; + width: fit-content; + padding: $s-4 $s-8; + border-radius: $br-8; + border-color: var(--menu-background-color-hover); + background-color: var(--menu-background-color-hover); + font-size: $fs-14; +} + +.has-priv { + cursor: pointer; +} + +.rol-label { + user-select: none; +} + +.roles-dropdown { + @extend .menu-dropdown; + bottom: calc(-1 * $s-76); + width: fit-content; + min-width: $s-160; +} + +.rol-dropdown-item { + @extend .menu-item-base; +} + +// MEMBER ACTIONS +.menu-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} + +.menu-btn { + @include buttonStyle; +} + +.actions-dropdown { + @extend .menu-dropdown; + bottom: calc(-1 * $s-32); + right: 0; + left: unset; + width: fit-content; + min-width: $s-160; +} + +.action-dropdown-item { + @extend .menu-item-base; +} + +// TEAM INVITATION PAGE +.dashboard-team-invitations { + display: grid; + justify-items: center; + width: 100%; + height: 100%; + padding-top: $s-20; + border-top: $s-1 solid var(--panel-border-color); + overflow-y: auto; + scrollbar-gutter: stable; +} + +.invitations { + display: grid; + grid-template-rows: auto 1fr; + height: fit-content; + max-width: $s-1000; + width: $s-1000; +} + +.table-row-invitations { + grid-template-columns: 43% 1fr $s-108 $s-12; + align-items: center; +} + +.empty-invitations { + display: grid; + place-items: center; + align-content: center; + height: $s-156; + max-width: $s-1000; + width: 100%; + margin-top: $s-16; + border: $s-1 solid var(--panel-border-color); + border-radius: $br-8; + color: var(--dashboard-list-text-foreground-color); +} + +.title-field-status { + position: relative; + cursor: default; +} + +.field-email { + @include textEllipsis; + @include bodyLargeTypography; + display: grid; + align-items: center; +} + +// STATUS BADGE +.status-badge { + @include flexCenter; + @include headlineSmallTypography; + min-width: $s-76; + width: fit-content; + height: $s-24; + border-radius: $br-8; + color: var(--pill-foreground-color); +} + +.badge-pending { + background-color: var(--status-widget-background-color-warning); +} + +.badge-expired { + background-color: var(--tag-background-color-disabled); +} + +.invitations-dropdown { + bottom: calc(-1 * $s-112); + right: calc(-1 * $s-20); +} + +// WEBHOOKS SECTION +.dashboard-team-webhooks { + display: grid; + grid-template-rows: auto 1fr; + justify-items: center; + gap: $s-24; + width: 100%; + height: 100%; + padding-top: $s-16; + border-top: $s-1 solid var(--panel-border-color); + overflow-y: auto; } .webhooks-hero-container { + display: grid; + gap: $s-32; + max-width: $s-1000; + width: $s-1000; +} + +.webhooks-empty { + display: grid; + place-items: center; + align-content: center; + height: $s-156; max-width: $s-1000; width: 100%; - display: flex; - flex-direction: column; - - width: $s-468; - background-color: transparent; - - .upload-button { - width: $s-100; - } - - .btn-secondary { - margin-left: $s-12; - } + padding: $s-32; + border: $s-1 solid var(--panel-border-color); + border-radius: $br-8; + color: var(--dashboard-list-text-foreground-color); } .webhooks-hero { font-size: $fs-14; - display: flex; - flex-direction: column; + display: grid; + grid-template-rows: auto 1fr auto; gap: $s-32; - justify-content: space-between; margin-top: $s-32; margin: 0; padding: $s-32; padding: 0; width: $s-468; - - .desc { - color: $df-secondary; - width: 100%; - - h2 { - color: $df-primary; - font-size: $fs-24; - font-weight: regular; - margin-bottom: $s-32; - } - p { - color: $df-secondary; - margin-bottom: 0; - font-size: $fs-16; - } - } - .btn-primary { - @extend .button-primary; - height: $s-32; - } } -.dropdown { - background-color: $db-tertiary; - border-radius: $br-8; - border: $s-1 solid $db-quaternary; - box-shadow: 0 $s-2 $s-8 rgba(0, 0, 0, 0.25); - left: calc(-1 * $s-144); - max-height: $s-480; - min-width: $s-252; - overflow-y: auto; - position: absolute; - top: $s-32; - width: $s-152; - z-index: $z-index-4; - - hr { - margin: 0; - border-color: $df-secondary; - } - - li { - display: flex; - align-items: center; - cursor: pointer; - font-size: $fs-14; - padding: $s-4 $s-16; - border-radius: $br-8; - height: $s-40; - margin: $s-6; - color: $df-primary; - - &:hover { - background-color: $db-quaternary; - } - - &.title { - font-weight: $fw700; - cursor: default; - } - } - - .separator { - border-color: transparent; - margin-top: $s-8; - } - - &.options-dropdown { - li { - color: $df-primary; - &.warning { - color: var(--element-foreground-warning); - } - } - } +.hero-title { + @include bigTitleTipography; + color: var(--dashboard-list-foreground-color); } -.dashboard-table { - display: flex; - flex-direction: column; - align-items: center; - margin-top: $s-20; - font-size: $fs-16; - - .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; - user-select: none; - width: 100%; - } - .table-rows { - display: flex; - flex-direction: column; - max-width: $s-1000; - width: 100%; - margin-top: $s-16; - color: $db-secondary; - } - - .table-row { - align-items: center; - background-color: $db-tertiary; - border-radius: $br-8; - color: $df-primary; - display: flex; - height: $s-64; - padding: 0 $s-16; - width: 100%; - - &:not(:first-child) { - margin-top: $s-16; - } - } - - .table-field { - display: flex; - align-items: center; - - .icon { - padding-left: $s-12; - cursor: pointer; - } - - &.name { - width: 43%; - min-width: $s-300; - display: flex; - } - &.roles { - flex-grow: 1; - cursor: default; - position: relative; - .rol-label { - user-select: none; - } - .rol-selector { - &.has-priv { - cursor: pointer; - } - min-width: $s-160; - height: $s-32; - display: flex; - justify-content: space-between; - align-items: center; - padding: $s-4 $s-8; - font-size: $fs-14; - background-color: $db-quaternary; - border-color: transparent; - border-radius: $br-8; - } - - .dropdown { - left: 0; - } - } - - &.actions { - position: relative; - .actions-dropdown { - max-height: $s-480; - min-width: $s-180; - } - - svg { - fill: $df-secondary; - } - } - - &.status { - .status-badge { - min-width: $s-76; - height: $s-24; - display: flex; - justify-content: center; - align-items: center; - border-radius: $br-8; - color: $db-primary; - text-transform: uppercase; - - &.pending { - background-color: var(--status-color-warning-500); - } - - &.expired { - background-color: $df-secondary; - } - - .status-label { - font-size: $fs-12; - } - } - } - - &.uri { - flex-grow: 1; - } - - &.active { - min-width: $s-100; - } - - &.last-delivery { - display: flex; - justify-content: center; - width: $s-52; - position: relative; - .success svg { - fill: $da-tertiary; - width: $s-16; - height: $s-16; - } - .failure svg { - fill: var(--element-foreground-warning); - width: $s-16; - height: $s-16; - } - - .icon-container { - width: $s-16; - height: $s-16; - overflow-x: visible; - } - - .icon { - padding: 0; - } - } - - .tooltip { - display: none; - position: absolute; - top: calc(-1 * $s-56); - left: 50%; - transform: translate(-50%, 0); - text-align: center; - - .label { - border-radius: $br-4; - color: $df-primary; - background-color: $db-secondary; - white-space: nowrap; - padding: $s-12 $s-20; - } - - .arrow-down { - margin: 0 auto; - width: 0; - height: 0; - border-left: $s-8 solid transparent; - border-right: $s-8 solid transparent; - border-top: $s-8 solid $db-secondary; - } - } - - .last-delivery-icon:hover { - .tooltip { - display: block; - } - } - } - - .member-info { - display: flex; - flex-direction: column; - margin-left: $s-16; - } - .member-name { - font-size: $fs-16; - } - .you { - color: $df-secondary; - margin-left: $s-6; - } - .member-email { - color: $df-secondary; - font-size: $fs-12; - } - .member-image { - height: $s-32; - width: $s-32; - img { - border-radius: 50%; - } - } - - .dashboard-team-webhooks & { - width: $s-800; - .table-rows { - padding-top: 0; - .table-row { - font-size: $fs-16; - min-height: $s-40; - height: fit-content; - .name { - color: $df-primary; - max-width: $s-480; - } - .expiration-date { - color: $df-secondary; - } - } - } - } - - &.team-members { - margin-bottom: $s-52; - } - - &.invitations { - .table-row { - display: grid; - grid-template-columns: 43% 1fr $s-108 $s-12; - } - } - - svg { - width: $s-12; - height: $s-12; - fill: $df-secondary; - } -} - -.empty-invitations { - height: $s-156; - max-width: $s-1000; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - margin-top: $s-16; - border: $s-1 solid $db-quaternary; - border-radius: $br-8; +.hero-desc { color: $df-secondary; + margin-bottom: 0; + font-size: $fs-16; + max-width: $s-512; } -.team-settings { - display: flex; - justify-content: center; - margin-top: $s-16; - - svg { - width: $s-20; - height: $s-20; - } - - .horizontal-blocks { - display: flex; - max-width: $s-1000; - justify-content: space-between; - width: 100%; - flex-direction: column; - gap: $s-24; - } - - .block { - display: flex; - max-width: $s-324; - width: $s-324; - flex-direction: column; - padding: $s-12; - - .label { - color: $df-secondary; - font-size: $fs-12; - text-transform: uppercase; - } - .icon svg { - fill: $df-secondary; - } - .name, - .text { - color: $df-primary; - } - } - - .info-block { - position: relative; - padding-top: $s-180; - - .name { - margin-top: $s-12; - font-size: $fs-24; - color: $df-primary; - @include text-ellipsis; - margin-right: $s-88; - } - - .icon { - position: absolute; - padding: $s-16; - right: 0; - top: 0; - left: 0; - height: $s-120; - width: $s-120; - - img { - border-radius: 50%; - width: $s-120; - height: $s-120; - } - - .update-overlay { - opacity: 0; - cursor: pointer; - position: absolute; - display: flex; - justify-content: center; - align-items: center; - border-radius: 50%; - color: $df-primary; - z-index: $z-index-modal; - background-color: $da-primary; - height: 100%; - width: 100%; - - svg { - fill: $db-primary; - } - } - - &:hover { - .update-overlay { - opacity: 1; - top: $s-16; - left: $s-16; - } - } - } - } - - .owner-block { - img { - width: $s-32; - height: $s-32; - border-radius: 50%; - } - - svg { - width: $s-12; - height: $s-12; - fill: $db-secondary; - } - - .owner { - margin-top: $s-6; - display: flex; - align-items: center; - color: $db-secondary; - .icon { - margin-right: $s-12; - } - } - - .summary { - margin-top: $s-6; - color: $db-secondary; - .icon { - padding: 0 $s-12; - margin-right: $s-12; - } - } - } - - .stats-block { - svg { - fill: $db-secondary; - } - - .projects, - .files { - margin-top: $s-8; - display: flex; - align-items: center; - color: $db-secondary; - - .icon { - display: flex; - align-items: center; - padding: 0 $s-2; - margin-right: $s-12; - } - } - } +.hero-btn { + @extend .button-primary; + height: $s-32; + max-width: $s-512; } +.webhook-table { + height: fit-content; +} + +.webhook-row { + display: grid; + align-items: center; + grid-template-columns: auto 1fr auto auto; + gap: $s-16; +} + +.actions { + position: relative; +} + +.webhook-actions-dropdown { + @extend .menu-dropdown; + right: calc(-1 * $s-16); + bottom: calc(-1 * $s-40); + width: fit-content; + min-width: $s-160; +} + +.webhook-dropdown-item { + @extend .menu-item-base; +} + +.success-icon { + @extend .button-icon; + stroke: var(--alert-icon-foreground-color-success); +} + +.warning-icon { + @extend .button-icon; + stroke: var(--alert-icon-foreground-color-warning); +} + +// INVITE MEMBERS MODAL .modal-team-container { @extend .modal-container-base; @include menuShadow; @@ -592,83 +461,46 @@ top: $s-216; right: $s-32; } - .modal-title { - @include headlineMediumTypography; - height: $s-32; - color: var(--modal-title-foreground-color); - } - .error-msg { - @include flexRow; - height: $s-32; - border-radius: $br-8; - background-color: var(--alert-background-color-error); - .icon { - @include flexCenter; - width: $s-16; - height: $s-24; - svg { - @extend .button-icon; - stroke: var(--alert-icon-foreground-color-error); - } - } - .message { - @include bodySmallTypography; - color: var(--alert-foreground-color-error); - } - } - - .warning-msg { - @include flexRow; - height: $s-32; - border-radius: $br-8; - background-color: var(--alert-background-color-warning); - padding: $s-24 $s-8; - gap: $s-8; - margin-bottom: $s-16; - - .icon { - @include flexCenter; - width: $s-16; - height: $s-24; - svg { - @extend .button-icon; - stroke: var(--alert-icon-foreground-color-warning); - } - } - .message { - @include bodySmallTypography; - color: var(--alert-foreground-color-warning); - } - } - - .role-select { - @include flexColumn; - row-gap: $s-8; - .role-title { - @include bodyLargeTypography; - margin: 0; - color: var(--modal-title-foreground-color); - } - } - - .invitation-row { - margin-top: $s-8; - margin-bottom: $s-24; - } - - .action-buttons { - display: flex; - justify-content: flex-end; - button { - @extend .modal-accept-btn; - &:disabled { - @extend .button-disabled; - } - } - } } -// WEBHOOKS +.modal-title { + @include headlineMediumTypography; + height: $s-32; + color: var(--modal-title-foreground-color); +} + +.role-select { + @include flexColumn; + row-gap: $s-8; +} + +.arrow-icon { + @extend .button-icon; + stroke: var(--icon-foreground); + transform: rotate(90deg); +} + +.role-title { + @include bodyLargeTypography; + margin: 0; + color: var(--modal-title-foreground-color); +} + +.invitation-row { + margin-top: $s-8; + margin-bottom: $s-24; +} + +.action-buttons { + display: flex; + justify-content: flex-end; +} + +.accept-btn { + @extend .modal-accept-btn; +} + +// WEBHOOKS MODAL .modal-overlay { @extend .modal-overlay-base; diff --git a/frontend/src/app/util/i18n.cljs b/frontend/src/app/util/i18n.cljs index acb581697..39575d601 100644 --- a/frontend/src/app/util/i18n.cljs +++ b/frontend/src/app/util/i18n.cljs @@ -177,10 +177,12 @@ {::mf/wrap-props false} [props] (let [label (obj/get props "label") + class (obj/get props "class") tag-name (obj/get props "tag-name" "p") params (obj/get props "params" []) html (apply tr (d/concat-vec [label] params))] - [:> tag-name {:dangerouslySetInnerHTML #js {:__html html}}])) + [:> tag-name {:dangerouslySetInnerHTML #js {:__html html} + :className class}])) ;; DEPRECATED (defn use-locale From 5157928cdb6ab18be01f6a1b4ae2cfcdea2350e5 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Thu, 7 Mar 2024 12:48:25 +0100 Subject: [PATCH 024/136] :bug: Fix copy and paste a main on another main doesn't work --- common/src/app/common/types/container.cljc | 49 ++++++++++++++-------- frontend/src/app/main/data/workspace.cljs | 10 +++-- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index a29d8b940..ddeeea734 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -416,12 +416,6 @@ (some ctk/main-instance? children) (some ctk/main-instance? parents)))) -(defn has-any-main-children? - "Check if the shape is a main component or has any children that is a main component." - [objects shape] - (let [children (cfh/get-children-with-self objects (:id shape))] - (some ctk/main-instance? children))) - (defn valid-shape-for-component? "Check if a main component can be generated from this shape in terms of nested components: - A main can't be the ancestor of another main @@ -431,10 +425,29 @@ (not (has-any-main? objects shape)) (not (has-any-copy-parent? objects shape)))) + +(defn collect-main-shapes [shape objects] + (if (ctk/main-instance? shape) + [shape] + (if-let [children (cfh/get-children objects (:id shape))] + (mapcat collect-main-shapes children objects) + []))) + (defn- invalid-structure-for-component? "Check if the structure generated nesting children in parent is invalid in terms of nested components" - [objects parent children] - (let [selected-main-instance? (some true? (map #(has-any-main-children? objects %) children)) + [objects parent children pasting? libraries] + (let [; When we are pasting, the main shapes will be pasted as copies, unless the + ; original component doesn't exist or is deleted. So for this function purposes, they + ; are removed from the list + remove? (fn [shape] + (let [component (get-in libraries [(:component-file shape) :data :components (:component-id shape)])] + (and component (not (:deleted component))))) + + selected-components (cond->> (mapcat collect-main-shapes children objects) + pasting? + (remove #(remove? %))) + + selected-main-instance? (seq selected-components) parent-in-component? (in-any-component? objects parent) comps-nesting-loop? (not (->> children (map #(cfh/components-nesting-loop? objects (:id %) (:id parent))) @@ -450,13 +463,15 @@ (defn find-valid-parent-and-frame-ids "Navigate trough the ancestors until find one that is valid. Returns [ parent-id frame-id ]" - [parent-id objects children] - (letfn [(get-frame [parent-id] - (if (cfh/frame-shape? objects parent-id) parent-id (get-in objects [parent-id :frame-id])))] - (let [parent (get objects parent-id) + ([parent-id objects children] + (find-valid-parent-and-frame-ids parent-id objects children false nil)) + ([parent-id objects children pasting? libraries] + (letfn [(get-frame [parent-id] + (if (cfh/frame-shape? objects parent-id) parent-id (get-in objects [parent-id :frame-id])))] + (let [parent (get objects parent-id) ;; We can always move the children to the parent they already have - no-changes? - (->> children (every? #(= parent-id (:parent-id %))))] - (if (or no-changes? (not (invalid-structure-for-component? objects parent children))) - [parent-id (get-frame parent-id)] - (recur (:parent-id parent) objects children))))) + no-changes? + (->> children (every? #(= parent-id (:parent-id %))))] + (if (or no-changes? (not (invalid-structure-for-component? objects parent children pasting? libraries))) + [parent-id (get-frame parent-id)] + (recur (:parent-id parent) objects children pasting? libraries)))))) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 0ef0c3c7a..e981a1420 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1967,8 +1967,13 @@ page-objects (:objects page) + libraries (wsh/get-libraries state) + ldata (wsh/get-local-file state) + + full-libs (assoc-in libraries [(:id ldata) :data] ldata) + [parent-id - frame-id] (ctn/find-valid-parent-and-frame-ids candidate-parent-id page-objects (vals objects)) + frame-id] (ctn/find-valid-parent-and-frame-ids candidate-parent-id page-objects (vals objects) true full-libs) index (if (= candidate-parent-id parent-id) index @@ -1978,8 +1983,7 @@ all-objects (merge page-objects objects) - libraries (wsh/get-libraries state) - ldata (wsh/get-file state file-id) + drop-cell (when (ctl/grid-layout? all-objects parent-id) (gslg/get-drop-cell frame-id all-objects position)) From 0d1af260a4bbadabf919b9b5fac764beb56d7b3e Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Thu, 7 Mar 2024 13:34:22 +0100 Subject: [PATCH 025/136] :bug: Remove incorrect find-component function --- common/src/app/common/types/file.cljc | 6 ------ .../test/common_tests/helpers/components.cljc | 18 ++++-------------- .../test/frontend_tests/helpers/libraries.cljs | 8 ++++---- .../frontend_tests/state_components_test.cljs | 7 ++++--- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 58b579f2e..42a0a7789 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -117,12 +117,6 @@ (ctkl/update-component file-data (:id container) f))) ;; Asset helpers - -(defn find-component - "Retrieve a component from libraries, iterating over all of them." - [libraries component-id & {:keys [include-deleted?] :or {include-deleted? false}}] - (some #(ctkl/get-component (:data %) component-id include-deleted?) (vals libraries))) - (defn find-component-file [file libraries component-file] (if (and (some? file) (= component-file (:id file))) diff --git a/common/test/common_tests/helpers/components.cljc b/common/test/common_tests/helpers/components.cljc index f842d2dc2..523438c44 100644 --- a/common/test/common_tests/helpers/components.cljc +++ b/common/test/common_tests/helpers/components.cljc @@ -82,7 +82,7 @@ [page root-inst-id libraries] (let [root-inst (ctn/get-shape page root-inst-id) - component (ctf/find-component libraries (:component-id root-inst)) + component (ctf/get-component libraries (:component-file root-inst) (:component-id root-inst)) shapes-inst (cfh/get-children-with-self (:objects page) root-inst-id) shapes-main (cfh/get-children-with-self (:objects component) (:shape-ref root-inst)) @@ -94,7 +94,7 @@ (ctn/get-component-shape (:objects page) shape) component - (ctf/find-component libraries (:component-id component-shape)) + (ctf/get-component libraries (:component-file component-shape) (:component-id component-shape)) main-shape (ctn/get-shape component (:shape-ref shape))] @@ -118,7 +118,7 @@ [page root-inst-id libraries] (let [root-inst (ctn/get-shape page root-inst-id) - component (ctf/find-component libraries (:component-id root-inst)) + component (ctf/get-component libraries (:component-file root-inst) (:component-id root-inst)) shapes-inst (cfh/get-children-with-self (:objects page) root-inst-id) shapes-main (cfh/get-children-with-self (:objects component) (:shape-ref root-inst)) @@ -130,7 +130,7 @@ (ctn/get-component-shape (:objects page) shape) component - (ctf/find-component libraries (:component-id component-shape)) + (ctf/get-component libraries (:component-file component-shape) (:component-id component-shape)) main-shape (ctn/get-shape component (:shape-ref shape))] @@ -142,15 +142,5 @@ [shapes-inst shapes-main component])) -(defn resolve-component - "Get the component with the given id and all its shapes." - [page component-id libraries] - (let [component (ctf/find-component libraries component-id) - root-main (ctk/get-component-root component) - shapes-main (cfh/get-children-with-self (:objects component) (:id root-main))] - ;; Validate that the component tree is well constructed - (run! check-noninstance shapes-main) - - [shapes-main component])) diff --git a/frontend/test/frontend_tests/helpers/libraries.cljs b/frontend/test/frontend_tests/helpers/libraries.cljs index 8519ec81c..1d9137f56 100644 --- a/frontend/test/frontend_tests/helpers/libraries.cljs +++ b/frontend/test/frontend_tests/helpers/libraries.cljs @@ -112,7 +112,7 @@ main-instance? (:main-instance root-inst) libs (wsh/get-libraries state) - component (ctf/find-component libs (:component-id root-inst)) + component (ctf/get-component libs (:component-file root-inst) (:component-id root-inst)) library (ctf/get-component-library libs root-inst) shapes-inst (cfh/get-children-with-self (:objects page) root-inst-id) @@ -152,7 +152,7 @@ root-inst (ctn/get-shape page root-inst-id) libs (wsh/get-libraries state) - component (ctf/find-component libs (:component-id root-inst)) + component (ctf/get-component libs (:component-file root-inst) (:component-id root-inst)) library (ctf/get-component-library libs root-inst) shapes-inst (cfh/get-children-with-self (:objects page) root-inst-id) @@ -165,9 +165,9 @@ (defn resolve-component "Get the component with the given id and all its shapes." - [state component-id] + [state component-file component-id] (let [libs (wsh/get-libraries state) - component (ctf/find-component libs component-id) + component (ctf/get-component libs component-file component-id) library (ctf/get-component-library libs component) shapes-main (ctf/get-component-shapes (:data library) component)] diff --git a/frontend/test/frontend_tests/state_components_test.cljs b/frontend/test/frontend_tests/state_components_test.cljs index 7cb62b212..3a8751019 100644 --- a/frontend/test/frontend_tests/state_components_test.cljs +++ b/frontend/test/frontend_tests/state_components_test.cljs @@ -186,9 +186,9 @@ ;; Expected shape tree: ;; ;; [Page: Page] - ;; Root Frame + ;; Root Frame ;; Rect 1 # - ;; Rect 1 + ;; Rect 1 ;; Rect 1 # ;; Rect 1* @--> Rect 1 ;; Rect 1 ---> Rect 1 @@ -362,6 +362,7 @@ component2] (thl/resolve-component new-state + (:current-file-id new-state) new-component-id)] (t/is (= (:name component2) "Rect 1")))))] @@ -657,7 +658,7 @@ ;; ;; [Board] ;; page1 / Board - ;; + ;; (let [instance1 (thp/get-shape new-state :instance1) [[group shape1 shape2] From 07939d11dc4cb296ea82d5d5270643c51fd27df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 29 Feb 2024 14:06:39 +0100 Subject: [PATCH 026/136] :tada: Improve sync algorithm when swapped copies --- common/src/app/common/files/helpers.cljc | 3 +- common/src/app/common/types/component.cljc | 29 ++++- common/src/app/common/types/file.cljc | 99 ++++++++++++++-- .../app/main/data/workspace/libraries.cljs | 43 +++++-- .../data/workspace/libraries_helpers.cljs | 112 ++++++++++++------ 5 files changed, 227 insertions(+), 59 deletions(-) diff --git a/common/src/app/common/files/helpers.cljc b/common/src/app/common/files/helpers.cljc index 296d4da83..676ba2c46 100644 --- a/common/src/app/common/files/helpers.cljc +++ b/common/src/app/common/files/helpers.cljc @@ -361,7 +361,8 @@ (defn set-touched-group [touched group] - (conj (or touched #{}) group)) + (when group + (conj (or touched #{}) group))) (defn touched-group? [shape group] diff --git a/common/src/app/common/types/component.cljc b/common/src/app/common/types/component.cljc index ec9a679a9..7c6570f0c 100644 --- a/common/src/app/common/types/component.cljc +++ b/common/src/app/common/types/component.cljc @@ -4,7 +4,11 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.common.types.component) +(ns app.common.types.component + (:require + [app.common.data :as d] + [app.common.uuid :as uuid] + [cuerdas.core :as str])) ;; Attributes that may be synced in components, and the group they belong to. ;; When one attribute is modified in a shape inside a component, the corresponding @@ -170,6 +174,29 @@ (and (= shape-id (:main-instance-id component)) (= page-id (:main-instance-page component)))) +(defn build-swap-slot-group + "Convert a swap-slot into a :touched group" + [swap-slot] + (when swap-slot + (keyword (str "swap-slot-" swap-slot)))) + +(defn get-swap-slot + "If the shape has a :touched group in the form :swap-slot-, get the id." + [shape] + (let [group (->> (:touched shape) + (map name) + (d/seek #(str/starts-with? % "swap-slot-")))] + (when group + (uuid/uuid (subs group 10))))) + +(defn match-swap-slot? + [shape-inst shape-main] + (let [slot-inst (get-swap-slot shape-inst) + slot-main (get-swap-slot shape-main)] + (when (some? slot-inst) + (or (= slot-inst slot-main) + (= slot-inst (:id shape-main)))))) + (defn get-component-root [component] (if (true? (:main-instance-id component)) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 42a0a7789..9f16496ab 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -177,12 +177,36 @@ shape-id))) (dm/get-in component [:objects shape-id])))) +(defn get-component-shape-context + "Retrieve one shape in the component by id. Return the shape and its + context (the file and the container)." + [file component shape-id] + (let [components-v2 (dm/get-in file [:data :options :components-v2])] + (if (and components-v2 (not (:deleted component))) + (let [component-page (get-component-page (:data file) component)] + (when component-page + (let [child (cfh/get-child (:objects component-page) + (:main-instance-id component) + shape-id)] + (when child + [child file (ctn/make-container component-page :page)])))) + [(dm/get-in component [:objects shape-id]) + file + (ctn/make-container component :component)]))) + (defn get-ref-shape "Retrieve the shape in the component that is referenced by the instance shape." [file-data component shape] (when (:shape-ref shape) (get-component-shape file-data component (:shape-ref shape)))) +(defn get-ref-shape-context + "Retrieve the shape in the component that is referenced by the instance shape. + Return the shape and its context (the file and the container)." + [file component shape] + (when (:shape-ref shape) + (get-component-shape-context file component (:shape-ref shape)))) + (defn get-shape-in-copy "Given a shape in the main component and the root of the copy component returns the equivalent shape inside the root copy that matches the main-shape" @@ -196,11 +220,33 @@ [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] (let [find-ref-shape-in-head (fn [head-shape] - (let [head-file (find-component-file file libraries (:component-file head-shape)) - head-component (when (some? head-file) - (ctkl/get-component (:data head-file) (:component-id head-shape) include-deleted?))] - (when (some? head-component) - (get-ref-shape (:data head-file) head-component shape))))] + (let [component-file (find-component-file file libraries (:component-file head-shape)) + component (when (some? component-file) + (ctkl/get-component (:data component-file) (:component-id head-shape) include-deleted?))] + (when (some? component) + (get-ref-shape (:data component-file) component shape))))] + + (some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape)))) + +(defn find-ref-shape-context + "Locate the nearest component in the local file or libraries, and retrieve the shape + referenced by the instance shape. Return the shape and its context (the file and + the container)." + ; TODO: It should be nice to avoid this duplicity without adding overhead in the simple case. + ; Perhaps adding the context as metadata of the shape? + [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] + (let [find-ref-shape-in-head + (fn [head-shape] + ;; (js/console.log "head-shape" (clj->js head-shape)) + ;; (js/console.log " component-file" (str (:component-file head-shape))) + ;; (js/console.log " component-id" (str (:component-id head-shape))) + (let [component-file (find-component-file file libraries (:component-file head-shape)) + component (when (some? component-file) + (ctkl/get-component (:data component-file) (:component-id head-shape) include-deleted?))] + ;; (js/console.log "component-file" (clj->js component-file)) + ;; (js/console.log "component" (clj->js component)) + (when (some? component) + (get-ref-shape-context component-file component shape))))] (some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape)))) @@ -210,12 +256,14 @@ [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] (let [find-ref-component-in-head (fn [head-shape] - (let [head-file (find-component-file file libraries (:component-file head-shape)) - head-component (when (some? head-file) - (ctkl/get-component (:data head-file) (:component-id head-shape) include-deleted?))] - (when (some? head-component) - (when (get-ref-shape (:data head-file) head-component shape) - head-component))))] + (let [component-file (find-component-file file libraries (:component-file head-shape)) + component (when (some? component-file) + (ctkl/get-component (:data component-file) + (:component-id head-shape) + include-deleted?))] + (when (some? component) + (when (get-ref-shape (:data component-file) component shape) + component))))] (some find-ref-component-in-head (ctn/get-parent-copy-heads (:objects page) shape)))) @@ -251,6 +299,35 @@ (let [ref-component (find-ref-component file page libraries shape :include-deleted? true)] (true? (= (:id component) (:id ref-component))))) +(defn find-swap-slot + [shape page file libraries] + (dm/assert! "expected shape is head" (ctk/instance-head? shape)) + ;; (js/console.log "find-swap-slot" (clj->js shape)) + (if-let [swap-slot (ctk/get-swap-slot shape)] + ;; (do (js/console.log "uno" (str swap-slot)) swap-slot) + swap-slot + (let [[ref-shape ref-file ref-container] (find-ref-shape-context file + page + libraries + shape + :include-deleted? true)] + ;; (js/console.log "ref-shape" (clj->js ref-shape)) + (when ref-shape + ;; (js/console.log "ref-shape" (clj->js ref-shape)) + (if-let [swap-slot (ctk/get-swap-slot ref-shape)] + ;; (do (js/console.log "dos" (str swap-slot)) swap-slot) + swap-slot + (if (ctk/main-instance? ref-shape) + (:id shape) + (find-swap-slot ref-shape ref-container ref-file libraries))))))) + +(defn match-swap-slot? + [shape-inst shape-main page-inst page-main file libraries] + (let [slot-inst (find-swap-slot shape-inst page-inst file libraries) + slot-main (find-swap-slot shape-main page-main file libraries)] + (or (= slot-inst slot-main) + (= slot-inst (:id shape-main))))) + (defn get-component-shapes "Retrieve all shapes of the component" [file-data component] diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index c24d1d469..0d64b733d 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -52,7 +52,7 @@ [potok.v2.core :as ptk])) ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default -(log/set-level! :warn) +(log/set-level! :trace) (defn- log-changes [changes file] @@ -870,16 +870,12 @@ 0))))) (defn- add-component-for-swap - [shape file-id id-new-component index target-cell keep-props-values {:keys [undo-group]}] + [shape file page libraries id-new-component index target-cell keep-props-values {:keys [undo-group]}] (dm/assert! (uuid? id-new-component)) - (dm/assert! (uuid? file-id)) (ptk/reify ::add-component-for-swap ptk/WatchEvent - (watch [it state _] - (let [page (wsh/lookup-page state) - libraries (wsh/get-libraries state) - - objects (:objects page) + (watch [it _ _] + (let [objects (:objects page) position (gpt/point (:x shape) (:y shape)) changes (-> (pcb/empty-changes it (:id page)) (pcb/set-undo-group undo-group) @@ -889,7 +885,7 @@ [new-shape changes] (dwlh/generate-instantiate-component changes objects - file-id + (:id file) id-new-component position page @@ -898,6 +894,16 @@ (:parent-id shape) (:frame-id shape)) + new-shape (cond-> new-shape + (nil? (ctk/get-swap-slot new-shape)) + (update :touched cfh/set-touched-group (-> (ctf/find-swap-slot shape + page + {:id (:id file) + :data file} + libraries) + (ctk/build-swap-slot-group)))) + + ;; _ (js/console.log "new-shape" (str (:id new-shape)) (clj->js new-shape)) changes (-> changes ;; Restore the properties @@ -905,7 +911,11 @@ ;; We need to set the same index as the original shape (pcb/change-parent (:parent-id shape) [new-shape] index {:component-swap true - :ignore-touched true}))] + :ignore-touched true}) + (dwlh/change-touched new-shape + shape + (ctn/make-container page :page) + {}))] ;; First delete so we don't break the grid layout cells (rx/of (dch/commit-changes changes) @@ -921,7 +931,10 @@ (watch [_ state _] ;; First delete shapes so we have space in the layout otherwise we can have problems ;; in the grid creating new rows/columns to make space - (let [objects (wsh/lookup-page-objects state) + (let [file (wsh/get-file state file-id) + libraries (wsh/get-libraries state) + page (wsh/lookup-page state) + objects (wsh/lookup-page-objects state) parent (get objects (:parent-id shape)) ;; If the target parent is a grid layout we need to pass the target cell @@ -941,7 +954,7 @@ (dwsh/delete-shapes nil (d/ordered-set (:id shape)) {:component-swap true :undo-id undo-id :undo-group undo-group}) - (add-component-for-swap shape file-id id-new-component index target-cell keep-props-values + (add-component-for-swap shape file page libraries id-new-component index target-cell keep-props-values {:undo-group undo-group}) (ptk/data-event :layout/update [(:parent-id shape)]) (dwu/commit-undo-transaction undo-id)))))) @@ -958,8 +971,12 @@ {::ev/name "component-swap"}) ptk/WatchEvent - (watch [_ _ _] + (watch [_ state _] (let [undo-id (js/Symbol)] + (log/info :msg "COMPONENT-SWAP" + :file (dwlh/pretty-file file-id state) + :id-new-component id-new-component + :undo-id undo-id) (rx/concat (rx/of (dwu/start-undo-transaction undo-id)) (rx/map #(component-swap % file-id id-new-component) (rx/from shapes)) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 32152b2ba..92b026456 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -30,7 +30,7 @@ [clojure.set :as set])) ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default -(log/set-level! :warn) +(log/set-level! :trace) (declare generate-sync-container) (declare generate-sync-shape) @@ -594,7 +594,7 @@ "Generate changes to synchronize one shape that is the root of a component instance, and all its children, from the given component." [changes libraries container shape-id reset? components-v2] - (log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?) + (log/debug :msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?) (let [shape-inst (ctn/get-shape container shape-id) library (dm/get-in libraries [(:component-file shape-inst) :data]) component (ctkl/get-component library (:component-id shape-inst) true)] @@ -656,7 +656,7 @@ (defn- generate-sync-shape-direct-recursive [changes container shape-inst component library shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2] (log/debug :msg "Sync shape direct recursive" - :shape (str (:name shape-inst)) + :shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst))) :component (:name component)) (if (nil? shape-main) @@ -713,6 +713,8 @@ (map #(redirect-shaperef %) children-inst) children-inst) only-inst (fn [changes child-inst] + (log/trace :msg "Only inst" + :child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst)))) (if-not (and omit-touched? (contains? (:touched shape-inst) :shapes-group)) @@ -723,6 +725,8 @@ changes)) only-main (fn [changes child-main] + (log/trace :msg "Only main" + :child-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) (if-not (and omit-touched? (contains? (:touched shape-inst) :shapes-group)) @@ -739,6 +743,9 @@ changes)) both (fn [changes child-inst child-main] + (log/trace :msg "Both" + :child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) + :child-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) (generate-sync-shape-direct-recursive changes container child-inst @@ -753,6 +760,9 @@ components-v2)) moved (fn [changes child-inst child-main] + (log/trace :msg "Move" + :child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) + :child-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) (move-shape changes child-inst @@ -768,7 +778,8 @@ only-main both moved - false)))) + false + reset?)))) (defn- generate-rename-component @@ -939,6 +950,7 @@ only-main both moved + true true) ;; The inverse sync may be made on a component that is inside a @@ -957,12 +969,15 @@ ;; ---- Operation generation helpers ---- (defn- compare-children - [changes children-inst children-main only-inst-cb only-main-cb both-cb moved-cb inverse?] + [changes children-inst children-main only-inst-cb only-main-cb both-cb moved-cb inverse? reset?] + (log/trace :msg "Compare children") (loop [children-inst (seq (or children-inst [])) children-main (seq (or children-main [])) changes changes] (let [child-inst (first children-inst) child-main (first children-main)] + (log/trace :main (str (:name child-main) " " (pretty-uuid (:id child-main))) + :inst (str (:name child-inst) " " (pretty-uuid (:id child-inst)))) (cond (and (nil? child-inst) (nil? child-main)) changes @@ -979,31 +994,58 @@ (next children-main) (both-cb changes child-inst child-main)) - (let [child-inst' (d/seek #(ctk/is-main-of? child-main %) children-inst) - child-main' (d/seek #(ctk/is-main-of? % child-inst) children-main)] - (cond - (nil? child-inst') - (recur children-inst - (next children-main) - (only-main-cb changes child-main)) - - (nil? child-main') + (if (and (ctk/match-swap-slot? child-main child-inst) (not reset?)) + (do + (log/trace :msg "Match slot" + :shape-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) + :shape-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) (recur (next children-inst) - children-main - (only-inst-cb changes child-inst)) + (next children-main) + changes)) - :else - (if inverse? - (recur (next children-inst) - (remove #(= (:id %) (:id child-main')) children-main) - (-> changes - (both-cb child-inst child-main') - (moved-cb child-inst child-main'))) - (recur (remove #(= (:id %) (:id child-inst')) children-inst) - (next children-main) - (-> changes - (both-cb child-inst' child-main) - (moved-cb child-inst' child-main))))))))))) + (let [child-inst' (d/seek #(ctk/is-main-of? child-main %) children-inst) + child-main' (d/seek #(ctk/is-main-of? % child-inst) children-main)] + (cond + (nil? child-inst') + (let [matching-inst (d/seek #(ctk/match-swap-slot? % child-main) children-inst)] + (if (and (some? matching-inst) (not reset?)) + (do + (log/trace :msg "Match slot inst" + :shape-inst (str (:name child-inst') " " (pretty-uuid (:id child-inst'))) + :shape-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) + (recur (remove #(= (:id %) (:id matching-inst)) children-inst) + (next children-main) + changes)) + (recur children-inst + (next children-main) + (only-main-cb changes child-main)))) + + (nil? child-main') + (let [matching-main (d/seek #(ctk/match-swap-slot? child-inst %) children-main)] + (if (and (some? matching-main) (not reset?)) + (do + (log/trace :msg "Match slot main" + :shape-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) + :shape-main (str (:name child-main') " " (pretty-uuid (:id child-main')))) + (recur (next children-inst) + (remove #(= (:id %) (:id matching-main)) children-inst) + changes)) + (recur (next children-inst) + children-main + (only-inst-cb changes child-inst)))) + + :else + (if inverse? + (recur (next children-inst) + (remove #(= (:id %) (:id child-main')) children-main) + (-> changes + (both-cb child-inst child-main') + (moved-cb child-inst child-main'))) + (recur (remove #(= (:id %) (:id child-inst')) children-inst) + (next children-main) + (-> changes + (both-cb child-inst' child-main) + (moved-cb child-inst' child-main)))))))))))) (defn- add-shape-to-instance [changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced?] @@ -1033,7 +1075,8 @@ (assoc :remote-synced true) :always - (assoc :shape-ref (:id original-shape))))) + (-> (assoc :shape-ref (:id original-shape)) + (dissoc :touched))))) ; New shape, by definition, is synced to the main shape update-original-shape (fn [original-shape _new-shape] original-shape) @@ -1270,11 +1313,10 @@ changes changes'))) -(defn- change-touched +(defn change-touched [changes dest-shape origin-shape container {:keys [reset-touched? copy-touched?] :as options}] - (if (or (nil? (:shape-ref dest-shape)) - (not (or reset-touched? copy-touched?))) + (if (nil? (:shape-ref dest-shape)) changes (do (log/info :msg (str "CHANGE-TOUCHED " @@ -1287,12 +1329,16 @@ (let [new-touched (cond reset-touched? nil + copy-touched? (if (:remote-synced origin-shape) nil (set/union (:touched dest-shape) - (:touched origin-shape))))] + (:touched origin-shape))) + + :else + (:touched dest-shape))] (-> changes (update :redo-changes conj (make-change From 4dfbfcf2ac2ca4e1e4863ae3cdde24e528e94a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 4 Mar 2024 17:13:25 +0100 Subject: [PATCH 027/136] :recycle: Avoid duplicating helpers --- common/src/app/common/types/file.cljc | 88 +++++++++------------------ 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 9f16496ab..814c583dc 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -166,46 +166,33 @@ (ctk/get-component-root component)))) (defn get-component-shape - "Retrieve one shape in the component by id." - [file-data component shape-id] + "Retrieve one shape in the component by id. If with-context? is true, add the + file and container where the shape resides in its metadata." + [file-data component shape-id & {:keys [with-context?] :or {with-context? false}}] (let [components-v2 (dm/get-in file-data [:options :components-v2])] (if (and components-v2 (not (:deleted component))) (let [component-page (get-component-page file-data component)] - (when component-page - (cfh/get-child (:objects component-page) - (:main-instance-id component) - shape-id))) - (dm/get-in component [:objects shape-id])))) - -(defn get-component-shape-context - "Retrieve one shape in the component by id. Return the shape and its - context (the file and the container)." - [file component shape-id] - (let [components-v2 (dm/get-in file [:data :options :components-v2])] - (if (and components-v2 (not (:deleted component))) - (let [component-page (get-component-page (:data file) component)] (when component-page (let [child (cfh/get-child (:objects component-page) (:main-instance-id component) shape-id)] - (when child - [child file (ctn/make-container component-page :page)])))) - [(dm/get-in component [:objects shape-id]) - file - (ctn/make-container component :component)]))) + (cond-> child + (and child with-context?) + (with-meta {:file {:id (:id file-data) + :data file-data} + :container (ctn/make-container component-page :page)}))))) + + (cond-> (dm/get-in component [:objects shape-id]) + with-context? + (with-meta {:file {:id (:id file-data) + :data file-data} + :container (ctn/make-container component :component)}))))) (defn get-ref-shape "Retrieve the shape in the component that is referenced by the instance shape." - [file-data component shape] + [file-data component shape & {:keys [with-context?] :or {with-context? false}}] (when (:shape-ref shape) - (get-component-shape file-data component (:shape-ref shape)))) - -(defn get-ref-shape-context - "Retrieve the shape in the component that is referenced by the instance shape. - Return the shape and its context (the file and the container)." - [file component shape] - (when (:shape-ref shape) - (get-component-shape-context file component (:shape-ref shape)))) + (get-component-shape file-data component (:shape-ref shape) :with-context? with-context?))) (defn get-shape-in-copy "Given a shape in the main component and the root of the copy component returns the equivalent @@ -217,36 +204,14 @@ (defn find-ref-shape "Locate the nearest component in the local file or libraries, and retrieve the shape referenced by the instance shape." - [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] + [file page libraries shape & {:keys [include-deleted? with-context?] :or {include-deleted? false with-context? false}}] (let [find-ref-shape-in-head (fn [head-shape] (let [component-file (find-component-file file libraries (:component-file head-shape)) component (when (some? component-file) (ctkl/get-component (:data component-file) (:component-id head-shape) include-deleted?))] (when (some? component) - (get-ref-shape (:data component-file) component shape))))] - - (some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape)))) - -(defn find-ref-shape-context - "Locate the nearest component in the local file or libraries, and retrieve the shape - referenced by the instance shape. Return the shape and its context (the file and - the container)." - ; TODO: It should be nice to avoid this duplicity without adding overhead in the simple case. - ; Perhaps adding the context as metadata of the shape? - [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] - (let [find-ref-shape-in-head - (fn [head-shape] - ;; (js/console.log "head-shape" (clj->js head-shape)) - ;; (js/console.log " component-file" (str (:component-file head-shape))) - ;; (js/console.log " component-id" (str (:component-id head-shape))) - (let [component-file (find-component-file file libraries (:component-file head-shape)) - component (when (some? component-file) - (ctkl/get-component (:data component-file) (:component-id head-shape) include-deleted?))] - ;; (js/console.log "component-file" (clj->js component-file)) - ;; (js/console.log "component" (clj->js component)) - (when (some? component) - (get-ref-shape-context component-file component shape))))] + (get-ref-shape (:data component-file) component shape :with-context? with-context?))))] (some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape)))) @@ -306,14 +271,19 @@ (if-let [swap-slot (ctk/get-swap-slot shape)] ;; (do (js/console.log "uno" (str swap-slot)) swap-slot) swap-slot - (let [[ref-shape ref-file ref-container] (find-ref-shape-context file - page - libraries - shape - :include-deleted? true)] + (let [ref-shape (find-ref-shape file + page + libraries + shape + :include-deleted? true + :with-context? true) + shape-meta (meta ref-shape) + ref-file (:file shape-meta) + ref-container (:container shape-meta)] ;; (js/console.log "ref-shape" (clj->js ref-shape)) + ;; (js/console.log "ref-file" (clj->js ref-file)) + ;; (js/console.log "ref-container" (clj->js ref-container)) (when ref-shape - ;; (js/console.log "ref-shape" (clj->js ref-shape)) (if-let [swap-slot (ctk/get-swap-slot ref-shape)] ;; (do (js/console.log "dos" (str swap-slot)) swap-slot) swap-slot From 9f7d1be0a9b8aa5a275d74731b2a2aa9b7f1be53 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 09:26:51 +0100 Subject: [PATCH 028/136] :recycle: Update dashboard comment icon --- .../src/app/main/ui/dashboard/comments.cljs | 25 +++++--- .../src/app/main/ui/dashboard/comments.scss | 61 ++++++++----------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index aa55bddf8..951a15598 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -20,6 +20,17 @@ [potok.v2.core :as ptk] [rumext.v2 :as mf])) + +(def ^:private close-icon + (i/icon-xref :close-refactor (stl/css :close-icon))) + +(def ^:private comments-icon-svg + (i/icon-xref :comments-refactor (stl/css :comments-icon))) + + +(def ^:private comments-icon-small + (i/icon-xref :comments-refactor (stl/css :comments-icon-small))) + (mf/defc comments-icon [{:keys [profile show? on-show-comments]}] @@ -47,7 +58,7 @@ :class (stl/css-case :button true :open show? :unread (boolean (seq tgroups)))} - i/comments-refactor]])) + comments-icon-small]])) (mf/defc comments-section [{:keys [profile team show? on-hide-comments]}] @@ -91,11 +102,11 @@ [: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]] + [:button {:class (stl/css :close-btn) + :tab-index (if show? "0" "-1") + :on-click on-hide-comments + :on-key-down handle-keydown} + close-icon]] (if (seq tgroups) [:div {:class (stl/css :thread-groups)} @@ -113,5 +124,5 @@ :key (:page-id tgroup)}])] [:div {:class (stl/css :thread-groups-placeholder)} - i/comments-refactor + comments-icon-svg (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 70b96cdae..5298f4948 100644 --- a/frontend/src/app/main/ui/dashboard/comments.scss +++ b/frontend/src/app/main/ui/dashboard/comments.scss @@ -48,14 +48,14 @@ padding: $s-24; text-align: center; color: $df-secondary; +} - svg { - stroke: $df-secondary; - fill: none; - height: $s-24; - margin-bottom: $s-24; - width: $s-24; - } +.comments-icon { + @extend .button-icon; + stroke: var(--icon-foreground); + height: $s-24; + width: $s-24; + margin-bottom: $s-24; } .button { @@ -65,28 +65,24 @@ border-radius: $br-8; height: $s-32; width: $s-32; + --comment-icon-small-foreground-color: var(--icon-foreground); - svg { - width: $s-16; - height: $s-16; - stroke: $df-secondary; - fill: none; - } - - &.unread svg, - &.open svg { - stroke: $da-tertiary; + &.unread, + &.open { + --comment-icon-small-foreground-color: var(--icon-foreground-selected); } &:hover { background-color: $db-quaternary; - - svg { - stroke: $da-primary; - } + --comment-icon-small-foreground-color: var(--icon-foreground-active); } } +.comments-icon-small { + @extend .button-icon; + stroke: var(--comment-icon-small-foreground-color); +} + .dropdown { @include menuShadow; background-color: $db-tertiary; @@ -111,7 +107,6 @@ height: $s-40; align-items: center; padding: 0 $s-12; - h3 { color: $df-secondary; font-size: $fs-11; @@ -119,16 +114,14 @@ flex-grow: 1; text-transform: uppercase; } - - .close { - display: flex; - align-items: center; - cursor: pointer; - svg { - width: $s-16; - height: $s-16; - transform: rotate(45deg); - fill: $df-secondary; - } - } +} + +.close-btn { + @include buttonStyle; + @include flexCenter; +} + +.close-icon { + @extend .button-icon; + stroke: var(--icon-foreground); } From cf41982ee2a9941f67fd1b16871807822d3355da Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 10:16:04 +0100 Subject: [PATCH 029/136] :recycle: Unnest scss of dashboard comments file --- .../styles/common/refactor/design-tokens.scss | 1 + .../src/app/main/ui/dashboard/comments.cljs | 4 +- .../src/app/main/ui/dashboard/comments.scss | 39 ++++++------------- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss index bd18e57fe..4049cc42e 100644 --- a/frontend/resources/styles/common/refactor/design-tokens.scss +++ b/frontend/resources/styles/common/refactor/design-tokens.scss @@ -156,6 +156,7 @@ --icon-foreground-accept: var(--status-color-success-500); --icon-foreground-discard: var(--status-color-error-500); --icon-foreground-active: var(--color-accent-primary); + --icon-foreground-selected: var(--color-accent-tertiary); // INPUTS, SELECTS, DROPDOWNS diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index 951a15598..3a567774d 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -55,7 +55,7 @@ :on-click on-show-comments :on-key-down handle-keydown :data-test "open-comments" - :class (stl/css-case :button true + :class (stl/css-case :comment-button true :open show? :unread (boolean (seq tgroups)))} comments-icon-small]])) @@ -101,7 +101,7 @@ [:& 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")] + [:h3 {:class (stl/css :header-title)} (tr "labels.comments")] [:button {:class (stl/css :close-btn) :tab-index (if show? "0" "-1") :on-click on-hide-comments diff --git a/frontend/src/app/main/ui/dashboard/comments.scss b/frontend/src/app/main/ui/dashboard/comments.scss index 5298f4948..1be90e32b 100644 --- a/frontend/src/app/main/ui/dashboard/comments.scss +++ b/frontend/src/app/main/ui/dashboard/comments.scss @@ -7,17 +7,9 @@ @use "common/refactor/common-refactor.scss" as *; .dashboard-comments-section { - display: flex; - align-items: center; - justify-content: center; + @include flexCenter; position: relative; border-radius: $br-8; - - button { - cursor: pointer; - background: none; - border: none; - } } .thread-groups { @@ -25,13 +17,6 @@ overflow-y: scroll; max-height: $s-440; overflow: auto; - - hr { - background-color: $df-primary; - border: 0; - height: $s-1; - margin: 0; - } } .thread-group { @@ -58,10 +43,9 @@ margin-bottom: $s-24; } -.button { - display: flex; - align-items: center; - justify-content: center; +.comment-button { + @include buttonStyle; + @include flexCenter; border-radius: $br-8; height: $s-32; width: $s-32; @@ -107,13 +91,14 @@ height: $s-40; align-items: center; padding: 0 $s-12; - h3 { - color: $df-secondary; - font-size: $fs-11; - line-height: 1.28; - flex-grow: 1; - text-transform: uppercase; - } +} + +.header-title { + color: $df-secondary; + font-size: $fs-11; + line-height: 1.28; + flex-grow: 1; + text-transform: uppercase; } .close-btn { From cfffb1e55174e1f24c705c84305cd6b9a6726683 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 10:36:07 +0100 Subject: [PATCH 030/136] :recycle: Update go back icon on dashboard --- .../src/app/main/ui/settings/sidebar.cljs | 5 +++- .../src/app/main/ui/settings/sidebar.scss | 23 ++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/main/ui/settings/sidebar.cljs b/frontend/src/app/main/ui/settings/sidebar.cljs index 366a0df9a..9638292f2 100644 --- a/frontend/src/app/main/ui/settings/sidebar.cljs +++ b/frontend/src/app/main/ui/settings/sidebar.cljs @@ -20,6 +20,9 @@ [potok.v2.core :as ptk] [rumext.v2 :as mf])) +(def ^:private arrow-icon + (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) + (def ^:private go-settings-profile #(st/emit! (rt/nav :settings-profile))) @@ -63,7 +66,7 @@ [: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] + arrow-icon [:span {:class (stl/css :text)} (tr "labels.dashboard")]]] [:hr] diff --git a/frontend/src/app/main/ui/settings/sidebar.scss b/frontend/src/app/main/ui/settings/sidebar.scss index afb7cb38f..59b4d9d8a 100644 --- a/frontend/src/app/main/ui/settings/sidebar.scss +++ b/frontend/src/app/main/ui/settings/sidebar.scss @@ -135,25 +135,20 @@ } .back-to-dashboard { + display: flex; + align-items: center; padding: $s-12 $s-16; font-size: $fs-14; cursor: pointer; - display: flex; - - .icon { - display: flex; - align-items: center; - margin-right: $s-12; - } .text { color: $df-primary; } - - svg { - fill: $df-secondary; - transform: rotate(90deg); - width: $s-12; - height: $s-12; - } +} + +.arrow-icon { + @extend .button-icon; + stroke: var(--icon-foreground); + transform: rotate(180deg); + margin-right: $s-12; } From 47df2855004c2eccd3c9bf1747ec805905944304 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 11:09:03 +0100 Subject: [PATCH 031/136] :recycle: Unnest scss rules in dashboard settings --- .../src/app/main/ui/settings/sidebar.cljs | 35 ++-- .../src/app/main/ui/settings/sidebar.scss | 167 ++++++------------ 2 files changed, 74 insertions(+), 128 deletions(-) diff --git a/frontend/src/app/main/ui/settings/sidebar.cljs b/frontend/src/app/main/ui/settings/sidebar.cljs index 9638292f2..def29fc6d 100644 --- a/frontend/src/app/main/ui/settings/sidebar.cljs +++ b/frontend/src/app/main/ui/settings/sidebar.cljs @@ -23,6 +23,9 @@ (def ^:private arrow-icon (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) +(def ^:private feedback-icon + (i/icon-xref :feedback-refactor (stl/css :feedback-icon))) + (def ^:private go-settings-profile #(st/emit! (rt/nav :settings-profile))) @@ -64,43 +67,49 @@ [:div {:class (stl/css :sidebar-content)} [:div {:class (stl/css :sidebar-content-section)} - [:div {:class (stl/css :back-to-dashboard) - :on-click go-dashboard} + [:button {:class (stl/css :back-to-dashboard) + :on-click go-dashboard} arrow-icon - [:span {:class (stl/css :text)} (tr "labels.dashboard")]]] + [:span {:class (stl/css :back-text)} (tr "labels.dashboard")]]] - [:hr] + [:hr {:class (stl/css :sidebar-separator)}] [:div {:class (stl/css :sidebar-content-section)} - [:ul {:class (stl/css :sidebar-nav :no-overflow)} - [:li {:class (when profile? (stl/css :current)) + [:ul {:class (stl/css :sidebar-nav-settings)} + [:li {:class (stl/css-case :current profile? + :settings-item true) :on-click go-settings-profile} [:span {:class (stl/css :element-title)} (tr "labels.profile")]] - [:li {:class (when password? (stl/css :current)) + [:li {:class (stl/css-case :current password? + :settings-item true) :on-click go-settings-password} [:span {:class (stl/css :element-title)} (tr "labels.password")]] - [:li {:class (when options? (stl/css :current)) + [:li {:class (stl/css-case :current options? + :settings-item true) :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)) + [:li {:class (stl/css-case :current access-tokens? + :settings-item true) :on-click go-settings-access-tokens :data-test "settings-access-tokens"} [:span {:class (stl/css :element-title)} (tr "labels.access-tokens")]]) - [:hr] + [:hr {:class (stl/css :sidebar-separator)}] - [:li {:on-click show-release-notes :data-test "release-notes"} + [:li {:on-click show-release-notes :data-test "release-notes" + :class (stl/css :settings-item)} [:span {:class (stl/css :element-title)} (tr "labels.release-notes")]] (when (contains? cf/flags :user-feedback) - [:li {:class (when feedback? (stl/css :current)) + [:li {:class (stl/css-case :current feedback? + :settings-item true) :on-click go-settings-feedback} - i/feedback-refactor + feedback-icon [:span {:class (stl/css :element-title)} (tr "labels.give-feedback")]])]]])) (mf/defc sidebar diff --git a/frontend/src/app/main/ui/settings/sidebar.scss b/frontend/src/app/main/ui/settings/sidebar.scss index 59b4d9d8a..a02745892 100644 --- a/frontend/src/app/main/ui/settings/sidebar.scss +++ b/frontend/src/app/main/ui/settings/sidebar.scss @@ -7,143 +7,80 @@ @use "common/refactor/common-refactor.scss" as *; .dashboard-sidebar { - background-color: var(--panel-background-color); - border-right: $s-1 solid $db-quaternary; - display: flex; - flex-direction: column; grid-column: 1 / span 2; grid-row: 1 / span 2; + display: grid; + grid-template-rows: 1fr auto; height: 100%; - margin: 0 $s-16 0 0; - padding: $s-16 0 0 0; + padding-block-start: $s-16; + border-right: $s-1 solid var(--panel-border-color); z-index: $z-index-1; + background-color: var(--panel-background-color); } .sidebar-content { - display: flex; - flex-direction: column; + display: grid; + grid-template-rows: auto auto 1fr; height: 100%; - overflow-y: auto; padding: 0; + overflow-y: auto; +} - hr { - border-color: transparent; - margin: $s-12 $s-16; +.sidebar-separator { + border-color: transparent; + margin: $s-12 $s-16; +} + +.sidebar-nav-settings { + display: grid; + grid-auto-rows: auto; + margin: 0; + overflow: unset; + user-select: none; +} + +.settings-item { + --settings-foreground-color: var(--menu-foreground-color-rest); + --settings-background-color: transparent; + display: flex; + align-items: center; + padding: $s-8 $s-8 $s-8 $s-24; + color: var(--settings-foreground-color); + background-color: var(--settings-background-color); + cursor: pointer; + + &:hover { + --settings-foreground-color: var(--sidebar-element-foreground-color-hover); + --settings-background-color: var(--sidebar-element-background-color-hover); + } + + &.current { + --settings-foreground-color: var(--sidebar-element-foreground-color-selected); + --settings-background-color: var(--sidebar-element-background-color-selected); } } -.sidebar-nav { - display: flex; - flex-direction: column; - margin: 0; - overflow-y: auto; - user-select: none; +.feedback-icon { + @extend .button-icon-small; + stroke: var(--settings-foreground-color); + margin-right: $s-8; +} - &.no-overflow { - overflow: unset; - } - - li { - align-items: center; - cursor: pointer; - display: flex; - flex-shrink: 0; - padding: $s-8 $s-8 $s-8 $s-24; - color: $df-secondary; - - a { - font-weight: $fw400; - width: 100%; - &:hover { - text-decoration: none; - } - } - - svg { - stroke: currentColor; - fill: none; - margin-right: $s-8; - height: $s-12; - width: $s-12; - } - - span { - font-size: $fs-14; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - &::before { - display: none; - background-color: transparent; - border-radius: $br-4; - content: ""; - height: $s-24; - margin-right: $s-8; - width: $s-4; - } - - &.recent-projects { - svg { - fill: $df-primary; - } - } - - & .edit-wrapper { - border: $s-1 solid $df-primary; - border-radius: $br-4; - display: flex; - width: 100%; - } - - input.element-title { - border: 0; - height: $s-32; - padding: $s-6; - margin: 0; - width: 100%; - background-color: $df-primary; - } - - .element-subtitle { - color: $df-secondary; - font-style: italic; - } - - &:hover { - background-color: $db-quaternary; - &::before { - background-color: $df-primary; - } - } - - &.current { - background-color: $db-quaternary; - color: $da-primary; - - a { - font-weight: $fw400; - color: currentColor; - } - - &::before { - background-color: $da-tertiary; - } - } - } +.element-title { + @include textEllipsis; + @include bodyMediumTypography; } .back-to-dashboard { + @include buttonStyle; display: flex; align-items: center; padding: $s-12 $s-16; font-size: $fs-14; - cursor: pointer; +} - .text { - color: $df-primary; - } +.back-text { + color: $df-primary; } .arrow-icon { From bc04eaa91046b7ce896d4e86c3397174a4ddd3eb Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 12:02:27 +0100 Subject: [PATCH 032/136] :recycle: Update access tokens icons --- .../src/app/main/ui/settings/access_tokens.cljs | 16 +++++++++++++--- .../src/app/main/ui/settings/access_tokens.scss | 14 +++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs index 8f8f4e6f4..d7897db5e 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.cljs +++ b/frontend/src/app/main/ui/settings/access_tokens.cljs @@ -25,6 +25,15 @@ [okulary.core :as l] [rumext.v2 :as mf])) +(def ^:private clipboard-icon + (i/icon-xref :clipboard-refactor (stl/css :clipboard-icon))) + +(def ^:private close-icon + (i/icon-xref :close-refactor (stl/css :close-icon))) + +(def ^:private menu-icon + (i/icon-xref :menu-refactor (stl/css :menu-icon))) + (def tokens-ref (l/derived :access-tokens st/state)) @@ -114,7 +123,8 @@ [: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]] + :on-click on-close} + close-icon]] [:div {:class (stl/css :modal-content)} [:div {:class (stl/css :fields-row)} @@ -154,7 +164,7 @@ [:button {:title (tr "modals.create-access-token.copy-token") :class (stl/css :copy-btn) :on-click copy-token} - i/clipboard-refactor]]) + clipboard-icon]]) #_(when @created? [:button {:class (stl/css :copy-btn) :title (tr "modals.create-access-token.copy-token") @@ -226,7 +236,7 @@ :ref menu-ref :on-click on-menu-click :on-key-down on-keydown} - i/actions + menu-icon [:& context-menu-a11y {:on-close on-menu-close :show show? diff --git a/frontend/src/app/main/ui/settings/access_tokens.scss b/frontend/src/app/main/ui/settings/access_tokens.scss index b3273c9c8..92cd33be3 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.scss +++ b/frontend/src/app/main/ui/settings/access_tokens.scss @@ -64,6 +64,8 @@ align-items: center; .icon { + height: 100%; + width: $s-16; padding-left: $s-12; cursor: pointer; } @@ -100,6 +102,11 @@ } } +.menu-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} + .dashboard-access-tokens { display: flex; flex-direction: column; @@ -232,9 +239,10 @@ @extend .button-secondary; height: $s-28; width: $s-28; - svg { - @extend .button-icon-small; - } +} + +.clipboard-icon { + @extend .button-icon-small; } .token-created-info { From 8b6be5b62e33de1958efc8eb20454f727f2be18a Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 12:33:49 +0100 Subject: [PATCH 033/136] :recycle: Refactor access tokens file --- .../app/main/ui/settings/access_tokens.cljs | 61 ++--- .../app/main/ui/settings/access_tokens.scss | 252 +++++++----------- 2 files changed, 125 insertions(+), 188 deletions(-) diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs index d7897db5e..dff8f400a 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.cljs +++ b/frontend/src/app/main/ui/settings/access_tokens.cljs @@ -138,7 +138,8 @@ :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")] + [: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"} @@ -192,16 +193,13 @@ (mf/defc access-tokens-hero [] (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")]] + [:div {:class (stl/css :access-tokens-hero)} + [:h2 {:class (stl/css :hero-title)} (tr "dashboard.access-tokens.personal")] + [:p {:class (stl/css :hero-desc)} (tr "dashboard.access-tokens.personal.description")] - [:button - {:class (stl/css :btn-primary) - :on-click on-click} - [:span (tr "dashboard.access-tokens.create")]]]])) + [:button {:class (stl/css :hero-btn) + :on-click on-click} + (tr "dashboard.access-tokens.create")]])) (mf/defc access-token-actions [{:keys [on-delete]}] @@ -231,11 +229,11 @@ (dom/stop-propagation event) (on-menu-click event))))] - [:div {:class (stl/css :icon) - :tab-index "0" - :ref menu-ref - :on-click on-menu-click - :on-key-down on-keydown} + [:button {:class (stl/css :menu-btn) + :tab-index "0" + :ref menu-ref + :on-click on-menu-click + :on-key-down on-keydown} menu-icon [:& context-menu-a11y {:on-close on-menu-close @@ -274,15 +272,15 @@ :on-accept delete-fn}))))] [:div {:class (stl/css :table-row)} - [:div {:class (stl/css :table-field :name)} + [:div {:class (stl/css :table-field :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-case :expiration-date true + :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 {:class (stl/css :table-field :actions)} [:& access-token-actions {:on-delete on-delete}]]])) @@ -295,14 +293,13 @@ (st/emit! (du/fetch-access-tokens))) [: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)}])]])]])) + [:& 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 92cd33be3..50239c61b 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.scss +++ b/frontend/src/app/main/ui/settings/access_tokens.scss @@ -6,175 +6,118 @@ @use "common/refactor/common-refactor.scss" as *; -.dashboard-table { - display: flex; - flex-direction: column; - font-size: $fs-16; - margin-top: $s-20; +// ACCESS TOKENS PAGE +.dashboard-access-tokens { + display: grid; + grid-template-rows: auto 1fr; + margin: $s-80 auto $s-120 auto; + gap: $s-32; width: $s-800; - svg { - width: $s-12; - height: $s-12; - fill: $df-primary; - } } -.table-header { - color: $df-secondary; +// hero +.access-tokens-hero { display: grid; - font-size: $fs-12; - grid-template-columns: 43% 1fr $s-108 $s-12; - height: $s-40; + grid-template-rows: auto auto 1fr; + gap: $s-32; + width: $s-500; + font-size: $fs-14; + margin: $s-16 auto 0 auto; +} + +.hero-title { + @include bigTitleTipography; + color: var(--title-foreground-color-hover); +} + +.hero-desc { + color: var(--title-foreground-color); + margin-bottom: 0; + font-size: $fs-14; +} + +.hero-btn { + @extend .button-primary; +} + +// table empty +.access-tokens-empty { + display: grid; + place-items: center; + align-content: center; + height: $s-156; max-width: $s-1000; - padding: 0 $s-16; - text-transform: uppercase; width: 100%; + padding: $s-32; + border: $s-1 solid var(--panel-border-color); + border-radius: $br-8; + color: var(--dashboard-list-text-foreground-color); +} + +// Access tokens table +.dashboard-table { + height: fit-content; } .table-rows { - color: $db-secondary; - display: flex; - flex-direction: column; - margin-top: $s-16; - max-width: $s-1000; - padding-top: 0; + display: grid; + grid-auto-rows: $s-64; + gap: $s-16; width: 100%; + height: 100%; + max-width: $s-1000; + margin-top: $s-16; + color: var(--title-foreground-color); } .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; + grid-template-columns: 43% 1fr auto; align-items: center; - - .icon { - height: 100%; - width: $s-16; - 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(--status-color-warning-500); - border-radius: $br-4; - color: $db-secondary; - } - } - } - &.access-token-created { - word-break: break-all; - } - - &.actions { - position: relative; - } + height: $s-64; + width: 100%; + padding: 0 $s-16; + border-radius: $br-8; + background-color: var(--dashboard-list-background-color); + color: var(--dashboard-list-foreground-color); } +.field-name { + @include textEllipsis; + display: grid; + width: 43%; + min-width: $s-300; +} + +.expiration-date { + @include flexCenter; + min-width: $s-76; + width: fit-content; + height: $s-24; + border-radius: $br-8; + color: var(--dashboard-list-text-foreground-color); +} + +.expired { + @include headlineSmallTypography; + padding: 0 $s-6; + color: var(--pill-foreground-color); + background-color: var(--status-widget-background-color-warning); +} + +.actions { + position: relative; +} .menu-icon { @extend .button-icon; stroke: var(--icon-foreground); } -.dashboard-access-tokens { - display: flex; - flex-direction: column; - margin-left: $s-120; - margin-top: $s-80; - width: $s-800; -} - -.access-tokens-hero-container { - background-color: transparent; - display: flex; - flex-direction: column; - max-width: $s-1000; - width: 100%; -} - -.access-tokens-hero { - display: flex; - flex-direction: column; - font-size: $fs-14; - gap: $s-32; - justify-content: space-between; - width: $s-468; - - .desc { - background-color: transparent; - color: $df-secondary; - width: 100%; - - h2 { - color: $df-primary; - font-size: $fs-24; - font-weight: regular; - margin-bottom: $s-32; - } - p { - color: $df-secondary; - margin-bottom: 0; - font-size: $fs-14; - } - } - .btn-primary { - flex-shrink: 0; - } -} - -.access-tokens-empty { - align-items: center; - border-radius: $br-8; - border: $s-1 solid $db-quaternary; - color: $df-secondary; - display: flex; - flex-direction: column; - font-size: $fs-14; - justify-content: center; - margin-top: $s-32; - max-width: $s-1000; - min-height: $s-136; - padding: $s-32; - text-align: center; - width: $s-468; -} - -.btn-primary { - @extend .button-primary; - height: $s-32; +.menu-btn { + @include buttonStyle; } +// Create access token modal .modal-overlay { @extend .modal-overlay-base; } @@ -186,13 +129,14 @@ .modal-header { margin-bottom: $s-24; - .modal-title { - @include uppercaseTitleTipography; - color: var(--modal-title-foreground-color); - } - .modal-close-btn { - @extend .modal-close-btn-base; - } +} + +.modal-title { + @include uppercaseTitleTipography; + color: var(--modal-title-foreground-color); +} +.modal-close-btn { + @extend .modal-close-btn-base; } .modal-content { @@ -202,10 +146,6 @@ margin-bottom: $s-24; } -.fields-row { - @include flexColumn; -} - .select-title { @include bodySmallTypography; color: var(--modal-title-foreground-color); From 2031e513ed0e79b18e9997e1df50c4000716c962 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 6 Mar 2024 13:18:39 +0100 Subject: [PATCH 034/136] :bug: Fix problem moving grid elements --- frontend/src/app/main/data/workspace/modifiers.cljs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/workspace/modifiers.cljs b/frontend/src/app/main/data/workspace/modifiers.cljs index d27b980f6..c76c91742 100644 --- a/frontend/src/app/main/data/workspace/modifiers.cljs +++ b/frontend/src/app/main/data/workspace/modifiers.cljs @@ -18,6 +18,7 @@ [app.common.types.component :as ctk] [app.common.types.container :as ctn] [app.common.types.modifiers :as ctm] + [app.common.types.shape-tree :as ctst] [app.common.types.shape.attrs :refer [editable-attrs]] [app.common.types.shape.layout :as ctl] [app.common.uuid :as uuid] @@ -193,13 +194,16 @@ (update :shapes #(d/removev ids %)) (ctl/assign-cells objects)) - ids (->> ids (remove #(ctl/position-absolute? objects %))) + ids (->> ids + (remove #(ctl/position-absolute? objects %)) + (ctst/sort-z-index objects) + reverse) + frame (-> frame (update :shapes d/concat-vec ids) (cond-> (some? cell) (ctl/push-into-cell ids row column)) (ctl/assign-cells objects))] - (-> modifiers (ctm/change-property :layout-grid-rows (:layout-grid-rows frame)) (ctm/change-property :layout-grid-columns (:layout-grid-columns frame)) From 0db24dc7ecfa9bd96a0553e9782b36e009e09c29 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 6 Mar 2024 17:08:57 +0100 Subject: [PATCH 035/136] :bug: Fix problem with shadow negative spread --- CHANGES.md | 1 + frontend/src/app/main/ui/shapes/filters.cljs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 9f87f4c9a..e24b3f1da 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -125,6 +125,7 @@ - [VIEWER] Cannot scroll down in code mode [Taiga #4655](https://tree.taiga.io/project/penpot/issue/4655) - Strange cursor behavior after clicking viewport with text tool [Taiga #4363](https://tree.taiga.io/project/penpot/issue/4363) - Selected color affects all of them [Taiga #5285](https://tree.taiga.io/project/penpot/issue/5285) +- Fix problem with shadow negative spread [Github #3421](https://github.com/penpot/penpot/issues/3421) ## 1.19.5 diff --git a/frontend/src/app/main/ui/shapes/filters.cljs b/frontend/src/app/main/ui/shapes/filters.cljs index 8ac7a15af..f7ff505db 100644 --- a/frontend/src/app/main/ui/shapes/filters.cljs +++ b/frontend/src/app/main/ui/shapes/filters.cljs @@ -45,6 +45,12 @@ :in "SourceAlpha" :result filter-id}]) + (when (< spread 0) + [:feMorphology {:radius (- spread) + :operator "erode" + :in "SourceAlpha" + :result filter-id}]) + [:feOffset {:dx offset-x :dy offset-y}] [:feGaussianBlur {:stdDeviation (/ blur 2)}] [:& color-matrix {:color color}] From b9b85b5ada513c8221f3652972584f591d920840 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 11:27:29 +0100 Subject: [PATCH 036/136] :bug: Fix undo for set typography --- frontend/src/app/main/data/workspace/texts.cljs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index c3e98739b..492cc6a83 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -601,12 +601,16 @@ attrs (-> typography (assoc :typography-ref-file file-id) (assoc :typography-ref-id (:id typography)) - (dissoc :id :name))] + (dissoc :id :name)) + undo-id (js/Symbol)] - (->> (rx/from (seq selected)) - (rx/map (fn [id] - (let [editor (get editor-state id)] - (update-text-attrs {:id id :editor editor :attrs attrs}))))))))) + (rx/concat + (rx/of (dwu/start-undo-transaction undo-id)) + (->> (rx/from (seq selected)) + (rx/map (fn [id] + (let [editor (get editor-state id)] + (update-text-attrs {:id id :editor editor :attrs attrs}))))) + (rx/of (dwu/commit-undo-transaction undo-id))))))) (defn generate-typography-name [{:keys [font-id font-variant-id] :as typography}] From 747cead31376e41ecd8402e0c91b51fddb931824 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 12:41:39 +0100 Subject: [PATCH 037/136] :bug: Fix forbid empty flow names --- .../main/ui/workspace/sidebar/options/menus/interactions.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d9e543d19..d40d0ef42 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 @@ -86,7 +86,7 @@ accept-edit (fn [] (let [name-input (mf/ref-val name-ref) - name (dom/get-value name-input)] + name (str/trim (dom/get-value name-input))] (reset! editing? false) (st/emit! (dwi/end-rename-flow) (when-not (str/empty? name) From 28d6cf6f51e93416c5528945e798cd1283495362 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 15:17:23 +0100 Subject: [PATCH 038/136] :bug: Fix import stroke attached library color --- CHANGES.md | 1 + backend/src/app/binfile/common.clj | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e24b3f1da..a1b9867c7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -126,6 +126,7 @@ - Strange cursor behavior after clicking viewport with text tool [Taiga #4363](https://tree.taiga.io/project/penpot/issue/4363) - Selected color affects all of them [Taiga #5285](https://tree.taiga.io/project/penpot/issue/5285) - Fix problem with shadow negative spread [Github #3421](https://github.com/penpot/penpot/issues/3421) +- Fix problem with linked colors to strokes [Github #3522](https://github.com/penpot/penpot/issues/3522) ## 1.19.5 diff --git a/backend/src/app/binfile/common.clj b/backend/src/app/binfile/common.clj index d5a4241e2..ace98c80e 100644 --- a/backend/src/app/binfile/common.clj +++ b/backend/src/app/binfile/common.clj @@ -277,7 +277,7 @@ (update :fill-color-ref-file lookup-index) ;; This covers the old shapes and the new :strokes - (uuid? (:storage-color-ref-file form)) + (uuid? (:stroke-color-ref-file form)) (update :stroke-color-ref-file lookup-index) ;; This covers all text shapes that have typography referenced From 8a6882e155aa8e740d80741499aa6ec1851a76d3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 15:36:18 +0100 Subject: [PATCH 039/136] :bug: Fix inspect copy stroke --- .../ui/viewer/inspect/attributes/stroke.cljs | 51 +++++++------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/main/ui/viewer/inspect/attributes/stroke.cljs b/frontend/src/app/main/ui/viewer/inspect/attributes/stroke.cljs index e8e1ebcd3..5d5567160 100644 --- a/frontend/src/app/main/ui/viewer/inspect/attributes/stroke.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/attributes/stroke.cljs @@ -7,18 +7,14 @@ (ns app.main.ui.viewer.inspect.attributes.stroke (:require-macros [app.main.style :as stl]) (:require - [app.common.data :as d] - [app.common.data.macros :as dm] - [app.main.ui.components.copy-button :refer [copy-button]] [app.main.ui.components.title-bar :refer [inspect-title-bar]] - [app.main.ui.formats :as fmt] [app.main.ui.viewer.inspect.attributes.common :refer [color-row]] - [app.util.code-gen.style-css-formats :as cssf] - [app.util.code-gen.style-css-values :as cssv] - [app.util.color :as uc] + [app.util.code-gen.style-css :as css] [app.util.i18n :refer [tr]] [rumext.v2 :as mf])) +(def properties [:border]) + (defn stroke->color [shape] {:color (:stroke-color shape) :opacity (:stroke-opacity shape) @@ -31,30 +27,21 @@ (seq (:strokes shape))) (mf/defc stroke-block - [{:keys [stroke]}] - (let [color-format (mf/use-state :hex) - color (stroke->color stroke)] - [:div {:class (stl/css :attributes-stroke-block)} - (let [{:keys [stroke-style stroke-alignment]} stroke - stroke-style (if (= stroke-style :svg) :solid stroke-style) - stroke-alignment (or stroke-alignment :center) - stroke-def (dm/str (fmt/format-pixels (:stroke-width stroke)) " " - (tr (dm/str "inspect.attributes.stroke.style." (or (d/name stroke-style) "none"))) " " - (tr (dm/str "inspect.attributes.stroke.alignment." (d/name stroke-alignment))))] - - [:* - [:& color-row {:color color - :format @color-format - :copy-data (uc/color->background color) - :on-change-format #(reset! color-format %)}] - - [:div {:class (stl/css :stroke-row)} - [:div {:class (stl/css :global/attr-label)} - "Border"] - [:div {:class (stl/css :global/attr-value)} - - [:& copy-button {:data (cssf/format-value :border (cssv/get-stroke-data stroke))} - [:div {:class (stl/css :button-children)} stroke-def]]]]])])) + {::mf/wrap-props false} + [{:keys [objects shape]}] + (let [format* (mf/use-state :hex) + format (deref format*) + color (stroke->color shape) + on-change + (mf/use-fn + (fn [format] + (reset! format* format)))] + [:div {:class (stl/css :attributes-fill-block)} + [:& color-row + {:color color + :format format + :on-change-format on-change + :copy-data (css/get-shape-properties-css objects {:strokes [shape]} properties)}]])) (mf/defc stroke-panel [{:keys [shapes]}] @@ -69,4 +56,4 @@ (for [shape shapes] (for [value (:strokes shape)] [:& stroke-block {:key (str "stroke-color-" (:id shape) value) - :stroke value}]))]]))) + :shape value}]))]]))) From ee4c56aa9b78a250d6776cc237e1b7bb7ec1cb23 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 16:27:20 +0100 Subject: [PATCH 040/136] :bug: Fix allow entering invalid emails into the invitation form --- .../src/app/main/ui/components/forms.cljs | 52 ++++++++++++------- .../src/app/main/ui/components/forms.scss | 7 +++ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index b7ad29e5f..7ae43e1e9 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -372,7 +372,10 @@ in-klass (str class " " (stl/css-case :inside-input true - :no-padding (pos? (count @items)))) + :no-padding (pos? (count @items)) + :invalid (and (some? valid-item-fn) + touched? + (not (valid-item-fn @value))))) on-focus (mf/use-fn #(reset! focus? true)) @@ -394,27 +397,38 @@ (mf/use-fn (mf/deps @value) (fn [event] - (cond - (or (kbd/enter? event) - (kbd/comma? event)) - (do - (dom/prevent-default event) - (dom/stop-propagation event) - (let [val (cond-> @value trim str/trim)] + (let [val (cond-> @value trim str/trim)] + (cond + (or (kbd/enter? event) (kbd/comma? event) (kbd/space? event)) + (do + (dom/prevent-default event) + (dom/stop-propagation event) + + ;; Once enter/comma is pressed we mark it as touched + (swap! form assoc-in [:touched input-name] true) + + ;; Empty values means "submit" the form (whent some items have been added (when (and (kbd/enter? event) (str/empty? @value) (not-empty @items)) (on-submit form)) - (when (not (str/empty? @value)) - (reset! value "") - (swap! items conj-dedup {:text val - :valid (valid-item-fn val) - :caution (caution-item-fn val)})))) - (and (kbd/backspace? event) - (str/empty? @value)) - (do - (dom/prevent-default event) - (dom/stop-propagation event) - (swap! items (fn [items] (if (c/empty? items) items (pop items)))))))) + ;; If we have a string in the input we add it only if valid + (when (and (valid-item-fn val) (not (str/empty? @value))) + (reset! value "") + + ;; Once added the form is back as "untouched" + (swap! form assoc-in [:touched input-name] false) + + ;; This split will allow users to copy comma/space separated values of emails + (doseq [val (str/split val #",|\s+")] + (swap! items conj-dedup {:text (str/trim val) + :valid (valid-item-fn val) + :caution (caution-item-fn val)})))) + + (and (kbd/backspace? event) (str/empty? @value)) + (do + (dom/prevent-default event) + (dom/stop-propagation event) + (swap! items (fn [items] (if (c/empty? items) items (pop items))))))))) on-blur (mf/use-fn diff --git a/frontend/src/app/main/ui/components/forms.scss b/frontend/src/app/main/ui/components/forms.scss index d77fce23b..19027a065 100644 --- a/frontend/src/app/main/ui/components/forms.scss +++ b/frontend/src/app/main/ui/components/forms.scss @@ -293,6 +293,13 @@ outline: none; border: $s-1 solid var(--input-border-color-focus); } + &.invalid { + border: $s-1 solid var(--input-border-color-error); + &:hover, + &:focus { + border: $s-1 solid var(--input-border-color-error); + } + } } label { display: none; From e2428fc0c6be4781e0f86ce86df22c343b29edcc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 16:37:49 +0100 Subject: [PATCH 041/136] :bug: Fix problem with space key stuck --- CHANGES.md | 1 + frontend/src/app/main/streams.cljs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a1b9867c7..541b6e1b6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -127,6 +127,7 @@ - Selected color affects all of them [Taiga #5285](https://tree.taiga.io/project/penpot/issue/5285) - Fix problem with shadow negative spread [Github #3421](https://github.com/penpot/penpot/issues/3421) - Fix problem with linked colors to strokes [Github #3522](https://github.com/penpot/penpot/issues/3522) +- Fix problem with hand tool stuck [Github #3318](https://github.com/penpot/penpot/issues/3318) ## 1.19.5 diff --git a/frontend/src/app/main/streams.cljs b/frontend/src/app/main/streams.cljs index 4fc3d970d..d6ebf074b 100644 --- a/frontend/src/app/main/streams.cljs +++ b/frontend/src/app/main/streams.cljs @@ -151,6 +151,11 @@ (rx/filter kbd/space?) (rx/filter (complement kbd/editing-event?)) (rx/map kbd/key-down-event?) + ;; Fix a situation caused by using `ctrl+alt` kind of + ;; shortcuts, that makes keyboard-alt stream + ;; registering the key pressed but on blurring the + ;; window (unfocus) the key down is never arrived. + (rx/merge window-blur) (rx/pipe (rxo/distinct-contiguous)))] (rx/sub! ob sub) sub)) From bb5eb4a0974c765170f7cdbd0bfd90eea0cb42f2 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 17:00:19 +0100 Subject: [PATCH 042/136] :bug: Fix black screen on non-log access to projects --- frontend/src/app/main/ui.cljs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 69c83db69..d00e466c7 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -107,8 +107,7 @@ (not= "0.0" (:main cf/version))) [:& release-notes-modal {:version (:main cf/version)}])) - (when profile - [:& dashboard-page {:route route :profile profile}])] + [:& dashboard-page {:route route :profile profile}]] :viewer (let [{:keys [query-params path-params]} route From 916d179009681f8791db40f3f600c5a66bec5d04 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 17:06:10 +0100 Subject: [PATCH 043/136] :bug: Fix error on websockets page --- frontend/src/app/main/ui/dashboard/team.cljs | 37 ++++++++++---------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index a2f80d058..4307d66cc 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -787,24 +787,25 @@ on-error (mf/use-fn - (fn [form {:keys [type code hint] :as error}] - (if (and (= type :validation) - (= code :webhook-validation)) - (let [message (cond - (= hint "unknown") - (tr "errors.webhooks.unexpected") - (= hint "invalid-uri") - (tr "errors.webhooks.invalid-uri") - (= hint "ssl-validation-error") - (tr "errors.webhooks.ssl-validation") - (= hint "timeout") - (tr "errors.webhooks.timeout") - (= hint "connection-error") - (tr "errors.webhooks.connection") - (str/starts-with? hint "unexpected-status") - (tr "errors.webhooks.unexpected-status" (extract-status hint)))] - (swap! form assoc-in [:errors :uri] {:message message})) - (rx/throw error)))) + (fn [form error] + (let [{:keys [type code hint]} (ex-data error)] + (if (and (= type :validation) + (= code :webhook-validation)) + (let [message (cond + (= hint "unknown") + (tr "errors.webhooks.unexpected") + (= hint "invalid-uri") + (tr "errors.webhooks.invalid-uri") + (= hint "ssl-validation-error") + (tr "errors.webhooks.ssl-validation") + (= hint "timeout") + (tr "errors.webhooks.timeout") + (= hint "connection-error") + (tr "errors.webhooks.connection") + (str/starts-with? hint "unexpected-status") + (tr "errors.webhooks.unexpected-status" (extract-status hint)))] + (swap! form assoc-in [:errors :uri] {:message message})) + (rx/throw error))))) on-create-submit (mf/use-fn From 9a976a8f6ece13ffe15e94ff48260aa4da44fb88 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Mar 2024 17:42:19 +0100 Subject: [PATCH 044/136] :bug: Fix problem with fix scrolling on nested elements --- CHANGES.md | 1 + common/src/app/common/files/helpers.cljc | 9 ++++++++- frontend/src/app/main/ui/viewer/interactions.cljs | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 541b6e1b6..66073f114 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -128,6 +128,7 @@ - Fix problem with shadow negative spread [Github #3421](https://github.com/penpot/penpot/issues/3421) - Fix problem with linked colors to strokes [Github #3522](https://github.com/penpot/penpot/issues/3522) - Fix problem with hand tool stuck [Github #3318](https://github.com/penpot/penpot/issues/3318) +- Fix problem with fix scrolling on nested elements [Github #3508](https://github.com/penpot/penpot/issues/3508) ## 1.19.5 diff --git a/common/src/app/common/files/helpers.cljc b/common/src/app/common/files/helpers.cljc index 5b31328e6..6203d5db1 100644 --- a/common/src/app/common/files/helpers.cljc +++ b/common/src/app/common/files/helpers.cljc @@ -762,6 +762,13 @@ (recur frame-id frame-parents (rest selected)))))) +(defn fixed-scroll? + [shape] + ^boolean + (and (:fixed-scroll shape) + (= (:parent-id shape) (:frame-id shape)) + (not= (:frame-id shape) uuid/zero))) + (defn fixed? [objects shape-id] (let [ids-to-check @@ -772,4 +779,4 @@ (take-while #(and (not= % uuid/zero) (not (root-frame? objects %))))))] (boolean (->> ids-to-check - (d/seek (fn [id] (dm/get-in objects [id :fixed-scroll]))))))) + (d/seek (fn [id] () (fixed-scroll? (get objects id)))))))) diff --git a/frontend/src/app/main/ui/viewer/interactions.cljs b/frontend/src/app/main/ui/viewer/interactions.cljs index dc4f30ef1..03910ea5d 100644 --- a/frontend/src/app/main/ui/viewer/interactions.cljs +++ b/frontend/src/app/main/ui/viewer/interactions.cljs @@ -41,7 +41,7 @@ (defn get-fixed-ids [objects] - (let [fixed-ids (filter :fixed-scroll (vals objects)) + (let [fixed-ids (filter cfh/fixed-scroll? (vals objects)) ;; we have to consider the children if the fixed element is a group fixed-children-ids From bdf0a64e3a04b8453a2f4179c7a9c331a087514c Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 8 Mar 2024 08:52:28 +0100 Subject: [PATCH 045/136] :bug: Fix release notes 2.0 --- frontend/src/app/main/ui/releases/v2_0.cljs | 4 ++-- frontend/src/app/main/ui/releases/v2_0.scss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/releases/v2_0.cljs b/frontend/src/app/main/ui/releases/v2_0.cljs index 53ce83ee1..d2d1cee79 100644 --- a/frontend/src/app/main/ui/releases/v2_0.cljs +++ b/frontend/src/app/main/ui/releases/v2_0.cljs @@ -13,7 +13,7 @@ (defmethod c/render-release-notes "1.21" [data] - (c/render-release-notes (assoc data :verstion "2.0"))) + (c/render-release-notes (assoc data :version "2.0"))) ;; TODO: Review all copies and alt text (defmethod c/render-release-notes "2.0" @@ -35,7 +35,7 @@ [:h1 {:class (stl/css :modal-title)} "What's new?"] - [:div {:class (stl/css :verstion-tag)} + [:div {:class (stl/css :version-tag)} (dm/str "Version " version)]] [:div {:class (stl/css :features-block)} diff --git a/frontend/src/app/main/ui/releases/v2_0.scss b/frontend/src/app/main/ui/releases/v2_0.scss index 60848a6f0..b085b5607 100644 --- a/frontend/src/app/main/ui/releases/v2_0.scss +++ b/frontend/src/app/main/ui/releases/v2_0.scss @@ -37,7 +37,7 @@ gap: $s-8; } -.verstion-tag { +.version-tag { @include flexCenter; @include headlineSmallTypography; height: $s-32; From 55293e60d65175b7c7c14bd110b8c9968f8d781c Mon Sep 17 00:00:00 2001 From: Aitor Date: Thu, 7 Mar 2024 11:56:57 +0100 Subject: [PATCH 046/136] :bug: Component layers are incorrectly relocated on drag'n'drop --- .../main/ui/workspace/sidebar/layer_item.cljs | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs index 6cc0ba1b0..97c8274d5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs @@ -262,29 +262,32 @@ (mf/use-fn (mf/deps id index objects expanded? selected) (fn [side _data] - (let [shape (get objects id) + (let [single? (= (count selected) 1) + same? (and single? (= (first selected) id))] + (when-not same? + (let [shape (get objects id) - parent-id - (cond - (= side :center) - id + parent-id + (cond + (= side :center) + id - (and expanded? (= side :bot) (d/not-empty? (:shapes shape))) - id + (and expanded? (= side :bot) (d/not-empty? (:shapes shape))) + id - :else - (cfh/get-parent-id objects id)) + :else + (cfh/get-parent-id objects id)) - [parent-id _] (ctn/find-valid-parent-and-frame-ids parent-id objects (map #(get objects %) selected)) + [parent-id _] (ctn/find-valid-parent-and-frame-ids parent-id objects (map #(get objects %) selected)) - parent (get objects parent-id) + parent (get objects parent-id) - to-index (cond - (= side :center) 0 - (and expanded? (= side :bot) (d/not-empty? (:shapes shape))) (count (:shapes parent)) - (= side :top) (inc index) - :else index)] - (st/emit! (dw/relocate-selected-shapes parent-id to-index))))) + to-index (cond + (= side :center) 0 + (and expanded? (= side :bot) (d/not-empty? (:shapes shape))) (count (:shapes parent)) + (= side :top) (inc index) + :else index)] + (st/emit! (dw/relocate-selected-shapes parent-id to-index))))))) on-hold (mf/use-fn From 895fb3b480a51d2281fd59f4ac75268f529dd775 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 5 Mar 2024 11:12:39 +0100 Subject: [PATCH 047/136] :tada: Remove shapes-group --- common/src/app/common/files/changes.cljc | 7 ++----- common/src/app/common/types/shape_tree.cljc | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index 2f1858505..c200749d8 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -507,8 +507,7 @@ (and (:shape-ref parent) (#{:group :frame} (:type parent)) (not ignore-touched)) - (-> (update :touched cfh/set-touched-group :shapes-group) - (dissoc :remote-synced))))) + (dissoc :remote-synced)))) (remove-from-old-parent [old-objects objects shape-id] (let [prev-parent-id (dm/get-in old-objects [shape-id :parent-id])] @@ -525,9 +524,7 @@ (-> objects (d/update-in-when [pid :shapes] d/without-obj sid) (d/update-in-when [pid :shapes] d/vec-without-nils) - (cond-> component? (d/update-when pid #(-> % - (update :touched cfh/set-touched-group :shapes-group) - (dissoc :remote-synced))))))))) + (cond-> component? (d/update-when pid #(dissoc % :remote-synced)))))))) (update-parent-id [objects id] (-> objects (d/update-when id assoc :parent-id parent-id))) diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc index 92e8880be..646c26641 100644 --- a/common/src/app/common/types/shape_tree.cljc +++ b/common/src/app/common/types/shape_tree.cljc @@ -40,8 +40,7 @@ (update :shapes update-parent-shapes) (update :shapes d/vec-without-nils) (cond-> (and (ctk/in-component-copy? parent) (not ignore-touched)) - (-> (update :touched cfh/set-touched-group :shapes-group) - (dissoc :remote-synced))))) + (dissoc :remote-synced)))) update-objects (fn [objects parent-id] @@ -85,8 +84,7 @@ (let [parent (update parent :shapes d/without-obj shape-id)] (cond-> parent (and (:shape-ref parent) (not ignore-touched)) - (-> (update :touched cfh/set-touched-group :shapes-group) - (dissoc :remote-synced))))) + (dissoc :remote-synced)))) (delete-from-objects [objects] (if-let [target (get objects shape-id)] From c214d8b044d8691f79bd6392daa2660d952c8b23 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Mon, 4 Mar 2024 17:44:34 +0100 Subject: [PATCH 048/136] :tada: Simplify and fix compare children --- common/src/app/common/types/component.cljc | 10 +- common/src/app/common/types/file.cljc | 10 +- .../data/workspace/libraries_helpers.cljs | 102 +++++++++--------- 3 files changed, 64 insertions(+), 58 deletions(-) diff --git a/common/src/app/common/types/component.cljc b/common/src/app/common/types/component.cljc index 7c6570f0c..70b030eaf 100644 --- a/common/src/app/common/types/component.cljc +++ b/common/src/app/common/types/component.cljc @@ -190,12 +190,12 @@ (uuid/uuid (subs group 10))))) (defn match-swap-slot? - [shape-inst shape-main] - (let [slot-inst (get-swap-slot shape-inst) - slot-main (get-swap-slot shape-main)] + [shape-main shape-inst] + (let [slot-main (get-swap-slot shape-main) + slot-inst (get-swap-slot shape-inst)] (when (some? slot-inst) - (or (= slot-inst slot-main) - (= slot-inst (:id shape-main)))))) + (or (= slot-main slot-inst) + (= (:id shape-main) slot-inst))))) (defn get-component-root [component] diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 814c583dc..98e8fbae0 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -292,11 +292,11 @@ (find-swap-slot ref-shape ref-container ref-file libraries))))))) (defn match-swap-slot? - [shape-inst shape-main page-inst page-main file libraries] - (let [slot-inst (find-swap-slot shape-inst page-inst file libraries) - slot-main (find-swap-slot shape-main page-main file libraries)] - (or (= slot-inst slot-main) - (= slot-inst (:id shape-main))))) + [shape-main shape-inst page-inst page-main file libraries] + (let [slot-main (find-swap-slot shape-main page-main file libraries) + slot-inst (find-swap-slot shape-inst page-inst file libraries)] + (or (= slot-main slot-inst) + (= (:id shape-main) slot-inst)))) (defn get-component-shapes "Retrieve all shapes of the component" diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 92b026456..adf8e4037 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -759,6 +759,13 @@ redirect-shaperef components-v2)) + swapped (fn [changes child-inst child-main] + (log/trace :msg "Match slot" + :child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) + :child-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) + ;; For now we don't make any sync here. + changes) + moved (fn [changes child-inst child-main] (log/trace :msg "Move" :child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) @@ -777,6 +784,7 @@ only-inst only-main both + swapped moved false reset?)))) @@ -933,6 +941,13 @@ redirect-shaperef components-v2)) + swapped (fn [changes child-inst child-main] + (log/trace :msg "Match slot" + :child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) + :child-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) + ;; For now we don't make any sync here. + changes) + moved (fn [changes child-inst child-main] (move-shape changes @@ -949,6 +964,7 @@ only-inst only-main both + swapped moved true true) @@ -969,7 +985,7 @@ ;; ---- Operation generation helpers ---- (defn- compare-children - [changes children-inst children-main only-inst-cb only-main-cb both-cb moved-cb inverse? reset?] + [changes children-inst children-main only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset?] (log/trace :msg "Compare children") (loop [children-inst (seq (or children-inst [])) children-main (seq (or children-main [])) @@ -989,63 +1005,53 @@ (reduce only-inst-cb changes children-inst) :else - (if (ctk/is-main-of? child-main child-inst) + (if (or (ctk/is-main-of? child-main child-inst) + (ctk/match-swap-slot? child-main child-inst)) (recur (next children-inst) (next children-main) - (both-cb changes child-inst child-main)) + (if (or (ctk/is-main-of? child-main child-inst) reset?) + (both-cb changes child-inst child-main) + (swapped-cb changes child-inst child-main))) - (if (and (ctk/match-swap-slot? child-main child-inst) (not reset?)) - (do - (log/trace :msg "Match slot" - :shape-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) - :shape-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) - (recur (next children-inst) + (let [child-inst' (d/seek #(or (ctk/is-main-of? child-main %) + (ctk/match-swap-slot? child-main %)) + children-inst) + child-main' (d/seek #(or (ctk/is-main-of? % child-inst) + (ctk/match-swap-slot? % child-inst)) + children-main)] + (cond + (nil? child-inst') + (recur children-inst (next children-main) - changes)) + (only-main-cb changes child-main)) - (let [child-inst' (d/seek #(ctk/is-main-of? child-main %) children-inst) - child-main' (d/seek #(ctk/is-main-of? % child-inst) children-main)] - (cond - (nil? child-inst') - (let [matching-inst (d/seek #(ctk/match-swap-slot? % child-main) children-inst)] - (if (and (some? matching-inst) (not reset?)) - (do - (log/trace :msg "Match slot inst" - :shape-inst (str (:name child-inst') " " (pretty-uuid (:id child-inst'))) - :shape-main (str (:name child-main) " " (pretty-uuid (:id child-main)))) - (recur (remove #(= (:id %) (:id matching-inst)) children-inst) - (next children-main) - changes)) - (recur children-inst - (next children-main) - (only-main-cb changes child-main)))) + (nil? child-main') + (recur (next children-inst) + children-main + (only-inst-cb changes child-inst)) - (nil? child-main') - (let [matching-main (d/seek #(ctk/match-swap-slot? child-inst %) children-main)] - (if (and (some? matching-main) (not reset?)) - (do - (log/trace :msg "Match slot main" - :shape-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))) - :shape-main (str (:name child-main') " " (pretty-uuid (:id child-main')))) - (recur (next children-inst) - (remove #(= (:id %) (:id matching-main)) children-inst) - changes)) - (recur (next children-inst) - children-main - (only-inst-cb changes child-inst)))) - - :else - (if inverse? + :else + (if inverse? + (let [is-main? (ctk/is-main-of? child-inst child-main')] (recur (next children-inst) (remove #(= (:id %) (:id child-main')) children-main) - (-> changes - (both-cb child-inst child-main') - (moved-cb child-inst child-main'))) + (cond-> changes + is-main? + (both-cb child-inst child-main') + (not is-main?) + (swapped-cb child-inst child-main') + :always + (moved-cb child-inst child-main')))) + (let [is-main? (ctk/is-main-of? child-inst' child-main)] (recur (remove #(= (:id %) (:id child-inst')) children-inst) (next children-main) - (-> changes - (both-cb child-inst' child-main) - (moved-cb child-inst' child-main)))))))))))) + (cond-> changes + is-main? + (both-cb child-inst' child-main) + (not is-main?) + (swapped-cb child-inst' child-main) + :always + (moved-cb child-inst' child-main)))))))))))) (defn- add-shape-to-instance [changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced?] From bad0fb912ba6e5f5c8b5e487bd068f117d3f963d Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 7 Mar 2024 11:04:35 +0100 Subject: [PATCH 049/136] :tada Add undo-group for layout updates --- frontend/src/app/main/data/workspace.cljs | 10 ++--- .../src/app/main/data/workspace/changes.cljs | 2 +- .../src/app/main/data/workspace/groups.cljs | 6 +-- .../app/main/data/workspace/libraries.cljs | 11 +++--- .../data/workspace/libraries_helpers.cljs | 23 ++++++------ .../app/main/data/workspace/modifiers.cljs | 3 +- .../app/main/data/workspace/path/edition.cljs | 2 +- .../app/main/data/workspace/selection.cljs | 2 +- .../app/main/data/workspace/shape_layout.cljs | 37 ++++++++++--------- .../src/app/main/data/workspace/shapes.cljs | 17 +++++---- .../app/main/data/workspace/svg_upload.cljs | 2 +- .../src/app/main/data/workspace/texts.cljs | 2 +- .../app/main/data/workspace/transforms.cljs | 2 +- 13 files changed, 61 insertions(+), 58 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index e981a1420..41fdb90ba 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -777,7 +777,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) - (ptk/data-event :layout/update selected-ids) + (ptk/data-event :layout/update {:ids selected-ids}) (dwu/commit-undo-transaction undo-id)))))) ;; --- Change Shape Order (D&D Ordering) @@ -987,7 +987,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dwco/expand-collapse parent-id) - (ptk/data-event :layout/update (concat all-parents ids)) + (ptk/data-event :layout/update {:ids (concat all-parents ids)}) (dwu/commit-undo-transaction undo-id)))))) (defn relocate-selected-shapes @@ -1105,7 +1105,7 @@ (when (can-align? selected objects) (rx/of (dwu/start-undo-transaction undo-id) (dwt/position-shapes moved) - (ptk/data-event :layout/update selected) + (ptk/data-event :layout/update {:ids selected}) (dwu/commit-undo-transaction undo-id))))))) (defn can-distribute? [selected] @@ -1132,7 +1132,7 @@ (when (can-distribute? selected) (rx/of (dwu/start-undo-transaction undo-id) (dwt/position-shapes moved) - (ptk/data-event :layout/update selected) + (ptk/data-event :layout/update {:ids selected}) (dwu/commit-undo-transaction undo-id))))))) ;; --- Shape Proportions @@ -2016,7 +2016,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dws/select-shapes selected) - (ptk/data-event :layout/update [frame-id]) + (ptk/data-event :layout/update {:ids [frame-id]}) (dwu/commit-undo-transaction undo-id))))))) (defn as-content [text] diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs index 061b3c550..b2d595086 100644 --- a/frontend/src/app/main/data/workspace/changes.cljs +++ b/frontend/src/app/main/data/workspace/changes.cljs @@ -101,7 +101,7 @@ ;; Update layouts for properties marked (if (d/not-empty? update-layout-ids) - (rx/of (ptk/data-event :layout/update update-layout-ids)) + (rx/of (ptk/data-event :layout/update {:ids update-layout-ids})) (rx/empty)))))))) (defn send-update-indices diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index a89d845cb..c3a403269 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -194,7 +194,7 @@ (prepare-create-group it objects page-id shapes "Group" false)] (rx/of (dch/commit-changes changes) (dws/select-shapes (d/ordered-set (:id group))) - (ptk/data-event :layout/update parents)))))))) + (ptk/data-event :layout/update {:ids parents})))))))) (def ungroup-selected (ptk/reify ::ungroup-selected @@ -244,7 +244,7 @@ (when-not (empty? selected) (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) - (ptk/data-event :layout/update parents) + (ptk/data-event :layout/update {:ids parents}) (dwu/commit-undo-transaction undo-id) (dws/select-shapes child-ids))))))) @@ -289,7 +289,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dws/select-shapes (d/ordered-set (:id group))) - (ptk/data-event :layout/update [(:id group)]) + (ptk/data-event :layout/update {:ids [(:id group)]}) (dwu/commit-undo-transaction undo-id)))))))) (def unmask-group diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 0d64b733d..e174df3e7 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -52,7 +52,7 @@ [potok.v2.core :as ptk])) ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default -(log/set-level! :trace) +(log/set-level! :warn) (defn- log-changes [changes file] @@ -334,7 +334,7 @@ (when-not (empty? (:redo-changes changes)) (rx/of (dch/commit-changes changes) (dws/select-shapes (d/ordered-set (:id root))) - (ptk/data-event :layout/update parents))))))))) + (ptk/data-event :layout/update {:ids parents}))))))))) (defn add-component "Add a new component to current file library, from the currently selected shapes. @@ -566,7 +566,7 @@ undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) - (ptk/data-event :layout/update [(:id new-shape)]) + (ptk/data-event :layout/update {:ids [(:id new-shape)]}) (dws/select-shapes (d/ordered-set (:id new-shape))) (when start-move? (dwtr/start-move initial-point #{(:id new-shape)})) @@ -948,7 +948,6 @@ undo-id (js/Symbol) undo-group (uuid/next)] - (rx/of (dwu/start-undo-transaction undo-id) (dwsh/delete-shapes nil (d/ordered-set (:id shape)) {:component-swap true @@ -956,7 +955,7 @@ :undo-group undo-group}) (add-component-for-swap shape file page libraries id-new-component index target-cell keep-props-values {:undo-group undo-group}) - (ptk/data-event :layout/update [(:parent-id shape)]) + (ptk/data-event :layout/update {:ids [(:parent-id shape)] :undo-group undo-group}) (dwu/commit-undo-transaction undo-id)))))) (defn component-multi-swap @@ -1082,7 +1081,7 @@ :file-id file-id)))) (when-not (empty? updated-frames) (rx/merge - (rx/of (ptk/data-event :layout/update (map :id updated-frames))) + (rx/of (ptk/data-event :layout/update {:ids (map :id updated-frames) :undo-group undo-group})) (->> (rx/from updated-frames) (rx/mapcat (fn [shape] diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index adf8e4037..8864214a6 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -30,7 +30,7 @@ [clojure.set :as set])) ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default -(log/set-level! :trace) +(log/set-level! :warn) (declare generate-sync-container) (declare generate-sync-shape) @@ -320,16 +320,17 @@ (loop [containers (ctf/object-containers-seq file) changes (pcb/empty-changes it)] (if-let [container (first containers)] - (recur (next containers) - (pcb/concat-changes - changes - (generate-sync-container it - asset-type - asset-id - library-id - state - container - components-v2))) + (do + (recur (next containers) + (pcb/concat-changes + changes + (generate-sync-container it + asset-type + asset-id + library-id + state + container + components-v2)))) changes)))) (defn generate-sync-library diff --git a/frontend/src/app/main/data/workspace/modifiers.cljs b/frontend/src/app/main/data/workspace/modifiers.cljs index d27b980f6..6821ed0e8 100644 --- a/frontend/src/app/main/data/workspace/modifiers.cljs +++ b/frontend/src/app/main/data/workspace/modifiers.cljs @@ -454,7 +454,7 @@ ([] (apply-modifiers nil)) - ([{:keys [modifiers undo-transation? stack-undo? ignore-constraints ignore-snap-pixel] + ([{:keys [modifiers undo-transation? stack-undo? ignore-constraints ignore-snap-pixel undo-group] :or {undo-transation? true stack-undo? false ignore-constraints false ignore-snap-pixel false}}] (ptk/reify ::apply-modifiers ptk/WatchEvent @@ -504,6 +504,7 @@ {:reg-objects? true :stack-undo? stack-undo? :ignore-tree ignore-tree + :undo-group undo-group ;; Attributes that can change in the transform. This way we don't have to check ;; all the attributes :attrs [:selrect diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs index a10b24b03..51d688707 100644 --- a/frontend/src/app/main/data/workspace/path/edition.cljs +++ b/frontend/src/app/main/data/workspace/path/edition.cljs @@ -332,7 +332,7 @@ ptk/WatchEvent (watch [_ _ _] - (rx/of (ptk/data-event :layout/update [id]))))) + (rx/of (ptk/data-event :layout/update {:ids [id]}))))) (defn split-segments [{:keys [from-p to-p t]}] diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 89904f836..15d3d5ab4 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -751,7 +751,7 @@ (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (select-shapes new-selected) - (ptk/data-event :layout/update frames) + (ptk/data-event :layout/update {:ids frames}) (memorize-duplicated id-original id-duplicated) (dwu/commit-undo-transaction undo-id)))))))))) diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 19e17a5a2..37e40cf91 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -94,7 +94,7 @@ ;; Never call this directly but through the data-event `:layout/update` ;; Otherwise a lot of cycle dependencies could be generated (defn- update-layout-positions - [ids] + [{:keys [ids undo-group]}] (ptk/reify ::update-layout-positions ptk/WatchEvent (watch [_ state _] @@ -103,7 +103,8 @@ (if (d/not-empty? ids) (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] (rx/of (dwm/apply-modifiers {:modifiers modif-tree - :stack-undo? true}))) + :stack-undo? true + :undo-group undo-group}))) (rx/empty)))))) (defn initialize @@ -139,7 +140,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (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]) + (ptk/data-event :layout/update {:ids [id]}) (dwu/commit-undo-transaction undo-id)))))) (defn create-layout-from-selection @@ -180,7 +181,7 @@ (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]) + (ptk/data-event :layout/update {:ids [new-shape-id]}) (dwu/commit-undo-transaction undo-id))) ;; Create Layout from selection @@ -191,7 +192,7 @@ (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]) + (rx/of (ptk/data-event :layout/update {:ids [new-shape-id]}) (dwu/commit-undo-transaction undo-id))))))) (defn remove-layout @@ -203,7 +204,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/update-shapes ids #(apply dissoc % layout-keys)) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))) (defn create-layout @@ -256,7 +257,7 @@ (let [undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dch/update-shapes ids (d/patch-object changes)) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))) (defn add-layout-track @@ -275,7 +276,7 @@ (case type :row (ctl/add-grid-row shape value index) :column (ctl/add-grid-column shape value index)))) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id))))))) (defn remove-layout-track @@ -309,7 +310,7 @@ :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) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id))))))) (defn duplicate-layout-track @@ -363,7 +364,7 @@ undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))) (defn reorder-layout-track @@ -381,7 +382,7 @@ (case type :row (ctl/reorder-grid-row shape from-index to-index move-content?) :column (ctl/reorder-grid-column shape from-index to-index move-content?)))) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))) (defn hover-layout-track @@ -426,7 +427,7 @@ (fn [shape] (-> shape (update-in [property index] merge props)))) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))) (defn fix-child-sizing @@ -523,7 +524,7 @@ (cond-> (ctl/grid-layout? parent) (ctl/assign-cells objects)))) {:with-objects? true}) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))) (defn update-grid-cells @@ -546,7 +547,7 @@ [:layout-grid-cells cell-id] d/patch-object props)) shape)))) - (ptk/data-event :layout/update [layout-id]) + (ptk/data-event :layout/update {:ids [layout-id]}) (dwu/commit-undo-transaction undo-id)))))) (defn change-cells-mode @@ -612,7 +613,7 @@ (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]) + (ptk/data-event :layout/update {:ids [layout-id]}) (dwu/commit-undo-transaction undo-id)))))) (defn merge-cells @@ -644,7 +645,7 @@ (ctl/assign-cells objects)))) {:with-objects? true}) (dwge/clean-selection layout-id) - (ptk/data-event :layout/update [layout-id]) + (ptk/data-event :layout/update {:ids [layout-id]}) (dwu/commit-undo-transaction undo-id)))))) (defn update-grid-cell-position @@ -669,7 +670,7 @@ (:row-span new-data) (:column-span new-data)) (ctl/assign-cells objects)))) {:with-objects? true}) - (ptk/data-event :layout/update [layout-id]) + (ptk/data-event :layout/update {:ids [layout-id]}) (dwu/commit-undo-transaction undo-id)))))) @@ -724,5 +725,5 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) - (ptk/data-event :layout/update [layout-id]) + (ptk/data-event :layout/update {:ids [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 72cbd6f7e..7febfef6f 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -57,7 +57,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (when-not no-update-layout? - (ptk/data-event :layout/update [(:parent-id shape)])) + (ptk/data-event :layout/update {:ids [(:parent-id shape)]})) (when-not no-select? (dws/select-shapes (d/ordered-set (:id shape)))) (dwu/commit-undo-transaction undo-id)) @@ -141,10 +141,11 @@ (rx/concat (rx/of (dwu/start-undo-transaction undo-id) - (update-shape-flags ids-to-hide {:hidden true})) + (update-shape-flags ids-to-hide {:hidden true :undo-group (:undo-group options)})) (real-delete-shapes file page objects ids-to-delete it {:components-v2 components-v2 :ignore-touched (:component-swap options) - :undo-group (:undo-group options)}) + :undo-group (:undo-group options) + :undo-id undo-id}) (rx/of (dwu/commit-undo-transaction undo-id)))))))) (defn- real-delete-shapes-changes @@ -291,11 +292,11 @@ (defn- real-delete-shapes [file page objects ids it options] (let [[changes all-parents] (real-delete-shapes-changes file page objects ids it options) - undo-id (js/Symbol)] + undo-id (or (:undo-id options) (js/Symbol))] (rx/of (dwu/start-undo-transaction undo-id) (dc/detach-comment-thread ids) (dch/commit-changes changes) - (ptk/data-event :layout/update all-parents) + (ptk/data-event :layout/update {:ids all-parents :undo-group (:undo-group options)}) (dwu/commit-undo-transaction undo-id)))) (defn create-and-add-shape @@ -377,7 +378,7 @@ (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dws/select-shapes (d/ordered-set (:id frame-shape))) - (ptk/data-event :layout/update [(:id frame-shape)]) + (ptk/data-event :layout/update {:ids [(:id frame-shape)]}) (dwu/commit-undo-transaction undo-id)))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -385,7 +386,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn update-shape-flags - [ids {:keys [blocked hidden transforming] :as flags}] + [ids {:keys [blocked hidden transforming undo-group] :as flags}] (dm/assert! "expected valid coll of uuids" (every? uuid? ids)) @@ -409,7 +410,7 @@ ids (if (boolean? blocked) (into ids (->> ids (mapcat #(cfh/get-children-ids objects %)))) ids)] - (rx/of (dch/update-shapes ids update-fn {:attrs #{:blocked :hidden :transforming}})))))) + (rx/of (dch/update-shapes ids update-fn {:attrs #{:blocked :hidden :transforming} :undo-group undo-group})))))) (defn toggle-visibility-selected [] diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index d0a262312..fa159cf04 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -102,7 +102,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dws/select-shapes (d/ordered-set (:id new-shape))) - (ptk/data-event :layout/update [(:id new-shape)]) + (ptk/data-event :layout/update {:ids [(:id new-shape)]}) (dwu/commit-undo-transaction undo-id))) (catch :default cause diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index c3e98739b..e2b7e1895 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -382,7 +382,7 @@ :stack-undo? true :ignore-remote? true :ignore-touched true}) - (ptk/data-event :layout/update ids) + (ptk/data-event :layout/update {:ids ids}) (dwu/commit-undo-transaction undo-id)))))))) (defn resize-text diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index be9635715..fc8ee350d 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -719,7 +719,7 @@ (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) - (ptk/data-event :layout/update selected) + (ptk/data-event :layout/update {:ids selected}) (dwu/commit-undo-transaction undo-id)))))) (defn nudge-selected-shapes From 2c740df767883a50f1276cbc0a5f019d0c066880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 7 Mar 2024 13:09:43 +0100 Subject: [PATCH 050/136] :bug: Do recursive swap-slot finding --- common/src/app/common/types/file.cljc | 20 +++++------ .../app/main/data/workspace/libraries.cljs | 6 ++-- .../data/workspace/libraries_helpers.cljs | 35 ++++++++++++++----- .../main/data/workspace/state_helpers.cljs | 5 +++ 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 98e8fbae0..5d8b8cd1c 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -204,7 +204,7 @@ (defn find-ref-shape "Locate the nearest component in the local file or libraries, and retrieve the shape referenced by the instance shape." - [file page libraries shape & {:keys [include-deleted? with-context?] :or {include-deleted? false with-context? false}}] + [file container libraries shape & {:keys [include-deleted? with-context?] :or {include-deleted? false with-context? false}}] (let [find-ref-shape-in-head (fn [head-shape] (let [component-file (find-component-file file libraries (:component-file head-shape)) @@ -213,7 +213,7 @@ (when (some? component) (get-ref-shape (:data component-file) component shape :with-context? with-context?))))] - (some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape)))) + (some find-ref-shape-in-head (ctn/get-parent-heads (:objects container) shape)))) (defn find-ref-component "Locate the nearest component in the local file or libraries that is referenced by the @@ -265,14 +265,13 @@ (true? (= (:id component) (:id ref-component))))) (defn find-swap-slot - [shape page file libraries] - (dm/assert! "expected shape is head" (ctk/instance-head? shape)) + [shape container file libraries] ;; (js/console.log "find-swap-slot" (clj->js shape)) (if-let [swap-slot (ctk/get-swap-slot shape)] ;; (do (js/console.log "uno" (str swap-slot)) swap-slot) swap-slot (let [ref-shape (find-ref-shape file - page + container libraries shape :include-deleted? true @@ -292,11 +291,12 @@ (find-swap-slot ref-shape ref-container ref-file libraries))))))) (defn match-swap-slot? - [shape-main shape-inst page-inst page-main file libraries] - (let [slot-main (find-swap-slot shape-main page-main file libraries) - slot-inst (find-swap-slot shape-inst page-inst file libraries)] - (or (= slot-main slot-inst) - (= (:id shape-main) slot-inst)))) + [shape-main shape-inst container-inst container-main file libraries] + (let [slot-main (find-swap-slot shape-main container-main file libraries) + slot-inst (find-swap-slot shape-inst container-inst file libraries)] + (when (some? slot-inst) + (or (= slot-main slot-inst) + (= (:id shape-main) slot-inst))))) (defn get-component-shapes "Retrieve all shapes of the component" diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index e174df3e7..c197e19ab 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -699,6 +699,7 @@ (watch [it state _] (log/info :msg "RESET-COMPONENT of shape" :id (str id)) (let [file (wsh/get-local-file state) + file-full (wsh/get-local-file-full state) libraries (wsh/get-libraries state) page-id (:current-page-id state) @@ -711,7 +712,7 @@ (-> (pcb/empty-changes it) (pcb/with-container container) (pcb/with-objects (:objects container)) - (dwlh/generate-sync-shape-direct libraries container id true components-v2))] + (dwlh/generate-sync-shape-direct file-full libraries container id true components-v2))] (log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes (:redo-changes changes) @@ -750,6 +751,7 @@ (log/info :msg "UPDATE-COMPONENT of shape" :id (str id) :undo-group undo-group) (let [page-id (get state :current-page-id) local-file (wsh/get-local-file state) + full-file (wsh/get-local-file-full state) container (cfh/get-container local-file :page page-id) shape (ctn/get-shape container id) components-v2 (features/active-feature? state "components/v2")] @@ -761,7 +763,7 @@ (-> (pcb/empty-changes it) (pcb/set-undo-group undo-group) (pcb/with-container container) - (dwlh/generate-sync-shape-inverse libraries container id components-v2)) + (dwlh/generate-sync-shape-inverse full-file libraries container id components-v2)) file-id (:component-file shape) file (wsh/get-file state file-id) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 8864214a6..97a0ac73f 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -425,8 +425,9 @@ (defmethod generate-sync-shape :components [_ changes _library-id state container shape components-v2] (let [shape-id (:id shape) + file (wsh/get-local-file-full state) libraries (wsh/get-libraries state)] - (generate-sync-shape-direct changes libraries container shape-id false components-v2))) + (generate-sync-shape-direct changes file libraries container shape-id false components-v2))) (defmethod generate-sync-shape :colors [_ changes library-id state _ shape _] @@ -594,7 +595,7 @@ (defn generate-sync-shape-direct "Generate changes to synchronize one shape that is the root of a component instance, and all its children, from the given component." - [changes libraries container shape-id reset? components-v2] + [changes file libraries container shape-id reset? components-v2] (log/debug :msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?) (let [shape-inst (ctn/get-shape container shape-id) library (dm/get-in libraries [(:component-file shape-inst) :data]) @@ -623,6 +624,8 @@ shape-inst component library + file + libraries shape-main root-inst root-main @@ -655,7 +658,7 @@ nil)))))) (defn- generate-sync-shape-direct-recursive - [changes container shape-inst component library shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2] + [changes container shape-inst component library file libraries shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2] (log/debug :msg "Sync shape direct recursive" :shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst))) :component (:name component)) @@ -752,6 +755,8 @@ child-inst component library + file + libraries child-main root-inst root-main @@ -782,6 +787,10 @@ (compare-children changes children-inst children-main + container + component-container + file + libraries only-inst only-main both @@ -812,7 +821,7 @@ (defn generate-sync-shape-inverse "Generate changes to update the component a shape is linked to, from the values in the shape and all its children." - [changes libraries container shape-id components-v2] + [changes file libraries container shape-id components-v2] (log/debug :msg "Sync shape inverse" :shape (str shape-id)) (let [redirect-shaperef (partial redirect-shaperef container libraries) shape-inst (ctn/get-shape container shape-id) @@ -843,6 +852,8 @@ shape-inst component library + file + libraries shape-main root-inst root-main @@ -852,7 +863,7 @@ changes))) (defn- generate-sync-shape-inverse-recursive - [changes container shape-inst component library shape-main root-inst root-main initial-root? redirect-shaperef components-v2] + [changes container shape-inst component library file libraries shape-main root-inst root-main initial-root? redirect-shaperef components-v2] (log/trace :msg "Sync shape inverse recursive" :shape (str (:name shape-inst)) :component (:name component)) @@ -935,6 +946,8 @@ child-inst component library + file + libraries child-main root-inst root-main @@ -962,6 +975,10 @@ (compare-children changes children-inst children-main + container + component-container + file + libraries only-inst only-main both @@ -986,7 +1003,7 @@ ;; ---- Operation generation helpers ---- (defn- compare-children - [changes children-inst children-main only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset?] + [changes children-inst children-main container-inst container-main file libraries only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset?] (log/trace :msg "Compare children") (loop [children-inst (seq (or children-inst [])) children-main (seq (or children-main [])) @@ -1007,7 +1024,7 @@ :else (if (or (ctk/is-main-of? child-main child-inst) - (ctk/match-swap-slot? child-main child-inst)) + (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries)) (recur (next children-inst) (next children-main) (if (or (ctk/is-main-of? child-main child-inst) reset?) @@ -1015,10 +1032,10 @@ (swapped-cb changes child-inst child-main))) (let [child-inst' (d/seek #(or (ctk/is-main-of? child-main %) - (ctk/match-swap-slot? child-main %)) + (ctf/match-swap-slot? child-main % container-inst container-main file libraries)) children-inst) child-main' (d/seek #(or (ctk/is-main-of? % child-inst) - (ctk/match-swap-slot? % child-inst)) + (ctf/match-swap-slot? % child-inst container-inst container-main file libraries)) children-main)] (cond (nil? child-inst') diff --git a/frontend/src/app/main/data/workspace/state_helpers.cljs b/frontend/src/app/main/data/workspace/state_helpers.cljs index c33f62d18..b04fa88f6 100644 --- a/frontend/src/app/main/data/workspace/state_helpers.cljs +++ b/frontend/src/app/main/data/workspace/state_helpers.cljs @@ -110,6 +110,11 @@ [state] (get state :workspace-data)) +(defn get-local-file-full + [state] + (-> (get state :workspace-file) + (assoc :data (get state :workspace-data)))) + (defn get-file "Get the data content of the given file (it may be the current file or one library)." From 2c12790782b9abbdef66aa935a7c46882fd25e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 7 Mar 2024 17:32:52 +0100 Subject: [PATCH 051/136] :bug: Fix child compare in reset mode --- .../src/app/main/data/workspace/libraries_helpers.cljs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 97a0ac73f..d157dcd3d 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -1024,18 +1024,18 @@ :else (if (or (ctk/is-main-of? child-main child-inst) - (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries)) + (and (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries) (not reset?))) (recur (next children-inst) (next children-main) - (if (or (ctk/is-main-of? child-main child-inst) reset?) + (if (ctk/is-main-of? child-main child-inst) (both-cb changes child-inst child-main) (swapped-cb changes child-inst child-main))) (let [child-inst' (d/seek #(or (ctk/is-main-of? child-main %) - (ctf/match-swap-slot? child-main % container-inst container-main file libraries)) + (and (ctf/match-swap-slot? child-main % container-inst container-main file libraries) (not reset?))) children-inst) child-main' (d/seek #(or (ctk/is-main-of? % child-inst) - (ctf/match-swap-slot? % child-inst container-inst container-main file libraries)) + (and (ctf/match-swap-slot? % child-inst container-inst container-main file libraries) (not reset?))) children-main)] (cond (nil? child-inst') From 8529927173938d8b52fb0943d803a2fd778f9c19 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 8 Mar 2024 11:56:44 +0100 Subject: [PATCH 052/136] :recycle: Avoid unnecessary logs --- common/src/app/common/types/file.cljc | 6 ------ frontend/src/app/main/data/workspace/libraries.cljs | 1 - 2 files changed, 7 deletions(-) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 5d8b8cd1c..676db6dc7 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -266,9 +266,7 @@ (defn find-swap-slot [shape container file libraries] - ;; (js/console.log "find-swap-slot" (clj->js shape)) (if-let [swap-slot (ctk/get-swap-slot shape)] - ;; (do (js/console.log "uno" (str swap-slot)) swap-slot) swap-slot (let [ref-shape (find-ref-shape file container @@ -279,12 +277,8 @@ shape-meta (meta ref-shape) ref-file (:file shape-meta) ref-container (:container shape-meta)] - ;; (js/console.log "ref-shape" (clj->js ref-shape)) - ;; (js/console.log "ref-file" (clj->js ref-file)) - ;; (js/console.log "ref-container" (clj->js ref-container)) (when ref-shape (if-let [swap-slot (ctk/get-swap-slot ref-shape)] - ;; (do (js/console.log "dos" (str swap-slot)) swap-slot) swap-slot (if (ctk/main-instance? ref-shape) (:id shape) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index c197e19ab..c27c00b0f 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -905,7 +905,6 @@ libraries) (ctk/build-swap-slot-group)))) - ;; _ (js/console.log "new-shape" (str (:id new-shape)) (clj->js new-shape)) changes (-> changes ;; Restore the properties From d488d69abc60d0c7efcf0478d363e6262d157040 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 8 Mar 2024 14:32:21 +0100 Subject: [PATCH 053/136] :recycle: Remove old color bullet component --- .../app/main/ui/components/color_bullet.cljs | 123 +++++++++++++----- ...olor_bullet_new.scss => color_bullet.scss} | 0 .../main/ui/components/color_bullet_new.cljs | 114 ---------------- frontend/src/app/main/ui/dashboard/grid.cljs | 6 +- frontend/src/app/main/ui/dashboard/grid.scss | 6 + .../ui/viewer/inspect/attributes/common.cljs | 14 +- .../app/main/ui/workspace/color_palette.cljs | 2 +- .../ui/workspace/color_palette_ctx_menu.cljs | 2 +- .../ui/workspace/colorpicker/libraries.cljs | 2 +- .../main/ui/workspace/colorpicker/ramp.cljs | 2 +- .../src/app/main/ui/workspace/libraries.cljs | 5 +- .../ui/workspace/sidebar/assets/colors.cljs | 2 +- .../sidebar/options/rows/color_row.cljs | 14 +- 13 files changed, 120 insertions(+), 172 deletions(-) rename frontend/src/app/main/ui/components/{color_bullet_new.scss => color_bullet.scss} (100%) delete mode 100644 frontend/src/app/main/ui/components/color_bullet_new.cljs diff --git a/frontend/src/app/main/ui/components/color_bullet.cljs b/frontend/src/app/main/ui/components/color_bullet.cljs index 7213a8347..1d4b9aacc 100644 --- a/frontend/src/app/main/ui/components/color_bullet.cljs +++ b/frontend/src/app/main/ui/components/color_bullet.cljs @@ -5,57 +5,110 @@ ;; Copyright (c) KALEIDOS INC (ns app.main.ui.components.color-bullet + (:require-macros [app.main.style :as stl]) (:require [app.config :as cfg] [app.util.color :as uc] - [app.util.dom :as dom] - [app.util.i18n :as i18n :refer [tr]] + [app.util.i18n :refer [tr]] [cuerdas.core :as str] [rumext.v2 :as mf])) +(defn- color-title + [color-item] + (let [name (:name color-item) + gradient (:gradient color-item) + image (:image color-item) + color (:color color-item)] + + (if (some? name) + (cond + (some? color) + (str/ffmt "% (%)" name color) + + (some? gradient) + (str/ffmt "% (%)" name (uc/gradient-type->string (:type gradient))) + + (some? image) + (str/ffmt "% (%)" name (tr "media.image")) + + :else + name) + + (cond + (some? color) + color + + (some? gradient) + (uc/gradient-type->string (:type gradient)) + + (some? image) + (tr "media.image"))))) + (mf/defc color-bullet {::mf/wrap [mf/memo] ::mf/wrap-props false} - [{:keys [color on-click]}] - (let [on-click (mf/use-fn - (mf/deps color on-click) - (fn [event] - (when (fn? on-click) - (^function on-click color event))))] + [{:keys [color on-click mini? area]}] + (let [read-only? (nil? on-click) + on-click + (mf/use-fn + (mf/deps color on-click) + (fn [event] + (when (fn? on-click) + (^function on-click color event))))] (if (uc/multiple? color) - [:div.color-bullet.multiple {:on-click on-click}] - + [:div {:class (stl/css :color-bullet :multiple) + :on-click on-click + :title (color-title color)}] ;; No multiple selection - (let [color (if (string? color) {:color color :opacity 1} color)] - [:div.color-bullet - {:class (dom/classnames :is-library-color (some? (:id color)) - :is-not-library-color (nil? (:id color)) - :is-gradient (some? (:gradient color))) + (let [color (if (string? color) {:color color :opacity 1} color) + id (:id color) + gradient (:gradient color) + opacity (:opacity color) + image (:image color)] + [:div + {:class (stl/css-case + :color-bullet true + :mini mini? + :is-library-color (some? id) + :is-not-library-color (nil? id) + :is-gradient (some? gradient) + :is-transparent (and opacity (> 1 opacity)) + :grid-area area + :read-only read-only?) + :data-readonly (str read-only?) :on-click on-click - :title (uc/get-color-name color)} - (cond - (:gradient color) - [:div.color-bullet-wrapper {:style {:background (uc/color->background color)}}] + :title (color-title color)} - (:image color) - (let [uri (cfg/resolve-file-media (:image color))] - [:div.color-bullet-wrapper {:style {:background-size "contain" :background-image (str/ffmt "url(%)" uri)}}]) + (cond + (some? gradient) + [:div {:class (stl/css :color-bullet-wrapper) + :style {:background (uc/color->background color)}}] + + (some? image) + (let [uri (cfg/resolve-file-media image)] + [:div {:class (stl/css :color-bullet-wrapper) + :style {:background-image (str/ffmt "url(%)" uri)}}]) :else - [:div.color-bullet-wrapper - [:div.color-bullet-left {:style {:background (uc/color->background (assoc color :opacity 1))}}] - [:div.color-bullet-right {:style {:background (uc/color->background color)}}]])])))) + [:div {:class (stl/css :color-bullet-wrapper)} + [:div {:class (stl/css :color-bullet-left) + :style {:background (uc/color->background (assoc color :opacity 1))}}] + [:div {:class (stl/css :color-bullet-right) + :style {:background (uc/color->background color)}}]])])))) (mf/defc color-name {::mf/wrap-props false} - [{:keys [color size on-click on-double-click]}] - (let [{:keys [name color gradient image]} (if (string? color) {:color color :opacity 1} color)] - (when (or (not size) (= size :big)) - [:span.color-text - {:on-click on-click - :on-double-click on-double-click - :title name} - (if (some? image) - (tr "media.image.short") - (or name color (uc/gradient-type->string (:type gradient))))]))) + [{:keys [color size on-click on-double-click origin]}] + (let [{:keys [name color gradient]} (if (string? color) {:color color :opacity 1} color)] + (when (or (not size) (> size 64)) + [:span {:class (stl/css-case + :color-text (and (= origin :palette) (< size 72)) + :small-text (and (= origin :palette) (>= size 64) (< size 72)) + :big-text (and (= origin :palette) (>= size 72)) + :gradient (some? gradient) + :color-row-name (not= origin :palette)) + :title name + :on-click on-click + :on-double-click on-double-click} + (or name color (uc/gradient-type->string (:type gradient)))]))) diff --git a/frontend/src/app/main/ui/components/color_bullet_new.scss b/frontend/src/app/main/ui/components/color_bullet.scss similarity index 100% rename from frontend/src/app/main/ui/components/color_bullet_new.scss rename to frontend/src/app/main/ui/components/color_bullet.scss diff --git a/frontend/src/app/main/ui/components/color_bullet_new.cljs b/frontend/src/app/main/ui/components/color_bullet_new.cljs deleted file mode 100644 index 6173a582f..000000000 --- a/frontend/src/app/main/ui/components/color_bullet_new.cljs +++ /dev/null @@ -1,114 +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.components.color-bullet-new - (:require-macros [app.main.style :as stl]) - (:require - [app.config :as cfg] - [app.util.color :as uc] - [app.util.i18n :refer [tr]] - [cuerdas.core :as str] - [rumext.v2 :as mf])) - -(defn- color-title - [color-item] - (let [name (:name color-item) - gradient (:gradient color-item) - image (:image color-item) - color (:color color-item)] - - (if (some? name) - (cond - (some? color) - (str/ffmt "% (%)" name color) - - (some? gradient) - (str/ffmt "% (%)" name (uc/gradient-type->string (:type gradient))) - - (some? image) - (str/ffmt "% (%)" name (tr "media.image")) - - :else - name) - - (cond - (some? color) - color - - (some? gradient) - (uc/gradient-type->string (:type gradient)) - - (some? image) - (tr "media.image"))))) - -(mf/defc color-bullet - {::mf/wrap [mf/memo] - ::mf/wrap-props false} - [{:keys [color on-click mini? area]}] - (let [read-only? (nil? on-click) - on-click - (mf/use-fn - (mf/deps color on-click) - (fn [event] - (when (fn? on-click) - (^function on-click color event))))] - - (if (uc/multiple? color) - [:div {:class (stl/css :color-bullet :multiple) - :on-click on-click - :title (color-title color)}] - ;; No multiple selection - (let [color (if (string? color) {:color color :opacity 1} color) - id (:id color) - gradient (:gradient color) - opacity (:opacity color) - image (:image color)] - [:div - {:class (stl/css-case - :color-bullet true - :mini mini? - :is-library-color (some? id) - :is-not-library-color (nil? id) - :is-gradient (some? gradient) - :is-transparent (and opacity (> 1 opacity)) - :grid-area area - :read-only read-only?) - :data-readonly (str read-only?) - :on-click on-click - :title (color-title color)} - - (cond - (some? gradient) - [:div {:class (stl/css :color-bullet-wrapper) - :style {:background (uc/color->background color)}}] - - (some? image) - (let [uri (cfg/resolve-file-media image)] - [:div {:class (stl/css :color-bullet-wrapper) - :style {:background-image (str/ffmt "url(%)" uri)}}]) - - :else - [:div {:class (stl/css :color-bullet-wrapper)} - [:div {:class (stl/css :color-bullet-left) - :style {:background (uc/color->background (assoc color :opacity 1))}}] - [:div {:class (stl/css :color-bullet-right) - :style {:background (uc/color->background color)}}]])])))) - -(mf/defc color-name - {::mf/wrap-props false} - [{:keys [color size on-click on-double-click origin]}] - (let [{:keys [name color gradient]} (if (string? color) {:color color :opacity 1} color)] - (when (or (not size) (> size 64)) - [:span {:class (stl/css-case - :color-text (and (= origin :palette) (< size 72)) - :small-text (and (= origin :palette) (>= size 64) (< size 72)) - :big-text (and (= origin :palette) (>= size 72)) - :gradient (some? gradient) - :color-row-name (not= origin :palette)) - :title name - :on-click on-click - :on-double-click on-double-click} - (or name color (uc/gradient-type->string (:type gradient)))]))) diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 16a5e9e31..4b35b7f70 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -163,10 +163,12 @@ (: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) + [:div {:class (stl/css :asset-list-item :color-item) :key (str "assets-color-" (:id color))} [:& bc/color-bullet {:color {:color (:color color) - :opacity (:opacity color)}}] + :id (:id color) + :opacity (:opacity color)} + :mini? true}] [:div {:class (stl/css :name-block)} [:span {:class (stl/css :color-name)} (:name color)] (when-not (= (:name color) default-name) diff --git a/frontend/src/app/main/ui/dashboard/grid.scss b/frontend/src/app/main/ui/dashboard/grid.scss index e3188a2f9..3108fa656 100644 --- a/frontend/src/app/main/ui/dashboard/grid.scss +++ b/frontend/src/app/main/ui/dashboard/grid.scss @@ -370,3 +370,9 @@ $thumbnail-default-height: $s-168; // Default width } } } + +.color-item { + display: grid; + grid-template-columns: auto 1fr; + gap: $s-8; +} diff --git a/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs b/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs index bbf5148f3..b5c26b07f 100644 --- a/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs @@ -14,7 +14,7 @@ [app.config :as cf] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.color-bullet-new :as cbn] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.copy-button :refer [copy-button]] [app.main.ui.components.select :refer [select]] [app.main.ui.formats :as fmt] @@ -69,8 +69,8 @@ [:div {:class (stl/css :attributes-color-row)} [:div {:class (stl/css :bullet-wrapper) :style #js {"--bullet-size" "16px"}} - [:& cbn/color-bullet {:color color - :mini? true}]] + [:& cb/color-bullet {:color color + :mini? true}]] [:div {:class (stl/css :format-wrapper)} [:div {:class (stl/css :image-format)} @@ -101,8 +101,8 @@ [:div {:class (stl/css :attributes-color-row)} [:div {:class (stl/css :bullet-wrapper) :style #js {"--bullet-size" "16px"}} - [:& cbn/color-bullet {:color color - :mini? true}]] + [:& cb/color-bullet {:color color + :mini? true}]] [:div {:class (stl/css :format-wrapper)} (when-not (and on-change-format (or (:gradient color) image)) @@ -125,9 +125,9 @@ [:span {:class (stl/css-case :color-value-wrapper true :gradient-name (:gradient color))} (if (:gradient color) - [:& cbn/color-name {:color color :size 90}] + [:& cb/color-name {:color color :size 90}] (case format - :hex [:& cbn/color-name {:color color}] + :hex [:& cb/color-name {:color color}] :rgba (let [[r g b a] (cc/hex->rgba (:color color) (:opacity color))] (str/ffmt "%, %, %, %" r g b a)) :hsla (let [[h s l a] (cc/hex->hsla (:color color) (:opacity color)) diff --git a/frontend/src/app/main/ui/workspace/color_palette.cljs b/frontend/src/app/main/ui/workspace/color_palette.cljs index b07848671..6ca87fabd 100644 --- a/frontend/src/app/main/ui/workspace/color_palette.cljs +++ b/frontend/src/app/main/ui/workspace/color_palette.cljs @@ -11,7 +11,7 @@ [app.main.data.workspace.colors :as mdc] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.color-bullet-new :as cb] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.hooks :as h] [app.main.ui.icons :as i] [app.util.color :as uc] diff --git a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs index 72be7f0a8..3f9ba68d8 100644 --- a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs +++ b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs @@ -9,7 +9,7 @@ (:require [app.common.data.macros :as dm] [app.main.refs :as refs] - [app.main.ui.components.color-bullet-new :as cb] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.dropdown :refer [dropdown]] [app.main.ui.icons :as i] [app.util.i18n :refer [tr]] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs index fe52c2e92..076aef276 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs @@ -14,7 +14,7 @@ [app.main.data.workspace.colors :as mdc] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.color-bullet-new :as cb] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.select :refer [select]] [app.main.ui.hooks :as h] [app.main.ui.hooks.resize :as r] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs index 8b5ee82a3..970525d3c 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs @@ -9,7 +9,7 @@ (:require [app.common.colors :as cc] [app.common.math :as mth] - [app.main.ui.components.color-bullet-new :as cb] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]] [app.util.dom :as dom] [rumext.v2 :as mf])) diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index cd9032a85..e976c0230 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -20,7 +20,7 @@ [app.main.refs :as refs] [app.main.render :refer [component-svg]] [app.main.store :as st] - [app.main.ui.components.color-bullet :as bc] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.link-button :as lb] [app.main.ui.components.search-bar :refer [search-bar]] [app.main.ui.components.tab-container :refer [tab-container tab-element]] @@ -407,7 +407,8 @@ [:div {:class (stl/css :libraries-updates-item) :key (dm/str (:id color))} [:* - [:& bc/color-bullet {:color {:color (:color color) + [:& cb/color-bullet {:color {:color (:color color) + :id (:id color) :opacity (:opacity color)}}] [:div {:class (stl/css :name-block)} [:span {:class (stl/css :item-name) 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 5dc91dba6..ef4b9200c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs @@ -18,7 +18,7 @@ [app.main.data.workspace.undo :as dwu] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.color-bullet-new :as cb] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.context :as ctx] [app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.assets.common :as cmm] 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 121efb9d7..c684a22c9 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,7 @@ [app.main.data.workspace.libraries :as dwl] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.color-bullet-new :as cbn] + [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-input :refer [color-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.context :as ctx] @@ -201,12 +201,12 @@ :editing editing-text? :gradient-name-wrapper gradient-color?)} [:div {: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}]] + [:& cb/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? From 1c29c73b8e564669f04ba28fd175d7a960e8139a Mon Sep 17 00:00:00 2001 From: Aitor Date: Fri, 8 Mar 2024 13:34:13 +0100 Subject: [PATCH 054/136] :bug: Fix rasterizer using wrong sizes --- frontend/src/app/rasterizer.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/rasterizer.cljs b/frontend/src/app/rasterizer.cljs index b8eff2336..e2bf9ede6 100644 --- a/frontend/src/app/rasterizer.cljs +++ b/frontend/src/app/rasterizer.cljs @@ -58,7 +58,7 @@ "Returns the adjusted size of an SVG." [width height max] (let [ratio (/ width height)] - (if (> width height) + (if (< width height) [max (* max (/ 1 ratio))] [(* max ratio) max]))) From d0889931b5e3e605de8f908f555b0cda56d7b302 Mon Sep 17 00:00:00 2001 From: Aitor Date: Thu, 7 Mar 2024 12:28:47 +0100 Subject: [PATCH 055/136] :bug: Fix color picker blurry bitmap --- frontend/src/app/main/ui/workspace/colorpicker.cljs | 6 +++--- frontend/src/app/main/ui/workspace/colorpicker.scss | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs index 59af137eb..115ba8f77 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs @@ -316,7 +316,7 @@ (if picking-color? [:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :center-circle)}] - [:canvas#picker-detail {:width 256 :height 140}]] + [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]] [:& ramp-selector {:color current-color :disable-opacity disable-opacity @@ -328,7 +328,7 @@ (if picking-color? [:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :center-circle)}] - [:canvas#picker-detail {:width 256 :height 140}]] + [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]] [:& harmony-selector {:color current-color :disable-opacity disable-opacity @@ -340,7 +340,7 @@ (if picking-color? [:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :center-circle)}] - [:canvas#picker-detail {:width 256 :height 140}]] + [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]] [:& hsva-selector {:color current-color :disable-opacity disable-opacity diff --git a/frontend/src/app/main/ui/workspace/colorpicker.scss b/frontend/src/app/main/ui/workspace/colorpicker.scss index 7865e349f..cc739678d 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker.scss +++ b/frontend/src/app/main/ui/workspace/colorpicker.scss @@ -132,6 +132,11 @@ transform: translate(calc(-1 * $s-12), calc(-1 * $s-12)); } +.picker-detail { + image-rendering: crisp-edges; + image-rendering: pixelated; +} + .select { width: $s-116; } From 4ef2482b02988c5541ef66f784f6dec0ad01437f Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 7 Mar 2024 14:46:18 +0100 Subject: [PATCH 056/136] :recycle: Remove unused icons --- .../{absolute-refactor.svg => absolute.svg} | 0 .../resources/images/icons/action-mark.svg | 1 - frontend/resources/images/icons/action.svg | 1 - frontend/resources/images/icons/actions.svg | 3 - .../icons/{add-refactor.svg => add.svg} | 0 .../images/icons/align-bottom-refactor.svg | 3 - .../resources/images/icons/align-bottom.svg | 6 +- .../align-content-column-around-refactor.svg | 3 - .../icons/align-content-column-around.svg | 6 +- .../align-content-column-between-refactor.svg | 3 - .../icons/align-content-column-between.svg | 6 +- .../align-content-column-center-refactor.svg | 3 - .../icons/align-content-column-center.svg | 6 +- .../align-content-column-end-refactor.svg | 3 - .../images/icons/align-content-column-end.svg | 6 +- .../align-content-column-evenly-refactor.svg | 3 - .../icons/align-content-column-evenly.svg | 6 +- .../align-content-column-start-refactor.svg | 3 - .../icons/align-content-column-start.svg | 6 +- ...r.svg => align-content-column-stretch.svg} | 0 .../align-content-row-around-refactor.svg | 3 - .../images/icons/align-content-row-around.svg | 6 +- .../align-content-row-between-refactor.svg | 3 - .../icons/align-content-row-between.svg | 6 +- .../align-content-row-center-refactor.svg | 3 - .../images/icons/align-content-row-center.svg | 6 +- .../icons/align-content-row-end-refactor.svg | 3 - .../images/icons/align-content-row-end.svg | 6 +- .../align-content-row-evenly-refactor.svg | 3 - .../images/icons/align-content-row-evenly.svg | 6 +- .../align-content-row-start-refactor.svg | 3 - .../images/icons/align-content-row-start.svg | 6 +- ...ctor.svg => align-content-row-stretch.svg} | 0 ...factor.svg => align-horizontal-center.svg} | 0 .../icons/align-items-column-baseline.svg | 3 - .../align-items-column-center-refactor.svg | 3 - .../icons/align-items-column-center.svg | 6 +- .../images/icons/align-items-column-end.svg | 3 - .../images/icons/align-items-column-start.svg | 3 - .../icons/align-items-column-strech.svg | 3 - .../images/icons/align-items-row-baseline.svg | 3 - .../images/icons/align-items-row-center.svg | 3 - .../images/icons/align-items-row-end.svg | 3 - .../images/icons/align-items-row-start.svg | 3 - .../images/icons/align-items-row-strech.svg | 3 - .../resources/images/icons/align-middle.svg | 3 - .../icons/align-self-column-baseline.svg | 3 - .../images/icons/align-self-column-bottom.svg | 3 - .../images/icons/align-self-column-center.svg | 3 - .../images/icons/align-self-column-strech.svg | 3 - .../images/icons/align-self-column-top.svg | 3 - .../images/icons/align-self-row-baseline.svg | 3 - .../images/icons/align-self-row-center.svg | 3 - .../images/icons/align-self-row-left.svg | 3 - .../images/icons/align-self-row-right.svg | 3 - .../images/icons/align-self-row-strech.svg | 3 - frontend/resources/images/icons/align-top.svg | 3 - frontend/resources/images/icons/alignment.svg | 3 - .../resources/images/icons/animate-down.svg | 3 - .../resources/images/icons/animate-left.svg | 3 - .../resources/images/icons/animate-right.svg | 3 - .../resources/images/icons/animate-up.svg | 3 - .../resources/images/icons/arrow-down.svg | 3 - frontend/resources/images/icons/arrow-end.svg | 3 - .../resources/images/icons/arrow-slide.svg | 3 - frontend/resources/images/icons/arrow-up.svg | 1 - frontend/resources/images/icons/artboard.svg | 3 - frontend/resources/images/icons/at.svg | 3 - .../resources/images/icons/auto-direction.svg | 3 - frontend/resources/images/icons/auto-fill.svg | 3 - .../images/icons/auto-fix-layout.svg | 3 - frontend/resources/images/icons/auto-fix.svg | 3 - frontend/resources/images/icons/auto-gap.svg | 3 - .../resources/images/icons/auto-height.svg | 3 - frontend/resources/images/icons/auto-hug.svg | 3 - .../images/icons/auto-margin-both-sides.svg | 3 - .../images/icons/auto-margin-side.svg | 3 - .../resources/images/icons/auto-margin.svg | 3 - .../images/icons/auto-padding-both-sides.svg | 3 - .../images/icons/auto-padding-side.svg | 3 - .../resources/images/icons/auto-padding.svg | 3 - .../resources/images/icons/auto-width.svg | 3 - frontend/resources/images/icons/auto-wrap.svg | 3 - .../images/icons/boolean-difference.svg | 3 - .../images/icons/boolean-exclude.svg | 3 - .../images/icons/boolean-flatten.svg | 3 - .../images/icons/boolean-intersection.svg | 3 - .../resources/images/icons/boolean-union.svg | 3 - frontend/resources/images/icons/box.svg | 3 - frontend/resources/images/icons/bug.svg | 3 - .../images/icons/cap-circle-marker.svg | 3 - .../images/icons/cap-diamond-marker.svg | 3 - .../resources/images/icons/cap-line-arrow.svg | 3 - frontend/resources/images/icons/cap-round.svg | 3 - .../images/icons/cap-square-marker.svg | 3 - .../resources/images/icons/cap-square.svg | 3 - .../images/icons/cap-triangle-arrow.svg | 3 - frontend/resources/images/icons/chain.svg | 3 - frontend/resources/images/icons/chat.svg | 1 - .../images/icons/checkbox-checked.svg | 1 - .../images/icons/checkbox-intermediate.svg | 1 - .../images/icons/checkbox-unchecked.svg | 1 - frontend/resources/images/icons/circle.svg | 1 - frontend/resources/images/icons/close.svg | 1 - frontend/resources/images/icons/code.svg | 3 - frontend/resources/images/icons/comment.svg | 4 - .../resources/images/icons/component-copy.svg | 3 - frontend/resources/images/icons/component.svg | 3 - frontend/resources/images/icons/copy.svg | 3 - frontend/resources/images/icons/cross.svg | 1 - frontend/resources/images/icons/curve.svg | 1 - frontend/resources/images/icons/download.svg | 3 - .../images/icons/easing-ease-in-out.svg | 3 - .../resources/images/icons/easing-ease-in.svg | 3 - .../images/icons/easing-ease-out.svg | 3 - .../resources/images/icons/easing-ease.svg | 3 - .../resources/images/icons/easing-linear.svg | 3 - frontend/resources/images/icons/exclude.svg | 1 - frontend/resources/images/icons/exit.svg | 3 - frontend/resources/images/icons/export.svg | 1 - .../resources/images/icons/eye-closed.svg | 1 - frontend/resources/images/icons/eye.svg | 1 - frontend/resources/images/icons/file-html.svg | 3 - frontend/resources/images/icons/file-svg.svg | 3 - frontend/resources/images/icons/fill.svg | 3 - frontend/resources/images/icons/filter.svg | 1 - .../resources/images/icons/folder-zip.svg | 3 - frontend/resources/images/icons/folder.svg | 3 - .../images/icons/full-screen-off.svg | 3 - .../resources/images/icons/full-screen.svg | 3 - frontend/resources/images/icons/go-next.svg | 1 - frontend/resources/images/icons/go-prev.svg | 1 - .../grid-justify-content-column-around.svg | 38 -- .../grid-justify-content-column-between.svg | 38 -- .../grid-justify-content-column-center.svg | 38 -- .../icons/grid-justify-content-column-end.svg | 38 -- .../grid-justify-content-column-start.svg | 38 -- .../icons/grid-justify-content-row-around.svg | 38 -- .../grid-justify-content-row-between.svg | 38 -- .../icons/grid-justify-content-row-center.svg | 38 -- .../icons/grid-justify-content-row-end.svg | 38 -- .../icons/grid-justify-content-row-start.svg | 38 -- .../images/icons/grid-layout-mode.svg | 3 - frontend/resources/images/icons/grid-snap.svg | 3 - frontend/resources/images/icons/grid.svg | 3 - frontend/resources/images/icons/help.svg | 4 - .../resources/images/icons/icon-empty.svg | 3 - frontend/resources/images/icons/icon-key.svg | 4 - frontend/resources/images/icons/icon-list.svg | 1 - frontend/resources/images/icons/icon-lock.svg | 3 - frontend/resources/images/icons/icon-set.svg | 1 - frontend/resources/images/icons/image.svg | 3 - frontend/resources/images/icons/import.svg | 3 - frontend/resources/images/icons/infocard.svg | 1 - .../resources/images/icons/interaction.svg | 3 - .../icons/justify-content-column-around.svg | 3 - .../icons/justify-content-column-between.svg | 3 - .../icons/justify-content-column-center.svg | 3 - .../icons/justify-content-column-end.svg | 3 - .../icons/justify-content-column-evenly.svg | 3 - .../icons/justify-content-column-start.svg | 3 - .../icons/justify-content-row-around.svg | 3 - .../icons/justify-content-row-between.svg | 3 - .../icons/justify-content-row-center.svg | 3 - .../images/icons/justify-content-row-end.svg | 3 - .../icons/justify-content-row-evenly.svg | 3 - .../icons/justify-content-row-start.svg | 3 - frontend/resources/images/icons/layers.svg | 3 - .../resources/images/icons/layout-columns.svg | 3 - .../resources/images/icons/layout-rows.svg | 3 - .../resources/images/icons/letter-spacing.svg | 3 - frontend/resources/images/icons/libraries.svg | 3 - frontend/resources/images/icons/library.svg | 3 - .../resources/images/icons/line-height.svg | 3 - frontend/resources/images/icons/line.svg | 1 - .../resources/images/icons/listing-enum.svg | 3 - .../resources/images/icons/listing-thumbs.svg | 3 - frontend/resources/images/icons/lock.svg | 3 - frontend/resources/images/icons/logout.svg | 3 - frontend/resources/images/icons/lowercase.svg | 3 - frontend/resources/images/icons/mail.svg | 3 - frontend/resources/images/icons/mask.svg | 3 - frontend/resources/images/icons/minus.svg | 3 - frontend/resources/images/icons/msg-error.svg | 3 - frontend/resources/images/icons/msg-info.svg | 3 - .../resources/images/icons/msg-success.svg | 3 - .../resources/images/icons/msg-warning.svg | 3 - frontend/resources/images/icons/navigate.svg | 3 - frontend/resources/images/icons/nodes-add.svg | 3 - .../resources/images/icons/nodes-corner.svg | 3 - .../resources/images/icons/nodes-curve.svg | 3 - .../resources/images/icons/nodes-join.svg | 3 - .../resources/images/icons/nodes-merge.svg | 3 - .../resources/images/icons/nodes-remove.svg | 3 - .../resources/images/icons/nodes-separate.svg | 3 - .../resources/images/icons/nodes-snap.svg | 3 - frontend/resources/images/icons/organize.svg | 1 - frontend/resources/images/icons/palette.svg | 3 - frontend/resources/images/icons/pen.svg | 3 - frontend/resources/images/icons/pencil.svg | 4 - .../resources/images/icons/picker-harmony.svg | 3 - .../resources/images/icons/picker-hsv.svg | 1 - .../resources/images/icons/picker-ramp.svg | 3 - frontend/resources/images/icons/picker.svg | 3 - frontend/resources/images/icons/pin-fill.svg | 3 - frontend/resources/images/icons/pin.svg | 3 - frontend/resources/images/icons/play.svg | 1 - frontend/resources/images/icons/plus.svg | 3 - .../resources/images/icons/pointer-inner.svg | 3 - .../images/icons/position-absolute.svg | 3 - .../images/icons/position-bottom-center.svg | 6 - .../images/icons/position-bottom-left.svg | 6 - .../images/icons/position-bottom-right.svg | 6 - .../images/icons/position-center.svg | 6 - .../images/icons/position-top-center.svg | 6 - .../images/icons/position-top-left.svg | 7 - .../images/icons/position-top-right.svg | 6 - frontend/resources/images/icons/puzzle.svg | 1 - frontend/resources/images/icons/radius-1.svg | 3 - frontend/resources/images/icons/radius-4.svg | 3 - frontend/resources/images/icons/radius.svg | 1 - frontend/resources/images/icons/recent.svg | 3 - frontend/resources/images/icons/redo.svg | 1 - frontend/resources/images/icons/reset.svg | 1 - frontend/resources/images/icons/rotate.svg | 1 - .../resources/images/icons/ruler-tool.svg | 3 - frontend/resources/images/icons/ruler.svg | 1 - frontend/resources/images/icons/search.svg | 1 - .../resources/images/icons/set-thumbnail.svg | 3 - .../images/icons/shape-halign-center.svg | 1 - .../images/icons/shape-halign-left.svg | 1 - .../images/icons/shape-halign-right.svg | 1 - .../images/icons/shape-hdistribute.svg | 1 - .../images/icons/shape-valign-bottom.svg | 1 - .../images/icons/shape-valign-center.svg | 1 - .../images/icons/shape-valign-top.svg | 1 - .../images/icons/shape-vdistribute.svg | 1 - frontend/resources/images/icons/shortcut.svg | 3 - .../resources/images/icons/size-horiz.svg | 3 - frontend/resources/images/icons/size-vert.svg | 3 - .../resources/images/icons/sort-ascending.svg | 3 - .../images/icons/sort-descending.svg | 3 - .../resources/images/icons/space-around.svg | 3 - .../resources/images/icons/space-between.svg | 3 - .../resources/images/icons/strikethrough.svg | 3 - frontend/resources/images/icons/stroke.svg | 1 - frontend/resources/images/icons/switch.svg | 5 - .../images/icons/text-LTR-refactor.svg | 3 - .../images/icons/text-RTL-refactor.svg | 3 - .../images/icons/text-align-center.svg | 1 - .../images/icons/text-align-justify.svg | 1 - .../images/icons/text-align-left.svg | 1 - .../images/icons/text-align-right.svg | 1 - .../images/icons/text-direction-ltr.svg | 3 - .../images/icons/text-direction-rtl.svg | 3 - frontend/resources/images/icons/text.svg | 1 - frontend/resources/images/icons/tick.svg | 3 - frontend/resources/images/icons/titlecase.svg | 3 - frontend/resources/images/icons/toggle.svg | 3 - frontend/resources/images/icons/trash.svg | 1 - frontend/resources/images/icons/tree.svg | 3 - frontend/resources/images/icons/underline.svg | 3 - frontend/resources/images/icons/undo.svg | 1 - frontend/resources/images/icons/ungroup.svg | 3 - frontend/resources/images/icons/unlock.svg | 3 - frontend/resources/images/icons/uppercase.svg | 3 - frontend/resources/images/icons/user.svg | 3 - frontend/src/app/main/ui.cljs | 2 +- .../app/main/ui/components/context_menu.cljs | 131 ------- .../src/app/main/ui/dashboard/import.cljs | 2 +- .../src/app/main/ui/dashboard/search.cljs | 6 +- .../src/app/main/ui/dashboard/search.scss | 2 +- frontend/src/app/main/ui/icons.cljs | 361 +++--------------- .../src/app/main/ui/onboarding/templates.cljs | 2 +- .../options/menus/layout_container.cljs | 26 +- 275 files changed, 116 insertions(+), 1526 deletions(-) rename frontend/resources/images/icons/{absolute-refactor.svg => absolute.svg} (100%) delete mode 100644 frontend/resources/images/icons/action-mark.svg delete mode 100644 frontend/resources/images/icons/action.svg delete mode 100644 frontend/resources/images/icons/actions.svg rename frontend/resources/images/icons/{add-refactor.svg => add.svg} (100%) delete mode 100644 frontend/resources/images/icons/align-bottom-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-column-around-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-column-between-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-column-center-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-column-end-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-column-evenly-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-column-start-refactor.svg rename frontend/resources/images/icons/{align-content-column-stretch-refactor.svg => align-content-column-stretch.svg} (100%) delete mode 100644 frontend/resources/images/icons/align-content-row-around-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-row-between-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-row-center-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-row-end-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-row-evenly-refactor.svg delete mode 100644 frontend/resources/images/icons/align-content-row-start-refactor.svg rename frontend/resources/images/icons/{align-content-row-stretch-refactor.svg => align-content-row-stretch.svg} (100%) rename frontend/resources/images/icons/{align-horizontal-center-refactor.svg => align-horizontal-center.svg} (100%) delete mode 100644 frontend/resources/images/icons/align-items-column-baseline.svg delete mode 100644 frontend/resources/images/icons/align-items-column-center-refactor.svg delete mode 100644 frontend/resources/images/icons/align-items-column-end.svg delete mode 100644 frontend/resources/images/icons/align-items-column-start.svg delete mode 100644 frontend/resources/images/icons/align-items-column-strech.svg delete mode 100644 frontend/resources/images/icons/align-items-row-baseline.svg delete mode 100644 frontend/resources/images/icons/align-items-row-center.svg delete mode 100644 frontend/resources/images/icons/align-items-row-end.svg delete mode 100644 frontend/resources/images/icons/align-items-row-start.svg delete mode 100644 frontend/resources/images/icons/align-items-row-strech.svg delete mode 100644 frontend/resources/images/icons/align-middle.svg delete mode 100644 frontend/resources/images/icons/align-self-column-baseline.svg delete mode 100644 frontend/resources/images/icons/align-self-column-bottom.svg delete mode 100644 frontend/resources/images/icons/align-self-column-center.svg delete mode 100644 frontend/resources/images/icons/align-self-column-strech.svg delete mode 100644 frontend/resources/images/icons/align-self-column-top.svg delete mode 100644 frontend/resources/images/icons/align-self-row-baseline.svg delete mode 100644 frontend/resources/images/icons/align-self-row-center.svg delete mode 100644 frontend/resources/images/icons/align-self-row-left.svg delete mode 100644 frontend/resources/images/icons/align-self-row-right.svg delete mode 100644 frontend/resources/images/icons/align-self-row-strech.svg delete mode 100644 frontend/resources/images/icons/align-top.svg delete mode 100644 frontend/resources/images/icons/alignment.svg delete mode 100644 frontend/resources/images/icons/animate-down.svg delete mode 100644 frontend/resources/images/icons/animate-left.svg delete mode 100644 frontend/resources/images/icons/animate-right.svg delete mode 100644 frontend/resources/images/icons/animate-up.svg delete mode 100644 frontend/resources/images/icons/arrow-down.svg delete mode 100644 frontend/resources/images/icons/arrow-end.svg delete mode 100644 frontend/resources/images/icons/arrow-slide.svg delete mode 100644 frontend/resources/images/icons/arrow-up.svg delete mode 100644 frontend/resources/images/icons/artboard.svg delete mode 100644 frontend/resources/images/icons/at.svg delete mode 100644 frontend/resources/images/icons/auto-direction.svg delete mode 100644 frontend/resources/images/icons/auto-fill.svg delete mode 100644 frontend/resources/images/icons/auto-fix-layout.svg delete mode 100644 frontend/resources/images/icons/auto-fix.svg delete mode 100644 frontend/resources/images/icons/auto-gap.svg delete mode 100644 frontend/resources/images/icons/auto-height.svg delete mode 100644 frontend/resources/images/icons/auto-hug.svg delete mode 100644 frontend/resources/images/icons/auto-margin-both-sides.svg delete mode 100644 frontend/resources/images/icons/auto-margin-side.svg delete mode 100644 frontend/resources/images/icons/auto-margin.svg delete mode 100644 frontend/resources/images/icons/auto-padding-both-sides.svg delete mode 100644 frontend/resources/images/icons/auto-padding-side.svg delete mode 100644 frontend/resources/images/icons/auto-padding.svg delete mode 100644 frontend/resources/images/icons/auto-width.svg delete mode 100644 frontend/resources/images/icons/auto-wrap.svg delete mode 100644 frontend/resources/images/icons/boolean-difference.svg delete mode 100644 frontend/resources/images/icons/boolean-exclude.svg delete mode 100644 frontend/resources/images/icons/boolean-flatten.svg delete mode 100644 frontend/resources/images/icons/boolean-intersection.svg delete mode 100644 frontend/resources/images/icons/boolean-union.svg delete mode 100644 frontend/resources/images/icons/box.svg delete mode 100644 frontend/resources/images/icons/bug.svg delete mode 100644 frontend/resources/images/icons/cap-circle-marker.svg delete mode 100644 frontend/resources/images/icons/cap-diamond-marker.svg delete mode 100644 frontend/resources/images/icons/cap-line-arrow.svg delete mode 100644 frontend/resources/images/icons/cap-round.svg delete mode 100644 frontend/resources/images/icons/cap-square-marker.svg delete mode 100644 frontend/resources/images/icons/cap-square.svg delete mode 100644 frontend/resources/images/icons/cap-triangle-arrow.svg delete mode 100644 frontend/resources/images/icons/chain.svg delete mode 100644 frontend/resources/images/icons/chat.svg delete mode 100644 frontend/resources/images/icons/checkbox-checked.svg delete mode 100644 frontend/resources/images/icons/checkbox-intermediate.svg delete mode 100644 frontend/resources/images/icons/checkbox-unchecked.svg delete mode 100644 frontend/resources/images/icons/circle.svg delete mode 100644 frontend/resources/images/icons/close.svg delete mode 100644 frontend/resources/images/icons/code.svg delete mode 100644 frontend/resources/images/icons/comment.svg delete mode 100644 frontend/resources/images/icons/component-copy.svg delete mode 100644 frontend/resources/images/icons/component.svg delete mode 100644 frontend/resources/images/icons/copy.svg delete mode 100644 frontend/resources/images/icons/cross.svg delete mode 100644 frontend/resources/images/icons/curve.svg delete mode 100644 frontend/resources/images/icons/download.svg delete mode 100644 frontend/resources/images/icons/easing-ease-in-out.svg delete mode 100644 frontend/resources/images/icons/easing-ease-in.svg delete mode 100644 frontend/resources/images/icons/easing-ease-out.svg delete mode 100644 frontend/resources/images/icons/easing-ease.svg delete mode 100644 frontend/resources/images/icons/easing-linear.svg delete mode 100644 frontend/resources/images/icons/exclude.svg delete mode 100644 frontend/resources/images/icons/exit.svg delete mode 100644 frontend/resources/images/icons/export.svg delete mode 100644 frontend/resources/images/icons/eye-closed.svg delete mode 100644 frontend/resources/images/icons/eye.svg delete mode 100644 frontend/resources/images/icons/file-html.svg delete mode 100644 frontend/resources/images/icons/file-svg.svg delete mode 100644 frontend/resources/images/icons/fill.svg delete mode 100644 frontend/resources/images/icons/filter.svg delete mode 100644 frontend/resources/images/icons/folder-zip.svg delete mode 100644 frontend/resources/images/icons/folder.svg delete mode 100644 frontend/resources/images/icons/full-screen-off.svg delete mode 100644 frontend/resources/images/icons/full-screen.svg delete mode 100644 frontend/resources/images/icons/go-next.svg delete mode 100644 frontend/resources/images/icons/go-prev.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-column-around.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-column-between.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-column-center.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-column-end.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-column-start.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-row-around.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-row-between.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-row-center.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-row-end.svg delete mode 100644 frontend/resources/images/icons/grid-justify-content-row-start.svg delete mode 100644 frontend/resources/images/icons/grid-layout-mode.svg delete mode 100644 frontend/resources/images/icons/grid-snap.svg delete mode 100644 frontend/resources/images/icons/grid.svg delete mode 100644 frontend/resources/images/icons/help.svg delete mode 100644 frontend/resources/images/icons/icon-empty.svg delete mode 100644 frontend/resources/images/icons/icon-key.svg delete mode 100644 frontend/resources/images/icons/icon-list.svg delete mode 100644 frontend/resources/images/icons/icon-lock.svg delete mode 100644 frontend/resources/images/icons/icon-set.svg delete mode 100644 frontend/resources/images/icons/image.svg delete mode 100644 frontend/resources/images/icons/import.svg delete mode 100644 frontend/resources/images/icons/infocard.svg delete mode 100644 frontend/resources/images/icons/interaction.svg delete mode 100644 frontend/resources/images/icons/justify-content-column-around.svg delete mode 100644 frontend/resources/images/icons/justify-content-column-between.svg delete mode 100644 frontend/resources/images/icons/justify-content-column-center.svg delete mode 100644 frontend/resources/images/icons/justify-content-column-end.svg delete mode 100644 frontend/resources/images/icons/justify-content-column-evenly.svg delete mode 100644 frontend/resources/images/icons/justify-content-column-start.svg delete mode 100644 frontend/resources/images/icons/justify-content-row-around.svg delete mode 100644 frontend/resources/images/icons/justify-content-row-between.svg delete mode 100644 frontend/resources/images/icons/justify-content-row-center.svg delete mode 100644 frontend/resources/images/icons/justify-content-row-end.svg delete mode 100644 frontend/resources/images/icons/justify-content-row-evenly.svg delete mode 100644 frontend/resources/images/icons/justify-content-row-start.svg delete mode 100644 frontend/resources/images/icons/layers.svg delete mode 100644 frontend/resources/images/icons/layout-columns.svg delete mode 100644 frontend/resources/images/icons/layout-rows.svg delete mode 100644 frontend/resources/images/icons/letter-spacing.svg delete mode 100644 frontend/resources/images/icons/libraries.svg delete mode 100644 frontend/resources/images/icons/library.svg delete mode 100644 frontend/resources/images/icons/line-height.svg delete mode 100644 frontend/resources/images/icons/line.svg delete mode 100644 frontend/resources/images/icons/listing-enum.svg delete mode 100644 frontend/resources/images/icons/listing-thumbs.svg delete mode 100644 frontend/resources/images/icons/lock.svg delete mode 100644 frontend/resources/images/icons/logout.svg delete mode 100644 frontend/resources/images/icons/lowercase.svg delete mode 100644 frontend/resources/images/icons/mail.svg delete mode 100644 frontend/resources/images/icons/mask.svg delete mode 100644 frontend/resources/images/icons/minus.svg delete mode 100644 frontend/resources/images/icons/msg-error.svg delete mode 100644 frontend/resources/images/icons/msg-info.svg delete mode 100644 frontend/resources/images/icons/msg-success.svg delete mode 100644 frontend/resources/images/icons/msg-warning.svg delete mode 100644 frontend/resources/images/icons/navigate.svg delete mode 100644 frontend/resources/images/icons/nodes-add.svg delete mode 100644 frontend/resources/images/icons/nodes-corner.svg delete mode 100644 frontend/resources/images/icons/nodes-curve.svg delete mode 100644 frontend/resources/images/icons/nodes-join.svg delete mode 100644 frontend/resources/images/icons/nodes-merge.svg delete mode 100644 frontend/resources/images/icons/nodes-remove.svg delete mode 100644 frontend/resources/images/icons/nodes-separate.svg delete mode 100644 frontend/resources/images/icons/nodes-snap.svg delete mode 100644 frontend/resources/images/icons/organize.svg delete mode 100644 frontend/resources/images/icons/palette.svg delete mode 100644 frontend/resources/images/icons/pen.svg delete mode 100644 frontend/resources/images/icons/pencil.svg delete mode 100644 frontend/resources/images/icons/picker-harmony.svg delete mode 100644 frontend/resources/images/icons/picker-hsv.svg delete mode 100644 frontend/resources/images/icons/picker-ramp.svg delete mode 100644 frontend/resources/images/icons/picker.svg delete mode 100644 frontend/resources/images/icons/pin-fill.svg delete mode 100644 frontend/resources/images/icons/pin.svg delete mode 100644 frontend/resources/images/icons/play.svg delete mode 100644 frontend/resources/images/icons/plus.svg delete mode 100644 frontend/resources/images/icons/pointer-inner.svg delete mode 100644 frontend/resources/images/icons/position-absolute.svg delete mode 100644 frontend/resources/images/icons/position-bottom-center.svg delete mode 100644 frontend/resources/images/icons/position-bottom-left.svg delete mode 100644 frontend/resources/images/icons/position-bottom-right.svg delete mode 100644 frontend/resources/images/icons/position-center.svg delete mode 100644 frontend/resources/images/icons/position-top-center.svg delete mode 100644 frontend/resources/images/icons/position-top-left.svg delete mode 100644 frontend/resources/images/icons/position-top-right.svg delete mode 100644 frontend/resources/images/icons/puzzle.svg delete mode 100644 frontend/resources/images/icons/radius-1.svg delete mode 100644 frontend/resources/images/icons/radius-4.svg delete mode 100644 frontend/resources/images/icons/radius.svg delete mode 100644 frontend/resources/images/icons/recent.svg delete mode 100644 frontend/resources/images/icons/redo.svg delete mode 100644 frontend/resources/images/icons/reset.svg delete mode 100644 frontend/resources/images/icons/rotate.svg delete mode 100644 frontend/resources/images/icons/ruler-tool.svg delete mode 100644 frontend/resources/images/icons/ruler.svg delete mode 100644 frontend/resources/images/icons/search.svg delete mode 100644 frontend/resources/images/icons/set-thumbnail.svg delete mode 100644 frontend/resources/images/icons/shape-halign-center.svg delete mode 100644 frontend/resources/images/icons/shape-halign-left.svg delete mode 100644 frontend/resources/images/icons/shape-halign-right.svg delete mode 100644 frontend/resources/images/icons/shape-hdistribute.svg delete mode 100644 frontend/resources/images/icons/shape-valign-bottom.svg delete mode 100644 frontend/resources/images/icons/shape-valign-center.svg delete mode 100644 frontend/resources/images/icons/shape-valign-top.svg delete mode 100644 frontend/resources/images/icons/shape-vdistribute.svg delete mode 100644 frontend/resources/images/icons/shortcut.svg delete mode 100644 frontend/resources/images/icons/size-horiz.svg delete mode 100644 frontend/resources/images/icons/size-vert.svg delete mode 100644 frontend/resources/images/icons/sort-ascending.svg delete mode 100644 frontend/resources/images/icons/sort-descending.svg delete mode 100644 frontend/resources/images/icons/space-around.svg delete mode 100644 frontend/resources/images/icons/space-between.svg delete mode 100644 frontend/resources/images/icons/strikethrough.svg delete mode 100644 frontend/resources/images/icons/stroke.svg delete mode 100644 frontend/resources/images/icons/switch.svg delete mode 100644 frontend/resources/images/icons/text-LTR-refactor.svg delete mode 100644 frontend/resources/images/icons/text-RTL-refactor.svg delete mode 100644 frontend/resources/images/icons/text-align-center.svg delete mode 100644 frontend/resources/images/icons/text-align-justify.svg delete mode 100644 frontend/resources/images/icons/text-align-left.svg delete mode 100644 frontend/resources/images/icons/text-align-right.svg delete mode 100644 frontend/resources/images/icons/text-direction-ltr.svg delete mode 100644 frontend/resources/images/icons/text-direction-rtl.svg delete mode 100644 frontend/resources/images/icons/text.svg delete mode 100644 frontend/resources/images/icons/tick.svg delete mode 100644 frontend/resources/images/icons/titlecase.svg delete mode 100644 frontend/resources/images/icons/toggle.svg delete mode 100644 frontend/resources/images/icons/trash.svg delete mode 100644 frontend/resources/images/icons/tree.svg delete mode 100644 frontend/resources/images/icons/underline.svg delete mode 100644 frontend/resources/images/icons/undo.svg delete mode 100644 frontend/resources/images/icons/ungroup.svg delete mode 100644 frontend/resources/images/icons/unlock.svg delete mode 100644 frontend/resources/images/icons/uppercase.svg delete mode 100644 frontend/resources/images/icons/user.svg delete mode 100644 frontend/src/app/main/ui/components/context_menu.cljs diff --git a/frontend/resources/images/icons/absolute-refactor.svg b/frontend/resources/images/icons/absolute.svg similarity index 100% rename from frontend/resources/images/icons/absolute-refactor.svg rename to frontend/resources/images/icons/absolute.svg diff --git a/frontend/resources/images/icons/action-mark.svg b/frontend/resources/images/icons/action-mark.svg deleted file mode 100644 index 7c5ca1f0d..000000000 --- a/frontend/resources/images/icons/action-mark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/action.svg b/frontend/resources/images/icons/action.svg deleted file mode 100644 index 8f0e0da96..000000000 --- a/frontend/resources/images/icons/action.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/actions.svg b/frontend/resources/images/icons/actions.svg deleted file mode 100644 index 30eedf85b..000000000 --- a/frontend/resources/images/icons/actions.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/add-refactor.svg b/frontend/resources/images/icons/add.svg similarity index 100% rename from frontend/resources/images/icons/add-refactor.svg rename to frontend/resources/images/icons/add.svg diff --git a/frontend/resources/images/icons/align-bottom-refactor.svg b/frontend/resources/images/icons/align-bottom-refactor.svg deleted file mode 100644 index add9efe67..000000000 --- a/frontend/resources/images/icons/align-bottom-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-bottom.svg b/frontend/resources/images/icons/align-bottom.svg index 79e156fd8..add9efe67 100644 --- a/frontend/resources/images/icons/align-bottom.svg +++ b/frontend/resources/images/icons/align-bottom.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-around-refactor.svg b/frontend/resources/images/icons/align-content-column-around-refactor.svg deleted file mode 100644 index a10b0133f..000000000 --- a/frontend/resources/images/icons/align-content-column-around-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-around.svg b/frontend/resources/images/icons/align-content-column-around.svg index d7f54514a..a10b0133f 100644 --- a/frontend/resources/images/icons/align-content-column-around.svg +++ b/frontend/resources/images/icons/align-content-column-around.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-between-refactor.svg b/frontend/resources/images/icons/align-content-column-between-refactor.svg deleted file mode 100644 index f3a70b757..000000000 --- a/frontend/resources/images/icons/align-content-column-between-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-between.svg b/frontend/resources/images/icons/align-content-column-between.svg index f07dbe1db..f3a70b757 100644 --- a/frontend/resources/images/icons/align-content-column-between.svg +++ b/frontend/resources/images/icons/align-content-column-between.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-center-refactor.svg b/frontend/resources/images/icons/align-content-column-center-refactor.svg deleted file mode 100644 index 04737fd9d..000000000 --- a/frontend/resources/images/icons/align-content-column-center-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-center.svg b/frontend/resources/images/icons/align-content-column-center.svg index 56317ce06..04737fd9d 100644 --- a/frontend/resources/images/icons/align-content-column-center.svg +++ b/frontend/resources/images/icons/align-content-column-center.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-end-refactor.svg b/frontend/resources/images/icons/align-content-column-end-refactor.svg deleted file mode 100644 index bec340dc7..000000000 --- a/frontend/resources/images/icons/align-content-column-end-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-end.svg b/frontend/resources/images/icons/align-content-column-end.svg index eab99cd62..bec340dc7 100644 --- a/frontend/resources/images/icons/align-content-column-end.svg +++ b/frontend/resources/images/icons/align-content-column-end.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-evenly-refactor.svg b/frontend/resources/images/icons/align-content-column-evenly-refactor.svg deleted file mode 100644 index f9f0cdd13..000000000 --- a/frontend/resources/images/icons/align-content-column-evenly-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-evenly.svg b/frontend/resources/images/icons/align-content-column-evenly.svg index bb613bc72..f9f0cdd13 100644 --- a/frontend/resources/images/icons/align-content-column-evenly.svg +++ b/frontend/resources/images/icons/align-content-column-evenly.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-start-refactor.svg b/frontend/resources/images/icons/align-content-column-start-refactor.svg deleted file mode 100644 index c85b3f48f..000000000 --- a/frontend/resources/images/icons/align-content-column-start-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-start.svg b/frontend/resources/images/icons/align-content-column-start.svg index d3490501f..c85b3f48f 100644 --- a/frontend/resources/images/icons/align-content-column-start.svg +++ b/frontend/resources/images/icons/align-content-column-start.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-column-stretch-refactor.svg b/frontend/resources/images/icons/align-content-column-stretch.svg similarity index 100% rename from frontend/resources/images/icons/align-content-column-stretch-refactor.svg rename to frontend/resources/images/icons/align-content-column-stretch.svg diff --git a/frontend/resources/images/icons/align-content-row-around-refactor.svg b/frontend/resources/images/icons/align-content-row-around-refactor.svg deleted file mode 100644 index 41537d8a9..000000000 --- a/frontend/resources/images/icons/align-content-row-around-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-around.svg b/frontend/resources/images/icons/align-content-row-around.svg index f49bb584f..41537d8a9 100644 --- a/frontend/resources/images/icons/align-content-row-around.svg +++ b/frontend/resources/images/icons/align-content-row-around.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-between-refactor.svg b/frontend/resources/images/icons/align-content-row-between-refactor.svg deleted file mode 100644 index b8e1ad1f5..000000000 --- a/frontend/resources/images/icons/align-content-row-between-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-between.svg b/frontend/resources/images/icons/align-content-row-between.svg index 6723db3d9..b8e1ad1f5 100644 --- a/frontend/resources/images/icons/align-content-row-between.svg +++ b/frontend/resources/images/icons/align-content-row-between.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-center-refactor.svg b/frontend/resources/images/icons/align-content-row-center-refactor.svg deleted file mode 100644 index 87775ca90..000000000 --- a/frontend/resources/images/icons/align-content-row-center-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-center.svg b/frontend/resources/images/icons/align-content-row-center.svg index b318cd9d2..87775ca90 100644 --- a/frontend/resources/images/icons/align-content-row-center.svg +++ b/frontend/resources/images/icons/align-content-row-center.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-end-refactor.svg b/frontend/resources/images/icons/align-content-row-end-refactor.svg deleted file mode 100644 index b31b629eb..000000000 --- a/frontend/resources/images/icons/align-content-row-end-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-end.svg b/frontend/resources/images/icons/align-content-row-end.svg index 56aecaae9..b31b629eb 100644 --- a/frontend/resources/images/icons/align-content-row-end.svg +++ b/frontend/resources/images/icons/align-content-row-end.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-evenly-refactor.svg b/frontend/resources/images/icons/align-content-row-evenly-refactor.svg deleted file mode 100644 index 2607631c6..000000000 --- a/frontend/resources/images/icons/align-content-row-evenly-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-evenly.svg b/frontend/resources/images/icons/align-content-row-evenly.svg index fd67e71e7..2607631c6 100644 --- a/frontend/resources/images/icons/align-content-row-evenly.svg +++ b/frontend/resources/images/icons/align-content-row-evenly.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-start-refactor.svg b/frontend/resources/images/icons/align-content-row-start-refactor.svg deleted file mode 100644 index e20658500..000000000 --- a/frontend/resources/images/icons/align-content-row-start-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-start.svg b/frontend/resources/images/icons/align-content-row-start.svg index d666646cf..e20658500 100644 --- a/frontend/resources/images/icons/align-content-row-start.svg +++ b/frontend/resources/images/icons/align-content-row-start.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-content-row-stretch-refactor.svg b/frontend/resources/images/icons/align-content-row-stretch.svg similarity index 100% rename from frontend/resources/images/icons/align-content-row-stretch-refactor.svg rename to frontend/resources/images/icons/align-content-row-stretch.svg diff --git a/frontend/resources/images/icons/align-horizontal-center-refactor.svg b/frontend/resources/images/icons/align-horizontal-center.svg similarity index 100% rename from frontend/resources/images/icons/align-horizontal-center-refactor.svg rename to frontend/resources/images/icons/align-horizontal-center.svg diff --git a/frontend/resources/images/icons/align-items-column-baseline.svg b/frontend/resources/images/icons/align-items-column-baseline.svg deleted file mode 100644 index 862f7afd1..000000000 --- a/frontend/resources/images/icons/align-items-column-baseline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-column-center-refactor.svg b/frontend/resources/images/icons/align-items-column-center-refactor.svg deleted file mode 100644 index 6685e5b1d..000000000 --- a/frontend/resources/images/icons/align-items-column-center-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/align-items-column-center.svg b/frontend/resources/images/icons/align-items-column-center.svg index e35973436..6685e5b1d 100644 --- a/frontend/resources/images/icons/align-items-column-center.svg +++ b/frontend/resources/images/icons/align-items-column-center.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/images/icons/align-items-column-end.svg b/frontend/resources/images/icons/align-items-column-end.svg deleted file mode 100644 index 7bdb1d632..000000000 --- a/frontend/resources/images/icons/align-items-column-end.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-column-start.svg b/frontend/resources/images/icons/align-items-column-start.svg deleted file mode 100644 index 5c231d486..000000000 --- a/frontend/resources/images/icons/align-items-column-start.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-column-strech.svg b/frontend/resources/images/icons/align-items-column-strech.svg deleted file mode 100644 index dd441d93f..000000000 --- a/frontend/resources/images/icons/align-items-column-strech.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-row-baseline.svg b/frontend/resources/images/icons/align-items-row-baseline.svg deleted file mode 100644 index b8b397e0a..000000000 --- a/frontend/resources/images/icons/align-items-row-baseline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-row-center.svg b/frontend/resources/images/icons/align-items-row-center.svg deleted file mode 100644 index a07e43a47..000000000 --- a/frontend/resources/images/icons/align-items-row-center.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-row-end.svg b/frontend/resources/images/icons/align-items-row-end.svg deleted file mode 100644 index ddeb660a1..000000000 --- a/frontend/resources/images/icons/align-items-row-end.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-row-start.svg b/frontend/resources/images/icons/align-items-row-start.svg deleted file mode 100644 index 69516fc68..000000000 --- a/frontend/resources/images/icons/align-items-row-start.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-items-row-strech.svg b/frontend/resources/images/icons/align-items-row-strech.svg deleted file mode 100644 index 22b308e14..000000000 --- a/frontend/resources/images/icons/align-items-row-strech.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-middle.svg b/frontend/resources/images/icons/align-middle.svg deleted file mode 100644 index 60a538eb3..000000000 --- a/frontend/resources/images/icons/align-middle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-column-baseline.svg b/frontend/resources/images/icons/align-self-column-baseline.svg deleted file mode 100644 index 4ed4d6357..000000000 --- a/frontend/resources/images/icons/align-self-column-baseline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-column-bottom.svg b/frontend/resources/images/icons/align-self-column-bottom.svg deleted file mode 100644 index 6ef7f1e75..000000000 --- a/frontend/resources/images/icons/align-self-column-bottom.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-column-center.svg b/frontend/resources/images/icons/align-self-column-center.svg deleted file mode 100644 index c45bfb53f..000000000 --- a/frontend/resources/images/icons/align-self-column-center.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-column-strech.svg b/frontend/resources/images/icons/align-self-column-strech.svg deleted file mode 100644 index 5803cb447..000000000 --- a/frontend/resources/images/icons/align-self-column-strech.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-column-top.svg b/frontend/resources/images/icons/align-self-column-top.svg deleted file mode 100644 index 67adbc722..000000000 --- a/frontend/resources/images/icons/align-self-column-top.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-row-baseline.svg b/frontend/resources/images/icons/align-self-row-baseline.svg deleted file mode 100644 index db2660684..000000000 --- a/frontend/resources/images/icons/align-self-row-baseline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-row-center.svg b/frontend/resources/images/icons/align-self-row-center.svg deleted file mode 100644 index df911a89c..000000000 --- a/frontend/resources/images/icons/align-self-row-center.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-row-left.svg b/frontend/resources/images/icons/align-self-row-left.svg deleted file mode 100644 index 7ff6caee1..000000000 --- a/frontend/resources/images/icons/align-self-row-left.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-row-right.svg b/frontend/resources/images/icons/align-self-row-right.svg deleted file mode 100644 index 665e7b562..000000000 --- a/frontend/resources/images/icons/align-self-row-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-self-row-strech.svg b/frontend/resources/images/icons/align-self-row-strech.svg deleted file mode 100644 index 426db52b5..000000000 --- a/frontend/resources/images/icons/align-self-row-strech.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/align-top.svg b/frontend/resources/images/icons/align-top.svg deleted file mode 100644 index 4e95be8d3..000000000 --- a/frontend/resources/images/icons/align-top.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/alignment.svg b/frontend/resources/images/icons/alignment.svg deleted file mode 100644 index 65db1eb38..000000000 --- a/frontend/resources/images/icons/alignment.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/animate-down.svg b/frontend/resources/images/icons/animate-down.svg deleted file mode 100644 index 6eb7a3501..000000000 --- a/frontend/resources/images/icons/animate-down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/animate-left.svg b/frontend/resources/images/icons/animate-left.svg deleted file mode 100644 index 39318e4cc..000000000 --- a/frontend/resources/images/icons/animate-left.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/animate-right.svg b/frontend/resources/images/icons/animate-right.svg deleted file mode 100644 index aadf5a05b..000000000 --- a/frontend/resources/images/icons/animate-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/animate-up.svg b/frontend/resources/images/icons/animate-up.svg deleted file mode 100644 index 31e877423..000000000 --- a/frontend/resources/images/icons/animate-up.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/arrow-down.svg b/frontend/resources/images/icons/arrow-down.svg deleted file mode 100644 index 9402aff96..000000000 --- a/frontend/resources/images/icons/arrow-down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/arrow-end.svg b/frontend/resources/images/icons/arrow-end.svg deleted file mode 100644 index a025ca2c5..000000000 --- a/frontend/resources/images/icons/arrow-end.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/arrow-slide.svg b/frontend/resources/images/icons/arrow-slide.svg deleted file mode 100644 index 754e3e97f..000000000 --- a/frontend/resources/images/icons/arrow-slide.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/arrow-up.svg b/frontend/resources/images/icons/arrow-up.svg deleted file mode 100644 index 63c47d9c8..000000000 --- a/frontend/resources/images/icons/arrow-up.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/artboard.svg b/frontend/resources/images/icons/artboard.svg deleted file mode 100644 index 87f4543a3..000000000 --- a/frontend/resources/images/icons/artboard.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/at.svg b/frontend/resources/images/icons/at.svg deleted file mode 100644 index c9bb6aada..000000000 --- a/frontend/resources/images/icons/at.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-direction.svg b/frontend/resources/images/icons/auto-direction.svg deleted file mode 100644 index 3429588fe..000000000 --- a/frontend/resources/images/icons/auto-direction.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-fill.svg b/frontend/resources/images/icons/auto-fill.svg deleted file mode 100644 index 344e188d7..000000000 --- a/frontend/resources/images/icons/auto-fill.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-fix-layout.svg b/frontend/resources/images/icons/auto-fix-layout.svg deleted file mode 100644 index f2be41986..000000000 --- a/frontend/resources/images/icons/auto-fix-layout.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-fix.svg b/frontend/resources/images/icons/auto-fix.svg deleted file mode 100644 index f2be41986..000000000 --- a/frontend/resources/images/icons/auto-fix.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-gap.svg b/frontend/resources/images/icons/auto-gap.svg deleted file mode 100644 index 25593da80..000000000 --- a/frontend/resources/images/icons/auto-gap.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-height.svg b/frontend/resources/images/icons/auto-height.svg deleted file mode 100644 index 963dda6d3..000000000 --- a/frontend/resources/images/icons/auto-height.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-hug.svg b/frontend/resources/images/icons/auto-hug.svg deleted file mode 100644 index f72fbd3c8..000000000 --- a/frontend/resources/images/icons/auto-hug.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-margin-both-sides.svg b/frontend/resources/images/icons/auto-margin-both-sides.svg deleted file mode 100644 index 841f73206..000000000 --- a/frontend/resources/images/icons/auto-margin-both-sides.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-margin-side.svg b/frontend/resources/images/icons/auto-margin-side.svg deleted file mode 100644 index 087ae8250..000000000 --- a/frontend/resources/images/icons/auto-margin-side.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-margin.svg b/frontend/resources/images/icons/auto-margin.svg deleted file mode 100644 index 4777ce3b1..000000000 --- a/frontend/resources/images/icons/auto-margin.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-padding-both-sides.svg b/frontend/resources/images/icons/auto-padding-both-sides.svg deleted file mode 100644 index a9702f96d..000000000 --- a/frontend/resources/images/icons/auto-padding-both-sides.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-padding-side.svg b/frontend/resources/images/icons/auto-padding-side.svg deleted file mode 100644 index d4c56746b..000000000 --- a/frontend/resources/images/icons/auto-padding-side.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-padding.svg b/frontend/resources/images/icons/auto-padding.svg deleted file mode 100644 index e546d0631..000000000 --- a/frontend/resources/images/icons/auto-padding.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-width.svg b/frontend/resources/images/icons/auto-width.svg deleted file mode 100644 index c88a331e3..000000000 --- a/frontend/resources/images/icons/auto-width.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/auto-wrap.svg b/frontend/resources/images/icons/auto-wrap.svg deleted file mode 100644 index 08a7a19a0..000000000 --- a/frontend/resources/images/icons/auto-wrap.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/boolean-difference.svg b/frontend/resources/images/icons/boolean-difference.svg deleted file mode 100644 index 4d5c7f6a8..000000000 --- a/frontend/resources/images/icons/boolean-difference.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/boolean-exclude.svg b/frontend/resources/images/icons/boolean-exclude.svg deleted file mode 100644 index 6a3865703..000000000 --- a/frontend/resources/images/icons/boolean-exclude.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/boolean-flatten.svg b/frontend/resources/images/icons/boolean-flatten.svg deleted file mode 100644 index f7816f8b5..000000000 --- a/frontend/resources/images/icons/boolean-flatten.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/boolean-intersection.svg b/frontend/resources/images/icons/boolean-intersection.svg deleted file mode 100644 index 3480e6366..000000000 --- a/frontend/resources/images/icons/boolean-intersection.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/boolean-union.svg b/frontend/resources/images/icons/boolean-union.svg deleted file mode 100644 index fdeb117b7..000000000 --- a/frontend/resources/images/icons/boolean-union.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/box.svg b/frontend/resources/images/icons/box.svg deleted file mode 100644 index d8ef1bffe..000000000 --- a/frontend/resources/images/icons/box.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/bug.svg b/frontend/resources/images/icons/bug.svg deleted file mode 100644 index 2904d3122..000000000 --- a/frontend/resources/images/icons/bug.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-circle-marker.svg b/frontend/resources/images/icons/cap-circle-marker.svg deleted file mode 100644 index 3068ad7b7..000000000 --- a/frontend/resources/images/icons/cap-circle-marker.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-diamond-marker.svg b/frontend/resources/images/icons/cap-diamond-marker.svg deleted file mode 100644 index 0391c0ffe..000000000 --- a/frontend/resources/images/icons/cap-diamond-marker.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-line-arrow.svg b/frontend/resources/images/icons/cap-line-arrow.svg deleted file mode 100644 index c24e84233..000000000 --- a/frontend/resources/images/icons/cap-line-arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-round.svg b/frontend/resources/images/icons/cap-round.svg deleted file mode 100644 index c717c13b9..000000000 --- a/frontend/resources/images/icons/cap-round.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-square-marker.svg b/frontend/resources/images/icons/cap-square-marker.svg deleted file mode 100644 index 00407fd37..000000000 --- a/frontend/resources/images/icons/cap-square-marker.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-square.svg b/frontend/resources/images/icons/cap-square.svg deleted file mode 100644 index 24ad4f43f..000000000 --- a/frontend/resources/images/icons/cap-square.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cap-triangle-arrow.svg b/frontend/resources/images/icons/cap-triangle-arrow.svg deleted file mode 100644 index 6d6f15978..000000000 --- a/frontend/resources/images/icons/cap-triangle-arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/chain.svg b/frontend/resources/images/icons/chain.svg deleted file mode 100644 index 661d8db6b..000000000 --- a/frontend/resources/images/icons/chain.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/chat.svg b/frontend/resources/images/icons/chat.svg deleted file mode 100644 index 5890c6960..000000000 --- a/frontend/resources/images/icons/chat.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/checkbox-checked.svg b/frontend/resources/images/icons/checkbox-checked.svg deleted file mode 100644 index 21d24f176..000000000 --- a/frontend/resources/images/icons/checkbox-checked.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/checkbox-intermediate.svg b/frontend/resources/images/icons/checkbox-intermediate.svg deleted file mode 100644 index 26502626c..000000000 --- a/frontend/resources/images/icons/checkbox-intermediate.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/checkbox-unchecked.svg b/frontend/resources/images/icons/checkbox-unchecked.svg deleted file mode 100644 index 68f7d0d11..000000000 --- a/frontend/resources/images/icons/checkbox-unchecked.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/circle.svg b/frontend/resources/images/icons/circle.svg deleted file mode 100644 index d9fcda7de..000000000 --- a/frontend/resources/images/icons/circle.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/close.svg b/frontend/resources/images/icons/close.svg deleted file mode 100644 index ec01cddba..000000000 --- a/frontend/resources/images/icons/close.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/code.svg b/frontend/resources/images/icons/code.svg deleted file mode 100644 index 3c80441e3..000000000 --- a/frontend/resources/images/icons/code.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/comment.svg b/frontend/resources/images/icons/comment.svg deleted file mode 100644 index f6c098e08..000000000 --- a/frontend/resources/images/icons/comment.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/resources/images/icons/component-copy.svg b/frontend/resources/images/icons/component-copy.svg deleted file mode 100644 index 658e0554d..000000000 --- a/frontend/resources/images/icons/component-copy.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/component.svg b/frontend/resources/images/icons/component.svg deleted file mode 100644 index b89a10c8d..000000000 --- a/frontend/resources/images/icons/component.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/copy.svg b/frontend/resources/images/icons/copy.svg deleted file mode 100644 index d676e2227..000000000 --- a/frontend/resources/images/icons/copy.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/cross.svg b/frontend/resources/images/icons/cross.svg deleted file mode 100644 index aa1472308..000000000 --- a/frontend/resources/images/icons/cross.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/curve.svg b/frontend/resources/images/icons/curve.svg deleted file mode 100644 index c6f046e9a..000000000 --- a/frontend/resources/images/icons/curve.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/download.svg b/frontend/resources/images/icons/download.svg deleted file mode 100644 index 1f78adb6c..000000000 --- a/frontend/resources/images/icons/download.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/easing-ease-in-out.svg b/frontend/resources/images/icons/easing-ease-in-out.svg deleted file mode 100644 index 3ada98e19..000000000 --- a/frontend/resources/images/icons/easing-ease-in-out.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/easing-ease-in.svg b/frontend/resources/images/icons/easing-ease-in.svg deleted file mode 100644 index 40d2bbd24..000000000 --- a/frontend/resources/images/icons/easing-ease-in.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/easing-ease-out.svg b/frontend/resources/images/icons/easing-ease-out.svg deleted file mode 100644 index 9bf6cd73f..000000000 --- a/frontend/resources/images/icons/easing-ease-out.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/easing-ease.svg b/frontend/resources/images/icons/easing-ease.svg deleted file mode 100644 index 7760f329d..000000000 --- a/frontend/resources/images/icons/easing-ease.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/easing-linear.svg b/frontend/resources/images/icons/easing-linear.svg deleted file mode 100644 index f3ab49784..000000000 --- a/frontend/resources/images/icons/easing-linear.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/exclude.svg b/frontend/resources/images/icons/exclude.svg deleted file mode 100644 index 843d6c0d0..000000000 --- a/frontend/resources/images/icons/exclude.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/exit.svg b/frontend/resources/images/icons/exit.svg deleted file mode 100644 index ce145a385..000000000 --- a/frontend/resources/images/icons/exit.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/export.svg b/frontend/resources/images/icons/export.svg deleted file mode 100644 index b645d17b1..000000000 --- a/frontend/resources/images/icons/export.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/eye-closed.svg b/frontend/resources/images/icons/eye-closed.svg deleted file mode 100644 index 6e48d6735..000000000 --- a/frontend/resources/images/icons/eye-closed.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/eye.svg b/frontend/resources/images/icons/eye.svg deleted file mode 100644 index 86edd73b0..000000000 --- a/frontend/resources/images/icons/eye.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/file-html.svg b/frontend/resources/images/icons/file-html.svg deleted file mode 100644 index 91a9e6c42..000000000 --- a/frontend/resources/images/icons/file-html.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/file-svg.svg b/frontend/resources/images/icons/file-svg.svg deleted file mode 100644 index 33e5830de..000000000 --- a/frontend/resources/images/icons/file-svg.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/fill.svg b/frontend/resources/images/icons/fill.svg deleted file mode 100644 index a509069cc..000000000 --- a/frontend/resources/images/icons/fill.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/filter.svg b/frontend/resources/images/icons/filter.svg deleted file mode 100644 index 0ca8a5ab8..000000000 --- a/frontend/resources/images/icons/filter.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/folder-zip.svg b/frontend/resources/images/icons/folder-zip.svg deleted file mode 100644 index a07dbcb80..000000000 --- a/frontend/resources/images/icons/folder-zip.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/folder.svg b/frontend/resources/images/icons/folder.svg deleted file mode 100644 index cd7c2a4ec..000000000 --- a/frontend/resources/images/icons/folder.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/full-screen-off.svg b/frontend/resources/images/icons/full-screen-off.svg deleted file mode 100644 index 47e7db42c..000000000 --- a/frontend/resources/images/icons/full-screen-off.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/full-screen.svg b/frontend/resources/images/icons/full-screen.svg deleted file mode 100644 index 252357a17..000000000 --- a/frontend/resources/images/icons/full-screen.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/go-next.svg b/frontend/resources/images/icons/go-next.svg deleted file mode 100644 index ed48fbcde..000000000 --- a/frontend/resources/images/icons/go-next.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/go-prev.svg b/frontend/resources/images/icons/go-prev.svg deleted file mode 100644 index 6737a43ab..000000000 --- a/frontend/resources/images/icons/go-prev.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/grid-justify-content-column-around.svg b/frontend/resources/images/icons/grid-justify-content-column-around.svg deleted file mode 100644 index 65cd17d58..000000000 --- a/frontend/resources/images/icons/grid-justify-content-column-around.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-column-between.svg b/frontend/resources/images/icons/grid-justify-content-column-between.svg deleted file mode 100644 index 783d91a21..000000000 --- a/frontend/resources/images/icons/grid-justify-content-column-between.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-column-center.svg b/frontend/resources/images/icons/grid-justify-content-column-center.svg deleted file mode 100644 index fc52ce5ed..000000000 --- a/frontend/resources/images/icons/grid-justify-content-column-center.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-column-end.svg b/frontend/resources/images/icons/grid-justify-content-column-end.svg deleted file mode 100644 index 18825a412..000000000 --- a/frontend/resources/images/icons/grid-justify-content-column-end.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-column-start.svg b/frontend/resources/images/icons/grid-justify-content-column-start.svg deleted file mode 100644 index 823ef4ebf..000000000 --- a/frontend/resources/images/icons/grid-justify-content-column-start.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-row-around.svg b/frontend/resources/images/icons/grid-justify-content-row-around.svg deleted file mode 100644 index 41a980b7f..000000000 --- a/frontend/resources/images/icons/grid-justify-content-row-around.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-row-between.svg b/frontend/resources/images/icons/grid-justify-content-row-between.svg deleted file mode 100644 index bfc38460a..000000000 --- a/frontend/resources/images/icons/grid-justify-content-row-between.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-row-center.svg b/frontend/resources/images/icons/grid-justify-content-row-center.svg deleted file mode 100644 index 402b8dba2..000000000 --- a/frontend/resources/images/icons/grid-justify-content-row-center.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-row-end.svg b/frontend/resources/images/icons/grid-justify-content-row-end.svg deleted file mode 100644 index 3515d5a95..000000000 --- a/frontend/resources/images/icons/grid-justify-content-row-end.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-justify-content-row-start.svg b/frontend/resources/images/icons/grid-justify-content-row-start.svg deleted file mode 100644 index 6539a9314..000000000 --- a/frontend/resources/images/icons/grid-justify-content-row-start.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/grid-layout-mode.svg b/frontend/resources/images/icons/grid-layout-mode.svg deleted file mode 100644 index c90cf5c85..000000000 --- a/frontend/resources/images/icons/grid-layout-mode.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/grid-snap.svg b/frontend/resources/images/icons/grid-snap.svg deleted file mode 100644 index 2f03be05a..000000000 --- a/frontend/resources/images/icons/grid-snap.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/grid.svg b/frontend/resources/images/icons/grid.svg deleted file mode 100644 index be57664c1..000000000 --- a/frontend/resources/images/icons/grid.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/help.svg b/frontend/resources/images/icons/help.svg deleted file mode 100644 index b1cb21827..000000000 --- a/frontend/resources/images/icons/help.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/resources/images/icons/icon-empty.svg b/frontend/resources/images/icons/icon-empty.svg deleted file mode 100644 index b3988c12b..000000000 --- a/frontend/resources/images/icons/icon-empty.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/icon-key.svg b/frontend/resources/images/icons/icon-key.svg deleted file mode 100644 index 01f6a28de..000000000 --- a/frontend/resources/images/icons/icon-key.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/icon-list.svg b/frontend/resources/images/icons/icon-list.svg deleted file mode 100644 index eb47d32f2..000000000 --- a/frontend/resources/images/icons/icon-list.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/icon-lock.svg b/frontend/resources/images/icons/icon-lock.svg deleted file mode 100644 index 8cb8aa6f7..000000000 --- a/frontend/resources/images/icons/icon-lock.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/icon-set.svg b/frontend/resources/images/icons/icon-set.svg deleted file mode 100644 index cb246d458..000000000 --- a/frontend/resources/images/icons/icon-set.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/image.svg b/frontend/resources/images/icons/image.svg deleted file mode 100644 index 1d3f13f09..000000000 --- a/frontend/resources/images/icons/image.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/import.svg b/frontend/resources/images/icons/import.svg deleted file mode 100644 index 4e0914b05..000000000 --- a/frontend/resources/images/icons/import.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/infocard.svg b/frontend/resources/images/icons/infocard.svg deleted file mode 100644 index 8fd6ec40d..000000000 --- a/frontend/resources/images/icons/infocard.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/interaction.svg b/frontend/resources/images/icons/interaction.svg deleted file mode 100644 index d95baa8be..000000000 --- a/frontend/resources/images/icons/interaction.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-column-around.svg b/frontend/resources/images/icons/justify-content-column-around.svg deleted file mode 100644 index 19fbfcc57..000000000 --- a/frontend/resources/images/icons/justify-content-column-around.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-column-between.svg b/frontend/resources/images/icons/justify-content-column-between.svg deleted file mode 100644 index 6e1bb1297..000000000 --- a/frontend/resources/images/icons/justify-content-column-between.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-column-center.svg b/frontend/resources/images/icons/justify-content-column-center.svg deleted file mode 100644 index f4c774653..000000000 --- a/frontend/resources/images/icons/justify-content-column-center.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-column-end.svg b/frontend/resources/images/icons/justify-content-column-end.svg deleted file mode 100644 index 9ac317727..000000000 --- a/frontend/resources/images/icons/justify-content-column-end.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-column-evenly.svg b/frontend/resources/images/icons/justify-content-column-evenly.svg deleted file mode 100644 index 22708241a..000000000 --- a/frontend/resources/images/icons/justify-content-column-evenly.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-column-start.svg b/frontend/resources/images/icons/justify-content-column-start.svg deleted file mode 100644 index f73b2c754..000000000 --- a/frontend/resources/images/icons/justify-content-column-start.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-row-around.svg b/frontend/resources/images/icons/justify-content-row-around.svg deleted file mode 100644 index ff52e7857..000000000 --- a/frontend/resources/images/icons/justify-content-row-around.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-row-between.svg b/frontend/resources/images/icons/justify-content-row-between.svg deleted file mode 100644 index 57cba5490..000000000 --- a/frontend/resources/images/icons/justify-content-row-between.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-row-center.svg b/frontend/resources/images/icons/justify-content-row-center.svg deleted file mode 100644 index 2a7e32c75..000000000 --- a/frontend/resources/images/icons/justify-content-row-center.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-row-end.svg b/frontend/resources/images/icons/justify-content-row-end.svg deleted file mode 100644 index 1b3a33d48..000000000 --- a/frontend/resources/images/icons/justify-content-row-end.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-row-evenly.svg b/frontend/resources/images/icons/justify-content-row-evenly.svg deleted file mode 100644 index 7d5add80e..000000000 --- a/frontend/resources/images/icons/justify-content-row-evenly.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/justify-content-row-start.svg b/frontend/resources/images/icons/justify-content-row-start.svg deleted file mode 100644 index 7ba66c756..000000000 --- a/frontend/resources/images/icons/justify-content-row-start.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/layers.svg b/frontend/resources/images/icons/layers.svg deleted file mode 100644 index 703fd0cbe..000000000 --- a/frontend/resources/images/icons/layers.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/layout-columns.svg b/frontend/resources/images/icons/layout-columns.svg deleted file mode 100644 index eb4b7ba55..000000000 --- a/frontend/resources/images/icons/layout-columns.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/layout-rows.svg b/frontend/resources/images/icons/layout-rows.svg deleted file mode 100644 index 9023c8fcf..000000000 --- a/frontend/resources/images/icons/layout-rows.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/letter-spacing.svg b/frontend/resources/images/icons/letter-spacing.svg deleted file mode 100644 index 6098501c7..000000000 --- a/frontend/resources/images/icons/letter-spacing.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/libraries.svg b/frontend/resources/images/icons/libraries.svg deleted file mode 100644 index 3e4e98b75..000000000 --- a/frontend/resources/images/icons/libraries.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/library.svg b/frontend/resources/images/icons/library.svg deleted file mode 100644 index c4be0d41f..000000000 --- a/frontend/resources/images/icons/library.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/line-height.svg b/frontend/resources/images/icons/line-height.svg deleted file mode 100644 index ee08402cc..000000000 --- a/frontend/resources/images/icons/line-height.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/line.svg b/frontend/resources/images/icons/line.svg deleted file mode 100644 index 35ce08de7..000000000 --- a/frontend/resources/images/icons/line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/listing-enum.svg b/frontend/resources/images/icons/listing-enum.svg deleted file mode 100644 index d979e5010..000000000 --- a/frontend/resources/images/icons/listing-enum.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/listing-thumbs.svg b/frontend/resources/images/icons/listing-thumbs.svg deleted file mode 100644 index ac5d98e47..000000000 --- a/frontend/resources/images/icons/listing-thumbs.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/lock.svg b/frontend/resources/images/icons/lock.svg deleted file mode 100644 index 6477336ae..000000000 --- a/frontend/resources/images/icons/lock.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/logout.svg b/frontend/resources/images/icons/logout.svg deleted file mode 100644 index b5ae8c421..000000000 --- a/frontend/resources/images/icons/logout.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/lowercase.svg b/frontend/resources/images/icons/lowercase.svg deleted file mode 100644 index 9741dae12..000000000 --- a/frontend/resources/images/icons/lowercase.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/mail.svg b/frontend/resources/images/icons/mail.svg deleted file mode 100644 index 0d03f891d..000000000 --- a/frontend/resources/images/icons/mail.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/mask.svg b/frontend/resources/images/icons/mask.svg deleted file mode 100644 index 3c2e31534..000000000 --- a/frontend/resources/images/icons/mask.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/minus.svg b/frontend/resources/images/icons/minus.svg deleted file mode 100644 index d79c63c51..000000000 --- a/frontend/resources/images/icons/minus.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/msg-error.svg b/frontend/resources/images/icons/msg-error.svg deleted file mode 100644 index 44ef863ce..000000000 --- a/frontend/resources/images/icons/msg-error.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/msg-info.svg b/frontend/resources/images/icons/msg-info.svg deleted file mode 100644 index 8c04184cc..000000000 --- a/frontend/resources/images/icons/msg-info.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/msg-success.svg b/frontend/resources/images/icons/msg-success.svg deleted file mode 100644 index 584811b18..000000000 --- a/frontend/resources/images/icons/msg-success.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/msg-warning.svg b/frontend/resources/images/icons/msg-warning.svg deleted file mode 100644 index a2e327a0e..000000000 --- a/frontend/resources/images/icons/msg-warning.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/navigate.svg b/frontend/resources/images/icons/navigate.svg deleted file mode 100644 index 1b13012e4..000000000 --- a/frontend/resources/images/icons/navigate.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-add.svg b/frontend/resources/images/icons/nodes-add.svg deleted file mode 100644 index 9c5ecf93a..000000000 --- a/frontend/resources/images/icons/nodes-add.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-corner.svg b/frontend/resources/images/icons/nodes-corner.svg deleted file mode 100644 index 295e316ab..000000000 --- a/frontend/resources/images/icons/nodes-corner.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-curve.svg b/frontend/resources/images/icons/nodes-curve.svg deleted file mode 100644 index b12913fc5..000000000 --- a/frontend/resources/images/icons/nodes-curve.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-join.svg b/frontend/resources/images/icons/nodes-join.svg deleted file mode 100644 index 551451cb9..000000000 --- a/frontend/resources/images/icons/nodes-join.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-merge.svg b/frontend/resources/images/icons/nodes-merge.svg deleted file mode 100644 index 5e0d9c336..000000000 --- a/frontend/resources/images/icons/nodes-merge.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-remove.svg b/frontend/resources/images/icons/nodes-remove.svg deleted file mode 100644 index e00ecd534..000000000 --- a/frontend/resources/images/icons/nodes-remove.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-separate.svg b/frontend/resources/images/icons/nodes-separate.svg deleted file mode 100644 index 4e188e3cb..000000000 --- a/frontend/resources/images/icons/nodes-separate.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/nodes-snap.svg b/frontend/resources/images/icons/nodes-snap.svg deleted file mode 100644 index 1bd5edac4..000000000 --- a/frontend/resources/images/icons/nodes-snap.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/organize.svg b/frontend/resources/images/icons/organize.svg deleted file mode 100644 index 5368b0249..000000000 --- a/frontend/resources/images/icons/organize.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/palette.svg b/frontend/resources/images/icons/palette.svg deleted file mode 100644 index 4984a76b1..000000000 --- a/frontend/resources/images/icons/palette.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/pen.svg b/frontend/resources/images/icons/pen.svg deleted file mode 100644 index cc3c91147..000000000 --- a/frontend/resources/images/icons/pen.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/pencil.svg b/frontend/resources/images/icons/pencil.svg deleted file mode 100644 index 8382b124f..000000000 --- a/frontend/resources/images/icons/pencil.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/resources/images/icons/picker-harmony.svg b/frontend/resources/images/icons/picker-harmony.svg deleted file mode 100644 index 1f8de0d5c..000000000 --- a/frontend/resources/images/icons/picker-harmony.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/picker-hsv.svg b/frontend/resources/images/icons/picker-hsv.svg deleted file mode 100644 index 2218c82a1..000000000 --- a/frontend/resources/images/icons/picker-hsv.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/picker-ramp.svg b/frontend/resources/images/icons/picker-ramp.svg deleted file mode 100644 index 815b3a944..000000000 --- a/frontend/resources/images/icons/picker-ramp.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/picker.svg b/frontend/resources/images/icons/picker.svg deleted file mode 100644 index 99c8edc76..000000000 --- a/frontend/resources/images/icons/picker.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/pin-fill.svg b/frontend/resources/images/icons/pin-fill.svg deleted file mode 100644 index 1e11c8c45..000000000 --- a/frontend/resources/images/icons/pin-fill.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/pin.svg b/frontend/resources/images/icons/pin.svg deleted file mode 100644 index 46d71436a..000000000 --- a/frontend/resources/images/icons/pin.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/play.svg b/frontend/resources/images/icons/play.svg deleted file mode 100644 index 5a9880b73..000000000 --- a/frontend/resources/images/icons/play.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/plus.svg b/frontend/resources/images/icons/plus.svg deleted file mode 100644 index 8368e0234..000000000 --- a/frontend/resources/images/icons/plus.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/pointer-inner.svg b/frontend/resources/images/icons/pointer-inner.svg deleted file mode 100644 index 50798578b..000000000 --- a/frontend/resources/images/icons/pointer-inner.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/position-absolute.svg b/frontend/resources/images/icons/position-absolute.svg deleted file mode 100644 index 067d77864..000000000 --- a/frontend/resources/images/icons/position-absolute.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/position-bottom-center.svg b/frontend/resources/images/icons/position-bottom-center.svg deleted file mode 100644 index 002466ead..000000000 --- a/frontend/resources/images/icons/position-bottom-center.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/position-bottom-left.svg b/frontend/resources/images/icons/position-bottom-left.svg deleted file mode 100644 index 4811b74a9..000000000 --- a/frontend/resources/images/icons/position-bottom-left.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/position-bottom-right.svg b/frontend/resources/images/icons/position-bottom-right.svg deleted file mode 100644 index ebf861dcf..000000000 --- a/frontend/resources/images/icons/position-bottom-right.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/position-center.svg b/frontend/resources/images/icons/position-center.svg deleted file mode 100644 index ce6695ba7..000000000 --- a/frontend/resources/images/icons/position-center.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/position-top-center.svg b/frontend/resources/images/icons/position-top-center.svg deleted file mode 100644 index 5a971d427..000000000 --- a/frontend/resources/images/icons/position-top-center.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/position-top-left.svg b/frontend/resources/images/icons/position-top-left.svg deleted file mode 100644 index 0285e444e..000000000 --- a/frontend/resources/images/icons/position-top-left.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/resources/images/icons/position-top-right.svg b/frontend/resources/images/icons/position-top-right.svg deleted file mode 100644 index 838f63602..000000000 --- a/frontend/resources/images/icons/position-top-right.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/resources/images/icons/puzzle.svg b/frontend/resources/images/icons/puzzle.svg deleted file mode 100644 index 495b38a11..000000000 --- a/frontend/resources/images/icons/puzzle.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/radius-1.svg b/frontend/resources/images/icons/radius-1.svg deleted file mode 100644 index f1ca422cf..000000000 --- a/frontend/resources/images/icons/radius-1.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/radius-4.svg b/frontend/resources/images/icons/radius-4.svg deleted file mode 100644 index 121940d51..000000000 --- a/frontend/resources/images/icons/radius-4.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/radius.svg b/frontend/resources/images/icons/radius.svg deleted file mode 100644 index 4777b58fd..000000000 --- a/frontend/resources/images/icons/radius.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/recent.svg b/frontend/resources/images/icons/recent.svg deleted file mode 100644 index 696757240..000000000 --- a/frontend/resources/images/icons/recent.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/redo.svg b/frontend/resources/images/icons/redo.svg deleted file mode 100644 index 2c1488b4f..000000000 --- a/frontend/resources/images/icons/redo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/reset.svg b/frontend/resources/images/icons/reset.svg deleted file mode 100644 index 59dd005ea..000000000 --- a/frontend/resources/images/icons/reset.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/rotate.svg b/frontend/resources/images/icons/rotate.svg deleted file mode 100644 index 5c7edbc20..000000000 --- a/frontend/resources/images/icons/rotate.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/ruler-tool.svg b/frontend/resources/images/icons/ruler-tool.svg deleted file mode 100644 index 0d18c21a5..000000000 --- a/frontend/resources/images/icons/ruler-tool.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/ruler.svg b/frontend/resources/images/icons/ruler.svg deleted file mode 100644 index d520e3e84..000000000 --- a/frontend/resources/images/icons/ruler.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/search.svg b/frontend/resources/images/icons/search.svg deleted file mode 100644 index 777105ceb..000000000 --- a/frontend/resources/images/icons/search.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/set-thumbnail.svg b/frontend/resources/images/icons/set-thumbnail.svg deleted file mode 100644 index e82fa55b1..000000000 --- a/frontend/resources/images/icons/set-thumbnail.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/shape-halign-center.svg b/frontend/resources/images/icons/shape-halign-center.svg deleted file mode 100644 index b861539f2..000000000 --- a/frontend/resources/images/icons/shape-halign-center.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-halign-left.svg b/frontend/resources/images/icons/shape-halign-left.svg deleted file mode 100644 index ded065048..000000000 --- a/frontend/resources/images/icons/shape-halign-left.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-halign-right.svg b/frontend/resources/images/icons/shape-halign-right.svg deleted file mode 100644 index fc1ed648f..000000000 --- a/frontend/resources/images/icons/shape-halign-right.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-hdistribute.svg b/frontend/resources/images/icons/shape-hdistribute.svg deleted file mode 100644 index 8e250a0a6..000000000 --- a/frontend/resources/images/icons/shape-hdistribute.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-valign-bottom.svg b/frontend/resources/images/icons/shape-valign-bottom.svg deleted file mode 100644 index 7b0911188..000000000 --- a/frontend/resources/images/icons/shape-valign-bottom.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-valign-center.svg b/frontend/resources/images/icons/shape-valign-center.svg deleted file mode 100644 index 0c6dae309..000000000 --- a/frontend/resources/images/icons/shape-valign-center.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-valign-top.svg b/frontend/resources/images/icons/shape-valign-top.svg deleted file mode 100644 index 2f091c9c3..000000000 --- a/frontend/resources/images/icons/shape-valign-top.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shape-vdistribute.svg b/frontend/resources/images/icons/shape-vdistribute.svg deleted file mode 100644 index f7271ede1..000000000 --- a/frontend/resources/images/icons/shape-vdistribute.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/shortcut.svg b/frontend/resources/images/icons/shortcut.svg deleted file mode 100644 index a5545e77e..000000000 --- a/frontend/resources/images/icons/shortcut.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/frontend/resources/images/icons/size-horiz.svg b/frontend/resources/images/icons/size-horiz.svg deleted file mode 100644 index ab9456580..000000000 --- a/frontend/resources/images/icons/size-horiz.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/size-vert.svg b/frontend/resources/images/icons/size-vert.svg deleted file mode 100644 index f2e807c40..000000000 --- a/frontend/resources/images/icons/size-vert.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/sort-ascending.svg b/frontend/resources/images/icons/sort-ascending.svg deleted file mode 100644 index 48ed056f4..000000000 --- a/frontend/resources/images/icons/sort-ascending.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/sort-descending.svg b/frontend/resources/images/icons/sort-descending.svg deleted file mode 100644 index 3a5838b95..000000000 --- a/frontend/resources/images/icons/sort-descending.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/space-around.svg b/frontend/resources/images/icons/space-around.svg deleted file mode 100644 index 94e6e8de4..000000000 --- a/frontend/resources/images/icons/space-around.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/space-between.svg b/frontend/resources/images/icons/space-between.svg deleted file mode 100644 index 639040b0b..000000000 --- a/frontend/resources/images/icons/space-between.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/strikethrough.svg b/frontend/resources/images/icons/strikethrough.svg deleted file mode 100644 index bbec524b4..000000000 --- a/frontend/resources/images/icons/strikethrough.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/stroke.svg b/frontend/resources/images/icons/stroke.svg deleted file mode 100644 index fd82b03f7..000000000 --- a/frontend/resources/images/icons/stroke.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/switch.svg b/frontend/resources/images/icons/switch.svg deleted file mode 100644 index d6bf0ab85..000000000 --- a/frontend/resources/images/icons/switch.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/resources/images/icons/text-LTR-refactor.svg b/frontend/resources/images/icons/text-LTR-refactor.svg deleted file mode 100644 index 8acf7188b..000000000 --- a/frontend/resources/images/icons/text-LTR-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/text-RTL-refactor.svg b/frontend/resources/images/icons/text-RTL-refactor.svg deleted file mode 100644 index 217b18c12..000000000 --- a/frontend/resources/images/icons/text-RTL-refactor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/text-align-center.svg b/frontend/resources/images/icons/text-align-center.svg deleted file mode 100644 index 304412d42..000000000 --- a/frontend/resources/images/icons/text-align-center.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/text-align-justify.svg b/frontend/resources/images/icons/text-align-justify.svg deleted file mode 100644 index acf125ade..000000000 --- a/frontend/resources/images/icons/text-align-justify.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/text-align-left.svg b/frontend/resources/images/icons/text-align-left.svg deleted file mode 100644 index 20f7e7caa..000000000 --- a/frontend/resources/images/icons/text-align-left.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/text-align-right.svg b/frontend/resources/images/icons/text-align-right.svg deleted file mode 100644 index 40dc9024d..000000000 --- a/frontend/resources/images/icons/text-align-right.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/resources/images/icons/text-direction-ltr.svg b/frontend/resources/images/icons/text-direction-ltr.svg deleted file mode 100644 index ec3a3c282..000000000 --- a/frontend/resources/images/icons/text-direction-ltr.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/text-direction-rtl.svg b/frontend/resources/images/icons/text-direction-rtl.svg deleted file mode 100644 index db287b350..000000000 --- a/frontend/resources/images/icons/text-direction-rtl.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/text.svg b/frontend/resources/images/icons/text.svg deleted file mode 100644 index aa17f967f..000000000 --- a/frontend/resources/images/icons/text.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/tick.svg b/frontend/resources/images/icons/tick.svg deleted file mode 100644 index 93e3f520b..000000000 --- a/frontend/resources/images/icons/tick.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/titlecase.svg b/frontend/resources/images/icons/titlecase.svg deleted file mode 100644 index 473b6c8cb..000000000 --- a/frontend/resources/images/icons/titlecase.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/toggle.svg b/frontend/resources/images/icons/toggle.svg deleted file mode 100644 index 732c7042c..000000000 --- a/frontend/resources/images/icons/toggle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/trash.svg b/frontend/resources/images/icons/trash.svg deleted file mode 100644 index a5d92bf57..000000000 --- a/frontend/resources/images/icons/trash.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/tree.svg b/frontend/resources/images/icons/tree.svg deleted file mode 100644 index ddfffe3e7..000000000 --- a/frontend/resources/images/icons/tree.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/underline.svg b/frontend/resources/images/icons/underline.svg deleted file mode 100644 index 3e35ddc93..000000000 --- a/frontend/resources/images/icons/underline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/undo.svg b/frontend/resources/images/icons/undo.svg deleted file mode 100644 index 9394fa24a..000000000 --- a/frontend/resources/images/icons/undo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/ungroup.svg b/frontend/resources/images/icons/ungroup.svg deleted file mode 100644 index 5afc3a40e..000000000 --- a/frontend/resources/images/icons/ungroup.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/unlock.svg b/frontend/resources/images/icons/unlock.svg deleted file mode 100644 index b9c1ffa83..000000000 --- a/frontend/resources/images/icons/unlock.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/uppercase.svg b/frontend/resources/images/icons/uppercase.svg deleted file mode 100644 index 3c681ac75..000000000 --- a/frontend/resources/images/icons/uppercase.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/user.svg b/frontend/resources/images/icons/user.svg deleted file mode 100644 index 228a69876..000000000 --- a/frontend/resources/images/icons/user.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index d00e466c7..7603e8e17 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -117,7 +117,7 @@ [:? {} (if (:token query-params) [:> static/error-container {} - [:div.image i/unchain] + [:div.image i/detach-refactor] [:div.main-message (tr "viewer.breaking-change.message")] [:div.desc-message (tr "viewer.breaking-change.description")]] diff --git a/frontend/src/app/main/ui/components/context_menu.cljs b/frontend/src/app/main/ui/components/context_menu.cljs deleted file mode 100644 index 4bf05203e..000000000 --- a/frontend/src/app/main/ui/components/context_menu.cljs +++ /dev/null @@ -1,131 +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.components.context-menu - (:require - [app.common.data :as d] - [app.common.data.macros :as dm] - [app.main.refs :as refs] - [app.main.ui.components.dropdown :refer [dropdown']] - [app.main.ui.icons :as i] - [app.util.dom :as dom] - [app.util.i18n :as i18n :refer [tr]] - [app.util.object :as obj] - [goog.object :as gobj] - [rumext.v2 :as mf])) - -(mf/defc context-menu - {::mf/wrap-props false} - [props] - (assert (fn? (gobj/get props "on-close")) "missing `on-close` prop") - (assert (boolean? (gobj/get props "show")) "missing `show` prop") - (assert (vector? (gobj/get props "options")) "missing `options` prop") - - (let [open? (gobj/get props "show") - on-close (gobj/get props "on-close") - options (gobj/get props "options") - is-selectable (gobj/get props "selectable") - selected (gobj/get props "selected") - top (gobj/get props "top" 0) - left (gobj/get props "left" 0) - fixed? (gobj/get props "fixed?" false) - min-width? (gobj/get props "min-width?" false) - route (mf/deref refs/route) - in-dashboard? (= :dashboard-projects (:name (:data route))) - - local (mf/use-state {:offset-y 0 - :offset-x 0 - :levels nil}) - - on-local-close - (mf/use-callback - (fn [] - (swap! local assoc :levels [{:parent-option nil - :options options}]) - (on-close))) - - check-menu-offscreen - (mf/use-callback - (mf/deps top (:offset-y @local) left (:offset-x @local)) - (fn [node] - (when (some? node) - (let [bounding_rect (dom/get-bounding-rect node) - window_size (dom/get-window-size) - {node-height :height node-width :width} bounding_rect - {window-height :height window-width :width} window_size - target-offset-y (if (> (+ top node-height) window-height) - (- node-height) - 0) - target-offset-x (if (> (+ left node-width) window-width) - (- node-width) - 0)] - - (when (or (not= target-offset-y (:offset-y @local)) (not= target-offset-x (:offset-x @local))) - (swap! local assoc :offset-y target-offset-y :offset-x target-offset-x)))))) - - enter-submenu - (mf/use-callback - (mf/deps options) - (fn [option-name sub-options] - (fn [event] - (dom/stop-propagation event) - (swap! local update :levels - conj {:parent-option option-name - :options sub-options})))) - - exit-submenu - (mf/use-callback - (fn [event] - (dom/stop-propagation event) - (swap! local update :levels pop))) - - props (obj/merge props #js {:on-close on-local-close})] - - (mf/use-effect - (mf/deps options) - #(swap! local assoc :levels [{:parent-option nil - :options options}])) - - (when (and open? (some? (:levels @local))) - [:> dropdown' props - [:div.context-menu {:class (dom/classnames :is-open open? - :fixed fixed? - :is-selectable is-selectable) - :style {:top (+ top (:offset-y @local)) - :left (+ left (:offset-x @local))}} - (let [level (-> @local :levels peek)] - [:ul.context-menu-items {:class (dom/classnames :min-width min-width?) - :ref check-menu-offscreen} - (when-let [parent-option (:parent-option level)] - [:* - [:li.context-menu-item - [:a.context-menu-action.submenu-back - {:data-no-close true - :on-click exit-submenu} - [:span i/arrow-slide] - parent-option]] - [:li.separator]]) - (for [[index [option-name option-handler sub-options data-test]] (d/enumerate (:options level))] - (when option-name - (if (= option-name :separator) - [:li.separator {:key (dm/str "context-item-" index)}] - [:li.context-menu-item - {:class (dom/classnames :is-selected (and selected (= option-name selected))) - :key (dm/str "context-item-" index)} - (if-not sub-options - [:a.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)] - [: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]])])))])]]))) diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index 2d079a778..c4a9302bf 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -270,7 +270,7 @@ :icon-fill ready?)} (cond loading? i/loader-pencil ready? i/logo-icon - import-warn? i/msg-warning + import-warn? i/msg-warning-refactor import-error? i/close-refactor import-finish? i/tick-refactor analyze-error? i/close-refactor)] diff --git a/frontend/src/app/main/ui/dashboard/search.cljs b/frontend/src/app/main/ui/dashboard/search.cljs index 3b4d09099..614555020 100644 --- a/frontend/src/app/main/ui/dashboard/search.cljs +++ b/frontend/src/app/main/ui/dashboard/search.cljs @@ -46,17 +46,17 @@ (cond (empty? search-term) [:div {:class (stl/css :grid-empty-placeholder :search)} - [:div {:class (stl/css :icon)} i/search] + [:div {:class (stl/css :icon)} i/search-refactor] [: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 :icon)} i/search-refactor] [: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 :icon)} i/search-refactor] [:div {:class (stl/css :text)} (tr "dashboard.no-matches-for" search-term)]] :else diff --git a/frontend/src/app/main/ui/dashboard/search.scss b/frontend/src/app/main/ui/dashboard/search.scss index 0922089ad..7c20671c2 100644 --- a/frontend/src/app/main/ui/dashboard/search.scss +++ b/frontend/src/app/main/ui/dashboard/search.scss @@ -42,7 +42,7 @@ color: $df-primary; } .icon svg { - fill: $df-secondary; + stroke: $df-secondary; width: $s-32; height: $s-32; } diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index 198a03515..11c8d520b 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -13,287 +13,44 @@ [rumext.v2 :as mf])) ;; Keep the list of icons sorted - -(def ^:icon action (icon-xref :action)) -(def ^:icon actions (icon-xref :actions)) -(def ^:icon align-bottom (icon-xref :align-bottom)) -(def ^:icon align-content-column-around (icon-xref :align-content-column-around)) -(def ^:icon align-content-column-evenly (icon-xref :align-content-column-evenly)) -(def ^:icon align-content-column-between (icon-xref :align-content-column-between)) -(def ^:icon align-content-column-center (icon-xref :align-content-column-center)) -(def ^:icon align-content-column-end (icon-xref :align-content-column-end)) -(def ^:icon align-content-column-start (icon-xref :align-content-column-start)) -(def ^:icon align-content-row-around (icon-xref :align-content-row-around)) -(def ^:icon align-content-row-evenly (icon-xref :align-content-row-evenly)) -(def ^:icon align-content-row-between (icon-xref :align-content-row-between)) -(def ^:icon align-content-row-center (icon-xref :align-content-row-center)) -(def ^:icon align-content-row-end (icon-xref :align-content-row-end)) -(def ^:icon align-content-row-start (icon-xref :align-content-row-start)) -(def ^:icon align-items-column-baseline (icon-xref :align-items-column-baseline)) -(def ^:icon align-items-column-center (icon-xref :align-items-column-center)) -(def ^:icon align-items-column-end (icon-xref :align-items-column-end)) -(def ^:icon align-items-column-start (icon-xref :align-items-column-start)) -(def ^:icon align-items-column-strech (icon-xref :align-items-column-strech)) -(def ^:icon align-items-row-baseline (icon-xref :align-items-row-baseline)) -(def ^:icon align-items-row-center (icon-xref :align-items-row-center)) -(def ^:icon align-items-row-end (icon-xref :align-items-row-end)) -(def ^:icon align-items-row-start (icon-xref :align-items-row-start)) -(def ^:icon align-items-row-strech (icon-xref :align-items-row-strech)) -(def ^:icon align-self-column-baseline (icon-xref :align-self-column-baseline)) -(def ^:icon align-self-column-center (icon-xref :align-self-column-center)) -(def ^:icon align-self-column-top (icon-xref :align-self-column-top)) -(def ^:icon align-self-column-bottom (icon-xref :align-self-column-bottom)) -(def ^:icon align-self-column-strech (icon-xref :align-self-column-strech)) -(def ^:icon align-self-row-baseline (icon-xref :align-self-row-baseline)) -(def ^:icon align-self-row-center (icon-xref :align-self-row-center)) -(def ^:icon align-self-row-left (icon-xref :align-self-row-left)) -(def ^:icon align-self-row-right (icon-xref :align-self-row-right)) -(def ^:icon align-self-row-strech (icon-xref :align-self-row-strech)) -(def ^:icon align-middle (icon-xref :align-middle)) -(def ^:icon align-top (icon-xref :align-top)) -(def ^:icon alignment (icon-xref :alignment)) -(def ^:icon animate-down (icon-xref :animate-down)) -(def ^:icon animate-left (icon-xref :animate-left)) -(def ^:icon animate-right (icon-xref :animate-right)) -(def ^:icon animate-up (icon-xref :animate-up)) -(def ^:icon arrow-down (icon-xref :arrow-down)) -(def ^:icon arrow-end (icon-xref :arrow-end)) -(def ^:icon arrow-slide (icon-xref :arrow-slide)) -(def ^:icon arrow-up (icon-xref :arrow-up)) -(def ^:icon artboard (icon-xref :artboard)) -(def ^:icon at (icon-xref :at)) -(def ^:icon auto-direction (icon-xref :auto-direction)) -(def ^:icon auto-fill (icon-xref :auto-fill)) -(def ^:icon auto-fix (icon-xref :auto-fix)) -(def ^:icon auto-fix-layout (icon-xref :auto-fix-layout)) -(def ^:icon auto-gap (icon-xref :auto-gap)) -(def ^:icon auto-height (icon-xref :auto-height)) -(def ^:icon auto-hug (icon-xref :auto-hug)) -(def ^:icon auto-margin-side (icon-xref :auto-margin-side)) -(def ^:icon auto-margin-both-sides (icon-xref :auto-margin-both-sides)) -(def ^:icon auto-margin (icon-xref :auto-margin)) -(def ^:icon auto-padding (icon-xref :auto-padding)) -(def ^:icon auto-padding-side (icon-xref :auto-padding-side)) -(def ^:icon auto-padding-both-sides (icon-xref :auto-padding-both-sides)) -(def ^:icon auto-width (icon-xref :auto-width)) -(def ^:icon auto-wrap (icon-xref :auto-wrap)) -(def ^:icon bool-difference (icon-xref :boolean-difference)) -(def ^:icon bool-exclude (icon-xref :boolean-exclude)) -(def ^:icon bool-flatten (icon-xref :boolean-flatten)) -(def ^:icon bool-intersection (icon-xref :boolean-intersection)) -(def ^:icon bool-union (icon-xref :boolean-union)) -(def ^:icon box (icon-xref :box)) -(def ^:icon bug (icon-xref :bug)) -(def ^:icon chain (icon-xref :chain)) -(def ^:icon chat (icon-xref :chat)) -(def ^:icon checkbox-checked (icon-xref :checkbox-checked)) -(def ^:icon checkbox-unchecked (icon-xref :checkbox-unchecked)) -(def ^:icon checkbox-intermediate (icon-xref :checkbox-intermediate)) -(def ^:icon circle (icon-xref :circle)) -(def ^:icon close (icon-xref :close)) -(def ^:icon code (icon-xref :code)) -(def ^:icon component (icon-xref :component)) -(def ^:icon component-copy (icon-xref :component-copy)) -(def ^:icon copy (icon-xref :copy)) -(def ^:icon curve (icon-xref :curve)) -(def ^:icon cross (icon-xref :cross)) -(def ^:icon download (icon-xref :download)) -(def ^:icon easing-linear (icon-xref :easing-linear)) -(def ^:icon easing-ease (icon-xref :easing-ease)) -(def ^:icon easing-ease-in (icon-xref :easing-ease-in)) -(def ^:icon easing-ease-out (icon-xref :easing-ease-out)) -(def ^:icon easing-ease-in-out (icon-xref :easing-ease-in-out)) -(def ^:icon exclude (icon-xref :exclude)) -(def ^:icon exit (icon-xref :exit)) -(def ^:icon export (icon-xref :export)) -(def ^:icon eye (icon-xref :eye)) -(def ^:icon eye-closed (icon-xref :eye-closed)) -(def ^:icon file-html (icon-xref :file-html)) -(def ^:icon file-svg (icon-xref :file-svg)) -(def ^:icon fill (icon-xref :fill)) -(def ^:icon folder (icon-xref :folder)) -(def ^:icon folder-zip (icon-xref :folder-zip)) -(def ^:icon full-screen (icon-xref :full-screen)) -(def ^:icon full-screen-off (icon-xref :full-screen-off)) -(def ^:icon grid (icon-xref :grid)) -(def ^:icon grid-justify-content-column-around (icon-xref :grid-justify-content-column-around)) -(def ^:icon grid-justify-content-column-between (icon-xref :grid-justify-content-column-between)) -(def ^:icon grid-justify-content-column-center (icon-xref :grid-justify-content-column-center)) -(def ^:icon grid-justify-content-column-end (icon-xref :grid-justify-content-column-end)) -(def ^:icon grid-justify-content-column-start (icon-xref :grid-justify-content-column-start)) -(def ^:icon grid-justify-content-row-around (icon-xref :grid-justify-content-row-around)) -(def ^:icon grid-justify-content-row-between (icon-xref :grid-justify-content-row-between)) -(def ^:icon grid-justify-content-row-center (icon-xref :grid-justify-content-row-center)) -(def ^:icon grid-justify-content-row-end (icon-xref :grid-justify-content-row-end)) -(def ^:icon grid-justify-content-row-start (icon-xref :grid-justify-content-row-start)) -(def ^:icon grid-layout-mode (icon-xref :grid-layout-mode)) -(def ^:icon grid-snap (icon-xref :grid-snap)) -(def ^:icon go-next (icon-xref :go-next)) -(def ^:icon go-prev (icon-xref :go-prev)) -(def ^:icon help (icon-xref :help)) -(def ^:icon icon-empty (icon-xref :icon-empty)) -(def ^:icon icon-filter (icon-xref :filter)) -(def ^:icon icon-list (icon-xref :icon-list)) -(def ^:icon icon-lock (icon-xref :icon-lock)) -(def ^:icon icon-set (icon-xref :icon-set)) (def ^:icon icon-verify (icon-xref :icon-verify)) -(def ^:icon image (icon-xref :image)) -(def ^:icon import (icon-xref :import)) -(def ^:icon infocard (icon-xref :infocard)) -(def ^:icon interaction (icon-xref :interaction)) -(def ^:icon justify-content-column-around (icon-xref :justify-content-column-around)) -(def ^:icon justify-content-column-evenly (icon-xref :justify-content-column-evenly)) -(def ^:icon justify-content-column-between (icon-xref :justify-content-column-between)) -(def ^:icon justify-content-column-center (icon-xref :justify-content-column-center)) -(def ^:icon justify-content-column-end (icon-xref :justify-content-column-end)) -(def ^:icon justify-content-column-start (icon-xref :justify-content-column-start)) -(def ^:icon justify-content-row-around (icon-xref :justify-content-row-around)) -(def ^:icon justify-content-row-evenly (icon-xref :justify-content-row-evenly)) -(def ^:icon justify-content-row-between (icon-xref :justify-content-row-between)) -(def ^:icon justify-content-row-center (icon-xref :justify-content-row-center)) -(def ^:icon justify-content-row-end (icon-xref :justify-content-row-end)) -(def ^:icon justify-content-row-start (icon-xref :justify-content-row-start)) -(def ^:icon icon-key (icon-xref :icon-key)) -(def ^:icon layers (icon-xref :layers)) -(def ^:icon layout-columns (icon-xref :layout-columns)) -(def ^:icon layout-rows (icon-xref :layout-rows)) -(def ^:icon letter-spacing (icon-xref :letter-spacing)) -(def ^:icon libraries (icon-xref :libraries)) -(def ^:icon library (icon-xref :library)) -(def ^:icon line (icon-xref :line)) -(def ^:icon line-height (icon-xref :line-height)) -(def ^:icon listing-enum (icon-xref :listing-enum)) -(def ^:icon listing-thumbs (icon-xref :listing-thumbs)) (def ^:icon loader (icon-xref :loader)) -(def ^:icon lock (icon-xref :lock)) (def ^:icon logo (icon-xref :penpot-logo)) (def ^:icon logo-icon (icon-xref :penpot-logo-icon)) (def ^:icon logo-error-screen (icon-xref :logo-error-screen)) -(def ^:icon logout (icon-xref :logout)) (def ^:icon login-illustration (icon-xref :login-illustration)) -(def ^:icon lowercase (icon-xref :lowercase)) -(def ^:icon mail (icon-xref :mail)) -(def ^:icon mask (icon-xref :mask)) -(def ^:icon minus (icon-xref :minus)) -(def ^:icon move (icon-xref :move)) -(def ^:icon msg-error (icon-xref :msg-error)) -(def ^:icon msg-info (icon-xref :msg-info)) -(def ^:icon msg-success (icon-xref :msg-success)) -(def ^:icon msg-warning (icon-xref :msg-warning)) -(def ^:icon navigate (icon-xref :navigate)) -(def ^:icon nodes-add (icon-xref :nodes-add)) -(def ^:icon nodes-corner (icon-xref :nodes-corner)) -(def ^:icon nodes-curve (icon-xref :nodes-curve)) -(def ^:icon nodes-join (icon-xref :nodes-join)) -(def ^:icon nodes-merge (icon-xref :nodes-merge)) -(def ^:icon nodes-remove (icon-xref :nodes-remove)) -(def ^:icon nodes-separate (icon-xref :nodes-separate)) -(def ^:icon nodes-snap (icon-xref :nodes-snap)) -(def ^:icon organize (icon-xref :organize)) -(def ^:icon palette (icon-xref :palette)) -(def ^:icon pen (icon-xref :pen)) -(def ^:icon pencil (icon-xref :pencil)) -(def ^:icon picker (icon-xref :picker)) -(def ^:icon picker-harmony (icon-xref :picker-harmony)) -(def ^:icon picker-hsv (icon-xref :picker-hsv)) -(def ^:icon picker-ramp (icon-xref :picker-ramp)) -(def ^:icon pin (icon-xref :pin)) -(def ^:icon pin-fill (icon-xref :pin-fill)) -(def ^:icon play (icon-xref :play)) -(def ^:icon plus (icon-xref :plus)) -(def ^:icon pointer-inner (icon-xref :pointer-inner)) -(def ^:icon position-absolute (icon-xref :position-absolute)) -(def ^:icon position-bottom-center (icon-xref :position-bottom-center)) -(def ^:icon position-bottom-left (icon-xref :position-bottom-left)) -(def ^:icon position-bottom-right (icon-xref :position-bottom-right)) -(def ^:icon position-center (icon-xref :position-center)) -(def ^:icon position-top-center (icon-xref :position-top-center)) -(def ^:icon position-top-left (icon-xref :position-top-left)) -(def ^:icon position-top-right (icon-xref :position-top-right)) -(def ^:icon radius (icon-xref :radius)) -(def ^:icon radius-1 (icon-xref :radius-1)) -(def ^:icon radius-4 (icon-xref :radius-4)) -(def ^:icon recent (icon-xref :recent)) -(def ^:icon redo (icon-xref :redo)) -(def ^:icon reset (icon-xref :reset)) -(def ^:icon rotate (icon-xref :rotate)) -(def ^:icon ruler (icon-xref :ruler)) -(def ^:icon ruler-tool (icon-xref :ruler-tool)) -(def ^:icon search (icon-xref :search)) -(def ^:icon set-thumbnail (icon-xref :set-thumbnail)) -(def ^:icon shape-halign-center (icon-xref :shape-halign-center)) -(def ^:icon shape-halign-left (icon-xref :shape-halign-left)) -(def ^:icon shape-halign-right (icon-xref :shape-halign-right)) -(def ^:icon shape-hdistribute (icon-xref :shape-hdistribute)) -(def ^:icon shape-valign-bottom (icon-xref :shape-valign-bottom)) -(def ^:icon shape-valign-center (icon-xref :shape-valign-center)) -(def ^:icon shape-valign-top (icon-xref :shape-valign-top)) -(def ^:icon shape-vdistribute (icon-xref :shape-vdistribute)) -(def ^:icon shortcut (icon-xref :shortcut)) -(def ^:icon size-horiz (icon-xref :size-horiz)) -(def ^:icon size-vert (icon-xref :size-vert)) -(def ^:icon sort-ascending (icon-xref :sort-ascending)) -(def ^:icon sort-descending (icon-xref :sort-descending)) -(def ^:icon space-around (icon-xref :space-around)) -(def ^:icon space-between (icon-xref :space-between)) -(def ^:icon strikethrough (icon-xref :strikethrough)) -(def ^:icon stroke (icon-xref :stroke)) -(def ^:icon switch (icon-xref :switch)) -(def ^:icon text (icon-xref :text)) -(def ^:icon text-align-center (icon-xref :text-align-center)) -(def ^:icon text-align-justify (icon-xref :text-align-justify)) -(def ^:icon text-align-left (icon-xref :text-align-left)) -(def ^:icon text-align-right (icon-xref :text-align-right)) -(def ^:icon text-direction-ltr (icon-xref :text-direction-ltr)) -(def ^:icon text-direction-rtl (icon-xref :text-direction-rtl)) -(def ^:icon tick (icon-xref :tick)) -(def ^:icon titlecase (icon-xref :titlecase)) -(def ^:icon toggle (icon-xref :toggle)) -(def ^:icon trash (icon-xref :trash)) -(def ^:icon tree (icon-xref :tree)) -(def ^:icon unchain (icon-xref :unchain)) -(def ^:icon underline (icon-xref :underline)) -(def ^:icon undo (icon-xref :undo)) -(def ^:icon ungroup (icon-xref :ungroup)) -(def ^:icon unlock (icon-xref :unlock)) -(def ^:icon uppercase (icon-xref :uppercase)) -(def ^:icon user (icon-xref :user)) (def ^:icon brand-openid (icon-xref :brand-openid)) (def ^:icon brand-github (icon-xref :brand-github)) (def ^:icon brand-gitlab (icon-xref :brand-gitlab)) (def ^:icon brand-google (icon-xref :brand-google)) -(def ^:icon add-refactor (icon-xref :add-refactor)) -(def ^:icon arrow-refactor (icon-xref :arrow-refactor)) -(def ^:icon asc-sort-refactor (icon-xref :asc-sort-refactor)) -(def ^:icon absolute-refactor (icon-xref :absolute-refactor)) -(def ^:icon align-bottom-refactor (icon-xref :align-bottom-refactor)) -(def ^:icon align-content-row-center-refactor (icon-xref :align-content-row-center-refactor)) -(def ^:icon align-content-column-around-refactor (icon-xref :align-content-column-around-refactor)) -(def ^:icon align-content-column-between-refactor (icon-xref :align-content-column-between-refactor)) -(def ^:icon align-content-column-center-refactor (icon-xref :align-content-column-center-refactor)) -(def ^:icon align-content-column-evenly-refactor (icon-xref :align-content-column-evenly-refactor)) -(def ^:icon align-content-column-start-refactor (icon-xref :align-content-column-start-refactor)) -(def ^:icon align-content-column-end-refactor (icon-xref :align-content-column-end-refactor)) -(def ^:icon align-content-column-stretch-refactor (icon-xref :align-content-column-stretch-refactor)) -(def ^:icon align-content-row-end-refactor (icon-xref :align-content-row-end-refactor)) -(def ^:icon align-content-row-around-refactor (icon-xref :align-content-row-around-refactor)) -(def ^:icon align-content-row-between-refactor (icon-xref :align-content-row-between-refactor)) -(def ^:icon align-content-row-evenly-refactor (icon-xref :align-content-row-evenly-refactor)) -(def ^:icon align-content-row-start-refactor (icon-xref :align-content-row-start-refactor)) -(def ^:icon align-content-row-stretch-refactor (icon-xref :align-content-row-stretch-refactor)) -(def ^:icon align-horizontal-center-refactor (icon-xref :align-horizontal-center-refactor)) -(def ^:icon align-vertical-center-refactor (icon-xref :align-vertical-center-refactor)) +(def ^:icon absolute-refactor (icon-xref :absolute)) +(def ^:icon add-refactor (icon-xref :add)) +(def ^:icon align-bottom-refactor (icon-xref :align-bottom)) +(def ^:icon align-content-column-around-refactor (icon-xref :align-content-column-around)) +(def ^:icon align-content-column-between-refactor (icon-xref :align-content-column-between)) +(def ^:icon align-content-column-center-refactor (icon-xref :align-content-column-center)) +(def ^:icon align-content-column-end-refactor (icon-xref :align-content-column-end)) +(def ^:icon align-content-column-evenly-refactor (icon-xref :align-content-column-evenly)) +(def ^:icon align-content-column-start-refactor (icon-xref :align-content-column-start)) +(def ^:icon align-content-column-stretch-refactor (icon-xref :align-content-column-stretch)) +(def ^:icon align-content-row-around-refactor (icon-xref :align-content-row-around)) +(def ^:icon align-content-row-between-refactor (icon-xref :align-content-row-between)) +(def ^:icon align-content-row-center-refactor (icon-xref :align-content-row-center)) +(def ^:icon align-content-row-end-refactor (icon-xref :align-content-row-end)) +(def ^:icon align-content-row-evenly-refactor (icon-xref :align-content-row-evenly)) +(def ^:icon align-content-row-start-refactor (icon-xref :align-content-row-start)) +(def ^:icon align-content-row-stretch-refactor (icon-xref :align-content-row-stretch)) +(def ^:icon align-horizontal-center-refactor (icon-xref :align-horizontal-center)) (def ^:icon align-items-row-center-refactor (icon-xref :align-items-row-center-refactor)) (def ^:icon align-items-row-end-refactor (icon-xref :align-items-row-end-refactor)) (def ^:icon align-items-row-start-refactor (icon-xref :align-items-row-start-refactor)) +(def ^:icon align-items-column-center-refactor (icon-xref :align-items-column-center)) (def ^:icon align-items-column-start-refactor (icon-xref :align-items-column-start-refactor)) (def ^:icon align-items-column-end-refactor (icon-xref :align-items-column-end-refactor)) -(def ^:icon align-items-column-center-refactor (icon-xref :align-items-column-center-refactor)) (def ^:icon align-left-refactor (icon-xref :align-left-refactor)) (def ^:icon align-right-refactor (icon-xref :align-right-refactor)) -(def ^:icon align-top-refactor (icon-xref :align-top-refactor)) (def ^:icon align-self-column-bottom-refactor (icon-xref :align-self-column-bottom-refactor)) (def ^:icon align-self-column-center-refactor (icon-xref :align-self-column-center-refactor)) (def ^:icon align-self-column-top-refactor (icon-xref :align-self-column-top-refactor)) @@ -302,6 +59,10 @@ (def ^:icon align-self-row-right-refactor (icon-xref :align-self-row-right-refactor)) (def ^:icon align-self-column-stretch-refactor (icon-xref :align-self-column-stretch-refactor)) (def ^:icon align-self-row-stretch-refactor (icon-xref :align-self-row-stretch-refactor)) +(def ^:icon align-top-refactor (icon-xref :align-top-refactor)) +(def ^:icon align-vertical-center-refactor (icon-xref :align-vertical-center-refactor)) +(def ^:icon arrow-refactor (icon-xref :arrow-refactor)) +(def ^:icon asc-sort-refactor (icon-xref :asc-sort-refactor)) (def ^:icon board-refactor (icon-xref :board-refactor)) (def ^:icon boards-thumbnail-refactor (icon-xref :boards-thumbnail-refactor)) (def ^:icon boolean-difference-refactor (icon-xref :boolean-difference-refactor)) @@ -315,37 +76,37 @@ (def ^:icon close-refactor (icon-xref :close-refactor)) (def ^:icon close-small-refactor (icon-xref :close-small-refactor)) (def ^:icon code-refactor (icon-xref :code-refactor)) -(def ^:icon component-refactor (icon-xref :component-refactor)) -(def ^:icon comments-refactor (icon-xref :comments-refactor)) -(def ^:icon copy-refactor (icon-xref :copy-refactor)) (def ^:icon column-refactor (icon-xref :column-refactor)) (def ^:icon column-reverse-refactor (icon-xref :column-reverse-refactor)) +(def ^:icon comments-refactor (icon-xref :comments-refactor)) +(def ^:icon component-refactor (icon-xref :component-refactor)) (def ^:icon constraint-horizontal-refactor (icon-xref :constraint-horizontal-refactor)) (def ^:icon constraint-vertical-refactor (icon-xref :constraint-vertical-refactor)) +(def ^:icon copy-refactor (icon-xref :copy-refactor)) (def ^:icon corner-bottom-refactor (icon-xref :corner-bottom-refactor)) (def ^:icon corner-bottomleft-refactor (icon-xref :corner-bottomleft-refactor)) (def ^:icon corner-bottomright-refactor (icon-xref :corner-bottom-refactor)) (def ^:icon corner-center-refactor (icon-xref :corner-center-refactor)) +(def ^:icon corner-radius-refactor (icon-xref :corner-radius-refactor)) (def ^:icon corner-top-refactor (icon-xref :corner-top-refactor)) (def ^:icon corner-topleft-refactor (icon-xref :corner-topleft-refactor)) (def ^:icon corner-topright-refactor (icon-xref :corner-topright-refactor)) -(def ^:icon corner-radius-refactor (icon-xref :corner-radius-refactor)) (def ^:icon curve-refactor (icon-xref :curve-refactor)) -(def ^:icon distribute-vertical-spacing-refactor (icon-xref :distribute-vertical-spacing-refactor)) -(def ^:icon distribute-horizontally-refactor (icon-xref :distribute-horizontally-refactor)) (def ^:icon delete-refactor (icon-xref :delete-refactor)) (def ^:icon delete-text-refactor (icon-xref :delete-text-refactor)) (def ^:icon desc-sort-refactor (icon-xref :desc-sort-refactor)) (def ^:icon detach-refactor (icon-xref :detach-refactor)) (def ^:icon detached-refactor (icon-xref :detached-refactor)) +(def ^:icon distribute-horizontally-refactor (icon-xref :distribute-horizontally-refactor)) +(def ^:icon distribute-vertical-spacing-refactor (icon-xref :distribute-vertical-spacing-refactor)) (def ^:icon document-refactor (icon-xref :document-refactor)) (def ^:icon download-refactor (icon-xref :download-refactor)) (def ^:icon drop-refactor (icon-xref :drop-refactor)) -(def ^:icon easing-linear-refactor (icon-xref :easing-linear-refactor)) -(def ^:icon easing-ease-refactor (icon-xref :easing-ease-refactor)) +(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out-refactor)) (def ^:icon easing-ease-in-refactor (icon-xref :easing-ease-in-refactor)) (def ^:icon easing-ease-out-refactor (icon-xref :easing-ease-out-refactor)) -(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out-refactor)) +(def ^:icon easing-ease-refactor (icon-xref :easing-ease-refactor)) +(def ^:icon easing-linear-refactor (icon-xref :easing-linear-refactor)) (def ^:icon effects-refactor (icon-xref :effects-refactor)) (def ^:icon elipse-refactor (icon-xref :elipse-refactor)) (def ^:icon exit-refactor (icon-xref :exit-refactor)) @@ -354,30 +115,33 @@ (def ^:icon fill-content-refactor (icon-xref :fill-content-refactor)) (def ^:icon filter-refactor (icon-xref :filter-refactor)) (def ^:icon fixed-width-refactor (icon-xref :fixed-width-refactor)) -(def ^:icon flex-refactor (icon-xref :flex-refactor)) -(def ^:icon flex-horizontal-refactor (icon-xref :flex-horizontal-refactor)) (def ^:icon flex-grid-refactor (icon-xref :flex-grid-refactor)) +(def ^:icon flex-horizontal-refactor (icon-xref :flex-horizontal-refactor)) +(def ^:icon flex-refactor (icon-xref :flex-refactor)) (def ^:icon flex-vertical-refactor (icon-xref :flex-vertical-refactor)) (def ^:icon flip-horizontal-refactor (icon-xref :flip-horizontal-refactor)) +(def ^:icon flip-vertical-refactor (icon-xref :flip-vertical-refactor)) +(def ^:icon gap-horizontal-refactor (icon-xref :gap-horizontal-refactor)) +(def ^:icon gap-vertical-refactor (icon-xref :gap-vertical-refactor)) (def ^:icon grid-column-refactor (icon-xref :grid-column-refactor)) (def ^:icon grid-columns-refactor (icon-xref :grid-columns-refactor)) (def ^:icon grid-gutter-refactor (icon-xref :grid-gutter-refactor)) (def ^:icon grid-margin-refactor (icon-xref :grid-margin-refactor)) +(def ^:icon grid-refactor (icon-xref :grid-refactor)) (def ^:icon grid-row-refactor (icon-xref :grid-row-refactor)) (def ^:icon grid-rows-refactor (icon-xref :grid-rows-refactor)) (def ^:icon grid-square-refactor (icon-xref :grid-square-refactor)) -(def ^:icon grid-refactor (icon-xref :grid-refactor)) (def ^:icon group-refactor (icon-xref :group-refactor)) +(def ^:icon gutter-horizontal-refactor (icon-xref :gutter-horizontal-refactor)) +(def ^:icon gutter-vertical-refactor (icon-xref :gutter-vertical-refactor)) (def ^:icon graphics-refactor (icon-xref :graphics-refactor)) -(def ^:icon gap-horizontal-refactor (icon-xref :gap-horizontal-refactor)) -(def ^:icon gap-vertical-refactor (icon-xref :gap-vertical-refactor)) (def ^:icon help-refactor (icon-xref :help-refactor)) (def ^:icon hide-refactor (icon-xref :hide-refactor)) (def ^:icon history-refactor (icon-xref :history-refactor)) (def ^:icon hsva-refactor (icon-xref :hsva-refactor)) (def ^:icon hug-content-refactor (icon-xref :hug-content-refactor)) -(def ^:icon img-refactor (icon-xref :img-refactor)) (def ^:icon icon-refactor (icon-xref :icon-refactor)) +(def ^:icon img-refactor (icon-xref :img-refactor)) (def ^:icon interaction-refactor (icon-xref :interaction-refactor)) (def ^:icon join-nodes-refactor (icon-xref :join-nodes-refactor)) (def ^:icon justify-content-column-around-refactor (icon-xref :justify-content-column-around-refactor)) @@ -393,17 +157,17 @@ (def ^:icon justify-content-row-around-refactor (icon-xref :justify-content-row-around-refactor)) (def ^:icon justify-content-row-evenly-refactor (icon-xref :justify-content-row-evenly-refactor)) (def ^:icon layers-refactor (icon-xref :layers-refactor)) -(def ^:icon locate-refactor (icon-xref :locate-refactor)) -(def ^:icon lock-refactor (icon-xref :lock-refactor)) -(def ^:icon logo-refactor (icon-xref :penpot-logo-icon)) ;; This icon will not change (def ^:icon library-refactor (icon-xref :library-refactor)) +(def ^:icon locate-refactor (icon-xref :locate-refactor)) +(def ^:icon lock-refactor (icon-xref :lock-refactor)) ;; This icon will not change +(def ^:icon logo-refactor (icon-xref :penpot-logo-icon)) (def ^:icon margin-bottom-refactor (icon-xref :margin-bottom-refactor)) (def ^:icon margin-left-refactor (icon-xref :margin-left-refactor)) (def ^:icon margin-left-right-refactor (icon-xref :margin-left-right-refactor)) (def ^:icon margin-refactor (icon-xref :margin-refactor)) (def ^:icon margin-right-refactor (icon-xref :margin-right-refactor)) -(def ^:icon margin-top-refactor (icon-xref :margin-top-refactor)) (def ^:icon margin-top-bottom-refactor (icon-xref :margin-top-bottom-refactor)) +(def ^:icon margin-top-refactor (icon-xref :margin-top-refactor)) (def ^:icon mask-refactor (icon-xref :mask-refactor)) (def ^:icon masked-refactor (icon-xref :masked-refactor)) (def ^:icon menu-refactor (icon-xref :menu-refactor)) @@ -415,12 +179,12 @@ (def ^:icon move-refactor (icon-xref :move-refactor)) (def ^:icon open-link-refactor (icon-xref :open-link-refactor)) (def ^:icon padding-bottom-refactor (icon-xref :padding-bottom-refactor)) -(def ^:icon padding-top-refactor (icon-xref :padding-top-refactor)) -(def ^:icon padding-top-bottom-refactor (icon-xref :padding-top-bottom-refactor)) +(def ^:icon padding-extended-refactor (icon-xref :padding-extended-refactor)) (def ^:icon padding-left-refactor (icon-xref :padding-left-refactor)) (def ^:icon padding-left-right-refactor (icon-xref :padding-left-right-refactor)) (def ^:icon padding-right-refactor (icon-xref :padding-right-refactor)) -(def ^:icon padding-extended-refactor (icon-xref :padding-extended-refactor)) +(def ^:icon padding-top-bottom-refactor (icon-xref :padding-top-bottom-refactor)) +(def ^:icon padding-top-refactor (icon-xref :padding-top-refactor)) (def ^:icon path-refactor (icon-xref :path-refactor)) (def ^:icon pentool-refactor (icon-xref :pentool-refactor)) (def ^:icon picker-refactor (icon-xref :picker-refactor)) @@ -429,28 +193,29 @@ (def ^:icon rectangle-refactor (icon-xref :rectangle-refactor)) (def ^:icon reload-refactor (icon-xref :reload-refactor)) (def ^:icon remove-refactor (icon-xref :remove-refactor)) -(def ^:icon rgba-refactor (icon-xref :rgba-refactor)) (def ^:icon rgba-complementary-refactor (icon-xref :rgba-complementary-refactor)) +(def ^:icon rgba-refactor (icon-xref :rgba-refactor)) (def ^:icon rotation-refactor (icon-xref :rotation-refactor)) +(def ^:icon row-refactor (icon-xref :row-refactor)) (def ^:icon row-reverse-refactor (icon-xref :row-reverse-refactor)) (def ^:icon search-refactor (icon-xref :search-refactor)) (def ^:icon separate-nodes-refactor (icon-xref :separate-nodes-refactor)) +(def ^:icon shown-refactor (icon-xref :shown-refactor)) (def ^:icon size-horizontal-refactor (icon-xref :size-horizontal-refactor)) (def ^:icon size-vertical-refactor (icon-xref :size-vertical-refactor)) -(def ^:icon shown-refactor (icon-xref :shown-refactor)) (def ^:icon snap-nodes-refactor (icon-xref :snap-nodes-refactor)) (def ^:icon status-alert-refactor (icon-xref :status-alert-refactor)) -(def ^:icon status-update-refactor (icon-xref :status-update-refactor)) (def ^:icon status-tick-refactor (icon-xref :status-tick-refactor)) +(def ^:icon status-update-refactor (icon-xref :status-update-refactor)) (def ^:icon status-wrong-refactor (icon-xref :status-wrong-refactor)) (def ^:icon stroke-arrow-refactor (icon-xref :stroke-arrow-refactor)) (def ^:icon stroke-circle-refactor (icon-xref :stroke-circle-refactor)) (def ^:icon stroke-diamond-refactor (icon-xref :stroke-diamond-refactor)) (def ^:icon stroke-rectangle-refactor (icon-xref :stroke-rectangle-refactor)) (def ^:icon stroke-rounded-refactor (icon-xref :stroke-rounded-refactor)) +(def ^:icon stroke-size-refactor (icon-xref :stroke-size-refactor)) (def ^:icon stroke-squared-refactor (icon-xref :stroke-squared-refactor)) (def ^:icon stroke-triangle-refactor (icon-xref :stroke-triangle-refactor)) -(def ^:icon stroke-size-refactor (icon-xref :stroke-size-refactor)) (def ^:icon svg-refactor (icon-xref :svg-refactor)) (def ^:icon swatches-refactor (icon-xref :swatches-refactor)) (def ^:icon switch-refactor (icon-xref :switch-refactor)) @@ -459,42 +224,36 @@ (def ^:icon text-align-right-refactor (icon-xref :text-align-right-refactor)) (def ^:icon text-auto-height-refactor (icon-xref :text-auto-height-refactor)) (def ^:icon text-auto-width-refactor (icon-xref :text-auto-width-refactor)) +(def ^:icon text-bottom-refactor (icon-xref :text-bottom-refactor)) (def ^:icon text-fixed-refactor (icon-xref :text-fixed-refactor)) (def ^:icon text-justify-refactor (icon-xref :text-justify-refactor)) (def ^:icon text-letterspacing-refactor (icon-xref :text-letterspacing-refactor)) (def ^:icon text-lineheight-refactor (icon-xref :text-lineheight-refactor)) (def ^:icon text-lowercase-refactor (icon-xref :text-lowercase-refactor)) +(def ^:icon text-ltr-refactor (icon-xref :text-ltr-refactor)) +(def ^:icon text-middle-refactor (icon-xref :text-middle-refactor)) +(def ^:icon text-mixed-refactor (icon-xref :text-mixed-refactor)) (def ^:icon text-palette-refactor (icon-xref :text-palette-refactor)) (def ^:icon text-paragraph-refactor (icon-xref :text-paragraph-refactor)) (def ^:icon text-refactor (icon-xref :text-refactor)) -(def ^:icon text-bottom-refactor (icon-xref :text-bottom-refactor)) -(def ^:icon text-ltr-refactor (icon-xref :text-ltr-refactor)) (def ^:icon text-rtl-refactor (icon-xref :text-rtl-refactor)) -(def ^:icon text-middle-refactor (icon-xref :text-middle-refactor)) -(def ^:icon text-mixed-refactor (icon-xref :text-mixed-refactor)) (def ^:icon text-stroked-refactor (icon-xref :text-stroked-refactor)) (def ^:icon text-top-refactor (icon-xref :text-top-refactor)) (def ^:icon text-underlined-refactor (icon-xref :text-underlined-refactor)) (def ^:icon text-uppercase-refactor (icon-xref :text-uppercase-refactor)) +(def ^:icon thumbnail-refactor (icon-xref :thumbnail-refactor)) (def ^:icon tick-refactor (icon-xref :tick-refactor)) -(def ^:icon tree-refactor (icon-xref :tree-refactor)) (def ^:icon to-corner-refactor (icon-xref :to-corner-refactor)) (def ^:icon to-curve-refactor (icon-xref :to-curve-refactor)) +(def ^:icon tree-refactor (icon-xref :tree-refactor)) (def ^:icon unlock-refactor (icon-xref :unlock-refactor)) (def ^:icon user-refactor (icon-xref :user-refactor)) (def ^:icon vertical-align-items-center-refactor (icon-xref :vertical-align-items-center-refactor)) (def ^:icon vertical-align-items-end-refactor (icon-xref :vertical-align-items-end-refactor)) (def ^:icon vertical-align-items-start-refactor (icon-xref :vertical-align-items-start-refactor)) (def ^:icon view-as-icons-refactor (icon-xref :view-as-icons-refactor)) -(def ^:icon wrap-refactor (icon-xref :wrap-refactor)) (def ^:icon view-as-list-refactor (icon-xref :view-as-list-refactor)) -(def ^:icon cap-line-arrow (icon-xref :cap-line-arrow)) -(def ^:icon cap-triangle-arrow (icon-xref :cap-triangle-arrow)) -(def ^:icon cap-square-marker (icon-xref :cap-square-marker)) -(def ^:icon cap-circle-marker (icon-xref :cap-circle-marker)) -(def ^:icon cap-diamond-marker (icon-xref :cap-diamond-marker)) -(def ^:icon cap-round (icon-xref :cap-round)) -(def ^:icon cap-square (icon-xref :cap-square)) +(def ^:icon wrap-refactor (icon-xref :wrap-refactor)) (def ^:icon v2-icon-1 (icon-xref :v2-icon-1)) (def ^:icon v2-icon-2 (icon-xref :v2-icon-2)) diff --git a/frontend/src/app/main/ui/onboarding/templates.cljs b/frontend/src/app/main/ui/onboarding/templates.cljs index af0abb2b1..121d661e7 100644 --- a/frontend/src/app/main/ui/onboarding/templates.cljs +++ b/frontend/src/app/main/ui/onboarding/templates.cljs @@ -71,7 +71,7 @@ [:div.modal-header [:div.modal-close-button {:on-click close-fn - :data-test "close-templates-btn"} i/close]] + :data-test "close-templates-btn"} i/close-refactor]] [:div.modal-content [:h3 (tr "onboarding.templates.title")] 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 894d92074..580b90a25 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 @@ -69,15 +69,11 @@ (case val :start i/align-items-column-start-refactor :end i/align-items-column-end-refactor - :center i/align-items-column-center-refactor - :stretch i/align-items-column-strech - :baseline i/align-items-column-baseline) - (case val ;; TODO Check strech and baseline icons + :center i/align-items-column-center-refactor) + (case val :start i/align-items-row-start-refactor :end i/align-items-row-end-refactor - :center i/align-items-row-center-refactor - :stretch i/align-items-row-strech - :baseline i/align-items-row-baseline)) + :center i/align-items-row-center-refactor)) :justify-content (if column? @@ -122,16 +118,12 @@ :auto i/remove-refactor :start i/align-self-row-left-refactor :end i/align-self-row-right-refactor - :center i/align-self-row-center-refactor - :stretch i/align-self-row-strech - :baseline i/align-self-row-baseline) + :center i/align-self-row-center-refactor) (case val :auto i/remove-refactor :start i/align-self-column-top-refactor :end i/align-self-column-bottom-refactor - :center i/align-self-column-center-refactor - :stretch i/align-self-column-strech - :baseline i/align-self-column-baseline)))) + :center i/align-self-column-center-refactor)))) (defn get-layout-grid-icon [type val ^boolean column?] @@ -142,16 +134,12 @@ :auto i/remove-refactor :start i/align-self-row-left-refactor :end i/align-self-row-right-refactor - :center i/align-self-row-center-refactor - :stretch i/align-self-row-strech - :baseline i/align-self-row-baseline) + :center i/align-self-row-center-refactor) (case val :auto i/remove-refactor :start i/align-self-column-top-refactor :end i/align-self-column-bottom-refactor - :center i/align-self-column-center-refactor - :stretch i/align-self-column-strech - :baseline i/align-self-column-baseline)) + :center i/align-self-column-center-refactor)) :justify-items (if (not column?) From 5739c0797c81cc2c594db5dfa7bf445d7ca5eaa9 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 8 Mar 2024 11:37:16 +0100 Subject: [PATCH 057/136] :recycle: Rename all refactored icons --- ...efactor.svg => align-items-column-end.svg} | 0 ...actor.svg => align-items-column-start.svg} | 0 ...efactor.svg => align-items-row-center.svg} | 0 ...d-refactor.svg => align-items-row-end.svg} | 0 ...refactor.svg => align-items-row-start.svg} | 0 ...align-left-refactor.svg => align-left.svg} | 0 ...ign-right-refactor.svg => align-right.svg} | 0 ...actor.svg => align-self-column-bottom.svg} | 0 ...actor.svg => align-self-column-center.svg} | 0 ...ctor.svg => align-self-column-stretch.svg} | 0 ...refactor.svg => align-self-column-top.svg} | 0 ...refactor.svg => align-self-row-center.svg} | 0 ...t-refactor.svg => align-self-row-left.svg} | 0 ...-refactor.svg => align-self-row-right.svg} | 0 ...efactor.svg => align-self-row-stretch.svg} | 0 .../{align-top-refactor.svg => align-top.svg} | 0 ...refactor.svg => align-vertical-center.svg} | 0 .../icons/{arrow-refactor.svg => arrow.svg} | 0 .../{asc-sort-refactor.svg => asc-sort.svg} | 0 frontend/resources/images/icons/auto-grid.svg | 3 - .../icons/{board-refactor.svg => board.svg} | 0 ...nail-refactor.svg => boards-thumbnail.svg} | 0 ...ce-refactor.svg => boolean-difference.svg} | 0 ...clude-refactor.svg => boolean-exclude.svg} | 0 ...atten-refactor.svg => boolean-flatten.svg} | 0 ...-refactor.svg => boolean-intersection.svg} | 0 ...n-union-refactor.svg => boolean-union.svg} | 0 .../icons/{bug-refactor.svg => bug.svg} | 0 ...-content-refactor.svg => clip-content.svg} | 0 .../{clipboard-refactor.svg => clipboard.svg} | 0 ...ose-small-refactor.svg => close-small.svg} | 0 .../icons/{close-refactor.svg => close.svg} | 0 .../icons/{code-refactor.svg => code.svg} | 0 ...everse-refactor.svg => column-reverse.svg} | 0 .../icons/{column-refactor.svg => column.svg} | 0 .../{comments-refactor.svg => comments.svg} | 0 .../{copy-refactor.svg => component-copy.svg} | 0 .../{component-refactor.svg => component.svg} | 0 ...refactor.svg => constraint-horizontal.svg} | 0 ...l-refactor.svg => constraint-vertical.svg} | 0 ...ft-refactor.svg => corner-bottom-left.svg} | 0 ...t-refactor.svg => corner-bottom-right.svg} | 0 ...-bottom-refactor.svg => corner-bottom.svg} | 0 ...-center-refactor.svg => corner-center.svg} | 0 ...-radius-refactor.svg => corner-radius.svg} | 0 ...pleft-refactor.svg => corner-top-left.svg} | 0 ...ight-refactor.svg => corner-top-right.svg} | 0 ...corner-top-refactor.svg => corner-top.svg} | 0 .../icons/{curve-refactor.svg => curve.svg} | 0 ...lete-text-refactor.svg => delete-text.svg} | 0 .../icons/{delete-refactor.svg => delete.svg} | 0 .../{desc-sort-refactor.svg => desc-sort.svg} | 0 .../icons/{detach-refactor.svg => detach.svg} | 0 .../{detached-refactor.svg => detached.svg} | 0 ...factor.svg => distribute-horizontally.svg} | 0 ...or.svg => distribute-vertical-spacing.svg} | 0 .../{document-refactor.svg => document.svg} | 0 .../{download-refactor.svg => download.svg} | 0 .../icons/{drop-refactor.svg => drop.svg} | 0 ...ut-refactor.svg => easing-ease-in-out.svg} | 0 ...ase-in-refactor.svg => easing-ease-in.svg} | 0 ...e-out-refactor.svg => easing-ease-out.svg} | 0 ...sing-ease-refactor.svg => easing-ease.svg} | 0 ...-linear-refactor.svg => easing-linear.svg} | 0 .../{effects-refactor.svg => effects.svg} | 0 .../icons/{elipse-refactor.svg => elipse.svg} | 0 .../icons/{exit-refactor.svg => exit.svg} | 0 .../icons/{expand-refactor.svg => expand.svg} | 0 .../{feedback-refactor.svg => feedback.svg} | 0 ...-content-refactor.svg => fill-content.svg} | 0 .../icons/{filter-refactor.svg => filter.svg} | 0 ...xed-width-refactor.svg => fixed-width.svg} | 0 .../{flex-grid-refactor.svg => flex-grid.svg} | 0 ...ontal-refactor.svg => flex-horizontal.svg} | 0 ...ertical-refactor.svg => flex-vertical.svg} | 0 .../icons/{flex-refactor.svg => flex.svg} | 0 ...ontal-refactor.svg => flip-horizontal.svg} | 0 ...ertical-refactor.svg => flip-vertical.svg} | 0 ...zontal-refactor.svg => gap-horizontal.svg} | 0 ...vertical-refactor.svg => gap-vertical.svg} | 0 .../{graphics-refactor.svg => graphics.svg} | 0 ...id-column-refactor.svg => grid-column.svg} | 0 ...-columns-refactor.svg => grid-columns.svg} | 0 ...id-gutter-refactor.svg => grid-gutter.svg} | 0 ...id-margin-refactor.svg => grid-margin.svg} | 0 .../{grid-row-refactor.svg => grid-row.svg} | 0 .../{grid-rows-refactor.svg => grid-rows.svg} | 0 ...id-square-refactor.svg => grid-square.svg} | 0 .../icons/{grid-refactor.svg => grid.svg} | 0 .../icons/{group-refactor.svg => group.svg} | 0 ...tal-refactor.svg => gutter-horizontal.svg} | 0 ...tical-refactor.svg => gutter-vertical.svg} | 0 .../icons/{help-refactor.svg => help.svg} | 0 .../icons/{hide-refactor.svg => hide.svg} | 0 .../{history-refactor.svg => history.svg} | 0 .../icons/{hsva-refactor.svg => hsva.svg} | 0 ...g-content-refactor.svg => hug-content.svg} | 0 .../icons/{icon-refactor.svg => icon.svg} | 0 .../icons/{img-refactor.svg => img.svg} | 0 ...teraction-refactor.svg => interaction.svg} | 0 ...join-nodes-refactor.svg => join-nodes.svg} | 0 ....svg => justify-content-column-around.svg} | 0 ...svg => justify-content-column-between.svg} | 0 ....svg => justify-content-column-center.svg} | 0 ...tor.svg => justify-content-column-end.svg} | 0 ....svg => justify-content-column-evenly.svg} | 0 ...r.svg => justify-content-column-start.svg} | 0 ...tor.svg => justify-content-row-around.svg} | 0 ...or.svg => justify-content-row-between.svg} | 0 ...tor.svg => justify-content-row-center.svg} | 0 ...factor.svg => justify-content-row-end.svg} | 0 ...tor.svg => justify-content-row-evenly.svg} | 0 ...ctor.svg => justify-content-row-start.svg} | 0 .../icons/{layers-refactor.svg => layers.svg} | 0 .../{library-refactor.svg => library.svg} | 0 .../resources/images/icons/line-arrow.svg | 1 - .../icons/{locate-refactor.svg => locate.svg} | 0 .../icons/{lock-refactor.svg => lock.svg} | 0 ...-bottom-refactor.svg => margin-bottom.svg} | 0 ...ght-refactor.svg => margin-left-right.svg} | 0 ...rgin-left-refactor.svg => margin-left.svg} | 0 ...in-right-refactor.svg => margin-right.svg} | 0 ...tom-refactor.svg => margin-top-bottom.svg} | 0 ...margin-top-refactor.svg => margin-top.svg} | 0 .../icons/{margin-refactor.svg => margin.svg} | 0 .../icons/{mask-refactor.svg => mask.svg} | 0 .../icons/{masked-refactor.svg => masked.svg} | 0 .../icons/{menu-refactor.svg => menu.svg} | 0 ...rge-nodes-refactor.svg => merge-nodes.svg} | 0 .../icons/{move-refactor.svg => move.svg} | 0 .../{msg-error-refactor.svg => msg-error.svg} | 0 ...g-neutral-refactor.svg => msg-neutral.svg} | 0 ...g-success-refactor.svg => msg-success.svg} | 0 ...g-warning-refactor.svg => msg-warning.svg} | 0 .../resources/images/icons/multi-canvas.svg | 3 - .../{open-link-refactor.svg => open-link.svg} | 0 ...bottom-refactor.svg => padding-bottom.svg} | 0 ...nded-refactor.svg => padding-extended.svg} | 0 ...ht-refactor.svg => padding-left-right.svg} | 0 ...ing-left-refactor.svg => padding-left.svg} | 0 ...g-right-refactor.svg => padding-right.svg} | 0 ...om-refactor.svg => padding-top-bottom.svg} | 0 ...dding-top-refactor.svg => padding-top.svg} | 0 .../icons/{path-refactor.svg => path.svg} | 0 .../{pentool-refactor.svg => pentool.svg} | 0 .../icons/{picker-refactor.svg => picker.svg} | 0 .../icons/{pin-refactor.svg => pin.svg} | 0 .../icons/{play-refactor.svg => play.svg} | 0 .../{rectangle-refactor.svg => rectangle.svg} | 0 .../icons/{reload-refactor.svg => reload.svg} | 0 .../icons/{remove-refactor.svg => remove.svg} | 0 ...ry-refactor.svg => rgba-complementary.svg} | 0 .../icons/{rgba-refactor.svg => rgba.svg} | 0 .../{rotation-refactor.svg => rotation.svg} | 0 ...w-reverse-refactor.svg => row-reverse.svg} | 0 .../icons/{row-refactor.svg => row.svg} | 0 .../icons/{search-refactor.svg => search.svg} | 0 ...-nodes-refactor.svg => separate-nodes.svg} | 0 .../icons/{shown-refactor.svg => shown.svg} | 0 ...ontal-refactor.svg => size-horizontal.svg} | 0 ...ertical-refactor.svg => size-vertical.svg} | 0 ...snap-nodes-refactor.svg => snap-nodes.svg} | 0 ...us-alert-refactor.svg => status-alert.svg} | 0 ...atus-tick-refactor.svg => status-tick.svg} | 0 ...-update-refactor.svg => status-update.svg} | 0 ...us-wrong-refactor.svg => status-wrong.svg} | 0 ...ke-arrow-refactor.svg => stroke-arrow.svg} | 0 ...-circle-refactor.svg => stroke-circle.svg} | 0 ...iamond-refactor.svg => stroke-diamond.svg} | 0 ...ngle-refactor.svg => stroke-rectangle.svg} | 0 ...ounded-refactor.svg => stroke-rounded.svg} | 0 ...roke-size-refactor.svg => stroke-size.svg} | 0 ...quared-refactor.svg => stroke-squared.svg} | 0 ...angle-refactor.svg => stroke-triangle.svg} | 0 .../icons/{svg-refactor.svg => svg.svg} | 0 .../{swatches-refactor.svg => swatches.svg} | 0 .../icons/{switch-refactor.svg => switch.svg} | 0 ...ter-refactor.svg => text-align-center.svg} | 0 ...-left-refactor.svg => text-align-left.svg} | 0 ...ight-refactor.svg => text-align-right.svg} | 0 ...ight-refactor.svg => text-auto-height.svg} | 0 ...width-refactor.svg => text-auto-width.svg} | 0 ...xt-bottom-refactor.svg => text-bottom.svg} | 0 ...text-fixed-refactor.svg => text-fixed.svg} | 0 ...-justify-refactor.svg => text-justify.svg} | 0 ...ng-refactor.svg => text-letterspacing.svg} | 0 ...eight-refactor.svg => text-lineheight.svg} | 0 ...ercase-refactor.svg => text-lowercase.svg} | 0 .../{text-ltr-refactor.svg => text-ltr.svg} | 0 ...xt-middle-refactor.svg => text-middle.svg} | 0 ...text-mixed-refactor.svg => text-mixed.svg} | 0 ...-palette-refactor.svg => text-palette.svg} | 0 ...agraph-refactor.svg => text-paragraph.svg} | 0 .../{text-rtl-refactor.svg => text-rtl.svg} | 0 ...-stroked-refactor.svg => text-stroked.svg} | 0 .../{text-top-refactor.svg => text-top.svg} | 0 ...lined-refactor.svg => text-underlined.svg} | 0 ...ercase-refactor.svg => text-uppercase.svg} | 0 .../icons/{text-refactor.svg => text.svg} | 0 .../{thumbnail-refactor.svg => thumbnail.svg} | 0 .../icons/{tick-refactor.svg => tick.svg} | 0 .../{to-corner-refactor.svg => to-corner.svg} | 0 .../{to-curve-refactor.svg => to-curve.svg} | 0 .../icons/{tree-refactor.svg => tree.svg} | 0 frontend/resources/images/icons/unchain.svg | 3 - .../icons/{unlock-refactor.svg => unlock.svg} | 0 .../icons/{user-refactor.svg => user.svg} | 0 ...or.svg => vertical-align-items-center.svg} | 0 ...actor.svg => vertical-align-items-end.svg} | 0 ...tor.svg => vertical-align-items-start.svg} | 0 ...s-icons-refactor.svg => view-as-icons.svg} | 0 ...-as-list-refactor.svg => view-as-list.svg} | 0 frontend/resources/styles/debug.scss | 1 - .../src/app/main/ui/components/title_bar.cljs | 2 +- .../src/app/main/ui/dashboard/comments.cljs | 6 +- frontend/src/app/main/ui/dashboard/files.cljs | 2 +- frontend/src/app/main/ui/dashboard/grid.cljs | 2 +- .../src/app/main/ui/dashboard/pin_button.cljs | 2 +- .../src/app/main/ui/dashboard/projects.cljs | 4 +- .../src/app/main/ui/dashboard/sidebar.cljs | 18 +- frontend/src/app/main/ui/dashboard/team.cljs | 16 +- .../src/app/main/ui/dashboard/templates.cljs | 4 +- frontend/src/app/main/ui/export.cljs | 6 +- frontend/src/app/main/ui/icons.cljs | 419 +++++++++--------- .../notifications/context_notification.cljs | 8 +- .../ui/notifications/toast_notification.cljs | 10 +- .../app/main/ui/settings/access_tokens.cljs | 6 +- .../src/app/main/ui/settings/sidebar.cljs | 4 +- .../workspace/sidebar/options/menus/bool.cljs | 2 +- .../sidebar/options/menus/interactions.cljs | 14 +- .../sidebar/options/menus/measures.cljs | 8 +- .../sidebar/options/rows/color_row.cljs | 2 +- 232 files changed, 267 insertions(+), 279 deletions(-) rename frontend/resources/images/icons/{align-items-column-end-refactor.svg => align-items-column-end.svg} (100%) rename frontend/resources/images/icons/{align-items-column-start-refactor.svg => align-items-column-start.svg} (100%) rename frontend/resources/images/icons/{align-items-row-center-refactor.svg => align-items-row-center.svg} (100%) rename frontend/resources/images/icons/{align-items-row-end-refactor.svg => align-items-row-end.svg} (100%) rename frontend/resources/images/icons/{align-items-row-start-refactor.svg => align-items-row-start.svg} (100%) rename frontend/resources/images/icons/{align-left-refactor.svg => align-left.svg} (100%) rename frontend/resources/images/icons/{align-right-refactor.svg => align-right.svg} (100%) rename frontend/resources/images/icons/{align-self-column-bottom-refactor.svg => align-self-column-bottom.svg} (100%) rename frontend/resources/images/icons/{align-self-column-center-refactor.svg => align-self-column-center.svg} (100%) rename frontend/resources/images/icons/{align-self-column-stretch-refactor.svg => align-self-column-stretch.svg} (100%) rename frontend/resources/images/icons/{align-self-column-top-refactor.svg => align-self-column-top.svg} (100%) rename frontend/resources/images/icons/{align-self-row-center-refactor.svg => align-self-row-center.svg} (100%) rename frontend/resources/images/icons/{align-self-row-left-refactor.svg => align-self-row-left.svg} (100%) rename frontend/resources/images/icons/{align-self-row-right-refactor.svg => align-self-row-right.svg} (100%) rename frontend/resources/images/icons/{align-self-row-stretch-refactor.svg => align-self-row-stretch.svg} (100%) rename frontend/resources/images/icons/{align-top-refactor.svg => align-top.svg} (100%) rename frontend/resources/images/icons/{align-vertical-center-refactor.svg => align-vertical-center.svg} (100%) rename frontend/resources/images/icons/{arrow-refactor.svg => arrow.svg} (100%) rename frontend/resources/images/icons/{asc-sort-refactor.svg => asc-sort.svg} (100%) delete mode 100644 frontend/resources/images/icons/auto-grid.svg rename frontend/resources/images/icons/{board-refactor.svg => board.svg} (100%) rename frontend/resources/images/icons/{boards-thumbnail-refactor.svg => boards-thumbnail.svg} (100%) rename frontend/resources/images/icons/{boolean-difference-refactor.svg => boolean-difference.svg} (100%) rename frontend/resources/images/icons/{boolean-exclude-refactor.svg => boolean-exclude.svg} (100%) rename frontend/resources/images/icons/{boolean-flatten-refactor.svg => boolean-flatten.svg} (100%) rename frontend/resources/images/icons/{boolean-intersection-refactor.svg => boolean-intersection.svg} (100%) rename frontend/resources/images/icons/{boolean-union-refactor.svg => boolean-union.svg} (100%) rename frontend/resources/images/icons/{bug-refactor.svg => bug.svg} (100%) rename frontend/resources/images/icons/{clip-content-refactor.svg => clip-content.svg} (100%) rename frontend/resources/images/icons/{clipboard-refactor.svg => clipboard.svg} (100%) rename frontend/resources/images/icons/{close-small-refactor.svg => close-small.svg} (100%) rename frontend/resources/images/icons/{close-refactor.svg => close.svg} (100%) rename frontend/resources/images/icons/{code-refactor.svg => code.svg} (100%) rename frontend/resources/images/icons/{column-reverse-refactor.svg => column-reverse.svg} (100%) rename frontend/resources/images/icons/{column-refactor.svg => column.svg} (100%) rename frontend/resources/images/icons/{comments-refactor.svg => comments.svg} (100%) rename frontend/resources/images/icons/{copy-refactor.svg => component-copy.svg} (100%) rename frontend/resources/images/icons/{component-refactor.svg => component.svg} (100%) rename frontend/resources/images/icons/{constraint-horizontal-refactor.svg => constraint-horizontal.svg} (100%) rename frontend/resources/images/icons/{constraint-vertical-refactor.svg => constraint-vertical.svg} (100%) rename frontend/resources/images/icons/{corner-bottomleft-refactor.svg => corner-bottom-left.svg} (100%) rename frontend/resources/images/icons/{corner-bottomright-refactor.svg => corner-bottom-right.svg} (100%) rename frontend/resources/images/icons/{corner-bottom-refactor.svg => corner-bottom.svg} (100%) rename frontend/resources/images/icons/{corner-center-refactor.svg => corner-center.svg} (100%) rename frontend/resources/images/icons/{corner-radius-refactor.svg => corner-radius.svg} (100%) rename frontend/resources/images/icons/{corner-topleft-refactor.svg => corner-top-left.svg} (100%) rename frontend/resources/images/icons/{corner-topright-refactor.svg => corner-top-right.svg} (100%) rename frontend/resources/images/icons/{corner-top-refactor.svg => corner-top.svg} (100%) rename frontend/resources/images/icons/{curve-refactor.svg => curve.svg} (100%) rename frontend/resources/images/icons/{delete-text-refactor.svg => delete-text.svg} (100%) rename frontend/resources/images/icons/{delete-refactor.svg => delete.svg} (100%) rename frontend/resources/images/icons/{desc-sort-refactor.svg => desc-sort.svg} (100%) rename frontend/resources/images/icons/{detach-refactor.svg => detach.svg} (100%) rename frontend/resources/images/icons/{detached-refactor.svg => detached.svg} (100%) rename frontend/resources/images/icons/{distribute-horizontally-refactor.svg => distribute-horizontally.svg} (100%) rename frontend/resources/images/icons/{distribute-vertical-spacing-refactor.svg => distribute-vertical-spacing.svg} (100%) rename frontend/resources/images/icons/{document-refactor.svg => document.svg} (100%) rename frontend/resources/images/icons/{download-refactor.svg => download.svg} (100%) rename frontend/resources/images/icons/{drop-refactor.svg => drop.svg} (100%) rename frontend/resources/images/icons/{easing-ease-in-out-refactor.svg => easing-ease-in-out.svg} (100%) rename frontend/resources/images/icons/{easing-ease-in-refactor.svg => easing-ease-in.svg} (100%) rename frontend/resources/images/icons/{easing-ease-out-refactor.svg => easing-ease-out.svg} (100%) rename frontend/resources/images/icons/{easing-ease-refactor.svg => easing-ease.svg} (100%) rename frontend/resources/images/icons/{easing-linear-refactor.svg => easing-linear.svg} (100%) rename frontend/resources/images/icons/{effects-refactor.svg => effects.svg} (100%) rename frontend/resources/images/icons/{elipse-refactor.svg => elipse.svg} (100%) rename frontend/resources/images/icons/{exit-refactor.svg => exit.svg} (100%) rename frontend/resources/images/icons/{expand-refactor.svg => expand.svg} (100%) rename frontend/resources/images/icons/{feedback-refactor.svg => feedback.svg} (100%) rename frontend/resources/images/icons/{fill-content-refactor.svg => fill-content.svg} (100%) rename frontend/resources/images/icons/{filter-refactor.svg => filter.svg} (100%) rename frontend/resources/images/icons/{fixed-width-refactor.svg => fixed-width.svg} (100%) rename frontend/resources/images/icons/{flex-grid-refactor.svg => flex-grid.svg} (100%) rename frontend/resources/images/icons/{flex-horizontal-refactor.svg => flex-horizontal.svg} (100%) rename frontend/resources/images/icons/{flex-vertical-refactor.svg => flex-vertical.svg} (100%) rename frontend/resources/images/icons/{flex-refactor.svg => flex.svg} (100%) rename frontend/resources/images/icons/{flip-horizontal-refactor.svg => flip-horizontal.svg} (100%) rename frontend/resources/images/icons/{flip-vertical-refactor.svg => flip-vertical.svg} (100%) rename frontend/resources/images/icons/{gap-horizontal-refactor.svg => gap-horizontal.svg} (100%) rename frontend/resources/images/icons/{gap-vertical-refactor.svg => gap-vertical.svg} (100%) rename frontend/resources/images/icons/{graphics-refactor.svg => graphics.svg} (100%) rename frontend/resources/images/icons/{grid-column-refactor.svg => grid-column.svg} (100%) rename frontend/resources/images/icons/{grid-columns-refactor.svg => grid-columns.svg} (100%) rename frontend/resources/images/icons/{grid-gutter-refactor.svg => grid-gutter.svg} (100%) rename frontend/resources/images/icons/{grid-margin-refactor.svg => grid-margin.svg} (100%) rename frontend/resources/images/icons/{grid-row-refactor.svg => grid-row.svg} (100%) rename frontend/resources/images/icons/{grid-rows-refactor.svg => grid-rows.svg} (100%) rename frontend/resources/images/icons/{grid-square-refactor.svg => grid-square.svg} (100%) rename frontend/resources/images/icons/{grid-refactor.svg => grid.svg} (100%) rename frontend/resources/images/icons/{group-refactor.svg => group.svg} (100%) rename frontend/resources/images/icons/{gutter-horizontal-refactor.svg => gutter-horizontal.svg} (100%) rename frontend/resources/images/icons/{gutter-vertical-refactor.svg => gutter-vertical.svg} (100%) rename frontend/resources/images/icons/{help-refactor.svg => help.svg} (100%) rename frontend/resources/images/icons/{hide-refactor.svg => hide.svg} (100%) rename frontend/resources/images/icons/{history-refactor.svg => history.svg} (100%) rename frontend/resources/images/icons/{hsva-refactor.svg => hsva.svg} (100%) rename frontend/resources/images/icons/{hug-content-refactor.svg => hug-content.svg} (100%) rename frontend/resources/images/icons/{icon-refactor.svg => icon.svg} (100%) rename frontend/resources/images/icons/{img-refactor.svg => img.svg} (100%) rename frontend/resources/images/icons/{interaction-refactor.svg => interaction.svg} (100%) rename frontend/resources/images/icons/{join-nodes-refactor.svg => join-nodes.svg} (100%) rename frontend/resources/images/icons/{justify-content-column-around-refactor.svg => justify-content-column-around.svg} (100%) rename frontend/resources/images/icons/{justify-content-column-between-refactor.svg => justify-content-column-between.svg} (100%) rename frontend/resources/images/icons/{justify-content-column-center-refactor.svg => justify-content-column-center.svg} (100%) rename frontend/resources/images/icons/{justify-content-column-end-refactor.svg => justify-content-column-end.svg} (100%) rename frontend/resources/images/icons/{justify-content-column-evenly-refactor.svg => justify-content-column-evenly.svg} (100%) rename frontend/resources/images/icons/{justify-content-column-start-refactor.svg => justify-content-column-start.svg} (100%) rename frontend/resources/images/icons/{justify-content-row-around-refactor.svg => justify-content-row-around.svg} (100%) rename frontend/resources/images/icons/{justify-content-row-between-refactor.svg => justify-content-row-between.svg} (100%) rename frontend/resources/images/icons/{justify-content-row-center-refactor.svg => justify-content-row-center.svg} (100%) rename frontend/resources/images/icons/{justify-content-row-end-refactor.svg => justify-content-row-end.svg} (100%) rename frontend/resources/images/icons/{justify-content-row-evenly-refactor.svg => justify-content-row-evenly.svg} (100%) rename frontend/resources/images/icons/{justify-content-row-start-refactor.svg => justify-content-row-start.svg} (100%) rename frontend/resources/images/icons/{layers-refactor.svg => layers.svg} (100%) rename frontend/resources/images/icons/{library-refactor.svg => library.svg} (100%) delete mode 100644 frontend/resources/images/icons/line-arrow.svg rename frontend/resources/images/icons/{locate-refactor.svg => locate.svg} (100%) rename frontend/resources/images/icons/{lock-refactor.svg => lock.svg} (100%) rename frontend/resources/images/icons/{margin-bottom-refactor.svg => margin-bottom.svg} (100%) rename frontend/resources/images/icons/{margin-left-right-refactor.svg => margin-left-right.svg} (100%) rename frontend/resources/images/icons/{margin-left-refactor.svg => margin-left.svg} (100%) rename frontend/resources/images/icons/{margin-right-refactor.svg => margin-right.svg} (100%) rename frontend/resources/images/icons/{margin-top-bottom-refactor.svg => margin-top-bottom.svg} (100%) rename frontend/resources/images/icons/{margin-top-refactor.svg => margin-top.svg} (100%) rename frontend/resources/images/icons/{margin-refactor.svg => margin.svg} (100%) rename frontend/resources/images/icons/{mask-refactor.svg => mask.svg} (100%) rename frontend/resources/images/icons/{masked-refactor.svg => masked.svg} (100%) rename frontend/resources/images/icons/{menu-refactor.svg => menu.svg} (100%) rename frontend/resources/images/icons/{merge-nodes-refactor.svg => merge-nodes.svg} (100%) rename frontend/resources/images/icons/{move-refactor.svg => move.svg} (100%) rename frontend/resources/images/icons/{msg-error-refactor.svg => msg-error.svg} (100%) rename frontend/resources/images/icons/{msg-neutral-refactor.svg => msg-neutral.svg} (100%) rename frontend/resources/images/icons/{msg-success-refactor.svg => msg-success.svg} (100%) rename frontend/resources/images/icons/{msg-warning-refactor.svg => msg-warning.svg} (100%) delete mode 100644 frontend/resources/images/icons/multi-canvas.svg rename frontend/resources/images/icons/{open-link-refactor.svg => open-link.svg} (100%) rename frontend/resources/images/icons/{padding-bottom-refactor.svg => padding-bottom.svg} (100%) rename frontend/resources/images/icons/{padding-extended-refactor.svg => padding-extended.svg} (100%) rename frontend/resources/images/icons/{padding-left-right-refactor.svg => padding-left-right.svg} (100%) rename frontend/resources/images/icons/{padding-left-refactor.svg => padding-left.svg} (100%) rename frontend/resources/images/icons/{padding-right-refactor.svg => padding-right.svg} (100%) rename frontend/resources/images/icons/{padding-top-bottom-refactor.svg => padding-top-bottom.svg} (100%) rename frontend/resources/images/icons/{padding-top-refactor.svg => padding-top.svg} (100%) rename frontend/resources/images/icons/{path-refactor.svg => path.svg} (100%) rename frontend/resources/images/icons/{pentool-refactor.svg => pentool.svg} (100%) rename frontend/resources/images/icons/{picker-refactor.svg => picker.svg} (100%) rename frontend/resources/images/icons/{pin-refactor.svg => pin.svg} (100%) rename frontend/resources/images/icons/{play-refactor.svg => play.svg} (100%) rename frontend/resources/images/icons/{rectangle-refactor.svg => rectangle.svg} (100%) rename frontend/resources/images/icons/{reload-refactor.svg => reload.svg} (100%) rename frontend/resources/images/icons/{remove-refactor.svg => remove.svg} (100%) rename frontend/resources/images/icons/{rgba-complementary-refactor.svg => rgba-complementary.svg} (100%) rename frontend/resources/images/icons/{rgba-refactor.svg => rgba.svg} (100%) rename frontend/resources/images/icons/{rotation-refactor.svg => rotation.svg} (100%) rename frontend/resources/images/icons/{row-reverse-refactor.svg => row-reverse.svg} (100%) rename frontend/resources/images/icons/{row-refactor.svg => row.svg} (100%) rename frontend/resources/images/icons/{search-refactor.svg => search.svg} (100%) rename frontend/resources/images/icons/{separate-nodes-refactor.svg => separate-nodes.svg} (100%) rename frontend/resources/images/icons/{shown-refactor.svg => shown.svg} (100%) rename frontend/resources/images/icons/{size-horizontal-refactor.svg => size-horizontal.svg} (100%) rename frontend/resources/images/icons/{size-vertical-refactor.svg => size-vertical.svg} (100%) rename frontend/resources/images/icons/{snap-nodes-refactor.svg => snap-nodes.svg} (100%) rename frontend/resources/images/icons/{status-alert-refactor.svg => status-alert.svg} (100%) rename frontend/resources/images/icons/{status-tick-refactor.svg => status-tick.svg} (100%) rename frontend/resources/images/icons/{status-update-refactor.svg => status-update.svg} (100%) rename frontend/resources/images/icons/{status-wrong-refactor.svg => status-wrong.svg} (100%) rename frontend/resources/images/icons/{stroke-arrow-refactor.svg => stroke-arrow.svg} (100%) rename frontend/resources/images/icons/{stroke-circle-refactor.svg => stroke-circle.svg} (100%) rename frontend/resources/images/icons/{stroke-diamond-refactor.svg => stroke-diamond.svg} (100%) rename frontend/resources/images/icons/{stroke-rectangle-refactor.svg => stroke-rectangle.svg} (100%) rename frontend/resources/images/icons/{stroke-rounded-refactor.svg => stroke-rounded.svg} (100%) rename frontend/resources/images/icons/{stroke-size-refactor.svg => stroke-size.svg} (100%) rename frontend/resources/images/icons/{stroke-squared-refactor.svg => stroke-squared.svg} (100%) rename frontend/resources/images/icons/{stroke-triangle-refactor.svg => stroke-triangle.svg} (100%) rename frontend/resources/images/icons/{svg-refactor.svg => svg.svg} (100%) rename frontend/resources/images/icons/{swatches-refactor.svg => swatches.svg} (100%) rename frontend/resources/images/icons/{switch-refactor.svg => switch.svg} (100%) rename frontend/resources/images/icons/{text-align-center-refactor.svg => text-align-center.svg} (100%) rename frontend/resources/images/icons/{text-align-left-refactor.svg => text-align-left.svg} (100%) rename frontend/resources/images/icons/{text-align-right-refactor.svg => text-align-right.svg} (100%) rename frontend/resources/images/icons/{text-auto-height-refactor.svg => text-auto-height.svg} (100%) rename frontend/resources/images/icons/{text-auto-width-refactor.svg => text-auto-width.svg} (100%) rename frontend/resources/images/icons/{text-bottom-refactor.svg => text-bottom.svg} (100%) rename frontend/resources/images/icons/{text-fixed-refactor.svg => text-fixed.svg} (100%) rename frontend/resources/images/icons/{text-justify-refactor.svg => text-justify.svg} (100%) rename frontend/resources/images/icons/{text-letterspacing-refactor.svg => text-letterspacing.svg} (100%) rename frontend/resources/images/icons/{text-lineheight-refactor.svg => text-lineheight.svg} (100%) rename frontend/resources/images/icons/{text-lowercase-refactor.svg => text-lowercase.svg} (100%) rename frontend/resources/images/icons/{text-ltr-refactor.svg => text-ltr.svg} (100%) rename frontend/resources/images/icons/{text-middle-refactor.svg => text-middle.svg} (100%) rename frontend/resources/images/icons/{text-mixed-refactor.svg => text-mixed.svg} (100%) rename frontend/resources/images/icons/{text-palette-refactor.svg => text-palette.svg} (100%) rename frontend/resources/images/icons/{text-paragraph-refactor.svg => text-paragraph.svg} (100%) rename frontend/resources/images/icons/{text-rtl-refactor.svg => text-rtl.svg} (100%) rename frontend/resources/images/icons/{text-stroked-refactor.svg => text-stroked.svg} (100%) rename frontend/resources/images/icons/{text-top-refactor.svg => text-top.svg} (100%) rename frontend/resources/images/icons/{text-underlined-refactor.svg => text-underlined.svg} (100%) rename frontend/resources/images/icons/{text-uppercase-refactor.svg => text-uppercase.svg} (100%) rename frontend/resources/images/icons/{text-refactor.svg => text.svg} (100%) rename frontend/resources/images/icons/{thumbnail-refactor.svg => thumbnail.svg} (100%) rename frontend/resources/images/icons/{tick-refactor.svg => tick.svg} (100%) rename frontend/resources/images/icons/{to-corner-refactor.svg => to-corner.svg} (100%) rename frontend/resources/images/icons/{to-curve-refactor.svg => to-curve.svg} (100%) rename frontend/resources/images/icons/{tree-refactor.svg => tree.svg} (100%) delete mode 100644 frontend/resources/images/icons/unchain.svg rename frontend/resources/images/icons/{unlock-refactor.svg => unlock.svg} (100%) rename frontend/resources/images/icons/{user-refactor.svg => user.svg} (100%) rename frontend/resources/images/icons/{vertical-align-items-center-refactor.svg => vertical-align-items-center.svg} (100%) rename frontend/resources/images/icons/{vertical-align-items-end-refactor.svg => vertical-align-items-end.svg} (100%) rename frontend/resources/images/icons/{vertical-align-items-start-refactor.svg => vertical-align-items-start.svg} (100%) rename frontend/resources/images/icons/{view-as-icons-refactor.svg => view-as-icons.svg} (100%) rename frontend/resources/images/icons/{view-as-list-refactor.svg => view-as-list.svg} (100%) diff --git a/frontend/resources/images/icons/align-items-column-end-refactor.svg b/frontend/resources/images/icons/align-items-column-end.svg similarity index 100% rename from frontend/resources/images/icons/align-items-column-end-refactor.svg rename to frontend/resources/images/icons/align-items-column-end.svg diff --git a/frontend/resources/images/icons/align-items-column-start-refactor.svg b/frontend/resources/images/icons/align-items-column-start.svg similarity index 100% rename from frontend/resources/images/icons/align-items-column-start-refactor.svg rename to frontend/resources/images/icons/align-items-column-start.svg diff --git a/frontend/resources/images/icons/align-items-row-center-refactor.svg b/frontend/resources/images/icons/align-items-row-center.svg similarity index 100% rename from frontend/resources/images/icons/align-items-row-center-refactor.svg rename to frontend/resources/images/icons/align-items-row-center.svg diff --git a/frontend/resources/images/icons/align-items-row-end-refactor.svg b/frontend/resources/images/icons/align-items-row-end.svg similarity index 100% rename from frontend/resources/images/icons/align-items-row-end-refactor.svg rename to frontend/resources/images/icons/align-items-row-end.svg diff --git a/frontend/resources/images/icons/align-items-row-start-refactor.svg b/frontend/resources/images/icons/align-items-row-start.svg similarity index 100% rename from frontend/resources/images/icons/align-items-row-start-refactor.svg rename to frontend/resources/images/icons/align-items-row-start.svg diff --git a/frontend/resources/images/icons/align-left-refactor.svg b/frontend/resources/images/icons/align-left.svg similarity index 100% rename from frontend/resources/images/icons/align-left-refactor.svg rename to frontend/resources/images/icons/align-left.svg diff --git a/frontend/resources/images/icons/align-right-refactor.svg b/frontend/resources/images/icons/align-right.svg similarity index 100% rename from frontend/resources/images/icons/align-right-refactor.svg rename to frontend/resources/images/icons/align-right.svg diff --git a/frontend/resources/images/icons/align-self-column-bottom-refactor.svg b/frontend/resources/images/icons/align-self-column-bottom.svg similarity index 100% rename from frontend/resources/images/icons/align-self-column-bottom-refactor.svg rename to frontend/resources/images/icons/align-self-column-bottom.svg diff --git a/frontend/resources/images/icons/align-self-column-center-refactor.svg b/frontend/resources/images/icons/align-self-column-center.svg similarity index 100% rename from frontend/resources/images/icons/align-self-column-center-refactor.svg rename to frontend/resources/images/icons/align-self-column-center.svg diff --git a/frontend/resources/images/icons/align-self-column-stretch-refactor.svg b/frontend/resources/images/icons/align-self-column-stretch.svg similarity index 100% rename from frontend/resources/images/icons/align-self-column-stretch-refactor.svg rename to frontend/resources/images/icons/align-self-column-stretch.svg diff --git a/frontend/resources/images/icons/align-self-column-top-refactor.svg b/frontend/resources/images/icons/align-self-column-top.svg similarity index 100% rename from frontend/resources/images/icons/align-self-column-top-refactor.svg rename to frontend/resources/images/icons/align-self-column-top.svg diff --git a/frontend/resources/images/icons/align-self-row-center-refactor.svg b/frontend/resources/images/icons/align-self-row-center.svg similarity index 100% rename from frontend/resources/images/icons/align-self-row-center-refactor.svg rename to frontend/resources/images/icons/align-self-row-center.svg diff --git a/frontend/resources/images/icons/align-self-row-left-refactor.svg b/frontend/resources/images/icons/align-self-row-left.svg similarity index 100% rename from frontend/resources/images/icons/align-self-row-left-refactor.svg rename to frontend/resources/images/icons/align-self-row-left.svg diff --git a/frontend/resources/images/icons/align-self-row-right-refactor.svg b/frontend/resources/images/icons/align-self-row-right.svg similarity index 100% rename from frontend/resources/images/icons/align-self-row-right-refactor.svg rename to frontend/resources/images/icons/align-self-row-right.svg diff --git a/frontend/resources/images/icons/align-self-row-stretch-refactor.svg b/frontend/resources/images/icons/align-self-row-stretch.svg similarity index 100% rename from frontend/resources/images/icons/align-self-row-stretch-refactor.svg rename to frontend/resources/images/icons/align-self-row-stretch.svg diff --git a/frontend/resources/images/icons/align-top-refactor.svg b/frontend/resources/images/icons/align-top.svg similarity index 100% rename from frontend/resources/images/icons/align-top-refactor.svg rename to frontend/resources/images/icons/align-top.svg diff --git a/frontend/resources/images/icons/align-vertical-center-refactor.svg b/frontend/resources/images/icons/align-vertical-center.svg similarity index 100% rename from frontend/resources/images/icons/align-vertical-center-refactor.svg rename to frontend/resources/images/icons/align-vertical-center.svg diff --git a/frontend/resources/images/icons/arrow-refactor.svg b/frontend/resources/images/icons/arrow.svg similarity index 100% rename from frontend/resources/images/icons/arrow-refactor.svg rename to frontend/resources/images/icons/arrow.svg diff --git a/frontend/resources/images/icons/asc-sort-refactor.svg b/frontend/resources/images/icons/asc-sort.svg similarity index 100% rename from frontend/resources/images/icons/asc-sort-refactor.svg rename to frontend/resources/images/icons/asc-sort.svg diff --git a/frontend/resources/images/icons/auto-grid.svg b/frontend/resources/images/icons/auto-grid.svg deleted file mode 100644 index c2acf2476..000000000 --- a/frontend/resources/images/icons/auto-grid.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/board-refactor.svg b/frontend/resources/images/icons/board.svg similarity index 100% rename from frontend/resources/images/icons/board-refactor.svg rename to frontend/resources/images/icons/board.svg diff --git a/frontend/resources/images/icons/boards-thumbnail-refactor.svg b/frontend/resources/images/icons/boards-thumbnail.svg similarity index 100% rename from frontend/resources/images/icons/boards-thumbnail-refactor.svg rename to frontend/resources/images/icons/boards-thumbnail.svg diff --git a/frontend/resources/images/icons/boolean-difference-refactor.svg b/frontend/resources/images/icons/boolean-difference.svg similarity index 100% rename from frontend/resources/images/icons/boolean-difference-refactor.svg rename to frontend/resources/images/icons/boolean-difference.svg diff --git a/frontend/resources/images/icons/boolean-exclude-refactor.svg b/frontend/resources/images/icons/boolean-exclude.svg similarity index 100% rename from frontend/resources/images/icons/boolean-exclude-refactor.svg rename to frontend/resources/images/icons/boolean-exclude.svg diff --git a/frontend/resources/images/icons/boolean-flatten-refactor.svg b/frontend/resources/images/icons/boolean-flatten.svg similarity index 100% rename from frontend/resources/images/icons/boolean-flatten-refactor.svg rename to frontend/resources/images/icons/boolean-flatten.svg diff --git a/frontend/resources/images/icons/boolean-intersection-refactor.svg b/frontend/resources/images/icons/boolean-intersection.svg similarity index 100% rename from frontend/resources/images/icons/boolean-intersection-refactor.svg rename to frontend/resources/images/icons/boolean-intersection.svg diff --git a/frontend/resources/images/icons/boolean-union-refactor.svg b/frontend/resources/images/icons/boolean-union.svg similarity index 100% rename from frontend/resources/images/icons/boolean-union-refactor.svg rename to frontend/resources/images/icons/boolean-union.svg diff --git a/frontend/resources/images/icons/bug-refactor.svg b/frontend/resources/images/icons/bug.svg similarity index 100% rename from frontend/resources/images/icons/bug-refactor.svg rename to frontend/resources/images/icons/bug.svg diff --git a/frontend/resources/images/icons/clip-content-refactor.svg b/frontend/resources/images/icons/clip-content.svg similarity index 100% rename from frontend/resources/images/icons/clip-content-refactor.svg rename to frontend/resources/images/icons/clip-content.svg diff --git a/frontend/resources/images/icons/clipboard-refactor.svg b/frontend/resources/images/icons/clipboard.svg similarity index 100% rename from frontend/resources/images/icons/clipboard-refactor.svg rename to frontend/resources/images/icons/clipboard.svg diff --git a/frontend/resources/images/icons/close-small-refactor.svg b/frontend/resources/images/icons/close-small.svg similarity index 100% rename from frontend/resources/images/icons/close-small-refactor.svg rename to frontend/resources/images/icons/close-small.svg diff --git a/frontend/resources/images/icons/close-refactor.svg b/frontend/resources/images/icons/close.svg similarity index 100% rename from frontend/resources/images/icons/close-refactor.svg rename to frontend/resources/images/icons/close.svg diff --git a/frontend/resources/images/icons/code-refactor.svg b/frontend/resources/images/icons/code.svg similarity index 100% rename from frontend/resources/images/icons/code-refactor.svg rename to frontend/resources/images/icons/code.svg diff --git a/frontend/resources/images/icons/column-reverse-refactor.svg b/frontend/resources/images/icons/column-reverse.svg similarity index 100% rename from frontend/resources/images/icons/column-reverse-refactor.svg rename to frontend/resources/images/icons/column-reverse.svg diff --git a/frontend/resources/images/icons/column-refactor.svg b/frontend/resources/images/icons/column.svg similarity index 100% rename from frontend/resources/images/icons/column-refactor.svg rename to frontend/resources/images/icons/column.svg diff --git a/frontend/resources/images/icons/comments-refactor.svg b/frontend/resources/images/icons/comments.svg similarity index 100% rename from frontend/resources/images/icons/comments-refactor.svg rename to frontend/resources/images/icons/comments.svg diff --git a/frontend/resources/images/icons/copy-refactor.svg b/frontend/resources/images/icons/component-copy.svg similarity index 100% rename from frontend/resources/images/icons/copy-refactor.svg rename to frontend/resources/images/icons/component-copy.svg diff --git a/frontend/resources/images/icons/component-refactor.svg b/frontend/resources/images/icons/component.svg similarity index 100% rename from frontend/resources/images/icons/component-refactor.svg rename to frontend/resources/images/icons/component.svg diff --git a/frontend/resources/images/icons/constraint-horizontal-refactor.svg b/frontend/resources/images/icons/constraint-horizontal.svg similarity index 100% rename from frontend/resources/images/icons/constraint-horizontal-refactor.svg rename to frontend/resources/images/icons/constraint-horizontal.svg diff --git a/frontend/resources/images/icons/constraint-vertical-refactor.svg b/frontend/resources/images/icons/constraint-vertical.svg similarity index 100% rename from frontend/resources/images/icons/constraint-vertical-refactor.svg rename to frontend/resources/images/icons/constraint-vertical.svg diff --git a/frontend/resources/images/icons/corner-bottomleft-refactor.svg b/frontend/resources/images/icons/corner-bottom-left.svg similarity index 100% rename from frontend/resources/images/icons/corner-bottomleft-refactor.svg rename to frontend/resources/images/icons/corner-bottom-left.svg diff --git a/frontend/resources/images/icons/corner-bottomright-refactor.svg b/frontend/resources/images/icons/corner-bottom-right.svg similarity index 100% rename from frontend/resources/images/icons/corner-bottomright-refactor.svg rename to frontend/resources/images/icons/corner-bottom-right.svg diff --git a/frontend/resources/images/icons/corner-bottom-refactor.svg b/frontend/resources/images/icons/corner-bottom.svg similarity index 100% rename from frontend/resources/images/icons/corner-bottom-refactor.svg rename to frontend/resources/images/icons/corner-bottom.svg diff --git a/frontend/resources/images/icons/corner-center-refactor.svg b/frontend/resources/images/icons/corner-center.svg similarity index 100% rename from frontend/resources/images/icons/corner-center-refactor.svg rename to frontend/resources/images/icons/corner-center.svg diff --git a/frontend/resources/images/icons/corner-radius-refactor.svg b/frontend/resources/images/icons/corner-radius.svg similarity index 100% rename from frontend/resources/images/icons/corner-radius-refactor.svg rename to frontend/resources/images/icons/corner-radius.svg diff --git a/frontend/resources/images/icons/corner-topleft-refactor.svg b/frontend/resources/images/icons/corner-top-left.svg similarity index 100% rename from frontend/resources/images/icons/corner-topleft-refactor.svg rename to frontend/resources/images/icons/corner-top-left.svg diff --git a/frontend/resources/images/icons/corner-topright-refactor.svg b/frontend/resources/images/icons/corner-top-right.svg similarity index 100% rename from frontend/resources/images/icons/corner-topright-refactor.svg rename to frontend/resources/images/icons/corner-top-right.svg diff --git a/frontend/resources/images/icons/corner-top-refactor.svg b/frontend/resources/images/icons/corner-top.svg similarity index 100% rename from frontend/resources/images/icons/corner-top-refactor.svg rename to frontend/resources/images/icons/corner-top.svg diff --git a/frontend/resources/images/icons/curve-refactor.svg b/frontend/resources/images/icons/curve.svg similarity index 100% rename from frontend/resources/images/icons/curve-refactor.svg rename to frontend/resources/images/icons/curve.svg diff --git a/frontend/resources/images/icons/delete-text-refactor.svg b/frontend/resources/images/icons/delete-text.svg similarity index 100% rename from frontend/resources/images/icons/delete-text-refactor.svg rename to frontend/resources/images/icons/delete-text.svg diff --git a/frontend/resources/images/icons/delete-refactor.svg b/frontend/resources/images/icons/delete.svg similarity index 100% rename from frontend/resources/images/icons/delete-refactor.svg rename to frontend/resources/images/icons/delete.svg diff --git a/frontend/resources/images/icons/desc-sort-refactor.svg b/frontend/resources/images/icons/desc-sort.svg similarity index 100% rename from frontend/resources/images/icons/desc-sort-refactor.svg rename to frontend/resources/images/icons/desc-sort.svg diff --git a/frontend/resources/images/icons/detach-refactor.svg b/frontend/resources/images/icons/detach.svg similarity index 100% rename from frontend/resources/images/icons/detach-refactor.svg rename to frontend/resources/images/icons/detach.svg diff --git a/frontend/resources/images/icons/detached-refactor.svg b/frontend/resources/images/icons/detached.svg similarity index 100% rename from frontend/resources/images/icons/detached-refactor.svg rename to frontend/resources/images/icons/detached.svg diff --git a/frontend/resources/images/icons/distribute-horizontally-refactor.svg b/frontend/resources/images/icons/distribute-horizontally.svg similarity index 100% rename from frontend/resources/images/icons/distribute-horizontally-refactor.svg rename to frontend/resources/images/icons/distribute-horizontally.svg diff --git a/frontend/resources/images/icons/distribute-vertical-spacing-refactor.svg b/frontend/resources/images/icons/distribute-vertical-spacing.svg similarity index 100% rename from frontend/resources/images/icons/distribute-vertical-spacing-refactor.svg rename to frontend/resources/images/icons/distribute-vertical-spacing.svg diff --git a/frontend/resources/images/icons/document-refactor.svg b/frontend/resources/images/icons/document.svg similarity index 100% rename from frontend/resources/images/icons/document-refactor.svg rename to frontend/resources/images/icons/document.svg diff --git a/frontend/resources/images/icons/download-refactor.svg b/frontend/resources/images/icons/download.svg similarity index 100% rename from frontend/resources/images/icons/download-refactor.svg rename to frontend/resources/images/icons/download.svg diff --git a/frontend/resources/images/icons/drop-refactor.svg b/frontend/resources/images/icons/drop.svg similarity index 100% rename from frontend/resources/images/icons/drop-refactor.svg rename to frontend/resources/images/icons/drop.svg diff --git a/frontend/resources/images/icons/easing-ease-in-out-refactor.svg b/frontend/resources/images/icons/easing-ease-in-out.svg similarity index 100% rename from frontend/resources/images/icons/easing-ease-in-out-refactor.svg rename to frontend/resources/images/icons/easing-ease-in-out.svg diff --git a/frontend/resources/images/icons/easing-ease-in-refactor.svg b/frontend/resources/images/icons/easing-ease-in.svg similarity index 100% rename from frontend/resources/images/icons/easing-ease-in-refactor.svg rename to frontend/resources/images/icons/easing-ease-in.svg diff --git a/frontend/resources/images/icons/easing-ease-out-refactor.svg b/frontend/resources/images/icons/easing-ease-out.svg similarity index 100% rename from frontend/resources/images/icons/easing-ease-out-refactor.svg rename to frontend/resources/images/icons/easing-ease-out.svg diff --git a/frontend/resources/images/icons/easing-ease-refactor.svg b/frontend/resources/images/icons/easing-ease.svg similarity index 100% rename from frontend/resources/images/icons/easing-ease-refactor.svg rename to frontend/resources/images/icons/easing-ease.svg diff --git a/frontend/resources/images/icons/easing-linear-refactor.svg b/frontend/resources/images/icons/easing-linear.svg similarity index 100% rename from frontend/resources/images/icons/easing-linear-refactor.svg rename to frontend/resources/images/icons/easing-linear.svg diff --git a/frontend/resources/images/icons/effects-refactor.svg b/frontend/resources/images/icons/effects.svg similarity index 100% rename from frontend/resources/images/icons/effects-refactor.svg rename to frontend/resources/images/icons/effects.svg diff --git a/frontend/resources/images/icons/elipse-refactor.svg b/frontend/resources/images/icons/elipse.svg similarity index 100% rename from frontend/resources/images/icons/elipse-refactor.svg rename to frontend/resources/images/icons/elipse.svg diff --git a/frontend/resources/images/icons/exit-refactor.svg b/frontend/resources/images/icons/exit.svg similarity index 100% rename from frontend/resources/images/icons/exit-refactor.svg rename to frontend/resources/images/icons/exit.svg diff --git a/frontend/resources/images/icons/expand-refactor.svg b/frontend/resources/images/icons/expand.svg similarity index 100% rename from frontend/resources/images/icons/expand-refactor.svg rename to frontend/resources/images/icons/expand.svg diff --git a/frontend/resources/images/icons/feedback-refactor.svg b/frontend/resources/images/icons/feedback.svg similarity index 100% rename from frontend/resources/images/icons/feedback-refactor.svg rename to frontend/resources/images/icons/feedback.svg diff --git a/frontend/resources/images/icons/fill-content-refactor.svg b/frontend/resources/images/icons/fill-content.svg similarity index 100% rename from frontend/resources/images/icons/fill-content-refactor.svg rename to frontend/resources/images/icons/fill-content.svg diff --git a/frontend/resources/images/icons/filter-refactor.svg b/frontend/resources/images/icons/filter.svg similarity index 100% rename from frontend/resources/images/icons/filter-refactor.svg rename to frontend/resources/images/icons/filter.svg diff --git a/frontend/resources/images/icons/fixed-width-refactor.svg b/frontend/resources/images/icons/fixed-width.svg similarity index 100% rename from frontend/resources/images/icons/fixed-width-refactor.svg rename to frontend/resources/images/icons/fixed-width.svg diff --git a/frontend/resources/images/icons/flex-grid-refactor.svg b/frontend/resources/images/icons/flex-grid.svg similarity index 100% rename from frontend/resources/images/icons/flex-grid-refactor.svg rename to frontend/resources/images/icons/flex-grid.svg diff --git a/frontend/resources/images/icons/flex-horizontal-refactor.svg b/frontend/resources/images/icons/flex-horizontal.svg similarity index 100% rename from frontend/resources/images/icons/flex-horizontal-refactor.svg rename to frontend/resources/images/icons/flex-horizontal.svg diff --git a/frontend/resources/images/icons/flex-vertical-refactor.svg b/frontend/resources/images/icons/flex-vertical.svg similarity index 100% rename from frontend/resources/images/icons/flex-vertical-refactor.svg rename to frontend/resources/images/icons/flex-vertical.svg diff --git a/frontend/resources/images/icons/flex-refactor.svg b/frontend/resources/images/icons/flex.svg similarity index 100% rename from frontend/resources/images/icons/flex-refactor.svg rename to frontend/resources/images/icons/flex.svg diff --git a/frontend/resources/images/icons/flip-horizontal-refactor.svg b/frontend/resources/images/icons/flip-horizontal.svg similarity index 100% rename from frontend/resources/images/icons/flip-horizontal-refactor.svg rename to frontend/resources/images/icons/flip-horizontal.svg diff --git a/frontend/resources/images/icons/flip-vertical-refactor.svg b/frontend/resources/images/icons/flip-vertical.svg similarity index 100% rename from frontend/resources/images/icons/flip-vertical-refactor.svg rename to frontend/resources/images/icons/flip-vertical.svg diff --git a/frontend/resources/images/icons/gap-horizontal-refactor.svg b/frontend/resources/images/icons/gap-horizontal.svg similarity index 100% rename from frontend/resources/images/icons/gap-horizontal-refactor.svg rename to frontend/resources/images/icons/gap-horizontal.svg diff --git a/frontend/resources/images/icons/gap-vertical-refactor.svg b/frontend/resources/images/icons/gap-vertical.svg similarity index 100% rename from frontend/resources/images/icons/gap-vertical-refactor.svg rename to frontend/resources/images/icons/gap-vertical.svg diff --git a/frontend/resources/images/icons/graphics-refactor.svg b/frontend/resources/images/icons/graphics.svg similarity index 100% rename from frontend/resources/images/icons/graphics-refactor.svg rename to frontend/resources/images/icons/graphics.svg diff --git a/frontend/resources/images/icons/grid-column-refactor.svg b/frontend/resources/images/icons/grid-column.svg similarity index 100% rename from frontend/resources/images/icons/grid-column-refactor.svg rename to frontend/resources/images/icons/grid-column.svg diff --git a/frontend/resources/images/icons/grid-columns-refactor.svg b/frontend/resources/images/icons/grid-columns.svg similarity index 100% rename from frontend/resources/images/icons/grid-columns-refactor.svg rename to frontend/resources/images/icons/grid-columns.svg diff --git a/frontend/resources/images/icons/grid-gutter-refactor.svg b/frontend/resources/images/icons/grid-gutter.svg similarity index 100% rename from frontend/resources/images/icons/grid-gutter-refactor.svg rename to frontend/resources/images/icons/grid-gutter.svg diff --git a/frontend/resources/images/icons/grid-margin-refactor.svg b/frontend/resources/images/icons/grid-margin.svg similarity index 100% rename from frontend/resources/images/icons/grid-margin-refactor.svg rename to frontend/resources/images/icons/grid-margin.svg diff --git a/frontend/resources/images/icons/grid-row-refactor.svg b/frontend/resources/images/icons/grid-row.svg similarity index 100% rename from frontend/resources/images/icons/grid-row-refactor.svg rename to frontend/resources/images/icons/grid-row.svg diff --git a/frontend/resources/images/icons/grid-rows-refactor.svg b/frontend/resources/images/icons/grid-rows.svg similarity index 100% rename from frontend/resources/images/icons/grid-rows-refactor.svg rename to frontend/resources/images/icons/grid-rows.svg diff --git a/frontend/resources/images/icons/grid-square-refactor.svg b/frontend/resources/images/icons/grid-square.svg similarity index 100% rename from frontend/resources/images/icons/grid-square-refactor.svg rename to frontend/resources/images/icons/grid-square.svg diff --git a/frontend/resources/images/icons/grid-refactor.svg b/frontend/resources/images/icons/grid.svg similarity index 100% rename from frontend/resources/images/icons/grid-refactor.svg rename to frontend/resources/images/icons/grid.svg diff --git a/frontend/resources/images/icons/group-refactor.svg b/frontend/resources/images/icons/group.svg similarity index 100% rename from frontend/resources/images/icons/group-refactor.svg rename to frontend/resources/images/icons/group.svg diff --git a/frontend/resources/images/icons/gutter-horizontal-refactor.svg b/frontend/resources/images/icons/gutter-horizontal.svg similarity index 100% rename from frontend/resources/images/icons/gutter-horizontal-refactor.svg rename to frontend/resources/images/icons/gutter-horizontal.svg diff --git a/frontend/resources/images/icons/gutter-vertical-refactor.svg b/frontend/resources/images/icons/gutter-vertical.svg similarity index 100% rename from frontend/resources/images/icons/gutter-vertical-refactor.svg rename to frontend/resources/images/icons/gutter-vertical.svg diff --git a/frontend/resources/images/icons/help-refactor.svg b/frontend/resources/images/icons/help.svg similarity index 100% rename from frontend/resources/images/icons/help-refactor.svg rename to frontend/resources/images/icons/help.svg diff --git a/frontend/resources/images/icons/hide-refactor.svg b/frontend/resources/images/icons/hide.svg similarity index 100% rename from frontend/resources/images/icons/hide-refactor.svg rename to frontend/resources/images/icons/hide.svg diff --git a/frontend/resources/images/icons/history-refactor.svg b/frontend/resources/images/icons/history.svg similarity index 100% rename from frontend/resources/images/icons/history-refactor.svg rename to frontend/resources/images/icons/history.svg diff --git a/frontend/resources/images/icons/hsva-refactor.svg b/frontend/resources/images/icons/hsva.svg similarity index 100% rename from frontend/resources/images/icons/hsva-refactor.svg rename to frontend/resources/images/icons/hsva.svg diff --git a/frontend/resources/images/icons/hug-content-refactor.svg b/frontend/resources/images/icons/hug-content.svg similarity index 100% rename from frontend/resources/images/icons/hug-content-refactor.svg rename to frontend/resources/images/icons/hug-content.svg diff --git a/frontend/resources/images/icons/icon-refactor.svg b/frontend/resources/images/icons/icon.svg similarity index 100% rename from frontend/resources/images/icons/icon-refactor.svg rename to frontend/resources/images/icons/icon.svg diff --git a/frontend/resources/images/icons/img-refactor.svg b/frontend/resources/images/icons/img.svg similarity index 100% rename from frontend/resources/images/icons/img-refactor.svg rename to frontend/resources/images/icons/img.svg diff --git a/frontend/resources/images/icons/interaction-refactor.svg b/frontend/resources/images/icons/interaction.svg similarity index 100% rename from frontend/resources/images/icons/interaction-refactor.svg rename to frontend/resources/images/icons/interaction.svg diff --git a/frontend/resources/images/icons/join-nodes-refactor.svg b/frontend/resources/images/icons/join-nodes.svg similarity index 100% rename from frontend/resources/images/icons/join-nodes-refactor.svg rename to frontend/resources/images/icons/join-nodes.svg diff --git a/frontend/resources/images/icons/justify-content-column-around-refactor.svg b/frontend/resources/images/icons/justify-content-column-around.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-column-around-refactor.svg rename to frontend/resources/images/icons/justify-content-column-around.svg diff --git a/frontend/resources/images/icons/justify-content-column-between-refactor.svg b/frontend/resources/images/icons/justify-content-column-between.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-column-between-refactor.svg rename to frontend/resources/images/icons/justify-content-column-between.svg diff --git a/frontend/resources/images/icons/justify-content-column-center-refactor.svg b/frontend/resources/images/icons/justify-content-column-center.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-column-center-refactor.svg rename to frontend/resources/images/icons/justify-content-column-center.svg diff --git a/frontend/resources/images/icons/justify-content-column-end-refactor.svg b/frontend/resources/images/icons/justify-content-column-end.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-column-end-refactor.svg rename to frontend/resources/images/icons/justify-content-column-end.svg diff --git a/frontend/resources/images/icons/justify-content-column-evenly-refactor.svg b/frontend/resources/images/icons/justify-content-column-evenly.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-column-evenly-refactor.svg rename to frontend/resources/images/icons/justify-content-column-evenly.svg diff --git a/frontend/resources/images/icons/justify-content-column-start-refactor.svg b/frontend/resources/images/icons/justify-content-column-start.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-column-start-refactor.svg rename to frontend/resources/images/icons/justify-content-column-start.svg diff --git a/frontend/resources/images/icons/justify-content-row-around-refactor.svg b/frontend/resources/images/icons/justify-content-row-around.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-row-around-refactor.svg rename to frontend/resources/images/icons/justify-content-row-around.svg diff --git a/frontend/resources/images/icons/justify-content-row-between-refactor.svg b/frontend/resources/images/icons/justify-content-row-between.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-row-between-refactor.svg rename to frontend/resources/images/icons/justify-content-row-between.svg diff --git a/frontend/resources/images/icons/justify-content-row-center-refactor.svg b/frontend/resources/images/icons/justify-content-row-center.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-row-center-refactor.svg rename to frontend/resources/images/icons/justify-content-row-center.svg diff --git a/frontend/resources/images/icons/justify-content-row-end-refactor.svg b/frontend/resources/images/icons/justify-content-row-end.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-row-end-refactor.svg rename to frontend/resources/images/icons/justify-content-row-end.svg diff --git a/frontend/resources/images/icons/justify-content-row-evenly-refactor.svg b/frontend/resources/images/icons/justify-content-row-evenly.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-row-evenly-refactor.svg rename to frontend/resources/images/icons/justify-content-row-evenly.svg diff --git a/frontend/resources/images/icons/justify-content-row-start-refactor.svg b/frontend/resources/images/icons/justify-content-row-start.svg similarity index 100% rename from frontend/resources/images/icons/justify-content-row-start-refactor.svg rename to frontend/resources/images/icons/justify-content-row-start.svg diff --git a/frontend/resources/images/icons/layers-refactor.svg b/frontend/resources/images/icons/layers.svg similarity index 100% rename from frontend/resources/images/icons/layers-refactor.svg rename to frontend/resources/images/icons/layers.svg diff --git a/frontend/resources/images/icons/library-refactor.svg b/frontend/resources/images/icons/library.svg similarity index 100% rename from frontend/resources/images/icons/library-refactor.svg rename to frontend/resources/images/icons/library.svg diff --git a/frontend/resources/images/icons/line-arrow.svg b/frontend/resources/images/icons/line-arrow.svg deleted file mode 100644 index aa4a34757..000000000 --- a/frontend/resources/images/icons/line-arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/resources/images/icons/locate-refactor.svg b/frontend/resources/images/icons/locate.svg similarity index 100% rename from frontend/resources/images/icons/locate-refactor.svg rename to frontend/resources/images/icons/locate.svg diff --git a/frontend/resources/images/icons/lock-refactor.svg b/frontend/resources/images/icons/lock.svg similarity index 100% rename from frontend/resources/images/icons/lock-refactor.svg rename to frontend/resources/images/icons/lock.svg diff --git a/frontend/resources/images/icons/margin-bottom-refactor.svg b/frontend/resources/images/icons/margin-bottom.svg similarity index 100% rename from frontend/resources/images/icons/margin-bottom-refactor.svg rename to frontend/resources/images/icons/margin-bottom.svg diff --git a/frontend/resources/images/icons/margin-left-right-refactor.svg b/frontend/resources/images/icons/margin-left-right.svg similarity index 100% rename from frontend/resources/images/icons/margin-left-right-refactor.svg rename to frontend/resources/images/icons/margin-left-right.svg diff --git a/frontend/resources/images/icons/margin-left-refactor.svg b/frontend/resources/images/icons/margin-left.svg similarity index 100% rename from frontend/resources/images/icons/margin-left-refactor.svg rename to frontend/resources/images/icons/margin-left.svg diff --git a/frontend/resources/images/icons/margin-right-refactor.svg b/frontend/resources/images/icons/margin-right.svg similarity index 100% rename from frontend/resources/images/icons/margin-right-refactor.svg rename to frontend/resources/images/icons/margin-right.svg diff --git a/frontend/resources/images/icons/margin-top-bottom-refactor.svg b/frontend/resources/images/icons/margin-top-bottom.svg similarity index 100% rename from frontend/resources/images/icons/margin-top-bottom-refactor.svg rename to frontend/resources/images/icons/margin-top-bottom.svg diff --git a/frontend/resources/images/icons/margin-top-refactor.svg b/frontend/resources/images/icons/margin-top.svg similarity index 100% rename from frontend/resources/images/icons/margin-top-refactor.svg rename to frontend/resources/images/icons/margin-top.svg diff --git a/frontend/resources/images/icons/margin-refactor.svg b/frontend/resources/images/icons/margin.svg similarity index 100% rename from frontend/resources/images/icons/margin-refactor.svg rename to frontend/resources/images/icons/margin.svg diff --git a/frontend/resources/images/icons/mask-refactor.svg b/frontend/resources/images/icons/mask.svg similarity index 100% rename from frontend/resources/images/icons/mask-refactor.svg rename to frontend/resources/images/icons/mask.svg diff --git a/frontend/resources/images/icons/masked-refactor.svg b/frontend/resources/images/icons/masked.svg similarity index 100% rename from frontend/resources/images/icons/masked-refactor.svg rename to frontend/resources/images/icons/masked.svg diff --git a/frontend/resources/images/icons/menu-refactor.svg b/frontend/resources/images/icons/menu.svg similarity index 100% rename from frontend/resources/images/icons/menu-refactor.svg rename to frontend/resources/images/icons/menu.svg diff --git a/frontend/resources/images/icons/merge-nodes-refactor.svg b/frontend/resources/images/icons/merge-nodes.svg similarity index 100% rename from frontend/resources/images/icons/merge-nodes-refactor.svg rename to frontend/resources/images/icons/merge-nodes.svg diff --git a/frontend/resources/images/icons/move-refactor.svg b/frontend/resources/images/icons/move.svg similarity index 100% rename from frontend/resources/images/icons/move-refactor.svg rename to frontend/resources/images/icons/move.svg diff --git a/frontend/resources/images/icons/msg-error-refactor.svg b/frontend/resources/images/icons/msg-error.svg similarity index 100% rename from frontend/resources/images/icons/msg-error-refactor.svg rename to frontend/resources/images/icons/msg-error.svg diff --git a/frontend/resources/images/icons/msg-neutral-refactor.svg b/frontend/resources/images/icons/msg-neutral.svg similarity index 100% rename from frontend/resources/images/icons/msg-neutral-refactor.svg rename to frontend/resources/images/icons/msg-neutral.svg diff --git a/frontend/resources/images/icons/msg-success-refactor.svg b/frontend/resources/images/icons/msg-success.svg similarity index 100% rename from frontend/resources/images/icons/msg-success-refactor.svg rename to frontend/resources/images/icons/msg-success.svg diff --git a/frontend/resources/images/icons/msg-warning-refactor.svg b/frontend/resources/images/icons/msg-warning.svg similarity index 100% rename from frontend/resources/images/icons/msg-warning-refactor.svg rename to frontend/resources/images/icons/msg-warning.svg diff --git a/frontend/resources/images/icons/multi-canvas.svg b/frontend/resources/images/icons/multi-canvas.svg deleted file mode 100644 index 94025eee1..000000000 --- a/frontend/resources/images/icons/multi-canvas.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/open-link-refactor.svg b/frontend/resources/images/icons/open-link.svg similarity index 100% rename from frontend/resources/images/icons/open-link-refactor.svg rename to frontend/resources/images/icons/open-link.svg diff --git a/frontend/resources/images/icons/padding-bottom-refactor.svg b/frontend/resources/images/icons/padding-bottom.svg similarity index 100% rename from frontend/resources/images/icons/padding-bottom-refactor.svg rename to frontend/resources/images/icons/padding-bottom.svg diff --git a/frontend/resources/images/icons/padding-extended-refactor.svg b/frontend/resources/images/icons/padding-extended.svg similarity index 100% rename from frontend/resources/images/icons/padding-extended-refactor.svg rename to frontend/resources/images/icons/padding-extended.svg diff --git a/frontend/resources/images/icons/padding-left-right-refactor.svg b/frontend/resources/images/icons/padding-left-right.svg similarity index 100% rename from frontend/resources/images/icons/padding-left-right-refactor.svg rename to frontend/resources/images/icons/padding-left-right.svg diff --git a/frontend/resources/images/icons/padding-left-refactor.svg b/frontend/resources/images/icons/padding-left.svg similarity index 100% rename from frontend/resources/images/icons/padding-left-refactor.svg rename to frontend/resources/images/icons/padding-left.svg diff --git a/frontend/resources/images/icons/padding-right-refactor.svg b/frontend/resources/images/icons/padding-right.svg similarity index 100% rename from frontend/resources/images/icons/padding-right-refactor.svg rename to frontend/resources/images/icons/padding-right.svg diff --git a/frontend/resources/images/icons/padding-top-bottom-refactor.svg b/frontend/resources/images/icons/padding-top-bottom.svg similarity index 100% rename from frontend/resources/images/icons/padding-top-bottom-refactor.svg rename to frontend/resources/images/icons/padding-top-bottom.svg diff --git a/frontend/resources/images/icons/padding-top-refactor.svg b/frontend/resources/images/icons/padding-top.svg similarity index 100% rename from frontend/resources/images/icons/padding-top-refactor.svg rename to frontend/resources/images/icons/padding-top.svg diff --git a/frontend/resources/images/icons/path-refactor.svg b/frontend/resources/images/icons/path.svg similarity index 100% rename from frontend/resources/images/icons/path-refactor.svg rename to frontend/resources/images/icons/path.svg diff --git a/frontend/resources/images/icons/pentool-refactor.svg b/frontend/resources/images/icons/pentool.svg similarity index 100% rename from frontend/resources/images/icons/pentool-refactor.svg rename to frontend/resources/images/icons/pentool.svg diff --git a/frontend/resources/images/icons/picker-refactor.svg b/frontend/resources/images/icons/picker.svg similarity index 100% rename from frontend/resources/images/icons/picker-refactor.svg rename to frontend/resources/images/icons/picker.svg diff --git a/frontend/resources/images/icons/pin-refactor.svg b/frontend/resources/images/icons/pin.svg similarity index 100% rename from frontend/resources/images/icons/pin-refactor.svg rename to frontend/resources/images/icons/pin.svg diff --git a/frontend/resources/images/icons/play-refactor.svg b/frontend/resources/images/icons/play.svg similarity index 100% rename from frontend/resources/images/icons/play-refactor.svg rename to frontend/resources/images/icons/play.svg diff --git a/frontend/resources/images/icons/rectangle-refactor.svg b/frontend/resources/images/icons/rectangle.svg similarity index 100% rename from frontend/resources/images/icons/rectangle-refactor.svg rename to frontend/resources/images/icons/rectangle.svg diff --git a/frontend/resources/images/icons/reload-refactor.svg b/frontend/resources/images/icons/reload.svg similarity index 100% rename from frontend/resources/images/icons/reload-refactor.svg rename to frontend/resources/images/icons/reload.svg diff --git a/frontend/resources/images/icons/remove-refactor.svg b/frontend/resources/images/icons/remove.svg similarity index 100% rename from frontend/resources/images/icons/remove-refactor.svg rename to frontend/resources/images/icons/remove.svg diff --git a/frontend/resources/images/icons/rgba-complementary-refactor.svg b/frontend/resources/images/icons/rgba-complementary.svg similarity index 100% rename from frontend/resources/images/icons/rgba-complementary-refactor.svg rename to frontend/resources/images/icons/rgba-complementary.svg diff --git a/frontend/resources/images/icons/rgba-refactor.svg b/frontend/resources/images/icons/rgba.svg similarity index 100% rename from frontend/resources/images/icons/rgba-refactor.svg rename to frontend/resources/images/icons/rgba.svg diff --git a/frontend/resources/images/icons/rotation-refactor.svg b/frontend/resources/images/icons/rotation.svg similarity index 100% rename from frontend/resources/images/icons/rotation-refactor.svg rename to frontend/resources/images/icons/rotation.svg diff --git a/frontend/resources/images/icons/row-reverse-refactor.svg b/frontend/resources/images/icons/row-reverse.svg similarity index 100% rename from frontend/resources/images/icons/row-reverse-refactor.svg rename to frontend/resources/images/icons/row-reverse.svg diff --git a/frontend/resources/images/icons/row-refactor.svg b/frontend/resources/images/icons/row.svg similarity index 100% rename from frontend/resources/images/icons/row-refactor.svg rename to frontend/resources/images/icons/row.svg diff --git a/frontend/resources/images/icons/search-refactor.svg b/frontend/resources/images/icons/search.svg similarity index 100% rename from frontend/resources/images/icons/search-refactor.svg rename to frontend/resources/images/icons/search.svg diff --git a/frontend/resources/images/icons/separate-nodes-refactor.svg b/frontend/resources/images/icons/separate-nodes.svg similarity index 100% rename from frontend/resources/images/icons/separate-nodes-refactor.svg rename to frontend/resources/images/icons/separate-nodes.svg diff --git a/frontend/resources/images/icons/shown-refactor.svg b/frontend/resources/images/icons/shown.svg similarity index 100% rename from frontend/resources/images/icons/shown-refactor.svg rename to frontend/resources/images/icons/shown.svg diff --git a/frontend/resources/images/icons/size-horizontal-refactor.svg b/frontend/resources/images/icons/size-horizontal.svg similarity index 100% rename from frontend/resources/images/icons/size-horizontal-refactor.svg rename to frontend/resources/images/icons/size-horizontal.svg diff --git a/frontend/resources/images/icons/size-vertical-refactor.svg b/frontend/resources/images/icons/size-vertical.svg similarity index 100% rename from frontend/resources/images/icons/size-vertical-refactor.svg rename to frontend/resources/images/icons/size-vertical.svg diff --git a/frontend/resources/images/icons/snap-nodes-refactor.svg b/frontend/resources/images/icons/snap-nodes.svg similarity index 100% rename from frontend/resources/images/icons/snap-nodes-refactor.svg rename to frontend/resources/images/icons/snap-nodes.svg diff --git a/frontend/resources/images/icons/status-alert-refactor.svg b/frontend/resources/images/icons/status-alert.svg similarity index 100% rename from frontend/resources/images/icons/status-alert-refactor.svg rename to frontend/resources/images/icons/status-alert.svg diff --git a/frontend/resources/images/icons/status-tick-refactor.svg b/frontend/resources/images/icons/status-tick.svg similarity index 100% rename from frontend/resources/images/icons/status-tick-refactor.svg rename to frontend/resources/images/icons/status-tick.svg diff --git a/frontend/resources/images/icons/status-update-refactor.svg b/frontend/resources/images/icons/status-update.svg similarity index 100% rename from frontend/resources/images/icons/status-update-refactor.svg rename to frontend/resources/images/icons/status-update.svg diff --git a/frontend/resources/images/icons/status-wrong-refactor.svg b/frontend/resources/images/icons/status-wrong.svg similarity index 100% rename from frontend/resources/images/icons/status-wrong-refactor.svg rename to frontend/resources/images/icons/status-wrong.svg diff --git a/frontend/resources/images/icons/stroke-arrow-refactor.svg b/frontend/resources/images/icons/stroke-arrow.svg similarity index 100% rename from frontend/resources/images/icons/stroke-arrow-refactor.svg rename to frontend/resources/images/icons/stroke-arrow.svg diff --git a/frontend/resources/images/icons/stroke-circle-refactor.svg b/frontend/resources/images/icons/stroke-circle.svg similarity index 100% rename from frontend/resources/images/icons/stroke-circle-refactor.svg rename to frontend/resources/images/icons/stroke-circle.svg diff --git a/frontend/resources/images/icons/stroke-diamond-refactor.svg b/frontend/resources/images/icons/stroke-diamond.svg similarity index 100% rename from frontend/resources/images/icons/stroke-diamond-refactor.svg rename to frontend/resources/images/icons/stroke-diamond.svg diff --git a/frontend/resources/images/icons/stroke-rectangle-refactor.svg b/frontend/resources/images/icons/stroke-rectangle.svg similarity index 100% rename from frontend/resources/images/icons/stroke-rectangle-refactor.svg rename to frontend/resources/images/icons/stroke-rectangle.svg diff --git a/frontend/resources/images/icons/stroke-rounded-refactor.svg b/frontend/resources/images/icons/stroke-rounded.svg similarity index 100% rename from frontend/resources/images/icons/stroke-rounded-refactor.svg rename to frontend/resources/images/icons/stroke-rounded.svg diff --git a/frontend/resources/images/icons/stroke-size-refactor.svg b/frontend/resources/images/icons/stroke-size.svg similarity index 100% rename from frontend/resources/images/icons/stroke-size-refactor.svg rename to frontend/resources/images/icons/stroke-size.svg diff --git a/frontend/resources/images/icons/stroke-squared-refactor.svg b/frontend/resources/images/icons/stroke-squared.svg similarity index 100% rename from frontend/resources/images/icons/stroke-squared-refactor.svg rename to frontend/resources/images/icons/stroke-squared.svg diff --git a/frontend/resources/images/icons/stroke-triangle-refactor.svg b/frontend/resources/images/icons/stroke-triangle.svg similarity index 100% rename from frontend/resources/images/icons/stroke-triangle-refactor.svg rename to frontend/resources/images/icons/stroke-triangle.svg diff --git a/frontend/resources/images/icons/svg-refactor.svg b/frontend/resources/images/icons/svg.svg similarity index 100% rename from frontend/resources/images/icons/svg-refactor.svg rename to frontend/resources/images/icons/svg.svg diff --git a/frontend/resources/images/icons/swatches-refactor.svg b/frontend/resources/images/icons/swatches.svg similarity index 100% rename from frontend/resources/images/icons/swatches-refactor.svg rename to frontend/resources/images/icons/swatches.svg diff --git a/frontend/resources/images/icons/switch-refactor.svg b/frontend/resources/images/icons/switch.svg similarity index 100% rename from frontend/resources/images/icons/switch-refactor.svg rename to frontend/resources/images/icons/switch.svg diff --git a/frontend/resources/images/icons/text-align-center-refactor.svg b/frontend/resources/images/icons/text-align-center.svg similarity index 100% rename from frontend/resources/images/icons/text-align-center-refactor.svg rename to frontend/resources/images/icons/text-align-center.svg diff --git a/frontend/resources/images/icons/text-align-left-refactor.svg b/frontend/resources/images/icons/text-align-left.svg similarity index 100% rename from frontend/resources/images/icons/text-align-left-refactor.svg rename to frontend/resources/images/icons/text-align-left.svg diff --git a/frontend/resources/images/icons/text-align-right-refactor.svg b/frontend/resources/images/icons/text-align-right.svg similarity index 100% rename from frontend/resources/images/icons/text-align-right-refactor.svg rename to frontend/resources/images/icons/text-align-right.svg diff --git a/frontend/resources/images/icons/text-auto-height-refactor.svg b/frontend/resources/images/icons/text-auto-height.svg similarity index 100% rename from frontend/resources/images/icons/text-auto-height-refactor.svg rename to frontend/resources/images/icons/text-auto-height.svg diff --git a/frontend/resources/images/icons/text-auto-width-refactor.svg b/frontend/resources/images/icons/text-auto-width.svg similarity index 100% rename from frontend/resources/images/icons/text-auto-width-refactor.svg rename to frontend/resources/images/icons/text-auto-width.svg diff --git a/frontend/resources/images/icons/text-bottom-refactor.svg b/frontend/resources/images/icons/text-bottom.svg similarity index 100% rename from frontend/resources/images/icons/text-bottom-refactor.svg rename to frontend/resources/images/icons/text-bottom.svg diff --git a/frontend/resources/images/icons/text-fixed-refactor.svg b/frontend/resources/images/icons/text-fixed.svg similarity index 100% rename from frontend/resources/images/icons/text-fixed-refactor.svg rename to frontend/resources/images/icons/text-fixed.svg diff --git a/frontend/resources/images/icons/text-justify-refactor.svg b/frontend/resources/images/icons/text-justify.svg similarity index 100% rename from frontend/resources/images/icons/text-justify-refactor.svg rename to frontend/resources/images/icons/text-justify.svg diff --git a/frontend/resources/images/icons/text-letterspacing-refactor.svg b/frontend/resources/images/icons/text-letterspacing.svg similarity index 100% rename from frontend/resources/images/icons/text-letterspacing-refactor.svg rename to frontend/resources/images/icons/text-letterspacing.svg diff --git a/frontend/resources/images/icons/text-lineheight-refactor.svg b/frontend/resources/images/icons/text-lineheight.svg similarity index 100% rename from frontend/resources/images/icons/text-lineheight-refactor.svg rename to frontend/resources/images/icons/text-lineheight.svg diff --git a/frontend/resources/images/icons/text-lowercase-refactor.svg b/frontend/resources/images/icons/text-lowercase.svg similarity index 100% rename from frontend/resources/images/icons/text-lowercase-refactor.svg rename to frontend/resources/images/icons/text-lowercase.svg diff --git a/frontend/resources/images/icons/text-ltr-refactor.svg b/frontend/resources/images/icons/text-ltr.svg similarity index 100% rename from frontend/resources/images/icons/text-ltr-refactor.svg rename to frontend/resources/images/icons/text-ltr.svg diff --git a/frontend/resources/images/icons/text-middle-refactor.svg b/frontend/resources/images/icons/text-middle.svg similarity index 100% rename from frontend/resources/images/icons/text-middle-refactor.svg rename to frontend/resources/images/icons/text-middle.svg diff --git a/frontend/resources/images/icons/text-mixed-refactor.svg b/frontend/resources/images/icons/text-mixed.svg similarity index 100% rename from frontend/resources/images/icons/text-mixed-refactor.svg rename to frontend/resources/images/icons/text-mixed.svg diff --git a/frontend/resources/images/icons/text-palette-refactor.svg b/frontend/resources/images/icons/text-palette.svg similarity index 100% rename from frontend/resources/images/icons/text-palette-refactor.svg rename to frontend/resources/images/icons/text-palette.svg diff --git a/frontend/resources/images/icons/text-paragraph-refactor.svg b/frontend/resources/images/icons/text-paragraph.svg similarity index 100% rename from frontend/resources/images/icons/text-paragraph-refactor.svg rename to frontend/resources/images/icons/text-paragraph.svg diff --git a/frontend/resources/images/icons/text-rtl-refactor.svg b/frontend/resources/images/icons/text-rtl.svg similarity index 100% rename from frontend/resources/images/icons/text-rtl-refactor.svg rename to frontend/resources/images/icons/text-rtl.svg diff --git a/frontend/resources/images/icons/text-stroked-refactor.svg b/frontend/resources/images/icons/text-stroked.svg similarity index 100% rename from frontend/resources/images/icons/text-stroked-refactor.svg rename to frontend/resources/images/icons/text-stroked.svg diff --git a/frontend/resources/images/icons/text-top-refactor.svg b/frontend/resources/images/icons/text-top.svg similarity index 100% rename from frontend/resources/images/icons/text-top-refactor.svg rename to frontend/resources/images/icons/text-top.svg diff --git a/frontend/resources/images/icons/text-underlined-refactor.svg b/frontend/resources/images/icons/text-underlined.svg similarity index 100% rename from frontend/resources/images/icons/text-underlined-refactor.svg rename to frontend/resources/images/icons/text-underlined.svg diff --git a/frontend/resources/images/icons/text-uppercase-refactor.svg b/frontend/resources/images/icons/text-uppercase.svg similarity index 100% rename from frontend/resources/images/icons/text-uppercase-refactor.svg rename to frontend/resources/images/icons/text-uppercase.svg diff --git a/frontend/resources/images/icons/text-refactor.svg b/frontend/resources/images/icons/text.svg similarity index 100% rename from frontend/resources/images/icons/text-refactor.svg rename to frontend/resources/images/icons/text.svg diff --git a/frontend/resources/images/icons/thumbnail-refactor.svg b/frontend/resources/images/icons/thumbnail.svg similarity index 100% rename from frontend/resources/images/icons/thumbnail-refactor.svg rename to frontend/resources/images/icons/thumbnail.svg diff --git a/frontend/resources/images/icons/tick-refactor.svg b/frontend/resources/images/icons/tick.svg similarity index 100% rename from frontend/resources/images/icons/tick-refactor.svg rename to frontend/resources/images/icons/tick.svg diff --git a/frontend/resources/images/icons/to-corner-refactor.svg b/frontend/resources/images/icons/to-corner.svg similarity index 100% rename from frontend/resources/images/icons/to-corner-refactor.svg rename to frontend/resources/images/icons/to-corner.svg diff --git a/frontend/resources/images/icons/to-curve-refactor.svg b/frontend/resources/images/icons/to-curve.svg similarity index 100% rename from frontend/resources/images/icons/to-curve-refactor.svg rename to frontend/resources/images/icons/to-curve.svg diff --git a/frontend/resources/images/icons/tree-refactor.svg b/frontend/resources/images/icons/tree.svg similarity index 100% rename from frontend/resources/images/icons/tree-refactor.svg rename to frontend/resources/images/icons/tree.svg diff --git a/frontend/resources/images/icons/unchain.svg b/frontend/resources/images/icons/unchain.svg deleted file mode 100644 index 911560889..000000000 --- a/frontend/resources/images/icons/unchain.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/resources/images/icons/unlock-refactor.svg b/frontend/resources/images/icons/unlock.svg similarity index 100% rename from frontend/resources/images/icons/unlock-refactor.svg rename to frontend/resources/images/icons/unlock.svg diff --git a/frontend/resources/images/icons/user-refactor.svg b/frontend/resources/images/icons/user.svg similarity index 100% rename from frontend/resources/images/icons/user-refactor.svg rename to frontend/resources/images/icons/user.svg diff --git a/frontend/resources/images/icons/vertical-align-items-center-refactor.svg b/frontend/resources/images/icons/vertical-align-items-center.svg similarity index 100% rename from frontend/resources/images/icons/vertical-align-items-center-refactor.svg rename to frontend/resources/images/icons/vertical-align-items-center.svg diff --git a/frontend/resources/images/icons/vertical-align-items-end-refactor.svg b/frontend/resources/images/icons/vertical-align-items-end.svg similarity index 100% rename from frontend/resources/images/icons/vertical-align-items-end-refactor.svg rename to frontend/resources/images/icons/vertical-align-items-end.svg diff --git a/frontend/resources/images/icons/vertical-align-items-start-refactor.svg b/frontend/resources/images/icons/vertical-align-items-start.svg similarity index 100% rename from frontend/resources/images/icons/vertical-align-items-start-refactor.svg rename to frontend/resources/images/icons/vertical-align-items-start.svg diff --git a/frontend/resources/images/icons/view-as-icons-refactor.svg b/frontend/resources/images/icons/view-as-icons.svg similarity index 100% rename from frontend/resources/images/icons/view-as-icons-refactor.svg rename to frontend/resources/images/icons/view-as-icons.svg diff --git a/frontend/resources/images/icons/view-as-list-refactor.svg b/frontend/resources/images/icons/view-as-list.svg similarity index 100% rename from frontend/resources/images/icons/view-as-list-refactor.svg rename to frontend/resources/images/icons/view-as-list.svg diff --git a/frontend/resources/styles/debug.scss b/frontend/resources/styles/debug.scss index e54ea5153..be3edc522 100644 --- a/frontend/resources/styles/debug.scss +++ b/frontend/resources/styles/debug.scss @@ -15,5 +15,4 @@ body { .deprecated-icon { fill: red !important; - stroke: red !important; } diff --git a/frontend/src/app/main/ui/components/title_bar.cljs b/frontend/src/app/main/ui/components/title_bar.cljs index 45a23a975..04e621133 100644 --- a/frontend/src/app/main/ui/components/title_bar.cljs +++ b/frontend/src/app/main/ui/components/title_bar.cljs @@ -12,7 +12,7 @@ [rumext.v2 :as mf])) (def ^:private chevron-icon - (i/icon-xref :arrow-refactor (stl/css :chevron-icon))) + (i/icon-xref :arrow (stl/css :chevron-icon))) (mf/defc title-bar {::mf/props :obj} diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index 3a567774d..f200d98f9 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -22,14 +22,14 @@ (def ^:private close-icon - (i/icon-xref :close-refactor (stl/css :close-icon))) + (i/icon-xref :close (stl/css :close-icon))) (def ^:private comments-icon-svg - (i/icon-xref :comments-refactor (stl/css :comments-icon))) + (i/icon-xref :comments (stl/css :comments-icon))) (def ^:private comments-icon-small - (i/icon-xref :comments-refactor (stl/css :comments-icon-small))) + (i/icon-xref :comments (stl/css :comments-icon-small))) (mf/defc comments-icon [{:keys [profile show? on-show-comments]}] diff --git a/frontend/src/app/main/ui/dashboard/files.cljs b/frontend/src/app/main/ui/dashboard/files.cljs index 50d776e62..afee2564d 100644 --- a/frontend/src/app/main/ui/dashboard/files.cljs +++ b/frontend/src/app/main/ui/dashboard/files.cljs @@ -25,7 +25,7 @@ [rumext.v2 :as mf])) (def ^:private menu-icon - (i/icon-xref :menu-refactor (stl/css :menu-icon))) + (i/icon-xref :menu (stl/css :menu-icon))) (mf/defc header [{:keys [project create-fn] :as props}] diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 4b35b7f70..11dfda283 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -96,7 +96,7 @@ ;; --- Grid Item Library (def ^:private menu-icon - (i/icon-xref :menu-refactor (stl/css :menu-icon))) + (i/icon-xref :menu (stl/css :menu-icon))) (mf/defc grid-item-library {::mf/wrap [mf/memo]} diff --git a/frontend/src/app/main/ui/dashboard/pin_button.cljs b/frontend/src/app/main/ui/dashboard/pin_button.cljs index be27a05f0..14ee57332 100644 --- a/frontend/src/app/main/ui/dashboard/pin_button.cljs +++ b/frontend/src/app/main/ui/dashboard/pin_button.cljs @@ -16,7 +16,7 @@ [rumext.v2 :as mf])) (def ^:private pin-icon - (icon-xref :pin-refactor (stl/css :icon))) + (icon-xref :pin (stl/css :icon))) (mf/defc pin-button* {::mf/props :obj} diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 883e5bb8a..5712c07f7 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -35,10 +35,10 @@ [rumext.v2 :as mf])) (def ^:private show-more-icon - (i/icon-xref :arrow-refactor (stl/css :show-more-icon))) + (i/icon-xref :arrow (stl/css :show-more-icon))) (def ^:private close-icon - (i/icon-xref :close-refactor (stl/css :close-icon))) + (i/icon-xref :close (stl/css :close-icon))) (mf/defc header {::mf/wrap [mf/memo]} diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index 1a93e3a64..96d4c9df0 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -40,31 +40,31 @@ [rumext.v2 :as mf])) (def ^:private clear-search-icon - (icon-xref :delete-text-refactor (stl/css :clear-search-icon))) + (icon-xref :delete-text (stl/css :clear-search-icon))) (def ^:private search-icon - (icon-xref :search-refactor (stl/css :search-icon))) + (icon-xref :search (stl/css :search-icon))) (def ^:private tick-icon - (icon-xref :tick-refactor (stl/css :tick-icon))) + (icon-xref :tick (stl/css :tick-icon))) (def ^:private logo-icon - (icon-xref :logo-refactor (stl/css :logo-icon))) + (icon-xref :logo (stl/css :logo-icon))) (def ^:private add-icon - (icon-xref :add-refactor (stl/css :add-icon))) + (icon-xref :add (stl/css :add-icon))) (def ^:private arrow-icon - (icon-xref :arrow-refactor (stl/css :arrow-icon))) + (icon-xref :arrow (stl/css :arrow-icon))) (def ^:private menu-icon - (icon-xref :menu-refactor (stl/css :menu-icon))) + (icon-xref :menu (stl/css :menu-icon))) (def ^:private pin-icon - (icon-xref :pin-refactor (stl/css :pin-icon))) + (icon-xref :pin (stl/css :pin-icon))) (def ^:private exit-icon - (icon-xref :exit-refactor (stl/css :exit-icon))) + (icon-xref :exit (stl/css :exit-icon))) (mf/defc sidebar-project [{:keys [item selected?] :as props}] diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index 4307d66cc..6d4ced479 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -34,28 +34,28 @@ (def ^:private arrow-icon - (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) + (i/icon-xref :arrow (stl/css :arrow-icon))) (def ^:private menu-icon - (i/icon-xref :menu-refactor (stl/css :menu-icon))) + (i/icon-xref :menu (stl/css :menu-icon))) (def ^:private warning-icon - (i/icon-xref :msg-warning-refactor (stl/css :warning-icon))) + (i/icon-xref :msg-warning (stl/css :warning-icon))) (def ^:private success-icon - (i/icon-xref :msg-success-refactor (stl/css :success-icon))) + (i/icon-xref :msg-success (stl/css :success-icon))) (def ^:private image-icon - (i/icon-xref :img-refactor (stl/css :image-icon))) + (i/icon-xref :img (stl/css :image-icon))) (def ^:private user-icon - (i/icon-xref :user-refactor (stl/css :user-icon))) + (i/icon-xref :user (stl/css :user-icon))) (def ^:private document-icon - (i/icon-xref :document-refactor (stl/css :document-icon))) + (i/icon-xref :document (stl/css :document-icon))) (def ^:private group-icon - (i/icon-xref :group-refactor (stl/css :group-icon))) + (i/icon-xref :group (stl/css :group-icon))) (mf/defc header {::mf/wrap [mf/memo] diff --git a/frontend/src/app/main/ui/dashboard/templates.cljs b/frontend/src/app/main/ui/dashboard/templates.cljs index 182345dc1..7fb943a88 100644 --- a/frontend/src/app/main/ui/dashboard/templates.cljs +++ b/frontend/src/app/main/ui/dashboard/templates.cljs @@ -26,10 +26,10 @@ [rumext.v2 :as mf])) (def ^:private arrow-icon - (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) + (i/icon-xref :arrow (stl/css :arrow-icon))) (def ^:private download-icon - (i/icon-xref :download-refactor (stl/css :download-icon))) + (i/icon-xref :download (stl/css :download-icon))) (def builtin-templates (l/derived :builtin-templates st/state)) diff --git a/frontend/src/app/main/ui/export.cljs b/frontend/src/app/main/ui/export.cljs index 711d4474b..c2e566828 100644 --- a/frontend/src/app/main/ui/export.cljs +++ b/frontend/src/app/main/ui/export.cljs @@ -26,13 +26,13 @@ [rumext.v2 :as mf])) (def ^:private neutral-icon - (i/icon-xref :msg-neutral-refactor (stl/css :icon))) + (i/icon-xref :msg-neutral (stl/css :icon))) (def ^:private error-icon - (i/icon-xref :delete-text-refactor (stl/css :icon))) + (i/icon-xref :delete-text (stl/css :icon))) (def ^:private close-icon - (i/icon-xref :close-refactor (stl/css :close-icon))) + (i/icon-xref :close (stl/css :close-icon))) (mf/defc export-multiple-dialog [{:keys [exports title cmd no-selection]}] diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index 11c8d520b..b8a72f29e 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -43,222 +43,221 @@ (def ^:icon align-content-row-start-refactor (icon-xref :align-content-row-start)) (def ^:icon align-content-row-stretch-refactor (icon-xref :align-content-row-stretch)) (def ^:icon align-horizontal-center-refactor (icon-xref :align-horizontal-center)) -(def ^:icon align-items-row-center-refactor (icon-xref :align-items-row-center-refactor)) -(def ^:icon align-items-row-end-refactor (icon-xref :align-items-row-end-refactor)) -(def ^:icon align-items-row-start-refactor (icon-xref :align-items-row-start-refactor)) (def ^:icon align-items-column-center-refactor (icon-xref :align-items-column-center)) -(def ^:icon align-items-column-start-refactor (icon-xref :align-items-column-start-refactor)) -(def ^:icon align-items-column-end-refactor (icon-xref :align-items-column-end-refactor)) -(def ^:icon align-left-refactor (icon-xref :align-left-refactor)) -(def ^:icon align-right-refactor (icon-xref :align-right-refactor)) -(def ^:icon align-self-column-bottom-refactor (icon-xref :align-self-column-bottom-refactor)) -(def ^:icon align-self-column-center-refactor (icon-xref :align-self-column-center-refactor)) -(def ^:icon align-self-column-top-refactor (icon-xref :align-self-column-top-refactor)) -(def ^:icon align-self-row-center-refactor (icon-xref :align-self-row-center-refactor)) -(def ^:icon align-self-row-left-refactor (icon-xref :align-self-row-left-refactor)) -(def ^:icon align-self-row-right-refactor (icon-xref :align-self-row-right-refactor)) -(def ^:icon align-self-column-stretch-refactor (icon-xref :align-self-column-stretch-refactor)) -(def ^:icon align-self-row-stretch-refactor (icon-xref :align-self-row-stretch-refactor)) -(def ^:icon align-top-refactor (icon-xref :align-top-refactor)) -(def ^:icon align-vertical-center-refactor (icon-xref :align-vertical-center-refactor)) -(def ^:icon arrow-refactor (icon-xref :arrow-refactor)) -(def ^:icon asc-sort-refactor (icon-xref :asc-sort-refactor)) -(def ^:icon board-refactor (icon-xref :board-refactor)) -(def ^:icon boards-thumbnail-refactor (icon-xref :boards-thumbnail-refactor)) -(def ^:icon boolean-difference-refactor (icon-xref :boolean-difference-refactor)) -(def ^:icon boolean-exclude-refactor (icon-xref :boolean-exclude-refactor)) -(def ^:icon boolean-flatten-refactor (icon-xref :boolean-flatten-refactor)) -(def ^:icon boolean-intersection-refactor (icon-xref :boolean-intersection-refactor)) -(def ^:icon boolean-union-refactor (icon-xref :boolean-union-refactor)) -(def ^:icon bug-refactor (icon-xref :bug-refactor)) -(def ^:icon clip-content-refactor (icon-xref :clip-content-refactor)) -(def ^:icon clipboard-refactor (icon-xref :clipboard-refactor)) -(def ^:icon close-refactor (icon-xref :close-refactor)) -(def ^:icon close-small-refactor (icon-xref :close-small-refactor)) -(def ^:icon code-refactor (icon-xref :code-refactor)) -(def ^:icon column-refactor (icon-xref :column-refactor)) -(def ^:icon column-reverse-refactor (icon-xref :column-reverse-refactor)) -(def ^:icon comments-refactor (icon-xref :comments-refactor)) -(def ^:icon component-refactor (icon-xref :component-refactor)) -(def ^:icon constraint-horizontal-refactor (icon-xref :constraint-horizontal-refactor)) -(def ^:icon constraint-vertical-refactor (icon-xref :constraint-vertical-refactor)) -(def ^:icon copy-refactor (icon-xref :copy-refactor)) -(def ^:icon corner-bottom-refactor (icon-xref :corner-bottom-refactor)) -(def ^:icon corner-bottomleft-refactor (icon-xref :corner-bottomleft-refactor)) -(def ^:icon corner-bottomright-refactor (icon-xref :corner-bottom-refactor)) -(def ^:icon corner-center-refactor (icon-xref :corner-center-refactor)) -(def ^:icon corner-radius-refactor (icon-xref :corner-radius-refactor)) -(def ^:icon corner-top-refactor (icon-xref :corner-top-refactor)) -(def ^:icon corner-topleft-refactor (icon-xref :corner-topleft-refactor)) -(def ^:icon corner-topright-refactor (icon-xref :corner-topright-refactor)) -(def ^:icon curve-refactor (icon-xref :curve-refactor)) -(def ^:icon delete-refactor (icon-xref :delete-refactor)) -(def ^:icon delete-text-refactor (icon-xref :delete-text-refactor)) -(def ^:icon desc-sort-refactor (icon-xref :desc-sort-refactor)) -(def ^:icon detach-refactor (icon-xref :detach-refactor)) -(def ^:icon detached-refactor (icon-xref :detached-refactor)) -(def ^:icon distribute-horizontally-refactor (icon-xref :distribute-horizontally-refactor)) -(def ^:icon distribute-vertical-spacing-refactor (icon-xref :distribute-vertical-spacing-refactor)) -(def ^:icon document-refactor (icon-xref :document-refactor)) -(def ^:icon download-refactor (icon-xref :download-refactor)) -(def ^:icon drop-refactor (icon-xref :drop-refactor)) -(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out-refactor)) -(def ^:icon easing-ease-in-refactor (icon-xref :easing-ease-in-refactor)) -(def ^:icon easing-ease-out-refactor (icon-xref :easing-ease-out-refactor)) -(def ^:icon easing-ease-refactor (icon-xref :easing-ease-refactor)) -(def ^:icon easing-linear-refactor (icon-xref :easing-linear-refactor)) -(def ^:icon effects-refactor (icon-xref :effects-refactor)) -(def ^:icon elipse-refactor (icon-xref :elipse-refactor)) -(def ^:icon exit-refactor (icon-xref :exit-refactor)) -(def ^:icon expand-refactor (icon-xref :expand-refactor)) -(def ^:icon feedback-refactor (icon-xref :feedback-refactor)) -(def ^:icon fill-content-refactor (icon-xref :fill-content-refactor)) -(def ^:icon filter-refactor (icon-xref :filter-refactor)) -(def ^:icon fixed-width-refactor (icon-xref :fixed-width-refactor)) -(def ^:icon flex-grid-refactor (icon-xref :flex-grid-refactor)) -(def ^:icon flex-horizontal-refactor (icon-xref :flex-horizontal-refactor)) -(def ^:icon flex-refactor (icon-xref :flex-refactor)) -(def ^:icon flex-vertical-refactor (icon-xref :flex-vertical-refactor)) -(def ^:icon flip-horizontal-refactor (icon-xref :flip-horizontal-refactor)) -(def ^:icon flip-vertical-refactor (icon-xref :flip-vertical-refactor)) -(def ^:icon gap-horizontal-refactor (icon-xref :gap-horizontal-refactor)) -(def ^:icon gap-vertical-refactor (icon-xref :gap-vertical-refactor)) -(def ^:icon grid-column-refactor (icon-xref :grid-column-refactor)) -(def ^:icon grid-columns-refactor (icon-xref :grid-columns-refactor)) -(def ^:icon grid-gutter-refactor (icon-xref :grid-gutter-refactor)) -(def ^:icon grid-margin-refactor (icon-xref :grid-margin-refactor)) -(def ^:icon grid-refactor (icon-xref :grid-refactor)) -(def ^:icon grid-row-refactor (icon-xref :grid-row-refactor)) -(def ^:icon grid-rows-refactor (icon-xref :grid-rows-refactor)) -(def ^:icon grid-square-refactor (icon-xref :grid-square-refactor)) -(def ^:icon group-refactor (icon-xref :group-refactor)) -(def ^:icon gutter-horizontal-refactor (icon-xref :gutter-horizontal-refactor)) -(def ^:icon gutter-vertical-refactor (icon-xref :gutter-vertical-refactor)) -(def ^:icon graphics-refactor (icon-xref :graphics-refactor)) -(def ^:icon help-refactor (icon-xref :help-refactor)) -(def ^:icon hide-refactor (icon-xref :hide-refactor)) -(def ^:icon history-refactor (icon-xref :history-refactor)) -(def ^:icon hsva-refactor (icon-xref :hsva-refactor)) -(def ^:icon hug-content-refactor (icon-xref :hug-content-refactor)) -(def ^:icon icon-refactor (icon-xref :icon-refactor)) -(def ^:icon img-refactor (icon-xref :img-refactor)) -(def ^:icon interaction-refactor (icon-xref :interaction-refactor)) -(def ^:icon join-nodes-refactor (icon-xref :join-nodes-refactor)) -(def ^:icon justify-content-column-around-refactor (icon-xref :justify-content-column-around-refactor)) -(def ^:icon justify-content-column-between-refactor (icon-xref :justify-content-column-between-refactor)) -(def ^:icon justify-content-column-center-refactor (icon-xref :justify-content-column-center-refactor)) -(def ^:icon justify-content-column-end-refactor (icon-xref :justify-content-column-end-refactor)) -(def ^:icon justify-content-column-evenly-refactor (icon-xref :justify-content-column-evenly-refactor)) -(def ^:icon justify-content-column-start-refactor (icon-xref :justify-content-column-start-refactor)) -(def ^:icon justify-content-row-center-refactor (icon-xref :justify-content-row-center-refactor)) -(def ^:icon justify-content-row-end-refactor (icon-xref :justify-content-row-end-refactor)) -(def ^:icon justify-content-row-start-refactor (icon-xref :justify-content-row-start-refactor)) -(def ^:icon justify-content-row-between-refactor (icon-xref :justify-content-row-between-refactor)) -(def ^:icon justify-content-row-around-refactor (icon-xref :justify-content-row-around-refactor)) -(def ^:icon justify-content-row-evenly-refactor (icon-xref :justify-content-row-evenly-refactor)) -(def ^:icon layers-refactor (icon-xref :layers-refactor)) -(def ^:icon library-refactor (icon-xref :library-refactor)) -(def ^:icon locate-refactor (icon-xref :locate-refactor)) -(def ^:icon lock-refactor (icon-xref :lock-refactor)) ;; This icon will not change +(def ^:icon align-items-column-end-refactor (icon-xref :align-items-column-end)) +(def ^:icon align-items-column-start-refactor (icon-xref :align-items-column-start)) +(def ^:icon align-items-row-center-refactor (icon-xref :align-items-row-center)) +(def ^:icon align-items-row-end-refactor (icon-xref :align-items-row-end)) +(def ^:icon align-items-row-start-refactor (icon-xref :align-items-row-start)) +(def ^:icon align-left-refactor (icon-xref :align-left)) +(def ^:icon align-right-refactor (icon-xref :align-right)) +(def ^:icon align-self-column-bottom-refactor (icon-xref :align-self-column-bottom)) +(def ^:icon align-self-column-center-refactor (icon-xref :align-self-column-center)) +(def ^:icon align-self-column-stretch-refactor (icon-xref :align-self-column-stretch)) +(def ^:icon align-self-column-top-refactor (icon-xref :align-self-column-top)) +(def ^:icon align-self-row-center-refactor (icon-xref :align-self-row-center)) +(def ^:icon align-self-row-left-refactor (icon-xref :align-self-row-left)) +(def ^:icon align-self-row-right-refactor (icon-xref :align-self-row-right)) +(def ^:icon align-self-row-stretch-refactor (icon-xref :align-self-row-stretch)) +(def ^:icon align-top-refactor (icon-xref :align-top)) +(def ^:icon align-vertical-center-refactor (icon-xref :align-vertical-center)) +(def ^:icon arrow-refactor (icon-xref :arrow)) +(def ^:icon asc-sort-refactor (icon-xref :asc-sort)) +(def ^:icon board-refactor (icon-xref :board)) +(def ^:icon boards-thumbnail-refactor (icon-xref :boards-thumbnail)) +(def ^:icon boolean-difference-refactor (icon-xref :boolean-difference)) +(def ^:icon boolean-exclude-refactor (icon-xref :boolean-exclude)) +(def ^:icon boolean-flatten-refactor (icon-xref :boolean-flatten)) +(def ^:icon boolean-intersection-refactor (icon-xref :boolean-intersection)) +(def ^:icon boolean-union-refactor (icon-xref :boolean-union)) +(def ^:icon bug-refactor (icon-xref :bug)) +(def ^:icon clip-content-refactor (icon-xref :clip-content)) +(def ^:icon clipboard-refactor (icon-xref :clipboard)) +(def ^:icon close-small-refactor (icon-xref :close-small)) +(def ^:icon close-refactor (icon-xref :close)) +(def ^:icon code-refactor (icon-xref :code)) +(def ^:icon column-reverse-refactor (icon-xref :column-reverse)) +(def ^:icon column-refactor (icon-xref :column)) +(def ^:icon comments-refactor (icon-xref :comments)) +(def ^:icon copy-refactor (icon-xref :component-copy)) +(def ^:icon component-refactor (icon-xref :component)) +(def ^:icon constraint-horizontal-refactor (icon-xref :constraint-horizontal)) +(def ^:icon constraint-vertical-refactor (icon-xref :constraint-vertical)) +(def ^:icon corner-bottomleft-refactor (icon-xref :corner-bottom-left)) +(def ^:icon corner-bottomright-refactor (icon-xref :corner-bottom-right)) +(def ^:icon corner-bottom-refactor (icon-xref :corner-bottom)) +(def ^:icon corner-center-refactor (icon-xref :corner-center)) +(def ^:icon corner-radius-refactor (icon-xref :corner-radius)) +(def ^:icon corner-top-refactor (icon-xref :corner-top)) +(def ^:icon corner-topleft-refactor (icon-xref :corner-top-left)) +(def ^:icon corner-topright-refactor (icon-xref :corner-top-right)) +(def ^:icon curve-refactor (icon-xref :curve)) +(def ^:icon delete-text-refactor (icon-xref :delete-text)) +(def ^:icon delete-refactor (icon-xref :delete)) +(def ^:icon desc-sort-refactor (icon-xref :desc-sort)) +(def ^:icon detach-refactor (icon-xref :detach)) +(def ^:icon detached-refactor (icon-xref :detached)) +(def ^:icon distribute-horizontally-refactor (icon-xref :distribute-horizontally)) +(def ^:icon distribute-vertical-spacing-refactor (icon-xref :distribute-vertical-spacing)) +(def ^:icon document-refactor (icon-xref :document)) +(def ^:icon download-refactor (icon-xref :download)) +(def ^:icon drop-refactor (icon-xref :drop)) +(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out)) +(def ^:icon easing-ease-in-refactor (icon-xref :easing-ease-in)) +(def ^:icon easing-ease-out-refactor (icon-xref :easing-ease-out)) +(def ^:icon easing-ease-refactor (icon-xref :easing-ease)) +(def ^:icon easing-linear-refactor (icon-xref :easing-linear)) +(def ^:icon effects-refactor (icon-xref :effects)) +(def ^:icon elipse-refactor (icon-xref :elipse)) +(def ^:icon exit-refactor (icon-xref :exit)) +(def ^:icon expand-refactor (icon-xref :expand)) +(def ^:icon feedback-refactor (icon-xref :feedback)) +(def ^:icon fill-content-refactor (icon-xref :fill-content)) +(def ^:icon filter-refactor (icon-xref :filter)) +(def ^:icon fixed-width-refactor (icon-xref :fixed-width)) +(def ^:icon flex-grid-refactor (icon-xref :flex-grid)) +(def ^:icon flex-horizontal-refactor (icon-xref :flex-horizontal)) +(def ^:icon flex-vertical-refactor (icon-xref :flex-vertical)) +(def ^:icon flex-refactor (icon-xref :flex)) +(def ^:icon flip-horizontal-refactor (icon-xref :flip-horizontal)) +(def ^:icon flip-vertical-refactor (icon-xref :flip-vertical)) +(def ^:icon gap-horizontal-refactor (icon-xref :gap-horizontal)) +(def ^:icon gap-vertical-refactor (icon-xref :gap-vertical)) +(def ^:icon graphics-refactor (icon-xref :graphics)) +(def ^:icon grid-column-refactor (icon-xref :grid-column)) +(def ^:icon grid-columns-refactor (icon-xref :grid-columns)) +(def ^:icon grid-gutter-refactor (icon-xref :grid-gutter)) +(def ^:icon grid-margin-refactor (icon-xref :grid-margin)) +(def ^:icon grid-refactor (icon-xref :grid)) +(def ^:icon grid-row-refactor (icon-xref :grid-row)) +(def ^:icon grid-rows-refactor (icon-xref :grid-rows)) +(def ^:icon grid-square-refactor (icon-xref :grid-square)) +(def ^:icon group-refactor (icon-xref :group)) +(def ^:icon gutter-horizontal-refactor (icon-xref :gutter-horizontal)) +(def ^:icon gutter-vertical-refactor (icon-xref :gutter-vertical)) +(def ^:icon help-refactor (icon-xref :help)) +(def ^:icon hide-refactor (icon-xref :hide)) +(def ^:icon history-refactor (icon-xref :history)) +(def ^:icon hsva-refactor (icon-xref :hsva)) +(def ^:icon hug-content-refactor (icon-xref :hug-content)) +(def ^:icon icon-refactor (icon-xref :icon)) +(def ^:icon img-refactor (icon-xref :img)) +(def ^:icon interaction-refactor (icon-xref :interaction)) +(def ^:icon join-nodes-refactor (icon-xref :join-nodes)) +(def ^:icon justify-content-column-around-refactor (icon-xref :justify-content-column-around)) +(def ^:icon justify-content-column-between-refactor (icon-xref :justify-content-column-between)) +(def ^:icon justify-content-column-center-refactor (icon-xref :justify-content-column-center)) +(def ^:icon justify-content-column-end-refactor (icon-xref :justify-content-column-end)) +(def ^:icon justify-content-column-evenly-refactor (icon-xref :justify-content-column-evenly)) +(def ^:icon justify-content-column-start-refactor (icon-xref :justify-content-column-start)) +(def ^:icon justify-content-row-around-refactor (icon-xref :justify-content-row-around)) +(def ^:icon justify-content-row-between-refactor (icon-xref :justify-content-row-between)) +(def ^:icon justify-content-row-center-refactor (icon-xref :justify-content-row-center)) +(def ^:icon justify-content-row-end-refactor (icon-xref :justify-content-row-end)) +(def ^:icon justify-content-row-evenly-refactor (icon-xref :justify-content-row-evenly)) +(def ^:icon justify-content-row-start-refactor (icon-xref :justify-content-row-start)) +(def ^:icon layers-refactor (icon-xref :layers)) +(def ^:icon library-refactor (icon-xref :library)) +(def ^:icon locate-refactor (icon-xref :locate)) +(def ^:icon lock-refactor (icon-xref :lock)) ;; This icon will not change (def ^:icon logo-refactor (icon-xref :penpot-logo-icon)) -(def ^:icon margin-bottom-refactor (icon-xref :margin-bottom-refactor)) -(def ^:icon margin-left-refactor (icon-xref :margin-left-refactor)) -(def ^:icon margin-left-right-refactor (icon-xref :margin-left-right-refactor)) -(def ^:icon margin-refactor (icon-xref :margin-refactor)) -(def ^:icon margin-right-refactor (icon-xref :margin-right-refactor)) -(def ^:icon margin-top-bottom-refactor (icon-xref :margin-top-bottom-refactor)) -(def ^:icon margin-top-refactor (icon-xref :margin-top-refactor)) -(def ^:icon mask-refactor (icon-xref :mask-refactor)) -(def ^:icon masked-refactor (icon-xref :masked-refactor)) -(def ^:icon menu-refactor (icon-xref :menu-refactor)) -(def ^:icon merge-nodes-refactor (icon-xref :merge-nodes-refactor)) -(def ^:icon msg-error-refactor (icon-xref :msg-error-refactor)) -(def ^:icon msg-neutral-refactor (icon-xref :msg-neutral-refactor)) -(def ^:icon msg-success-refactor (icon-xref :msg-success-refactor)) -(def ^:icon msg-warning-refactor (icon-xref :msg-warning-refactor)) -(def ^:icon move-refactor (icon-xref :move-refactor)) -(def ^:icon open-link-refactor (icon-xref :open-link-refactor)) -(def ^:icon padding-bottom-refactor (icon-xref :padding-bottom-refactor)) -(def ^:icon padding-extended-refactor (icon-xref :padding-extended-refactor)) -(def ^:icon padding-left-refactor (icon-xref :padding-left-refactor)) -(def ^:icon padding-left-right-refactor (icon-xref :padding-left-right-refactor)) -(def ^:icon padding-right-refactor (icon-xref :padding-right-refactor)) -(def ^:icon padding-top-bottom-refactor (icon-xref :padding-top-bottom-refactor)) -(def ^:icon padding-top-refactor (icon-xref :padding-top-refactor)) -(def ^:icon path-refactor (icon-xref :path-refactor)) -(def ^:icon pentool-refactor (icon-xref :pentool-refactor)) -(def ^:icon picker-refactor (icon-xref :picker-refactor)) -(def ^:icon pin-refactor (icon-xref :pin-refactor)) -(def ^:icon play-refactor (icon-xref :play-refactor)) -(def ^:icon rectangle-refactor (icon-xref :rectangle-refactor)) -(def ^:icon reload-refactor (icon-xref :reload-refactor)) -(def ^:icon remove-refactor (icon-xref :remove-refactor)) -(def ^:icon rgba-complementary-refactor (icon-xref :rgba-complementary-refactor)) -(def ^:icon rgba-refactor (icon-xref :rgba-refactor)) -(def ^:icon rotation-refactor (icon-xref :rotation-refactor)) -(def ^:icon row-refactor (icon-xref :row-refactor)) -(def ^:icon row-reverse-refactor (icon-xref :row-reverse-refactor)) -(def ^:icon search-refactor (icon-xref :search-refactor)) -(def ^:icon separate-nodes-refactor (icon-xref :separate-nodes-refactor)) -(def ^:icon shown-refactor (icon-xref :shown-refactor)) -(def ^:icon size-horizontal-refactor (icon-xref :size-horizontal-refactor)) -(def ^:icon size-vertical-refactor (icon-xref :size-vertical-refactor)) -(def ^:icon snap-nodes-refactor (icon-xref :snap-nodes-refactor)) -(def ^:icon status-alert-refactor (icon-xref :status-alert-refactor)) -(def ^:icon status-tick-refactor (icon-xref :status-tick-refactor)) -(def ^:icon status-update-refactor (icon-xref :status-update-refactor)) -(def ^:icon status-wrong-refactor (icon-xref :status-wrong-refactor)) -(def ^:icon stroke-arrow-refactor (icon-xref :stroke-arrow-refactor)) -(def ^:icon stroke-circle-refactor (icon-xref :stroke-circle-refactor)) -(def ^:icon stroke-diamond-refactor (icon-xref :stroke-diamond-refactor)) -(def ^:icon stroke-rectangle-refactor (icon-xref :stroke-rectangle-refactor)) -(def ^:icon stroke-rounded-refactor (icon-xref :stroke-rounded-refactor)) -(def ^:icon stroke-size-refactor (icon-xref :stroke-size-refactor)) -(def ^:icon stroke-squared-refactor (icon-xref :stroke-squared-refactor)) -(def ^:icon stroke-triangle-refactor (icon-xref :stroke-triangle-refactor)) -(def ^:icon svg-refactor (icon-xref :svg-refactor)) -(def ^:icon swatches-refactor (icon-xref :swatches-refactor)) -(def ^:icon switch-refactor (icon-xref :switch-refactor)) -(def ^:icon text-align-center-refactor (icon-xref :text-align-center-refactor)) -(def ^:icon text-align-left-refactor (icon-xref :text-align-left-refactor)) -(def ^:icon text-align-right-refactor (icon-xref :text-align-right-refactor)) -(def ^:icon text-auto-height-refactor (icon-xref :text-auto-height-refactor)) -(def ^:icon text-auto-width-refactor (icon-xref :text-auto-width-refactor)) -(def ^:icon text-bottom-refactor (icon-xref :text-bottom-refactor)) -(def ^:icon text-fixed-refactor (icon-xref :text-fixed-refactor)) -(def ^:icon text-justify-refactor (icon-xref :text-justify-refactor)) -(def ^:icon text-letterspacing-refactor (icon-xref :text-letterspacing-refactor)) -(def ^:icon text-lineheight-refactor (icon-xref :text-lineheight-refactor)) -(def ^:icon text-lowercase-refactor (icon-xref :text-lowercase-refactor)) -(def ^:icon text-ltr-refactor (icon-xref :text-ltr-refactor)) -(def ^:icon text-middle-refactor (icon-xref :text-middle-refactor)) -(def ^:icon text-mixed-refactor (icon-xref :text-mixed-refactor)) -(def ^:icon text-palette-refactor (icon-xref :text-palette-refactor)) -(def ^:icon text-paragraph-refactor (icon-xref :text-paragraph-refactor)) -(def ^:icon text-refactor (icon-xref :text-refactor)) -(def ^:icon text-rtl-refactor (icon-xref :text-rtl-refactor)) -(def ^:icon text-stroked-refactor (icon-xref :text-stroked-refactor)) -(def ^:icon text-top-refactor (icon-xref :text-top-refactor)) -(def ^:icon text-underlined-refactor (icon-xref :text-underlined-refactor)) -(def ^:icon text-uppercase-refactor (icon-xref :text-uppercase-refactor)) -(def ^:icon thumbnail-refactor (icon-xref :thumbnail-refactor)) -(def ^:icon tick-refactor (icon-xref :tick-refactor)) -(def ^:icon to-corner-refactor (icon-xref :to-corner-refactor)) -(def ^:icon to-curve-refactor (icon-xref :to-curve-refactor)) -(def ^:icon tree-refactor (icon-xref :tree-refactor)) -(def ^:icon unlock-refactor (icon-xref :unlock-refactor)) -(def ^:icon user-refactor (icon-xref :user-refactor)) -(def ^:icon vertical-align-items-center-refactor (icon-xref :vertical-align-items-center-refactor)) -(def ^:icon vertical-align-items-end-refactor (icon-xref :vertical-align-items-end-refactor)) -(def ^:icon vertical-align-items-start-refactor (icon-xref :vertical-align-items-start-refactor)) -(def ^:icon view-as-icons-refactor (icon-xref :view-as-icons-refactor)) -(def ^:icon view-as-list-refactor (icon-xref :view-as-list-refactor)) -(def ^:icon wrap-refactor (icon-xref :wrap-refactor)) - +(def ^:icon margin-bottom-refactor (icon-xref :margin-bottom)) +(def ^:icon margin-left-refactor (icon-xref :margin-left)) +(def ^:icon margin-left-right-refactor (icon-xref :margin-left-right)) +(def ^:icon margin-right-refactor (icon-xref :margin-right)) +(def ^:icon margin-top-bottom-refactor (icon-xref :margin-top-bottom)) +(def ^:icon margin-top-refactor (icon-xref :margin-top)) +(def ^:icon margin-refactor (icon-xref :margin)) +(def ^:icon mask-refactor (icon-xref :mask)) +(def ^:icon masked-refactor (icon-xref :masked)) +(def ^:icon menu-refactor (icon-xref :menu)) +(def ^:icon merge-nodes-refactor (icon-xref :merge-nodes)) +(def ^:icon move-refactor (icon-xref :move)) +(def ^:icon msg-error-refactor (icon-xref :msg-error)) +(def ^:icon msg-neutral-refactor (icon-xref :msg-neutral)) +(def ^:icon msg-success-refactor (icon-xref :msg-success)) +(def ^:icon msg-warning-refactor (icon-xref :msg-warning)) +(def ^:icon open-link-refactor (icon-xref :open-link)) +(def ^:icon padding-bottom-refactor (icon-xref :padding-bottom)) +(def ^:icon padding-extended-refactor (icon-xref :padding-extended)) +(def ^:icon padding-left-right-refactor (icon-xref :padding-left-right)) +(def ^:icon padding-left-refactor (icon-xref :padding-left)) +(def ^:icon padding-right-refactor (icon-xref :padding-right)) +(def ^:icon padding-top-bottom-refactor (icon-xref :padding-top-bottom)) +(def ^:icon padding-top-refactor (icon-xref :padding-top)) +(def ^:icon path-refactor (icon-xref :path)) +(def ^:icon pentool-refactor (icon-xref :pentool)) +(def ^:icon picker-refactor (icon-xref :picker)) +(def ^:icon pin-refactor (icon-xref :pin)) +(def ^:icon play-refactor (icon-xref :play)) +(def ^:icon rectangle-refactor (icon-xref :rectangle)) +(def ^:icon reload-refactor (icon-xref :reload)) +(def ^:icon remove-refactor (icon-xref :remove)) +(def ^:icon rgba-complementary-refactor (icon-xref :rgba-complementary)) +(def ^:icon rgba-refactor (icon-xref :rgba)) +(def ^:icon rotation-refactor (icon-xref :rotation)) +(def ^:icon row-reverse-refactor (icon-xref :row-reverse)) +(def ^:icon row-refactor (icon-xref :row)) +(def ^:icon search-refactor (icon-xref :search)) +(def ^:icon separate-nodes-refactor (icon-xref :separate-nodes)) +(def ^:icon shown-refactor (icon-xref :shown)) +(def ^:icon size-horizontal-refactor (icon-xref :size-horizontal)) +(def ^:icon size-vertical-refactor (icon-xref :size-vertical)) +(def ^:icon snap-nodes-refactor (icon-xref :snap-nodes)) +(def ^:icon status-alert-refactor (icon-xref :status-alert)) +(def ^:icon status-tick-refactor (icon-xref :status-tick)) +(def ^:icon status-update-refactor (icon-xref :status-update)) +(def ^:icon status-wrong-refactor (icon-xref :status-wrong)) +(def ^:icon stroke-arrow-refactor (icon-xref :stroke-arrow)) +(def ^:icon stroke-circle-refactor (icon-xref :stroke-circle)) +(def ^:icon stroke-diamond-refactor (icon-xref :stroke-diamond)) +(def ^:icon stroke-rectangle-refactor (icon-xref :stroke-rectangle)) +(def ^:icon stroke-rounded-refactor (icon-xref :stroke-rounded)) +(def ^:icon stroke-size-refactor (icon-xref :stroke-size)) +(def ^:icon stroke-squared-refactor (icon-xref :stroke-squared)) +(def ^:icon stroke-triangle-refactor (icon-xref :stroke-triangle)) +(def ^:icon svg-refactor (icon-xref :svg)) +(def ^:icon swatches-refactor (icon-xref :swatches)) +(def ^:icon switch-refactor (icon-xref :switch)) +(def ^:icon text-align-center-refactor (icon-xref :text-align-center)) +(def ^:icon text-align-left-refactor (icon-xref :text-align-left)) +(def ^:icon text-align-right-refactor (icon-xref :text-align-right)) +(def ^:icon text-auto-height-refactor (icon-xref :text-auto-height)) +(def ^:icon text-auto-width-refactor (icon-xref :text-auto-width)) +(def ^:icon text-bottom-refactor (icon-xref :text-bottom)) +(def ^:icon text-fixed-refactor (icon-xref :text-fixed)) +(def ^:icon text-justify-refactor (icon-xref :text-justify)) +(def ^:icon text-letterspacing-refactor (icon-xref :text-letterspacing)) +(def ^:icon text-lineheight-refactor (icon-xref :text-lineheight)) +(def ^:icon text-lowercase-refactor (icon-xref :text-lowercase)) +(def ^:icon text-ltr-refactor (icon-xref :text-ltr)) +(def ^:icon text-middle-refactor (icon-xref :text-middle)) +(def ^:icon text-mixed-refactor (icon-xref :text-mixed)) +(def ^:icon text-palette-refactor (icon-xref :text-palette)) +(def ^:icon text-paragraph-refactor (icon-xref :text-paragraph)) +(def ^:icon text-rtl-refactor (icon-xref :text-rtl)) +(def ^:icon text-stroked-refactor (icon-xref :text-stroked)) +(def ^:icon text-top-refactor (icon-xref :text-top)) +(def ^:icon text-underlined-refactor (icon-xref :text-underlined)) +(def ^:icon text-uppercase-refactor (icon-xref :text-uppercase)) +(def ^:icon text-refactor (icon-xref :text)) +(def ^:icon thumbnail-refactor (icon-xref :thumbnail)) +(def ^:icon tick-refactor (icon-xref :tick)) +(def ^:icon to-corner-refactor (icon-xref :to-corner)) +(def ^:icon to-curve-refactor (icon-xref :to-curve)) +(def ^:icon tree-refactor (icon-xref :tree)) +(def ^:icon unlock-refactor (icon-xref :unlock)) +(def ^:icon user-refactor (icon-xref :user)) (def ^:icon v2-icon-1 (icon-xref :v2-icon-1)) (def ^:icon v2-icon-2 (icon-xref :v2-icon-2)) (def ^:icon v2-icon-3 (icon-xref :v2-icon-3)) (def ^:icon v2-icon-4 (icon-xref :v2-icon-4)) +(def ^:icon vertical-align-items-center-refactor (icon-xref :vertical-align-items-center)) +(def ^:icon vertical-align-items-end-refactor (icon-xref :vertical-align-items-end)) +(def ^:icon vertical-align-items-start-refactor (icon-xref :vertical-align-items-start)) +(def ^:icon view-as-icons-refactor (icon-xref :view-as-icons)) +(def ^:icon view-as-list-refactor (icon-xref :view-as-list)) +(def ^:icon wrap-refactor (icon-xref :wrap)) (def ^:icon loader-pencil diff --git a/frontend/src/app/main/ui/notifications/context_notification.cljs b/frontend/src/app/main/ui/notifications/context_notification.cljs index cdd9a1d10..19a68ad26 100644 --- a/frontend/src/app/main/ui/notifications/context_notification.cljs +++ b/frontend/src/app/main/ui/notifications/context_notification.cljs @@ -14,16 +14,16 @@ [rumext.v2 :as mf])) (def ^:private neutral-icon - (i/icon-xref :msg-neutral-refactor (stl/css :icon))) + (i/icon-xref :msg-neutral (stl/css :icon))) (def ^:private error-icon - (i/icon-xref :delete-text-refactor (stl/css :icon))) + (i/icon-xref :delete-text (stl/css :icon))) (def ^:private success-icon - (i/icon-xref :status-tick-refactor (stl/css :icon))) + (i/icon-xref :status-tick (stl/css :icon))) (def ^:private info-icon - (i/icon-xref :help-refactor (stl/css :icon))) + (i/icon-xref :help (stl/css :icon))) (defn get-icon-by-type [type] diff --git a/frontend/src/app/main/ui/notifications/toast_notification.cljs b/frontend/src/app/main/ui/notifications/toast_notification.cljs index a43e5d5af..c4583c901 100644 --- a/frontend/src/app/main/ui/notifications/toast_notification.cljs +++ b/frontend/src/app/main/ui/notifications/toast_notification.cljs @@ -14,19 +14,19 @@ [rumext.v2 :as mf])) (def ^:private neutral-icon - (i/icon-xref :msg-neutral-refactor (stl/css :icon))) + (i/icon-xref :msg-neutral (stl/css :icon))) (def ^:private error-icon - (i/icon-xref :delete-text-refactor (stl/css :icon))) + (i/icon-xref :delete-text (stl/css :icon))) (def ^:private success-icon - (i/icon-xref :status-tick-refactor (stl/css :icon))) + (i/icon-xref :status-tick (stl/css :icon))) (def ^:private info-icon - (i/icon-xref :help-refactor (stl/css :icon))) + (i/icon-xref :help (stl/css :icon))) (def ^:private close-icon - (i/icon-xref :close-refactor (stl/css :close-icon))) + (i/icon-xref :close (stl/css :close-icon))) (defn get-icon-by-type [type] diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs index dff8f400a..4a2ffce59 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.cljs +++ b/frontend/src/app/main/ui/settings/access_tokens.cljs @@ -26,13 +26,13 @@ [rumext.v2 :as mf])) (def ^:private clipboard-icon - (i/icon-xref :clipboard-refactor (stl/css :clipboard-icon))) + (i/icon-xref :clipboard (stl/css :clipboard-icon))) (def ^:private close-icon - (i/icon-xref :close-refactor (stl/css :close-icon))) + (i/icon-xref :close (stl/css :close-icon))) (def ^:private menu-icon - (i/icon-xref :menu-refactor (stl/css :menu-icon))) + (i/icon-xref :menu (stl/css :menu-icon))) (def tokens-ref (l/derived :access-tokens st/state)) diff --git a/frontend/src/app/main/ui/settings/sidebar.cljs b/frontend/src/app/main/ui/settings/sidebar.cljs index def29fc6d..c878c7b4b 100644 --- a/frontend/src/app/main/ui/settings/sidebar.cljs +++ b/frontend/src/app/main/ui/settings/sidebar.cljs @@ -21,10 +21,10 @@ [rumext.v2 :as mf])) (def ^:private arrow-icon - (i/icon-xref :arrow-refactor (stl/css :arrow-icon))) + (i/icon-xref :arrow (stl/css :arrow-icon))) (def ^:private feedback-icon - (i/icon-xref :feedback-refactor (stl/css :feedback-icon))) + (i/icon-xref :feedback (stl/css :feedback-icon))) (def ^:private go-settings-profile #(st/emit! (rt/nav :settings-profile))) 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 882cd276d..5b77d49b7 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 @@ -18,7 +18,7 @@ [rumext.v2 :as mf])) (def ^:private flatten-icon - (i/icon-xref :boolean-flatten-refactor (stl/css :flatten-icon))) + (i/icon-xref :boolean-flatten (stl/css :flatten-icon))) (mf/defc bool-options [] 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 d40d0ef42..f124fd252 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 @@ -183,19 +183,19 @@ [:& flow-item {:flow flow :key (str (:id flow))}])]))) (def ^:private corner-center-icon - (i/icon-xref :corner-center-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-center (stl/css :corner-icon))) (def ^:private corner-bottom-icon - (i/icon-xref :corner-bottom-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-bottom (stl/css :corner-icon))) (def ^:private corner-bottomleft-icon - (i/icon-xref :corner-bottomleft-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-bottomleft (stl/css :corner-icon))) (def ^:private corner-bottomright-icon - (i/icon-xref :corner-bottomright-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-bottomright (stl/css :corner-icon))) (def ^:private corner-top-icon - (i/icon-xref :corner-top-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-top (stl/css :corner-icon))) (def ^:private corner-topleft-icon - (i/icon-xref :corner-topleft-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-topleft (stl/css :corner-icon))) (def ^:private corner-topright-icon - (i/icon-xref :corner-topright-refactor (stl/css :corner-icon))) + (i/icon-xref :corner-topright (stl/css :corner-icon))) (mf/defc interaction-entry [{:keys [index shape interaction update-interaction remove-interaction]}] 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 a3aaf2422..92f2e5c40 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 @@ -52,10 +52,10 @@ :svg-raw #{:size :position :rotation} :text #{:size :position :rotation}}) -(def ^:private clip-content-icon (i/icon-xref :clip-content-refactor (stl/css :checkbox-button))) -(def ^:private play-icon (i/icon-xref :play-refactor (stl/css :checkbox-button))) -(def ^:private locked-icon (i/icon-xref :detach-refactor (stl/css :lock-ratio-icon))) -(def ^:private unlocked-icon (i/icon-xref :detached-refactor (stl/css :lock-ratio-icon))) +(def ^:private clip-content-icon (i/icon-xref :clip-content (stl/css :checkbox-button))) +(def ^:private play-icon (i/icon-xref :play (stl/css :checkbox-button))) +(def ^:private locked-icon (i/icon-xref :detach (stl/css :lock-ratio-icon))) +(def ^:private unlocked-icon (i/icon-xref :detached (stl/css :lock-ratio-icon))) (defn select-measure-keys "Consider some shapes can be drawn from bottom to top or from left to right" 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 c684a22c9..f86bf374d 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 @@ -29,7 +29,7 @@ (def ^:private detach-icon - (i/icon-xref :detach-refactor (stl/css :detach-icon))) + (i/icon-xref :detach (stl/css :detach-icon))) (defn opacity->string [opacity] From ca7438aab50d43972ca446529250dfba9abe635e Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 8 Mar 2024 13:56:32 +0100 Subject: [PATCH 058/136] :recycle: Rename all icon functions --- frontend/src/app/main/ui.cljs | 2 +- frontend/src/app/main/ui/alert.cljs | 2 +- frontend/src/app/main/ui/comments.cljs | 6 +- .../main/ui/components/context_menu_a11y.cljs | 6 +- .../app/main/ui/components/copy_button.cljs | 4 +- .../main/ui/components/editable_label.cljs | 2 +- .../main/ui/components/editable_select.cljs | 4 +- .../src/app/main/ui/components/forms.cljs | 12 +- .../app/main/ui/components/search_bar.cljs | 2 +- .../src/app/main/ui/components/select.cljs | 4 +- .../ui/components/shape_icon_refactor.cljs | 52 +- .../app/main/ui/components/tab_container.cljs | 2 +- frontend/src/app/main/ui/confirm.cljs | 4 +- .../app/main/ui/dashboard/change_owner.cljs | 2 +- frontend/src/app/main/ui/dashboard/fonts.cljs | 12 +- frontend/src/app/main/ui/dashboard/grid.cljs | 2 +- .../src/app/main/ui/dashboard/import.cljs | 18 +- .../app/main/ui/dashboard/inline_edition.cljs | 2 +- .../app/main/ui/dashboard/placeholder.cljs | 2 +- .../src/app/main/ui/dashboard/projects.cljs | 4 +- .../src/app/main/ui/dashboard/search.cljs | 6 +- frontend/src/app/main/ui/dashboard/team.cljs | 2 +- .../src/app/main/ui/dashboard/team_form.cljs | 2 +- .../app/main/ui/debug/components_preview.cljs | 30 +- frontend/src/app/main/ui/delete_shared.cljs | 2 +- frontend/src/app/main/ui/export.cljs | 16 +- frontend/src/app/main/ui/icons.clj | 8 +- frontend/src/app/main/ui/icons.cljs | 457 +++++++++--------- .../app/main/ui/onboarding/newsletter.cljs | 4 +- .../src/app/main/ui/onboarding/questions.cljs | 2 +- .../app/main/ui/onboarding/team_choice.cljs | 10 +- .../src/app/main/ui/onboarding/templates.cljs | 2 +- .../app/main/ui/settings/access_tokens.cljs | 2 +- .../app/main/ui/settings/change_email.cljs | 2 +- .../app/main/ui/settings/delete_account.cljs | 2 +- frontend/src/app/main/ui/viewer.cljs | 6 +- frontend/src/app/main/ui/viewer/comments.cljs | 10 +- frontend/src/app/main/ui/viewer/header.cljs | 20 +- .../src/app/main/ui/viewer/inspect/code.cljs | 8 +- .../app/main/ui/viewer/inspect/exports.cljs | 6 +- .../main/ui/viewer/inspect/right_sidebar.cljs | 6 +- .../src/app/main/ui/viewer/interactions.cljs | 14 +- frontend/src/app/main/ui/viewer/login.cljs | 2 +- .../src/app/main/ui/viewer/share_link.cljs | 12 +- .../src/app/main/ui/viewer/thumbnails.cljs | 8 +- .../app/main/ui/workspace/color_palette.cljs | 4 +- .../ui/workspace/color_palette_ctx_menu.cljs | 6 +- .../app/main/ui/workspace/colorpicker.cljs | 10 +- .../ui/workspace/colorpicker/libraries.cljs | 4 +- .../src/app/main/ui/workspace/comments.cljs | 12 +- .../app/main/ui/workspace/context_menu.cljs | 4 +- .../app/main/ui/workspace/left_header.cljs | 2 +- .../src/app/main/ui/workspace/libraries.cljs | 8 +- .../src/app/main/ui/workspace/main_menu.cljs | 12 +- frontend/src/app/main/ui/workspace/nudge.cljs | 2 +- .../src/app/main/ui/workspace/palette.cljs | 6 +- .../app/main/ui/workspace/right_header.cljs | 18 +- .../app/main/ui/workspace/sidebar/assets.cljs | 8 +- .../ui/workspace/sidebar/assets/colors.cljs | 2 +- .../ui/workspace/sidebar/assets/common.cljs | 8 +- .../workspace/sidebar/assets/components.cljs | 6 +- .../sidebar/assets/file_library.cljs | 4 +- .../ui/workspace/sidebar/assets/graphics.cljs | 2 +- .../ui/workspace/sidebar/assets/groups.cljs | 2 +- .../sidebar/assets/typographies.cljs | 2 +- .../workspace/sidebar/collapsable_button.cljs | 2 +- .../app/main/ui/workspace/sidebar/debug.cljs | 4 +- .../workspace/sidebar/debug_shape_info.cljs | 2 +- .../main/ui/workspace/sidebar/history.cljs | 34 +- .../main/ui/workspace/sidebar/layer_item.cljs | 6 +- .../app/main/ui/workspace/sidebar/layers.cljs | 38 +- .../sidebar/options/menus/align.cljs | 16 +- .../workspace/sidebar/options/menus/blur.cljs | 10 +- .../workspace/sidebar/options/menus/bool.cljs | 8 +- .../sidebar/options/menus/component.cljs | 29 +- .../sidebar/options/menus/constraints.cljs | 2 +- .../sidebar/options/menus/exports.cljs | 7 +- .../workspace/sidebar/options/menus/fill.cljs | 6 +- .../sidebar/options/menus/frame_grid.cljs | 18 +- .../sidebar/options/menus/grid_cell.cljs | 24 +- .../sidebar/options/menus/interactions.cljs | 44 +- .../sidebar/options/menus/layer.cljs | 8 +- .../options/menus/layout_container.cljs | 170 +++---- .../sidebar/options/menus/layout_item.cljs | 26 +- .../sidebar/options/menus/measures.cljs | 16 +- .../sidebar/options/menus/shadow.cljs | 12 +- .../sidebar/options/menus/stroke.cljs | 4 +- .../sidebar/options/menus/svg_attrs.cljs | 2 +- .../workspace/sidebar/options/menus/text.cljs | 34 +- .../sidebar/options/menus/typography.cljs | 22 +- .../sidebar/options/rows/color_row.cljs | 4 +- .../sidebar/options/rows/stroke_row.cljs | 26 +- .../main/ui/workspace/sidebar/shortcuts.cljs | 6 +- .../main/ui/workspace/sidebar/sitemap.cljs | 6 +- .../app/main/ui/workspace/text_palette.cljs | 4 +- .../ui/workspace/text_palette_ctx_menu.cljs | 4 +- .../app/main/ui/workspace/top_toolbar.cljs | 18 +- .../viewport/grid_layout_editor.cljs | 4 +- .../ui/workspace/viewport/path_actions.cljs | 20 +- .../main/ui/workspace/viewport/widgets.cljs | 8 +- 100 files changed, 777 insertions(+), 772 deletions(-) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 7603e8e17..9c7e3110c 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -117,7 +117,7 @@ [:? {} (if (:token query-params) [:> static/error-container {} - [:div.image i/detach-refactor] + [:div.image i/detach] [:div.main-message (tr "viewer.breaking-change.message")] [:div.desc-message (tr "viewer.breaking-change.description")]] diff --git a/frontend/src/app/main/ui/alert.cljs b/frontend/src/app/main/ui/alert.cljs index 8c7ee4b02..821b97cee 100644 --- a/frontend/src/app/main/ui/alert.cljs +++ b/frontend/src/app/main/ui/alert.cljs @@ -54,7 +54,7 @@ [: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]] + :on-click accept-fn} i/close]] [:div {:class (stl/css :modal-content)} (when (and (string? message) (not= message "")) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 938d108a1..9cb417b8f 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -323,12 +323,12 @@ [: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]]) + :global/checked (:is-resolved thread))} i/tick]]) (when (= (:id profile) (:id owner)) [:div {:class (stl/css :options) :on-click on-toggle-options} - i/menu-refactor])] + i/menu])] [:div {:class (stl/css :content)} (if @edition? @@ -585,7 +585,7 @@ [: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 :icon)} i/document] [:span {:class (stl/css :page-name)} (:page-name group)]]) [:div {:class (stl/css :threads)} 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 f6fd0c424..0787b69e7 100644 --- a/frontend/src/app/main/ui/components/context_menu_a11y.cljs +++ b/frontend/src/app/main/ui/components/context_menu_a11y.cljs @@ -220,7 +220,7 @@ [: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] + [:span {:class (stl/css :submenu-icon-back)} i/arrow] parent-option]] [:li {:class (stl/css :separator)}]]) @@ -257,14 +257,14 @@ option-name) (when (and selected (= data-test selected)) - [:span {:class (stl/css :selected-icon)} i/tick-refactor])] + [:span {:class (stl/css :selected-icon)} i/tick])] [: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]])]))))])])]))) + [:span {:class (stl/css :submenu-icon)} i/arrow]])]))))])])]))) (mf/defc context-menu-a11y {::mf/wrap-props false} diff --git a/frontend/src/app/main/ui/components/copy_button.cljs b/frontend/src/app/main/ui/components/copy_button.cljs index c9456acff..912fcb9f9 100644 --- a/frontend/src/app/main/ui/components/copy_button.cljs +++ b/frontend/src/app/main/ui/components/copy_button.cljs @@ -43,5 +43,5 @@ children [:span {:class (stl/css :icon-btn)} (if active? - i/tick-refactor - i/clipboard-refactor)]])) + i/tick + i/clipboard)]])) diff --git a/frontend/src/app/main/ui/components/editable_label.cljs b/frontend/src/app/main/ui/components/editable_label.cljs index 0b5930c92..32f8b3eb0 100644 --- a/frontend/src/app/main/ui/components/editable_label.cljs +++ b/frontend/src/app/main/ui/components/editable_label.cljs @@ -97,7 +97,7 @@ [:span {:class (stl/css :editable-label-close) :on-click cancel-edition} - i/delete-text-refactor]] + i/delete-text]] [:span {:class final-class :title tooltip diff --git a/frontend/src/app/main/ui/components/editable_select.cljs b/frontend/src/app/main/ui/components/editable_select.cljs index a39ea201c..614fd7002 100644 --- a/frontend/src/app/main/ui/components/editable_select.cljs +++ b/frontend/src/app/main/ui/components/editable_select.cljs @@ -180,7 +180,7 @@ [:span {:class (stl/css :dropdown-button) :on-click toggle-dropdown} - i/arrow-refactor] + i/arrow] [:& dropdown {:show (or is-open? false) :on-close close-dropdown} @@ -199,4 +199,4 @@ :on-click select-item} [:span {:class (stl/css :label)} label] [:span {:class (stl/css :check-icon)} - i/tick-refactor]])))]]])) + i/tick]])))]]])) diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index 7ae43e1e9..7d1ad4a46 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -52,11 +52,11 @@ help-icon' (cond (and (= input-type "password") (= @type' "password")) - i/shown-refactor + i/shown (and (= input-type "password") (= @type' "text")) - i/hide-refactor + i/hide :else help-icon) @@ -125,7 +125,7 @@ :for (name input-name)} label (when is-checkbox? - [:span {:class (stl/css-case :global/checked checked?)} (when checked? i/status-tick-refactor)]) + [:span {:class (stl/css-case :global/checked checked?)} (when checked? i/status-tick)]) (if is-checkbox? [:> :input props] @@ -140,11 +140,11 @@ (when show-valid? [:span {:class (stl/css :valid-icon)} - i/tick-refactor]) + i/tick]) (when show-invalid? [:span {:class (stl/css :invalid-icon)} - i/close-refactor])])] + i/close])])] (some? children) [:label {:for (name input-name)} @@ -479,7 +479,7 @@ :caution (:caution item))} [:span {:class (stl/css :text)} (:text item)] [:button {:class (stl/css :icon) - :on-click #(remove-item! item)} i/close-refactor]]])])])) + :on-click #(remove-item! item)} i/close]]])])])) ;; --- Validators diff --git a/frontend/src/app/main/ui/components/search_bar.cljs b/frontend/src/app/main/ui/components/search_bar.cljs index 0db4f1a87..0fb73303c 100644 --- a/frontend/src/app/main/ui/components/search_bar.cljs +++ b/frontend/src/app/main/ui/components/search_bar.cljs @@ -62,4 +62,4 @@ (when (not= "" value) [:button {:class (stl/css :clear) :on-click handle-clear} - i/delete-text-refactor])]])) + i/delete-text])]])) diff --git a/frontend/src/app/main/ui/components/select.cljs b/frontend/src/app/main/ui/components/select.cljs index 51c7874b4..0187499e6 100644 --- a/frontend/src/app/main/ui/components/select.cljs +++ b/frontend/src/app/main/ui/components/select.cljs @@ -104,7 +104,7 @@ (when (and current-icon current-icon-ref) [:span {:class (stl/css :current-icon)} current-icon-ref]) [:span {:class (stl/css :current-label)} current-label] - [:span {:class (stl/css :dropdown-button)} i/arrow-refactor] + [:span {:class (stl/css :dropdown-button)} i/arrow] [:& dropdown {:show is-open? :on-close close-dropdown} [:ul {:ref dropdown-element* :data-direction @dropdown-direction* :class (dm/str dropdown-class " " (stl/css :custom-select-dropdown))} @@ -126,4 +126,4 @@ :on-click select-item} (when (and icon icon-ref) [:span {:class (stl/css :icon)} icon-ref]) [:span {:class (stl/css :label)} label] - [:span {:class (stl/css :check-icon)} i/tick-refactor]])))]]]))) + [:span {:class (stl/css :check-icon)} i/tick]])))]]]))) diff --git a/frontend/src/app/main/ui/components/shape_icon_refactor.cljs b/frontend/src/app/main/ui/components/shape_icon_refactor.cljs index d4a9cf927..7874ac371 100644 --- a/frontend/src/app/main/ui/components/shape_icon_refactor.cljs +++ b/frontend/src/app/main/ui/components/shape_icon_refactor.cljs @@ -17,49 +17,49 @@ [{:keys [shape main-instance?]}] (if (ctk/instance-head? shape) (if main-instance? - i/component-refactor - i/copy-refactor) + i/component + i/component-copy) (case (:type shape) :frame (cond (and (ctl/flex-layout? shape) (ctl/col? shape)) - i/flex-horizontal-refactor + i/flex-horizontal (and (ctl/flex-layout? shape) (ctl/row? shape)) - i/flex-vertical-refactor + i/flex-vertical (ctl/grid-layout? shape) - i/flex-grid-refactor + i/flex-grid :else - i/board-refactor) + i/board) ;; TODO -> THUMBNAIL ICON - :image i/img-refactor - :line (if (cts/has-images? shape) i/img-refactor i/path-refactor) - :circle (if (cts/has-images? shape) i/img-refactor i/elipse-refactor) - :path (if (cts/has-images? shape) i/img-refactor i/path-refactor) - :rect (if (cts/has-images? shape) i/img-refactor i/rectangle-refactor) - :text i/text-refactor + :image i/img + :line (if (cts/has-images? shape) i/img i/path) + :circle (if (cts/has-images? shape) i/img i/elipse) + :path (if (cts/has-images? shape) i/img i/path) + :rect (if (cts/has-images? shape) i/img i/rectangle) + :text i/text :group (if (:masked-group shape) - i/mask-refactor - i/group-refactor) + i/mask + i/group) :bool (case (:bool-type shape) - :difference i/boolean-difference-refactor - :exclude i/boolean-exclude-refactor - :intersection i/boolean-intersection-refactor - #_:default i/boolean-union-refactor) - :svg-raw i/img-refactor + :difference i/boolean-difference + :exclude i/boolean-exclude + :intersection i/boolean-intersection + #_:default i/boolean-union) + :svg-raw i/img nil))) (mf/defc element-icon-refactor-by-type [{:keys [type main-instance?] :as props}] (if main-instance? - i/component-refactor + i/component (case type - :frame i/board-refactor - :image i/img-refactor - :shape i/path-refactor - :text i/text-refactor - :mask i/mask-refactor - :group i/group-refactor + :frame i/board + :image i/img + :shape i/path + :text i/text + :mask i/mask + :group i/group nil))) diff --git a/frontend/src/app/main/ui/components/tab_container.cljs b/frontend/src/app/main/ui/components/tab_container.cljs index 495ceeec2..4dae9d52b 100644 --- a/frontend/src/app/main/ui/components/tab_container.cljs +++ b/frontend/src/app/main/ui/components/tab_container.cljs @@ -48,7 +48,7 @@ {:on-click handle-collapse :class (stl/css :collapse-sidebar) :aria-label (tr "workspace.sidebar.collapse")} - i/arrow-refactor]) + i/arrow]) [:div {:class (stl/css :tab-container-tab-wrapper)} (for [tab children] (let [props (.-props tab) diff --git a/frontend/src/app/main/ui/confirm.cljs b/frontend/src/app/main/ui/confirm.cljs index cfce7c2c1..66fd00e92 100644 --- a/frontend/src/app/main/ui/confirm.cljs +++ b/frontend/src/app/main/ui/confirm.cljs @@ -70,7 +70,7 @@ [: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]] + :on-click cancel-fn} i/close]] [:div {:class (stl/css :modal-content)} (when (and (string? message) (not= message "")) @@ -87,7 +87,7 @@ (for [item items] [:li {:class (stl/css :modal-item-element)} [:span {:class (stl/css :modal-component-icon)} - i/component-refactor] + i/component] [:span {:class (stl/css :modal-component-name)} (:name item)]])]])] diff --git a/frontend/src/app/main/ui/dashboard/change_owner.cljs b/frontend/src/app/main/ui/dashboard/change_owner.cljs index cae033df3..0af37045d 100644 --- a/frontend/src/app/main/ui/dashboard/change_owner.cljs +++ b/frontend/src/app/main/ui/dashboard/change_owner.cljs @@ -45,7 +45,7 @@ [: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]] + :on-click on-cancel} i/close]] [:div {:class (stl/css :modal-content)} [:p {:class (stl/css :modal-msg)} diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index a444236ce..17aa4a8d4 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -227,7 +227,7 @@ [:div {:class (stl/css :table-field :options)} (when (:height-warning? item) [:span {:class (stl/css :icon :failure)} - i/msg-neutral-refactor]) + i/msg-neutral]) [:button {:on-click on-upload :data-id (dm/str id) @@ -242,7 +242,7 @@ [:span {:class (stl/css :icon :close) :data-id (dm/str id) :on-click on-delete} - i/close-refactor]]]))]])) + i/close]]]))]])) (mf/defc installed-font-context-menu {::mf/props :obj @@ -368,7 +368,7 @@ {:class (stl/css :icon :close) :data-id (dm/str id) :on-click on-delete-variant} - i/add-refactor]])] + i/add]])] (if ^boolean edition? [:div {:class (stl/css :table-field :options)} @@ -380,12 +380,12 @@ (tr "labels.save")] [:button {:class (stl/css :icon :close) :on-click on-cancel} - i/close-refactor]] + i/close]] [:div {:class (stl/css :table-field :options)} [:span {:class (stl/css :icon) :on-click on-menu-open} - i/menu-refactor] + i/menu] [:& installed-font-context-menu {:on-close on-menu-close @@ -432,7 +432,7 @@ :else [:div {:class (stl/css :fonts-placeholder)} - [:div {:class (stl/css :icon)} i/text-refactor] + [:div {:class (stl/css :icon)} i/text] [:div {:class (stl/css :label)} (tr "dashboard.fonts.empty-placeholder")]])])) (mf/defc fonts-page diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 11dfda283..bb2f44b2b 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -365,7 +365,7 @@ :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-refactor]) + [:div {:class (stl/css :item-badge)} i/library]) [:div {:class (stl/css :info-wrapper)} [:div {:class (stl/css :item-info)} diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index c4a9302bf..d51195184 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -270,10 +270,10 @@ :icon-fill ready?)} (cond loading? i/loader-pencil ready? i/logo-icon - import-warn? i/msg-warning-refactor - import-error? i/close-refactor - import-finish? i/tick-refactor - analyze-error? i/close-refactor)] + import-warn? i/msg-warning + import-error? i/close + import-finish? i/tick + analyze-error? i/close)] (if editing? [:div {:class (stl/css :file-name-edit)} @@ -287,14 +287,14 @@ (:name entry) (when ^boolean is-shared? [:span {:class (stl/css :icon)} - i/library-refactor])]) + i/library])]) [:div {:class (stl/css :edit-entry-buttons)} (when (and (= "application/zip" (:type entry)) (= status :ready)) - [:button {:on-click on-edit'} i/curve-refactor]) + [:button {:on-click on-edit'} i/curve]) (when can-be-deleted - [:button {:on-click on-delete'} i/delete-refactor])]] + [:button {:on-click on-delete'} i/delete])]] (cond analyze-error? @@ -322,7 +322,7 @@ [:span {:class (stl/css-case :linked-library-tag true :error error?)} - i/detach-refactor]])))]])) + i/detach]])))]])) (mf/defc import-dialog {::mf/register modal/components @@ -455,7 +455,7 @@ [:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")] [:button {:class (stl/css :modal-close-btn) - :on-click on-cancel} i/close-refactor]] + :on-click on-cancel} i/close]] [:div {:class (stl/css :modal-content)} (when (and (= :analyzing status) errors?) diff --git a/frontend/src/app/main/ui/dashboard/inline_edition.cljs b/frontend/src/app/main/ui/dashboard/inline_edition.cljs index 499f52214..0ceda89a6 100644 --- a/frontend/src/app/main/ui/dashboard/inline_edition.cljs +++ b/frontend/src/app/main/ui/dashboard/inline_edition.cljs @@ -69,5 +69,5 @@ :on-key-down on-keyup :on-blur on-blur}] [:span {:class (stl/css :close) - :on-click on-cancel} i/close-refactor]])) + :on-click on-cancel} i/close]])) diff --git a/frontend/src/app/main/ui/dashboard/placeholder.cljs b/frontend/src/app/main/ui/dashboard/placeholder.cljs index ce8c5d81f..8f5daa04e 100644 --- a/frontend/src/app/main/ui/dashboard/placeholder.cljs +++ b/frontend/src/app/main/ui/dashboard/placeholder.cljs @@ -36,7 +36,7 @@ {:class (stl/css :grid-empty-placeholder)} [:button {:class (stl/css :create-new) :on-click on-click} - i/add-refactor]]))) + i/add]]))) (mf/defc loading-placeholder [] diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 5712c07f7..82bbe0378 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -315,7 +315,7 @@ :aria-label (tr "dashboard.new-file") :data-test "project-new-file" :on-key-down handle-create-click} - i/add-refactor] + i/add] [:button {:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom) @@ -324,7 +324,7 @@ :aria-label (tr "dashboard.options") :data-test "project-options" :on-key-down handle-menu-click} - i/menu-refactor]]]] + i/menu]]]] [:div {:class (stl/css :grid-container) :ref rowref} [:& line-grid diff --git a/frontend/src/app/main/ui/dashboard/search.cljs b/frontend/src/app/main/ui/dashboard/search.cljs index 614555020..3b4d09099 100644 --- a/frontend/src/app/main/ui/dashboard/search.cljs +++ b/frontend/src/app/main/ui/dashboard/search.cljs @@ -46,17 +46,17 @@ (cond (empty? search-term) [:div {:class (stl/css :grid-empty-placeholder :search)} - [:div {:class (stl/css :icon)} i/search-refactor] + [: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-refactor] + [: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-refactor] + [:div {:class (stl/css :icon)} i/search] [:div {:class (stl/css :text)} (tr "dashboard.no-matches-for" search-term)]] :else diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index 6d4ced479..adc63664c 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -846,7 +846,7 @@ [: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]] + :on-click on-modal-close} i/close]] [:div {:class (stl/css :modal-content)} [:div {:class (stl/css :fields-row)} diff --git a/frontend/src/app/main/ui/dashboard/team_form.cljs b/frontend/src/app/main/ui/dashboard/team_form.cljs index e93244e53..7a37ec9c6 100644 --- a/frontend/src/app/main/ui/dashboard/team_form.cljs +++ b/frontend/src/app/main/ui/dashboard/team_form.cljs @@ -101,7 +101,7 @@ (tr "labels.create-team")]) [:button {:class (stl/css :modal-close-btn) - :on-click on-close} i/close-refactor]] + :on-click on-close} i/close]] [:div {:class (stl/css :modal-content)} [:& fm/input {:type "text" diff --git a/frontend/src/app/main/ui/debug/components_preview.cljs b/frontend/src/app/main/ui/debug/components_preview.cljs index e13ad747e..9fd0788b7 100644 --- a/frontend/src/app/main/ui/debug/components_preview.cljs +++ b/frontend/src/app/main/ui/debug/components_preview.cljs @@ -109,7 +109,7 @@ [:& title-bar {:collapsable false :title "Title" :on-btn-click on-btn-click - :btn-children i/add-refactor}]] + :btn-children i/add}]] [:& component-wrapper {:title "Collapsed title and action button"} [:& title-bar {:collapsable true @@ -117,7 +117,7 @@ :on-collapsed toggle-collapsed :title "Title" :on-btn-click on-btn-click - :btn-children i/add-refactor}]] + :btn-children i/add}]] [:& component-wrapper {:title "Collapsed title and children"} [:& title-bar {:collapsable true @@ -179,10 +179,10 @@ [:& radio-buttons {:selected radio-selected :on-change set-radio-selected :name "listing-style"} - [:& radio-button {:icon i/view-as-list-refactor + [:& radio-button {:icon i/view-as-list :value "first" :id :list}] - [:& radio-button {:icon i/flex-grid-refactor + [:& radio-button {:icon i/flex-grid :value "second" :id :grid}]]] [:& component-wrapper @@ -190,14 +190,14 @@ [:& radio-buttons {:selected radio-selected :on-change set-radio-selected :name "listing-style"} - [:& radio-button {:icon i/view-as-list-refactor + [:& radio-button {:icon i/view-as-list :value "first" :id :first}] - [:& radio-button {:icon i/flex-grid-refactor + [:& radio-button {:icon i/flex-grid :value "second" :id :second}] - [:& radio-button {:icon i/add-refactor + [:& radio-button {:icon i/add :value "third" :id :third}]]] @@ -206,18 +206,18 @@ [:& radio-buttons {:selected radio-selected :on-change set-radio-selected :name "listing-style"} - [:& radio-button {:icon i/view-as-list-refactor + [:& radio-button {:icon i/view-as-list :value "first" :id :first}] - [:& radio-button {:icon i/flex-grid-refactor + [:& radio-button {:icon i/flex-grid :value "second" :id :second}] - [:& radio-button {:icon i/add-refactor + [:& radio-button {:icon i/add :value "third" :id :third}] - [:& radio-button {:icon i/board-refactor + [:& radio-button {:icon i/board :value "forth" :id :forth}]]]] [:div {:class (stl/css :components-group)} @@ -229,7 +229,7 @@ [:& component-wrapper {:title "Button primary with icon"} [:button {:class (stl/css :button-primary)} - i/add-refactor]] + i/add]] [:& component-wrapper {:title "Button secondary"} @@ -238,7 +238,7 @@ [:& component-wrapper {:title "Button secondary with icon"} [:button {:class (stl/css :button-secondary)} - i/add-refactor]] + i/add]] [:& component-wrapper {:title "Button tertiary"} @@ -247,7 +247,7 @@ [:& component-wrapper {:title "Button tertiary with icon"} [:button {:class (stl/css :button-tertiary)} - i/add-refactor]]] + i/add]]] [:div {:class (stl/css :components-group)} [:h3 "Inputs"] [:& component-wrapper @@ -265,6 +265,6 @@ {:title "Input with icon"} [:div {:class (stl/css :input-wrapper)} [:span {:class (stl/css :input-label)} - i/add-refactor] + i/add] [:input {:class (stl/css :basic-input) :placeholder "----"}]]]]]]])) diff --git a/frontend/src/app/main/ui/delete_shared.cljs b/frontend/src/app/main/ui/delete_shared.cljs index f0e8dabc3..ec2100937 100644 --- a/frontend/src/app/main/ui/delete_shared.cljs +++ b/frontend/src/app/main/ui/delete_shared.cljs @@ -97,7 +97,7 @@ [: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]] + :on-click cancel-fn} i/close]] [:div {:class (stl/css :modal-content)} (when (and (string? subtitle) (not= subtitle "")) diff --git a/frontend/src/app/main/ui/export.cljs b/frontend/src/app/main/ui/export.cljs index c2e566828..c13b074a4 100644 --- a/frontend/src/app/main/ui/export.cljs +++ b/frontend/src/app/main/ui/export.cljs @@ -86,7 +86,7 @@ [:h2 {:class (stl/css :modal-title)} title] [:button {:class (stl/css :modal-close-btn) :on-click cancel-fn} - i/close-refactor]] + i/close]] [:* [:div {:class (stl/css :modal-content)} @@ -99,12 +99,12 @@ (cond all-checked? [:span {:class (stl/css-case :checkobox-tick true :global/checked true)} - i/tick-refactor] + i/tick] all-unchecked? [:span {:class (stl/css-case :checkobox-tick true :global/uncheked true)}] :else [:span {:class (stl/css-case :checkobox-tick true :global/intermediate true)} - i/remove-refactor])]] + i/remove-icon])]] [:div {:class (stl/css :selection-title)} (tr "dashboard.export-multiple.selected" (c (count enabled-exports)) @@ -123,7 +123,7 @@ (if (:enabled export) [:span {:class (stl/css-case :checkobox-tick true :global/checked true)} - i/tick-refactor] + i/tick] [:span {:class (stl/css-case :checkobox-tick true :global/uncheked true)}])] @@ -318,8 +318,8 @@ [: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 + (cond (:export-success? file) i/tick + (:export-error? file) i/close (:loading? file) i/loader-pencil)] [:div {:class (stl/css :file-name-label)} @@ -417,7 +417,7 @@ [:h2 {:class (stl/css :modal-title)} (tr "dashboard.export.title")] [:button {:class (stl/css :modal-close-btn) - :on-click on-cancel} i/close-refactor]] + :on-click on-cancel} i/close]] (cond (= status :prepare) @@ -440,7 +440,7 @@ ;; dashboard.export.options.merge.title [:span {:class (stl/css-case :global/checked (= selected type))} (when (= selected type) - i/status-tick-refactor)] + i/status-tick)] [: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"))]] diff --git a/frontend/src/app/main/ui/icons.clj b/frontend/src/app/main/ui/icons.clj index 636f585c4..600dc7e02 100644 --- a/frontend/src/app/main/ui/icons.clj +++ b/frontend/src/app/main/ui/icons.clj @@ -15,13 +15,7 @@ (defmacro icon-xref [id & [class]] (let [href (str "#icon-" (name id)) - class (or class (str "icon-" (name id))) - - ;; FIXME: Debug tool. Remove when we remove the old icons - class (cond-> class - (and (not (str/ends-with? (name id) "-refactor")) - (not (contains? exceptions id))) - (str " deprecated-icon"))] + class (or class (str "icon-" (name id)))] `(rumext.v2/html [:svg {:width 500 :height 500 :class ~class} [:use {:href ~href}]]))) diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index b8a72f29e..ec9712471 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -25,239 +25,238 @@ (def ^:icon brand-gitlab (icon-xref :brand-gitlab)) (def ^:icon brand-google (icon-xref :brand-google)) -(def ^:icon absolute-refactor (icon-xref :absolute)) -(def ^:icon add-refactor (icon-xref :add)) -(def ^:icon align-bottom-refactor (icon-xref :align-bottom)) -(def ^:icon align-content-column-around-refactor (icon-xref :align-content-column-around)) -(def ^:icon align-content-column-between-refactor (icon-xref :align-content-column-between)) -(def ^:icon align-content-column-center-refactor (icon-xref :align-content-column-center)) -(def ^:icon align-content-column-end-refactor (icon-xref :align-content-column-end)) -(def ^:icon align-content-column-evenly-refactor (icon-xref :align-content-column-evenly)) -(def ^:icon align-content-column-start-refactor (icon-xref :align-content-column-start)) -(def ^:icon align-content-column-stretch-refactor (icon-xref :align-content-column-stretch)) -(def ^:icon align-content-row-around-refactor (icon-xref :align-content-row-around)) -(def ^:icon align-content-row-between-refactor (icon-xref :align-content-row-between)) -(def ^:icon align-content-row-center-refactor (icon-xref :align-content-row-center)) -(def ^:icon align-content-row-end-refactor (icon-xref :align-content-row-end)) -(def ^:icon align-content-row-evenly-refactor (icon-xref :align-content-row-evenly)) -(def ^:icon align-content-row-start-refactor (icon-xref :align-content-row-start)) -(def ^:icon align-content-row-stretch-refactor (icon-xref :align-content-row-stretch)) -(def ^:icon align-horizontal-center-refactor (icon-xref :align-horizontal-center)) -(def ^:icon align-items-column-center-refactor (icon-xref :align-items-column-center)) -(def ^:icon align-items-column-end-refactor (icon-xref :align-items-column-end)) -(def ^:icon align-items-column-start-refactor (icon-xref :align-items-column-start)) -(def ^:icon align-items-row-center-refactor (icon-xref :align-items-row-center)) -(def ^:icon align-items-row-end-refactor (icon-xref :align-items-row-end)) -(def ^:icon align-items-row-start-refactor (icon-xref :align-items-row-start)) -(def ^:icon align-left-refactor (icon-xref :align-left)) -(def ^:icon align-right-refactor (icon-xref :align-right)) -(def ^:icon align-self-column-bottom-refactor (icon-xref :align-self-column-bottom)) -(def ^:icon align-self-column-center-refactor (icon-xref :align-self-column-center)) -(def ^:icon align-self-column-stretch-refactor (icon-xref :align-self-column-stretch)) -(def ^:icon align-self-column-top-refactor (icon-xref :align-self-column-top)) -(def ^:icon align-self-row-center-refactor (icon-xref :align-self-row-center)) -(def ^:icon align-self-row-left-refactor (icon-xref :align-self-row-left)) -(def ^:icon align-self-row-right-refactor (icon-xref :align-self-row-right)) -(def ^:icon align-self-row-stretch-refactor (icon-xref :align-self-row-stretch)) -(def ^:icon align-top-refactor (icon-xref :align-top)) -(def ^:icon align-vertical-center-refactor (icon-xref :align-vertical-center)) -(def ^:icon arrow-refactor (icon-xref :arrow)) -(def ^:icon asc-sort-refactor (icon-xref :asc-sort)) -(def ^:icon board-refactor (icon-xref :board)) -(def ^:icon boards-thumbnail-refactor (icon-xref :boards-thumbnail)) -(def ^:icon boolean-difference-refactor (icon-xref :boolean-difference)) -(def ^:icon boolean-exclude-refactor (icon-xref :boolean-exclude)) -(def ^:icon boolean-flatten-refactor (icon-xref :boolean-flatten)) -(def ^:icon boolean-intersection-refactor (icon-xref :boolean-intersection)) -(def ^:icon boolean-union-refactor (icon-xref :boolean-union)) -(def ^:icon bug-refactor (icon-xref :bug)) -(def ^:icon clip-content-refactor (icon-xref :clip-content)) -(def ^:icon clipboard-refactor (icon-xref :clipboard)) -(def ^:icon close-small-refactor (icon-xref :close-small)) -(def ^:icon close-refactor (icon-xref :close)) -(def ^:icon code-refactor (icon-xref :code)) -(def ^:icon column-reverse-refactor (icon-xref :column-reverse)) -(def ^:icon column-refactor (icon-xref :column)) -(def ^:icon comments-refactor (icon-xref :comments)) -(def ^:icon copy-refactor (icon-xref :component-copy)) -(def ^:icon component-refactor (icon-xref :component)) -(def ^:icon constraint-horizontal-refactor (icon-xref :constraint-horizontal)) -(def ^:icon constraint-vertical-refactor (icon-xref :constraint-vertical)) -(def ^:icon corner-bottomleft-refactor (icon-xref :corner-bottom-left)) -(def ^:icon corner-bottomright-refactor (icon-xref :corner-bottom-right)) -(def ^:icon corner-bottom-refactor (icon-xref :corner-bottom)) -(def ^:icon corner-center-refactor (icon-xref :corner-center)) -(def ^:icon corner-radius-refactor (icon-xref :corner-radius)) -(def ^:icon corner-top-refactor (icon-xref :corner-top)) -(def ^:icon corner-topleft-refactor (icon-xref :corner-top-left)) -(def ^:icon corner-topright-refactor (icon-xref :corner-top-right)) -(def ^:icon curve-refactor (icon-xref :curve)) -(def ^:icon delete-text-refactor (icon-xref :delete-text)) -(def ^:icon delete-refactor (icon-xref :delete)) -(def ^:icon desc-sort-refactor (icon-xref :desc-sort)) -(def ^:icon detach-refactor (icon-xref :detach)) -(def ^:icon detached-refactor (icon-xref :detached)) -(def ^:icon distribute-horizontally-refactor (icon-xref :distribute-horizontally)) -(def ^:icon distribute-vertical-spacing-refactor (icon-xref :distribute-vertical-spacing)) -(def ^:icon document-refactor (icon-xref :document)) -(def ^:icon download-refactor (icon-xref :download)) -(def ^:icon drop-refactor (icon-xref :drop)) -(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out)) -(def ^:icon easing-ease-in-refactor (icon-xref :easing-ease-in)) -(def ^:icon easing-ease-out-refactor (icon-xref :easing-ease-out)) -(def ^:icon easing-ease-refactor (icon-xref :easing-ease)) -(def ^:icon easing-linear-refactor (icon-xref :easing-linear)) -(def ^:icon effects-refactor (icon-xref :effects)) -(def ^:icon elipse-refactor (icon-xref :elipse)) -(def ^:icon exit-refactor (icon-xref :exit)) -(def ^:icon expand-refactor (icon-xref :expand)) -(def ^:icon feedback-refactor (icon-xref :feedback)) -(def ^:icon fill-content-refactor (icon-xref :fill-content)) -(def ^:icon filter-refactor (icon-xref :filter)) -(def ^:icon fixed-width-refactor (icon-xref :fixed-width)) -(def ^:icon flex-grid-refactor (icon-xref :flex-grid)) -(def ^:icon flex-horizontal-refactor (icon-xref :flex-horizontal)) -(def ^:icon flex-vertical-refactor (icon-xref :flex-vertical)) -(def ^:icon flex-refactor (icon-xref :flex)) -(def ^:icon flip-horizontal-refactor (icon-xref :flip-horizontal)) -(def ^:icon flip-vertical-refactor (icon-xref :flip-vertical)) -(def ^:icon gap-horizontal-refactor (icon-xref :gap-horizontal)) -(def ^:icon gap-vertical-refactor (icon-xref :gap-vertical)) -(def ^:icon graphics-refactor (icon-xref :graphics)) -(def ^:icon grid-column-refactor (icon-xref :grid-column)) -(def ^:icon grid-columns-refactor (icon-xref :grid-columns)) -(def ^:icon grid-gutter-refactor (icon-xref :grid-gutter)) -(def ^:icon grid-margin-refactor (icon-xref :grid-margin)) -(def ^:icon grid-refactor (icon-xref :grid)) -(def ^:icon grid-row-refactor (icon-xref :grid-row)) -(def ^:icon grid-rows-refactor (icon-xref :grid-rows)) -(def ^:icon grid-square-refactor (icon-xref :grid-square)) -(def ^:icon group-refactor (icon-xref :group)) -(def ^:icon gutter-horizontal-refactor (icon-xref :gutter-horizontal)) -(def ^:icon gutter-vertical-refactor (icon-xref :gutter-vertical)) -(def ^:icon help-refactor (icon-xref :help)) -(def ^:icon hide-refactor (icon-xref :hide)) -(def ^:icon history-refactor (icon-xref :history)) -(def ^:icon hsva-refactor (icon-xref :hsva)) -(def ^:icon hug-content-refactor (icon-xref :hug-content)) -(def ^:icon icon-refactor (icon-xref :icon)) -(def ^:icon img-refactor (icon-xref :img)) -(def ^:icon interaction-refactor (icon-xref :interaction)) -(def ^:icon join-nodes-refactor (icon-xref :join-nodes)) -(def ^:icon justify-content-column-around-refactor (icon-xref :justify-content-column-around)) -(def ^:icon justify-content-column-between-refactor (icon-xref :justify-content-column-between)) -(def ^:icon justify-content-column-center-refactor (icon-xref :justify-content-column-center)) -(def ^:icon justify-content-column-end-refactor (icon-xref :justify-content-column-end)) -(def ^:icon justify-content-column-evenly-refactor (icon-xref :justify-content-column-evenly)) -(def ^:icon justify-content-column-start-refactor (icon-xref :justify-content-column-start)) -(def ^:icon justify-content-row-around-refactor (icon-xref :justify-content-row-around)) -(def ^:icon justify-content-row-between-refactor (icon-xref :justify-content-row-between)) -(def ^:icon justify-content-row-center-refactor (icon-xref :justify-content-row-center)) -(def ^:icon justify-content-row-end-refactor (icon-xref :justify-content-row-end)) -(def ^:icon justify-content-row-evenly-refactor (icon-xref :justify-content-row-evenly)) -(def ^:icon justify-content-row-start-refactor (icon-xref :justify-content-row-start)) -(def ^:icon layers-refactor (icon-xref :layers)) -(def ^:icon library-refactor (icon-xref :library)) -(def ^:icon locate-refactor (icon-xref :locate)) -(def ^:icon lock-refactor (icon-xref :lock)) ;; This icon will not change -(def ^:icon logo-refactor (icon-xref :penpot-logo-icon)) -(def ^:icon margin-bottom-refactor (icon-xref :margin-bottom)) -(def ^:icon margin-left-refactor (icon-xref :margin-left)) -(def ^:icon margin-left-right-refactor (icon-xref :margin-left-right)) -(def ^:icon margin-right-refactor (icon-xref :margin-right)) -(def ^:icon margin-top-bottom-refactor (icon-xref :margin-top-bottom)) -(def ^:icon margin-top-refactor (icon-xref :margin-top)) -(def ^:icon margin-refactor (icon-xref :margin)) -(def ^:icon mask-refactor (icon-xref :mask)) -(def ^:icon masked-refactor (icon-xref :masked)) -(def ^:icon menu-refactor (icon-xref :menu)) -(def ^:icon merge-nodes-refactor (icon-xref :merge-nodes)) -(def ^:icon move-refactor (icon-xref :move)) -(def ^:icon msg-error-refactor (icon-xref :msg-error)) -(def ^:icon msg-neutral-refactor (icon-xref :msg-neutral)) -(def ^:icon msg-success-refactor (icon-xref :msg-success)) -(def ^:icon msg-warning-refactor (icon-xref :msg-warning)) -(def ^:icon open-link-refactor (icon-xref :open-link)) -(def ^:icon padding-bottom-refactor (icon-xref :padding-bottom)) -(def ^:icon padding-extended-refactor (icon-xref :padding-extended)) -(def ^:icon padding-left-right-refactor (icon-xref :padding-left-right)) -(def ^:icon padding-left-refactor (icon-xref :padding-left)) -(def ^:icon padding-right-refactor (icon-xref :padding-right)) -(def ^:icon padding-top-bottom-refactor (icon-xref :padding-top-bottom)) -(def ^:icon padding-top-refactor (icon-xref :padding-top)) -(def ^:icon path-refactor (icon-xref :path)) -(def ^:icon pentool-refactor (icon-xref :pentool)) -(def ^:icon picker-refactor (icon-xref :picker)) -(def ^:icon pin-refactor (icon-xref :pin)) -(def ^:icon play-refactor (icon-xref :play)) -(def ^:icon rectangle-refactor (icon-xref :rectangle)) -(def ^:icon reload-refactor (icon-xref :reload)) -(def ^:icon remove-refactor (icon-xref :remove)) -(def ^:icon rgba-complementary-refactor (icon-xref :rgba-complementary)) -(def ^:icon rgba-refactor (icon-xref :rgba)) -(def ^:icon rotation-refactor (icon-xref :rotation)) -(def ^:icon row-reverse-refactor (icon-xref :row-reverse)) -(def ^:icon row-refactor (icon-xref :row)) -(def ^:icon search-refactor (icon-xref :search)) -(def ^:icon separate-nodes-refactor (icon-xref :separate-nodes)) -(def ^:icon shown-refactor (icon-xref :shown)) -(def ^:icon size-horizontal-refactor (icon-xref :size-horizontal)) -(def ^:icon size-vertical-refactor (icon-xref :size-vertical)) -(def ^:icon snap-nodes-refactor (icon-xref :snap-nodes)) -(def ^:icon status-alert-refactor (icon-xref :status-alert)) -(def ^:icon status-tick-refactor (icon-xref :status-tick)) -(def ^:icon status-update-refactor (icon-xref :status-update)) -(def ^:icon status-wrong-refactor (icon-xref :status-wrong)) -(def ^:icon stroke-arrow-refactor (icon-xref :stroke-arrow)) -(def ^:icon stroke-circle-refactor (icon-xref :stroke-circle)) -(def ^:icon stroke-diamond-refactor (icon-xref :stroke-diamond)) -(def ^:icon stroke-rectangle-refactor (icon-xref :stroke-rectangle)) -(def ^:icon stroke-rounded-refactor (icon-xref :stroke-rounded)) -(def ^:icon stroke-size-refactor (icon-xref :stroke-size)) -(def ^:icon stroke-squared-refactor (icon-xref :stroke-squared)) -(def ^:icon stroke-triangle-refactor (icon-xref :stroke-triangle)) -(def ^:icon svg-refactor (icon-xref :svg)) -(def ^:icon swatches-refactor (icon-xref :swatches)) -(def ^:icon switch-refactor (icon-xref :switch)) -(def ^:icon text-align-center-refactor (icon-xref :text-align-center)) -(def ^:icon text-align-left-refactor (icon-xref :text-align-left)) -(def ^:icon text-align-right-refactor (icon-xref :text-align-right)) -(def ^:icon text-auto-height-refactor (icon-xref :text-auto-height)) -(def ^:icon text-auto-width-refactor (icon-xref :text-auto-width)) -(def ^:icon text-bottom-refactor (icon-xref :text-bottom)) -(def ^:icon text-fixed-refactor (icon-xref :text-fixed)) -(def ^:icon text-justify-refactor (icon-xref :text-justify)) -(def ^:icon text-letterspacing-refactor (icon-xref :text-letterspacing)) -(def ^:icon text-lineheight-refactor (icon-xref :text-lineheight)) -(def ^:icon text-lowercase-refactor (icon-xref :text-lowercase)) -(def ^:icon text-ltr-refactor (icon-xref :text-ltr)) -(def ^:icon text-middle-refactor (icon-xref :text-middle)) -(def ^:icon text-mixed-refactor (icon-xref :text-mixed)) -(def ^:icon text-palette-refactor (icon-xref :text-palette)) -(def ^:icon text-paragraph-refactor (icon-xref :text-paragraph)) -(def ^:icon text-rtl-refactor (icon-xref :text-rtl)) -(def ^:icon text-stroked-refactor (icon-xref :text-stroked)) -(def ^:icon text-top-refactor (icon-xref :text-top)) -(def ^:icon text-underlined-refactor (icon-xref :text-underlined)) -(def ^:icon text-uppercase-refactor (icon-xref :text-uppercase)) -(def ^:icon text-refactor (icon-xref :text)) -(def ^:icon thumbnail-refactor (icon-xref :thumbnail)) -(def ^:icon tick-refactor (icon-xref :tick)) -(def ^:icon to-corner-refactor (icon-xref :to-corner)) -(def ^:icon to-curve-refactor (icon-xref :to-curve)) -(def ^:icon tree-refactor (icon-xref :tree)) -(def ^:icon unlock-refactor (icon-xref :unlock)) -(def ^:icon user-refactor (icon-xref :user)) +(def ^:icon absolute (icon-xref :absolute)) +(def ^:icon add (icon-xref :add)) +(def ^:icon align-bottom (icon-xref :align-bottom)) +(def ^:icon align-content-column-around (icon-xref :align-content-column-around)) +(def ^:icon align-content-column-between (icon-xref :align-content-column-between)) +(def ^:icon align-content-column-center (icon-xref :align-content-column-center)) +(def ^:icon align-content-column-end (icon-xref :align-content-column-end)) +(def ^:icon align-content-column-evenly (icon-xref :align-content-column-evenly)) +(def ^:icon align-content-column-start (icon-xref :align-content-column-start)) +(def ^:icon align-content-column-stretch (icon-xref :align-content-column-stretch)) +(def ^:icon align-content-row-around (icon-xref :align-content-row-around)) +(def ^:icon align-content-row-between (icon-xref :align-content-row-between)) +(def ^:icon align-content-row-center (icon-xref :align-content-row-center)) +(def ^:icon align-content-row-end (icon-xref :align-content-row-end)) +(def ^:icon align-content-row-evenly (icon-xref :align-content-row-evenly)) +(def ^:icon align-content-row-start (icon-xref :align-content-row-start)) +(def ^:icon align-content-row-stretch (icon-xref :align-content-row-stretch)) +(def ^:icon align-horizontal-center (icon-xref :align-horizontal-center)) +(def ^:icon align-items-column-center (icon-xref :align-items-column-center)) +(def ^:icon align-items-column-end (icon-xref :align-items-column-end)) +(def ^:icon align-items-column-start (icon-xref :align-items-column-start)) +(def ^:icon align-items-row-center (icon-xref :align-items-row-center)) +(def ^:icon align-items-row-end (icon-xref :align-items-row-end)) +(def ^:icon align-items-row-start (icon-xref :align-items-row-start)) +(def ^:icon align-left (icon-xref :align-left)) +(def ^:icon align-right (icon-xref :align-right)) +(def ^:icon align-self-column-bottom (icon-xref :align-self-column-bottom)) +(def ^:icon align-self-column-center (icon-xref :align-self-column-center)) +(def ^:icon align-self-column-stretch (icon-xref :align-self-column-stretch)) +(def ^:icon align-self-column-top (icon-xref :align-self-column-top)) +(def ^:icon align-self-row-center (icon-xref :align-self-row-center)) +(def ^:icon align-self-row-left (icon-xref :align-self-row-left)) +(def ^:icon align-self-row-right (icon-xref :align-self-row-right)) +(def ^:icon align-self-row-stretch (icon-xref :align-self-row-stretch)) +(def ^:icon align-top (icon-xref :align-top)) +(def ^:icon align-vertical-center (icon-xref :align-vertical-center)) +(def ^:icon arrow (icon-xref :arrow)) +(def ^:icon asc-sort (icon-xref :asc-sort)) +(def ^:icon board (icon-xref :board)) +(def ^:icon boards-thumbnail (icon-xref :boards-thumbnail)) +(def ^:icon boolean-difference (icon-xref :boolean-difference)) +(def ^:icon boolean-exclude (icon-xref :boolean-exclude)) +(def ^:icon boolean-flatten (icon-xref :boolean-flatten)) +(def ^:icon boolean-intersection (icon-xref :boolean-intersection)) +(def ^:icon boolean-union (icon-xref :boolean-union)) +(def ^:icon bug (icon-xref :bug)) +(def ^:icon clip-content (icon-xref :clip-content)) +(def ^:icon clipboard (icon-xref :clipboard)) +(def ^:icon close-small (icon-xref :close-small)) +(def ^:icon close (icon-xref :close)) +(def ^:icon code (icon-xref :code)) +(def ^:icon column-reverse (icon-xref :column-reverse)) +(def ^:icon column (icon-xref :column)) +(def ^:icon comments (icon-xref :comments)) +(def ^:icon component-copy (icon-xref :component-copy)) +(def ^:icon component (icon-xref :component)) +(def ^:icon constraint-horizontal (icon-xref :constraint-horizontal)) +(def ^:icon constraint-vertical (icon-xref :constraint-vertical)) +(def ^:icon corner-bottom-left (icon-xref :corner-bottom-left)) +(def ^:icon corner-bottom-right (icon-xref :corner-bottom-right)) +(def ^:icon corner-bottom (icon-xref :corner-bottom)) +(def ^:icon corner-center (icon-xref :corner-center)) +(def ^:icon corner-radius (icon-xref :corner-radius)) +(def ^:icon corner-top (icon-xref :corner-top)) +(def ^:icon corner-top-left (icon-xref :corner-top-left)) +(def ^:icon corner-top-right (icon-xref :corner-top-right)) +(def ^:icon curve (icon-xref :curve)) +(def ^:icon delete-text (icon-xref :delete-text)) +(def ^:icon delete (icon-xref :delete)) +(def ^:icon desc-sort (icon-xref :desc-sort)) +(def ^:icon detach (icon-xref :detach)) +(def ^:icon detached (icon-xref :detached)) +(def ^:icon distribute-horizontally (icon-xref :distribute-horizontally)) +(def ^:icon distribute-vertical-spacing (icon-xref :distribute-vertical-spacing)) +(def ^:icon document (icon-xref :document)) +(def ^:icon download (icon-xref :download)) +(def ^:icon drop-icon (icon-xref :drop)) +(def ^:icon easing-ease-in-out (icon-xref :easing-ease-in-out)) +(def ^:icon easing-ease-in (icon-xref :easing-ease-in)) +(def ^:icon easing-ease-out (icon-xref :easing-ease-out)) +(def ^:icon easing-ease (icon-xref :easing-ease)) +(def ^:icon easing-linear (icon-xref :easing-linear)) +(def ^:icon effects (icon-xref :effects)) +(def ^:icon elipse (icon-xref :elipse)) +(def ^:icon exit (icon-xref :exit)) +(def ^:icon expand (icon-xref :expand)) +(def ^:icon feedback (icon-xref :feedback)) +(def ^:icon fill-content (icon-xref :fill-content)) +(def ^:icon filter-icon (icon-xref :filter)) +(def ^:icon fixed-width (icon-xref :fixed-width)) +(def ^:icon flex-grid (icon-xref :flex-grid)) +(def ^:icon flex-horizontal (icon-xref :flex-horizontal)) +(def ^:icon flex-vertical (icon-xref :flex-vertical)) +(def ^:icon flex (icon-xref :flex)) +(def ^:icon flip-horizontal (icon-xref :flip-horizontal)) +(def ^:icon flip-vertical (icon-xref :flip-vertical)) +(def ^:icon gap-horizontal (icon-xref :gap-horizontal)) +(def ^:icon gap-vertical (icon-xref :gap-vertical)) +(def ^:icon graphics (icon-xref :graphics)) +(def ^:icon grid-column (icon-xref :grid-column)) +(def ^:icon grid-columns (icon-xref :grid-columns)) +(def ^:icon grid-gutter (icon-xref :grid-gutter)) +(def ^:icon grid-margin (icon-xref :grid-margin)) +(def ^:icon grid (icon-xref :grid)) +(def ^:icon grid-row (icon-xref :grid-row)) +(def ^:icon grid-rows (icon-xref :grid-rows)) +(def ^:icon grid-square (icon-xref :grid-square)) +(def ^:icon group (icon-xref :group)) +(def ^:icon gutter-horizontal (icon-xref :gutter-horizontal)) +(def ^:icon gutter-vertical (icon-xref :gutter-vertical)) +(def ^:icon help (icon-xref :help)) +(def ^:icon hide (icon-xref :hide)) +(def ^:icon history (icon-xref :history)) +(def ^:icon hsva (icon-xref :hsva)) +(def ^:icon hug-content (icon-xref :hug-content)) +(def ^:icon icon (icon-xref :icon)) +(def ^:icon img (icon-xref :img)) +(def ^:icon interaction (icon-xref :interaction)) +(def ^:icon join-nodes (icon-xref :join-nodes)) +(def ^:icon justify-content-column-around (icon-xref :justify-content-column-around)) +(def ^:icon justify-content-column-between (icon-xref :justify-content-column-between)) +(def ^:icon justify-content-column-center (icon-xref :justify-content-column-center)) +(def ^:icon justify-content-column-end (icon-xref :justify-content-column-end)) +(def ^:icon justify-content-column-evenly (icon-xref :justify-content-column-evenly)) +(def ^:icon justify-content-column-start (icon-xref :justify-content-column-start)) +(def ^:icon justify-content-row-around (icon-xref :justify-content-row-around)) +(def ^:icon justify-content-row-between (icon-xref :justify-content-row-between)) +(def ^:icon justify-content-row-center (icon-xref :justify-content-row-center)) +(def ^:icon justify-content-row-end (icon-xref :justify-content-row-end)) +(def ^:icon justify-content-row-evenly (icon-xref :justify-content-row-evenly)) +(def ^:icon justify-content-row-start (icon-xref :justify-content-row-start)) +(def ^:icon layers (icon-xref :layers)) +(def ^:icon library (icon-xref :library)) +(def ^:icon locate (icon-xref :locate)) +(def ^:icon lock (icon-xref :lock)) +(def ^:icon margin-bottom (icon-xref :margin-bottom)) +(def ^:icon margin-left (icon-xref :margin-left)) +(def ^:icon margin-left-right (icon-xref :margin-left-right)) +(def ^:icon margin-right (icon-xref :margin-right)) +(def ^:icon margin-top-bottom (icon-xref :margin-top-bottom)) +(def ^:icon margin-top (icon-xref :margin-top)) +(def ^:icon margin (icon-xref :margin)) +(def ^:icon mask (icon-xref :mask)) +(def ^:icon masked (icon-xref :masked)) +(def ^:icon menu (icon-xref :menu)) +(def ^:icon merge-nodes (icon-xref :merge-nodes)) +(def ^:icon move (icon-xref :move)) +(def ^:icon msg-error (icon-xref :msg-error)) +(def ^:icon msg-neutral (icon-xref :msg-neutral)) +(def ^:icon msg-success (icon-xref :msg-success)) +(def ^:icon msg-warning (icon-xref :msg-warning)) +(def ^:icon open-link (icon-xref :open-link)) +(def ^:icon padding-bottom (icon-xref :padding-bottom)) +(def ^:icon padding-extended (icon-xref :padding-extended)) +(def ^:icon padding-left-right (icon-xref :padding-left-right)) +(def ^:icon padding-left (icon-xref :padding-left)) +(def ^:icon padding-right (icon-xref :padding-right)) +(def ^:icon padding-top-bottom (icon-xref :padding-top-bottom)) +(def ^:icon padding-top (icon-xref :padding-top)) +(def ^:icon path (icon-xref :path)) +(def ^:icon pentool (icon-xref :pentool)) +(def ^:icon picker (icon-xref :picker)) +(def ^:icon pin (icon-xref :pin)) +(def ^:icon play (icon-xref :play)) +(def ^:icon rectangle (icon-xref :rectangle)) +(def ^:icon reload (icon-xref :reload)) +(def ^:icon remove-icon (icon-xref :remove)) +(def ^:icon rgba-complementary (icon-xref :rgba-complementary)) +(def ^:icon rgba (icon-xref :rgba)) +(def ^:icon rotation (icon-xref :rotation)) +(def ^:icon row-reverse (icon-xref :row-reverse)) +(def ^:icon row (icon-xref :row)) +(def ^:icon search (icon-xref :search)) +(def ^:icon separate-nodes (icon-xref :separate-nodes)) +(def ^:icon shown (icon-xref :shown)) +(def ^:icon size-horizontal (icon-xref :size-horizontal)) +(def ^:icon size-vertical (icon-xref :size-vertical)) +(def ^:icon snap-nodes (icon-xref :snap-nodes)) +(def ^:icon status-alert (icon-xref :status-alert)) +(def ^:icon status-tick (icon-xref :status-tick)) +(def ^:icon status-update (icon-xref :status-update)) +(def ^:icon status-wrong (icon-xref :status-wrong)) +(def ^:icon stroke-arrow (icon-xref :stroke-arrow)) +(def ^:icon stroke-circle (icon-xref :stroke-circle)) +(def ^:icon stroke-diamond (icon-xref :stroke-diamond)) +(def ^:icon stroke-rectangle (icon-xref :stroke-rectangle)) +(def ^:icon stroke-rounded (icon-xref :stroke-rounded)) +(def ^:icon stroke-size (icon-xref :stroke-size)) +(def ^:icon stroke-squared (icon-xref :stroke-squared)) +(def ^:icon stroke-triangle (icon-xref :stroke-triangle)) +(def ^:icon svg (icon-xref :svg)) +(def ^:icon swatches (icon-xref :swatches)) +(def ^:icon switch (icon-xref :switch)) +(def ^:icon text-align-center (icon-xref :text-align-center)) +(def ^:icon text-align-left (icon-xref :text-align-left)) +(def ^:icon text-align-right (icon-xref :text-align-right)) +(def ^:icon text-auto-height (icon-xref :text-auto-height)) +(def ^:icon text-auto-width (icon-xref :text-auto-width)) +(def ^:icon text-bottom (icon-xref :text-bottom)) +(def ^:icon text-fixed (icon-xref :text-fixed)) +(def ^:icon text-justify (icon-xref :text-justify)) +(def ^:icon text-letterspacing (icon-xref :text-letterspacing)) +(def ^:icon text-lineheight (icon-xref :text-lineheight)) +(def ^:icon text-lowercase (icon-xref :text-lowercase)) +(def ^:icon text-ltr (icon-xref :text-ltr)) +(def ^:icon text-middle (icon-xref :text-middle)) +(def ^:icon text-mixed (icon-xref :text-mixed)) +(def ^:icon text-palette (icon-xref :text-palette)) +(def ^:icon text-paragraph (icon-xref :text-paragraph)) +(def ^:icon text-rtl (icon-xref :text-rtl)) +(def ^:icon text-stroked (icon-xref :text-stroked)) +(def ^:icon text-top (icon-xref :text-top)) +(def ^:icon text-underlined (icon-xref :text-underlined)) +(def ^:icon text-uppercase (icon-xref :text-uppercase)) +(def ^:icon text (icon-xref :text)) +(def ^:icon thumbnail (icon-xref :thumbnail)) +(def ^:icon tick (icon-xref :tick)) +(def ^:icon to-corner (icon-xref :to-corner)) +(def ^:icon to-curve (icon-xref :to-curve)) +(def ^:icon tree (icon-xref :tree)) +(def ^:icon unlock (icon-xref :unlock)) +(def ^:icon user (icon-xref :user)) (def ^:icon v2-icon-1 (icon-xref :v2-icon-1)) (def ^:icon v2-icon-2 (icon-xref :v2-icon-2)) (def ^:icon v2-icon-3 (icon-xref :v2-icon-3)) (def ^:icon v2-icon-4 (icon-xref :v2-icon-4)) -(def ^:icon vertical-align-items-center-refactor (icon-xref :vertical-align-items-center)) -(def ^:icon vertical-align-items-end-refactor (icon-xref :vertical-align-items-end)) -(def ^:icon vertical-align-items-start-refactor (icon-xref :vertical-align-items-start)) -(def ^:icon view-as-icons-refactor (icon-xref :view-as-icons)) -(def ^:icon view-as-list-refactor (icon-xref :view-as-list)) -(def ^:icon wrap-refactor (icon-xref :wrap)) +(def ^:icon vertical-align-items-center (icon-xref :vertical-align-items-center)) +(def ^:icon vertical-align-items-end (icon-xref :vertical-align-items-end)) +(def ^:icon vertical-align-items-start (icon-xref :vertical-align-items-start)) +(def ^:icon view-as-icons (icon-xref :view-as-icons)) +(def ^:icon view-as-list (icon-xref :view-as-list)) +(def ^:icon wrap (icon-xref :wrap)) (def ^:icon loader-pencil diff --git a/frontend/src/app/main/ui/onboarding/newsletter.cljs b/frontend/src/app/main/ui/onboarding/newsletter.cljs index 0d027d607..e0336641e 100644 --- a/frontend/src/app/main/ui/onboarding/newsletter.cljs +++ b/frontend/src/app/main/ui/onboarding/newsletter.cljs @@ -56,7 +56,7 @@ [:label {:for "newsletter-updates"} [:span {:class (stl/css-case :global/checked @newsletter-updates)} (when @newsletter-updates - i/status-tick-refactor)] + i/status-tick)] (tr "onboarding-v2.newsletter.updates") [:input {:type "checkbox" :id "newsletter-updates" @@ -66,7 +66,7 @@ [:label {:for "newsletter-news"} [:span {:class (stl/css-case :global/checked @newsletter-news)} (when @newsletter-news - i/status-tick-refactor)] + i/status-tick)] (tr "onboarding-v2.newsletter.news") [:input {:type "checkbox" :id "newsletter-news" diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs index c509ca987..f7d96dca4 100644 --- a/frontend/src/app/main/ui/onboarding/questions.cljs +++ b/frontend/src/app/main/ui/onboarding/questions.cljs @@ -164,7 +164,7 @@ {:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png" :area "image3"} {:label (tr "questions.canva") :value "canva" :image "images/form/canva.png" :area "image4"} {:label (tr "questions.invision") :value "invision" :image "images/form/invision.png" :area "image5"} - {:label (tr "questions.never-used-one") :area "image6" :value "never-used-a-tool" :icon i/curve-refactor} + {:label (tr "questions.never-used-one") :area "image6" :value "never-used-a-tool" :icon i/curve} {:label (tr "questions.other") :value "other" :area "other"}] :name :experience-design-tool :class (stl/css :image-radio) diff --git a/frontend/src/app/main/ui/onboarding/team_choice.cljs b/frontend/src/app/main/ui/onboarding/team_choice.cljs index 646184e6f..a3a007c38 100644 --- a/frontend/src/app/main/ui/onboarding/team_choice.cljs +++ b/frontend/src/app/main/ui/onboarding/team_choice.cljs @@ -40,23 +40,23 @@ (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] + [:span {:class (stl/css :icon)} i/document] [:p {:class (stl/css :modal-desc)} (tr "onboarding.team-modal.create-team-feature-1")]] [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} i/move-refactor] + [:span {:class (stl/css :icon)} i/move] [:p {:class (stl/css :modal-desc)} (tr "onboarding.team-modal.create-team-feature-2")]] [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} i/tree-refactor] + [:span {:class (stl/css :icon)} i/tree] [:p {:class (stl/css :modal-desc)} (tr "onboarding.team-modal.create-team-feature-3")]] [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} i/user-refactor] + [:span {:class (stl/css :icon)} i/user] [:p {:class (stl/css :modal-desc)} (tr "onboarding.team-modal.create-team-feature-4")]] [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} i/tick-refactor] + [:span {:class (stl/css :icon)} i/tick] [:p {:class (stl/css :modal-desc)} (tr "onboarding.team-modal.create-team-feature-5")]]]]) diff --git a/frontend/src/app/main/ui/onboarding/templates.cljs b/frontend/src/app/main/ui/onboarding/templates.cljs index 121d661e7..af0abb2b1 100644 --- a/frontend/src/app/main/ui/onboarding/templates.cljs +++ b/frontend/src/app/main/ui/onboarding/templates.cljs @@ -71,7 +71,7 @@ [:div.modal-header [:div.modal-close-button {:on-click close-fn - :data-test "close-templates-btn"} i/close-refactor]] + :data-test "close-templates-btn"} i/close]] [:div.modal-content [:h3 (tr "onboarding.templates.title")] diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs index 4a2ffce59..663c9a09d 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.cljs +++ b/frontend/src/app/main/ui/settings/access_tokens.cljs @@ -172,7 +172,7 @@ :on-click copy-token} [:span {:class (stl/css :token-value)} (:token created "")] [:span {:class (stl/css :icon)} - i/clipboard-refactor]])]] + i/clipboard]])]] [:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :action-buttons)} diff --git a/frontend/src/app/main/ui/settings/change_email.cljs b/frontend/src/app/main/ui/settings/change_email.cljs index 64805a1b7..5543f7d18 100644 --- a/frontend/src/app/main/ui/settings/change_email.cljs +++ b/frontend/src/app/main/ui/settings/change_email.cljs @@ -107,7 +107,7 @@ :data-test "change-email-title"} (tr "modals.change-email.title")] [:button {:class (stl/css :modal-close-btn) - :on-click on-close} i/close-refactor]] + :on-click on-close} i/close]] [:div {:class (stl/css :modal-content)} [:& context-notification diff --git a/frontend/src/app/main/ui/settings/delete_account.cljs b/frontend/src/app/main/ui/settings/delete_account.cljs index d6803b215..384907dfe 100644 --- a/frontend/src/app/main/ui/settings/delete_account.cljs +++ b/frontend/src/app/main/ui/settings/delete_account.cljs @@ -44,7 +44,7 @@ [: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]] + :on-click on-close} i/close]] [:div {:class (stl/css :modal-content)} [:& context-notification diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 22137758a..60480d5f6 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -100,18 +100,18 @@ [:button {:class (stl/css-case :viewer-go-prev true :left-bar left-bar) :on-click go-prev-frame} - i/arrow-refactor]) + i/arrow]) (when (< (+ index 1) num-frames) [:button {:class (stl/css-case :viewer-go-next true :comment-sidebar comment-sidebar :right-bar right-bar) :on-click go-next-frame} - i/arrow-refactor]) + i/arrow]) [:div {:class (stl/css-case :viewer-bottom true :left-bar left-bar)} [:button {:on-click go-first-frame :class (stl/css :reset-button)} - i/reload-refactor] + i/reload] [:span {:class (stl/css :counter)} (str/join " / " [(+ index 1) num-frames])] [:span]]])) diff --git a/frontend/src/app/main/ui/viewer/comments.cljs b/frontend/src/app/main/ui/viewer/comments.cljs index 55b59e40d..c5677e0fb 100644 --- a/frontend/src/app/main/ui/viewer/comments.cljs +++ b/frontend/src/app/main/ui/viewer/comments.cljs @@ -67,7 +67,7 @@ [:div {:class (stl/css :view-options) :on-click toggle-dropdown} [:span {:class (stl/css :dropdown-title)} (tr "labels.comments")] - [:span {:class (stl/css :icon-dropdown)} i/arrow-refactor] + [:span {:class (stl/css :icon-dropdown)} i/arrow] [:& dropdown {:show @show-dropdown? :on-close hide-dropdown} @@ -80,7 +80,7 @@ :on-click update-mode} [:span {:class (stl/css :label)} (tr "labels.show-all-comments")] (when (or (= :all cmode) (nil? cmode)) - [:span {:class (stl/css :icon)} i/tick-refactor])] + [:span {:class (stl/css :icon)} i/tick])] [:li {:class (stl/css-case :dropdown-element true @@ -90,7 +90,7 @@ [:span {:class (stl/css :label)} (tr "labels.show-your-comments")] (when (= :yours cmode) [:span {:class (stl/css :icon)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css :separator)}] @@ -102,7 +102,7 @@ [:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")] (when (= :pending cshow) [:span {:class (stl/css :icon)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css :separator)}] @@ -113,7 +113,7 @@ :on-click update-options} [:span {:class (stl/css :label)} (tr "labels.show-comments-list")] (when show-sidebar? - [:span {:class (stl/css :icon)} i/tick-refactor])]]]])) + [:span {:class (stl/css :icon)} i/tick])]]]])) (defn- update-thread-position diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index e37f0e3b9..1b1734dca 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -86,13 +86,13 @@ [:button {:class (stl/css :zoom-btn) :on-click on-decrease} [:span {:class (stl/css :zoom-icon)} - i/remove-refactor]] + i/remove-icon]] [:p {:class (stl/css :zoom-text)} (fmt/format-percent zoom)] [:button {:class (stl/css :zoom-btn) :on-click on-increase} [:span {:class (stl/css :zoom-icon)} - i/add-refactor]]] + i/add]]] [:button {:class (stl/css :reset-btn) :on-click on-zoom-reset} (tr "workspace.header.reset-zoom")]] @@ -183,13 +183,13 @@ (when (:can-edit permissions) [:span {:on-click go-to-workspace :class (stl/css :edit-btn)} - i/curve-refactor]) + i/curve]) [:span {:title (tr "viewer.header.fullscreen") :class (stl/css-case :fullscreen-btn true :selected fullscreen?) :on-click toggle-fullscreen} - i/expand-refactor] + i/expand] (when (:is-admin permissions) [:button {:on-click open-share-dialog @@ -238,7 +238,7 @@ :on-click open-dropdown} [:span {:class (stl/css :breadcrumb-text)} (dm/str file-name " / " page-name)] - [:span {:class (stl/css :icon)} i/arrow-refactor] + [:span {:class (stl/css :icon)} i/arrow] [:span "/"] [:& dropdown {:show @show-dropdown? :on-close close-dropdown} @@ -252,11 +252,11 @@ [:span {:class (stl/css :label)} (get-in file [:data :pages-index id :name])] (when (= page-id id) - [:span {:class (stl/css :icon-check)} i/tick-refactor])])]]] + [:span {:class (stl/css :icon-check)} i/tick])])]]] [:div {:class (stl/css :current-frame) :on-click toggle-thumbnails} [:span {:class (stl/css :frame-name)} frame-name] - [:span {:class (stl/css :icon)} i/arrow-refactor]]]])) + [:span {:class (stl/css :icon)} i/arrow]]]])) (mf/defc header [{:keys [project file page frame zoom section permissions index interactions-mode]}] @@ -308,7 +308,7 @@ :class (stl/css-case :mode-zone-btn true :selected (= section :interactions)) :title (tr "viewer.header.interactions-section" (sc/get-tooltip :open-interactions))} - i/play-refactor] + i/play] (when (or (:can-edit permissions) (= (:who-comment permissions) "all")) @@ -317,7 +317,7 @@ :class (stl/css-case :mode-zone-btn true :selected (= section :comments)) :title (tr "viewer.header.comments-section" (sc/get-tooltip :open-comments))} - i/comments-refactor]) + i/comments]) (when (or (= (:type permissions) :membership) (and (= (:type permissions) :share-link) @@ -326,7 +326,7 @@ :class (stl/css-case :mode-zone-btn true :selected (= section :inspect)) :title (tr "viewer.header.inspect-section" (sc/get-tooltip :open-inspect))} - i/code-refactor])] + i/code])] [:& header-options {:section section :permissions permissions diff --git a/frontend/src/app/main/ui/viewer/inspect/code.cljs b/frontend/src/app/main/ui/viewer/inspect/code.cljs index 06dcdbe80..747d06204 100644 --- a/frontend/src/app/main/ui/viewer/inspect/code.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/code.cljs @@ -256,7 +256,7 @@ [:span {:class (stl/css-case :collapsabled-icon true :rotated collapsed-css?)} - i/arrow-refactor]] + i/arrow]] [:div {:class (stl/css :code-lang-option)} "CSS"] @@ -269,7 +269,7 @@ [:div {:class (stl/css :action-btns)} [:button {:class (stl/css :expand-button) :on-click on-expand} - i/code-refactor] + i/code] [:& copy-button {:data copy-css-fn :class (stl/css :css-copy-btn) @@ -295,7 +295,7 @@ [:span {:class (stl/css-case :collapsabled-icon true :rotated collapsed-markup?)} - i/arrow-refactor]] + i/arrow]] [:& radio-buttons {:selected markup-type :on-change set-markup @@ -310,7 +310,7 @@ [:div {:class (stl/css :action-btns)} [:button {:class (stl/css :expand-button) :on-click on-expand} - i/code-refactor] + i/code] [:& copy-button {:data copy-html-fn :class (stl/css :html-copy-btn) diff --git a/frontend/src/app/main/ui/viewer/inspect/exports.cljs b/frontend/src/app/main/ui/viewer/inspect/exports.cljs index 8e41f4a2f..392b6d8cd 100644 --- a/frontend/src/app/main/ui/viewer/inspect/exports.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/exports.cljs @@ -139,7 +139,7 @@ :title (tr "workspace.options.export") :class (stl/css :title-spacing-export-viewer)} [:button {:class (stl/css :add-export) - :on-click add-export} i/add-refactor]]] + :on-click add-export} i/add]]] (cond (= :multiple exports) @@ -148,7 +148,7 @@ [:div {:class (stl/css :actions)} [:button {:class (stl/css :action-btn) :on-click ()} - i/remove-refactor]]] + i/remove-icon]]] (seq @exports) [:div {:class (stl/css :element-set-content)} @@ -182,7 +182,7 @@ [:button {:class (stl/css :action-btn) :on-click (partial delete-export index)} - i/remove-refactor]])]) + i/remove-icon]])]) (when (or (= :multiple exports) (seq @exports)) [:button {:on-click (when-not in-progress? on-download) 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 1ab908b04..fffa430e1 100644 --- a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs @@ -89,7 +89,7 @@ [:div {:class (stl/css :shape-row)} (if (> (count shapes) 1) [:* - [:span {:class (stl/css :layers-icon)} i/layers-refactor] + [:span {:class (stl/css :layers-icon)} i/layers] [:span {:class (stl/css :layer-title)} (tr "inspect.tabs.code.selected.multiple" (count shapes))]] [:* [:span {:class (stl/css :shape-icon)} @@ -130,12 +130,12 @@ [:div {:class (stl/css :empty)} [:div {:class (stl/css :code-info)} [:span {:class (stl/css :placeholder-icon)} - i/code-refactor] + i/code] [: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] + i/help] [:span {:class (stl/css :placeholder-label)} (tr "inspect.empty.help")]] [:button {:class (stl/css :more-info-btn) diff --git a/frontend/src/app/main/ui/viewer/interactions.cljs b/frontend/src/app/main/ui/viewer/interactions.cljs index 03910ea5d..8d5fd829f 100644 --- a/frontend/src/app/main/ui/viewer/interactions.cljs +++ b/frontend/src/app/main/ui/viewer/interactions.cljs @@ -246,9 +246,9 @@ (when (seq flows) [:div {:on-click toggle-dropdown :class (stl/css :view-options)} - [:span {:class (stl/css :icon)} i/play-refactor] + [:span {:class (stl/css :icon)} i/play] [:span {:class (stl/css :dropdown-title)} (:name current-flow)] - [:span {:class (stl/css :icon-dropdown)} i/arrow-refactor] + [:span {:class (stl/css :icon-dropdown)} i/arrow] [:& dropdown {:show show-dropdown? :on-close hide-dropdown} [:ul {:class (stl/css :dropdown)} @@ -261,7 +261,7 @@ :on-click select-flow} [:span {:class (stl/css :label)} (:name flow)] (when (= (:id flow) (:id current-flow)) - [:span {:class (stl/css :icon)} i/tick-refactor])])]]]))) + [:span {:class (stl/css :icon)} i/tick])])]]]))) (mf/defc interactions-menu [{:keys [interactions-mode]}] @@ -280,7 +280,7 @@ [:div {:on-click toggle-dropdown :class (stl/css :view-options)} [:span {:class (stl/css :dropdown-title)} (tr "viewer.header.interactions")] - [:span {:class (stl/css :icon-dropdown)} i/arrow-refactor] + [:span {:class (stl/css :icon-dropdown)} i/arrow] [:& dropdown {:show @show-dropdown? :on-close hide-dropdown} [:ul {:class (stl/css :dropdown)} @@ -291,7 +291,7 @@ [:span {:class (stl/css :label)} (tr "viewer.header.dont-show-interactions")] (when (= interactions-mode :hide) - [:span {:class (stl/css :icon)} i/tick-refactor])] + [:span {:class (stl/css :icon)} i/tick])] [:li {:class (stl/css-case :dropdown-element true :selected (= interactions-mode :show)) @@ -299,7 +299,7 @@ :data-mode "show"} [:span {:class (stl/css :label)} (tr "viewer.header.show-interactions")] (when (= interactions-mode :show) - [:span {:class (stl/css :icon)} i/tick-refactor])] + [:span {:class (stl/css :icon)} i/tick])] @@ -310,7 +310,7 @@ [:span {:class (stl/css :label)} (tr "viewer.header.show-interactions-on-click")] (when (= interactions-mode :show-on-click) - [:span {:class (stl/css :icon)} i/tick-refactor])]]]])) + [:span {:class (stl/css :icon)} i/tick])]]]])) (defn animate-go-to-frame [animation current-viewport orig-viewport current-size orig-size wrapper-size] diff --git a/frontend/src/app/main/ui/viewer/login.cljs b/frontend/src/app/main/ui/viewer/login.cljs index afec5e502..a4f2c2f65 100644 --- a/frontend/src/app/main/ui/viewer/login.cljs +++ b/frontend/src/app/main/ui/viewer/login.cljs @@ -75,7 +75,7 @@ [: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]] + :on-click close} i/close]] [:div {:class (stl/css :modal-content)} diff --git a/frontend/src/app/main/ui/viewer/share_link.cljs b/frontend/src/app/main/ui/viewer/share_link.cljs index a937eada3..8b08ba935 100644 --- a/frontend/src/app/main/ui/viewer/share_link.cljs +++ b/frontend/src/app/main/ui/viewer/share_link.cljs @@ -172,7 +172,7 @@ [:button {:class (stl/css :modal-close-button) :on-click on-close :title (tr "labels.close")} - i/close-refactor]] + i/close]] [:div {:class (stl/css :modal-content)} [:div {:class (stl/css :share-link-section)} (when (and (not confirm?) (some? current-link)) @@ -186,7 +186,7 @@ [:button {:class (stl/css :copy-button) :title (tr "viewer.header.share.copy-link") :on-click copy-link} - i/clipboard-refactor]]) + i/clipboard]]) [:div {:class (stl/css :hint-wrapper)} (when (not ^boolean confirm?) @@ -227,7 +227,7 @@ :on-click toggle-perms-visibility} [:span {:class (stl/css-case :icon true :rotated perms-visible?)} - i/arrow-refactor] + i/arrow] (tr "common.share-link.manage-ops")] (when ^boolean perms-visible? @@ -247,7 +247,7 @@ :class (stl/css-case :global/checked true)} [:span {:class (stl/css :checked)} - i/status-tick-refactor] + i/status-tick] (:name current-page)] @@ -265,7 +265,7 @@ :class (stl/css :select-all-label)} [:span {:class (stl/css-case :global/checked all-selected?)} (when all-selected? - i/status-tick-refactor)] + i/status-tick)] (tr "common.share-link.view-all") [:input {:type "checkbox" :id "view-all" @@ -283,7 +283,7 @@ [:label {:for (dm/str "page-" id)} [:span {:class (stl/css-case :global/checked (contains? selected id))} (when (contains? selected id) - i/status-tick-refactor)] + i/status-tick)] name (when (= current-page-id id) [:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))]) diff --git a/frontend/src/app/main/ui/viewer/thumbnails.cljs b/frontend/src/app/main/ui/viewer/thumbnails.cljs index 22cead07f..7da49dfab 100644 --- a/frontend/src/app/main/ui/viewer/thumbnails.cljs +++ b/frontend/src/app/main/ui/viewer/thumbnails.cljs @@ -62,9 +62,9 @@ [:div {:class (stl/css :thumbnails-content)} [:button {:class (stl/css :left-scroll-handler) - :on-click on-left-arrow-click} i/arrow-refactor] + :on-click on-left-arrow-click} i/arrow] [:button {:class (stl/css :right-scroll-handler) - :on-click on-right-arrow-click} i/arrow-refactor] + :on-click on-right-arrow-click} i/arrow] [:div {:class (stl/css :thumbnails-list) :ref container @@ -80,9 +80,9 @@ (tr "labels.num-of-frames" (i18n/c total))] [:span {:class (stl/css :actions)} [:button {:class (stl/css :expand-btn) - :on-click on-toggle-expand} i/arrow-refactor] + :on-click on-toggle-expand} i/arrow] [:button {:class (stl/css :close-btn) - :on-click on-close} i/close-refactor]]]) + :on-click on-close} i/close]]]) (mf/defc thumbnail-item {::mf/wrap [mf/memo diff --git a/frontend/src/app/main/ui/workspace/color_palette.cljs b/frontend/src/app/main/ui/workspace/color_palette.cljs index 6ca87fabd..b48eb89dc 100644 --- a/frontend/src/app/main/ui/workspace/color_palette.cljs +++ b/frontend/src/app/main/ui/workspace/color_palette.cljs @@ -108,7 +108,7 @@ (when show-arrows? [:button {:class (stl/css :left-arrow) :disabled (= offset 0) - :on-click on-left-arrow-click} i/arrow-refactor]) + :on-click on-left-arrow-click} i/arrow]) [:div {:class (stl/css :color-palette-content) :ref container :on-wheel on-scroll} @@ -128,7 +128,7 @@ (when show-arrows? [:button {:class (stl/css :right-arrow) :disabled (= offset max-offset) - :on-click on-right-arrow-click} i/arrow-refactor])])) + :on-click on-right-arrow-click} i/arrow])])) (defn library->colors [shared-libs selected] (map #(merge % {:file-id selected}) diff --git a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs index 3f9ba68d8..17dbb9450 100644 --- a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs +++ b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs @@ -39,7 +39,7 @@ (dm/str "(" (count colors) ")")]] (when (= selected id) [:span {:class (stl/css :icon-wrapper)} - i/tick-refactor])] + i/tick])] [:div {:class (stl/css :color-sample) :style #js {"--bullet-size" "20px"}} (for [[i {:keys [color id gradient]}] (map-indexed vector (take 7 colors))] @@ -63,7 +63,7 @@ (when (= selected :file) [:span {:class (stl/css :icon-wrapper)} - i/tick-refactor])] + i/tick])] [:div {:class (stl/css :color-sample) :style #js {"--bullet-size" "20px"}} (for [[i color] (map-indexed vector (take 7 (vals file-colors)))] @@ -85,7 +85,7 @@ (when (= selected :recent) [:span {:class (stl/css :icon-wrapper)} - i/tick-refactor])] + i/tick])] [:div {:class (stl/css :color-sample) :style #js {"--bullet-size" "20px"}} (for [[idx color] (map-indexed vector (take 7 (reverse recent-colors)))] diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs index 115ba8f77..bfcb839db 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs @@ -264,7 +264,7 @@ [:button {:class (stl/css-case :picker-btn true :selected picking-color?) :on-click handle-click-picker} - i/picker-refactor])] + i/picker])] (when (or (= selected-mode :linear-gradient) (= selected-mode :radial-gradient)) @@ -287,7 +287,7 @@ :class (stl/css-case :global/checked keep-aspect-ratio?)} [:span {:class (stl/css-case :global/checked keep-aspect-ratio?)} (when keep-aspect-ratio? - i/status-tick-refactor)] + i/status-tick)] (tr "media.keep-aspect-ratio") [:input {:type "checkbox" :id "keep-aspect-ratio" @@ -312,7 +312,7 @@ :selected @active-color-tab :collapsable false} - [:& tab-element {:id :ramp :title i/rgba-refactor} + [:& tab-element {:id :ramp :title i/rgba} (if picking-color? [:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :center-circle)}] @@ -324,7 +324,7 @@ :on-start-drag on-start-drag :on-finish-drag on-finish-drag}])] - [:& tab-element {:id :harmony :title i/rgba-complementary-refactor} + [:& tab-element {:id :harmony :title i/rgba-complementary} (if picking-color? [:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :center-circle)}] @@ -336,7 +336,7 @@ :on-start-drag on-start-drag :on-finish-drag on-finish-drag}])] - [:& tab-element {:id :hsva :title i/hsva-refactor} + [:& tab-element {:id :hsva :title i/hsva} (if picking-color? [:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :center-circle)}] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs index 076aef276..a00058dfb 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs @@ -109,11 +109,11 @@ (when (= @selected :file) [:button {:class (stl/css :add-color-btn) :on-click on-add-library-color} - i/add-refactor]) + i/add]) [:button {:class (stl/css :palette-btn) :on-click toggle-palette} - i/swatches-refactor] + i/swatches] (for [[idx color] (map-indexed vector @current-colors)] [:& cb/color-bullet diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index 19fce235f..4ff0e1842 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -53,19 +53,19 @@ :on-click update-mode} [:span {:class (stl/css :label)} (tr "labels.show-all-comments")] - [:span {:class (stl/css :icon)} i/tick-refactor]] + [:span {:class (stl/css :icon)} i/tick]] [: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]] + [:span {:class (stl/css :icon)} i/tick]] [: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]]])) + [:span {:class (stl/css :icon)} i/tick]]])) (mf/defc comments-sidebar {::mf/props :obj} @@ -125,7 +125,7 @@ [:span (tr "labels.comments")] [:button {:class (stl/css :close-button) :on-click close-section} - i/close-refactor]] + i/close]] [:button {:class (stl/css :mode-dropdown-wrapper) :on-click toggle-mode-selector} @@ -133,7 +133,7 @@ [: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 :arrow-icon)} i/arrow-refactor]] + [:div {:class (stl/css :arrow-icon)} i/arrow]] [:& dropdown {:show options? :on-close #(reset! state* false)} @@ -155,6 +155,6 @@ :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-icon)} i/comments] [:span {:class (stl/css :placeholder-label)} (tr "labels.no-comments-available")]])]])) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index cf566b7af..01b008502 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -96,7 +96,7 @@ [:span {:class (stl/css :icon-wrapper)} (if selected? [:span {:class (stl/css :selected-icon)} - i/tick-refactor] + i/tick] [:span {:class (stl/css :selected-icon)}]) [:span {:class (stl/css :shape-icon)} icon]] [:span {:class (stl/css :title)} title]] @@ -115,7 +115,7 @@ :class (stl/css :shortcut-key)} sc])]) (when (> (count children) 1) - [:span {:class (stl/css :submenu-icon)} i/arrow-refactor]) + [:span {:class (stl/css :submenu-icon)} i/arrow]) (when (> (count children) 1) [:ul {:class (stl/css :workspace-context-submenu) diff --git a/frontend/src/app/main/ui/workspace/left_header.cljs b/frontend/src/app/main/ui/workspace/left_header.cljs index 0c1cd4930..64d8e068d 100644 --- a/frontend/src/app/main/ui/workspace/left_header.cljs +++ b/frontend/src/app/main/ui/workspace/left_header.cljs @@ -108,7 +108,7 @@ :on-double-click start-editing-name} file-name])] (when ^boolean shared? - [:span {:class (stl/css :shared-badge)} i/library-refactor]) + [:span {:class (stl/css :shared-badge)} i/library]) [:div {:class (stl/css :menu-section)} [:& main-menu/menu {:layout layout diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index e976c0230..e88013b76 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -230,7 +230,7 @@ :type "button" :data-library-id (dm/str id) :on-click unlink-library} - i/detach-refactor]])]] + i/detach]])]] [:div {:class (stl/css :section)} [:& title-bar {:collapsable false @@ -240,7 +240,7 @@ [:& search-bar {:on-change change-search-term :value search-term :placeholder (tr "workspace.libraries.search-shared-libraries") - :icon (mf/html [:span {:class (stl/css :search-icon)} i/search-refactor])}]] + :icon (mf/html [:span {:class (stl/css :search-icon)} i/search])}]] (if (seq shared-libraries) [:div {:class (stl/css :section-list-shared)} @@ -261,7 +261,7 @@ [:button {:class (stl/css :item-button-shared) :data-library-id (dm/str id) :on-click link-library} - i/add-refactor]])] + i/add]])] (when (empty? shared-libraries) [:div {:class (stl/css :section-list-empty)} @@ -493,7 +493,7 @@ [:div {:class (stl/css :modal-dialog)} [:button {:class (stl/css :close) :on-click close-dialog} - i/close-refactor] + i/close] [:div {:class (stl/css :modal-title)} "Libraries"] [:div {:class (stl/css :modal-content)} diff --git a/frontend/src/app/main/ui/workspace/main_menu.cljs b/frontend/src/app/main/ui/workspace/main_menu.cljs index 8255202d8..9c6c83418 100644 --- a/frontend/src/app/main/ui/workspace/main_menu.cljs +++ b/frontend/src/app/main/ui/workspace/main_menu.cljs @@ -654,7 +654,7 @@ [:* [:div {:on-click open-menu - :class (stl/css :menu-btn)} i/menu-refactor] + :class (stl/css :menu-btn)} i/menu] [:& dropdown-menu {:show show-menu? :on-close close-menu @@ -669,7 +669,7 @@ :data-test "file" :id "file-menu-file"} [:span {:class (stl/css :item-name)} (tr "workspace.header.menu.option.file")] - [:span {:class (stl/css :open-arrow)} i/arrow-refactor]] + [:span {:class (stl/css :open-arrow)} i/arrow]] [:> dropdown-menu-item* {:class (stl/css :menu-item) :on-click on-menu-click @@ -680,7 +680,7 @@ :data-test "edit" :id "file-menu-edit"} [:span {:class (stl/css :item-name)} (tr "workspace.header.menu.option.edit")] - [:span {:class (stl/css :open-arrow)} i/arrow-refactor]] + [:span {:class (stl/css :open-arrow)} i/arrow]] [:> dropdown-menu-item* {:class (stl/css :menu-item) :on-click on-menu-click @@ -691,7 +691,7 @@ :data-test "view" :id "file-menu-view"} [:span {:class (stl/css :item-name)} (tr "workspace.header.menu.option.view")] - [:span {:class (stl/css :open-arrow)} i/arrow-refactor]] + [:span {:class (stl/css :open-arrow)} i/arrow]] [:> dropdown-menu-item* {:class (stl/css :menu-item) :on-click on-menu-click @@ -702,7 +702,7 @@ :data-test "preferences" :id "file-menu-preferences"} [:span {:class (stl/css :item-name)} (tr "workspace.header.menu.option.preferences")] - [:span {:class (stl/css :open-arrow)} i/arrow-refactor]] + [:span {:class (stl/css :open-arrow)} i/arrow]] [:div {:class (stl/css :separator)}] [:> dropdown-menu-item* {:class (stl/css-case :menu-item true) :on-click on-menu-click @@ -713,7 +713,7 @@ :data-test "help-info" :id "file-menu-help-info"} [:span {:class (stl/css :item-name)} (tr "workspace.header.menu.option.help-info")] - [:span {:class (stl/css :open-arrow)} i/arrow-refactor]]] + [:span {:class (stl/css :open-arrow)} i/arrow]]] (case sub-menu :file diff --git a/frontend/src/app/main/ui/workspace/nudge.cljs b/frontend/src/app/main/ui/workspace/nudge.cljs index 868e294fd..28e567611 100644 --- a/frontend/src/app/main/ui/workspace/nudge.cljs +++ b/frontend/src/app/main/ui/workspace/nudge.cljs @@ -46,7 +46,7 @@ [: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]] + :on-click on-close} i/close]] [:div {:class (stl/css :modal-content)} [:div {:class (stl/css :input-wrapper)} [:label {:class (stl/css :modal-msg) diff --git a/frontend/src/app/main/ui/workspace/palette.cljs b/frontend/src/app/main/ui/workspace/palette.cljs index 8eb2ac84a..eab23c77b 100644 --- a/frontend/src/app/main/ui/workspace/palette.cljs +++ b/frontend/src/app/main/ui/workspace/palette.cljs @@ -162,7 +162,7 @@ :class (stl/css-case :palette-btn true :selected color-palette?) :on-click on-select-color-palette} - i/drop-refactor]] + i/drop-icon]] [:li {:class (stl/css :palette-item)} [:button {:title (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette)) @@ -170,14 +170,14 @@ :class (stl/css-case :palette-btn true :selected text-palette?) :on-click on-select-text-palette} - i/text-palette-refactor]]] + i/text-palette]]] (if any-palette? [:* [:button {:class (stl/css :palette-actions) :on-click #(swap! state* update :show-menu not)} - i/menu-refactor] + i/menu] [:div {:class (stl/css :palette) :ref container} (when text-palette? diff --git a/frontend/src/app/main/ui/workspace/right_header.cljs b/frontend/src/app/main/ui/workspace/right_header.cljs index dd9598e30..1fae7d76c 100644 --- a/frontend/src/app/main/ui/workspace/right_header.cljs +++ b/frontend/src/app/main/ui/workspace/right_header.cljs @@ -40,25 +40,25 @@ [:div {:class (stl/css-case :status-icon true :pending-status true) :title (tr "workspace.header.unsaved")} - i/status-alert-refactor] + i/status-alert] :saving [:div {:class (stl/css-case :status-icon true :saving-status true) :title (tr "workspace.header.saving")} - i/status-update-refactor] + i/status-update] :saved [:div {:class (stl/css-case :status-icon true :saved-status true) :title (tr "workspace.header.saved")} - i/status-tick-refactor] + i/status-tick] :error [:div {:class (stl/css-case :status-icon true :error-status true) :title "There was an error saving the data. Please refresh if this persists."} - i/status-wrong-refactor] + i/status-wrong] nil)])) @@ -112,12 +112,12 @@ [:button {:class (stl/css :zoom-btn) :on-click on-decrease} [:span {:class (stl/css :zoom-icon)} - i/remove-refactor]] + i/remove-icon]] [:p {:class (stl/css :zoom-text)} zoom] [:button {:class (stl/css :zoom-btn) :on-click on-increase} [:span {:class (stl/css :zoom-icon)} - i/add-refactor]]] + i/add]]] [:button {:class (stl/css :reset-btn) :on-click on-zoom-reset} (tr "workspace.header.reset-zoom")]] @@ -223,7 +223,7 @@ :selected (= selected-drawtool :comments)) :on-click toggle-comments :data-tool "comments"} - i/comments-refactor]] + i/comments]] (when-not ^boolean read-only? [:div {:class (stl/css :history-section)} @@ -233,10 +233,10 @@ :class (stl/css-case :selected (contains? layout :document-history) :history-button true) :on-click toggle-history} - i/history-refactor]]) + i/history]]) [:a {:class (stl/css :viewer-btn) :title (tr "workspace.header.viewer" (sc/get-tooltip :open-viewer)) :on-click nav-to-viewer} - i/play-refactor]])) + i/play]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index f43724ca1..da7ed67fe 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -159,7 +159,7 @@ [:button {:class (stl/css :libraries-button) :on-click show-libraries-dialog} [:span {:class (stl/css :libraries-icon)} - i/library-refactor] + i/library] (tr "workspace.assets.libraries")]) [:div {:class (stl/css :search-wrapper)} @@ -170,7 +170,7 @@ {:on-click on-open-menu :class (stl/css-case :section-button true :opened menu-open?)} - i/filter-refactor]] + i/filter-icon]] [:& context-menu-a11y {:on-close on-menu-close :selectable true @@ -186,8 +186,8 @@ [:button {:class (stl/css :sort-button) :on-click toggle-ordering} (if reverse-sort? - i/asc-sort-refactor - i/desc-sort-refactor)]]] + i/asc-sort + i/desc-sort)]]] [:& (mf/provider cmm/assets-filters) {:value filters} [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering} 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 ef4b9200c..1f0004462 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs @@ -485,7 +485,7 @@ (when-not read-only? [:button {:class (stl/css :assets-btn) :on-click add-color-clicked} - i/add-refactor])]) + i/add])]) [:& cmm/asset-section-block {:role :content} 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 f8f7bb6c5..888143fdb 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs @@ -123,10 +123,10 @@ {::mf/wrap-props false} [{:keys [section]}] (case section - :colors i/drop-refactor - :components i/component-refactor - :typographies i/text-palette-refactor - i/add-refactor)) + :colors i/drop-icon + :components i/component + :typographies i/text-palette + i/add)) (mf/defc asset-section {::mf/wrap-props false} 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 65b87340c..65a109333 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs @@ -517,17 +517,17 @@ [:& radio-buttons {:selected (if listing-thumbs? "grid" "list") :on-change toggle-list-style :name "listing-style"} - [:& radio-button {:icon i/view-as-list-refactor + [:& radio-button {:icon i/view-as-list :value "list" :id "opt-list"}] - [:& radio-button {:icon i/flex-grid-refactor + [:& radio-button {:icon i/flex-grid :value "grid" :id "opt-grid"}]]]) (when (and components-v2 (not read-only?) local?) [:div {:on-click add-component :class (stl/css :add-component)} - i/add-refactor + i/add [:& file-uploader {:accept cm/str-image-types :multi true :ref input-ref 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 257418869..f822fb5f8 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 @@ -70,7 +70,7 @@ :href (str "#" url) :target "_blank" :on-click dom/stop-propagation} - i/open-link-refactor]])]])) + i/open-link]])]])) (mf/defc file-library-content {::mf/wrap-props false} @@ -290,7 +290,7 @@ (not ^boolean show-typography?)) [:div {:class (stl/css :asset-title)} [:span {:class (stl/css :no-found-icon)} - i/search-refactor] + i/search] [:span {:class (stl/css :no-found-text)} (tr "workspace.assets.not-found")]])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs index 45d2a1535..f8c7e2b8a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs @@ -390,7 +390,7 @@ (when (and (not components-v2) (not read-only?)) [:button {:class (stl/css :assets-btn) :on-click add-graphic} - i/add-refactor + i/add [:& file-uploader {:accept cm/str-image-types :multi true :ref input-ref 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 2431c88b7..dc882483e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs @@ -131,7 +131,7 @@ (tr "workspace.assets.create-group") (tr "workspace.assets.rename-group"))] [:button {:class (stl/css :modal-close-btn) - :on-click on-close} i/close-refactor]] + :on-click on-close} i/close]] [:div {:class (stl/css :modal-content)} [:& fm/form {:form form :on-submit on-accept} 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 34ae000a6..6c5ae2fd2 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs @@ -403,7 +403,7 @@ (when-not read-only? [:button {:class (stl/css :assets-btn) :on-click add-typography} - i/add-refactor])]) + i/add])]) [:& cmm/asset-section-block {:role :content} [:& typographies-group {:file-id file-id 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 349ea74bd..31c9b0af5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs @@ -24,4 +24,4 @@ [:button {:class (stl/css :collapsed-button) :on-click on-click :aria-label (tr "workspace.sidebar.expand")} - i/arrow-refactor]]])) + i/arrow]]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs index b49371e5f..56f4f6119 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs @@ -35,14 +35,14 @@ [:div {:class (stl/css :panel-title)} [:span "Debugging tools"] [:div {:class (stl/css :close-button) :on-click handle-close} - i/close-refactor]] + i/close]] [:div {:class (stl/css :debug-panel-inner)} (for [option (sort-by d/name dbg/options)] [: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)] + (when (dbg/enabled? option) i/status-tick)] [:input {:type "checkbox" :id (d/name option) diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs b/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs index 663f84b3e..12745448f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs @@ -129,7 +129,7 @@ [:span "Debug"] [:div {:class (stl/css :close-button) :on-click #(dbg/disable! :shape-panel)} - i/close-refactor]] + i/close]] (if (empty? selected) [:div {:class (stl/css :attrs-container)} "No shapes selected"] diff --git a/frontend/src/app/main/ui/workspace/sidebar/history.cljs b/frontend/src/app/main/ui/workspace/sidebar/history.cljs index d592efe4f..38b83de94 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/history.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/history.cljs @@ -150,20 +150,20 @@ (defn entry->icon [{:keys [type]}] (case type - :page i/document-refactor - :shape i/svg-refactor - :rect i/rectangle-refactor - :circle i/elipse-refactor - :text i/text-refactor - :path i/path-refactor - :frame i/board-refactor - :group i/group-refactor - :color i/drop-refactor - :typography i/text-palette-refactor - :component i/component-refactor - :media i/img-refactor - :image i/img-refactor - i/svg-refactor)) + :page i/document + :shape i/svg + :rect i/rectangle + :circle i/elipse + :text i/text + :path i/path + :frame i/board + :group i/group + :color i/drop-icon + :typography i/text-palette + :component i/component + :media i/img + :image i/img + i/svg)) (defn is-shape? [type] (contains? #{:shape :rect :circle :text :path :frame :group} type)) @@ -315,7 +315,7 @@ :button-opened @show-detail?) :on-click toggle-show-detail :data-has-entry (dm/str (not (nil? (:detail entry))))} - i/arrow-refactor])] + i/arrow])] (when @show-detail? [:& history-entry-details {:entry entry}])])) @@ -334,10 +334,10 @@ [:span (t locale "workspace.undo.title")] [:div {:class (stl/css :close-button) :on-click toggle-history} - i/close-refactor]] + i/close]] (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-icon)} i/history] [: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)] diff --git a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs index 97c8274d5..43fb73974 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs @@ -93,7 +93,7 @@ :toggle-content true :inverse expanded?) :on-click on-toggle-collapse} - i/arrow-refactor]) + i/arrow]) [:div {:class (stl/css :icon-shape) :on-double-click on-zoom-to-selected} @@ -142,7 +142,7 @@ (tr "workspace.shape.menu.show") (tr "workspace.shape.menu.hide")) :on-click on-toggle-visibility} - (if ^boolean hidden? i/hide-refactor i/shown-refactor)] + (if ^boolean hidden? i/hide i/shown)] [:button {:class (stl/css-case :block-element true :selected blocked?) @@ -150,7 +150,7 @@ (tr "workspace.shape.menu.unlock") (tr "workspace.shape.menu.lock")) :on-click on-toggle-blocking} - (if ^boolean blocked? i/lock-refactor i/unlock-refactor)]])]] + (if ^boolean blocked? i/lock i/unlock)]])]] children])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index b2d460d44..258d6dcd5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -283,11 +283,11 @@ :filter-button true :opened show-menu? :active active?)} - i/filter-refactor]] + i/filter-icon]] [:button {:class (stl/css :close-search) :on-click toggle-search} - i/close-refactor]] + i/close]] [:div {:class (stl/css :active-filters)} (for [fkey current-filters] @@ -314,7 +314,7 @@ [:span {:class (stl/css :layer-filter-name)} name] [:span {:class (stl/css :layer-filter-close)} - i/close-small-refactor]]))] + i/close-small]]))] (when ^boolean show-menu? [:ul {:class (stl/css :filters-container)} @@ -324,13 +324,13 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/board-refactor] + i/board] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.frames")]] (when (contains? current-filters :frame) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css-case :filter-menu-item true :selected (contains? current-filters :group)) @@ -338,13 +338,13 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/group-refactor] + i/group] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.groups")]] (when (contains? current-filters :group) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css-case :filter-menu-item true :selected (contains? current-filters :mask)) @@ -352,13 +352,13 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/mask-refactor] + i/mask] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.masks")]] (when (contains? current-filters :mask) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css-case :filter-menu-item true :selected (contains? current-filters :component)) @@ -366,13 +366,13 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/component-refactor] + i/component] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.components")]] (when (contains? current-filters :component) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css-case :filter-menu-item true :selected (contains? current-filters :text)) @@ -380,13 +380,13 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/text-refactor] + i/text] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.texts")]] (when (contains? current-filters :text) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css-case :filter-menu-item true :selected (contains? current-filters :image)) @@ -394,13 +394,13 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/img-refactor] + i/img] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.images")]] (when (contains? current-filters :image) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])] + i/tick])] [:li {:class (stl/css-case :filter-menu-item true :selected (contains? current-filters :shape)) @@ -408,19 +408,19 @@ :on-click add-filter} [:div {:class (stl/css :filter-menu-item-name-wrapper)} [:span {:class (stl/css :filter-menu-item-icon)} - i/path-refactor] + i/path] [:span {:class (stl/css :filter-menu-item-name)} (tr "workspace.sidebar.layers.shapes")]] (when (contains? current-filters :shape) [:span {:class (stl/css :filter-menu-item-tick)} - i/tick-refactor])]])] + i/tick])]])] [:div {:class (stl/css :tool-window-bar)} [:& title-bar {:collapsable false :title (:name page) :on-btn-click toggle-search - :btn-children i/search-refactor}]]))])) + :btn-children i/search}]]))])) (defn- on-scroll @@ -507,7 +507,7 @@ [:button {:class (stl/css :focus-title) :on-click toogle-focus-mode} [:span {:class (stl/css :back-button)} - i/arrow-refactor] + i/arrow] [:div {:class (stl/css :focus-name)} (or title (tr "workspace.sidebar.layers"))] 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 f6dc8e634..d91fc9757 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 @@ -50,7 +50,7 @@ :title (tr "workspace.align.hleft" (sc/get-tooltip :align-left)) :data-value "hleft" :on-click align-objects} - i/align-left-refactor] + i/align-left] [:button {:class (stl/css-case :align-button true :disabled disabled-align) @@ -58,7 +58,7 @@ :title (tr "workspace.align.hcenter" (sc/get-tooltip :align-hcenter)) :data-value "hcenter" :on-click align-objects} - i/align-horizontal-center-refactor] + i/align-horizontal-center] [:button {:class (stl/css-case :align-button true :disabled disabled-align) @@ -66,7 +66,7 @@ :title (tr "workspace.align.hright" (sc/get-tooltip :align-right)) :data-value "hright" :on-click align-objects} - i/align-right-refactor] + i/align-right] [:button {:class (stl/css-case :align-button true :disabled disabled-distribute) @@ -74,7 +74,7 @@ :title (tr "workspace.align.hdistribute" (sc/get-tooltip :h-distribute)) :data-value "horizontal" :on-click distribute-objects} - i/distribute-horizontally-refactor]] + i/distribute-horizontally]] [:div {:class (stl/css :align-group)} [:button {:class (stl/css-case :align-button true @@ -83,7 +83,7 @@ :title (tr "workspace.align.vtop" (sc/get-tooltip :align-top)) :data-value "vtop" :on-click align-objects} - i/align-top-refactor] + i/align-top] [:button {:class (stl/css-case :align-button true :disabled disabled-align) @@ -91,7 +91,7 @@ :title (tr "workspace.align.vcenter" (sc/get-tooltip :align-vcenter)) :data-value "vcenter" :on-click align-objects} - i/align-vertical-center-refactor] + i/align-vertical-center] [:button {:class (stl/css-case :align-button true :disabled disabled-align) @@ -99,7 +99,7 @@ :title (tr "workspace.align.vbottom" (sc/get-tooltip :align-bottom)) :data-value "vbottom" :on-click align-objects} - i/align-bottom-refactor] + i/align-bottom] [:button {:title (tr "workspace.align.vdistribute" (sc/get-tooltip :v-distribute)) :class (stl/css-case :align-button true @@ -107,5 +107,5 @@ :disabled disabled-distribute :data-value "vertical" :on-click distribute-objects} - i/distribute-vertical-spacing-refactor]]]))) + i/distribute-vertical-spacing]]]))) 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 102c9e68c..89ecb0bc9 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 @@ -87,7 +87,7 @@ :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])]] + :on-click handle-add} i/add])]] (when (and open? has-value?) [:div {:class (stl/css :element-set-content)} [:div {:class (stl/css-case :first-row true @@ -96,17 +96,17 @@ [:button {:class (stl/css-case :show-more true :selected more-options?) :on-click toggle-more-options} - i/menu-refactor] + i/menu] [: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)] + i/hide + i/shown)] [:button {:class (stl/css :action-btn) - :on-click handle-delete} i/remove-refactor]]] + :on-click handle-delete} i/remove-icon]]] (when more-options? [:div {:class (stl/css :second-row)} [:label {:class (stl/css :label) 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 5b77d49b7..e223622b8 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 @@ -64,22 +64,22 @@ :class (stl/css :boolean-radio-btn) :on-change set-bool :name "bool-options"} - [:& radio-button {:icon i/boolean-union-refactor + [:& radio-button {:icon i/boolean-union :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 + [:& radio-button {:icon i/boolean-difference :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 + [:& radio-button {:icon i/boolean-intersection :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 + [:& radio-button {:icon i/boolean-exclude :value "exclude" :disabled disabled-bool-btns :title (str (tr "exclude") " (" (sc/get-tooltip :bool-exclude) ")") 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 84a888fba..9e6bb7c50 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 @@ -168,7 +168,7 @@ [:span {:class (stl/css-case :icon-arrow true :expanded expanded?)} - i/arrow-refactor] + i/arrow] [:span {:class (stl/css :annotation-text)} (tr "workspace.options.component.annotation")]]) @@ -186,21 +186,21 @@ :icon true :icon-tick true :hidden invalid-text?)} - i/tick-refactor] + i/tick] [:div {:class (stl/css :icon :icon-cross) :title (tr "labels.discard") :on-click on-discard} - i/close-refactor]] + i/close]] [:* [:div {:class (stl/css :icon :icon-edit) :title (tr "labels.edit") :on-click on-edit} - i/curve-refactor] + i/curve] [:div {:class (stl/css :icon :icon-trash) :title (tr "labels.delete") :on-click on-delete-annotation} - i/delete-refactor]]))]] + i/delete]]))]] [:div {:class (stl/css-case :hidden (not expanded?))} [:div {:class (stl/css :grow-wrap)} @@ -263,7 +263,7 @@ (cfh/last-path group-name)]] [:span {:class (stl/css :arrow-icon)} - i/arrow-refactor]])) + i/arrow]])) (def ^:private ref:swap-libraries (letfn [(get-libraries [state] @@ -440,7 +440,8 @@ :id "swap-component-search-filter" :value (:term filters) :placeholder (str (tr "labels.search") " " (get-in libraries [current-library-id :name])) - :icon (mf/html [:span {:class (stl/css :search-icon)} i/search-refactor])}]] + :icon (mf/html [:span {:class (stl/css :search-icon)} + i/search])}]] [:& select {:class (stl/css :select-library) :default-value current-library-id @@ -456,10 +457,10 @@ :selected (if (:listing-thumbs? filters) "grid" "list") :on-change toggle-list-style :name "swap-listing-style"} - [:& radio-button {:icon i/view-as-list-refactor + [:& radio-button {:icon i/view-as-list :value "list" :id "swap-opt-list"}] - [:& radio-button {:icon i/flex-grid-refactor + [:& radio-button {:icon i/flex-grid :value "grid" :id "swap-opt-grid"}]]]] @@ -467,7 +468,7 @@ [:button {:class (stl/css :component-path) :on-click on-go-back :title filter-path-with-dots} - [:span {:class (stl/css :back-arrow)} i/arrow-refactor] + [:span {:class (stl/css :back-arrow)} i/arrow] (when-not (= "" filter-path-with-dots) [:span {:class (stl/css :path-name)} (dm/str "\u00A0\u2022\u00A0" filter-path-with-dots)]) @@ -590,7 +591,7 @@ (if swap-opened? [:button {:class (stl/css :title-back) :on-click on-component-back} - [:span {:class (stl/css :icon-back)} i/arrow-refactor] + [:span {:class (stl/css :icon-back)} i/arrow] [:span (tr "workspace.options.component")]] [:& title-bar {:collapsable true @@ -615,8 +616,8 @@ [:span {:class (stl/css :component-icon)} (if main-instance? - i/component-refactor - i/copy-refactor)] + i/component + i/component-copy)] [:div {:class (stl/css :name-wrapper)} [:div {:class (stl/css :component-name)} @@ -633,7 +634,7 @@ [:button {:class (stl/css-case :menu-btn true :selected menu-open?) :on-click on-menu-click} - i/menu-refactor] + i/menu] [:& component-ctx-menu {:show menu-open? :on-close on-menu-close 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 538b4f960..ce3bdedca 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 @@ -225,7 +225,7 @@ [:span {:class (stl/css-case :check-mark true :checked (:fixed-scroll values))} (when (:fixed-scroll values) - i/status-tick-refactor)] + i/status-tick)] (tr "workspace.options.constraints.fix-when-scrolling") [:input {:type "checkbox" :id "fixed-on-scroll" 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 da7b371a5..216ad4231 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 @@ -177,7 +177,8 @@ :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]]] + :on-click add-export} + i/add]]] (when open? [:div {:class (stl/css :element-set-content)} @@ -188,7 +189,7 @@ [:div {:class (stl/css :actions)} [:button {:class (stl/css :action-btn) :on-click on-remove-all} - i/remove-refactor]]] + i/remove-icon]]] (seq exports) [:* @@ -222,7 +223,7 @@ [:button {:class (stl/css :action-btn) :on-click (partial delete-export index)} - i/remove-refactor]])]) + i/remove-icon]])]) (when (or (= :multiple exports) (seq exports)) [:button 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 eb6eff7f2..82e8fe530 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 @@ -145,7 +145,7 @@ (when (and (not disable-remove?) (not (= :multiple fills))) [:button {:class (stl/css :add-fill) - :on-click on-add} i/add-refactor])]] + :on-click on-add} i/add])]] (when open? [:div {:class (stl/css :element-content)} @@ -156,7 +156,7 @@ (tr "settings.multiple")] [:button {:on-click on-remove-all :class (stl/css :remove-btn)} - i/remove-refactor]] + i/remove-icon]] (seq fills) [:& h/sortable-container {} @@ -187,7 +187,7 @@ [:span {:class (stl/css-case :check-mark true :checked (not hide-fill-on-export?))} (when (not hide-fill-on-export?) - i/status-tick-refactor)] + i/status-tick)] (tr "workspace.options.show-fill-on-export") [:input {:type "checkbox" :id "show-fill-on-export" 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 3859a60bd..7b7e69aed 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 @@ -148,7 +148,7 @@ [:button {:class (stl/css-case :show-options true :selected open?) :on-click toggle-advanced-options} - i/menu-refactor] + i/menu] [:div {:class (stl/css :type-select-wrapper)} [:& select {:class (stl/css :grid-type-select) @@ -179,10 +179,10 @@ [:div {:class (stl/css :actions)} [:button {:class (stl/css :action-btn) :on-click handle-toggle-visibility} - (if display i/shown-refactor i/hide-refactor)] + (if display i/shown i/hide)] [:button {:class (stl/css :action-btn) :on-click on-remove} - i/remove-refactor]]] + i/remove-icon]]] (when (:display grid) [:& advanced-options {:class (stl/css :grid-advanced-options) @@ -201,7 +201,7 @@ [:button {:class (stl/css-case :show-more-options true :selected show-more-options?) :on-click toggle-more-options} - i/menu-refactor]] + i/menu]] (when show-more-options? [:div {:class (stl/css :second-row)} [:button {:class (stl/css-case :btn-options true @@ -258,7 +258,8 @@ [: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] + :rotated (= type :row))} + i/gap-horizontal] [:> numeric-input* {:placeholder "0" :on-change (handle-change :params :gutter) :nillable true @@ -268,7 +269,8 @@ [: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] + :rotated (= type :column))} + i/grid-margin] [:> numeric-input* {:placeholder "0" :on-change (handle-change :params :margin) :nillable true @@ -279,7 +281,7 @@ :selected show-more-options?) :on-click toggle-more-options :disabled is-default} - i/menu-refactor] + i/menu] (when show-more-options? [:div {:class (stl/css :more-options)} [:button {:class (stl/css :option-btn) @@ -309,7 +311,7 @@ [:button {:on-click handle-create-grid :class (stl/css :add-grid)} - i/add-refactor]] + i/add]] (when (and open? (seq frame-grids)) [:div {:class (stl/css :element-set-content)} 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 c818dc826..db5de12bd 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 @@ -51,22 +51,30 @@ :allow-empty true :name (dm/str "flex-align-items-" type)} [:& radio-button {:value "start" - :icon (if is-col? i/align-self-row-left-refactor i/align-self-column-top-refactor) + :icon (if is-col? + i/align-self-row-left + i/align-self-column-top) :title "Align self start" :id (dm/str "align-self-start-" type)}] [:& radio-button {:value "center" - :icon (if is-col? i/align-self-row-center-refactor i/align-self-column-center-refactor) + :icon (if is-col? + i/align-self-row-center + i/align-self-column-center) :title "Align self center" :id (dm/str "align-self-center-" type)}] [:& radio-button {:value "end" - :icon (if is-col? i/align-self-row-right-refactor i/align-self-column-bottom-refactor) + :icon (if is-col? + i/align-self-row-right + i/align-self-column-bottom) :title "Align self end" :id (dm/str "align-self-end-" type)}] [:& radio-button {:value "stretch" - :icon (if is-col? i/align-self-row-stretch-refactor i/align-self-column-stretch-refactor) + :icon (if is-col? + i/align-self-row-stretch + i/align-self-column-stretch) :title "Align self stretch" :id (dm/str "align-self-stretch-" type)}]]])) @@ -200,7 +208,7 @@ (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] + [:span {:class (stl/css :icon)} i/flex-vertical] [:div {:class (stl/css :coord-input)} [:> numeric-input* {:placeholder "--" @@ -210,7 +218,7 @@ :value column}]]] [:div {:class (stl/css :grid-coord-group)} - [:span {:class (stl/css :icon)} i/flex-horizontal-refactor] + [:span {:class (stl/css :icon)} i/flex-horizontal] [:div {:class (stl/css :coord-input)} [:> numeric-input* {:placeholder "--" @@ -222,7 +230,7 @@ (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/flex-vertical-refactor] + [:span {:class (stl/css :icon)} i/flex-vertical] [:div {:class (stl/css :coord-input)} [:> numeric-input* {:placeholder "--" @@ -237,7 +245,7 @@ :value column-end}]]] [:div {:class (stl/css :grid-coord-group)} - [:span {:class (stl/css :icon)} i/flex-horizontal-refactor] + [:span {:class (stl/css :icon)} i/flex-horizontal] [:div {:class (stl/css :coord-input :double)} [:> numeric-input* {:placeholder "--" 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 f124fd252..515c109eb 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 @@ -139,7 +139,7 @@ [:button {:class (stl/css :start-flow-btn) :on-click start-flow} [:span {:class (stl/css :button-icon)} - i/play-refactor]] + i/play]] [:span {:class (stl/css :flow-input-wrapper)} [:input {:class (stl/css :flow-input) @@ -151,7 +151,7 @@ [:button {:class (stl/css :remove-flow-btn) :on-click remove-flow} - i/remove-refactor]])) + i/remove-icon]])) (mf/defc page-flows [{:keys [flows]}] @@ -177,7 +177,7 @@ [:button {:class (stl/css :add-flow-btn) :title (tr "workspace.options.flows.add-flow-start") :on-click add-flow} - i/add-refactor])] + i/add])] (when flow [:& flow-item {:flow flow :key (str (:id flow))}])]))) @@ -412,11 +412,11 @@ (d/concat-vec basic-animation-opts [{:value :push :label (tr "workspace.options.interaction-animation-push")}]) basic-animation-opts)) - easing-options [{:icon :easing-linear-refactor :value :linear :label (tr "workspace.options.interaction-easing-linear")} - {:icon :easing-ease-refactor :value :ease :label (tr "workspace.options.interaction-easing-ease")} - {:icon :easing-ease-in-refactor :value :ease-in :label (tr "workspace.options.interaction-easing-ease-in")} - {:icon :easing-ease-out-refactor :value :ease-out :label (tr "workspace.options.interaction-easing-ease-out")} - {:icon :easing-ease-in-out-refactor :value :ease-in-out :label (tr "workspace.options.interaction-easing-ease-in-out")}]] + easing-options [{:icon :easing-linear :value :linear :label (tr "workspace.options.interaction-easing-linear")} + {:icon :easing-ease :value :ease :label (tr "workspace.options.interaction-easing-ease")} + {:icon :easing-ease-in :value :ease-in :label (tr "workspace.options.interaction-easing-ease-in")} + {:icon :easing-ease-out :value :ease-out :label (tr "workspace.options.interaction-easing-ease-out")} + {:icon :easing-ease-in-out :value :ease-in-out :label (tr "workspace.options.interaction-easing-ease-in-out")}]] [:div {:class (stl/css-case :element-set-options-group true @@ -426,7 +426,7 @@ [:button {:class (stl/css-case :extend-btn true :extended extended-open?) :on-click toggle-extended} - i/menu-refactor] + i/menu] [:div {:class (stl/css :interactions-info) :on-click toggle-extended} @@ -435,7 +435,7 @@ [:button {:class (stl/css :remove-btn) :data-value index :on-click #(remove-interaction index)} - i/remove-refactor]] + i/remove-icon]] (when extended-open? [:div {:class (stl/css :extended-options)} @@ -490,7 +490,7 @@ :class (stl/css-case :global/checked preserve-scroll?)} [:span {:class (stl/css-case :global/checked preserve-scroll?)} (when preserve-scroll? - i/status-tick-refactor)] + i/status-tick)] (tr "workspace.options.interaction-preserve-scroll") [:input {:type "checkbox" :id (str "preserve-" index) @@ -586,7 +586,7 @@ :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)] + i/status-tick)] (tr "workspace.options.interaction-close-outside") [:input {:type "checkbox" :id (str "close-" index) @@ -600,7 +600,7 @@ :class (stl/css-case :global/checked background-overlay?)} [:span {:class (stl/css-case :global/checked background-overlay?)} (when background-overlay? - i/status-tick-refactor)] + i/status-tick)] (tr "workspace.options.interaction-background") [:input {:type "checkbox" :id (str "background-" index) @@ -638,19 +638,19 @@ [:& radio-buttons {:selected (d/name direction) :on-change change-direction :name "animation-direction"} - [:& radio-button {:icon i/column-refactor + [:& radio-button {:icon i/column :icon-class (stl/css :right) :value "right" :id "animation-right"}] - [:& radio-button {:icon i/column-refactor + [:& radio-button {:icon i/column :icon-class (stl/css :left) :id "animation-left" :value "left"}] - [:& radio-button {:icon i/column-refactor + [:& radio-button {:icon i/column :icon-class (stl/css :down) :id "animation-down" :value "down"}] - [:& radio-button {:icon i/column-refactor + [:& radio-button {:icon i/column :icon-class (stl/css :up) :id "animation-up" :value "up"}]]]]) @@ -687,7 +687,7 @@ :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)] + i/status-tick)] (tr "workspace.options.interaction-offset-effect") [:input {:type "checkbox" :id (str "offset-effect-" index) @@ -726,21 +726,21 @@ [:button {:class (stl/css :add-interaction-btn) :on-click add-interaction} - i/add-refactor]]]) + i/add]]]) (when (= (count interactions) 0) [:div {:class (stl/css :help-content)} (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-icon)} i/add] [:div {:class (stl/css :interactions-help)} (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-icon)} i/interaction] [: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-icon)} i/play] [:div {:class (stl/css :interactions-help)} (tr "workspace.options.use-play-button")]]]) [:div {:class (stl/css :groups)} 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 eea27c06c..938d2d878 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 @@ -173,18 +173,18 @@ (cond (or (= :multiple hidden?) (not hidden?)) [:button {:on-click handle-set-hidden - :class (stl/css :hidden-btn)} i/shown-refactor] + :class (stl/css :hidden-btn)} i/shown] :else [:button {:on-click handle-set-visible - :class (stl/css :hidden-btn)} i/hide-refactor]) + :class (stl/css :hidden-btn)} i/hide]) (cond (or (= :multiple blocked?) (not blocked?)) [:button {:on-click handle-set-blocked - :class (stl/css :lock-btn)} i/unlock-refactor] + :class (stl/css :lock-btn)} i/unlock] :else [:button {:on-click handle-set-unblocked :class (stl/css-case :lock-btn true - :locked blocked?)} i/lock-refactor])]]])) + :locked blocked?)} i/lock])]]])) 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 580b90a25..fc31dc4f0 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 @@ -36,10 +36,10 @@ (defn- dir-icons-refactor [val] (case val - :row i/grid-row-refactor - :row-reverse i/row-reverse-refactor - :column i/column-refactor - :column-reverse i/column-reverse-refactor)) + :row i/grid-row + :row-reverse i/row-reverse + :column i/column + :column-reverse i/column-reverse)) ;; FLEX COMPONENTS @@ -67,63 +67,63 @@ :align-items (if column? (case val - :start i/align-items-column-start-refactor - :end i/align-items-column-end-refactor - :center i/align-items-column-center-refactor) + :start i/align-items-column-start + :end i/align-items-column-end + :center i/align-items-column-center) (case val - :start i/align-items-row-start-refactor - :end i/align-items-row-end-refactor - :center i/align-items-row-center-refactor)) + :start i/align-items-row-start + :end i/align-items-row-end + :center i/align-items-row-center)) :justify-content (if column? (case val - :start i/justify-content-column-start-refactor - :end i/justify-content-column-end-refactor - :center i/justify-content-column-center-refactor - :space-around i/justify-content-column-around-refactor - :space-evenly i/justify-content-column-evenly-refactor - :space-between i/justify-content-column-between-refactor) + :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-refactor - :end i/justify-content-row-end-refactor - :center i/justify-content-row-center-refactor - :space-around i/justify-content-row-around-refactor - :space-evenly i/justify-content-row-evenly-refactor - :space-between i/justify-content-row-between-refactor)) + :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 column? (case val - :start i/align-content-column-start-refactor - :end i/align-content-column-end-refactor - :center i/align-content-column-center-refactor - :space-around i/align-content-column-around-refactor - :space-evenly i/align-content-column-evenly-refactor - :space-between i/align-content-column-between-refactor + :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-refactor - :end i/align-content-row-end-refactor - :center i/align-content-row-center-refactor - :space-around i/align-content-row-around-refactor - :space-evenly i/align-content-row-evenly-refactor - :space-between i/align-content-row-between-refactor + :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)) :align-self (if column? (case val - :auto i/remove-refactor - :start i/align-self-row-left-refactor - :end i/align-self-row-right-refactor - :center i/align-self-row-center-refactor) + :auto i/remove-icon + :start i/align-self-row-left + :end i/align-self-row-right + :center i/align-self-row-center) (case val - :auto i/remove-refactor - :start i/align-self-column-top-refactor - :end i/align-self-column-bottom-refactor - :center i/align-self-column-center-refactor)))) + :auto i/remove-icon + :start i/align-self-column-top + :end i/align-self-column-bottom + :center i/align-self-column-center)))) (defn get-layout-grid-icon [type val ^boolean column?] @@ -131,32 +131,32 @@ :align-items (if column? (case val - :auto i/remove-refactor - :start i/align-self-row-left-refactor - :end i/align-self-row-right-refactor - :center i/align-self-row-center-refactor) + :auto i/remove-icon + :start i/align-self-row-left + :end i/align-self-row-right + :center i/align-self-row-center) (case val - :auto i/remove-refactor - :start i/align-self-column-top-refactor - :end i/align-self-column-bottom-refactor - :center i/align-self-column-center-refactor)) + :auto i/remove-icon + :start i/align-self-column-top + :end i/align-self-column-bottom + :center i/align-self-column-center)) :justify-items (if (not column?) (case val - :start i/align-content-column-start-refactor - :center i/align-content-column-center-refactor - :end i/align-content-column-end-refactor - :space-around i/align-content-column-around-refactor - :space-between i/align-content-column-between-refactor - :stretch i/align-content-column-stretch-refactor) + :start i/align-content-column-start + :center i/align-content-column-center + :end i/align-content-column-end + :space-around i/align-content-column-around + :space-between i/align-content-column-between + :stretch i/align-content-column-stretch) (case val - :start i/align-content-row-start-refactor - :center i/align-content-row-center-refactor - :end i/align-content-row-end-refactor - :space-around i/align-content-row-around-refactor - :space-between i/align-content-row-between-refactor - :stretch i/align-content-row-stretch-refactor)))) + :start i/align-content-row-start + :center i/align-content-row-center + :end i/align-content-row-end + :space-around i/align-content-row-around + :space-between i/align-content-row-between + :stretch i/align-content-row-stretch)))) (mf/defc direction-row-flex {::mf/props :obj @@ -192,7 +192,7 @@ "No wrap" "Wrap") :on-click on-click} - i/wrap-refactor]) + i/wrap]) (mf/defc align-row {::mf/props :obj} @@ -335,7 +335,7 @@ [:div {:class (stl/css :padding-simple) :title "Vertical padding"} [:span {:class (stl/css :icon)} - i/padding-top-bottom-refactor] + i/padding-top-bottom] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" @@ -349,7 +349,7 @@ :title "Horizontal padding"} [:span {:class (stl/css :icon)} - i/padding-left-right-refactor] + i/padding-left-right] [:> numeric-input* {:className (stl/css :numeric-input) :placeholder "--" @@ -392,7 +392,7 @@ [:div {:class (stl/css :padding-multiple) :title "Top padding"} [:span {:class (stl/css :icon)} - i/padding-top-refactor] + i/padding-top] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" @@ -407,7 +407,7 @@ [:div {:class (stl/css :padding-multiple) :title "Right padding"} [:span {:class (stl/css :icon)} - i/padding-right-refactor] + i/padding-right] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" @@ -422,7 +422,7 @@ [:div {:class (stl/css :padding-multiple) :title "Bottom padding"} [:span {:class (stl/css :icon)} - i/padding-bottom-refactor] + i/padding-bottom] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" @@ -437,7 +437,7 @@ [:div {:class (stl/css :padding-multiple) :title "Left padding"} [:span {:class (stl/css :icon)} - i/padding-left-refactor] + i/padding-left] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" @@ -482,7 +482,7 @@ :selected (= type :multiple)) :data-type (d/name type) :on-click on-type-change'} - i/padding-extended-refactor]])) + i/padding-extended]])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GAP @@ -539,7 +539,7 @@ :row-gap true :disabled row-gap-disabled?) :title "Row gap"} - [:span {:class (stl/css :icon)} i/gap-vertical-refactor] + [:span {:class (stl/css :icon)} i/gap-vertical] [:> numeric-input* {:class (stl/css :numeric-input true) :no-validate true @@ -558,7 +558,7 @@ :column-gap true :disabled col-gap-disabled?) :title "Column gap"} - [:span {:class (stl/css :icon)} i/gap-horizontal-refactor] + [:span {:class (stl/css :icon)} i/gap-horizontal] [:> numeric-input* {:class (stl/css :numeric-input true) :no-validate true @@ -745,7 +745,7 @@ [:div {:class (stl/css :track-info-container)} [:div {:class (stl/css :track-info-dir-icon) :on-click handle-select-track} - (if is-column i/flex-vertical-refactor i/flex-horizontal-refactor)] + (if is-column i/flex-vertical i/flex-horizontal)] [:div {:class (stl/css :track-info-value)} [:> numeric-input* {:no-validate true @@ -766,7 +766,7 @@ [:button {:class (stl/css :remove-track-btn) :on-click #(remove-element type index)} - i/remove-refactor]])) + i/remove-icon]])) (mf/defc grid-columns-row {::mf/props :obj} @@ -789,11 +789,11 @@ [: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] + [:button {:class (stl/css :expand-icon) :on-click toggle} i/menu] [: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]] + [:button {:class (stl/css :add-column) :on-click add-track} i/add]] (when expanded? [:& h/sortable-container {} @@ -1002,7 +1002,7 @@ [:* [:button {:class (stl/css :add-layout) :on-click on-toggle-dropdown-visibility} - i/menu-refactor] + i/menu] [:& dropdown {:show show-dropdown? :on-close on-hide-dropdown} @@ -1019,14 +1019,14 @@ (when has-layout? [:button {:class (stl/css :remove-layout) :on-click on-remove-layout} - i/remove-refactor])] + i/remove-icon])] [:div {:class (stl/css :title-actions)} (if ^boolean grid-enabled? [:* [:button {:class (stl/css :add-layout) :on-click on-toggle-dropdown-visibility} - i/add-refactor] + i/add] [:& dropdown {:show show-dropdown? :on-close on-hide-dropdown} @@ -1043,11 +1043,11 @@ [:button {:class (stl/css :add-layout) :data-type "flex" :on-click on-add-layout} - i/add-refactor]) + i/add]) (when has-layout? [:button {:class (stl/css :remove-layout) :on-click on-remove-layout} - i/remove-refactor])])]] + i/remove-icon])])]] (when (and ^boolean open? ^boolean has-layout? @@ -1073,7 +1073,7 @@ [:button {:on-click open-flex-help :class (stl/css :help-button)} - i/help-refactor]] + i/help]] (when (= :wrap wrap-type) [:div {:class (stl/css :third-row)} [:& align-content-row {:is-column is-column @@ -1096,7 +1096,7 @@ [:div {:class (stl/css :edit-grid-wrapper)} [:& grid-edit-mode {:id (first ids)}] [:button {:on-click open-grid-help - :class (stl/css :help-button)} i/help-refactor]]) + :class (stl/css :help-button)} i/help]]) [:div {:class (stl/css :row :first-row)} [:div {:class (stl/css :direction-edit)} @@ -1273,7 +1273,7 @@ [:div {:class (stl/css :row)} [:div {:class (stl/css :grid-layout-menu-title)} "GRID LAYOUT"] [:button {:on-click open-grid-help - :class (stl/css :help-button)} i/help-refactor] + :class (stl/css :help-button)} i/help] [:button {:class (stl/css :exit-btn) :on-click #(st/emit! (udw/clear-edition-mode))} (tr "workspace.layout_grid.editor.options.exit")]] @@ -1303,7 +1303,7 @@ [:button {:on-click handle-locate-grid :class (stl/css :locate-button) :title (tr "workspace.layout_grid.editor.top-bar.locate.tooltip")} - i/locate-refactor]] + i/locate]] [:div {:class (stl/css :row)} [:& gap-section {:on-change on-gap-change 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 6f23f9ae2..5092d025b 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 @@ -80,7 +80,7 @@ [:div {:class (stl/css :vertical-margin) :title "Vertical margin"} [:span {:class (stl/css :icon)} - i/margin-top-bottom-refactor] + i/margin-top-bottom] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" :data-name "m1" @@ -93,7 +93,7 @@ [:div {:class (stl/css :horizontal-margin) :title "Horizontal margin"} [:span {:class (stl/css :icon)} - i/margin-left-right-refactor] + i/margin-left-right] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" :data-name "m2" @@ -133,7 +133,7 @@ [:div {:class (stl/css :top-margin) :title "Top margin"} [:span {:class (stl/css :icon)} - i/margin-top-refactor] + i/margin-top] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" :data-name "m1" @@ -145,7 +145,7 @@ [:div {:class (stl/css :right-margin) :title "Right margin"} [:span {:class (stl/css :icon)} - i/margin-right-refactor] + i/margin-right] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" :data-name "m2" @@ -158,7 +158,7 @@ [:div {:class (stl/css :bottom-margin) :title "Bottom margin"} [:span {:class (stl/css :icon)} - i/margin-bottom-refactor] + i/margin-bottom] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" :data-name "m3" @@ -171,7 +171,7 @@ [:div {:class (stl/css :left-margin) :title "Left margin"} [:span {:class (stl/css :icon)} - i/margin-left-refactor] + i/margin-left] [:> numeric-input* {:class (stl/css :numeric-input) :placeholder "--" :data-name "m4" @@ -216,7 +216,7 @@ :selected (= type :multiple)) :title "Margin - multiple" :on-click on-type-change'} - i/margin-refactor]])) + i/margin]])) (mf/defc element-behaviour-horizontal {::mf/props :obj @@ -236,20 +236,20 @@ [:& radio-button {:value "fix" - :icon i/fixed-width-refactor + :icon i/fixed-width :title "Fix width" :id "behaviour-h-fix"}] (when has-fill [:& radio-button {:value "fill" - :icon i/fill-content-refactor + :icon i/fill-content :title "Width 100%" :id "behaviour-h-fill"}]) (when is-auto [:& radio-button {:value "auto" - :icon i/hug-content-refactor + :icon i/hug-content :title "Fit content" :id "behaviour-h-auto"}])]]) @@ -271,7 +271,7 @@ [:& radio-button {:value "fix" - :icon i/fixed-width-refactor + :icon i/fixed-width :icon-class (stl/css :rotated) :title "Fix height" :id "behaviour-v-fix"}] @@ -279,14 +279,14 @@ (when has-fill [:& radio-button {:value "fill" - :icon i/fill-content-refactor + :icon i/fill-content :icon-class (stl/css :rotated) :title "Height 100%" :id "behaviour-v-fill"}]) (when is-auto [:& radio-button {:value "auto" - :icon i/hug-content-refactor + :icon i/hug-content :icon-class (stl/css :rotated) :title "Fit content" :id "behaviour-v-auto"}])]]) 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 92f2e5c40..13c4ffe53 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 @@ -353,7 +353,7 @@ :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] + [:span {:class (stl/css :collapsed-icon)} i/arrow] [:& dropdown {:show show-presets-dropdown? :on-close close-presets} @@ -377,15 +377,15 @@ [:span {:class (stl/css :preset-name)} (:name size-preset)] [:span {:class (stl/css :preset-size)} (:width size-preset) " x " (:height size-preset)]] (when preset-match - [:span {:class (stl/css :check-icon)} i/tick-refactor])])))]]] + [:span {:class (stl/css :check-icon)} i/tick])])))]]] [:& radio-buttons {:selected (or (d/name orientation) "") :on-change on-orientation-change :name "frame-otientation"} - [:& radio-button {:icon i/size-vertical-refactor + [:& radio-button {:icon i/size-vertical :value "vert" :id "size-vertical"}] - [:& radio-button {:icon i/size-horizontal-refactor + [:& radio-button {:icon i/size-horizontal :value "horiz" :id "size-horizontal"}]]]) (when (options :size) @@ -449,7 +449,7 @@ (when (options :rotation) [:div {:class (stl/css :rotation) :title (tr "workspace.options.rotation")} - [:span {:class (stl/css :icon)} i/rotation-refactor] + [:span {:class (stl/css :icon)} i/rotation] [:> numeric-input* {:no-validate true :min -359 @@ -467,7 +467,7 @@ (= radius-mode :radius-1) [:div {:class (stl/css :radius-1) :title (tr "workspace.options.radius")} - [:span {:class (stl/css :icon)} i/corner-radius-refactor] + [:span {:class (stl/css :icon)} i/corner-radius] [:> numeric-input* {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") :ref radius-input-ref @@ -479,7 +479,7 @@ @radius-multi? [:div {:class (stl/css :radius-1) :title (tr "workspace.options.radius")} - [:span {:class (stl/css :icon)} i/corner-radius-refactor] + [:span {:class (stl/css :icon)} i/corner-radius] [:input.input-text {:type "number" :placeholder "Mixed" @@ -532,7 +532,7 @@ (tr "workspace.options.radius.all-corners") (tr "workspace.options.radius.single-corners")) :on-click toggle-radius-mode} - i/corner-radius-refactor]])]) + i/corner-radius]])]) (when (or (options :clip-content) (options :show-in-viewer)) [:div {:class (stl/css :clip-show)} (when (options :clip-content) 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 23881b43d..b3a8072a0 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 @@ -160,7 +160,7 @@ [:button {:class (stl/css-case :more-options true :selected open-shadow) :on-click on-toggle-open-shadow} - i/menu-refactor] + i/menu] [:div {:class (stl/css :type-select)} [:& select {:class (stl/css :shadow-type-select) @@ -171,11 +171,11 @@ [:button {:class (stl/css :action-btn) :on-click toggle-visibility} (if hidden? - i/hide-refactor - i/shown-refactor)] + i/hide + i/shown)] [:button {:class (stl/css :action-btn) :on-click on-remove-shadow} - i/remove-refactor]]] + i/remove-icon]]] (when open-shadow [:& advanced-options {:class (stl/css :shadow-advanced-options) :visible? open-shadow @@ -298,7 +298,7 @@ (when-not (= :multiple shadows) [:button {:class (stl/css :add-shadow) - :on-click on-add-shadow} i/add-refactor])]] + :on-click on-add-shadow} i/add])]] (when open? (cond @@ -309,7 +309,7 @@ [:div {:class (stl/css :actions)} [:button {:class (stl/css :action-btn) :on-click on-remove-all} - i/remove-refactor]]]] + i/remove-icon]]]] (seq shadows) [:& h/sortable-container {} 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 13a2984a4..3539f693f 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 @@ -171,7 +171,7 @@ :class (stl/css-case :title-spacing-stroke (not has-strokes?))} [:button {:class (stl/css :add-stroke) - :on-click on-add-stroke} i/add-refactor]]] + :on-click on-add-stroke} i/add]]] (when open? [:div {:class (stl/css-case :element-content true :empty-content (not has-strokes?))} @@ -182,7 +182,7 @@ (tr "settings.multiple")] [:button {:on-click handle-remove-all :class (stl/css :remove-btn)} - i/remove-refactor]] + i/remove-icon]] (seq strokes) [:& h/sortable-container {} (for [[index value] (d/enumerate (:strokes values []))] 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 3891f5556..11f126428 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 @@ -41,7 +41,7 @@ [:div {:class (stl/css :attr-actions)} [:button {:class (stl/css :attr-action-btn) :on-click handle-delete} - i/remove-refactor]]] + i/remove-icon]]] [:div {:class (stl/css :attr-nested-content)} [:div {:class (stl/css :attr-title)} (str (d/name (last attr)))] 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 058421aab..5fbb3b840 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 @@ -45,19 +45,19 @@ [:& 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}] + :icon i/text-align-left}] [:& 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}] + :icon i/text-align-center}] [:& 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}] + :icon i/text-align-right}] [:& 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}]]])) + :icon i/text-justify}]]])) (mf/defc text-direction-options [{:keys [values on-change on-blur] :as props}] @@ -80,12 +80,12 @@ :type "checkbox" :id "ltr-text-direction" :title (tr "workspace.options.text-options.direction-ltr") - :icon i/text-ltr-refactor}] + :icon i/text-ltr}] [:& radio-button {:value "rtl" :type "checkbox" :id "rtl-text-direction" :title (tr "workspace.options.text-options.direction-rtl") - :icon i/text-rtl-refactor}]]])) + :icon i/text-rtl}]]])) (mf/defc vertical-align [{:keys [values on-change on-blur] :as props}] @@ -105,15 +105,15 @@ [:& radio-button {:value "top" :id "vertical-text-align-top" :title (tr "workspace.options.text-options.align-top") - :icon i/text-top-refactor}] + :icon i/text-top}] [:& radio-button {:value "center" :id "vertical-text-align-center" :title (tr "workspace.options.text-options.align-middle") - :icon i/text-middle-refactor}] + :icon i/text-middle}] [:& radio-button {:value "bottom" :id "vertical-text-align-bottom" :title (tr "workspace.options.text-options.align-bottom") - :icon i/text-bottom-refactor}]]])) + :icon i/text-bottom}]]])) (mf/defc grow-options [{:keys [ids values on-blur] :as props}] @@ -139,15 +139,15 @@ [:& radio-button {:value "fixed" :id "text-fixed-grow" :title (tr "workspace.options.text-options.grow-fixed") - :icon i/text-fixed-refactor}] + :icon i/text-fixed}] [:& 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}] + :icon i/text-auto-width}] [:& 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}]]])) + :icon i/text-auto-height}]]])) (mf/defc text-decoration-options [{:keys [values on-change on-blur] :as props}] @@ -169,12 +169,12 @@ :type "checkbox" :id "underline-text-decoration" :title (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline)) - :icon i/text-underlined-refactor}] + :icon i/text-underlined}] [:& 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}]]])) + :icon i/text-stroked}]]])) (mf/defc text-menu {::mf/wrap [mf/memo]} @@ -291,7 +291,7 @@ (when (and (not typography) (not multiple?)) [:button {:class (stl/css :add-typography) :on-click on-convert-to-typography} - i/add-refactor])]] + i/add])]] (when main-menu-open? [:div {:class (stl/css :element-content)} @@ -309,7 +309,7 @@ [:div {:class (stl/css :multiple-typography-button) :on-click handle-detach-typography :title (tr "workspace.libraries.text.multiple-typography-tooltip")} - i/detach-refactor]] + i/detach]] :else [:> text-options opts]) @@ -319,7 +319,7 @@ [:> grow-options opts] [:button {:class (stl/css :more-options) :on-click toggle-more-options} - i/menu-refactor]] + i/menu]] (when more-options-open? [:div {:class (stl/css :text-decoration-options)} 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 5f945a406..c98013450 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 @@ -77,7 +77,7 @@ [: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)]]])) + [:span {:class (stl/css :icon)} (when current? i/tick)]]])) (declare row-renderer) @@ -303,7 +303,7 @@ [:span {:class (stl/css :name)} (:name font)] [:span {:class (stl/css :icon)} - i/arrow-refactor]] + i/arrow]] :else (tr "dashboard.fonts.deleted-placeholder"))] @@ -362,7 +362,7 @@ [:div {:class (stl/css :line-height)} [:span {:class (stl/css :icon) :alt (tr "workspace.options.text-options.line-height")} - i/text-lineheight-refactor] + i/text-lineheight] [:> numeric-input* {:min -200 :max 200 @@ -379,7 +379,7 @@ [:span {:class (stl/css :icon) :alt (tr "workspace.options.text-options.letter-spacing")} - i/text-letterspacing-refactor] + i/text-letterspacing] [:> numeric-input* {:min -200 :max 200 @@ -405,15 +405,15 @@ [:& radio-buttons {:selected text-transform :on-change handle-change :name "text-transform"} - [:& radio-button {:icon i/text-uppercase-refactor + [:& radio-button {:icon i/text-uppercase :type "checkbox" :value "uppercase" :id "text-transform-uppercase"}] - [:& radio-button {:icon i/text-mixed-refactor + [:& radio-button {:icon i/text-mixed :type "checkbox" :value "capitalize" :id "text-transform-capitalize"}] - [:& radio-button {:icon i/text-lowercase-refactor + [:& radio-button {:icon i/text-lowercase :type "checkbox" :value "lowercase" :id "text-transform-lowercase"}]]])) @@ -472,7 +472,7 @@ [:div {:class (stl/css :action-btn) :on-click on-close} - i/tick-refactor]] + i/tick]] [:& text-options {:values typography :on-change on-change @@ -494,7 +494,7 @@ (:name font-data)] [:div {:class (stl/css :action-btn) :on-click on-close} - i/menu-refactor]] + i/menu]] [:div {:class (stl/css :info-row)} [:span {:class (stl/css :info-label)} (tr "workspace.assets.typography.font-variant-id")] @@ -624,10 +624,10 @@ (when ^boolean on-detach [:button {:class (stl/css :element-set-actions-button) :on-click on-detach} - i/detach-refactor]) + i/detach]) [:button {:class (stl/css :menu-btn) :on-click on-open} - i/menu-refactor]]] + i/menu]]] [:& typography-advanced-options {:visible? open? 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 f86bf374d..31dd285cb 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 @@ -265,9 +265,9 @@ (when (some? on-remove) [:button {:class (stl/css :remove-btn) - :on-click on-remove} i/remove-refactor]) + :on-click on-remove} i/remove-icon]) (when select-only [:button {:class (stl/css :select-btn) :on-click handle-select} - i/move-refactor])])) + i/move])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs index 9548d8b28..9f545aed7 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs @@ -59,13 +59,13 @@ (fn [color] (on-color-change index color))) - on-color-detach-refactor + on-color-detach (mf/use-callback (mf/deps index on-color-detach) (fn [color] (on-color-detach index color))) - on-remove-refactor + on-remove (mf/use-callback (mf/deps index on-remove) #(on-remove index)) @@ -123,14 +123,14 @@ stroke-caps-options [{:value nil :label (tr "workspace.options.stroke-cap.none")} :separator - {:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon :stroke-arrow-refactor} - {:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon :stroke-triangle-refactor} - {:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon :stroke-rectangle-refactor} - {:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon :stroke-circle-refactor} - {:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon :stroke-diamond-refactor} + {:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon :stroke-arrow} + {:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon :stroke-triangle} + {:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon :stroke-rectangle} + {:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon :stroke-circle} + {:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon :stroke-diamond} :separator - {:value :round :label (tr "workspace.options.stroke-cap.round") :icon :stroke-rounded-refactor} - {:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared-refactor}] + {:value :round :label (tr "workspace.options.stroke-cap.round") :icon :stroke-rounded} + {:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared}] on-cap-switch (mf/use-callback @@ -152,8 +152,8 @@ :index index :title title :on-change on-color-change-refactor - :on-detach on-color-detach-refactor - :on-remove on-remove-refactor + :on-detach on-color-detach + :on-remove on-remove :disable-drag disable-drag :on-focus on-focus :select-on-focus select-on-focus @@ -164,7 +164,7 @@ [:div {:class (stl/css :stroke-width-input-element) :title (tr "workspace.options.stroke-width")} [:span {:class (stl/css :icon)} - i/stroke-size-refactor] + i/stroke-size] [:> numeric-input* {:min 0 :className (stl/css :stroke-width-input) @@ -201,7 +201,7 @@ [:button {:class (stl/css :swap-caps-btn) :on-click on-cap-switch} - i/switch-refactor] + i/switch] [:div {:class (stl/css :cap-select)} [:& select diff --git a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs index 8f0a2bbad..f9499f91e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs @@ -268,7 +268,7 @@ (stl/css :subsection-title) (stl/css :section-title))} [:span {:class (stl/css-case :open is-visible? - :collapsed-shortcuts true)} i/arrow-refactor] + :collapsed-shortcuts true)} i/arrow] [:span {:class (if is-sub? (stl/css :subsection-name) (stl/css :section-name))} name]]) @@ -473,14 +473,14 @@ [:div {:class (stl/css :shortcuts-title)} (tr "shortcuts.title")] [:div {:class (stl/css :shortcuts-close-button) :on-click close-fn} - i/close-refactor]] + i/close]] [: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 (stl/css :search-icon)} i/search-refactor])}]] + :icon (mf/html [:span {:class (stl/css :search-icon)} i/search])}]] (if match-any? [:div {:class (stl/css :shortcuts-list)} diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs index f40719327..73977a797 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs @@ -131,7 +131,7 @@ :on-double-click on-double-click :on-context-menu on-context-menu} [:div {:class (stl/css :page-icon)} - i/document-refactor] + i/document] (if editing? [:* @@ -148,7 +148,7 @@ [:div {:class (stl/css :page-actions)} (when (and deletable? (not workspace-read-only?)) [:button {:on-click on-delete} - i/delete-refactor])]])]])) + i/delete])]])]])) ;; --- Page Item Wrapper @@ -222,7 +222,7 @@ (tr "labels.view-only")] [:button {:class (stl/css :add-page) :on-click on-create} - i/add-refactor])] + i/add])] [:div {:class (stl/css :tool-window-content)} [:& pages-list {:file file :key (:id file)}]]])) diff --git a/frontend/src/app/main/ui/workspace/text_palette.cljs b/frontend/src/app/main/ui/workspace/text_palette.cljs index da432d528..3869a3ec3 100644 --- a/frontend/src/app/main/ui/workspace/text_palette.cljs +++ b/frontend/src/app/main/ui/workspace/text_palette.cljs @@ -136,7 +136,7 @@ (when show-arrows? [:button {:class (stl/css :left-arrow) :disabled (= offset 0) - :on-click on-left-arrow-click} i/arrow-refactor]) + :on-click on-left-arrow-click} i/arrow]) [:div {:class (stl/css :text-palette-content) :ref container @@ -164,7 +164,7 @@ (when show-arrows? [:button {:class (stl/css :right-arrow) :disabled (= offset max-offset) - :on-click on-right-arrow-click} i/arrow-refactor])])) + :on-click on-right-arrow-click} i/arrow])])) (mf/defc text-palette {::mf/wrap [mf/memo]} diff --git a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs index 8e4988a09..f3cbb2208 100644 --- a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs +++ b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs @@ -38,7 +38,7 @@ (when (= selected (:id cur-library)) [:span {:class (stl/css :icon-wrapper)} - i/tick-refactor])])) + i/tick])])) [:li {:class (stl/css-case :file-library true @@ -52,4 +52,4 @@ (dm/str "(" (count file-typographies) ")")]] (when (= selected :file) [:span {:class (stl/css :icon-wrapper)} - i/tick-refactor])]]])) + i/tick])]]])) diff --git a/frontend/src/app/main/ui/workspace/top_toolbar.cljs b/frontend/src/app/main/ui/workspace/top_toolbar.cljs index e0160222d..406d28fcb 100644 --- a/frontend/src/app/main/ui/workspace/top_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/top_toolbar.cljs @@ -58,7 +58,7 @@ :aria-label (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image)) :on-click on-click :class (stl/css :main-toolbar-options-button)} - i/img-refactor + i/img [:& file-uploader {:input-id "image-upload" :accept cm/str-image-types @@ -130,7 +130,7 @@ :selected (and (nil? selected-drawtool) (not edition))) :on-click interrupt} - i/move-refactor]] + i/move]] [:* [:li [:button @@ -140,7 +140,7 @@ :on-click select-drawtool :data-tool "frame" :data-test "artboard-btn"} - i/board-refactor]] + i/board]] [:li [:button {:title (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect)) @@ -149,7 +149,7 @@ :on-click select-drawtool :data-tool "rect" :data-test "rect-btn"} - i/rectangle-refactor]] + i/rectangle]] [:li [:button {:title (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse)) @@ -158,7 +158,7 @@ :on-click select-drawtool :data-tool "circle" :data-test "ellipse-btn"} - i/elipse-refactor]] + i/elipse]] [:li [:button {:title (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text)) @@ -166,7 +166,7 @@ :class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :text)) :on-click select-drawtool :data-tool "text"} - i/text-refactor]] + i/text]] [:& image-upload] @@ -178,7 +178,7 @@ :on-click select-drawtool :data-tool "curve" :data-test "curve-btn"} - i/curve-refactor]] + i/curve]] [:li [:button {:title (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path)) @@ -187,7 +187,7 @@ :on-click select-drawtool :data-tool "path" :data-test "path-btn"} - i/path-refactor]] + i/path]] (when *assert* [:li @@ -195,7 +195,7 @@ {:title "Debugging tool" :class (stl/css-case :main-toolbar-options-button true :selected (contains? layout :debug-panel)) :on-click toggle-debug-panel} - i/bug-refactor]])]] + i/bug]])]] [:button {:class (stl/css :toolbar-handler) :on-click toggle-toolbar} 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 4621560a7..572c1068d 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 @@ -133,7 +133,7 @@ :y icon-y :width (/ 22 zoom) :height (/ 22 zoom) - :href "#icon-add-refactor"}]])) + :href "#icon-add"}]])) (defn use-drag [{:keys [on-drag-start on-drag-end on-drag-delta on-drag-position]}] @@ -864,7 +864,7 @@ :on-blur handle-blur-track-input}] (when (and hovering? (not medium?) (not small?)) [:button {:class (stl/css :grid-editor-button) - :on-click handle-show-track-menu} i/menu-refactor])]])] + :on-click handle-show-track-menu} i/menu])]])] [:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))} [:& track-marker 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 3f2c7558b..e337d4b17 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs @@ -117,14 +117,14 @@ {: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] + i/pentool] ;; 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]] + i/move]] [:div {:class (stl/css :sub-actions-group)} ;; Add Node @@ -132,14 +132,14 @@ {: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] + i/add] ;; 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]] + i/remove-icon]] [:div {:class (stl/css :sub-actions-group)} ;; Merge Nodes @@ -147,21 +147,21 @@ {: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] + i/merge-nodes] ;; 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] + i/join-nodes] ;; 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]] + i/separate-nodes]] ;; Make Corner [:div {:class (stl/css :sub-actions-group)} @@ -169,14 +169,14 @@ {: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] + i/to-corner] ;; 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]] + i/to-curve]] ;; Toggle snap [:div {:class (stl/css :sub-actions-group)} @@ -184,5 +184,5 @@ {: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]]])) + i/snap-nodes]]])) diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index ab0b10777..6674446fc 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -153,13 +153,13 @@ :visibility (if show-artboard-names? "visible" "hidden")} (cond (:use-for-thumbnail frame) - [:use {:href "#icon-boards-thumbnail-refactor"}] + [:use {:href "#icon-boards-thumbnail"}] grid-edition? - [:use {:href "#icon-grid-refactor"}] + [:use {:href "#icon-grid"}] main-instance? - [:use {:href "#icon-component-refactor"}])]) + [:use {:href "#icon-component"}])]) [:foreignObject {:x text-pos-x @@ -266,7 +266,7 @@ :on-double-click on-double-click :on-pointer-enter on-pointer-enter :on-pointer-leave on-pointer-leave} - i/play-refactor + i/play [:span (:name flow)]]]])) (mf/defc frame-flows From 4f01a63771851deb25fb980e9c9c8fba00f0c78a Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 8 Mar 2024 14:05:06 +0100 Subject: [PATCH 059/136] :recycle: Update name of shape icon refactor --- .../{shape_icon_refactor.cljs => shape_icon.cljs} | 6 +++--- frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs | 4 ++-- frontend/src/app/main/ui/workspace/context_menu.cljs | 4 ++-- frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs | 6 +++--- frontend/src/app/main/ui/workspace/sidebar/layers.cljs | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) rename frontend/src/app/main/ui/components/{shape_icon_refactor.cljs => shape_icon.cljs} (93%) diff --git a/frontend/src/app/main/ui/components/shape_icon_refactor.cljs b/frontend/src/app/main/ui/components/shape_icon.cljs similarity index 93% rename from frontend/src/app/main/ui/components/shape_icon_refactor.cljs rename to frontend/src/app/main/ui/components/shape_icon.cljs index 7874ac371..060213681 100644 --- a/frontend/src/app/main/ui/components/shape_icon_refactor.cljs +++ b/frontend/src/app/main/ui/components/shape_icon.cljs @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.components.shape-icon-refactor +(ns app.main.ui.components.shape-icon (:require [app.common.types.component :as ctk] [app.common.types.shape :as cts] @@ -12,7 +12,7 @@ [app.main.ui.icons :as i] [rumext.v2 :as mf])) -(mf/defc element-icon-refactor +(mf/defc element-icon {::mf/wrap-props false} [{:keys [shape main-instance?]}] (if (ctk/instance-head? shape) @@ -51,7 +51,7 @@ nil))) -(mf/defc element-icon-refactor-by-type +(mf/defc element-icon-by-type [{:keys [type main-instance?] :as props}] (if main-instance? i/component 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 fffa430e1..c90ab718a 100644 --- a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs @@ -10,7 +10,7 @@ [app.common.data.macros :as dm] [app.common.types.component :as ctk] [app.main.refs :as refs] - [app.main.ui.components.shape-icon-refactor :as sir] + [app.main.ui.components.shape-icon :as sir] [app.main.ui.components.tab-container :refer [tab-container tab-element]] [app.main.ui.icons :as i] [app.main.ui.viewer.inspect.attributes :refer [attributes]] @@ -93,7 +93,7 @@ [: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?}]] + [:& sir/element-icon {:shape first-shape :main-instance? main-instance?}]] ;; Execution time translation strings: ;; inspect.tabs.code.selected.circle ;; inspect.tabs.code.selected.component diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 01b008502..8ba1763fe 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -30,7 +30,7 @@ [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] - [app.main.ui.components.shape-icon-refactor :as sic] + [app.main.ui.components.shape-icon :as sic] [app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.assets.common :as cmm] [app.util.dom :as dom] @@ -180,7 +180,7 @@ :on-pointer-enter (on-pointer-enter (:id object)) :on-pointer-leave (on-pointer-leave (:id object)) :on-unmount (on-unmount (:id object)) - :icon (sic/element-icon-refactor {:shape object})}])]) + :icon (sic/element-icon {:shape object})}])]) [:& menu-entry {:title (tr "workspace.shape.menu.forward") :shortcut (sc/get-tooltip :bring-forward) :on-click do-bring-forward}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs index 43fb73974..be6a1fffb 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs @@ -17,7 +17,7 @@ [app.main.data.workspace.collapse :as dwc] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.shape-icon-refactor :as sic] + [app.main.ui.components.shape-icon :as sic] [app.main.ui.context :as ctx] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] @@ -100,7 +100,7 @@ (when absolute? [:div {:class (stl/css :absolute)}]) - [:& sic/element-icon-refactor + [:& sic/element-icon {:shape item :main-instance? main-instance?}]]] @@ -111,7 +111,7 @@ :on-double-click on-zoom-to-selected} (when ^boolean absolute? [:div {:class (stl/css :absolute)}]) - [:& sic/element-icon-refactor + [:& sic/element-icon {:shape item :main-instance? main-instance?}]]]) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 258d6dcd5..c3f927e04 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -15,7 +15,7 @@ [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.search-bar :refer [search-bar]] - [app.main.ui.components.shape-icon-refactor :as sic] + [app.main.ui.components.shape-icon :as sic] [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] @@ -308,7 +308,7 @@ :on-click remove-filter} [:span {:class (stl/css :layer-filter-icon)} - [:& sic/element-icon-refactor-by-type + [:& sic/element-icon-by-type {:type fkey :main-instance? (= fkey :component)}]] [:span {:class (stl/css :layer-filter-name)} From f32aaee41f347373ce39a3a9cc76c8271ee56ee3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Mar 2024 11:52:57 +0100 Subject: [PATCH 060/136] :bug: Fix problem when changing typography assets --- CHANGES.md | 1 + .../data/workspace/libraries_helpers.cljs | 42 ++++++++++++------- frontend/translations/en.po | 4 +- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 66073f114..f80e97245 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -129,6 +129,7 @@ - Fix problem with linked colors to strokes [Github #3522](https://github.com/penpot/penpot/issues/3522) - Fix problem with hand tool stuck [Github #3318](https://github.com/penpot/penpot/issues/3318) - Fix problem with fix scrolling on nested elements [Github #3508](https://github.com/penpot/penpot/issues/3508) +- Fix problem when changing typography assets [Github #3683](https://github.com/penpot/penpot/issues/3683) ## 1.19.5 diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index d157dcd3d..296cd7c92 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -464,21 +464,35 @@ [changes shape container update-node] (let [old-content (:content shape) new-content (txt/transform-nodes update-node old-content) + + redo-change + (make-change + container + {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :content + :val new-content} + {:type :set + :attr :position-data + :val nil}]}) + + undo-change + (make-change + container + {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :content + :val old-content} + {:type :set + :attr :position-data + :val nil}]}) + changes' (-> changes - (update :redo-changes conj (make-change - container - {:type :mod-obj - :id (:id shape) - :operations [{:type :set - :attr :content - :val new-content}]})) - (update :undo-changes conj (make-change - container - {:type :mod-obj - :id (:id shape) - :operations [{:type :set - :attr :content - :val old-content}]})))] + (update :redo-changes conj redo-change) + (update :undo-changes conj undo-change))] + (if (= new-content old-content) changes changes'))) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index b1a01bb1a..df15b1c17 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -988,7 +988,7 @@ msgid "errors.webhooks.invalid-uri" msgstr "URL does not pass validation." msgid "errors.webhooks.last-delivery" -msgstr "Last delivery was not successfull." +msgstr "Last delivery was not successful." msgid "errors.webhooks.ssl-validation" msgstr "Error on SSL validation." @@ -3144,7 +3144,7 @@ msgid "viewer.header.sitemap" msgstr "Sitemap" msgid "webhooks.last-delivery.success" -msgstr "Last delivery was successfull." +msgstr "Last delivery was successful." #: src/app/main/ui/workspace/sidebar/align.cljs msgid "workspace.align.hcenter" From 7f93c41005a773027c9413ddb507bf4f1a8f48eb Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Mar 2024 12:16:12 +0100 Subject: [PATCH 061/136] :bug: Fix colorpicker open palete library --- .../src/app/main/ui/workspace/colorpicker/libraries.cljs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs index a00058dfb..14e851d31 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs @@ -21,7 +21,6 @@ [app.main.ui.icons :as i] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] - [app.util.timers :as ts] [rumext.v2 :as mf])) (mf/defc libraries @@ -51,12 +50,13 @@ toggle-palette (mf/use-fn + (mf/deps @selected) (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")))))) + (st/emit! (dw/remove-layout-flag :textpalette) + (-> (mdc/show-palette @selected) + (vary-meta assoc ::ev/origin "workspace-colorpicker"))))) shared-libs-options (mapv (fn [lib] {:value (d/name (:id lib)) :label (:name lib)}) (vals shared-libs)) From 69f9982d260040c48b14438091ee575432b849d8 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Mar 2024 12:33:36 +0100 Subject: [PATCH 062/136] :bug: Fix problem with comment thread ignoring filters --- frontend/src/app/main/ui/workspace/viewport/comments.cljs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs index 8adbce9cd..ca842d1c6 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs @@ -81,9 +81,10 @@ (when-let [id (:open local)] (when-let [thread (get threads-map id)] - [:& cmt/thread-comments {:thread (update-position positions thread) - :users users - :zoom zoom}])) + (when (seq (dcm/apply-filters local profile [thread])) + [:& cmt/thread-comments {:thread (update-position positions thread) + :users users + :zoom zoom}]))) (when-let [draft (:comment drawing)] [:& cmt/draft-thread {:draft draft From 8963cb2739241e47da21a9653f191cc06a1b3742 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Mar 2024 13:55:02 +0100 Subject: [PATCH 063/136] :bug: Fix recent fonts name changes --- frontend/src/app/main/data/fonts.cljs | 7 +++++-- .../ui/workspace/sidebar/options/menus/typography.cljs | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/data/fonts.cljs b/frontend/src/app/main/data/fonts.cljs index 5c9e3837d..bb8fe193f 100644 --- a/frontend/src/app/main/data/fonts.cljs +++ b/frontend/src/app/main/data/fonts.cljs @@ -318,9 +318,12 @@ (swap! storage assoc ::recent-fonts most-recent-fonts))))) (defn load-recent-fonts - [] + [fonts] (ptk/reify ::load-recent-fonts ptk/UpdateEvent (update [_ state] - (let [saved-recent-fonts (::recent-fonts @storage)] + (let [fonts-map (d/index-by :id fonts) + saved-recent-fonts (->> (::recent-fonts @storage) + (keep #(get fonts-map (:id %))) + (into #{}))] (assoc-in state [:workspace-data :recent-fonts] saved-recent-fonts))))) 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 c98013450..0d7977266 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 @@ -144,8 +144,8 @@ (on-select font) (on-close)))] - (mf/with-effect [] - (st/emit! (fts/load-recent-fonts))) + (mf/with-effect [fonts] + (st/emit! (fts/load-recent-fonts fonts))) (mf/with-effect [fonts] (let [key (events/listen js/document "keydown" on-key-down)] From 5390eabcd6fa9290164f42bfa8d5efd9daa41358 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Mar 2024 15:25:07 +0100 Subject: [PATCH 064/136] :bug: Add more shortcuts for next/previous frame in viewer --- frontend/src/app/main/data/viewer/shortcuts.cljs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/data/viewer/shortcuts.cljs b/frontend/src/app/main/data/viewer/shortcuts.cljs index 5cae65f67..f6ac67296 100644 --- a/frontend/src/app/main/data/viewer/shortcuts.cljs +++ b/frontend/src/app/main/data/viewer/shortcuts.cljs @@ -37,17 +37,17 @@ :fn #(st/emit! dv/toggle-zoom-style)} :toggle-fullscreen {:tooltip (ds/shift "F") - :command "shift+f" + :command ["shift+f" "alt+enter"] :subsections [:zoom-viewer] :fn #(st/emit! dv/toggle-fullscreen)} - :next-frame {:tooltip ds/left-arrow - :command ["left" "up"] + :prev-frame {:tooltip ds/left-arrow + :command ["left" "up" "shift+enter" "pageup" "shift+space"] :subsections [:general-viewer] :fn #(st/emit! dv/select-prev-frame)} - :prev-frame {:tooltip ds/right-arrow - :command ["right" "down"] + :next-frame {:tooltip ds/right-arrow + :command ["right" "down" "enter" "pagedown" "space"] :subsections [:general-viewer] :fn #(st/emit! dv/select-next-frame)} From 9940dabfff7c588a4fd1aa150f2002000738c3ff Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 11 Mar 2024 10:16:56 +0100 Subject: [PATCH 065/136] :bug: Fix z-index of workspace context menu --- .../resources/styles/common/framework.scss | 2 +- .../styles/common/refactor/basic-rules.scss | 2 +- .../styles/common/refactor/z-index.scss | 5 +- frontend/resources/styles/main-default.scss | 1 - .../styles/main/partials/context-menu.scss | 2 +- .../styles/main/partials/dropdown.scss | 2 +- .../styles/main/partials/exception-page.scss | 2 +- .../styles/main/partials/loader.scss | 2 +- .../styles/main/partials/tool-bar.scss | 48 ------------------- .../main/ui/components/context_menu_a11y.scss | 2 +- .../src/app/main/ui/dashboard/comments.scss | 2 +- .../src/app/main/ui/dashboard/templates.scss | 2 +- .../app/main/ui/workspace/color_palette.scss | 2 +- .../ui/workspace/color_palette_ctx_menu.scss | 2 +- .../app/main/ui/workspace/context_menu.scss | 2 +- .../src/app/main/ui/workspace/palette.scss | 2 +- .../src/app/main/ui/workspace/presence.scss | 2 +- .../src/app/main/ui/workspace/sidebar.scss | 2 +- .../main/ui/workspace/sidebar/layer_item.scss | 2 +- .../sidebar/options/menus/frame_grid.scss | 2 +- .../sidebar/options/menus/typography.scss | 2 +- .../ui/workspace/text_palette_ctx_menu.scss | 2 +- .../app/main/ui/workspace/top_toolbar.scss | 2 +- 23 files changed, 23 insertions(+), 71 deletions(-) delete mode 100644 frontend/resources/styles/main/partials/tool-bar.scss diff --git a/frontend/resources/styles/common/framework.scss b/frontend/resources/styles/common/framework.scss index 5a22085ee..a90e22dbd 100644 --- a/frontend/resources/styles/common/framework.scss +++ b/frontend/resources/styles/common/framework.scss @@ -1011,7 +1011,7 @@ input[type="range"]:focus::-ms-fill-upper { padding-left: 16px; top: 16px; right: 16px; - z-index: 1005; + z-index: 40; display: flex; align-items: center; diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss index 61a1c4c49..4b8663f33 100644 --- a/frontend/resources/styles/common/refactor/basic-rules.scss +++ b/frontend/resources/styles/common/refactor/basic-rules.scss @@ -905,7 +905,7 @@ margin: 0; margin-top: $s-1; border-radius: $br-8; - z-index: $z-index-3; + z-index: $z-index-4; overflow-y: auto; overflow-x: hidden; background-color: var(--menu-background-color); diff --git a/frontend/resources/styles/common/refactor/z-index.scss b/frontend/resources/styles/common/refactor/z-index.scss index 5be8e2e5b..755b2e9fa 100644 --- a/frontend/resources/styles/common/refactor/z-index.scss +++ b/frontend/resources/styles/common/refactor/z-index.scss @@ -6,8 +6,9 @@ $z-index-1: 1; // floating elements $z-index-2: 2; // sidebars -$z-index-3: 3; // context menu -$z-index-4: 4; // modal +$z-index-3: 3; // topbar +$z-index-4: 4; // context menu +$z-index-5: 5; // modal $z-index-10: 10; $z-index-20: 20; $z-index-modal: 30; // When refactor finish we can reduce this number, diff --git a/frontend/resources/styles/main-default.scss b/frontend/resources/styles/main-default.scss index f3fd5e5bc..0a914e78d 100644 --- a/frontend/resources/styles/main-default.scss +++ b/frontend/resources/styles/main-default.scss @@ -60,7 +60,6 @@ @import "main/partials/project-bar"; @import "main/partials/sidebar"; @import "main/partials/tab-container"; -@import "main/partials/tool-bar"; @import "main/partials/user-settings"; @import "main/partials/workspace"; @import "main/partials/color-bullet"; diff --git a/frontend/resources/styles/main/partials/context-menu.scss b/frontend/resources/styles/main/partials/context-menu.scss index e7a302655..3f4e3f0dd 100644 --- a/frontend/resources/styles/main/partials/context-menu.scss +++ b/frontend/resources/styles/main/partials/context-menu.scss @@ -8,7 +8,7 @@ position: relative; visibility: hidden; opacity: 0; - z-index: 100; + z-index: 3; } .context-menu.is-open { diff --git a/frontend/resources/styles/main/partials/dropdown.scss b/frontend/resources/styles/main/partials/dropdown.scss index 0abd62a4f..ed3a2817f 100644 --- a/frontend/resources/styles/main/partials/dropdown.scss +++ b/frontend/resources/styles/main/partials/dropdown.scss @@ -4,7 +4,7 @@ background-color: $color-white; border-radius: $br2; box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25); - z-index: 12; + z-index: 3; hr { margin: 0 !important; diff --git a/frontend/resources/styles/main/partials/exception-page.scss b/frontend/resources/styles/main/partials/exception-page.scss index 3ffd4ca1b..30686023a 100644 --- a/frontend/resources/styles/main/partials/exception-page.scss +++ b/frontend/resources/styles/main/partials/exception-page.scss @@ -12,7 +12,7 @@ display: flex; align-items: center; padding: 32px; - z-index: 1000; + z-index: 40; cursor: pointer; diff --git a/frontend/resources/styles/main/partials/loader.scss b/frontend/resources/styles/main/partials/loader.scss index f42675aaf..ce2542d2d 100644 --- a/frontend/resources/styles/main/partials/loader.scss +++ b/frontend/resources/styles/main/partials/loader.scss @@ -9,7 +9,7 @@ position: fixed; top: 0; width: 100%; - z-index: 999; + z-index: 40; } // full with loader CSS diff --git a/frontend/resources/styles/main/partials/tool-bar.scss b/frontend/resources/styles/main/partials/tool-bar.scss deleted file mode 100644 index eea14f2e3..000000000 --- a/frontend/resources/styles/main/partials/tool-bar.scss +++ /dev/null @@ -1,48 +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 - -.tool-bar { - background-color: $color-gray-40; - bottom: 0; - height: 100%; - position: fixed; - left: 0; - width: 50px; - z-index: 10; - - .tool-bar-inside { - padding-top: 70px; - - .main-tools { - align-items: center; - display: flex; - flex-direction: column; - - li { - cursor: pointer; - margin-bottom: $size-5; - - svg { - fill: $color-gray-20; - height: 25px; - width: 25px; - } - - &:hover { - svg { - fill: $color-white; - } - } - - &.current { - svg { - fill: $color-primary; - } - } - } - } - } -} diff --git a/frontend/src/app/main/ui/components/context_menu_a11y.scss b/frontend/src/app/main/ui/components/context_menu_a11y.scss index ed007261c..ea8a89cc5 100644 --- a/frontend/src/app/main/ui/components/context_menu_a11y.scss +++ b/frontend/src/app/main/ui/components/context_menu_a11y.scss @@ -10,7 +10,7 @@ position: relative; visibility: hidden; opacity: $op-0; - z-index: $z-index-3; + z-index: $z-index-4; &.is-open { position: relative; diff --git a/frontend/src/app/main/ui/dashboard/comments.scss b/frontend/src/app/main/ui/dashboard/comments.scss index 1be90e32b..b6e872e52 100644 --- a/frontend/src/app/main/ui/dashboard/comments.scss +++ b/frontend/src/app/main/ui/dashboard/comments.scss @@ -78,7 +78,7 @@ min-height: $s-200; position: absolute; width: 100%; - z-index: $z-index-3; + z-index: $z-index-4; hr { margin: 0; diff --git a/frontend/src/app/main/ui/dashboard/templates.scss b/frontend/src/app/main/ui/dashboard/templates.scss index 2fa508411..2649d166b 100644 --- a/frontend/src/app/main/ui/dashboard/templates.scss +++ b/frontend/src/app/main/ui/dashboard/templates.scss @@ -42,7 +42,7 @@ border-top-right-radius: $br-10; margin-right: $s-32; position: relative; - z-index: 1; + z-index: $z-index-1; background-color: $db-quaternary; } diff --git a/frontend/src/app/main/ui/workspace/color_palette.scss b/frontend/src/app/main/ui/workspace/color_palette.scss index dfe3e8229..4815dee3e 100644 --- a/frontend/src/app/main/ui/workspace/color_palette.scss +++ b/frontend/src/app/main/ui/workspace/color_palette.scss @@ -19,7 +19,7 @@ height: 100%; width: $s-24; padding: 0; - z-index: $z-index-4; + z-index: $z-index-5; svg { @extend .button-icon; stroke: var(--icon-foreground); diff --git a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss index 7b09a1ab6..920d6031b 100644 --- a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss +++ b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss @@ -13,7 +13,7 @@ max-width: $s-480; padding: $s-4; margin: 0 0 $s-4 0; - z-index: $z-index-3; + z-index: $z-index-4; border-radius: $br-10; background-color: var(--context-menu-background-color); diff --git a/frontend/src/app/main/ui/workspace/context_menu.scss b/frontend/src/app/main/ui/workspace/context_menu.scss index f6d10a8ec..0ce429a5b 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.scss +++ b/frontend/src/app/main/ui/workspace/context_menu.scss @@ -19,7 +19,7 @@ border-radius: $br-8; border: $s-2 solid var(--panel-border-color); background-color: var(--menu-background-color); - z-index: $z-index-3; + z-index: $z-index-4; } .separator { diff --git a/frontend/src/app/main/ui/workspace/palette.scss b/frontend/src/app/main/ui/workspace/palette.scss index 70f0639e0..9474a7909 100644 --- a/frontend/src/app/main/ui/workspace/palette.scss +++ b/frontend/src/app/main/ui/workspace/palette.scss @@ -43,7 +43,7 @@ .resize-area { grid-area: resize; height: $s-8; - z-index: $z-index-3; + z-index: $z-index-4; width: calc(100% - $s-8); border-radius: $br-circle; cursor: ns-resize; diff --git a/frontend/src/app/main/ui/workspace/presence.scss b/frontend/src/app/main/ui/workspace/presence.scss index 07c883950..22c76e3b0 100644 --- a/frontend/src/app/main/ui/workspace/presence.scss +++ b/frontend/src/app/main/ui/workspace/presence.scss @@ -42,7 +42,7 @@ padding: $s-8; margin: calc(-1 * $s-2) calc(-1 * $s-4) 0 0; background-color: var(--menu-background-color); - z-index: $z-index-3; + z-index: $z-index-4; .active-users-list { gap: $s-4; .users-num, diff --git a/frontend/src/app/main/ui/workspace/sidebar.scss b/frontend/src/app/main/ui/workspace/sidebar.scss index b14ca1253..192a8416e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar.scss +++ b/frontend/src/app/main/ui/workspace/sidebar.scss @@ -47,7 +47,7 @@ $width-settings-bar-max: $s-500; position: absolute; top: 0; left: unset; - z-index: $z-index-3; + z-index: $z-index-4; width: $s-8; cursor: ew-resize; height: 100%; diff --git a/frontend/src/app/main/ui/workspace/sidebar/layer_item.scss b/frontend/src/app/main/ui/workspace/sidebar/layer_item.scss index 68779f911..124ee6f48 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layer_item.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/layer_item.scss @@ -249,7 +249,7 @@ :global(.sticky) { position: sticky; top: $s-0; - z-index: $z-index-3; + z-index: $z-index-4; } .tab-indentation { 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 d1bb3aa4c..bf1a29c77 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 @@ -224,7 +224,7 @@ margin: 0 0 $s-40 0; margin-top: $s-4; border-radius: $br-8; - z-index: $z-index-3; + z-index: $z-index-4; overflow-y: auto; background-color: var(--menu-background-color); .option-btn { 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 1106ea3c1..b5c417a41 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 @@ -351,7 +351,7 @@ right: 0; height: 100%; width: 100%; - z-index: $z-index-3; + z-index: $z-index-4; } .show-recent { diff --git a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss index e1b2bb08d..e29217eaa 100644 --- a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss +++ b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss @@ -13,7 +13,7 @@ max-width: $s-480; padding: $s-4; margin: 0 0 $s-4 0; - z-index: $z-index-3; + z-index: $z-index-4; border-radius: $br-10; background-color: var(--context-menu-background-color); diff --git a/frontend/src/app/main/ui/workspace/top_toolbar.scss b/frontend/src/app/main/ui/workspace/top_toolbar.scss index 293956c6c..bc7850c72 100644 --- a/frontend/src/app/main/ui/workspace/top_toolbar.scss +++ b/frontend/src/app/main/ui/workspace/top_toolbar.scss @@ -17,7 +17,7 @@ padding: $s-8 $s-16; border-radius: $s-8; border: $s-2 solid var(--panel-border-color); - z-index: $z-index-10; + z-index: $z-index-3; background-color: var(--color-background-primary); transition: top 0.3s, From 71b4079483ef2cce2a713569db89fbc1a7ad3297 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 11 Mar 2024 10:54:00 +0100 Subject: [PATCH 066/136] :bug: Fix the hero project height in dashboard --- frontend/src/app/main/ui/dashboard.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/dashboard.scss b/frontend/src/app/main/ui/dashboard.scss index 064694ec9..ed79f5362 100644 --- a/frontend/src/app/main/ui/dashboard.scss +++ b/frontend/src/app/main/ui/dashboard.scss @@ -21,7 +21,7 @@ .dashboard-content { display: grid; - grid-template-rows: $s-64 1fr; + grid-template-rows: $s-64 auto auto 1fr; position: relative; grid-row: 1 / span 2; padding: $s-16 $s-16 0 0; From f714f08716c4e722d4c25b88959b1c6d9dde8988 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 11 Mar 2024 11:05:21 +0100 Subject: [PATCH 067/136] :bug: Fix comment bubble border --- frontend/src/app/main/ui/comments.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss index ddad36a6b..2c6b622d0 100644 --- a/frontend/src/app/main/ui/comments.scss +++ b/frontend/src/app/main/ui/comments.scss @@ -138,6 +138,7 @@ width: $s-284; padding: $s-12; border-radius: $br-8; + border: $s-2 solid var(--modal-border-color); background-color: var(--comment-modal-background-color); .comments { display: flex; From d860eac59fa5f07ed9a55874dc82a98c9dfee0ed Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 11 Mar 2024 11:16:15 +0100 Subject: [PATCH 068/136] :bug: Fix disabled buttons height in login and auth pages --- frontend/resources/styles/common/refactor/basic-rules.scss | 1 - frontend/src/app/main/ui/components/forms.scss | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss index 4b8663f33..0a257da60 100644 --- a/frontend/resources/styles/common/refactor/basic-rules.scss +++ b/frontend/resources/styles/common/refactor/basic-rules.scss @@ -223,7 +223,6 @@ .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); diff --git a/frontend/src/app/main/ui/components/forms.scss b/frontend/src/app/main/ui/components/forms.scss index 19027a065..53db07493 100644 --- a/frontend/src/app/main/ui/components/forms.scss +++ b/frontend/src/app/main/ui/components/forms.scss @@ -263,6 +263,7 @@ :disabled { @extend .button-disabled; + min-height: $s-32; } // MULTI INPUT From b30d525400fe62f83eb51fe9e27749d087d8691d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Mar 2024 10:59:38 +0100 Subject: [PATCH 069/136] :bug: Fix opts passing on process-file! srepl helper --- backend/src/app/srepl/main.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/app/srepl/main.clj b/backend/src/app/srepl/main.clj index ba9693e93..17df79a9a 100644 --- a/backend/src/app/srepl/main.clj +++ b/backend/src/app/srepl/main.clj @@ -378,11 +378,11 @@ (defn process-file! "Apply a function to the file. Optionally save the changes or not. The function receives the decoded and migrated file data." - [file-id update-fn & {:keys [rollback?] :or {rollback? true}}] + [file-id update-fn & {:keys [rollback?] :or {rollback? true} :as opts}] (db/tx-run! (assoc main/system ::db/rollback rollback?) (fn [system] (binding [h/*system* system] - (h/process-file! system file-id update-fn))))) + (h/process-file! system file-id update-fn opts))))) (defn process-team-files! "Apply a function to each file of the specified team." From 4ffaf6f996d9d32e7b92f5785e39798cb04b9225 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 11 Mar 2024 11:41:49 +0100 Subject: [PATCH 070/136] :bug: Fix gradient background image --- frontend/resources/styles/main-default.scss | 1 - .../styles/main/partials/color-bullet.scss | 209 ------------------ .../app/main/ui/components/color_bullet.scss | 4 +- .../ui/workspace/colorpicker/gradients.scss | 2 +- .../colorpicker/slider_selector.scss | 3 +- 5 files changed, 5 insertions(+), 214 deletions(-) delete mode 100644 frontend/resources/styles/main/partials/color-bullet.scss diff --git a/frontend/resources/styles/main-default.scss b/frontend/resources/styles/main-default.scss index 0a914e78d..48c342b70 100644 --- a/frontend/resources/styles/main-default.scss +++ b/frontend/resources/styles/main-default.scss @@ -62,6 +62,5 @@ @import "main/partials/tab-container"; @import "main/partials/user-settings"; @import "main/partials/workspace"; -@import "main/partials/color-bullet"; @import "main/partials/exception-page"; @import "main/partials/signup-questions"; diff --git a/frontend/resources/styles/main/partials/color-bullet.scss b/frontend/resources/styles/main/partials/color-bullet.scss deleted file mode 100644 index 43983d50f..000000000 --- a/frontend/resources/styles/main/partials/color-bullet.scss +++ /dev/null @@ -1,209 +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 - -.color-bullet { - border: 2px solid $color-gray-30; - position: relative; - width: var(--bullet-size); - height: var(--bullet-size); - - &:hover { - border-color: $color-primary; - } -} -.color-cell { - display: grid; - grid-template-columns: 100%; - grid-template-rows: 1fr auto; - height: 100%; - justify-items: center; - width: 65px; - - .color-bullet { - border: 2px solid $color-gray-30; - position: relative; - width: var(--bullet-size); - height: var(--bullet-size); - - &:hover { - border-color: $color-primary; - } - } - - & > * { - overflow: hidden; - } -} - -.color-cell.current { - .color-bullet { - border-color: $color-gray-30; - } -} - -ul.palette-menu .color-bullet { - width: 20px; - height: 20px; - border: 1px solid $color-gray-30; - margin-right: 5px; - background-size: 8px; -} -.color-cell.add-color .color-bullet { - align-items: center; - background-color: $color-gray-50; - border: 3px dashed $color-gray-30; - cursor: pointer; - display: flex; - justify-content: center; - margin-bottom: 1rem; - padding: 0.6rem; - - svg { - fill: $color-gray-10; - height: 30px; - width: 30px; - } -} - -.colorpicker-content .color-bullet { - grid-area: color; - width: 20px; - height: 20px; - border: 1px solid $color-gray-30; - background-size: 8px; - overflow: hidden; -} - -.asset-section .asset-list-item .color-bullet { - border: 1px solid $color-gray-30; - height: 20px; - margin-right: $size-1; - width: 20px; -} -.tool-window-content .asset-list .asset-list-item { - &:hover { - .color-bullet { - border: 1px solid $color-primary; - } - } -} - -.color-cell.add-color:hover .color-bullet { - border-color: $color-gray-30; - - svg { - fill: $color-gray-30; - } -} - -.color-bullet { - display: flex; - flex-direction: row; - border-radius: 50%; - - & .color-bullet-wrapper { - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") - left center; - background-color: $color-white; - clip-path: circle(50%); - display: flex; - flex-direction: row; - height: 100%; - width: 100%; - } - - &.is-gradient { - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") - left center; - background-color: $color-white; - } - - & .color-bullet-wrapper > * { - width: 100%; - height: 100%; - } -} - -.color-data .color-bullet.multiple { - background: transparent; - - &::before { - content: "?"; - } -} - -.color-data .color-bullet { - border: 1px solid $color-gray-30; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - color: $color-gray-10; - flex-shrink: 0; - height: 20px; - margin: 5px 4px 0 0; - width: 20px; - - &.palette-th { - align-items: center; - border: 1px solid $color-gray-30; - display: flex; - justify-content: center; - - svg { - fill: $color-gray-30; - height: 16px; - width: 16px; - } - - &:hover { - border-color: $color-primary; - svg { - fill: $color-primary; - } - } - } -} - -.colorpicker-content .libraries .selected-colors .color-bullet { - grid-area: auto; - margin-bottom: 0.25rem; - cursor: pointer; - - &:hover { - border-color: $color-primary; - z-index: 10; - } - - &.button { - background: $color-white; - display: flex; - align-items: center; - justify-content: center; - } - - &.button svg { - width: 12px; - height: 12px; - fill: $color-gray-30; - } - - &.plus-button svg { - width: 8px; - height: 8px; - fill: $color-black; - } -} - -.color-bullet.is-not-library-color { - border-radius: $br3; - overflow: hidden; - - & .color-bullet-wrapper { - clip-path: none; - } -} diff --git a/frontend/src/app/main/ui/components/color_bullet.scss b/frontend/src/app/main/ui/components/color_bullet.scss index 36afda4b2..3a8e0e202 100644 --- a/frontend/src/app/main/ui/components/color_bullet.scss +++ b/frontend/src/app/main/ui/components/color_bullet.scss @@ -39,13 +39,13 @@ } } &.is-gradient { - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAExJREFUSIljvHnz5n8GLEBNTQ2bMMOtW7ewiuNSz4RVlIpg1IKBt4Dx////WFMRqakFl/qhH0SjFhAELNRKLaNl0Qi2YLQsGrWAcgAA0gAgQPhT2rAAAAAASUVORK5CYII=") left center; background-color: var(--color-bullet-background-color); transform: rotate(-90deg); } &.is-transparent { - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAExJREFUSIljvHnz5n8GLEBNTQ2bMMOtW7ewiuNSz4RVlIpg1IKBt4Dx////WFMRqakFl/qhH0SjFhAELNRKLaNl0Qi2YLQsGrWAcgAA0gAgQPhT2rAAAAAASUVORK5CYII=") left center; background-color: var(--color-bullet-background-color); } diff --git a/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss b/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss index 0fe9529f2..374edaaa7 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss +++ b/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss @@ -19,7 +19,7 @@ height: 100%; width: 100%; border-radius: $br-6; - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAExJREFUSIljvHnz5n8GLEBNTQ2bMMOtW7ewiuNSz4RVlIpg1IKBt4Dx////WFMRqakFl/qhH0SjFhAELNRKLaNl0Qi2YLQsGrWAcgAA0gAgQPhT2rAAAAAASUVORK5CYII=") left center; } diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss index aef415df5..3e30ad7ea 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss +++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss @@ -54,12 +54,13 @@ } &.opacity { - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAExJREFUSIljvHnz5n8GLEBNTQ2bMMOtW7ewiuNSz4RVlIpg1IKBt4Dx////WFMRqakFl/qhH0SjFhAELNRKLaNl0Qi2YLQsGrWAcgAA0gAgQPhT2rAAAAAASUVORK5CYII=") var(--background-repeat) center; &::after { content: ""; position: absolute; + border-radius: $br-6; width: 100%; height: 100%; background: linear-gradient( From 25cf30e7d3fb6e215c881ca57c1dd76069664fea Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Fri, 8 Mar 2024 13:36:33 +0100 Subject: [PATCH 071/136] :bug: Fix possible loop in the list of swappable components --- .../sidebar/options/menus/component.cljs | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) 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 84a888fba..95e80b0b2 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 @@ -7,12 +7,10 @@ (ns app.main.ui.workspace.sidebar.options.menus.component (:require-macros [app.main.style :as stl]) (:require - [app.common.data :as d] [app.common.data.macros :as dm] [app.common.files.helpers :as cfh] [app.common.types.component :as ctk] [app.common.types.file :as ctf] - [app.common.uuid :as uuid] [app.main.data.modal :as modal] [app.main.data.workspace :as dw] [app.main.data.workspace.libraries :as dwl] @@ -296,16 +294,6 @@ (= (:component-id shape-a) (:component-id shape-b))) -;; Get the ids of the components and its root-shapes that are parents of the current shape, to avoid loops -(defn get-parent-component-ids - [objects shape ids] - (let [shape-id (:id shape)] - (if (uuid/zero? shape-id) - ids - (let [ids (if (ctk/instance-head? shape) - (conj ids shape-id (:component-id shape)) - ids)] - (get-parent-component-ids objects (get objects (:parent-id shape)) ids))))) (mf/defc component-swap {::mf/props :obj} @@ -386,13 +374,17 @@ (->> (concat groups components) (sort-by :name))) - parent-components (mf/with-memo [shapes objects] - (into #{} - (comp - (map :parent-id) - (map (d/getf objects)) - (mapcat #(get-parent-component-ids objects % []))) - shapes)) + find-parent-components + (mf/use-fn + (mf/deps objects) + (fn [shape] + (->> (cfh/get-parents objects (:id shape)) + (map :component-id) + (remove nil?)))) + + ;; Get the ids of the components that are parents of the shapes, to avoid loops + parent-components (mapcat find-parent-components shapes) + libraries-options (map (fn [library] {:value (:id library) :label (:name library)}) (vals libraries)) @@ -489,8 +481,10 @@ (let [data (dm/get-in libraries [current-library-id :data]) container (ctf/get-component-page data item) root-shape (ctf/get-component-root data item) - loop? (or (contains? parent-components (:main-instance-id item)) - (contains? parent-components (:id item)))] + components (->> (cfh/get-children-with-self (:objects container) (:id root-shape)) + (keep :component-id) + set) + loop? (some #(contains? components %) parent-components)] [:& component-swap-item {:key (dm/str (:id item)) :item item :loop loop? From 358176c92753444b63f6d7c7881dc9dcc038e67a Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 11 Mar 2024 16:03:40 +0100 Subject: [PATCH 072/136] :bug: Fix project name in sidebar --- frontend/src/app/main/ui/dashboard/sidebar.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/dashboard/sidebar.scss b/frontend/src/app/main/ui/dashboard/sidebar.scss index c6cea273a..1a5c627e6 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.scss +++ b/frontend/src/app/main/ui/dashboard/sidebar.scss @@ -239,6 +239,7 @@ .element-title { @include textEllipsis; + width: $s-256; color: var(--sidebar-element-foreground-color); font-size: $fs-14; } From 338b6cdbd60e303ecd1b9d705d2e7524ad4411d2 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Mar 2024 16:01:28 +0100 Subject: [PATCH 073/136] :bug: Add tooltip to button in layout --- .../ui/workspace/sidebar/options/menus/layout_container.cljs | 1 + frontend/translations/en.po | 3 +++ frontend/translations/es.po | 3 +++ 3 files changed, 7 insertions(+) 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 fc31dc4f0..b7a5dde44 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 @@ -480,6 +480,7 @@ [:button {:class (stl/css-case :padding-toggle true :selected (= type :multiple)) + :title (tr "workspace.layout_grid.editor.padding.expand") :data-type (d/name type) :on-click on-type-change'} i/padding-extended]])) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index df15b1c17..d4b3e9527 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -3520,6 +3520,9 @@ msgstr "Edit grid" msgid "workspace.layout_grid.editor.options.exit" msgstr "Exit" +msgid "workspace.layout_grid.editor.padding.expand" +msgstr "Show 4 sided padding options" + #: src/app/main/ui/workspace/libraries.cljs msgid "workspace.libraries.add" msgstr "Add" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 5ce93d9b9..e2072c81d 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -3582,6 +3582,9 @@ msgstr "Editar rejilla" msgid "workspace.layout_grid.editor.options.exit" msgstr "Salir" +msgid "workspace.layout_grid.editor.padding.expand" +msgstr "Mostrar el padding a 4 lados" + #: src/app/main/ui/workspace/libraries.cljs msgid "workspace.libraries.add" msgstr "Añadir" From 112e71a259acc44a5378b66867c597d98f102ab1 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Mar 2024 16:01:53 +0100 Subject: [PATCH 074/136] :bug: Fix propagation of auto/fix sizing on components --- .../data/workspace/libraries_helpers.cljs | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 296cd7c92..75fb6945a 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -1521,11 +1521,26 @@ (defn- update-flex-child-copy-attrs "Synchronizes the attributes inside the flex-child items (main->copy)" - [changes _shape-main shape-copy main-container main-component copy-container omit-touched?] + [changes shape-main shape-copy main-container main-component copy-container omit-touched?] + (let [new-changes (-> (pcb/empty-changes) (pcb/with-container copy-container) (pcb/with-objects (:objects copy-container)) + + ;; The layout-item-sizing needs to be update when the parent is auto or fix + (pcb/update-shapes + [(:id shape-copy)] + (fn [shape-copy] + (cond-> shape-copy + (contains? #{:auto :fix} (:layout-item-h-sizing shape-main)) + (propagate-attrs shape-main #{:layout-item-h-sizing} omit-touched?) + + (contains? #{:auto :fix} (:layout-item-h-sizing shape-main)) + (propagate-attrs shape-main #{:layout-item-v-sizing} omit-touched?))) + {:ignore-touched true}) + + ;; Update the child flex properties from the parent (pcb/update-shapes (:shapes shape-copy) (fn [child-copy] @@ -1542,6 +1557,20 @@ (-> (pcb/empty-changes) (pcb/with-page main-container) (pcb/with-objects (:objects main-container)) + + ;; The layout-item-sizing needs to be update when the parent is auto or fix + (pcb/update-shapes + [(:id shape-main)] + (fn [shape-main] + (cond-> shape-main + (contains? #{:auto :fix} (:layout-item-h-sizing shape-copy)) + (propagate-attrs shape-copy #{:layout-item-h-sizing} omit-touched?) + + (contains? #{:auto :fix} (:layout-item-h-sizing shape-copy)) + (propagate-attrs shape-copy #{:layout-item-v-sizing} omit-touched?))) + {:ignore-touched true}) + + ;; Updates the children properties from the parent (pcb/update-shapes (:shapes shape-main) (fn [child-main] @@ -1620,4 +1649,3 @@ (if (cfh/page? container) (assoc change :page-id (:id container)) (assoc change :component-id (:id container)))) - From bed13c24dfcb23a510441e964df81444f399a9df Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Mar 2024 16:13:36 +0100 Subject: [PATCH 075/136] :bug: Fix problem with comments new line --- frontend/src/app/main/ui/comments.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss index ddad36a6b..12890644d 100644 --- a/frontend/src/app/main/ui/comments.scss +++ b/frontend/src/app/main/ui/comments.scss @@ -196,6 +196,7 @@ position: relative; .text { @include bodySmallTypography; + white-space: pre; } } } From de1dae7f9386a88930016cf8e637cd4aaed3d6df Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Mar 2024 16:53:53 +0100 Subject: [PATCH 076/136] :bug: Fix problem with input fast change --- .../src/app/main/ui/components/numeric_input.cljs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/main/ui/components/numeric_input.cljs b/frontend/src/app/main/ui/components/numeric_input.cljs index 308ef8e42..54965605e 100644 --- a/frontend/src/app/main/ui/components/numeric_input.cljs +++ b/frontend/src/app/main/ui/components/numeric_input.cljs @@ -152,7 +152,7 @@ handle-key-down (mf/use-fn - (mf/deps set-delta apply-value update-input) + (mf/deps set-delta apply-value update-input parse-value) (fn [event] (mf/set-ref-val! dirty-ref true) (let [up? (kbd/up-arrow? event) @@ -162,19 +162,13 @@ node (mf/ref-val ref)] (when (or up? down?) (set-delta event up? down?)) + (reset! last-value* (parse-value)) (when enter? (dom/blur! node)) (when esc? (update-input value-str) (dom/blur! node))))) - handle-key-up - (mf/use-fn - (mf/deps parse-value) - (fn [] - ;; Store the last value inputed - (reset! last-value* (parse-value)))) - handle-mouse-wheel (mf/use-fn (mf/deps set-delta) @@ -231,7 +225,6 @@ (obj/set! "defaultValue" (fmt/format-number value)) (obj/set! "title" title) (obj/set! "onKeyDown" handle-key-down) - (obj/set! "onKeyUp" handle-key-up) (obj/set! "onBlur" handle-blur) (obj/set! "onFocus" handle-focus))] From 9852558a57eec99298c4502a44bba4e8b726efcc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Mar 2024 18:11:18 +0100 Subject: [PATCH 077/136] :bug: Fix problem when importing templates --- .../src/app/main/ui/dashboard/import.cljs | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index d51195184..14f0318e3 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -345,18 +345,21 @@ edition* (mf/use-state nil) edition (deref edition*) + template-finished* (mf/use-state nil) + template-finished (deref template-finished*) + on-template-cloned-success (mf/use-fn (fn [] - (swap! status* (constantly :importing)) - ;; (swap! state assoc :status :importing :importing-templates 0) + (reset! status* :importing) + (reset! template-finished* true) (st/emit! (dd/fetch-recent-files)))) on-template-cloned-error (mf/use-fn (fn [cause] - (swap! status* (constantly :error)) - ;; (swap! state assoc :status :error :importing-templates 0) + (reset! status* :error) + (reset! template-finished* true) (errors/print-error! cause) (rx/of (modal/hide) (msg/error (tr "dashboard.libraries-and-templates.import-error"))))) @@ -434,15 +437,29 @@ 1 (count (filterv has-status-success? entries))) - errors? (or (some has-status-error? entries) - (zero? (count entries))) - + errors? (if (some? template) + (= status :error) + (or (some has-status-error? entries) + (zero? (count entries)))) pending-analysis? (some has-status-analyzing? entries) - pending-import? (pos? num-importing) - valid-all-entries? (or (some? template) - (not (some has-status-analyze-error? entries)))] + pending-import? (and (or (nil? template) + (not template-finished)) + (pos? num-importing)) + valid-all-entries? (or (some? template) + (not (some has-status-analyze-error? entries))) + + template-status + (cond + (and (= :importing status) pending-import?) + :importing + + (and (= :importing status) (not ^boolean pending-import?)) + :import-finish + + :else + :ready)] ;; Run analyze operation on component mount (mf/with-effect [] @@ -486,7 +503,7 @@ :can-be-deleted (> (count entries) 1)}]) (when (some? template) - [:& import-entry {:entry (assoc template :status :ready) + [:& import-entry {:entry (assoc template :status template-status) :can-be-deleted false}])] [:div {:class (stl/css :modal-footer)} From d08dfaa022384de8bc455fa5c3df70ec33a4cb34 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 11 Mar 2024 17:55:57 +0100 Subject: [PATCH 078/136] :bug: Fix reset override behaviour --- frontend/src/app/main/data/workspace/libraries_helpers.cljs | 3 ++- frontend/test/frontend_tests/state_components_sync_test.cljs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 296cd7c92..1fb4cfd1d 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -620,7 +620,8 @@ shape-main (when component (if (and reset? components-v2) - (ctf/find-remote-shape container libraries shape-inst) + ;; the reset is against the ref-shape, not against the original shape of the component + (ctf/find-ref-shape file container libraries shape-inst) (ctf/get-ref-shape library component shape-inst))) shape-inst (if (and reset? components-v2) diff --git a/frontend/test/frontend_tests/state_components_sync_test.cljs b/frontend/test/frontend_tests/state_components_sync_test.cljs index 7e74291f8..1751fe9a5 100644 --- a/frontend/test/frontend_tests/state_components_sync_test.cljs +++ b/frontend/test/frontend_tests/state_components_sync_test.cljs @@ -1177,8 +1177,8 @@ (t/is (= (:fill-opacity shape1) 0)) (t/is (= (:name shape2) "Rect 1")) (t/is (= (:touched shape2) nil)) - (t/is (= (:fill-color shape2) clr/white)) - (t/is (= (:fill-opacity shape2) 1)) + (t/is (= (:fill-color shape2) clr/test)) + (t/is (= (:fill-opacity shape2) 0.5)) (t/is (= (:name c-instance2) "Board")) (t/is (= (:touched c-instance2) nil)) From 3fdf0c727e99c2190f735fed57d8cd217f5ad90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Mon, 11 Mar 2024 11:01:00 +0100 Subject: [PATCH 079/136] :bug: Fix comments thread overflowing the viewport and displacing comment bubbles --- .../styles/main/partials/workspace.scss | 20 +++------ frontend/src/app/main/ui/comments.cljs | 42 +++++++++++++++---- frontend/src/app/main/ui/comments.scss | 10 +++++ .../main/ui/workspace/viewport/comments.cljs | 2 + .../main/ui/workspace/viewport/comments.scss | 7 +++- 5 files changed, 56 insertions(+), 25 deletions(-) diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index 5288b7475..a387fed48 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -152,16 +152,6 @@ $height-palette-max: 80px; } } -// .workspace-loader { -// display: flex; -// justify-content: center; -// align-items: center; - -// svg { -// fill: $color-gray-50; -// } -// } - .workspace-content { background-color: $color-canvas; display: flex; @@ -242,20 +232,22 @@ $height-palette-max: 80px; .viewport-overlays { cursor: initial; - height: 100%; overflow: hidden; pointer-events: none; position: absolute; - width: 100%; + top: 0; + left: 0; + bottom: 0; + right: 0; z-index: 10; .pixel-overlay { - height: 100%; left: 0; pointer-events: initial; position: absolute; top: 0; - width: 100%; + right: 0; + bottom: 0; z-index: 1; } } diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 9cb417b8f..c1c1b5685 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -355,22 +355,41 @@ [thread-id] (l/derived (l/in [:comments thread-id]) st/state)) +(defn- offset-position [position viewport zoom bubble-margin] + (let [base-x (+ (* (:x position) zoom) (:offset-x viewport)) + base-y (+ (* (:y position) zoom) (:offset-y viewport)) + w (:width viewport) + h (:height viewport) + comment-width 284 ;; TODO: this is the width set via CSS in an outer container… + ;; We should probably do this in a different way. + orientation-left? (>= (+ base-x comment-width (:x bubble-margin)) w) + orientation-top? (>= base-y (/ h 2)) + h-dir (if orientation-left? :left :right) + v-dir (if orientation-top? :top :bottom) + x (:x position) + y (:y position)] + {:x x :y y :h-dir h-dir :v-dir v-dir})) + (mf/defc thread-comments {::mf/wrap [mf/memo]} - [{:keys [thread zoom users origin position-modifier]}] + [{:keys [thread zoom users origin position-modifier viewport]}] (let [ref (mf/use-ref) - - thread-id (:id thread) thread-pos (:position thread) - pos (cond-> thread-pos + base-pos (cond-> thread-pos (some? position-modifier) (gpt/transform position-modifier)) - pos-x (+ (* (:x pos) zoom) 24) - pos-y (- (* (:y pos) zoom) 28) + max-height (int (* (:height viewport) 0.75)) + ;; We should probably look for a better way of doing this. + bubble-margin {:x 24 :y 0} + pos (offset-position base-pos viewport zoom bubble-margin) + margin-x (* (:x bubble-margin) (if (= (:h-dir pos) :left) -1 1)) + margin-y (* (:y bubble-margin) (if (= (:v-dir pos) :top) -1 1)) + pos-x (+ (* (:x pos) zoom) margin-x) + pos-y (- (* (:y pos) zoom) margin-y) comments-ref (mf/with-memo [thread-id] (make-comments-ref thread-id)) @@ -393,9 +412,14 @@ (dom/scroll-into-view-if-needed! node))) (when (some? comment) - [:div {:class (stl/css :thread-content) - :style {:top (str pos-y "px") - :left (str pos-x "px")} + [:div {:class (stl/css-case :thread-content true + :thread-content-left (= (:h-dir pos) :left) + :thread-content-top (= (:v-dir pos) :top)) + :id (str "thread-" thread-id) + :style {:left (str pos-x "px") + :top (str pos-y "px") + :max-height max-height + :overflow-y "scroll"} :on-click dom/stop-propagation} [:div {:class (stl/css :comments)} diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss index ddad36a6b..368ed4824 100644 --- a/frontend/src/app/main/ui/comments.scss +++ b/frontend/src/app/main/ui/comments.scss @@ -139,6 +139,9 @@ padding: $s-12; border-radius: $br-8; background-color: var(--comment-modal-background-color); + --translate-x: 0%; + --translate-y: 0%; + transform: translate(var(--translate-x), var(--translate-y)); .comments { display: flex; flex-direction: column; @@ -146,6 +149,13 @@ } } +.thread-content-left { + --translate-x: -100%; +} +.thread-content-top { + --translate-y: -100%; +} + // comment-item .comment-container { diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs index ca842d1c6..f75559b5e 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs @@ -84,6 +84,7 @@ (when (seq (dcm/apply-filters local profile [thread])) [:& cmt/thread-comments {:thread (update-position positions thread) :users users + :viewport {:offset-x pos-x :offset-y pos-y :width (:width vport) :height (:height vport)} :zoom zoom}]))) (when-let [draft (:comment drawing)] @@ -91,3 +92,4 @@ :on-cancel on-draft-cancel :on-submit on-draft-submit :zoom zoom}])]]])) + diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.scss b/frontend/src/app/main/ui/workspace/viewport/comments.scss index ee56bc948..9c587d596 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.scss +++ b/frontend/src/app/main/ui/workspace/viewport/comments.scss @@ -15,10 +15,13 @@ pointer-events: none; overflow: hidden; user-select: text; + position: absolute; } .threads { position: absolute; - top: $s-0; - left: $s-0; + top: 0; + left: 0; + right: 0; + bottom: 0; } From 343efc68c5599643c7f8df0172f6792726e86137 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 12 Mar 2024 09:11:06 +0100 Subject: [PATCH 080/136] :bug: Propagate parent changes con reset overrides --- frontend/src/app/main/data/workspace/libraries.cljs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index c27c00b0f..448997208 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -708,11 +708,18 @@ components-v2 (features/active-feature? state "components/v2") + shape-inst (ctn/get-shape container id) + swap-slot (-> (ctn/get-shape container id) + (ctk/get-swap-slot)) changes (-> (pcb/empty-changes it) (pcb/with-container container) (pcb/with-objects (:objects container)) - (dwlh/generate-sync-shape-direct file-full libraries container id true components-v2))] + (dwlh/generate-sync-shape-direct file-full libraries container id true components-v2) + (cond-> + (some? swap-slot) + ;; We need to propagate parent changes + (dwlh/generate-sync-shape-direct file-full libraries container (:parent-id shape-inst) true components-v2)))] (log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes (:redo-changes changes) From 56bc70dffecc3ff980c184ab0e9a8fd8694f8ed5 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 12 Mar 2024 12:43:42 +0100 Subject: [PATCH 081/136] :bug: Fix restore component --- frontend/src/app/main/data/workspace/libraries_helpers.cljs | 3 --- frontend/src/app/main/data/workspace/selection.cljs | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 296cd7c92..8f3def937 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -263,9 +263,6 @@ parent (get-in page [:objects parent-id]) main-inst (get-in component [:objects (:main-instance-id component)]) inside-component? (some? (ctn/get-instance-root (:objects page) parent)) - origin-frame (get-in page [:objects (:frame-id main-inst)]) - ;; We are using a deleted component andit's coordenates are absolute, we must adjust them to its containing frame to adjust the delta - delta (gpt/subtract delta (-> origin-frame :selrect gpt/point)) shapes (cfh/get-children-with-self (:objects component) (:main-instance-id component)) shapes (map #(gsh/move % delta) shapes) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 15d3d5ab4..bf1d68e44 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -433,6 +433,8 @@ main-component (ctf/get-component libraries file-id component-id) moved-component (gsh/move component-root delta) pos (gpt/point (:x moved-component) (:y moved-component)) + origin-frame (get-in page [:objects frame-id]) + delta (gpt/subtract delta (-> origin-frame :selrect gpt/point)) instantiate-component #(dwlh/generate-instantiate-component changes From d478a7d8d92e6c0f2ba634f4e3d444c88ad713e2 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Tue, 12 Mar 2024 13:05:51 +0100 Subject: [PATCH 082/136] :bug: Fix project name too long --- frontend/src/app/main/ui/dashboard/grid.scss | 2 +- .../src/app/main/ui/dashboard/projects.cljs | 69 ++++++++++--------- .../src/app/main/ui/dashboard/projects.scss | 13 +++- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/grid.scss b/frontend/src/app/main/ui/dashboard/grid.scss index 3108fa656..a8c812c92 100644 --- a/frontend/src/app/main/ui/dashboard/grid.scss +++ b/frontend/src/app/main/ui/dashboard/grid.scss @@ -18,7 +18,7 @@ $thumbnail-default-height: $s-168; // Default width } .grid-row { - display: flex; + display: grid; width: 100%; gap: $s-24; } diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 82bbe0378..9135ca83b 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -276,7 +276,8 @@ (fn [event] (when (kbd/enter? event) (dom/stop-propagation event) - (on-menu-click event))))] + (on-menu-click event)))) + title-width (/ 100 limit)] [:article {:class (stl/css-case :dashboard-project-row true :first first?)} [:header {:class (stl/css :project)} @@ -285,46 +286,52 @@ [:& inline-edition {:content (:name project) :on-end on-edit}] [:h2 {:on-click on-nav + :style {:max-width (str title-width "%")} + :class (stl/css :project-name) + :title (if (:is-default project) + (tr "labels.drafts") + (:name project)) :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}] + [:div {:class (stl/css :info-wrapper)} + [:& 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)))] + [: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)]) + (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) - [:> pin-button* {:class (stl/css :pin-button) :is-pinned (:is-pinned project) :on-click toggle-pin :tab-index 0}]) + [:div {:class (stl/css :project-actions)} + (when-not (:is-default project) + [:> pin-button* {:class (stl/css :pin-button) :is-pinned (:is-pinned project) :on-click toggle-pin :tab-index 0}]) - [: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/add] + [:button {:class (stl/css :btn-secondary :btn-small) + :on-click on-create-click + :title (tr "dashboard.new-file") + :aria-label (tr "dashboard.new-file") + :data-test "project-new-file" + :on-key-down handle-create-click} + i/add] - [: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/menu]]]] + [:button + {:class (stl/css :btn-secondary :btn-small) + :on-click on-menu-click + :title (tr "dashboard.options") + :aria-label (tr "dashboard.options") + :data-test "project-options" + :on-key-down handle-menu-click} + i/menu]]]]] [:div {:class (stl/css :grid-container) :ref rowref} [:& line-grid diff --git a/frontend/src/app/main/ui/dashboard/projects.scss b/frontend/src/app/main/ui/dashboard/projects.scss index 13204f3d5..aa1be237a 100644 --- a/frontend/src/app/main/ui/dashboard/projects.scss +++ b/frontend/src/app/main/ui/dashboard/projects.scss @@ -48,6 +48,7 @@ display: flex; align-items: center; justify-content: flex-start; + width: 100%; min-height: $s-32; margin-left: $s-8; } @@ -57,7 +58,8 @@ padding: $s-8; } - h2 { + .project-name { + @include textEllipsis; cursor: pointer; font-size: $fs-16; line-height: 0.8; @@ -65,8 +67,13 @@ color: $df-primary; margin-right: $s-4; margin-right: $s-12; + width: fit-content; + } + .info-wrapper { + display: flex; + align-items: center; + gap: $s-8; } - .info, .recent-files-row-title-info { font-size: $fs-14; @@ -80,7 +87,7 @@ .project-actions { display: flex; - opacity: 1; + opacity: 0; margin-left: $s-32; .btn-small:not(.pin-button) { From c865a1bdfda85954a57ed689865434a2ce746cb4 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Tue, 12 Mar 2024 14:04:06 +0100 Subject: [PATCH 083/136] :recycle: Refactor project header css --- .../src/app/main/ui/dashboard/projects.cljs | 43 ++-- .../src/app/main/ui/dashboard/projects.scss | 206 +++++++++--------- 2 files changed, 124 insertions(+), 125 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 9135ca83b..931ac0604 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -40,6 +40,12 @@ (def ^:private close-icon (i/icon-xref :close (stl/css :close-icon))) +(def ^:private add-icon + (i/icon-xref :add (stl/css :add-icon))) + +(def ^:private menu-icon + (i/icon-xref :menu (stl/css :menu-icon))) + (mf/defc header {::mf/wrap [mf/memo]} [] @@ -312,26 +318,26 @@ (dt/timeago {:locale locale}))] [:span {:class (stl/css :recent-files-row-title-info)} (str ", " time)]) - [:div {:class (stl/css :project-actions)} + [:div {:class (stl/css-case :project-actions true + :pinned-project (:is-pinned project))} (when-not (:is-default project) [:> pin-button* {:class (stl/css :pin-button) :is-pinned (:is-pinned project) :on-click toggle-pin :tab-index 0}]) - [:button {:class (stl/css :btn-secondary :btn-small) + [:button {:class (stl/css :add-file-btn) :on-click on-create-click :title (tr "dashboard.new-file") :aria-label (tr "dashboard.new-file") :data-test "project-new-file" :on-key-down handle-create-click} - i/add] + add-icon] - [:button - {:class (stl/css :btn-secondary :btn-small) - :on-click on-menu-click - :title (tr "dashboard.options") - :aria-label (tr "dashboard.options") - :data-test "project-options" - :on-key-down handle-menu-click} - i/menu]]]]] + [:button {:class (stl/css :options-btn) + :on-click on-menu-click + :title (tr "dashboard.options") + :aria-label (tr "dashboard.options") + :data-test "project-options" + :on-key-down handle-menu-click} + menu-icon]]]]] [:div {:class (stl/css :grid-container) :ref rowref} [:& line-grid @@ -343,14 +349,13 @@ (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")] + [:button {:class (stl/css :show-more) + :on-click on-nav + :tab-index "0" + :on-key-down (fn [event] + (when (kbd/enter? event) + (on-nav)))} + [:span {:class (stl/css :placeholder-label)} (tr "dashboard.show-all-files")] show-more-icon])])) diff --git a/frontend/src/app/main/ui/dashboard/projects.scss b/frontend/src/app/main/ui/dashboard/projects.scss index aa1be237a..735f4e7ee 100644 --- a/frontend/src/app/main/ui/dashboard/projects.scss +++ b/frontend/src/app/main/ui/dashboard/projects.scss @@ -9,135 +9,129 @@ .dashboard-container { flex: 1 0 0; - margin-right: $s-16; - overflow-y: auto; width: 100%; - border-top: $s-1 solid $db-quaternary; + margin-right: $s-16; + border-top: $s-1 solid var(--panel-border-color); + overflow-y: auto; +} - &.dashboard-projects { - user-select: none; - } - &.dashboard-shared { - width: calc(100vw - $s-320); - margin-right: $s-52; - } +.dashboard-projects { + user-select: none; +} - &.search { - margin-top: $s-12; - } +.dashboard-shared { + width: calc(100vw - $s-320); + margin-right: $s-52; +} + +.search { + margin-top: $s-12; } .dashboard-project-row { + --actions-opacity: 0; margin-bottom: $s-24; position: relative; - .project { - align-items: center; - border-radius: $br-4; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - margin-top: $s-16; - padding: $s-8 $s-8 $s-8 $s-16; - width: 99%; - max-height: $s-40; - gap: $s-8; - - .project-name-wrapper { - display: flex; - align-items: center; - justify-content: flex-start; - width: 100%; - min-height: $s-32; - margin-left: $s-8; - } - - .btn-secondary { - border: none; - padding: $s-8; - } - - .project-name { - @include textEllipsis; - cursor: pointer; - font-size: $fs-16; - line-height: 0.8; - font-weight: $fw400; - color: $df-primary; - margin-right: $s-4; - margin-right: $s-12; - width: fit-content; - } - .info-wrapper { - display: flex; - align-items: center; - gap: $s-8; - } - .info, - .recent-files-row-title-info { - font-size: $fs-14; - line-height: 1.15; - font-weight: $fw400; - color: $df-secondary; - @media (max-width: 760px) { - display: none; - } - } - - .project-actions { - display: flex; - opacity: 0; - margin-left: $s-32; - - .btn-small:not(.pin-button) { - height: $s-32; - margin: 0 $s-8; - width: $s-32; - - &:not(:hover) { - background: transparent; - } - svg { - fill: $df-primary; - height: $s-16; - width: $s-16; - } - } - } - } - - .grid-container { - width: 100%; - padding: 0 $s-4; - } - &:hover, &:focus, &:focus-within { - .project-actions { - opacity: 1; - } + --actions-opacity: 1; } } -.show-more { +.pinned-project { + --actions-opacity: 1; +} + +.project { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: $s-8; + width: 99%; + max-height: $s-40; + padding: $s-8 $s-8 $s-8 $s-16; + margin-top: $s-16; + border-radius: $br-4; +} + +.project-name-wrapper { display: flex; align-items: center; - column-gap: $s-12; + justify-content: flex-start; + width: 100%; + min-height: $s-32; + margin-left: $s-8; +} - color: $df-secondary; - font-size: $fs-14; - justify-content: space-between; +.project-name { + @include bodyLargeTypography; + @include textEllipsis; + width: fit-content; + margin-right: $s-12; + line-height: 0.8; + color: var(--title-foreground-color-hover); cursor: pointer; - background-color: transparent; - border: none; +} + +.info-wrapper { + display: flex; + align-items: center; + gap: $s-8; +} + +.info, +.recent-files-row-title-info { + @include bodyMediumTypography; + color: var(--title-foreground-color); + @media (max-width: 760px) { + display: none; + } +} + +.project-actions { + display: flex; + opacity: var(--actions-opacity); + margin-left: $s-32; +} + +.add-file-btn, +.options-btn { + @extend .button-tertiary; + height: $s-32; + width: $s-32; + margin: 0 $s-8; + padding: $s-8; +} + +.add-icon, +.menu-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} + +.grid-container { + width: 100%; + padding: 0 $s-4; +} + +.show-more { + --show-more-color: var(--button-secondary-foreground-color-rest); + @include buttonStyle; + @include bodyMediumTypography; position: absolute; top: $s-8; right: $s-52; + display: flex; + align-items: center; + justify-content: space-between; + column-gap: $s-12; + color: var(--show-more-color); &:hover { - color: $da-tertiary; + --show-more-color: var(--button-secondary-foreground-color-active); } } @@ -145,7 +139,7 @@ height: $s-16; width: $s-16; fill: none; - stroke: currentColor; + stroke: var(--show-more-color); } // Team hero From 37859a20a640ff7b0a691e5d32001d1f822d05b6 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Tue, 12 Mar 2024 14:04:41 +0100 Subject: [PATCH 084/136] :bug: Recover lost wrap icon --- .../icons/{wrap-refactor.svg => wrap.svg} | 0 .../main/partials/debug-icons-preview.scss | 3 +-- frontend/src/app/main/ui/icons.cljs | 26 ++++++------------- 3 files changed, 9 insertions(+), 20 deletions(-) rename frontend/resources/images/icons/{wrap-refactor.svg => wrap.svg} (100%) diff --git a/frontend/resources/images/icons/wrap-refactor.svg b/frontend/resources/images/icons/wrap.svg similarity index 100% rename from frontend/resources/images/icons/wrap-refactor.svg rename to frontend/resources/images/icons/wrap.svg diff --git a/frontend/resources/styles/main/partials/debug-icons-preview.scss b/frontend/resources/styles/main/partials/debug-icons-preview.scss index 763485890..4b72bd0a7 100644 --- a/frontend/resources/styles/main/partials/debug-icons-preview.scss +++ b/frontend/resources/styles/main/partials/debug-icons-preview.scss @@ -61,8 +61,7 @@ .cursor-item div, .icon-item-old svg { - fill: #aab5ba; - stroke: none; + stroke: #aab5ba; } .cursor-item { diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index ec9712471..002ef71a8 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -284,24 +284,14 @@ {::mf/wrap-props false} [] (let [entries (->> (seq (js/Object.entries default)) - (sort-by first)) - refactor? (fn [[key]] (str/ends-with? key "Refactor"))] - [:* - [:section.debug-icons-preview - [:h2.subtitle-old "Classic (Deprecated)"] - (for [[key val] (remove refactor? entries)] - [:div.icon-item-old {:key key - :title key} - val - [:span key]])] - - [:section.debug-icons-preview - [:h2 "Refactor"] - (for [[key val] (filter refactor? entries)] - [:div.icon-item {:key key - :title key} - val - [:span key]])]])) + (sort-by first))] + [:section.debug-icons-preview + [:h2 "icons"] + (for [[key val] entries] + [:div.icon-item-old {:key key + :title key} + val + [:span key]])])) (defn key->icon [icon-key] From a3bfeace736c6369072c427e74f53c7dbb49d0fc Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Tue, 12 Mar 2024 14:10:47 +0100 Subject: [PATCH 085/136] :bug: Fix search icon on dhasboard --- .../resources/styles/common/refactor/common-dashboard.scss | 6 ++++-- frontend/src/app/main/ui/dashboard/placeholder.scss | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/resources/styles/common/refactor/common-dashboard.scss b/frontend/resources/styles/common/refactor/common-dashboard.scss index 5404d5630..79ffa2542 100644 --- a/frontend/resources/styles/common/refactor/common-dashboard.scss +++ b/frontend/resources/styles/common/refactor/common-dashboard.scss @@ -95,12 +95,14 @@ cursor: pointer; svg { - fill: $df-secondary; + stroke: $df-secondary; + fill: none; width: $s-16; height: $s-16; &:hover { - fill: $da-tertiary; + stroke: $da-tertiary; + fill: none; } } } diff --git a/frontend/src/app/main/ui/dashboard/placeholder.scss b/frontend/src/app/main/ui/dashboard/placeholder.scss index 6f05ba000..f2a37fbf0 100644 --- a/frontend/src/app/main/ui/dashboard/placeholder.scss +++ b/frontend/src/app/main/ui/dashboard/placeholder.scss @@ -23,7 +23,8 @@ svg { width: $s-64; height: $s-64; - fill: $df-secondary; + stroke: $df-secondary; + fill: none; } } From 3bbf97fde9e5ccc527a2a96341e19826e3c356e8 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Tue, 12 Mar 2024 17:19:40 +0100 Subject: [PATCH 086/136] :bug: Fix invitation badge colors --- .../styles/common/refactor/design-tokens.scss | 32 +++++----- frontend/src/app/main/ui/dashboard/team.cljs | 20 ++---- frontend/src/app/main/ui/dashboard/team.scss | 19 ------ .../src/app/main/ui/notifications/badge.cljs | 27 ++++++++ .../src/app/main/ui/notifications/badge.scss | 64 +++++++++++++++++++ .../app/main/ui/workspace/sidebar/layers.cljs | 4 +- .../app/main/ui/workspace/sidebar/layers.scss | 10 --- .../main/ui/workspace/sidebar/sitemap.cljs | 6 +- .../main/ui/workspace/sidebar/sitemap.scss | 16 +---- 9 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 frontend/src/app/main/ui/notifications/badge.cljs create mode 100644 frontend/src/app/main/ui/notifications/badge.scss diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss index 4049cc42e..a1527bf05 100644 --- a/frontend/resources/styles/common/refactor/design-tokens.scss +++ b/frontend/resources/styles/common/refactor/design-tokens.scss @@ -315,7 +315,13 @@ --modal-navigator-foreground-color-rest: var(--color-background-quaternary); --modal-navigator-foreground-color-active: var(--color-accent-primary); - // ALERTS NOTIFICATION TOAST & STATUS WIDGET + // ALERTS, NOTIFICATION, TOAST & BADGES + + --alert-background-color-default: var(--color-background-primary); + --alert-text-foreground-color-default: var(--color-foreground-primary); + --alert-icon-foreground-color-default: var(--color-foreground-primary); + --alert-border-color-default: var(--color-background-quaternary); + --alert-background-color-success: var(--color-success-background); --alert-text-foreground-color-success: var(--color-foreground-primary); --alert-icon-foreground-color-success: var(--color-success-foreground); @@ -336,26 +342,20 @@ --alert-icon-foreground-color-info: var(--color-info-foreground); --alert-border-color-info: var(--color-info-foreground); - --alert-background-color-default: var(--color-background-primary); - --alert-text-foreground-color-default: var(--color-foreground-primary); - --alert-icon-foreground-color-default: var(--color-foreground-primary); - --alert-border-color-default: var(--color-background-quaternary); + --alert-text-foreground-color-focus: var(--color-accent-primary); + --alert-border-color-focus: var(--color-accent-primary); - --notification-background-color-success: var(); - --notification-foreground-color-success: var(); - --notification-border-color-success: var(); --notification-foreground-color-default: var(--color-foreground-secondary); + --element-foreground-warning: var(--status-color-warning-500); + --element-foreground-error: var(--status-color-error-500); + + // STATUS WIDGET --status-widget-background-color-success: var(--status-color-success-500); --status-widget-background-color-warning: var(--status-color-warning-500); --status-widget-background-color-pending: var(--status-color-pending-500); --status-widget-background-color-error: var(--status-color-error-500); - --status-widget-icon-foreground-color: var(--color-background-primary); // TODO review - - --element-foreground-success: var(--status-color-success-500); - --element-foreground-warning: var(--status-color-warning-500); - --element-foreground-pending: var(--status-color-info-500); - --element-foreground-error: var(--status-color-error-500); + --status-widget-icon-foreground-color: var(--color-background-primary); // INTERFACE ELEMENTS --search-bar-background-color: var(--color-background-primary); @@ -370,9 +370,6 @@ --pill-background-color: var(--color-background-tertiary); --pill-foreground-color: var(--color-foreground-primary); - --tag-background-color: var(--color-accent-primary); - --tag-background-color-disabled: var(--color-foreground-primary); - --link-foreground-color: var(--color-accent-primary); --resize-area-background-color: var(--color-background-primary); @@ -382,6 +379,7 @@ --dashboard-list-background-color: var(--color-background-tertiary); --dashboard-list-foreground-color: var(--color-foreground-primary); --dashboard-list-text-foreground-color: var(--color-foreground-secondary); + --flow-tag-background-color: var(--color-background-tertiary); --flow-tag-foreground-color: var(--color-foreground-secondary); --flow-tag-background-color-hover: var(--color-background-quaternary); diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index adc63664c..76652e98a 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -24,6 +24,7 @@ [app.main.ui.dashboard.change-owner] [app.main.ui.dashboard.team-form] [app.main.ui.icons :as i] + [app.main.ui.notifications.badge :refer [badge-notification]] [app.main.ui.notifications.context-notification :refer [context-notification]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] @@ -551,19 +552,6 @@ :on-click on-change'} (tr "labels.editor")]]]])) -(mf/defc invitation-status-badge - {::mf/wrap-props false} - [{:keys [status]}] - [:div - {:class (stl/css-case - :status-badge true - :badge-expired (= status :expired) - :badge-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]}] @@ -668,6 +656,10 @@ email (:email invitation) role (:role invitation) status (if expired? :expired :pending) + type (if expired? :warning :default) + badge-content (if (= status :expired) + (tr "labels.expired-invitation") + (tr "labels.pending-invitation")) on-change-role (mf/use-fn @@ -688,7 +680,7 @@ :on-change on-change-role}]] [:div {:class (stl/css :table-field :field-status)} - [:& invitation-status-badge {:status status}]] + [:& badge-notification {:type type :content badge-content}]] [:div {:class (stl/css :table-field :field-actions)} (when can-invite? diff --git a/frontend/src/app/main/ui/dashboard/team.scss b/frontend/src/app/main/ui/dashboard/team.scss index c5d67a027..e79a69f63 100644 --- a/frontend/src/app/main/ui/dashboard/team.scss +++ b/frontend/src/app/main/ui/dashboard/team.scss @@ -322,25 +322,6 @@ align-items: center; } -// STATUS BADGE -.status-badge { - @include flexCenter; - @include headlineSmallTypography; - min-width: $s-76; - width: fit-content; - height: $s-24; - border-radius: $br-8; - color: var(--pill-foreground-color); -} - -.badge-pending { - background-color: var(--status-widget-background-color-warning); -} - -.badge-expired { - background-color: var(--tag-background-color-disabled); -} - .invitations-dropdown { bottom: calc(-1 * $s-112); right: calc(-1 * $s-20); diff --git a/frontend/src/app/main/ui/notifications/badge.cljs b/frontend/src/app/main/ui/notifications/badge.cljs new file mode 100644 index 000000000..e6e6c449e --- /dev/null +++ b/frontend/src/app/main/ui/notifications/badge.cljs @@ -0,0 +1,27 @@ +;; 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.notifications.badge + (:require-macros [app.main.style :as stl]) + (:require + [rumext.v2 :as mf])) + +(mf/defc badge-notification + "They are persistent, informative and non-actionable. + They are small messages in specific areas off the app" + + {::mf/props :obj} + [{:keys [type content size is-focus] :as props}] + + [:aside {:class (stl/css-case :badge-notification true + :warning (= type :warning) + :error (= type :error) + :success (= type :success) + :info (= type :info) + :small (= size :small) + :focus is-focus)} + content]) + diff --git a/frontend/src/app/main/ui/notifications/badge.scss b/frontend/src/app/main/ui/notifications/badge.scss new file mode 100644 index 000000000..b98a5ee88 --- /dev/null +++ b/frontend/src/app/main/ui/notifications/badge.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"; + +.badge-notification { + @include smallTitleTipography; + --badge-notification-bg-color: var(--alert-background-color-default); + --badge-notification-fg-color: var(--alert-text-foreground-color-default); + --badge-notification-border-color: var(--alert-border-color-default); + box-sizing: border-box; + display: grid; + place-items: center; + grid-template-columns: 1fr; + min-height: $s-32; + height: fit-content; + min-width: $s-80; + width: fit-content; + padding: 0; + margin: 0; + border: $s-1 solid var(--badge-notification-border-color); + border-radius: $br-8; + background-color: var(--badge-notification-bg-color); + color: var(--badge-notification-fg-color); +} + +.small { + @include bodySmallTypography; + min-height: $s-20; + border-radius: $br-6; +} + +.warning { + --badge-notification-bg-color: var(--alert-background-color-warning); + --badge-notification-fg-color: var(--alert-text-foreground-color-warning); + --badge-notification-border-color: var(--alert-border-color-warning); +} + +.success { + --badge-notification-bg-color: var(--alert-background-color-success); + --badge-notification-fg-color: var(--alert-text-foreground-color-success); + --badge-notification-border-color: var(--alert-border-color-success); +} + +.info { + --badge-notification-bg-color: var(--alert-background-color-info); + --badge-notification-fg-color: var(--alert-text-foreground-color-info); + --badge-notification-border-color: var(--alert-border-color-info); +} + +.error { + --badge-notification-bg-color: var(--alert-background-color-error); + --badge-notification-fg-color: var(--alert-text-foreground-color-error); + --badge-notification-border-color: var(--alert-border-color-error); +} + +.focus { + --badge-notification-bg-color: transparent; + --badge-notification-fg-color: var(--alert-text-foreground-color-focus); + --badge-notification-border-color: var(--alert-border-color-focus); +} diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index c3f927e04..5d3f5da5d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -19,6 +19,7 @@ [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] + [app.main.ui.notifications.badge :refer [badge-notification]] [app.main.ui.workspace.sidebar.layer-item :refer [layer-item]] [app.util.dom :as dom] [app.util.globals :as globals] @@ -513,8 +514,7 @@ (or title (tr "workspace.sidebar.layers"))] [:div {:class (stl/css :focus-mode-tag-wrapper)} - [:div {:class (stl/css :focus-mode-tag)} - (tr "workspace.focus.focus-mode")]]]] + [:& badge-notification {:content (tr "workspace.focus.focus-mode") :size :small :is-focus true}]]]] (filter-component)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.scss b/frontend/src/app/main/ui/workspace/sidebar/layers.scss index 422f72c19..4c0823ddf 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.scss @@ -122,16 +122,6 @@ margin-right: $s-12; } -.focus-mode-tag { - @include flexCenter; - @include bodySmallTypography; - height: $s-20; - padding: $s-4 $s-6; - border: $s-1 solid var(--tag-background-color); - border-radius: $br-6; - color: var(--tag-background-color); -} - .active-filters { @include flexRow; flex-wrap: wrap; diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs index 73977a797..975615048 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs @@ -17,6 +17,7 @@ [app.main.ui.context :as ctx] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] + [app.main.ui.notifications.badge :refer [badge-notification]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] [app.util.keyboard :as kbd] @@ -218,8 +219,9 @@ :class (stl/css :title-spacing-sitemap)} (if ^boolean read-only? - [:div {:class (stl/css :view-only-mode)} - (tr "labels.view-only")] + [:& badge-notification {:is-focus true + :size :small + :content (tr "labels.view-only")}] [:button {:class (stl/css :add-page) :on-click on-create} i/add])] diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss b/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss index a02e38df3..1363ea1c5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss @@ -33,17 +33,6 @@ } } -.view-only-mode { - @include flexCenter; - @include bodySmallTypography; - height: $s-20; - padding: $s-4 $s-6; - margin-right: $s-12; - border: $s-1 solid var(--tag-background-color); - border-radius: $br-6; - color: var(--tag-background-color); -} - .resize-area { position: absolute; bottom: calc(-1 * $s-8); @@ -236,6 +225,7 @@ } .title-spacing-sitemap { - padding-left: $s-8; - margin-top: $s-8; + padding-inline-start: $s-8; + margin-block-start: $s-8; + padding-inline-end: $s-20; } From 786513863b887278be75fa724486810b687de0ba Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 12 Mar 2024 11:55:40 +0100 Subject: [PATCH 087/136] :bug: Fix problem with duplicate in main component --- common/src/app/common/types/component.cljc | 10 ++++++++++ frontend/src/app/main/data/workspace/selection.cljs | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/common/src/app/common/types/component.cljc b/common/src/app/common/types/component.cljc index 70b030eaf..205454d71 100644 --- a/common/src/app/common/types/component.cljc +++ b/common/src/app/common/types/component.cljc @@ -240,3 +240,13 @@ (distinct) (filter #(not (eq % (get comp1 %) (get comp2 %)))) set))) + +(defn allow-duplicate? + [objects shape] + + (let [parent (get objects (:parent-id shape))] + ;; We don't want to change the structure of component copies + (and (not (in-component-copy-not-head? shape)) + ;; Non instance, non copy. We allow + (or (not (instance-head? shape)) + (not (in-component-copy? parent)))))) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 15d3d5ab4..eb5e9e168 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -709,8 +709,8 @@ (let [page (wsh/lookup-page state) objects (:objects page) selected (->> (wsh/lookup-selected state) - (map #(get objects %)) - (remove #(ctk/in-component-copy-not-root? %)) ;; We don't want to change the structure of component copies + (map (d/getf objects)) + (filter #(ctk/allow-duplicate? objects %)) (map :id) set)] (when (seq selected) From 8128171d8e2eb5289605b555c6245ff4bd5c08c5 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 12 Mar 2024 17:34:24 +0100 Subject: [PATCH 088/136] :bug: Fix problem with complementary colors slider in picker --- .../app/main/ui/workspace/colorpicker/harmony.cljs | 14 +++++++++++--- .../ui/workspace/colorpicker/slider_selector.scss | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs index 7ca720bd2..361a51f7e 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs @@ -8,6 +8,7 @@ (:require-macros [app.main.style :as stl]) (:require [app.common.colors :as cc] + [app.common.data.macros :as dm] [app.common.geom.point :as gpt] [app.common.math :as mth] [app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]] @@ -118,17 +119,24 @@ :h new-hue :s saturation}))) - on-change-opacity (fn [new-alpha] (on-change {:alpha new-alpha}))] + on-change-opacity (fn [new-alpha] (on-change {:alpha new-alpha})) + + ;; This colors are to display the value slider + [h1 s1 l1] (cc/hsv->hsl [hue saturation 0]) + [h2 s2 l2] (cc/hsv->hsl [hue saturation 255])] (mf/use-effect (mf/deps canvas-ref) (fn [] (when canvas-ref (create-color-wheel (mf/ref-val canvas-ref))))) - [:div {:class (stl/css :harmony-selector)} + + [:div {:class (stl/css :harmony-selector) + :style {"--hue-from" (dm/str "hsl(" h1 ", " (* s1 100) "%, " (* l1 100) "%)") + "--hue-to" (dm/str "hsl(" h2 ", " (* s2 100) "%, " (* l2 100) "%)")}} [:div {:class (stl/css :handlers-wrapper)} [:& slider-selector {:type :value :vertical? true - :reverse? true + :reverse? false :value value :max-value 255 :vertical true diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss index 3e30ad7ea..7de62cbef 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss +++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss @@ -107,7 +107,7 @@ } .slider-selector.value { - background: linear-gradient(var(--gradient-direction), #000 0%, #fff 100%); + background: linear-gradient(var(--gradient-direction), var(--hue-from, #000) 0%, var(--hue-to, #fff) 100%); } .slider-selector.saturation { background: linear-gradient( From 3b0148046bc5dac7c3f323f82644357e45e12233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Tue, 12 Mar 2024 15:10:23 +0100 Subject: [PATCH 089/136] :bug: Fix horizontal scroll bar in comments --- frontend/src/app/main/ui/comments.scss | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss index 095e14294..2b10eb9e5 100644 --- a/frontend/src/app/main/ui/comments.scss +++ b/frontend/src/app/main/ui/comments.scss @@ -98,8 +98,12 @@ } .content { + position: relative; @include bodySmallTypography; color: var(--color-foreground-primary); + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; } .replies { @@ -203,13 +207,6 @@ } } } - .content { - position: relative; - .text { - @include bodySmallTypography; - white-space: pre; - } - } } .comment-options-dropdown { @extend .dropdown-wrapper; @@ -233,7 +230,6 @@ height: 100%; width: 100%; max-width: $s-260; - min-width: $s-260; margin-bottom: $s-8; padding: $s-8; color: var(--input-foreground-color-active); From 8ee79e5d7c51a1cf1204355135f442aac383d7ee Mon Sep 17 00:00:00 2001 From: Aitor Date: Tue, 12 Mar 2024 15:18:42 +0100 Subject: [PATCH 090/136] :bug: Fix viewer background visible on transition between frames --- .../src/app/main/ui/viewer/interactions.cljs | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/viewer/interactions.cljs b/frontend/src/app/main/ui/viewer/interactions.cljs index 8d5fd829f..9fc794f60 100644 --- a/frontend/src/app/main/ui/viewer/interactions.cljs +++ b/frontend/src/app/main/ui/viewer/interactions.cljs @@ -316,18 +316,37 @@ [animation current-viewport orig-viewport current-size orig-size wrapper-size] (case (:animation-type animation) + ;; Why use three keyframes instead of two? + ;; If we use two keyframes, the first frame + ;; will disappear while the second frame + ;; is still appearing. + ;; ___ ___ + ;; \/ + ;; ___/\___ + ;; ^ in here we have 50% opacity of both frames so the background + ;; is visible. + ;; + ;; This solution waits until the second frame + ;; has appeared to disappear the first one. + ;; ________ + ;; /\ + ;; _/ \___ + ;; ^ in here we have 100% opacity of the first frame and 0% opacity. :dissolve (do (dom/animate! orig-viewport [#js {:opacity "100%"} - #js {:opacity "0"}] - #js {:duration (:duration animation) - :easing (name (:easing animation))} - #(st/emit! (dv/complete-animation))) + #js {:opacity "0%"} + #js {:opacity "0%"}] + #js {:delay (/ (:duration animation) 3) + :duration (/ (* 2 (:duration animation)) 3) + :easing (name (:easing animation))}) (dom/animate! current-viewport - [#js {:opacity "0"} + [#js {:opacity "0%"} + #js {:opacity "100%"} #js {:opacity "100%"}] #js {:duration (:duration animation) - :easing (name (:easing animation))})) + :easing (name (:easing animation))} + #(st/emit! (dv/complete-animation)))) :slide (case (:way animation) From 76b75192e799368843ef8caadb30a6231f035f90 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Tue, 12 Mar 2024 14:36:09 +0100 Subject: [PATCH 091/136] :bug: Fix crash copy paste a Copy --- common/src/app/common/types/file.cljc | 11 ++++++++++- frontend/src/app/main/data/workspace/selection.cljs | 9 ++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 676db6dc7..a060fe634 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -215,6 +215,15 @@ (some find-ref-shape-in-head (ctn/get-parent-heads (:objects container) shape)))) +(defn find-original-ref-shape + "Recursively call to find-ref-shape until find the original shape of the original component" + [file container libraries shape & options] + (let [ref-shape (find-ref-shape file container libraries shape options)] + (if (nil? (:shape-ref ref-shape)) + ref-shape + (find-original-ref-shape file container libraries ref-shape options)))) + + (defn find-ref-component "Locate the nearest component in the local file or libraries that is referenced by the instance shape." @@ -303,7 +312,7 @@ (vals (:objects component))))) ;; Return true if the object is a component that exists on the file or its libraries (even a deleted one) -(defn is-known-component? +(defn is-main-of-known-component? [shape libraries] (let [main-instance? (ctk/main-instance? shape) component-id (:component-id shape) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 15d3d5ab4..7f4cc84ca 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -466,7 +466,7 @@ (nil? obj) changes - (ctf/is-known-component? obj libraries) + (ctf/is-main-of-known-component? obj libraries) (prepare-duplicate-component-change changes objects page obj parent-id frame-id delta libraries library-data it) :else @@ -484,6 +484,9 @@ (ctk/instance-root? obj)) duplicating-component? (or duplicating-component? (ctk/instance-head? obj)) is-component-main? (ctk/main-instance? obj) + + original-ref-shape (-> (ctf/find-original-ref-shape nil page libraries obj {:include-deleted? true}) + :id) into-component? (and duplicating-component? (ctn/in-any-component? objects parent)) @@ -514,6 +517,10 @@ (cond-> (or frame? group? bool?) (assoc :shapes [])) + (cond-> (and (some? original-ref-shape) + (not= original-ref-shape (:shape-ref obj))) + (assoc :shape-ref original-ref-shape)) + (gsh/move delta) (d/update-when :interactions #(ctsi/remap-interactions % ids-map objects)) From f8c416c5aeabac014d4b632361e84fae6fc84bbe Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Tue, 12 Mar 2024 21:34:45 +0100 Subject: [PATCH 092/136] :bug: Fixes the folders in the Swap pannel appear weird on mixed --- .../app/main/ui/workspace/sidebar/options/menus/component.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3cb70d94f..49c077daa 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 @@ -275,7 +275,7 @@ (defn- find-common-path ([components] - (let [paths (map (comp cfh/last-path :path) components)] + (let [paths (map (comp cfh/split-path :path) components)] (find-common-path paths [] 0))) ([paths path n] (let [current (nth (first paths) n nil)] From d4fb85bb02a335cce1de1898896a199bc5f46f92 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 13 Mar 2024 09:44:51 +0100 Subject: [PATCH 093/136] :bug: Fix problem with language update --- frontend/src/app/main/ui/settings/options.cljs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/settings/options.cljs b/frontend/src/app/main/ui/settings/options.cljs index efef14923..2586559bd 100644 --- a/frontend/src/app/main/ui/settings/options.cljs +++ b/frontend/src/app/main/ui/settings/options.cljs @@ -24,12 +24,16 @@ (s/def ::options-form (s/keys :opt-un [::lang ::theme])) +(defn- on-success + [profile] + (st/emit! (msg/success (tr "notifications.profile-saved")) + (du/profile-fetched profile))) + (defn- on-submit [form _event] (let [data (:clean-data @form)] (st/emit! (du/update-profile data) - (du/persist-profile) - (msg/success (tr "notifications.profile-saved"))))) + (du/persist-profile {:on-success on-success})))) (mf/defc options-form {::mf/wrap-props false} From 98b41a5bff800c9ce30ad11749973b61de21a52f Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 09:57:12 +0100 Subject: [PATCH 094/136] :bug: Fix assets group name when is too long --- .../src/app/main/ui/components/title_bar.scss | 25 ++++--------------- .../ui/workspace/sidebar/assets/groups.scss | 1 - 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/main/ui/components/title_bar.scss b/frontend/src/app/main/ui/components/title_bar.scss index 2ff458ded..43de2b42c 100644 --- a/frontend/src/app/main/ui/components/title_bar.scss +++ b/frontend/src/app/main/ui/components/title_bar.scss @@ -20,9 +20,10 @@ .title-only, .inspect-title { @include uppercaseTitleTipography; - display: flex; + display: grid; align-items: center; - flex-grow: 1; + justify-content: flex-start; + grid-auto-flow: column; height: 100%; min-height: $s-32; color: var(--title-foreground-color); @@ -30,7 +31,8 @@ } .title-only { - margin-left: $s-8; + --title-bar-title-margin: #{$s-8}; + margin-inline-start: var(--title-bar-title-margin); } .inspect-title { @@ -66,23 +68,6 @@ } } -.title, -.title-only { - @include uppercaseTitleTipography; - display: flex; - align-items: center; - flex-grow: 1; - height: 100%; - min-height: $s-32; - color: var(--title-foreground-color); - overflow: hidden; -} - -.title-only { - --title-bar-title-margin: #{$s-8}; - margin-inline-start: var(--title-bar-title-margin); -} - .title-only-icon-gap { --title-bar-title-margin: #{$s-12}; } 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 52634fee3..aeafdfeca 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss @@ -18,7 +18,6 @@ .path { @include textEllipsis; - max-width: 90%; margin-left: $s-2; text-transform: initial; color: var(--title-foreground-color-hover); From 16c8c3483f3051cf9b9d33033d6418803ce9ff47 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 10:18:19 +0100 Subject: [PATCH 095/136] :bug: Change view only message --- frontend/src/app/main/ui/workspace/viewport/top_bar.cljs | 2 +- frontend/translations/en.po | 4 ++-- frontend/translations/es.po | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) 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 a7937e670..0c7d6b01b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs @@ -31,7 +31,7 @@ [: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"}]] + :label "workspace.top-bar.view-only"}]] [:button {:class (stl/css :done-btn) :on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]]])) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index d4b3e9527..a894c3360 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -5063,8 +5063,8 @@ msgid "workspace.viewport.click-to-close-path" msgstr "Click to close the path" #, markdown -msgid "workspace.top-bar.read-only" -msgstr "**Inspect mode** (View Only)" +msgid "workspace.top-bar.view-only" +msgstr "**Inspecting mode** (View Only)" msgid "workspace.top-bar.read-only.done" msgstr "Done" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index e2072c81d..7656b949d 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -5148,7 +5148,7 @@ msgid "workspace.viewport.click-to-close-path" msgstr "Pulsar para cerrar la ruta" #, markdown -msgid "workspace.top-bar.read-only" +msgid "workspace.top-bar.view-only" msgstr "**Modo inspección** (View only)" msgid "workspace.top-bar.read-only.done" From e2412b3d437910eb458f544820d7d28a33ab4f68 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 11:05:48 +0100 Subject: [PATCH 096/136] :bug: Fix draft grid columns --- frontend/src/app/main/ui/dashboard/grid.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/app/main/ui/dashboard/grid.scss b/frontend/src/app/main/ui/dashboard/grid.scss index a8c812c92..72f95e4ec 100644 --- a/frontend/src/app/main/ui/dashboard/grid.scss +++ b/frontend/src/app/main/ui/dashboard/grid.scss @@ -19,6 +19,8 @@ $thumbnail-default-height: $s-168; // Default width .grid-row { display: grid; + grid-auto-flow: column; + grid-auto-columns: calc($s-12 + var(--th-width, #{$thumbnail-default-width})); width: 100%; gap: $s-24; } From f525c6df5e9785df9b534b6de1b5308084627699 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 6 Mar 2024 23:48:17 +0100 Subject: [PATCH 097/136] :sparkles: Improve internal naming of setup/props --- backend/src/app/auth/oidc.clj | 11 +++++----- backend/src/app/http.clj | 3 ++- backend/src/app/http/access_token.clj | 3 ++- backend/src/app/http/awsns.clj | 5 +++-- backend/src/app/http/client.clj | 4 ++-- backend/src/app/http/debug.clj | 3 ++- backend/src/app/http/session.clj | 5 +++-- backend/src/app/loggers/audit.clj | 13 ++++++------ backend/src/app/main.clj | 18 ++++++++-------- backend/src/app/rpc.clj | 5 +++-- backend/src/app/rpc/commands/access_token.clj | 5 +++-- backend/src/app/rpc/commands/auth.clj | 21 ++++++++++--------- backend/src/app/rpc/commands/ldap.clj | 3 ++- backend/src/app/rpc/commands/profile.clj | 5 +++-- backend/src/app/rpc/commands/teams.clj | 5 +++-- backend/src/app/rpc/commands/verify_token.clj | 3 ++- backend/src/app/setup.clj | 9 ++++---- backend/src/app/tasks/telemetry.clj | 5 +++-- 18 files changed, 70 insertions(+), 56 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 243c08da5..e1a22288c 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -22,6 +22,7 @@ [app.loggers.audit :as audit] [app.main :as-alias main] [app.rpc.commands.profile :as profile] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.json :as json] [app.util.time :as dt] @@ -413,7 +414,7 @@ ::props])) (defn get-info - [{:keys [provider ::main/props] :as cfg} {:keys [params] :as request}] + [{:keys [provider ::setup/props] :as cfg} {:keys [params] :as request}] (when-let [error (get params :error)] (ex/raise :type :internal :code :error-on-retrieving-code @@ -508,7 +509,7 @@ (if profile (let [sxf (session/create-fn cfg (:id profile)) token (or (:invitation-token info) - (tokens/generate (::main/props cfg) + (tokens/generate (::setup/props cfg) {:iss :auth :exp (dt/in-future "15m") :profile-id (:id profile)})) @@ -536,7 +537,7 @@ :iss :prepared-register :is-active true :exp (dt/in-future {:hours 48})) - token (tokens/generate (::main/props cfg) info) + token (tokens/generate (::setup/props cfg) info) params (d/without-nils {:token token :fullname (:fullname info)}) @@ -551,7 +552,7 @@ (defn- auth-handler [cfg {:keys [params] :as request}] (let [props (audit/extract-utm-params params) - state (tokens/generate (::main/props cfg) + state (tokens/generate (::setup/props cfg) {:iss :oauth :invitation-token (:invitation-token params) :props props @@ -618,7 +619,7 @@ [_] (s/keys :req [::session/manager ::http/client - ::main/props + ::setup/props ::db/pool ::providers])) diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index 1e605cdb0..a696d5477 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -23,6 +23,7 @@ [app.metrics :as mtx] [app.rpc :as-alias rpc] [app.rpc.doc :as-alias rpc.doc] + [app.setup :as-alias setup] [clojure.spec.alpha :as s] [integrant.core :as ig] [promesa.exec :as px] @@ -136,7 +137,7 @@ ::rpc/routes ::rpc.doc/routes ::oidc/routes - ::main/props + ::setup/props ::assets/routes ::debug/routes ::db/pool diff --git a/backend/src/app/http/access_token.clj b/backend/src/app/http/access_token.clj index bfddbb42d..0d1865f10 100644 --- a/backend/src/app/http/access_token.clj +++ b/backend/src/app/http/access_token.clj @@ -10,6 +10,7 @@ [app.config :as cf] [app.db :as db] [app.main :as-alias main] + [app.setup :as-alias setup] [app.tokens :as tokens] [ring.request :as rreq])) @@ -42,7 +43,7 @@ (defn- wrap-soft-auth "Soft Authentication, will be executed synchronously on the undertow worker thread." - [handler {:keys [::main/props]}] + [handler {:keys [::setup/props]}] (letfn [(handle-request [request] (try (let [token (get-token request) diff --git a/backend/src/app/http/awsns.clj b/backend/src/app/http/awsns.clj index 7508be8a2..88060bb20 100644 --- a/backend/src/app/http/awsns.clj +++ b/backend/src/app/http/awsns.clj @@ -13,6 +13,7 @@ [app.db.sql :as sql] [app.http.client :as http] [app.main :as-alias main] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.worker :as-alias wrk] [clojure.spec.alpha :as s] @@ -30,7 +31,7 @@ (defmethod ig/pre-init-spec ::routes [_] (s/keys :req [::http/client - ::main/props + ::setup/props ::db/pool])) (defmethod ig/init-key ::routes @@ -106,7 +107,7 @@ [cfg headers] (let [tdata (get headers "x-penpot-data")] (when-not (str/empty? tdata) - (let [result (tokens/verify (::main/props cfg) {:token tdata :iss :profile-identity})] + (let [result (tokens/verify (::setup/props cfg) {:token tdata :iss :profile-identity})] (:profile-id result))))) (defn- parse-notification diff --git a/backend/src/app/http/client.clj b/backend/src/app/http/client.clj index 5b4a8541c..9ef4cc4b2 100644 --- a/backend/src/app/http/client.clj +++ b/backend/src/app/http/client.clj @@ -55,8 +55,8 @@ convention." ([cfg-or-client request] (let [client (resolve-client cfg-or-client)] - (send! client request {}))) + (send! client request {:sync? true}))) ([cfg-or-client request options] (let [client (resolve-client cfg-or-client)] - (send! client request options)))) + (send! client request (merge {:sync? true} options))))) diff --git a/backend/src/app/http/debug.clj b/backend/src/app/http/debug.clj index 1d2a129cf..a453c6872 100644 --- a/backend/src/app/http/debug.clj +++ b/backend/src/app/http/debug.clj @@ -20,6 +20,7 @@ [app.rpc.commands.auth :as auth] [app.rpc.commands.files-create :refer [create-file]] [app.rpc.commands.profile :as profile] + [app.setup :as-alias setup] [app.srepl.helpers :as srepl] [app.storage :as-alias sto] [app.storage.tmp :as tmp] @@ -340,7 +341,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn- resend-email-notification - [{:keys [::db/pool ::main/props] :as cfg} {:keys [params] :as request}] + [{:keys [::db/pool ::setup/props] :as cfg} {:keys [params] :as request}] (when-not (contains? params :force) (ex/raise :type :validation diff --git a/backend/src/app/http/session.clj b/backend/src/app/http/session.clj index 7ff6dfa01..c4a3f0ba6 100644 --- a/backend/src/app/http/session.clj +++ b/backend/src/app/http/session.clj @@ -15,6 +15,7 @@ [app.db.sql :as sql] [app.http.session.tasks :as-alias tasks] [app.main :as-alias main] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.time :as dt] [clojure.spec.alpha :as s] @@ -138,7 +139,7 @@ (declare ^:private gen-token) (defn create-fn - [{:keys [::manager ::main/props]} profile-id] + [{:keys [::manager ::setup/props]} profile-id] (us/assert! ::manager manager) (us/assert! ::us/uuid profile-id) @@ -196,7 +197,7 @@ (neg? (compare default-renewal-max-age elapsed))))) (defn- wrap-soft-auth - [handler {:keys [::manager ::main/props]}] + [handler {:keys [::manager ::setup/props]}] (us/assert! ::manager manager) (letfn [(handle-request [request] (try diff --git a/backend/src/app/loggers/audit.clj b/backend/src/app/loggers/audit.clj index 45c36334a..aead09110 100644 --- a/backend/src/app/loggers/audit.clj +++ b/backend/src/app/loggers/audit.clj @@ -24,6 +24,7 @@ [app.main :as-alias main] [app.rpc :as-alias rpc] [app.rpc.retry :as rtry] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as-alias sv] [app.util.time :as dt] @@ -261,7 +262,7 @@ (s/def ::tasks/uri ::us/string) (defmethod ig/pre-init-spec ::tasks/archive-task [_] - (s/keys :req [::db/pool ::main/props ::http.client/client])) + (s/keys :req [::db/pool ::setup/props ::http.client/client])) (defmethod ig/init-key ::tasks/archive [_ cfg] @@ -287,7 +288,7 @@ (px/sleep 100) (recur (+ total ^long n))) (when (pos? total) - (l/debug :hint "events archived" :total total))))))))) + (l/dbg :hint "events archived" :total total))))))))) (def ^:private sql:retrieve-batch-of-audit-log "select * @@ -322,7 +323,7 @@ :context])) (send [events] - (let [token (tokens/generate (::main/props cfg) + (let [token (tokens/generate (::setup/props cfg) {:iss "authentication" :iat (dt/now) :uid uuid/zero}) @@ -331,11 +332,11 @@ "origin" (cf/get :public-uri) "cookie" (u/map->query-string {:auth-token token})} params {:uri uri - :timeout 6000 + :timeout 12000 :method :post :headers headers :body body} - resp (http.client/req! cfg params {:sync? true})] + resp (http.client/req! cfg params)] (if (= (:status resp) 204) true (do @@ -355,7 +356,7 @@ (map row->event)) events (into [] xform rows)] (when-not (empty? events) - (l/trace :hint "archive events chunk" :uri uri :events (count events)) + (l/trc :hint "archive events chunk" :uri uri :events (count events)) (when (send events) (mark-as-archived conn rows) (count events))))))) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 47e43f5cf..e0177110f 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -221,7 +221,7 @@ {::db/pool (ig/ref ::db/pool)} ::http.awsns/routes - {::props (ig/ref ::setup/props) + {::setup/props (ig/ref ::setup/props) ::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client)} @@ -262,7 +262,7 @@ ::oidc/routes {::http.client/client (ig/ref ::http.client/client) ::db/pool (ig/ref ::db/pool) - ::props (ig/ref ::setup/props) + ::setup/props (ig/ref ::setup/props) ::oidc/providers {:google (ig/ref ::oidc.providers/google) :github (ig/ref ::oidc.providers/github) :gitlab (ig/ref ::oidc.providers/gitlab) @@ -274,7 +274,7 @@ ::db/pool (ig/ref ::db/pool) ::rpc/routes (ig/ref ::rpc/routes) ::rpc.doc/routes (ig/ref ::rpc.doc/routes) - ::props (ig/ref ::setup/props) + ::setup/props (ig/ref ::setup/props) ::mtx/routes (ig/ref ::mtx/routes) ::oidc/routes (ig/ref ::oidc/routes) ::http.debug/routes (ig/ref ::http.debug/routes) @@ -286,7 +286,7 @@ {::db/pool (ig/ref ::db/pool) ::session/manager (ig/ref ::session/manager) ::sto/storage (ig/ref ::sto/storage) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} ::http.ws/routes {::db/pool (ig/ref ::db/pool) @@ -322,7 +322,7 @@ ::rpc/climit (ig/ref ::rpc/climit) ::rpc/rlimit (ig/ref ::rpc/rlimit) ::setup/templates (ig/ref ::setup/templates) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} :app.rpc.doc/routes {:methods (ig/ref :app.rpc/methods)} @@ -331,7 +331,7 @@ {::rpc/methods (ig/ref :app.rpc/methods) ::db/pool (ig/ref ::db/pool) ::session/manager (ig/ref ::session/manager) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} ::wrk/registry {::mtx/metrics (ig/ref ::mtx/metrics) @@ -388,7 +388,7 @@ :app.tasks.telemetry/handler {::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} [::srepl/urepl ::srepl/server] {::srepl/port (cf/get :urepl-port 6062) @@ -402,7 +402,7 @@ ::setup/props {::db/pool (ig/ref ::db/pool) - ::key (cf/get :secret-key) + ::setup/key (cf/get :secret-key) ;; NOTE: this dependency is only necessary for proper initialization ordering, props ;; module requires the migrations to run before initialize. @@ -412,7 +412,7 @@ {} ::audit.tasks/archive - {::props (ig/ref ::setup/props) + {::setup/props (ig/ref ::setup/props) ::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client)} diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 8ae7a38d6..ea49b6b70 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -27,6 +27,7 @@ [app.rpc.helpers :as rph] [app.rpc.retry :as retry] [app.rpc.rlimit :as rlimit] + [app.setup :as-alias setup] [app.storage :as-alias sto] [app.util.services :as sv] [app.util.time :as dt] @@ -248,7 +249,7 @@ ::ldap/provider ::sto/storage ::mtx/metrics - ::main/props] + ::setup/props] :opt [::climit ::rlimit])) @@ -265,7 +266,7 @@ (defmethod ig/pre-init-spec ::routes [_] (s/keys :req [::methods ::db/pool - ::main/props + ::setup/props ::session/manager])) (defmethod ig/init-key ::routes diff --git a/backend/src/app/rpc/commands/access_token.clj b/backend/src/app/rpc/commands/access_token.clj index dd10f3371..06a6e516c 100644 --- a/backend/src/app/rpc/commands/access_token.clj +++ b/backend/src/app/rpc/commands/access_token.clj @@ -13,6 +13,7 @@ [app.rpc :as-alias rpc] [app.rpc.doc :as-alias doc] [app.rpc.quotes :as quotes] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] @@ -23,7 +24,7 @@ (dissoc row :perms)) (defn create-access-token - [{:keys [::db/conn ::main/props]} profile-id name expiration] + [{:keys [::db/conn ::setup/props]} profile-id name expiration] (let [created-at (dt/now) token-id (uuid/next) token (tokens/generate props {:iss "access-token" @@ -47,7 +48,7 @@ [{:keys [::db/pool] :as system} profile-id name expiration] (db/with-atomic [conn pool] (let [props (:app.setup/props system)] - (create-access-token {::db/conn conn ::main/props props} + (create-access-token {::db/conn conn ::setup/props props} profile-id name expiration)))) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index 8e9671e59..e87979007 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -26,6 +26,7 @@ [app.rpc.commands.teams :as teams] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] @@ -88,7 +89,7 @@ (profile/strip-private-attrs)) invitation (when-let [token (:invitation-token params)] - (tokens/verify (::main/props cfg) {:token token :iss :team-invitation})) + (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation})) ;; If invitation member-id does not matches the profile-id, we just proceed to ignore the ;; invitation because invitations matches exactly; and user can't login with other email and @@ -133,7 +134,7 @@ (defn recover-profile [{:keys [::db/pool] :as cfg} {:keys [token password]}] (letfn [(validate-token [token] - (let [tdata (tokens/verify (::main/props cfg) {:token token :iss :password-recovery})] + (let [tdata (tokens/verify (::setup/props cfg) {:token token :iss :password-recovery})] (:profile-id tdata))) (update-password [conn profile-id] @@ -170,7 +171,7 @@ :code :registration-disabled))) (when (contains? params :invitation-token) - (let [invitation (tokens/verify (::main/props cfg) {:token (:invitation-token params) :iss :team-invitation})] + (let [invitation (tokens/verify (::setup/props cfg) {:token (:invitation-token params) :iss :team-invitation})] (when-not (= (:email params) (:member-email invitation)) (ex/raise :type :restriction :code :email-does-not-match-invitation @@ -233,7 +234,7 @@ params (d/without-nils params) - token (tokens/generate (::main/props cfg) params)] + token (tokens/generate (::setup/props cfg) params)] (with-meta {:token token} {::audit/profile-id uuid/zero}))) @@ -340,7 +341,7 @@ (defn register-profile [{:keys [::db/conn] :as cfg} {:keys [token fullname] :as params}] - (let [claims (tokens/verify (::main/props cfg) {:token token :iss :prepared-register}) + (let [claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register}) params (-> claims (into params) (assoc :fullname fullname)) @@ -357,7 +358,7 @@ (create-profile-rels! conn)))) invitation (when-let [token (:invitation-token params)] - (tokens/verify (::main/props cfg) {:token token :iss :team-invitation}))] + (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))] ;; If profile is filled in claims, means it tries to register ;; again, so we proceed to update the modified-at attr @@ -377,7 +378,7 @@ ;; email. (and (some? invitation) (= (:email profile) (:member-email invitation))) (let [claims (assoc invitation :member-id (:id profile)) - token (tokens/generate (::main/props cfg) claims) + token (tokens/generate (::setup/props cfg) claims) resp {:invitation-token token}] (-> resp (rph/with-transform (session/create-fn cfg (:id profile))) @@ -404,7 +405,7 @@ ;; In all other cases, send a verification email. :else (do - (send-email-verification! conn (::main/props cfg) profile) + (send-email-verification! conn (::setup/props cfg) profile) (rph/with-meta profile {::audit/replace-props (audit/profile->props profile) ::audit/profile-id (:id profile)}))))) @@ -429,14 +430,14 @@ (defn request-profile-recovery [{:keys [::db/pool] :as cfg} {:keys [email] :as params}] (letfn [(create-recovery-token [{:keys [id] :as profile}] - (let [token (tokens/generate (::main/props cfg) + (let [token (tokens/generate (::setup/props cfg) {:iss :password-recovery :exp (dt/in-future "15m") :profile-id id})] (assoc profile :token token))) (send-email-notification [conn profile] - (let [ptoken (tokens/generate (::main/props cfg) + (let [ptoken (tokens/generate (::setup/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})] diff --git a/backend/src/app/rpc/commands/ldap.clj b/backend/src/app/rpc/commands/ldap.clj index bb86aec90..780f0e100 100644 --- a/backend/src/app/rpc/commands/ldap.clj +++ b/backend/src/app/rpc/commands/ldap.clj @@ -18,6 +18,7 @@ [app.rpc.commands.profile :as profile] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [clojure.spec.alpha :as s])) @@ -40,7 +41,7 @@ {::rpc/auth false ::doc/added "1.15" ::doc/module :auth} - [{:keys [::main/props ::ldap/provider] :as cfg} params] + [{:keys [::setup/props ::ldap/provider] :as cfg} params] (when-not provider (ex/raise :type :restriction :code :ldap-not-initialized diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index 6ef2ef90d..ccb6a8b2e 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -23,6 +23,7 @@ [app.rpc.climit :as climit] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] + [app.setup :as-alias setup] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] @@ -296,12 +297,12 @@ (defn- request-email-change! [{:keys [::conn] :as cfg} {:keys [profile email] :as params}] - (let [token (tokens/generate (::main/props cfg) + (let [token (tokens/generate (::setup/props cfg) {:iss :change-email :exp (dt/in-future "15m") :profile-id (:id profile) :email email}) - ptoken (tokens/generate (::main/props cfg) + ptoken (tokens/generate (::setup/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})] diff --git a/backend/src/app/rpc/commands/teams.clj b/backend/src/app/rpc/commands/teams.clj index 4b5f07700..f62f8bc6a 100644 --- a/backend/src/app/rpc/commands/teams.clj +++ b/backend/src/app/rpc/commands/teams.clj @@ -26,6 +26,7 @@ [app.rpc.helpers :as rph] [app.rpc.permissions :as perms] [app.rpc.quotes :as quotes] + [app.setup :as-alias setup] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] @@ -691,7 +692,7 @@ (defn- create-invitation-token [cfg {:keys [profile-id valid-until team-id member-id member-email role]}] - (tokens/generate (::main/props cfg) + (tokens/generate (::setup/props cfg) {:iss :team-invitation :exp valid-until :profile-id profile-id @@ -702,7 +703,7 @@ (defn- create-profile-identity-token [cfg profile] - (tokens/generate (::main/props cfg) + (tokens/generate (::setup/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})) diff --git a/backend/src/app/rpc/commands/verify_token.clj b/backend/src/app/rpc/commands/verify_token.clj index 49c76c110..e072c90d6 100644 --- a/backend/src/app/rpc/commands/verify_token.clj +++ b/backend/src/app/rpc/commands/verify_token.clj @@ -18,6 +18,7 @@ [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] [app.rpc.quotes :as quotes] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.tokens.spec.team-invitation :as-alias spec.team-invitation] [app.util.services :as sv] @@ -38,7 +39,7 @@ ::doc/module :auth} [{:keys [::db/pool] :as cfg} {:keys [token] :as params}] (db/with-atomic [conn pool] - (let [claims (tokens/verify (::main/props cfg) {:token token}) + (let [claims (tokens/verify (::setup/props cfg) {:token token}) cfg (assoc cfg :conn conn)] (process-token cfg params claims)))) diff --git a/backend/src/app/setup.clj b/backend/src/app/setup.clj index 8e889e2b4..d187f3e5f 100644 --- a/backend/src/app/setup.clj +++ b/backend/src/app/setup.clj @@ -50,16 +50,15 @@ :cause cause)))) instance-id))) -(s/def ::main/key ::us/string) -(s/def ::main/props - (s/map-of ::us/keyword some?)) +(s/def ::key ::us/string) +(s/def ::props (s/map-of ::us/keyword some?)) (defmethod ig/pre-init-spec ::props [_] (s/keys :req [::db/pool] - :opt [::main/key])) + :opt [::key])) (defmethod ig/init-key ::props - [_ {:keys [::db/pool ::main/key] :as cfg}] + [_ {:keys [::db/pool ::key] :as cfg}] (db/with-atomic [conn pool] (db/xact-lock! conn 0) (when-not key diff --git a/backend/src/app/tasks/telemetry.clj b/backend/src/app/tasks/telemetry.clj index 70fa8c35b..cadfff552 100644 --- a/backend/src/app/tasks/telemetry.clj +++ b/backend/src/app/tasks/telemetry.clj @@ -15,6 +15,7 @@ [app.db :as db] [app.http.client :as http] [app.main :as-alias main] + [app.setup :as-alias setup] [app.util.json :as json] [clojure.spec.alpha :as s] [integrant.core :as ig] @@ -32,10 +33,10 @@ (defmethod ig/pre-init-spec ::handler [_] (s/keys :req [::http/client ::db/pool - ::main/props])) + ::setup/props])) (defmethod ig/init-key ::handler - [_ {:keys [::db/pool ::main/props] :as cfg}] + [_ {:keys [::db/pool ::setup/props] :as cfg}] (fn [{:keys [send? enabled?] :or {send? true enabled? false}}] (let [subs {:newsletter-updates (get-subscriptions-newsletter-updates pool) :newsletter-news (get-subscriptions-newsletter-news pool)} From eabec6be2076735a59c97242edd5632a4664a0ff Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 7 Mar 2024 15:15:42 +0100 Subject: [PATCH 098/136] :fire: Remove not needed events --- backend/src/app/auth/oidc.clj | 2 +- backend/src/app/tasks/telemetry.clj | 12 ++++++------ frontend/src/app/main/data/events.cljs | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index e1a22288c..34e2cee57 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -38,7 +38,7 @@ ;; HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defn- obfuscate-string +(defn obfuscate-string [s] (if (< (count s) 10) (apply str (take (count s) (repeat "*"))) diff --git a/backend/src/app/tasks/telemetry.clj b/backend/src/app/tasks/telemetry.clj index cadfff552..43c0b26f9 100644 --- a/backend/src/app/tasks/telemetry.clj +++ b/backend/src/app/tasks/telemetry.clj @@ -40,6 +40,7 @@ (fn [{:keys [send? enabled?] :or {send? true enabled? false}}] (let [subs {:newsletter-updates (get-subscriptions-newsletter-updates pool) :newsletter-news (get-subscriptions-newsletter-news pool)} + enabled? (or enabled? (contains? cf/flags :telemetry) (cf/get :telemetry-enabled)) @@ -78,12 +79,11 @@ (defn- send! [cfg data] - (let [response (http/req! cfg - {:method :post - :uri (cf/get :telemetry-uri) - :headers {"content-type" "application/json"} - :body (json/encode-str data)} - {:sync? true})] + (let [request {:method :post + :uri (cf/get :telemetry-uri) + :headers {"content-type" "application/json"} + :body (json/encode-str data)} + response (http/req! cfg request)] (when (> (:status response) 206) (ex/raise :type :internal :code :invalid-response diff --git a/frontend/src/app/main/data/events.cljs b/frontend/src/app/main/data/events.cljs index a1460eedd..f80883672 100644 --- a/frontend/src/app/main/data/events.cljs +++ b/frontend/src/app/main/data/events.cljs @@ -86,12 +86,10 @@ (derive :app.main.data.dashboard/delete-team-member ::generic-action) (derive :app.main.data.dashboard/duplicate-project ::generic-action) (derive :app.main.data.dashboard/create-file ::generic-action) -(derive :app.main.data.dashboard/file-created ::generic-action) (derive :app.main.data.dashboard/invite-team-members ::generic-action) (derive :app.main.data.dashboard/leave-team ::generic-action) (derive :app.main.data.dashboard/move-files ::generic-action) (derive :app.main.data.dashboard/move-project ::generic-action) -(derive :app.main.data.dashboard/project-created ::generic-action) (derive :app.main.data.dashboard/rename-file ::generic-action) (derive :app.main.data.dashboard/set-file-shared ::generic-action) (derive :app.main.data.dashboard/update-team-member-role ::generic-action) From b41b3de46d14e9f0111a9536b011d9a876c7f44f Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 13:07:39 +0100 Subject: [PATCH 099/136] :recycle: Refactor libraries css --- .../src/app/main/ui/workspace/libraries.cljs | 251 +++++----- .../src/app/main/ui/workspace/libraries.scss | 447 +++++++++--------- 2 files changed, 347 insertions(+), 351 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index e88013b76..4cf953ae8 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -34,6 +34,9 @@ [okulary.core :as l] [rumext.v2 :as mf])) +(def ^:private close-icon + (i/icon-xref :close (stl/css :close-icon))) + (def ref:workspace-file (l/derived :workspace-file st/state)) @@ -185,7 +188,7 @@ :on-cancel on-delete-cancel :count-libraries 1}))))] - [:* + [:div {:class (stl/css :libraries-content)} [:div {:class (stl/css :section)} [:& title-bar {:collapsable false :title (tr "workspace.libraries.in-this-file") @@ -200,16 +203,15 @@ :graphics-count (count media) :colors-count (count colors) :typography-count (count typographies)}]]] - [:div - (if ^boolean shared? - [:input {:class (stl/css :item-unpublish) - :type "button" - :value (tr "common.unpublish") - :on-click unpublish}] - [:input {:class (stl/css :item-publish) - :type "button" - :value (tr "common.publish") - :on-click publish}])]] + (if ^boolean shared? + [:input {:class (stl/css :item-unpublish) + :type "button" + :value (tr "common.unpublish") + :on-click unpublish}] + [:input {:class (stl/css :item-publish) + :type "button" + :value (tr "common.publish") + :on-click publish}])] (for [{:keys [id name] :as library} linked-libraries] [:div {:class (stl/css :section-list-item) @@ -348,106 +350,107 @@ (dwl/set-updating-library true) (dwl/sync-file file-id library-id))))))] - [:div {:class (stl/css :section)} - (if (empty? libs-assets) - [:div {:class (stl/css :section-list-empty)} - (tr "workspace.libraries.no-libraries-need-sync")] - [:* - [:div {:class (stl/css :section-title)} (tr "workspace.libraries.library-updates")] + [:div {:class (stl/css :updates-content)} + [:div {:class (stl/css :section)} + (if (empty? libs-assets) + [:div {:class (stl/css :section-list-empty)} + (tr "workspace.libraries.no-libraries-need-sync")] + [:* + [:div {:class (stl/css :section-title)} (tr "workspace.libraries.library-updates")] - [:div {:class (stl/css :section-list)} - (for [[{:keys [id name] :as library} - exceeded - {:keys [components colors typographies]}] libs-assets] - [:div {:class (stl/css :section-list-item) - :key (dm/str id)} - [:div - [:div {:class (stl/css :item-name)} name] - [:ul {:class (stl/css :item-contents)} (describe-library - (count components) - 0 - (count colors) - (count typographies))]] - [:button {:type "button" - :class (stl/css :item-update) - :disabled updating? - :data-library-id (dm/str id) - :on-click update} - (tr "workspace.libraries.update")] + [:div {:class (stl/css :section-list)} + (for [[{:keys [id name] :as library} + exceeded + {:keys [components colors typographies]}] libs-assets] + [:div {:class (stl/css :section-list-item) + :key (dm/str id)} + [:div + [:div {:class (stl/css :item-name)} name] + [:ul {:class (stl/css :item-contents)} (describe-library + (count components) + 0 + (count colors) + (count typographies))]] + [:button {:type "button" + :class (stl/css :item-update) + :disabled updating? + :data-library-id (dm/str id) + :on-click update} + (tr "workspace.libraries.update")] - [:div {:class (stl/css :libraries-updates)} - (when-not (empty? components) - [:div {:class (stl/css :libraries-updates-column)} - (for [component components] - [:div {:class (stl/css :libraries-updates-item) - :key (dm/str (:id component))} - (let [component (ctf/load-component-objects (:data library) component) - root-shape (ctf/get-component-root (:data library) component)] - [:* - [:& component-svg {:root-shape root-shape - :objects (:objects component)}] - [:div {:class (stl/css :name-block)} - [:span {:class (stl/css :item-name) - :title (:name component)} - (:name component)]]])]) - (when (:components exceeded) - [:div {:class (stl/css :libraries-updates-item) - :key (uuid/next)} - [:div {:class (stl/css :name-block.ellipsis)} - [:span {:class (stl/css :item-name)} "(...)"]]])]) + [:div {:class (stl/css :libraries-updates)} + (when-not (empty? components) + [:div {:class (stl/css :libraries-updates-column)} + (for [component components] + [:div {:class (stl/css :libraries-updates-item) + :key (dm/str (:id component))} + (let [component (ctf/load-component-objects (:data library) component) + root-shape (ctf/get-component-root (:data library) component)] + [:* + [:& component-svg {:root-shape root-shape + :objects (:objects component)}] + [:div {:class (stl/css :name-block)} + [:span {:class (stl/css :item-name) + :title (:name component)} + (:name component)]]])]) + (when (:components exceeded) + [:div {:class (stl/css :libraries-updates-item) + :key (uuid/next)} + [:div {:class (stl/css :name-block.ellipsis)} + [:span {:class (stl/css :item-name)} "(...)"]]])]) - (when-not (empty? colors) - [:div {:class (stl/css :libraries-updates-column) - :style #js {"--bullet-size" "24px"}} - (for [color 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 :libraries-updates-item) - :key (dm/str (:id color))} - [:* - [:& cb/color-bullet {:color {:color (:color color) - :id (:id color) - :opacity (:opacity color)}}] - [:div {:class (stl/css :name-block)} - [:span {:class (stl/css :item-name) - :title (:name color)} - (:name color)] - (when-not (= (:name color) default-name) - [:span.color-value (:color color)])]]])) - (when (:colors exceeded) - [:div {:class (stl/css :libraries-updates-item) - :key (uuid/next)} - [:div {:class (stl/css :name-block.ellipsis)} - [:span {:class (stl/css :item-name)} "(...)"]]])]) + (when-not (empty? colors) + [:div {:class (stl/css :libraries-updates-column) + :style #js {"--bullet-size" "24px"}} + (for [color 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 :libraries-updates-item) + :key (dm/str (:id color))} + [:* + [:& cb/color-bullet {:color {:color (:color color) + :id (:id color) + :opacity (:opacity color)}}] + [:div {:class (stl/css :name-block)} + [:span {:class (stl/css :item-name) + :title (:name color)} + (:name color)] + (when-not (= (:name color) default-name) + [:span.color-value (:color color)])]]])) + (when (:colors exceeded) + [:div {:class (stl/css :libraries-updates-item) + :key (uuid/next)} + [:div {:class (stl/css :name-block.ellipsis)} + [:span {:class (stl/css :item-name)} "(...)"]]])]) - (when-not (empty? typographies) - [:div {:class (stl/css :libraries-updates-column)} - (for [typography typographies] - [:div {:class (stl/css :libraries-updates-item) - :key (dm/str (:id typography))} - [:* - [:div {: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 (:typographies exceeded) - [:div {:class (stl/css :libraries-updates-item) - :key (uuid/next)} - [:div {:class (stl/css :name-block.ellipsis)} - [:span {:class (stl/css :item-name)} "(...)"]]])])] + (when-not (empty? typographies) + [:div {:class (stl/css :libraries-updates-column)} + (for [typography typographies] + [:div {:class (stl/css :libraries-updates-item) + :key (dm/str (:id typography))} + [:* + [:div {: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 (:typographies exceeded) + [:div {:class (stl/css :libraries-updates-item) + :key (uuid/next)} + [:div {:class (stl/css :name-block.ellipsis)} + [:span {:class (stl/css :item-name)} "(...)"]]])])] - (when (or (pos? (:components exceeded)) - (pos? (:colors exceeded)) - (pos? (:typographies exceeded))) - [:div {:class (stl/css :libraries-updates-see-all)} - [:& lb/link-button {:on-click see-all-assets - :value (str "(" (tr "workspace.libraries.update.see-all-changes") ")")}]])])]])])) + (when (or (pos? (:components exceeded)) + (pos? (:colors exceeded)) + (pos? (:typographies exceeded))) + [:div {:class (stl/css :libraries-updates-see-all)} + [:& lb/link-button {:on-click see-all-assets + :value (str "(" (tr "workspace.libraries.update.see-all-changes") ")")}]])])]])]])) (mf/defc libraries-dialog {::mf/register modal/components @@ -491,28 +494,24 @@ [:div {:class (stl/css :modal-overlay) :on-click close-dialog-outside} [:div {:class (stl/css :modal-dialog)} - [:button {:class (stl/css :close) + [:button {:class (stl/css :close-btn) :on-click close-dialog} - i/close] + close-icon] [:div {:class (stl/css :modal-title)} - "Libraries"] - [:div {:class (stl/css :modal-content)} - [:div {:class (stl/css :libraries-header)} - [:& tab-container - {:on-change-tab on-tab-change - :selected selected-tab - :collapsable false} - [:& tab-element {:id :libraries :title (tr "workspace.libraries.libraries")} - [:div {:class (stl/css :libraries-content)} - [:& libraries-tab {:file-id file-id - :shared? shared? - :linked-libraries libraries - :shared-libraries shared-libraries}]]] - [:& tab-element {:id :updates :title (tr "workspace.libraries.updates")} - [:div {:class (stl/css :updates-content)} - [:& updates-tab {:file-id file-id - :file-data file-data - :libraries libraries}]]]]]]]])) + (tr "workspace.libraries.libraries")] + [:& tab-container + {:on-change-tab on-tab-change + :selected selected-tab + :collapsable false} + [:& tab-element {:id :libraries :title (tr "workspace.libraries.libraries")} + [:& libraries-tab {:file-id file-id + :shared? shared? + :linked-libraries libraries + :shared-libraries shared-libraries}]] + [:& tab-element {:id :updates :title (tr "workspace.libraries.updates")} + [:& updates-tab {:file-id file-id + :file-data file-data + :libraries libraries}]]]]])) (mf/defc v2-info-dialog {::mf/register modal/components diff --git a/frontend/src/app/main/ui/workspace/libraries.scss b/frontend/src/app/main/ui/workspace/libraries.scss index ec759217e..79c12bf94 100644 --- a/frontend/src/app/main/ui/workspace/libraries.scss +++ b/frontend/src/app/main/ui/workspace/libraries.scss @@ -6,175 +6,169 @@ @import "refactor/common-refactor.scss"; +// Library .modal-overlay { - @include flexCenter; - position: fixed; - left: 0; - top: 0; - height: 100%; - width: 100%; - z-index: $z-index-modal; - background-color: var(--overlay-color); + @extend .modal-overlay-base; } .modal-dialog { - position: relative; + @extend .modal-container-base; height: $s-520; - max-height: 100%; + max-height: $s-520; width: $s-712; - padding: $s-32; - border-radius: $br-10; - background-color: var(--modal-background-color); - .close { - @extend .button-tertiary; - position: absolute; - top: $s-8; - right: $s-8; - width: $s-28; - height: $s-32; - border-radius: $br-8; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } - } + max-width: $s-712; +} - .modal-title { - @include headlineMediumTypography; - margin-bottom: $s-16; - color: var(--modal-title-foreground-color); +.close-btn { + @extend .modal-close-btn-base; +} + +.close-icon { + @extend .button-icon; + stroke: var(--icon-foreground); +} + +.modal-title { + @include headlineMediumTypography; + margin-bottom: $s-16; + color: var(--modal-title-foreground-color); +} + +// Tabs content +.libraries-content, +.updates-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: $s-32; + padding-top: $s-24; + height: 100%; + max-height: $s-400; +} + +.section { + display: flex; + flex-direction: column; + height: calc(100% - $s-12); +} + +.title-spacing-lib { + margin: 0 0 0 calc(-1 * $s-8); +} + +.section-list, +.section-list-shared { + height: 100%; + max-height: $s-320; + margin-top: $s-12; + overflow: auto; +} + +.section-list-item { + display: grid; + grid-template-columns: 1fr auto; + column-gap: $s-12; + margin-bottom: $s-24; + &:last-child { + margin-bottom: $s-8; } } -.modal-content { - height: 100%; - .libraries-header { - height: 100%; +.item-name { + @include bodyLargeTypography; + color: var(--library-name-foreground-color); +} + +.item-publish, +.item-unpublish { + @extend .button-primary; + @include uppercaseTitleTipography; + height: $s-32; + min-width: $s-92; + padding: $s-8 $s-24; + border-radius: $br-8; +} + +.item-unpublish { + @extend .button-secondary; +} + +.item-button, +.item-button-shared { + @extend .button-secondary; + padding: $s-8 $s-24; + height: $s-32; + border-radius: $br-8; + margin-right: $s-2; + padding: $s-8; + width: $s-32; + margin-left: $s-8; + svg { + @extend .button-icon; + stroke: var(--icon-foreground); } - .libraries-content, - .updates-content { - display: grid; - grid-template-columns: 1fr 1fr; - gap: $s-32; - padding-top: $s-24; - height: 100%; - max-height: $s-400; - .section { - display: flex; - flex-direction: column; - height: calc(100% - $s-12); - .title-spacing-lib { - margin: 0 0 0 calc(-1 * $s-8); - } - .section-list, - .section-list-shared { - height: 100%; - max-height: $s-320; - margin-top: $s-12; - overflow: auto; - .section-list-item { - display: grid; - grid-template-columns: 1fr auto; - column-gap: $s-12; - margin-bottom: $s-24; - &:last-child { - margin-bottom: $s-8; - } - .item-name { - @include bodyLargeTypography; - color: var(--library-name-foreground-color); - } - .item-publish, - .item-unpublish { - @extend .button-primary; - @include uppercaseTitleTipography; - height: $s-32; - min-width: $s-92; - padding: $s-8 $s-24; - border-radius: $br-8; - } +} - .item-unpublish { - @extend .button-secondary; - } - .item-button, - .item-button-shared { - @extend .button-secondary; - padding: $s-8 $s-24; - height: $s-32; - border-radius: $br-8; - margin-right: $s-2; - padding: $s-8; - width: $s-32; - margin-left: $s-8; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } - } - - .item-button-icon { - width: $s-28; - height: $s-28; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } - } - } - } - .section-list-shared { - max-height: $s-272; - } - - .section-title { - @include bodyLargeTypography; - color: var(--modal-title-foreground-color); - margin-bottom: $s-12; - } - - .libraries-search { - margin: $s-12 0; - .search-icon { - @include flexCenter; - padding: 0 0 0 $s-8; - width: $s-20; - svg { - @extend .button-icon-small; - stroke: var(--icon-foreground); - } - } - } - .section-list-empty { - @include bodyLargeTypography; - @include flexCenter; - color: var(--empty-message-foreground-color); - - svg { - @extend .button-icon-small; - stroke: var(--icon-foreground); - width: $s-16; - height: $s-16; - } - } - } - - .libraries-updates-see-all { - direction: rtl; - grid-column: span 3; - margin-top: $s-8; - margin-right: $s-8; - & input { - @extend .link; - margin: 0; - } - } +.item-button-icon { + width: $s-28; + height: $s-28; + svg { + @extend .button-icon; + stroke: var(--icon-foreground); } - .updates-content { - grid-template-columns: 1fr; +} + +.section-list-shared { + max-height: $s-272; +} + +.section-title { + @include bodyLargeTypography; + color: var(--modal-title-foreground-color); + margin-bottom: $s-12; +} + +.libraries-search { + margin: $s-12 0; +} + +.search-icon { + @include flexCenter; + padding: 0 0 0 $s-8; + width: $s-20; + svg { + @extend .button-icon-small; + stroke: var(--icon-foreground); } } +.section-list-empty { + @include bodyLargeTypography; + @include flexCenter; + color: var(--empty-message-foreground-color); + + svg { + @extend .button-icon-small; + stroke: var(--icon-foreground); + width: $s-16; + height: $s-16; + } +} + +.libraries-updates-see-all { + direction: rtl; + grid-column: span 3; + margin-top: $s-8; + margin-right: $s-8; + & input { + @extend .link; + margin: 0; + } +} + +.updates-content { + grid-template-columns: 1fr; +} + .libraries-updates { display: grid; grid-column: span 3; @@ -182,43 +176,43 @@ grid-gap: $s-24; font-size: $fs-12; margin-top: $s-16; +} - .libraries-updates-item { - display: flex; - align-items: center; - color: var(--library-content-foreground-color); +.libraries-updates-item { + display: flex; + align-items: center; + color: var(--library-content-foreground-color); - &:not(:first-child) { - margin-top: $s-8; + &:not(:first-child) { + margin-top: $s-8; + } + + & svg { + background-color: var(--color-canvas); + border-radius: $br-4; + border: $s-2 solid transparent; + height: $s-24; + width: $s-24; + min-height: $s-24; + min-width: $s-24; + } + + & .name-block { + color: var(--gray-20-color); + margin-left: $s-8; + width: $s-168; + + &.ellipsis { + padding-left: calc($s-24 + #{$s-8}); } + } - & svg { - background-color: var(--color-canvas); - border-radius: $br-4; - border: $s-2 solid transparent; - height: $s-24; - width: $s-24; - min-height: $s-24; - min-width: $s-24; - } - - & .name-block { - color: var(--gray-20-color); - margin-left: $s-8; - width: $s-168; - - &.ellipsis { - padding-left: calc($s-24 + #{$s-8}); - } - } - - & .item-name { - display: block; - margin: 0; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } + & .item-name { + display: block; + margin: 0; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; } } @@ -264,55 +258,58 @@ display: flex; flex-direction: column; gap: $s-24; +} - .info-block { - display: grid; - grid-template-columns: auto 1fr; - column-gap: $s-20; - grid-template: - "icon title" - "icon content"; - } +.info-block { + display: grid; + grid-template-columns: auto 1fr; + column-gap: $s-20; + grid-template: + "icon title" + "icon content"; +} - .info-icon { - grid-area: icon; - width: $s-52; - height: $s-52; - margin-top: $s-8; - border-radius: $br-circle; - background: $db-quaternary; +.info-icon { + grid-area: icon; + width: $s-52; + height: $s-52; + margin-top: $s-8; + border-radius: $br-circle; + background: $db-quaternary; - display: flex; - justify-content: center; - align-items: center; + display: flex; + justify-content: center; + align-items: center; - svg { - width: $s-32; - height: $s-32; - fill: $da-primary; - } - } - .info-block-title { - grid-area: title; - font-size: $fs-16; - color: $df-primary; - } - .info-block-content { - grid-area: content; - font-size: $fs-14; - color: $df-secondary; - line-height: 1.2; + svg { + width: $s-32; + height: $s-32; + fill: $da-primary; } } +.info-block-title { + grid-area: title; + font-size: $fs-16; + color: $df-primary; +} + +.info-block-content { + grid-area: content; + font-size: $fs-14; + color: $df-secondary; + line-height: 1.2; +} + .info-bottom { margin-top: $s-24; margin-right: $s-8; display: flex; justify-content: flex-end; - .primary-button { - @extend .button-primary; - @include uppercaseTitleTipography; - padding: $s-0 $s-16; - } +} + +.primary-button { + @extend .button-primary; + @include uppercaseTitleTipography; + padding: $s-0 $s-16; } From 18fc08d4181a0af566b9eb158b69b112629335ff Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 13:17:39 +0100 Subject: [PATCH 100/136] :bug: Fix typographies in update modal --- .../styles/common/refactor/basic-rules.scss | 11 +++++++++-- .../src/app/main/ui/components/tab_container.scss | 2 +- frontend/src/app/main/ui/components/title_bar.scss | 2 +- frontend/src/app/main/ui/workspace/libraries.scss | 12 ++++++------ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss index 0a257da60..f057974d0 100644 --- a/frontend/resources/styles/common/refactor/basic-rules.scss +++ b/frontend/resources/styles/common/refactor/basic-rules.scss @@ -32,6 +32,12 @@ background: var(--text-editor-selection-background-color); color: var(--text-editor-selection-foreground-color); } + + ::placeholder, + ::-webkit-input-placeholder { + @include bodySmallTypography; + color: var(--input-placeholder-color); + } } // BUTTONS @@ -39,7 +45,7 @@ @include buttonStyle; @include flexCenter; @include focusPrimary; - @include uppercaseTitleTipography; + @include headlineSmallTypography; background-color: var(--button-primary-background-color-rest); border: $s-1 solid var(--button-primary-border-color-rest); color: var(--button-primary-foreground-color-rest); @@ -303,7 +309,7 @@ } .input-label { - @include uppercaseTitleTipography; + @include headlineSmallTypography; @include flexCenter; width: $s-20; padding-left: $s-8; @@ -401,6 +407,7 @@ background-color: var(--input-background-color); } ::placeholder { + @include bodySmallTypography; color: var(--input-placeholder-color); } &:hover { diff --git a/frontend/src/app/main/ui/components/tab_container.scss b/frontend/src/app/main/ui/components/tab_container.scss index 86ac4c4f3..7c9b08b52 100644 --- a/frontend/src/app/main/ui/components/tab_container.scss +++ b/frontend/src/app/main/ui/components/tab_container.scss @@ -28,7 +28,7 @@ width: 100%; .tab-container-tab-title { @include flexCenter; - @include uppercaseTitleTipography; + @include headlineSmallTypography; height: 100%; width: 100%; padding: 0 $s-8; diff --git a/frontend/src/app/main/ui/components/title_bar.scss b/frontend/src/app/main/ui/components/title_bar.scss index 43de2b42c..c6882c4e0 100644 --- a/frontend/src/app/main/ui/components/title_bar.scss +++ b/frontend/src/app/main/ui/components/title_bar.scss @@ -19,7 +19,7 @@ .title, .title-only, .inspect-title { - @include uppercaseTitleTipography; + @include headlineSmallTypography; display: grid; align-items: center; justify-content: flex-start; diff --git a/frontend/src/app/main/ui/workspace/libraries.scss b/frontend/src/app/main/ui/workspace/libraries.scss index 79c12bf94..761d47efa 100644 --- a/frontend/src/app/main/ui/workspace/libraries.scss +++ b/frontend/src/app/main/ui/workspace/libraries.scss @@ -6,7 +6,7 @@ @import "refactor/common-refactor.scss"; -// Library +// Library modal .modal-overlay { @extend .modal-overlay-base; } @@ -122,8 +122,8 @@ } .section-title { - @include bodyLargeTypography; - color: var(--modal-title-foreground-color); + @include headlineSmallTypography; + color: var(--title-foreground-color); margin-bottom: $s-12; } @@ -226,7 +226,7 @@ .item-update { @extend .button-primary; - @include uppercaseTitleTipography; + @include headlineSmallTypography; height: $s-32; min-width: $s-92; padding: $s-8 $s-24; @@ -238,7 +238,7 @@ } .item-contents { - @include bodyLargeTypography; + @include bodyMediumTypography; color: var(--library-content-foreground-color); display: flex; flex-wrap: wrap; @@ -310,6 +310,6 @@ .primary-button { @extend .button-primary; - @include uppercaseTitleTipography; + @include headlineSmallTypography; padding: $s-0 $s-16; } From 5f0b86e0df04b2c677566d4dbf0f6c699f1ee6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Wed, 13 Mar 2024 12:55:08 +0100 Subject: [PATCH 101/136] :bug: Fix file renaming input size --- frontend/src/app/main/ui/workspace/left_header.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/left_header.scss b/frontend/src/app/main/ui/workspace/left_header.scss index c6ebf454a..207101743 100644 --- a/frontend/src/app/main/ui/workspace/left_header.scss +++ b/frontend/src/app/main/ui/workspace/left_header.scss @@ -41,7 +41,6 @@ height: $s-16; width: 100%; padding-bottom: $s-2; - margin-top: calc(-1 * $s-2); color: var(--title-foreground-color); cursor: pointer; } @@ -54,10 +53,10 @@ .file-name-input { @include flexCenter; - height: 100%; width: 100%; margin: 0; border: 0; + padding: 0; border-radius: $br-4; background-color: var(--input-background-color); font-size: $fs-14; From a6f70c77cbe72875875ab83587d5dcd9cfc61e34 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 13 Mar 2024 16:21:12 +0100 Subject: [PATCH 102/136] Revert ":sparkles: Improve internal naming of setup/props" This reverts commit f525c6df5e9785df9b534b6de1b5308084627699. --- backend/src/app/auth/oidc.clj | 11 +++++----- backend/src/app/http.clj | 3 +-- backend/src/app/http/access_token.clj | 3 +-- backend/src/app/http/awsns.clj | 5 ++--- backend/src/app/http/client.clj | 4 ++-- backend/src/app/http/debug.clj | 3 +-- backend/src/app/http/session.clj | 5 ++--- backend/src/app/loggers/audit.clj | 13 ++++++------ backend/src/app/main.clj | 18 ++++++++-------- backend/src/app/rpc.clj | 5 ++--- backend/src/app/rpc/commands/access_token.clj | 5 ++--- backend/src/app/rpc/commands/auth.clj | 21 +++++++++---------- backend/src/app/rpc/commands/ldap.clj | 3 +-- backend/src/app/rpc/commands/profile.clj | 5 ++--- backend/src/app/rpc/commands/teams.clj | 5 ++--- backend/src/app/rpc/commands/verify_token.clj | 3 +-- backend/src/app/setup.clj | 9 ++++---- backend/src/app/tasks/telemetry.clj | 5 ++--- 18 files changed, 56 insertions(+), 70 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 34e2cee57..9e07a21e2 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -22,7 +22,6 @@ [app.loggers.audit :as audit] [app.main :as-alias main] [app.rpc.commands.profile :as profile] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.json :as json] [app.util.time :as dt] @@ -414,7 +413,7 @@ ::props])) (defn get-info - [{:keys [provider ::setup/props] :as cfg} {:keys [params] :as request}] + [{:keys [provider ::main/props] :as cfg} {:keys [params] :as request}] (when-let [error (get params :error)] (ex/raise :type :internal :code :error-on-retrieving-code @@ -509,7 +508,7 @@ (if profile (let [sxf (session/create-fn cfg (:id profile)) token (or (:invitation-token info) - (tokens/generate (::setup/props cfg) + (tokens/generate (::main/props cfg) {:iss :auth :exp (dt/in-future "15m") :profile-id (:id profile)})) @@ -537,7 +536,7 @@ :iss :prepared-register :is-active true :exp (dt/in-future {:hours 48})) - token (tokens/generate (::setup/props cfg) info) + token (tokens/generate (::main/props cfg) info) params (d/without-nils {:token token :fullname (:fullname info)}) @@ -552,7 +551,7 @@ (defn- auth-handler [cfg {:keys [params] :as request}] (let [props (audit/extract-utm-params params) - state (tokens/generate (::setup/props cfg) + state (tokens/generate (::main/props cfg) {:iss :oauth :invitation-token (:invitation-token params) :props props @@ -619,7 +618,7 @@ [_] (s/keys :req [::session/manager ::http/client - ::setup/props + ::main/props ::db/pool ::providers])) diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index a696d5477..1e605cdb0 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -23,7 +23,6 @@ [app.metrics :as mtx] [app.rpc :as-alias rpc] [app.rpc.doc :as-alias rpc.doc] - [app.setup :as-alias setup] [clojure.spec.alpha :as s] [integrant.core :as ig] [promesa.exec :as px] @@ -137,7 +136,7 @@ ::rpc/routes ::rpc.doc/routes ::oidc/routes - ::setup/props + ::main/props ::assets/routes ::debug/routes ::db/pool diff --git a/backend/src/app/http/access_token.clj b/backend/src/app/http/access_token.clj index 0d1865f10..bfddbb42d 100644 --- a/backend/src/app/http/access_token.clj +++ b/backend/src/app/http/access_token.clj @@ -10,7 +10,6 @@ [app.config :as cf] [app.db :as db] [app.main :as-alias main] - [app.setup :as-alias setup] [app.tokens :as tokens] [ring.request :as rreq])) @@ -43,7 +42,7 @@ (defn- wrap-soft-auth "Soft Authentication, will be executed synchronously on the undertow worker thread." - [handler {:keys [::setup/props]}] + [handler {:keys [::main/props]}] (letfn [(handle-request [request] (try (let [token (get-token request) diff --git a/backend/src/app/http/awsns.clj b/backend/src/app/http/awsns.clj index 88060bb20..7508be8a2 100644 --- a/backend/src/app/http/awsns.clj +++ b/backend/src/app/http/awsns.clj @@ -13,7 +13,6 @@ [app.db.sql :as sql] [app.http.client :as http] [app.main :as-alias main] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.worker :as-alias wrk] [clojure.spec.alpha :as s] @@ -31,7 +30,7 @@ (defmethod ig/pre-init-spec ::routes [_] (s/keys :req [::http/client - ::setup/props + ::main/props ::db/pool])) (defmethod ig/init-key ::routes @@ -107,7 +106,7 @@ [cfg headers] (let [tdata (get headers "x-penpot-data")] (when-not (str/empty? tdata) - (let [result (tokens/verify (::setup/props cfg) {:token tdata :iss :profile-identity})] + (let [result (tokens/verify (::main/props cfg) {:token tdata :iss :profile-identity})] (:profile-id result))))) (defn- parse-notification diff --git a/backend/src/app/http/client.clj b/backend/src/app/http/client.clj index 9ef4cc4b2..5b4a8541c 100644 --- a/backend/src/app/http/client.clj +++ b/backend/src/app/http/client.clj @@ -55,8 +55,8 @@ convention." ([cfg-or-client request] (let [client (resolve-client cfg-or-client)] - (send! client request {:sync? true}))) + (send! client request {}))) ([cfg-or-client request options] (let [client (resolve-client cfg-or-client)] - (send! client request (merge {:sync? true} options))))) + (send! client request options)))) diff --git a/backend/src/app/http/debug.clj b/backend/src/app/http/debug.clj index a453c6872..1d2a129cf 100644 --- a/backend/src/app/http/debug.clj +++ b/backend/src/app/http/debug.clj @@ -20,7 +20,6 @@ [app.rpc.commands.auth :as auth] [app.rpc.commands.files-create :refer [create-file]] [app.rpc.commands.profile :as profile] - [app.setup :as-alias setup] [app.srepl.helpers :as srepl] [app.storage :as-alias sto] [app.storage.tmp :as tmp] @@ -341,7 +340,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn- resend-email-notification - [{:keys [::db/pool ::setup/props] :as cfg} {:keys [params] :as request}] + [{:keys [::db/pool ::main/props] :as cfg} {:keys [params] :as request}] (when-not (contains? params :force) (ex/raise :type :validation diff --git a/backend/src/app/http/session.clj b/backend/src/app/http/session.clj index c4a3f0ba6..7ff6dfa01 100644 --- a/backend/src/app/http/session.clj +++ b/backend/src/app/http/session.clj @@ -15,7 +15,6 @@ [app.db.sql :as sql] [app.http.session.tasks :as-alias tasks] [app.main :as-alias main] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.time :as dt] [clojure.spec.alpha :as s] @@ -139,7 +138,7 @@ (declare ^:private gen-token) (defn create-fn - [{:keys [::manager ::setup/props]} profile-id] + [{:keys [::manager ::main/props]} profile-id] (us/assert! ::manager manager) (us/assert! ::us/uuid profile-id) @@ -197,7 +196,7 @@ (neg? (compare default-renewal-max-age elapsed))))) (defn- wrap-soft-auth - [handler {:keys [::manager ::setup/props]}] + [handler {:keys [::manager ::main/props]}] (us/assert! ::manager manager) (letfn [(handle-request [request] (try diff --git a/backend/src/app/loggers/audit.clj b/backend/src/app/loggers/audit.clj index aead09110..45c36334a 100644 --- a/backend/src/app/loggers/audit.clj +++ b/backend/src/app/loggers/audit.clj @@ -24,7 +24,6 @@ [app.main :as-alias main] [app.rpc :as-alias rpc] [app.rpc.retry :as rtry] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as-alias sv] [app.util.time :as dt] @@ -262,7 +261,7 @@ (s/def ::tasks/uri ::us/string) (defmethod ig/pre-init-spec ::tasks/archive-task [_] - (s/keys :req [::db/pool ::setup/props ::http.client/client])) + (s/keys :req [::db/pool ::main/props ::http.client/client])) (defmethod ig/init-key ::tasks/archive [_ cfg] @@ -288,7 +287,7 @@ (px/sleep 100) (recur (+ total ^long n))) (when (pos? total) - (l/dbg :hint "events archived" :total total))))))))) + (l/debug :hint "events archived" :total total))))))))) (def ^:private sql:retrieve-batch-of-audit-log "select * @@ -323,7 +322,7 @@ :context])) (send [events] - (let [token (tokens/generate (::setup/props cfg) + (let [token (tokens/generate (::main/props cfg) {:iss "authentication" :iat (dt/now) :uid uuid/zero}) @@ -332,11 +331,11 @@ "origin" (cf/get :public-uri) "cookie" (u/map->query-string {:auth-token token})} params {:uri uri - :timeout 12000 + :timeout 6000 :method :post :headers headers :body body} - resp (http.client/req! cfg params)] + resp (http.client/req! cfg params {:sync? true})] (if (= (:status resp) 204) true (do @@ -356,7 +355,7 @@ (map row->event)) events (into [] xform rows)] (when-not (empty? events) - (l/trc :hint "archive events chunk" :uri uri :events (count events)) + (l/trace :hint "archive events chunk" :uri uri :events (count events)) (when (send events) (mark-as-archived conn rows) (count events))))))) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index e0177110f..47e43f5cf 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -221,7 +221,7 @@ {::db/pool (ig/ref ::db/pool)} ::http.awsns/routes - {::setup/props (ig/ref ::setup/props) + {::props (ig/ref ::setup/props) ::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client)} @@ -262,7 +262,7 @@ ::oidc/routes {::http.client/client (ig/ref ::http.client/client) ::db/pool (ig/ref ::db/pool) - ::setup/props (ig/ref ::setup/props) + ::props (ig/ref ::setup/props) ::oidc/providers {:google (ig/ref ::oidc.providers/google) :github (ig/ref ::oidc.providers/github) :gitlab (ig/ref ::oidc.providers/gitlab) @@ -274,7 +274,7 @@ ::db/pool (ig/ref ::db/pool) ::rpc/routes (ig/ref ::rpc/routes) ::rpc.doc/routes (ig/ref ::rpc.doc/routes) - ::setup/props (ig/ref ::setup/props) + ::props (ig/ref ::setup/props) ::mtx/routes (ig/ref ::mtx/routes) ::oidc/routes (ig/ref ::oidc/routes) ::http.debug/routes (ig/ref ::http.debug/routes) @@ -286,7 +286,7 @@ {::db/pool (ig/ref ::db/pool) ::session/manager (ig/ref ::session/manager) ::sto/storage (ig/ref ::sto/storage) - ::setup/props (ig/ref ::setup/props)} + ::props (ig/ref ::setup/props)} ::http.ws/routes {::db/pool (ig/ref ::db/pool) @@ -322,7 +322,7 @@ ::rpc/climit (ig/ref ::rpc/climit) ::rpc/rlimit (ig/ref ::rpc/rlimit) ::setup/templates (ig/ref ::setup/templates) - ::setup/props (ig/ref ::setup/props)} + ::props (ig/ref ::setup/props)} :app.rpc.doc/routes {:methods (ig/ref :app.rpc/methods)} @@ -331,7 +331,7 @@ {::rpc/methods (ig/ref :app.rpc/methods) ::db/pool (ig/ref ::db/pool) ::session/manager (ig/ref ::session/manager) - ::setup/props (ig/ref ::setup/props)} + ::props (ig/ref ::setup/props)} ::wrk/registry {::mtx/metrics (ig/ref ::mtx/metrics) @@ -388,7 +388,7 @@ :app.tasks.telemetry/handler {::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client) - ::setup/props (ig/ref ::setup/props)} + ::props (ig/ref ::setup/props)} [::srepl/urepl ::srepl/server] {::srepl/port (cf/get :urepl-port 6062) @@ -402,7 +402,7 @@ ::setup/props {::db/pool (ig/ref ::db/pool) - ::setup/key (cf/get :secret-key) + ::key (cf/get :secret-key) ;; NOTE: this dependency is only necessary for proper initialization ordering, props ;; module requires the migrations to run before initialize. @@ -412,7 +412,7 @@ {} ::audit.tasks/archive - {::setup/props (ig/ref ::setup/props) + {::props (ig/ref ::setup/props) ::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client)} diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index ea49b6b70..8ae7a38d6 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -27,7 +27,6 @@ [app.rpc.helpers :as rph] [app.rpc.retry :as retry] [app.rpc.rlimit :as rlimit] - [app.setup :as-alias setup] [app.storage :as-alias sto] [app.util.services :as sv] [app.util.time :as dt] @@ -249,7 +248,7 @@ ::ldap/provider ::sto/storage ::mtx/metrics - ::setup/props] + ::main/props] :opt [::climit ::rlimit])) @@ -266,7 +265,7 @@ (defmethod ig/pre-init-spec ::routes [_] (s/keys :req [::methods ::db/pool - ::setup/props + ::main/props ::session/manager])) (defmethod ig/init-key ::routes diff --git a/backend/src/app/rpc/commands/access_token.clj b/backend/src/app/rpc/commands/access_token.clj index 06a6e516c..dd10f3371 100644 --- a/backend/src/app/rpc/commands/access_token.clj +++ b/backend/src/app/rpc/commands/access_token.clj @@ -13,7 +13,6 @@ [app.rpc :as-alias rpc] [app.rpc.doc :as-alias doc] [app.rpc.quotes :as quotes] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] @@ -24,7 +23,7 @@ (dissoc row :perms)) (defn create-access-token - [{:keys [::db/conn ::setup/props]} profile-id name expiration] + [{:keys [::db/conn ::main/props]} profile-id name expiration] (let [created-at (dt/now) token-id (uuid/next) token (tokens/generate props {:iss "access-token" @@ -48,7 +47,7 @@ [{:keys [::db/pool] :as system} profile-id name expiration] (db/with-atomic [conn pool] (let [props (:app.setup/props system)] - (create-access-token {::db/conn conn ::setup/props props} + (create-access-token {::db/conn conn ::main/props props} profile-id name expiration)))) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index e87979007..8e9671e59 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -26,7 +26,6 @@ [app.rpc.commands.teams :as teams] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] @@ -89,7 +88,7 @@ (profile/strip-private-attrs)) invitation (when-let [token (:invitation-token params)] - (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation})) + (tokens/verify (::main/props cfg) {:token token :iss :team-invitation})) ;; If invitation member-id does not matches the profile-id, we just proceed to ignore the ;; invitation because invitations matches exactly; and user can't login with other email and @@ -134,7 +133,7 @@ (defn recover-profile [{:keys [::db/pool] :as cfg} {:keys [token password]}] (letfn [(validate-token [token] - (let [tdata (tokens/verify (::setup/props cfg) {:token token :iss :password-recovery})] + (let [tdata (tokens/verify (::main/props cfg) {:token token :iss :password-recovery})] (:profile-id tdata))) (update-password [conn profile-id] @@ -171,7 +170,7 @@ :code :registration-disabled))) (when (contains? params :invitation-token) - (let [invitation (tokens/verify (::setup/props cfg) {:token (:invitation-token params) :iss :team-invitation})] + (let [invitation (tokens/verify (::main/props cfg) {:token (:invitation-token params) :iss :team-invitation})] (when-not (= (:email params) (:member-email invitation)) (ex/raise :type :restriction :code :email-does-not-match-invitation @@ -234,7 +233,7 @@ params (d/without-nils params) - token (tokens/generate (::setup/props cfg) params)] + token (tokens/generate (::main/props cfg) params)] (with-meta {:token token} {::audit/profile-id uuid/zero}))) @@ -341,7 +340,7 @@ (defn register-profile [{:keys [::db/conn] :as cfg} {:keys [token fullname] :as params}] - (let [claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register}) + (let [claims (tokens/verify (::main/props cfg) {:token token :iss :prepared-register}) params (-> claims (into params) (assoc :fullname fullname)) @@ -358,7 +357,7 @@ (create-profile-rels! conn)))) invitation (when-let [token (:invitation-token params)] - (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))] + (tokens/verify (::main/props cfg) {:token token :iss :team-invitation}))] ;; If profile is filled in claims, means it tries to register ;; again, so we proceed to update the modified-at attr @@ -378,7 +377,7 @@ ;; email. (and (some? invitation) (= (:email profile) (:member-email invitation))) (let [claims (assoc invitation :member-id (:id profile)) - token (tokens/generate (::setup/props cfg) claims) + token (tokens/generate (::main/props cfg) claims) resp {:invitation-token token}] (-> resp (rph/with-transform (session/create-fn cfg (:id profile))) @@ -405,7 +404,7 @@ ;; In all other cases, send a verification email. :else (do - (send-email-verification! conn (::setup/props cfg) profile) + (send-email-verification! conn (::main/props cfg) profile) (rph/with-meta profile {::audit/replace-props (audit/profile->props profile) ::audit/profile-id (:id profile)}))))) @@ -430,14 +429,14 @@ (defn request-profile-recovery [{:keys [::db/pool] :as cfg} {:keys [email] :as params}] (letfn [(create-recovery-token [{:keys [id] :as profile}] - (let [token (tokens/generate (::setup/props cfg) + (let [token (tokens/generate (::main/props cfg) {:iss :password-recovery :exp (dt/in-future "15m") :profile-id id})] (assoc profile :token token))) (send-email-notification [conn profile] - (let [ptoken (tokens/generate (::setup/props cfg) + (let [ptoken (tokens/generate (::main/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})] diff --git a/backend/src/app/rpc/commands/ldap.clj b/backend/src/app/rpc/commands/ldap.clj index 780f0e100..bb86aec90 100644 --- a/backend/src/app/rpc/commands/ldap.clj +++ b/backend/src/app/rpc/commands/ldap.clj @@ -18,7 +18,6 @@ [app.rpc.commands.profile :as profile] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [clojure.spec.alpha :as s])) @@ -41,7 +40,7 @@ {::rpc/auth false ::doc/added "1.15" ::doc/module :auth} - [{:keys [::setup/props ::ldap/provider] :as cfg} params] + [{:keys [::main/props ::ldap/provider] :as cfg} params] (when-not provider (ex/raise :type :restriction :code :ldap-not-initialized diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index ccb6a8b2e..6ef2ef90d 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -23,7 +23,6 @@ [app.rpc.climit :as climit] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] - [app.setup :as-alias setup] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] @@ -297,12 +296,12 @@ (defn- request-email-change! [{:keys [::conn] :as cfg} {:keys [profile email] :as params}] - (let [token (tokens/generate (::setup/props cfg) + (let [token (tokens/generate (::main/props cfg) {:iss :change-email :exp (dt/in-future "15m") :profile-id (:id profile) :email email}) - ptoken (tokens/generate (::setup/props cfg) + ptoken (tokens/generate (::main/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})] diff --git a/backend/src/app/rpc/commands/teams.clj b/backend/src/app/rpc/commands/teams.clj index f62f8bc6a..4b5f07700 100644 --- a/backend/src/app/rpc/commands/teams.clj +++ b/backend/src/app/rpc/commands/teams.clj @@ -26,7 +26,6 @@ [app.rpc.helpers :as rph] [app.rpc.permissions :as perms] [app.rpc.quotes :as quotes] - [app.setup :as-alias setup] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] @@ -692,7 +691,7 @@ (defn- create-invitation-token [cfg {:keys [profile-id valid-until team-id member-id member-email role]}] - (tokens/generate (::setup/props cfg) + (tokens/generate (::main/props cfg) {:iss :team-invitation :exp valid-until :profile-id profile-id @@ -703,7 +702,7 @@ (defn- create-profile-identity-token [cfg profile] - (tokens/generate (::setup/props cfg) + (tokens/generate (::main/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})) diff --git a/backend/src/app/rpc/commands/verify_token.clj b/backend/src/app/rpc/commands/verify_token.clj index e072c90d6..49c76c110 100644 --- a/backend/src/app/rpc/commands/verify_token.clj +++ b/backend/src/app/rpc/commands/verify_token.clj @@ -18,7 +18,6 @@ [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] [app.rpc.quotes :as quotes] - [app.setup :as-alias setup] [app.tokens :as tokens] [app.tokens.spec.team-invitation :as-alias spec.team-invitation] [app.util.services :as sv] @@ -39,7 +38,7 @@ ::doc/module :auth} [{:keys [::db/pool] :as cfg} {:keys [token] :as params}] (db/with-atomic [conn pool] - (let [claims (tokens/verify (::setup/props cfg) {:token token}) + (let [claims (tokens/verify (::main/props cfg) {:token token}) cfg (assoc cfg :conn conn)] (process-token cfg params claims)))) diff --git a/backend/src/app/setup.clj b/backend/src/app/setup.clj index d187f3e5f..8e889e2b4 100644 --- a/backend/src/app/setup.clj +++ b/backend/src/app/setup.clj @@ -50,15 +50,16 @@ :cause cause)))) instance-id))) -(s/def ::key ::us/string) -(s/def ::props (s/map-of ::us/keyword some?)) +(s/def ::main/key ::us/string) +(s/def ::main/props + (s/map-of ::us/keyword some?)) (defmethod ig/pre-init-spec ::props [_] (s/keys :req [::db/pool] - :opt [::key])) + :opt [::main/key])) (defmethod ig/init-key ::props - [_ {:keys [::db/pool ::key] :as cfg}] + [_ {:keys [::db/pool ::main/key] :as cfg}] (db/with-atomic [conn pool] (db/xact-lock! conn 0) (when-not key diff --git a/backend/src/app/tasks/telemetry.clj b/backend/src/app/tasks/telemetry.clj index 43c0b26f9..d040a08f9 100644 --- a/backend/src/app/tasks/telemetry.clj +++ b/backend/src/app/tasks/telemetry.clj @@ -15,7 +15,6 @@ [app.db :as db] [app.http.client :as http] [app.main :as-alias main] - [app.setup :as-alias setup] [app.util.json :as json] [clojure.spec.alpha :as s] [integrant.core :as ig] @@ -33,10 +32,10 @@ (defmethod ig/pre-init-spec ::handler [_] (s/keys :req [::http/client ::db/pool - ::setup/props])) + ::main/props])) (defmethod ig/init-key ::handler - [_ {:keys [::db/pool ::setup/props] :as cfg}] + [_ {:keys [::db/pool ::main/props] :as cfg}] (fn [{:keys [send? enabled?] :or {send? true enabled? false}}] (let [subs {:newsletter-updates (get-subscriptions-newsletter-updates pool) :newsletter-news (get-subscriptions-newsletter-news pool)} From 2a998a2dcc3479d7d4b29bbe34626afa9f11f234 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 13 Mar 2024 13:29:50 +0100 Subject: [PATCH 103/136] :bug: Fix problem when expanding components tab --- frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 888143fdb..4c6fa807c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs @@ -142,7 +142,7 @@ on-collapsed (mf/use-fn - (mf/deps file-id section open?) + (mf/deps file-id section open? assets-count) (fn [_] (when (< 0 assets-count) (st/emit! (dw/set-assets-section-open file-id section (not open?)))))) From c47fe2954a739a1a75dc3a5aed214cedb5037e44 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 13 Mar 2024 13:34:01 +0100 Subject: [PATCH 104/136] :bug: Fix problem with typography sample --- .../app/main/ui/workspace/sidebar/options/menus/typography.cljs | 1 + 1 file changed, 1 insertion(+) 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 0d7977266..44d3de561 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 @@ -441,6 +441,7 @@ [{:keys [visible? typography editable? name-input-ref on-close on-change on-name-blur local? navigate-to-library on-key-down]}] (let [ref (mf/use-ref nil) font-data (fonts/get-font-data (:font-id typography))] + (fonts/ensure-loaded! (:font-id typography)) (mf/use-effect (mf/deps visible?) From b00b77895f7bf64b35b2a697abbf3f9bdf781c03 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 13 Mar 2024 14:07:36 +0100 Subject: [PATCH 105/136] :bug: Fix comment number in sidebar --- frontend/src/app/main/data/comments.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index ce8e1bd6d..5762229d4 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -274,7 +274,9 @@ (ptk/reify ::delete-comment ptk/UpdateEvent (update [_ state] - (d/update-in-when state [:comments thread-id] dissoc id)) + (-> state + (d/update-in-when [:comments thread-id] dissoc id) + (d/update-in-when [:comment-threads thread-id :count-comments] dec))) ptk/WatchEvent (watch [_ state _] From 04a69c2a2cbc363c4a64450e0f2f7e7d6d8b130d Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 16:41:53 +0100 Subject: [PATCH 106/136] :bug: Fix update modal spacing --- .../styles/common/refactor/mixins.scss | 2 +- .../src/app/main/ui/workspace/libraries.cljs | 56 +++-- .../src/app/main/ui/workspace/libraries.scss | 222 +++++++++--------- frontend/translations/es.po | 2 +- 4 files changed, 151 insertions(+), 131 deletions(-) diff --git a/frontend/resources/styles/common/refactor/mixins.scss b/frontend/resources/styles/common/refactor/mixins.scss index 60f2f1e3d..992380e57 100644 --- a/frontend/resources/styles/common/refactor/mixins.scss +++ b/frontend/resources/styles/common/refactor/mixins.scss @@ -116,11 +116,11 @@ } @mixin textEllipsis { + display: block; max-width: 99%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - display: block; } @mixin twoLineTextEllipsis { diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index 4cf953ae8..564093850 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -37,6 +37,15 @@ (def ^:private close-icon (i/icon-xref :close (stl/css :close-icon))) +(def ^:private add-icon + (i/icon-xref :add (stl/css :add-icon))) + +(def ^:private detach-icon + (i/icon-xref :detach (stl/css :detach-icon))) + +(def ^:private library-icon + (i/icon-xref :library (stl/css :library-icon))) + (def ref:workspace-file (l/derived :workspace-file st/state)) @@ -189,14 +198,14 @@ :count-libraries 1}))))] [:div {:class (stl/css :libraries-content)} - [:div {:class (stl/css :section)} + [:div {:class (stl/css :lib-section)} [:& title-bar {:collapsable false :title (tr "workspace.libraries.in-this-file") :class (stl/css :title-spacing-lib)}] [:div {:class (stl/css :section-list)} [:div {:class (stl/css :section-list-item)} - [:div + [:div {:class (stl/css :item-content)} [:div {:class (stl/css :item-name)} (tr "workspace.libraries.file-library")] [:ul {:class (stl/css :item-contents)} [:& describe-library-blocks {:components-count (count components) @@ -216,7 +225,7 @@ (for [{:keys [id name] :as library} linked-libraries] [:div {:class (stl/css :section-list-item) :key (dm/str id)} - [:div + [:div {:class (stl/css :item-content)} [:div {:class (stl/css :item-name)} name] [:ul {:class (stl/css :item-contents)} (let [components-count (count (or (ctkl/components-seq (:data library)) [])) @@ -232,24 +241,23 @@ :type "button" :data-library-id (dm/str id) :on-click unlink-library} - i/detach]])]] + detach-icon]])]] - [:div {:class (stl/css :section)} + [:div {:class (stl/css :shared-section)} [:& title-bar {:collapsable false :title (tr "workspace.libraries.shared-libraries") :class (stl/css :title-spacing-lib)}] - [:div {:class (stl/css :libraries-search)} - [:& search-bar {:on-change change-search-term - :value search-term - :placeholder (tr "workspace.libraries.search-shared-libraries") - :icon (mf/html [:span {:class (stl/css :search-icon)} i/search])}]] + [:& search-bar {:on-change change-search-term + :value search-term + :placeholder (tr "workspace.libraries.search-shared-libraries") + :icon (mf/html [:span {:class (stl/css :search-icon)} i/search])}] (if (seq shared-libraries) [:div {:class (stl/css :section-list-shared)} (for [{:keys [id name] :as library} shared-libraries] [:div {:class (stl/css :section-list-item) :key (dm/str id)} - [:div + [:div {:class (stl/css :item-content)} [:div {:class (stl/css :item-name)} name] [:ul {:class (stl/css :item-contents)} (let [components-count (dm/get-in library [:library-summary :components :count] 0) @@ -263,7 +271,7 @@ [:button {:class (stl/css :item-button-shared) :data-library-id (dm/str id) :on-click link-library} - i/add]])] + add-icon]])] (when (empty? shared-libraries) [:div {:class (stl/css :section-list-empty)} @@ -272,7 +280,10 @@ (tr "workspace.libraries.loading") (str/empty? search-term) - (tr "workspace.libraries.no-shared-libraries-available") + [:* + [:span {:class (stl/css :empty-state-icon)} + library-icon] + (tr "workspace.libraries.no-shared-libraries-available")] :else (tr "workspace.libraries.no-matches-for" search-term))]))]])) @@ -351,9 +362,11 @@ (dwl/sync-file file-id library-id))))))] [:div {:class (stl/css :updates-content)} - [:div {:class (stl/css :section)} + [:div {:class (stl/css :update-section)} (if (empty? libs-assets) [:div {:class (stl/css :section-list-empty)} + [:span {:class (stl/css :empty-state-icon)} + library-icon] (tr "workspace.libraries.no-libraries-need-sync")] [:* [:div {:class (stl/css :section-title)} (tr "workspace.libraries.library-updates")] @@ -364,7 +377,7 @@ {:keys [components colors typographies]}] libs-assets] [:div {:class (stl/css :section-list-item) :key (dm/str id)} - [:div + [:div {:class (stl/css :item-content)} [:div {:class (stl/css :item-name)} name] [:ul {:class (stl/css :item-contents)} (describe-library (count components) @@ -388,6 +401,7 @@ root-shape (ctf/get-component-root (:data library) component)] [:* [:& component-svg {:root-shape root-shape + :class (stl/css :component-svg) :objects (:objects component)}] [:div {:class (stl/css :name-block)} [:span {:class (stl/css :item-name) @@ -396,7 +410,7 @@ (when (:components exceeded) [:div {:class (stl/css :libraries-updates-item) :key (uuid/next)} - [:div {:class (stl/css :name-block.ellipsis)} + [:div {:class (stl/css :name-block :ellipsis)} [:span {:class (stl/css :item-name)} "(...)"]]])]) (when-not (empty? colors) @@ -448,10 +462,9 @@ (when (or (pos? (:components exceeded)) (pos? (:colors exceeded)) (pos? (:typographies exceeded))) - [:div {:class (stl/css :libraries-updates-see-all)} - [:& lb/link-button {:on-click see-all-assets - :value (str "(" (tr "workspace.libraries.update.see-all-changes") ")")}]])])]])]])) - + [:& lb/link-button {:on-click see-all-assets + :class (stl/css :libraries-updates-see-all) + :value (str "(" (tr "workspace.libraries.update.see-all-changes") ")")}])])]])]])) (mf/defc libraries-dialog {::mf/register modal/components ::mf/register-as :libraries-dialog} @@ -525,7 +538,8 @@ [:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-dialog :modal-v2-info)} - [:div {:class (stl/css :modal-title)} "IMPORTANT INFORMATION ABOUT NEW COMPONENTS"] + [:div {:class (stl/css :modal-v2-title)} + "IMPORTANT INFORMATION ABOUT NEW COMPONENTS"] [:div {:class (stl/css :modal-content)} [:div {:class (stl/css :info-content)} [:div {:class (stl/css :info-block)} diff --git a/frontend/src/app/main/ui/workspace/libraries.scss b/frontend/src/app/main/ui/workspace/libraries.scss index 761d47efa..6c430b0d8 100644 --- a/frontend/src/app/main/ui/workspace/libraries.scss +++ b/frontend/src/app/main/ui/workspace/libraries.scss @@ -13,6 +13,8 @@ .modal-dialog { @extend .modal-container-base; + display: grid; + grid-template-rows: auto 1fr; height: $s-520; max-height: $s-520; width: $s-712; @@ -30,7 +32,7 @@ .modal-title { @include headlineMediumTypography; - margin-bottom: $s-16; + margin-block-end: $s-16; color: var(--modal-title-foreground-color); } @@ -40,15 +42,20 @@ display: grid; grid-template-columns: 1fr 1fr; gap: $s-32; - padding-top: $s-24; - height: 100%; max-height: $s-400; + padding-block-start: $s-16; } -.section { - display: flex; - flex-direction: column; - height: calc(100% - $s-12); +.lib-section, +.update-section, +.shared-section { + display: grid; + grid-template-rows: auto 1fr; + gap: $s-8; +} + +.shared-section { + grid-template-rows: auto auto 1fr; } .title-spacing-lib { @@ -57,20 +64,21 @@ .section-list, .section-list-shared { - height: 100%; + display: grid; + grid-auto-rows: min-content; + gap: $s-8; max-height: $s-320; - margin-top: $s-12; - overflow: auto; + overflow-y: auto; } .section-list-item { display: grid; grid-template-columns: 1fr auto; - column-gap: $s-12; - margin-bottom: $s-24; - &:last-child { - margin-bottom: $s-8; - } + gap: $s-8; +} + +.item-content { + height: fit-content; } .item-name { @@ -85,6 +93,7 @@ height: $s-32; min-width: $s-92; padding: $s-8 $s-24; + margin: 0; border-radius: $br-8; } @@ -95,26 +104,17 @@ .item-button, .item-button-shared { @extend .button-secondary; - padding: $s-8 $s-24; height: $s-32; - border-radius: $br-8; - margin-right: $s-2; - padding: $s-8; width: $s-32; - margin-left: $s-8; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } + margin-inline-start: $s-2; + margin-inline-end: $s-8; + padding: $s-8; } -.item-button-icon { - width: $s-28; - height: $s-28; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } +.detach-icon, +.add-icon { + @extend .button-icon; + stroke: var(--icon-foreground); } .section-list-shared { @@ -123,46 +123,56 @@ .section-title { @include headlineSmallTypography; + margin-block-end: $s-12; color: var(--title-foreground-color); - margin-bottom: $s-12; -} - -.libraries-search { - margin: $s-12 0; } .search-icon { @include flexCenter; - padding: 0 0 0 $s-8; width: $s-20; + padding: 0 0 0 $s-8; svg { @extend .button-icon-small; stroke: var(--icon-foreground); } } +// empty state .section-list-empty { - @include bodyLargeTypography; - @include flexCenter; - color: var(--empty-message-foreground-color); - - svg { - @extend .button-icon-small; - stroke: var(--icon-foreground); - width: $s-16; - height: $s-16; - } + @include bodyMediumTypography; + display: grid; + grid-template-rows: auto 1fr; + justify-items: center; + gap: $s-8; + text-align: center; + height: fit-content; + margin-block: $s-16; + color: var(--modal-title-foreground-color); } +.empty-state-icon { + @include flexCenter; + width: $s-48; + height: $s-48; + border-radius: $br-circle; + background-color: var(--pill-background-color); +} + +.library-icon { + @extend .button-icon; + stroke: var(--icon-foreground); + height: $s-32; + width: $s-32; +} + +// Update library tab .libraries-updates-see-all { + @extend .link; direction: rtl; grid-column: span 3; - margin-top: $s-8; - margin-right: $s-8; - & input { - @extend .link; - margin: 0; - } + margin-block-start: $s-8; + margin-inline-start: $s-8; + margin: 0; } .updates-content { @@ -173,55 +183,41 @@ display: grid; grid-column: span 3; grid-template-columns: repeat(auto-fill, minmax($s-160, 1fr)); - grid-gap: $s-24; - font-size: $fs-12; - margin-top: $s-16; + gap: $s-24; + margin-block-start: $s-16; } .libraries-updates-item { - display: flex; - align-items: center; + @include bodyLargeTypography; + display: grid; + grid-template-columns: auto 1fr; + align-items: start; + gap: $s-8; color: var(--library-content-foreground-color); - - &:not(:first-child) { - margin-top: $s-8; - } - - & svg { - background-color: var(--color-canvas); - border-radius: $br-4; - border: $s-2 solid transparent; - height: $s-24; - width: $s-24; - min-height: $s-24; - min-width: $s-24; - } - - & .name-block { - color: var(--gray-20-color); - margin-left: $s-8; - width: $s-168; - - &.ellipsis { - padding-left: calc($s-24 + #{$s-8}); - } - } - - & .item-name { - display: block; - margin: 0; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } } -.modal-v2-info { - width: $s-664; - height: fit-content; - .modal-title { - font-size: $fs-18; - } +.component-svg { + background-color: var(--color-canvas); + border-radius: $br-4; + border: $s-2 solid transparent; + height: $s-24; + width: $s-24; + min-height: $s-24; + min-width: $s-24; +} + +.name-block { + color: var(--library-content-foreground-color); + width: $s-168; +} + +.ellipsis { + padding-inline-start: calc($s-24 + #{$s-8}); +} + +.item-name { + @include textEllipsis; + margin: 0; } .item-update { @@ -230,8 +226,8 @@ height: $s-32; min-width: $s-92; padding: $s-8 $s-24; + margin-inline-end: $s-2; border-radius: $br-8; - margin-right: $s-2; &:disabled { @extend .button-disabled; } @@ -242,6 +238,7 @@ color: var(--library-content-foreground-color); display: flex; flex-wrap: wrap; + margin: 0; } .element-count { @@ -253,10 +250,21 @@ } } +// Modal Component v2 update +.modal-v2-info { + width: $s-664; + height: fit-content; +} + +.modal-v2-title { + @include headlineMediumTypography; + color: var(--modal-title-foreground-color); +} + .info-content { + display: grid; + grid-template-rows: repeat(4, 1fr); margin-top: $s-32; - display: flex; - flex-direction: column; gap: $s-24; } @@ -276,7 +284,6 @@ margin-top: $s-8; border-radius: $br-circle; background: $db-quaternary; - display: flex; justify-content: center; align-items: center; @@ -284,28 +291,27 @@ svg { width: $s-32; height: $s-32; - fill: $da-primary; + fill: var(--icon-foreground-active); } } .info-block-title { + @include bodyLargeTypography; grid-area: title; - font-size: $fs-16; - color: $df-primary; + color: var(--modal-title-foreground-color); } .info-block-content { + @include bodyMediumTypography; grid-area: content; - font-size: $fs-14; - color: $df-secondary; - line-height: 1.2; + color: var(--library-content-foreground-color); } .info-bottom { - margin-top: $s-24; - margin-right: $s-8; display: flex; justify-content: flex-end; + margin-block-start: $s-24; + margin-inline-end: $s-8; } .primary-button { diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 7656b949d..8d9831183 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -3633,7 +3633,7 @@ msgstr "%s componentes" #: src/app/main/ui/workspace/libraries.cljs msgid "workspace.libraries.file-library" -msgstr "Biblioteca de este archivo" +msgstr "Biblioteca del archivo" #: src/app/main/ui/workspace/libraries.cljs msgid "workspace.libraries.graphics" From 2247f0ecac93f7afd61ae8c5a1db4c1b58a7f056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 8 Mar 2024 16:47:30 +0100 Subject: [PATCH 107/136] :recycle: Add a tool to generate swap-slots --- backend/src/app/srepl/fixes.clj | 105 ++++++++++++++++++++- common/src/app/common/types/container.cljc | 6 +- common/src/app/common/types/file.cljc | 13 +-- 3 files changed, 116 insertions(+), 8 deletions(-) diff --git a/backend/src/app/srepl/fixes.clj b/backend/src/app/srepl/fixes.clj index 955f08366..2d50bd8a8 100644 --- a/backend/src/app/srepl/fixes.clj +++ b/backend/src/app/srepl/fixes.clj @@ -10,10 +10,15 @@ (:require [app.binfile.common :as bfc] [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.files.changes :as cpc] + [app.common.files.helpers :as cfh] [app.common.files.repair :as cfr] [app.common.files.validate :as cfv] [app.common.logging :as l] + [app.common.types.component :as ctk] + [app.common.types.container :as ctn] + [app.common.types.file :as ctf] [app.common.uuid :as uuid] [app.db :as db] [app.features.fdata :as feat.fdata] @@ -133,4 +138,102 @@ (fn [touched] (disj touched :shapes-group))))] file (-> file - (update :data fix-fdata)))) \ No newline at end of file + (update :data fix-fdata)))) + +(defn add-swap-slots + [file libs _opts] + ;; Detect swapped copies and try to generate a valid swap-slot. + (letfn [(process-fdata [data] + ;; Walk through all containers in the file, both pages and deleted components. + (reduce process-container data (ctf/object-containers-seq data))) + + (process-container [data container] + ;; Walk through all shapes in depth-first tree order. + (l/dbg :hint "Processing container" :type (:type container) :name (:name container)) + (let [root-shape (ctn/get-container-root container)] + (ctf/update-container data + container + #(reduce process-shape % (ctn/get-direct-children container root-shape))))) + + (process-shape [container shape] + ;; Look for head copies in the first level (either component roots or inside main components). + ;; Even if they have been swapped, we don't add slot to them because there is no way to know + ;; the original shape. Only children. + (if (and (ctk/instance-head? shape) + (ctk/in-component-copy? shape) + (nil? (ctk/get-swap-slot shape))) + (process-copy-head container shape) + (reduce process-shape container (ctn/get-direct-children container shape)))) + + (process-copy-head [container head-shape] + ;; Process recursively all children, comparing each one with the corresponding child in the main + ;; component, looking by position. If the shape-ref does not point to the found child, then it has + ;; been swapped and need to set up a slot. + (l/trc :hint "Processing copy-head" :id (:id head-shape) :name (:name head-shape)) + (let [component-shape (ctf/find-ref-shape file container libs head-shape :include-deleted? true :with-context? true) + component-container (:container (meta component-shape))] + (loop [container container + children (map #(ctn/get-shape container %) (:shapes head-shape)) + component-children (map #(ctn/get-shape component-container %) (:shapes component-shape))] + (let [child (first children) + component-child (first component-children)] + (if (or (nil? child) (nil? component-child)) + container + (let [container (if (and (not (ctk/is-main-of? component-child child)) + (nil? (ctk/get-swap-slot child)) + (ctk/instance-head? child)) + (let [slot (guess-swap-slot component-child component-container)] + (l/dbg :hint "child" :id (:id child) :name (:name child) :slot slot) + (ctn/update-shape container (:id child) + #(update % :touched + cfh/set-touched-group + (ctk/build-swap-slot-group slot)))) + container)] + (recur (process-copy-head container child) + (rest children) + (rest component-children)))))))) + + (guess-swap-slot [shape container] + ;; To guess the slot, we must follow the chain until we find the definitive main. But + ;; we cannot navigate by shape-ref, because main shapes may also have been swapped. So + ;; chain by position, too. + (if-let [slot (ctk/get-swap-slot shape)] + slot + (if-not (ctk/in-component-copy? shape) + (:id shape) + (let [head-copy (ctn/get-component-shape (:objects container) shape)] + (if (= (:id head-copy) (:id shape)) + (:id shape) + (let [head-main (ctf/find-ref-shape file + container + libs + head-copy + :include-deleted? true + :with-context? true) + container-main (:container (meta head-main)) + shape-main (find-match-by-position shape + head-copy + container + head-main + container-main)] + (guess-swap-slot shape-main container-main))))))) + + (find-match-by-position [shape-copy head-copy container-copy head-main container-main] + ;; Find the shape in the main that has the same position under its parent than + ;; the copy under its one. To get the parent we must process recursively until + ;; the component head, because mains may also have been swapped. + (let [parent-copy (ctn/get-shape container-copy (:parent-id shape-copy)) + parent-main (if (= (:id parent-copy) (:id head-copy)) + head-main + (find-match-by-position parent-copy + head-copy + container-copy + head-main + container-main)) + index (cfh/get-position-on-parent (:objects container-copy) + (:id shape-copy)) + shape-main-id (dm/get-in parent-main [:shapes index])] + (ctn/get-shape container-main shape-main-id)))] + + file (-> file + (update :data process-fdata)))) diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index ddeeea734..ee2be1ae6 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -90,6 +90,10 @@ [container shape-id f] (update-in container [:objects shape-id] f)) +(defn get-container-root + [container] + (d/seek #(or (nil? (:parent-id %)) (= (:parent-id %) uuid/zero)) (shapes-seq container))) + (defn get-direct-children [container shape] (map #(get-shape container %) (:shapes shape))) @@ -107,7 +111,7 @@ (get-children-rec [] id))) (defn get-component-shape - "Get the parent top shape linked to a component for this shape, if any" + "Get the parent top shape linked to a component main for this shape, if any" ([objects shape] (get-component-shape objects shape nil)) ([objects shape {:keys [allow-main?] :or {allow-main? false} :as options}] (let [parent (get objects (:parent-id shape))] diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index a060fe634..3afb89c24 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -147,7 +147,7 @@ (defn get-component-container "Retrieve the container that holds the component shapes (the page in components-v2 - or the component itself in v1)" + or the component itself in v1 or deleted component)." [file-data component] (let [components-v2 (dm/get-in file-data [:options :components-v2])] (if (and components-v2 (not (:deleted component))) @@ -182,11 +182,12 @@ :data file-data} :container (ctn/make-container component-page :page)}))))) - (cond-> (dm/get-in component [:objects shape-id]) - with-context? - (with-meta {:file {:id (:id file-data) - :data file-data} - :container (ctn/make-container component :component)}))))) + (let [shape (dm/get-in component [:objects shape-id])] + (cond-> shape + (and shape with-context?) + (with-meta {:file {:id (:id file-data) + :data file-data} + :container (ctn/make-container component :component)})))))) (defn get-ref-shape "Retrieve the shape in the component that is referenced by the instance shape." From fbe09e6b5a8c68a48d3bb6d884cf917a99f07ec2 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 13 Mar 2024 17:36:40 +0100 Subject: [PATCH 108/136] :bug: Fix workspace context menu in small screens --- .../styles/main/partials/workspace.scss | 84 ------------------- .../app/main/ui/workspace/context_menu.cljs | 9 +- .../app/main/ui/workspace/context_menu.scss | 2 + .../ui/workspace/text_palette_ctx_menu.cljs | 2 +- .../ui/workspace/text_palette_ctx_menu.scss | 2 +- 5 files changed, 8 insertions(+), 91 deletions(-) diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index a387fed48..088add928 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -68,90 +68,6 @@ $height-palette-max: 80px; } } -.workspace-context-menu { - background-color: $color-white; - border-radius: $br3; - box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25); - left: 740px; - position: absolute; - top: 40px; - width: 240px; - z-index: 12; - - li { - align-items: center; - font-size: $fs14; - padding: $size-1 $size-4; - cursor: pointer; - - display: flex; - justify-content: space-between; - - &.separator { - border-top: 1px solid $color-gray-10; - padding: 0px; - margin: 2px; - } - - span { - color: $color-gray-60; - } - - span.shortcut { - color: $color-gray-20; - font-size: $fs12; - } - - &:hover { - background-color: $color-primary-lighter; - } - - .submenu-icon { - position: absolute; - right: 1rem; - - svg { - width: 10px; - height: 10px; - } - } - } - - .icon-menu-item { - display: flex; - justify-content: flex-start; - - &:hover { - background-color: $color-primary-lighter; - } - - span.title { - margin-left: 5px; - } - - .selected-icon { - svg { - width: 10px; - height: 10px; - } - } - - .shape-icon { - margin-left: 3px; - svg { - width: 13px; - height: 13px; - } - } - - .icon-wrapper { - display: grid; - grid-template-columns: 1fr 1fr; - margin: 0; - } - } -} - .workspace-content { background-color: $color-canvas; display: flex; diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 8ba1763fe..21f06b71c 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -652,11 +652,10 @@ [:& dropdown {:show (boolean mdata) :on-close #(st/emit! dw/hide-context-menu)} - [:ul - {:class (stl/css :workspace-context-menu) - :ref dropdown-ref - :style {:top top :left left} - :on-context-menu prevent-default} + [:ul {:class (stl/css :workspace-context-menu) + :ref dropdown-ref + :style {:top top :left left} + :on-context-menu prevent-default} (case (:kind mdata) :shape [:& shape-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 0ce429a5b..94b7060a0 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.scss +++ b/frontend/src/app/main/ui/workspace/context_menu.scss @@ -20,6 +20,8 @@ border: $s-2 solid var(--panel-border-color); background-color: var(--menu-background-color); z-index: $z-index-4; + max-height: 100vh; + overflow-y: auto; } .separator { diff --git a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs index f3cbb2208..3f1b573df 100644 --- a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs +++ b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.cljs @@ -21,7 +21,7 @@ shared-libs (mf/deref refs/workspace-libraries)] [:& dropdown {:show show-menu? :on-close close-menu} - [:ul {:class (stl/css :workspace-context-menu)} + [:ul {:class (stl/css :text-context-menu)} (for [[idx cur-library] (map-indexed vector (vals shared-libs))] (let [typographies (-> cur-library (get-in [:data :typographies]) vals)] [:li diff --git a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss index e29217eaa..664738562 100644 --- a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss +++ b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss @@ -6,7 +6,7 @@ @import "refactor/common-refactor.scss"; -.workspace-context-menu { +.text-context-menu { position: absolute; left: auto; bottom: var(--height); From 75d064806522745f68e33c2c5e1850719c85a67e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 13 Mar 2024 17:53:30 +0100 Subject: [PATCH 109/136] :bug: Fix problem with throttle function --- .../app/main/ui/workspace/sidebar/layers.cljs | 28 ++++++++++--------- frontend/src/app/util/rxops.cljs | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 5d3f5da5d..4ab174a38 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -25,7 +25,7 @@ [app.util.globals :as globals] [app.util.i18n :as i18n :refer [tr]] [app.util.keyboard :as kbd] - [app.util.timers :as ts] + [app.util.rxops :refer [throttle-fn]] [beicon.v2.core :as rx] [cuerdas.core :as str] [goog.events :as events] @@ -38,22 +38,24 @@ (mf/defc frame-wrapper {::mf/props :obj} [{:keys [selected] :as props}] - (let [disposable (mf/use-var nil) - pending-selected (mf/use-var selected) + (let [pending-selected (mf/use-var selected) current-selected (mf/use-state selected) - props (mf/spread props :selected @current-selected)] + props (mf/spread props :selected @current-selected) - (mf/with-effect [selected] + set-selected + (mf/use-memo + (fn [] + (throttle-fn + 50 + #(when-let [pending-selected @pending-selected] + (reset! current-selected pending-selected)))))] + + (mf/with-effect [selected set-selected] (reset! pending-selected selected) - (swap! disposable (fn [value] - (when (some? value) - (rx/dispose! value)) - (ts/idle-then-raf - (fn [] - (reset! current-selected @pending-selected) - (reset! disposable nil))))) + (set-selected) (fn [] - (some-> @disposable rx/dispose!))) + (reset! pending-selected nil) + #(rx/dispose! set-selected))) [:> layer-item props])) diff --git a/frontend/src/app/util/rxops.cljs b/frontend/src/app/util/rxops.cljs index 05732f3d0..7a36a8c3e 100644 --- a/frontend/src/app/util/rxops.cljs +++ b/frontend/src/app/util/rxops.cljs @@ -44,7 +44,7 @@ (when-not ^boolean timeout-id (set! (.-timeoutId state) - (js/setTimeout execute-fn (- delay ctime ltime))))))))] + (js/setTimeout execute-fn (- delay (- ctime ltime)))))))))] (specify! wrapped-fn rx/IDisposable From 91118bec709b261cef0b95f191e15fc27fcae738 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 14 Mar 2024 10:29:21 +0100 Subject: [PATCH 110/136] :sparkles: Improve internal naming of setup/props This reverts commit a6f70c77cbe72875875ab83587d5dcd9cfc61e34. --- backend/src/app/auth/oidc.clj | 11 +++++----- backend/src/app/http.clj | 3 ++- backend/src/app/http/access_token.clj | 3 ++- backend/src/app/http/awsns.clj | 5 +++-- backend/src/app/http/client.clj | 4 ++-- backend/src/app/http/debug.clj | 3 ++- backend/src/app/http/session.clj | 5 +++-- backend/src/app/loggers/audit.clj | 13 ++++++------ backend/src/app/main.clj | 18 ++++++++-------- backend/src/app/rpc.clj | 5 +++-- backend/src/app/rpc/commands/access_token.clj | 5 +++-- backend/src/app/rpc/commands/auth.clj | 21 ++++++++++--------- backend/src/app/rpc/commands/ldap.clj | 3 ++- backend/src/app/rpc/commands/profile.clj | 5 +++-- backend/src/app/rpc/commands/teams.clj | 5 +++-- backend/src/app/rpc/commands/verify_token.clj | 3 ++- backend/src/app/setup.clj | 9 ++++---- backend/src/app/tasks/telemetry.clj | 5 +++-- .../backend_tests/bounce_handling_test.clj | 14 ++++++------- 19 files changed, 77 insertions(+), 63 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 9e07a21e2..34e2cee57 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -22,6 +22,7 @@ [app.loggers.audit :as audit] [app.main :as-alias main] [app.rpc.commands.profile :as profile] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.json :as json] [app.util.time :as dt] @@ -413,7 +414,7 @@ ::props])) (defn get-info - [{:keys [provider ::main/props] :as cfg} {:keys [params] :as request}] + [{:keys [provider ::setup/props] :as cfg} {:keys [params] :as request}] (when-let [error (get params :error)] (ex/raise :type :internal :code :error-on-retrieving-code @@ -508,7 +509,7 @@ (if profile (let [sxf (session/create-fn cfg (:id profile)) token (or (:invitation-token info) - (tokens/generate (::main/props cfg) + (tokens/generate (::setup/props cfg) {:iss :auth :exp (dt/in-future "15m") :profile-id (:id profile)})) @@ -536,7 +537,7 @@ :iss :prepared-register :is-active true :exp (dt/in-future {:hours 48})) - token (tokens/generate (::main/props cfg) info) + token (tokens/generate (::setup/props cfg) info) params (d/without-nils {:token token :fullname (:fullname info)}) @@ -551,7 +552,7 @@ (defn- auth-handler [cfg {:keys [params] :as request}] (let [props (audit/extract-utm-params params) - state (tokens/generate (::main/props cfg) + state (tokens/generate (::setup/props cfg) {:iss :oauth :invitation-token (:invitation-token params) :props props @@ -618,7 +619,7 @@ [_] (s/keys :req [::session/manager ::http/client - ::main/props + ::setup/props ::db/pool ::providers])) diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index 1e605cdb0..a696d5477 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -23,6 +23,7 @@ [app.metrics :as mtx] [app.rpc :as-alias rpc] [app.rpc.doc :as-alias rpc.doc] + [app.setup :as-alias setup] [clojure.spec.alpha :as s] [integrant.core :as ig] [promesa.exec :as px] @@ -136,7 +137,7 @@ ::rpc/routes ::rpc.doc/routes ::oidc/routes - ::main/props + ::setup/props ::assets/routes ::debug/routes ::db/pool diff --git a/backend/src/app/http/access_token.clj b/backend/src/app/http/access_token.clj index bfddbb42d..0d1865f10 100644 --- a/backend/src/app/http/access_token.clj +++ b/backend/src/app/http/access_token.clj @@ -10,6 +10,7 @@ [app.config :as cf] [app.db :as db] [app.main :as-alias main] + [app.setup :as-alias setup] [app.tokens :as tokens] [ring.request :as rreq])) @@ -42,7 +43,7 @@ (defn- wrap-soft-auth "Soft Authentication, will be executed synchronously on the undertow worker thread." - [handler {:keys [::main/props]}] + [handler {:keys [::setup/props]}] (letfn [(handle-request [request] (try (let [token (get-token request) diff --git a/backend/src/app/http/awsns.clj b/backend/src/app/http/awsns.clj index 7508be8a2..88060bb20 100644 --- a/backend/src/app/http/awsns.clj +++ b/backend/src/app/http/awsns.clj @@ -13,6 +13,7 @@ [app.db.sql :as sql] [app.http.client :as http] [app.main :as-alias main] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.worker :as-alias wrk] [clojure.spec.alpha :as s] @@ -30,7 +31,7 @@ (defmethod ig/pre-init-spec ::routes [_] (s/keys :req [::http/client - ::main/props + ::setup/props ::db/pool])) (defmethod ig/init-key ::routes @@ -106,7 +107,7 @@ [cfg headers] (let [tdata (get headers "x-penpot-data")] (when-not (str/empty? tdata) - (let [result (tokens/verify (::main/props cfg) {:token tdata :iss :profile-identity})] + (let [result (tokens/verify (::setup/props cfg) {:token tdata :iss :profile-identity})] (:profile-id result))))) (defn- parse-notification diff --git a/backend/src/app/http/client.clj b/backend/src/app/http/client.clj index 5b4a8541c..9ef4cc4b2 100644 --- a/backend/src/app/http/client.clj +++ b/backend/src/app/http/client.clj @@ -55,8 +55,8 @@ convention." ([cfg-or-client request] (let [client (resolve-client cfg-or-client)] - (send! client request {}))) + (send! client request {:sync? true}))) ([cfg-or-client request options] (let [client (resolve-client cfg-or-client)] - (send! client request options)))) + (send! client request (merge {:sync? true} options))))) diff --git a/backend/src/app/http/debug.clj b/backend/src/app/http/debug.clj index 1d2a129cf..a453c6872 100644 --- a/backend/src/app/http/debug.clj +++ b/backend/src/app/http/debug.clj @@ -20,6 +20,7 @@ [app.rpc.commands.auth :as auth] [app.rpc.commands.files-create :refer [create-file]] [app.rpc.commands.profile :as profile] + [app.setup :as-alias setup] [app.srepl.helpers :as srepl] [app.storage :as-alias sto] [app.storage.tmp :as tmp] @@ -340,7 +341,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn- resend-email-notification - [{:keys [::db/pool ::main/props] :as cfg} {:keys [params] :as request}] + [{:keys [::db/pool ::setup/props] :as cfg} {:keys [params] :as request}] (when-not (contains? params :force) (ex/raise :type :validation diff --git a/backend/src/app/http/session.clj b/backend/src/app/http/session.clj index 7ff6dfa01..c4a3f0ba6 100644 --- a/backend/src/app/http/session.clj +++ b/backend/src/app/http/session.clj @@ -15,6 +15,7 @@ [app.db.sql :as sql] [app.http.session.tasks :as-alias tasks] [app.main :as-alias main] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.time :as dt] [clojure.spec.alpha :as s] @@ -138,7 +139,7 @@ (declare ^:private gen-token) (defn create-fn - [{:keys [::manager ::main/props]} profile-id] + [{:keys [::manager ::setup/props]} profile-id] (us/assert! ::manager manager) (us/assert! ::us/uuid profile-id) @@ -196,7 +197,7 @@ (neg? (compare default-renewal-max-age elapsed))))) (defn- wrap-soft-auth - [handler {:keys [::manager ::main/props]}] + [handler {:keys [::manager ::setup/props]}] (us/assert! ::manager manager) (letfn [(handle-request [request] (try diff --git a/backend/src/app/loggers/audit.clj b/backend/src/app/loggers/audit.clj index 45c36334a..aead09110 100644 --- a/backend/src/app/loggers/audit.clj +++ b/backend/src/app/loggers/audit.clj @@ -24,6 +24,7 @@ [app.main :as-alias main] [app.rpc :as-alias rpc] [app.rpc.retry :as rtry] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as-alias sv] [app.util.time :as dt] @@ -261,7 +262,7 @@ (s/def ::tasks/uri ::us/string) (defmethod ig/pre-init-spec ::tasks/archive-task [_] - (s/keys :req [::db/pool ::main/props ::http.client/client])) + (s/keys :req [::db/pool ::setup/props ::http.client/client])) (defmethod ig/init-key ::tasks/archive [_ cfg] @@ -287,7 +288,7 @@ (px/sleep 100) (recur (+ total ^long n))) (when (pos? total) - (l/debug :hint "events archived" :total total))))))))) + (l/dbg :hint "events archived" :total total))))))))) (def ^:private sql:retrieve-batch-of-audit-log "select * @@ -322,7 +323,7 @@ :context])) (send [events] - (let [token (tokens/generate (::main/props cfg) + (let [token (tokens/generate (::setup/props cfg) {:iss "authentication" :iat (dt/now) :uid uuid/zero}) @@ -331,11 +332,11 @@ "origin" (cf/get :public-uri) "cookie" (u/map->query-string {:auth-token token})} params {:uri uri - :timeout 6000 + :timeout 12000 :method :post :headers headers :body body} - resp (http.client/req! cfg params {:sync? true})] + resp (http.client/req! cfg params)] (if (= (:status resp) 204) true (do @@ -355,7 +356,7 @@ (map row->event)) events (into [] xform rows)] (when-not (empty? events) - (l/trace :hint "archive events chunk" :uri uri :events (count events)) + (l/trc :hint "archive events chunk" :uri uri :events (count events)) (when (send events) (mark-as-archived conn rows) (count events))))))) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 47e43f5cf..e0177110f 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -221,7 +221,7 @@ {::db/pool (ig/ref ::db/pool)} ::http.awsns/routes - {::props (ig/ref ::setup/props) + {::setup/props (ig/ref ::setup/props) ::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client)} @@ -262,7 +262,7 @@ ::oidc/routes {::http.client/client (ig/ref ::http.client/client) ::db/pool (ig/ref ::db/pool) - ::props (ig/ref ::setup/props) + ::setup/props (ig/ref ::setup/props) ::oidc/providers {:google (ig/ref ::oidc.providers/google) :github (ig/ref ::oidc.providers/github) :gitlab (ig/ref ::oidc.providers/gitlab) @@ -274,7 +274,7 @@ ::db/pool (ig/ref ::db/pool) ::rpc/routes (ig/ref ::rpc/routes) ::rpc.doc/routes (ig/ref ::rpc.doc/routes) - ::props (ig/ref ::setup/props) + ::setup/props (ig/ref ::setup/props) ::mtx/routes (ig/ref ::mtx/routes) ::oidc/routes (ig/ref ::oidc/routes) ::http.debug/routes (ig/ref ::http.debug/routes) @@ -286,7 +286,7 @@ {::db/pool (ig/ref ::db/pool) ::session/manager (ig/ref ::session/manager) ::sto/storage (ig/ref ::sto/storage) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} ::http.ws/routes {::db/pool (ig/ref ::db/pool) @@ -322,7 +322,7 @@ ::rpc/climit (ig/ref ::rpc/climit) ::rpc/rlimit (ig/ref ::rpc/rlimit) ::setup/templates (ig/ref ::setup/templates) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} :app.rpc.doc/routes {:methods (ig/ref :app.rpc/methods)} @@ -331,7 +331,7 @@ {::rpc/methods (ig/ref :app.rpc/methods) ::db/pool (ig/ref ::db/pool) ::session/manager (ig/ref ::session/manager) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} ::wrk/registry {::mtx/metrics (ig/ref ::mtx/metrics) @@ -388,7 +388,7 @@ :app.tasks.telemetry/handler {::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client) - ::props (ig/ref ::setup/props)} + ::setup/props (ig/ref ::setup/props)} [::srepl/urepl ::srepl/server] {::srepl/port (cf/get :urepl-port 6062) @@ -402,7 +402,7 @@ ::setup/props {::db/pool (ig/ref ::db/pool) - ::key (cf/get :secret-key) + ::setup/key (cf/get :secret-key) ;; NOTE: this dependency is only necessary for proper initialization ordering, props ;; module requires the migrations to run before initialize. @@ -412,7 +412,7 @@ {} ::audit.tasks/archive - {::props (ig/ref ::setup/props) + {::setup/props (ig/ref ::setup/props) ::db/pool (ig/ref ::db/pool) ::http.client/client (ig/ref ::http.client/client)} diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 8ae7a38d6..ea49b6b70 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -27,6 +27,7 @@ [app.rpc.helpers :as rph] [app.rpc.retry :as retry] [app.rpc.rlimit :as rlimit] + [app.setup :as-alias setup] [app.storage :as-alias sto] [app.util.services :as sv] [app.util.time :as dt] @@ -248,7 +249,7 @@ ::ldap/provider ::sto/storage ::mtx/metrics - ::main/props] + ::setup/props] :opt [::climit ::rlimit])) @@ -265,7 +266,7 @@ (defmethod ig/pre-init-spec ::routes [_] (s/keys :req [::methods ::db/pool - ::main/props + ::setup/props ::session/manager])) (defmethod ig/init-key ::routes diff --git a/backend/src/app/rpc/commands/access_token.clj b/backend/src/app/rpc/commands/access_token.clj index dd10f3371..06a6e516c 100644 --- a/backend/src/app/rpc/commands/access_token.clj +++ b/backend/src/app/rpc/commands/access_token.clj @@ -13,6 +13,7 @@ [app.rpc :as-alias rpc] [app.rpc.doc :as-alias doc] [app.rpc.quotes :as quotes] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] @@ -23,7 +24,7 @@ (dissoc row :perms)) (defn create-access-token - [{:keys [::db/conn ::main/props]} profile-id name expiration] + [{:keys [::db/conn ::setup/props]} profile-id name expiration] (let [created-at (dt/now) token-id (uuid/next) token (tokens/generate props {:iss "access-token" @@ -47,7 +48,7 @@ [{:keys [::db/pool] :as system} profile-id name expiration] (db/with-atomic [conn pool] (let [props (:app.setup/props system)] - (create-access-token {::db/conn conn ::main/props props} + (create-access-token {::db/conn conn ::setup/props props} profile-id name expiration)))) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index 8e9671e59..e87979007 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -26,6 +26,7 @@ [app.rpc.commands.teams :as teams] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] @@ -88,7 +89,7 @@ (profile/strip-private-attrs)) invitation (when-let [token (:invitation-token params)] - (tokens/verify (::main/props cfg) {:token token :iss :team-invitation})) + (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation})) ;; If invitation member-id does not matches the profile-id, we just proceed to ignore the ;; invitation because invitations matches exactly; and user can't login with other email and @@ -133,7 +134,7 @@ (defn recover-profile [{:keys [::db/pool] :as cfg} {:keys [token password]}] (letfn [(validate-token [token] - (let [tdata (tokens/verify (::main/props cfg) {:token token :iss :password-recovery})] + (let [tdata (tokens/verify (::setup/props cfg) {:token token :iss :password-recovery})] (:profile-id tdata))) (update-password [conn profile-id] @@ -170,7 +171,7 @@ :code :registration-disabled))) (when (contains? params :invitation-token) - (let [invitation (tokens/verify (::main/props cfg) {:token (:invitation-token params) :iss :team-invitation})] + (let [invitation (tokens/verify (::setup/props cfg) {:token (:invitation-token params) :iss :team-invitation})] (when-not (= (:email params) (:member-email invitation)) (ex/raise :type :restriction :code :email-does-not-match-invitation @@ -233,7 +234,7 @@ params (d/without-nils params) - token (tokens/generate (::main/props cfg) params)] + token (tokens/generate (::setup/props cfg) params)] (with-meta {:token token} {::audit/profile-id uuid/zero}))) @@ -340,7 +341,7 @@ (defn register-profile [{:keys [::db/conn] :as cfg} {:keys [token fullname] :as params}] - (let [claims (tokens/verify (::main/props cfg) {:token token :iss :prepared-register}) + (let [claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register}) params (-> claims (into params) (assoc :fullname fullname)) @@ -357,7 +358,7 @@ (create-profile-rels! conn)))) invitation (when-let [token (:invitation-token params)] - (tokens/verify (::main/props cfg) {:token token :iss :team-invitation}))] + (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))] ;; If profile is filled in claims, means it tries to register ;; again, so we proceed to update the modified-at attr @@ -377,7 +378,7 @@ ;; email. (and (some? invitation) (= (:email profile) (:member-email invitation))) (let [claims (assoc invitation :member-id (:id profile)) - token (tokens/generate (::main/props cfg) claims) + token (tokens/generate (::setup/props cfg) claims) resp {:invitation-token token}] (-> resp (rph/with-transform (session/create-fn cfg (:id profile))) @@ -404,7 +405,7 @@ ;; In all other cases, send a verification email. :else (do - (send-email-verification! conn (::main/props cfg) profile) + (send-email-verification! conn (::setup/props cfg) profile) (rph/with-meta profile {::audit/replace-props (audit/profile->props profile) ::audit/profile-id (:id profile)}))))) @@ -429,14 +430,14 @@ (defn request-profile-recovery [{:keys [::db/pool] :as cfg} {:keys [email] :as params}] (letfn [(create-recovery-token [{:keys [id] :as profile}] - (let [token (tokens/generate (::main/props cfg) + (let [token (tokens/generate (::setup/props cfg) {:iss :password-recovery :exp (dt/in-future "15m") :profile-id id})] (assoc profile :token token))) (send-email-notification [conn profile] - (let [ptoken (tokens/generate (::main/props cfg) + (let [ptoken (tokens/generate (::setup/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})] diff --git a/backend/src/app/rpc/commands/ldap.clj b/backend/src/app/rpc/commands/ldap.clj index bb86aec90..780f0e100 100644 --- a/backend/src/app/rpc/commands/ldap.clj +++ b/backend/src/app/rpc/commands/ldap.clj @@ -18,6 +18,7 @@ [app.rpc.commands.profile :as profile] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.util.services :as sv] [clojure.spec.alpha :as s])) @@ -40,7 +41,7 @@ {::rpc/auth false ::doc/added "1.15" ::doc/module :auth} - [{:keys [::main/props ::ldap/provider] :as cfg} params] + [{:keys [::setup/props ::ldap/provider] :as cfg} params] (when-not provider (ex/raise :type :restriction :code :ldap-not-initialized diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index 6ef2ef90d..ccb6a8b2e 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -23,6 +23,7 @@ [app.rpc.climit :as climit] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] + [app.setup :as-alias setup] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] @@ -296,12 +297,12 @@ (defn- request-email-change! [{:keys [::conn] :as cfg} {:keys [profile email] :as params}] - (let [token (tokens/generate (::main/props cfg) + (let [token (tokens/generate (::setup/props cfg) {:iss :change-email :exp (dt/in-future "15m") :profile-id (:id profile) :email email}) - ptoken (tokens/generate (::main/props cfg) + ptoken (tokens/generate (::setup/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})] diff --git a/backend/src/app/rpc/commands/teams.clj b/backend/src/app/rpc/commands/teams.clj index 4b5f07700..f62f8bc6a 100644 --- a/backend/src/app/rpc/commands/teams.clj +++ b/backend/src/app/rpc/commands/teams.clj @@ -26,6 +26,7 @@ [app.rpc.helpers :as rph] [app.rpc.permissions :as perms] [app.rpc.quotes :as quotes] + [app.setup :as-alias setup] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] @@ -691,7 +692,7 @@ (defn- create-invitation-token [cfg {:keys [profile-id valid-until team-id member-id member-email role]}] - (tokens/generate (::main/props cfg) + (tokens/generate (::setup/props cfg) {:iss :team-invitation :exp valid-until :profile-id profile-id @@ -702,7 +703,7 @@ (defn- create-profile-identity-token [cfg profile] - (tokens/generate (::main/props cfg) + (tokens/generate (::setup/props cfg) {:iss :profile-identity :profile-id (:id profile) :exp (dt/in-future {:days 30})})) diff --git a/backend/src/app/rpc/commands/verify_token.clj b/backend/src/app/rpc/commands/verify_token.clj index 49c76c110..e072c90d6 100644 --- a/backend/src/app/rpc/commands/verify_token.clj +++ b/backend/src/app/rpc/commands/verify_token.clj @@ -18,6 +18,7 @@ [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] [app.rpc.quotes :as quotes] + [app.setup :as-alias setup] [app.tokens :as tokens] [app.tokens.spec.team-invitation :as-alias spec.team-invitation] [app.util.services :as sv] @@ -38,7 +39,7 @@ ::doc/module :auth} [{:keys [::db/pool] :as cfg} {:keys [token] :as params}] (db/with-atomic [conn pool] - (let [claims (tokens/verify (::main/props cfg) {:token token}) + (let [claims (tokens/verify (::setup/props cfg) {:token token}) cfg (assoc cfg :conn conn)] (process-token cfg params claims)))) diff --git a/backend/src/app/setup.clj b/backend/src/app/setup.clj index 8e889e2b4..d187f3e5f 100644 --- a/backend/src/app/setup.clj +++ b/backend/src/app/setup.clj @@ -50,16 +50,15 @@ :cause cause)))) instance-id))) -(s/def ::main/key ::us/string) -(s/def ::main/props - (s/map-of ::us/keyword some?)) +(s/def ::key ::us/string) +(s/def ::props (s/map-of ::us/keyword some?)) (defmethod ig/pre-init-spec ::props [_] (s/keys :req [::db/pool] - :opt [::main/key])) + :opt [::key])) (defmethod ig/init-key ::props - [_ {:keys [::db/pool ::main/key] :as cfg}] + [_ {:keys [::db/pool ::key] :as cfg}] (db/with-atomic [conn pool] (db/xact-lock! conn 0) (when-not key diff --git a/backend/src/app/tasks/telemetry.clj b/backend/src/app/tasks/telemetry.clj index d040a08f9..43c0b26f9 100644 --- a/backend/src/app/tasks/telemetry.clj +++ b/backend/src/app/tasks/telemetry.clj @@ -15,6 +15,7 @@ [app.db :as db] [app.http.client :as http] [app.main :as-alias main] + [app.setup :as-alias setup] [app.util.json :as json] [clojure.spec.alpha :as s] [integrant.core :as ig] @@ -32,10 +33,10 @@ (defmethod ig/pre-init-spec ::handler [_] (s/keys :req [::http/client ::db/pool - ::main/props])) + ::setup/props])) (defmethod ig/init-key ::handler - [_ {:keys [::db/pool ::main/props] :as cfg}] + [_ {:keys [::db/pool ::setup/props] :as cfg}] (fn [{:keys [send? enabled?] :or {send? true enabled? false}}] (let [subs {:newsletter-updates (get-subscriptions-newsletter-updates pool) :newsletter-news (get-subscriptions-newsletter-news pool)} diff --git a/backend/test/backend_tests/bounce_handling_test.clj b/backend/test/backend_tests/bounce_handling_test.clj index 61a322084..13774e042 100644 --- a/backend/test/backend_tests/bounce_handling_test.clj +++ b/backend/test/backend_tests/bounce_handling_test.clj @@ -102,7 +102,7 @@ (t/deftest test-parse-bounce-report (let [profile (th/create-profile* 1) props (:app.setup/props th/*system*) - cfg {:app.main/props props} + cfg {:app.setup/props props} report (bounce-report {:token (tokens/generate props {:iss :profile-identity :profile-id (:id profile)})}) @@ -118,7 +118,7 @@ (t/deftest test-parse-complaint-report (let [profile (th/create-profile* 1) props (:app.setup/props th/*system*) - cfg {:app.main/props props} + cfg {:app.setup/props props} report (complaint-report {:token (tokens/generate props {:iss :profile-identity :profile-id (:id profile)})}) @@ -132,7 +132,7 @@ (t/deftest test-parse-complaint-report-without-token (let [props (:app.setup/props th/*system*) - cfg {:app.main/props props} + cfg {:app.setup/props props} report (complaint-report {:token ""}) result (#'awsns/parse-notification cfg report)] (t/is (= "complaint" (:type result))) @@ -145,7 +145,7 @@ (let [profile (th/create-profile* 1) props (:app.setup/props th/*system*) pool (:app.db/pool th/*system*) - cfg {:app.main/props props :app.db/pool pool} + cfg {:app.setup/props props :app.db/pool pool} report (bounce-report {:token (tokens/generate props {:iss :profile-identity :profile-id (:id profile)})}) @@ -172,7 +172,7 @@ (let [profile (th/create-profile* 1) props (:app.setup/props th/*system*) pool (:app.db/pool th/*system*) - cfg {:app.main/props props + cfg {:app.setup/props props :app.db/pool pool} report (complaint-report {:token (tokens/generate props {:iss :profile-identity @@ -202,7 +202,7 @@ (let [profile (th/create-profile* 1) props (:app.setup/props th/*system*) pool (:app.db/pool th/*system*) - cfg {:app.main/props props :app.db/pool pool} + cfg {:app.setup/props props :app.db/pool pool} report (bounce-report {:email (:email profile) :token (tokens/generate props {:iss :profile-identity @@ -224,7 +224,7 @@ (let [profile (th/create-profile* 1) props (:app.setup/props th/*system*) pool (:app.db/pool th/*system*) - cfg {:app.main/props props :app.db/pool pool} + cfg {:app.setup/props props :app.db/pool pool} report (complaint-report {:email (:email profile) :token (tokens/generate props {:iss :profile-identity From 4e9710ddfa0326b7e32867d4e1067f49101a7db5 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 14 Mar 2024 12:15:01 +0100 Subject: [PATCH 111/136] :bug: Fix dashboard comment title --- frontend/src/app/main/ui/comments.cljs | 6 ++++-- frontend/src/app/main/ui/comments.scss | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index c1c1b5685..2fd50ec86 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -604,11 +604,13 @@ [{:keys [group users on-thread-click]}] [:div {:class (stl/css :thread-group)} (if (:file-name group) - [:div {:class (stl/css :section-title)} + [:div {:class (stl/css :section-title) + :title (str (:file-name group) ", " (:page-name group))} [:span {:class (stl/css :file-name)} (:file-name group) ", "] [:span {:class (stl/css :page-name)} (:page-name group)]] - [:div {:class (stl/css :section-title)} + [:div {:class (stl/css :section-title) + :title (:page-name group)} [:span {:class (stl/css :icon)} i/document] [:span {:class (stl/css :page-name)} (:page-name group)]]) diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss index 2b10eb9e5..51e6ddadb 100644 --- a/frontend/src/app/main/ui/comments.scss +++ b/frontend/src/app/main/ui/comments.scss @@ -19,6 +19,8 @@ } .section-title { + display: grid; + grid-template-columns: auto auto; @include bodySmallTypography; height: $s-32; display: flex; @@ -27,10 +29,12 @@ } .file-name { + @include textEllipsis; color: var(--comment-subtitle-color); } .page-name { + @include textEllipsis; color: var(--comment-subtitle-color); } From d5b2a91bce1ac905b7cbb50ab3b3b2c41df4af3f Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 14 Mar 2024 12:42:07 +0100 Subject: [PATCH 112/136] :bug: Fix problem with fast change between numeric inputs --- frontend/src/app/main/ui/components/numeric_input.cljs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/components/numeric_input.cljs b/frontend/src/app/main/ui/components/numeric_input.cljs index 54965605e..134a01440 100644 --- a/frontend/src/app/main/ui/components/numeric_input.cljs +++ b/frontend/src/app/main/ui/components/numeric_input.cljs @@ -169,6 +169,13 @@ (update-input value-str) (dom/blur! node))))) + handle-change + (mf/use-fn + (mf/deps parse-value) + (fn [] + ;; Store the last value inputed + (reset! last-value* (parse-value)))) + handle-mouse-wheel (mf/use-fn (mf/deps set-delta) @@ -218,7 +225,7 @@ (obj/unset! "selectOnFocus") (obj/unset! "nillable") (obj/set! "value" mf/undefined) - (obj/set! "onChange" mf/undefined) + (obj/set! "onChange" handle-change) (obj/set! "className" class) (obj/set! "type" "text") (obj/set! "ref" ref) From 3bc6d2b0a790b6e4079d588ade07300eab141b8b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 14 Mar 2024 13:35:56 +0100 Subject: [PATCH 113/136] :bug: Fix migrating old components should not clip the content --- backend/src/app/features/components_v2.clj | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/backend/src/app/features/components_v2.clj b/backend/src/app/features/components_v2.clj index 8c7933160..e24cbc469 100644 --- a/backend/src/app/features/components_v2.clj +++ b/backend/src/app/features/components_v2.clj @@ -806,7 +806,8 @@ :width (:width (:selrect root-shape)) :height (:height (:selrect root-shape)) :name (:name component) - :shapes [new-id]}) + :shapes [new-id] + :show-content true}) (assoc :frame-id nil :parent-id nil)) root-shape' (assoc root-shape @@ -846,13 +847,15 @@ (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 - :shapes (or (:shapes shape) []) - :hide-in-viewer (or (:hide-in-viewer shape) true) - :rx (or (:rx shape) 0) - :ry (or (:ry shape) 0)) + (let [frame? (= :frame (:type shape))] + (assoc shape + :type :frame ; Old groups must be converted + :fills (or (:fills shape) []) ; to frames and conform to spec + :shapes (or (:shapes shape) []) + :hide-in-viewer (if frame? (boolean (:hide-in-viewer shape)) true) + :show-content (if frame? (boolean (:show-content shape)) true) + :rx (or (:rx shape) 0) + :ry (or (:ry shape) 0))) shape))] (-> file-data (update :pages-index update-vals fix-container) From 6bf336342948b3470344c7f3eb8d9ee964fbeb0f Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 14 Mar 2024 14:19:55 +0100 Subject: [PATCH 114/136] :bug: Fix scroll when file menu open --- frontend/src/app/main/ui/dashboard.cljs | 4 ++++ frontend/src/app/main/ui/dashboard/grid.cljs | 21 +++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard.cljs b/frontend/src/app/main/ui/dashboard.cljs index 29c41f8e9..4adec8d15 100644 --- a/frontend/src/app/main/ui/dashboard.cljs +++ b/frontend/src/app/main/ui/dashboard.cljs @@ -58,6 +58,9 @@ project-id (:id project) team-id (:id team) + dashboard-local (mf/deref refs/dashboard-local) + file-menu-open? (:menu-open dashboard-local) + default-project-id (mf/with-memo [projects] (->> (vals projects) @@ -83,6 +86,7 @@ [:div {:class (stl/css :dashboard-content) + :style {:pointer-events (when file-menu-open? "none")} :on-click clear-selected-fn :ref container} (case section :dashboard-projects diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index bb2f44b2b..6f5565611 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -388,15 +388,18 @@ (on-menu-click event)))} menu-icon (when (and selected? file-menu-open?) - [:& file-menu {:files (vals selected-files) - :show? (:menu-open dashboard-local) - :left (+ 24 (:x (:menu-pos dashboard-local))) - :top (:y (:menu-pos dashboard-local)) - :navigate? true - :on-edit on-edit - :on-menu-close on-menu-close - :origin origin - :parent-id (str file-id "-action-menu")}])]]]]])) + ;; When the menu is open we disable events in the dashboard. We need to force pointer events + ;; so the menu can be handled + [:div {:style {:pointer-events "all"}} + [:& file-menu {:files (vals selected-files) + :show? (:menu-open dashboard-local) + :left (+ 24 (:x (:menu-pos dashboard-local))) + :top (:y (:menu-pos dashboard-local)) + :navigate? true + :on-edit on-edit + :on-menu-close on-menu-close + :origin origin + :parent-id (str file-id "-action-menu")}]])]]]]])) (mf/defc grid [{:keys [files project origin limit library-view? create-fn] :as props}] From 5c33bc689291798e66351b40db74bbfcf087938d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 14 Mar 2024 15:52:26 +0100 Subject: [PATCH 115/136] :bug: Make the layout boards export as responsive markup --- frontend/src/app/main/data/preview.cljs | 2 +- .../src/app/main/ui/viewer/inspect/code.cljs | 4 +- frontend/src/app/util/code_gen.cljs | 4 +- frontend/src/app/util/code_gen/style_css.cljs | 40 +++---- .../app/util/code_gen/style_css_values.cljs | 101 ++++++++++-------- 5 files changed, 82 insertions(+), 69 deletions(-) diff --git a/frontend/src/app/main/data/preview.cljs b/frontend/src/app/main/data/preview.cljs index 519ed96d3..7510fb089 100644 --- a/frontend/src/app/main/data/preview.cljs +++ b/frontend/src/app/main/data/preview.cljs @@ -76,7 +76,7 @@ (let [style-code (dm/str fontfaces-css "\n" - (-> (cg/generate-style-code objects style-type all-children) + (-> (cg/generate-style-code objects style-type [shape] all-children) (cb/format-code style-type))) markup-code diff --git a/frontend/src/app/main/ui/viewer/inspect/code.cljs b/frontend/src/app/main/ui/viewer/inspect/code.cljs index 747d06204..c1e5ebcd2 100644 --- a/frontend/src/app/main/ui/viewer/inspect/code.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/code.cljs @@ -124,11 +124,11 @@ style-code (mf/use-memo - (mf/deps fontfaces-css style-type all-children cg/generate-style-code) + (mf/deps fontfaces-css style-type shapes all-children cg/generate-style-code) (fn [] (dm/str fontfaces-css "\n" - (-> (cg/generate-style-code objects style-type all-children) + (-> (cg/generate-style-code objects style-type shapes all-children) (cb/format-code style-type))))) markup-code diff --git a/frontend/src/app/util/code_gen.cljs b/frontend/src/app/util/code_gen.cljs index e1c35d169..1c8e255b9 100644 --- a/frontend/src/app/util/code_gen.cljs +++ b/frontend/src/app/util/code_gen.cljs @@ -19,8 +19,8 @@ (generate-markup objects shapes))) (defn generate-style-code - [objects type shapes] + [objects type root-shapes all-shapes] (let [generate-style (case type "css" css/generate-style)] - (generate-style objects shapes))) + (generate-style objects root-shapes all-shapes))) diff --git a/frontend/src/app/util/code_gen/style_css.cljs b/frontend/src/app/util/code_gen/style_css.cljs index 197e883ff..5f1776044 100644 --- a/frontend/src/app/util/code_gen/style_css.cljs +++ b/frontend/src/app/util/code_gen/style_css.cljs @@ -35,8 +35,8 @@ body { display: flex; flex-direction: column; align-items: center; - padding: 2rem; - gap: 2rem; + width: 100vw; + min-height: 100vh; } * { @@ -94,6 +94,7 @@ body { :flex-direction :flex-wrap :flex + :flex-grow ;; Grid related properties :grid-template-rows @@ -117,8 +118,8 @@ body { :grid-area]) (defn shape->css-property - [shape objects property] - (when-let [value (get-value property shape objects)] + [shape objects property options] + (when-let [value (get-value property shape objects options)] [property value])) (defn shape->wrapper-css-properties @@ -155,10 +156,10 @@ body { (defn shape->css-properties "Given a shape extract the CSS properties in the format of list [property value]" - [shape objects properties] + [shape objects properties options] (->> properties (keep (fn [property] - (when-let [value (get-value property shape objects)] + (when-let [value (get-value property shape objects options)] [property value]))))) (defn format-css-value @@ -189,7 +190,7 @@ body { ([objects shape properties options] (-> shape - (shape->css-properties objects properties) + (shape->css-properties objects properties options) (format-css-properties options)))) (defn format-js-styles @@ -248,13 +249,13 @@ body { properties (-> shape - (shape->css-properties objects css-properties) + (shape->css-properties objects css-properties options) (format-css-properties options)) wrapper-properties (when wrapper? (-> (d/concat-vec - (shape->css-properties shape objects shape-wrapper-css-properties) + (shape->css-properties shape objects shape-wrapper-css-properties options) (shape->wrapper-css-properties shape objects)) (format-css-properties options))) @@ -285,7 +286,7 @@ body { ([objects shape property options] (-> shape - (shape->css-property objects property) + (shape->css-property objects property options) (format-css-property options)))) (defn get-css-value @@ -293,18 +294,19 @@ body { (get-css-value objects shape property nil)) ([objects shape property options] - (when-let [prop (shape->css-property shape objects property)] + (when-let [prop (shape->css-property shape objects property options)] (format-css-value prop options)))) (defn generate-style - ([objects shapes] - (generate-style objects shapes nil)) - ([objects shapes options] - (dm/str - prelude - (->> shapes - (keep #(get-shape-css-selector % objects options)) - (str/join "\n\n"))))) + ([objects root-shapes all-shapes] + (generate-style objects root-shapes all-shapes nil)) + ([objects root-shapes all-shapes options] + (let [options (assoc options :root-shapes (into #{} (map :id) root-shapes))] + (dm/str + prelude + (->> all-shapes + (keep #(get-shape-css-selector % objects options)) + (str/join "\n\n")))))) (defn shadow->css [shadow] diff --git a/frontend/src/app/util/code_gen/style_css_values.cljs b/frontend/src/app/util/code_gen/style_css_values.cljs index 3659d33a2..fe2179c8d 100644 --- a/frontend/src/app/util/code_gen/style_css_values.cljs +++ b/frontend/src/app/util/code_gen/style_css_values.cljs @@ -25,10 +25,10 @@ :image fill-image}) (defmulti get-value - (fn [property _shape _objects] property)) + (fn [property _shape _objects _options] property)) (defmethod get-value :position - [_ shape objects] + [_ shape objects _] (cond (or (and (ctl/any-layout-immediate-child? objects shape) (not (ctl/position-absolute? shape)) @@ -65,15 +65,15 @@ (- shape-value parent-value)))) (defmethod get-value :left - [_ shape objects] + [_ shape objects _] (get-shape-position shape objects :x)) (defmethod get-value :top - [_ shape objects] + [_ shape objects _] (get-shape-position shape objects :y)) (defmethod get-value :flex - [_ shape objects] + [_ shape objects _] (let [parent (cfh/get-parent objects (:id shape))] (when (and (ctl/flex-layout-immediate-child? objects shape) (or (and (contains? #{:row :row-reverse} (:layout-flex-dir parent)) @@ -112,15 +112,26 @@ (get shape type)))) (defmethod get-value :width - [_ shape objects] - (get-shape-size shape objects :width)) + [_ shape objects options] + (let [root? (contains? (:root-shapes options) (:id shape))] + (if (and root? (ctl/any-layout? shape)) + :fill + (get-shape-size shape objects :width)))) (defmethod get-value :height - [_ shape objects] - (get-shape-size shape objects :height)) + [_ shape objects options] + (let [root? (contains? (:root-shapes options) (:id shape))] + (when-not (and root? (ctl/any-layout? shape)) + (get-shape-size shape objects :height)))) + +(defmethod get-value :flex-grow + [_ shape _ options] + (let [root? (contains? (:root-shapes options) (:id shape))] + (when (and root? (ctl/any-layout? shape)) + 1))) (defmethod get-value :transform - [_ shape objects] + [_ shape objects _] (if (cgc/svg-markup? shape) (let [parent (get objects (:parent-id shape)) transform @@ -145,7 +156,7 @@ transform-str)))) (defmethod get-value :background - [_ {:keys [fills] :as shape} _] + [_ {:keys [fills] :as shape} _ _] (let [single-fill? (= (count fills) 1)] (when (and (not (cgc/svg-markup? shape)) (not (cfh/group-shape? shape)) single-fill?) (fill->color (first fills))))) @@ -164,12 +175,12 @@ :width width}))) (defmethod get-value :border - [_ shape _] + [_ shape _ _] (when-not (cgc/svg-markup? shape) (get-stroke-data (first (:strokes shape))))) (defmethod get-value :border-radius - [_ {:keys [rx r1 r2 r3 r4] :as shape} _] + [_ {:keys [rx r1 r2 r3 r4] :as shape} _ _] (cond (cfh/circle-shape? shape) "50%" @@ -181,76 +192,76 @@ [r1 r2 r3 r4])) (defmethod get-value :box-shadow - [_ shape _] + [_ shape _ _] (when-not (cgc/svg-markup? shape) (:shadow shape))) (defmethod get-value :filter - [_ shape _] + [_ shape _ _] (when-not (cgc/svg-markup? shape) (get-in shape [:blur :value]))) (defmethod get-value :display - [_ shape _] + [_ shape _ _] (cond (:hidden shape) "none" (ctl/flex-layout? shape) "flex" (ctl/grid-layout? shape) "grid")) (defmethod get-value :opacity - [_ shape _] + [_ shape _ _] (when (< (:opacity shape) 1) (:opacity shape))) (defmethod get-value :overflow - [_ shape _] + [_ shape _ _] (when (and (cfh/frame-shape? shape) (not (cgc/svg-markup? shape)) (not (:show-content shape))) "hidden")) (defmethod get-value :flex-direction - [_ shape _] + [_ shape _ _] (:layout-flex-dir shape)) (defmethod get-value :align-items - [_ shape _] + [_ shape _ _] (:layout-align-items shape)) (defmethod get-value :align-content - [_ shape _] + [_ shape _ _] (:layout-align-content shape)) (defmethod get-value :justify-items - [_ shape _] + [_ shape _ _] (:layout-justify-items shape)) (defmethod get-value :justify-content - [_ shape _] + [_ shape _ _] (:layout-justify-content shape)) (defmethod get-value :flex-wrap - [_ shape _] + [_ shape _ _] (:layout-wrap-type shape)) (defmethod get-value :gap - [_ shape _] + [_ shape _ _] (let [[g1 g2] (ctl/gaps shape)] (when (and (= g1 g2) (or (not= g1 0) (not= g2 0))) [g1]))) (defmethod get-value :row-gap - [_ shape _] + [_ shape _ _] (let [[g1 g2] (ctl/gaps shape)] (when (and (not= g1 g2) (not= g1 0)) [g1]))) (defmethod get-value :column-gap - [_ shape _] + [_ shape _ _] (let [[g1 g2] (ctl/gaps shape)] (when (and (not= g1 g2) (not= g2 0)) [g2]))) (defmethod get-value :padding - [_ {:keys [layout-padding]} _] + [_ {:keys [layout-padding]} _ _] (when (some? layout-padding) (let [default-padding {:p1 0 :p2 0 :p3 0 :p4 0} {:keys [p1 p2 p3 p4]} (merge default-padding layout-padding)] @@ -258,11 +269,11 @@ [p1 p2 p3 p4])))) (defmethod get-value :grid-template-rows - [_ shape _] + [_ shape _ _] (:layout-grid-rows shape)) (defmethod get-value :grid-template-columns - [_ shape _] + [_ shape _ _] (:layout-grid-columns shape)) (defn area-cell? @@ -270,7 +281,7 @@ (and (= position :area) (d/not-empty? area-name))) (defmethod get-value :grid-template-areas - [_ shape _] + [_ shape _ _] (when (and (ctl/grid-layout? shape) (some area-cell? (vals (:layout-grid-cells shape)))) (let [result @@ -304,15 +315,15 @@ (get cell prop)))))) (defmethod get-value :grid-column - [_ shape objects] + [_ shape objects _] (get-grid-coord shape objects :column :column-span)) (defmethod get-value :grid-row - [_ shape objects] + [_ shape objects _] (get-grid-coord shape objects :row :row-span)) (defmethod get-value :grid-area - [_ shape objects] + [_ shape objects _] (when (and (ctl/grid-layout-immediate-child? objects shape) (not (ctl/position-absolute? shape))) (let [parent (get objects (:parent-id shape)) @@ -321,7 +332,7 @@ (str/replace (:area-name cell) " " "-"))))) (defmethod get-value :flex-shrink - [_ shape objects] + [_ shape objects _] (when (and (ctl/flex-layout-immediate-child? objects shape) (not (and (contains? #{:row :reverse-row} (:layout-flex-dir shape)) @@ -337,7 +348,7 @@ 0)) (defmethod get-value :margin - [_ {:keys [layout-item-margin] :as shape} objects] + [_ {:keys [layout-item-margin] :as shape} objects _] (when (ctl/any-layout-immediate-child? objects shape) (let [default-margin {:m1 0 :m2 0 :m3 0 :m4 0} @@ -346,7 +357,7 @@ [m1 m2 m3 m4])))) (defmethod get-value :z-index - [_ {:keys [layout-item-z-index] :as shape} objects] + [_ {:keys [layout-item-z-index] :as shape} objects _] (cond (cfh/root-frame? shape) 0 @@ -355,13 +366,13 @@ layout-item-z-index)) (defmethod get-value :max-height - [_ shape objects] + [_ shape objects _] (cond (ctl/any-layout-immediate-child? objects shape) (:layout-item-max-h shape))) (defmethod get-value :min-height - [_ shape objects] + [_ shape objects _] (cond (and (ctl/any-layout-immediate-child? objects shape) (some? (:layout-item-min-h shape))) (:layout-item-min-h shape) @@ -370,13 +381,13 @@ (-> shape :selrect :height))) (defmethod get-value :max-width - [_ shape objects] + [_ shape objects _] (cond (ctl/any-layout-immediate-child? objects shape) (:layout-item-max-w shape))) (defmethod get-value :min-width - [_ shape objects] + [_ shape objects _] (cond (and (ctl/any-layout-immediate-child? objects shape) (some? (:layout-item-min-w shape))) (:layout-item-min-w shape) @@ -385,7 +396,7 @@ (-> shape :selrect :width))) (defmethod get-value :align-self - [_ shape objects] + [_ shape objects _] (cond (ctl/flex-layout-immediate-child? objects shape) (:layout-item-align-self shape) @@ -397,7 +408,7 @@ (when (not= align-self :auto) align-self)))) (defmethod get-value :justify-self - [_ shape objects] + [_ shape objects _] (cond (ctl/grid-layout-immediate-child? objects shape) (let [parent (get objects (:parent-id shape)) @@ -406,10 +417,10 @@ (when (not= justify-self :auto) justify-self)))) (defmethod get-value :grid-auto-flow - [_ shape _] + [_ shape _ _] (when (and (ctl/grid-layout? shape) (= (:layout-grid-dir shape) :column)) "column")) (defmethod get-value :default - [property shape _] + [property shape _ _] (get shape property)) From 1a12e630274c3c352712036a06f448c6528e8eb8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 14 Mar 2024 12:53:26 +0100 Subject: [PATCH 116/136] :recycle: Simplify audit events code --- frontend/deps.edn | 4 +- frontend/src/app/main/data/comments.cljs | 124 +++++++++----- frontend/src/app/main/data/dashboard.cljs | 73 ++++++--- frontend/src/app/main/data/events.cljs | 152 ++++-------------- frontend/src/app/main/data/fonts.cljs | 37 ++++- frontend/src/app/main/data/modal.cljs | 9 +- frontend/src/app/main/data/users.cljs | 25 ++- frontend/src/app/main/data/workspace.cljs | 7 +- .../src/app/main/data/workspace/comments.cljs | 4 +- .../src/app/main/data/workspace/guides.cljs | 20 ++- .../src/app/main/data/workspace/layout.cljs | 4 +- .../app/main/data/workspace/libraries.cljs | 56 +++++-- .../app/main/data/workspace/selection.cljs | 4 + .../src/app/main/ui/dashboard/projects.cljs | 20 +-- frontend/src/app/util/router.cljs | 11 +- 15 files changed, 320 insertions(+), 230 deletions(-) diff --git a/frontend/deps.edn b/frontend/deps.edn index f4a152eae..3cd46d85a 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -9,8 +9,8 @@ funcool/okulary {:mvn/version "2022.04.11-16"} funcool/potok2 - {:git/tag "v2.0" - :git/sha "2bb377b" + {:git/tag "v2.1" + :git/sha "84c97b9" :git/url "https://github.com/funcool/potok.git"} funcool/beicon2 diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 5762229d4..981f78336 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -12,6 +12,7 @@ [app.common.schema :as sm] [app.common.types.shape-tree :as ctst] [app.common.uuid :as uuid] + [app.main.data.events :as ev] [app.main.data.workspace.state-helpers :as wsh] [app.main.repo :as rp] [beicon.v2.core :as rx] @@ -61,13 +62,23 @@ (ptk/reify ::created-thread-on-workspace ptk/UpdateEvent (update [_ state] - (-> state - (update :comment-threads assoc id (dissoc thread :comment)) - (update-in [:workspace-data :pages-index page-id :options :comment-threads-position] assoc id (select-keys thread [:position :frame-id])) - (update :comments-local assoc :open id) - (update :comments-local dissoc :draft) - (update :workspace-drawing dissoc :comment) - (update-in [:comments id] assoc (:id comment) comment))))) + (let [position (select-keys thread [:position :frame-id])] + (-> state + (update :comment-threads assoc id (dissoc thread :comment)) + (update-in [:workspace-data :pages-index page-id :options :comment-threads-position] assoc id position) + (update :comments-local assoc :open id) + (update :comments-local dissoc :draft) + (update :workspace-drawing dissoc :comment) + (update-in [:comments id] assoc (:id comment) comment)))) + + ptk/WatchEvent + (watch [_ _ _] + (rx/of (ptk/data-event ::ev/event + {::ev/name "create-comment-thread" + ::ev/origin "workspace" + :id id + :content-size (count (:content comment))}))))) + (def ^:private @@ -81,8 +92,7 @@ (defn create-thread-on-workspace [params] - (dm/assert! - (sm/check! schema:create-thread-on-workspace params)) + (dm/assert! (sm/check! schema:create-thread-on-workspace params)) (ptk/reify ::create-thread-on-workspace ptk/WatchEvent @@ -105,13 +115,22 @@ (ptk/reify ::created-thread-on-viewer ptk/UpdateEvent (update [_ state] - (-> state - (update :comment-threads assoc id (dissoc thread :comment)) - (update-in [:viewer :pages page-id :options :comment-threads-position] assoc id (select-keys thread [:position :frame-id])) - (update :comments-local assoc :open id) - (update :comments-local dissoc :draft) - (update :workspace-drawing dissoc :comment) - (update-in [:comments id] assoc (:id comment) comment))))) + (let [position (select-keys thread [:position :frame-id])] + (-> state + (update :comment-threads assoc id (dissoc thread :comment)) + (update-in [:viewer :pages page-id :options :comment-threads-position] assoc id position) + (update :comments-local assoc :open id) + (update :comments-local dissoc :draft) + (update :workspace-drawing dissoc :comment) + (update-in [:comments id] assoc (:id comment) comment)))) + + ptk/WatchEvent + (watch [_ _ _] + (rx/of (ptk/data-event ::ev/event + {::ev/name "create-comment-thread" + ::ev/origin "viewer" + :id id + :content-size (count (:content comment))}))))) (def ^:private schema:create-thread-on-viewer @@ -191,21 +210,27 @@ "expected valid content" (string? content)) - (letfn [(created [comment state] - (update-in state [:comments (:id thread)] assoc (:id comment) comment))] - (ptk/reify ::create-comment - ptk/WatchEvent - (watch [_ state _] - (let [share-id (-> state :viewer-local :share-id)] - (rx/concat - (->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id}) - (rx/map #(partial created %)) - (rx/catch (fn [{:keys [type code] :as cause}] - (if (and (= type :restriction) - (= code :max-quote-reached)) - (rx/throw cause) - (rx/throw {:type :comment-error}))))) - (rx/of (refresh-comment-thread thread)))))))) + (ptk/reify ::create-comment + ev/Event + (-data [_] + {:thread-id (:id thread) + :file-id (:file-id thread) + :content-size (count content)}) + + ptk/WatchEvent + (watch [_ state _] + (let [share-id (-> state :viewer-local :share-id) + created (fn [comment state] + (update-in state [:comments (:id thread)] assoc (:id comment) comment))] + (rx/concat + (->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id}) + (rx/map (fn [comment] (partial created comment))) + (rx/catch (fn [{:keys [type code] :as cause}] + (if (and (= type :restriction) + (= code :max-quote-reached)) + (rx/throw cause) + (rx/throw {:type :comment-error}))))) + (rx/of (refresh-comment-thread thread))))))) (defn update-comment [{:keys [id content thread-id] :as comment}] @@ -214,6 +239,12 @@ (check-comment! comment)) (ptk/reify ::update-comment + ev/Event + (-data [_] + {:thread-id thread-id + :id id + :content-size (count content)}) + ptk/UpdateEvent (update [_ state] (d/update-in-when state [:comments thread-id id] assoc :content content)) @@ -241,9 +272,14 @@ ptk/WatchEvent (watch [_ _ _] - (->> (rp/cmd! :delete-comment-thread {:id id}) - (rx/catch #(rx/throw {:type :comment-error})) - (rx/ignore))))) + (rx/concat + (->> (rp/cmd! :delete-comment-thread {:id id}) + (rx/catch #(rx/throw {:type :comment-error})) + (rx/ignore)) + (rx/of (ptk/data-event ::ev/event + {::ev/name "delete-comment-thread" + ::ev/origin "workspace" + :id id})))))) (defn delete-comment-thread-on-viewer [{:keys [id] :as thread}] @@ -262,16 +298,24 @@ ptk/WatchEvent (watch [_ state _] (let [share-id (-> state :viewer-local :share-id)] - (->> (rp/cmd! :delete-comment-thread {:id id :share-id share-id}) - (rx/catch #(rx/throw {:type :comment-error})) - (rx/ignore)))))) - + (rx/concat + (->> (rp/cmd! :delete-comment-thread {:id id :share-id share-id}) + (rx/catch #(rx/throw {:type :comment-error})) + (rx/ignore)) + (rx/of (ptk/data-event ::ev/event + {::ev/name "delete-comment-thread" + ::ev/origin "viewer" + :id id}))))))) (defn delete-comment [{:keys [id thread-id] :as comment}] (dm/assert! "expected valid comment" (check-comment! comment)) (ptk/reify ::delete-comment + ev/Event + (-data [_] + {:thread-id thread-id}) + ptk/UpdateEvent (update [_ state] (-> state @@ -375,6 +419,10 @@ "expected valid comment thread" (check-comment-thread! thread)) (ptk/reify ::open-comment-thread + ev/Event + (-data [_] + {:thread-id id}) + ptk/UpdateEvent (update [_ state] (-> state diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index b75fddfc9..bde91339d 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -469,7 +469,11 @@ (rx/map prepare) (rx/mapcat #(rp/cmd! :update-team-photo %)) (rx/tap on-success) - (rx/map du/fetch-teams) + (rx/mapcat (fn [_] + (rx/of (du/fetch-teams) + (ptk/data-event ::ev/event + {::ev/name "update-team-photo" + :team-id team-id})))) (rx/catch on-error)))))) (defn update-team-member-role @@ -484,7 +488,12 @@ (->> (rp/cmd! :update-team-member-role params) (rx/mapcat (fn [_] (rx/of (fetch-team-members team-id) - (du/fetch-teams))))))))) + (du/fetch-teams) + (ptk/data-event ::ev/event + {::ev/name "update-team-member-role" + :team-id team-id + :role role + :member-id member-id}))))))))) (defn delete-team-member [{:keys [member-id] :as params}] @@ -497,7 +506,11 @@ (->> (rp/cmd! :delete-team-member params) (rx/mapcat (fn [_] (rx/of (fetch-team-members team-id) - (du/fetch-teams))))))))) + (du/fetch-teams) + (ptk/data-event ::ev/event + {::ev/name "delete-team-member" + :team-id team-id + :member-id member-id}))))))))) (defn leave-team [{:keys [reassign-to] :as params}] @@ -516,6 +529,11 @@ (assoc :reassign-to reassign-to))] (->> (rp/cmd! :leave-team params) (rx/tap #(tm/schedule on-success)) + (rx/map (fn [_] + (ptk/data-event ::ev/event + {::ev/name "leave-team" + :reassign-to reassign-to + :team-id team-id}))) (rx/catch on-error)))))) (defn invite-team-members @@ -528,8 +546,11 @@ (sm/check-set-of-emails! emails)) (ptk/reify ::invite-team-members - IDeref - (-deref [_] {:role role :team-id team-id :resend? resend?}) + ev/Event + (-data [_] + {:role role + :team-id team-id + :resend resend?}) ptk/WatchEvent (watch [_ _ _] @@ -727,6 +748,11 @@ [{:keys [id name] :as params}] (dm/assert! (uuid? id)) (ptk/reify ::duplicate-project + ev/Event + (-data [_] + {:project-id id + :name name}) + ptk/WatchEvent (watch [_ _ _] (let [{:keys [on-success on-error] @@ -744,10 +770,12 @@ [{:keys [id team-id] :as params}] (dm/assert! (uuid? id)) (dm/assert! (uuid? team-id)) + (ptk/reify ::move-project - IDeref - (-deref [_] - {:id id :team-id team-id}) + ev/Event + (-data [_] + {:id id + :team-id team-id}) ptk/WatchEvent (watch [_ _ _] @@ -834,9 +862,11 @@ (defn rename-file [{:keys [id name] :as params}] (ptk/reify ::rename-file - IDeref - (-deref [_] - {::ev/origin "dashboard" :id id :name name}) + ev/Event + (-data [_] + {::ev/origin "dashboard" + :id id + :name name}) ptk/UpdateEvent (update [_ state] @@ -856,9 +886,11 @@ (defn set-file-shared [{:keys [id is-shared] :as params}] (ptk/reify ::set-file-shared - IDeref - (-deref [_] - {::ev/origin "dashboard" :id id :shared is-shared}) + ev/Event + (-data [_] + {::ev/origin "dashboard" + :id id + :shared is-shared}) ptk/UpdateEvent (update [_ state] @@ -912,9 +944,8 @@ [{:keys [project-id] :as params}] (dm/assert! (uuid? project-id)) (ptk/reify ::create-file - - IDeref - (-deref [_] {:project-id project-id}) + ev/Event + (-data [_] {:project-id project-id}) ptk/WatchEvent (watch [it state _] @@ -967,8 +998,8 @@ (sm/check-set-of-uuid! ids)) (ptk/reify ::move-files - IDeref - (-deref [_] + ev/Event + (-data [_] {:num-files (count ids) :project-id project-id}) @@ -998,8 +1029,8 @@ [{:keys [template-id project-id] :as params}] (dm/assert! (uuid? project-id)) (ptk/reify ::clone-template - IDeref - (-deref [_] + ev/Event + (-data [_] {:template-id template-id :project-id project-id}) diff --git a/frontend/src/app/main/data/events.cljs b/frontend/src/app/main/data/events.cljs index f80883672..ec217339c 100644 --- a/frontend/src/app/main/data/events.cljs +++ b/frontend/src/app/main/data/events.cljs @@ -75,71 +75,23 @@ ;; --- EVENT TRANSLATION -(derive :app.main.data.comments/create-comment ::generic-action) -(derive :app.main.data.comments/create-comment-thread ::generic-action) -(derive :app.main.data.comments/delete-comment ::generic-action) -(derive :app.main.data.comments/delete-comment-thread ::generic-action) -(derive :app.main.data.comments/open-comment-thread ::generic-action) -(derive :app.main.data.comments/update-comment ::generic-action) -(derive :app.main.data.comments/update-comment-thread ::generic-action) -(derive :app.main.data.comments/update-comment-thread-status ::generic-action) -(derive :app.main.data.dashboard/delete-team-member ::generic-action) -(derive :app.main.data.dashboard/duplicate-project ::generic-action) -(derive :app.main.data.dashboard/create-file ::generic-action) -(derive :app.main.data.dashboard/invite-team-members ::generic-action) -(derive :app.main.data.dashboard/leave-team ::generic-action) -(derive :app.main.data.dashboard/move-files ::generic-action) -(derive :app.main.data.dashboard/move-project ::generic-action) -(derive :app.main.data.dashboard/rename-file ::generic-action) -(derive :app.main.data.dashboard/set-file-shared ::generic-action) -(derive :app.main.data.dashboard/update-team-member-role ::generic-action) -(derive :app.main.data.dashboard/update-team-photo ::generic-action) -(derive :app.main.data.dashboard/clone-template ::generic-action) -(derive :app.main.data.fonts/add-font ::generic-action) -(derive :app.main.data.fonts/delete-font ::generic-action) -(derive :app.main.data.fonts/delete-font-variant ::generic-action) -(derive :app.main.data.modal/show-modal ::generic-action) -(derive :app.main.data.users/logout ::generic-action) -(derive :app.main.data.users/request-email-change ::generic-action) -(derive :app.main.data.users/update-password ::generic-action) -(derive :app.main.data.users/update-photo ::generic-action) -(derive :app.main.data.workspace.comments/open-comment-thread ::generic-action) -(derive :app.main.data.workspace.guides/update-guides ::generic-action) -(derive :app.main.data.workspace.libraries/add-color ::generic-action) -(derive :app.main.data.workspace.libraries/add-media ::generic-action) -(derive :app.main.data.workspace.libraries/add-typography ::generic-action) -(derive :app.main.data.workspace.libraries/delete-color ::generic-action) -(derive :app.main.data.workspace.libraries/delete-media ::generic-action) -(derive :app.main.data.workspace.libraries/delete-typography ::generic-action) -(derive :app.main.data.workspace.persistence/attach-library ::generic-action) -(derive :app.main.data.workspace.persistence/detach-library ::generic-action) -(derive :app.main.data.workspace.persistence/set-file-shard ::generic-action) -(derive :app.main.data.workspace.selection/toggle-focus-mode ::generic-action) -(derive :app.main.data.workspace/create-page ::generic-action) -(derive :app.main.data.workspace/set-workspace-layout ::generic-action) -(derive :app.main.data.workspace/toggle-layout-flag ::generic-action) - (defprotocol Event (-data [_] "Get event data")) (defn- simplify-props "Removes complex data types from props." [data] - (into {} - (comp - (remove (fn [[_ v]] (nil? v))) - (map (fn [[k v :as kv]] - (cond - (map? v) [k :placeholder/map] - (vector? v) [k :placeholder/vec] - (set? v) [k :placeholder/set] - (coll? v) [k :placeholder/coll] - (fn? v) [k :placeholder/fn] - :else kv)))) - data)) - - -(defmulti process-event-by-type ptk/type) + (reduce-kv (fn [data k v] + (cond + (map? v) (assoc data k :placeholder/map) + (vector? v) (assoc data k :placeholder/vec) + (set? v) (assoc data k :placeholder/set) + (coll? v) (assoc data k :placeholder/coll) + (fn? v) (assoc data k :placeholder/fn) + (nil? v) (dissoc data k) + :else data)) + data + data)) (defn- process-event-by-proto [event] @@ -158,72 +110,30 @@ :context context :props props})) +(defn- process-data-event + [event] + (let [data (deref event) + name (::name data)] + + (when (string? name) + (let [type (::type data "action") + context (-> (::context data) + (assoc :event-origin (::origin data)) + (d/without-nils)) + props (-> data d/without-qualified simplify-props)] + {:type type + :name name + :context context + :props props})))) + (defn- process-event [event] - (if (satisfies? Event event) + (cond + (satisfies? Event event) (process-event-by-proto event) - (process-event-by-type event))) -(defmethod process-event-by-type :default [_] nil) - -(defmethod process-event-by-type ::event - [event] - (let [data (deref event) - context (-> (::context data) - (assoc :event-origin (::origin data)) - (d/without-nils)) - props (-> data d/without-qualified simplify-props)] - - {:type (::type data "action") - :name (::name data "unnamed") - :context context - :props props})) - -(defmethod process-event-by-type ::generic-action - [event] - (let [type (ptk/type event) - data (if (satisfies? IDeref event) - (deref event) - {}) - data (d/deep-merge data (meta event))] - - {:type "action" - :name (or (::name data) (name type)) - :props (-> (d/without-qualified data) - (simplify-props)) - :context (d/without-nils - {:event-origin (::origin data) - :event-namespace (namespace type) - :event-symbol (name type)})})) - -(defmethod process-event-by-type :app.util.router/navigated - [event] - (let [match (deref event) - route (get-in match [:data :name]) - props {:route (name route) - :team-id (get-in match [:path-params :team-id]) - :file-id (get-in match [:path-params :file-id]) - :project-id (get-in match [:path-params :project-id])}] - {:name "navigate" - :type "action" - :props (simplify-props props)})) - -(defmethod process-event-by-type :app.main.data.users/logged-in - [event] - (let [data (deref event) - mdata (meta data) - props {:signin-source (::source mdata) - :email (:email data) - :auth-backend (:auth-backend data) - :fullname (:fullname data) - :is-muted (:is-muted data) - :default-team-id (str (:default-team-id data)) - :default-project-id (str (:default-project-id data))}] - - {:name "signin" - :type "identify" - :profile-id (:id data) - :props (simplify-props props)})) + (ptk/data-event? event) + (process-data-event event))) ;; --- MAIN LOOP diff --git a/frontend/src/app/main/data/fonts.cljs b/frontend/src/app/main/data/fonts.cljs index bb8fe193f..b7150b033 100644 --- a/frontend/src/app/main/data/fonts.cljs +++ b/frontend/src/app/main/data/fonts.cljs @@ -12,6 +12,7 @@ [app.common.logging :as log] [app.common.media :as cm] [app.common.uuid :as uuid] + [app.main.data.events :as ev] [app.main.data.messages :as msg] [app.main.fonts :as fonts] [app.main.repo :as rp] @@ -236,12 +237,19 @@ (defn add-font [font] (ptk/reify ::add-font - IDeref - (-deref [_] (select-keys font [:font-family :font-style :font-weight])) - ptk/UpdateEvent (update [_ state] - (update state :dashboard-fonts assoc (:id font) font)))) + (update state :dashboard-fonts assoc (:id font) font)) + + ptk/WatchEvent + (watch [_ state _] + (let [team-id (:current-team-id state)] + (rx/of (ptk/data-event ::ev/event {::ev/name "add-font" + :team-id team-id + :font-id (:id font) + :font-family (:font-family font) + :font-style (:font-style font) + :font-weight (:font-weight font)})))))) (defn update-font [{:keys [id name] :as params}] @@ -271,6 +279,10 @@ [font-id] (dm/assert! (uuid? font-id)) (ptk/reify ::delete-font + ev/Event + (-data [_] + {:id font-id}) + ptk/UpdateEvent (update [_ state] (update state :dashboard-fonts @@ -280,8 +292,12 @@ ptk/WatchEvent (watch [_ state _] (let [team-id (:current-team-id state)] - (->> (rp/cmd! :delete-font {:id font-id :team-id team-id}) - (rx/ignore)))))) + (rx/concat + (->> (rp/cmd! :delete-font {:id font-id :team-id team-id}) + (rx/ignore)) + (rx/of (ptk/data-event ::ev/event {::ev/name "delete-font" + :team-id team-id + :font-id font-id}))))))) (defn delete-font-variant [id] @@ -297,8 +313,13 @@ ptk/WatchEvent (watch [_ state _] (let [team-id (:current-team-id state)] - (->> (rp/cmd! :delete-font-variant {:id id :team-id team-id}) - (rx/ignore)))))) + (rx/concat + (->> (rp/cmd! :delete-font-variant {:id id :team-id team-id}) + (rx/ignore)) + (rx/of (ptk/data-event ::ev/event {::ev/name "delete-font-variant" + :id id + :team-id team-id}))))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Workspace related events diff --git a/frontend/src/app/main/data/modal.cljs b/frontend/src/app/main/data/modal.cljs index 5b5b79524..1055014c2 100644 --- a/frontend/src/app/main/data/modal.cljs +++ b/frontend/src/app/main/data/modal.cljs @@ -8,6 +8,7 @@ (:refer-clojure :exclude [update]) (:require [app.common.uuid :as uuid] + [app.main.data.events :as ev] [app.main.store :as st] [cljs.core :as c] [potok.v2.core :as ptk])) @@ -23,9 +24,11 @@ (show (uuid/next) type props)) ([id type props] (ptk/reify ::show-modal - IDeref - (-deref [_] - (merge (dissoc props :type) {:name type})) + ev/Event + (-data [_] + (-> props + (dissoc :type) + (assoc :name type))) ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/users.cljs b/frontend/src/app/main/data/users.cljs index 64142d327..392c6e055 100644 --- a/frontend/src/app/main/data/users.cljs +++ b/frontend/src/app/main/data/users.cljs @@ -161,8 +161,16 @@ (rt/nav' :dashboard-projects {:team-id team-id}))))] (ptk/reify ::logged-in - IDeref - (-deref [_] profile) + ev/Event + (-data [_] + {::ev/name "signing" + ::ev/type "identify" + :email (:email profile) + :auth-backend (:auth-backend profile) + :fullname (:fullname profile) + :is-muted (:is-muted profile) + :default-team-id (:default-team-id profile) + :default-project-id (:default-project-id profile)}) ptk/WatchEvent (watch [_ _ _] @@ -288,6 +296,9 @@ ([] (logout {})) ([params] (ptk/reify ::logout + ev/Event + (-data [_] {}) + ptk/WatchEvent (watch [_ _ _] (->> (rp/cmd! :logout) @@ -360,6 +371,10 @@ [{:keys [email] :as data}] (dm/assert! ::us/email email) (ptk/reify ::request-email-change + ev/Event + (-data [_] + {:email email}) + ptk/WatchEvent (watch [_ _ _] (let [{:keys [on-error on-success] @@ -395,6 +410,9 @@ (sm/check! schema:update-password data)) (ptk/reify ::update-password + ev/Event + (-data [_] {}) + ptk/WatchEvent (watch [_ _ _] (let [{:keys [on-error on-success] @@ -458,6 +476,9 @@ (di/blob? file)) (ptk/reify ::update-photo + ev/Event + (-data [_] {}) + ptk/WatchEvent (watch [_ _ _] (let [on-success di/notify-finished-loading diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 41fdb90ba..da8ac8eab 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -458,9 +458,10 @@ [{:keys [file-id]}] (let [id (uuid/next)] (ptk/reify ::create-page - IDeref - (-deref [_] - {:id id :file-id file-id}) + ev/Event + (-data [_] + {:id id + :file-id file-id}) ptk/WatchEvent (watch [it state _] diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs index 3d1457d56..246034878 100644 --- a/frontend/src/app/main/data/workspace/comments.cljs +++ b/frontend/src/app/main/data/workspace/comments.cljs @@ -13,6 +13,7 @@ [app.common.schema :as sm] [app.common.types.shape-tree :as ctst] [app.main.data.comments :as dcm] + [app.main.data.events :as ev] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.common :as dwco] [app.main.data.workspace.drawing :as dwd] @@ -118,7 +119,8 @@ (rx/take 1) (rx/mapcat #(rx/of (center-to-comment-thread thread) (dwd/select-for-drawing :comments) - (dcm/open-thread thread))))))))) + (with-meta (dcm/open-thread thread) + {::ev/origin "workspace"}))))))))) (defn update-comment-thread-position ([thread [new-x new-y]] diff --git a/frontend/src/app/main/data/workspace/guides.cljs b/frontend/src/app/main/data/workspace/guides.cljs index 222921010..2c7c6c2c0 100644 --- a/frontend/src/app/main/data/workspace/guides.cljs +++ b/frontend/src/app/main/data/workspace/guides.cljs @@ -11,23 +11,30 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.types.page :as ctp] + [app.main.data.events :as ev] [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])) -(defn make-update-guide [guide] +(defn make-update-guide + [guide] (fn [other] (cond-> other (= (:id other) (:id guide)) (merge guide)))) -(defn update-guides [guide] +(defn update-guides + [guide] (dm/assert! "expected valid guide" (ctp/check-page-guide! guide)) (ptk/reify ::update-guides + ev/Event + (-data [_] + (assoc guide ::ev/name "update-guide")) + ptk/WatchEvent (watch [it state _] (let [page (wsh/lookup-page state) @@ -37,17 +44,20 @@ (pcb/update-page-option :guides assoc (:id guide) guide))] (rx/of (dch/commit-changes changes)))))) -(defn remove-guide [guide] +(defn remove-guide + [guide] (dm/assert! "expected valid guide" (ctp/check-page-guide! guide)) (ptk/reify ::remove-guide + ev/Event + (-data [_] guide) + ptk/UpdateEvent (update [_ state] (let [sdisj (fnil disj #{})] - (-> state - (update-in [:workspace-guides :hover] sdisj (:id guide))))) + (update-in state [:workspace-guides :hover] sdisj (:id guide)))) ptk/WatchEvent (watch [it state _] diff --git a/frontend/src/app/main/data/workspace/layout.cljs b/frontend/src/app/main/data/workspace/layout.cljs index 24cfc6779..750653c2a 100644 --- a/frontend/src/app/main/data/workspace/layout.cljs +++ b/frontend/src/app/main/data/workspace/layout.cljs @@ -82,8 +82,8 @@ (defn toggle-layout-flag [flag & {:keys [force?] :as opts}] (ptk/reify ::toggle-layout-flag - IDeref - (-deref [_] {:name flag}) + ev/Event + (-data [_] {:name flag}) ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 448997208..9f4867ace 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -108,8 +108,8 @@ (uc/gradient-type->string (get-in color [:gradient :type])))))] (dm/assert! ::ctc/color color) (ptk/reify ::add-color - IDeref - (-deref [_] color) + ev/Event + (-data [_] color) ptk/WatchEvent (watch [it _ _] @@ -185,6 +185,9 @@ [{:keys [id] :as params}] (dm/assert! (uuid? id)) (ptk/reify ::delete-color + ev/Event + (-data [_] {:id id}) + ptk/WatchEvent (watch [it state _] (let [data (get state :workspace-data) @@ -200,6 +203,9 @@ (ctf/check-media-object! media)) (ptk/reify ::add-media + ev/Event + (-data [_] media) + ptk/WatchEvent (watch [it _ _] (let [obj (select-keys media [:id :name :width :height :mtype]) @@ -230,6 +236,9 @@ [{:keys [id] :as params}] (dm/assert! (uuid? id)) (ptk/reify ::delete-media + ev/Event + (-data [_] {:id id}) + ptk/WatchEvent (watch [it state _] (let [data (get state :workspace-data) @@ -247,8 +256,8 @@ (ctt/check-typography! typography)) (ptk/reify ::add-typography - IDeref - (-deref [_] typography) + ev/Event + (-data [_] typography) ptk/WatchEvent (watch [it _ _] @@ -291,6 +300,9 @@ (dm/assert! (uuid? id)) (dm/assert! (string? new-name)) (ptk/reify ::rename-typography + ev/Event + (-data [_] {:id id :name new-name}) + ptk/WatchEvent (watch [it state _] (when (and (some? new-name) (not= "" new-name)) @@ -304,6 +316,9 @@ [id] (dm/assert! (uuid? id)) (ptk/reify ::delete-typography + ev/Event + (-data [_] {:id id}) + ptk/WatchEvent (watch [it state _] (let [data (get state :workspace-data) @@ -316,8 +331,10 @@ "This is the second step of the component creation." [selected components-v2] (ptk/reify ::add-component2 - IDeref - (-deref [_] {:num-shapes (count selected)}) + ev/Event + (-data [_] + {::ev/name "add-component" + :shapes (count selected)}) ptk/WatchEvent (watch [it state _] @@ -369,9 +386,10 @@ selected-objects (map #(get objects %) selected) ;; We don't want to change the structure of component copies can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects)) - added-components (map - #(add-component2 [%] components-v2) - selected) + added-components (map (fn [id] + (with-meta (add-component2 [id] components-v2) + {:multiple true})) + selected) undo-id (js/Symbol)] (when can-make-component (rx/concat @@ -1266,9 +1284,11 @@ [id is-shared] {:pre [(uuid? id) (boolean? is-shared)]} (ptk/reify ::set-file-shared - IDeref - (-deref [_] - {::ev/origin "workspace" :id id :shared is-shared}) + ev/Event + (-data [_] + {::ev/origin "workspace" + :id id + :shared is-shared}) ptk/UpdateEvent (update [_ state] @@ -1302,6 +1322,12 @@ (defn link-file-to-library [file-id library-id] (ptk/reify ::attach-library + ev/Event + (-data [_] + {::ev/name "attach-library" + :file-id file-id + :library-id library-id}) + ;; NOTE: this event implements UpdateEvent protocol for perform an ;; optimistic update state for make the UI feel more responsive. ptk/UpdateEvent @@ -1331,6 +1357,12 @@ (defn unlink-file-from-library [file-id library-id] (ptk/reify ::detach-library + ev/Event + (-data [_] + {::ev/name "detach-library" + :file-id file-id + :library-id library-id}) + ptk/UpdateEvent (update [_ state] (d/dissoc-in state [:workspace-libraries library-id])) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 56b4e6800..825cfedab 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -24,6 +24,7 @@ [app.common.types.shape.interactions :as ctsi] [app.common.types.shape.layout :as ctl] [app.common.uuid :as uuid] + [app.main.data.events :as ev] [app.main.data.modal :as md] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.collapse :as dwc] @@ -791,6 +792,9 @@ (defn toggle-focus-mode [] (ptk/reify ::toggle-focus-mode + ev/Event + (-data [_] {}) + ptk/UpdateEvent (update [_ state] (let [selected (wsh/lookup-selected state)] diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 931ac0604..fd855f4b1 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -385,24 +385,24 @@ (mf/use-fn (fn [] (st/emit! (du/update-profile-props {:team-hero? false}) - (ptk/event ::ev/event {::ev/name "dont-show-team-up-hero" - ::ev/origin "dashboard"})))) + (ptk/data-event ::ev/event {::ev/name "dont-show-team-up-hero" + ::ev/origin "dashboard"})))) close-tutorial (mf/use-fn (fn [] (st/emit! (du/update-profile-props {:viewed-tutorial? true}) - (ptk/event ::ev/event {::ev/name "dont-show" - ::ev/origin "get-started-hero-block" - :type "tutorial" - :section "dashboard"})))) + (ptk/data-event ::ev/event {::ev/name "dont-show-tutorial" + ::ev/origin "get-started-hero" + :type "tutorial" + :section "dashboard"})))) close-walkthrough (mf/use-fn (fn [] (st/emit! (du/update-profile-props {:viewed-walkthrough? true}) - (ptk/event ::ev/event {::ev/name "dont-show" - ::ev/origin "get-started-hero-block" - :type "walkthrough" - :section "dashboard"}))))] + (ptk/data-event ::ev/event {::ev/name "dont-show-walkthrough" + ::ev/origin "get-started-hero" + :type "walkthrough" + :section "dashboard"}))))] (mf/with-effect [team] (let [tname (if (:is-default team) diff --git a/frontend/src/app/util/router.cljs b/frontend/src/app/util/router.cljs index 50a9bb0fd..c4d541cfd 100644 --- a/frontend/src/app/util/router.cljs +++ b/frontend/src/app/util/router.cljs @@ -7,8 +7,10 @@ (ns app.util.router (:refer-clojure :exclude [resolve]) (:require + [app.common.data.macros :as dm] [app.common.uri :as u] [app.config :as cf] + [app.main.data.events :as ev] [app.util.browser-history :as bhistory] [app.util.dom :as dom] [app.util.timers :as ts] @@ -59,8 +61,13 @@ (defn navigated [match] (ptk/reify ::navigated - IDeref - (-deref [_] match) + ev/Event + (-data [_] + (let [route (dm/get-in match [:data :name]) + params (get match :path-params)] + (assoc params + ::ev/name "navigate" + :route (name route)))) ptk/UpdateEvent (update [_ state] From b5fe07d5ee28f84c2d8b340a146b248cf4e8b472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Thu, 14 Mar 2024 15:15:14 +0100 Subject: [PATCH 117/136] :bug: Fix projects & teams dashboard pages --- frontend/src/app/main/ui/dashboard.scss | 2 +- .../src/app/main/ui/dashboard/projects.cljs | 51 ++++++++++--------- .../src/app/main/ui/dashboard/projects.scss | 5 ++ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard.scss b/frontend/src/app/main/ui/dashboard.scss index ed79f5362..064694ec9 100644 --- a/frontend/src/app/main/ui/dashboard.scss +++ b/frontend/src/app/main/ui/dashboard.scss @@ -21,7 +21,7 @@ .dashboard-content { display: grid; - grid-template-rows: $s-64 auto auto 1fr; + grid-template-rows: $s-64 1fr; position: relative; grid-row: 1 / span 2; padding: $s-16 $s-16 0 0; diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 931ac0604..7cf1ef2b4 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -417,31 +417,32 @@ (when (seq projects) [:* [:& header] + [:div {:class (stl/css :projects-container)} + [:* + (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}]))]]))) + [: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/projects.scss b/frontend/src/app/main/ui/dashboard/projects.scss index 735f4e7ee..105dabd50 100644 --- a/frontend/src/app/main/ui/dashboard/projects.scss +++ b/frontend/src/app/main/ui/dashboard/projects.scss @@ -44,6 +44,11 @@ --actions-opacity: 1; } +.projects-container { + display: grid; + grid-auto-rows: min-content; +} + .project { display: flex; flex-direction: row; From 55b6df0ae4adb34e490a761885f5338d99ede447 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 14 Mar 2024 16:16:33 +0100 Subject: [PATCH 118/136] :bug: Make opacity override same color recent-color --- common/src/app/common/files/changes.cljc | 14 +++++++++----- common/src/app/common/types/color.cljc | 6 ++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index c200749d8..978cc8edf 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -609,11 +609,15 @@ (defmethod process-change :add-recent-color [data {:keys [color]}] ;; Moves the color to the top of the list and then truncates up to 15 - (update data :recent-colors (fn [rc] - (let [rc (conj (filterv (comp not #{color}) (or rc [])) color)] - (if (> (count rc) 15) - (subvec rc 1) - rc))))) + (update + data + :recent-colors + (fn [rc] + (let [rc (->> rc (d/removev (partial ctc/eq-recent-color? color))) + rc (-> rc (conj color))] + (cond-> rc + (> (count rc) 15) + (subvec 1)))))) ;; -- Media diff --git a/common/src/app/common/types/color.cljc b/common/src/app/common/types/color.cljc index 382530ac2..7bded1492 100644 --- a/common/src/app/common/types/color.cljc +++ b/common/src/app/common/types/color.cljc @@ -358,3 +358,9 @@ (process-shape-colors shape sync-color))) +(defn eq-recent-color? + [c1 c2] + (or (= c1 c2) + (and (some? (:color c1)) + (some? (:color c2)) + (= (:color c1) (:color c2))))) From affa37f0c5dec55cc5c1b1ae353af6fd9149236b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 14 Mar 2024 16:54:15 +0100 Subject: [PATCH 119/136] :bug: Fix problem with scroll style in windows --- .../ui/workspace/sidebar/options/menus/layout_container.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 62ce26e4f..a51118e29 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 @@ -113,7 +113,7 @@ .padding-simple { @extend .input-element; - width: $s-108; + max-width: $s-108; } } @@ -124,7 +124,7 @@ .padding-multiple { @extend .input-element; - width: $s-108; + max-width: $s-108; } } From a3ca905f37259eb33ff4d8b0b2061939c2a4209f Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 14 Mar 2024 16:18:10 +0100 Subject: [PATCH 120/136] :bug: Fix uneven layer opacities --- frontend/src/app/main/ui/shapes/attrs.cljs | 14 +------------- frontend/src/app/main/ui/shapes/custom_stroke.cljs | 3 +-- frontend/src/app/main/ui/shapes/frame.cljs | 6 ++++-- frontend/src/app/main/ui/shapes/shape.cljs | 2 ++ frontend/src/app/main/ui/shapes/text/fo_text.cljs | 2 -- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs index 43fb21123..5c148d26d 100644 --- a/frontend/src/app/main/ui/shapes/attrs.cljs +++ b/frontend/src/app/main/ui/shapes/attrs.cljs @@ -148,17 +148,6 @@ attrs)) -(defn add-layer-styles! - [props shape] - (let [opacity (:opacity shape)] - (if (some? opacity) - (obj/set! props "opacity" opacity) - props))) - -(defn get-layer-styles - [shape] - (add-layer-styles! #js {} shape)) - (defn get-svg-props [shape render-id] (let [attrs (get shape :svg-attrs {}) @@ -195,8 +184,7 @@ style (-> (obj/get props "style") (obj/clone) - (obj/merge! svg-styles) - (add-layer-styles! shape)) + (obj/merge! svg-styles)) url-fill? (or ^boolean (some? (:fill-image shape)) ^boolean (cfh/image-shape? shape) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index e855405a1..43c9d607a 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -476,8 +476,7 @@ svg-attrs (attrs/get-svg-props shape render-id) style (-> (obj/get props "style") - (obj/clone) - (attrs/add-layer-styles! shape)) + (obj/clone)) props (mf/spread-props svg-attrs {:id stroke-id diff --git a/frontend/src/app/main/ui/shapes/frame.cljs b/frontend/src/app/main/ui/shapes/frame.cljs index 64bd709f9..970e1ce7f 100644 --- a/frontend/src/app/main/ui/shapes/frame.cljs +++ b/frontend/src/app/main/ui/shapes/frame.cljs @@ -69,6 +69,7 @@ y (dm/get-prop shape :y) w (dm/get-prop shape :width) h (dm/get-prop shape :height) + opacity (dm/get-prop shape :opacity) transform (gsh/transform-str shape) show-content? (get shape :show-content) @@ -92,7 +93,8 @@ ;; transparent). It may have been changed to default black ;; if a shape coming from an imported SVG file is ;; rendered. See main.ui.shapes.attrs/add-style-attrs. - :fill "none"} + :fill "none" + :opacity opacity} [:& shape-fills {:shape shape} (if ^boolean path? @@ -171,7 +173,7 @@ (ctl/sort-layout-children-z-index))] [:> frame-container props - [:g.frame-children {:opacity (:opacity shape)} + [:g.frame-children (for [item childs] (let [id (dm/get-prop item :id)] (when (some? id) diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 39e13482d..47b32bf52 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -70,6 +70,8 @@ filter-id (dm/str "filter-" render-id) styles (-> (obj/create) (obj/set! "pointerEvents" pointer-events) + (cond-> (not (cfh/frame-shape? shape)) + (obj/set! "opacity" (:opacity shape))) (cond-> (and blend-mode (not= blend-mode :normal)) (obj/set! "mixBlendMode" (d/name blend-mode)))) diff --git a/frontend/src/app/main/ui/shapes/text/fo_text.cljs b/frontend/src/app/main/ui/shapes/text/fo_text.cljs index 7e2ebc504..1f7836cc0 100644 --- a/frontend/src/app/main/ui/shapes/text/fo_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/fo_text.cljs @@ -10,7 +10,6 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.geom.shapes :as gsh] - [app.main.ui.shapes.attrs :as attrs] [app.main.ui.shapes.text.styles :as sts] [app.util.object :as obj] [cuerdas.core :as str] @@ -192,7 +191,6 @@ :transform transform :width (if (#{:auto-width} grow-type) 100000 width) :height (if (#{:auto-height :auto-width} grow-type) 100000 height) - :style (attrs/get-layer-styles shape) :ref ref} ;; We use a class here because react has a bug that won't use the appropriate selector for ;; `background-clip` From 1e9c6f3ebe89b36b8ff9d2a8758f9be3712e89b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Fri, 15 Mar 2024 11:19:37 +0100 Subject: [PATCH 121/136] :bug: Fix main toolbar positioning when rulers are hidden --- .../app/main/ui/workspace/top_toolbar.cljs | 2 +- .../app/main/ui/workspace/top_toolbar.scss | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/top_toolbar.cljs b/frontend/src/app/main/ui/workspace/top_toolbar.cljs index 406d28fcb..979c84e19 100644 --- a/frontend/src/app/main/ui/workspace/top_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/top_toolbar.cljs @@ -119,7 +119,7 @@ (when-not ^boolean read-only? [:aside {:class (stl/css-case :main-toolbar true - :not-rulers-present (not rulers?) + :main-toolbar-no-rulers (not rulers?) :main-toolbar-hidden hide-toolbar?)} [:ul {:class (stl/css :main-toolbar-options)} [:li diff --git a/frontend/src/app/main/ui/workspace/top_toolbar.scss b/frontend/src/app/main/ui/workspace/top_toolbar.scss index bc7850c72..625e5384e 100644 --- a/frontend/src/app/main/ui/workspace/top_toolbar.scss +++ b/frontend/src/app/main/ui/workspace/top_toolbar.scss @@ -9,7 +9,8 @@ .main-toolbar { cursor: initial; position: absolute; - left: calc(50% - $s-160); + left: 50%; + transform: translateX(-50%); display: flex; align-items: center; flex-direction: column; @@ -23,13 +24,19 @@ top 0.3s, height 0.3s, opacity 0.3s; - &:not(.main-toolbar-hidden) { - top: $s-28; - } + + --toolbar-position-y: #{$s-28}; + --toolbar-offset-y: 0px; + top: calc(var(--toolbar-position-y) + var(--toolbar-offset-y)); +} + +.main-toolbar-no-rulers { + --toolbar-position-y: 0px; + --toolbar-offset-y: #{$s-8}; } .main-toolbar-hidden { - top: $s-24; + --toolbar-offset-y: -#{$s-4}; height: $s-16; z-index: $z-index-1; border-radius: 0 0 $s-8 $s-8; @@ -88,13 +95,6 @@ } } -.main-toolbar.not-rulers-present { - top: $s-8; - &.hidden-toolbar { - top: $s-0; - } -} - ul.main-toolbar-panels { display: none; } From 51c2269c84a657a7f223ee4d3e155a454bc13bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Fri, 15 Mar 2024 12:21:51 +0100 Subject: [PATCH 122/136] :bug: Fix subactions toolbar positioning --- .../src/app/main/ui/workspace/viewport/path_actions.scss | 3 ++- frontend/src/app/main/ui/workspace/viewport/top_bar.cljs | 3 ++- frontend/src/app/main/ui/workspace/viewport/top_bar.scss | 9 ++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport/path_actions.scss b/frontend/src/app/main/ui/workspace/viewport/path_actions.scss index c4d346603..e64aa4ffd 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.scss +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.scss @@ -11,7 +11,8 @@ pointer-events: initial; position: absolute; top: $s-12; - left: calc(50% - 240px); + left: 50%; + transform: translateX(-50%); display: flex; align-items: center; height: $s-56; 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 0c7d6b01b..2e6b5d498 100644 --- a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs @@ -41,6 +41,7 @@ (let [edition (mf/deref refs/selected-edition) selected (mf/deref refs/selected-objects) drawing (mf/deref refs/workspace-drawing) + rulers? (mf/deref refs/rulers?) drawing-obj (:object drawing) shape (or drawing-obj (-> selected first)) @@ -69,7 +70,7 @@ [:& view-only-actions] path-edition? - [:div {:class (stl/css :viewport-actions)} + [:div {:class (stl/css-case :viewport-actions true :viewport-actions-no-rulers (not rulers?))} [:& path-actions {:shape shape}]] grid-edition? diff --git a/frontend/src/app/main/ui/workspace/viewport/top_bar.scss b/frontend/src/app/main/ui/workspace/viewport/top_bar.scss index b83e795d6..7d922dcfc 100644 --- a/frontend/src/app/main/ui/workspace/viewport/top_bar.scss +++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.scss @@ -9,7 +9,10 @@ .viewport-actions { pointer-events: none; position: absolute; - top: $s-44; + --actions-toolbar-position-y: #{$s-28}; + --actions-toolbar-offset-y: #{$s-6}; + + top: calc(var(--actions-toolbar-position-y) + var(--actions-toolbar-offset-y)); left: 50%; z-index: $z-index-20; @@ -47,3 +50,7 @@ } } } + +.viewport-actions-no-rulers { + --actions-toolbar-position-y: 0px; +} From 80370e39b590f6f281d6f06d6fc07851a416960e Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 15 Mar 2024 13:56:51 +0100 Subject: [PATCH 123/136] :sparkles: Add new copies to the release modal --- .../resources/images/features/2.0-html.gif | Bin 0 -> 325556 bytes frontend/src/app/main/ui/releases/v2_0.cljs | 145 +++++++++++------- frontend/src/app/main/ui/releases/v2_0.scss | 8 + 3 files changed, 99 insertions(+), 54 deletions(-) create mode 100644 frontend/resources/images/features/2.0-html.gif diff --git a/frontend/resources/images/features/2.0-html.gif b/frontend/resources/images/features/2.0-html.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e10f5ad787f1a117273b02aae1a408def8565dc GIT binary patch literal 325556 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 wk!^|Yo*jV0@do(= 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

INE^U5$sa>bzbs^I( z_uP;Dn7B;Apxd|AKT)$N&`Zo7l*EMq%=8k!h`8Tep$%qL7z z(%5(8i~H00*Di@ai@$oGH)(D^dtv!|sTTj*flF5pZZW9hp}pLx&qq$a?B-9u2*uD>}CxZk44o|L-q)PomGN-_Gde0&CpY_zPrF$ULUrf@ZLFd3ze*#T*( zlmWfZM+pQ_ha)h)FFsA4Ik&QH^ zE~R#o|J7a)uSBzzaTGgKN?z*Ql4s|k+eeGCw_ZTd+@%SVg-9a?K%pE9VRt62?tJk& z^VYvh4mWpyUNJW@r>ChcE^fA$UQYe23+?)*IcpsMVQ26}_lK?g{f}zb1jmk<{t`ae zUpDvME7>?QdEvT0$@_z3?)DWUo0ETU;rHQY;lx*3lDKp9E{M691*UTnF4^MS;jq!k zW9kEvS330vP<^V!je@M<>34$IPrIyc|dvNlOq; zPmpX+n16F=l>xIhL%k-%R+FQ8QezM7t=+%g!yN*E)Hi}qRyfH4u>3~EcTtLo*hR1n zrMm2DD+B!v!1ol7;IboAnUo_WYsZs;OO^?^PhJD(QH5mGSXzpBd&;b6qQ_v$)Wej) z^ZLgIE*ijMX++dp?6t>)aJBTS1=|iof8u)BVWVwymq5_dGQhhRVAYMdm{~e)%^m9= zRJg_eMmD*D!@I#kcdbS`*aV)>b!^g0aim0Na*$r0`ffofMd>M}I~fJD83l+;53$UL z)fo?CG8vwkRje4T?U*7q@;!&QGn=ON+9fq#YV}F1UjH>}K90Lj93lskvxDjRS)4y~ zV!puTNS+!7ItzjMDu*~oY(uW-WuDWyxomi|GUg^D|K{>q=8EUd z^|hPldNWN$uLlhxzfbbklYQ4F4L*sc^`1Lv2TSKCkNxT^#pKvbs zeo@E$lA8OBx%*|i_sdWH??ZcQ@Zv5OWlckr`tj6q&tdm&t99;kvAp*Cg?#+^v{O>D zqJP zw-P&Whp>^y=PM4jB})u&`x*DZc4>~olBecluh@{Ey{v%lRibA~`13qPnQ zCU0b;k;;f7vj1K-vd`c?9#xZN)UZ5U-Aia#^=kN1>v%5zMk3juVv-johZ>!%AtG!i z|G0Iq51~m9is|o|;{Ro79(b~ms zm4@Sj`&*d>?jlTp3M1{*TafBxQgACEq_FkOBT(q+Ht)CI+$g0yfO+uzFeGUbEM=W` z>g%=OD{0F3y3<6sE~8b20Fnnh`gMwl&W8E3z^|v09%XtnzeH?`pQ9Yfllt1IMCI*s zGJOf)TXiZ+2Uyg%=pJBwa%#?BstUZ+7WhQXzhlI8)$3`{pTN(1PcN=Ky|5DK-yHZk zMC@#hT^Rs=6_4l$7k$J${c*Cy@wDMhfYZL}5eo(v_l5P4sI2wE9K`dJT8lel0QwSN+T#ZZX24B0m}pq1tyO8gDy97C zb$NQac82<_lWD2Hm8~+OokCEzuns*L$j(07V}Nn^{j@#4=b-)3)3(AM_0b;HuBTcF zJ#B@}8g)+S&*8G|Nf+ZIaW)WFG5{71tl9%Q zVfus50pQ{NFiyK?08p3$K$H7burHukpzb6nSnUZU93bli3Q-3ckikCQ{V>KOpDcjW z=!>UR5Es%YdcD$10&-;%tTqV>wQm&J01k$5pFuz_i?egsdpHFo&xEEhADxb_%c*Po zF%XybHv(b;lY)aZn4sa`VWa12Q;XU}M?Cj_0dCHm)WX6n056Y+1K|vS7akr!gt>FLtvsM>ESL!q z6yycc*?_08kaPwlTMZn+LS{KZO#l&594H-+j3t8+9H`-qJI3Spln9YFclELU~2m^pj3LnG!{~chdlKQJ~88-;@P+Sp+*qn`VMfT z!6|um9)5HoU$xKmz_Z%tTg$QBn7}~y9@?2%`qA0c#Mz7sv)Aiq9j*l4;F(MRH=Flu zHud4laUlxA~+0RJ2+%ai9G8J@5K6WcS+Mpjepdd^>7wz(K+ z)4lAlxa|1fvXk^Dm;aXY|M~0@5a9qgm)X8S=4l1wu5k*tB`gpB_U+YcC8Ss3IeoH3 zkRcHU*??+mE?wFHU=5~1u%KIipuFGUm%_PtO~`ow5J3SNke?h1f2TXyt`ZJ_V&TUb zWLC(cIT<`J1=j{doF{48m{3R= zEOs1pJsz+NpCN=JJtzRfN#wDOAka@(4hxwRj?^czU||5SNyLFZ0~ScRu&vfEhK2X3 zyjEg`1^rid(P;joz@gd0N^2XaN0j_;tOwy6Bdj{XcKFGe zSycIgCy>(xfb&gcqiVQm1Hkur=lODp*1N(-0AKr3y(ikvKsAW~EiT>D>D_M}M0VpD zi)Z0qGypycjbOdg<$zQsLBES$XF6~P1b=@WbTM?%j{I2*3+HhH5}2P?G$6uSs|n&) zo*D)Jz7EHu>mZR>tW%H!E`*g-)~5M19pb+`;7HM5fL@Oi?U-)r-wss>JMp8 zEZrRe!^n_C7C3zpvJwBq`5C|pfI3MAk6i%;3vV4XhFKaodT=78w3OW?~rmP!QXU1|MyMfyS}^mNxKE5yG74;OWyA?4tC4m@9s+n7H$0ay2z`S zgK8yISk`PjtgpyB33A*IGbAq%PjGK$m;q;v%Q(G62FMb!LPr9$!ojlP@5=v=q%(1c z@_qa8>@&tT_FXgf?7Oix_AUFGb*$NwJ#8~)Aqm;iK7=TQ5E5fe@)aUNHFiltg;4X( z?|A=%=Xmb>c#iA2uFrLzxuEI4$pJBtpa!so(;Mx)@zVOAk@T-K5+GXc=b0+MH+QP` zl_0t(@Ktq)eLR~nV}J!yMr9&A)qg`)q0#j8>%PF#j0Hmg*u-fbF#g6en-A(#iVGUU zi5eSmq}ld|+z=8_qN;D0g2DGqNfFyN2#^Ib1Lp9+;hf=<)Xdz=i7M)HfP?&=Ugm?JEKsWEC76T(m{OqZ@JQKIX5>0DveO-(unHw=hvUS@nqYk*(irz+x!b)K zP_+)WODFk)i9|#w-miMwEEmDfZlUV!OvuTB3gG*1?kpVTfCDD*DAVxk?7Z@!745;& z3vYNeWjxBp!^YsEq)G3FMP6Cl0pO;J4Gv=}BYb9&s)zhThg&gQ+j`(yao%WzMH;>b zU2qzQpg<>3{S@JU!hKX0No;}B(BuGjL$AwTqX!y_>ZMLNE;YU`Q9!8-amYwF*+?gY z;Nmg4pJb}GtV7#zJ&5Q z>Md0yIvTF@KOZ&vWTbUMnF&c!yM)y+Z?G?FUz6~#Xs;5B&m~XV3@i63=i|iB!x1L} zcz3lXE*aI4GYV{$IP^E$2o&yu{3UL+I27_1YDvQljiCi8@5k@&2t zSgLt3WMg?BS$R8y$MH~sOcBTs?*F90+AqIm@5kb}k}OmZ6n04?A+D<`>mXj+!}SF) ziE@Bv1G4whxOCG1Eun=@@ip(qq{7-)?)L*9i^aOWsl0zNr21f3PN{yY zR7Ozu&9MAe?P58tNZtF?!>^BT1^7f&J)#!*tqAxl$T3BEUg`+vl&THaMU2s#*^Z8Z4+c$zF9Tp2DhApU9m3f{2O(W0J z!ICctVDVu*)XI54(ftifxl=O-ANocSdHhrBSU3An`%4j0q%uZB{h=O2tI z+v+|Y8k8S)x&2oAi`JUAMfwIq?|5?Q&GxPCK;2&&%Q(1(y9@i>*d^YW=Vk&$JI}r1 z5`_EKBa|>MmUcr6Z*+BkkS|a)PH^QSF4+Mku%IarnM6t=iLHlqogz-#l`EEFv_W zGzZCo$+E-zTp2kX?p4D#s~vPiPFy}Lxa%n(zvRuU2n%-Kwcfw8MOu&q4% z*Ufgk!?TrZ80jkv7FRvb+Q|=bNxtarARaO`1aZ^S8!6Kurip-HPSVt-p!%YFmQ3wtD{_XPbQ{3Aq@8)bpOsdk2ge4-{x{bYa;xlU=2i6 z0VotEeJ-2Xm>Wdy&}mSxuLN+tO!GFWuDK9#G5G zxckabL4eVQyby0`xLS6@H7i(QcVIUpt5ZaLBemPsYSp%%l%+&#MCVq?7t0z)+G$M< znp9?|@Wd?FYo;gFcw}9MUGeOP#c$~->$7h|lA|(xJjWWuZYtFTOQ#F;(;pBLV zX1>|GNg6bEoX4CN+96NU)lB^3>%`d-06y-HHJ3W}v+G4z5e|>P~=AmtY zcwgyx+LAzxGv&WoQ=}H63<|&#L_GZkJU)w(8%lI!lwG2q&-zyG11#Bu@i#U6%0+%+ zGgU8j3g6{Fn)CWEl9NrsTV{VKXSW>8TjXUC?K!)20)8Q{<5g4U^O*OX@17_aT;#r< zOJqSNa8K6$i@Hi`7&u4mABi?`O%u+5g7G-^C+Ms|R=lwq1-%6H-@S)^`Pl8#%}Az^ z9_Z%`&V`}*^C!+V+e2?40erE#t_esh!= z9xx(;hx)Bc{}=j6|J8mImp3_suPol~DL7BoA>k29Nf%wU2 zzfFr(mNWEjDE1EIngVuQHl2X#clEj9pJ`ld%_UkT#70%0zos`9#O|JBCYJQ#h$wCNP_I@@1c4DHy=5K!#+PbO|$`ZQ0>) zJ1_mcL9n(iAOmRV4UJ}LcE6InoDE(m8FDvwqudQ28#av_s>6TELq6(8k-7!%Y5x)9 z-Fbi4;r%PGb%@Ua^ll@}O028&dB%+>`np>udXoK;FhroiWRVYK7*9DD54Yrjx;Icl z2$;-1wt1!YLs2=p=BaV?Ju%@7`K$~LnLbUKK6zB1Ms0?odY^7mpB}jntKIiMN@fK2 zeqxW&X$4{a9+O|@M{WfnX)OOA{lWp&9uMX!r33Lq(|8l9Bszv{afuE+nPpVE1i*}u z{jl)Vc&g_*x#E#o0su}Ee$g78bIN_7LHg9_Op&TZ_t_4hwmZ{Ymu&7+WbRkg=f6Cl zY0)Q^W^BxFHIQL>uF&+>$yUd?Q!ZJ(?OGO&Ltvq-P9UH|kwFe(WL_cl$3lu$`k;pK zfKq7_Nnw(s0xWgA-v==u*kO$ONe!uG8|!=a?5GISFreVwhn*a_c&|@;bKvTTr9n<> zkc>@mg>~BG-3Io4_jri=7)4&6!xR9HtQZ6`2r3MSx3E%=Titsf`qZI~cW-7;J|(Qo z>U3v@kvB9VEi*Mg(*B#yi7A$&i98KiK^*!jf_S<|zX2M_VJXGB&rX=)}^#}?s;#`J&wE0YO25L#S#Y^Ew+&I9zi+5{ z^jrUEg?NTx=g5|k2M=@Q%vrKQdQaCtkhTn@+?qM|z3bWA90 z%;rkI!(@{~>!DLM-o!f}>d4}Z&M-4D-o&Yj!F_&^?mEeJ8yXuAi*<&&k3n40puXOY z35e69MX%{Dy4G% zrm!x{WHa!O_5|%4@WfE#i}X6V$Z5}tVG~|U8JbMce0Q7BY zPnx%k8Z0{sg-ss05XWiONMR=tDNEBNh{G7fJpvkg;Np*_SO~jHra960-u@xKleYA5 zZ?XB~H#KE67HEv_<~r^lQJeTJel?APP^N4yo|8A*u?4;P!P8$-k!@RUEw( zpqMZ)h5-~Kyz>;WM=}7VL(}{H(;PEim%;#72c|Ds>SXA6T(X?WxP0xR#|$-WCR1nT z>Zj>H7T#Rj(}epo`|eXZ0``&&qLMJlVx5dFejiy4^`wvChQ_?SN4M<<&P%ZLbVZ*O zO@DneLv91Oor$rFA0Pbw_z*fv`&1=>nl0CvePlUX;W1koHcR{OOey_?F!_wMe*2xa zS0N2h7X;a^nn`xVL48W8`mtUf>kwxNux=aZLNYLY${U|N_kuFlRy@~U>Fa*^-Irz{ z1_e?VCglr|U7RTnQxqQ>1^*4=5J9#Yb3RA-5P5$#N_Ir0(^HLOy1Hfl?ZEuV)ck)d z^P|7#-$DIt2IgPu@T#z9t{gX8rIGC-$fy6#dX~b%reJ|%6wkEjrvFGr*f}KtNy%oe zdCK?Ie{+%tM9Co@Og!*{K!&8S=c3N%&j03?{+nCAAMmv$U_I=!Bt1ZKEI?=|VBP=o z>R%#5BJdTI^lHUlR~T$OM6y7AbXA~~S3_qwb=?~RPp{14Xmt_asfx#AHJmQv&p)Es zCT(<>46qdg;>lp)QDG?zIF$jG!>>wxdc974d4VIIuK2lcvhO>7T4mlx{fxix{A?`L z!DMOrH0Dqu z0d`t<-p+A4=`X|PLs$`K>*3|)XDeauv?cw2K0&JCa$Mm>600Hq!a}%O@v7lxTfYR9 zgooya+Jt+CuekWG&f2AXddBG+m1gE)Ly1Pi6+Ks8UGuwVv67-I=dz`eTC#Sbt10P9 z_1sUKW1+~M@#pf|qmc^pN0-Ugc(AeX`jo%_2Z!kozgMX#>zUN`EGxfjRqNTUVGfMh z9IJI}^$272h|@PheX61QmkT)Vi6zqU7hBo7cJA8usHx{NN1M%h0eo`%g_oTSb;1bbrVaS;&vNV3rw>9NJn-5Q-<8{J8rG(p~Yx%Z6~ z#d_t)=q!mWPPrYYp6MQMbyY5iN6wGKfow^iw6r1jhkbdwx-qi1Uj1QnbT8&f%0|Bf z#34T>e=F>!m8YXIyzmMoX`34PJGAu1x89LO)f50So-mg};24XY-~0Xc3qI?H}xx@`exgOxGr4D*20@YOIjp522KW6S_Zs zTK)L-U}0DC`(DYWP{4+TFvSND&ZC>@M;J$j5#Va8%n{>~r%sLZ=W zY~Zl-_H;Yp%pC#h4yJWS?DdZL^p3>Zj^w)?(H{`>DL>~}vZO?`A=g}8vyp#wo$K+o zeC9X6YmPUZVKHG_V{PA=2Bs=r4Uv!3No_#nt$22!M2UuY&4=5tX`)!$ceT&)AsuI` z2j-O?&sS5n)~Q82XJNFsOg_Cch5kGJoCycA6jy~`{HjT2nO`i`DE11$2d^MDYQfg2 zzfxn9>{EX^wk0{_B{{xMI{h%o`PnbKv%l=sk}dUqxqJOig-+eP&s@DG6`AV2JA3#g z=|SwRD;=dNglR3+Vs&Z0p^l>U-$j5u=aWSB)NKicL@lqM63%P4V=mB%j?+Ih*S04P_N99%yL#i~aQ1`czGFD|!2*TdApD2g&kK!D&cqvJu@RWpEy=wVAN6nj z?5YBg)s6R$e&>ow$?{zY^-7e8PeBI$2}}J0?*HJPvQI;^lhta=CaA{M=#iEFw40e;{o=4Lm6H79@Y!1W zlh^6Bj}M!!rdMA*Yz|DXOr`mWh=3I%+-Y7!M7rhW*Whg#i#@<1k$%ruU{uZ!q#YFnWC(V}b8Z zb2tt=FZC=(L?fYMrm=h=3nijRhQ%!OgbyIC+~gW&--frVCc9d)3#jFAo*SyVb}1*_~;+{h#Yt z&h3oJv2yD|)f@ccZSU7}f5+@Q-mQ;p30+h6P@Ha`Z}0y4ul2iLJY%Yr^I5pjot-G~ zEwyul_h>&Olq;hC9>Yp1#M_#OjEIbL{7=JN4(7 zCLT|{8&%Er`l8POkytblQXY28H>zjFGb34NhLNE#2EFAUqmwejWsLF^4!IIry+9Qb zUG+E%y^|)Deey|LIZ?JLYcX6+Fzv(*o!ObmsM*q`S;LNXS9X=U$=>YPm(7WzH?3Ez zLN7QNd=x8s`CCr1crHJ6RCg)t_DY(!)yI{>AnI+If_9JRb`E;uy`Qy>|MYWc&15A` z-bkLk{l()9bRy78vnopvd1W2v%kMCFBK?>;G1iinZJ96(Qm-g&wX_;6ZAoIOrL3_!yZ}m0>XXF~}k%lpa zr(tg^8vFm<*=%~XVJBDrJ?6RH$=Yh6(2KL3KiRdW(+X#67Vc2xJ&AycFIOKrlz2Y6 zUIG9iWGm=GohJxrOs8Tq{uxrS0uMq6{qkL4%dVd)t-LaTG6!={I`@G!mK)4j3b;;| zK-B2oNqk}46V)Ni_08Ku{MdNSVYyq!#ce8gXaB=KP6n^3ne>D^Dj77ox@n9b9&3%6 zvKu$Q>-ra?J>I!`M|;8^?k{(zvRY(Wdv@>;X~5{{)Nx>Ah)v!b zZ_2J(!TAij*K26Tu2So-hm`h5ttMvPylFUbxj3Xc2Fly%dXnS&iUZ_1b zkA8Dw%;Ber(ayk6uFmFrNg3JcW*vHlTCKD`gWvWS{yU+0S(Z1=$ZkIz#$!;^OQ*`z|%TR0ru*xv(W_<4{9+Gw^k zlo_W19%9E|Ml6{j%ih^m9}JBP4(9V+Gpm+@=hMOSKM8R0?UQhCQ_jk{4ABF8@79|L zN8L^gS7LRa#BM{T$uS0XHA^&Urd)6}o;kP~{G88SMk=+#Omg>%pk?`Y$87gzsrsrJ zE(NRTY`5A)LDH%rP2{^+#h8Ws2RC;Ap^%hk_(5k^fqwmo#@v+Vvgzht0l=SYRQQwp z14T606al>K$=Yv?BLJmk%n-`nM2-oZ4LhB|nZyVb>Sz#x-e#ri$nG4WgiK{f8CyOh z1IDjG5mjKY=cmzO{6W-{cvBwNY9bX|b&|USL6$lWBjRXOm3VHd3`*cD=$An7gtOJu z#j40vNN$Mwl0bA(rhd_og}m9fGhQ5z#yW-T6bqh9tcX9}$;#9Y)c+=a*6)F0=zF>F z$wh(wby!rXrhEidDevMg_X(!47p<_ELL1&ZEzcu>ZE>ev(h&wCDhM{BXaZXb!?Y)K zn`+`+1~T;~iPqD>%tne?Y@>aM8H9vk1c9$z{38 z#}F{l#hpzMO)~5JartsusO9%tf;W1{K({#}nH`Kb9Ti398rwioT_Q}Ge*uWxHj@#h z0gccY#LWmZu)+(bhCd8eZT2^oXoH^wiSRvT#xhRlvS()pWh#n@{B7t&2Cp!dpXlW33$^uU3rk) zq0?K~K0>J{^bTE>*8&HN9nDz9?m{>P$lQQFvfdaT3Tsf{_9lRCL`}k@yn970>|E(( z{6W{wc!S&VY(`l?uqmAcYa+lz(7-{R1F+;Co_fOOv_%(GRsGE>QBOTFChTLcm=EBS z0A?C_(w)TZTH34X-J?AITdkyUk@N5DV#iD}Sx)dKGAt|d^Z*MGkx?1GQ~z;fNyVvY zcwXi+lK>Ze>P?mtCn7hydIgt<)RJ3DRt^Dee&k}Fj92;i^4vX0fouh4nhwhLnS?2; z6Rm<8s2ab3U<_9sS#-XHBFRxCOponvAW$Ea1CdEXAdXAw!*C8$a6~)_l0u*BIp7_- zFMSu8mDBO=ehhnb1o0t1duAbLua<-7C)(rT>GJ%Lw}&lT$zQM!w*72JKU2>=U#z{0 z&D@`JD*suu?#HWp*FTzdpYD2O{NvOK z^Ym$Ny%*299>kuz_zf?`-SLuBHtAivy?X&~aoeZly3Dh4-8=tvEN$KW!hcqz3u`s? zs%$^%o8HFa?Eb0uzoiQABb+%zbx6+Jz!RnC)SPJXNM!=qq>TWT-R=;*}@;ITfuA9y(R>1apd)kj*5pA+LI;-7>cW%I-} z6=4DDy@0fWETiGT7@JH&mJk(_c_54|!GwnrkR$nLXs9>$$_Uk_6E|{2Im~97%fi%y zy2?mgAk2xqGH#!1f7r^InIA0AP2(x0+IYQ?Mc_DC<|r4_PZ}TF^p%nJhA}I?K}eypuB0ozR&tz+w8V zaY#D+Hnsx1_XndPC_VSepC=;|Ma`VA3Dog6Pjx1#DfdbJlakrUd=O*VO+m>y1~E9C z1w}_bYWvj0V$OY?*!X^jZMb~5Sw0}_vG;Y}ncEXU$V}EEVTU$(vEF)_&L-`{?T042Wv4)87)dD}t_lYql7_g<<$Iy`nb-xwr}ACPP)aF(DCV9^ za0TUfa>X4PTpPR^U%{2NZ0)$h017$T%^5c>+e_xnL##U(wVL?esH-@d2vCm!c+$-}G#2nsV;Smh>sgl)J%uMh$_vM0O-Q}WNt3nS8 zbxlJ3%Oy8Blr#2oZb$Kem^*tFX8;X(_eh(?AHa z%hs2Yt3p$e6=xIVtmNTnfbOzOW6neSM(jKWR-(>G}UYowiaS7d)IVUP&%r z;YqNjhCkM+T}iPp&wL=4YG>^@n(4x?kX>GVN+%1=5(0i;L?9J5jiLQ{}r&UpSagiQ%0|OtZ8#j zR4#Y)D_&+WclGOoswd7a8yg&vNz{n4!KhkE#X6}cC7O!$i;5+#nTfa!joQ_UrVTgx zs^ssJ*|qWkbV^e_u1WLhbKR$G2kZc|Z_hoIS^}b5nsC+Gm=`HeU!(_d&lBK~;wL3f zJ&;e|azx%VGmlJlyTWS+KPz>o#3aX`G(%f-?|#$z_4Jn226oe} zUr^bcOYn9%P2$eNu#v>`@UD@y%l)MOeHBRW=ODq>R;WI8JK~r?=~aZ3Y*`{A-!shbwhpA%^vHO z+BCG<>hn~s_Lf?jwbi46bvygU2V+0^yna8SvTmaCVek7_P#i-FvLIUjt*d?^;krhe zc|&*{Ryd}kx^8Pr^~YZQk1JN$uxHyao;4rv%iOJbxo7K(vE5wcjgrlupg3)3^Is;< z7^3yvRAp^`@MeJ8{vEQdA9$Ec?GMwls%LNRN7b{#dbOh`_9MBJ?;qIKRKeN@--l+^ zHg;8hbRB>g+F6IYNHychq+$oCCj$2kSL}4Y$p` zA!O&$HENpx)+Y!6ZUp{W*Vp=!e_<`O0J>v_1{ zVV9n0s%dHIJ=Z#=rEUFO+v&O1w}D>8rpvTO-Cs(3<-1B(wXoCbSS@vKEwXLt&l7VA zC)S$Kh7F=ZyJ~@CBYU#ic7}={7#fnu<691v@snq2;o!|UZf(<4%|L#M>!{~uLe;v7 z&-Ze*R0_59pZ?_f(q!=Xr{#<1Dr*TC_9lzwpN4&jHhvaHU@g?cb+gAwT=&n(R%HbU zYM*}HeEOZXL*On%_Y0gE@;nj`#wwF^z0JYbpG&GWs2(+{x;5KCb`6+2==}!ktG^6M zzYOgmwr>+LzB-;qy{erclW)Ji2WK- z?>PHvbDwIke5{4`g>bJWaR2;`W>2u;ZpDWr2Zbbi9+|xutM}F0>!Q>#1RhkC>x6l= zh6U;}&`H^8$&oDi<3aO@IUOsl7SSb5n~Tl($0_b$-C*gIpzf6D*L#)+8J1(MY6oVj z^NA)(O_kx>dl4HlA+7P;dgqy13c;#p^I%cJBwgoz)u9wTcrWtQb`(k5-R*_Zi4@zH zUxLmi$G+8yefcnrIoEo$li|6PqFRxf{te`nsLL2weF)Igd8ZfKaq{vPy(?=kuDCr9 zUrS2J983@+9ewXrjYwAA>?J#;eC-PzQ^xE?HuyNAZhhY7?>=zy~FVK!Iv}rhx$Gqw1iej87~6aR&H1Ev?hq)q0Ps;XXBYJ4o*?-WP)h+-<~XhR==+UOntgpEK;tY-2%&-pY5p zeR-+eYpE+_$&Y!sw?7YUJ|XL0`ryuR1n%{^FV--CcO-W2Qv5>#aQN}q+q6qkul$Sj zKTawSnp^6{91rCg4PV4&Xk92u{QJ`U&oH}TR$phiyus|<%Ol)|sGQcg3;4H%iAB$vm zZ3pdaj>I#|g?X6M@n+P9^QpR}M;O2EsFT(HbHx`D*WMYYo2RNg9>1d>INV?VDSdzA z%hMCG$mAN=s^#&=dL6?8M;<@EytEt05!PMb-_c@&`0nJ+n7h+|Iv=B-86V7(__{oo?`aA6$9&X$Yy4*B#GO?mFA zCZC143yc3{g-C$%pHAa<738Y@riRjsR)MlBBFZ4Vr=80v-34PAP(DF#8b#0rwZI|j z<84aewZpp5c)V@E*K~3a3lOl6B})Jg>1goq^YsS+x!v%lM1z28bA+gS+go>jSM`y} zIQ_zfJi{&Latd!pON$PlfllqjoZuZyZqzyNAlRw&22*H?Q$)+4gthMt>VPw&*41G= z*}klsIvPZ)$eZTOR|Y4Wr-yIcXK@Yy~Dnv+#`j(8p^VUY$J4wa7{Z%e<3Z-{i@^Q3OGrQ6O+6cALyaQ}d0FEc~?WO+O1QvPA6S zTQnk70%`!rJn5&N)yq{tJ0g$3?c#rloy}kRo{1>!K?!-&8qAPR>gmH3g+D(YJ{T~C zk9fMvsjcdH1?YES-`x6md^_?%V)5PB0Oraq-^hnWp6<6F@_VdGQ`f%zQDci>LMSCU zbt}%7KE4f61%M>C(L}a<9Ef*Y5xzA<9LivT{n0?N`!rP;7O?st8RN|4L4!;b?y?0Z zVOT73%Lj!$pm^CA>~(V5uMe+t#-M8Sl!G{J6vQA~bck?2hV$%EuTc0l=mg88li=LP zS-{8?YsP1pWQlX~CQFI1wDV7FF^wFIvc9xYKUzmVoTYt*;x=>EGdz(o&QArD7dSPu zz?`lCLt$mQc^L*E@Hw8yBG7oGchYN$!U!nzTS(ajK{jEKqFNde8fOaxHUlyRIlh{; zMhPIq8H7h3k@l6^D<@rU+j-O%6xSuKC`q~c8KlTWnTRU%;&CluLSk3Mql2{ zP$UB~;7LRj8AamsV^F2$2@peO8x>@!hyNaq7_WVC<&%hSdqbtAio_qJgbT8e^zWrVEvMNdBXnxvc zUm&qXReCjgdU|9=)9vHYB<|xKPFKSo{I8)p{)h!G(`{3U=7tP`O90rp^5I^r%`He$Xu!!5$Hp7+Zr^FRcR z=5P+OV3AfP4O9-pAd=E>FN*D8m^NC?`3L}hNu7igUf@9C0I)b(hFJ4Ogvn5e*(UGP znU83YZY59-x&U%42Bc`0iX)oyVcnvbl(d*3Qyan?qZxpOzyV#fv*8ij5C*|50F?43 zP{HcBcF*A7Q>+$UR5(QZQ=66Iy)(X!uRSNIx)war`Jd6`ZZ&-VxCFAnH3{YxWLVd5&oj6i+AIVF(}_F7ENlw^yF_D0(fXu{+SLOmV zkb_NhH!k<42A=CjbiGPc{!{3R&1zdUT;R1wykKbGsa(zfA0 zR56(-#Ls$!M8OXqXSQNzegmS^{*IL8f>Y5dv*LQjQayD3s-vmgTeqLe#P5_ z4u_bsxZ9lb4C2TbRO%5YqDNK@heVVChu(g?H<)ZfK#l?iVGE!SL*nmoH*q+TKmd3G z=V65dE)&=|So^vF_~3acnw}Pc|1{%(NJm5O4We!6h+{ND70>yP6@;L3KNvxv%isn$ z-a9nV9UL!W2c1OzP_D_D!+`!{K&9B(GH58gh7J_DWV zIV#S37ZCWUv^Pa`XabD|b`TlO(Q9ji)702(=#WJm(|OTlNFO|~lzvWlLFjgi)Oya8P9{^0oAVBN~!wSCe$(b;M23p*Ihe{zp>sNu#2GGg?HsLZ@D2~?^2{W^m{8|WM z*6QbBTxF+>V~HZ=ZU&Ww20w2ayw@@wPduSiz-B%rW!U1rf8JP&*G*?v_;~b(jECzR zjLF(_7gJv4{@zo79%abTwz%vOwpz6z&&&)5qP9GC#JP)`@1m;_td=MaXX^-XFkb>I zLfx-~+HhrDzXH*OWLz()gp@wh!G%E5pLm@IYr;a_;H0&;BOoSt_2wsDLcwVDH4w*= z|Ht3pE;()YQ1we>FV;jf*Ane6L$n!i*$qb9;B}Q(HRi)0?qoMuZyGMHK= zF+Mj}f=U5AaTRRqgt#q!NdK<)MleMEI!=@7X*~v6D-`d?c)B#`zgZBz!{;jf+xX;^ zaoNwa9v%j6K#yylZf+iKq*mjy=Vwn&>B~-uEj|wq)A6j)HRQ%$7T>pWZP-hr%LNDDdpK$7IpTwBCRzg;06o_xFsi z3thODnkFsadT#H+Q^BY@!PJ#RlSsXkx;3Xm^N1|D58KbrIqa?-E++E)h>oLkpfS7* zG^C;td(X-(qc348I9{i(XSo%)){;;d>T=xM)3mKCDH9#BrYksrf!(@twK(o)aD1VR zodF5Eb?cmUEu@pcmELFRNX8Ix9$!h!~he;&T2_xZqOR?nG<=1+@J0kg`aZ0^M~ zH>A~4>|AhZxU9CkzcXYvEXC!T^hTpJAx*l|H2s;LIPXWQ#O<5WGcrcInZ$!Ul|Kb; zZ>B&)7YEob{myV5OtrPyM9WqBv4|pTf~u|1WTk;%s~A(>O3fUdqT8h(#HI3t1|o&i z(CC@s!sU!VLN``YRI@{4-fU!WV&9}cu}PA45tlO`Y$7S$(yGP!aFblE5>(VL+-<** z-&a=Dv2aIsvADPWuDy5ufBN^GX0l#IIwOBvT$%D((!ZJ)`oMY_&#@Sj3pq*&6BPkP zA6zicUtUw!yDB6_`+k8oHA7Q5Ybsj#Kw=;oa>qh}f|fjFqOEYGeXXOE(6kiU?8jBu zQCM=*AF0Vd6@P{A51f(i6sc^ix#Po1P>bHxKI8SJy>QywJR4lVC3?gk>|sT4nZ&C0 z=RB1eS2t2PNS{T!h64L*-5|XzVhrw68$|ulRrZ`YHPfP=1)GHxR!~()rqy)uKu*0=yK1KZu&dc)-6`nb zqL~jJ>Q1Xr0bP{6_^u=9YDX_b{_gXc+ZV5|Cg%+nCi=waD_BFYwjIC0o_&~n*``+7 z<+b4CWn79K*y|3GHxzFgCsX9KYh%)G_D2CGDaF)Qh4|F}F{{@&b5IRSAq7YS0weHL z6vLgP_a?{7hc38kzt>S*pvo&hY(qnJd{`Pi0!Nw_?|2%z;bN_1(hb$nCoX^vH=1Qb z9$=Ktk%orsm8OTMce|wD3p2>?{!{FJSaf{1n{&QM_wF|OVtcw_^HrUP4xYDV8K4rC zgX$T7;|R_>=xhgu8IpkX5%V|kK|2;DN6;=fi&1T8H8Q3!x|ljzH#lO==h0jbYA)2c zQZs1@jI!g!Y4_;|@isGHF?5JGBM(~!Gh2dA0C?}9+gy%VRsh)M#JPX?Yl26Be*`Y| zfj|{B+Xl{6&O1-JB%h1Memv-d&0%tM;6Ov!=EnjfUKFjUvoK){|35seqSnXEl(!b& zb&mq*MRP}m_Gm~w=P@1^cy*R{{(fO;JfFeDz5pb^QV%^ulp)0OWL!rO00B7IgWvw# zwD*@?Kygq#M*<|2mJ7o?@>n(#tf@K1!SKcqvSE(QqrP{DGcRp)I9@^tkA2UfxfTH< z>I34K9ylRO&)gg$NBp8phiew8{(a)jLFWxZBd`l>QcA11idf|ZZUtE#PiZ!v$8ouo z+7Tp}ivYpVQwW7!Q!$+{>E^1q;Ok*Px}V-g71roAR}A6pOaWIX{xuo{!!4Pu&vlvO z!)_*yW3Du57%n~}G4CgO$UJj?EHRI!4Zv9#ZmAFsL=WoVYv*DxB#!pxFIvzE51QI# z_{`xKh8n#Hr_3LTpJ$AU5ZM54x!dUH?2>@$c$E5Sb{{ljg)zFs0De|N@WVk<)!w-j zFFYNT;OPBehZBWv0(=IjQ=l`Ag=Gt5pc33(ZzR9ZtZ-`4|d|jZ64p`ZMmBI^wF*-m@PAV8cnA>HyU++%awR zV=)2VR=Z4p!1t1%V9v;SP??lw$?m@LtdzkOjt3nx>SyJ+G61|$IA|*h1}Jyr<5fV< zpG-7=DZc5g>O+ zI~oVOiQ-8eY^I-oJe+HA7JmtShF6xT<)fZ(!4t`P^Ptys*VFRY5J!atA zn<6FOu1g{Vp=ymVB6d^+PcUha zjjvxPWP1q;1F@FyZ3_O6uk#FQGVZp0dI+I}-XV057CItI2)&9(?;WIuB2CaFbOZ#X zNi!4y=|~rZ&=I65N)x3DRuDuHQEuLI?%aFsmzz(Sc_x#2GAld(?7jAH&7WOm0n51) z3NI%m=PQa>i)3q4CLY4!&e%gHZHwAtKaomoxu_{s8#H|gWy8!dP^9+@LV_0ZLW&3q zA;K8~r^NF%u%UPw*@ZcU%ecw9-}OP~^MPkYV~yt&5 z;^8FNZ3%LgXuiqNa~8o`G6^o3i&>_T9#Itl>i9x|T;3veP@oWC35Tp=fDF}3w_t|( zF2$OI5YSkn0Zp4c5y0eINEqUBCSXXJ!VOs<1b-nOM5}fZ0;WH6a^ry%Y$uV@O__-) zNR!05Z(RIE7%KRX9i7ajgxVNK8ryD;Gb@eEkM?(#3bwMt)DFC#yO*Vh7CKeG2%VDs zqx-?_+*@`tv&h{F@xU|eTL~Af&;zE)i{1w7iJWwWuoSW+Yw{3{053HNPzQ}4w9w*2 zeXI(m8#Y~R+Q#yF6-kJy%aeO}@Am1Z=Gog0@>9Gi!V|Trigx(J^gCY0l@uJ;xwm5r z1gC@sx~nBX>@mC*S&^oieR2#dN7RgMJIbB3~69e(PhmaZ#ZOw+h2}NrXd#R!?Msg9Admkj`y5rvPCkT4at_j4?7%fK z6-Xhwc!8IwWSN5&^O@_Sa{I7Ub1Vrly)lBif{)j<9RwM;Ld5^A!_~U6$VgWm30Mf& zt;e9qp>|Pr?fHOmgO;sC?C{5zbMfp|u242xkZ=qhB<_75A&DJa6B$fZ!;%7>&1VH% zb3ts7CS(X1h-7bp8RJO|@tlLV<`Rt_)8UxqP6?%E9JFRs-{~Drh=@ol?5->YS)Mh5 z-ot|LRlkHFU2#fWgAjE8I-_zPsofQuY<{-E=#AH+UD3H>5))cy*;r>~r^4W#GK6u= zdpK?MQ>=6+xZyzKKb;}sOTZ_>j|#dFOH|`Il@JEq`{eHb?mAbWv-iWsXd7l5EGQgk zthjhep%pPAolH!b@24*IYCL^WCjUyiFGu2;&Q{ou%7&rt!%cxA;_2tCJARCh63Mla3c`KDy&-2UW46gBf zv@}!4o7@s@y!LETE9`0P&-hQpyL4Y%kvzs*X#LXX#DL5DOSA55N1o1Hp3=Q-9nT<} zInnGN{xC#9&?%<5<#AvAIqDqF)g7uUO&vaHxs0tgc`9T@PJa3t)6@R+Tch1q`meY4 zne)*2pU%-4ZEnceb;!LbwY0bZ&;6cRt52uhtT3O{^iZ**Vqm5~EFKO)_Y`{JSBsmj{_C25O& zk=XRB=l#r2$E%l`*=hkmI!ahf&8=?+HU1Zv)L zYjgQ{@}9-x+ySxP{X2|Xd5^p{T)SM_{+iY(_FAnFw_=|WxhJeGtDb zwY!*UucE`hvN=xrsET}7l{Nu{j(10ma5@XEl1#a#F86UuI>wq=9 z0OP}9L+$`7@{PVl!`%QQyKW|l0^Y_8(OEJtr!cdjAhBq0A|X0o3&fxWU|I)fcG-#&Dy0G6MniEvsu+&2JY`~I zH;jt2N-_r%kErA}!|HAC0EINk$2rBh@h{jTv_&W(0Bkfqc#)|w=|Dy627M43T_z%u^;nS zgD>V&Xw>oGP}IfGBqI-+OmT6k%Lixy04uWs^mIgXkrWgqsuPKa`>zK=vGV+np^UCT z$wCkrs3T2~`0)!=?=JNw0eGT{fX3Tw?!g(D&8G!Zbr8T1S1Cg*SmqqXlNJf0Cd+TQ z(a0X~YvBQkoOmh8;{x6mbAaFo!T>UF=jq?CmQ4 z>rm7C3H-;PPz-qF2nsTQT4v?OuY=)KoSQj7&l4)uqWl&^_Z3CU-l4=`9X8Ga;>e2P zFMxeM41i=oJooIjXn2J};5x1VXFNi=#rfnWSN)D68@kY+A|Xrwd!oVe6m`P za0|T=7Sy8SKjbc*gb9@sFN9v_dLjfl4F{EQL5@NIK3Oms5W<)YT228V$EDhQ6OJ>v=Dseqb~X~N@ef}$UU z{6@2+YH((O^)7^5=I|47l@2=r4&xwUiOGrGTHFga_ZMV>QXR$C^BX%r%bVyNVufiq zU?Ks?hypuC!Lk(*1q8>s=S5=XKpIM=1+=Qeul|l!RbWzD_rKv$T0VH^k=9C+_ zHzYWXYrLkb0S1^tK-57cf!5JSSEI9cI zzxg#CWKJg_tSidYC^>$LQIopwPdiNgcm6W<46OuU4o$qw5J*%3arW{?_)guv7DRN_ zU!wO(@l=m?QH1Vf{pz_F=mG}Bjt5?!gD-Bvg3v$<*OG|`HsTm?=mE%V1IkVXi5)zk zoeMNd1tMGc1an}9=KLWT2-}NY@wU#*h^Ls0LaL$mp2s1^`ox=AwA^@+Pfq{(*s!Z&l05w zZCvWdMpBodMbb&YJ1sCIO85FfUi;CtJ!4xFSKy@!>~#9&VEOSayMR>QXsVCuWjP;lvJDa@wLT!Fe>3?Qn2Z2{SL+Ms(^PE2C{Lav$)Qpc!B2az0_KlL1D@tp zaCQG-(}0H$oUt7Z%F1=wc~x^^e@PuzfcmNjr8_4+zL;?FN@Msnap`)9@H$l2l{?}5 z08AX^u7LV4MCu9axk>2zzw{1$@WJfo=sk-un+oeo@#Ds2c_ZIHyx2=}A+>3;{B?nz z#wX%Xueob>-9+X96o`q)dx50*rc3XY5pcXIMbG_@M+cWIcuJ zt1hnq%)j(!T&~u<=9}o@vsrF$x2!kKLeFAZl5B49F8mhtYwnEAYi-W5cE8@ZAaHrc zt#gF6)Ad8FV%*qEuf`nNuQU54&vkbBqf;HDtz0w>-TyceY;e1QzbCF!~5gYmRhS=@zq=2GRw*-Z!mmMlj5kw+otAcP|V->vvVVt z7_UV(j{7;U3qu=MqAniS~ zwZr#oVnClii`U;N9Z0d5Ubk*putubSsN7*bbNC;wThZ`l9qM=u%_LS}^!BptWOA-| z<_B3<3GV*80ltaw!tw`NbEyT3M9;)f3d&fY`SLo5Uw3yN6fPofTLhR`{xV?K)D0(RVuOb0DkWP(R_fM-OmZyzJ1w^Y1gyuM;Zs_ZmvmDt|Rx3`llxn zzyp77cl2GcpqCGR-4(kQ*_L~_rnka*ki4e@RwB}9QqUGHLe6tg698NWAJ{V`#NrIJ z+*Ojs1-B&iT^u;t0V1riQt_y-S_d#~G!0KAm-(x}?(UTGpDuF}U^OogmCLFn$&_CS zYj>x)>jBwyLp6p@U>QCJ3;5*mwS~<_#8-zlS3wHaaR};w9YCWV4dyV1BmfXW1Yg7) zAccY`_yW#yHLjrIf?Xvt^fa8w(DW9VKnuhN16)0S0KQuWy1xKY!rsKH-a)lN19}nuSwQXIQf*UnkrfzNVh*PBJWcN~V#D;o$N(2t*kly2 zcONt*{3F8;G+@Hw5zNm?Nlr(DGj!nPM^LH-TbMABIe4&p@88Gff1hXneck`J|L|Yv z)n7+)zTYgvu2K+Rv9v~WAQ}M5nI=P0VVg*Y)8)rMzmFcoa+t3C@FkL;3n3)U$mt z4wzJefIH7+6M+^cL2uQU4X))@B0xIlFsGFDU z*T}8ei8icKG_kE)6+=h^P6k(35icOKCX4q;w)^l99L}l`@Zqi9Tc5dd-FsqAD?e^5 zJhp1~URyc#UuyN5t#(@Nyy1zBFkfF=RSoV8Ok@;ye%n2sA;x}2Jl3OOHVgiqV zQ{m2li_)Qc`q|Q~qTz1Yn_4+o?Ry`#IW6dEP{I~j64(#v?A(%=K63?~R1{CZ$y7o` z#8Z#ETK!}kio;@VPk4i(ut`s+*K!b_n{z=V0qS`WOe0tphN)qpFxMjt(+QA9W?pGo z8KH^VtwdH^3T5~lP({RoE}nO-EA2+sUt|ZN9Lt}ELZs65ugQ<0fj-=7_r?1 z^<=*jL89cI0hRDO7X_)FvSx0~wn zV@GOl93s~w_^nd3GA7kKhSl>P8q|J}6^Wu`N&1OZ^}!2$g^2C|j;eHVy-GAs z5EgMmm_`jLm4AzmI#(5p1i@T%6C~dt#v2XPze0ehkB~uHoC%CZb3$;hyH~Yi;ziXq67828uZq`EcwN4-5L8y+WaljzPKM()441k8+)DmUDr=}D)n2h zobJ&Ds}Q3px9s(+Nxgo^-WUsaD+>IM?Jzyws-c%nwo%ndN@l=dsyXPzLz|WK;F1`d zz7JN-UL-$D;&m&^lMat9i)v){uzco)c46q@_12~5HBA*%I`=aQ)V|8Ph52qv=g3F5 z#iciy)5oeeM_)Rd-m+hi?P$JT>gUSAz39i@=@Gnk-)EF_G(+ZRYsXq3()g433aqY+ z9vb*MsopL#^^I!Pj;UYiAIH54R5_yfkv|Z*T2f7@82|e!P&Kq|JSexf=(u4mi)Hc9 zJF@SI>5UkkRfjK6IeJ3B(%<-6Ox*imGw|p5ZTMG9r_ZpZZUiq=^!ct=?qz0`?h4xd z7|l!T%Vk#m&jTB8iobAPK0Pu!-k}@SICDcK+l~l}efK}RRYQx6D$j18YqY&k@5*(* zVl{Ek&^^H9fZZ6xO!LA9@M`sl{ny~pPSM$%(G&>Y*;ee;(!yWwCKbY&aP}xPuTi@C zwVv|m1^$5e>qRUzjzUbEr|z=Bqf9xc?Jov-2f@|m;7+@}%%#z$oJBu1co^3sSW{i- zUn3$j+PByhI0YH{Q&KG-c1xj;u}bDwYATC>;@tM3(DVo zu#5umc?VfdycxYw%F)=^AyimrPMvKt#Q8h!+AsE6n^t^&dcI>bpepX-U%-r(hw-nE z01ORAnUt&`(&>U0$_7~QTWpH92w4_^k7vAl5D%X#r_aVf1RGqza#$Qf!0Pk`q9X}ryc$brT$pXnOD-2{tAIk2}7B&jJTCpVoT1-M4 zu=BZel#>C0a|9)-n&P&QE944JUm~NViA=*;5FW86&>Fkr2gRD-FEWh7;=l{9zNWk(7QFk537{LlM{z|6ikP$bD2L#lY{t~g|Fd8aT(bl#ft|lLMRC*q}C(!ZcI(yu4 zqny)P6sCN>CYscH2t;mU>33BqbnPLKHnCQkggtp0en9H_YYIbucs!4vcZyIH0ZLEM zVN&=?lEn)1tX~01W5Lpy?SJ|{J78f-rCnPZ>yv%yF9pB`@z_NE#9>_9RdmbH+fkwBLs{Xz_e${&Ljka(7Vd6??@&8Yd0Z zv$9rXlJzq29v>3OL18UsLKH7xJLbB8ldSva(`lbPjI79NgnGL7d{ zSru#R(ltnLr)$LO7|`9n+&5G5z8>b!}pGZ39N8PjL1Px(8x|D;)3cDVKFozpZ7*W&bo`m~)E`qVUt&=!I}uzK~7Dr%hoNBz$i#)4wU zVP|^k3r$QX6~%ZlNFmS(JHWKm%4htaC~bCI?ZFjA8V~)1aGA&i{iKE~(R7`ETTz7A z>JltLX^)x@2Gs9S;=uz?2xIQV1|1WF97}_%Uoeg)hIx*LvatrS{sr92mpb;+;3yn_ zHv!%P#!)xHIpYNmKzg<$R+=o!sgWEFBQ}SLBuAr89$k=03&b8kw+FUeO4N{GL}ruB z$th;vGhus%)QqmYtpuqPVlhg`*2K8OaVpc?s5;j8PS|rwh0H813Aar0x4XM%2hrl3 zfKWgMw{p+r0U!vLkTsuVQG1s|$7oEa_kPut?(`RTrUuz)89+*-ol!tz0`y8$Cc7<= ziYRpgfYXp&LKrUD14D={V6r|*M-9=LZn|t@+?8vxx**p>*D_qu&Da7m^M&iwBEcAv zHNKMtW15TtKa54#?txdso{XiNQ7-7^H<*3yn_-@suB%ghPO7~S6>qOa&@_PXyAn}R z1X;B*m~XsB7C{~p&jXO#%QZV~f3(tPdKNDG6(T)*m;!feK=*-wlE9L;y($!v27tt5 zaQSXd&1vkM-7OQ37guSIdw9OU$}7%qxh)w0q6{YfPcezTR>;ob8v0lUk$6pLT8gW*L;i;}Duo!tL-Q12 zA#wA?$KpAmMvF)47D>!D|NmFW(&Q?eq#q9V5Ryqc25OkUIlF4EA~KH zT%+Ze%KMYs3h*29%vuB_p@5=>5YiaQiY?d7Sg5Qr`{HP29r!x2=auYMimon^8Fls0 z^RB|JGS}a_mS3$-i!6-k-{79jX?l#YKgo*d$#1qL0-hNbl|O)R0=Wr{eGca5F3+sl zOD)~j-k?ZUnZF6h69Cs+xd)*k88F4G5P+QP5M?|tf=49a*#hOrqIT07R6aV&&5 zIXO(C836p`67ldTQDBeA(vr)#G@yb4aRY2vqmwTZD$+--t&VL<*Oue{+Qz?4xk3wd zG>`Wm%%iP<`qZmQ?-|^`OT2Lm)FLEWnS<1xEuX$!%AB^pTxDXXV4bbh)P6uRZ%Imw zBcv2}BW*QBO$aInKu%188#)p7_ImwStA^M1eLGT3YyG6_qnVt*b7VI`fe?RUPBI6e zs{H}$AJuS6M1F|`QNoyViRonH+vOK_Wz&w+PKE^2`C^Zd1ZH=G8WU?rn}s2H(q5K37B5_vb<`Hg~04-1x^&X~vAuo6z-y zDi=_ulWm48&uf;-==HTaJ%sZ$+9ub&XX_9An#I}Jz5MQ;uN<#4Ce5MPHyXU&ZMCd@ zIo6$e@y<%*wRNuYx36vjD$h8Q+%lCH-eKNoTu5WNLY$;Uac9-u&ys&oQ9IyTCid-B zbKnO2^_UcsyWq?;+?oH95xK|{%)<#}R@-uPe~PJiUGcl3BD&0N!^(7Iv;MWs&NB~< z8D%ap2KdEA%Cr0oSINn?%Xea}5mt#@km!vfcDP$knhqpVTeGMZCV`o?z0E&Y3q(+ zdcbcxz?p42Hntj?MDvMwVOJpAM5r>zdOoDhfJG|A3A75Qm4z_5~?7+thNq|&2 z(Y_ulopCF*r7PaKHng> zfy-#1SL9dXI3LJNeeb;Elfs%;k*p6`ul0P9B+#@l@Ry2JEoe|%m)SPez zPOIQ_fhjkmrhuvZh6nHbk>5V2|NiX$q(XE(QTUKXcZSB)?Wx2M1J)>laXm4Wb7Cqp zaG9OK_)UQN+SZ~ZkV`#{+wksJdtH_&f~v1K77s2Ie!XlKG}RQidgVG-oHU3@c=l8F zW%>~o8lo5mVt`HPgz5EJUu$^h_nm)#`M~bVU>==Va|WPN@z%$>zu(+EzkO(Wd8uRM z#jwkoddZu_-~_th!+*hmbDNoe9W`$^-h?>snBk}L_J5069I;>j*KY?4KH&KJiDuwn zZe<7X9?zhe0UtkLFT>N;%rU}45I?EizN_EQWkXmBT$ltx&e{*yABNm}>Cd@u%U%;w zANQT7;02Xvn!fX$KY2<3et3)RP|#;mNcGTP_fRBwLewX;clwLCz=A}KEKJWQ=fo z*kkkSn7ic23GRBS#?qr1Z+G=4s^-VJ_dOG*JQxgnK{JME(9IqegX89{RcrvUjQgi<}b}_;=Ig%(4^|84B z&adxryT8x{zv4MY6Kqa|eNK|}!`;1PQVQ@q4^JL7{JLA99lIEHd+Q{#Yv>;Q_j8fs z1n%D{zasDN>SfzRb4vft-))W%k1AFTvmC!!y1!VE96fXY_k;22|MYQSx^{1M@th98Z^m<+^@^Vj70gid zW2N7P*7g5!;QsCe zi%vxT^KbsUm;86?m;c)Pe@jXKK6kx(UGpy_^6$RDU&8L~9}hkE<<43BZhxP}ANrhU zF`oY#h}1YVm@@NelwGbcqn5(KL2BZXK8>97@Y| zg#9ezB3TBe`Roy zgG>OAg}b=e3Ko({NQEVGJR`1_eCIOI;GCSu!R$-EdKR)&p8Uv^(;|^G$F?Gh`zLF8 zn$(k}io0?{G;CfEGkhyDRJ}iNWe6NDRo;t8+~dg9W;WzZ6C5q9$}v`0uDY)c{e3M% z*TT;0rUuims(gpg)>N>li9YE^Ws(0A#I?c(C`V06*h{;b(#XvlJVlyu z%QX-0fSzs^dlcE#mWzFTphdo`uu@xTLSIxG7N@uPy7eBa{Y(3OwmWD>Vu#l0N+ zy2p2BPV8t4pRCl?HxGR(%6xd!zP|DDZSJ}zZ@-xO=7A>#eqIUR?7w8RS;HEhOnHk3 zIMk1EH@3gBkmAiC%NI9xqMs)3+!^8KIhRd(7Ua;>ld*H5>8WVWt)|}nNwymuM=u@Z z8omw{H}^9?>TMd}in;r~AIy?&-&JS&yLo7P!=YuE;a6|V$W}&7-6)3#oyQ1En6%R{ zV|>H@7~lPd<#EBv*l!b}Z2_K?xJSH-eNtVHVfNxvC5kOdt8W$U*nD`~=d?X`q#f2z zOTx`2I(6G$UDa-6oi(~{$}*$w;q-aID(vse*LLyKAKp0KZ+yAvR+;g6@L+khb2WH1 zI$|X(Of6zLvOq+2?H0WEXXM-vU-x?aVzuh~Gg0=53=X;RG_<)>1oX+$mIr$$iJ%SIcX*gWsKFI|aK067&w*PmaqM)q* z^ih8Bzo(1$1kSOC%+3RUiIoHW|Ni`0?*FqnboKUk#UdL(1CIg+EiE7aI`=#o>56xy-e`Rr#SgBe3?nwua!+mIIL zr%&<9kazSUG#B{3VInX8C@&{)>MYY|r}X8x8D#E_;6<*bdMa$PT;$M|v`$U4YIw`m zYAYfWG#}#hV>64wIW|1MpWx>xj6eK!PEj3d)%6hBYAr0RR(yib3|GqL`fi|l`CGP5 z+z*cx0M`VPJ|~L`Ul0W9@m?8~&&f$Z3G+yjbuK9Q3!SBjK1|l=^0Xl2eG!Sna7~tE zflu#GH94-Bop#bz6Lx3&&yMYbA}@ z_1DWXTPtCKiiUhpH|8>lOk*h%QXpOlrk=HQ1j}iiB(!OKJFRjdrW5X+0FwB3|O(3D(*)!F|eJ8-J$so1{bkC%dY}kY1H@i61r!PxoZ`S*- zeRfyv{g1h`_w(95N%b5mWgrz2zpOI_?2`S+_6T1Zw)$&Gwg0eGF7C7c`#+ni1CE1V z_@uhtB~d8{y=>#OTa)j>#)v^$XX@YbFY9n^wISx)RRHkY!jSZ>fm@0P375WXFvhEm z2=U9`QNDztiwE;M2FRs4eA(m}RvVLjSDYkZ;gNFEDTp;})e4eUWSCN$!0{_&C-$lG z+d!U!zRTk*8nzRwP6n>RczllicceTnPT9XxDENNMlTCkQ2#RPal(hJeYGQX^T2`TW z^~(oU)xxn&nikbhU+6>MF3-d?DV83+*u4yXI!pL>M22Vh;8yJ@VPJ(4p09iQZND4M znP^m6hz!Oq+T(difM@N!N>}&ujBj*uG1CiWs?R=`+C9w>=KHv$GVtf?{vEK! zI!Him5L)KuBWLmMr?c9y;B;5)t=@I!hiaoz{a@obEH>!htBt3g9r%CYS^tI~zid>N zar?ao|J!xFfwquCl7H{Ek7*ev4nY;P(q~=64_ezAc=9dg=|j?}T6W2*GZm z;0I#5`~emui-w%5zAcBN4Y2eo;wKYw8zBC4H%==?9TaJU0j=W%D#ybWzEHP$mDbjm zIQ7T6^ndhj@r~)TC-;NDF<_T~0_B{zrg1ENL9hdBK+BkhCn}Aw*tfb^3&doV!&NCD zny^9~rhPCedc9<)h;vxORS@jSS@QfDUCcX&{ZsJ%+M+=ug!da0ttfh!@47Es!(t}G zo-p`PD@tSF()VbW2>|<MH^fdZqyJFbsa~>6&LC5VPVve z#t2TODqbC+EZ7YVG)@3L%!>u_e$o0;y1){+$D=PC6nCV1K$cW|r)Z#s$r|D$zhlLdkhu3!w@FZtV^aC1vb%>$k)T&Y zUUb~1s%#1T2Nnwe2>ymZVbmRUX*W;>7)X5rpn(9u5XgUBfd79l004|Y>Y#%9igf^( zhS$KnM2!R)&-ko@;#DJUk0okL%n6PH;Bw6EH>VwRh;(xQFzgmv6d|1RqaziwO0B5t zga-G=^BbB`9=B7BYA}@Hr1gIvdwpOug7<;{c6uXc8Q|BJB$ANhQmm3XL^T7HE{hE=q7BA zAVkKq-|F7wQjIt(Gx=E=Puh``+9MoFcfa^?CH(@*n_b% zR9=|lyRk_@qv|hx9sReQ2?c#{#ZFI0=258LC_8!nNDMJHr{w*WVs#qsJv8HWJ_5 z=q}fOY!^1esEKcRAu79sn@N=rTjaFKQf@C)b?vbLqc&OP$24TsNHeLtk7|Xq$=Pq% z!OSfoQyGhXnF&dbiWa!Hr1g6ta0#_#pubH9PcR-W zh3Kj-<^J^4-OYGaW!8CsO;cu0ad#|a|Cms2mK39?$7E}tx^WZniH6BM_g&jF+*7E;Z9Lo1@Im9&+c|#MH`wXrt73}WiqQ= ztS1ejwbnDq36ZfIU`6CkFTu1U5t(tU}QM}zrGK?Qya8X1@vr&NxN|LXHr|;`psV7{_ z;_b=88j2~e$k$=ZO&{{-spr+<8XTA+pnlYap90^=I;YRqD{Z>W5c#GPKcpQxF0Wdb z@(@b8av49<_8E8AX}dSiF@3(9w?Efvh$KBLN&}Mpx5h4)N@wHU5=y|9-l!DLr$O5R zncboVLI!X*mjkpe9 z*G8**zDi(wQ#*Uv!yt=RMfM%UBb{#A7A?*CA#6SB*U}(Cm?2bx`P%u-M3&U~d7F*P zzYdsbB~u_n@sJ8nmCPUpLoVCY&A(xcs*@NB5QSw0!qCl8ZRNVzmz4xnjZ8vj86&EE zcF8rB(i7u+Q#OWB@x>DLk@-sJh`mlcIb(FAVU;5~U(qh1o?gk9?KLm`S{sy!IwEmBPF^+0f0mCr0|DzmI1`A*Lcd6-Hg}uy z$e_}QZK++*vhI2t^D{rI8-Qk)Qa?Va@S4Fk9}bx4)En`|7Sk>DxYf=k{il|OlTMR1 z4Qm5@kwQAgYBKA?f;XG295`h*$7L8*g6LSE?3Bcdv+#GHJn>28QNHeNoU!7QS0NcG zw)!PpXB2zg|KIA$O|#{;z|UqW4nKB%df9%?1ad_kBn=}4T*_j@*4$|_KC?Tv^lX&B z1(`xKECYauDJew5Xlj&6gT8M>L^((hwnW-etx6bea`20VB+LiWRb~l z8CEN$pQ2TC;$RFQSpj5KnI1Q9`Km~P{b@C4P)bkEpy-9d@)s&Jb}S_xC2YP0Qv7sn zci~=GgUz@Hfgg&kU%!x;Q>l*vOlfv6m?wt3pW`eG2nGimhb z%b&%1wa3V7LcG*GXjPmv@ZPh61ixZ*QFxAlFr7r08KVjv1=*WQmzyF6j6DkhpzhFx zOcWKCJP~_Z%}bbKXv@_fhbS{+`7^f5;o!tMiZ(#sHYAhYX5nm3IGWD$NH{_x2Q{NM zUXsI)XeFXJ!FYTE))mu&Y@)r!N8zQllgVD9xfa;Dz-HG7Uj|<@?R*Ok2t4NHU23HV zyLO*n?tB|l_*Z2;jC}dzy$Adt0v9GO+qId=F{8KP*-X#;)WYg8R8)nrD)j@`R{KYa-z{)?GL3tRq~D&K0lIFS+iFM2oN9%-_Fn4@{J{}G+k7f}tz z3c5QDxg;aWc5}IB2Y>1m`mnD*^8k*A{56e^hi$G-oxE&g?#I?b=KlUzWz3aZZQ9E* z2K*Es`GjrAEQd(&a%$`Rvb019PcEJ z!g4zPz6aPt^CUoexfYI78xB6uVkFJc3DaQ_UMGXaM7)s57c?FG$q*Y1z<|qR+U^3LbP*4krY94{g(g0ZP)^#}0^I#bRpq3+r#46DWl_G1=+M@v6`1v$%)(Kix z95|tYDcyN{lY3Dui&eT6u8P7jLWB|k8d|if0h}2MSwLD(3Ye7!3xnYdbYonzAvZ*X z1q@M)cvp08x~C39^n_uA1v<-f8_R4sLDx=!SdCPnL!3?u7C)7_b|uT1x{!HR65=q zksp%{mKCFS2;Qx8j{GVq7>6CAr^^xlo)3^U!TD8-74WCp!Ph^wx*7&c| zit(5%d5+@ixx20O^6h_0>qD$=^+>k@wX_=Czo2|kY4>G~d8JX}iskM?y=|MH=na;d z*Nv{jX?&OPzGKavuj-uq+b^tkQBNM>Qe91Jy}Z5sVQF2>?*~|An01leEgK!-j8e|h zD)L+7S(Tr5czT}fbdn@p-o3D^-kKq6hfSN#L67 z&)+n9etdhM9|jhfu~qxNl{n3=J9CEL|1d|-bI+{w>yJ-MQRaK{I;k1a$sLa( zL0l48gQ{E;IbV)BC-JK6StX+@AY^aBeA_okV%4?fMpKVDD~PiBYHsO#&IXmYG4CeI zGt}Rxdfa0@q^Y`vV|eVGt(X7HBZo%lxk!}RmFG^m7Vcf1d4I2^dWG8uEjt!C3)R@) zb^8GKelWa~QXS{h)U%ow#GmS3a`@QL=T_i5NuH7z+(-0-xSRqXas$1QM369T)Ly`5 z3bj7N24Np7+Wr@Dclp+I{6BhpV}p$`U??D6g3=<=UDAzGA_CGmLQ)z=!)Qc0q!Ca$ z9HE4yAl=jK{6NfZ`+3F_mAihL6fh2JlHLYHI%G3AUVX?|j90g9gLf$qCA(s@K`| zgqA3F?7yzi$o>``(%n%5WV3(PmES4|j;&t|y54J8cK;kJGAg9Q-MCvh!zHr0Sh}Y> z2kk1CI_%3oXuCPzIcWP+b#j2grmyS?oy;c_z4)W}Fs>6J$?4pMP@oy=BGtG-{-o~i zj1*f5$*3|~Es*{FleMTtqmT7#|MBlf&G3`otv$i9J&!wa2SsbkcfW~W_t0nzOG~Pr zj&MKpeLgJvc+c(G?qbG^H?eK9QG9pidm570lPenHcU7+6d2S{_-~Sj-JUr#PHJ^*) zQWiuQW>qAzBVUpkRY!>krP6lUq%{1nbT^-OqStkLbn){11ca7s?>q zbaf(|Q~7??1hey%-9PReUb@z;%#54Y3lb2iJ3TTFo8+d51A03-6}_hg(?i;}Uvrz! zOC>`jt$Bai4EWka%}-&+tbWwd#?UT2&YO{{uPv{B?*?q974MObrH!?)`ffr+Q0v*A z4|H%bel^{fhLY*vAFw!Y$R+!k*Vxc_6oZ6QjiXovn<|{yD{bG?Tr?<%{E7+gZF>Al z`BxQ+vc{BJw1Dv;+jDs)mv}NC<}QgZveK5Jk*hr2d;+~nhW39FvuBx`WQ1dkne!8i znJw7GOJY57|0HM}$@ea{*M@knFgEt1@?NGPezz2+MAd~MG13aCpwnckiCiCKxPVa#0Y%7kNs<^| z$yxGt7sQj-LO(q!w0_mIT5LvC@Hy~ExlRt2q9;+n&S7CAg*zROoK*Ufx}~P-oKEv+ zH>t?4dMn!x_Nrx)REn707WuJsEQ7bUBzc7GRsPjji3HvkUEh8!1G%yCHrz7f*U_4d zRO3GtYs&{q*bT9~2^a z$6TiU--^HDjsdIbbGMxJ%~?P$&p?^Eqxp^I^$!uQqoR*aYbKg|e4RALITpZ;^=*&Y zp7|-bylvmVXgRud@&R!!rViI*7~8o#NZ=&5ybX^bepL!IoJ$d!4ILyAJSeV@3xq$u zchWhAqhxPPaS|sV!z7%8giDvvMh!n9O3$O8a?Vq_PId_l@`Sq@vD2JP%Ff(Y%b9bo zhMfx5zf`wDC+;GcUNk=8_j8dkzIp#t#j8)N&85Ko<~_T|{dMt^@Kjg(H69&sza{s# zPa3N${G)i-0ZTg9*fskVk{6!_U;KIzy_aDwUOzd+zU~?iR5Rnh2z{++ykg!|z1W2A zESP8h{^i)FLix?rpR~d6)y3h7KDJk*IYj)$b4oNckym5I>L03l7`ePW4gXffo)v|S zGQFXCOk3Y}#@kf8W3(bd+j>`98G5^8ay>oy^T~OYZ>zo8$~^%T%1H_NB7Cyx{ipn0+#0vW9wTs)DFC7uIDcY>)S2}Bi|gp znXkF5$3WDPe$6;E=oCUVTwWrNq@ag2`k`IIj7P6ETb3VXd;a8VbB=xgafNc?vRgsj zB`&IEl@Uwa*sG@QtZh$2S}Ek!D_sps4Zc}tdFRz9+IEt0VYJSXDm)+^7$w)ePMfcY z%R4L$w-(9V((t(A&ze6i?zG!h|JwAonn;O_-eGB=tJ4()}428P2-=r-Aiwd`BsQ7>Q&};46PPq<6aOIMBz}@5Vb5qG%h>dP>~K=^I216xxKeH%uXwC`+82P z(T9yZ-uZa8%Bb?LlY{36XelsIzte+ar1NiZoH-VHhErD$hvk21@R<=yaLzp7yZt z$-u}-PYH^c7@_FT&f(>rC~a%MS;c7G%g9Ed*w@<87_Eo^kBE3{>MxUF#gjpkm$BYV zF+C)4f5ZI;tSLXR#_os5rbx#uY=)IshvD=xU+UXlU6TJq5dO`LZPky%$0z+6K+9Vk zShEzPNkWLQp%TjgW9mhvy?jFPaF7*jgyLyfET5CE$?_!T_J9V$;XT zGnQmVz$5;}huEa_A=7}GgusAL&!@tL zBLY88k%ZbHMl=cO3aB0m8aQPf z^BMqe!_V|qN>{~CDYAL+%qHd8zXY49e6D}lRfoj?a^T`Q;N~1S2ATBp5dL#GEz>!p zK0ZSa2ppj|VQx0B*(*;5iop0Y$mbBMWWf zl#d90R1q|zi#|3Hw4saqr~m~RU}pd^7Fm3l0~W7>wP33V8V?B?5rAd{z{{3O+m?DL zE&pjeK}IP-<6=qHbV)XQF-;ZW6|y+o7FR$D*0>1EzA8QRiW1z;G$C=VM3yzMJJ+#0 zr(%Gzk)`2HxLg5HU=^&|x#SzkC#75%SQ-Y*f$>8sN~K_@WCUHyX^{`-vqfxd|ypG8qKQ8kz{_) zpd)s&bOvZTx`yL3l%uTXnF_)kU5&*MZeS5G5C$lQ0ZHD|!DvYOVhwj$4REmrDD^#g zB!yliTX6*Hu8HtM0AkRPm_z6*(c0H4wT4l(?-##bVhHae|3e0_j3&O9CO$Br4kxe{ z&$L#Dn$pLhD4m_e-UQ*TiLlRs*lX4UtLpt!5GEL43xGfY1H`E!Kw^Nd42Y;Vh!{J> z$EbQBvfiID*!W*=pin)rbG@rnW3*@^u&Tk^r@o*Jl4;kJMBNZ%0#d->i6L<}FhCQ{ zdi&wVJfG%7j;7q5Mo@cWPFXXitiJ9|eVmWd!qbFg=Njn|sLc%2mIINTgO8JoKk~WG zrnzRatj-Gqq(OqYXKFE607MK81xvRAbMX7^+SaaHKu0as9IXd-tz%JbgQDcDUNL}w zq{Te2Vg%sk4eYz-*IQ8-FdEjs{i7W7qf`o0nu8Al;1ytCKuwq!19TPxL}FmKq6jb? zLo0^BQzd|qU~tP}cr8DG@D4Drn!d{?^*7oCpDc$8kZ*{H7eU1Lm56X6Y8arnK#2G- z5t0E6T7vO$BATQ+<&6;X@G>B}3rDMy5B@WY3Q(zxfb_S6#1y-K)9iYNX~#p52!I6u zVqt=3ZjWcdfUrQ+I(+=)h5TiShS;ihTkzn)HKBbx09{0_s~EzT2B1}ju;T2oQ$@IO z_E=+S02*b8CUjSsCV>$rd`_^8pp=vogTt583tYtETf_lkaJZ{*fK@m-88{pm95$Xl z&S4zjVqb0x&SzB+d>HgGAge5+kE;rYOA5qS^}E2nkJAK^t_muq0c7{%6mTNaTl)Ei zLE=(fz#Q;s3+{WKUtLsWDQ{}hl;f49fplmfmlTi^0ie@FY2643p?{6sJ z7yw@U;JPYsyMJ(v6F~tMe?>rfy>DP$m{z06Iq4k>~ zko4e6#^7qk;H}Z%T0a2KcW8-bnA8D5F8&AfcI0Ze?{UQt7uN`m^boiLM*~Yz5Bc=t z2>6Ev0l4HGHJbIAZHe!*qrgD`UcMcJrhE2KQ+^U5-$4Kl1Bee1fC~Vz1|jhUh7gD$ zeC%_?hWVcuPar zuz0vY)Ayd3`J2m`1@Xj12PXJVNJj%wlC|uVB4{N?Yg#<+&^xx*d|^5~;&34P$J=T9 z@P%ysIOrg1&!Lwwmnut^rJX?l{ znTFWJ<)9}*zo;G2JBm8!&1or_BEc9qXEFuwn4lez=e?Y>(_pl0b^4j}TQZ?t+Yi{?Y;V0K~sUmcLuWK_mBOMZeAh9_Ve%N;EJK zh*@(|E4M`ta7wHb#!~sFMqR}219J{yqUX~n7CfZ4dlm^wcuEcz%cCU@R__BFie*qc zei!@7rg$(jQ5aUDWN&y2w6OV&HM`AZFC420Wgc2?uB1l01ZvF^arl4d8k%2w%SPoq z-G*M(BZ5#nodoz&32XQT6cYk|9A8Pye>YzDe{}Lg3c;6sYU_7metGoBAJHMc@>&C> z?gW4S459rD3i`3W`9UB!8eg=PrP?S6$b=;cExF|U!5T^%3SMGfq zJcx`x^nZ#lkVM!MPYV!V%FKC^|G4=04(d0wVIi56LJw#I5Q}S^=t%y1AbEteCW=r; zaO|H;&+mm+x;>9O;?y{_bv#UgA4}2zK4Y&$d#L0zN|GEeeTk1|2|G3D&qEi^Sv1yr zV$Z8Dub~IqO&V+%!HsvHE^?eM__6d)j}@l7_y6@~pXJlDP8`4|b1uW$FUkD7z=5Yt z`!|*go|-=h#GWCH=(jV8KV>^10J%>vKLEIdbaH8$OEM@zT8R(}t!24LGA?drh;mxJ z^Afiom{OZr&LdxraWsXUF+=+C+qMu&opse<%FGWt@;V!X@dxsSyz3m8uU>crM{?<} zw*Ev=3dX*tdTkq!Af>Y|1GU=Lt$h2~Ovn1+XN9j8rdMJ%Rd1VvLiN)_sVB-uoi*3y z3xx)s4g+dKIyhJr37J|#3FE%MMrYIq3%JsuT98J6b7TqY;7Gn>%R%@%)3KgvSF7(m zq_8JqhG*L$0`1kP@{6a+$*EWnW(5Am!>TBHZ$DP_pVhD-J_MvdM>#ey(Yunu9sZZW zcH{4XE%U{-qfiY&JHLOA`0_>YGAPZdLD0JN9lqrVG^WHUC$MqqO}wi=>18Ln5F_A^gRMw$t4u26QygUIR}J1=nkFF ztx@Lq+QqBFRbQS!L(aiIoR(x}4H8|S`QU+^nwo-4Va{vg=koa;V+Khh z@>pilk(YYnW16NRh>k!weA#ta(k`Yu%l90}m-QAqt3YJ~So@%9b2+P^_bzqq^^|99 zJgHc4*U@keWBgI5_>91sJF_K@{ywd)=j{jm_n~`a1}-CS$>&UaamV#syjs^_6hb{F zcCPr`Sz2vLdH)V z011=Rn9q?}35P8UHsDbio*ub3ADynH&(+eWY`+4a=!Qvqib0yW*M8BQw14s=bDyJ7 z%8g9tb+3uEe@g#S{C<(+ZFqX$P16T!kh@!(dVLTQ-KPr^JMQizEfvp4eim^>tr`^O ztYwT`I{K5>ZIHLzmUP>X?p1HBd*01IMFwcJ;l6ey$+}((YMbXjeD6#tuJ3RDu6`r& zma>^HI82b%K@xl3oSi=kRM6fjQ|R{IEBk8P8pKHqR~vW{_KVV?3Z;|g;eB*=vH0Qk zTHjP#!<~L~Djr4Wy_j;lU(>ta%{4g^_h*XZ9iGzEfIfuJSen=h89aZJpg;^fmZhjK z4m&L{t@plE$LejP@7ZofnFlGz5N5F@QDx}@Llaz{m0(jq4oN29Qie6_J%oQUmD7i( z$^ZqL1fAgt_`#jRZ%o1}(P^A(d*%LID*^jBIrW5B_ViM}lb0OZdX!ZoFd$)E{PIFGZc!gi#R&|nEnU>nL!V*tM zDK{ly{hZKnERXy9^K*ebLIOY481+RX5H}#Y7IBg#VhJ3stX)0}F38S}zx_X>= z?&Wmm*x#@D{%JL5E)iR&?ov>gRQ38!<ASy$-R=)mhX@3 z4W8tF@);FuW0VaJ$1xg2r1rUg5oCmEBum^!WWG;CID$s(-X+ctstbg{gXwDSt7nZOc6!~OX{jyM6uBtt=L~KjQczU`YW;4v-<& zA~V3wt|oJu{Edvnm|0bhTkdC==_mL>i0kTI4)=WFOTacS_^JRIr4Dnj>eucE;YQ8o-`xfvyCKg zVvUt;FO+!IGJ!d8pcM9Lk2L0NXotHaLm0)DAbR>8^2J z7XMH(3w6viC9*V{Y$tVp9&HhAN=0v)@vm>K6(hcu3L`1?^UFN@=enDD3^B>L?-q6~F&$IG!G5lSDI@`OJ+_AYByRRAsg(GdjC#~j+_33{|BKOJ&Wd=j|25h3^Rb{hI z3l1h5W$2D;Ygr#B8JRyCv+&Yc0=pks*&B`dB<;B_@=@XfwRSx=_5 z9WmVO_+S*iHtMpV#-+)4w9kr?aDaFRUeN`3QBWT?|Ld=#KFR66_$bt7ZK~UKciEFe zOcN@2qb5Wjz!{yxAvbXk`QLc& z`&l)S+)dJDog`5!YxO7HtuAKX+_`HxD69InjCHi-khG4Jas9Xyy=x{&HW3UKZM(>a z|B{geB}KhP;5rlwppelcJK`YImMw$?bTxADIi%_^c0wQ1-T7_d1$1^8Ld+R8UEDTH zfa(4%wTzCfGm&mUmI6GbkAe{oUr7i_gWD;>sdr&uxB9JoVtD^ErX+$upERsp3`eu1 zt4@nO+n0^^GKGjoMIxwtkQ8f36J?h~Frb-pHqvz%WuX$5G1-oN02ccqDh{RuZ#;&+ zP=y&^@*yb*n4_gJzcD{$!`q8xMOPyzoKae7Xn`adycRL>rVN0-v`jS2{Y4w|YRi0C zn$e{wXOdi+5X4$4^c7E7f)3^-U;Ff*6r5eTLeEe;MJWleY_XlxQ`eT)=8<;ygS8nl zuD>P6zP&8rfe3{B9HYii^+&%mk8}itY18}|`TR4;GgnnwzED&Cr8yCBRaE0!yNzlj zx4Ha103zO;!qm&Xy(pjQDP#9a-in5ZG^3M9Od*Y;$;eF>^G2r58eep=%kw7u6>FP* zh;;h7qPPim2}-)$gVyQ7TjtLlZ|ce8S| zrf}9~XGGW?c08kLt?x_{L@O0!gpW@ejbd@r}_pa`l=0wG?>4q?~Nr~W| zu(q4<&t=`!%_(j?P)~h!8}t5%DwLsqT{weE6LWu10G=mL`R}A~YXpBp)sN~I#CghL zde*Gn!J+;Xa(_ag_nQS~LWI6tlfMgqcrt_n7C~4!O}w@OwJ?g%WvQ@O(!LrvBJz7E z%C;q*G{l#4kSd{J0@^157C8~7s2 zN>7xoxzyN040IUHqi zMA(E0-fMk!;D-?ku5jI9$-z~P#&6#wXUmoo+vGMi88R6S72#CA{c)gbxJ7&y&l3hU zDBB0gzsv+@Ra(JPs$Akw`^}+QADFxtJ{Ag$dKG{gVIGA~Y3wD5W(N$#BHC%9bsP{v zc8uB+C(>=f2q&~^8uO^GklL(V_#o$R00a97G+;G)H0TmPs<`pYT+_Knvlu{Jel$Wc z_xv=v!%B2i{F~Ti7eDqt(>s4Wc%Uz1WK8vksc&PnSq5~6HB?xHsBmi)ej>IyHEf{( z)|U|dw_{9%WBjyzN2jO{t0KGlxsxX@y|m0lBx4vTtIX{_me~98lOSN>%q`ak@z)()HVGyvR84m`smxKrQz|M zR^^n?)-(%4%&Ean=VURNVbN^^yw*^kPtPWkP;qWrpVqKvY@#YukL8tN{@g^6?{wbl zH?}VgOIvlm5fXH3r+e&u4K92WO7{BZdiuWSw*IMGUTYZF-+t( z*rWEQmt|C?bv(BAEth!P+&~7lC+6)GmsUjR+<0M2C!ziV?w?`tIs4c16mMrc`B8;j zZ~YyNx94Uy$>vI9-mWK$R_x6;epeXBeYI}bfGUVc4(&ab&gyU<9u zV5h3PLAb#8(zvR^_@-iZdu?IQ;@wK-+-!&;aNlSiG=Cj4v6H;;?*peQ%i?P5LYufi zE5ETpjEUo?_Fo^2x|Lgl_ZGLAM=JkvleSLX-X`4Onr7ANw(LD)CN!>-U7Go`c=~eU zEOY)*$`pm=>;vvWrvc^bxkXykyIX$a&ze7Fk$Rl_ zeyfDV8{F6Wp}G{S0HM{;N!4)u&;@(**9^FdDXWTiYKrdRO1h!i=vD2@fq~)o!oS{s zVlY>9#MP!S*U=TwL9OZ-uPJ|71z^mz0pr0rtNL}TL6>Uk<7*Z>tK&k^B44Hj*P{og zRCV^(LW|b`IjgUSSKsTdE6IneqSlnxSKkb-8gYk9ycP&QTq(F*{rKU{pr?iQ=Gp?M zm4%{T0fR&r>ec@x}y1wfE#LDfLg@?S=TLEa`==%7kWr64H@yh%N5?8MWR}UR( zq-Y&#X{|Sj8z#RQtZt1p;JMdIH=_hLgXVG7(VNkA*0J2yk=&c{Pi*uSL*ga2UJGqC z+ru@+4WRRIEk)cm;U#lDqQ!+a~)9YaFBVU5UNKMswai=qQLXW*)DUpwQJZa zm4JLnu`5D_x?kco&Z9~Px0+Jyvg>T@kalHXw%vQSJLT%6$6P_afT&!uTui(p|~sZC}GwheW*n|z>?izaggHR zUS(y|#8FQ>@G=SEUJRvA!}*s5d2e#W2Hopy3(`dH+e_`f0t9fUBK8dkqg zPT%MB10^RpX zgE%6?+yEeL>mdD}Irvt1&n7ZF-?TA+#)$x83v{(a-#1Jkbxk)Zg^+E(lg`0VT0vLl z!-GyD@QY25VDWyZWiZerfSbb60|2t4aD2ZAWDG!>o8Ud!#GwNOX*NJSpdniKzgT*R zJw@1-i_KZg?jRz}EiG7M5yia-b{w|n(Z_pbbyBW=hI`=D<#@`X86>J;FGm3~mqM|z zo~TrT`pH9lvLR;m01^E|MhZOb;b1S;bA1e+jb2QZKt1t15;f^YYb1}g1%~Ne21Z%| z9tnl`^n`Lq?Z#m9eV{1U36P@V{y!9%KI^~dinuQY!TgtxUj&5wbHpY8aNKE(M?Q%f zP66uQn@oTpdL)3d3fCjX^MHI|B4(i>AWaUAaP~YXr#mZug8O3gl1&Qb#uH+K#1+^$ z(T1 z&`Xt?p2pxw*5@~!Pf3nZ-r7CevcnhU?x9TK$5a%k9!Yy1A>7T_W2SpKpEZa#``|em zz_5wK@C?U9X!qqM5T62MhlDUNfGhBVvmv)$p170>H?u>x*tfJsi6^%Ukh{f4ehWVY zm!91%#(6qV?qMzO*16Bt!|ukpKWOs_XHwtobl>ex_(ed%SnImAk)f_R3Br_Ec1Elp zFZT2q_DsS5ToQYshdodAuWJjt3Jbfc$KL#a_%(!GL&ALy_whMd(e%>ycs3DVPgRag z&;^rBMp_l4eBj}Hp-=b7ib5Ri%OD!c#VpUPbSz^`C5|VDdSy4>o`EHOl10srenX`fZ=TUoX9ITEK)6Jj;sw zRJr`aeuaBjJlla5 zd#uFWjX<~8x3%mHf8exB|8wBE)$c$M`R2QzJ6czUKqBs9h9HnO>ryC*AuB@|t@kGV zb9%#`K2cf}>te*+0FzlHy?TRb0D!k=DVV}IZ7B*QBg7a-Ag|9Le1$K}94{2{&;X#| zy+SCgBA`T+q{iFGoUA4BuOLxNL}@KaRi>9E4Qm)=u$J)Rlh>C|^Er)A{OwC42A(sU zJyuV*Xe#-VZmsQAlxpVPXpwBDj9;8>WQcE_VtyxVA^1|{evni*_B~5svatFx#ipKJTsUFn2?nRA2Wk8?=(l6-Skfj7@f7 zGGWhD1dyO;{6=%beZr!R{d?S0M#i)$!_P3JK zZNh}jK06&jzBRtl#*^*qvO4~?W+%;A@+te~m!$-UzF4Lf9*au%M5k6@zzTP#(yyq| zE})z$bMt}J&cV-AHlu2D%EXT@evk7%J~YS1x!)Z1!OLh~4DffWR(0>+iMm>xP2Id0 z7CoZjYj|eW;@Ts}(Rzxee$l#LGW^BXMeUW|_~xjA-R<|kGRyE6e-b~m@=sYzzy~`) z3ToA(_j?CiXDoj^oD8Q@a+%M$?hx9~`{dY!4W&U6eW6hIUgV^ zA-wiR&{%l=)5OQd^-Q1Gs@3c$36Z9ZL_d*jLBzU<**aF<~T&@Ka%#TA1{KtFxV$p~{gZYQnL4868vgi~I0 zQ2arL@^R+kITd$4+(rir>@q^VpmO-@$Z)QkT#{$3UCd9A5vrUF53B_7FF@OVn_*Ny>C!p2TMi$_?m>a=6Rk`D9J-uhn6 zUzPC%q!vsX_&>Bt6F%J21KR+66|9*vtsFM=-=29P*kO;*R=zTog0)VFob zEZX@Zx|X7@`RgQeue@mESA@pfFD}_@M%j`vUPA$9L>b`Qbtz&IVNZ598$5^2`BVIn z&?jzrkv_#Q=d1>!-D7iU=8PmI(}m+A$Nb5-N)~t`wZAC26$U>pQF$aVlqN&;g>Ozz z#YsdkdHd8#V6OzI0ekf?)UDV}#Zc3DysXWjzgYSNrQK^m`9&m|_k9z)Zfi)Shk0$8 zNgn>|GWMjN91zVWD~Cu`pl)qC_H~67f0@CMGSm0;WEyKS$lDW<=Wfv;ns}`u{h#u& zanS`;j9XAMC8jv@;m6gnESyU4>+vsmx{_9fVPc!o#J1Mt9O-ME;u*P9gR$e3N1NT& zvZ98=3FqGm*A&4VpR?VHJL&#}LmXYpX6DY#>f7%7cW0kBOE`k{qiD#xJ(ij4fEC*Q z$!>{dlDW<8l%|Hz$`3{V5ef8~=I>wdRX4{OS9MzbZXGhQVVvJoULmhXh>|QAi37`Ck`I%iB)6A{ z-DlmK7S50!y>?uHIDT{Ns$!UTwNDiOj|uwoDu|>b5axdx+*+TbAX#8X>_05qao6+J z$B85kR6o%%xrghLtg`%Irl4_~@PLbnbK%joEQOYzb8vq294&zt{aKYu&_hl*_+o{8 z_YmUQ{hP=o&7)T;*U+1QW{u}!1#?>*h9aI_By{@p>%rYI*S6LQM<+$+MGSYszwPy0 zj2DJ5_G|X@{@54vX}`$VkKIaWEZvPLe{iSZiC?zI;*@h|3s`98kBdc2c zN^AWMG=K2V;&Gs}oyCQtP@nXCRh)39<#9UIUnzV@O($bDFzVvF#V=&Jf6FqB%H;TM zm4cY}+nw{{l_?Sl>^Jc?nq_8cAKu`Kmx1rZOsQn=56q5-%^o*q?&a4%wX%?slhtt^ zzYSaN99$dyA6VTz$XJXsb}IVmgY%ctuZVj*?; z)GlbB`gRuVzDKpV%iNQzG3t#7gLflQpGI5O1%3z*5J#V6uF#OJOKtylWgaiJS}`dyY<3JWbE@@q~#gMrik!^q`}g&3fI;hD>aD7`u1716YZ{MI>m6sV2y+Y z!5b|*(YmXG^Bm8=W$(&-bU*W51d#2#ZWT#MPD-!PQ|mo=z0mx7Tz=>?fc(fS6#ZcvR-E_}2-$Q$>vJ`{sXldDM3MTJP>=Av?Nd;|Km< zdO#&TOW^|G9DGNcGuM-i6RCN6^A0pEha+#YyGM^pggYoSiu)%P;FzP)k`37hLs2H` zfLI`E5t@)gV2}gDV<4!@xi{P4ekPE?9I(V9zPAaiBL_a610ByH-Zvpo&mrcG#jY*l z!E#~jSVnwaMi{RNi8mc$I_Kf`BI%$BvHTJ&FPpqi6X?D~u1rXw%s@(RO7>)l?AU~g z$dnRqiHduPT7Z!#)>O@$k>Y{rqpT&|h{d)@J_rh9b|_c zJUuevtL6{Kz|@yuO&m?B|7j}x4>}@N)-vW*m}+}E*F z-%WmJ>U^_J78+aZ%X`xq$+G#%CjJGzQ z3#bclCu4i^`|F+O#;eQ1!jaZXfFQNzJRbYhFs`4hSVG6T{VS{mVIjH7&j1L4#Lp@u zuA!~;Lx7TfVd!7~ZDApFC@v60$V27Q0pi52f>el=S7i`9IJuiSC{pc90@-J<)2L_7 zt1>Xi#%3_FMCUz7{}i~p{QFts;e!>aMg$xB8J9qb3b%#?z6E#A{e=JkyLdt@s0@{k zjCdffgh*10tc&Ep$z>b(&mtnPE6SKx_d=v89zJk2f;tvFf$7@j~RsygoD?+$@2GEO31p*M-XkWNF@f8CAkCYe9l_Q0BsoxU&{)ecC^fHN~*TdSy&KSaY!r6@rrxG2^4WMyuJig*B0m=G@@$37gK+by1F z^MZL+^{J7)W~jv2(4*9b+fAp9-4-yR_W4+P<8hCeGlB6`>3T4GEVD{*fbNvH8L25Ba0uaHdy zo}Tf$x{OofCFlm`IDGUkBzvkYj3Da?XQ*xX#orUy{e-1X!?o!TApkQK(!vEOfdWLT zNSX>ut<AqF)KH~lDy5_dZ2BHBy+jn`)>;2^ z8}tn4knmk`M@A3JI1A0`)F$~()i~EU;>+S7fK-p68!9DKqmug!wkp0__?Kc4J#YBw z4{VYasy9c1#adMv%kb3l#XEaOH2-g5&h&=|nR|Hzn+_j_kpH-I4se#F zsjvD&pM+-;6O!7EO?o80=FP8NhHu6{9!wnUQm&xgDuQvgRwBJ8*qtGKnuHQBK-5pCdrqnYkC}!-FD8D= zN3e@QHmn!qCW{qui((ucQpbb<3!-@S&6x@A)}X)Zi?$`bnGdW~se8RG>s8j<8(-1O zIv&?4HBqKHrG-$_?Cg6e!YUlN32vCPTk&kVeUWh=MFIW8wixO*61f{QI?3^0rEJ^@ zD!VeM5)*l%r-RN>3_*`hu-1?}0b`f={!Yr=iu*UqHM7fv1=RBl|N0r1j{rpAY0io_~IiG%kbY||EL?@z}FyOV5Lai*@@Ia*&R_)UDK6vE#Dlj8S|lhH zT{*yK3uQNqc7NzAxW9izy9Rs~XMitfntph*OfaAv*C(7x#-{ zd$b*A8)I>}56yeOi@&TP);Q7m!hm;kLEqDoX~d1ia`smO(JIucRN>r~tWh4PX8(2r zypJB@_y$TzxL!js*yGT4cP-C%qE~Nv?hlcEb?=F&4y?Op=G(P`%>Dmq`upJE;|v8c z%QEaiKCJVwr6eM}o+1XNh{1vWN*4s9Ch8=~kx7NXh{f|0iXN)d4u5g|O_{Rm?mX$#$kP~dPV;vy8p82X+SWvqx0 zU9=HbL=0kFV1Z7n0CybVC;_OG9|KP*k5#Oy(vW-#w;Bh-kVYrgAd|%owvOgcyRl)mz1G=tmC=MfO5t_j+Qs z8)A=z;(jT{9#OU z$9B)-qzbqisw&2>D<%!O!D2R@i?vcl@@U_d^4MsH_Tk7`D8J6(EflNJjViUb`}_58 zhwinqd+ua4u#QlSK+9n&@o!sivI^R9*2yU>YmVAvSKrR`WZO-7a!aZZHyegB;FPL1 z8)A|Trdgz1%}J)VGKN1)v$D>T1#v*t7&ZY#!e3|4I3BSX|8V~|&Ehj5H3c+3so_Eh zI{l^p&}a$he$Bnq@fKIguSM8(>37`25Te;7_O&t*LK7a#WRHVNT{bM~GqhOy;ooNo z+g$*yD6T@qk^~L^w%e=AgCQp}slV*n6~zw#Y`2Aanrso~RfJC|jkNlL5h*U{5WIvj zB_=o~;SHXQ+wxKvovw8P0|@^Q6x6pE9LLFcY7+J&!kP&h4eWvDKLPc!B4YRxCRbu5 zZ2v^WWR3}$$AkG3!nBg11qF1h%lAf3A5>bF&Wp9gJS7g1w3cdUIn^T-BZjjsWdKY1 zFS_pgo9+0I7x*Vjf{;*q?@dG1DjIvQR$IGv&DLtoYC;fdgsM&Lt+iUKh&^hSDm99t zC@n2TSFZ2(-h1vn_nezQAV1`s&nNHqYdoHM0w8&3JwX@7Quy`2dJq+4VD(3e`Y%60 zDBMx36wV1Ax1K5ljTNCeW2vx}MTtC2`k7SkdT#^Yn8e<41qM_PaY0H?Co3s_CD6j; zNDgvE5=Z|Iw)#0G%)FL%b6P^9vRN)k0kk@hfL(^7O?8!SM!5*)s4@yymGoYR!DGGN zy5`a_+kR?(OC#@_29jsLqd{N{Lrc%VNTZiGkdGN8KvUOfBuZLqsA2UOBMDU(KN3Q` z7BSB&QJo0B*aj-Rme2vf(ce0%0Uy7fZ^_pVG?b_g^o3{Czxx6++r>!=mBcht#Z_Xd z5zuD$wpZcT{G!}dKR?{?$R^Ef9(I=7bqPBx9!$bDla0(9Y03o93ZJafF&)Hie32bH14)&BFb^Wjk{0ROG%soJ(-T~QF2}%W z8u2L#22Ce3H3g>SL6VK$^zHS=pU0Pw$q$er*ghK26j>9<>>&5jWZvTeHgjlaTehT6 z)yz>97vu+LKzy1`fci`?P0t>c-wxK`>IMkb0bkXi>b`>pVBpnal$87td7KXEM*_hi zZc|ZMc7)mAZ(Tp`njg>eYJ=cRXdzWvO#}m(1#Iu!B&qJ5kO~I@7ayH4p;3?JOmjp@HZ+p^+SfK;D6!zr-WNrJT`^Ou(B8X=Q8Phev-Kh6aR0_ycIY{a9R)e zu8WazK;%6>h~u#Q-8+nf%!CVW05-;k4|WC7&-!6%U`Z|j6|y7;HoB5bC8oR9Ux#_=?6+o#WFxQj!M4S zi6@O51(C+}VR|b$nAeI?P|rLpV=66P`@2A_6fr^5pWc*1=&7Z+E1-!tW@qe2)&Q}W zO`T0*9GfIct_>eSzb6NaRWJ|f!<7sNNgfUxd9KrXa-48}wW0F@%d46gV#fN!CYMX0 zmZx617;!3AMP4B4Gzkj^{~r}E2f%<@fsz0Ft$B~?|0$dFda+#kpJkKSacJxx{r{Ft zU@Wxedkf?YNqD=lK~uTO6Eak@<6OQmOYVr+|MgUo{M@cPit3aZ>oH?*_*72%S5x(k zw6-9(aSrlR%{s@HC_3zM^+MByThw*~H}|z)czha7s!Xt4?g;#`yKm)XS=C*_k@3N( z71Lu%ybvrm*6Oce5-;z`2yF`hG(e1WrN-z$+z43X(cE6^(U5AA`RCA5mHQ9DJidUzdc2j4^@oFGd z00o8Vaty_9_Hl0Ts9kwr0+KK&cwrD(at3nf%Y4Qg89{*@o_y4Ny1~k;@dj3(7xtn} z^p<#KWz_k#8EeHaT{fk;CdTH)#vg}{B02$#)pApgcvvBSJhLg$5D=$163}=m|6N~L zk!9P_uI*^MB<1;OCG(ATge8lHjcoekTROhX*i>+~zJN4_3bU5%zv-mQ4)UpTV|R~W zcV~CZm|nzoW?PqMK=Ib*?0(w{ByPH$;>WjMI)<{)N;jWB(DDZ(pJ^oPvC*`#JiqP$ zGE>;fVnRFMQ39&x+o4HpL<4k@G_znj&=Q7(hWg6J76iDRKiUwt)#~aOT@((W1`z;)DP(ueHptH+)opr}ERB^P#(H;@ZZ6#RHeR`pBJYrj733M6WT^NRLeG9tVb zrGC2o1f>r8Q-YF`_FLEB75`Y9GOf=mJvFWT<&yb~5=HQMR#CJxWfpw47c@b|?+hyk zoo`O|AaU)ZGM58|E~^iOV30EWS@_A>pf8)vSlfDZEf$QV)VD|~m-$YAsBcX|NvZjO zP|Fmy!6r?lhlG+|YblxTY8-6?Ofm7w;2X|i8Ymh2@bpTXHieu9QcMZFL}1KQe2$*; zUmHVR^oF7jw!u9bhL^tO@h~j%*r}scZ=8~UX*R!!2?UCKiqM#^SeN#Lo2+;L9NHcM zv{#$n6tGTwwloX`j;TzGvGeCg+Mi~(x>Pkz(*65n>~bIc7#s$Ze`CL5h)S!9=t4S3 z1gs~HT_2q=v}49s&o+E^(?T6ALI_zja^#gG$L|qS_|kIqVCU=wEzjNi2qbyUwTD{k zK;s@=ZT6J_i^q4e>wO1p*`(OeQ9NQjH16By#Xc@#wP|fX2MgEmr1@}?u+JKg)+%Ho zB%}Afzj!>fCr&Ow5y_9lgX#eo?W%uEj<^O*0d)bkodNJed?U2Z_iR-I@ViGihBN)# z4QQ0M)H;L}d4O97ljE8FO3<2OE+0y<98y#O3m6v-2{%WCkP4$ce`o-Megjdj%|fCu z(Nfn$NE!$yZa)$iFSJ+L@_3LY-^Y+q90OcJ5;!GSp+dfHHPXmvVpzL??t|}AK{yv& zh07eDYelStUlf%;BSPkTtBj=72FHq+6JzKafFkoVf!7EV=4JA>^iY0KeG%t!NV|kp z55AF&YPj${y`$zA<78v~(NhMBi7=Bho9CrF>eR)})zsQ_+nQFa$g~8&Q4n~>wS85F zUxIKb08ASr6a-YJxX+uoBB!_5XK_N}bn+yyg$DoELp^G&(SzwcJpe*R`lwt>g^cK_ zE6l~!I*lNOI-x3%g9LA65FZ8Df;aTTm8Porw%Fp7NTHTeUVWU)g+L) z>PS!F>FOengC_KKBzeMa(!MQb9zx)(7jqQ6pnPWFY)N|xjE++!y(FA@Nm8F}ekR-U zMU2i3Nn@J%{$ejeGV_wLpwYtU*D`J@rwTXj*~IU3BHYW{vF?gr_p4+GcY`Uj?(O}=ON89zw;qB(mE#}~xVYSzF2JlC;}J?1m>is5+)`!#!fA`2bYOU+ zD@OUeL|`%7`kbZPV|p-jfYToMT-FH^lL@7h%Je2a=s_wNg$y)IBi^``|9$D_@PH8r zG`Gs-P@sJX3%GF{J1>zr4|BgzyL2HJ#$X)EC}D_nVyzGw*w0$CZ}4`hY3^ecf%&I| zMk(M=?{h7mej^!yU7}Vm1DXzvCR+{8;=iFog0C7gq~|xJ!`rIs9H}mKC8pV%FK|o# zluRG7OAFk{qV!wR;H06N^!Mr)1T7sJR4t3B|E(wsBjSHNyBdYK%_gK9eV*13fL|C9 z$q};W8J1@$iPzEgWR8uL*I_e3TY7+%pL&!kXB2tH?}5ibQ-jA;Q3*FIYi3azxf~Tv zr1$Aj9rejX1$U-GfKTN8g>3OUx?*aZN=?>2s#jVPl?nSeeuaFQw-OFcNVhxv^E*t# zS#_Q0%Od^S*M7;EwAGP3#5P7Chc!}QzYlrboAvl|e5$*Lg*n2%oK zx=Fm$-?{71-?t13VQYgoW&zl~#cTzA)t`soVo*@*gkRj1Q8-=r$1A{Jk>Gx(CbX|o z312S-J>0{po}{`{$yY;+huFPGIs9+7@k8|=y`#p*Z^o+4{JpK z(cI$#?)f?JJt&vnh7_I=B3AfHzv3Z)vG5hTj0s4Quc9_89RE7yCpE)ECH1!7uhSel zt6yTC`+ooEmlru~sNV7Ya_<+Q(B+KYpkE;8cKEjB#_>ElVk^5N!dBjaZ^EkL$1ywr zd5`>{+Er99z33`gg;VIyWuB`GP2!K@l=@naMb$Xz1dzWzKjJ^hj5vG$=-jrUz#|Pr zaNk9dun-(L?h!pPfQ}6h^M7=B>k-rg2WP`EiQzd~@znEpS4F%48^C21C8rl9z=oqy zibS5`DZx>~r%_@aQT$5L67zUDu_$?BloT;a%_{23JYJ(U3OyXX0F6GrgO~Prs8boe za4XtOA8(8xDC@^45(&4qaaWb14Ys4L^$E7aF$N+rE{Lek&oOth9%@gs2W!2p3tOIaJ*#vP7N9p2Nq*QJ4h8xSUDAf5I+JIC(7RMvEafH>V zc=HT=e+7xXgpFmGNVI~NdDxX3qZ-q)Of$sO=}J`4B*XfiV= zi}ynFK_d+Dcv7khSUO!ZdE;BCj{kMAL#t}#hwF~}M)j)t+q2bP&_CtDJ8aK3BF+G# znhcE7d1j&?qwWSH8k_OES@chKW1%_}=bDE^E> z2T3;lyVL=W=36VvlU_@Hsm5;Px7Lxe46F`faDi^Z8Wh5Sxy(a z9l*%cifmh=w2Y6y9P-kB^0kU8^v+sE>da4umIwJTR{XJUZIZuN+U{-o=SOcf!& z$m<#oVE^+&$bs>QS?bwZ8d#CP_j(NK^JH4La}9ce7oLe>Pu6#Edegq*^9KEamz?tG6?wtm-PTuVoO z)Gf;_(R(bO{*7S8m{XuG`aZp*E>VpSY(_e&9vDfFMl_i68vVIaquy6b9>K8hHJbK< zDkaRN?4^3BY21OFk9bb_Y7AD1Zw&|0AUKP(po93PXhCSlAIM03DTmPu&~p~~;{1{Z z9KAYLSF5$Cnkp<3&YH-2Nl5LeOhDw2RD2fde}vUjdC)XYQtE+gpI1ukWO?Km%P zqgS;HwWdXpbdo=7|09no98(ARTD67z*j<*y_*!ONA2{STZuPtI{C>~M<+0X=PuY?C zGLgpT@@O2fQ$i-Jt?Bcm-Ni_{KW)uBgQ>zTYUAyf9r`y2jrUDDURigqTgEkwcbqu2 zH!OVpY4SS6bg4Z_@^-RZV8GT?N%+wf`UA_I`KBMGHKDJ5ep~(hi^3$W`uc3IO7VsI zq=T~0!jr`}CrNgH56(_~ue3btzPf)N(Y)~ySHAz58;@{c;ZSDd&RUI5F8jLxL-YFogDsmkr+!;5pnOpm`TRDQCcRS;WG z#;yykrD(8Fv-=&q^w>xfKNDv5G}iTGOqMtF6xJ8f4BgD&wiwyWWYkd*%yL!PaLe`( z5fX{@d}T0|eRr_UJXpUN=vRJmYL$Fw}K1aJ)CKuyb zWxAhfyIWC^&FBWn(96)X@K0#iW?otX$3}i~j+an*S#`Bwg>pM3%&R1O)XSwb|3mwy zn3ub|>ro+IJ6~#K+l994`)?AGjY0)-Yi&N2?$#z${#2=ptKABdj*q8l-G9;i>X&a! z>!6Cvt0h>?cAKEPw@k+d%NxhagUI2U*5gK2Z>7zf?BtF!uaS*C%-CR6xNqG=Xi??#6U8CRz_-TXMn`U%aW4aArLX$3zte7eeE;3e>vPR- zzeh?xc%Q!i>gAwqpveOl&y!q*QSU2r3YGVMa49a{iL-B64rZnN{5c!my%cO6s8?&d z%85$8wPw$q9I~F!aicXc#fY=bE>ZNRa#v>VW#y*az?IM&%I@?*+fgZ|VJoqd#Ma&L z?60R^>MthWw*ifH1@HTFFW-3^oRBa7tus*mK|?p~MXAGAaBg5Z_tGS5!U*l0%M2BF z=kudGX9b*!ar(&)=j!XkvhqqWb36m^w4nIcnJ=)CD}%;oCXp2OS=KECH6 zOek!O((Gjl)Ajxr;N<4GiDj1<;FSHtu0-?T*&lXNoI<~mIfcHl8M6F>Uk_Pq5zE#X z1lz5*PEe3i6;dI2w|EwLnP;J1yb;uv9KTzlL)1`N4A5 z94G%ad*XgtAE#^39sPb;dZ%B}JT0UOdGu(q?NJ}^;pw*YT?^EMyz3l4p-|VsjO{%}vStLkw9 zOnBSKK*FlBv7`V~R(J?=-3*);*DO`K@4NhXo7prX}{P_5owvmzVGq#{2vN+F1j0k z;#fQ#?5r0}4j%jT9GTj4F>*#=lON^F);6rC5RjHxOBYIH95FWyNUd1fka*L_^(H5i zKKeCj3HK@0QD);xc~7E_uJBlL-g}erVK*r`4@ye#tYF@vezL!D(>TiFlh%n6y#n~o zq<2IUC(QSA-Wt2WgXc}fLk-(1qAJr)KJw9f#-4^|?Nf1IiH;J|Xj3>a(`NMETw?jN z*^>_wE3JX$SKcNONi>nucK1!dVqZ!_CdH+dxpKYhF7#uJ@UImNU4J3II4T;$U$kcP6!<4yf_~r`V(dWieBZB~T3x2dgjQa3z#dgCt<`z2y|MqRo;LY99+bH- zeqlu^;TzYZqn{^}4a5FLsE3=d%++Z;PXp?~pKbM^v$yZ$ee=!!ep)pR9ceo4tNCOn zefCpD6D#xc1x01W?M23P9DQHo_0A~u;EoWHe?hOBph5R3Z7*!Uind)?_UnJ8JiE4h zzwOE5H>Gc(E5VT={oUeUHcfvIzvKyM6f9723Vyx$cO_(K(*Dr<{qGIIi$BLDWo*Ep z0Pj;BYI6@2p&Y8-YG^=q+65q?`_$b$!pA{Ihk1 zayCi{ynUDE@2)N7*ZkzaL&_%aQ%}n8RTPEt<1oMDK?3E^wpsV#p;ni5D}|{E*Zt>{ z8RcxT``>AI_rD*Ll)t~bDL}}hrd9fC4DH~-BgFY-Dhr2f#nI2>eteEZFw$2{QKgb# ztV9@VE8e;g&vuIE8OHM?qPVi~!t;1hr6`e8yrfu^ct}(#4#qMZWkrJJ0n`Lc)TI#o zl`NRrX*3stz$->jWh3Y+5%jDG`mF@Rd4hTtL5z)hWyWH@)jK z$Vuw9hHUBQ%dVvi8cuh(s8iO~)V_zL3$@vI=&@U*^Gq{vVi?lRMtCfsX-D&{p9;e+ z5rl4@4<6oPTPG7iBrk_E?t9e9&oJRt@0|r^gKorghc6I)M_>8LXUEi!aP0We!DQXH4(P$D^yNWxBO_cdJ+t>La<0#F9+8l3 z0Nn>ZboW928w$E$?jV245!uy{<>{JVYK?z^$x^c9>_!8N;t{8CkRA2;9ji$BU+5nrMeqjN zr$q&kp(UxUg(_hjWDL67{Mjr}0MjUfPZv|A7U_DGB|DXz;qxu6ILH7URYQL3Dslju z%e9mAmHJt(0sFu~sk%y;*JzgDucx}%*@zG97CFd9EZu~8#nZNmstxF&F%@aMRmJSp#=pvA z4om$xfCjJfSpezjRr6#tvnI5JxiWsilVhAz4%4Wq%Bgu^SotKoqSTPHU!t<(SJ_~E z`s;@L3G>>)_UhXSxee}|AI(v{tH@)Z3RF+`(XsYT0&k~ER_Am{Q(lC0%c+_(4EKqzePWFVkxH_DRs1k0BCkFlz?UA- z@WkeL9jUNEjnL4V7w>*mLM)KetJ&0Fc*_j9%yj6ENrmlU4OQ9CKaX;JHb-Ss!ss`1 za;R(SpX4;K^>F_4Yf|n&pLlT!j5am1);oo9ysM`JThM9HB99M{_Y>-#eyG3nhQsWb zb{5lIpi&83Ny)b6H07jIcuf0e_a(x+Ld?7J;Rxqh4swG0!tM9VNt>#!u;RMZ%9UMY zYBh4yyz#wP?hUal&*p|?h87PaI&SZlXM@%C@#mvBtziFGqz|ppv`w_$Ro98lvD3&x zqh}v~Rc3X(`m)nDRa9GP%T{FcEc+K-Voj6Jo0>Ew(n}{gg)c1)SI|)%T>6H5t>X2~ z{?#RKT01*lX~s9oaXx#cQ9I7paj&EO&014db;mgNV}^_;VD;#cd!Xj@n~$F6rh+$jHwQHQg5Thd|Y-!C1M z^Be+|x&X<>J)_pls^$;2Z0r#_*?iI~HEW&&39p-%nVf_eX_D@?*>AcSCW8s}P@ot_Rt&%N&c5BV@n!j`8 zmNB%x!`8ney(sB8kKIJR!wrRT4b1^VLvJ|Jce^BfI2Zk11<`gI(DWHld^i?Yo1qqT zeBty-OJwi8>`;k;@}gHy!)aH44VC8(D~*+QrgnTLqjT&^D71ZDyMtpY?K<8qPmS|q z-@GoscTSSZ&wb#;cJeG=ts}CHV~;(5x5UG+L8Nvd#Jkujf`yN!xNVj8n7vYWw|C#R z)dJa_kxKiVMB83C{$UTaB6JENm=90EQRkae3)xc(OTQKBd<(IlejQ9MqS(dn_;3Vb(1BC5p%{1= zA6i)r9Y&^FG@3+7zpgEUt8)XL2MG1f*{i;2qx=~Qx><|PSrG1>z2VHZMD?x&!;WK4 z0RIdJHz4Ob$C^a#E{(pkjBtB62RfL89L@!e&vER}ox`^hCKvQ(S&aKN-SX5#X~*WJ znBn~NA#Xh&9imgr=NM#ZAQtDWElnAYCQW*w1hW7uqRF;j$X27N#?f4grKv5XdCCn` z)=!p@K4d3-sHvlAo>~C$EmU#?&E|_aCg>VzbUubA9}RSK&oE5W&0YwHXz0+nG;rIO zpcBz5znWG~7$30Y)$yV0%%@`dWjeO|8 z%II&tD+iquOSR|?WAs}7$~zOyo$a-<4%q;m6H1E<2>aBI-iHMYn#zLhoRl{KanS}*JxlwnMhpr}n zf*wMt*1&52v2MX2U`v|xUm=(8d=CIDQ@C|*0pcM8vEDfCt>4{+}0-ZMq3@u4-*z;$z&8+kDki$3Rg>+Lt; z{&YQU8$SIW?^1Q6rdjf?uc8vWVGI#XtWTk`%N9j>bH1B(e3MWoIJgK3_J??zqM6Py z-6=5Bxu=Uk^ZV_Ad-le7fJq*Je`;^40K{}|bSLjGL_)JLPGF@A2%9(tlO(+fw6$n(@K%?ygwLptnQmBAHhAFLBjOyrcU1PRTvf@a_4SGRelz=F5;!oF^Y zseiwC^|KJ=;t%PIKcwzK_Md;32OwE~FwsZfvG^3hH|t>NtDyEQWF-a`6{&5_I084O*c5bX#ba)u9CNT$gmuNh(BZs@;nufp}ssiwN2bGNA` zU;JI5bpM?<`#YBcUA_A6W6Ix^dw;jC{(EMiNthev>S`?qwJ^6q@K{t@M5 z^6$drU!bAXnB6!FEBxfCaZ#`5NO|@p#iZ=^0OmI)l0!&tWq*+Bxjf2P+A5XqlcXhn zZPPGA`oHq1yRm=8hxr_4vaMdqI=R#3hLPAM8?B0+Ygy*vy-^Ujvp_3!CNCSbv@ePKYAlyBuGP%f;o&u;+>+VN-M3|0C(7h2cfPxh1hN#aT(RTv#H^C=RB$*w z#Y4aI-3uPY$j~T!v4)`#8@mU zz^On=h_xqDFE8B*wI2yTVVB$qEPRMzv*}*4`ipcKZhAHC^4I9%MP-*s5abuIxhL2|S%f=a zcxR+O^Yr@I80fug(|CbT??~=l`A>UUNyFMhtSOPyWNt6jT~H}XSqzeXU-d1VqVtf& zt=Zz?ck7Dji0`36*YrfoEUy_W)>&THV;^t6Zmw0Ae(jpZ!=vja2EtEuBm5X#qwU_+Kng5GD3|^y)|jO9 z<$DRuMO9HP(g$X80`Tt)UakWf%rZ$(D`v}3S3Rh-Cndxy0xnU)KYL^coU9lA<&7)3 zE7C>?SKR$`OuTd-tgn~r&<$IS)%@C1;ruu|U3q6nVJpko6pY5Yri>zR6tmRkBAxsz zSHN+$SyOwrJR9JI3r#@#KjNhVwYS1KPmAfX8CrMRLwq`JJO2_)_(lzEq$sg{N~8S< z8gYN#Lb{1?E$XSEMe>A+SS1_<4| z9(emn&VcgShPRg>&g=3Qs!C6r1{FZVrjQxnRXSS=KNGYKV!KpIFOPfhnhslpNxF}m z_fYH}VkSDyjj}6k_asQwK>nE&&wP>FlNHJruCqR*wHgdX#s6`z<}N_KBLMgJ(&y9h2!a^XJoezVTQ$bE;L z$LFW9w>_W;_DcqQ_yPPVASTA#j)`h`%quR$cqp3)5Nc>1ZeLeRb5e6Q*43cpSkp@s z8|uh5Hx)Q^x?+b&6CY0^>Dw|T@G;{emin&U4k}~0by@s+7>d>KVEBUSwWKhF7IV!M zLgD$#D;WoRgu5HAV`NeFd_pOUNstpi*c>K|AtOsEPd=7@^-sB9+xK+Q4qocjHXh;E zkeebPswjA0Uz5ra4kAVMTM8z6))up9&5m)pvA%LmmJUEfWlL`RKMox3O=+{FQb?^B z51)4e(h!5HOARm-a+RiNcyPcb8~&Nj5ugw0Q91BWG2M0qr0caXjk4VdFvEf)Qp_ch zh1!vNsc;Ed5tHBI3K!_7Z*PwbOf2)Eu?{__U0N*7uYIAY!kOaX6(!=jtb? z`jSt3s7+^!8EL0_^$mLP()z^=s`{Fkd3Ke%Sw$%>+tC<8PeF>~r}BY~TOz?;G6xpk z@$XNGSMM?am%^a*(APtX1ah?L0Z{#N6-NE`x#R+UJwb148bO6wH~(R!3)>*4M2u;1 zuH2|Q`93XM4I}eSU@vYRgx*RWd(gQTb2Bo-^A%tz2h8E(98tEn8L#c}4yfG~46CjVc^uZZ)d1-%cUB@Pt@GxRwkzsn^-s^e{RKuXgPGL!o)8zv5IwfOxA2 z9O|^vFIcq4^P7ba+IBTsV^=n17P`tdE|+E0j`Upo?&|mrHnMehnpQpC3B8)noBO+l zh8~KY{j7vzG2N%m7lr(xW#LKFR?0ctKbtwwfxLTs;kV@~oem`6?I20#jpPdu043zX6@Y3x94uY+kk+uWgfY#bsS&s2_Ug52UOY3m8#TZ)E1j}*uedOl zi@3Yo%#pY*n|PZ=$Mif+nSjdNeyR8T@XPbeEdOR{RopfkV~EcuM$fAjzTcj=EX4g~ zDI^n!SZ8{lR*KAnCP?_Mu#09>g&o>Tqkrp(_3v_vu9aVfa1k0jH7QX5=tXwL$J`6a zC0?}RUCWJw+n#i;*jH`6P*nee|DAG>!rqUCgFET}>|dn~eujl#TD_c-{N64q9!h;g zOAR8(N0QZ+ufToHVYj`Tm8!cHib{e)Vx-#O?|KsWuXlX_VLt?Rf%dQ$XX-SkIsvaX zxa*UyoEUG%*c($+A@yY2)g<}w*CSuBKLoKq<;Y8K3LjJ!crz#{X{udNMdq9lyhCDW z43tyI2^JFF3r!kFPgIoG<809yBrEdmnF?XX-pkgV%mk{CDZxWpz^7N4y|?3ac(2$} zjrazH!r%{kcS!8zlkGokUtR3|i+f^?iM8}7bSH^WymK}KJ4B^kuM}!3s>We9*gpuo zzOo_L_#2vvChSD_ASL@aIJG&0o){T(M53vdAu(#d5XyggRD!etwskWZ|ld{`N3Ipv};$XGO7pSL(^Zk^#m+n zJ)E@E3txB*s}xM|)t`aod6RF#1$sUOrocQKT8pbE#SvzK9{*^BK8cuAY)CY-(opjs|5T%$ zU6q>}1+UJ2^ACwzc8v%2p=(m65MS^`$0+^~5c}{rB8%{P5z{Y!ZRv#YK)7^DJ{+QTu%elNB`$Vl39=0&`jdzP6<`b_Dxi21=Z!W^cJ!s6 zCWce-d=ZlkO?vK?IYNmuY$iE0uHdUClBTUu4+m~!9^|QU11Va#tHZH@qp^zhCSr6D zk+wLaVROOy=SFDoQsT9n?Q;AF(-#r3rDJeY^RXpkNi$~B_t(%khE8RT_qQ$ITjsYU zTXkBlUQkMZpVb!ES8c@Q!Dv49zP6ErITtR7Su^-=S0@2wtT}GhK3Js$1|T^t)1`U^L$w>g(dDHHK?&VGR1`CpzN05!+S3`_v?1jj5fTb$J4^`c|q z4YIJrIej>D5VR8bT)46(umupwThhbdi##{py?XJefV{GQk z)QrNNPfQl>Kb-9Iwh$pqv-M}CuE$DXOc8}qMZRetTJOJeiq6Pr@nb@ z{RqOr5^r>XXC=-XZswYsN3Au#6?lpl`TBw0Y6}0y{JACdQDXiRbL-2US5N5TPcO5A zVkVNgNAHuMwlU`=Aw$Za4>0~yTdO9ykV-IrD^%zJ5B@s8P23NnE1dPnfPi|+y7cM)U-GHs-;g~1P*DQ_q@^FxM zxF86%?`WJRiTQkoR0kg?jRsp+M*SNzxr&H=8Zy5v?|j2?9zf$C=jVpw;L49pRUHf@ z95zze)N=Z(W}a+>YMHp87i79(oLVP6_^b9Wn||Fhqj~PAH0bx6}{SN7tsmH4h zn||%Ld62Ur&?RM3_y!=`#1ykxTd^*0OxZ1uW^mc+-h^3@S!ZPIHuq}ZcyEr~N52dggYb&o8FfjcSwH`EO{KA`TBB}o`igMU=Y2bK z(!7X}gE52OTFT#kG@Y8Ovb7YI(+u?48^8CiH+vUgY_4>GjLvQfpQE6?6Zk8TI0*B+ zW`3Pb>$0N@S2^3|OQ{m)3%ukB6?4h-oXE& zY91|oN&*vsM2VLqoK2PVmw$9%ulv`=ebRi`2r^Hd+6umWw~YU>?0LNJefm1ydYIAZ zACa-kof2Rm^pLdY>^laS*ZJJA+&2bOz2kM@ZhXW>WwlC3aR#7%I0zO8#@)0_wj5PU zAI!JgKPC#{rocCstmf-+78|52((ePu$ZB5`6@|>>81h|@j}A2fX?FShUunYQ{>qzf zCaRh`0_!m_wgbFRD+qeNR3-*ME=O5mFFnn2c)BGJf)SM2x7oLI`kMDfD|LOE&N}(% zDSvNllgURZ_xCr(^%z+9hR)z48B>2d;c8Vz3|2D9;#8<}{nZhVqJ~{&!x1C#@_cm} zBs=?mh_|UCNKxl@dGm|rD(~Gd(D5t=>dWtE51rhce&cuhmxx!#f{pODlfePkb;%e? zLRl1h3=D;U@z3LB{BXiJ7`)QOU{yAA_`N{PI>4nB;t0Kr00ij3LI+Vwg_fyNI$p;2 zlxDr7)DH{P-~67TGN`>*#-2Y(b=5@dW-XZ7&Jo8l4}P}}WnPW#6Uo;IpqBK$l2MtZ z)4-IX9~3z4Nb-oWz`*?rn{$>#rBA+Oprs@iKT3k1;yQ$cO?~&qxntL zKu6u*jux(b;0#$HdBi2iTQH&4PV-1>pm@WUd(w>YaoT0qdJHpGW0_Y86sJ|3xyLD3 z+Z`4dYv~7TqNARl?h2%MvJB)2H7iHo9*TiG5S~#hRf0_m@$8S|4_@Y4!{co{U`_%e zDJ=%l-Q92R^J}mAvg@4P!NaJ`K}z-R+L|05fmb>Y3l5W(?B}^?reRV`-1%mtNUKHehftNkfHAwF&Tv3}0fR9tkvlYAzhv z^;3&u64`ZHh2sCPbw-##8-Lw@RLYiQ`svj3Pus|@hrMu>V2(((#@i~+L-}x7lW&Po z&6e&Fm&FS#if4%<6Lfh?Ji;YbR9rd|yBM@#(v5^ps*oM@96=5oJ zD&HxOs=I{QkMNkjBEe%j^-*+sXjuC0jg+k4PQmV*jvywQtinT_ya{lq|#BzX+w-io2>O06@HcUW{~}^SXs2fKDCT z2a=xk5*bCW)q2RDgPqK44Tl#JpUGX6BVpdccLqqTx?l5u$PqR=0bR#BTEC08aWYz2 z&|w8#eK;cTD8{+5)ClL;`sy`xqpSHVf=cKdve4|~K&?%S#GfHEHePj*%zn=M=fz41 z>y75$w~{26S_3}6t;;oEs!&LE7tgCOH}8vk01y5fd|%)-MV9C6slf%GTTcxZ{G{>B z$lJUs3lle}nQ4cFl1{dS5BtpKa(oUr^5gHP+00~G z87+VOlqsE2D@SsM;h6b8s-5t`Q0fbn83>LZ@^u=9h7E|BPrVew~Q?hdAS&P!fd?C+_#ME2L8Y`UE zIujTkS~l={aKH{wm;Iy~Vt5rU3&eTnV=)j$4JgCtHH!8M#8t||bVpBtcLl+E^|o}d zfy}-ttA%Jj6icskLFdk6Mak!9qJ>_YZblk4rve398?c-k{#+&kx0!of`%t{eYuBh^ z7A>bQsN3tW+j@Y`SGI3`@r#NUugUjc5Vm1!HN_Z8%Z};AcrY02e$kJrE`IDFv>re` z9+<3ISvZ`LFn89zmxQ4|idP05FfusC%XwRrB#0~Na`g}xal&8nAcI064-P|2-syoS zP_#0W%v!X1frh@GEJ$SiBg~ZWTz9ylKc)!EKY{@fdQmb;Q1f>$nc}n1c^B9@$+A1f zOcMoj;)|G}_x^g73RT9gB`?@-1l`d6lgK}!LOEfY8K4!C9-9=F4ZHv_${kF@gnBR_ zT5W);egK{8-j~Lpj_E~-f{+aZEv=Ta#LP#lE)vr>YvU%Lm_Aq%vFZ^C%Frw}&Lb(j zFO8;Gn&(^mJjngVmo+$bK0qvqCiQjY2+OfAvo2$HZHkkfpdv$6@q_%-HEPe&$%rRu zIjOp_C40y3M>UK;U7>y{*C0akk}-AhZI4=u=6Y$Fxl&zR;QL*Mm+D!&9s_q%u>_8w zN=>9Sr`Tqe+3d+xrH5H4QwIOPMej?(*ciUk2%|cEZIMmMIa8dJ;4MKBZK(!O{aYdr zwHjlp3`?f^o1K7nrqg@1-8|&q*5en$H7P$PBPou5hG3=z>Qr?A5bZ;~u=uQXNOoP> z)33gsr>{0mZB`uWb1&ig=kpR~ypU!Ph))-oX9QYG%Q!zB+y;7`dYK%?9<2~>|N9fy z%hXQqf+=;P^JdfHUdO~;ZZ@U+E!4qI1>lZ2XGQ6cA2V_v1mmtb_OWd%i5~W07PL^X z3Pde|aL2T+Qd>ut6$rA6mYz9$g0hA8%m4Bt9{w)+LgHt5A0M6c;I$ynyO7?6RESyV zXaYmNo1)9?`BpUo%MZqprQ{k@nGCYGLb^)$1g-?FzADFwcC!*9XKH-;k30QWuRdNWu!lv?=@1gRB zCQB9iHn^$aO<0y@S1Q^@6^sm=g0M*|CwM{&na2?P!bE=hfaInk={0(<(HF_z zNO7w3c#9sUXV*|W-Zt#yqn zT_ci#9-5V|U`@zA%DRu(Cd3}nnC)ykJ6qf0mb1NuEp2-{+hedzEwOW!?qV7d-_?{w zhP7ue6&n$s(nTNB3z2ffatU2fBa9M3YC_l|jnv*XthkNGZSN|L*7nx6y4`JTf2&*I zN&^N$Z~*MYF%GldLK?TY1#tUYTe99F9%sd^H2iyu-NpmJUlneAAzU$X&`)(1zOd@@ zLJ)HtBmnTNR&x`0Sm<7ay8l`+v0U&u5ikURs2hxkHpIvlwFaQS|4m4OYb@6P@_50q zZSXD3DpvnS7{b40aRyfF7Pp|cAO7%1KMV|3dej5Q?C?hb`r+f*Uir!Hb#j&$Y}WBg zBOwO9>pqTgrzNww&ED{@I(X?pr|t6Mr==>qPWD;ZLFIVq6?uW#1RVlg*K4d ziVcdQjCdF?S)B}JvkK$M{$PhRB>m)m%=Q+N?ni>{0p-q)7rhKlYiyT51Nl{l9ikRS znL)kYdhjE*l^!dUdwXenI2pkHz;!>qs$hkL8olvQb07QYmSiWpI!N3d69yj8Q zeI^XG8=GB=OpMURbpJ&FQjvv7#MK|L4gjWeEovXH_tISUhgi)mX?hsg#<#U?f~BmG zB%3oG{)VePJRRj*nETiJphrK#TIt=|qaOX0Mm>b#)dUNJA9S^J!leP_OmkWro%1)y zL+)>Lx`Pk_K!!7>;f#8~0~DAj1SX^rVw~!^+KkM$dAxE9Oz`{?@-Qhu!N`ha{QMmC zsIp0AK?`lrff8&Dw!q^NWn2e&9~{@MyAPi6OLKhFV8yb=OPdhlUYmRETE6nF?UB;5JHzaSC%oC~L5f_QL!OaNd2 z2%toaMgYb{MHrw(_@4q6pkFYc07f7JQbYq%-~$pMh(Ho3)ZhJ?Ui^Ka{H5N|fgmfe z!XH4wnSE7inb|%NT$Ih$+o9d7!JuyS13hqDnGqO(MO>$;T9ReJF_6PC97DbRp78kt zKR_Nk1pk{^d6j{Y6_LH#dhu61P+hx;pFhysJ}?71s96wxp%+pN#e4!G5QHwY0^@xH zC?rx~5Jz1c20U$$#h4S?sKXp?kU7lZ9Y)I>Duf>LVM16;9!i8B2EZViQ?$^b2H7Fn z1R@{?q9NWPBbvjDrNblkAtVl>HmHL_lpXbG8$*bNE9}BF&_Y58T>$t3G*AODIKvXD zf+@1aS<&9_kyQX_T(DuCFx(Ygv4dFI;A|Bi+x1uR5gZT3))l}2zcE{+g|-Jdq(0{3K;C1t zOr$|pL^;^RC#IO2h)qRo5H-AmGiZY|1b`@LgDk!l;FTIK78q#_-&jRi@oAhd`dy|e z1lvg++hJKkB%?x{5;@qzl|f!TL>Z3#T3LPCE&du&KAuwYUG~kIrQw=c?PSFi5j6P~ zUj#tj1OSL#9$okXLsG;-&SO3TWJ6NqJQAcmR-{_uV?D}cJRW3Ou4Oz*1V6GRU*cs# zY~*p^Q^ZV?M6g05PK0>HmObzT#>Im_80DoUgiIFS_8nzsWf`ai+os{#dTnC>*#8&5 zmC~3c*m|WFjp10CeU)5+Rj7s4EkYWvX<3e`AcJuso~TeaxK0suLv9AZpv;0X5mOV* zoL!VdIV>bZE@W9^q*fqjUgqOLwk2~WXNd9cHlvfGH{( zc!^A6qGqv?W@*+|Y8hBr&8C^%Voko*X*O6gu2zNVmu8hODNZV?wa zq(up-MU2dXK}<`X@seE#XGI|AULNE=9%ld?r#jrFUq0knuBAX)WM4k#UOJ?RBBVS< zr&ff|U^rGMD#RQ}L@P`~bT(QR-~oIpgn$a@S82rxO5Irbs6?n54d9pRg#W`hNJBCR z*I6Cdlb#paO=)jMX?vmFfw|ReNf~jm6kk;Y5*;KwF_&1*1@HKyKN@F3?7}YaLMZsc zp==~ZYQrvs0x!5JFXRH9MZ}%vf-eB3KeB0?9+X5-XLXXOJx*kZGUr49W{0Y2g?>+9 zZd*ch7hnYdi#>v!1VAYSz==eJc#W5lL0Fb%DV2tmscM##QfUja7za222e{5S$U`qc zqp^)wt==k`*(z!BDw+MNuf{{J;$O0z(k!KpK)91vQj0u|rHU$qacYAqctH?A01m7{ zC=jZkfk6iZMF+gV1jv9T;A1Crs}zJnhf?Gkyg&zN!G>;yqE=)>#{X+uT10fJsd26- zbSi|4zGx)D38BrX@~Oh7hTAN#h3WNbt>zoU0&B1SD#SJ{uRv- zMj9$HMGKrt#743xv|7Y>9;Y_=0(Bk=J#H<}_A8);4OeIaDs*Z>yn;$n0yES?$*!!* z7Ovrz;>o70;wo-39Dxt$XE$hNLZE{=N(AMKBZXNmIhJEZWdAO+^$|LdLvDU4T5#o| z9Lk3^tC>#3MXG~K1i%}hf*y3h1Q3ENY-Bm?BQ1ymEvP~wbZa1xXgL_c*S~VAZ~~-Ggx!K7 zMHH+;5S6jSSa`JsCwcDVPDJKzuIF+tIfSk`hHkO}@cjlr58zkoh=W@sgqtn!TZ|9` zKk$-`kOQ|FORbatAQy0YrC;ccgw_RFCZciXD>Gby5Tv3xpaRq`!qMs@hbH78q{JF* z>^(X|BlrLlsDTe0uR?f%55PecOn?@2C<{ZRHp~GXg#Q95Oo1o_fEo;fE||liBw8w- zZKC;tHYD1M8KNtUfd)OKIdlOdA_As6zp5%TALE(H@Zn_X~ANd$Kg#4W*t0jaKB zP-sLZZY^+a=s-XxXsbfVgC@)X1jLIrh%G2AK>!#69}K~{cBnRJ!VAoRF0cXfYU@On z!!+;)FN91jJc0}iK>(QV6oA1Pkb*C4ff=yD6*?3A8`^rS4Tn^YnLRSYN$BkA9l7kw`a$)jZ9A`kjYr2{PBd{_O z7%e@@V>y69(++_Z7y>VF7!$mJAn<}qSV1UULjZt6N z0VnXnC9uIVt3k+20VgCvBk%$zsPIOv0vCg2C^StfFasEygDz|VBxqzgr14w;Rh+CC zi;X9!N=HF6G_yH$TQjsmzxC%X^g;W{MUbvSv^CribPE|YUsE)6JloAiC~-O~MTD?A zID^-AKmd>e((-Hwm%}6EfgUWu(E5QkRR6*RB!QiJ!3#9Oo4Nw=zCkF2!WIB=E}$!k zCL%Lvf*w@CDEI;#ST8L+0TO_75ir9RT*5tW0V#|E7}&ujz^Oi3GaF0+HebP3_x8qe zar#OGS*MtCV8WWZL%*_fM7(o1#B*Ep^~Mym>cn+i&#^fQvLVYgUh}bWRrIl5MEnr+ z`y?p}$?Pm4*C$kjM#BY#LTm17gBqkn5Tt@JMau^1LZbO8C4zzy0I@27fdT}r4}7f* zbbuaof(!ty&{p^a)BqwJl%bw5obo~+z%=B>#jNQ^a($$w!XGL{yeS1VSf_fz5AnoxFElV7dLE(0oVoVAt&KY;ZhvFk&~VInXc!1i%zPLbRCeocTg2z=3HWR46of z5wBpg+`kN?6dclIc_0*F^6DuBTifPo$`gD%hl7=S@4v;rG|0UL;d zIWY6TFG9Z$JR2;+y9&Ij>jA;r2{Y({ly4-#*SmBRhCbi}P$7gnoCP!}gvcnwD-2-@ zWlXQPwu(A?rXWdn#Ho2RC~r8)`h#!q)~sw@$zeOu!b%v=7+9DbRu*1p2qi zz!a>4aVDg3;&3eMBh>4{902k6uI)gU12a&4>)zv|CWKKVt;>QvKqlm)CZwv*c|vZj zI%K`t%KC`~z&SI=oJfQa3L!QGP>QsVT*Ulw3_Hu$MX_5%;iCvwLR;_bH&+}Ai|Q^3 z3&9Y4dkO1-F(APZbpHa>C&CpFa{%-Kh<~R# z@{a>y`@%d37C>OS#f@J8g9i~NRG6@wI&%*LJao7)fI4;Bbg2ta&K$*v4G-D@Hu{wx-Id9qX3WyEkOqy$Jc; z`gw33*Z}XewMqysAyP^Kyfyth*`QR)m-UJ})h3cHV+IWy99xjGFO6(Zv#pr=v`Eyi zVZ(*Jnssd3w{gFY+nV?8-KY=dqui6v&r7=w;+*Tz@lwf{^;(8L{V7(hpO~%k6#(AB z(U*ZCG-=Y{c=O|J#y!8DeS7!s;m4N`e`0sa^?W7_T|Ft}0OP1DOS%9FR7kTnUiriv z#Sju}AkuRB=O2Xh(FY;n0`Nt{4LR)4!w*3WQA7|k)Ud?uHazjf5m_AZmv1HeD1+g%PhIv z5=(x%4D(Ad$@H?!GtEpB%{A3*bIQwz8w{a$wsXp{St2{KNIm(?%9dFOLnz7!V>GBj zg@m)P!bKTv)X_&Fja1S}DXrAfNT~}<&adV%$d!Y-F=$7G!g0(SZ}^1D$W*60P)TM2 zs8P@dDLZsBTUpIj*8nsfY?s0U(4`honG5p2A$Lt^)nq606T4QtI!KT~_rkT>D&J%_ zS8L%U&Y(+VWsXOLOhr{&WzW6rzy!0~4jxjTq&8iIvYq!xZs8QnSB22|ks@%gG4?-u zm;beQD(kjt_n<6f9>G$(A1D)(b;e+GIX>)6%qpm%D$4d9oA z1R4fHk8u4*I1KZ_&>+JDNWAd?ur>T1#uJiIxGO0-d?CgU$MByD9q*jp&>x@JaLpBe zn)A{peq3`zO~+a%nTreHxPy!m)gz`lj;v>}^{!6nXX^w7k)sEv$X3}aPaXDzQvY|p z^cbD5eshdHmz`qiDc(Fdr=rh?`JCPk0J(Pz(uN#=i&YBmdBYA~RA-ri)*yHrMjEPo z?g_vhgWll|@g1ap|8ocWK9`&Wx`TmFBcK8O_lOV}uC72?K?44{of3A`;UYLZHElSD3>a-MHD< zdiOQ?iOp4g3zujx!4s?0f{L|BMJ?`Op$WO7imIrEE(U0jRb0`Ft?og#V)|AXlhW zRI!eRa$p+OxQZt#1Y)$4Q#-U#vTGcJ97i+|&$NY(B_7OAv*2R10x*c9O~rEj3qb$w zF^?%R?jE=_i1U2;%Y@*vf2M2UEm1biV>)h8xSU7-5|=1j_VSh&5)LsDRZMCEvzUt; z<~@{ikV0y3akBfN`2qlqgOG!6?ep00Rtd8v!m3Uw)8Et@7tO>K3UT_Bo<6$?y=Zs%6 z<71i9Vo@~4nZ8mS1RLx_qWj>fCqM+^tJQIqLH=ftLQE@doLuXoEIS>E zvCWvOvzD#u+C#WT6l<}_W1*57ioQbivQ7&rLeil-clxfeKueM>P?St4#ZA>xvWsW{f>Bh2+#wbQ;h|~~0{@HX7V5p^n^8it8`}Vs za<)p$6%fk15N9pO7xS=B{?;3{xyqNrmyy_CJwn=pWFi1gNQhAb&{Wk9BLE^UE(@zW zBSD}u0IUdrg24*j2pbGxEUhOLrT7#O&-cZm?X6|wTSy+}*C74%L{3!PV%7P!vlz23 zLLfOx?|yfywB51AHbXL#HAr3_8FFpi8>1&f#R;2eu4-Y-NvE(?A?HMnHU=92ljaz) zUj|t#iT1b9lv%W(-7t~sJDvDmRC$M{3X4BSW#M8Lr23+2JA#;sYmg&UTt1bbEjG`V z8icZfql%#?O_ei0WzmzCkSUZ)5fcYs4+*(LizR&_tN+mMAb$&G05%oFS1JV;#R$nntqt;Tfg^;)x(aMNunX*CxclA3KDNAB)nkP% zjL_$Dn$)i3Xz1)A6Wull$H5J5fY0=_MB;UF45D3O^O>s<*Vf2pp^a1^ryZOK0A=rK zuT__`LfJS-Fk%68CYQw&BXfsmJ0c3wMYJAv>pa;mK3z6L*V0G@G> zRG`D8StZxqE1&F<;dWTuQ7^vr5sO%a8zCkRy|>+7Yeno~+rlS4t-X!>;e$I9Pxb_f zpPvagkJ#SJsJVP^DBZq?1mdV_POfuH3AiYLR8#dm{W*RKYvvDlbG-Z zS+o2T^5o_lWcqIQ#3r8asOk>@k?#5WC+a8zAG{?1NP!v*0u@S%ojlFU%8ySjuV`i^ z=Rjskg259+FCmo9{;W>~Nst8Z?;rpW|NnGi`uOic5b!VbK>;ld6s*A@1}oUGj{GXn z0%xyeRA?8%j{R6AMy@1v@+wPx0JlW} zXT~5h=pb0{q~MM6b`UcjYgm*+5Y~_Lv?U)bBpZTZ=nw)8s4okrPz#-p36~HHPi)QZ z4-2g@5Sfq(J%JAo5fHafZDf#P1OXJ>0Vg1EyT~x>&QMP-?;28pXab-ZL}MVBMM5x# zhhl*V|7{@*&ky^}BT%dr_3IT8VimLS#H8>KUlFO`unRQ>6HqSC#P6_L?h*^6#}EP@ zn&IaB4%*blLg0@g?jQtHD%)6Ps{bg0;k0V_OZlMr11(FN`9IWy6$}k&;G0be?8nVL~!08kDK^a#jIR2p&6T%77 z(c_G&ze=&cn#>d+G5{X3s3!6t5V9f@LL(_sA~Dh1g z+!1T?jVgEo6fof@(u*p*#tdijDQZ$whDViLK^JoA5)eTkaDjD?taGtwwY z@*|(36bp_nk#Zr962&eOB>zVeDHkcNrjjb^As&Ci0TW^zUQ$#9hAX>LC+0?Hh!G*~ zVU7gi5;QKjVh1Yd@F3bu7OUbSDMB=3aWqMjBK7h#{c9lxb1L}3D*2!kwgDlCp+^>T zXY%neDWfU)hHDt4JI*p5uZ2)n(FyDjznBFg?-C(Yb1$-JsWNji>H#)EgJ@LZHgQu( zbdxe9Q)p(PHVG&^1fmZJ@?ta&+h(oJ4iPzjjyW$wG)eO!RdXWg6C>@DIUQ%HqVq5O z0Tb2_A#%rN$S@eUb23&68@MI_YVZ@`p!C?w>0nX!@GIyj6zG2LB884VGZZ74EJO1v z=nSIZKolW7v^g(y=>O<2zdAElguyDqu4eXzXB@LYuVP1f%)5RqW#B*--tj?m!W<2v zL)-I0*;7S_)JRD*NRt#vQwX%0;6f>F#RaC;l zR$)Br4h91N+wjmJoInv)6d{20OD_Ya3IPiiM!bf~$M_LI%KjSOR zrx!qh56s{N55ni1jKpHiAS_`-4MGkB07&J~=YqjfGj&rN)l+{CQ#TbO+O$YINDW-}6`h`4bT-l2bb;T8g*3__ti zp&}O6(IC)Z6aQQ_A>x!z-jpJ)bs@6#RmZUp_@EaGK^FQaj*KlFAP?`FgHLyLDtx3S z`Q{*)K^35(9k}5Z5;XvRLei8>*2tjA(li^Sab2gQ3}6Zr5VK@VDpd4zwgk2++_jZH zEg^)V7k;7)-0v?!VHkp89paQ@vyF#9Hcdq~WJz{pMRqkyHf2rLV-G@QU3O&w_GHzP zRki@8WT74u0y`N~Db%%LtHW-FCt?wT9&VuzlC=;RX)SpV1!EzpNH0sqiCHZspr|8^ zQUxB&07^gs6q;m?5@KPmqCY6mXB~?(ij7B1Y7`vMA9_IzjCKp)>eWW>4u%0pc_?+1 zENatKIR8wtZ?EY>O!Alfc5exHa1EDl{floEw{REtaI48ArItV@qzt+M6M6v`F3dj; zCP;dgY|C~lyg>p>Mi=IxFlP)7wtx?$iz3vNO{FzWu`PB%R!vzpb}yA=c?e)<_flc^ zc5@eZeHV6PmUh*2czaiOdv|w{*Lbl_cWpOU@F8op)*1Lg7a-{vu)!V$l+XO5Pkr|C zLN{m7F95!wFiD{d45A8@idxAn0PK(-0M>csw|VJTcjq^LV;6rtc7N}8f9sciJ=S^u zcYXtye`Obc^%r1Uvnu`p6s$lrgn=6BVOU-v020(T_cY!-_iKsK8-8SbwZR{5AzYq7 zdjB=kzk(qQnkyFIAse_M8(cVsW%z|(c!q5_hHE&7Z&-(S_=a1!hjAE&c{qpHVTgtJ zh`C{bsR9lj)=7YZ{WgaE**&4Gde795mW zA~%gs7%CzcX8yqr)Yl+zK^UCD83JHfMrCt(R)eqjPhDm5dWIf)p&f7m4g#Qwm0+Bj zW|hir$0lS55;+e@0YBuy#EkY!u~-GXh0$Ap%)-9d#hMRdzm?4PIC!M9(sWy24Dr2lPy`Lmnvi(^nsdS zw?cXe+wyZA?zyA0VVp2Ji;_yBk82%BnxdImPyXQ&GGGU2#31N_6=*>lJQ!#ABR31$ zKp-~q3<4W2IRNlDRuDM=GC%-&03Oonktd^<;1JuG8g{SA9g&NpJ9-!hX_+$``}ik| zjw>6Ox}*)}9~glH5&|cn0iADbFVa<=rY8bUD z5{DO*fCqjc6uepxTEGL|z@+D45MZDO5CPi?sYzntp6db9F6tg!!2&Fym$sk0$$NEacdiAEYv$o9(K>&rP!$G%M z!5mUy6mm2n1b_t^2Wym?DmrH#R3Qn1;Sv&Ikr-hM=AjY%AQ+~f)++W9%z9XaIzl3;lBq| zR|VX*IRj6eyjOQS0GL4(Pyre`B|H#90LZJyiR2#OK?sh3uvY;LU;!SwU%2?01UzghFZ4{6=PkbJ#Ko*dI69U)N??GAd0Tz^C8}6YG)*u`D01obf7g!u0 zQkuOuVF+g4Ai%(AJ*f5$LK|v9(%ET80JT(H4egJ9!5t6u}xWD_ozoD`kA57YDG@5@VN~;qm{N0gJ z^r>+wI&n~1qQxKmzrX(NKOaH?_W@x45rPx|Vp)Iyx>9utV2hl$h3RN9LkEtWxPcTa zTC6B83#9A$EU|G^7zg#pC@6b}y6)(RC!a_?y26ekgCMoPBExups> zuH3mISGI{Xi(^HaHnqKbm+r4NZSq+4>g9}Hy?V|-B`uJGZpA#C-9&R~shrumd7H$w+fp zGV(a%-ESw-lMGHdIfv3(ZM`L3jW$MS*DEhs1P(aqpdt#8LJAoqDn=T{N-~BWhRKEO zU07dzpkOj3C{>ij1IRdMmBA62&VGnE2p;ug3O@Y^_=W z+pDg)z6xu!&{DK2R}7rGMJ1Q8690fa1Jx3MCOwH_OGlN$R4F-!YBVE^jJ^vmNYq*9 zO*if?1QWjc>T8QA;RYg>E)}&BE=4wQAgioeX~il7yE;5;v8Xy+?5Y(nd~wAVQ|y4S zLvUbm$Rdxd@v0DStT6=)P@rr`T-9oW3l_QZZ7Z~RHBhu%JMyYUVUuU#%B zYEilh>7?&W13l7+xU^X0jKD;vB&-mpUR^6iGFzlcDFX>SO)cCGR7p<*?YwlpJ;(HO zyIjw`=)8Dc8j?8Tj58_UZBuj%I-;m;QQ6vzP1O%VxUjeoHZ=Y?<2^*)IO8(A(1Xl2 z1b{gYM_{tV5ta>YQ`#_~HTl5P%RA2?53x6^#MXDg=XjHqHZe zV#_i3UYaht=)&l;N*Xmscl0&pc%8i$h0~))Z@Cqd&pM%VQrXi4P>U|$O5aDGm<-g2 zMeQd-(fb3z-&7}rTcnCbQ}Yx6Dw>ETDRoUMITqob(A2^%w;WJ<42;UWj^>R>@dz9P zNsits7%2&+A|Fi|Q?qBFQ=86o*(5J_ev{AsmPv^iYvUR03`7v(Y9mlBa?#Dr#vH2__!_lJQZ* z9Tv$>(VnM7L(1|b)zOhR7TL<|TriO007o|t7l3xmqawN}TmJy~2uCC$5CdTY-5$}4 zPZEs{dT{1Nm|2lZ1{0X+@CF3~DU$5XWsta>r8xuOsJwJUF5vLSH3;I4s|3Iq+5qAB zMiGET^hBQn$pb2FL`{)Y0u$04S|0S^Px@(M5f#~AD^z(AbYKIW7I`FelIW3hYV;yT zQzSdPkq(Nqga41((1ke&MhjY`q9=I>7yLRwKZXvi5$fxtTx@y~P0&veJW0g;DiX%> z9nKx?;HJ8+Cqe7cg`DNwC=(yJql!H8f>9ZaDtVX)J?N8*7wN<$4swZig_3Apbe|bf z@j{EdV}!1JB_)vN)VQV-QqS?@Pgq&fim2is^uy;sNmVQgRrGT79HL=z}QMJ-xk4uPG+ z9cw*C04O*#rpDE&9j#YWNkYMNFe3m&J;&i7ioaEuB(11b1u2~CTo*o#&OxjNgOPTP({bbB+2n=Me>u1 zfK!kfSqP0zJj=PRlbz{!#o^lFj*^xQrBEpbRg6rL8UrH$IQB7)Sp?x}9AB_9EJF1}pWOz$Zi5kPp0$H`+>-qYh*q)CfRcUAV+(M1vyMphu9YQE2H{V;fBw zbN@(0EEr}?l*LPhrJncvR7Accg3-~2JB&NyTGWCT%q7}6C~Xlw*5ek`sK+=kE%K9k+~(O!WUN}}>Bm4W*{#qUb|Lrc z(dS&_6`=|WC0E^Qx>4I7!l-p2IS~LlS_B$K<(i4Ty~Gsjg)S6yaRA<7Xah@+8w1I; zwB5bLbF3n4Q&UAP#^;xT*tW#5%qYH@Se++AXUXL_oVQ+!++gyt9Y5g)wHcLUb|buj zu%$-yyX8gD@6tpg z$~tthGfL(4Ai6Bq&hxedjqPwRF-u+%Zs^dRBBBVyPa7z0XHeVgvQ$^#>+ANy>$f@( zocfLY6@Y6jy5JP~hKbt(gZ42JXZ`b@qiwzUc(}nH}IfiXV@9F>x ze<0t8yznKN>vNc%ZUPK|>;<1G!rMN#h)jHq1ice4?sPVfeXJ+zteBM@A&Im z%Td2e(Elyu_nlD>Ys~Vf7Nwhvw0C}@rE}l;FNr@`-+c|Fdso+F=GT8kQ~!Owb$}!> zYw#z33ph^ff`1TLH=H+W14x12R}2A2fhl2MpVommf_tPEf)??AxWGrIw|yn(ff5LU zEI3XHsB4eu9!0nl32&$7y#99f*dG>^5TL=_#FBMH#%5@$*_Uc zuzX555YRNL3R#Zm=e_x4J+7&Z@7ZfXN6(t zK!S%X&ZHaFGznejz#@>ghn0vCF4%)~sBcpSgHMPHkQRxRNQs`Ph#7Ysix+~;@c#_-a2tE5Xsn1% zpooh*D1$!O49&nI&X9)G0DP)gfQYz@7y*PN*ob+EiqC+H_a}YH$WgdA4j8C;(0CEh z@P3e1h@NO))ToFu7>aP`jMNYm(U^JSm^T*4e? zBD+v%_Xv)<$d2;Ti~Tqd^ym!n7-#sHbp_c<%ZQC|XK5hukIqnN&;Se?iH~vvk*#En z6M2C2xRC*{kz=Nj9C?M|_>t8}FG`4J)bI=G$cp#YlIY})<#=KhX%WA0k!=Q)l4xHt z_mTX#fWUx~GdYtR8H~<=l)HF{I=PYuS%T^4lgY3PLgr>T2LBXZxQZ>gUw7DnMrLFe zS&_fs3l));E4hw0iB4I#fIgNBL^cq+;0w-h3%cM8yU<}BMiFW0msI$bMM;ha2$+0X zmmRhXA|eaF5SRlomysC&a>7X z4rzdHDP=-IZuc?CqlblsU5due@;2CWCNR55Q z5k$Fwy5I`B;9#x*VF6H|%QiFYNqcTN5ILfLELflQ>HlD>fSt*xnS^;4eiodXM_=}t z466`w0|_+lsi2owFBC{&6lP%oP(ld0V7uv&w%HOY)|vU|p)=!P?3hFtnvAXp6F%rW z+clvInr8qSpw;Jm;z>6wO_aA~vOfPo#umwx7fHJTF3$FjFv4G;OhA|32qOsoEu_b%4 z7hAC@dkn9zvcBiCN(PJMI(X))gJ3$YhI9vv=(c$)4&Sr zin0V-v?(jJKO3|^o3O>>4acAp-GH@#l>aWy2M!NPfbB`MFeqhS%Qea27P%J=lM*;O z3l8Xzvn~s_#RInqo3QfW5N;c{bSt-WtFuaSX>n4t{&Jf}6GJ61fqL5{l+r<)vqs}p7M5QCe!1EjjcySl_%ySAH4yj6g(I}mXBRC?1^jtjlh zOTFUI4b@w{kIT6^0S?gHBRzt>;VZu4J4Mi|yzL3Q54*7TXTIoUyN#5+l{>!JtG#BC z6Z4C|;|spj%enz7SIe8e%XnhOOaH(H+(=|W3xU%k#A`1G?7$0byso>e4EiW}`n*(S zx$v96)w{nLj22~a7W2!xtc$-SOuvn^TP%sG324Df^hhWSoDM9*j*Gy7LlXr|xsyA? zIc&Vmlfo0srxwV&Lrla)Y{W;5#6_$P_M5~_?8HwD#ZVlcD|{E3qCi)S#aXPyTYSZ4 z%f(*I#aax;VNAxHdmQ3B4jZh-?K=?Ikj93H4M6O$PDBZxV8?fi$9b&Bd(6jndI?nX3xj-j_K^p04>m@xK08M z5(+J@YqQSj9M0a1z`v^y5$(|EywCeW5#)T)aD_Aoeb5z=(7xI<@95DEy*7UYqts~5 z11-|~yc0L;G=D^j0+cT?{YS`S({01k$-~ob)6;3Yy^^amH*M5K{nJb1(?^Xr>H@=y zm%6IE7fnsP0_4L>Q~%IK#5Y^byfa}b=ybR#LA+EE){eBpJPf}Gj1$Nq)i6vFGhBag z?bb*ok`atSKJ309k*ob2MH!S|WLpw73=wP%!*dOR76rkVd&wmT*oG9=QK8oNJG?g1 z*w0%*Zb?9H{n*k|*2=Nj7hyfEE7%e7zJ*=cAo1C|mD)G?YjL&OCK1_$ZP;P>+Tys< z`S-yI3=ySm+ER7eQuN!5a@*{<*{v&wGB*)sjMgap!oi(i#@*E-QQPAe5g?osQSG=f z?AvnT+|doY(;X7kt=l&&)!NNSjSb%3t=_)f-LcKvQTbT z-{%M2n)lzAV*lOxz2Dvz;QdX7qusUTjo=LqYBlV+lkMOWeqyn$-xQAFaV6N~o!uGk z;pPe)Db7F;zT5?_;xFD57LMXDPUG>i;S1j3HLl}}65+ zJ`+to<7EEjTu!}cKIT_G4rYw@7?H^9^Gm_y_`Pj_M66H4(dC8=t*Ac z{k`aap8x7F4(W*A>M8E$gdXc9-s5Lp>neWgo1W_*x$3mu>lyCeq#o=fKI@TQ>>hsW zz@F?5zU$3y>zPjM&`#mcPVLH`>8yV34Q}n*UhQ_y?B4F(!*1!~&h6XF;jnJ*<1Xk< zzV50%)b9T7>;3D^|N&uI~E|pv!LW0I#FnPVimr<^zB5H)-$-U-00r z@D2}=ua4>xABM;N?-nnP0-y03pNyW)#vbqM*&gm9kBbd&^6a?i)1LCwNb$Vh@(T#^ z2OjgDnD8B6^K^*vInRpZzUDmt@$ru9KyUN;{_{lN^Fm+pNUwx9U-3*Y^GYA_P~Y?< z-~Zt>KOK8b_10tSnkNKIe z`GGMF>Hrv<5Bi$_y^_CCe{ml4aQdlF52(NT=b`%j@FA|x`m?Y4w9oqJa2%w6PUIjD z@~{uT5B$L|{KHTD#c%xk5D)fX4)5^Qx^GDA&{lh=~+YkKO zfBeBu3(TLo&i_>70R7XCCek4N>regrAPs183&EfK@<0FkaQ$fV``3T{_zw{K?Emc} zXph!Aa^%E`3((NvLx>S2PNZ1T;zf)ZHE!hC(c?#uAw@am;juS_(mp^*(?D@NO%b&fi z^rUSSX744zebQbUMe9=Kz*{Zj`jl2w8q%av_3q`{*YDq`%9jcmaau9Mcv%_bLgkVVYBLwob0!yd_Z@NtwwP526Hs&<6@kSi|8Yh6k62z?^ zfwHq{pag+J5y-7pLQ5cj2vVsgCN&EUp}cam@=7d08fP$^Zdy{PfzY}MCxOV^ZAq}u zdWonq!yHJo02az}PCDy!Xq=Ol)N@Zh``q&^Kk?cT9B>@!W=A^{Rn)#6Pa@M#NF$YW zADn1OhnzwKAaqeqJDqPKZBUV>mv~4uwbW95GF4Sng&H;0S5J)mP?pf!cQ)YOfZcF+(>7E-pv}mfo)wSD;ur68SV{q+uA+RYT zRM)D@E_>&O!KtumZzY=AY`D+Xm|=z3);eyytCn-?c5!98>HoX~$6INR#j#s(#O2-? zQ@h(v{PCFySIuy?A-9}lwAH2@@XI@wnDDv}_k8qwGY1E3)Jazz+?~A^eRbG91s(O& zW4B#Vv>AW>cHZYCJWks8?tOSGa|fq!;*-x&^3XX~{&@^DZ~kuRtEX>v*>C^(`sr`F^@Q~IzjFKCFM0pl-`omE zK>r0GfC3yI0!zZRv^g+=3@o1mnFl@zzK??LvmgX@mqGb$kb?;1-`YSJLJ>kwf}oq; z33r!5*mZA(5Y(It(+9%_wrz$gYoQIDhr`(2ZHGKNp8pSD2*lM1v4bj`oDq+R#L+2{ zgf#4-51|;l)CEtAw42=)z4*njU9opVL`Mys_(L(qaEWxopb^u^J2IN_jBmUh7`0eJ zJLZvgbhOtMM`Stjn57GYr<9TLl2S`L^J zFwhK{n;-$j?Wu!eTa;SNVnz#-P~a2VdTA6SQFvf?mGzq(jcLC2oRd0 z21J?yp?3sC1p%e^5_;FrJA@(~1Vsb|q)8Jn^eO@(U8E{qq(~8E^Z&ket#2Kyp*O9^&vv?wx~miK%~_+~uyo;lhm&K2c~9n# z`-s&)gEE7k(Of?157A`1&ffD`M0vXV&qvRskF(=fAKmUVr1i2;GqV#j&FpXxOiY>H zvc2)){P<&_$9|r6+6rhk`vgTgbYf#zXa`%(4nFr|~jW~rk`u8nypi-n- zGWXmy_xafXl>nL9X&Oz~*tMuTc@M7-5 z8vkg?2r|M3LZ+$mkCB`rd8UYh`QU!h*UGQJuXTaBK=`m$UPF((`(0dK7zhKHoJhR? zXDL7$(oeDA9W!Um2C7m9{Lw^XB>y_2rh4OH#jY3G`fCfR{k`=(`q5f2n_**wN|@O1 z*wXiuG_jFg6(GNmPyAdU2PNh4d6HBy1rpSF^V_eal&9~PxnBUCLXEucHl@mNHoEsG zU@*XY0->Y^K!7M7SO6G7;~)Tf4s^#N(0ELHIF#X%SzlGre_*lVoErLEvf=dCo#y)f z3tCALfzYfe?vLPyaU+18;=xQz=gWu_Pr(alWoOD84gEabJiPNiL8Blw{r+$94Jc;@ujD&#!GynTp95(8_^)?S{&)@BQ~D z1dfs>{sX^UzkpU&Eq40N_LvPeiW#-liKgD%Y^+(WiQ_liifz1rR{Hav(;%Dc)<4Hy zw{IDm`85oriZm2_eQ@YB)7X9QO4j=Z>sk5`L~r1(v20jpS{fy{L6cYgtswbl1y4^p zOR!I!BIfDJlzvjT^PFR;^;)jEUZo_Gry{eJX0H}dwgB7>c+)emn`oO3q+fY-0M zLQbm%9uZx2B^kqhEcWvFBGrT~gSEw=ixI4LjafuZ6XT*NOw?LR_@TM*QmpXIktI>E zWX&oLOW(K@FHykCAADt^bU8xmyVP2>k5 zK-P`2=+x6MX5|mhb1sEd_FS^9z%M#&rZmrwZ&u>}!S5uIJ4DL$-!MCuzj!Hy#&Lp*d@Zuxgk#*}RgtkR!6w_(f3rS=riSwkyP~`rMZ#$eznT(|>08 z@3it}aHO`LiD$cq0MstnR?!`2T+~12m%ANS@(Jb5=*=lyF5`W(K)cjyLK9c1WvLmosEm-cHJU@07i%d_UG={rJz%k5=Q} zyIr?;Zt4~aJvrR#%+PDudi7$b9Qq(R5sNDkvp z%7HGSsi{Tix#LSkloRQSA|oF-<^BgAH$m0Y5o*ny(BvRAmhnCm5C!XpCa8#MFK_lp ziwpM8-=d(tiEFV}s@}SyA&U?`GK^WS9C>-Mq zB?}z$s#E<g^~MM!$;v zoZF(ZD1VX?TDZ9+YG>Ub;c8NB5q9m5VcbZvhd!p_%`2ZUI;8Ar-9;f(rXR_E5wLz( zs-}C%F!QxhA=UDWr0_D=d2xEXaz0?mCRs?Q`tEK2!#8G>oA+DU?^P$gdt=AtY%&@+ z@vh`IbjA{=}ui{uQjYLuuA{80KFeV?7jN+lmKId!J zT*rOtj2`ckg4gOBT0i#6Mj_@FD)~7&n647sgHW^c_4OYF+&rIdny%9}H1|ENB-Cnu zoeu=VcMFR@B?+gwT?A0kmaX5n3nB#{?PlUKW?*7Xr{>NY{uJau9dZ?!#yt6|bMfwO!VRkj*JY)dnif#W9DLsr zkNrC*PAVNDZyB`ZPjrEZf_zi8HhC`Ny{|!@32bT)`NQ`y#s1p?&B3WRzbl`&4uy(6 zefc_voGuN#$3TUEH&)Rt3;Zu^^(2Kw?C8ppodhaXuhtE%>X5UsXZ{q5|2QuQEH5b# z{n2?J?tZ7g>BZX#(B?XZIfkXPgQ)`!v}Mm0WulEVWA!`%>FU)RH`xVWYV;xL_rhq? zo3G?@|0GE%Ex8?o6L0QZ*9rcL=79iTRMr7HFxd&+sonJ&94)0Ix@n`JLd8{epoRfL zp^!%2(8sYEKsgwLygz!^a90WWioXAuvA-i%MHyn<2*B=dS%b$X9hnc_l-Wd1VLPknd4{F-o4Qj60!j- z5HYXiV;ZGWfBvL8`6~D+yHmmZAR_Az=2~*VXI@W~8l-5_@F(yZQQ+i6Yq`Lw_>Oa< zZ(rnRQBHL|;Cp;_Zvq9!1_w-{$D&$m%!obdmO#v0p)~VKa(*=5vN- z&xsBB(kqEB#}**^rFq%55FR3%e+O?cYuI)yI>E>6dc%*#j`K?Xj({ZNQR-`GKfznU zXFh*9A1@Jh6}$Qe0Rn}zFPy8(w@RY#mfoip*AKuShb#GeEZqwL;b7;51gJp}9iB3r8PN1c?dnq*W;!KH z2D2$rg9?2&C!H)ZgK32PS&aR&0YuRPx|9l3n2B~8L9?p6d7u$pH;~SN9{`O+js|d5 z`(V}WcB3SP{Q`sSbZLJ%Hy@%ryC8@dA4ofu%6XsrbqmM?3kX5T&;C_}K&aEwcb~^B z`Z6&}ia&H@zq@iT(w^N#YG8s1QXoTW5I825f6^^KCfq`UQA5o4P%RF{ON105O#RXI zOn|#DEdlS9+~>lDdn^S4tw*E3NQO?^xeP~yic-_5tx-d};eHyL2HxsbIOsznM1d6& z*9Y~Cu~HfJ8!^5%_=5&gjd;;#PY<#K`Rnia=pL_`8XTa`NItms*r+I16&suI-tawt zgYEl%r-g=Xt9H5>Y+RDIkB*&oYr}szIAcKZF^v~<Qk?LPaQuV7@1Wzmk0{jAP9uFzeZn=G&_9_hj*J|BM%@u= zx*pn?>Z+JVE=u~z%*t3M&OGHB%#3(^l1XIC3X{nSoxT%ck`>{Y72T8-E@E3-ddaOR zZ3geo;>dLZQ0ft>^$WA}nzD0asj}B0&!@AC*Rx*+BoLf`{>WAe` zHNngP%AhLP(0cB-*!;!w?EIDN{5il=-j7K?*5Ouv=8wfkZA{O8IX)>Dp!6Yxd|?87 zY*ckD;O$igRb;@J4Uj(aKf$YlMgrlPG|l6I15)ru69+{{D|SMAkD1n!M1*)%V$mH~JwP3uqk^85fEHDOLl!`;G3X=xLgO6t zPl69Tg~~(={kRZ~ZxYM@p41e}=L)AgvrsKs09BD;mjQ|*z;2s_`ZEpnL?e!fa3d1B z5kr8Tk5U>lS-ZnE?CBEIvJu<**=&3;>J%E}23m&!b|R`_ z;3a9(wbNS21(wX167VlRO4<<+ql*72&EJm5xr(3)4)Geb-^K{ zT_)+=V^)O7L>VvDbP|)AAk_S5xDK08A|8z&)Uh>+pW?6g2tXhDVH+H$bjM(&h44#sz`1PQsdYn72KsWQfnB`SF@UHc!=f-yQ9P)K5bp6D_JW9BBhoCB z8-=VJZk-4O%{H`pqd*%VxkAW23#yPpWWjsEd^}p3%JR`>QpCz*5T=SV&KhC>)#SjQ z;+lRoQ=Z`P4CbBJE5r?HajteztYt{7>r=N88HHw(qm8gS!-< z3)mbMQ=*<2IM~p+K%ulyl}Vu3t$KTh4-WBYjL}BFMFYKLmOUbRk4y_9kYNdA_#7E| zMn-V9(`}JqoWLOgB2RAP<5gobvTh^6+Xyu-UD*CyP|X5`DS)~QQ122b5{M$vv+yo$ z^mk$_G#LE{4g9V`{jTbi&Fhrs?2_R`-O}ljLw13HF4dMUnP4>ANE;WYGt{F+(GZDT z0GZ-dg9m6LF_6bhmH>AFo%}sq-&^xNbGhY4C=UYtnU~$fi0+n zCn&-Jlpv8ACkga^H_Ok{ zrL7Rrw$^VQfgZyk|Bj$QW3QLObDNKn;Rt?Fvj5Q{5%Q_zS5TI7BAq zx*)%XK!iT&Jh}rsip_%(hyRFJME<-W&EnBg!H8Ki!74K75ymeK%Ihw{G$Dd z9{BD;KXf(>!hC`&B1$o%ATqq4ge}XnjXO zE}#co&ggbT=`0q|wK^9!IJ}T9w0%y?1e#Ff0_u?yHe6iB;xui?w4g$o5eus_GE$#r zU=8`%71Rr@W_YW}y+A-}&fv+?U!kPqNvh`dP@tGuNpSxtS6g4qMm3)k0oNPT(y5;%u5i^M1zg(( z`^(WatRv!j!ea{U9?_4Nam^G}pt};M`dlX>X*e+AogRraNq?CT`RG_t2pgvN`{!v5 zZNZ^)b2{q^^tbIf8@YKj-Te2DJg@Nx>tJ-4%Pg(IB$vTteg4-OuI{h;qz@a@pphAB zkGa<&6UD9Q?+f47DtMdX(QnDfF2a!b6`EJ&=vLqxiVnq4F#H_32&cOsR(_q|ZzCAe z{`-r5VotkZvBVCtT$kg`AAxOs)tTH){|;Ez;b`K_mv31v2NX|9?#$h)oT5%qhmJ18 z#b^Q`6lpb?1AI$-kI}kr*r#}Oxjs{9(VKu)G}V`PG?uH)Id1~;+muKvq;i$3ipVjV zm%G0P>@FmU_YL2xT#2qi;7$20aMaLHc*V#CUlFms`_{U6GA?N7?P8MtM$!uLd-J&# zZ7*^VVYvz`YG*a7!k=WRMAYJ=vu%M3(4w1d3bYi?k< zYNM)UW0|l)4O-v19QElyv|I&_F3~7#rdo9?ut#pv;Y?G^fKe3IKV zz4|uaK5r#$&T86e(U*uWZVPD8WiJh+AyJ}KZrHsMcs>RWDsL1{`NeZy@J&u8ECH^N&yG6e!N0S!3_Z}vrcgW*tP(7aa zsN0UVf}AP!^Ke^NgIXM|m&0cAK_7B>{$BS&XTe|WBZYG^#x}5mr~&G zn~alP7}oShC$;ju+tS$|EKa4r!Jik>ILO~DJZEZie@gS@NshvukLT8Z2d=Fbmc)v|8F@n}#Q*pTh2U4z*@nMvRIOUj; z1*Iq&F4?Z%IJ|V+Lh}i{>P;agmP_seT4}hVkt(1oe(R{xi0IubC|}H)wxpRuPZzdd za^-HNF9qTYgxzRO|M`so8l$Ii*^Ph>kD!q;qk~R-vlGphjKe~OSSN<6*sfH!>Q*AdVHm;>*u!*4IzL3(Y)3&B3dux$wmY=x?}L%Wr4M?JqquU zpI&)H)qm+}lLyyqb9aKj+i(KH-D98q!Qn>Rh*oR!J!7%XuA=i$NFSNxBxPR4`rVex z?0C{J_hvle$FA4jph7{?L|OF@!p4`_4qurdOV`c!FLJ-znV%gezohb`5b|g`&TVmC zg#&Lb9=5G)e-p||ul>EP-}?=#D}F|W#R2vZZECrHv|0`=UxPJO$-rYcrUiVB@tR!y z%tjKQhi4p)xQ@emNZV66IabivTA_;a<~gbhPqm8as+v_aqd5;&oT@qr@)7zb7Xjn3ZV`gPoI_OEvJmqKda-k09ry3TWD?0Y|M^6c_p zR7Uae`-JZ>B7@3Q*PYjp_m(@l*PF^qIjpO4?3v*EDhKCSbA5xoPtp`$VDcwmR&fJu z)iJx5$qSrrQekTc>xKsEO4M9TPrd3s(CxnN~0&3M%{7G)_~2`$s*-V zB8-`sb%_de~&`UY%zbo0GMmlcm;V!uQO1-AZNr_FL>LqN{p1Lm-F{J}TBvqb}tpfVZ zOjw)FW=WUs@28;)>+2bz6Im%9^v>0*FO!c;-10nT9t^&WJe}erKH2?cW|XDAbHCbG z@LhQFlx=>9Rrc39yURCye{gwzv+bBcYFP?#kIvsU)q4;&E^HkOFuQYq`k`#9SN&)M zhR;~6ZSejRmWdVAe3HsrirmYW;yx8f`+Di@h~dV0%_>GuH7jh-fs1B`rR2<{#PO$W zw&DUF4M&o+D9eZbQ5lwxOA~a_5S?wjwc>Pl@_7&wD0+;{+X^&V1#@EQsm{mh==iWQ zsr-F%8|l$N1Ren6d1H;%GC!n{Fx$XgTIV`t?ulW{tH8(-D$iFSXo^a4Ji}yTeR~*g znYEOaQZb1SBJ?mOCPeHZn1Wb)H3J&=dd8#y4o(cc^&$asx@1aEp&UE3%mK;*qkvtt zy}T5AM^Wfsc_!e&uasLJjD!1K#%Qm(QBw55!bw7OU6^#jJ-1+N%lL2gm$vjeG01p` zoDxj{YXowbu^h}1e6f> z#+3>Y0-DOzO?t5^kOD-Cu!dNUL6RLVcdAiH(OWFhSF@Nd*`Z5A>aHQVszz`g7yV{# zG>J9anw@@>g5v=5dGzC+|7&b4CRF3HYhR~jg@YqNUmXKD@X_6)!E+xJekrH_a{FC6 zk1m(zmD0Zh1(1))Mm)TCbw!mJ_FJ6H-dwu-R-C5Xd6`zfU^>l@vFrJLM-^^*1Cq8k zUp$CaRfy{ORI}Yj51y7c=NgsZ*9@bgnpbEdOs-mH2tVc1qTr3R=g>wc(ne-W1boMz z%95UqDHY`$m#b)0$4yV%V=8t~b#af!8g6AIzx?>hm_vy+6fF+CdFS$;c9Ue*_`K<3 zbPnjx<*AASIrJybXC4GhvTV8J*zWI7_h8CF&!BJuR$DF9r5mpEc?9TGmE;& z92z3`-MYtNE+mqIB}4IIvS5q%=>pMv6`H=9sobW)4P4*+dnJYzabXD!*jbWDn4_op zUn+nfV!7_{PWxN6g9IN%(Oqvx%TZBw<1WX|V!@O^ddW)PjymFNlk{I!!QIkN<+?@pdGV1;_mb`on*tg1M|rB|Dd5c6nGH$Mf&^ijD{Q!L>1aXRER-hM$b-_Cr4<3@bjdl?_(Y%s)Y{ z^1uy-`6WFKaum_(kC!=rTec{%)H*niba&JZkD}b@qC7b9(!sW$jnF&mO&|^ZWI_RmpJo zV4>srf0ce8K*R3mxPPV#y%$_nn#a4n0=H%m_R@~LZmBZzl1n#Cq~0Hfcx>sJjdT1s z4(57jm3;lyEU%(pUwo>ECcW9}fo~J%oqv0URc878uL8yzx$?4qa4wsI8HYoXcC&Ju zR=^4}LyGd=QQUG^&1X{MgDc*_+H&7++Mo7TU)_0WZ@z9iDLvInYhC@VWzD)_a~gK# zpxV^@2U_`0UD?0Gn%q>_)DgC6d^lv-cympgSVdwf`V?be3er_+C; z^9M;k>$m0J{>fQ7pFg1a)hZf({-=k6YcOBvap&c0PveB1sWVFjtu?J?jD?&3Hv7=l zanum9paPm^Kb+yAH+BsL+={TW2RW;m<9lyhi zc_lg`G0_J&rPyitF@z+jF8L&!rzQNR2Z0;bv+Mgl_^(2)mH;al&N678Y~ zb)XWOuZ$~e1jZ=JsaFg*{;dm8X+PD5&Cm>xGqS{q33VqdNWr}~iahiDn~FRUsmX6l24SZr61 z9~SOW+&dzy?$)B7rlEd!PW^+iO30ad>Tyr#S-h)6-v@Gc#2MnDjfSfZCN#J&sj(-P z5usw^tsXB5zcb!fMd(XPhg+m;kj!EtvHj0WyVJ07{-SD68RL?@`?Ij9fOO5Gs*aR$ z&7AW7{FVM&mOTZZuF0?MgTg=v3sj=W?hjsDge z43@b9!-FjhAb8%-RB5pQ}zW5f+|#eWZQpkX72&5RDR=zj?C0+?Vx| zetxLwdPi@8ay++gbDd*X$(=V3KR&pzF;Sw}ShRa?cCTB>+_k4|+spT_ zJ!%RMZrvob{eYi5USWY(?0?c6Gx+f+xQ2J)Tj-JiD|h%;MGJ`SfvW@r@>@~*DU^}9 z@v9nx!|^zR*Vhk5SSMFT!osg#DOi8+q`7NG!F{0fPkRF{OSVDs>|UNiujRB z*D}_YlUb+L)inQzt)QhqUD6}6U>`scWOLAmRp-hZEmA+K<3|%gSz!W-tndh1O~hk1 zOep323wX{wW=5-6_AEXj#a##vk^r{7j#WSMrpM>H(lS1O8t|`79|sQ1Dh;_d6IXL7B-WgtiYR#eHPLv=W*7cRlhDopzp6`x1~E}( z(``JbsF=!3M6ii)nt*j<>;MlXhiA1XjP{1_aIIc0ir!8QDYcX*hO78#|0%A7dushz z-Zfe^79yVwIbOfN8qnvG@=Z<1t?d|M_D1^)3}RpgrXG6UVY>Kd)M&$LjWb?}y>7Uh z)jrQ7ncZ*eS1%?yp<3R#&6M{YqJUjTvb}t+X7Fk)vUW(K!EAp>@<*`Ou=M*pp8GSN zcYoolBWn6bHH0b-#&o2%4?gQf(+_!lPSmtftX=@YxP916n;Hsa@=nIkLcF?CEBJT&BmvXY_9*c~OhkxKC4uN!B{Rd;O5BqB-vsC&o z$4a^RFP8{g#m2T&v*yT~XotKWSeIAB$e){?-IlNU>h-A`Qjoq)JZ&s^CSRMY_h)0e z;K10p-B?Le)aI$$Lx*ZSJrOC7tlprn!g&9ZJ0{ntiZ(yjo08jS1tBV+ltY2_X9vG} z%T8k+t=qjm=YK5UZc2~bd37j|Ba&fkHE_+kZ&9eiU8G+t3>^<(kj%~L3ab1oNp-J(eQc1xYVXkQa|T$Hd%Nu)c~e^>`uqU1qZAdaBpSc%kR zeP{$Mnxpf%(g8E4Z;_`d6puc?$hS8UnLoY5F*Ucpy`ci>j zkJlF6CkY1Pbw>b}Q(`1V7``=lJdOcEcSos?tQv~6jtF0-W~L|%y*ZxZuH>a7Dmtnj zYAgmknOnh=G3UBkhH3ZmVnUe~Jd&e0J@Owu(7>h$$66ZG^AwE$+!AaIx0)%_Ly(Np z6zCz|hXz=UQgt9>Asnzsdoah^!ElkWLbzH4kAB}Pm4%DAOofRVWsISv6o)=u>3r#y z*R_k*s(vn9n_L<`q%aPv2(?JL-zXf)M;V54Gg5?hV&dXRK9<->U!hiQ+TXwIOmOssHe z!bfAzH2~)Kd>VHv$V6<5WPMfs6?Qvq(@85ur)3zTR;Pik&jz33I*n8jCc|cU?<5aU zW+v|aYCbMsd2bGR>rWGtY&GX2uoxaGdXc&!KS!i^kGXcYljC8i<-L}szxQvb`sZr#mA_#yg~nqtD(s4bH|3mg1X>9xCOrSD#j5-ZEfpO=Z#3D}5Wm4Eqjy(SHh&kHIT5Ym4309m~f%cjTobFevt9T*j9JYHZ`-MBEwxKn}_IlvVQ02SY zZdcbw?i_R9X#FhO{yO_u+sq&reXE^aT}>u$%I|%L)_(n%V&Qc&<_`^Ow zL*-Xa_t5>xpzPeLaBoHLN5U@*2mklyQXhEq(6J1wV;n#9-tvEhC!00THZ06*TnfwD z{+-1e1F}#9_~iFJOZf%BCXx4VeN8c2zyaU)qyxhi;({1VS-dbRfcGL($z~lhw`EWN zY8qqcg*rqc`Q7sa94SG8a>7MeR;`>2d(?MpCFR#kyuXKUWJ1w~uSS4DPvL&$E$FVvWqv1tl^4Z^n{YTUkI;{FM3GvZN##{L5JMK(d`02P%G zjQ)M7NYz7<=Zg8Y%(XtoV;PbWQC@InN_v5}cxU>J^^DT9!0yWm=-B<)$y)o7b^EK_ zx!0i+owp6}|6TO_mzvTN{G0-GQT+f=2tWaW{Ey7?|F-a7Wzzp`;s3QqJp)ofTEMmc zqef%b@ZW$)`{Q_v!~M9m5}*c4WaD%Ah4}N=^D;|_HDx>#CaXWRT{=}qX3wf0z}_6l zlhJ3RP&uL6_ zh3pshLyA%~tM_-KrmGy&4TNZ%6;ocFmG*2C-%+F|>p{n?P% znm}zAPw51dKRF?sOpRT|XG+9SOUCKs*fCts2>QNUq5_k0VrR(LL`pe3CKc7(<%;^b zwsA?h(KVfce0jXoGJ2lbSO8zIRF=#g+0YH*ucXvnHE)|6NWF@*kUP)#hvH_Sl7|{@ z?k$bY@|tc4dm^*z7MW2;qj~P0>?vIw(Evv6+8~3 zC^8x;?`U0aKQJ^(hg5O-6}W^E{pmND;X+Y_UwClR6&8L!5TQMig_fL}EI&u49{`XV zgmwzC3#_%GnM-=Hj)P6(gzH$lQv2gM(duqFt%DR@_bg5OaRbVLegpZV5ot#G?qb}K zj54$x4`j{(sM{-lmzmVrrXB6GEOMF{McEc=I+^E;K-9Nn%?yRY5U103#gP7lDTTap zvM#SYVZAh4?yfCWfE<#Z2+wob_z|*8=vXz_`SrP%{&?=(al_R+Z2B|qGC^F2s;E!a z+2&@fOac4HQ6T#5hf~#ucg`7?@dyI)x>ZernCgh$NjU>t>a*ddeSTt~>5Sa|oU&W? zDivv`d9D6J__)<}*}dhUAlD6$d1*bT8gq2W5zi8PPhDIO3aZ2b%e>Jw581W z#|qmI%h0jcP?-v0lEd6$u90DbN|}FoLJ}PMKfim=fKZSupzy!95*!)9b`7E={NFlq zo_nwn-sj!%bo_WTV=MncJs2)>75O`5MT7SmGjmI{p`}vj74xW;v7+Za z(F#8BNPRjb`fHTB-x&jc71RLokTx>mx*-v9j_+wFykPNGvn5y76yPOAJP(Z z&S9qt&Ih_`sZ4{!rd*7ud)3ysR`%RxkcTp!EMxjKD2%az=Bo3`5xk-{j z(EtwwAXOA~h6@4Ry)dc(@_6EZ3xEe?rF{k~L+;)~? zC#F*x-7A;l01~ZwHDg128Nv z>2d9iCO1IQzhg(aJ@yYt2*TomYmdW@kg2j&>UveviCx`YjJI{vyEO@xqh8DxaiU}z zc87zZ*SnDi%HDhZ=FwMtr`EF=@YB56FA`-Pf=ZI6L0Q&G zvL26Aj%Eu!%AvmoF$8us;0Z?wQVXnqU4PHUdk&3&OEa!C`aOBh?MHXKoAi-*23`&OpIgHPrxqvOjN|!qAB3`51U$fyBIzK+Q;JQd7 zwj+WB!6%w3m+03FkrWnUR=bO@yI72TPWuLv87Lr6Jini1-Lnv;Z9G`CULh-$`fzdi z7HZQ8PXNbp?^vULK9e_=vO;!dA9Tk@Rf!Xpk5D}FZpy)g%crPfJee;Va+P(ab7#J_ z$#os1?dG1P3{g6!7tLLt>Pal1e*P+XeIq9WwPDoyZ|~pU$(Yl>8B=bW8?` z7FGeb{bBu)pP~eRO+NCdIWDwjA`m`P@b3ylaw;PI3$20wI--^E+2gW=N(uyE*TsgX z4JW)%B5K}c!TYpB*y9C4sn`Lo=EGkq)*zRqwHG8et5^t$tfa_wchP_v>tI|{R+9H1 zObzR&L6;9v#M575CpqMxOUs+jPe<&lyXX@t!kF0;?$MW8UeINsD@IjM1XqkySYZ$$ zHP!$~f&9r_nzrb4dI{_Zw1uQ0F5_(74p7tK!^$6Z zm7x@Z`#eOAJG*9QJQpO!TN8h3@a!Y9*kXA2{8nL{^vXVPZ!h@u>9Z0ViiU)L(-HVsm4OHke$gOpX%d)4{zI(bNJHo3P# z!&PodU2PAx-3Nd5zjwvFmAE;f`bP?<9O6&Y%UE888*YfBSl)N=eXR8M8@<0WQ+IBcSOn$h-t={ysdfFl%L(FsL1*jCs3ndop5Ph*eZ^l&v+ynbnC8_T~I$|mWVz4xB)G+g8t>u4}Y6KkDb$ifGEhE}#mxL}Y{e5Gs%$v)rdt!%BJeSPnSuV0M4pm zkLtgwxJ%nr-Rsrn?O4+fHrum-wbypj;u#=S??8Qu^r@S)5s^Zj!A|;C{c316l3D+5 z7?L$T*iPwu?oJQQ`-O9c)J7BCUDal-+>h&Ts%`d5o8r>aOYdwG4I@!U1+jL<$K*vt z;V4JxXFA6Cy}iN3jLRd)0>XjEZR~fiVJ4bKNiy;wHWmkHW-mwz>M9~#GgZPeH1f?P zSbk(2l9EKX0}rLV&3&}7kGj}*`4B=;(2g*Q5NL{v$p@4%X_u(<+II(_cwMb{4S!`s z_IxGtlU%F>CmDA}?jTajAuS`>LKY}?(kD}b`yd z$H=DX_oe#6>tFeK9>mY%f~zPWBa2WHS}{kS4Ro@YK|eCbBSDLHnJ6;^IQ(+oKtxTF zWqGJ&6)}?X+P`LN9py<{rqQ7oU14euZ_B5^LHC zX2vC4B8T!wS#*)_LF+RGbnQ07V{cj*-gq7B1fYnK^3p|MH%28W)N#-N>R+98;>aI? zBwii=-Bw82ywKq0AZsjZsxV+~?1D;8goSJoo*3p6w>b7s<*EWcib<#Cj^cM_h@k%> zDgl>$@J|fNLk>r2_uYHJ-Op6h{!74vU4!o;@_*Vqi9=$c3nz|-|0YuM-ZbswK#9CO ze!7lRg~y+X+7AVn7QyohL7W4^0?8Z=`S0e0~SR10`Y@i4Gi(j^Z{@`FG3)}Am4WZxn5%Z)%g0Z=&0#9H*S-8; z^7TZ0&0&R|511LQiVk)OqtESo^YDnBDCkfK%+1$7}J?xvoaTrjhS>N>W34wxnfTYA_NL>VwAbdJFRe=7*0OowP zmp2YU&aVNb%+Yo!RJOVTj6%FbH?R8ro0Z0WO)r?uy&8`T)c`ljI3HGBjBb?{kbyzF z=|}LSHBn!M)Ii(T#B;!Y%AmR51uEc_veF3;kP0# zkuW_j0Cx*{{U0qw%7PAvFe(hgfvzhLVv>mq~HO+uZqu zN;-1dY!DheEUv^?9PyT#(j6?7yHVHA z7E!m4Z8@+0>ZRORV*S*34;OYP(O$3)x!%~zU%Q-=d&^0v_tVfLtpd-=s+Lt;a+B4W z$bQaj%jI=k^zi2*QXVy)LzV~n$(@_Y3qt1H(2tQ#s6>}A{1wpr0Ue`2`xJA?ZQTAD z^Eu7!@MTa4#@z38Jip*DGC^*`SfLr;Sm0Zk8N%--q%k?E_xmNPm=n_eXBOe<6V}zb zt#kX&=waJYSZVk!y#3}9MWO!(mU)ans`*>K-f_3Wzddmlm8)ioBr_bvzInD1Ko1J+ zykLHXU2EOAGavh9Gm@FZH^jv7T2QHRo5=sFZT`P+UH;$trvLwVE8ya?0KcI4--GqS z|HH8lt<~RPCh~Q~Q*=Ad#r!JjCM-e>2dv_!8k2>I?z zrr%jmOOjTEpN;oS^cVaej{QqqQqB|79&FBGbCj^%bUh zD@(Lnvim~!DtKW@@!C5M^9@7_1owqw-!dV%|8QmCo&8cLiC?=wr^!>-bE@j;$Nnt0 z;UR@9|20@&CmY#2uFRcW8-6`?kGe6axqf@L(d!lCzGL2Ij&IOoCV#CVv5(DZmmdwE z9Z1K{pAOegpGpy)3rIl$;je2vBBH#SoE_YYUz$M(-@t>Z*;*^%i2@@jOBKt}RBVZFjRc zCyaVq0FQok^TvqQuko2Cvw2%-vkXX>-3tyqTuQq2dy3I6r$YFSv&2_vv&+>PQf5$T_LymRv3*4sX#NRbfmu#$@Dd;uPl%Hr`m-<(qIe z`P_g4ZB?h8E*V(UnP6dOl67$gD(HvgNEGCh_uT{zHt3Nx=%bK67~e!@jR_N#IBC>q zSwcqY>8H)bH{fO`hGrqAH;scGr=Yg#YIEce|6|or6P}q8syB&4%!aS_>Z@%cBB_wA zD3zJ2ik<$d?6QT$NKiMGTH2AZHU*n3v)E?KR!CW98XQvLWM-CU+Lmi>RANPW6tOQ+ zo9CFR#U{?R=hka)fncudCYgz5iru_u-Yf9HHWfM`z%yQoYfY+(VM~zWWJvJD6th$) zC5PU$FmNLsLsrBUhb%Hg&rvcTe+jSTu8EsoCGE&C$1JLLSfzYwzc0@&=< zS{1-=d#F39ISL2Z!FWiarNBv)dVM|SVA^mBsEMLr6?uVWK#^}gk2Z= zHB4WL`*PWEYYQdRQJ09JShL6*_ul7z|M>}hB-$O*i5X(&&D(q@?rOS$-nmxunUeBMk)9?tKE)iS-Jx4xx-WfeX6w=;Fsm6|8JuKS=t zUnS7iG_73MSe&xH`|&#lYbEeQqRz02$VcC0Vu-i9c1($}EB*E^o^8C!&d-h&Xf@xP zK?dB{JGaYq3(mHV!^L}O^}e2;e&1j&7Jf_QfHj;rt2zn&UPS>4+)sU)^A_#Qm z>|s`OmHh@%zyd17f(Hau<|t9R@c?Im47^iFK-Ve^62yc7Kp{dVn88nx?t8boUd}o; zE9UJ;g(<<{`6_6@6!uVu=<5g$|6BN>FO5n}_Icb)phb{0Ic#Y@!XXPE0z`*Qaf%4x zArW6h6-O0Bb}BgQO}G)4B`|W-~dkAuZL&cWF`YZOE&V70R*0klk^K!oW-fe^Bn9Ka+eff)b~I6$1d zq@@EmzyU%Qvxxc1O7QH6|B|qQ#fjc9Nx*h=OM%pK3u>sQ8WL)Sgue42Oen+~1~CXh z*kJ_aMBfjAi2)^~laLv3fCrH9hC&2D2<;^4AmGr0dQS454`LkMlBmQgtp!yEYE(Jpi$ z03YZ>4~&ooLG+;vHt3}+IpEa*48aTaw7?sLzyk&pGOY}nRPIbyyHl>@K;u{)PhUDg zYzotUpUtZSlA41L|5!i`H*mlO>>vaStYHaem;z;kFow?3(gVZffCpgkhRp^btUGW( z5aj{E2&|wgWxIsvfJA|+5mk)*Tf)~I*PwYCViv)tEDZLv)U44v88to%q10YD& zW}vTT=z#@Z00-sHld>}4gBo}c0IC+30TfuH12BM63sk@kyu1KC5zvJzG}yrml4D!J z_&#Tjs7IewXI{~lO;>h!g6Ly!4`yozB{<*)TWEoA17Ly|U1P2vx%pd}&XEvNyU82<#jB@PrJg zAquk%zz%Gy21Ho3kH=*~N#QW&k(N}kWTrEKMmc0a)r5RV_A``2x`b*zA;!0awI{tS4dnw=5@(a|N7n=6JX$is*JQQq)eqqse6&Wg_);OVq%0*%BQvzY0NpzKM8 z=ernT0kVm#3Bx{|Dk<` zD1vDsG_FU1Y`99&7Kw034!ps8G}ufOvMPV5i3jL|&+>)|5r`>aB*F(k(U*v%$bXD8 ziX3Q(Ho_?SQGl_ygOlP7Ge?UKp^A58g}S(lFIaQ}fi}SSMFOZ2De*MX2##+TEQpha2eFMV(TD1|gBm!4`_zFR zXcEgfkCsP*192lavWN=Nd1I6}bJ2wS7=JQ|BJe|wCn$spV-VPpkUKah^HMWoa*Y9q zk9m@CA0sgo`G6agB?5_mV#F^7F%krrjUoAVq_a5?nSu-{5=GdO7+7=y|1^gs8Ai}( zlMqOaSEzn20gp!0jo;{#04IlZ*o9trEOCL5NV$6Ac#lh2CGr@R{a25r29+(*Hkz@I zSV?F8$ZW2$lLtYNUpO@302Z(jmJhg)2w|3U6qC)5B(vICibsh;NtXM`ehhk+8^W9tiab+kGYT4_B08exh({6Hp}UiSiS!k#WNPr9W*$~7EeoovFPRVq5$sij@Rm9wtfL!lv2O4Pcq{2Ce{ z+MtnXulMt*pbD=+s-|bzfEFmQ(qk>q`Z5OVtq41gzq7Cm8$GhBjS)+t4RIq%v#b{j zGfB#+#=5aY0+q;_H}x8_x^tzx3QZ>4i~yt{?#QxN|Ff5Nn5t@NJ9t7DR8k&k3K2JT zp0VMcHhVdYV-fxYi1x>kYWS_WShGj#Gvw-vkV=#n;h@Bbty7CXqq0v2>0P6l5cJBc zU5m6v=@$iZl0}BFnz6EHYdHklT|=5Ws2aCq>VSk9fi{Gw!zg}XOb3Z00{q)uxz?>4!Qi!G*zxjS3A{nVyK$hDdKDnSdqrBrE) z)f+i8YZRQjzM$fRJqy39DYYHzCVf(b=4-#lyRBidtZP`kxTtUfEHg5PyL79+47j!R zyTF5@Zabxnt$CR}s3!C=!4xbgK)G(^8or4ez#UOMz5BrggS`A3w#w@g$g9EwbCuWF z!XlKqDiOUhOfj-*!+xs4<7p5dyTcQ1zLBe5tzYT1hIFVYR>%(n4DD4WW;zP%y z3JwmWCQOvXbsQ)yn8FVX!7w~8;-S8Q|GXqIJd{8zw0Nk)i>xiUNvSu3!zL*hEhoUA^lU=<#WwX2veBs3J_%FVr^JgMoByKKfP(G`jJlwTpv<}6BaamvU15YZvY^9(AYytivB5FZPY`}`_K z{JM&gA*!4uRy@$7)`|HU#qvBX|1>#kaySdk(8iQNoO{44p(>$^(W65tr@O_)yrRC` zGHeXeJtA6WTUwahPc$TQDh(<5|HO=W%*8gr!B9NYkK)ZGZOkv+5-!uYJpCzm>z&CP z)TbqZMa?@Fo6+e920E5qJ8<4?WjgQo5px%FleK)9lw;!qN_$)PVe*;R&GW zvCW3f92WdfLYcv2{mjn9!HFE%UDASN7q|!QOq@c><0w&|3&Zh;TW;2^Tw5FOfM$36`1A_WcF#|aj} ziq;d}&B<-ag^b_>8Q0gn;Xzi{{k_%rah_gH;vWLo(6Y4T4dN8i6^`hARn6j(f!GGV zk^jvQ*H{)?8{aq%8S0i5;JJR~{hrzU(?dSrD-Ojce#1$wHli&aH{Rrtp*$5!mPu?E z?485dyA@^OELV=@ghAEi0WE9!NoKnVfR=%7C8%U}%4(CVh{ z3#r}_ybu7tunWA*Wl;4{vPiT09Zf? zz#tINpbgNl5b2H**8c3+uI#%o?aEFN^&ao_j_ul>3kH$uzi{loU<}Ye30&~$zCP~n z0Sv$Z1$aOZ#qjP0vF#F%5y`&nzwiqe&kGnI0K0(kAOG?9t`fhX2v|Vv0)Y+aaOny! z8KsT|c#!TD|1S_TFA%>_^9_;lI-l_uQSZ`z5Ubwt(+=$cVDhdI3Zs4vx8Cx)0Sv_u z0CYeJPfrj|U-j)y@&m!}rT*?SkMlO4>=PdVU@s8aj_=DJ3RuwW06jEJ-yc&y5LcfP z&`|SL&+tg0@gqO--N5E;e;d$14Fb^&1Mv(201Z#?^eln+TJQBV!SSp<5cN)oJKp!V zLHGyp43;ktZ=Vv2Z}&=(?%S>n=}GzBp$xE)`7}`t(GUR95Dlu|`q3cxNx=(G&kM#N z`bN95P%;55x@DQ4h+0t{5($+&+zU~9}1x`^~t^rldt=x!3CQT_XnX2 z1ECDm|DX)fp#2c>^une%>c`O1;8fG=v1mztzN~N zRqIx+U13%WpbQEgYY?g3+@@?>G-Yh5fekB?=uoQ}lk!rwke64!ef|Cg99ZyR!VkB- zrL)NzT!&``>Qrg4Xw{p~Hqp7Lu<&NiojrdB9hx%3i~}3qgv|8hwr}6IvHljobxd9v z{}(EwYi$`raH4(x1|D4aaI4jnwT`_lz&Ygsnx{RBlGiTkyRJfp1}(s^U%Pw-IF`;E zaq{KOpGOZo=d*!DOEau(GFtO$_3bmR`s~@;X!yZNO)o$J2PCjSn3Tz>KZjzAs5y=% zYlx`#jIs^By{HQSoomJk$3PE11Tn+{m4RiGcW!FNA@%}TF|vaWGHtsFS<(p>Sb)ik zp`ykUu}2?&1adQAxY*>Whu#AQGLWKqh)HUwi6%-W8EPg)+BV@LGtz?OvP&<&q)Hhq z6v+rO2US}RrE}I~5UZqi*(-qfz@)QIJMWz6oB(J7=^N&l6X`YB9IPsuig>xP{~=-m z=mt+mABFTsKGR(APll9Z&QFpAeXS!xL+Z4lOt65ZtN^TGs?kVSWwllF5;JuhJr`tf zR@Xk&=o`3RyN@bDFT+te)l_x0SYwaf>{I2GLyke#P`VF4m(XZymz*Be3l2uf7A(tR|W#nFOoF0D9ZDUVHC7DbtNQy>=vY?F*pal-j)s!6=n{ zh**3VX1L*qNYqtb!&YjyK7*^NvQPvOWT?e%$ZfIMmudTx1q`Es{_t@N-5nkN+JV0F;Nx@rGuczI^lfA~AU?!4GNn6}vBs(A0muN_5M-svV38$) z1Y}B}VU4*kq=&}{0LU0Q%8yhpk0>}n3C@_dW&{sHEZUy&tXP%oP@{*jBxNo;;z%;8 zO?FtppbYx_Cpha6a$ydpw=@%SHP*rkuK2qMJ^aZi;J=o znZ6{PRixCGkhY|mma)hdCDMshsG_C1%;?nkxCvmCMHwj)TRkxb7G)U6sZAByQe8Jy z;|%R}Yh+JR3R#T!RiY9OL4{8n!or`rFsM>PkTpbiRgy$YVliQyHQcr(h;#xKsHg=% zqe9lQN)QEq1?*n~7matM$sYD}CVcA@s6|JRWh*~6qA6>N-VEZyjND&mOroP9n4w;57Y7u~R zD2%n|b8XJ5QKEM=)MaxkRK-e!DuJP*6AsbFal?pNzyhurSSY7UisDfgd2}ex@F+u7 z!ZoCs?x=K?$TR|=jo~IzyZYmcq5GCExj2JH8e!s{?WlAYx#*5BtYcA^koYc!got$mu-b;0!x;@BXoY=uVVtG$ zJ1S*~E^?t`9lK)3Dg|h_)bGq|J;yPID{E8M(#`1Mh8m>Sr@JlvPo9K zkS%kW%d2pOR&)^xH@G5B0SGfguDj#_)It~9Xs(c-2IUz`S#Voc#VYcgXHvAH&ni&` zDFVHfGzXx|4!Q0_wDDs4@vLnjZBzG+hr>hk5|2UUG&kz3N)GI!bB| z^Co1$A&(ftM20)`>2;i8k7xuIHt+~dG~(0^v3mf%8h}%Ob?=(kJ3}hb_q#LX?%KBd z;0-T$h2K5!C#ggrl7Iz0NL=JCe|!K~!S=QnU20gs0!vY0>CuOEwX`TjSVw_+)SF%v zs3=A2V~=T0!+!L%fITfnVQEgU|1|Zpzy0f9pZej4we_n{{U}P$X)JI7A^@+%Bccy@ z&YLg4CsZ0t^5GR6qpG0|N{|iF=4Lpf>?TKm+7A zGvGIdumg`+g;rQQbKAc<Olbcj2o06dJOJnX|93IGp) zqyPv34sZxMq(eS@h)8M(KJ)-N)Wb%^Lpo%L>v6<};D9>}fEH*07Z8E~2*dvyzlw9i z)VaREp}`o;02;`E7I?*0%m5pZMObu2TZ~0qyv1A`!~md0S0qFwln59c#yw;RC4|8i zAVh|cMH+}iSZoLfKtzV<0VQY%P!OwAyc{@O7zc0wN2CD`AjXvt#{l4fO+3eP6h}nN zL~{&BcVvilgvW+}L3Iqr3|L1R@Wx0Y#z>M!j*y3B(8j6ZMtqS2BnW^dm;;1-h=u&W zB}mAnQ^<%!g8xGT|A}~hk<06R0JG32!)gAhmT+fb`XYr zum_ZQN|2ZYKM;lh5Qba0g@;%IOqc_j#DuU+$%s&eWDqO)Ldu0H$a@I`Q{V@Nn9GL9 zh5)F`hv0|1gb2RmONRJMZeWOhxJtToh`IdBx)jWYSWLVOOu)p;$P9p3K!d}~%Z4xl zJ3PmSfP(4i>}pH5^gNuw2Yi5nO!x%K|J>Y7hQQ6(3;^5=fY$8I=62+Di-Imk5&lLsEm~hdD z0Md{cPKN*hh6u%n@F{J;1|CHgA2p(WV22n5jZlhkucLVRf#Pqg=q=^W3RFP_6QxueH1Grh{ZEI$Q+{C8 zR&~`^h1FIi%vhz>T1`@qpiFMi)RaiOc3`rH&^S>A6GAjC6$w+of^5jpl$cS82vc$hRbk~4Vm+4BOjZ?zh<=a;X^01Rh1YkL z*La}Ud6foxhzEPHhj`^zdF@wz?T1_K2v2~5Y(Q0)u#SijS8}xzb2XOKln7-F0DZNG z|9zlJi>=s;wb+f-Sc{DZj0IVZ&DfFM*pX#TkeJSU=vJ422495;bz)dAaoA#E&xpm+ ziRIXw#n^XkS81@=p7q&})!CsXT8ll|j|c_|y;+plfd@Ran0=I)ZIu)i34JZveYjVD zsE2x>2aBZ#f8Ymy*w?EiTaP_jk3dkEm_{jJ2$zLgJdxT~IZ}|wSfSNfY48VnxCL3L z2YvMiX#fR(=m(x{S9&d6o*i1d-G_VNha#2OhPc(oEr}{%h_XnARY-BZ zeBD@~wcB{;2YLVnVGvuYw1-=uhkn?Hyq#8QV28iOTXyi++r?ehblj!AP~Ig8|0{S1 zS4f6e*ip{y63<-~GeuMY1znvL+IDSLeqaZowFiD+SG=tU=oJQO=!e)1-S6GldnnNU z)QCHsPstq#8*+%PTm_cuhH*7s5FypHG1TRCh`PnyjlBiIjfdIY*NWv{cJ+s;+y}zc zSAM96eNbEl=Gc!t+m66g^ks=;&3 ziGVs_YH!t94z_}5Ml0*KD8$OAe{fK|~hea;it4-ZiCfZBhh@{n3 zQa*_tZiiXXh4Fyjt$-d-#-kwah;G2(j~ItxMu|Bat6mO($!W5Am&1yW(BU^%XA1-e$hT&2@H&gMnUFc?h9~uG-38-lYm2X_6%fZ2zcIz>x5>KnA?s( zWfTV5o+aFU_UC%_=YSSy*@cJej0kV$O;rWwk-&v6U6K0fO}K?gkOo%3gkHD>Ouz(TNCuL=g?63k zTL1-2kOOHDhF+LylE#EvSm~s`g?i8kgw}|9_6YTKwuS)Xk@#qh<_wP3IE$8Nhq!7- zgNUns8hWX$sz%d=wpoZ!-i|0zTCIm8kc1azY7TIKCBTJj;0H{ofJv~@KCl4>sDLu? z2fVz8Qs@D|=7V~`>sNKnU4>7lZV2;*2&h&GuHM{v30BPZ2zf^4uEy$;IMI*}X}`GY zC^aBcvXXjRoGNc|KF9^2#!(8_J~sGtiTxU z&;AHe&I*c_2xo2xHHgr(E{R<=)!Kef$WGOUkW&YZZU$}BhltZTWl#mB)7@3*>_+8W zUC{G3idmU29zpK(P;Qto=ZP56nQ4gXL^#op9&q%aFy6_t{?}fX$4(q2j_-d6nBYTh1jfM(H1WWgf;~< z7zX65@swcdh^U2tLg!uX@y~#_5e4&x0P`^y^D)0~|L8Gu3=gF=FLN`emo$&HH2>3x z=!H<==8quddp2d}MDUmJ%^^k7kU;Wapo71x@|3s*KDaa`sf8#t^EM}QhJf=oe{=wW zbLbHVILB-@?{aGbW=MAkPM7pF7YB3}^)-L=Q6F=QW^+q_bY^G;Ux0_|YzSOX&yf&r zPOb_o{fh)w34Zu#PdW!bigZ;k_B3bpN;mc}H}zCsb`tIMhJd$Ip!QSn8-|#LS*Uhv zZ-{K)cE5ohZ?E=i4*+qec5*lOQy2#TNq2PD_G%A+R|qq17zR3^108mVY{&*fZEe8Z z_gH9c_|$iPKUBN?_kIt6yCnF92l$3x_>-sy|6C~etGLU7Z}@ya_=!*We+PK~wD|hf zPJF0`TcCqApo35_@>wv3Z~vQiZ~1qp_I1a0n78(qXL)pX`I+B#V~lo&fHz72dP=Yy zY7cr!m=}g1`k;4+qzC$?KZT+{`T$^hqi=|*clx4F2ML7*EP#SEh--s3R8J6lQ}EBQ z7yAHj2(uS^hfsU8e+aj42)Kv)0GRs#HwA}~dxtQENqGB+n0to!d%ACky9fNZzx!B- zg|mnIwrBgqKl{d4{2Su`S$Nqfh{_vj&?+*a;X9)B6{`GGN^r!wf z_yhHC|M^dU`aggBXa9#Vh4Ih+{sf3%bhr@Y65wEfYy%4-3?Q(eL4628#aY;J79cSi z#dsq}ZXCvqVmt-_nQ>#sk0CdDRC!Wk$^a`hwlpa+9l{I^ck=A%^C!@tLWdG9YV;`5 zq)L}EJ>m2zRH5Fcru;aLDphg;#9hVOv1He*AGvxZ85XNnvS`zWCFkuLvsD4^HA94u z+rOR?5$-*>7aw1}`uZZw7hq4e|AYzGF%GcKapT905k6j=E%HIhjuY~`47s7?%9A&L zCjEI`;>4R1V;Po>aDcvh3DX{$Hvk`=tO5}0CU%@!u_e7uWm{J3xU6<#<8g(Kua|4Vu|j+bD9g=Cp%2Joet=Ur0^LccVGmtU~)W#>|c8JG`+ z74~_hbuoGpfQxw6iByaTVJJ*P-!y~{IO2tQq*iH4x~7?IUMglymXZV|prML7DygHQ za4M>&67?NVpYFtJtCha$>a0CodXSnu!LwhYJM{{ko(KLp>Yu|hl@}JU1OwEsLp9q_ z9|3IhYNWCv1Z%Ca(t546+-@7dtvZ!DF1h8JYgCp`om*u$2jvpLJUn3->SKGXW7xXb zDLAOIR_1lfLG}3rPQFBmTQI^2D~w&bPAx2DI|$_%)U!oBTkk!FK0MTc2T|zab-ymU zlRLg3)J?Y=gQ_yi|1Grgx3=;s>TwksB*K6z3b^we95N$IE zrGgGN;EFTz!DIXVcXd$%ZWJklG^FB+i7UQ1OjF0fZ+$#gU@}n+kQLlx$BNQK3D*?LECyL`RuEoMl1{l zb-ZH`syw`d|NN{Ihd=70zrO$62fzWcuO95c1Oh>^i-VLxbYxmu-?%5i)TJs_6XXdz zNKpt(NJAR-um?LpC_)j2aD*W|;RjJjLKChqgtxdw|9Ub!{5ee;w_wLDq@ltcwvdG= z{9zB-v5yY+q8AHv1}j97j&4}*f=+y5zP5M4*WCgX``AZ3?6D6mUXhDh^x_r6xJ5B$ zF^pftq8QD%4;b!b2=ohp@Rk;Y0KC8mX;dQ~@7P5>a*>RBj7JA|aSm;$;uXxmhUrcR z#YH-;VT=p_CT^j}A$Cw2SFEHo;*rJ<0&0%?LvXfF1RSNh|`gm6{AA zCoTEP|4-f#kO2UlC<4Gl2tKlxER&fd7s-iUSTT)R^hZ4ms6}BQ(;w`3Wfskc%n#C1 zk8C{15_&?vt<9{ClVm18{9z9p_9L18kYpI?5l(;fW0utnqb(1jiU3?=m%h9wKChFm zCz>o`k@TZ9`f*NX+9MwIpvNux(GPSU6BIAJWDYY~$#}H#inF{$Jq*(X8KBOaezb=( z6M9Z|EEI-9e5F5x@j{AXGL|g0BpNL$jaxbcA;)N11oNrWD5?vJ3k<+8iz!AJjuVFc z0N*V>SPx-XRG}|Kr$6Z74|YmJsyg%sOf9-be*_>8!Fyvv3J{xa27m~6RO&6VxYR4Y z|1hOuTPnWLsaNhk4ja63PX#>q-#Nu znaPyel^x>DDk!;%kO++OAe@cdQijJ5!_1315SRc2=IF;QE;glF6zD?5IMu0+lOFXL zXKO7B(^*oKC+%vY%W~@1;SzUBRpjGr5lhn93UQ0}=!ZQBYFDN{mmVL)$8Gm$(HqXO zCs*je@YW$pr6`~<5dz8!z&hTY1n&iO48SCpJJn}u5~NJ+B6Od7PI}Peik7|N_zGIf znKnde0RV2xgj?JNGgv7mgU2Nb%UgTA5EKfH$5UY_3_yM`hY3}zFgmE*dSKO^|79}jz)0>LWpeGsNO=&Q-yOtm8w$RsQV2a9j_~_7(bX?|IRjrXBH?swb)E{#zUd1h9)SDFl2<#xFHh| zGUZIc69wht9y4}t5^zjtqJUxt?meE*ev%J-yzZ2#jOi9FOIzI1)yb~j|Mpy|3etiq zl+0Kpa7_bXj^yxi)b4)wLF5!MQ1rsEyyfFr`?wFco^_05wsQf}i{}9RIso{azzmEK z6g5WYB=#fmXu$$Q#tHxh0#F4cJUk8Dyu=J%Q1Do+SJBwsqrS}uM#n-qk9~9} zmVwl+F2TFzHg_2)Q2oxGpLyp)yz@?Kd=TSJE)>Cl(O~YC4_t(z>7j_9L?#q~RXE_h z_gIHAs=k9lA0!mAX!;~zao%mr04Vneg%V8e^G}w$n$V0#00yZFCH|JnH^2LWf$^^U-Iwcig|H$;gP+M(4qu|K zH2(30&(h_)5|B2u$3bxM<2k(zAGr8>)3d=3dkJAgtV zT!Qmu*bCVZ1zKPQQeXyp*ad3fEl7ee)J|pW1ZwTXKj6bX@PgCf!aCf;J!C^D>;flX zU(=ah(=kE@aKa8O0XG~3H}t?I3G#L@A1|AE5c4+KQg2V&p`df-z@ zVFylO6?V`q6cIwq-4f{y1BRg(N(Y?8%Rzk4RGCvUtsxtR6C1uE9KxX+s^J-I!hP7t zdU?zV-h(V4LIuRZITXVXc)$=a9UORo18@KbD8M8%oh&c{12{kx(8&rMLsl z^Z^fWKn5JZ3vfeUl)>W77>~^u1iSza;6go^0{=AA8zK{lsUaN7qAbSYEv6I#6+$5Z zLjXX-Zj25%AQ-5Pp)qEU$t;lXO$Db*dHYDnJgEsucF#JQ?RHQ|I&0%m;PsqX$l;WMJ9w%@D68M2T zfPss&0~ky~Ho(I+3_=xLo+}7JA!LIW3<6+W!VYjl87RRyAOS3NpDPFg6J(wV_C$Bt z2ijx;7Q{j}T%=Q0WKX!mL5zYqAW|X)mqTXd-*kg6)Iu)I!|Rlbo=6*L5s2l50uo5V zJg|WwtOF_VfFA_IJ_GYuE-g znhn|j+I1j;oJ`&HC}g{7C1$#eI3yB8rosY&|Bk36O4#^{o%F}ym>wrEK`6`vG%SGy zut6TgBt%FtY=NHz1%*Ug002#)+>A2{ z#a_q_Pf#T`;Oul1Pg6ICV<>SK9oTyz(YHrMs6D2 zJfK2hHpE=!feol+LkvLGodYAN!9g%WAK-^{rYAx`0m#@4Q|JR=5KT|$f;Zq4cvh&( zL?pSK=V1)wU|d{m=mW9cLl?*bVh(~n;DQneWN#Wq8I-|2;KLTg zjv6pRW0Gb=^h%*niGv13Ef7OVAVfIO{~S+nr-e4@(=aJ@c!YL#Lo(9GxYWx)qK${f z$h37qDBMFaD1i;gKqye&J?McY+zUb|!xf;O8Sueg{KGtqfd{OB7pO)Va6)uAr)^#d zb?!tfAZe1WiIVQbFcxZ3Kq-_OjFT#0nZ6_q!AvT+goin_LO-!1xnPWj zXozW!s*Vvzf8587-oy53UVq?2wCRU~+K3At#MbzSX$nZI-sR@y>NDa4zYs-_5{2hP zPXOdXJIup5bR{}uYV~vprn1MSN~*M0Dz8yw<3wG+{$^($7Gs| zVJL!n_RPWn&DoI4Jb-4V4x_hx|4KK|9JtP_wz!I!;On(A;3@p;DR{#J&B81I>?gb!aA(!MC`wM!^Af1zdn#mVC*Tx$3YAOBn*W5)x%z7LpH<$%K9Zj zm~6@hLtn6L$~FYdqO4!&i6@u>&f;tU}=I1cS;p z1kv*B&q6KFmJM&FY||#h$s+C5&aBI>Y}V2&QVPQwya5-`!7as$H3UE;04(W1EXN9L zl2UBIUaZ2JhubRbRNSq@GOWTjgthkTm$g9_L_!v9W^$auA+!PEMuIJn$v7bH;0|u% zPAK9kZWd$#IwZ&A9zx_||1NNBuH|BZ=5B7}GVTLaF5zZ@F>vZU!~z{)0TiTxB-F!g z#DXQ@0Un?M9%Rfx*e>qsF7F0_@8<6A?#1u|Z_;f*0BnF0FfSAY!1Fe5^FlB6Lctyc zfFkSx9_)c4bZ_=5!uBcx_I5A#g6|$|LMW84_g?Sydhhxk#`t!x6Fe{dQm+$KFZ9mu z@_NGU;sF%kfq(d}?(Xh>9B=XVZvP_hd4a+gZ~^R&C!r7m6x0FXZYEbi?&3D?;U+HO zimv8ju;iXD2VZXHk_ia60XBRt>RxV6{4L-%SR}-7By>bLfP^i?u;PA&Ox$oJhaYv9z65}wt5wQ$!>c5eDgMEg*HEj zHD8tp^!?Fa3U%H^t`XCO_>OK5}Gxgbx_Q4sb?0ziEWuRbYm}WjKEjI)MH()eE z$MijLLpGQ~EL`38-RO_j>aEsnuI7wH?6aT54MNxjyc~p7W|=p1!)E$MI6v$n}G$CykCmmCCHdq_ogw0)-q2P8|Hy&dgX=bBPk*SXQX`EB$TND(jWmQWL`=NALjb@@Ie-IprnRfE^{2S?rcjE# zhIIg}MKyo*-MuxZXl#=Zcai9Dn1ly$dqhmktF>@S0GN!)oJ&4HLD|5Vhx$Qc|Aeub zEkeYC5mcNta!{5AMI0c6b|*n`{=}b{0u)?bjI9Wjyz4FX1kDu*aYt%%YpawZ#8s3v ze`_qKSc?k-cX53hP%H^>TqUmfgsU*=w`6Kibc4qhb#4Sox>|Q%{K;OhfhAn+Pt1!f zpjZHGbVEcEEc}CNG{RCeW_v?HHc%dEMyFAX3{SWNkH`a@gbrGFiRL=^r$soWMn{1g z|F{CmYf>ONba+Eo?t&Rc35_3wbpu7tX!lQGc48Yrv_JxX98eVmfF&d?LQDV-JoZ6+ zIRj}y08qn0FhQ8-Awrk}8VIDn1OS8vz%IB0Xllc51b{6N3^)wx!xXuZ@16xS_)skB zRv`M4US);DD~1zA9SGZ<{HW9Z#FuBov>-$m)QB_nXcDMKLkxpqUU-J+>1qFjKs064 z!8vpcX;emxYeR>k6Gg2L1)&$ZU$x6n(2A08iMLkDuMbQUQK?r3KvZ@%>P8L z?>lfmu~2m7QCkebW5?#z2!Cu%P?Ly_I8%x4N*k-j1V5YL(~xk z6GX?{M>*9W#jNv$CLn|^7#O2_Nz4;Pk}9e=v_05I{&jSwL9PqZ(*4gH{{_+?MGrE? z(z;(+S_jHEgjA;6P9%an?F55EzMvMx;!FMl(p-|VenYT6?e9d}-~Lb-`%c*PsGxx- zlx5)i=ud2ZsKf#qFtnA}ctgxOEwK1bXhJCjYC{nB?dv}7&wlL(Gugww&Aon<If3dUfm95kA+x`e4?A-IDK`hdn^P!l!fc&OPwFXnX;V z4%9_(4j6*9R7EAo%*yid6 zGbW!aGRZmVtdk))@f0Zla01ZgqyXR{FP31|Q!J-K!wM!CFGXW)LxCP7sFOZ(3?P>P zbkSy&fv}+}&(-9#Q`AwD{M6KsoYW6tltBc6k2*9w$xyT!NizivZW0@8AU^o$ z!%}FbIq8uAP@zSaciw5oLuj;VMHFVb=~SFktqPUYZMi*g$Zx^b3>FVJI|D)GJMn5c-9$%7Mz8++b$Q%#D9({KqU91heC-=usr4zB^ zPA86E?RE~$PBr!7Nt%3qb@C2Z{C9uM`_Lb6{DkfOP4%>lZtXoYf#Q9Nd-GCgyS&y! zGy4Afx35pN!^(G1TVZTXxy~)~N1yM1``3A@YtGzd{gLFm9f12v@BpsIMMUP=MRk!` zzXd3DSs~)W@y)rk{!#ffCHS9!jp^2&mmAc9WU38)OvW{;UwlptI0N@~iKUMaF2uJM zSSTkfrVEahePfJ-XkJ}H#a_TKU;a||Yfd=#LIOQ2hIw_N7oEomD8V4*BM?}1T2u6$ z;m}v>PX(M`d&PJPQjZC(D;TweF_G&(({6RG?=(E$>oM>n-{L-0o}GyH!GD7nkx%EV zGBRSM$iaDvm(nQsviWx|pKsYpH*oRwr$dgy=Q9HqE0pNQl%Hdd*nl%D{?fj3`+J(a z4@w|m#v}MEJHGhC{!s6WXqx2m{N>yC*{*jol|&kgoEQ{L;6cR@owMXCo!>v3qTqq+ zg{k)$e@Fz&uvu8QMK>|yOV(?c;!hlM7k!O=IRLe9=#2&V8>i+CVXOGJwOy4uk&|=R zL$KJoBrJQ0g`_~;uAGUDd0;I>lNFkC0#d7cfwNB&BlC~IrdI|;u`%=|OO@q5S;wsN zY`pTs(|u68o4}a8w5L>Bv+`BB`k=;~{`?tKX)hQ{_sW`@gQ}lxvtz{B5pBZ;Bvh)i zRmG{7?G+EJ_-eb%zn_?mDu#Dfl-dn%A=lF+7JIfoXC)S2MgEIuD~+mR|t2I zJfq^gy}*-aW%~DVyY{cjf3d6ze9|Q@WlBxk4IPcDu|sIL%$r*p!>b^{5ir5HpQ9d? z05k-@kC^)KI3>=(%t-7JF{t>3mH+;|;@WPJ=zH{%j*4mz9?x-vi=fASuU?JEJI;W# zJ&5wk!_&Y%+iupb<4wBv^jvSCz0;Y2y$XRZkj8cnd+QC(dUi*SlZPwV#p0~2st_T^ zm_%gMbLsO#31r|UJ_m34BAaGXVzm^U2Jmhgi(B;>EXnsqV2uGWT93?45?rp%JoQ4p zbgH~DdjAShXN7m^NXVey``FCeQk)ZHbc~Wg1g+s#$-ura+L*`p8X4y)eTN1T`-$_H z`n(AT%?pccoke4!+bqLiq#N!Tc{VS2I>lSYzJortckkP+=dlnQLG4xSqRzB7-`(Jc z?y4OgaI!0Vt#-v`6deX-^ZQk+hrmFPC0p`j$!>rrSJRGa5(iH}b zZZ~>ocoL>u!QGwDFwk3n*%ZWG3G)CTUsnCRBO---XpChlO}DS6P!h=6vbzAygI+S(8oxC+Wr)Sb3K?8DY+r? zhRMH8J&ZsnfjCbdKOY-|+QB*yQ{rcT3C4yo<7i@;__SyVci;Cz4)RMtuev?PdB-0u zS#G*C5$lakyJuDLUTgKhXAhni5)Q%>QrsRH<=6=%!X__n{J3-O>(h@ohSY=VNb-3+ z%z`F`61Hlz3ss!y2oKpKYR^O-Ttc`J2s0hbzaFe!w%1R)fJvxtnokP@zIGsz312_uulLH#%H0UO0a~ zaPw%q^*AN#&YO(P7Sks|=^7|lr3 zQR)G{3@>B_9uC|`RC-?`@fsOxd8IJ1!FgSC#KoTLiX^BhrRfXVXa9A_E(QIxmYF#q z-tsAxGpuk!S5^7RK6!XDOZ9E43UuyL(YoNxd#r^y{i~dH?te~RXL6I6h`W96f zLzEc{#_b06tPO#xz4-5y3OxG9T$1>E65&;NxLO72Z6)GquMM0b@eZakTIsyq*Zh+U z2Js2sIfq8M)}BzMB|e6bqaH{kZqij&yRk;=Si^A@;~W)BFUc*A%C9-e9T=%SjgtCa z#0wR01q2dPAycM{4L8EhAc()Zm8nLuXJTX%#+5hbWRozmKMACAa+gF`;srplayBMR8>LtHMP;MDlu7W7GddXLX;M$FpUKlCGG@_mj z$iwise|XD2im4-6p$noAC@#O11AHT^P{))~Vw6tJ$yCkBTo_jrF;?b{E2AeACyj`c zM)r6pX?2|V?-c$3Bs8*4Wv920EFUZ-Ih@BR(T$YXLZtq3RCr#vKXdBS-HM;))cb6eE)$E@*ha1C(a>Or%?EK7;kgimUg@+D6O*nULzlfo22tY9(e4nc@ zlw){mT=wIf4An?8Fqd#@&h*$%-yG!?j^^ppDl#DK$Gl2pxU?W=XBoGjxKB** zbWX{gEH%Li`18#vd>RgTI=2+7b3ckHWr z|G4t-^F7C~vQCYrFYfLlgi4g~MDJ8ey$ajgVM_VCTi)e6p-xgU=DFf&ta^Bp;v*xM z#CmIq}5fxIqYgG|vd>|t>NL2$1DLr*8ZhBnBd%w}76AK>#fG8#T<~j6;1(rI-3*`~)}71c;d` z=N4E;xcP-GxclcTatT7$%>wTtJ=8+UB3}c?&4OP1AV|ap&Fl{%b5!6&8RZ@n8Y&Y^ zwp&2OZq-0ne8UYdJ$rVQN;Iyrh*i}XaflLskB_LJycs93%w=eKS{F0% zlnv?X8~)eLqdJc|OIA2*LREa&y2c?A8^QRJ?Q^JpYsZM=0>s{^zZ;<^yiVTvL6|?Q zD-|LkV+im8_q%k7-g!Y-WilKZENF>sO`*I#OI50%8WAO>x=$~kjb;)Q7<6&@){|DJ zB4Ge-mzne!-Cy70?5DmMH&vOoZ^xJ+l(?UM`W4a3=D@BNJmre+uV&*X_Gfcs-B_`@ zP*Z{i2bSI=?(2-1a?naWS4iXc3(c42wk8#1ivB6rt@gzaOo}H<@7_Ff1{I;W`7CKh zcE{ig(?39BcSVfCzSHSMd329L?2qKXSFF(o&P#+!{_2)swBk2tiISGY?UYXOq-2xY zxtX(?yO8X+6Zna*7tJj7xIC#<%xvBE^|pLM0RcLl5iVcEHp*9Ck4@y zAqGRQIi;Gh&bboOgc+xPx26ph=^m9rJgi_zw9z?5c=HhJ#;NUlS)=STV8PN!;S59j zMZ0eKDmCDctl}Ui`EeWDmq_jHk%Hb!SMtk|u+LH2GGD~yE>C3(hh~e}%enMMz!_3U z^?<^cY^Q16svOheR@Qr5iY6ob+GLK1y)yHN9HIg|w3hcMK0jtl+~c0!gSXK8)+zn)VNn6!|1 zI}Xpfk++t>X`R1zs;ERZv}DFghStLRP;}kMy8QLD=CFUMMSxeAnucgGarXgy8J**0 zO&mB^paPB9)2;Gv>zID1^~J4h5u(R#j<_ENPoC1H>D-_P5I(m=@9C`w4=@^8(2Vu7 zOZugoA1YM@Im?urG6X+Ca3N)f2lx#>jw ztHk;jiHBgpuIGMU`B+^4C6OX{Q+(*OMg4#K?<7}<%6g?&SJW{(nD6BY@fL(8`FgSW zJEtoeWs@2ovGKn;O0;(nED{HOL)K~AqRG#8AIx+926A$n`UL5kh zM=!o7$vF4lkCyRYEpDy%am=lUkp!b?zNoj%9Cc1`JPp(&Tu(b*$6l-MaY&4J-N)EUxH_;9vHP%_j0V>3Z4`nO-_OX?wUU#PK(1;7Kae_%^CGqIiCt!FZ z{@eqTKRdAty(Tt&RyKVC4%Y@-*~g)X?Ciojzv;f(PTEbuq?l&%q-sL#2{T|j1 zeYEvEn*$hS{n5?kDCaYzxdt-V0&1sD=##yH$4vaeix$Wa-@d<9s)3-jG zs!cxoDEAE2W2jY1ZDpBy?l=7vEVgH+%mefi{i{@(kDqOM;leC;gNRbjBqbyhJE;@Zel=jYKbn<=5>07tYfz#{7cuZzsW{jrd0`A zr=2p}lXZWcedBU9YTx}6S7-2geAA3TQ$K>-?h_Z@{GD-{A{zBv3Z*OYUYnX)>G{;- zt?$3flRdrgckUcihD9%PQ&m6)899?5;*_s=1yP%!k}Ky(ehR9G$jWE`(=&gNMOGq2 z?<8aclD|Tf4g~2Q{YRvbr4%veiMsEH+TQE;2$ASYVQ-z6l8M;_C1~NYp!KDPs+8R> ztu{4<^M{CU=`znDN^dD2GK;3Vi4Je^Kouv5I-;nS*h+pm2bzC>qyRh!zKu1pV z^?iBwp&?|ye*BxD`_Bh1(mV{C4pPSi%>T{(iL zhk|WnjY$`U;%w4LoSqa>1tD%XH;)|k>_l_Lds5}VWyKwde~`vigE?v*#Wv~2H--!J z4t9JO_=O=ICVw`fh z+gZq^=0w`+jj6`4$HhA{&Ffz^M?OAV;jj`++>?ArqvKjy$RSp`{Pc9d1e@S3bkJY4 zJVWL-3u|^JcgnnJaVTH+;DaoyyJTy2ApOrUCT{LPZGgI3JvZ({c7>Ay>-o+6TCTWR zN_hCMa_c8uNx%Pz*|bsf{kUWHXG)}F7wfVO9h)r|<`+Xa!n}BJAujus)meKdVGqqc z!9&8l`|LOTA8W5WFG^etzv14maD2XY;=KKyU;S?jSnAKvO zq~I_M>**Sj(iPL#t$6H1_gugps?jBK5+Zi?3}hvA)DV5uB->Kv0rE(e@hEOWHKEPO zSvj%l-Vq1IjiQ&hXjAMUc~L(UjB3U&ieL8Jg$mC%L|4chI#+sc(*Cr%sqYn}QnjD` zGM=@ag>+3nT705m`sERboq5JVcEK6c5s~+FP`_4hXzXg_KU73HgW-b?fv~+Jw8aW4 zB7iGei9=eKg}`H)XNcdc9nYNg9#$`jUR}ACU1+>)&sKh}eIrl4DxxCo!LRq^!H{JS z;Pbu8%LXmD#pUt`|Il^iC5n#2I{nHg*EkJwju|?a%stk88?0_;+mx6X``;zpv_Kbq7{_tYntNYX4o=e-yIZe07GyyMqJfj2+& z*G2Zu#*gu9_AVC1=N`g!s9|qruiFp6?NYS#<9|IdM+Vsg{?lf- zGllKjazH_hDpSaa^Zk2jPZN)H@hOUS-0n&%Gq^I2xWO^;V#eN_iG5Wnk8a&Jda$T)zjsDeJ$=}xVOfzWDd`$fecuEsk)O;ehwaGi>>2;8 z5Y2o|Hn@`WtR}XoFH+?BXoy=c0e<#U=X-t0indqDs#iLm&zQP-iv<(=qWaTbo8P+% zo>Fuy>estv^(a<+RsFR3tw`U`udZUL%5WK0+w@v3Ml3>$r8uv)Y$ZUA<+t_9KaE7K zi4PY}CqI)PKpq3)abs!j`D$OZv^>PodmGQgPRW&4yV(93z88E?P$?_MGe0T|czB9e z=|z2T4u*)FE6>-%?awq6tMI?*CsOM55ffP}AcHOkGGlyh_n zqj;aIQdLiQS&)T;wP3ZoKdm}Gg_to%d#xI%Kg$VEN1eL!(c#2-RrxA`QhKca@1XY@(k=NX z1Az+ihVbb#k-fy5N4aka0QhXe6VlJ{h$rBRYS@C;P;;*DR)(w|UHgsUDo?tV#LV zdALedta|!@iCtIl70M+37kohD6<4IWKB~X#34m}!T2;G=5!fDg7Dha(>^-mT;T|UocN<%IiziX4T zIB?f(Vr1!V+ozM%?7Jnxuiqn_nc^JRqvd}`K-V2``KRUg1UGc|1SRJpa9nEd6KHVL zU8P_3=?CzpZ$rfPC^$}Nc$t|ViZa`u=j2p8DsLDWk`)a<`yA^;23%($qF1b0R|l@$ zfKek0B045`@n)tOgp*fHf6M;zIaA-z?R4m(6hgULwM4q-#O1c)s3+0p)pLrUn*Q|2 z@{_7tR5KXZH^Iog@jYO)9RqkioqAH*Ea{wRR5=?ICiA?0b#G4$UX*SXgDG|H(~PDZvATB*psJey9nsO zFNspnv8a@>=?lMD^1Ybs(9;t4SDx*%?3JjXo_M@-E>@5-<3GPEWs`WPo!w5Jy)|EV z{TpgOKT)cd??mc+HFo;?j%n;@PSg0`&uX@5hTq%2X4fTs^ZD6tu#t`MJ#P&(OucA8 z?9G*|{s;fQqx)qg}+e|;6L;Z=R2ercG2OfgOE=@O&cN+eU^l@=rvZ}}|R$>L^ z&oXrF=XM2k5tZmJ$wsXWG1I?0GSg@eKA)Rw;wvnM534*}K8d)nuB-NE?auzUKbn&Y z*tSwE{>aGDrOVF_zEjm8LD2smCM$Ci2~6mIFe%7afPhRn{LVf1#rJ&YWYUTzoi7{1 zU*0t<3oL4y803Mo%XI!SeeTKyB`*_LKInTa==UV%uP_Zgh=KVTBI0SU9)U-W**+Lc z_&rZAYfZYo%-j_ZUO#8vNinyXN?4do+TR-OxS3$kXgFkHr?F}De0i@<8{?lajZ~c| zNCim|;2}#x#NZj>BAVIM=`mGPgN207SthZFF1CI_u95!!5w;zlB1}#_pyhV^QKFDn z{1L6B!+j#0axvT>Gpv^`la|`C9pq@FhjtraRMUqn^m13w9TlnDmEwO>LBXvQOklTK?Ke4HbMgkLihYLa&6NhTU|5jL6iomBXD4}t~tDBgT zc#x9@_Th|gw1Jmgn2_0wI?Kq>O5+FROhO0)=3{cU?fhBSR50)S+lb6EjtJ7G6N}nd1AkvQXr#0UWRq0S@{Z-muIViI2aDyu7h5DZc1Dd>Twx0e>5( z#t(w$+RiUpW=~dw^R6gA9tz`Nvs4lOtq4>dV;pWvl!si>;6lImq+DD%b9d4SmO!j( zy+H9ZxuTV)@0P9aZ-lYR(V@*%roDJFj83F#0NKWhzf+ z99>95RIv>^K*K#l7(4*ocN~gd&$)OND%=R@bD=3HEwvi(AhPgD1b8IDwtDcn%5;*)FU%97K^0&Bjki9sTVIHSuHcF4hsM19a8i>E1*yUoWWYHXsST7}p}^GG z(4{S*Lm*VM9QrfHW*UT{VpMFITFNi5vdHqb6+k5<`JGH`@FO0MUOaKAOih50$1iOTX z3w(>}ZWSnFpxQAoU`R%V1{1@`Qp?kzM-wHbN$_*Qa0CdHP++<= zDBKQlHW=3Fj#Z^$A0FKxBF;J_6*azwVp}Pezp>bh@vD@M~r-U0DWT~Kck}w2l ze*Fk}|5uT~uPXPrZB4nBAArEV(nph<(i(MYytHb^TI(nD^1RWxO*OZhT17CLNF#Lm zNwD8b=do%$o||mJy^9*RJB-Uv$KOFvZ<^b|G)PbtJHQc-Gyt!;fx@5Ua}_WUp>YI$ z9HK%6g}E4uF{mE5LzE0a@JKAFS!^A$hYO;wVbsQ2up;&~R50##mt0O;!eem0R_nrJ zy{uTRj}CgzI&~_@ZM8jZ3S^{V5;#K>+kM<~F9;ZeSP>9#EJxs|;2Ab(fNK%sz)Nwo zudg7vB)EAwRFexB2g7qo0)##VLgEYW=0W+1(7}jWRE*GW5QrHAg?JCb@US%n;35q) zDaY9J@9B_k)}1R64v}^SP`Gj!gwI27dovTjAOI>v?i34wvJ&flAFtk-kI2EJA#8L7 zA8q?ax&qX!A)y^dF!fk~`C2Cz+Ar^=Q%XXY;?X{OI@|4{_K{!?8*zsu0-=h&4Suk! z)&&_8x(I>(I0j;9RH#WX zDk~VVaU9H|zy!Awf31N3RzW2$7&i-p05Av_uEOm>dO<7yq^Pr-AppvP3hv}S67v!W zeNq5&K_HFSqraAqn!6)Zbb9c%UEm@zhkHfp3MR0w59Kv75ZPZr?N{sW7Yz})Llteo zKT(kcZUM-aS+VKBfu*=dLS&>O2>l$86)8F>dJ-ZZ2{tJJc)OMsMIc4HbH8@8$T(wN z=9O&|Ms9`f%IH-!hiY4Z?5?Xs=|soT&MR{WNU_?C;y3{`a6`AMiE zaEGh=X!ehL4ml6yq7FqQfOSL zBJJVc8m{K-9bM`m#4dMlO;OtJN5Wo3-*#tJwk7&m-i&y{gCUtEE2B}#pdR<$>*bSw zf9BU+X;wcDRj&@m;9 z%TwQU$0GEb18TD9b?vt;N?yARRSc$H(`w%9KXZ9H_1Pzk*U9no@mb>QLVEb-*HJTi zZwh|KccJDoNS|yv>MzbMigla;S22EZRR?FvpKaE^7Q*;>e-gY~I`|rB2z_ny>|fYB zY%}yzE!5*z?vz z&}*8fHkzszKRHuhl&9A`E0!B1p7E*l4L%Ni%dS==8ap#&llht0k>a2E51X<}d`H!@ z<*@%c0+v+$=hkIrIJoIjziHT~lW1IqO2RlRYI?Kt&4<5&hT5`KU8U78?p$eu)$)Ix z^#&im>MWr+S$7Vt>VIkCMNcs?7^Vkasgu@0EM z6ed8hq+#K`H$Sc+asX5&9%5hzg-y-#B-<1!a-+W#h{T4s-jTFIG zy)Xw8EdBnxFBr_ZA=EwLB7r^0cEcWnvI9dGqn2`L_ zb(J%Zu)#mI*?wxY>hz##1#XtAep^P6R zf1Vh=ePX*R8}zh5?C%TP)gLx9Bkw*wkyv=~@Xt$?W)-==?c)FRgQ|9^iD&asTR(qr z41XOXh~Jt;PW|Cy5cB(J!_jy+fd_w&26GGqs6_623Iij%mUi3-O3rh_+84Q!`av}d zlpTKVUWyZ1!Q8Xl(raSTEnjc(J;_&c8YO{i_!reYqj9cvX*4g_qF_P?m_Mx$eO>>P&{Z zi{~55riJg>suq)94)f>;iP2#VS{C4h?P^?LAViFuPOxwgCM8EiLR{L5JkL?UD?6J; zsP?B^Gr*o7qxU}+l~A?{e|j_M^~NXQ-syKsGk1S}d1ajRMd(o1xqUbHRvsO+o7y_P z!uavBUP0;Po3@vYU+Z^d*PrFj^`DE96Ug+jA49Ou*<41-HKIjq#s}}5F$oEEWxM>b z3Kq^t%e6esJbIJIK#WjRWC=dFq3UvP`{63oo(%135mg(sz1WW3H8-!@RIwcj*$3UN z&_xQToMaFm8*YDr_ZkfF`!K0G3a27tT$D?7|I-b8K1-m1_F4>a`#05dsTgP4sV0m~ z1dR>v(_#u^?c%j6KpQF(Bz0%aF(t~{;Dz2S*KQ5WYnHZy#X^>(r`5;&8nmQWeyz){ z-+dt@=ByV3kiXvuo3oI0(f9~`EwyGK%@&_LcUjY$dBM4b~x3c)vYu4pPfeL6@Yse zDLzKD<0{PuI%7Po!b_qLlr&Ognw5kVnj6d}->BS*{VxSD7UN}@-z;W;%G=DA9f}4J zQc{VKMTV3?TQJYu^F3{Ue+I5{auN=Z#I8EvbbP`YL@KRTe_+Vn!XA!_F6?Riwk#|tNF zk2|y^e7Q3)G#@4?@ZFW~6r(lNBNO_4J}G9G`jaOtDbM)2yT#tz5*CJnpQCGE#COB7 z?!j~+P))x(){TtoX3fOva{N6$K6gKoPA_)v&CotHR6Auduz3@(_RNl%U;cV6_a3x- z+PctR@e%(B*0(Eu6?Qv+z9k_5k|J$v!GVAF!a?95mf9<-;F|V_HDYorBc;%p|6#5S zS`^pw`pg%Sz+&r8ksx19geKGD4+u2v>VjA7VU91MKZI@ON?mnF#t;73)X09A6P_^g zyYSntoRpPM;Y=Adjvw^^NB9N&NQwJ|m=7gyG8_>Ze)k>J;%sNpBI#mWkKY06Qm;xP zBFS9psQ^4TxI>B9s9R{?{btpaCvQbv&QjV^AOyI`` z?}yWrS{-~aImc&A^5y#4$u~@eKIb^++f}+zXBJiWUr@WYt0gM?!Mgij_>lR%8+-oC z_@j#Np6}CiHqw=f%*I7slFdhm+dO$af5SXG2ReXH}}ztJ?|=jt1w=R8E(!_#a{@j%jG?>}i{hG$5)R=S1KY8Ylm+63l| z>4)9h6;WwhJKm%8mhYDA);aq+?;Y5g07V7bLI1iPs9I_rRD6X^C5Hv?jH<@Ml^cst zyEQPS0_okb7Ps_cflD)7x1Fosor<4{N?7uYr0>TaVF}+@A?&$o_1IrMd!JRf^2aLx zTcaFdID+~+vT62&p3Ob~ciS*QV^AQ|~z_Re;oE|AZajyna{UKv8x;Z5z=$`N`L zh)BmH=oZ=F^rQpflkp|J^Yhu~#JY6v4j-UYuYIU7d;C%}dzh@B?Gm^szqaq#Rj+K~ ztVH@O8NEC8zVKi$nnUi^^00WUu-mPESB(1TwsCPrnon2$b!%-S!}t6KHvY8tr#`Ly z6anXEb)%}TocbZtf*a17HM)uZBS+20XL7l2GF%{1ExaAann&AEmaX^xs0Bt&=onZ^ zyTUafvMd^6UoF{TSXMXv-YirG=_V4v(0;UQ|$rl8YhN zwUI6b#SkPuxj~Mz#uy`qZn~dk+ldK5GAWDQ2=nspU)$W=H_Ii+#rA(*L|suz>COwkG0bw~KHfDr`{8PF4EZ}l+ZrMyUmdI?R75wpFvff$ z$2jmYhVHQW3Yc!#<I#+xs*^t-vm!&+-TwV%AV9$&q!`)Hv=E#e8s<>3Fx{9x&30139EvW^IJ^huH3F5r8K!#=1atsLb~lMvZGG;jWA z3vvj6gD0r*vR$*jS13K`mA?w7ua9T%QVzTD?xpw8$G$<57;%sO%tS?zLeyRZv*zzR zH|kE`vWEEW43$HdzTDSeT&=0BcrX+y5?C&pKqPQY>AckA^y>;*Cbdl#emTIl?{o%7C)Sv>oiyM6H_XkW3H#kT z6RN8ps42l!Y-&=Sw6EvysM+2dTPBdx6Y52BI$pj4VZ-T~cQbzK+UJhToWgPTD~Qtf z)$Id?2YPx}=_&_8OA{(B^c7)7<#Yu6nzR6yQ8*=+`>X7m3E9$0M$T9xEW;sio^$7_ z(h(io#ILvhcxABGrLapTAdxLENYsojQIVvwpCuGwD0CTG(H(7+k)lI(MN!r( zxiOeoX;lWUV=&0x-K7#IJ!V$hhkHDiZkbqAr`BFKQtc3Dv(GraPR|W%vu&uYEZaR? zh#%I7xm7zjoVTJe7|=bNK-3zpceB2K4KCuNOKMngc)01n=jQm{9pXvJv80;Hs-zk_ z&@aYs6qVO%jH|C>261n0*o4-UFkH=6OKa2yRlErMJ1j6^*NSWNt2-?I5z^J~p=$kl zo@eRC6R&q>>0q9#ZVib=aIQ(B>ITkdU#PV0PT08)Ix=CE^J|#+jQpq5%JmaA87SSQ zTJ&Qh8Vm^$An|ZJz*I!HZQD?a-lT~Ho7@H+%#SPFwsF_ku78{@o=6|YA|cncP$HmC zUa-MTpEJx3sBpa7@YQJ@Q)K2g%!gl7f|uiJJ{0(DS^g&N z-EK&XC`}@Q_~1N4OTKnFKf7tldL6Lu!CStE?ARONrM#8%`-5JMsgj&M#Mqzmj-mwJ zWaw+jv+m`~r7>mMF!}g9KwGO+HBFYb?Zwg2z>+nFcYLJ}N{;RMHGI7cKZYxEuLW?e zeH8PPD3~8jq?-P&1P!LqcC0|;d1L%Y$YbKT1h@9-5DIjKn#SL$ea-cyp;(<-&Gf3wS+wKhOG)HN$x6qO%7tEq;GUeLnKs?k2LX{m-ZaUeXJO_gAQ$jr9FdQ5Cg3FPzN=$ zsvnukSuXMk;;8{;PI7(Am&NIh6csx-*|o(04|fnyVNX+f{>af4s(o!q(CbE1W}7f$ zJX4W}s@p8w zv<;?$V`uM?=QCxIfHNDibfQ8BEcHAfjVX$6!c*sllQWRE0KoESzOP0rYV!kVg@n z@g50*=pzHAssS}V6IBG*7C{w|GnRHx=W58{7J#c}9@+^(w!utR=!R`DLOC71J!eNU z2dV+lc$gu6dZZiT;m0_&3x>1v*&zmz<nb4nV_{OWe(Jm+q8J3nrV}Vo0>8!Ql46rJ zM3fIRq(R^mK>Nl7q-A@sLB|1*>@z-Y@5|KKFa(KVOP$gFLC3LKl(v&*miAIwbCMb~ z3*@##mHD66Te%{LD-W>wag@3trwXpgqye_&&m?dxw<4AjFGz8dDU64j+CgMow_lma z+#g3>+dfh#Oqrr7WiCCYtN~4;;b|;_--Y2vymn$j^5os#1@)J^Key7T5t6yu11zB=+Zu z8E-*1oK6~3@(B9g#XJ0!H|bpWnw)AH!4l?C&BWt^-EfS?Xa;PBmUy4(hJ(qDF-!)r zVtiO=3*4g!u6}_bHP)OLq;hoeq!e<-17slCFq2K1;TRMO(tDL<`U~IKiuuS)`KoNv zJ`-qw9SfNC)35_ZM>|bip_@5AtpQ3u2)c@VrpBHl>TO4nZ7ltGY3DP~$E4x1mfI^r z#Z8Qsrw)S6u)rxHOE&Gq5gG&{CXrU@&`;69LvPp4-~}XFgV_6!*-If2sT68ob%qWC9}RPb zy2V3qsPlQ?pPYI>c)&1gb&m7e#Vs$n|x{{U+*#~mX{2xQFOBVTwZqm$! zsE9VE0Wf#)%M@rA@#Y_6->IqGzi#>Z5c?Fm2nDdMW)S$yh#R%%Z-1-9joiga^o?}v zjbJjb9lt0m^7RAMgiBLjX@m2i?kxnc{*{BoUa5Z!=;k8v37xRHNdOt6#bS~)+7Bl{ zgZ5s#0CMUdOal*Gen3mthoJ=Jj2%S~1c_y~Nqe-1ajY5UkktjuesmjW*iryQ8gqaG zk>^JYBrBcDW@`L@l*2gqb~gVyL{2tT*VaFEMw#~Dl`U}SG%P}q3mB%I6t#ru+wHqf zfLZ$iCzP20GD#GdboRJHo&^ID0ky?JmSTdu%v7BQ3uqtgfO`kNPKRD*^8qBy*8uTC> zuGyYSo*0395+aVxdhVg=CR1-OxG|JxEUc-_(_8QId~ba>qoQ1 z!D+NUZM$?pq>GhnnkFtHsRb>u#PC=M4Ys{esQr=tOk0j~c{Mg%ZAeGUn=%Lnt3NI@ zINXz^eOlv5vH7X_5v$Q_7O`)SGGJHs9c`;{&J^D>?5+4T#5L(y@L|g>X3) z2(tchS2l2b(=lV%&$pP={gpE(1@7-ctWm??OY7NO|9cxsM7N(N-*xT8!PCj-DLVe3p07p_>xHE`$yi#Pwy|B4b}Uw-|tY8TUBs4 zw*KA~mUjMoCwYPz&MRD3x=1eVU2^rcW3QTh{OMH*M}t!}>)5jnh{E^~^3@mb=Tgue zrZZ6*U$_^LHtbK(%FbNUt}03umtStQ-*CmH97!LXz1C>#5m^>xzN%D}Tl^|2d7&hB z*m9;$$|t!raW$-slf7Es`Q@#TqJPPrYm;f*0e2|*S6M&^NB@)dQnM*}Me{CHp{u(2 z-@HOp7oNBE<>))@YoA>I>ygs#QrKtaDU&nO`XOoM#8x`4C2e&NB`EgI*DCQ=mh`>v zJzWz>RaemdzQOT+=~E^jPDErES$(`y5kI35$Hl&5-RtIA@ASG}b0L*4qHN$5rv3396#hpnDoorj>hb=Co>qlm7mgx!ucZ zsn#Vpsay#xyB0k|RWbSbs_vWk+qbutgQlNI)RTII|3}ezMm4duQFvxDX(T}Cp~-~a z2}L@Xgd$x;M7p7fpn?HWK~R%Wq=})~Kn=wLq5>i!qIW_Q5EK;^6*UwQd+g}-%9rnF z*2#N?Rc<30*)lSPt>56gI{gI4AnU5Ou{ zZI3H*0bHtaU*z!z$b}*%*=`Xec_S8TUd!im(75RbtOHfTwYPVuv^;$C=~eg&8k!y{eVUKfO)UfvpFE=dimX{z5Lnc2**CvHR`K-G8YGwpu4p79z3i$8>7h` z;>7r#guCw7)Lr3n(u|=ENVg&pMzLTU0A;Z;12ca4&r7L)go}Mtce!MG>zu#yfz>~) zOApmnY<$C68o+$aH(He+b2#78Q}@ML?pG&$gVU_TKrR5Qc5}7;(lIJ_LRkR^L*q)g z_y8UypMt?hv(MOj&Qj9ou>e7VxZDj8E2;e|sT^qYNJY-;oG{tAqCWU(!BMNS$14Jh zF6gIUsJvlzC_7o#rn&Qj`|@R%yC0k01ghL00H})?yDacPKo3Zf7eKV(seGa#oA2s_ zV!9Whzmx`$NXgTVrsOeEUFGa0CZOnWDNk3qzSg(iUs=_MUN2w5uhk0Z>T25l5FlS`g*Fviz*Nbeegb{WvhTk8Z?)i03lDMu(45;W|-4fP1 z!cZJF_6)J2=ZENuaU=fdF;B2~?O!p*{3x3c0PyiJW6$4TAY>_lJ&flRU4%T3teV#N z3XbW9)64b9A@zplKyu6O+$~8iE)m-*EIZerQxQ(Mi)-HBX?)%r5?)Fu=Nz2ddHRHf ze_225+lf(dkbnVeoE|#|%;06uF=e+&c$)7!&&r?UncUzIh{K5T%kF%|v`uQqKAYCd zTp1;+n>yd~vh023qTzU5Q>pa+qt1w>felX{MM@?E{Xo}a=SGjmmZ@&9@>|SHpB5Lw zO&tWaMToXVz_kvbVUcd8i&O*M_4YFHKpT(zLNFN-XxIPrMpM=pY31F)X79IVG;MrX zyu|xL!$j}m-sd~JI-gvPX2pG2ezESV$qftAwc5l|e;Km_Z2+850cv}v6zQ5z1>{Qy zP0IljuATuPXK<|zt#AUG3&;$vifakIsC0RuS3hzoa^z@n;(|-%wb41;^FakyKTV);Jj*G0-^Wcpcq$<5ppV_JuIwc+-Ce&lh*(=%2l>;sVO-nYcJ~ zuGjL3#)I(3?TR9mvu+mMxb?=z{I^!t5m^y8UM(1mUtC|+U8R5jl<`U3RXKXFOA($ zmdmhHob`aKf?YQaoXOdd;&$k1p9Hoz0K2&!Gx@stgi}TG+yPrwl2X_iY^B@b-a`l# z9Qfwpb1z==-H$gd7eyrohN&g3tb3PVI32!vLEg{HEZhHcOHxcnD{wFM^FhJ-Zzo>O zZ{8ksQe{dFusxH{~~JF5HmJIi2U&l0BrJua&_p^!*+HTrcdrs;~;7q@(nitaRK?;|_`wE(Sy+)ovZ=LZY^j>|l)e@Pw?k%mFp32xZr zJxLk%M7GY}EOO3Hot)^GIf8!igUU4IV@?mWy%619U+u@Z|~)R0h-;j5rI16e6r9=7M&OpDGdn)qFUf4fqLRT@>yB-1zkb z0TWv^x9Tk!7uG=XX>bkUsZzN>IStg}s<$wfc~tKtvPg3nMasBDIFZzf`dmaE!xUty z;mS^3%b>v%du#0jPuy0)3I`8CpQqV+m># zJgr>badJFug}(6~X0$s<7)EubMcSUT1Tv^D0QLTekZDxGkzE}T2!&~dJq&@@V6;2fdBuhs%yoVi!+JUbfadf7HgB5iUq2~ zVYyVZ^i`QsMV->gRMY3GC{JM~z@Th^WS$^9_HyH1ECmLLS%Wmf2AAGV?ccdcOCQ8hnObZvlnlmeG$~FouqZ=&7@ckgNSz5PQ{33jIn`-EVcUX? z=YpoWh=QW7H+k}&3rgJpvxAXn%AovVDvix(x&q0a3HpB(!C;WIb2c6`|VSxU!z8HUX5a6D4&p0D8=>Fs%G%`9Qz3%l0Q&iYmdm z^>3Oc>i!v4kTFMfP=3L+wa1D?oa)!uc`h%zK=YgdsqCI?t{7t{(j_NY$BU@cASD=@ z$pR65E~$yTrsh88Pw1I1fqC}a!jmGhlk*E(0u3je*_Bt2qq)sto zPz@9^A{03U@u+O6<`AaV$<(Cq8!rw~?`et@8hW=_4!S*`3#k821$a-4;1uPc=tR-$y^gz zHbcXw@571ae+;p=Mfr92*|pA<{sRYcCoWulKVtbP3K%;f*9)49`;@y;+g)DS?hLge zkTM+#B{os*cr%irIab1XeL#CE6#By@=`$2Vw~(4<)_@??^!`mdeB0gx-e#r^gJ7<- zDR1sxhbg%`A@0hctA_LowB-w`3@~8vvRvxy;(N7FW?KkT-3L&ih#c=ok2*lESA?y5 zt7H5Q?3^PZ3_>RWCi6UHgkUchqA=iGk!lmFNya$zUNWENMlAVUdjXQexj4=njw1I1 z5B;hV;{Vqo5MJvKV_$?|FFe$sj6?#;65u7iBlD@%rb3wkRDt`438 zm5~U&`z!$E*Z@v{2%NM8r%~+m7Pp%W#oYT7m@`e9OFWwRjx*z_9ULJDD}Ei9N-@^BK8^+h`pA{(Od1Co-b)H4)avgADS~ zj(hEfJVy(wR;xk!`IhakMnOwWtX5!fc4icf>uQIN#pXK6x?h^o_?j%Dv~ARevoxu|5xOi11=l+Ku-OD?4q$zG(eh; z0akr6#0$C|>kRz8Za*CF8Gd9~<=3D*`f3_mp2g^!E!;jW6P79Hc{TWE-0$mAu6hAC zecE>)$EVcuR`6v&c6wyA%RqaWi|-xW3FF?ScyAZ_Y@Z&D=q!ByrZ72QEE6q_-3(nC z^kV1hTk{7tc6)CvS|J1A(uYqH$%T(a6t)13IyDeYUP&|1@_+0}j`uKsvHE5S-rybb z^VhMB|J-^c4K?n~h^a2tbj|eH6&sZ22PGV8E~b@|(>Hm2U~;*S-)7wzH?6m7c|yS(kwikR23?A{+QBs)hwVfC;JEo}d-IOl^QR&&YgA`iTPzc?m0s1euC9%_LW_KZr+EzR5|C+ZxOPb>8-t&`YXt%^4N|I#j76u zm>Rk}=-HEPzsJKd)bUQu_MnNK*#!=yqfwPPR%eeryI}rkH}o2Dh%>6YO?+HTDSD61 zSuTG?R9{#bn|$f{5to`HoNHl3=TnqDq2W=-`m-^Y2QUt2q3cI5SK;#>Jv-OX=iX2M z4j=mShP)>I#l8ASxt-SxemOO^PPHvtytMuqYQ85+u)gE2^W^03rv8CDp+kl#Sa}Ix zpHVPV#*pE2WhFqTt4sUF+V+3VzSm^R+7$a~PISNa?8H~?ORmJe-=RCUj(0Ic6Gi1X ze6>HQroo-=^BOOXUH@m_*vDb##=G;Q$HwG({tZTRdN&R(`$-*lRF+G3pQ;q~O6gPf zVVGJR*2wQWxk4nrG;~=$HCWohomJ{Zp`OP1 zeC=sKzMG-I<~cw`a_}*E0%YFGSM1Iit-3S1=4YWwG7W zP=;E5AAKH_R|aYM+{G@QJj$h!F(zd^8JXS({l5-va0{jE+N+g)?bUz#R;@=r*1o}C zFJ2nOXM$SY3=FkT`MnZtks+_#M{(3&*#9&0uElbLZCzD&&td&vi=VDu32;6V;gmwg z5$K|@5|H+d%RKF#`_H?2tLz4R_UqRJuhqJOzgaj@_J7XVTea#i{WMjqR9CN1J_9f{ zzoBy~e}D&WhdlNuJ$ZWk>hHa!HJJU?lNe8chasxkWl`c-1tfL*%q7Y!L)lm>sLuFa z{19JFPY(W!1|EddraOZPv!1JK%p$rnf3=M&9kV^(+nKGj`A)&*q=TAgmEs)hJqjQT zf?OTrU;%}UJ)EKzxL|W}7L_@D5UHH309O$O9cWh)8hU6N=xTvUDDXO#cvA%Go3gf7cpDD8&DJU>+kC@t`vE?GEMEN+$S zdHXRS?qbjT_%F8@D)AMH+i|w%YG2|?w!3S|A6K|3By6d^x3u_glkAEd@+7wml27j#DMe5BMGaFH)#*^QV}Y|e}GVtnZ~+(kw>%C(9i zFcGu8sgFh#2pu*6MY!!p-WFMCChu)sP1guXBn$LPw!Bq-UZ8bsP;+~HV$pqHiWf5EfqV468aiaTPmgAe&xBJqDyZhSnabh+qFu5 z-rM`hqAXS;b?gZ3NiXQgzKVTFzC5Sst`%2UN)pgu>yC9;F~+xvm#t3+;g4-todG6^P6g!* zEApwGs6L#B>I*n|j!iVInd7XsVVt|wpBXHDDNpSjoF_dJlfToPhC)I}@lG7hg4 zaFr2ekyJFN)TP%kI1Fiz4UeeelSk%=54Z?sa2CTVa>JYhRugv!8QuNbZ`%qnyA zxg;e^E?|;&0B@i5WH4N;MMV+0K!gc&jPO;&V!2PPc?uLRVEt+>%NTtvo6OF4o@OUU zF7b874&)o>`jWN-qFv{j?7Px!VqDXOEb}L84~5w1`lnYw*2i_%6e^xJS%1gxTqe(Q zK3=mx2ol&6h4$O(32p=?<|*P~T}A_$h^N8|HonOXfvxRmq@GDrh1_}|ae@y`UFBkn zxMVw_$l+)9m~NOD@O>}5^Hu<3sWds8Za}|VbTDq2GpCpiMYg*m!-k>dgbZUN^^H%C6qoXdMcg@A;=Pqs3}J)2Ctn z``QO5RUKq~$@Z#Wp9B@(=a|%75QXyjGAObydkK^cp!4Om8VC+YHxmbtLS@x@S$PSB z=u;q_ZL~ylj)%e)I)4Ke!D5qV)ovpEm49rZ#6{7sB4Hs#3n6s=i^|^NV(u;m;jX&% zlf%V%wCUXhw`3`bB@&-q2|)Yk5bh3}NQIe-TY|Z2h(ca=>@c%G@032h4Iod%k&14x z?z1U3R=EoOL;JwZZ!*?C#+fdYPI13yc7R){7>XsAMGW26^YBBt4>l6f+H{+KTp zXP}PKer&jer~g#x=GDM{@|IhM)*IF$ao37cjOBGpk>?4Z#`5v) zreT?H_e3ZrmSI)GxoV3-Ti;=EVVN9{*m@kYt`Xlqc}%38h!U0pp?y)wedKf1`Od+f zyUI8qAs|yX_B_FDKoAw82qo0MbRD{^I_k)IUK{g|mSg>7dRxIj%Yo2aS9K&jB!6O| zUakrDqUV!K+Y0dHxO2od4_~>UN_Y|}$2xHps0x@Zrg2#NGOkv`nM|j$a8e%IR@%~l zh1ue+lnYxm_#E(GIVRDa!XjziQdL&2BgXxzB$uJZ24!5_?g7SJqc(s^7Rh}u2baJ7 zzFD{`_zi{>%+)z5hAbvQj5T#YVu%~l8XnTr7fJ79IV#9CG zTHZOmG@KBVv1ViLA^gimnoaY@Z8O`8KH*j;u=JDpb}YW7j}c+{H7p2T|K7C=z@&@*EsEaQ3vNc#|a1pYYDVWghd?JldPvhUTehmRJ0v-Mv%aWj=!r6VW$V=be3^g$9#U$=QzndB&)so3?cbUk;k5N zvCSgQj~zHaV4<}TKz^rwH9-#-qKk);gAth)hGvw7wvL{ASgUsk>9u#IzONthbS`!> zZ^5~8T?;F{M8B(OKqWOklq{W>*n`uft#4kE*W>X*!n7Fc?L zWd=G4CIL3v`zr8CkcqNS)5K?!IsOzOpPhJ`Guv*krDK!3-WnvtT)A&*s*kp+-$Le7 zGA+0g2_xzMdtdpN;#RFHnq8w4 zFt4LNVVXQ>s++i;!18NjnWXnEIxZJjZV^~(_OE1n*xOf_=2+1`V68C>-^{y1lT$US=IrcF_yCjJ(IJ>fFJ=+nMBH%aata8HjQV_c=p& zjd2DW#vn1hv5ONPNZd3K6NmG=PnTS5ayQ@Z$-pY=B=+NY#3U)ynkqNZ6r!U0ZTdZ%oJknC9hCWH-|iWL<>tRLgr zdw@a)6?PdMMntj!MP3R#CGKrZE}*Czr%aep+#-gkQp+?qu*FB^fpy^4?Q3@EDn0)u zT}rFZR}RkN*dgDY6`D@>u+^$T1>B)6Qk5S?U?1ce0i+}{2rHy#%UiG;k@qa3458R? zlj9U2aT*}BzQY_xluH7L_nRfHmz#oC>WON?RQfdkN!N<{x;}NB_TwyXbSLAT={_-v zbzeT`L`H~Pc=-4=*UGj=bjVUX&k^Ki@Pc=k!<$GAZ@}Yh1xL083d4nfLUp}7bjRu1 z+GwnDY!rXBrd{Qu@144RM$Wqu{B6NF5v4_(XAFUVg$h~Hn(HuVsfLv3dl;!_x1(6| za;ak{?!rTipV&W*A)CQd8%5rqv`HAbk|@t=)Oxe>9WK$$v?&SnKCT*g!7N@jjvB@! z&)|#Jv{@Zd-5RCa zITZJEHWL|Unx1`B=^19dI?NPvm0;`r29CqeQsf-tEFebs4OH&J2u}?4@&H0q>{N5ztWTVc7QjH3M_opMf zZmrDc$-Di zmg8rmX>TkzOBTtEykVx1cW}L~CG2g;R=o z`9Wi~`E}t6r7GDKD@&{|P8lqPn+j%AUM^Ms>W@pD)ctF6Xu2sry1-rjO6VxH`coE% z1XZT?Rqx;@dRbfd)L#jEVt>oP-yM+iiEE(a-OmpqR>z7Dsvk;sSb3UNnLfKRZ@azk zvEvbq2sjS4&gb>@^&Q?l+g9zj+*Z=E$cm+A>`*ViyewswU)3WlngrjcyHC~rbIi^W zE-^>(IGREh!(5Jy%Z$6q5Q5WO$|BHhiO3zjSQ2}NCC(0fb*+qu)tvUKiPEjz-p7Bf zmj7RbSA#dfaz-mUjzq8mD2S|c{S!-6b_@X-8=x*kxllwY6zAQ)?-XpkcV$o6)-0_h zoDr^wE*T8j(|s!NxE&cKRf{NN2VA_xpm`iwV1y%pgcZUwB~r^Q0LHQ@?0VsK*vk61 z&#~~bR0sTStCCFv_-04KW|fwa{&aILkxf$;i*fEnQPo_vU0j?w@JB zt=vAvcmBeqs&gkCl|*2(S5MH9<(@nYkS1}y6md=AI{WNbAlsZlk(*(;3(x=a5qc`d zuVBkQrKycEaMqpztDM5GOO5{5F3#}x|J~fV!Nb(e!QAZXfY?;ANduAk}BazL7Xw*;s$|lQW zS9wb*+rxXSB3E@}RE_4?2^)=HXX#psF@T6wsRb?baT2-Ubcc?bRBU`ouyp!aIdY)!u8lQXZ?$7D3=fB>Ss0#eLeWcR&(X`=Q zrRPL+B4hK4&+#4&9y$>cQO|b}4;L&#M2?b6fq%dB8em#aDej!k4&-Y2RIL3B8*dTKj`c zSM%0)udp5-d!CapJ%3j}{@&T%j`kmAZ~AZVw7lKy*y;7`(Z*TAi8;R}&*VrHyTW^i z-z{A~WCwYxzptIbhQ(8F*R8i(R)0=QwXj<~by{C1z1lfN_o=`Ap(vH0y%Dz}pvt@H z&$h=G)wVc9As92E(tBa#&0uIE(d+AuS2sJoZe{w5LJOjiA3>r1wU|{*+$!JKq^bor z@h;q*#kf&>9E>pipne-`YigR6Cm*|_g3KnTu^xEWfYFZ68goO`IAm}>@qd!T;z>-Yx;QzF0e&F`o6kO8Rm`r3cWIu>xX zSaA$>v$#tN<>4)ni08s1`HX@lvH6+X*KBsKb5Vg8(IasxLQ~WMC`n#ucgiAgN@q?vD<0je=4}ne4hLGVCfttqm z8hvUWy%@i~8)%v8Eslz+efQ`&dwaQUj=4qp%ZWz+L!|hDgAQ$+!1i_kW8#Jcy9$`b zylmDgx>*o#EKbdusNXF`x9rGOv*<-HRRF_z%1!m0V=N1OMv=Tjv<=xPY+{0+_P~qq zFtyvOqB@_N)LrEmnms2QG%~VjI(@iU33WWx8Ar0;lCn5kdegV5im2F3>DLIEVx!CC zoq$#f8%o){y?ku8e!Je5!P;=J$hK6kEByQPi6X<%2gI_I!gY;h zmBG(t%n*sUiE9%Fg7UA#718{BBwXz}YCK+_bq?s04_auttJpb(T^ghc!%z z@{1#o?9)?*WoeUuue>^_$p|bNiU=)OZ)cVoHJ9a4?(lqia@;Xy1pDZ!;Sbzmabe5D z51oroP44wa+9-hLi^AUplBb_bEbmoaTZrYQN{ z!O+3?$AL4Rk`B!scU@PLI|CK|(`pN$UY`DPIkWG5=L3@iw_g|C=ec};l)lp9b&t=> z#Lg+>f%Bn6#5}Huv~6L2%@!MwxXZnpc`(TlY#hy zP`^SRrEkvPR+~CgjUlhRRkQieh>7#BHx}JA*6vZ0DZg{dwS7(lwFh73Uaq_BxOx*gF=93pZ&moqEZ%B{c_w7S5N?eluR=sJ z-YB&H0t(A#p){X30?qtjfqL=qcN^;2&nAKcRvE%8bm|e}51f~2d_|-#Vc^2bKn6J> z2G}*Jr%^3VCyM)|{v9c3<$!zg?FQ|Af;=?(a|uo0L-Y~yRe;uF`j?sKV&i((56#=d zx4sn0Jk)g_x*!D-{ojI`XOF{yDT@ON3=a5JpFuWWR$iYgr^xs2Vp>~rc(6wE4fv=S z6Q!$9{O=si$x={#<@1F0=cBit>aW&X5pr8`?Hf<^7%@ie|8`Un|9;VdSXTy$aeaVu zE)%(WEtOHZ9G)dbSFsSuM>*JUCdlDZ##yw2dIfEDDdBP;~L;!5+r! zibB0VV&;eZAV=F#&5WW(&48wZ3MsZ1Q+d@Vv`&N(lh`sLZ6c<9I|B>17s>y*d(<_H ztI9(PEs+Phc0Pdi88pw%9i>RJ6_*L&QhkihRQz<*Lu1{jX2axo+Sw-4sBiY=f|A8L zeeK(h-wI{Fr>u-ImYzzS&p4Wd8}j)ZmKrYgm9jzd(+9Kit{5Wg+ZDW7o0(=w2_G&i zQ9d$eM94)5;jJv<=I7(ydL*^h|IEOyf-s>Khb9 z&b9N%cCVyOA5SDFLd)yx<*^>9j-m*oDiA|S#_~yH0IW`BS$k3QxT=1WD0QpM3Mb0> z!xMbf(14vqHta%pd93=?7Bw^NJ>{7*eGwaMj4Y13wUq_{E=t4R5np>C*)XJ5v%CIM znpCE@l-#{(%5z_Rg71ID06@JoxuhNp4 z5S3WW37vA#)Hl0jp8Q6yLg}<)?NOf6MwzDs1_It1EXkkV%KH$%o_`!$dizjq%hwl! zkS4wWU5|ZMd$~u+F<}s0m*gkuFk`-bge&e6Y&v<*bo2Dy;ABvf_hddmFHb$Ftf?64!aYfZ)hrReMGA$=cLh61h5w5v}|9(Ifdx^9S>Fv%VF+1UukW=<8M+|%cop$#TId8cR4|h5qqloq@`B`2M6^Rk`jNVfS;_R^yVy-(qWZ@0 zt?6gENrsmk`+bT&*UUMIU4NZ>_{}0D^i!dhn0@a`+~31IkKBC)e`DL7lIJpCe@vYp zI=wuaB(-2f8{2=^`N(CZmAUQR`5%UNx9`Wto1T#j=HudjT9oXU|J(f@L5rUl*la(E z!E#(SmyTz9JlfE+?8f?}H6?Q_HsRp~QdkEO9er-RR5O?O%KVdX2E(wGdLuzXvfeCM zxHNic`nA0^3L>X`6{AmXE;>T^<}TpluT0O7Jy0xVO=HQLdjN~g`)1Atmt+1j>|8C4 zB;BQB%#kB@?@B-VTirM^UuoQ{^!+(A^9jcyt7l(QX~dwlb37L-zWq|RQGCVQ_Jup3 zBK!~AbZ1s!Dl|UoFXMgJ`&HjvwqVz;$pL;V@~oz5axUQ@!5xjy`tQ8+U)x=4k8E{j z0-j>5Hydxs-j#GUA^Dc^-!F>a>Jw64uPW=1rut1~y%oFu-skjFb(X92L7I50Jrlq( za1`O5pB)9|R}EBz{FE$EMFP@&fM^1wDgoiPY(m??=f;p47g#t@NcYjf2ZMA%9!Y#? znUHOcGqGL7#-K1~0s@HH1o0}nCBesJFwF;VV_axP$omhQCr#nqP!^Oa3l2R{ixuE# z^!*MLe0nh6@S4(3K4v!^cIMzBIe-;F3}FC~bOH?kcTXUpT%0sko-V{$Cws+(9OK=9l z$UF&t^Mv$?pv?j}U5pRp0(c=1E5R@C6JswnV!0;xLLu%yD!fySPoZGcIMNI)&R2rp zFO)(QE7JwI3_2$KT1HOXKI~;WjNtc6af2v9fM8m#loMwK;GiDj7}|0^TSAVE`0> z=+1^SxS-Vex?37wmU0%QJZ^5a$`_CI>aH;=A-On}wZEK9I&@pZYGRat=lAe!ZKP}t zMh%IQZ-a~Pxlv|qyVUVE!sIj-HgN*$A;lj~fEkqNPziRYIzEyM`UK-;B)m&g;N~{0 z1-o`Rg)XHdLNEo)qri9}b}JV+w1kfo!X9kyRxX%M$M`a^B!oCUA=f`4cLc?}fPIV^ zfRYAWN5SlV0`3dOI!Lg|VkFI&VA)ov3Sjne@XBv7)qRix2e01_Z7IfuM&c~lRbuIo zZXI39=}g_hne?r~aWRL*_`^;FH9BS=MaD(|CvyN>4!(*4Gf@H+!4Mc_nF+M{{!<`( z_0(fkS$j>fa7%7=^Woo0B`30wgCYYycK$|_MXr-I0<(SC&hgp^1-W37~&SO%X9%wn~T}V0d458hcpl_ z!RRU5J|Bjebn_H37N)eSaix!hu@F}6rR$ipYj;k-*nT?sEZCKd(Fy}H0AeP?1V3?Z zrDWwqbCMl~{#OwfD#R5E;N6n5fe2B`aw>;L1wltBlmYV|H+gb!n;E#c z38A)hZvw3wx4@ebyr=l$KgU~r&f}0^5HD%eS;D0p=$zER%QE0l4ycMG(Iy~!6f@uD z9rP6Ij}lfQ$8bydO3E2GHfC933X(8a_D{e@zIuO^zc95U_#Y%jR)xv&v{1gPvZojlDUUj6EAOuzW*H;^L4YH;wj zT;TUx$d2Baf)pFGYx6V<6~R1R4!-<}8nx|cI+wnaNHpxWtl3)G!z)bH1k5Gajnee` zZ~W{#{POX~pcF~#$-%#C1}eoEcQIapzRy^4QW8-k{N6F8x;OT7uF?JVCuDkK=4=%| z!`m4chY4JoV58TBoBa=8Is@m(1*vSMNCy0%6qCp}=}EzP{KDG+SInFnBk2tr+ps3w zRvHTF(BVV`!Wk2~li|15uc(NH-t4pP=!NMX%$n6u<2CHTJ($;{7j4>rNHKnI6zGc( zWr8tjWXygPo?k%siI28-<1&Rn23vY|LT6ksYr~!SK3&vyuZJ4!~ z`^_aLD7+sfBvDonp4byxabTeb7r;9&ndWoAzUxXTgaEMUJBj$DrtJtUxmG?XPs zHx}2{2j8y~V+P(~blPC84_3RcK^Bx0^ETX8MwWr#7LCwH7h|sv9B1j?DhBbeFlDlE9|Mv8Cdr5nWuvyOLoFMrvW zxED%JU3I=O*_58(vI}xV@b+RUWp-4~n1_z{n!TyX->*FstFB#o6|imH=2E?>7QM^%yewkr*@6REyts@IyX*oZ zmyFc7QoQoOiD|yY)E%WgaUHhy3)6dF?@?jkqtKKFwWkF~G8VMGo_u&TexrAwH+Pu& zti$bDDi|_FukkteZ2Ma1s#I@ta|1E6#x;2Ia(q;WgfdT6Zg+ z{qTL62CB**e);>ks<{Nf*V`^U&(wXfV{f4SGVs?BmfIdwF*|%g$>l4(*++BDH}Rzt z*oukOZyQ${Z=IQ}JmuFplL4ABzIuL3nuUTG9=DW3l&$^K(!AYg1JV*St2uIy#j70j zT<63WV&=cA${me-7N!j_{wP2CF&5jtx)7Ql9bBcCrWxXqzWTi8_WoJt`lsfbm3F0N zDD-pKd6zJmelMOYxj**adPa#S_j+yYw9!x7?gvw0D?6fJq~6kx za*MmNRn_jp-t&9gGgobX<=npCe|1*L%4_C^`;#56eOSF`cPzukW8cgV`VP@^`@!8C z`?=P(Z}&|ZetV#1Q~Gv>IX9Gi{Xv+`;h=>_s@lt4{%=mK=rz7$8>zZ0$Gz;79h6!G z;1D++({}vBqXQ1l0XYF_0yC9`>5+Uz|kzkIgef%s1#TotVSHx(bySUau;t!Z9T{Z-IB_)F@!$g#X4{mf@#x zfo+A~R^#ds;xDy*U26Y_mA4b|t{m!e2Bj7jKxA>^=ST5hD6_^1HrGb{l8zjO!3DfzFebI^3Alq;lJ0axT)kK6VQNyFFuffj`!HF;?r`xP6-}9_ zLh}j;TjJpV2%+7h110S`rWAxSFM3pIp_hM+nPBFjVj5hQWjk+1RECv@Q!>E(0vU_b zuHkXk0M9llE1%HDA5@3*T0BK{*JL8vPq^*JX-9rbzJEIKl(%eT^kJXbp<)sux9jbL znQbq-0;6_w(@%9w_1Rkjj-2ZUbylB@{*^Ij6cpYTteaoypA@N|%v!9}w6+Tc7M*d(UjtH95Z*(#sAZ5a=uW>oXIFNFGec<~a3sKUNpB#O+XMIM+~OG?d#Q zvv9}LcKlV}2){B7BH-^h9x(eD@Z@7%;P|w2W0P!DkwUrSO1wd5u*bS*TR>8)xJf%i ziXtttFYIQL9YTGW=I3OPMj4GtN4@3?HV`i#(;1wHRTvKLD%*X^`g-C&zfYs06`-@XJ5Z*ECJV(L^&KO&vb4m4+lOURKG+{B^_%Z~r1)!)&N zGA&p4qtC22OB3?TBI9@knrYJ`bIsdTLgJcN9VLkJl>@>{6wZbdtjb(h)Ny-IC2h^h&%HY)+_19T%9r$u-HBCe&Wv9xfwDfzhrgio4XgH0`Y{?M zoIGsiU_5xhDlNGlGE57e(X}WdFbgoTC<+8couJ8SnWEfP)LA-ofyzL|Sc5`Je7I(~ zkJS+F!3~cmDo}7eR`w6254ZpH!()aD+3cA-yV+ndS8Iij$VsGK6cYgdxGx9cwXMOAU!Li#1Y%xlk9xiX#aPUfctc&v1XQryJ zl~(2DxUG4#`}K{9?IWxi{z~>tB3W%4hgoJ4PGH`z(X;`vx;H80)B9I-b7h*Ch!A5j zkK~cfqR#=vw(}D#Uhl>wR=HJSmKY+j2%>_yl%)-{J5bhPHpRP$tFsGHQx0W-D@sQ2 zO(EFigVN~H7Z0_QUyfa%S^{G&DCrJ84-Q;IKM#eJzP*K6@%|F+*mdGRA45>JKXGge zT|oT{0v^vrp)-09l<0cxFTS_M&v2yad|KU|`Q$sqJ7Wc&wD zo+1R|iU2>greqN&(SDQ*&I9EF4!C7rv=D>ExJD;t(Jt#9Sc@BiR_&cnkw z@6Y@5x~`W~aN*1GrQI??Y)l%Jsyts-%E$p_r+=3JHEP8-!c{_AbhXB^)1nT33$8 zQsv3Q)M*?{vu-6+b{W{`{ThMCi>u)n$k=SZC4-}E|8&pP%@-Nk0XfqM;w=!9KJF5$Z80 zUd9#kTpDd(Duip}rw}L;rpzgCHw#6!u#kJ+K7>gi5}4vS@6Wc6k>n|% zXEP`kVSysxFF+;9ph3uyWYM;=p8*zwBqDne$?EC!zPaAN_tC(Fs zey^sSlTbqH;F;KfT4~eJ@O?RD+|nKJ;0i6WWKI*Ls-t76)Q1cR2y@U$i@r2mZ! z39lW`f*Z$z0hae6*=7L@ClkRol2Sn$>)e!%C+`d+5&d`a%?M@zrvnBcl|5<0hLec_ zxIOa#N8-@MgaceBtK1!V<#v}W%x#AqEkxJR(UeTf&-O59%$QKxrWqvMqFp++^}}u( ziwlT2mSJVcWN(!&Ial>de>?rKPS`ukfOGpIFcrel<=;=L?)}-hS{?d;?vlFYY2wh^ zcW11awq4bCeD-DSD9zdub6_Pfau46kA;42_K_`uN;4-Y%CC}(-(0ULT-z5CV=^ho9(nCjaLMEB z{%O3@4Qa`I{ILOl%d@AS#U(vNd%!H0IEMmbwR(Fze&{D{JX^R!xY86#OvbM6h@cJ{ z_Z!-m(XJk|PTaMnR*7Xs%L-e1@SpnKfb6X(m(5RdY}0!w0mbs1j8_ka9Xh`2>#4hZ zoRU5D#@poJeEHFxbmRJD(Ttoow#bl?yuK} zj7i|g*wW4muBkSKvAwlYft@ebC8BpH9e-n(wmkkR?D4kqHj>NwWtLXPv+O3#s?nm- zy0Sj2@GYkiq6|4|j8h`%duW%UPOd>O112;nFwB%C-g(M62`{!T& zQ@e0cqA-Enb%ufXT4OlEzTO@R#>ffe@QuHsHu^J{9R<-<-|VZ%elWdBmLBzVS**nG zUko_`shrL%!viq;bDenY^0De65~FOgXk6<;KMw3RAj0e!m_)hdWfJTnfGNrT-6s$6 zG~piwXuRZUZ!*lAiN$Nf`FYuE4!Qj|i%&PjwOpZ`9iYgSB;&KGHcPKC$f_h znM?8H?)3unyZ~D(p}pnIKqy-uchNqS{iP7DEDEVJ;D!bwT^?Lw74%+bIWb1CK5VP8 z()~MByo;EGF%W5OU1<+otbn&vFq~#ttv;~pERKGtHaTrnY0|qus!~$)eG+LD1-j;V zPtiRQiUGEqWjZc{Sdk)<3(H*S`;tmYtga|HZEIcV>2x+fAqbyT(%M)kQPy7t2a(8 zG23{(11yld%2c!Fh-_loL=GAcAQ^DYF`dA(W3nW+4o}6C#De|LbjNt=M8SBQWikk+ z>yRr?QX6Pdq&A$MgRql@e$C(m__#RWqR1tGV{%kNC4DNGjqk=4y_tw+hTSsM6<%ge z@{RGe{n~XmC)qNVzH-mAJ4{CAQ=M3)jrXvydupQli z9&$?VI#br4WsihB1s>r(nx-U?%TX1o0Nv2613N&|=DdcPyvA=6N7%B#5h63iZnSQ*SchR7o0ZSEm4u|KM9lfB%JFi88^&AA@9B@4%xBJ88 zLP<>9oh}@dJlkx_DLj|Okooi`1EbV=N?>%#^8sYYQ0G{0$Bm#;|8_)#)G#$#TK5s4I}tdM+Nxdhrn{JvO56 zt)hSjOqXFH{k-p_yPDyi7L66Q4y|tFx=+pprWrTyM)&@%f2`k@EsHjF>ILP)(629o z@_YsX&+#V0C6w9gJ`CGfHoUjBFvw4W-^&}WQ$9m5FK&Sv{wgW3OPm=Z^=R@ot( zT5}S|$CB)qf3ry|6Am!N4WP>n53&DKm;i$|uSNICM4rwS z08j6ZnEXDUwG26m#FTWi2k`0RLC_}xi@XZ@@!`nY=XhZm?*!;Zf`Z~%j%mi1S8rNC z%!gnxu`sA(Yk}=MF|DJ%ab01FJFkrezes{T*d6T>^d7SBHO7cs58jObB7#=~04Fp{ zoD24pKyJ;Tl6^QOmIYr2yPox&dc?BnRnaDa@&+^82o>9(k+gxF(^T$5%MF&LI$Vs* zyorOU_C9m;hQUc=rhJAO7p9EdY0t<5s5_(yxGiMMqC{SeFvTLjumkI!q5gH6ubxSye)fD*FeFZi9IU+NgdqL$)TpPRYR*3R#^`$ zJLCm`50#}j`ABdXD%s2QmqEDUAjRxGrWH%R9VkVE4HM5X<|zxv6`A2W%fe1Zdg5C$ z*RR=xG63p;+7~t!6%w0yxhc16mX1)r`e%=op)BtU)tP!$OgfY3Ss*9xVDVQ{jcoLG3g30=j=6?Y?S#U6+?MXB zVE#m`1KO}ROQoCVt>?hs>pL zg}!!l-=hyU#R?=*7@_>xwVY>flosqOSKnr2YfKW$l47pc|FDc+7&r^-s>SxT+Fq#8 zzMfiSGkD8D;V*WW9CH1k2 z<2y%Kf8lV#4%nH`_}q?TJx^_~xOBXk?A`U}D`i?}GoNXG_SyS5o1|A2fe&zT&zpx# z+7(t3KP~+r%wYHb{SY@J>{((Z31e2CR}5czy>j$x(yrmw#x|Sn$2L{^+BP=q*X@{o zr}1I0r^3_TA@h}w2abM@y><8BCwt+&X#D-)qwEr(uW0&Lx?Ac9Z)Yg`z*pS>5Uu z1wGk6VIcZw*IFt=W#HOO#oX!i{TFrY+tigy|E-}n%({Z5%zgn&oqPhhqy1UeY#=?i zzvt4{)yeh!sxJprZ+@EW1zS~$RlQSYVr`?m-}ovdHE3UYm$7Jd>C=!cSb|1o5GMk? zIedKfFW=kPI8c>%-K;;w_`sTQ{|Z9(tJ{$-&kY+d@%+;&3ciJ3ABHZr?=2v_#Lcd5 z)46nz{#%nF#&q&(keNgf?F}8ir@k^Kf~^~0-0ftdo~5{HuJ+veqO$wjT;{=l_IJ|=4Y{(6YcDk$g4ST*MWB!*5b!v8v>?=Rbq@c>g0u+-Nd z=OVM?_93|45tZ#pubU6i5)Qus-tEg(|Gll)SSoJwfuEEo`R<(z{n(NqMoBvf@V2iI z7XUrS86N@GuaP?EW;OBuQbLV??$~#bvg7B@?Vq3CIP!ql+998kek8T)*0;Qu(x-n) zq3FsL3ry0>90D>!bl`$>S#AIX_kMYHH$#;O+dhWaD*?#!zgrik6`e|Z>GQ(urTv@? zAc_732os-Bwa#cJ>4YE6K67Y+aLxj`aZq&`>4eY7w@b^YChYVW8NM9ug6?E$yvH|l4;CBv=9L)YK8?(R004P;$NEh0cEb@Avao;FZ_2) zDc|V3RA*2@qUl-l(M;l@KcQ#R6jZtt8K4axQZ>-t*<6hQz$=IJEf^0rtMiKP{duCF zALEo@#5o%KWz|0GZwb?G3SA9X1{d8Kb_NKI&?*ZK+*`zjC52H|?D&fV8ue?|rxNisjDWNGe$-F0T?svgP%I+G5wVZsn=irF>jo(;hY{ zyv1xV_@r~UNPalOZ~bDvY2qvImbSRBdK0<&fy+w{QzO}O66v=8humX8w59a|ecwcL z(1oD(`0wv2UR?uI)px%b-)mirakxC%WBj-~{!tyNb82PiiexZ{izjd-8xwwhS^4nO zd?NY9SYdFQrBNt9SoVze+m(;@$qfBqF^R3U4>QVb{+qv}CCCBv9RE`b3tM<|w`F_R z{+)%y$jYo#y?>61YP~>ybpNN7s>stBhCvLp3eTOMJ^bvhV$F`;7cZwT1aBAzHa(g% zJ@EFiX>iK-)kMOzzd)VG2C5gFs~j^?8eQd#KeNj-|L5}W4}RZx<;qs4BNA&_`KNv> zXFp82uPfRwIms#iw5+giT|aMp2Mt6j&2EuIS@VcPu-d%AVVG<-*;{pg9>`JR8Z5A+Z5sso zC%AVV6T+y6Hy#FT*DKqzH?Y^N!Js~(&f`PYxH5yRHMt6jqYRG=SeT9_9t8?OesO~x z%v&2q=Z$DdsLEz$DxV*zJZ9#-*|RPIxN$DDDl}}u+C(H~^cs?C;tq*Pn?{5(5iI28 zp{h{+0tJdl3|A97ux@!*+PEZl&vnIce>sP+O`gm3wrfX=YcmVKSJ2dVN2s4LkRnK! zWFQCKM7y0;(doVy7=j(d47v?n(4vu*s|_BCqh8rIEZy-rZ-PtQdO}Sxx*(~oo2lJK zg2@+kvysx4c2mA*beAIF)lL5daFfw*Q^WMBEq{MJTM%4PkEGU*eCpV)*B$T1QKt9@f;h)pBKMN}s1KXw3aPI}duboCGz=>+*YWM0% zgwlxNEu1a9!};f%9IM4df~L_mU%i|zE!&re9&FE4yLC;&O^298l~5v1c|acBweU>! zj*X4-a~R#D8DE_0VAU9+0qBRW70I!=b{1)+AxcJoutkU*`hKS zB(B%6Y2^-DA=kj;eRHdyj6+_(BgLivPJ&2JtL4ot`KK!OIH2&0CqLxNA*iZ?%G$GJBq| z(4ppmMq_)Cne`B|ho9blPtW;)rOZN~WkJrMgb9p@|2Wd6HGVNza)ZM_24MCDrQ=7X zgSf745m6y_%S;`Ua!6b*$TK}L#?`8&@N;4FxpXVMOaHLNx3%K3i=E!)d+8GU+oGh% zqKK(?WENVOhYsSA73TObl{Nx~zdU@e&doPp{<}7{D2TEx{lUQ=OZ~-ruW7wr%xn-SiNl-FAdLZ0X?3AQo=3~zq^w5LjO)Ie|0Iug|tO88cC|Dda6kmupVb6v4p zwq!B1<&PcFA6t+>DW%lbxA%^kXiQP0L~nual;N2qq)+;>+xoFbZYvulZ`~ZdWcu(& zhnkzzvBn}@ff((MecO-%#E8jQx2?T%sC^^w?rVpQ-Af(MD`K+l+07+aJY{>f%E~Ki zz2(4v6WAwn%HFj-O(vbjMWoO8Y;%zFaTQrq_aYljp|)tG@yNzKM!wecl`X|bDVi2N zb>R`=h6hG`j~3tkNuz}6!?=*`9g>(O>qE#@+_hE2N~?uBgXorT5+jkAkvc9XIa~Pz zIO+e8p!+R4_UcQ?P;V~o z?=t(5M%k{mu$uYgVaE^Ujk~k^l%3{l9B@O7=#|5}``u_=D>=8XfBt~7^P?a7Ik@>c zAyw(>O9k`Mp)nmxmcH}SPM50TwE9aYwmQFgVxJp~)|)Qe_;a^(UOi{~rmsz(@m}X; zem}YtK?wQ%!Z3Sk{oz9m29ziLA=Ned*5vUYJsX>Terow|VIzDCBfxRB_52n`Ke|re&Ce$_Z4lHPF$kqG zqvVSA?U2xE<`0Qud5tVd6mE-0zA2_r8|5;ItS!iC=TeT8Kc^3781Mzrk}d}=v?V-D zw=V{>p6`7bsgy?GNNXl8cqr|x*y0J;z6e!CZfowmg|+LZF{NU@UA!f2JTf_|5^pdy z1nn#VvsC=M`9tW0fm%;lQ|?ucO8h~&*aY3>Bg56Z5) zF);8Qmel62vXo*BlA)AewHZU=ZWU87v0V`h6a;xTc|pd6Kk1>UXi{qec`i-4NsZ6( zlzXeq@Gvz>gkS{sMmZO{q+=pNt0|K}VQ$O}j}?35;tu1$3DeOR657XUqYAfL`0fgO zr3Qx*<`>>Z@lbe+Oljl*Hw!hU*akykLm2yuwy!b-*KE05sL$4fzdx5~P&=FOlv%E= z5MDvxlJG0txUPJwEY%IR;Xk*{>p$n6Co4*YMh`l7 zFgVR$;!THd?K(w&FRv-!r81{49_wsflFS*wn&r`9J;>cLxWuQaecG`Q?M{)Ba#% zuI&icWXbMW=+%x1!!W+$GpFgD&5@oBW>WE)(jGg1#5L!KO}f{_hem2N9SC*PoZ+(- z=QoGUr9O$Q2qu~-x0tBh@z{YGHt{an_oy0_+$&v35?HkV! zTN{^E9WGb-q7!h?a9g0*6++!W{t=4K80_kB>1*m5G3lMm&6r*il5#7@;$rU25i5ni zA+he-zW1b1mzCtvaJa;mC;7|EC3cb{4s#YdYL{?@NXrbTn3hTPDeZGJf5!2b6|x!d zZnrnc`v%t4kJN6usd$*l>t#Ik&1idQ%gPssSu=Fw{Uww>pyAe0?x4wDWk7DLyjf$5 zHvINwLiCP(F~^=Q8b(v@Z4JwUpB%U^*Obn=Ug$}h zhA3w^i++KJ%fuA9-}^SEhLF!7d|6|P*Miaof(@94+5$|MH;6W3=6HTggtx)T?xE>k z-LnEQw*HI(<+Jk^XQ!ae>^!}4QItg4 zXv=9YHKv%JJw@{y9gh1bS^GHMk8(4!%z+UJ-!mi|b~p=L^Cjdw#&`L!H_Z=pc-Zpx zkCfz629m%bAud|a`8q|h%H&7dDopl9nAK-_IoCC%_P&!N%01C;qiz4!Jt%kW?32*< zU*(b??K@|*xG*gpw-`hY1bs1vxNw|^G;9S+^g`Uz1 zH!&BYIP2DrCJMeo?~MRdX`t8X*^|(YQ$1{qbhp+;3UH40psP6!?pEOz_sICkyTD>G z8vRoE8Ggo6<&QpFgOz~ofS<<4pz~hdpN{QRee!FFbfYuBBcRG@Ty{yu6=TW3ia?%r z{2KQO+}ta06~1=v5Fw*>5IY+lhVw7(uxn%<{pqlsNL)wyrI|?s$AV?s@Up#+;CeyF zXE6^+$cK9lC?_7}NbAzXgvi8ZxL&+baMcy% z2dSj}=CRI@#4j;e0-qh@_HDxWz>+9Ky-LcYa(%1f;C@8Yokyf-{tfAHtCJj;Dq{|A z^TS7WHJ`;}iIfwSSsattwOwA5^Tuk-LAU+%%Bt`u+B2=ktc@SY*T%e|0{c91QZIDOLm5<_JsB4OxBdAdcwv7AM~S!t9u z$=;m4x2xCWKXGlotZ7X^q0S2$a&zbqdcW{qX6T#Std0@Ik0x;T+*z@!8A+QT2EewL zhxOckp@HHEvW`wwiXGp;b@L8X#?C&z2XjJyJ6L5^IhWJ&*`J^7bcr;CM$jysbD2# z>U5ls6%>A7i`bSGGKl23C+xcO_i?IH_VkML(4hxMIXz9x{Nhbzn0b|_Z^(|9viE=M zgZ;apH(O&gbuSQexklT6WQ(fuH1-PqP=*c-C84tEha&XPQYZAPjd^fwXMe6uy#?XD z`hnklRrp$;gHK3W2bo{0y&8jlecYb6RoP}QK)4)!UiA?NI~`tZ9uYTz-V_R5*Rjx= zkT~(_`>YblaoXi{_4vjn^D~7gXv66`CV!t!Fw6YJh5Xbl(yCUEwr^%b8|2cek z4S)VMKLsv_wDiy4;+|^FP}+tTTgU8f(8t%Re7fyvz&o)}g5INp`>~JVtEklV#TNNR z7ejEUSazQ;QSrpBaumMy=qV?hA zR8bl}GR8y_FMi+)@qqniTSAsna$tJ*Rz(sbga_b=CRjc|w((j@2CNuxB$co`ih)|q z9c%{5g7R+nvNh3w5{-fa;ylriF%?v#0`7bfZ3wn5*}Ajzg;O4M0)q@UW#hrVRA3)k zQk3P4qr=S5AxUds(-=~A($<)#Es2*X2ojM25|)$4-YEfH>w0fHRW!Mf8a&v#Hutrc zTkQXVK3V`-oR^PeFj{NbOU(!|I#`Evmt#X35=HrG%Gyt}Kc@ij4PiD&1Ioz&91p{B zoe*xoYaE0{t10oF#AtvGMZ-2K<8pFpHX7A(F#EG|rKddO>JTY(@sw5ZcyzuGRs5u= z0-0zGu8N}lCVS}r!+F?rm}5|$5!1x`-$j(A73lz{3|6L@-K_0CxP{VXa7INfAv#Qx|b$2Zb=iDk4V2 zS`9)=&7$^nZwGH6R-)ju1B?JbiURmS0H!J7BFf5&FckDEB3cMm)*^hUr@zJ(KxFuC z0c6aD?_O1}s~6i#^Hg#_{)-HNlL#ac41Whbc&d9k9q&T{$)X)N3^{pTi7O`RPTS3GjK+igUl8uATR|Swtz51ziVLqoL|P-|sc}q@ zBWa_AWuhWkO_YceLWW%UKD3JuUc3o+PJ9*O3Sq)f;D|shQMnP)xTEj&`n`5+-wqatoWN1KvL=xAsq>*#p7I>NV9kq4CditXWv;kjb=q-Hn| zaWGX^1W;%Yt(ak$pK)+2lDMqU=Cc>;L+~M@vRFi_SQrm?`j@&7L#!$cR&!T`)M(e; zts(MinkDN*{jYJ|=k6Yf8>KW7f%CF%z-|FtNzk~f@;>_Md4&DfNL6Mhor$RVn`x_B5iI~UGcVko^Z*4H)Aj*VrW~ccrD%lP-p)pZ^tC zY7Dd{#MSSkiV`B=n>Fzs$D79EM+6(Hzq5x6HcnAibq5PKHNTWu2>NuVhzP7 zwImLaYJ7#z?8Tb(UIfYkK8KJ9$9o=ULY8=m??HRJ7Rrs7Jy5HMfjqr@K{Y;d>*j0w zrAq6L5R?(c`K^(DHzIcm2YrpdW&Pa-;&_MvfzMVQtrUCg<3Z@Zpu!%o?#kFvJslQl zT36< zA1H(_`BI|&)S|;Nw!Y#hv`Za^%-CUqPSz>2DD;x2_=I+P?n#p=I_$o{s+&R_;2Xyw z8ZWoVc?4&nb&MZnL7zgIbT38E4Xe@Jw=jRVDVMohby}iX7vbr_UPzO``?camX;Q7k-uYdXv44-3w$!|EB^^*7tplWf@j)w(!sE*tx<;)O?GRYaho z!C2t}Q%p^1|0}x3lGoo9h34aN*JrZ&I4ABd+}k-7hpr!UTlR9t5cqR`cbw6&%|mKF zzBS+cWI8b~BXixIPd2NLCS~21+hPPOJc~tBzGp?MvTjQZ+N~(LyM=n8h@A|0%)*}w zwAXh&ZaHCHytVQP&Yv>@o8lnz3u_|cKDT+UeN;>_PUJtG90V zfEyHh3ce-plH?hyL1R1g^;2B< z{8N1PhumYiEsuAn1$y+7VpnYQ=8qZ>%XJ?nN~vQ>f6HGV2XJ&TEdUZ>fyerRPt9k& zeu3`q5GE4PgJurMJKLEAYMymYlq+jZQ#B+Zd`OrjxiYM%6k-~iewNg0S&c<=KFg~i ztkh%^)vs?{hVY4g!g1fEUYz8rc;jCilFb#`RQbvsC_G*`vgBB*-1 zN9>o|N*0R0Iw5f?&~XAp((02Z!JkhNhye7B!bTtN!?|^iV+!a+X-1QP1R+9^4{&}% zD87@NWKYry9Ub0$op;GDzh*alvn5w-dPL``0VOo7%wpb#1!?xd@$_~l@t2DK3auuWELzVWi`Gr3(<_=u$~$emmWD+4Ph!u?mpioz`|(U#9f4Rsl!DMQS47lmGUM_FBUi?Q5+ z8SI|ACM&AZ&tLFszoApBjed4$U!|tev)WjGNxp%OlvBUuB6!@@xG39wOY9 zdcw|2%w5>HecCuh2GTqYw^)TFfgWh;*s#To{cbDYDJw2~xWi9S5s%!<&Cli|;F2(# z2k;CU;CSihc79@|2P8%nU)@z&74bxm@?Q1UwQX~nwqZg^#(CHjUd;S8j;D*gr!8c{ zlJT&*Ux=r>fD{27%Z1%r14Bq+tjz=m?}c6Iz}_>UA`R}#prjYrH7cwmoc?J|UDjm4 z9h9E!6R&&O3V&_Zx0UyE6BXP=mvAL%G;BO~G=SR(*N%J2V8YgJ-@YpFRv36C*Pn3_ z@uThtYzwKhIE#&5W8nZC4GxONUg{;FunsB)PTpsPT0r7wai%Ww_NliYsC({m5lm{m zJyWJ(1XXYeae316dV$r>JED;F8pcsXdCIVtT3}w&ENu;(!pa+%X$4(=EuBa9i)}6( z$$p?qAUOCej>P3kD;UhQ`7pIe07mah-Q=~cA44zi9Y5z$_1MJsiov70O}}gs8S?sG z$AM%*#%V=kNNucY=(E>NR7eHQVu%5v@ziQ!K0mZJl+N(ki6^&AchCWQj$CPff^9Wp_HNU7nUAmstWF`*_I0(_weRrNG}1!<7AXTKkiU z%T5l;jr638I6;~6ZQi)~w|AJ{j?;c7Ie8gSw>I+`^h*g0u=9A}>>y!-%FuY2_svP{ zq1z)Wnvn5TTQRmc?~&%EJ z>ZS0m_Rd)h4|Xp!4Do4uyZ@+1nzQ84CYl8-%$qsA=T+sAONSr+Cl}JSj6io|DfIHe zvC0#Pp>e}v4X4+@QGFLVJGZLZ<(+rr;C26sXpmV27E}%BuT;B*I zj(Hd81jRA|ttIX-N{VLHm-J+`G~Em1BJ0L!cM*yPi~EP$EgxPd0Uj*l1Suxa`)|#< z(bRwhSBU^xKX$mrR-Z|S6fO;qqK+M5fWwcW*9Qo!ke%`i4{45yWmv5Sh&*YOP^ zM&Wng-aX51N90O6e8LZFKIV&h$1)IxXizy@nB{n%2a)k?_a$PsI5jrpe_N~5^XNk)Mlu+1zg%ZzJ+m@9VkT;y|57{&=K9#Vcxf{f6Spg-OXw|`O< z_bn2oA{k8_L}1AiJd3P(7RsP+5H1;KyotwrH-mHS#J&l%?S1u%ProKV_TV=qf1!9#0OlkjpViJEQBbvy7 zOv2MifMW$5YG$kbA!egUCN;KWG&POY2|F>8gc%Z0yo>h1%?ut7fgauv$cKm;x9FDi z*P0dhar813g+!Bav2;?;xOk|tN9$3k?-RTKCoS85K<~UPc}{WHk=Gb?F?n&^XW`n>^`_1)lK=m zHFhD3VZA$0JZY!2o}GWX6law+(L+_`7NjT^al`{Y)cO&Jj+CD)pfN z|AZM&CPb?2qtRYwUovWbTj}Z(2E{RWaZQ0xnk=Z1TcT!JcVB|djwI*C(8XK@RI#-# z3QCHXG1DP{+jHGKvNyge*zkdH`S&E1KdUb>(eB!wX@Q6$Ua$@S2i%qU;ee*|o80|g z#xp)sk|8vPWT=2*Oe|;K&tS=P(kwvlEtwkDERr7lf&83${Lv8RbAkXs8j#;1Nuuto z=J6A2(V1G}Dwon@vUNoS;Co%JWVKjS_74B(7vGqYbkmgZvuavRv^~fB{M&ofzg{i+ z)~5Cs?WL=tHU4S%{7$y+6T*k$WKSMToZRH9DSvqPFW(GpdFF-u%FW{>^vA1ePEWpF ze0r>*rU3y52Tg4pq+HRA-L0s;NJZJ7{ z`|yplFvDqnV?jDo{Mcf@LQ@wGFC8r$WL{yxn@L)FSqt}Ag$I>zqO{bGR|Rif4ot4GGZ_hcmRQe?pT4T z4geIJ_c^{|bjU;>9+Gn?qZkJ`Em-<8ZndcpN-FgmuS) zTqY%f!!2buPdc0QoD%+_E?uUL77 ze!cPeRr6GQD<-XO&$ODPFCMl-bHGyFo(pJq0p{y4*LAk*EK@GlAgaq%L9#`BOcLV4 z^cWzF%D5lTh;qbtBC(C-+FO7H0d zs9C6H58P(?7VlZkE4m=X+4qXu?f5B4CWC1eYpk%|%$0As7{UC$kl*TGu&4OS&)<+X zUQ|Fqf!*O*H{&s}ZPr}2bvENj5x6lw#O%B8)qxY(XT#*D^Ub}XM}L$$XiQ5hmrX(t zMr64QnHm=NVcyWk8Lh3+kfSgkezrPp39id6@;1CXUR`{JZtuLqE9?(TFH~Etq80u= zw`GDnJC@1CmEu(ue*P!PJO=PJ%bW zQr$5doWu#tXNNXqW1F@27%1VGZAHvF|6wHDpUh*5HWC`bN__S(md7lmvDz_k4aTr3 zjVYqIYPwxu+3Z2MuT(Ef?Yh0Dse1`txsxZ#YpY4!Gc=_$F|(Zu?->)d;QXASrhUaz zxl#L2m}xJdC$MlOa#TY{w>dMm|6wVIvmR8qha87tW=E@i*w(YT;BlCpg$#ywCra&3 zdpeua%eiB1_~sRdnw_K019d8Hk*Sbs@2$jd+myDl5L~7oj(v^@==H)i(iGkud(f5L z(iL0gpV8a5+WT1{7k)M%IvA7us^?`d>P&1Nd`)53ht?4)Mv+^hm?nd!fxXTJ3f{<# z7G*HGKUawXLysyYp zlGnCKG~|r5GTjQhc%{o1{+q;}{CagMooy*(itoW7e~E$sMGOD+^{LC&AJ0YI z!MQCw>zN9u$}V@ z4ks{cUf*|MVp@~!XX_#&-`&5G++!~%w|k-JlVB(Ath5IHz9PNw(OB-6+yRXp*d(8@ zsIK|U@M|o?XP=O}58o+S6qftWfAdQAg8D-t6pc%gvK`j9I5%&9T5%!77Iz zV*jK$s#%0Ohht>^I4SkQL(m9Yd)8l`ie~ez*dn$?tWf1*o)k0h$83lBd`?xcGy9qF z2eIVeDp_rz@@a+AjSA3JV9a}pLQ34gQ0uRAT~9$OH|$YTF;US>r;TgDi;Dbf^-rH; z+;hkH(i8PgYtP$=f&B@oQXTX>OnQOlBwX!9F6lkYkcfuxu%&y}Q7ooeHmGz_@>2*j zwr1zdEa@^emMN=}Ok?X+okBq-=Zf?Km7AP$A1&uF`|zjy zUTr`8>fpPnE4fOa`1vP`G%kU;qd@*SWDJ~-!;rHFLy0TTQ7hxpE2S|S07@g2<6sX( z%RuCHW@U2Y9!HYll!njjg@JXThtulwO8v9Lb65lrKc|9PEqj^{(q_0CTkh2tIiV&2 zlPk;<1!{oQTP#r(Q2~nn&i!fRuC=@qGE%dPDmGtKHl`P9-T=&%FDje;z^udQ83AfT zeW9JGUNg-)L1AXrv7AC-*hw`FC$`LTZthNYfC>3>1uOvhsOm7NGRgKzgNICVwCR^M zz2RzlSDv%kOU9u4Nw#YR$4W3|UcnI|sev?i?TUC20p?CW@6^opS!Y9JaC7DRdqWDJ zmf-57xid6vY-x!E7uISGiGFV_h*Fsy^;u=7|E{*?b9}tnVz=U3ZcPyfnl5B=R7jRL z%iwwjOuQn>y$R-10jF;Acja^X>Ka_VVb=ro(*L~YPe^Q*M5M>4^1bm$D#M14#7+{l zDnL!TuLBWE@MSMRxn{AJD#Y9kbOp={S@073-XSf+s{%$8f@hYPbrWyoi8o68{Va(b zLN>z*C*fHPkG>ZBhQPj;gHsb>g$!`wscw)pLs`fn2qhEbIXG{bQze z&D2$9W4UxS0mFV38ZYFSp)Z6X4y?TisF}}J@W5T@|7?DJ5Z8;UjGEK_57K9YdiHpw zDcZ|Gf2H0y)n%qb8b_1vEN%wYVfV=6l9vhsw^MGoU52T~ns`?P|38w>J+8(7asT)3 zoe$Nv4y#1#e9k(k5Vn<$tJVRPWStMfA|%PZHA#i3R0!*!LTM5DkZd({pjMKcS3)XG zLg=mEzK`FZ`)Au9+wR@h>$;xL|LE}(XWjS9j28ZlIAL-rbZF6_4W{;dG<4bmBZ);f z0t8)wg~CGb4opW5t}<_l#Wn}0Xi ze}viWgXKjQ`DO8_5cjk1jJw9}HQsz#&dB!_w+wk@{$*E=NuZAv#=PtIK91=}ctw7e z=mh`X{!nv=j`Guv9Yz1diD@4!;0-OzD{p9-7_e{g#`9E+SdWZxw(3#tgQNndG;N_bLU(8{9)oMivdI<%$Q#jg_Nh_U~ zdI})|pPS-(X{xMC#!2#Pw$M?7Usgx@D|0Cl-lBg4kH8lg&>an$eo|?CMg#8#GNs|H zMl%(L%;Xh{_)97N#@uUfBlF+7?Sy~3F`t`eV>Bykg_)LjMF&lyBX$_PIYA2YRb$LA z7sF`+nB69lUy!YdHu;Gl|J5AGU#6Ft|i))Wt_Eyx_;>> zOt0Z`{;j8!hI#jgHudWcc!i%keQ)^oj|8oTZi*PnXJYJp!1UF2E9v02KVmoo_BwBW zi4%`F4+|smO)?R|G{yNZ81X!Fk^Ug@;c5uO>NDI}*L9&XsvWp-{+yF)T-ePUIfF25 zgPil>cSzKra(>F4i;QkwlVXWSe&C<*mYwI?mrR32LWHh}=jL-kmkl=zhg=n0kPa8S zmfPI?hEu|PlR?|}0(~G~FDI*YQsIp`ra_x@j$rTsJx?QqUwVv8qZq&OwgD}6((5p# zGFDL`kTK7=xpIcTfpA0t;FvVj=&QM&b=E1UQq>F$=?F!Hkxyl{ zNBnq{)8qr(Ioq^S#>G!3&6n8EneLJ@>k9oFlB<|2^1P8IN7Lq1Q-yDNoHa4w^g+`~FAI1EDWj6~I;xGbzjTD4Vlg4$F!1qMSU zGO=#2U|nF{DNZK{+|1O^u@VqVV0$dbzz~O~vGs=>4+`J%2$zYbkiBZt1!7RZ1h`0x zq9x`cDvoxUtq`6DPusA5OOa;oo)2`)Mvp!zjnZFvu`u+q@ZE8Idoo|BW3b> zr(P7=K*_A~#9P;LK%Bi_WXpZWyA@0pV_~oh*Oj^uTchKDn~%GLl6-Agv>M(v`#`HN z?Cbp{LGB6U%lC~uapX|KcbUUU;e;;h&7Bt3zF6DFhlr<@JO4NH=kL`!)_<*c4Y{l+ z*c0k_S_DdzJ=<1Pm*qTe40KCxdQ$Z3LBWl4zl-f|jHG;wztpT#Z{0k)k`&%Nx?=40 z&1cyM&S}41M7`P(6l0MEzIm17n;!UW)z!AZZ9(c6dMf+^T<#U8p1<)b?@88^Zo7TQ zzZP~GpVPco^%3!d_4}%v&nH~in?5z4XK*V_dzn&xx6HG(v+*Bm(b z_50Iuo7qnt`q6(=jx-;4o^IX!X3Z}*?AA7A`_A)o;?t3fZjx_D9*1IQo&4?L0}c&GWNK5T2nMS8N4e7jo4$XwguyHAXgoqkw{12+XgJEH!E85H!x-&duD}Pzi`L?S?Qnq1KH={ z#QHaJD+fON#cvkD)i%m&XN>$35L&v25OwR}ekXTLU*#Zx zn$+WAxBx=tE6}D%U`zmPuX>C~V!hL6aCoabf{_5o`#+B75=4){J{2}@JlX{)j)cBE zu=Q5vzLxNVSc_XMe@5bN*PQpwud|3xV0o2BL>aUWERMDQAVJHtqQygB` zEydVkq_AS;k#)&qFcUYJ`j!2Uoh<>6S96IPS6fv@Iw!4z$uLb@X;7f2Q}L>?9*_^^ zFC%J}gynAf4(S3FrNKg-QKNc(2G48`LOWu~eB0lKh*8n+OBSqAJE@a8UI_RK;xOUX zb%=tA%y)ey0XK3G7H{P6C9F@IZaFhT`+%1=w4@6~>@MRw%De$}CKhmnn~1G2%cAJ0 zT!oC9P4BxLwLUiLiXX*vB!%GRzq)ebC-#-ndpBY1R7Q?b`bIu8$V-MI)dQfOj z!*sJbumGZLVln;&69b+W;HmWY&XyQR7U@v4kyA~ zHrkN@L+m-6t2Y0{8u9Q(t!?YkiwLbz|51@6InjU!yU90iuPQwdP@k{H5xgJA!JYH` z3HC+;e6|GVA?_iAR_c28}n3IqP3O^Y8MgFB;gp6 z(cnSWqAJmzXl$ei)IP7d)vh+?inAQnY9^&X_(}z;+@q6nb$bXQ1MQ5Nq&Eq*QFWiK zG|q4SalAZr1D;~j9LQ|Um1CFDdPgkOk6!iQf|M8q)mwOjnj;K5-ZKlNC=gbrQtXxz zpiCIDIh4fACEEhv?bY^YeT-MB}@iA5zyev z4W6SnnRP9RRVFpKtC-~ZU4-iIXd7sQn)0p(Wi6FY;~b{rTwvJ6d>~Voa9(|U%>rS{ z`sr&2SOL!b+E2P2^DtBQN4@znNrl0f%zm@DbR(s1oj$?dyReTjsqvbtL?zTM#dQg>8B@aZJZK-6|v;dV5}R;u|x z_H0-k<-`9`^$?Wt^jal&TIc9pSQZtwR08cIz)&)&M#xJYl`^bCs>bQXG~(10>XaVY zF*_Im0~)yHBioZDY+JqG9WOSL7pEg_Zh@^ zqD@wfqhHZYb?D(oFKqb+S(Zg>y%!>dT1i!bKy9o+CQscKKR!>)#th6fL4-(&KEyX_ zfEh=585UtQseJrAkf;`xd|&dUDh6eVNO9n&+>j(dpvfG}nAM|015LHc@!Tpg8|iH1 zxl!wZ85dl-z*siANT(>JXfdQsU?Q{W6fWPe+h{jZy4#^s$EWB}IC3Lf0~L)*`yo~1 zKC)qu>$p!0wGIEJ+C7yAyuqjwWU@+N>cBMfv;JwdR~2*q$Vxiy9{#Z zglQNQU~ivKXoT_pJH>J@(2&C{Yzu?TkJBEUz!GZ~GKAHsAI%7avibJ}^)0w;39+50-uhCL8PF_8#E&56 zOIes0zX7d}i4}n9`Xb;5;hsVrr^NT>2Yr?o%jWu?c@_;2*zo5Fl$`NOTj$q&qWWM! zJFWlT9Fdfgc=^7!z(C`}E42-l8XxjM-cAc*QH%9`K+93s#`wp>k|P%ldQDpj|3vu- zlKUs~3ACK!JKxZ?=PXpT;vbd)eZl}$KPPF`@ka)e2RyZKmOZv($}`PJB1mc&b{zMydAb5=&x9Dk7isywUfnHYMbm2J|nV@p|&Ij&-5A*vqS*p!US% z8t3W#XDr)AYQ+WkZ;vb_v&n@yfo*%Ir%xV}#unR10b>^LM(R`@bNbE$|JXHG?u?|w zGOWHipO8g{x9@Ev>i9y7C{ni(DZ>C#rZp-Wa{M75pf7#}5#%->jPkxJAj8i;# zHLm;RX6!be&S$CdmmzC`>P=7YpQ_tI4s`2&&}lzIK6PFG1$b_MYGjA`p#5j^hpUrQ zh2+bU;%z6c+Rb)0HtR-r?IL_oH1>nR5BooNMBCoTnw|*UF=C7i(cdn~+4(Bfc7MUn z*|M+gDoX~nQ@cq0$BWN%8+W|Uu|CPv_=Vf{*8aVcj!_tEDE=kgftr7#XwQtKW)=4r zQ-l7#v4cfy&+q)&;+K|$(@=jNba>CzAC66jXJE1c7{$`9ekx+_|mApLr)BIkCrK?M;J9~pW(D$xhA;GWqInu7_2ku|?^A>Qxur;i$5f*pd0f5yMsdo-FR^&lDsHeWqqaCtC7+~3**zTNsTH!fmPl~vBcYoy{&!A2T+U9o=LAOeuDA;~gxq z0$^Q`crJg~r~cYv`qeO5fxO%;(8!dg9aPy+AOa^c0RjjaFxew&&bMRl=Fyf-5bg^x zl)y{0lrOx}BD<9oKKhPM)-5c^-nN7W=)!RSNToY|TI!L}^^|kcKvxFf!XO)R;30RG|MG3nT@UVt8<%rLChk+uCGH}IBL9?{k{iY7i$JxtrL?eD)AC@Lcv3l7Oz^&5EP20%*h zmH(bixx!eQBOxoQkW_}=D|%Y9RKG!*d>uNFIj57!BbD-!&lV?iOLSIo6ZU;(#Qpp` zgTu+_sks*knLItwwuig6_( z2N4iiG#b29ikt@wW`Jh15Ug`|wgyZs1E$IGp-^EEo`IRDiP0=+7zsL9B+2fQ5^HN% z2IJZy|E!Pm3)ftG{>3+MfL*j@P|~DC-9@KGdqA`OFw>HO!yv69q&k%n9ASP(F0lw9 z)x0LzHSLl_Dj>|?ER6C>>QZ%aBxwYOdc4uzU(!`q08N^-ejd^znnakl^52N4~1#Umh$QS8T+Ja6+EH>K@d47 zN&T4#zmIg>s`v0i%7BFAl|k+hC2S*p+~~vF?sGIhP0qgbfgd>PO84)0p6<_+bN^en zYE|8@_ZR}BRCCp}C4U5edckhG-YC!Shw%x7l8_B^2rIFePjfPf2Z z;wu-zK_GWsLGH((vug<3rHhc>B*32mJRWn-Rs)*OFv2T|8o>(yGARuPG5SB3nf;tT zZbsm}FD+$UIM~o&{P#cWzcqoyNSgGRO~cjJOf0NTBh3BKJI^MKF?ss$BU$X24C!aF z4?%DN*B-L-Ev_)*wg!C&m%-2k3=J^SuANgyPCyzgSiotiX4{WQ%}~{g;yH&yj7Mf3 z$Uqqo&2q`|SjhU)CVLX_*RAMD+tg`taNsd|+7(z`pJCCF)wts$YH3ReMm*9_>5__( z?N|S&KPe%$IT5Kl*gKwi3|NAbI5HnyO64c&Emcze2Y}eKt-3hCW3s`%?7+2>%V=qoNCAj~u z=+s-Mx(wI*|2&@#cGMc|RBD`nWv_0Tohg{=sJuwiFFS)rXSU!tTryi%vSm2 zk^&mo6(?&wk7?MIwa|qbBV?q6oSu4{A`eQ$vqt=vIOxw$|V!ziDu z(p>7`_%4{6=IYy`_Up*-GT1 z65e_GAU0V*N)z+)bRKLT%Qs0=NL_1%FECcO1d%bw7u8QbBgkwq(L?QY?lHHne9g}qnD z^~!OSCfnBWkzp{+h&kJ9Y};pdr=4;5yP$KsySUT(gv~K)2u3mshj6Rs5$~pa%-~32 z&lK_4C41AFG%X919{+Q`qxIm#Nt0x;xY&PrZH(&hS|mkPnY#1QAL}aP)NQ=k()(2* z!=<6D2nB<=#JaEaskX3y#?*OX<5-2{w@n-&?a&$#!`?H=tB*A}1;0qSlrVSeq``Kr zp~J;P?@oHVoP$3xu_oOL)v<3Ewq-cf8V!3tIz^0_tuuWV#k$0LCLpKz?DNy~;*@Vn z30`y)g)a+FZg4kQ(V50ht!dggo;ub$GG2VsY|K_`2ej$wO8dibP5T3bxxF^DPqqH~ zmq)cU10-%>LYVVlZSk_Y8P{R<82w_oU4UxQS^ly%=C~Iv#WZn=pkX3`W}59}G@E}H zF-G2+ntA1dc}LT9vxD{QYSH=j(V5)-$QZ0}-FbK(-ht$rtNoz?LC}}1sm2A!E^2Mf z{H9j%+QdtAEh_u4WCEw}auJ5=u=rg3%Kdo5lC4GD19E7^41IoEo-yid?BJ>Gg@f0F z(HV!W>1)9^-cwH}IyJl+R{ylItykgUzvbNpgZg~*N<6dX6c|?GE!v0P<#z8v9>y)A zJZ9g;?a;7=cIJDKjWT^=Vv7PQHii#MJDyZ+4-L9U(+p4i`_AOegW9b2j}4o0`c8yb zN2yP)c~`PANhhWkY_S0 z-}$@b75W3$ll6Go9i_!2*`crbOGT9N-Yu`JUC|B4piL7oJXpaVTeqi2-Nzyp<4;n5 z`}q2iZB8KGQSkZLdaN|mgvd11xdm#7)8Y@bR~_Hzb+J5!U!psV!G%*1YX#T1gbbs) zsk)xkL!y+Z%Z9M3ieg;5g1jSy_v;$DXOn)yX_MCAVrCLE|5dkLx##PRY^q0nEwsis z6=#G!eckFf*@&c;SgY#nV@~ji+AS;BtS2U)R={0Fx!RF(zQ?8a z8Q)KjWK*x{=OuiOh|Ugw-iS3*1=KELJ)C5jGsus3_I7-fJeK?rtVNupp42MvGIZ7& z%a~)VHDGLC`$x1GqjZ4j%+G(9r%Pl?CYGqHBu1nv2Y5US85L=>E*E(gZ zLOSmirY`N`#;>#rPeQ%DyrIeXlWkuNF2OjZq2REfVdqk8PMK!eWVh*B-1FX4-1`x& z>JyIq$Bj|K0?p&xy<30j;bU0OBCZYkws>7^5)9=?Bdk;3=hawGpf@PpixCA*A zr|Xd-uv)c&T$5D@;1T=MoR9kA`iEX3!y&;$dPPh&^G-*lWL@6Dl5^_CHJ8Ipug(0X z#~Bx!e8By>>G!@Hrp^K20!78MX~Kt}_t|+`wjC(tbnKFe#c;T-0zhD-aaVUeZQ5=D z=rpLn4szjjHlpQkrypP~hKOmOt#|d3FidX6B`N@eZEwDRb#rBtdjmXazRNI+%gSpI zA+rNuJMGwfqJcADyVs#;Q4@-*^Sruf_XPJdj)>2cYU~T|+Ei&=Iv!YZ+Q^{JD4cx~ zsjC40T77d^yl#-|P>r%vnB&TxZ2mZbC3|2br`4*VRhCjzvenn4cS~Z^#w-9sh^N!a z&0P|I@qal(y|6^3VClL(pBz-H2)<#oqplud(#F#{Lk$VnfiS5Uhs|2#sE@cFPOcF0 z!K$YE;j!ct4i7Jnl%;4TnjVjB?=MfFCA_!J`jtS|Z(fWzdrE=l95XgaT%C!4cxwO7Ih=qfL! z4Q$m?K3)vTW`FL)4d0neQPU(D(O2l*CW08DRNX~&^yXF_1u7ttMmPW_yT3kqM}q2# zmk|jN;1@?#uk^f$w3qXPdFpn38*O3*OytT}Ji;MmCv$=b364SpPo>AwL^h8qGy-yj zUDRb_u|y-t*1c4BxJ2B2JlCqz&Q zEH98^&@Wkqi%6?U&G3*lsAY;JBzqrKs$MKuC66TUsgNx#mGdd$EOLkfb~Zs(P9Kd# zE{kFG!Bw`rC?5LcgZ94A>t}8@h$Mqw9G^d-<^tJOc#7~Q38V{X@~gmGb=UOl)mw_1 zMRUfJyO2V99*6+O4Cg`h%xGwNni1mLe|%Du)6eXW`IxPuEkA+)uI^|RUVd(5*CYNu z!4VOB59EO<=H>~^80vzZe6WM9MB0jgeToIze>Au`-l&uL?@PEJ9W|uDp};xzL)+O2 zLZT=L!})CrjZ7+Fnf9RsFiH8Czyw@$B$x#ed|HIwNDUh2pah)*S_&X<0KZ6A%xCt$ zd_YAwPvMK{Zh7EacRMKa3z9=s<3p_8_~P*i%aF(9jdp5GDiRS?gZK&*NmP7=XYr89 z)Cu6oC-n}|<3C^RAZFa{zD8m%@T;?al`&G~uq$BxJ}*J4E0E)Ku!lo6rUIV#QD)GZ z+Uap3-LqG0+4~qj2~2|kVhBKwUWMI~AS3C>1`cWs6R8aN5*_!WhzbhrAr>xhLf{_K z^nbPRR;p-dIW&4=ByGEz9s?CcMb;_5MJv?JrQ}2jveH-uE?g5G-_}kf$Ll#dxvpceC%1NI!EiGqNm2zOh844gV5OgZT|XgPZv%~hypNl?XrTCxKE<>ZL&7;1z_P89`BHRG0PpiHZ< z9dz{_A|x$nC7&SfU{gYK-Dd^pLSvwasuoR$fvT7pKo9RkQt9d`5cVAaj|C79K0mT{ z#1Os!tsFHX=SL&y$+eR}TQKq_3l)6z7CXpcfiRsdL6WO442uZjx=1zz^iwsWIM38c z=mjc@LscIK=1qB6w@Gri@myp@5Imn5I~U~)rS;n;Sl=AHE@K3KmTp|3q)#{ z02Q{t7b;+|8?jdOXX?1|!Xu(WMGLx!AW+pGNRT=bJduZ_QPoUgBK9`>xXiQGq?qrb>(2&-ByQfOeCtcqn#+4-R8(FB2;Yp5-PDQIIsN|R z;-lD>WwkWZVJZ$lPjcQ`W7&w>laYN4pPIBYpQ*PMYO^UGq3_(-)vaq|Tl*c2myS2f zyo@CpCgyfVeA~9$_($XF2T}&o1K0!5U zfoOM6A7|&*GgmQdJK=$GAcytPHZfRWOpe(yqe6n>cy|muk96S z^^e*(JCFCXeXe%+`-JeBj+lV;b3qY-b5OO%8jyuFSu6K@p4u5oI%S77$kLDMoot8M5yaA%8|M<<#saX;k8pdyHEWuo@JFrYJAP$ao$2KS(W8M0GB3Tc)+~rFNXg26I^p&<(sc zuJNag1LRiFEdby4XoWac%%*nXY~g5D+G+{lBSL%_c)h4DLK4)Gl9r*hBFSxnOKH(M zoYE-%=B+eE(t&A55a*my)A#C9pJ>nO4U$`JRw51-J_UWR1f5UDZoBJ3uSjSIC4TSe z>i_6!I+8Wh5{-=GCLM|o6C6~Afba#{gC0YD;l7MldmBBYMw5Ue^nF_!2^)nNBI!jV zXLSS}pHG#k1Mqf*#)JeDC|ZmM$TuY@ACW0vv}Yxc)TsEJ%^{ldNQmkSlOjBdr#Y;E z6Jm(eDxxk=y-tSHjX8JT|E=Ku`iEI9mgYNXr%q_DEWySO z=tf9h(u6J_P5^HnH;?wC|D~zzGF4wZC_&LBh}tHVHuhr{71>TQ2m;=|;h;wYvBpKn zY=s*6gjWz1V;Vz97UBN^D2|Az08l~&Ss)oe@klp07|(ffDUfq%BUYdw*NVVZ`Dns8 z@DJeSzhm5{tC16VyP3^?aXu`O@xfs2@&P2Mk|y_4``v&Ykjm1E?0g2^mT3F~$ec$A z)$gK^)2AhAmX#fdat4GFu=ds$z$Z&3os_v??CH5CGxY!Bw)k^U|0JXF3XNaj?n1F)$4yr2)}R^lQu`cDqf)ms6$XX?om(L;3zGXw#X)KN+2lt=?1+q-Aeubwx1 zOdjm>^ZJb}14zU?MqurIrGT0W9Fh5VD_0dy!?{rH^l@`4fe> ze9lXm4jLzd;}j^JrdwhC#xINkkLRdps5D?ddY31$S2BQz!8@bMV7G}Iuj8&N-U<3s z+qOey6G?WsY-%Js@3Q$Wn;jPhDep!w{T$PK62h4Xj9H zj=ohV^*_@)-G_KLuENw~EHY}iOOR`nSq=&RL1Yn&UGZ(QSPX}{%K@(%}K zLW18xMb6F6E;t(QW77^&UCkRg#R?5wqaT%*!6L=|MqrE365@t&ek|+pn;C{cAd=$_Kiri|y%%A-L?94eztsb|21q zhej};j_;2<0Dm_tFouT5uY^h9Y1MY^gQ5MOD$W=agRfXeo3guZwNB8Wc88cPldwhpYC|4@um!}kqHi*X zE=Dy3?rGc}%ld_9?^2VDYtdh1!p>ya8&7XDS{n8aydR^z*&BbN~w?% zdBh*@dbKeecG&nPE8>LjZRU;$blSh$jXs63)$9A-T4}#d=o|#M%R9%be&GkT0?c(- z1U+M9ev|i^AC{#-xcPbNY%P{X#qW-_N~fw#DWdxV_8g^(+_vwz3&8miAAT{9O>41x zKfk(d>&@ID0W;%1?tFRs@lV;~W=SJh3L=<0`czz(MT*2^Rk#ZMveY&C{TD>r4u=?a?;Oz(iAKigr0<*4;YKgS7Io+S`MlW~P3XErdNbdh2 zI*v&^{(t#EX8*^bFYvtMgrckawyQ)xG|Z3!#)WX)V(eM~JpmEI-y&Cudb$-@)5^~i z3cMHlcdKMN{2r3%UK}FUY1{*59ZiIQ7^$jQiLniX(!F4(XowEP zX(J0JkG6%*vZW{b6ymh|byqGzHGxOKtwXYWx|bgwBu=n^Z&io_4cFleUlM@CX_|uw zHzo79&dT(%D7sY*NOIgpXB)*rSUpGE;gMf4?8-`w1p zIP$iS9Z&IV+vmTH|91Sb#GMOtwBl<-zdaoU3|&t_)gWl0rjM{Z!qz9P*P+tk_^rW= z^%+b5`*y@2hcLTH$6L20cEK2K&z1#*On9wNpgc8#V*<>y4L1ATJVu>&DmjCfQ zVV(^nesc8izPC85TIH6gHO1(7A#-ZaIBwm|6{Cc0dt{y%go5o87cUnv<6Y*wmtuAw z6Kj)L$yMvUqh*j3?;7O-`gx2hHZR4|PvsFTw@Al=JMKHcuqJLRIx!Z2dHK$y46X#0 z(dOf&6}UGX$cAd*KPPaIJ%8R(oVbfV~tHFvc6^~W^B&Rl3 z1%0xZ@tMX_6#^OlkaJ9ofm1`nh_96qJxo86w&@{Z=_gM}C!v&E=1-A{ErPv_-cvS< zmTg-^2+)}=d9bCGEuI*+%5NZQn`sLlYp5z3saXMupR%S>3U+p6oboZQU-&sa9Fc)I z*@-og3k3#;GSjfKs55a@jTJ5R@teS zlTA88K-b3H_ls0%9YRf(8_)>(qg4q}=0Xu&KS$Ow8xi`sw-cwGX>`OO^_6%eBEQIJ z+r>XS9{+H%YWnBsRP+q~u^);Jm z{p21!v^LV={lRyC0gUPH>JKS9dGDUT{wgW4`;wBj95-Bucz2CYY6w`~0}pus(yB+0 z3b$WVRCrKD^MQjOy{+YjAqz?6xSPmqy9~po9S=)&Mu^DOAq+hCp;q&$Zr-nVls`UN zE|0e3@+{M0w{R(xrZIf>uh>G2gYNyT!34K=4uM=%vD>61u zz7YE6*#oV)6mLdp;r#f`ntfH&DMbhY(0 zDvspMXkh|GrTcDB5vy=it)5XCCej`tiNg){Qae}i*;zXIZxAnw9gNvkDYmDV*upu? zo4OMGzBZ3d@t9ie|39~#2O)$n7bG+DD?-oAGEAikvL9e>+5Bm#maYQWD&m7QBB0F* z^ta-?@?--|8bl6?!Np)Ox?&Ag7R}dHq*Ok=`j3BuK#UD- zBLZfmilhtbbZCEF`dPFn3TZ1QilY>cuXp!)s**&LY~IczOPKFLF@PsZfYQHo;4G0@3;mg-;r=l$9-t(*9n?GqNd}OM-p%P8~-_*9I;%{U1~k1!so%( zn+$Df zQD#Q1Lg|kJR^06$(6(ZP2iI8LaPiz5s+&W;S>=7=femouEJzEVIYwscrm+IJC!HSw z

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 Date: Fri, 15 Mar 2024 14:15:49 +0100 Subject: [PATCH 124/136] :bug: Fix duplicate board --- frontend/src/app/main/data/workspace/selection.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 56b4e6800..3f22275b9 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -434,7 +434,9 @@ moved-component (gsh/move component-root delta) pos (gpt/point (:x moved-component) (:y moved-component)) origin-frame (get-in page [:objects frame-id]) - delta (gpt/subtract delta (-> origin-frame :selrect gpt/point)) + delta (cond-> delta + (some? origin-frame) + (gpt/subtract (-> origin-frame :selrect gpt/point))) instantiate-component #(dwlh/generate-instantiate-component changes From 895f649ef1c02eb1477d44acb0ffb7da096c4e37 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 14:01:37 +0100 Subject: [PATCH 125/136] :bug: Stop drag events when the user focus out the application --- .../app/main/data/workspace/drawing/box.cljs | 8 +------ .../main/data/workspace/drawing/curve.cljs | 19 ++++++---------- .../app/main/data/workspace/interactions.cljs | 8 ++----- .../app/main/data/workspace/path/drawing.cljs | 12 +++------- .../app/main/data/workspace/path/edition.cljs | 8 ++----- .../main/data/workspace/path/selection.cljs | 13 +++-------- .../app/main/data/workspace/path/streams.cljs | 4 +--- .../app/main/data/workspace/selection.cljs | 13 ++++------- .../app/main/data/workspace/transforms.cljs | 19 ++++------------ .../app/main/ui/workspace/viewport/hooks.cljs | 7 ++++-- frontend/src/app/util/mouse.cljs | 22 ++++++++++++++++++- 11 files changed, 53 insertions(+), 80 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 76a6c3ce8..a595a8c3f 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -78,13 +78,7 @@ (ptk/reify ::handle-drawing ptk/WatchEvent (watch [_ state stream] - (let [stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - (->> stream - (rx/filter #(= % :interrupt)))) - + (let [stopper (mse/drag-stopper stream) layout (get state :workspace-layout) zoom (dm/get-in state [:workspace-local :zoom] 1) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index 8a2194962..5c0d98898 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -28,11 +28,6 @@ (def simplify-tolerance 0.3) -(defn stopper-event? - [{:keys [type] :as event}] - (and (mse/mouse-event? event) - (= type :up))) - (defn- insert-point [point] (ptk/reify ::insert-point @@ -104,13 +99,13 @@ (ptk/reify ::handle-drawing ptk/WatchEvent (watch [_ _ stream] - (let [stopper (rx/filter stopper-event? stream) - mouse (rx/sample 10 ms/mouse-position) - shape (cts/setup-shape {:type :path - :initialized? true - :frame-id uuid/zero - :parent-id uuid/zero - :segments []})] + (let [stopper (mse/drag-stopper stream) + mouse (rx/sample 10 ms/mouse-position) + shape (cts/setup-shape {:type :path + :initialized? true + :frame-id uuid/zero + :parent-id uuid/zero + :segments []})] (rx/concat (rx/of #(update % :workspace-drawing assoc :object shape)) (->> mouse diff --git a/frontend/src/app/main/data/workspace/interactions.cljs b/frontend/src/app/main/data/workspace/interactions.cljs index 5708ca3c4..1aad31f2f 100644 --- a/frontend/src/app/main/data/workspace/interactions.cljs +++ b/frontend/src/app/main/data/workspace/interactions.cljs @@ -193,9 +193,7 @@ (watch [_ state stream] (let [initial-pos @ms/mouse-position selected (wsh/lookup-selected state) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?))] + stopper (mse/drag-stopper stream)] (when (= 1 (count selected)) (rx/concat (->> ms/mouse-position @@ -305,9 +303,7 @@ (watch [_ state stream] (let [initial-pos @ms/mouse-position selected (wsh/lookup-selected state) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?))] + stopper (mse/drag-stopper stream)] (when (= 1 (count selected)) (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) diff --git a/frontend/src/app/main/data/workspace/path/drawing.cljs b/frontend/src/app/main/data/workspace/path/drawing.cljs index af492bc0f..f536f3369 100644 --- a/frontend/src/app/main/data/workspace/path/drawing.cljs +++ b/frontend/src/app/main/data/workspace/path/drawing.cljs @@ -139,9 +139,7 @@ (rx/map #(drag-handler position idx prefix %)) (rx/take-until (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter helpers/end-path-event?)))))] @@ -166,9 +164,7 @@ ptk/WatchEvent (watch [_ state stream] (let [stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter helpers/end-path-event?))) @@ -197,9 +193,7 @@ (gpt/point? down-event)) (let [stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter helpers/end-path-event?))) diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs index 51d688707..164e37acb 100644 --- a/frontend/src/app/main/data/workspace/path/edition.cljs +++ b/frontend/src/app/main/data/workspace/path/edition.cljs @@ -150,9 +150,7 @@ (ptk/reify ::drag-selected-points ptk/WatchEvent (watch [_ state stream] - (let [stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (let [stopper (mse/drag-stopper stream) id (dm/get-in state [:workspace-local :edition]) @@ -279,9 +277,7 @@ (not alt?))))) (rx/take-until (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter streams/finish-edition?))))) diff --git a/frontend/src/app/main/data/workspace/path/selection.cljs b/frontend/src/app/main/data/workspace/path/selection.cljs index 028a6ec3b..b2256b3c9 100644 --- a/frontend/src/app/main/data/workspace/path/selection.cljs +++ b/frontend/src/app/main/data/workspace/path/selection.cljs @@ -10,7 +10,6 @@ [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] - [app.main.data.workspace.common :as dwc] [app.main.data.workspace.path.state :as st] [app.main.streams :as ms] [app.util.mouse :as mse] @@ -119,15 +118,9 @@ (ptk/reify ::handle-area-selection ptk/WatchEvent (watch [_ state stream] - (let [zoom (get-in state [:workspace-local :zoom] 1) - stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - (->> stream - (rx/filter dwc/interrupt?))) - - from-p @ms/mouse-position] + (let [zoom (get-in state [:workspace-local :zoom] 1) + stopper (mse/drag-stopper stream) + from-p @ms/mouse-position] (rx/concat (->> ms/mouse-position (rx/map #(grc/points->rect [from-p %])) diff --git a/frontend/src/app/main/data/workspace/path/streams.cljs b/frontend/src/app/main/data/workspace/path/streams.cljs index 9f55e92a0..38d0efd50 100644 --- a/frontend/src/app/main/data/workspace/path/streams.cljs +++ b/frontend/src/app/main/data/workspace/path/streams.cljs @@ -53,9 +53,7 @@ start (-> @ms/mouse-position to-pixel-snap) stopper (rx/merge - (->> st/stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper st/stream) (->> st/stream (rx/filter finish-edition?))) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 3f22275b9..ca4200c11 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -27,6 +27,7 @@ [app.main.data.modal :as md] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.collapse :as dwc] + [app.main.data.workspace.edition :as dwe] [app.main.data.workspace.libraries-helpers :as dwlh] [app.main.data.workspace.specialized-panel :as-alias dwsp] [app.main.data.workspace.state-helpers :as wsh] @@ -63,14 +64,8 @@ (ptk/reify ::handle-area-selection ptk/WatchEvent (watch [_ state stream] - (let [zoom (dm/get-in state [:workspace-local :zoom] 1) - stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - (->> stream - (rx/filter interrupt?))) - + (let [zoom (dm/get-in state [:workspace-local :zoom] 1) + stopper (mse/drag-stopper stream) init-position @ms/mouse-position init-selrect (grc/make-rect @@ -155,7 +150,7 @@ objects (wsh/lookup-page-objects state page-id)] (rx/of (dwc/expand-all-parents [id] objects) - :interrupt + (dwe/clear-edition-mode) ::dwsp/interrupt)))))) (defn select-prev-shape diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index fc8ee350d..c52cd2fbb 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -257,9 +257,7 @@ (watch [_ state stream] (let [initial-position @ms/mouse-position - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + stopper (mse/drag-stopper stream) layout (:workspace-layout state) page-id (:current-page-id state) focus (:workspace-focus-selected state) @@ -370,10 +368,7 @@ ptk/WatchEvent (watch [_ _ stream] - (let [stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - + (let [stopper (mse/drag-stopper stream) group (gsh/shapes->rect shapes) group-center (grc/rect->center group) initial-angle (gpt/angle @ms/mouse-position group-center) @@ -436,10 +431,7 @@ (watch [_ state stream] (let [initial (deref ms/mouse-position) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - + stopper (mse/drag-stopper stream) zoom (get-in state [:workspace-local :zoom] 1) ;; We toggle the selection so we don't have to wait for the event @@ -518,10 +510,7 @@ duplicate-move-started? (get-in state [:workspace-local :duplicate-move-started?] false) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - + stopper (mse/drag-stopper stream) layout (get state :workspace-layout) zoom (get-in state [:workspace-local :zoom] 1) focus (:workspace-focus-selected state) diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 1a8c45567..c2d4ab55b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -32,6 +32,7 @@ [app.util.dom :as dom] [app.util.globals :as globals] [app.util.keyboard :as kbd] + [app.util.mouse :as mse] [beicon.v2.core :as rx] [beicon.v2.operators :as rxo] [goog.events :as events] @@ -42,7 +43,8 @@ (let [on-key-down (actions/on-key-down) on-key-up (actions/on-key-up) on-mouse-wheel (actions/on-mouse-wheel zoom) - on-paste (actions/on-paste disable-paste in-viewport? workspace-read-only?)] + on-paste (actions/on-paste disable-paste in-viewport? workspace-read-only?) + on-blur (mf/use-fn #(st/emit! (mse/->BlurEvent)))] (mf/use-layout-effect (mf/deps on-key-down on-key-up on-mouse-wheel on-paste workspace-read-only?) @@ -52,7 +54,8 @@ ;; bind with passive=false to allow the event to be cancelled ;; https://stackoverflow.com/a/57582286/3219895 (events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false}) - (events/listen js/window EventType.PASTE on-paste)]] + (events/listen js/window EventType.PASTE on-paste) + (events/listen js/window EventType.BLUR on-blur)]] (fn [] (doseq [key keys] (events/unlistenByKey key)))))))) diff --git a/frontend/src/app/util/mouse.cljs b/frontend/src/app/util/mouse.cljs index b7771eba2..4576ed325 100644 --- a/frontend/src/app/util/mouse.cljs +++ b/frontend/src/app/util/mouse.cljs @@ -4,11 +4,14 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.util.mouse) +(ns app.util.mouse + (:require + [beicon.v2.core :as rx])) (defrecord MouseEvent [type ctrl shift alt meta]) (defrecord PointerEvent [source pt ctrl shift alt meta]) (defrecord ScrollEvent [point]) +(defrecord BlurEvent []) (defn mouse-event? [v] @@ -22,6 +25,10 @@ [v] (instance? ScrollEvent v)) +(defn blur-event? + [v] + (instance? BlurEvent v)) + (defn mouse-down-event? [^MouseEvent v] (= :down (.-type v))) @@ -61,3 +68,16 @@ (defn get-pointer-shift-mod [^PointerEvent ev] (.-shift ev)) + +(defn drag-stopper + "Creates a stream to stop drag events. Takes into account the mouse and also + if the window loses focus or the esc key is pressed." + [stream] + (rx/merge + (->> stream + (rx/filter blur-event?)) + (->> stream + (rx/filter mouse-event?) + (rx/filter mouse-up-event?)) + (->> stream + (rx/filter #(= % :interrupt))))) From b097f73b135e937ace9b4e7b24148cc5b6515f74 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 14:18:17 +0100 Subject: [PATCH 126/136] :bug: Fix problem with snap to frame guides --- frontend/src/app/worker/snaps.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/worker/snaps.cljs b/frontend/src/app/worker/snaps.cljs index ceecc5b89..77bf5d8f5 100644 --- a/frontend/src/app/worker/snaps.cljs +++ b/frontend/src/app/worker/snaps.cljs @@ -29,6 +29,7 @@ (let [match-bounds? (fn [[_ data]] (some #(or (= :guide (:type %)) + (= :layout (:type %)) (grc/contains-point? bounds (:pt %))) data))] (->> (into [] (comp (mapcat #(sd/query @state page-id frame-id axis %)) From 8850fd88948ce7aa622ee6bd707adbd740abfa10 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 14:52:38 +0100 Subject: [PATCH 127/136] :bug: Fix problem dragging in draft/projects screen --- frontend/src/app/main/ui/dashboard/grid.cljs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 6f5565611..276fa7ce4 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -419,8 +419,9 @@ on-drag-enter (mf/use-fn (fn [e] - (when (or (dnd/has-type? e "Files") - (dnd/has-type? e "application/x-moz-file")) + (when (and (not (dnd/has-type? e "penpot/files")) + (or (dnd/has-type? e "Files") + (dnd/has-type? e "application/x-moz-file"))) (dom/prevent-default e) (reset! dragging? true)))) @@ -440,8 +441,9 @@ on-drop (mf/use-fn (fn [e] - (when (or (dnd/has-type? e "Files") - (dnd/has-type? e "application/x-moz-file")) + (when (and (not (dnd/has-type? e "penpot/files")) + (or (dnd/has-type? e "Files") + (dnd/has-type? e "application/x-moz-file"))) (dom/prevent-default e) (reset! dragging? false) (import-files (.-files (.-dataTransfer e))))))] From db7ed75a91cedf12009d9b634c905fa2421d4e3c Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 15:02:29 +0100 Subject: [PATCH 128/136] :bug: Add mime-type otf to color picker --- common/src/app/common/media.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/app/common/media.cljc b/common/src/app/common/media.cljc index 212d43f2a..a342a227f 100644 --- a/common/src/app/common/media.cljc +++ b/common/src/app/common/media.cljc @@ -10,7 +10,7 @@ [cuerdas.core :as str])) ;; We have added ".ttf" as string to solve a problem with chrome input selector -(def valid-font-types #{"font/ttf", ".ttf", "font/woff", "application/font-woff", "font/otf"}) +(def valid-font-types #{"font/ttf" ".ttf" "font/woff", "application/font-woff" "woff" "font/otf" ".otf" "font/opentype"}) (def valid-image-types #{"image/jpeg", "image/png", "image/webp", "image/gif", "image/svg+xml"}) (def str-image-types (str/join "," valid-image-types)) (def str-font-types (str/join "," valid-font-types)) From dd69762b311b6c4d3e918966f6f7d491da7a68e1 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 15:13:57 +0100 Subject: [PATCH 129/136] :bug: Fix problem with dismiss fonts --- frontend/src/app/main/ui/dashboard/fonts.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index 17aa4a8d4..be6cd908f 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -161,7 +161,7 @@ (mf/use-fn (mf/deps fonts) (fn [_] - (run! on-delete (vals fonts))))] + (run! #(swap! fonts* dissoc (:id %)) (vals fonts))))] [:div {:class (stl/css :dashboard-fonts-upload)} [:div {:class (stl/css :dashboard-fonts-hero)} From dc7d279e9dd803cd580270e66caa2ac298c59eb4 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 15:33:51 +0100 Subject: [PATCH 130/136] :bug: Fix problem with interactions over frames --- frontend/src/app/main/ui/viewer/shapes.cljs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 6a739d320..5832f28ce 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -265,8 +265,7 @@ (mf/defc interaction [{:keys [shape interactions interactions-show?]}] - (let [{:keys [x y width height]} (:selrect shape) - frame? (= :frame (:type shape))] + (let [{:keys [x y width height]} (:selrect shape)] (when-not (empty? interactions) [:rect {:x (- x 1) :y (- y 1) @@ -276,7 +275,6 @@ :stroke "var(--color-accent-tertiary)" :stroke-width (if interactions-show? 1 0) :fill-opacity (if interactions-show? 0.2 0) - :style {:pointer-events (when frame? "none")} :transform (gsh/transform-str shape)}]))) From 8e7471509cb4c267e23d15089bd70f8e074ede63 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 15:54:40 +0100 Subject: [PATCH 131/136] :bug: Fix problem on modal transfer owner --- frontend/src/app/main/ui/dashboard/change_owner.cljs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/change_owner.cljs b/frontend/src/app/main/ui/dashboard/change_owner.cljs index 0af37045d..b3a8e04d2 100644 --- a/frontend/src/app/main/ui/dashboard/change_owner.cljs +++ b/frontend/src/app/main/ui/dashboard/change_owner.cljs @@ -29,10 +29,13 @@ members-map (mf/deref refs/dashboard-team-members) members (vals members-map) - options (into [{:value "" - :label (tr "modals.leave-and-reassign.select-member-to-promote")}] - (filter #(not= (:label %) (:fullname profile)) - (map #(hash-map :label (:name %) :value (str (:id %))) members))) + options + (into [{:value "" + :label (tr "modals.leave-and-reassign.select-member-to-promote")}] + (comp + (filter #(not= (:email %) (:email profile))) + (map #(hash-map :label (:name %) :value (str (:id %))))) + members) on-cancel #(st/emit! (modal/hide)) on-accept From cdab615cbb3f6b90d5c60ec6de90cdc7127a304e Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 14 Mar 2024 14:12:58 +0100 Subject: [PATCH 132/136] :bug: Fix copies of snap to grid and show hide grid --- .../src/app/main/data/workspace/layout.cljs | 13 +-- .../app/main/data/workspace/shortcuts.cljs | 92 +++++++++---------- frontend/src/app/main/snap.cljs | 6 +- frontend/src/app/main/ui/dashboard.scss | 1 + .../src/app/main/ui/workspace/main_menu.cljs | 36 ++++---- .../main/ui/workspace/sidebar/shortcuts.cljs | 6 +- .../src/app/main/ui/workspace/viewport.cljs | 4 +- frontend/translations/ar.po | 22 ----- frontend/translations/ca.po | 25 ----- frontend/translations/cs.po | 25 ----- frontend/translations/de.po | 25 ----- frontend/translations/el.po | 16 ---- frontend/translations/en.po | 38 ++++---- frontend/translations/es.po | 36 ++++---- frontend/translations/eu.po | 28 ------ frontend/translations/fa.po | 4 - frontend/translations/fr.po | 25 ----- frontend/translations/ha.po | 25 ----- frontend/translations/he.po | 25 ----- frontend/translations/hr.po | 29 ------ frontend/translations/id.po | 25 ----- frontend/translations/lv.po | 25 ----- frontend/translations/nb_NO.po | 8 -- frontend/translations/nl.po | 25 ----- frontend/translations/pl.po | 25 ----- frontend/translations/pt_BR.po | 25 ----- frontend/translations/pt_PT.po | 25 ----- frontend/translations/ro.po | 25 ----- frontend/translations/ru.po | 19 ---- frontend/translations/tr.po | 25 ----- frontend/translations/zh_CN.po | 25 ----- frontend/translations/zh_Hant.po | 3 - 32 files changed, 117 insertions(+), 619 deletions(-) diff --git a/frontend/src/app/main/data/workspace/layout.cljs b/frontend/src/app/main/data/workspace/layout.cljs index 24cfc6779..66eb0605a 100644 --- a/frontend/src/app/main/data/workspace/layout.cljs +++ b/frontend/src/app/main/data/workspace/layout.cljs @@ -23,12 +23,12 @@ :colorpalette :element-options :rulers - :display-grid - :snap-grid + :display-guides + :snap-guides :scale-text :dynamic-alignment :display-artboard-names - :snap-guides + :snap-ruler-guides :show-pixel-grid :snap-pixel-grid}) @@ -53,11 +53,11 @@ :layers :element-options :rulers - :display-grid - :snap-grid + :display-guides + :snap-guides :dynamic-alignment :display-artboard-names - :snap-guides + :snap-ruler-guides :show-pixel-grid :snap-pixel-grid}) @@ -89,6 +89,7 @@ (update [_ state] (update state :workspace-layout (fn [flags] + (prn flags) (if force? (conj flags flag) (if (contains? flags flag) diff --git a/frontend/src/app/main/data/workspace/shortcuts.cljs b/frontend/src/app/main/data/workspace/shortcuts.cljs index 66ad43b6e..b8d10264d 100644 --- a/frontend/src/app/main/data/workspace/shortcuts.cljs +++ b/frontend/src/app/main/data/workspace/shortcuts.cljs @@ -364,19 +364,12 @@ :subsections [:main-menu] :fn #(st/emit! (dw/select-all))} - :toggle-grid {:tooltip (ds/meta "'") + :toggle-guides {:tooltip (ds/meta "'") ;;https://github.com/ccampbell/mousetrap/issues/85 :command [(ds/c-mod "'") (ds/c-mod "219")] :show-command (ds/c-mod "'") :subsections [:main-menu] - :fn #(st/emit! (toggle-layout-flag :display-grid))} - - :toggle-snap-grid {:tooltip (ds/meta-shift "'") - ;;https://github.com/ccampbell/mousetrap/issues/85 - :command [(ds/c-mod "shift+'") (ds/c-mod "shift+219")] - :show-command (ds/c-mod "shift+'") - :subsections [:main-menu] - :fn #(st/emit! (toggle-layout-flag :snap-grid))} + :fn #(st/emit! (toggle-layout-flag :display-guides))} :toggle-alignment {:tooltip (ds/meta "\\") :command (ds/c-mod "\\") @@ -404,10 +397,17 @@ :fn #(st/emit! (de/show-workspace-export-dialog))} - :toggle-snap-guide {:tooltip (ds/meta-shift "G") - :command (ds/c-mod "shift+g") - :subsections [:main-menu] - :fn #(st/emit! (toggle-layout-flag :snap-guides))} + :toggle-snap-ruler-guide {:tooltip (ds/meta-shift "G") + :command (ds/c-mod "shift+g") + :subsections [:main-menu] + :fn #(st/emit! (toggle-layout-flag :snap-ruler-guides))} + + :toggle-snap-guides {:tooltip (ds/meta-shift "'") + ;;https://github.com/ccampbell/mousetrap/issues/85 + :command [(ds/c-mod "shift+'") (ds/c-mod "shift+219")] + :show-command (ds/c-mod "shift+'") + :subsections [:main-menu] + :fn #(st/emit! (toggle-layout-flag :snap-guides))} :show-shortcuts {:tooltip "?" :command "?" @@ -416,34 +416,34 @@ ;; PANELS - :toggle-layers {:tooltip (ds/alt "L") - :command (ds/a-mod "l") - :subsections [:panels] - :fn #(st/emit! (dw/go-to-layout :layers))} + :toggle-layers {:tooltip (ds/alt "L") + :command (ds/a-mod "l") + :subsections [:panels] + :fn #(st/emit! (dw/go-to-layout :layers))} - :toggle-assets {:tooltip (ds/alt "I") - :command (ds/a-mod "i") - :subsections [:panels] - :fn #(st/emit! (dw/go-to-layout :assets))} + :toggle-assets {:tooltip (ds/alt "I") + :command (ds/a-mod "i") + :subsections [:panels] + :fn #(st/emit! (dw/go-to-layout :assets))} - :toggle-history {:tooltip (ds/alt "H") - :command (ds/a-mod "h") - :subsections [:panels] - :fn #(emit-when-no-readonly (dw/go-to-layout :document-history))} + :toggle-history {:tooltip (ds/alt "H") + :command (ds/a-mod "h") + :subsections [:panels] + :fn #(emit-when-no-readonly (dw/go-to-layout :document-history))} - :toggle-colorpalette {:tooltip (ds/alt "P") - :command (ds/a-mod "p") - :subsections [:panels] - :fn #(do (r/set-resize-type! :bottom) - (emit-when-no-readonly (dw/remove-layout-flag :textpalette) - (toggle-layout-flag :colorpalette)))} + :toggle-colorpalette {:tooltip (ds/alt "P") + :command (ds/a-mod "p") + :subsections [:panels] + :fn #(do (r/set-resize-type! :bottom) + (emit-when-no-readonly (dw/remove-layout-flag :textpalette) + (toggle-layout-flag :colorpalette)))} - :toggle-textpalette {:tooltip (ds/alt "T") - :command (ds/a-mod "t") - :subsections [:panels] - :fn #(do (r/set-resize-type! :bottom) - (emit-when-no-readonly (dw/remove-layout-flag :colorpalette) - (toggle-layout-flag :textpalette)))} + :toggle-textpalette {:tooltip (ds/alt "T") + :command (ds/a-mod "t") + :subsections [:panels] + :fn #(do (r/set-resize-type! :bottom) + (emit-when-no-readonly (dw/remove-layout-flag :colorpalette) + (toggle-layout-flag :textpalette)))} :hide-ui {:tooltip "\\" :command "\\" @@ -482,10 +482,10 @@ :subsections [:zoom-workspace] :fn identity} - :zoom-lense-decrease {:tooltip (ds/alt "Z") - :command "alt+z" - :subsections [:zoom-workspace] - :fn identity} + :zoom-lense-decrease {:tooltip (ds/alt "Z") + :command "alt+z" + :subsections [:zoom-workspace] + :fn identity} ;; NAVIGATION @@ -553,11 +553,11 @@ :fn #(emit-when-no-readonly (dp/open-preview-selected))} ;; THEME - :toggle-theme {:tooltip (ds/alt "M") - :command (ds/a-mod "m") - :subsections [:basics] - :fn #(st/emit! (with-meta (du/toggle-theme) - {::ev/origin "workspace:shortcut"}))}}) + :toggle-theme {:tooltip (ds/alt "M") + :command (ds/a-mod "m") + :subsections [:basics] + :fn #(st/emit! (with-meta (du/toggle-theme) + {::ev/origin "workspace:shortcut"}))}}) (def opacity-shortcuts (into {} (->> diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index 5e8f14431..d5ec5a6cf 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -40,14 +40,14 @@ (fn [{:keys [type id frame-id]}] (cond (= type :layout) - (or (not (contains? layout :display-grid)) - (not (contains? layout :snap-grid)) + (or (not (contains? layout :display-guides)) + (not (contains? layout :snap-guides)) (and (d/not-empty? focus) (not (contains? focus id)))) (= type :guide) (or (not (contains? layout :rulers)) - (not (contains? layout :snap-guides)) + (not (contains? layout :snap-ruler-guides)) (and (d/not-empty? focus) (not (contains? focus frame-id)))) diff --git a/frontend/src/app/main/ui/dashboard.scss b/frontend/src/app/main/ui/dashboard.scss index ed79f5362..96db3bf55 100644 --- a/frontend/src/app/main/ui/dashboard.scss +++ b/frontend/src/app/main/ui/dashboard.scss @@ -7,6 +7,7 @@ @use "refactor/common-refactor.scss" as *; .dashboard { + @extend .new-scrollbar; background-color: var(--app-background); display: grid; grid-template-columns: $s-40 $s-256 1fr; diff --git a/frontend/src/app/main/ui/workspace/main_menu.cljs b/frontend/src/app/main/ui/workspace/main_menu.cljs index 9c6c83418..d144706c3 100644 --- a/frontend/src/app/main/ui/workspace/main_menu.cljs +++ b/frontend/src/app/main/ui/workspace/main_menu.cljs @@ -192,15 +192,15 @@ :on-key-down (fn [event] (when (kbd/enter? event) (toggle-flag event))) - :data-test "snap-guides" - :id "file-menu-snap-guides"} + :data-test "snap-ruler-guides" + :id "file-menu-snap-ruler-guides"} [:span {:class (stl/css :item-name)} - (if (contains? layout :snap-guides) - (tr "workspace.header.menu.disable-snap-guides") - (tr "workspace.header.menu.enable-snap-guides"))] + (if (contains? layout :snap-ruler-guides) + (tr "workspace.header.menu.disable-snap-ruler-guides") + (tr "workspace.header.menu.enable-snap-ruler-guides"))] [:span {:class (stl/css :shortcut)} - (for [sc (scd/split-sc (sc/get-tooltip :toggle-snap-guide))] + (for [sc (scd/split-sc (sc/get-tooltip :toggle-snap-ruler-guide))] [:span {:class (stl/css :shortcut-key) :key sc} sc])]] [:> dropdown-menu-item* {:on-click toggle-flag @@ -208,14 +208,14 @@ :on-key-down (fn [event] (when (kbd/enter? event) (toggle-flag event))) - :data-test "snap-grid" - :id "file-menu-snap-grid"} + :data-test "snap-guides" + :id "file-menu-snap-guides"} [:span {:class (stl/css :item-name)} - (if (contains? layout :snap-grid) - (tr "workspace.header.menu.disable-snap-grid") - (tr "workspace.header.menu.enable-snap-grid"))] + (if (contains? layout :snap-guides) + (tr "workspace.header.menu.disable-snap-guides") + (tr "workspace.header.menu.enable-snap-guides"))] [:span {:class (stl/css :shortcut)} - (for [sc (scd/split-sc (sc/get-tooltip :toggle-snap-grid))] + (for [sc (scd/split-sc (sc/get-tooltip :toggle-snap-guides))] [:span {:class (stl/css :shortcut-key) :key sc} sc])]] [:> dropdown-menu-item* {:on-click toggle-flag @@ -321,14 +321,14 @@ :on-key-down (fn [event] (when (kbd/enter? event) (toggle-flag event))) - :data-test "display-grid" - :id "file-menu-grid"} + :data-test "display-guides" + :id "file-menu-guides"} [:span {:class (stl/css :item-name)} - (if (contains? layout :display-grid) - (tr "workspace.header.menu.hide-grid") - (tr "workspace.header.menu.show-grid"))] + (if (contains? layout :display-guides) + (tr "workspace.header.menu.hide-guides") + (tr "workspace.header.menu.show-guides"))] [:span {:class (stl/css :shortcut)} - (for [sc (scd/split-sc (sc/get-tooltip :toggle-grid))] + (for [sc (scd/split-sc (sc/get-tooltip :toggle-guides))] [:span {:class (stl/css :shortcut-key) :key sc} sc])]] diff --git a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs index f9499f91e..4fde27d0c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs @@ -171,15 +171,15 @@ ;; shortcuts.toggle-assets ;; shortcuts.toggle-colorpalette ;; shortcuts.toggle-focus-mode - ;; shortcuts.toggle-grid + ;; shortcuts.toggle-guides ;; shortcuts.toggle-history ;; shortcuts.toggle-layers ;; shortcuts.toggle-lock ;; shortcuts.toggle-lock-size ;; shortcuts.toggle-rules ;; shortcuts.scale - ;; shortcuts.toggle-snap-grid - ;; shortcuts.toggle-snap-guide + ;; shortcuts.toggle-snap-guides + ;; shortcuts.toggle-snap-ruler-guide ;; shortcuts.toggle-textpalette ;; shortcuts.toggle-visibility ;; shortcuts.toggle-zoom-style diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 0894f0b84..2a808e627 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -200,7 +200,7 @@ show-cursor-tooltip? tooltip show-draw-area? drawing-obj show-gradient-handlers? (= (count selected) 1) - show-grids? (contains? layout :display-grid) + show-grids? (contains? layout :display-guides) show-frame-outline? (= transform :move) show-outlines? (and (nil? transform) @@ -223,7 +223,7 @@ (= transform :move) (seq selected)) show-snap-points? (and (or (contains? layout :dynamic-alignment) - (contains? layout :snap-grid)) + (contains? layout :snap-guides)) (or drawing-obj transform)) show-selrect? (and selrect (empty? drawing) (not text-editing?)) show-measures? (and (not transform) diff --git a/frontend/translations/ar.po b/frontend/translations/ar.po index b455dde95..9bc152ac5 100644 --- a/frontend/translations/ar.po +++ b/frontend/translations/ar.po @@ -2534,10 +2534,6 @@ msgstr "إبطال المحاذاة الدينماكية" msgid "workspace.header.menu.disable-scale-text" msgstr "إبطال المقياس النسبي" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "إبطال الفرقعة للتشبيك" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-dynamic-alignment" msgstr "تككين المحاذاة الدينماكية" @@ -2546,14 +2542,6 @@ msgstr "تككين المحاذاة الدينماكية" msgid "workspace.header.menu.enable-scale-text" msgstr "تمكين نص المقياس" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "الفرقعة للتشبيك" - -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "إخفاء التشبيك" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "إخفاء لون اللوحة" @@ -2566,10 +2554,6 @@ msgstr "إخفاء المسطرات" msgid "workspace.header.menu.select-all" msgstr "حدد الجميع" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "أظهر التشبيك" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "أظهر لون اللوحة" @@ -3742,9 +3726,6 @@ msgstr "أصل الرسومات" msgid "workspace.options.layout.packed" msgstr "معباة" -msgid "shortcuts.toggle-snap-guide" -msgstr "تبديل الفرقعة للمرشد" - msgid "workspace.header.menu.enable-snap-pixel-grid" msgstr "تمكين الفرقعة للبكسل" @@ -4198,9 +4179,6 @@ msgstr "أقصى ارتفاع" msgid "workspace.shape.menu.restore-main" msgstr "استعادة العنصر الرئيسي" -msgid "shortcuts.toggle-snap-grid" -msgstr "تبديل الفرقعة للتشبيك" - #: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs msgid "workspace.options.layer-options.blend-mode.saturation" msgstr "التشبع" diff --git a/frontend/translations/ca.po b/frontend/translations/ca.po index a71c294e8..b75496da4 100644 --- a/frontend/translations/ca.po +++ b/frontend/translations/ca.po @@ -2242,9 +2242,6 @@ msgstr "Activa/desactiva el mode de concentració" msgid "shortcuts.toggle-fullscreen" msgstr "Activa/desactiva la pantalla completa" -msgid "shortcuts.toggle-grid" -msgstr "Mostra/Amaga la graella" - msgid "shortcuts.toggle-history" msgstr "Mostra/Amaga l'historial" @@ -2260,12 +2257,6 @@ msgstr "Bloqueja les proporcions" msgid "shortcuts.toggle-rules" msgstr "Mostra/Amaga les regles" -msgid "shortcuts.toggle-snap-grid" -msgstr "Ajusta a la graella" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Ajusta a les guies" - msgid "shortcuts.toggle-textpalette" msgstr "Mostra/amaga la paleta de text" @@ -2594,10 +2585,6 @@ msgstr "Desactiva l'alineació dinàmica" msgid "workspace.header.menu.disable-scale-text" msgstr "Desactiva l'escalat del text" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "No ajustis a la quadrícula" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "No ajustis a les guies" @@ -2613,10 +2600,6 @@ msgstr "Activa l'alineació dinàmica" msgid "workspace.header.menu.enable-scale-text" msgstr "Activa l'escalat del text" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Ajusta a la quadrícula" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Ajusta a les guies" @@ -2628,10 +2611,6 @@ msgstr "Ajusta als píxels" msgid "workspace.header.menu.hide-artboard-names" msgstr "Amaga els noms dels taulers" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Amaga la quadrícula" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Amaga la paleta de colors" @@ -2675,10 +2654,6 @@ msgstr "Selecciona-ho tot" msgid "workspace.header.menu.show-artboard-names" msgstr "Mostra els noms dels taulers" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Mostra la quadrícula" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Mostra la paleta de colors" diff --git a/frontend/translations/cs.po b/frontend/translations/cs.po index 8fd299f42..b2f2225f4 100644 --- a/frontend/translations/cs.po +++ b/frontend/translations/cs.po @@ -2556,9 +2556,6 @@ msgstr "Přepnout režim soustředění" msgid "shortcuts.toggle-fullscreen" msgstr "Přepnout zobrazení na celou obrazovku" -msgid "shortcuts.toggle-grid" -msgstr "Zobrazit/skrýt mřížku" - msgid "shortcuts.toggle-history" msgstr "Přepnout historii" @@ -2577,12 +2574,6 @@ msgstr "Uzamknout proporce" msgid "shortcuts.toggle-rules" msgstr "Zobrazit/skrýt pravítka" -msgid "shortcuts.toggle-snap-grid" -msgstr "Přichytit k mřížce" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Přichytit k vodicím lištám" - msgid "shortcuts.toggle-textpalette" msgstr "Přepnout paletu textu" @@ -2940,10 +2931,6 @@ msgstr "Zakázat proporcionální měřítko" msgid "workspace.header.menu.disable-scale-text" msgstr "Zakázat měřítko textu" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Zakázat přichycení k mřížce" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Zakázat přichycení k vodicím lištám" @@ -2962,10 +2949,6 @@ msgstr "Povolit proporcionální měřítko" msgid "workspace.header.menu.enable-scale-text" msgstr "Povolit měřítko textu" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Přichytit k mřížce" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Přichytit k vodicím lištám" @@ -2977,10 +2960,6 @@ msgstr "Povolit přichycení k pixelu" msgid "workspace.header.menu.hide-artboard-names" msgstr "Skrýt názvy tabulí" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Skrýt mřížky" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Skrýt paletu barev" @@ -3027,10 +3006,6 @@ msgstr "Vybrat vše" msgid "workspace.header.menu.show-artboard-names" msgstr "Zobrazit názvy tabulí" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Zobrazit mřížku" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Zobrazit paletu barev" diff --git a/frontend/translations/de.po b/frontend/translations/de.po index 3a5d167b0..fe563da32 100644 --- a/frontend/translations/de.po +++ b/frontend/translations/de.po @@ -2777,9 +2777,6 @@ msgstr "Fokusmodus umschalten" msgid "shortcuts.toggle-fullscreen" msgstr "Vollbild aktivieren/deaktivieren" -msgid "shortcuts.toggle-grid" -msgstr "Raster ein-/ausblenden" - msgid "shortcuts.toggle-history" msgstr "Verlauf ein-/ausblenden" @@ -2798,12 +2795,6 @@ msgstr "Seitenverhältnis sperren/entsperren" msgid "shortcuts.toggle-rules" msgstr "Lineale ein-/ausblenden" -msgid "shortcuts.toggle-snap-grid" -msgstr "Am Raster ausrichten" - -msgid "shortcuts.toggle-snap-guide" -msgstr "An Hilfslinien ausrichten" - msgid "shortcuts.toggle-textpalette" msgstr "Textpalette ein-/ausblenden" @@ -3173,10 +3164,6 @@ msgstr "Proportionale Skalierung deaktivieren" msgid "workspace.header.menu.disable-scale-text" msgstr "Textskalierung deaktivieren" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Am Raster ausrichten deaktivieren" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Ausrichten an Hilfslinien deaktivieren" @@ -3195,10 +3182,6 @@ msgstr "Proportionale Skalierung aktivieren" msgid "workspace.header.menu.enable-scale-text" msgstr "Textskalierung aktivieren" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Am Raster ausrichten" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "An Hilfslinien ausrichten" @@ -3210,10 +3193,6 @@ msgstr "Ausrichten am Pixel aktivieren" msgid "workspace.header.menu.hide-artboard-names" msgstr "Namen von Zeichenflächen ausblenden" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Raster ausblenden" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Farbpalette ausblenden" @@ -3260,10 +3239,6 @@ msgstr "Alles auswählen" msgid "workspace.header.menu.show-artboard-names" msgstr "Namen der Zeichenflächen anzeigen" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Raster einblenden" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Farbpalette einblenden" diff --git a/frontend/translations/el.po b/frontend/translations/el.po index d8c1acc11..cc62a2301 100644 --- a/frontend/translations/el.po +++ b/frontend/translations/el.po @@ -1348,22 +1348,10 @@ msgstr "Ακτινική κλίση" msgid "workspace.header.menu.disable-dynamic-alignment" msgstr "Απενεργοποίηση δυναμικής ευθυγράμμισης" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Απενεργοποιήστε τη σύνδεση στο πλέγμα" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-dynamic-alignment" msgstr "Ενεργοποίηση δυναμικής ευθυγράμμισης" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Σύνδεση στο πλέγμα" - -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Απόκρυψη πλεγμάτων" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Απόκρυψη παλέτας χρωμάτων" @@ -1376,10 +1364,6 @@ msgstr "Απόκρυψη κανόνες" msgid "workspace.header.menu.select-all" msgstr "Επιλογή όλων" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Εμφάνιση πλέγματος" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Εμφάνιση παλέτας χρωμάτων" diff --git a/frontend/translations/en.po b/frontend/translations/en.po index a894c3360..fa989a0c7 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -2949,8 +2949,8 @@ msgstr "Toggle focus mode" msgid "shortcuts.toggle-fullscreen" msgstr "Toggle fullscreen" -msgid "shortcuts.toggle-grid" -msgstr "Show / Hide grid" +msgid "shortcuts.toggle-guides" +msgstr "Show / Hide guides" msgid "shortcuts.toggle-history" msgstr "Toggle history" @@ -2967,18 +2967,18 @@ msgstr "Lock / Unlock" msgid "shortcuts.toggle-lock-size" msgstr "Lock proportions" -msgid "shortcuts.toggle-rules" +msgid "shortcuts.toggle-rulers" msgstr "Show / Hide rulers" msgid "shortcuts.scale" msgstr "Scale" -msgid "shortcuts.toggle-snap-grid" -msgstr "Snap to grid" - -msgid "shortcuts.toggle-snap-guide" +msgid "shortcuts.toggle-snap-guides" msgstr "Snap to guides" +msgid "shortcuts.toggle-snap-ruler-guide" +msgstr "Snap to ruler guides" + msgid "shortcuts.toggle-textpalette" msgstr "Toggle text palette" @@ -3339,14 +3339,14 @@ msgstr "Disable proportional scale" msgid "workspace.header.menu.disable-scale-text" msgstr "Disable scale text" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Disable snap to grid" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Disable snap to guides" +#: src/app/main/ui/workspace/header.cljs +msgid "workspace.header.menu.disable-snap-ruler-guides" +msgstr "Disable snap to ruler guides" + msgid "workspace.header.menu.disable-snap-pixel-grid" msgstr "Disable snap to pixel" @@ -3361,14 +3361,14 @@ msgstr "Enable proportional scale" msgid "workspace.header.menu.enable-scale-text" msgstr "Enable scale text" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Snap to grid" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Snap to guides" +#: src/app/main/ui/workspace/header.cljs +msgid "workspace.header.menu.enable-snap-ruler-guides" +msgstr "Snap to ruler guides" + msgid "workspace.header.menu.enable-snap-pixel-grid" msgstr "Enable snap to pixel" @@ -3377,8 +3377,8 @@ msgid "workspace.header.menu.hide-artboard-names" msgstr "Hide board names" #: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Hide grids" +msgid "workspace.header.menu.hide-guides" +msgstr "Hide guides" #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" @@ -3427,8 +3427,8 @@ msgid "workspace.header.menu.show-artboard-names" msgstr "Show boards names" #: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Show grid" +msgid "workspace.header.menu.show-guides" +msgstr "Show guides" #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 8d9831183..73140e72c 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -2995,8 +2995,8 @@ msgstr "Mostrar/ocultar focus mode" msgid "shortcuts.toggle-fullscreen" msgstr "Activar/desactivar pantalla completa" -msgid "shortcuts.toggle-grid" -msgstr "Mostrar/ocultar rejilla" +msgid "shortcuts.toggle-guides" +msgstr "Mostrar/ocultar guías" msgid "shortcuts.toggle-history" msgstr "Mostrar/ocultar histórico" @@ -3013,17 +3013,17 @@ msgstr "Bloquear/Desbloquear" msgid "shortcuts.toggle-lock-size" msgstr "Bloquear/Desbloquear proporciones" -msgid "shortcuts.toggle-rules" +msgid "shortcuts.toggle-rulers" msgstr "Mostrar/ocultar reglas" msgid "shortcuts.scale" msgstr "Escalado" -msgid "shortcuts.toggle-snap-grid" -msgstr "Alinear a la rejilla" +msgid "shortcuts.toggle-snap-guides" +msgstr "Alinear a las guías" -msgid "shortcuts.toggle-snap-guide" -msgstr "Alinear a las guias" +msgid "shortcuts.toggle-snap-ruler-guide" +msgstr "Alinear a las guías de reglas" msgid "shortcuts.toggle-textpalette" msgstr "Mostrar/ocultar paleta de textos" @@ -3401,14 +3401,14 @@ msgstr "Desactivar escala proporcional" msgid "workspace.header.menu.disable-scale-text" msgstr "Desactivar escalar texto" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Desactivar alinear a la rejilla" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Desactivar alinear a las guias" +#: src/app/main/ui/workspace/header.cljs +msgid "workspace.header.menu.disable-snap-ruler-guides" +msgstr "Desactivar alinear a las guias de reglas" + msgid "workspace.header.menu.disable-snap-pixel-grid" msgstr "Desactivar ajuste al pixel" @@ -3423,14 +3423,14 @@ msgstr "Activar escala proporcional" msgid "workspace.header.menu.enable-scale-text" msgstr "Activar escalar texto" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Alinear a la rejilla" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Alinear a las guias" +#: src/app/main/ui/workspace/header.cljs +msgid "workspace.header.menu.enable-snap-ruler-guides" +msgstr "Alinear a las guias de reglas" + msgid "workspace.header.menu.enable-snap-pixel-grid" msgstr "Activar ajuste al pixel" @@ -3439,8 +3439,8 @@ msgid "workspace.header.menu.hide-artboard-names" msgstr "Ocultar nombres de tableros" #: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Ocultar rejillas" +msgid "workspace.header.menu.hide-guides" +msgstr "Ocultar guías" #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" @@ -3489,7 +3489,7 @@ msgid "workspace.header.menu.show-artboard-names" msgstr "Mostrar nombres de tableros" #: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" +msgid "workspace.header.menu.show-g" msgstr "Mostrar rejilla" #: src/app/main/ui/workspace/header.cljs diff --git a/frontend/translations/eu.po b/frontend/translations/eu.po index 5be03e1d3..9436e9d85 100644 --- a/frontend/translations/eu.po +++ b/frontend/translations/eu.po @@ -2553,9 +2553,6 @@ msgstr "Erakutsi/ezkutatu foko-modua" msgid "shortcuts.toggle-fullscreen" msgstr "Aktibatu/desaktibatu pantaila osoa" -msgid "shortcuts.toggle-grid" -msgstr "Erakutsi/ezkutatu sarea" - msgid "shortcuts.toggle-history" msgstr "Erakutsi/Ezkutatu historikoa" @@ -2574,12 +2571,6 @@ msgstr "Blokeatu/Desblokeatu proportzioak" msgid "shortcuts.toggle-rules" msgstr "Erakutsi/ezkutatu erregelak" -msgid "shortcuts.toggle-snap-grid" -msgstr "Lerrokatu sarera" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Lerroatu gidetara" - msgid "shortcuts.toggle-textpalette" msgstr "Erakutsi/Ezkutatu testuen paleta" @@ -2938,10 +2929,6 @@ msgstr "Desaktibatu eskala proportzionala" msgid "workspace.header.menu.disable-scale-text" msgstr "Desaktibatu testu eskala" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Desaktibatu sarera atxikitzea" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Desaktibatu gidetara atxikitzea" @@ -2960,10 +2947,6 @@ msgstr "Aktibatu eskala proportzionala" msgid "workspace.header.menu.enable-scale-text" msgstr "Aktibatu testua eskalatzea" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Atxikitu sarera" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Atxikitu gidetara" @@ -2975,10 +2958,6 @@ msgstr "Aktibatu pixelera atxikitzea" msgid "workspace.header.menu.hide-artboard-names" msgstr "Ezkutatu arbelen izenak" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Ezkutatu saretak" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Ezkutatu kolore-paleta" @@ -3025,17 +3004,10 @@ msgstr "Guztiak aukeratu" msgid "workspace.header.menu.show-artboard-names" msgstr "Erakutsi arbelen izenak" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Erakutsi sareta" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Erakutsi kolore-paleta" -msgid "workspace.header.menu.show-pixel-grid" -msgstr "Erakutsi pixelen sarea" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-rules" msgstr "Erakutsi erregelak" diff --git a/frontend/translations/fa.po b/frontend/translations/fa.po index e93886d64..f010b9a74 100644 --- a/frontend/translations/fa.po +++ b/frontend/translations/fa.po @@ -1876,10 +1876,6 @@ msgstr "انتقال" msgid "shortcuts.paste" msgstr "چسباندن" -#, fuzzy -msgid "shortcuts.toggle-grid" -msgstr "نمایش/پنهان کردن شبکه‌بندی" - msgid "shortcuts.toggle-rules" msgstr "نمایش/پنهان کردن خط‌کش‌ها" diff --git a/frontend/translations/fr.po b/frontend/translations/fr.po index 9c0f87d06..87d06e573 100644 --- a/frontend/translations/fr.po +++ b/frontend/translations/fr.po @@ -2771,9 +2771,6 @@ msgstr "Activer/désactiver le mode focus" msgid "shortcuts.toggle-fullscreen" msgstr "Activer/désactiver le plein écran" -msgid "shortcuts.toggle-grid" -msgstr "Afficher/masquer la grille" - msgid "shortcuts.toggle-history" msgstr "Activer/désactiver l'historique" @@ -2792,12 +2789,6 @@ msgstr "Verrouiller les proportions" msgid "shortcuts.toggle-rules" msgstr "Afficher/masquer les règles" -msgid "shortcuts.toggle-snap-grid" -msgstr "Aligner sur la grille" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Aligner sur les guides" - msgid "shortcuts.toggle-textpalette" msgstr "Afficher/masquer la palette de texte" @@ -3136,10 +3127,6 @@ msgstr "Désactiver l’alignement dynamique" msgid "workspace.header.menu.disable-scale-text" msgstr "Désactiver la mise à l'échelle du texte" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Désactiver l’alignement sur la grille" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Désactiver l’alignement sur les guides" @@ -3155,10 +3142,6 @@ msgstr "Activer l’alignement dynamique" msgid "workspace.header.menu.enable-scale-text" msgstr "Activer le redimensionnement du texte" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Aligner sur la grille" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Aligner sur les guides" @@ -3170,10 +3153,6 @@ msgstr "Activer l’alignement au pixel" msgid "workspace.header.menu.hide-artboard-names" msgstr "Masquer le nom des plans de travail" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Masquer la grille" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Masquer la palette de couleurs" @@ -3217,10 +3196,6 @@ msgstr "Tout sélectionner" msgid "workspace.header.menu.show-artboard-names" msgstr "Afficher le nom des plans de travail" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Montrer la grille" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Montrer la palette de couleurs" diff --git a/frontend/translations/ha.po b/frontend/translations/ha.po index 5f2773ae9..27661a3aa 100644 --- a/frontend/translations/ha.po +++ b/frontend/translations/ha.po @@ -1908,10 +1908,6 @@ msgstr "kulle" msgid "labels.help-center" msgstr "sashen taimako" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Boye akwati" - #: src/app/main/ui/workspace/sidebar/history.cljs msgid "workspace.undo.entry.modify" msgstr "gyaggyarawa %s" @@ -1946,10 +1942,6 @@ msgstr "" msgid "errors.email-has-permanent-bounces" msgstr "imel «%s» na da bayanan matsaloli na dindindin." -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "kashe tsinkewa zuwa akwati" - msgid "errors.webhooks.unexpected-status" msgstr "matsayin da ba zato %s" @@ -2966,9 +2958,6 @@ msgstr "tsarin salo" msgid "dashboard.import.analyze-error" msgstr "kash! mun gaza shigo da kundinka" -msgid "shortcuts.toggle-snap-guide" -msgstr "Tsinke zuwa mai jagora" - #: src/app/main/ui/auth/recovery_request.cljs msgid "auth.recovery-request-subtitle" msgstr "za mu aika maka da saqon qa'idoji ta imel" @@ -3307,10 +3296,6 @@ msgstr "kammala aiki" msgid "ds.confirm-ok" msgstr "haka" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "nuna akwati" - #: src/app/main/ui/settings/team-form.cljs, src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/settings/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs msgid "auth.name.not-all-space" msgstr "dole suna ya qumshi waxansu alamimon rubutu, sannan tazara." @@ -3722,9 +3707,6 @@ msgstr "fadi" msgid "inspect.empty.select" msgstr "zabar zubi, hukumar masu sa ido akan bangarorinsu da lambobinsu" -msgid "shortcuts.toggle-grid" -msgstr "Nuna/boye akwati" - #: src/app/main/ui/settings/access-tokens.cljs msgid "dashboard.access-tokens.expires-on" msgstr "gama aiki kan %s" @@ -4023,10 +4005,6 @@ msgstr "yanayin kallo (%s)" msgid "workspace.path.actions.make-curve" msgstr "Ta lankwasa (%s)" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Tsinke zuwa akwati" - msgid "workspace.options.search-font" msgstr "nemo jerin harufa" @@ -4501,9 +4479,6 @@ msgstr "Upload custom fonts" msgid "shortcuts.flip-horizontal" msgstr "kifa shi dai dai" -msgid "shortcuts.toggle-snap-grid" -msgstr "Tsinke akwati" - msgid "dashboard.import.progress.process-components" msgstr "aikin sassa" diff --git a/frontend/translations/he.po b/frontend/translations/he.po index 7f75d5c40..eafd1cd44 100644 --- a/frontend/translations/he.po +++ b/frontend/translations/he.po @@ -2802,9 +2802,6 @@ msgstr "החלפת מצב מיקוד" msgid "shortcuts.toggle-fullscreen" msgstr "החלפת מילוי מסך" -msgid "shortcuts.toggle-grid" -msgstr "הצגת/הסתרת רשת" - msgid "shortcuts.toggle-history" msgstr "החלפת הצגת היסטוריה" @@ -2823,12 +2820,6 @@ msgstr "נעילת יחס" msgid "shortcuts.toggle-rules" msgstr "הצגת/הסתרת סרגלים" -msgid "shortcuts.toggle-snap-grid" -msgstr "הצמדה לרשת" - -msgid "shortcuts.toggle-snap-guide" -msgstr "הצמדה לקווים מנחים" - msgid "shortcuts.toggle-textpalette" msgstr "החלפת לוח טקסט" @@ -3202,10 +3193,6 @@ msgstr "השבתת קנה מידה יחסי" msgid "workspace.header.menu.disable-scale-text" msgstr "השבתת שינוי גודל טקסט" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "השבתת הצמדה לרשת" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "השבתת הצמדה לקווים המנחים" @@ -3224,10 +3211,6 @@ msgstr "הפעלת קנה מידה יחסי" msgid "workspace.header.menu.enable-scale-text" msgstr "הפעלת שינוי גודל טקסט" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "הצמדה לרשת" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "הצמדה לקווים מנחים" @@ -3239,10 +3222,6 @@ msgstr "הפעלת הצמדה לפיקסל" msgid "workspace.header.menu.hide-artboard-names" msgstr "הסתרת שמות לוחות" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "הסתרת רשתות" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "הסתרת ערכת צבעים" @@ -3289,10 +3268,6 @@ msgstr "לבחור הכול" msgid "workspace.header.menu.show-artboard-names" msgstr "הצגת שמות לוחות" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "הצגת רשת" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "הצגת ערכת צבעים" diff --git a/frontend/translations/hr.po b/frontend/translations/hr.po index 7fc04586d..a0e38637e 100644 --- a/frontend/translations/hr.po +++ b/frontend/translations/hr.po @@ -2333,10 +2333,6 @@ msgstr "Promijena fokus moda" msgid "shortcuts.toggle-fullscreen" msgstr "Promijeni cijeli zaslon" -#, fuzzy -msgid "shortcuts.toggle-grid" -msgstr "Promijena \"grida\"" - msgid "shortcuts.toggle-history" msgstr "Promijena povijesti" @@ -2353,14 +2349,6 @@ msgstr "Zaključaj proporcije" msgid "shortcuts.toggle-rules" msgstr "Prikaži/sakrij \"rules\"" -#, fuzzy -msgid "shortcuts.toggle-snap-grid" -msgstr "Poravnanje s \"gridom\"" - -#, fuzzy -msgid "shortcuts.toggle-snap-guide" -msgstr "Pričvrsti na guides" - msgid "shortcuts.toggle-textpalette" msgstr "Promijeni paletu teksta" @@ -2692,10 +2680,6 @@ msgstr "Onemogući dinamičko poravnanje" msgid "workspace.header.menu.disable-scale-text" msgstr "Onemogući skaliranje teksta" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Onemogući \"snap to grid\"" - #: src/app/main/ui/workspace/header.cljs #, fuzzy msgid "workspace.header.menu.disable-snap-guides" @@ -2713,10 +2697,6 @@ msgstr "Omogući dinamičko poravnanje" msgid "workspace.header.menu.enable-scale-text" msgstr "Omogući skaliranje teksta" -#: src/app/main/ui/workspace/header.cljs -#, fuzzy -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Poravnanje s \"gridom\"" #: src/app/main/ui/workspace/header.cljs #, fuzzy @@ -2731,11 +2711,6 @@ msgstr "Omogući \"snap to pixel\"" msgid "workspace.header.menu.hide-artboard-names" msgstr "Sakrij nazive ploča" -#: src/app/main/ui/workspace/header.cljs -#, fuzzy -msgid "workspace.header.menu.hide-grid" -msgstr "Sakrij \"grid\"" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Sakrij paletu boja" @@ -2780,10 +2755,6 @@ msgstr "Odaberi sve" msgid "workspace.header.menu.show-artboard-names" msgstr "Prikaži nazive ploča" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Prikaži \"grid\"" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Prikaži paletu boja" diff --git a/frontend/translations/id.po b/frontend/translations/id.po index 551cd6091..037737bdd 100644 --- a/frontend/translations/id.po +++ b/frontend/translations/id.po @@ -2910,9 +2910,6 @@ msgstr "Alih mode fokus" msgid "shortcuts.toggle-fullscreen" msgstr "Alih layar penuh" -msgid "shortcuts.toggle-grid" -msgstr "Tampilkan/sembunyikan kisi" - msgid "shortcuts.toggle-history" msgstr "Alih riwayat" @@ -2931,12 +2928,6 @@ msgstr "Kunci proporsi" msgid "shortcuts.toggle-rules" msgstr "Tampilkan/sembunyikan penggaris" -msgid "shortcuts.toggle-snap-grid" -msgstr "Tancap ke kisi" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Tancap ke pemandu" - msgid "shortcuts.toggle-textpalette" msgstr "Alih palet teks" @@ -3307,10 +3298,6 @@ msgstr "Nonaktifkan skala proporsional" msgid "workspace.header.menu.disable-scale-text" msgstr "Nonaktifkan skala teks" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Nonaktifkan tancapan ke kisi" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Nonaktifkan tancapan ke pemandu" @@ -3329,10 +3316,6 @@ msgstr "Aktifkan skala proporsional" msgid "workspace.header.menu.enable-scale-text" msgstr "Aktifkan skala teks" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Tancapkan ke kisi" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Tancapkan ke pemandu" @@ -3344,10 +3327,6 @@ msgstr "Aktifkan tancapkan ke piksel" msgid "workspace.header.menu.hide-artboard-names" msgstr "Sembunyikan nama papan" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Sembunyikan kisi" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Sembunyikan palet warna" @@ -3394,10 +3373,6 @@ msgstr "Pilih semua" msgid "workspace.header.menu.show-artboard-names" msgstr "Tampilkan nama papan" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Tampilkan kisi" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Tampilkan palet warna" diff --git a/frontend/translations/lv.po b/frontend/translations/lv.po index e786756ee..72c325638 100644 --- a/frontend/translations/lv.po +++ b/frontend/translations/lv.po @@ -2897,9 +2897,6 @@ msgstr "Pārslēgt fokusa režīmu" msgid "shortcuts.toggle-fullscreen" msgstr "Pārslēgt pilnekrāna režīmu" -msgid "shortcuts.toggle-grid" -msgstr "Rādīt/paslēpt režģi" - msgid "shortcuts.toggle-history" msgstr "Pārslēgt vēsturi" @@ -2918,12 +2915,6 @@ msgstr "Slēgt proporcijas" msgid "shortcuts.toggle-rules" msgstr "Rādīt/paslēpt mērjoslas" -msgid "shortcuts.toggle-snap-grid" -msgstr "Pieķerties režģim" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Pieķerties vadotnēm" - msgid "shortcuts.toggle-textpalette" msgstr "Pārslēgt teksta paleti" @@ -3293,10 +3284,6 @@ msgstr "Atspējot proporcionālo mērogu" msgid "workspace.header.menu.disable-scale-text" msgstr "Deaktivizēt teksta mērogošanu" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Atspējot pieķeršanos režģim" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Atspējot pieķeršanos vadotnēm" @@ -3315,10 +3302,6 @@ msgstr "Iespējot proporcionālo mērogu" msgid "workspace.header.menu.enable-scale-text" msgstr "Aktivizēt teksta mērogošanu" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Pieķerties režģim" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Pieķerties vadotnēm" @@ -3330,10 +3313,6 @@ msgstr "Iespējot pieķeršanos pikselim" msgid "workspace.header.menu.hide-artboard-names" msgstr "Paslēpt plātņu nosaukumus" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Paslēpt režģus" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Paslēpt krāsu paleti" @@ -3380,10 +3359,6 @@ msgstr "Atlasīt visu" msgid "workspace.header.menu.show-artboard-names" msgstr "Rādīt plātņu nosaukumus" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Rādīt režģi" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Rādīt krāsu paleti" diff --git a/frontend/translations/nb_NO.po b/frontend/translations/nb_NO.po index 0d8307fa2..33b0e4b1d 100644 --- a/frontend/translations/nb_NO.po +++ b/frontend/translations/nb_NO.po @@ -602,14 +602,6 @@ msgstr "Størrelse" msgid "workspace.assets.typography.font-variant-id" msgstr "Variant" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Fest til rutenett" - -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Vis rutenett" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-rules" msgstr "Vis regler" diff --git a/frontend/translations/nl.po b/frontend/translations/nl.po index ad9b4beff..3e7a9bc04 100644 --- a/frontend/translations/nl.po +++ b/frontend/translations/nl.po @@ -2959,9 +2959,6 @@ msgstr "Focusmodus in/uitschakelen" msgid "shortcuts.toggle-fullscreen" msgstr "Volledig scherm in/uitschakelen" -msgid "shortcuts.toggle-grid" -msgstr "Raster tonen/verbergen" - msgid "shortcuts.toggle-history" msgstr "Geschiedenis in/uitschakelen" @@ -2980,12 +2977,6 @@ msgstr "Proporties vergrendelen" msgid "shortcuts.toggle-rules" msgstr "Linialen tonen/verbergen" -msgid "shortcuts.toggle-snap-grid" -msgstr "Uitlijnen op raster" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Uitlijnen op hulplijnen" - msgid "shortcuts.toggle-textpalette" msgstr "Tekstpalet in/uitschakelen" @@ -3357,10 +3348,6 @@ msgstr "Proportionele schaal uitschakelen" msgid "workspace.header.menu.disable-scale-text" msgstr "Tekstschaal uitschakelen" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Uitlijnen op raster uitschakelen" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Uitlijnen op hulplijnen uitschakelen" @@ -3379,10 +3366,6 @@ msgstr "Proportionele schaal inschakelen" msgid "workspace.header.menu.enable-scale-text" msgstr "Tekstschaal inschakelen" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Uitlijnen op raster" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Uitlijnen op hulplijnen" @@ -3394,10 +3377,6 @@ msgstr "Uitlijnen op pixel" msgid "workspace.header.menu.hide-artboard-names" msgstr "Bordnamen verbergen" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Rasters verbergen" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Kleurenpalet verbergen" @@ -3444,10 +3423,6 @@ msgstr "Alles selecteren" msgid "workspace.header.menu.show-artboard-names" msgstr "Bordnamen tonen" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Raster tonen" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Kleurenpalet tonen" diff --git a/frontend/translations/pl.po b/frontend/translations/pl.po index b460b8b14..839c34218 100644 --- a/frontend/translations/pl.po +++ b/frontend/translations/pl.po @@ -2451,9 +2451,6 @@ msgstr "Przełącz tryb skupienia" msgid "shortcuts.toggle-fullscreen" msgstr "Przełącz tryb pełnoekranowy" -msgid "shortcuts.toggle-grid" -msgstr "Pokaż/ukryj siatkę" - msgid "shortcuts.toggle-history" msgstr "Przełącz historię" @@ -2472,12 +2469,6 @@ msgstr "Zablokuj proporcje" msgid "shortcuts.toggle-rules" msgstr "Pokaż/ukryj linijki" -msgid "shortcuts.toggle-snap-grid" -msgstr "Przyciągaj do siatki" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Przyciągaj do prowadnic" - msgid "shortcuts.toggle-textpalette" msgstr "Przełącz paletę tekstu" @@ -2805,10 +2796,6 @@ msgstr "Wyłącz wyrównanie dynamiczne" msgid "workspace.header.menu.disable-scale-text" msgstr "Wyłącz skalowanie tekstu" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Wyłącz przyciąganie do siatki" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Wyłącz przyciąganie do prowadnic" @@ -2824,10 +2811,6 @@ msgstr "Włącz dynamiczne wyrównanie" msgid "workspace.header.menu.enable-scale-text" msgstr "Włącz skalowanie tekstu" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Przyciągaj do siatki" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Przyciągaj do prowadnic" @@ -2839,10 +2822,6 @@ msgstr "Włącz przyciąganie do piksela" msgid "workspace.header.menu.hide-artboard-names" msgstr "Ukryj nazwy obszarów kompozycji" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Ukryj siatki" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Ukryj paletę kolorów" @@ -2886,10 +2865,6 @@ msgstr "Zaznacz wszystko" msgid "workspace.header.menu.show-artboard-names" msgstr "Pokaz nazwy obszarów kompozycji" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Pokaż siatkę" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Pokaż paletę kolorów" diff --git a/frontend/translations/pt_BR.po b/frontend/translations/pt_BR.po index 91ff93e5d..9610c9f4f 100644 --- a/frontend/translations/pt_BR.po +++ b/frontend/translations/pt_BR.po @@ -2442,9 +2442,6 @@ msgstr "Entrar/Sair do modo de foco" msgid "shortcuts.toggle-fullscreen" msgstr "Entrar/Sair da tela cheia" -msgid "shortcuts.toggle-grid" -msgstr "Mostrar/Esconder grade" - msgid "shortcuts.toggle-history" msgstr "Mostrar/Esconder histórico" @@ -2463,12 +2460,6 @@ msgstr "Fixar proporções" msgid "shortcuts.toggle-rules" msgstr "Mostrar/ocultar réguas" -msgid "shortcuts.toggle-snap-grid" -msgstr "Aderir a grade" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Aderir as réguas" - msgid "shortcuts.toggle-textpalette" msgstr "Mostrar/Esconder paleta de tipografias" @@ -2795,10 +2786,6 @@ msgstr "Desabilitar alinhamento dinâmico" msgid "workspace.header.menu.disable-scale-text" msgstr "Desativar escalonamento de texto" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Desativar aderência a grade" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Desativar aderência as réguas" @@ -2814,10 +2801,6 @@ msgstr "Habilitar alinhamento dinâmico" msgid "workspace.header.menu.enable-scale-text" msgstr "Ativar escalonamento de texto" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Aderir a grade de pixels" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Aderir as réguas" @@ -2829,10 +2812,6 @@ msgstr "Habilitar aderência a grade de pixels" msgid "workspace.header.menu.hide-artboard-names" msgstr "Esconder nomes das telas" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Ocultar grades" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Esconder paleta de cores" @@ -2876,10 +2855,6 @@ msgstr "Selecionar tudo" msgid "workspace.header.menu.show-artboard-names" msgstr "Mostrar nomes das telas" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Mostrar grade" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Mostrar paleta de cores" diff --git a/frontend/translations/pt_PT.po b/frontend/translations/pt_PT.po index 7e7c16ffc..3bd8735be 100644 --- a/frontend/translations/pt_PT.po +++ b/frontend/translations/pt_PT.po @@ -2903,9 +2903,6 @@ msgstr "Alternar modo de foco" msgid "shortcuts.toggle-fullscreen" msgstr "Alternar tela cheia" -msgid "shortcuts.toggle-grid" -msgstr "Mostrar/ocultar grade" - msgid "shortcuts.toggle-history" msgstr "Alternar histórico" @@ -2924,12 +2921,6 @@ msgstr "Bloquear proporções" msgid "shortcuts.toggle-rules" msgstr "Mostrar/ocultar regras" -msgid "shortcuts.toggle-snap-grid" -msgstr "Ajustar à grade" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Ajustar às guias" - msgid "shortcuts.toggle-textpalette" msgstr "Alternar paleta de texto" @@ -3303,10 +3294,6 @@ msgstr "Desativar escala proporcional" msgid "workspace.header.menu.disable-scale-text" msgstr "Desativar escala de texto" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Desativar ajuste à grade" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Desativar ajuste às guias" @@ -3325,10 +3312,6 @@ msgstr "Ativar escala proporcional" msgid "workspace.header.menu.enable-scale-text" msgstr "Ativar escalar texto" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Ajustar à grade" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Ajustar às guias" @@ -3340,10 +3323,6 @@ msgstr "Ativar ajuste ao pixel" msgid "workspace.header.menu.hide-artboard-names" msgstr "Ocultar nome das pranchetas" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Ocultar grades" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Ocultar paleta de cor" @@ -3390,10 +3369,6 @@ msgstr "Selecionar tudo" msgid "workspace.header.menu.show-artboard-names" msgstr "Mostrar nomes das pranchetas" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Mostrar grade" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Mostrar paleta de cor" diff --git a/frontend/translations/ro.po b/frontend/translations/ro.po index 82698e7ef..232fc9a6c 100644 --- a/frontend/translations/ro.po +++ b/frontend/translations/ro.po @@ -2943,9 +2943,6 @@ msgstr "Comutați modul de focus" msgid "shortcuts.toggle-fullscreen" msgstr "Comutați la ecran complet" -msgid "shortcuts.toggle-grid" -msgstr "Afișați/ascundeți grila" - msgid "shortcuts.toggle-history" msgstr "Comutați istoricul" @@ -2964,12 +2961,6 @@ msgstr "Blocați proporțiile" msgid "shortcuts.toggle-rules" msgstr "Afișați/ascundeți rigle" -msgid "shortcuts.toggle-snap-grid" -msgstr "Fixare la grilă" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Fixare la ghiduri" - msgid "shortcuts.toggle-textpalette" msgstr "Comutați paleta de text" @@ -3342,10 +3333,6 @@ msgstr "Dezactivare scară proporțională" msgid "workspace.header.menu.disable-scale-text" msgstr "Dezactivează dimensionarea textului" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Dezactivați snap-ul la grilă" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Dezactivați fixarea la ghiduri" @@ -3364,10 +3351,6 @@ msgstr "Activare scară proporțională" msgid "workspace.header.menu.enable-scale-text" msgstr "Activează scalarea textului" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Aliniază per grilă" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Fixare la ghiduri" @@ -3379,10 +3362,6 @@ msgstr "Activați fixarea la pixel" msgid "workspace.header.menu.hide-artboard-names" msgstr "Ascundeți numele tablelor" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Ascunde grila de ghidaj" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Ascunde paleta de culori" @@ -3429,10 +3408,6 @@ msgstr "Selectează tot" msgid "workspace.header.menu.show-artboard-names" msgstr "Afișați numele tablelor" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Afişează sistemul grid" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Afişează paleta de culori" diff --git a/frontend/translations/ru.po b/frontend/translations/ru.po index 9bbb8f993..5a68e36df 100644 --- a/frontend/translations/ru.po +++ b/frontend/translations/ru.po @@ -1973,9 +1973,6 @@ msgstr "Переключить палитру цветов" msgid "shortcuts.toggle-focus-mode" msgstr "Переключить режим фокуса" -msgid "shortcuts.toggle-grid" -msgstr "Показать/скрыть сетку" - msgid "shortcuts.toggle-history" msgstr "Переключить историю" @@ -2251,26 +2248,14 @@ msgstr "Разгруппировать" msgid "workspace.header.menu.disable-dynamic-alignment" msgstr "Отключить активное выравнивание" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Отключить привязку к сетке" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-dynamic-alignment" msgstr "Включить активное выравнивание" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Привяка к сетке" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-artboard-names" msgstr "Скрыть имена кадров" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Скрыть сетки" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Скрыть палитру цветов" @@ -2302,10 +2287,6 @@ msgstr "" msgid "workspace.header.menu.show-artboard-names" msgstr "Показать имена кадров" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Показать сетку" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Показать палитру цветов" diff --git a/frontend/translations/tr.po b/frontend/translations/tr.po index 717b1bda0..f1ef022f9 100644 --- a/frontend/translations/tr.po +++ b/frontend/translations/tr.po @@ -2482,9 +2482,6 @@ msgstr "Odak modunu değiştir" msgid "shortcuts.toggle-fullscreen" msgstr "Tam ekranı değiştir" -msgid "shortcuts.toggle-grid" -msgstr "Izgarayı göster/gizle" - msgid "shortcuts.toggle-history" msgstr "Geçmişi değiştir" @@ -2503,12 +2500,6 @@ msgstr "Oranları kilitle" msgid "shortcuts.toggle-rules" msgstr "Cetvelleri göster/gizle" -msgid "shortcuts.toggle-snap-grid" -msgstr "Izgaraya tuttur" - -msgid "shortcuts.toggle-snap-guide" -msgstr "Kılavuzlara tuttur" - msgid "shortcuts.toggle-textpalette" msgstr "Metin paletini değiştir" @@ -2847,10 +2838,6 @@ msgstr "Dinamik hizalamayı devre dışı bırak" msgid "workspace.header.menu.disable-scale-text" msgstr "Metin ölçeklendirmeyi devre dışı bırak" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "Izgaraya tutturmayı devre dışı bırak" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "Kılavuzlara tutturmayı devre dışı bırak" @@ -2866,10 +2853,6 @@ msgstr "Dinamik hizalamayı etkinleştir" msgid "workspace.header.menu.enable-scale-text" msgstr "Metin ölçeklendirmeyi etkinleştir" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "Izgaraya tuttur" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "Kılavuzlara tuttur" @@ -2881,10 +2864,6 @@ msgstr "Piksele tutturmayı etkinleştir" msgid "workspace.header.menu.hide-artboard-names" msgstr "Çalışma yüzeyi adlarını gizle" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "Izgaraları gizle" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "Renk paletini gizle" @@ -2928,10 +2907,6 @@ msgstr "Tümünü seç" msgid "workspace.header.menu.show-artboard-names" msgstr "Çalışma yüzeylerinin adlarını göster" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "Izgarayı göster" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "Renk paletini göster" diff --git a/frontend/translations/zh_CN.po b/frontend/translations/zh_CN.po index ebb12eca6..c7f736a1f 100644 --- a/frontend/translations/zh_CN.po +++ b/frontend/translations/zh_CN.po @@ -2456,9 +2456,6 @@ msgstr "切换焦点模式" msgid "shortcuts.toggle-fullscreen" msgstr "切换全屏" -msgid "shortcuts.toggle-grid" -msgstr "显示/隐藏网格" - msgid "shortcuts.toggle-history" msgstr "切换历史" @@ -2477,12 +2474,6 @@ msgstr "锁定比例" msgid "shortcuts.toggle-rules" msgstr "显示/隐藏规则" -msgid "shortcuts.toggle-snap-grid" -msgstr "网络对齐" - -msgid "shortcuts.toggle-snap-guide" -msgstr "辅助线对齐" - msgid "shortcuts.toggle-textpalette" msgstr "切换文本调色板" @@ -2837,10 +2828,6 @@ msgstr "禁用比例尺" msgid "workspace.header.menu.disable-scale-text" msgstr "禁用缩放文本" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.disable-snap-grid" -msgstr "禁用吸附到网格" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.disable-snap-guides" msgstr "禁用与参考线对齐" @@ -2859,10 +2846,6 @@ msgstr "启用比例尺" msgid "workspace.header.menu.enable-scale-text" msgstr "启用缩放文本" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.enable-snap-grid" -msgstr "吸附到网格" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.enable-snap-guides" msgstr "与参考线对齐" @@ -2874,10 +2857,6 @@ msgstr "启用像素对齐" msgid "workspace.header.menu.hide-artboard-names" msgstr "隐藏画板名称" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.hide-grid" -msgstr "隐藏网格" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.hide-palette" msgstr "隐藏调色盘" @@ -2924,10 +2903,6 @@ msgstr "全选" msgid "workspace.header.menu.show-artboard-names" msgstr "显示画板名称" -#: src/app/main/ui/workspace/header.cljs -msgid "workspace.header.menu.show-grid" -msgstr "显示网格" - #: src/app/main/ui/workspace/header.cljs msgid "workspace.header.menu.show-palette" msgstr "显示调色盘" diff --git a/frontend/translations/zh_Hant.po b/frontend/translations/zh_Hant.po index c6151391e..ad1fe9a14 100644 --- a/frontend/translations/zh_Hant.po +++ b/frontend/translations/zh_Hant.po @@ -1584,9 +1584,6 @@ msgstr "切換調色板" msgid "shortcuts.toggle-focus-mode" msgstr "切換專注模式" -msgid "shortcuts.toggle-grid" -msgstr "顯示/隱藏網格" - msgid "shortcuts.toggle-history" msgstr "切換歷史記錄" From 3f316ca9c908e947b9f09ae2676f3e36de3cd18b Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 12 Mar 2024 14:14:47 +0100 Subject: [PATCH 133/136] :bug: Fix swap on anidated frames --- frontend/src/app/main/data/workspace/libraries.cljs | 3 ++- .../src/app/main/data/workspace/libraries_helpers.cljs | 10 +++++++--- frontend/src/app/main/data/workspace/selection.cljs | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 448997208..2d69cf7b6 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -901,7 +901,8 @@ libraries nil (:parent-id shape) - (:frame-id shape)) + (:frame-id shape) + {:force-frame? true}) new-shape (cond-> new-shape (nil? (ctk/get-swap-slot new-shape)) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index b75f13e00..b3aa937db 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -152,9 +152,11 @@ (defn generate-instantiate-component "Generate changes to create a new instance from a component." ([changes objects file-id component-id position page libraries] - (generate-instantiate-component changes objects file-id component-id position page libraries nil nil nil)) + (generate-instantiate-component changes objects file-id component-id position page libraries nil nil nil {})) - ([changes objects file-id component-id position page libraries old-id parent-id frame-id] + ([changes objects file-id component-id position page libraries old-id parent-id frame-id + {:keys [force-frame?] + :or {force-frame? false}}] (let [component (ctf/get-component libraries file-id component-id) parent (when parent-id (get objects parent-id)) library (get libraries file-id) @@ -166,7 +168,9 @@ component (:data library) position - components-v2) + components-v2 + (cond-> {} + force-frame? (assoc :force-frame-id frame-id))) first-shape (cond-> (first new-shapes) (not (nil? parent-id)) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index ca4200c11..975e21704 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -443,7 +443,8 @@ libraries (:id component-root) parent-id - frame-id) + frame-id + {}) restore-component #(let [restore (dwlh/prepare-restore-component changes library-data (:component-id component-root) it page delta (:id component-root) parent-id frame-id)] From ca5e2c345b936320d8cda6a4022f974e12cf652f Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 15 Mar 2024 10:30:09 +0100 Subject: [PATCH 134/136] :tada: Improve naming of components for Main components page on v1 to v2 migration --- backend/src/app/features/components_v2.clj | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/app/features/components_v2.clj b/backend/src/app/features/components_v2.clj index e24cbc469..46d04636f 100644 --- a/backend/src/app/features/components_v2.clj +++ b/backend/src/app/features/components_v2.clj @@ -1092,7 +1092,12 @@ (let [shapes (cfh/get-children-with-self (:objects component) (:id component)) - root-shape (first shapes) + ;; Let's calculate the top shame name from the components path and name + root-shape (-> (first shapes) + (assoc :name (cfh/merge-path-item (:path component) (:name component)))) + + shapes (assoc shapes 0 root-shape) + orig-pos (gpt/point (:x root-shape) (:y root-shape)) delta (gpt/subtract position orig-pos) From b999057be107b8e02acdba52ffcb9e39319e4bef Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 15 Mar 2024 11:39:16 +0100 Subject: [PATCH 135/136] :bug: Fix path top bat z-index --- .../ui/workspace/viewport/path_actions.cljs | 154 +++++++++++------- .../ui/workspace/viewport/path_actions.scss | 59 +++---- .../main/ui/workspace/viewport/top_bar.cljs | 5 +- .../main/ui/workspace/viewport/top_bar.scss | 64 ++++---- 4 files changed, 159 insertions(+), 123 deletions(-) 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 e337d4b17..69597f5a1 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs @@ -16,6 +16,38 @@ [app.util.path.tools :as upt] [rumext.v2 :as mf])) + +(def ^:private pentool-icon + (i/icon-xref :pentool (stl/css :pentool-icon :pathbar-icon))) + +(def ^:private move-icon + (i/icon-xref :move (stl/css :move-icon :pathbar-icon))) + +(def ^:private add-icon + (i/icon-xref :add (stl/css :add-icon :pathbar-icon))) + +(def ^:private remove-icon + (i/icon-xref :remove-icon (stl/css :remove-icon :pathbar-icon))) + +(def ^:private merge-nodes-icon + (i/icon-xref :merge-nodes (stl/css :merge-nodes-icon :pathbar-icon))) + +(def ^:private join-nodes-icon + (i/icon-xref :join-nodes (stl/css :join-nodes-icon :pathbar-icon))) + +(def ^:private separate-nodes-icon + (i/icon-xref :separate-nodes (stl/css :separate-nodes-icon :pathbar-icon))) + +(def ^:private to-corner-icon + (i/icon-xref :to-corner (stl/css :to-corner-icon :pathbar-icon))) + +(def ^:private to-curve-icon + (i/icon-xref :to-curve (stl/css :to-curve-icon :pathbar-icon))) + +(def ^:private snap-nodes-icon + (i/icon-xref :snap-nodes (stl/css :snap-nodes-icon :pathbar-icon))) + + (defn check-enabled [content selected-points] (let [segments (upt/get-segments content selected-points) num-segments (count segments) @@ -36,6 +68,7 @@ :join-nodes (and points-selected? (>= num-points 2) (< num-segments max-segments)) :separate-nodes segments-selected?})) + (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) @@ -112,77 +145,76 @@ [: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] + ;; Draw Mode + [:button {:class (stl/css-case :is-toggled (= edit-mode :draw) + :topbar-btn true) + :title (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) + :on-click on-select-draw-mode} + pentool-icon] - ;; 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]] + ;; Edit mode + [:button {:class (stl/css-case :is-toggled (= edit-mode :move) + :topbar-btn true) + :title (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) + :on-click on-select-edit-mode} + move-icon]] [: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] + ;; Add Node + [:button {:disabled (not (:add-node enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node)) + :on-click on-add-node} + add-icon] - ;; 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-icon]] + ;; Remove node + [:button {:disabled (not (:remove-node enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node)) + :on-click on-remove-node} + remove-icon]] [: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] + ;; Merge Nodes + [:button {:disabled (not (:merge-nodes enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes)) + :on-click on-merge-nodes} + merge-nodes-icon] - ;; 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] + ;; Join Nodes + [:button {:disabled (not (:join-nodes enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes)) + :on-click on-join-nodes} + join-nodes-icon] - ;; 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]] + ;; Separate Nodes + [:button {:disabled (not (:separate-nodes enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes)) + :on-click on-separate-nodes} + separate-nodes-icon]] - ;; 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] + ; Make Corner + [:button {:disabled (not (:make-corner enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner)) + :on-click on-make-corner} + to-corner-icon] - ;; 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]] - - ;; Toggle snap + ;; Make Curve + [:button {:disabled (not (:make-curve enabled-buttons)) + :class (stl/css :topbar-btn) + :title (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve)) + :on-click on-make-curve} + to-curve-icon]] [: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]]])) + ;; Toggle snap + [:button {:class (stl/css-case :is-toggled snap-toggled + :topbar-btn true) + :title (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes)) + :on-click on-toggle-snap} + snap-nodes-icon]]])) diff --git a/frontend/src/app/main/ui/workspace/viewport/path_actions.scss b/frontend/src/app/main/ui/workspace/viewport/path_actions.scss index e64aa4ffd..205cfa367 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.scss +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.scss @@ -19,41 +19,44 @@ padding: $s-8 $s-16; border-radius: $s-8; gap: $s-16; - z-index: $z-index-10; + border: $s-2 solid var(--panel-border-color); + z-index: $z-index-3; background-color: var(--color-background-primary); transition: top 0.3s, height 0.3s, opacity 0.3s; +} - .sub-actions-group { - position: relative; - display: flex; - align-items: center; - margin: 0; - opacity: $op-10; - transition: opacity 0.3s ease; +.sub-actions-group { + position: relative; + display: flex; + align-items: center; + margin: 0; + opacity: $op-10; + transition: opacity 0.3s ease; +} - button { - @extend .button-tertiary; - height: $s-36; - width: $s-36; - flex-shrink: 0; - background-color: transparent; - border-radius: $s-8; - border: none; - margin: 0 $s-2; - &.is-toggled { - background-color: var(--button-radio-background-color-active); - svg { - stroke: var(--button-radio-foreground-color-active); - } - } +.topbar-btn { + --pathbar-icon-color: var(--color-foreground-secondary); + @extend .button-tertiary; + height: $s-36; + width: $s-36; + flex-shrink: 0; + background-color: transparent; + border-radius: $s-8; + border: none; + margin: 0 $s-2; - svg { - @extend .button-icon; - stroke: var(--color-foreground-secondary); - } - } + &.is-toggled { + --pathbar-icon-color: var(--button-radio-foreground-color-active); + background-color: var(--button-radio-background-color-active); + } + + .pathbar-icon { + @extend .button-icon; + stroke: var(--pathbar-icon-color); } } + + 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 2e6b5d498..1cbd37d1c 100644 --- a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs @@ -33,7 +33,8 @@ [:& i18n/tr-html {:tag-name "span" :label "workspace.top-bar.view-only"}]] [:button {:class (stl/css :done-btn) - :on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]]])) + :on-click handle-close-view-mode} + (tr "workspace.top-bar.read-only.done")]]])) (mf/defc top-bar {::mf/wrap [mf/memo]} @@ -70,7 +71,7 @@ [:& view-only-actions] path-edition? - [:div {:class (stl/css-case :viewport-actions true :viewport-actions-no-rulers (not rulers?))} + [:div {:class (stl/css-case :viewport-actions-path true :viewport-actions-no-rulers (not rulers?))} [:& path-actions {:shape shape}]] grid-edition? diff --git a/frontend/src/app/main/ui/workspace/viewport/top_bar.scss b/frontend/src/app/main/ui/workspace/viewport/top_bar.scss index 7d922dcfc..9109d8e8b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/top_bar.scss +++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.scss @@ -6,7 +6,8 @@ @import "refactor/common-refactor.scss"; -.viewport-actions { +.viewport-actions, +.viewport-actions-path { pointer-events: none; position: absolute; --actions-toolbar-position-y: #{$s-28}; @@ -15,40 +16,39 @@ top: calc(var(--actions-toolbar-position-y) + var(--actions-toolbar-offset-y)); left: 50%; z-index: $z-index-20; +} - .viewport-actions-container { - @include flexRow; - background: var(--panel-background-color); - border-radius: $br-12; - box-shadow: 0 0 $s-12 0 var(--menu-shadow-color); - gap: $s-8; - height: $s-48; - margin-left: -50%; - padding: $s-8; - cursor: initial; - pointer-events: initial; - width: $s-400; - } +.viewport-actions-path { + z-index: $z-index-3; +} - .viewport-actions-title { - flex: 1; - font-size: $fs-12; - color: var(--color-foreground-secondary); - padding-left: $s-8; - } +.viewport-actions-container { + @include flexRow; + background: var(--panel-background-color); + border-radius: $br-12; + box-shadow: 0 0 $s-12 0 var(--menu-shadow-color); + gap: $s-8; + height: $s-48; + margin-left: -50%; + padding: $s-8; + cursor: initial; + pointer-events: initial; + width: $s-400; + border: $s-2 solid var(--panel-border-color); +} - .done-btn { - @extend .button-primary; - text-transform: uppercase; - padding: $s-8 $s-20; - font-size: $fs-11; - } - .close-btn { - @extend .button-tertiary; - svg { - @extend .button-icon; - } - } +.viewport-actions-title { + flex: 1; + font-size: $fs-12; + color: var(--color-foreground-secondary); + padding-left: $s-8; +} + +.done-btn { + @extend .button-primary; + text-transform: uppercase; + padding: $s-8 $s-20; + font-size: $fs-11; } .viewport-actions-no-rulers { From 440495a1d0391b68bbe1e12abd8774af98937775 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 15 Mar 2024 17:27:51 +0100 Subject: [PATCH 136/136] :bug: Fix submenu positioning in context menu --- .../app/main/ui/workspace/context_menu.cljs | 23 +++++++++---------- .../app/main/ui/workspace/context_menu.scss | 18 ++++++++++----- .../ui/workspace/viewport/path_actions.scss | 2 -- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 21f06b71c..987052774 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -652,16 +652,15 @@ [:& dropdown {:show (boolean mdata) :on-close #(st/emit! dw/hide-context-menu)} - [:ul {:class (stl/css :workspace-context-menu) - :ref dropdown-ref - :style {:top top :left left} - :on-context-menu prevent-default} - - (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}])]])) - + [:div {:class (stl/css :workspace-context-menu) + :ref dropdown-ref + :style {:top top :left left} + :on-context-menu prevent-default} + [:ul {:class (stl/css :context-list)} + (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 94b7060a0..b7ea96aa4 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.scss +++ b/frontend/src/app/main/ui/workspace/context_menu.scss @@ -6,24 +6,30 @@ @import "refactor/common-refactor.scss"; -.workspace-context-menu, -.workspace-context-submenu { - @include menuShadow; +.workspace-context-menu { position: absolute; top: $s-40; left: $s-736; - display: flex; - flex-direction: column; + z-index: $z-index-4; +} + +.context-list, +.workspace-context-submenu { + @include menuShadow; + display: grid; width: $s-240; padding: $s-4; border-radius: $br-8; border: $s-2 solid var(--panel-border-color); background-color: var(--menu-background-color); - z-index: $z-index-4; max-height: 100vh; overflow-y: auto; } +.workspace-context-submenu { + position: absolute; +} + .separator { height: $s-12; } diff --git a/frontend/src/app/main/ui/workspace/viewport/path_actions.scss b/frontend/src/app/main/ui/workspace/viewport/path_actions.scss index 205cfa367..c5e5ecc1b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.scss +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.scss @@ -58,5 +58,3 @@ stroke: var(--pathbar-icon-color); } } - -