mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
♻️ Refactor version preview/restore flow
Separate enter-preview and enter-restore flows with dedicated dialogs instead of a persistent banner. Removes preview-banner component in favor of inline actions dialog. Uses backup/restore pattern for exit-preview instead of full workspace reinitialization. Adds analytics events for preview/restore actions. Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
e83efadc61
commit
c1f587d0da
@ -70,6 +70,7 @@
|
||||
(assoc :version (:version snapshot))
|
||||
(assoc :features (:features snapshot))
|
||||
(assoc :revn (:revn snapshot))
|
||||
(assoc :vern (rand-int 100000))
|
||||
(assoc :permissions perms))))))
|
||||
|
||||
(def ^:private schema:create-file-snapshot
|
||||
|
||||
@ -231,22 +231,6 @@
|
||||
(assoc :thumbnails thumbnails)
|
||||
(update :files assoc file-id file)))))
|
||||
|
||||
(defn apply-snapshot-data
|
||||
"Swap the file data in app state with the provided snapshot-file
|
||||
response. Used by the version preview feature to show historical
|
||||
file content without modifying the database.
|
||||
|
||||
Also sets workspace-file-version-id to snapshot-id so the WASM
|
||||
viewport detects the change and reloads shapes into its internal
|
||||
buffer (it only re-initialises when this value changes)."
|
||||
[file-id snapshot-id snapshot-file]
|
||||
(ptk/reify ::apply-snapshot-data
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :files assoc file-id snapshot-file)
|
||||
(assoc :workspace-file-version-id snapshot-id)))))
|
||||
|
||||
(defn zoom-to-frame
|
||||
[]
|
||||
(ptk/reify ::zoom-to-frame
|
||||
|
||||
@ -13,13 +13,16 @@
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.persistence :as dwp]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.pages :as dwpg]
|
||||
[app.main.data.workspace.thumbnails :as th]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
@ -125,32 +128,6 @@
|
||||
(rx/take 1)
|
||||
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id snapshot-id}))))
|
||||
|
||||
(defn restore-version
|
||||
[id origin]
|
||||
(assert (uuid? id) "expected valid uuid for `id`")
|
||||
(ptk/reify ::restore-version
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
team-id (:current-team-id state)
|
||||
event-name (case origin
|
||||
:version "restore-pin-version"
|
||||
:snapshot "restore-autosave"
|
||||
:plugin "restore-version-plugin")]
|
||||
|
||||
(rx/concat
|
||||
(rx/of ::dwp/force-persist
|
||||
(dw/remove-layout-flag :document-history))
|
||||
|
||||
(->> (wait-for-persistence file-id id)
|
||||
(rx/map #(initialize-version)))
|
||||
|
||||
(if event-name
|
||||
(rx/of (ev/event {::ev/name event-name
|
||||
:file-id file-id
|
||||
:team-id team-id}))
|
||||
(rx/empty)))))))
|
||||
|
||||
(defn delete-version
|
||||
[id]
|
||||
(assert (uuid? id) "expected valid uuid for `id`")
|
||||
@ -196,73 +173,145 @@
|
||||
(->> (rp/cmd! :unlock-file-snapshot {:id id})
|
||||
(rx/map fetch-versions)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; RESTORE VERSION EVENTS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- restore-version
|
||||
[id]
|
||||
(assert (uuid? id) "expected valid uuid for `id`")
|
||||
(ptk/reify ::restore-version
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)]
|
||||
(rx/concat
|
||||
(rx/of ::dwp/force-persist
|
||||
(dw/remove-layout-flag :document-history))
|
||||
|
||||
(->> (wait-for-persistence file-id id)
|
||||
(rx/map #(initialize-version))))))))
|
||||
|
||||
(defn enter-restore
|
||||
[id]
|
||||
(assert (uuid? id) "expected valid uuid for `id`")
|
||||
(ptk/reify ::restore-version
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [output-s (rx/subject)]
|
||||
(rx/merge
|
||||
output-s
|
||||
(rx/of (ntf/dialog
|
||||
:content (tr "workspace.versions.restore-warning")
|
||||
:controls :inline-actions
|
||||
:cancel {:label (tr "workspace.updates.dismiss")
|
||||
:callback #(do
|
||||
(rx/push! output-s (ntf/hide :tag :restore-dialog))
|
||||
(rx/end! output-s))}
|
||||
:accept {:label (tr "labels.restore")
|
||||
:callback #(do
|
||||
(rx/push! output-s (restore-version id))
|
||||
(rx/end! output-s))}
|
||||
:tag :restore-dialog)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; PREVIEW VERSION EVENTS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn preview-version
|
||||
"Load a snapshot into the workspace for read-only preview without
|
||||
modifying any database state. Sets a read-only flag so no changes
|
||||
are persisted while previewing."
|
||||
[id]
|
||||
(assert (uuid? id) "expected valid uuid for `id`")
|
||||
(ptk/reify ::preview-version
|
||||
(defn- apply-snapshot
|
||||
"Swap the file data in app state with the provided snapshot-file
|
||||
response. Used by the version preview feature to show historical
|
||||
file content without modifying the database"
|
||||
[{:keys [id] :as snapshot}]
|
||||
(ptk/reify ::apply-snapshot-data
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :workspace-versions assoc :preview-id id)
|
||||
(update :workspace-global assoc :read-only? true)))
|
||||
(update state :files assoc id snapshot))))
|
||||
|
||||
(defn exit-preview
|
||||
"Exit from preview mode and reload the live file data"
|
||||
[]
|
||||
(ptk/reify ::exit-preview
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [backup (dm/get-in state [:workspace-versions :backup])]
|
||||
(-> state
|
||||
(update :workspace-versions dissoc :backup)
|
||||
(update :workspace-global dissoc :read-only? :preview-id)
|
||||
(update :files assoc (:id backup) backup))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)
|
||||
file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)]
|
||||
|
||||
(rx/of (dwpg/initialize-page file-id page-id))))))
|
||||
|
||||
(defn enter-preview
|
||||
"Load a snapshot into the workspace for read-only preview without
|
||||
modifying any database state. Sets a read-only flag so no changes
|
||||
are persisted while previewing and enter on the preview mode"
|
||||
[id]
|
||||
(assert (uuid? id) "expected valid uuid for `id`")
|
||||
|
||||
(ptk/reify ::enter-preview
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [file (dsh/lookup-file state)]
|
||||
(-> state
|
||||
(update :workspace-versions assoc :backup file)
|
||||
(update :workspace-global assoc :read-only? true :preview-id id))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
features (get-in state [:files file-id :features])]
|
||||
(->> (rp/cmd! :get-file-snapshot
|
||||
{:file-id file-id
|
||||
:id id
|
||||
:features features})
|
||||
(rx/mapcat
|
||||
(fn [snapshot-file]
|
||||
(rx/of
|
||||
;; Swap the file data in state with snapshot content.
|
||||
;; Passing id sets workspace-file-version-id, which
|
||||
;; causes the WASM viewport to reload its shape buffer.
|
||||
(dw/apply-snapshot-data file-id id snapshot-file)
|
||||
;; Re-initialize the page to rebuild its search index
|
||||
;; and page-local state with the new snapshot objects.
|
||||
(dw/initialize-page file-id page-id))))
|
||||
(rx/catch (fn [err]
|
||||
;; On error roll back the read-only flag so the
|
||||
;; user is not stuck in a broken preview state.
|
||||
(log/error :hint "failed to load snapshot" :cause err :file-id file-id :snapshot-id id)
|
||||
(rx/of (update-versions-state {:preview-id nil})
|
||||
(ptk/reify ::clear-preview-read-only
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-global dissoc :read-only?)))))))))))
|
||||
team-id (:current-team-id state)
|
||||
features (features/get-enabled-features state team-id)
|
||||
snapshot (->> (dm/get-in state [:workspace-versions :data])
|
||||
(d/seek #(= id (:id %))))
|
||||
label (or (:label snapshot)
|
||||
(tr "workspace.versions.preview.unnamed"))
|
||||
output-s (rx/subject)]
|
||||
(rx/merge
|
||||
output-s
|
||||
|
||||
(defn exit-preview
|
||||
"Exit version preview mode and reload the live file data."
|
||||
[]
|
||||
(ptk/reify ::exit-preview
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :workspace-versions dissoc :preview-id)
|
||||
(update :workspace-global dissoc :read-only?)
|
||||
;; A fresh UUID triggers the WASM viewport to reload its shape
|
||||
;; buffer with the live file objects once initialize-workspace
|
||||
;; completes.
|
||||
(assoc :workspace-file-version-id (uuid/next))))
|
||||
(rx/of (ntf/dialog
|
||||
:content (tr "workspace.versions.preview-banner-title" label)
|
||||
:controls :inline-actions
|
||||
:cancel {:label (tr "labels.exit")
|
||||
:callback #(do
|
||||
(rx/push! output-s (ntf/hide))
|
||||
(rx/push! output-s (exit-preview))
|
||||
(rx/end! output-s))}
|
||||
:accept {:label (tr "labels.restore")
|
||||
:callback #(do
|
||||
(rx/push! output-s (ntf/hide))
|
||||
(rx/push! output-s (restore-version id))
|
||||
(rx/end! output-s))}
|
||||
:tag :preview-dialog))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)
|
||||
file-id (:current-file-id state)]
|
||||
;; Full workspace re-init reloads the live file from the server,
|
||||
;; clearing all snapshot data and restoring normal edit mode.
|
||||
(rx/of (dw/initialize-workspace team-id file-id))))))
|
||||
(->> (rp/cmd! :get-file-snapshot
|
||||
{:file-id file-id
|
||||
:id id
|
||||
:features features})
|
||||
(rx/mapcat
|
||||
(fn [snapshot]
|
||||
(rx/of
|
||||
;; Swap the file data in state with snapshot content.
|
||||
;; Passing id sets workspace-file-version-id, which
|
||||
;; causes the WASM viewport to reload its shape buffer.
|
||||
(apply-snapshot snapshot)
|
||||
;; Re-initialize the page to rebuild its search index
|
||||
;; and page-local state with the new snapshot
|
||||
;; objects.
|
||||
(dwpg/initialize-page file-id page-id))))
|
||||
|
||||
(rx/catch (fn [err]
|
||||
;; On error roll back the read-only flag so the
|
||||
;; user is not stuck in a broken preview state.
|
||||
(log/error :hint "failed to load snapshot" :cause err :file-id file-id :snapshot-id id)
|
||||
(rx/of (exit-preview))))))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; PLUGINS SPECIFIC EVENTS
|
||||
@ -320,9 +369,8 @@
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(rx/concat
|
||||
(rx/of (ev/event {::ev/name "restore-version-plugin"
|
||||
:file-id file-id
|
||||
:team-id team-id})
|
||||
(rx/of (ev/event {::ev/name "restore-version"
|
||||
::ev/origin "plugins"})
|
||||
::dwp/force-persist)
|
||||
|
||||
(->> (wait-for-persistence file-id id)
|
||||
|
||||
@ -134,54 +134,6 @@
|
||||
:overlay true
|
||||
:file-loading true}])
|
||||
|
||||
(def ^:private workspace-versions-ref
|
||||
(l/derived :workspace-versions st/state))
|
||||
|
||||
(mf/defc preview-banner*
|
||||
"Banner shown at the top of the workspace when the user is previewing
|
||||
a saved version. Provides Exit and Restore actions."
|
||||
{::mf/private true}
|
||||
[]
|
||||
(let [versions-state (mf/deref workspace-versions-ref)
|
||||
preview-id (:preview-id versions-state)
|
||||
preview-entry (when preview-id
|
||||
(d/seek #(= (:id %) preview-id) (:data versions-state)))
|
||||
preview-label (or (:label preview-entry)
|
||||
(tr "workspace.versions.preview.unnamed"))
|
||||
|
||||
on-exit
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (dwv/exit-preview))))
|
||||
|
||||
on-restore
|
||||
(mf/use-fn
|
||||
(mf/deps preview-id)
|
||||
(fn []
|
||||
(when preview-id
|
||||
(st/emit!
|
||||
(ntf/dialog
|
||||
:content (tr "workspace.versions.restore-warning")
|
||||
:controls :inline-actions
|
||||
:cancel {:label (tr "workspace.updates.dismiss")
|
||||
:callback #(st/emit! (ntf/hide))}
|
||||
:accept {:label (tr "labels.restore")
|
||||
:callback #(st/emit! (ntf/hide)
|
||||
(dwv/exit-preview)
|
||||
(dwv/restore-version preview-id :version))}
|
||||
:tag :restore-dialog)))))]
|
||||
|
||||
(when preview-id
|
||||
[:div {:class (stl/css :preview-banner)}
|
||||
[:span {:class (stl/css :preview-banner-label)}
|
||||
(tr "workspace.versions.preview.banner-label" preview-label)]
|
||||
[:button {:class (stl/css :preview-banner-exit-btn)
|
||||
:on-click on-exit}
|
||||
(tr "workspace.versions.preview.exit")]
|
||||
[:button {:class (stl/css :preview-banner-restore-btn)
|
||||
:on-click on-restore}
|
||||
(tr "labels.restore")]])))
|
||||
|
||||
(defn- make-team-ref
|
||||
[team-id]
|
||||
(l/derived (fn [state]
|
||||
@ -319,7 +271,6 @@
|
||||
:touch-action "none"
|
||||
:position "relative"}}
|
||||
[:> context-menu*]
|
||||
[:> preview-banner*]
|
||||
(when (and file-loaded? page-id)
|
||||
[:> workspace-inner*
|
||||
{:page-id page-id
|
||||
|
||||
@ -54,53 +54,3 @@
|
||||
grid-template-columns: deprecated.$s-20 1fr;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.preview-banner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: var(--z-index-modal);
|
||||
background: var(--color-accent-primary);
|
||||
color: var(--color-background-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: deprecated.$s-12;
|
||||
padding: deprecated.$s-8 deprecated.$s-16;
|
||||
border-radius: 0 0 deprecated.$s-8 deprecated.$s-8;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 deprecated.$s-4 deprecated.$s-16 rgb(0 0 0 / 0.25);
|
||||
}
|
||||
|
||||
.preview-banner-label {
|
||||
font-size: deprecated.$fs-12;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.preview-banner-exit-btn,
|
||||
.preview-banner-restore-btn {
|
||||
border: none;
|
||||
border-radius: deprecated.$s-4;
|
||||
cursor: pointer;
|
||||
padding: deprecated.$s-4 deprecated.$s-8;
|
||||
font-size: deprecated.$fs-11;
|
||||
}
|
||||
|
||||
.preview-banner-exit-btn {
|
||||
background: rgb(255 255 255 / 0.2);
|
||||
color: inherit;
|
||||
|
||||
&:hover {
|
||||
background: rgb(255 255 255 / 0.35);
|
||||
}
|
||||
}
|
||||
|
||||
.preview-banner-restore-btn {
|
||||
background: rgb(255 255 255 / 0.9);
|
||||
color: var(--color-accent-primary);
|
||||
font-weight: 600;
|
||||
|
||||
&:hover {
|
||||
background: rgb(255 255 255);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cfg]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.workspace.versions :as dwv]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
@ -77,17 +77,6 @@
|
||||
(assoc item :index index)))
|
||||
(reverse)))
|
||||
|
||||
(defn- open-restore-version-dialog
|
||||
[origin id]
|
||||
(st/emit! (ntf/dialog
|
||||
:content (tr "workspace.versions.restore-warning")
|
||||
:controls :inline-actions
|
||||
:cancel {:label (tr "workspace.updates.dismiss")
|
||||
:callback #(st/emit! (ntf/hide))}
|
||||
:accept {:label (tr "labels.restore")
|
||||
:callback #(st/emit! (dwv/restore-version id origin))}
|
||||
:tag :restore-dialog)))
|
||||
|
||||
(mf/defc version-entry*
|
||||
{::mf/private true}
|
||||
[{:keys [entry current-profile on-preview on-restore on-delete on-rename on-lock on-unlock on-edit on-cancel-edit is-editing]}]
|
||||
@ -352,22 +341,34 @@
|
||||
on-preview-version
|
||||
(mf/use-fn
|
||||
(fn [id]
|
||||
(st/emit! (dwv/preview-version id))))
|
||||
(st/emit! (dwv/enter-preview id)
|
||||
(ev/event {::ev/name "preview-version"
|
||||
::ev/origin "workspace:sidebar"
|
||||
:type "pinned-version"}))))
|
||||
|
||||
on-preview-snapshot
|
||||
(mf/use-fn
|
||||
(fn [id _event]
|
||||
(st/emit! (dwv/preview-version id))))
|
||||
(st/emit! (dwv/enter-preview id)
|
||||
(ev/event {::ev/name "preview-version"
|
||||
::ev/origin "workspace:sidebar"
|
||||
:type "autosaved-version"}))))
|
||||
|
||||
on-restore-version
|
||||
(mf/use-fn
|
||||
(fn [id _event]
|
||||
(open-restore-version-dialog :version id)))
|
||||
(st/emit! (dwv/enter-restore id)
|
||||
(ev/event {::ev/name "restore-version"
|
||||
::ev/origin "workspace:sidebar"
|
||||
:type "pinned-version"}))))
|
||||
|
||||
on-restore-snapshot
|
||||
(mf/use-fn
|
||||
(fn [id _event]
|
||||
(open-restore-version-dialog :snapshot id)))
|
||||
(st/emit! (dwv/enter-restore id)
|
||||
(ev/event {::ev/name "restore-version"
|
||||
::ev/origin "workspace:sidebar"
|
||||
:type "autosaved-version"}))))
|
||||
|
||||
on-delete-version
|
||||
(mf/use-fn
|
||||
|
||||
@ -97,6 +97,7 @@
|
||||
|
||||
{:keys [options-mode
|
||||
tooltip
|
||||
preview-id
|
||||
show-distances?
|
||||
picking-color?]}
|
||||
wglobal
|
||||
@ -313,23 +314,28 @@
|
||||
(hooks/setup-shortcuts path-editing? path-drawing? text-editing? grid-editing?)
|
||||
(hooks/setup-active-frames base-objects hover-ids selected active-frames zoom transform vbox)
|
||||
|
||||
[:div {:class (stl/css :viewport) :style #js {"--zoom" zoom} :data-testid "viewport"}
|
||||
(when (:can-edit permissions)
|
||||
(if read-only?
|
||||
[:> view-only-bar* {}]
|
||||
[:*
|
||||
(when-not hide-ui?
|
||||
[:> top-toolbar* {:layout layout}])
|
||||
[:div {:class (stl/css :viewport) :style {"--zoom" zoom} :data-testid "viewport"}
|
||||
(cond
|
||||
(some? preview-id)
|
||||
nil
|
||||
|
||||
(when (and ^boolean path-editing?
|
||||
^boolean single-select?)
|
||||
[:> path-edition-bar* {:shape editing-shape
|
||||
:edit-path-state edit-path-state
|
||||
:layout layout}])
|
||||
(and read-only? (:can-edit permissions))
|
||||
[:> view-only-bar* {}]
|
||||
|
||||
(when (and ^boolean grid-editing?
|
||||
^boolean single-select?)
|
||||
[:> grid-edition-bar* {:shape editing-shape}])]))
|
||||
:else
|
||||
[:*
|
||||
(when-not hide-ui?
|
||||
[:> top-toolbar* {:layout layout}])
|
||||
|
||||
(when (and ^boolean path-editing?
|
||||
^boolean single-select?)
|
||||
[:> path-edition-bar* {:shape editing-shape
|
||||
:edit-path-state edit-path-state
|
||||
:layout layout}])
|
||||
|
||||
(when (and ^boolean grid-editing?
|
||||
^boolean single-select?)
|
||||
[:> grid-edition-bar* {:shape editing-shape}])])
|
||||
|
||||
[:div {:class (stl/css :viewport-overlays)}
|
||||
;; The behaviour inside a foreign object is a bit different that in plain HTML so we wrap
|
||||
|
||||
@ -20,14 +20,12 @@
|
||||
;; branch.
|
||||
|
||||
(mf/defc view-only-bar*
|
||||
{::mf/private true}
|
||||
[]
|
||||
(let [handle-close-view-mode
|
||||
(let [on-close
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! :interrupt
|
||||
(dw/set-options-mode :design)
|
||||
(dwc/set-workspace-read-only false))))]
|
||||
#(st/emit! :interrupt
|
||||
(dw/set-options-mode :design)
|
||||
(dwc/set-workspace-read-only false)))]
|
||||
[:div {:class (stl/css :viewport-actions)}
|
||||
[:div {:class (stl/css :viewport-actions-container)}
|
||||
[:div {:class (stl/css :viewport-actions-title)}
|
||||
@ -35,7 +33,7 @@
|
||||
{:tag-name "span"
|
||||
:content (tr "workspace.top-bar.view-only")}]]
|
||||
[:button {:class (stl/css :done-btn)
|
||||
:on-click handle-close-view-mode}
|
||||
:on-click on-close}
|
||||
(tr "workspace.top-bar.read-only.done")]]]))
|
||||
|
||||
(mf/defc path-edition-bar*
|
||||
|
||||
@ -98,6 +98,7 @@
|
||||
{:keys [options-mode
|
||||
tooltip
|
||||
show-distances?
|
||||
preview-id
|
||||
picking-color?]}
|
||||
wglobal
|
||||
|
||||
@ -454,22 +455,28 @@
|
||||
(hooks/setup-active-frames base-objects hover-ids selected active-frames zoom transform vbox)
|
||||
|
||||
[:div {:class (stl/css :viewport) :style #js {"--zoom" zoom} :data-testid "viewport"}
|
||||
(when (:can-edit permissions)
|
||||
(if read-only?
|
||||
[:> view-only-bar* {}]
|
||||
[:*
|
||||
(when-not hide-ui?
|
||||
[:> top-toolbar* {:layout layout}])
|
||||
|
||||
(when (and ^boolean path-editing?
|
||||
^boolean single-select?)
|
||||
[:> path-edition-bar* {:shape editing-shape
|
||||
:edit-path-state edit-path-state
|
||||
:layout layout}])
|
||||
(cond
|
||||
(some? preview-id)
|
||||
nil
|
||||
|
||||
(when (and ^boolean grid-editing?
|
||||
^boolean single-select?)
|
||||
[:> grid-edition-bar* {:shape editing-shape}])]))
|
||||
(and read-only? (:can-edit permissions))
|
||||
[:> view-only-bar* {}]
|
||||
|
||||
:else
|
||||
[:*
|
||||
(when-not hide-ui?
|
||||
[:> top-toolbar* {:layout layout}])
|
||||
|
||||
(when (and ^boolean path-editing?
|
||||
^boolean single-select?)
|
||||
[:> path-edition-bar* {:shape editing-shape
|
||||
:edit-path-state edit-path-state
|
||||
:layout layout}])
|
||||
|
||||
(when (and ^boolean grid-editing?
|
||||
^boolean single-select?)
|
||||
[:> grid-edition-bar* {:shape editing-shape}])])
|
||||
|
||||
[:div {:class (stl/css :viewport-overlays)}
|
||||
(when show-comments?
|
||||
|
||||
@ -2960,6 +2960,9 @@ msgstr "Resend invitation"
|
||||
msgid "labels.restore"
|
||||
msgstr "Restore"
|
||||
|
||||
msgid "labels.exit"
|
||||
msgstr "Exit"
|
||||
|
||||
#: src/app/main/ui/components/progress.cljs:80, src/app/main/ui/static.cljs:299, src/app/main/ui/static.cljs:308, src/app/main/ui/static.cljs:419
|
||||
msgid "labels.retry"
|
||||
msgstr "Retry"
|
||||
@ -8878,11 +8881,8 @@ msgstr "This version is locked by %s and cannot be modified"
|
||||
msgid "workspace.versions.locked-by-you"
|
||||
msgstr "This version is locked by you"
|
||||
|
||||
msgid "workspace.versions.preview.banner-label"
|
||||
msgstr "Previewing: %s"
|
||||
|
||||
msgid "workspace.versions.preview.exit"
|
||||
msgstr "Exit preview"
|
||||
msgid "workspace.versions.preview-banner-title"
|
||||
msgstr "Previewing version: %s"
|
||||
|
||||
msgid "workspace.versions.preview.unnamed"
|
||||
msgstr "Unnamed version"
|
||||
|
||||
@ -2907,6 +2907,9 @@ msgstr "Reenviar invitacion"
|
||||
msgid "labels.restore"
|
||||
msgstr "Restaurar"
|
||||
|
||||
msgid "labels.exit"
|
||||
msgstr "Salir"
|
||||
|
||||
#: src/app/main/ui/components/progress.cljs:80, src/app/main/ui/static.cljs:299, src/app/main/ui/static.cljs:308, src/app/main/ui/static.cljs:419
|
||||
msgid "labels.retry"
|
||||
msgstr "Reintentar"
|
||||
@ -8726,6 +8729,9 @@ msgstr "Versiones de %s"
|
||||
msgid "workspace.versions.loading"
|
||||
msgstr "Cargando..."
|
||||
|
||||
msgid "workspace.versions.preview-banner-title"
|
||||
msgstr "Previsualizando version: %s"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:83
|
||||
msgid "workspace.versions.restore-warning"
|
||||
msgstr "¿Quieres restaurar esta versión?"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user