mirror of
https://github.com/penpot/penpot.git
synced 2025-05-14 10:46:38 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
33887711f7
17 changed files with 406 additions and 309 deletions
|
@ -207,12 +207,14 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(rx/concat
|
||||
(rx/of
|
||||
(rt/nav :workspace
|
||||
(-> (rt/get-params state)
|
||||
(assoc :page-id (:page-id thread))
|
||||
(dissoc :comment-id))
|
||||
{::rt/replace true}))
|
||||
(if (some? thread)
|
||||
(rx/of
|
||||
(rt/nav :workspace
|
||||
(-> (rt/get-params state)
|
||||
(assoc :page-id (:page-id thread))
|
||||
(dissoc :comment-id))
|
||||
{::rt/replace true}))
|
||||
(rx/empty))
|
||||
(->> (rx/of
|
||||
(dwd/select-for-drawing :comments)
|
||||
(center-to-comment-thread thread)
|
||||
|
|
|
@ -476,3 +476,24 @@
|
|||
(rx/take 1)
|
||||
(rx/map #(svg/add-svg-shapes id % position {:ignore-selection? true
|
||||
:change-selection? false}))))))
|
||||
(defn create-svg-shape-with-images
|
||||
[file-id id name svg-string position on-success on-error]
|
||||
(ptk/reify ::create-svg-shape-with-images
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (svg->clj [name svg-string])
|
||||
(rx/take 1)
|
||||
(rx/mapcat
|
||||
(fn [svg-data]
|
||||
(->> (svg/upload-images svg-data file-id)
|
||||
(rx/map #(assoc svg-data :image-data %)))))
|
||||
(rx/map
|
||||
(fn [svg-data]
|
||||
(svg/add-svg-shapes
|
||||
id
|
||||
svg-data
|
||||
position
|
||||
{:ignore-selection? true
|
||||
:change-selection? false})))
|
||||
(rx/tap on-success)
|
||||
(rx/catch on-error)))))
|
||||
|
|
|
@ -455,6 +455,7 @@
|
|||
|
||||
.modal-team-container-workspace {
|
||||
top: $s-40;
|
||||
z-index: $z-index-modal;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
project-id (:id project)
|
||||
team-id (:team-id project)
|
||||
shared? (:is-shared file)
|
||||
persistence
|
||||
(mf/deref refs/persistence)
|
||||
|
||||
persistence-status
|
||||
(get persistence :status)
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
|
@ -108,6 +113,25 @@
|
|||
{:class (stl/css :file-name)
|
||||
:title file-name
|
||||
:on-double-click start-editing-name}
|
||||
;;-- Persistende state widget
|
||||
[:div {:class (case persistence-status
|
||||
:pending (stl/css :status-notification :pending-status)
|
||||
:saving (stl/css :status-notification :saving-status)
|
||||
:saved (stl/css :status-notification :saved-status)
|
||||
:error (stl/css :status-notification :error-status)
|
||||
(stl/css :status-notification))
|
||||
:title (case persistence-status
|
||||
:pending (tr "workspace.header.saving")
|
||||
:saving (tr "workspace.header.saving")
|
||||
:saved (tr "workspace.header.saved")
|
||||
:error (tr "workspace.header.save-error")
|
||||
nil)}
|
||||
(case persistence-status
|
||||
:pending i/status-alert
|
||||
:saving i/status-alert
|
||||
:saved i/status-tick
|
||||
:error i/status-wrong
|
||||
nil)]
|
||||
file-name])]
|
||||
(when ^boolean shared?
|
||||
[:span {:class (stl/css :shared-badge)} i/library])
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
@include smallTitleTipography;
|
||||
text-transform: none;
|
||||
color: var(--title-foreground-color-hover);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.file-name-input {
|
||||
|
@ -80,3 +83,41 @@
|
|||
width: $s-16;
|
||||
}
|
||||
}
|
||||
|
||||
.status-notification {
|
||||
width: $s-6;
|
||||
height: $s-6;
|
||||
border-radius: 50%;
|
||||
margin-right: $s-4;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--status-widget-background-color-pending);
|
||||
|
||||
&.pending-status {
|
||||
background-color: var(--status-widget-background-color-warning);
|
||||
}
|
||||
|
||||
&.saving-status {
|
||||
background-color: var(--status-widget-background-color-pending);
|
||||
}
|
||||
|
||||
&.saved-status {
|
||||
background-color: var(--status-widget-background-color-success);
|
||||
animation: jump 0.3s ease-out;
|
||||
}
|
||||
|
||||
&.error-status {
|
||||
background-color: var(--status-widget-background-color-error);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes jump {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
[app.main.store :as st]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.dashboard.team]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.exports.assets :refer [export-progress-widget]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
|
@ -32,39 +33,6 @@
|
|||
(def ref:persistence-status
|
||||
(l/derived :status refs/persistence))
|
||||
|
||||
;; --- Persistence state Widget
|
||||
|
||||
(mf/defc persistence-state-widget
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[]
|
||||
(let [status (mf/deref ref:persistence-status)
|
||||
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)]
|
||||
(when-not workspace-read-only?
|
||||
[:div {:class (stl/css :persistence-status-widget)}
|
||||
(case status
|
||||
:pending
|
||||
[:div {:class (stl/css :status-icon :pending-status)
|
||||
:title (tr "workspace.header.unsaved")}
|
||||
i/status-alert]
|
||||
|
||||
:saving
|
||||
[:div {:class (stl/css :status-icon :pending-status)
|
||||
:title (tr "workspace.header.unsaved")}
|
||||
i/status-alert]
|
||||
|
||||
:saved
|
||||
[:div {:class (stl/css :status-icon :saved-status)
|
||||
:title (tr "workspace.header.saved")}
|
||||
i/status-tick]
|
||||
|
||||
:error
|
||||
[:div {:class (stl/css :status-icon :error-status)
|
||||
:title "There was an error saving the data. Please refresh if this persists."}
|
||||
i/status-wrong]
|
||||
|
||||
nil)])))
|
||||
|
||||
;; --- Zoom Widget
|
||||
|
||||
(mf/defc zoom-widget-workspace
|
||||
|
@ -216,8 +184,6 @@
|
|||
[:div {:class (stl/css :users-section)}
|
||||
[:& active-sessions]]
|
||||
|
||||
[:& persistence-state-widget]
|
||||
|
||||
[:& export-progress-widget]
|
||||
|
||||
[:div {:class (stl/css :separator)}]
|
||||
|
|
|
@ -320,7 +320,7 @@
|
|||
(tr "workspace.assets.not-found")]])]))
|
||||
|
||||
(mf/defc file-library*
|
||||
[{:keys [file is-local is-default-open? filters]}]
|
||||
[{:keys [file is-local is-default-open filters]}]
|
||||
(let [file-id (:id file)
|
||||
file-name (:name file)
|
||||
page-id (dm/get-in file [:data :pages 0])
|
||||
|
@ -376,7 +376,7 @@
|
|||
;; if the user has closed it specifically, respect that
|
||||
false
|
||||
(or force-lib-open?
|
||||
(d/nilv (:library open-status) is-default-open?)))
|
||||
(d/nilv (:library open-status) is-default-open)))
|
||||
|
||||
unselect-all
|
||||
(mf/use-fn
|
||||
|
|
|
@ -346,6 +346,25 @@
|
|||
(st/emit! (dwm/create-svg-shape id "svg" svg-string (gpt/point 0 0)))
|
||||
(shape/shape-proxy plugin-id file-id page-id id))))
|
||||
|
||||
:createShapeFromSvgWithImages
|
||||
(fn [svg-string]
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(cond
|
||||
(or (not (string? svg-string)) (empty? svg-string))
|
||||
(do
|
||||
(u/display-not-valid :createShapeFromSvg "Svg not valid")
|
||||
(reject "Svg not valid"))
|
||||
|
||||
:else
|
||||
(let [id (uuid/next)
|
||||
file-id (:current-file-id @st/state)
|
||||
page-id (:current-page-id @st/state)]
|
||||
(st/emit! (dwm/create-svg-shape-with-images
|
||||
file-id id "svg" svg-string (gpt/point 0 0)
|
||||
#(resolve (shape/shape-proxy plugin-id file-id page-id id))
|
||||
reject)))))))
|
||||
|
||||
:createBoolean
|
||||
(fn [bool-type shapes]
|
||||
(let [bool-type (keyword bool-type)]
|
||||
|
|
|
@ -641,7 +641,7 @@
|
|||
:else
|
||||
(let [component (u/proxy->library-component self)
|
||||
value (dm/str (d/nilv (:path component) "") " / " value)]
|
||||
(st/emit! (dwl/rename-component id value)))))}
|
||||
(st/emit! (dwl/rename-component-and-main-instance id value)))))}
|
||||
|
||||
:path
|
||||
{:this true
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
(u/display-not-valid :name value)
|
||||
|
||||
:else
|
||||
(st/emit! (dwsh/update-shapes [id] #(assoc % :name value))))))}
|
||||
(st/emit! (dw/end-rename-shape id value)))))}
|
||||
|
||||
:blocked
|
||||
{:this true
|
||||
|
@ -515,9 +515,10 @@
|
|||
;; not enumerable so there are no infinite loops
|
||||
:enumerable false
|
||||
:get (fn [self]
|
||||
(let [shape (u/proxy->shape self)
|
||||
parent-id (:parent-id shape)]
|
||||
(shape-proxy plugin-id (obj/get self "$file") (obj/get self "$page") parent-id)))}
|
||||
(let [shape (u/proxy->shape self)]
|
||||
(when-not (cfh/root? shape)
|
||||
(let [parent-id (:parent-id shape)]
|
||||
(shape-proxy plugin-id (obj/get self "$file") (obj/get self "$page") parent-id)))))}
|
||||
|
||||
:parentX
|
||||
{:this true
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.viewport :as dwv]
|
||||
[app.main.data.workspace.zoom :as dwz]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.format :as format]
|
||||
[app.plugins.shape :as ps]
|
||||
[app.plugins.utils :as u]
|
||||
[app.util.object :as obj]))
|
||||
|
||||
|
@ -85,12 +85,13 @@
|
|||
|
||||
:zoomIntoView
|
||||
(fn [shapes]
|
||||
(let [ids
|
||||
(->> shapes
|
||||
(map (fn [v]
|
||||
(if (string? v)
|
||||
(uuid/uuid v)
|
||||
(uuid/uuid (obj/get v "x"))))))]
|
||||
(st/emit! (dwz/fit-to-shapes ids))))))
|
||||
(cond
|
||||
(not (every? ps/shape-proxy? shapes))
|
||||
(u/display-not-valid :zoomIntoView "Argument should be valid shapes")
|
||||
|
||||
:else
|
||||
(let [ids (->> shapes
|
||||
(map (fn [shape] (obj/get shape "$id"))))]
|
||||
(st/emit! (dwz/fit-to-shapes ids)))))))
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue