mirror of
https://github.com/penpot/penpot.git
synced 2025-03-29 08:01:41 -05:00
⚡ Refactor state management of workspace assets sidebar
This commit is contained in:
parent
ef27301238
commit
fcc4f4eed8
16 changed files with 1665 additions and 1368 deletions
|
@ -43,4 +43,3 @@
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(->> (rp/cmd! :delete-share-link {:id id})
|
(->> (rp/cmd! :delete-share-link {:id id})
|
||||||
(rx/ignore)))))
|
(rx/ignore)))))
|
||||||
|
|
||||||
|
|
|
@ -237,34 +237,6 @@
|
||||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
||||||
(rx/map shared-files-fetched))))))
|
(rx/map shared-files-fetched))))))
|
||||||
|
|
||||||
;; --- EVENT: Get files that use this shared-file
|
|
||||||
|
|
||||||
(defn clean-temp-shared
|
|
||||||
[]
|
|
||||||
(ptk/reify ::clean-temp-shared
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:dashboard-local :files-with-shared] nil))))
|
|
||||||
|
|
||||||
(defn library-using-files-fetched
|
|
||||||
[files]
|
|
||||||
(ptk/reify ::library-using-files-fetched
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [files (d/index-by :id files)]
|
|
||||||
(assoc-in state [:dashboard-local :files-with-shared] files)))))
|
|
||||||
|
|
||||||
(defn fetch-libraries-using-files
|
|
||||||
[files]
|
|
||||||
(ptk/reify ::fetch-library-using-files
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ _]
|
|
||||||
(->> (rx/from files)
|
|
||||||
(rx/map :id)
|
|
||||||
(rx/mapcat #(rp/cmd! :get-library-file-references {:file-id %}))
|
|
||||||
(rx/reduce into [])
|
|
||||||
(rx/map library-using-files-fetched)))))
|
|
||||||
|
|
||||||
;; --- EVENT: recent-files
|
;; --- EVENT: recent-files
|
||||||
|
|
||||||
(defn recent-files-fetched
|
(defn recent-files-fetched
|
||||||
|
|
|
@ -181,13 +181,14 @@
|
||||||
(rx/of (dwn/initialize team-id id)
|
(rx/of (dwn/initialize team-id id)
|
||||||
(dwsl/initialize))
|
(dwsl/initialize))
|
||||||
|
|
||||||
;; Load team fonts. We must ensure custom fonts are fully loadad before starting the workspace load
|
;; Load team fonts. We must ensure custom fonts are fully loadad
|
||||||
|
;; before starting the workspace load.
|
||||||
(rx/merge
|
(rx/merge
|
||||||
|
(rx/of (df/load-team-fonts team-id))
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded))
|
(rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/ignore))
|
(rx/ignore)))
|
||||||
(rx/of (df/load-team-fonts team-id)))
|
|
||||||
|
|
||||||
(rx/merge
|
(rx/merge
|
||||||
;; Load all pages, independently if they are pointers or already
|
;; Load all pages, independently if they are pointers or already
|
||||||
|
@ -218,8 +219,6 @@
|
||||||
(rx/merge-map
|
(rx/merge-map
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (workspace-initialized))
|
|
||||||
|
|
||||||
(->> data
|
(->> data
|
||||||
(filter (comp t/pointer? val))
|
(filter (comp t/pointer? val))
|
||||||
(resolve-pointers id)
|
(resolve-pointers id)
|
||||||
|
@ -249,8 +248,9 @@
|
||||||
(fn [pages-index]
|
(fn [pages-index]
|
||||||
(assoc-in file [:data :pages-index] pages-index))))))
|
(assoc-in file [:data :pages-index] pages-index))))))
|
||||||
(rx/reduce conj [])
|
(rx/reduce conj [])
|
||||||
(rx/map libraries-fetched))))))))
|
(rx/map libraries-fetched)))))))
|
||||||
|
|
||||||
|
(rx/of (workspace-initialized)))
|
||||||
(rx/take-until stoper)))))))
|
(rx/take-until stoper)))))))
|
||||||
|
|
||||||
(defn- libraries-fetched
|
(defn- libraries-fetched
|
||||||
|
@ -1135,6 +1135,19 @@
|
||||||
qparams {:page-id page-id :layout (name layout)}]
|
qparams {:page-id page-id :layout (name layout)}]
|
||||||
(rx/of (rt/nav :workspace pparams qparams))))))
|
(rx/of (rt/nav :workspace pparams qparams))))))
|
||||||
|
|
||||||
|
(defn navigate-to-library
|
||||||
|
"Open a new tab, and navigate to the workspace with the provided file"
|
||||||
|
[library-id]
|
||||||
|
(ptk/reify ::navigate-to-file
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(when-let [file (dm/get-in state [:workspace-libraries library-id])]
|
||||||
|
(let [params {:rname :workspace
|
||||||
|
:path-params {:project-id (:project-id file)
|
||||||
|
:file-id (:id file)}
|
||||||
|
:query-params {:page-id (dm/get-in file [:data :pages 0])}}]
|
||||||
|
(rx/of (rt/nav-new-window* params)))))))
|
||||||
|
|
||||||
(defn check-in-asset
|
(defn check-in-asset
|
||||||
[items element]
|
[items element]
|
||||||
(let [items (or items #{})]
|
(let [items (or items #{})]
|
||||||
|
@ -1147,31 +1160,31 @@
|
||||||
(ptk/reify ::toggle-selected-assets
|
(ptk/reify ::toggle-selected-assets
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(update-in state [:workspace-global :selected-assets type] #(check-in-asset % asset)))))
|
(update-in state [:workspace-assets-selected type] #(check-in-asset % asset)))))
|
||||||
|
|
||||||
(defn select-single-asset
|
(defn select-single-asset
|
||||||
[asset type]
|
[asset type]
|
||||||
(ptk/reify ::select-single-asset
|
(ptk/reify ::select-single-asset
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-global :selected-assets type] #{asset}))))
|
(assoc-in state [:workspace-assets-selected type] #{asset}))))
|
||||||
|
|
||||||
(defn select-assets
|
(defn select-assets
|
||||||
[assets type]
|
[assets type]
|
||||||
(ptk/reify ::select-assets
|
(ptk/reify ::select-assets
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-global :selected-assets type] (into #{} assets)))))
|
(assoc-in state [:workspace-assets-selected type] (into #{} assets)))))
|
||||||
|
|
||||||
(defn unselect-all-assets
|
(defn unselect-all-assets
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::unselect-all-assets
|
(ptk/reify ::unselect-all-assets
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-global :selected-assets] {:components #{}
|
(assoc state :workspace-assets-selected {:components #{}
|
||||||
:graphics #{}
|
:graphics #{}
|
||||||
:colors #{}
|
:colors #{}
|
||||||
:typographies #{}}))))
|
:typographies #{}}))))
|
||||||
(defn go-to-main-instance
|
(defn go-to-main-instance
|
||||||
[page-id shape-id]
|
[page-id shape-id]
|
||||||
(dm/assert! (uuid? page-id))
|
(dm/assert! (uuid? page-id))
|
||||||
|
@ -1216,8 +1229,8 @@
|
||||||
pparams {:file-id file-id :project-id project-id}
|
pparams {:file-id file-id :project-id project-id}
|
||||||
qparams {:page-id page-id :layout :assets}]
|
qparams {:page-id page-id :layout :assets}]
|
||||||
(rx/of (rt/nav :workspace pparams qparams)
|
(rx/of (rt/nav :workspace pparams qparams)
|
||||||
(dwl/set-assets-box-open file-id :library true)
|
(dwl/set-assets-section-open file-id :library true)
|
||||||
(dwl/set-assets-box-open file-id :components true)
|
(dwl/set-assets-section-open file-id :components true)
|
||||||
(select-single-asset component-id :components))))))
|
(select-single-asset component-id :components))))))
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
|
@ -1238,8 +1251,8 @@
|
||||||
pparams {:file-id file-id :project-id project-id}
|
pparams {:file-id file-id :project-id project-id}
|
||||||
qparams {:page-id page-id :layout :assets}]
|
qparams {:page-id page-id :layout :assets}]
|
||||||
(rx/of (rt/nav :workspace pparams qparams)
|
(rx/of (rt/nav :workspace pparams qparams)
|
||||||
(dwl/set-assets-box-open file-id :library true)
|
(dwl/set-assets-section-open file-id :library true)
|
||||||
(dwl/set-assets-box-open file-id :components true)
|
(dwl/set-assets-section-open file-id :components true)
|
||||||
(select-single-asset component-id :components))))
|
(select-single-asset component-id :components))))
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
|
@ -2091,26 +2104,6 @@
|
||||||
(dissoc :page-item))]
|
(dissoc :page-item))]
|
||||||
(assoc state :workspace-local local)))))
|
(assoc state :workspace-local local)))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; File Library persistent settings
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
|
|
||||||
(defn set-file-library-listing-thumbs
|
|
||||||
[listing-thumbs?]
|
|
||||||
(ptk/reify ::set-file-library-listing-thumbs
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:workspace-global :file-library-listing-thumbs] listing-thumbs?))))
|
|
||||||
|
|
||||||
(defn set-file-library-reverse-sort
|
|
||||||
[reverse-sort?]
|
|
||||||
(ptk/reify ::set-file-library-reverse-sort
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:workspace-global :file-library-reverse-sort] reverse-sort?))))
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Components annotations
|
;; Components annotations
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -76,19 +76,19 @@
|
||||||
|
|
||||||
(declare sync-file)
|
(declare sync-file)
|
||||||
|
|
||||||
(defn set-assets-box-open
|
(defn set-assets-section-open
|
||||||
[file-id box open?]
|
[file-id section open?]
|
||||||
(ptk/reify ::set-assets-box-open
|
(ptk/reify ::set-assets-section-open
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-global :assets-files-open file-id box] open?))))
|
(assoc-in state [:workspace-assets-open-status file-id section] open?))))
|
||||||
|
|
||||||
(defn set-assets-group-open
|
(defn set-assets-group-open
|
||||||
[file-id box path open?]
|
[file-id section path open?]
|
||||||
(ptk/reify ::set-assets-group-open
|
(ptk/reify ::set-assets-group-open
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-global :assets-files-open file-id :groups box path] open?))))
|
(assoc-in state [:workspace-assets-open-status file-id :groups section path] open?))))
|
||||||
|
|
||||||
(defn extract-path-if-missing
|
(defn extract-path-if-missing
|
||||||
[item]
|
[item]
|
||||||
|
@ -951,12 +951,22 @@
|
||||||
(defn link-file-to-library
|
(defn link-file-to-library
|
||||||
[file-id library-id]
|
[file-id library-id]
|
||||||
(ptk/reify ::attach-library
|
(ptk/reify ::attach-library
|
||||||
|
;; NOTE: this event implements UpdateEvent protocol for perform an
|
||||||
|
;; optimistic update state for make the UI feel more responsive.
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [libraries (:workspace-shared-files state)
|
||||||
|
library (d/seek #(= (:id %) library-id) libraries)]
|
||||||
|
(if library
|
||||||
|
(update state :workspace-libraries assoc library-id (dissoc library :library-summary))
|
||||||
|
state)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [features (cond-> ffeat/enabled
|
(let [features (cond-> ffeat/enabled
|
||||||
(features/active-feature? state :components-v2)
|
(features/active-feature? state :components-v2)
|
||||||
(conj "components/v2"))]
|
(conj "components/v2"))]
|
||||||
(rx/concat
|
(rx/merge
|
||||||
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
||||||
(rx/ignore))
|
(rx/ignore))
|
||||||
(->> (rp/cmd! :get-file {:id library-id :features features})
|
(->> (rp/cmd! :get-file {:id library-id :features features})
|
||||||
|
|
|
@ -15,17 +15,22 @@
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.common.types.modifiers :as ctm]
|
[app.common.types.modifiers :as ctm]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.data.workspace.modifiers :as dwm]
|
[app.main.data.workspace.modifiers :as dwm]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
|
[app.main.fonts :as fonts]
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[app.util.text-editor :as ted]
|
[app.util.text-editor :as ted]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
|
[cuerdas.core :as str]
|
||||||
[potok.core :as ptk]))
|
[potok.core :as ptk]))
|
||||||
|
|
||||||
;; -- Attrs
|
;; -- Attrs
|
||||||
|
@ -321,6 +326,7 @@
|
||||||
(cph/group-shape? shape) (cph/get-children-ids objects id))]
|
(cph/group-shape? shape) (cph/get-children-ids objects id))]
|
||||||
(rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? d/txt-merge attrs))))))))
|
(rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? d/txt-merge attrs))))))))
|
||||||
|
|
||||||
|
|
||||||
(defn migrate-node
|
(defn migrate-node
|
||||||
[node]
|
[node]
|
||||||
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
|
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
|
||||||
|
@ -595,22 +601,97 @@
|
||||||
(rx/empty))))))
|
(rx/empty))))))
|
||||||
|
|
||||||
(defn update-attrs
|
(defn update-attrs
|
||||||
[id attrs]
|
[id attrs]
|
||||||
(ptk/reify ::update-attrs
|
(ptk/reify ::update-attrs
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
|
(rx/concat
|
||||||
|
(let [attrs (select-keys attrs root-attrs)]
|
||||||
|
(if-not (empty? attrs)
|
||||||
|
(rx/of (update-root-attrs {:id id :attrs attrs}))
|
||||||
|
(rx/empty)))
|
||||||
|
|
||||||
|
(let [attrs (select-keys attrs paragraph-attrs)]
|
||||||
|
(if-not (empty? attrs)
|
||||||
|
(rx/of (update-paragraph-attrs {:id id :attrs attrs}))
|
||||||
|
(rx/empty)))
|
||||||
|
|
||||||
|
(let [attrs (select-keys attrs text-attrs)]
|
||||||
|
(if-not (empty? attrs)
|
||||||
|
(rx/of (update-text-attrs {:id id :attrs attrs}))
|
||||||
|
(rx/empty)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn apply-typography
|
||||||
|
"A higher level event that has the resposability of to apply the
|
||||||
|
specified typography to the selected shapes."
|
||||||
|
[typography file-id]
|
||||||
|
(ptk/reify ::apply-typography
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [editor-state (:workspace-editor-state state)
|
||||||
|
selected (wsh/lookup-selected state)
|
||||||
|
attrs (-> typography
|
||||||
|
(assoc :typography-ref-file file-id)
|
||||||
|
(assoc :typography-ref-id (:id typography))
|
||||||
|
(dissoc :id :name))]
|
||||||
|
|
||||||
|
(->> (rx/from (seq selected))
|
||||||
|
(rx/map (fn [id]
|
||||||
|
(let [editor (get editor-state id)]
|
||||||
|
(update-text-attrs {:id id :editor editor :attrs attrs})))))))))
|
||||||
|
|
||||||
|
(defn generate-typography-name
|
||||||
|
[{:keys [font-id font-variant-id] :as typography}]
|
||||||
|
(let [{:keys [name]} (fonts/get-font-data font-id)]
|
||||||
|
(assoc typography :name (str name " " (str/title font-variant-id)))))
|
||||||
|
|
||||||
|
(defn add-typography
|
||||||
|
"A higher level version of dwl/add-typography, and has mainly two
|
||||||
|
responsabilities: add the typography to the library and apply it to
|
||||||
|
the currently selected text shapes (being aware of the open text
|
||||||
|
editors."
|
||||||
|
[file-id]
|
||||||
|
(ptk/reify ::add-typography
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [selected (wsh/lookup-selected state)
|
||||||
|
objects (wsh/lookup-page-objects state)
|
||||||
|
|
||||||
|
xform (comp (keep (d/getf objects))
|
||||||
|
(filter cph/text-shape?))
|
||||||
|
shapes (into [] xform selected)
|
||||||
|
shape (first shapes)
|
||||||
|
|
||||||
|
values (current-text-values
|
||||||
|
{:editor-state (dm/get-in state [:workspace-editor-state (:id shape)])
|
||||||
|
:shape shape
|
||||||
|
:attrs text-attrs})
|
||||||
|
|
||||||
|
multiple? (or (> 1 (count shapes))
|
||||||
|
(d/seek (partial = :multiple)
|
||||||
|
(vals values)))
|
||||||
|
|
||||||
|
values (-> (d/without-nils values)
|
||||||
|
(select-keys
|
||||||
|
(d/concat-vec text-font-attrs
|
||||||
|
text-spacing-attrs
|
||||||
|
text-transform-attrs)))
|
||||||
|
|
||||||
|
typ-id (uuid/next)
|
||||||
|
typ (-> (if multiple?
|
||||||
|
txt/default-typography
|
||||||
|
(merge txt/default-typography values))
|
||||||
|
(generate-typography-name)
|
||||||
|
(assoc :id typ-id))]
|
||||||
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(let [attrs (select-keys attrs root-attrs)]
|
(rx/of (dwl/add-typography typ)
|
||||||
(if-not (empty? attrs)
|
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||||
(rx/of (update-root-attrs {:id id :attrs attrs}))
|
:asset-type "typography"}))
|
||||||
(rx/empty)))
|
|
||||||
|
|
||||||
(let [attrs (select-keys attrs paragraph-attrs)]
|
(when (not multiple?)
|
||||||
(if-not (empty? attrs)
|
(rx/of (update-attrs (:id shape)
|
||||||
(rx/of (update-paragraph-attrs {:id id :attrs attrs}))
|
{:typography-ref-id typ-id
|
||||||
(rx/empty)))
|
:typography-ref-file file-id}))))))))
|
||||||
|
|
||||||
(let [attrs (select-keys attrs text-attrs)]
|
|
||||||
(if-not (empty? attrs)
|
|
||||||
(rx/of (update-text-attrs {:id id :attrs attrs}))
|
|
||||||
(rx/empty)))))))
|
|
||||||
|
|
|
@ -187,18 +187,9 @@
|
||||||
(def editing-page-item
|
(def editing-page-item
|
||||||
(l/derived :page-item workspace-local))
|
(l/derived :page-item workspace-local))
|
||||||
|
|
||||||
(def file-library-listing-thumbs?
|
|
||||||
(l/derived :file-library-listing-thumbs workspace-global))
|
|
||||||
|
|
||||||
(def file-library-reverse-sort?
|
|
||||||
(l/derived :file-library-reverse-sort workspace-global))
|
|
||||||
|
|
||||||
(def current-hover-ids
|
(def current-hover-ids
|
||||||
(l/derived :hover-ids context-menu))
|
(l/derived :hover-ids context-menu))
|
||||||
|
|
||||||
(def selected-assets
|
|
||||||
(l/derived :selected-assets workspace-global))
|
|
||||||
|
|
||||||
(def workspace-layout
|
(def workspace-layout
|
||||||
(l/derived :workspace-layout st/state))
|
(l/derived :workspace-layout st/state))
|
||||||
|
|
||||||
|
@ -212,10 +203,9 @@
|
||||||
data (:workspace-data state)]
|
data (:workspace-data state)]
|
||||||
(-> file
|
(-> file
|
||||||
(dissoc :data)
|
(dissoc :data)
|
||||||
(assoc :options (:options data)
|
;; FIXME: still used in sitemaps but sitemaps
|
||||||
:components (:components data)
|
;; should declare its own lense for it
|
||||||
:pages (:pages data)
|
(assoc :pages (:pages data)))))
|
||||||
:pages-index (:pages-index data)))))
|
|
||||||
st/state =))
|
st/state =))
|
||||||
|
|
||||||
(def workspace-data
|
(def workspace-data
|
||||||
|
@ -395,9 +385,7 @@
|
||||||
|
|
||||||
(def selected-objects
|
(def selected-objects
|
||||||
(letfn [(selector [{:keys [selected objects]}]
|
(letfn [(selector [{:keys [selected objects]}]
|
||||||
(->> selected
|
(into [] (keep (d/getf objects)) selected))]
|
||||||
(map #(get objects %))
|
|
||||||
(filterv (comp not nil?))))]
|
|
||||||
(l/derived selector selected-data =)))
|
(l/derived selector selected-data =)))
|
||||||
|
|
||||||
(def selected-shapes-with-children
|
(def selected-shapes-with-children
|
||||||
|
|
|
@ -98,12 +98,12 @@
|
||||||
(let [num-shared (filter #(:is-shared %) files)]
|
(let [num-shared (filter #(:is-shared %) files)]
|
||||||
|
|
||||||
(if (< 0 (count num-shared))
|
(if (< 0 (count num-shared))
|
||||||
(do (st/emit! (dd/fetch-libraries-using-files files))
|
(st/emit! (modal/show
|
||||||
(st/emit! (modal/show
|
{:type :delete-shared-libraries
|
||||||
{:type :delete-shared
|
:origin :delete
|
||||||
:origin :delete
|
:ids (into #{} (map :id) files)
|
||||||
:on-accept delete-fn
|
:on-accept delete-fn
|
||||||
:count-libraries (count num-shared)})))
|
:count-libraries (count num-shared)}))
|
||||||
|
|
||||||
(if multi?
|
(if multi?
|
||||||
(st/emit! (modal/show
|
(st/emit! (modal/show
|
||||||
|
@ -161,10 +161,10 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (dd/fetch-libraries-using-files files))
|
|
||||||
(st/emit! (modal/show
|
(st/emit! (modal/show
|
||||||
{:type :delete-shared
|
{:type :delete-shared-libraries
|
||||||
:origin :unpublish
|
:origin :unpublish
|
||||||
|
:ids (into #{} (map :id) files)
|
||||||
:on-accept del-shared
|
:on-accept del-shared
|
||||||
:count-libraries file-count})))
|
:count-libraries file-count})))
|
||||||
|
|
||||||
|
|
|
@ -6,88 +6,101 @@
|
||||||
|
|
||||||
(ns app.main.ui.delete-shared
|
(ns app.main.ui.delete-shared
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.dashboard :as dd]
|
[app.common.data.macros :as dm]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.refs :as refs]
|
[app.main.repo :as rp]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as k]
|
[app.util.keyboard :as k]
|
||||||
|
[beicon.core :as rx]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[rumext.v2 :as mf])
|
[rumext.v2 :as mf]))
|
||||||
(:import goog.events.EventType))
|
|
||||||
|
(def ^:private noop (constantly nil))
|
||||||
|
|
||||||
(mf/defc delete-shared-dialog
|
(mf/defc delete-shared-dialog
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :delete-shared}
|
::mf/register-as :delete-shared-libraries
|
||||||
[{:keys [on-accept
|
::mf/wrap-props false}
|
||||||
on-cancel
|
[{:keys [ids on-accept on-cancel accept-style origin count-libraries]}]
|
||||||
accept-style
|
(let [references* (mf/use-state {})
|
||||||
origin
|
references (deref references*)
|
||||||
count-libraries] :as props}]
|
|
||||||
(let [on-accept (or on-accept identity)
|
|
||||||
on-cancel (or on-cancel identity)
|
|
||||||
cancel-label (tr "labels.cancel")
|
|
||||||
accept-style (or accept-style :danger)
|
|
||||||
dashboard-local (mf/deref refs/dashboard-local)
|
|
||||||
files->shared (:files-with-shared dashboard-local)
|
|
||||||
|
|
||||||
is-delete? (= origin :delete)
|
on-accept (or on-accept noop)
|
||||||
count-files (count (keys files->shared))
|
on-cancel (or on-cancel noop)
|
||||||
|
|
||||||
title (if is-delete?
|
cancel-label (tr "labels.cancel")
|
||||||
(tr "modals.delete-shared-confirm.title" (i18n/c count-libraries))
|
accept-style (or accept-style :danger)
|
||||||
(tr "modals.unpublish-shared-confirm.title" (i18n/c count-libraries)))
|
|
||||||
message (if is-delete?
|
is-delete? (= origin :delete)
|
||||||
(tr "modals.delete-shared-confirm.message" (i18n/c count-libraries))
|
count-files (count (keys references))
|
||||||
(tr "modals.unpublish-shared-confirm.message" (i18n/c count-libraries)))
|
|
||||||
accept-label (if is-delete?
|
title (if ^boolean is-delete?
|
||||||
(tr "modals.delete-shared-confirm.accept" (i18n/c count-libraries))
|
(tr "modals.delete-shared-confirm.title" (i18n/c count-libraries))
|
||||||
(tr "modals.unpublish-shared-confirm.accept" (i18n/c count-libraries)))
|
(tr "modals.unpublish-shared-confirm.title" (i18n/c count-libraries)))
|
||||||
no-files-message (if is-delete?
|
|
||||||
(tr "modals.delete-shared-confirm.no-files-message" (i18n/c count-libraries))
|
subtitle (if ^boolean is-delete?
|
||||||
(tr "modals.unpublish-shared-confirm.no-files-message" (i18n/c count-libraries)))
|
(tr "modals.delete-shared-confirm.message" (i18n/c count-libraries))
|
||||||
scd-message (if is-delete?
|
(tr "modals.unpublish-shared-confirm.message" (i18n/c count-libraries)))
|
||||||
(if (= count-files 1)
|
|
||||||
(tr "modals.delete-shared-confirm.scd-message" (i18n/c count-libraries))
|
accept-label (if ^boolean is-delete?
|
||||||
(tr "modals.delete-shared-confirm.scd-message-many" (i18n/c count-libraries)))
|
(tr "modals.delete-shared-confirm.accept" (i18n/c count-libraries))
|
||||||
(if (= count-files 1)
|
(tr "modals.unpublish-shared-confirm.accept" (i18n/c count-libraries)))
|
||||||
(tr "modals.unpublish-shared-confirm.scd-message" (i18n/c count-libraries))
|
|
||||||
(tr "modals.unpublish-shared-confirm.scd-message-many" (i18n/c count-libraries))))
|
no-files-msg (if ^boolean is-delete?
|
||||||
hint (if is-delete?
|
(tr "modals.delete-shared-confirm.no-files-message" (i18n/c count-libraries))
|
||||||
(if (= count-files 1)
|
(tr "modals.unpublish-shared-confirm.no-files-message" (i18n/c count-libraries)))
|
||||||
(tr "modals.delete-shared-confirm.hint" (i18n/c count-libraries))
|
|
||||||
|
scd-msg (if ^boolean is-delete?
|
||||||
|
(if (= count-files 1)
|
||||||
|
(tr "modals.delete-shared-confirm.scd-message" (i18n/c count-libraries))
|
||||||
|
(tr "modals.delete-shared-confirm.scd-message-many" (i18n/c count-libraries)))
|
||||||
|
(if (= count-files 1)
|
||||||
|
(tr "modals.unpublish-shared-confirm.scd-message" (i18n/c count-libraries))
|
||||||
|
(tr "modals.unpublish-shared-confirm.scd-message-many" (i18n/c count-libraries))))
|
||||||
|
hint (if ^boolean is-delete?
|
||||||
|
(if (= count-files 1)
|
||||||
|
(tr "modals.delete-shared-confirm.hint" (i18n/c count-libraries))
|
||||||
(tr "modals.delete-shared-confirm.hint-many" (i18n/c count-libraries)))
|
(tr "modals.delete-shared-confirm.hint-many" (i18n/c count-libraries)))
|
||||||
(if (= count-files 1)
|
(if (= count-files 1)
|
||||||
(tr "modals.unpublish-shared-confirm.hint" (i18n/c count-libraries))
|
(tr "modals.unpublish-shared-confirm.hint" (i18n/c count-libraries))
|
||||||
(tr "modals.unpublish-shared-confirm.hint-many" (i18n/c count-libraries))))
|
(tr "modals.unpublish-shared-confirm.hint-many" (i18n/c count-libraries))))
|
||||||
|
|
||||||
accept-fn
|
accept-fn
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
|
(mf/deps on-accept)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(st/emit! (modal/hide))
|
(st/emit! (modal/hide))
|
||||||
(on-accept props)))
|
(on-accept)))
|
||||||
|
|
||||||
cancel-fn
|
cancel-fn
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
|
(mf/deps on-cancel)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(st/emit! (modal/hide))
|
(st/emit! (modal/hide))
|
||||||
(on-cancel props)))]
|
(on-cancel)))]
|
||||||
|
|
||||||
(mf/with-effect
|
(mf/with-effect [ids]
|
||||||
|
(->> (rx/from ids)
|
||||||
|
(rx/map #(array-map :file-id %))
|
||||||
|
(rx/mapcat #(rp/cmd! :get-library-file-references %))
|
||||||
|
(rx/mapcat identity)
|
||||||
|
(rx/map (juxt :id :name))
|
||||||
|
(rx/reduce conj [])
|
||||||
|
(rx/subs #(reset! references* %))))
|
||||||
|
|
||||||
|
(mf/with-effect [accept-fn]
|
||||||
(letfn [(on-keydown [event]
|
(letfn [(on-keydown [event]
|
||||||
(when (k/enter? event)
|
(when (k/enter? event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (modal/hide))
|
(accept-fn)))]
|
||||||
(on-accept props)))]
|
(let [key (events/listen js/document "keydown" on-keydown)]
|
||||||
(let [key (events/listen js/document EventType.KEYDOWN on-keydown)]
|
(partial events/unlistenByKey key))))
|
||||||
(fn []
|
|
||||||
(events/unlistenByKey key)
|
|
||||||
(st/emit! (dd/clean-temp-shared))))))
|
|
||||||
|
|
||||||
[:div.modal-overlay
|
[:div.modal-overlay
|
||||||
[:div.modal-container.confirm-dialog
|
[:div.modal-container.confirm-dialog
|
||||||
|
@ -98,23 +111,23 @@
|
||||||
{:on-click cancel-fn} i/close]]
|
{:on-click cancel-fn} i/close]]
|
||||||
|
|
||||||
[:div.modal-content.delete-shared
|
[:div.modal-content.delete-shared
|
||||||
(when (and (string? message) (not= message ""))
|
(when (and (string? subtitle) (not= subtitle ""))
|
||||||
[:h3 message])
|
[:h3 subtitle])
|
||||||
(when (not= 0 count-libraries)
|
(when (not= 0 count-libraries)
|
||||||
(if (> (count files->shared) 0)
|
(if (pos? (count references))
|
||||||
[:*
|
[:*
|
||||||
[:div
|
[:div
|
||||||
(when (and (string? scd-message) (not= scd-message ""))
|
(when (and (string? scd-msg) (not= scd-msg ""))
|
||||||
[:h3 scd-message])
|
[:h3 scd-msg])
|
||||||
[:ul.file-list
|
[:ul.file-list
|
||||||
(for [[id file] files->shared]
|
(for [[file-id file-name] references]
|
||||||
[:li.modal-item-element
|
[:li.modal-item-element
|
||||||
{:key id}
|
{:key (dm/str file-id)}
|
||||||
[:span "- " (:name file)]])]]
|
[:span "- " file-name]])]]
|
||||||
(when (and (string? hint) (not= hint ""))
|
(when (and (string? hint) (not= hint ""))
|
||||||
[:h3 hint])]
|
[:h3 hint])]
|
||||||
[:*
|
[:*
|
||||||
[:h3 no-files-message]]))]
|
[:h3 no-files-msg]]))]
|
||||||
|
|
||||||
[:div.modal-footer
|
[:div.modal-footer
|
||||||
[:div.action-buttons
|
[:div.action-buttons
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.globals :as globals]
|
[app.util.globals :as globals]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.object :as obj]
|
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[debug :refer [debug?]]
|
[debug :refer [debug?]]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
|
@ -47,14 +46,11 @@
|
||||||
|
|
||||||
(mf/defc workspace-content
|
(mf/defc workspace-content
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[{:keys [file layout page-id wglobal]}]
|
||||||
(let [selected (mf/deref refs/selected-shapes)
|
(let [selected (mf/deref refs/selected-shapes)
|
||||||
file (obj/get props "file")
|
|
||||||
layout (obj/get props "layout")
|
|
||||||
page-id (obj/get props "page-id")
|
|
||||||
|
|
||||||
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
|
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
|
||||||
{:keys [options-mode] :as wglobal} (obj/get props "wglobal")
|
{:keys [options-mode]} wglobal
|
||||||
|
|
||||||
colorpalette? (:colorpalette layout)
|
colorpalette? (:colorpalette layout)
|
||||||
textpalette? (:textpalette layout)
|
textpalette? (:textpalette layout)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.dashboard :as dd]
|
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.exports :as de]
|
[app.main.data.exports :as de]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
@ -108,6 +107,7 @@
|
||||||
|
|
||||||
;; --- Header Users
|
;; --- Header Users
|
||||||
|
|
||||||
|
;; FIXME: refactor & optimizations
|
||||||
(mf/defc menu
|
(mf/defc menu
|
||||||
[{:keys [layout project file team-id] :as props}]
|
[{:keys [layout project file team-id] :as props}]
|
||||||
(let [show-menu? (mf/use-state false)
|
(let [show-menu? (mf/use-state false)
|
||||||
|
@ -122,9 +122,6 @@
|
||||||
add-shared-fn
|
add-shared-fn
|
||||||
#(st/emit! (dwl/set-file-shared (:id file) true))
|
#(st/emit! (dwl/set-file-shared (:id file) true))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
on-add-shared
|
on-add-shared
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file)
|
(mf/deps file)
|
||||||
|
@ -144,10 +141,10 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (dd/fetch-libraries-using-files [file]))
|
|
||||||
(st/emit! (modal/show
|
(st/emit! (modal/show
|
||||||
{:type :delete-shared
|
{:type :delete-shared-libraries
|
||||||
:origin :unpublish
|
:origin :unpublish
|
||||||
|
:ids #{(:id file)}
|
||||||
:on-accept #(st/emit! (dwl/set-file-shared (:id file) false))
|
:on-accept #(st/emit! (dwl/set-file-shared (:id file) false))
|
||||||
:count-libraries 1}))))
|
:count-libraries 1}))))
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
(ns app.main.ui.workspace.libraries
|
(ns app.main.ui.workspace.libraries
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.main.data.dashboard :as dd]
|
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.assets :as a]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
|
@ -22,243 +22,302 @@
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def workspace-file
|
(def ref:workspace-file
|
||||||
(l/derived :workspace-file st/state))
|
(l/derived :workspace-file st/state))
|
||||||
|
|
||||||
(defn library-str
|
(defn create-file-library-ref
|
||||||
|
[library-id]
|
||||||
|
(letfn [(getter-fn [state]
|
||||||
|
(let [fdata (let [{:keys [id] :as wfile} (:workspace-data state)]
|
||||||
|
(if (= id library-id)
|
||||||
|
wfile
|
||||||
|
(dm/get-in state [:workspace-libraries library-id :data])))]
|
||||||
|
{:colors (-> fdata :colors vals)
|
||||||
|
:media (-> fdata :media vals)
|
||||||
|
:components (ctkl/components-seq fdata)
|
||||||
|
:typographies (-> fdata :typographies vals)}))]
|
||||||
|
(l/derived getter-fn st/state =)))
|
||||||
|
|
||||||
|
(defn- describe-library
|
||||||
[components-count graphics-count colors-count typography-count]
|
[components-count graphics-count colors-count typography-count]
|
||||||
(str
|
(str
|
||||||
(str/join " · "
|
(str/join " · "
|
||||||
(cond-> []
|
(cond-> []
|
||||||
(< 0 components-count)
|
(pos? components-count)
|
||||||
(conj (tr "workspace.libraries.components" components-count))
|
(conj (tr "workspace.libraries.components" components-count))
|
||||||
|
|
||||||
(< 0 graphics-count)
|
(pos? graphics-count)
|
||||||
(conj (tr "workspace.libraries.graphics" graphics-count))
|
(conj (tr "workspace.libraries.graphics" graphics-count))
|
||||||
|
|
||||||
(< 0 colors-count)
|
(pos? colors-count)
|
||||||
(conj (tr "workspace.libraries.colors" colors-count))
|
(conj (tr "workspace.libraries.colors" colors-count))
|
||||||
|
|
||||||
(< 0 typography-count)
|
(pos? typography-count)
|
||||||
(conj (tr "workspace.libraries.typography" typography-count))))
|
(conj (tr "workspace.libraries.typography" typography-count))))
|
||||||
"\u00A0"))
|
"\u00A0"))
|
||||||
|
|
||||||
(defn local-library-str
|
(defn- describe-linked-library
|
||||||
[library]
|
[library]
|
||||||
(let [components-count (count (or (ctkl/components-seq (:data library)) []))
|
(let [components-count (count (or (ctkl/components-seq (:data library)) []))
|
||||||
graphics-count (count (get-in library [:data :media] []))
|
graphics-count (count (dm/get-in library [:data :media] []))
|
||||||
colors-count (count (get-in library [:data :colors] []))
|
colors-count (count (dm/get-in library [:data :colors] []))
|
||||||
typography-count (count (get-in library [:data :typographies] []))]
|
typography-count (count (dm/get-in library [:data :typographies] []))]
|
||||||
(library-str components-count graphics-count colors-count typography-count)))
|
(describe-library components-count graphics-count colors-count typography-count)))
|
||||||
|
|
||||||
(defn external-library-str
|
(defn- describe-external-library
|
||||||
[library]
|
[library]
|
||||||
(let [components-count (get-in library [:library-summary :components :count] 0)
|
(let [components-count (dm/get-in library [:library-summary :components :count] 0)
|
||||||
graphics-count (get-in library [:library-summary :media :count] 0)
|
graphics-count (dm/get-in library [:library-summary :media :count] 0)
|
||||||
colors-count (get-in library [:library-summary :colors :count] 0)
|
colors-count (dm/get-in library [:library-summary :colors :count] 0)
|
||||||
typography-count (get-in library [:library-summary :typographies :count] 0)]
|
typography-count (dm/get-in library [:library-summary :typographies :count] 0)]
|
||||||
(library-str components-count graphics-count colors-count typography-count)))
|
(describe-library components-count graphics-count colors-count typography-count)))
|
||||||
|
|
||||||
(mf/defc libraries-tab
|
(mf/defc libraries-tab
|
||||||
[{:keys [file colors typographies media components libraries shared-files] :as props}]
|
{::mf/wrap-props false}
|
||||||
(let [search-term (mf/use-state "")
|
[{:keys [file-id shared? linked-libraries shared-libraries]}]
|
||||||
|
(let [search-term* (mf/use-state "")
|
||||||
|
search-term (deref search-term*)
|
||||||
|
|
||||||
sorted-libraries (->> (vals libraries)
|
library-ref (mf/with-memo [file-id]
|
||||||
(sort-by #(str/lower (:name %))))
|
(create-file-library-ref file-id))
|
||||||
|
library (deref library-ref)
|
||||||
|
colors (:colors library)
|
||||||
|
components (:components library)
|
||||||
|
media (:media library)
|
||||||
|
typographies (:typographies library)
|
||||||
|
|
||||||
filtered-files (->> shared-files
|
shared-libraries
|
||||||
(filter #(not= (:id %) (:id file)))
|
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
|
||||||
(filter #(nil? (get libraries (:id %))))
|
(->> shared-libraries
|
||||||
(filter #(matches-search (:name %) @search-term))
|
(remove #(= (:id %) file-id))
|
||||||
(sort-by #(str/lower (:name %))))
|
(remove #(contains? linked-libraries (:id %)))
|
||||||
|
(filter #(matches-search (:name %) search-term))
|
||||||
|
(sort-by (comp str/lower :name))))
|
||||||
|
|
||||||
on-search-term-change
|
linked-libraries
|
||||||
(mf/use-callback
|
(mf/with-memo [linked-libraries]
|
||||||
|
(->> (vals linked-libraries)
|
||||||
|
(sort-by (comp str/lower :name))))
|
||||||
|
|
||||||
|
change-search-term
|
||||||
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [value (-> (dom/get-target event)
|
(let [value (-> (dom/get-target event)
|
||||||
(dom/get-value))]
|
(dom/get-value))]
|
||||||
(reset! search-term value))))
|
(reset! search-term* value))))
|
||||||
|
|
||||||
on-search-clear
|
clear-search-term
|
||||||
(mf/use-callback
|
(mf/use-fn #(reset! search-term* ""))
|
||||||
(fn [_]
|
|
||||||
(reset! search-term "")))
|
|
||||||
|
|
||||||
link-library
|
link-library
|
||||||
(mf/use-callback (mf/deps file) #(st/emit! (dwl/link-file-to-library (:id file) %)))
|
(mf/use-fn
|
||||||
|
(mf/deps file-id)
|
||||||
|
(fn [event]
|
||||||
|
(let [library-id (some-> (dom/get-target event)
|
||||||
|
(dom/get-data "library-id")
|
||||||
|
(parse-uuid))]
|
||||||
|
(st/emit! (dwl/link-file-to-library file-id library-id)))))
|
||||||
|
|
||||||
unlink-library
|
unlink-library
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps file)
|
(mf/deps file-id)
|
||||||
(fn [library-id]
|
|
||||||
(st/emit! (dwl/unlink-file-from-library (:id file) library-id)
|
|
||||||
(dwl/sync-file (:id file) library-id))))
|
|
||||||
add-shared
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
#(st/emit! (dwl/set-file-shared (:id file) true)))
|
|
||||||
|
|
||||||
del-shared
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
(fn [_]
|
|
||||||
(st/emit! (dd/fetch-libraries-using-files [file]))
|
|
||||||
(st/emit! (modal/show
|
|
||||||
{:type :delete-shared
|
|
||||||
:origin :unpublish
|
|
||||||
:on-accept (fn []
|
|
||||||
(st/emit! (dwl/set-file-shared (:id file) false))
|
|
||||||
(modal/show! :libraries-dialog {}))
|
|
||||||
:on-cancel #(modal/show! :libraries-dialog {})
|
|
||||||
:count-libraries 1}))))
|
|
||||||
handle-key-down
|
|
||||||
(mf/use-callback
|
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [enter? (kbd/enter? event)
|
(let [library-id (some-> (dom/get-target event)
|
||||||
esc? (kbd/esc? event)
|
(dom/get-data "library-id")
|
||||||
input-node (dom/event->target event)]
|
(parse-uuid))]
|
||||||
|
(st/emit! (dwl/unlink-file-from-library file-id library-id)
|
||||||
|
(dwl/sync-file file-id library-id)))))
|
||||||
|
|
||||||
(when enter?
|
on-delete-accept
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps file-id)
|
||||||
|
#(st/emit! (dwl/set-file-shared file-id false)
|
||||||
|
(modal/show :libraries-dialog {})))
|
||||||
|
|
||||||
|
on-delete-cancel
|
||||||
|
(mf/use-fn #(st/emit! (modal/show :libraries-dialog {})))
|
||||||
|
|
||||||
|
publish
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps file-id)
|
||||||
|
#(st/emit! (dwl/set-file-shared file-id true)))
|
||||||
|
|
||||||
|
unpublish
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps file-id)
|
||||||
|
(fn [_]
|
||||||
|
(st/emit! (modal/show
|
||||||
|
{:type :delete-shared-libraries
|
||||||
|
:ids #{file-id}
|
||||||
|
:origin :unpublish
|
||||||
|
:on-accept on-delete-accept
|
||||||
|
:on-cancel on-delete-cancel
|
||||||
|
:count-libraries 1}))))
|
||||||
|
|
||||||
|
handle-key-down
|
||||||
|
(mf/use-fn
|
||||||
|
(fn [event]
|
||||||
|
(let [enter? (kbd/enter? event)
|
||||||
|
esc? (kbd/esc? event)
|
||||||
|
input-node (dom/event->target event)]
|
||||||
|
(when ^boolean enter?
|
||||||
(dom/blur! input-node))
|
(dom/blur! input-node))
|
||||||
(when esc?
|
(when ^boolean esc?
|
||||||
(dom/blur! input-node)))))]
|
(dom/blur! input-node)))))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:div.section
|
[:div.section
|
||||||
[:div.section-title (tr "workspace.libraries.in-this-file")]
|
[:div.section-title (tr "workspace.libraries.in-this-file")]
|
||||||
[:div.section-list
|
[:div.section-list
|
||||||
|
|
||||||
[:div.section-list-item
|
[:div.section-list-item
|
||||||
[:div
|
[:div {:data-kaka "1"}
|
||||||
[:div.item-name (tr "workspace.libraries.file-library")]
|
[:div.item-name (tr "workspace.libraries.file-library")]
|
||||||
[:div.item-contents (library-str (count components) (count media) (count colors) (count typographies) )]]
|
[:div.item-contents (describe-library
|
||||||
|
(count components)
|
||||||
|
(count media)
|
||||||
|
(count colors)
|
||||||
|
(count typographies))]]
|
||||||
[:div
|
[:div
|
||||||
(if (:is-shared file)
|
(if ^boolean shared?
|
||||||
[:input.item-button {:type "button"
|
[:input.item-button {:type "button"
|
||||||
:value (tr "common.unpublish")
|
:value (tr "common.unpublish")
|
||||||
:on-click del-shared}]
|
:on-click unpublish}]
|
||||||
[:input.item-button {:type "button"
|
[:input.item-button {:type "button"
|
||||||
:value (tr "common.publish")
|
:value (tr "common.publish")
|
||||||
:on-click add-shared}])]]
|
:on-click publish}])]]
|
||||||
|
|
||||||
(for [library sorted-libraries]
|
(for [{:keys [id name] :as library} linked-libraries]
|
||||||
[:div.section-list-item {:key (:id library)}
|
[:div.section-list-item {:key (dm/str id)}
|
||||||
[:div.item-name (:name library)]
|
[:div.item-name name]
|
||||||
[:div.item-contents (local-library-str library)]
|
[:div.item-contents (describe-linked-library library)]
|
||||||
[:input.item-button {:type "button"
|
[:input.item-button {:type "button"
|
||||||
:value (tr "labels.remove")
|
:value (tr "labels.remove")
|
||||||
:on-click #(unlink-library (:id library))}]])
|
:data-library-id (dm/str id)
|
||||||
]]
|
:on-click unlink-library}]])]]
|
||||||
|
|
||||||
[:div.section
|
[:div.section
|
||||||
[:div.section-title (tr "workspace.libraries.shared-libraries")]
|
[:div.section-title (tr "workspace.libraries.shared-libraries")]
|
||||||
[:div.libraries-search
|
[:div.libraries-search
|
||||||
[:input.search-input
|
[:input.search-input
|
||||||
{:placeholder (tr "workspace.libraries.search-shared-libraries")
|
{:placeholder (tr "workspace.libraries.search-shared-libraries")
|
||||||
:type "text"
|
:type "text"
|
||||||
:value @search-term
|
:value search-term
|
||||||
:on-change on-search-term-change
|
:on-change change-search-term
|
||||||
:on-key-down handle-key-down}]
|
:on-key-down handle-key-down}]
|
||||||
(if (str/empty? @search-term)
|
(if (str/empty? search-term)
|
||||||
[:div.search-icon
|
[:div.search-icon
|
||||||
i/search]
|
i/search]
|
||||||
[:div.search-icon.search-close
|
[:div.search-icon.search-close
|
||||||
{:on-click on-search-clear}
|
{:on-click clear-search-term}
|
||||||
i/close])]
|
i/close])]
|
||||||
(if (> (count filtered-files) 0)
|
|
||||||
|
(if (seq shared-libraries)
|
||||||
[:div.section-list
|
[:div.section-list
|
||||||
(for [file filtered-files]
|
(for [{:keys [id name] :as library} shared-libraries]
|
||||||
[:div.section-list-item {:key (:id file)}
|
[:div.section-list-item {:key (dm/str id)}
|
||||||
[:div.item-name (:name file)]
|
[:div.item-name name]
|
||||||
[:div.item-contents (external-library-str file)]
|
[:div.item-contents (describe-external-library library)]
|
||||||
[:input.item-button {:type "button"
|
[:input.item-button {:type "button"
|
||||||
:value (tr "workspace.libraries.add")
|
:value (tr "workspace.libraries.add")
|
||||||
:on-click #(link-library (:id file))}]])]
|
:data-library-id (dm/str id)
|
||||||
|
:on-click link-library}]])]
|
||||||
|
|
||||||
[:div.section-list-empty
|
[:div.section-list-empty
|
||||||
(if (nil? shared-files)
|
(if (nil? shared-libraries)
|
||||||
i/loader-pencil
|
i/loader-pencil
|
||||||
[:* i/library
|
[:* i/library
|
||||||
(if (str/empty? @search-term)
|
(if (str/empty? search-term)
|
||||||
(tr "workspace.libraries.no-shared-libraries-available")
|
(tr "workspace.libraries.no-shared-libraries-available")
|
||||||
(tr "workspace.libraries.no-matches-for" @search-term))])])]]))
|
(tr "workspace.libraries.no-matches-for" search-term))])])]]))
|
||||||
|
|
||||||
|
|
||||||
(mf/defc updates-tab
|
(mf/defc updates-tab
|
||||||
[{:keys [file libraries] :as props}]
|
{::mf/wrap-props false}
|
||||||
(let [libraries-need-sync (filter #(> (:modified-at %) (:synced-at %))
|
[{:keys [file-id libraries]}]
|
||||||
(vals libraries))
|
(let [libraries (mf/with-memo [libraries]
|
||||||
update-library #(st/emit! (dwl/sync-file (:id file) %))]
|
(filter #(> (:modified-at %) (:synced-at %)) (vals libraries)))
|
||||||
[:div.section
|
|
||||||
(if (empty? libraries-need-sync)
|
update (mf/use-fn
|
||||||
[:div.section-list-empty
|
(mf/deps file-id)
|
||||||
i/library
|
(fn [event]
|
||||||
(tr "workspace.libraries.no-libraries-need-sync")]
|
(let [library-id (some-> (dom/get-target event)
|
||||||
[:*
|
(dom/get-data "library-id")
|
||||||
[:div.section-title (tr "workspace.libraries.library")]
|
(parse-uuid))]
|
||||||
[:div.section-list
|
(st/emit! (dwl/sync-file file-id library-id)))))]
|
||||||
(for [library libraries-need-sync]
|
[:div.section
|
||||||
[:div.section-list-item {:key (:id library)}
|
(if (empty? libraries)
|
||||||
[:div.item-name (:name library)]
|
[:div.section-list-empty
|
||||||
[:div.item-contents (external-library-str library)]
|
i/library
|
||||||
[:input.item-button {:type "button"
|
(tr "workspace.libraries.no-libraries-need-sync")]
|
||||||
:value (tr "workspace.libraries.update")
|
[:*
|
||||||
:on-click #(update-library (:id library))}]])]])]))
|
[:div.section-title (tr "workspace.libraries.library")]
|
||||||
|
[:div.section-list
|
||||||
|
(for [{:keys [id name] :as library} libraries]
|
||||||
|
[:div.section-list-item {:key (dm/str id)}
|
||||||
|
[:div.item-name name]
|
||||||
|
[:div.item-contents (describe-external-library library)]
|
||||||
|
[:input.item-button {:type "button"
|
||||||
|
:value (tr "workspace.libraries.update")
|
||||||
|
:data-library-id (dm/str id)
|
||||||
|
:on-click update}]])]])]))
|
||||||
|
|
||||||
(mf/defc libraries-dialog
|
(mf/defc libraries-dialog
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :libraries-dialog}
|
::mf/register-as :libraries-dialog}
|
||||||
[{:keys [] :as ctx}]
|
[]
|
||||||
(let [selected-tab (mf/use-state :libraries)
|
(let [project (mf/deref refs/workspace-project)
|
||||||
project (mf/deref refs/workspace-project)
|
file (mf/deref ref:workspace-file)
|
||||||
file (mf/deref workspace-file)
|
|
||||||
|
|
||||||
libraries (->> (mf/deref refs/workspace-libraries)
|
team-id (:team-id project)
|
||||||
(d/removem (fn [[_ val]] (:is-indirect val))))
|
file-id (:id file)
|
||||||
shared-files (mf/deref refs/workspace-shared-files)
|
shared? (:is-shared file)
|
||||||
|
|
||||||
colors-ref (mf/use-memo (mf/deps (:id file)) #(a/file-colors-ref (:id file)))
|
selected-tab* (mf/use-state :libraries)
|
||||||
colors (mf/deref colors-ref)
|
selected-tab (deref selected-tab*)
|
||||||
|
|
||||||
typography-ref (mf/use-memo (mf/deps (:id file)) #(a/file-typography-ref (:id file)))
|
libraries (mf/deref refs/workspace-libraries)
|
||||||
typographies (mf/deref typography-ref)
|
libraries (mf/with-memo [libraries]
|
||||||
|
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
||||||
|
|
||||||
media-ref (mf/use-memo (mf/deps (:id file)) #(a/file-media-ref (:id file)))
|
;; NOTE: we really don't need react on shared files
|
||||||
media (mf/deref media-ref)
|
shared-libraries
|
||||||
|
(mf/deref refs/workspace-shared-files)
|
||||||
|
|
||||||
components-ref (mf/use-memo (mf/deps (:id file)) #(a/file-components-ref (:id file)))
|
select-libraries-tab
|
||||||
components (mf/deref components-ref)
|
(mf/use-fn #(reset! selected-tab* :libraries))
|
||||||
|
|
||||||
change-tab #(reset! selected-tab %)
|
select-updates-tab
|
||||||
close #(modal/hide!)]
|
(mf/use-fn #(reset! selected-tab* :updates))
|
||||||
|
|
||||||
(mf/use-effect
|
close-dialog
|
||||||
(mf/deps project)
|
(mf/use-fn #(modal/hide!))]
|
||||||
(fn []
|
|
||||||
(when (:team-id project)
|
(mf/with-effect [team-id]
|
||||||
(st/emit! (dwl/fetch-shared-files {:team-id (:team-id project)})))))
|
(when team-id
|
||||||
|
(st/emit! (dwl/fetch-shared-files {:team-id team-id}))))
|
||||||
|
|
||||||
[:div.modal-overlay
|
[:div.modal-overlay
|
||||||
[:div.modal.libraries-dialog
|
[:div.modal.libraries-dialog
|
||||||
[:a.close {:on-click close} i/close]
|
[:a.close {:on-click close-dialog} i/close]
|
||||||
[:div.modal-content
|
[:div.modal-content
|
||||||
[:div.libraries-header
|
[:div.libraries-header
|
||||||
[:div.header-item
|
[:div.header-item
|
||||||
{:class (dom/classnames :active (= @selected-tab :libraries))
|
{:class (dom/classnames :active (= selected-tab :libraries))
|
||||||
:on-click #(change-tab :libraries)}
|
:on-click select-libraries-tab}
|
||||||
(tr "workspace.libraries.libraries")]
|
(tr "workspace.libraries.libraries")]
|
||||||
[:div.header-item
|
[:div.header-item
|
||||||
{:class (dom/classnames :active (= @selected-tab :updates))
|
{:class (dom/classnames :active (= selected-tab :updates))
|
||||||
:on-click #(change-tab :updates)}
|
:on-click select-updates-tab}
|
||||||
(tr "workspace.libraries.updates")]]
|
(tr "workspace.libraries.updates")]]
|
||||||
[:div.libraries-content
|
[:div.libraries-content
|
||||||
(case @selected-tab
|
(case selected-tab
|
||||||
:libraries
|
:libraries
|
||||||
[:& libraries-tab {:file file
|
[:& libraries-tab {:file-id file-id
|
||||||
:colors colors
|
:shared? shared?
|
||||||
:typographies typographies
|
:linked-libraries libraries
|
||||||
:media media
|
:shared-libraries shared-libraries}]
|
||||||
:components components
|
|
||||||
:libraries libraries
|
|
||||||
:shared-files shared-files}]
|
|
||||||
:updates
|
:updates
|
||||||
[:& updates-tab {:file file
|
[:& updates-tab {:file-id file-id
|
||||||
:libraries libraries}])]]]]))
|
:libraries libraries}])]]]]))
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,15 +18,16 @@
|
||||||
(mf/defc collapsed-button
|
(mf/defc collapsed-button
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[]
|
[]
|
||||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
|
(let [new-css? (mf/use-ctx ctx/new-css-system)
|
||||||
(if new-css-system
|
on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
|
||||||
|
(if ^boolean new-css?
|
||||||
[:div {:class (dom/classnames (css :collapsed-sidebar) true)}
|
[:div {:class (dom/classnames (css :collapsed-sidebar) true)}
|
||||||
[:div {:class (dom/classnames (css :collapsed-title) true)}
|
[:div {:class (dom/classnames (css :collapsed-title) true)}
|
||||||
[:button {:class (dom/classnames (css :collapsed-button) true)
|
[:button {:class (dom/classnames (css :collapsed-button) true)
|
||||||
:on-click #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar))
|
:on-click on-click
|
||||||
:aria-label (tr "workspace.sidebar.expand")}
|
:aria-label (tr "workspace.sidebar.expand")}
|
||||||
i/arrow-refactor]]]
|
i/arrow-refactor]]]
|
||||||
[:button.collapse-sidebar.collapsed
|
[:button.collapse-sidebar.collapsed
|
||||||
{:on-click #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar))
|
{:on-click on-click
|
||||||
:aria-label (tr "workspace.sidebar.expand")}
|
:aria-label (tr "workspace.sidebar.expand")}
|
||||||
i/arrow-slide])))
|
i/arrow-slide])))
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
[app.main.data.workspace.shortcuts :as sc]
|
[app.main.data.workspace.shortcuts :as sc]
|
||||||
[app.main.data.workspace.texts :as dwt]
|
[app.main.data.workspace.texts :as dwt]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.fonts :as fonts]
|
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
|
@ -23,7 +22,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
[cuerdas.core :as str]
|
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc text-align-options
|
(mf/defc text-align-options
|
||||||
|
@ -159,11 +157,6 @@
|
||||||
:on-click #(handle-change % "line-through")}
|
:on-click #(handle-change % "line-through")}
|
||||||
i/strikethrough]]))
|
i/strikethrough]]))
|
||||||
|
|
||||||
(defn generate-typography-name
|
|
||||||
[{:keys [font-id font-variant-id] :as typography}]
|
|
||||||
(let [{:keys [name]} (fonts/get-font-data font-id)]
|
|
||||||
(assoc typography :name (str name " " (str/title font-variant-id)))))
|
|
||||||
|
|
||||||
(mf/defc text-menu
|
(mf/defc text-menu
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [ids type values] :as props}]
|
[{:keys [ids type values] :as props}]
|
||||||
|
@ -215,7 +208,7 @@
|
||||||
dwt/text-spacing-attrs
|
dwt/text-spacing-attrs
|
||||||
dwt/text-transform-attrs)))
|
dwt/text-transform-attrs)))
|
||||||
typography (merge txt/default-typography set-values)
|
typography (merge txt/default-typography set-values)
|
||||||
typography (generate-typography-name typography)
|
typography (dwt/generate-typography-name typography)
|
||||||
id (uuid/next)]
|
id (uuid/next)]
|
||||||
(st/emit! (dwl/add-typography (assoc typography :id id) false))
|
(st/emit! (dwl/add-typography (assoc typography :id id) false))
|
||||||
(run! #(emit-update! % {:typography-ref-id id
|
(run! #(emit-update! % {:typography-ref-id id
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.main.data.fonts :as fts]
|
[app.main.data.fonts :as fts]
|
||||||
[app.main.data.shortcuts :as dsc]
|
[app.main.data.shortcuts :as dsc]
|
||||||
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -24,8 +25,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.object :as obj]
|
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.strings :as ust]
|
[app.util.strings :as ust]
|
||||||
[app.util.timers :as tm]
|
[app.util.timers :as tm]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
@ -38,7 +37,7 @@
|
||||||
(ust/format-precision value 2)))
|
(ust/format-precision value 2)))
|
||||||
|
|
||||||
(defn select-all [event]
|
(defn select-all [event]
|
||||||
(dom/select-text! (dom/get-target event)))
|
(some-> event dom/get-target dom/select-text!))
|
||||||
|
|
||||||
(defn- get-next-font
|
(defn- get-next-font
|
||||||
[{:keys [id] :as current} fonts]
|
[{:keys [id] :as current} fonts]
|
||||||
|
@ -229,8 +228,8 @@
|
||||||
[:div.fonts-list
|
[:div.fonts-list
|
||||||
[:> rvt/AutoSizer {}
|
[:> rvt/AutoSizer {}
|
||||||
(fn [props]
|
(fn [props]
|
||||||
(let [width (obj/get props "width")
|
(let [width (unchecked-get props "width")
|
||||||
height (obj/get props "height")
|
height (unchecked-get props "height")
|
||||||
render #(row-renderer fonts @selected on-select-and-close %)]
|
render #(row-renderer fonts @selected on-select-and-close %)]
|
||||||
(mf/html
|
(mf/html
|
||||||
[:> rvt/List #js {:height height
|
[:> rvt/List #js {:height height
|
||||||
|
@ -241,9 +240,9 @@
|
||||||
:rowRenderer render}])))]]]]))
|
:rowRenderer render}])))]]]]))
|
||||||
(defn row-renderer
|
(defn row-renderer
|
||||||
[fonts selected on-select props]
|
[fonts selected on-select props]
|
||||||
(let [index (obj/get props "index")
|
(let [index (unchecked-get props "index")
|
||||||
key (obj/get props "key")
|
key (unchecked-get props "key")
|
||||||
style (obj/get props "style")
|
style (unchecked-get props "style")
|
||||||
font (nth fonts index)]
|
font (nth fonts index)]
|
||||||
(mf/html
|
(mf/html
|
||||||
[:& font-item {:key key
|
[:& font-item {:key key
|
||||||
|
@ -253,7 +252,8 @@
|
||||||
:current? (= (:id font) (:id selected))}])))
|
:current? (= (:id font) (:id selected))}])))
|
||||||
|
|
||||||
(mf/defc font-options
|
(mf/defc font-options
|
||||||
[{:keys [values on-change on-blur show-recent] :as props}]
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [values on-change on-blur show-recent]}]
|
||||||
(let [{:keys [font-id font-size font-variant-id]} values
|
(let [{:keys [font-id font-size font-variant-id]} values
|
||||||
|
|
||||||
font-id (or font-id (:font-id txt/default-text-attrs))
|
font-id (or font-id (:font-id txt/default-text-attrs))
|
||||||
|
@ -371,7 +371,8 @@
|
||||||
|
|
||||||
|
|
||||||
(mf/defc spacing-options
|
(mf/defc spacing-options
|
||||||
[{:keys [values on-change on-blur] :as props}]
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [values on-change on-blur]}]
|
||||||
(let [{:keys [line-height
|
(let [{:keys [line-height
|
||||||
letter-spacing]} values
|
letter-spacing]} values
|
||||||
|
|
||||||
|
@ -416,7 +417,8 @@
|
||||||
:on-blur on-blur}]]]))
|
:on-blur on-blur}]]]))
|
||||||
|
|
||||||
(mf/defc text-transform-options
|
(mf/defc text-transform-options
|
||||||
[{:keys [values on-change on-blur] :as props}]
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [values on-change on-blur]}]
|
||||||
(let [text-transform (or (:text-transform values) "none")
|
(let [text-transform (or (:text-transform values) "none")
|
||||||
handle-change
|
handle-change
|
||||||
(fn [_ type]
|
(fn [_ type]
|
||||||
|
@ -446,6 +448,7 @@
|
||||||
i/titlecase]]))
|
i/titlecase]]))
|
||||||
|
|
||||||
(mf/defc typography-options
|
(mf/defc typography-options
|
||||||
|
{::mf/wrap-props false}
|
||||||
[{:keys [ids editor values on-change on-blur show-recent]}]
|
[{:keys [ids editor values on-change on-blur show-recent]}]
|
||||||
(let [opts #js {:editor editor
|
(let [opts #js {:editor editor
|
||||||
:ids ids
|
:ids ids
|
||||||
|
@ -460,19 +463,18 @@
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:> text-transform-options opts]]]))
|
[:> text-transform-options opts]]]))
|
||||||
|
|
||||||
|
|
||||||
;; TODO: this need to be refactored, right now combines too much logic
|
|
||||||
;; and has a dropdown that behaves like a modal but is not a modal.
|
|
||||||
;; In summary, this need to a good UX/UI/IMPL rework.
|
|
||||||
|
|
||||||
(mf/defc typography-entry
|
(mf/defc typography-entry
|
||||||
[{:keys [typography local? selected? on-click on-change on-detach on-context-menu editing? focus-name? file open?]}]
|
{::mf/wrap-props false}
|
||||||
(let [hover-detach (mf/use-state false)
|
[{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? focus-name? external-open*]}]
|
||||||
|
(let [hover-detach* (mf/use-state false)
|
||||||
|
hover-detach? (deref hover-detach*)
|
||||||
|
|
||||||
name-input-ref (mf/use-ref)
|
name-input-ref (mf/use-ref)
|
||||||
on-change-ref (mf/use-ref nil)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
editable? (and local? (not read-only?))
|
||||||
editable? (and local? (not workspace-read-only?))
|
|
||||||
open? (if (nil? open?) (mf/use-state editing?) open?)
|
open* (mf/use-state editing?)
|
||||||
|
open? (deref open*)
|
||||||
|
|
||||||
on-name-blur
|
on-name-blur
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -480,11 +482,36 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [name (dom/get-target-val event)]
|
(let [name (dom/get-target-val event)]
|
||||||
(when-not (str/blank? name)
|
(when-not (str/blank? name)
|
||||||
(on-change {:name name})))))]
|
(on-change {:name name})))))
|
||||||
|
|
||||||
|
on-pointer-enter
|
||||||
|
(mf/use-fn #(reset! hover-detach* true))
|
||||||
|
|
||||||
|
on-pointer-leave
|
||||||
|
(mf/use-fn #(reset! hover-detach* false))
|
||||||
|
|
||||||
|
on-open
|
||||||
|
(mf/use-fn #(reset! open* true))
|
||||||
|
|
||||||
|
on-close
|
||||||
|
(mf/use-fn #(reset! open* false))
|
||||||
|
|
||||||
|
navigate-to-library
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps file-id)
|
||||||
|
(fn []
|
||||||
|
(when file-id
|
||||||
|
(st/emit! (dw/navigate-to-library file-id)))))
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
(mf/with-effect [editing?]
|
(mf/with-effect [editing?]
|
||||||
(when editing?
|
(when editing?
|
||||||
(reset! open? editing?)))
|
(reset! open* editing?)))
|
||||||
|
|
||||||
|
(mf/with-effect [open?]
|
||||||
|
(when (some? external-open*)
|
||||||
|
(reset! external-open* open?)))
|
||||||
|
|
||||||
(mf/with-effect [focus-name?]
|
(mf/with-effect [focus-name?]
|
||||||
(when focus-name?
|
(when focus-name?
|
||||||
|
@ -493,15 +520,12 @@
|
||||||
(dom/focus! node)
|
(dom/focus! node)
|
||||||
(dom/select-text! node)))))
|
(dom/select-text! node)))))
|
||||||
|
|
||||||
(mf/with-effect [on-change]
|
|
||||||
(mf/set-ref-val! on-change-ref {:on-change on-change}))
|
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:div.element-set-options-group.typography-entry
|
[:div.element-set-options-group.typography-entry
|
||||||
{:class (when selected? "selected")
|
{:class (when ^boolean selected? "selected")
|
||||||
:style {:display (when @open? "none")}}
|
:style {:display (when ^boolean open? "none")}}
|
||||||
[:div.typography-selection-wrapper
|
[:div.typography-selection-wrapper
|
||||||
{:class (when on-click "is-selectable")
|
{:class (when ^boolean on-click "is-selectable")
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
:on-context-menu on-context-menu}
|
:on-context-menu on-context-menu}
|
||||||
[:div.typography-sample
|
[:div.typography-sample
|
||||||
|
@ -511,20 +535,36 @@
|
||||||
(tr "workspace.assets.typography.sample")]
|
(tr "workspace.assets.typography.sample")]
|
||||||
[:div.typography-name {:title (:name typography)}(:name typography)]]
|
[:div.typography-name {:title (:name typography)}(:name typography)]]
|
||||||
[:div.element-set-actions
|
[:div.element-set-actions
|
||||||
(when on-detach
|
(when ^boolean on-detach
|
||||||
[:div.element-set-actions-button
|
[:div.element-set-actions-button
|
||||||
{:on-pointer-enter #(reset! hover-detach true)
|
{:on-pointer-enter on-pointer-enter
|
||||||
:on-pointer-leave #(reset! hover-detach false)
|
:on-pointer-leave on-pointer-leave
|
||||||
:on-click on-detach}
|
:on-click on-detach}
|
||||||
(if @hover-detach i/unchain i/chain)])
|
(if ^boolean hover-detach? i/unchain i/chain)])
|
||||||
|
|
||||||
[:div.element-set-actions-button
|
[:div.element-set-actions-button
|
||||||
{:on-click #(reset! open? true)}
|
{:on-click on-open}
|
||||||
i/actions]]]
|
i/actions]]]
|
||||||
|
|
||||||
[:& advanced-options {:visible? @open?
|
[:& advanced-options {:visible? open? :on-close on-close}
|
||||||
:on-close #(reset! open? false)}
|
(if ^boolean editable?
|
||||||
(if (not editable?)
|
[:*
|
||||||
|
[:div.element-set-content
|
||||||
|
[:div.row-flex
|
||||||
|
[:input.element-name.adv-typography-name
|
||||||
|
{:type "text"
|
||||||
|
:ref name-input-ref
|
||||||
|
:default-value (:name typography)
|
||||||
|
:on-blur on-name-blur}]
|
||||||
|
|
||||||
|
[:div.element-set-actions-button
|
||||||
|
{:on-click on-close}
|
||||||
|
i/actions]]]
|
||||||
|
|
||||||
|
[:& typography-options {:values typography
|
||||||
|
:on-change on-change
|
||||||
|
:show-recent false}]]
|
||||||
|
|
||||||
[:div.element-set-content.typography-read-only-data
|
[:div.element-set-content.typography-read-only-data
|
||||||
[:div.row-flex.typography-name
|
[:div.row-flex.typography-name
|
||||||
[:span {:title (:name typography)} (:name typography)]]
|
[:span {:title (:name typography)} (:name typography)]]
|
||||||
|
@ -534,7 +574,7 @@
|
||||||
[:span (:font-id typography)]]
|
[:span (:font-id typography)]]
|
||||||
|
|
||||||
[:div.element-set-actions-button.actions-inside
|
[:div.element-set-actions-button.actions-inside
|
||||||
{:on-click #(reset! open? false)}
|
{:on-click on-close}
|
||||||
i/actions]
|
i/actions]
|
||||||
|
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
|
@ -560,25 +600,7 @@
|
||||||
(when-not local?
|
(when-not local?
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:a.go-to-lib-button
|
[:a.go-to-lib-button
|
||||||
{:on-click #(st/emit! (rt/nav-new-window* {:rname :workspace
|
{:on-click navigate-to-library}
|
||||||
:path-params {:project-id (:project-id file)
|
|
||||||
:file-id (:id file)}
|
|
||||||
:query-params {:page-id (get-in file [:data :pages 0])}}))}
|
|
||||||
(tr "workspace.assets.typography.go-to-edit")]])]
|
(tr "workspace.assets.typography.go-to-edit")]])]
|
||||||
|
|
||||||
[:*
|
)]]))
|
||||||
[:div.element-set-content
|
|
||||||
[:div.row-flex
|
|
||||||
[:input.element-name.adv-typography-name
|
|
||||||
{:type "text"
|
|
||||||
:ref name-input-ref
|
|
||||||
:default-value (:name typography)
|
|
||||||
:on-blur on-name-blur}]
|
|
||||||
|
|
||||||
[:div.element-set-actions-button
|
|
||||||
{:on-click #(reset! open? false)}
|
|
||||||
i/actions]]]
|
|
||||||
|
|
||||||
[:& typography-options {:values typography
|
|
||||||
:on-change on-change
|
|
||||||
:show-recent false}]])]]))
|
|
||||||
|
|
|
@ -224,7 +224,7 @@
|
||||||
|
|
||||||
(defn on-context-menu
|
(defn on-context-menu
|
||||||
[hover hover-ids workspace-read-only?]
|
[hover hover-ids workspace-read-only?]
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps @hover @hover-ids workspace-read-only?)
|
(mf/deps @hover @hover-ids workspace-read-only?)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(if workspace-read-only?
|
(if workspace-read-only?
|
||||||
|
|
Loading…
Add table
Reference in a new issue