mirror of
https://github.com/penpot/penpot.git
synced 2025-06-13 01:41:38 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
e4c9b736f7
26 changed files with 170 additions and 167 deletions
39
CHANGES.md
39
CHANGES.md
|
@ -24,29 +24,31 @@
|
||||||
- The plugin list in the navigation menu lacks scrolling, some plugins are not visible when a large number are installed [Taiga #9360](https://tree.taiga.io/project/penpot/us/9360)
|
- The plugin list in the navigation menu lacks scrolling, some plugins are not visible when a large number are installed [Taiga #9360](https://tree.taiga.io/project/penpot/us/9360)
|
||||||
- Fix hidden toolbar click event still available [Taiga #10437](https://tree.taiga.io/project/penpot/us/10437)
|
- Fix hidden toolbar click event still available [Taiga #10437](https://tree.taiga.io/project/penpot/us/10437)
|
||||||
|
|
||||||
## 2.5.3
|
|
||||||
|
|
||||||
### :rocket: Epics and highlights
|
## 2.5.4 (Unreleased)
|
||||||
|
|
||||||
### :boom: Breaking changes & Deprecations
|
|
||||||
|
|
||||||
### :heart: Community contributions (Thank you!)
|
|
||||||
|
|
||||||
### :sparkles: New features
|
### :sparkles: New features
|
||||||
|
|
||||||
|
- Add support for WEBP format on shape export [Github #6053](https://github.com/penpot/penpot/pull/6053) and [Github #6074](https://github.com/penpot/penpot/pull/6074)
|
||||||
|
|
||||||
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
- Fix feature loading on workspace when opening a file in a background
|
||||||
|
tab [Taiga #10377](https://tree.taiga.io/project/penpot/issue/10377)
|
||||||
|
- Fix minor inconsistencies on RPC `get-file-libraries` and `get-file`
|
||||||
|
methods (add missing team-id prop)
|
||||||
|
|
||||||
|
|
||||||
|
## 2.5.3
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
- Component sync issues with multiple tabs [Taiga #10471](https://tree.taiga.io/project/penpot/issue/10471)
|
- Component sync issues with multiple tabs [Taiga #10471](https://tree.taiga.io/project/penpot/issue/10471)
|
||||||
|
|
||||||
## 2.5.2
|
## 2.5.2
|
||||||
|
|
||||||
### :rocket: Epics and highlights
|
|
||||||
|
|
||||||
### :boom: Breaking changes & Deprecations
|
|
||||||
|
|
||||||
### :heart: Community contributions (Thank you!)
|
|
||||||
|
|
||||||
### :sparkles: New features
|
### :sparkles: New features
|
||||||
|
|
||||||
- When the workspace is empty, set default the board creation tool [Taiga #9425](https://tree.taiga.io/project/penpot/us/9425)
|
- When the workspace is empty, set default the board creation tool [Taiga #9425](https://tree.taiga.io/project/penpot/us/9425)
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
@ -58,22 +60,12 @@
|
||||||
|
|
||||||
## 2.5.1
|
## 2.5.1
|
||||||
|
|
||||||
### :rocket: Epics and highlights
|
|
||||||
|
|
||||||
### :boom: Breaking changes & Deprecations
|
|
||||||
|
|
||||||
### :heart: Community contributions (Thank you!)
|
|
||||||
|
|
||||||
### :sparkles: New features
|
### :sparkles: New features
|
||||||
|
|
||||||
- Improve Nginx entryponit to get the resolvers dinamically by default
|
- Improve Nginx entryponit to get the resolvers dinamically by default
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
|
||||||
|
|
||||||
## 2.5.0
|
## 2.5.0
|
||||||
|
|
||||||
### :rocket: Epics and highlights
|
|
||||||
|
|
||||||
### :boom: Breaking changes & Deprecations
|
### :boom: Breaking changes & Deprecations
|
||||||
|
|
||||||
Although this is not a breaking change, we believe it’s important to highlight it in this
|
Although this is not a breaking change, we believe it’s important to highlight it in this
|
||||||
|
@ -102,9 +94,6 @@ If you have a big database and many cores available, you can reduce the time of
|
||||||
all files by increasing paralelizacion changing the `max-jobs` value from 1 to N (where N
|
all files by increasing paralelizacion changing the `max-jobs` value from 1 to N (where N
|
||||||
is a number of cores)
|
is a number of cores)
|
||||||
|
|
||||||
|
|
||||||
### :heart: Community contributions (Thank you!)
|
|
||||||
|
|
||||||
### :sparkles: New features
|
### :sparkles: New features
|
||||||
|
|
||||||
- [GRADIENTS] New gradients UI with multi-stop support. [Taiga #3418](https://tree.taiga.io/project/penpot/epic/3418)
|
- [GRADIENTS] New gradients UI with multi-stop support. [Taiga #3418](https://tree.taiga.io/project/penpot/epic/3418)
|
||||||
|
|
|
@ -323,6 +323,7 @@
|
||||||
|
|
||||||
file (-> (get-file cfg id :project-id project-id)
|
file (-> (get-file cfg id :project-id project-id)
|
||||||
(assoc :permissions perms)
|
(assoc :permissions perms)
|
||||||
|
(assoc :team-id (:id team))
|
||||||
(check-version!))]
|
(check-version!))]
|
||||||
|
|
||||||
(-> (cfeat/get-team-enabled-features cf/flags team)
|
(-> (cfeat/get-team-enabled-features cf/flags team)
|
||||||
|
@ -613,6 +614,7 @@
|
||||||
SELECT l.id,
|
SELECT l.id,
|
||||||
l.features,
|
l.features,
|
||||||
l.project_id,
|
l.project_id,
|
||||||
|
p.team_id,
|
||||||
l.created_at,
|
l.created_at,
|
||||||
l.modified_at,
|
l.modified_at,
|
||||||
l.deleted_at,
|
l.deleted_at,
|
||||||
|
@ -622,6 +624,7 @@
|
||||||
l.synced_at,
|
l.synced_at,
|
||||||
l.is_shared
|
l.is_shared
|
||||||
FROM libs AS l
|
FROM libs AS l
|
||||||
|
INNER JOIN project AS p ON (p.id = l.project_id)
|
||||||
WHERE l.deleted_at IS NULL OR l.deleted_at > now();")
|
WHERE l.deleted_at IS NULL OR l.deleted_at > now();")
|
||||||
|
|
||||||
(defn get-file-libraries
|
(defn get-file-libraries
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.schema :as sm]))
|
[app.common.schema :as sm]))
|
||||||
|
|
||||||
(def types #{:png :jpeg :svg :pdf})
|
(def types #{:png :jpeg :webp :svg :pdf})
|
||||||
|
|
||||||
(def schema:export
|
(def schema:export
|
||||||
[:map {:title "ShapeExport"}
|
[:map {:title "ShapeExport"}
|
||||||
|
|
|
@ -27,7 +27,7 @@ title: 07· Exporting objects
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Size</strong> - Options for the most common sizing scales.</li>
|
<li><strong>Size</strong> - Options for the most common sizing scales.</li>
|
||||||
<li><strong>Suffix</strong> - Especially useful if you are exporting at different scales.</li>
|
<li><strong>Suffix</strong> - Especially useful if you are exporting at different scales.</li>
|
||||||
<li><strong>File format</strong> - PNG, SVG, JPEG, PDF.</li>
|
<li><strong>File format</strong> - PNG, JPEG, WEBP, SVG, PDF.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 id="export-multiple-elements">Exporting multiple elements</h2>
|
<h2 id="export-multiple-elements">Exporting multiple elements</h2>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
(s/def ::name ::us/string)
|
(s/def ::name ::us/string)
|
||||||
(s/def ::suffix ::us/string)
|
(s/def ::suffix ::us/string)
|
||||||
(s/def ::type #{:jpeg :png :pdf :svg})
|
(s/def ::type #{:png :jpeg :webp :pdf :svg})
|
||||||
(s/def ::page-id ::us/uuid)
|
(s/def ::page-id ::us/uuid)
|
||||||
(s/def ::file-id ::us/uuid)
|
(s/def ::file-id ::us/uuid)
|
||||||
(s/def ::share-id ::us/uuid)
|
(s/def ::share-id ::us/uuid)
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
(case type
|
(case type
|
||||||
:png (rb/render params on-object)
|
:png (rb/render params on-object)
|
||||||
:jpeg (rb/render params on-object)
|
:jpeg (rb/render params on-object)
|
||||||
|
:webp (rb/render params on-object)
|
||||||
:pdf (rp/render params on-object)
|
:pdf (rp/render params on-object)
|
||||||
:svg (rs/render params on-object)))
|
:svg (rs/render params on-object)))
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,11 @@
|
||||||
(bw/wait-for node)
|
(bw/wait-for node)
|
||||||
(case type
|
(case type
|
||||||
:png (bw/screenshot node {:omit-background? true :type type :path path})
|
:png (bw/screenshot node {:omit-background? true :type type :path path})
|
||||||
:jpeg (bw/screenshot node {:omit-background? false :type type :path path}))
|
:jpeg (bw/screenshot node {:omit-background? false :type type :path path})
|
||||||
|
:webp (p/let [png-path (sh/tempfile :prefix "penpot.tmp.render.bitmap." :suffix ".png")]
|
||||||
|
;; playwright only supports jpg and png, we need to convert it afterwards
|
||||||
|
(bw/screenshot node {:omit-background? true :type :png :path png-path})
|
||||||
|
(sh/run-cmd! (str "convert " png-path " -quality 100 WEBP:" path))))
|
||||||
(on-object (assoc object :path path))))
|
(on-object (assoc object :path path))))
|
||||||
|
|
||||||
(render [uri page]
|
(render [uri page]
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
(case type
|
(case type
|
||||||
:png ".png"
|
:png ".png"
|
||||||
:jpeg ".jpg"
|
:jpeg ".jpg"
|
||||||
|
:webp ".webp"
|
||||||
:svg ".svg"
|
:svg ".svg"
|
||||||
:pdf ".pdf"
|
:pdf ".pdf"
|
||||||
:zip ".zip"))
|
:zip ".zip"))
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
:pdf "application/pdf"
|
:pdf "application/pdf"
|
||||||
:svg "image/svg+xml"
|
:svg "image/svg+xml"
|
||||||
:jpeg "image/jpeg"
|
:jpeg "image/jpeg"
|
||||||
:png "image/png"))
|
:png "image/png"
|
||||||
|
:webp "image/webp"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
(declare process-message)
|
(declare process-message)
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize
|
||||||
[]
|
[team-id]
|
||||||
|
(assert (uuid? team-id) "expected uuid instance for `team-id`")
|
||||||
|
|
||||||
(ptk/reify ::initialize
|
(ptk/reify ::initialize
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
|
@ -47,8 +49,8 @@
|
||||||
profile-id (:profile-id state)]
|
profile-id (:profile-id state)]
|
||||||
|
|
||||||
(->> (rx/merge
|
(->> (rx/merge
|
||||||
(rx/of (fetch-projects)
|
(rx/of (fetch-projects team-id)
|
||||||
(df/fetch-fonts))
|
(df/fetch-fonts team-id))
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter (ptk/type? ::dws/message))
|
(rx/filter (ptk/type? ::dws/message))
|
||||||
(rx/map deref)
|
(rx/map deref)
|
||||||
|
@ -61,8 +63,8 @@
|
||||||
(rx/take-until stopper))))))
|
(rx/take-until stopper))))))
|
||||||
|
|
||||||
(defn finalize
|
(defn finalize
|
||||||
[]
|
[team-id]
|
||||||
(ptk/data-event ::finalize {}))
|
(ptk/data-event ::finalize {:team-id team-id}))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Data Fetching (context aware: current team)
|
;; Data Fetching (context aware: current team)
|
||||||
|
@ -70,7 +72,7 @@
|
||||||
|
|
||||||
;; --- EVENT: fetch-projects
|
;; --- EVENT: fetch-projects
|
||||||
|
|
||||||
(defn projects-fetched
|
(defn- projects-fetched
|
||||||
[projects]
|
[projects]
|
||||||
(ptk/reify ::projects-fetched
|
(ptk/reify ::projects-fetched
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -81,13 +83,12 @@
|
||||||
projects))))
|
projects))))
|
||||||
|
|
||||||
(defn fetch-projects
|
(defn fetch-projects
|
||||||
[]
|
[team-id]
|
||||||
(ptk/reify ::fetch-projects
|
(ptk/reify ::fetch-projects
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ _ _]
|
||||||
(let [team-id (:current-team-id state)]
|
(->> (rp/cmd! :get-projects {:team-id team-id})
|
||||||
(->> (rp/cmd! :get-projects {:team-id team-id})
|
(rx/map projects-fetched)))))
|
||||||
(rx/map projects-fetched))))))
|
|
||||||
|
|
||||||
;; --- EVENT: search
|
;; --- EVENT: search
|
||||||
|
|
||||||
|
@ -116,7 +117,7 @@
|
||||||
|
|
||||||
;; --- EVENT: recent-files
|
;; --- EVENT: recent-files
|
||||||
|
|
||||||
(defn recent-files-fetched
|
(defn- recent-files-fetched
|
||||||
[files]
|
[files]
|
||||||
(ptk/reify ::recent-files-fetched
|
(ptk/reify ::recent-files-fetched
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -127,13 +128,14 @@
|
||||||
(update :files d/merge files))))))
|
(update :files d/merge files))))))
|
||||||
|
|
||||||
(defn fetch-recent-files
|
(defn fetch-recent-files
|
||||||
[]
|
([] (fetch-recent-files nil))
|
||||||
(ptk/reify ::fetch-recent-files
|
([team-id]
|
||||||
ptk/WatchEvent
|
(ptk/reify ::fetch-recent-files
|
||||||
(watch [_ state _]
|
ptk/WatchEvent
|
||||||
(let [team-id (:current-team-id state)]
|
(watch [_ state _]
|
||||||
(->> (rp/cmd! :get-team-recent-files {:team-id team-id})
|
(when-let [team-id (or team-id (:current-team-id state))]
|
||||||
(rx/map recent-files-fetched))))))
|
(->> (rp/cmd! :get-team-recent-files {:team-id team-id})
|
||||||
|
(rx/map recent-files-fetched)))))))
|
||||||
|
|
||||||
;; --- EVENT: fetch-template-files
|
;; --- EVENT: fetch-template-files
|
||||||
|
|
||||||
|
|
|
@ -266,10 +266,10 @@
|
||||||
(defn export-shapes-event
|
(defn export-shapes-event
|
||||||
[exports origin]
|
[exports origin]
|
||||||
(let [types (reduce (fn [counts {:keys [type]}]
|
(let [types (reduce (fn [counts {:keys [type]}]
|
||||||
(if (#{:png :pdf :svg :jpeg} type)
|
(if (#{:png :jpeg :webp :svg :pdf} type)
|
||||||
(update counts type inc)
|
(update counts type inc)
|
||||||
counts))
|
counts))
|
||||||
{:png 0, :pdf 0, :svg 0, :jpeg 0}
|
{:png 0, :jpeg 0, :webp 0, :pdf 0, :svg 0}
|
||||||
exports)]
|
exports)]
|
||||||
(ptk/event
|
(ptk/event
|
||||||
::ev/event (merge types
|
::ev/event (merge types
|
||||||
|
|
|
@ -73,13 +73,12 @@
|
||||||
(fonts/register! :custom fonts))))))
|
(fonts/register! :custom fonts))))))
|
||||||
|
|
||||||
(defn fetch-fonts
|
(defn fetch-fonts
|
||||||
[]
|
[team-id]
|
||||||
(ptk/reify ::load-team-fonts
|
(ptk/reify ::fetch-fonts
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ _ _]
|
||||||
(let [team-id (:current-team-id state)]
|
(->> (rp/cmd! :get-font-variants {:team-id team-id})
|
||||||
(->> (rp/cmd! :get-font-variants {:team-id team-id})
|
(rx/map fonts-fetched)))))
|
||||||
(rx/map fonts-fetched))))))
|
|
||||||
|
|
||||||
(defn process-upload
|
(defn process-upload
|
||||||
"Given a seq of blobs and the team id, creates a ready-to-use fonts
|
"Given a seq of blobs and the team id, creates a ready-to-use fonts
|
||||||
|
|
|
@ -64,13 +64,14 @@
|
||||||
(update :profiles merge (d/index-by :id members))))))
|
(update :profiles merge (d/index-by :id members))))))
|
||||||
|
|
||||||
(defn fetch-members
|
(defn fetch-members
|
||||||
[]
|
([] (fetch-members nil))
|
||||||
(ptk/reify ::fetch-members
|
([team-id]
|
||||||
ptk/WatchEvent
|
(ptk/reify ::fetch-members
|
||||||
(watch [_ state _]
|
ptk/WatchEvent
|
||||||
(let [team-id (:current-team-id state)]
|
(watch [_ state _]
|
||||||
(->> (rp/cmd! :get-team-members {:team-id team-id})
|
(when-let [team-id (or team-id (:current-team-id state))]
|
||||||
(rx/map (partial members-fetched team-id)))))))
|
(->> (rp/cmd! :get-team-members {:team-id team-id})
|
||||||
|
(rx/map (partial members-fetched team-id))))))))
|
||||||
|
|
||||||
(defn- invitations-fetched
|
(defn- invitations-fetched
|
||||||
[team-id invitations]
|
[team-id invitations]
|
||||||
|
@ -88,41 +89,20 @@
|
||||||
(->> (rp/cmd! :get-team-invitations {:team-id team-id})
|
(->> (rp/cmd! :get-team-invitations {:team-id team-id})
|
||||||
(rx/map (partial invitations-fetched team-id)))))))
|
(rx/map (partial invitations-fetched team-id)))))))
|
||||||
|
|
||||||
(defn set-current-team
|
|
||||||
[{:keys [id permissions features] :as team}]
|
|
||||||
(ptk/reify ::set-current-team
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(-> state
|
|
||||||
;; FIXME: redundant operation, only necessary on workspace
|
|
||||||
;; until workspace initialization is refactored
|
|
||||||
(update-in [:teams id] merge team)
|
|
||||||
(assoc :permissions permissions)
|
|
||||||
;; FIXME: this is a redundant operation that only needed by
|
|
||||||
;; workspace; ti will not be needed after workspace
|
|
||||||
;; bootstrap & urls refactor
|
|
||||||
(assoc :current-team-id id)))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ _]
|
|
||||||
(rx/of (features/initialize (or features #{}))))
|
|
||||||
|
|
||||||
ptk/EffectEvent
|
|
||||||
(effect [_ _ _]
|
|
||||||
(swap! storage/global assoc ::current-team-id id))))
|
|
||||||
|
|
||||||
(defn- team-initialized
|
(defn- team-initialized
|
||||||
[]
|
[team-id]
|
||||||
(ptk/reify ::team-initialized
|
(ptk/reify ::team-initialized
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [team-id (:current-team-id state)
|
(let [teams (get state :teams)
|
||||||
teams (get state :teams)
|
team (get teams team-id)]
|
||||||
team (get teams team-id)]
|
|
||||||
(if (not team)
|
(if (not team)
|
||||||
(rx/throw (ex/error :type :authentication))
|
(rx/throw (ex/error :type :authentication))
|
||||||
(rx/of (set-current-team team)
|
(let [permissions (get team :permissions)
|
||||||
(fetch-members)))))))
|
features (get team :features)]
|
||||||
|
(rx/of #(assoc % :permissions permissions)
|
||||||
|
(features/initialize (or features #{}))
|
||||||
|
(fetch-members team-id))))))))
|
||||||
|
|
||||||
(defn initialize-team
|
(defn initialize-team
|
||||||
[team-id]
|
[team-id]
|
||||||
|
@ -138,8 +118,7 @@
|
||||||
(rx/of (fetch-teams))
|
(rx/of (fetch-teams))
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter (ptk/type? ::teams-fetched))
|
(rx/filter (ptk/type? ::teams-fetched))
|
||||||
(rx/observe-on :async)
|
(rx/map (partial team-initialized team-id))))
|
||||||
(rx/map team-initialized)))
|
|
||||||
(rx/take-until stopper))))))
|
(rx/take-until stopper))))))
|
||||||
|
|
||||||
(defn finalize-team
|
(defn finalize-team
|
||||||
|
@ -169,7 +148,7 @@
|
||||||
params (assoc params :team-id team-id)]
|
params (assoc params :team-id team-id)]
|
||||||
(->> (rp/cmd! :update-team-member-role params)
|
(->> (rp/cmd! :update-team-member-role params)
|
||||||
(rx/mapcat (fn [_]
|
(rx/mapcat (fn [_]
|
||||||
(rx/of (fetch-members)
|
(rx/of (fetch-members team-id)
|
||||||
(fetch-teams)
|
(fetch-teams)
|
||||||
(ptk/data-event ::ev/event
|
(ptk/data-event ::ev/event
|
||||||
{::ev/name "update-team-member-role"
|
{::ev/name "update-team-member-role"
|
||||||
|
@ -187,7 +166,7 @@
|
||||||
params (assoc params :team-id team-id)]
|
params (assoc params :team-id team-id)]
|
||||||
(->> (rp/cmd! :delete-team-member params)
|
(->> (rp/cmd! :delete-team-member params)
|
||||||
(rx/mapcat (fn [_]
|
(rx/mapcat (fn [_]
|
||||||
(rx/of (fetch-members)
|
(rx/of (fetch-members team-id)
|
||||||
(fetch-teams)
|
(fetch-teams)
|
||||||
(ptk/data-event ::ev/event
|
(ptk/data-event ::ev/event
|
||||||
{::ev/name "delete-team-member"
|
{::ev/name "delete-team-member"
|
||||||
|
|
|
@ -291,7 +291,8 @@
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [features (features/get-team-enabled-features state)
|
(let [features (features/get-team-enabled-features state)
|
||||||
render-wasm? (contains? features "render-wasm/v1")
|
render-wasm? (contains? features "render-wasm/v1")
|
||||||
stopper-s (rx/filter (ptk/type? ::finalize-workspace) stream)]
|
stopper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
||||||
|
team-id (:current-team-id state)]
|
||||||
|
|
||||||
(->> (rx/concat
|
(->> (rx/concat
|
||||||
;; Firstly load wasm module if it is enabled and fonts
|
;; Firstly load wasm module if it is enabled and fonts
|
||||||
|
@ -305,7 +306,7 @@
|
||||||
(rx/filter (ptk/type? ::df/fonts-loaded))
|
(rx/filter (ptk/type? ::df/fonts-loaded))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/ignore))
|
(rx/ignore))
|
||||||
(rx/of (df/fetch-fonts)))
|
(rx/of (df/fetch-fonts team-id)))
|
||||||
|
|
||||||
;; Then fetch file and thumbnails
|
;; Then fetch file and thumbnails
|
||||||
(->> (rx/zip (rp/cmd! :get-file {:id file-id :features features})
|
(->> (rx/zip (rp/cmd! :get-file {:id file-id :features features})
|
||||||
|
@ -335,7 +336,7 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(log/debug :hint "initialize-workspace" :file-id file-id)
|
(log/debug :hint "initialize-workspace" :file-id (dm/str file-id))
|
||||||
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
||||||
rparams (rt/get-params state)]
|
rparams (rt/get-params state)]
|
||||||
|
|
||||||
|
|
|
@ -210,42 +210,45 @@
|
||||||
(swap! storage/session dissoc :plugin-url))))))
|
(swap! storage/session dissoc :plugin-url))))))
|
||||||
|
|
||||||
(defn use-templates-import
|
(defn use-templates-import
|
||||||
[can-edit? template-url default-project-id]
|
[can-edit? template-url project]
|
||||||
(mf/with-layout-effect
|
(let [project-id (get project :id)
|
||||||
[can-edit? template-url default-project-id]
|
team-id (get project :team-id)]
|
||||||
(when (and (some? template-url) (some? default-project-id))
|
(mf/with-layout-effect [can-edit? template-url project-id team-id]
|
||||||
(if can-edit?
|
(when (and (some? template-url)
|
||||||
(let [valid-url? (and (str/ends-with? template-url ".penpot")
|
(some? project-id)
|
||||||
(str/starts-with? template-url cf/templates-uri))
|
(some? team-id))
|
||||||
template-name (when valid-url? (subs template-url (count cf/templates-uri)))
|
(if can-edit?
|
||||||
on-import #(st/emit! (dpj/fetch-files default-project-id)
|
(let [valid-url? (and (str/ends-with? template-url ".penpot")
|
||||||
(dd/fetch-recent-files)
|
(str/starts-with? template-url cf/templates-uri))
|
||||||
(dd/fetch-projects)
|
template-name (when valid-url? (subs template-url (count cf/templates-uri)))
|
||||||
(dd/clear-selected-files)
|
on-import #(st/emit! (dpj/fetch-files project-id)
|
||||||
(ptk/event ::ev/event {::ev/name "install-template-from-link-finished"
|
(dd/fetch-recent-files team-id)
|
||||||
:name template-name
|
(dd/fetch-projects team-id)
|
||||||
:url template-url}))]
|
(dd/clear-selected-files)
|
||||||
(if valid-url?
|
(ptk/event ::ev/event {::ev/name "install-template-from-link-finished"
|
||||||
(do
|
:name template-name
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url}))
|
:url template-url}))]
|
||||||
(->> (http/send! {:method :get
|
(if valid-url?
|
||||||
:uri template-url
|
(do
|
||||||
:response-type :blob
|
(st/emit! (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url}))
|
||||||
:omit-default-headers true})
|
(->> (http/send! {:method :get
|
||||||
(rx/subs!
|
:uri template-url
|
||||||
(fn [result]
|
:response-type :blob
|
||||||
(if (or (< (:status result) 200) (>= (:status result) 300))
|
:omit-default-headers true})
|
||||||
(st/emit! (notif/error (tr "dashboard.import.error")))
|
(rx/subs!
|
||||||
(st/emit! (modal/show
|
(fn [result]
|
||||||
{:type :import
|
(if (or (< (:status result) 200) (>= (:status result) 300))
|
||||||
:project-id default-project-id
|
(st/emit! (notif/error (tr "dashboard.import.error")))
|
||||||
:entries [{:name template-name :uri (wapi/create-uri (:body result))}]
|
(st/emit! (modal/show
|
||||||
:on-finish-import on-import})))))))
|
{:type :import
|
||||||
(st/emit! (notif/error (tr "dashboard.import.bad-url")))))
|
:project-id project-id
|
||||||
(st/emit! (notif/error (tr "dashboard.import.no-perms"))))
|
:entries [{:name template-name :uri (wapi/create-uri (:body result))}]
|
||||||
|
:on-finish-import on-import})))))))
|
||||||
|
(st/emit! (notif/error (tr "dashboard.import.bad-url")))))
|
||||||
|
(st/emit! (notif/error (tr "dashboard.import.no-perms"))))
|
||||||
|
|
||||||
(binding [storage/*sync* true]
|
(binding [storage/*sync* true]
|
||||||
(swap! storage/session dissoc :template-url)))))
|
(swap! storage/session dissoc :template-url))))))
|
||||||
|
|
||||||
(mf/defc dashboard*
|
(mf/defc dashboard*
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
|
@ -270,10 +273,10 @@
|
||||||
|
|
||||||
(hooks/use-shortcuts ::dashboard sc/shortcuts)
|
(hooks/use-shortcuts ::dashboard sc/shortcuts)
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect [team-id]
|
||||||
(st/emit! (dd/initialize))
|
(st/emit! (dd/initialize team-id))
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/finalize))))
|
(st/emit! (dd/finalize team-id))))
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(let [key (events/listen goog/global "keydown"
|
(let [key (events/listen goog/global "keydown"
|
||||||
|
@ -285,7 +288,7 @@
|
||||||
(events/unlistenByKey key))))
|
(events/unlistenByKey key))))
|
||||||
|
|
||||||
(use-plugin-register plugin-url team-id (:id default-project))
|
(use-plugin-register plugin-url team-id (:id default-project))
|
||||||
(use-templates-import can-edit? template-url (:id default-project))
|
(use-templates-import can-edit? template-url default-project)
|
||||||
|
|
||||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||||
[:> modal-container*]
|
[:> modal-container*]
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
(st/emit! (dcm/go-to-dashboard-files
|
(st/emit! (dcm/go-to-dashboard-files
|
||||||
{:project-id project-id
|
{:project-id project-id
|
||||||
:team-id team-id}))
|
:team-id team-id}))
|
||||||
(st/emit! (dd/fetch-recent-files)
|
(st/emit! (dd/fetch-recent-files team-id)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
||||||
on-move-accept
|
on-move-accept
|
||||||
|
|
|
@ -566,8 +566,9 @@
|
||||||
|
|
||||||
on-finish-import
|
on-finish-import
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
(mf/deps team-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/fetch-recent-files)
|
(st/emit! (dd/fetch-recent-files team-id)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
||||||
import-files (use-import-file project-id on-finish-import)
|
import-files (use-import-file project-id on-finish-import)
|
||||||
|
@ -608,9 +609,10 @@
|
||||||
|
|
||||||
on-drop-success
|
on-drop-success
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
(mf/deps team-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ntf/success (tr "dashboard.success-move-file"))
|
(st/emit! (ntf/success (tr "dashboard.success-move-file"))
|
||||||
(dd/fetch-recent-files)
|
(dd/fetch-recent-files team-id)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
|
|
|
@ -344,11 +344,13 @@
|
||||||
|
|
||||||
continue-template
|
continue-template
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
(mf/deps on-finish-import)
|
||||||
(fn [template]
|
(fn [template]
|
||||||
(let [on-success
|
(let [on-success
|
||||||
(fn [_event]
|
(fn [_event]
|
||||||
(reset! status* :import-success)
|
(reset! status* :import-success)
|
||||||
(st/emit! (dd/fetch-recent-files)))
|
(when (fn? on-finish-import)
|
||||||
|
(on-finish-import)))
|
||||||
|
|
||||||
on-error
|
on-error
|
||||||
(fn [cause]
|
(fn [cause]
|
||||||
|
@ -479,8 +481,6 @@
|
||||||
[:> import-entry* {:entry (assoc template :status status)
|
[:> import-entry* {:entry (assoc template :status status)
|
||||||
:can-be-deleted false}])]
|
:can-be-deleted false}])]
|
||||||
|
|
||||||
;; (prn "import-dialog" status)
|
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-footer)}
|
[:div {:class (stl/css :modal-footer)}
|
||||||
[:div {:class (stl/css :action-buttons)}
|
[:div {:class (stl/css :action-buttons)}
|
||||||
(when (= :analyze status)
|
(when (= :analyze status)
|
||||||
|
|
|
@ -105,7 +105,8 @@
|
||||||
[{:keys [project is-first team files can-edit]}]
|
[{:keys [project is-first team files can-edit]}]
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [locale (mf/deref i18n/locale)
|
||||||
|
|
||||||
project-id (:id project)
|
project-id (get project :id)
|
||||||
|
team-id (get team :id)
|
||||||
|
|
||||||
file-count (or (:count project) 0)
|
file-count (or (:count project) 0)
|
||||||
is-draft? (:is-default project)
|
is-draft? (:is-default project)
|
||||||
|
@ -191,11 +192,11 @@
|
||||||
|
|
||||||
on-import
|
on-import
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps project-id)
|
(mf/deps project-id team-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dpj/fetch-files project-id)
|
(st/emit! (dpj/fetch-files project-id)
|
||||||
(dd/fetch-recent-files)
|
(dd/fetch-recent-files team-id)
|
||||||
(dd/fetch-projects)
|
(dd/fetch-projects team-id)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
||||||
handle-create-click
|
handle-create-click
|
||||||
|
@ -317,6 +318,8 @@
|
||||||
(sort-by :modified-at)
|
(sort-by :modified-at)
|
||||||
(reverse)))
|
(reverse)))
|
||||||
|
|
||||||
|
team-id (get team :id)
|
||||||
|
|
||||||
recent-map (mf/deref ref:recent-files)
|
recent-map (mf/deref ref:recent-files)
|
||||||
permisions (:permissions team)
|
permisions (:permissions team)
|
||||||
|
|
||||||
|
@ -327,7 +330,7 @@
|
||||||
show-team-hero* (mf/use-state #(get storage/global ::show-team-hero true))
|
show-team-hero* (mf/use-state #(get storage/global ::show-team-hero true))
|
||||||
show-team-hero? (deref show-team-hero*)
|
show-team-hero? (deref show-team-hero*)
|
||||||
|
|
||||||
is-my-penpot (= (:default-team-id profile) (:id team))
|
is-my-penpot (= (:default-team-id profile) team-id)
|
||||||
is-defalt-team? (:is-default team)
|
is-defalt-team? (:is-default team)
|
||||||
|
|
||||||
on-close
|
on-close
|
||||||
|
@ -346,8 +349,8 @@
|
||||||
(:name team))]
|
(:name team))]
|
||||||
(dom/set-html-title (tr "title.dashboard.projects" tname))))
|
(dom/set-html-title (tr "title.dashboard.projects" tname))))
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect [team-id]
|
||||||
(st/emit! (dd/fetch-recent-files)
|
(st/emit! (dd/fetch-recent-files team-id)
|
||||||
(dd/clear-selected-files)))
|
(dd/clear-selected-files)))
|
||||||
|
|
||||||
(when (seq projects)
|
(when (seq projects)
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
[template team-id project-id default-project-id section]
|
[template team-id project-id default-project-id section]
|
||||||
(letfn [(on-finish []
|
(letfn [(on-finish []
|
||||||
(st/emit!
|
(st/emit!
|
||||||
|
(dd/fetch-recent-files team-id)
|
||||||
(ptk/event ::ev/event {::ev/name "import-template-finish"
|
(ptk/event ::ev/event {::ev/name "import-template-finish"
|
||||||
::ev/origin "dashboard"
|
::ev/origin "dashboard"
|
||||||
:template (:name template)
|
:template (:name template)
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
scale-enabled?
|
scale-enabled?
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(fn [export]
|
(fn [export]
|
||||||
(#{:png :jpeg} (:type export))))
|
(#{:png :jpeg :webp} (:type export))))
|
||||||
|
|
||||||
in-progress? (:in-progress xstate)
|
in-progress? (:in-progress xstate)
|
||||||
|
|
||||||
|
@ -123,6 +123,7 @@
|
||||||
|
|
||||||
format-options [{:value "png" :label "PNG"}
|
format-options [{:value "png" :label "PNG"}
|
||||||
{:value "jpeg" :label "JPG"}
|
{:value "jpeg" :label "JPG"}
|
||||||
|
{:value "webp" :label "WEBP"}
|
||||||
{:value "svg" :label "SVG"}
|
{:value "svg" :label "SVG"}
|
||||||
{:value "pdf" :label "PDF"}]]
|
{:value "pdf" :label "PDF"}]]
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
.element-group {
|
.element-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(8, 1fr);
|
grid-template-columns: repeat(9, 1fr);
|
||||||
column-gap: $s-4;
|
column-gap: $s-4;
|
||||||
.action-btn {
|
.action-btn {
|
||||||
@extend .button-tertiary;
|
@extend .button-tertiary;
|
||||||
|
@ -64,13 +64,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-wrapper {
|
.input-wrapper {
|
||||||
grid-column: span 7;
|
grid-column: span 8;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: subgrid;
|
grid-template-columns: subgrid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.format-select {
|
.format-select {
|
||||||
grid-column: span 2;
|
grid-column: span 3;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.dropdown-upwards {
|
.dropdown-upwards {
|
||||||
|
|
|
@ -568,7 +568,6 @@
|
||||||
[{:keys [starting-tab file-id] :as props :or {starting-tab :libraries}}]
|
[{:keys [starting-tab file-id] :as props :or {starting-tab :libraries}}]
|
||||||
(let [files (mf/deref refs/files)
|
(let [files (mf/deref refs/files)
|
||||||
file (get files file-id)
|
file (get files file-id)
|
||||||
team-id (:team-id file)
|
|
||||||
shared? (:is-shared file)
|
shared? (:is-shared file)
|
||||||
|
|
||||||
linked-libraries
|
linked-libraries
|
||||||
|
@ -616,8 +615,8 @@
|
||||||
:id "updates"
|
:id "updates"
|
||||||
:content updates-tab}]]
|
:content updates-tab}]]
|
||||||
|
|
||||||
(mf/with-effect [team-id]
|
(mf/with-effect []
|
||||||
(st/emit! (dtm/fetch-shared-files team-id)))
|
(st/emit! (dtm/fetch-shared-files)))
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-overlay)
|
[:div {:class (stl/css :modal-overlay)
|
||||||
:on-click close-dialog-outside
|
:on-click close-dialog-outside
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
scale-enabled?
|
scale-enabled?
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [export]
|
(fn [export]
|
||||||
(#{:png :jpeg} (:type export))))
|
(#{:png :jpeg :webp} (:type export))))
|
||||||
|
|
||||||
on-download
|
on-download
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -173,6 +173,7 @@
|
||||||
|
|
||||||
format-options [{:value "png" :label "PNG"}
|
format-options [{:value "png" :label "PNG"}
|
||||||
{:value "jpeg" :label "JPG"}
|
{:value "jpeg" :label "JPG"}
|
||||||
|
{:value "webp" :label "WEBP"}
|
||||||
{:value "svg" :label "SVG"}
|
{:value "svg" :label "SVG"}
|
||||||
{:value "pdf" :label "PDF"}]]
|
{:value "pdf" :label "PDF"}]]
|
||||||
|
|
||||||
|
|
|
@ -32,18 +32,18 @@
|
||||||
|
|
||||||
.element-group {
|
.element-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(8, 1fr);
|
grid-template-columns: repeat(9, 1fr);
|
||||||
column-gap: $s-4;
|
column-gap: $s-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-wrapper {
|
.input-wrapper {
|
||||||
grid-column: span 7;
|
grid-column: span 8;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: subgrid;
|
grid-template-columns: subgrid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.format-select {
|
.format-select {
|
||||||
grid-column: span 2;
|
grid-column: span 3;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.dropdown-upwards {
|
.dropdown-upwards {
|
||||||
|
|
|
@ -261,7 +261,7 @@
|
||||||
:hidden hidden})))
|
:hidden hidden})))
|
||||||
|
|
||||||
;; export interface Export {
|
;; export interface Export {
|
||||||
;; type: 'png' | 'jpeg' | 'svg' | 'pdf';
|
;; type: 'png' | 'jpeg' | 'webp' | 'svg' | 'pdf';
|
||||||
;; scale: number;
|
;; scale: number;
|
||||||
;; suffix: string;
|
;; suffix: string;
|
||||||
;; }
|
;; }
|
||||||
|
|
|
@ -243,7 +243,7 @@
|
||||||
|
|
||||||
|
|
||||||
;; export interface Export {
|
;; export interface Export {
|
||||||
;; type: 'png' | 'jpeg' | 'svg' | 'pdf';
|
;; type: 'png' | 'jpeg' | 'webp' | 'svg' | 'pdf';
|
||||||
;; scale: number;
|
;; scale: number;
|
||||||
;; suffix: string;
|
;; suffix: string;
|
||||||
;; }
|
;; }
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.uri :as u]
|
[app.common.uri :as u]
|
||||||
[app.main.data.fonts :as df]
|
[app.main.data.fonts :as df]
|
||||||
[app.main.data.team :as dtm]
|
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.render :as render]
|
[app.main.render :as render]
|
||||||
[app.main.repo :as repo]
|
[app.main.repo :as repo]
|
||||||
|
@ -30,6 +29,20 @@
|
||||||
|
|
||||||
(log/setup! {:app :info})
|
(log/setup! {:app :info})
|
||||||
|
|
||||||
|
(defn set-current-team
|
||||||
|
[{:keys [id permissions features] :as team}]
|
||||||
|
(ptk/reify ::set-current-team
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(-> state
|
||||||
|
(assoc :permissions permissions)
|
||||||
|
(update :teams assoc id team)
|
||||||
|
(assoc :current-team-id id)))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(rx/of (features/initialize (or features #{}))))))
|
||||||
|
|
||||||
(defn- fetch-team
|
(defn- fetch-team
|
||||||
[& {:keys [file-id]}]
|
[& {:keys [file-id]}]
|
||||||
(ptk/reify ::fetch-team
|
(ptk/reify ::fetch-team
|
||||||
|
@ -37,7 +50,7 @@
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(->> (repo/cmd! :get-team {:file-id file-id})
|
(->> (repo/cmd! :get-team {:file-id file-id})
|
||||||
(rx/mapcat (fn [team]
|
(rx/mapcat (fn [team]
|
||||||
(rx/of (dtm/set-current-team team)
|
(rx/of (set-current-team team)
|
||||||
(ptk/data-event ::team-fetched team))))))))
|
(ptk/data-event ::team-fetched team))))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue