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