mirror of
https://github.com/penpot/penpot.git
synced 2025-04-01 01:21:21 -05:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
045e83e871
16 changed files with 165 additions and 28 deletions
|
@ -59,6 +59,11 @@
|
||||||
- Export shapes that are rotated act a bit strange when reimported [Taiga #7585](https://tree.taiga.io/project/penpot/issue/7585)
|
- Export shapes that are rotated act a bit strange when reimported [Taiga #7585](https://tree.taiga.io/project/penpot/issue/7585)
|
||||||
- Penpot crashes when a new colorpicker is created while uploading an image to another instance [Taiga #8119](https://tree.taiga.io/project/penpot/issue/8119)
|
- Penpot crashes when a new colorpicker is created while uploading an image to another instance [Taiga #8119](https://tree.taiga.io/project/penpot/issue/8119)
|
||||||
- Removing Underline and Strikethrough Affects the Previous Text Object [Taiga #8103](https://tree.taiga.io/project/penpot/issue/8103)
|
- Removing Underline and Strikethrough Affects the Previous Text Object [Taiga #8103](https://tree.taiga.io/project/penpot/issue/8103)
|
||||||
|
- Color library loses association with shapes when exporting/importing the document [Taiga #8132](https://tree.taiga.io/project/penpot/issue/8132)
|
||||||
|
- Fix can't collapse groups when searching in the assets tab [Taiga #8125](https://tree.taiga.io/project/penpot/issue/8125)
|
||||||
|
- Fix 'Detach instance' shortcut is not working [Taiga #8102](https://tree.taiga.io/project/penpot/issue/8102)
|
||||||
|
- Fix import file message does not detect 0 as error [Taiga #6824](https://tree.taiga.io/project/penpot/issue/6824)
|
||||||
|
|
||||||
|
|
||||||
## 2.0.3
|
## 2.0.3
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,8 @@
|
||||||
(let [result (handler)]
|
(let [result (handler)]
|
||||||
(events/tap :end result))
|
(events/tap :end result))
|
||||||
(catch Throwable cause
|
(catch Throwable cause
|
||||||
|
(l/err :hint "unexpected error on processing sse response"
|
||||||
|
:cause cause)
|
||||||
(events/tap :error (errors/handle' cause request)))
|
(events/tap :error (errors/handle' cause request)))
|
||||||
(finally
|
(finally
|
||||||
(sp/close! events/*channel*)
|
(sp/close! events/*channel*)
|
||||||
|
|
|
@ -30,14 +30,12 @@
|
||||||
|
|
||||||
;; --- Command: export-binfile
|
;; --- Command: export-binfile
|
||||||
|
|
||||||
(def ^:private
|
(def ^:private schema:export-binfile
|
||||||
schema:export-binfile
|
[:map {:title "export-binfile"}
|
||||||
(sm/define
|
[:name :string]
|
||||||
[:map {:title "export-binfile"}
|
[:file-id ::sm/uuid]
|
||||||
[:name :string]
|
[:include-libraries :boolean]
|
||||||
[:file-id ::sm/uuid]
|
[:embed-assets :boolean]])
|
||||||
[:include-libraries :boolean]
|
|
||||||
[:embed-assets :boolean]]))
|
|
||||||
|
|
||||||
(sv/defmethod ::export-binfile
|
(sv/defmethod ::export-binfile
|
||||||
"Export a penpot file in a binary format."
|
"Export a penpot file in a binary format."
|
||||||
|
@ -76,13 +74,11 @@
|
||||||
{:id project-id})
|
{:id project-id})
|
||||||
result))
|
result))
|
||||||
|
|
||||||
(def ^:private
|
(def ^:private schema:import-binfile
|
||||||
schema:import-binfile
|
[:map {:title "import-binfile"}
|
||||||
(sm/define
|
[:name :string]
|
||||||
[:map {:title "import-binfile"}
|
[:project-id ::sm/uuid]
|
||||||
[:name :string]
|
[:file ::media/upload]])
|
||||||
[:project-id ::sm/uuid]
|
|
||||||
[:file ::media/upload]]))
|
|
||||||
|
|
||||||
(sv/defmethod ::import-binfile
|
(sv/defmethod ::import-binfile
|
||||||
"Import a penpot file in a binary format."
|
"Import a penpot file in a binary format."
|
||||||
|
|
|
@ -582,6 +582,38 @@
|
||||||
:deleted-at (dt/now)
|
:deleted-at (dt/now)
|
||||||
:id file-id})))))
|
:id file-id})))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn process-deleted-teams-cascade
|
||||||
|
[]
|
||||||
|
(->> (db/exec! main/system ["select id, deleted_at from team where deleted_at is not null"])
|
||||||
|
(run! (fn [{:keys [id deleted-at]}]
|
||||||
|
(wrk/invoke! (-> main/system
|
||||||
|
(assoc ::wrk/task :delete-object)
|
||||||
|
(assoc ::wrk/params {:object :team
|
||||||
|
:deleted-at deleted-at
|
||||||
|
:id id})))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn process-deleted-projects-cascade
|
||||||
|
[]
|
||||||
|
(->> (db/exec! main/system ["select id, deleted_at from project where deleted_at is not null"])
|
||||||
|
(run! (fn [{:keys [id deleted-at]}]
|
||||||
|
(wrk/invoke! (-> main/system
|
||||||
|
(assoc ::wrk/task :delete-object)
|
||||||
|
(assoc ::wrk/params {:object :project
|
||||||
|
:deleted-at deleted-at
|
||||||
|
:id id})))))))
|
||||||
|
|
||||||
|
(defn process-deleted-files-cascade
|
||||||
|
[]
|
||||||
|
(->> (db/exec! main/system ["select id, deleted_at from file where deleted_at is not null"])
|
||||||
|
(run! (fn [{:keys [id deleted-at]}]
|
||||||
|
(wrk/invoke! (-> main/system
|
||||||
|
(assoc ::wrk/task :delete-object)
|
||||||
|
(assoc ::wrk/params {:object :file
|
||||||
|
:deleted-at deleted-at
|
||||||
|
:id id})))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; MISC
|
;; MISC
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -6,4 +6,4 @@
|
||||||
|
|
||||||
(ns app.common.files.defaults)
|
(ns app.common.files.defaults)
|
||||||
|
|
||||||
(def version 49)
|
(def version 50)
|
||||||
|
|
|
@ -957,6 +957,54 @@
|
||||||
|
|
||||||
(update data :pages-index update-vals update-page)))
|
(update data :pages-index update-vals update-page)))
|
||||||
|
|
||||||
|
(defn migrate-up-50
|
||||||
|
"This migration mainly fixes paths with curve-to segments
|
||||||
|
without :c1x :c1y :c2x :c2y properties. Additionally, we found a
|
||||||
|
case where the params instead to be plain hash-map, is a points
|
||||||
|
instance. This migration normalizes all params to plain map."
|
||||||
|
|
||||||
|
[data]
|
||||||
|
(let [update-segment
|
||||||
|
(fn [{:keys [command params] :as segment}]
|
||||||
|
(let [params (into {} params)
|
||||||
|
params (cond
|
||||||
|
(= :curve-to command)
|
||||||
|
(let [x (get params :x)
|
||||||
|
y (get params :y)]
|
||||||
|
|
||||||
|
(cond-> params
|
||||||
|
(nil? (:c1x params))
|
||||||
|
(assoc :c1x x)
|
||||||
|
|
||||||
|
(nil? (:c1y params))
|
||||||
|
(assoc :c1y y)
|
||||||
|
|
||||||
|
(nil? (:c2x params))
|
||||||
|
(assoc :c2x x)
|
||||||
|
|
||||||
|
(nil? (:c2y params))
|
||||||
|
(assoc :c2y y)))
|
||||||
|
|
||||||
|
:else
|
||||||
|
params)]
|
||||||
|
|
||||||
|
(assoc segment :params params)))
|
||||||
|
|
||||||
|
update-shape
|
||||||
|
(fn [shape]
|
||||||
|
(if (cfh/path-shape? shape)
|
||||||
|
(d/update-when shape :content (fn [content] (mapv update-segment content)))
|
||||||
|
shape))
|
||||||
|
|
||||||
|
update-container
|
||||||
|
(fn [page]
|
||||||
|
(d/update-when page :objects update-vals update-shape))]
|
||||||
|
|
||||||
|
(-> data
|
||||||
|
(update :pages-index update-vals update-container)
|
||||||
|
(update :components update-vals update-container))))
|
||||||
|
|
||||||
|
|
||||||
(def migrations
|
(def migrations
|
||||||
"A vector of all applicable migrations"
|
"A vector of all applicable migrations"
|
||||||
[{:id 2 :migrate-up migrate-up-2}
|
[{:id 2 :migrate-up migrate-up-2}
|
||||||
|
@ -997,4 +1045,5 @@
|
||||||
{:id 46 :migrate-up migrate-up-46}
|
{:id 46 :migrate-up migrate-up-46}
|
||||||
{:id 47 :migrate-up migrate-up-47}
|
{:id 47 :migrate-up migrate-up-47}
|
||||||
{:id 48 :migrate-up migrate-up-48}
|
{:id 48 :migrate-up migrate-up-48}
|
||||||
{:id 49 :migrate-up migrate-up-49}])
|
{:id 49 :migrate-up migrate-up-49}
|
||||||
|
{:id 50 :migrate-up migrate-up-50}])
|
||||||
|
|
|
@ -1046,7 +1046,6 @@
|
||||||
(str/includes? data "<!DOCTYPE")
|
(str/includes? data "<!DOCTYPE")
|
||||||
(str/replace #"<\!DOCTYPE[^>]*>" "")))
|
(str/replace #"<\!DOCTYPE[^>]*>" "")))
|
||||||
|
|
||||||
|
|
||||||
(defn parse
|
(defn parse
|
||||||
[text]
|
[text]
|
||||||
#?(:cljs (tubax/xml->clj text)
|
#?(:cljs (tubax/xml->clj text)
|
||||||
|
|
|
@ -1124,6 +1124,14 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-assets :open-status file-id section] open?))))
|
(assoc-in state [:workspace-assets :open-status file-id section] open?))))
|
||||||
|
|
||||||
|
(defn clear-assets-section-open
|
||||||
|
[]
|
||||||
|
(ptk/reify ::clear-assets-section-open
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:workspace-assets :open-status] {}))))
|
||||||
|
|
||||||
|
|
||||||
(defn set-assets-group-open
|
(defn set-assets-group-open
|
||||||
[file-id section path open?]
|
[file-id section path open?]
|
||||||
(ptk/reify ::set-assets-group-open
|
(ptk/reify ::set-assets-group-open
|
||||||
|
|
|
@ -609,9 +609,13 @@
|
||||||
(assoc :type :color))))))))
|
(assoc :type :color))))))))
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
;; Type can be null, because the colorpicker can be closed while a color image finish its upload
|
(let [selected-type (-> state
|
||||||
(when (and add-recent? (some? (:type state)))
|
:colorpicker
|
||||||
(let [formated-color (get-color-from-colorpicker-state (:colorpicker state))]
|
:type)
|
||||||
|
formated-color (get-color-from-colorpicker-state (:colorpicker state))
|
||||||
|
;; Type is set to color on closing the colorpicker, but we can can close it while still uploading an image fill
|
||||||
|
ignore-color? (and (= selected-type :color) (nil? (:color formated-color)))]
|
||||||
|
(when (and add-recent? (not ignore-color?))
|
||||||
(rx/of (dwl/add-recent-color formated-color)))))))
|
(rx/of (dwl/add-recent-color formated-color)))))))
|
||||||
|
|
||||||
(defn update-colorpicker-gradient
|
(defn update-colorpicker-gradient
|
||||||
|
|
|
@ -615,7 +615,6 @@
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
file (wsh/get-local-file state)
|
file (wsh/get-local-file state)
|
||||||
container (cfh/get-container file :page page-id)
|
|
||||||
libraries (wsh/get-libraries state)
|
libraries (wsh/get-libraries state)
|
||||||
selected (->> state
|
selected (->> state
|
||||||
(wsh/lookup-selected)
|
(wsh/lookup-selected)
|
||||||
|
@ -627,7 +626,7 @@
|
||||||
changes (when can-detach?
|
changes (when can-detach?
|
||||||
(reduce
|
(reduce
|
||||||
(fn [changes id]
|
(fn [changes id]
|
||||||
(cll/generate-detach-instance changes container libraries id))
|
(cll/generate-detach-component changes id file page-id libraries))
|
||||||
(pcb/empty-changes it)
|
(pcb/empty-changes it)
|
||||||
selected))]
|
selected))]
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[:& context-notification
|
[:& context-notification
|
||||||
{:type :success
|
{:type (if (zero? success-num) :warning :success)
|
||||||
:content (tr "dashboard.import.import-message" (i18n/c success-num))}]))
|
:content (tr "dashboard.import.import-message" (i18n/c success-num))}]))
|
||||||
|
|
||||||
(for [entry entries]
|
(for [entry entries]
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.assets :as dwa]
|
[app.main.data.workspace.assets :as dwa]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
|
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
|
||||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
|
@ -103,6 +105,7 @@
|
||||||
on-search-term-change
|
on-search-term-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
|
(st/emit! (dw/clear-assets-section-open))
|
||||||
(swap! filters* assoc :term event)))
|
(swap! filters* assoc :term event)))
|
||||||
|
|
||||||
on-section-filter-change
|
on-section-filter-change
|
||||||
|
@ -112,6 +115,7 @@
|
||||||
(dom/get-value))
|
(dom/get-value))
|
||||||
(as-> (dom/get-current-target event) $
|
(as-> (dom/get-current-target event) $
|
||||||
(dom/get-attribute $ "data-testid")))]
|
(dom/get-attribute $ "data-testid")))]
|
||||||
|
(st/emit! (dw/clear-assets-section-open))
|
||||||
(swap! filters* assoc :section value :open-menu false))))
|
(swap! filters* assoc :section value :open-menu false))))
|
||||||
|
|
||||||
show-libraries-dialog
|
show-libraries-dialog
|
||||||
|
|
|
@ -192,8 +192,10 @@
|
||||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
||||||
selected-full local]}]
|
selected-full local]}]
|
||||||
|
|
||||||
(let [group-open? (or ^boolean force-open?
|
(let [group-open? (if (false? (get open-groups prefix)) ;; if the user has closed it specifically, respect that
|
||||||
^boolean (get open-groups prefix (if (= prefix "") true false)))
|
false
|
||||||
|
(or ^boolean force-open?
|
||||||
|
^boolean (get open-groups prefix (if (= prefix "") true false))))
|
||||||
dragging* (mf/use-state false)
|
dragging* (mf/use-state false)
|
||||||
dragging? (deref dragging*)
|
dragging? (deref dragging*)
|
||||||
|
|
||||||
|
|
|
@ -318,6 +318,7 @@
|
||||||
(and has-term?
|
(and has-term?
|
||||||
(some pos? (map count [filtered-components filtered-colors filtered-media filtered-typographies]))
|
(some pos? (map count [filtered-components filtered-colors filtered-media filtered-typographies]))
|
||||||
(some #(> 60 (count %)) [filtered-components filtered-colors filtered-media filtered-typographies]))))
|
(some #(> 60 (count %)) [filtered-components filtered-colors filtered-media filtered-typographies]))))
|
||||||
|
|
||||||
(mf/defc file-library
|
(mf/defc file-library
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [file local? default-open? filters]}]
|
[{:keys [file local? default-open? filters]}]
|
||||||
|
@ -333,8 +334,10 @@
|
||||||
open-status (mf/deref open-status-ref)
|
open-status (mf/deref open-status-ref)
|
||||||
force-open-lib? (force-lib-open? file-id filters)
|
force-open-lib? (force-lib-open? file-id filters)
|
||||||
|
|
||||||
open? (or force-open-lib?
|
open? (if (false? (:library open-status)) ;; if the user has closed it specifically, respect that
|
||||||
(d/nilv (:library open-status) default-open?))
|
false
|
||||||
|
(or force-open-lib?
|
||||||
|
(d/nilv (:library open-status) default-open?)))
|
||||||
|
|
||||||
unselect-all
|
unselect-all
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
[app.common.svg.path.subpath :refer [pt=]]
|
[app.common.svg.path.subpath :refer [pt=]]
|
||||||
[app.util.array :as arr]))
|
[app.util.array :as arr]))
|
||||||
|
|
||||||
|
;; TODO: move to common
|
||||||
|
|
||||||
(def path-precision 3)
|
(def path-precision 3)
|
||||||
|
|
||||||
(defn- join-params
|
(defn- join-params
|
||||||
|
|
|
@ -223,6 +223,32 @@
|
||||||
(uuid? (get item :typography-ref-file))
|
(uuid? (get item :typography-ref-file))
|
||||||
(d/update-when :typography-ref-file resolve)))))))
|
(d/update-when :typography-ref-file resolve)))))))
|
||||||
|
|
||||||
|
(defn resolve-fills-content
|
||||||
|
[fills context]
|
||||||
|
(let [resolve (:resolve context)]
|
||||||
|
(->> fills
|
||||||
|
(mapv
|
||||||
|
(fn [fill]
|
||||||
|
(cond-> fill
|
||||||
|
(uuid? (get fill :fill-color-ref-id))
|
||||||
|
(d/update-when :fill-color-ref-id resolve)
|
||||||
|
|
||||||
|
(uuid? (get fill :fill-color-ref-file))
|
||||||
|
(d/update-when :fill-color-ref-file resolve)))))))
|
||||||
|
|
||||||
|
(defn resolve-strokes-content
|
||||||
|
[fills context]
|
||||||
|
(let [resolve (:resolve context)]
|
||||||
|
(->> fills
|
||||||
|
(mapv
|
||||||
|
(fn [fill]
|
||||||
|
(cond-> fill
|
||||||
|
(uuid? (get fill :stroke-color-ref-id))
|
||||||
|
(d/update-when :stroke-color-ref-id resolve)
|
||||||
|
|
||||||
|
(uuid? (get fill :stroke-color-ref-file))
|
||||||
|
(d/update-when :stroke-color-ref-file resolve)))))))
|
||||||
|
|
||||||
(defn resolve-data-ids
|
(defn resolve-data-ids
|
||||||
[data type context]
|
[data type context]
|
||||||
(let [resolve (:resolve context)]
|
(let [resolve (:resolve context)]
|
||||||
|
@ -238,6 +264,12 @@
|
||||||
(cond-> (= type :text)
|
(cond-> (= type :text)
|
||||||
(d/update-when :content resolve-text-content context))
|
(d/update-when :content resolve-text-content context))
|
||||||
|
|
||||||
|
(cond-> (:fills data)
|
||||||
|
(d/update-when :fills resolve-fills-content context))
|
||||||
|
|
||||||
|
(cond-> (:strokes data)
|
||||||
|
(d/update-when :strokes resolve-strokes-content context))
|
||||||
|
|
||||||
(cond-> (and (= type :frame) (= :grid (:layout data)))
|
(cond-> (and (= type :frame) (= :grid (:layout data)))
|
||||||
(update
|
(update
|
||||||
:layout-grid-cells
|
:layout-grid-cells
|
||||||
|
|
Loading…
Add table
Reference in a new issue