Compare commits

...

23 Commits

Author SHA1 Message Date
Andrey Antukh
bb5804cde3 📎 Update changelog and increase version. 2021-06-04 14:15:48 +02:00
Andrey Antukh
7819757759 🐛 Fix unexpected exception on searching without term.
When term is empty on frontend, frontend just does not sends it
to backend, leving it as missing field. This commit makes the
seatch-term as optional.
2021-06-04 14:15:48 +02:00
Andrey Antukh
b861e261ed 🐛 Replace frame term usage by artboard on viewer app.
Replace frame with artboard.
2021-06-04 14:15:48 +02:00
Andrey Antukh
17b32d6518 🐛 Don't allow rename drafts project. 2021-06-04 14:15:48 +02:00
Andrey Antukh
d2359046c4 🐛 Fix problem when moving files with drag & drop. 2021-06-04 14:15:48 +02:00
Andrey Antukh
8a700170b0 🐛 Fix font loading on viewer app. 2021-06-04 13:39:01 +02:00
Andrey Antukh
8c68e29bf3 🐛 Fix custom font rendering on exporting shapes. 2021-06-04 13:26:37 +02:00
Andrey Antukh
1a81631886 📎 Decrease default bulk buffers on storage tasks. 2021-06-04 09:41:42 +02:00
Andrey Antukh
634fe2c458 📎 Reduce file_change preserve interval to 24h. 2021-06-04 01:27:21 +02:00
Andrey Antukh
053d46144e 📎 Fix linter issues. 2021-06-03 17:24:19 +02:00
Andrey Antukh
b2e7bb6be1 🐛 Properly handle nil values on update-shapes function. 2021-06-03 17:19:14 +02:00
Andrey Antukh
bae709df5b 🐛 Fix custom font deletion task. 2021-06-03 12:55:31 +02:00
Andrey Antukh
1b495ebad1 Minor improvements on loki reporter. 2021-06-03 12:40:22 +02:00
Andrey Antukh
4e0289b341 Reduce the deletion window of file_changes. 2021-06-03 12:34:11 +02:00
Andrey Antukh
056fce9187 📎 Minor changes on background tasks cron expr. 2021-06-02 13:13:25 +02:00
Andrey Antukh
9f034c7e7e Disable excesive logging of some modules. 2021-06-02 11:27:22 +02:00
Andrey Antukh
a6de4e3742 📎 Change version.txt file. 2021-06-01 15:19:37 +02:00
Andrey Antukh
2d6a375afc 📎 Update changelog. 2021-06-01 15:18:26 +02:00
Andrey Antukh
585e5d0199 📎 Minor changes on internal audit module buffers. 2021-06-01 15:14:39 +02:00
alonso.torres
71524fe649 🐛 Fix problem with empty path editing 2021-05-31 12:50:24 +02:00
alonso.torres
55d2768807 🐛 Fix problem with create component 2021-05-31 12:50:24 +02:00
alonso.torres
3d7a3f27d5 🐛 Fix problem with move-objects 2021-05-28 11:05:18 +02:00
alonso.torres
46448bc5c7 🐛 Fix problem with merge and join nodes 2021-05-28 10:51:36 +02:00
37 changed files with 267 additions and 156 deletions

View File

@@ -1,7 +1,12 @@
{:lint-as {potok.core/reify clojure.core/reify
promesa.core/let clojure.core/let
rumext.alpha/defc clojure.core/defn
app.common.data/export clojure.core/def
app.db/with-atomic clojure.core/with-open}
:hooks
{:analyze-call {app.common.data/export hooks.export/export}}
:output
{:exclude-files ["data_readers.clj"]}

View File

@@ -0,0 +1,11 @@
(ns hooks.export
(:require [clj-kondo.hooks-api :as api]))
(defn export
[{:keys [:node]}]
(let [[_ sname] (:children node)
result (api/list-node
[(api/token-node (symbol "def"))
(api/token-node (symbol (name (:value sname))))
sname])]
{:node result}))

2
.gitignore vendored
View File

@@ -30,6 +30,8 @@ node_modules
/exporter/target
/exporter/.shadow-cljs
/docker/images/bundle*
/common/.shadow-cljs
/common/target
/.clj-kondo/.cache
/bundle*
/media

View File

@@ -1,6 +1,5 @@
# CHANGELOG #
## :rocket: Next
### :sparkles: New features
@@ -10,6 +9,34 @@
### :boom: Breaking changes
### :heart: Community contributions by (Thank you!)
## 1.6.4-alpha
### :sparkles: Minor improvements
- Decrease default bulk buffers on storage tasks.
- Reduce file_change preserve interval to 24h.
### :bug: Bugs fixed
- Don't allow rename drafts project.
- Fix custom font deletion task.
- Fix custom font rendering on exporting shapes.
- Fix font loading on viewer app.
- Fix problem when moving files with drag & drop.
- Fix unexpected exception on searching without term.
- Properly handle nil values on `update-shapes` function.
- Replace frame term usage by artboard on viewer app.
## 1.6.3-alpha
### :bug: Bugs fixed
- Fix problem with merge and join nodes [#990](https://github.com/penpot/penpot/issues/990)
- Fix problem with empty path editing.
- Fix problem with create component.
- Fix problem with move-objects.
- Fix problem with merge and join nodes.
## 1.6.2-alpha

View File

@@ -140,10 +140,13 @@
(when-let [[reason batch] (a/<! input)]
(let [result (a/<! (update-sessions cfg batch))]
(mcnt :inc)
(if (ex/exception? result)
(cond
(ex/exception? result)
(l/error :task "updater"
:hint "unexpected error on update sessions"
:cause result)
(= :size reason)
(l/debug :task "updater"
:action "update sessions"
:reason (name reason)

View File

@@ -75,15 +75,12 @@
[_ {:keys [enabled] :as cfg}]
(when enabled
(l/info :msg "intializing audit collector")
(let [input (a/chan 1 event-xform)
(let [input (a/chan 512 event-xform)
buffer (aa/batch input {:max-batch-size 100
:max-batch-age (* 5 1000)
:max-batch-age (* 10 1000) ; 10s
:init []})]
(a/go-loop []
(when-let [[type events] (a/<! buffer)]
(l/debug :action "persist-events (batch)"
:reason (name type)
:count (count events))
(when-let [[_type events] (a/<! buffer)]
(let [res (a/<! (persist-events cfg events))]
(when (ex/exception? res)
(l/error :hint "error on persiting events"

View File

@@ -31,7 +31,7 @@
[_ {:keys [receiver uri] :as cfg}]
(when uri
(l/info :msg "intializing loki reporter" :uri uri)
(let [input (a/chan (a/sliding-buffer 1024))]
(let [input (a/chan (a/dropping-buffer 512))]
(receiver :sub input)
(a/go-loop []
(let [msg (a/<! input)]
@@ -69,17 +69,23 @@
:method :post
:headers {"content-type" "application/json"}
:body (json/encode payload)})]
(if (= (:status response) 204)
(cond
(= (:status response) 204)
true
(= (:status response) 400)
(do
(l/error :hint "error on sending log to loki"
:try i
(l/error :hint "error on sending log to loki (no retry)"
:rsp (pr-str response))
true)
:else
(do
(l/error :hint "error on sending log to loki" :try i
:rsp (pr-str response))
false)))
(catch Exception e
(l/error :hint "error on sending message to loki"
:cause e
:try i)
(l/error :hint "error on sending message to loki" :cause e :try i)
false)))
(defn- handle-event

View File

@@ -166,25 +166,25 @@
:tasks (ig/ref :app.worker/registry)
:pool (ig/ref :app.db/pool)
:schedule
[{:cron #app/cron "0 0 0 */1 * ? *" ;; daily
[{:cron #app/cron "0 0 0 * * ? *" ;; daily
:task :file-media-gc}
{:cron #app/cron "0 0 */1 * * ?" ;; hourly
{:cron #app/cron "0 0 * * * ?" ;; hourly
:task :file-xlog-gc}
{:cron #app/cron "0 0 1 */1 * ?" ;; daily (1 hour shift)
{:cron #app/cron "0 0 1 * * ?" ;; daily (1 hour shift)
:task :storage-deleted-gc}
{:cron #app/cron "0 0 2 */1 * ?" ;; daily (2 hour shift)
{:cron #app/cron "0 0 2 * * ?" ;; daily (2 hour shift)
:task :storage-touched-gc}
{:cron #app/cron "0 0 3 */1 * ?" ;; daily (3 hour shift)
{:cron #app/cron "0 0 3 * * ?" ;; daily (3 hour shift)
:task :session-gc}
{:cron #app/cron "0 0 */1 * * ?" ;; hourly
{:cron #app/cron "0 0 * * * ?" ;; hourly
:task :storage-recheck}
{:cron #app/cron "0 0 0 */1 * ?" ;; daily
{:cron #app/cron "0 0 0 * * ?" ;; daily
:task :tasks-gc}
(when (cf/get :audit-archive-enabled)
@@ -230,31 +230,22 @@
:app.tasks.tasks-gc/handler
{:pool (ig/ref :app.db/pool)
:max-age cf/deletion-delay
:metrics (ig/ref :app.metrics/metrics)}
:max-age cf/deletion-delay}
:app.tasks.delete-object/handler
{:pool (ig/ref :app.db/pool)
:metrics (ig/ref :app.metrics/metrics)}
:app.tasks.delete-storage-object/handler
{:pool (ig/ref :app.db/pool)
:storage (ig/ref :app.storage/storage)
:metrics (ig/ref :app.metrics/metrics)}
:storage (ig/ref :app.storage/storage)}
:app.tasks.delete-profile/handler
{:pool (ig/ref :app.db/pool)
:metrics (ig/ref :app.metrics/metrics)}
{:pool (ig/ref :app.db/pool)}
:app.tasks.file-media-gc/handler
{:pool (ig/ref :app.db/pool)
:metrics (ig/ref :app.metrics/metrics)
:max-age cf/deletion-delay}
:app.tasks.file-xlog-gc/handler
{:pool (ig/ref :app.db/pool)
:metrics (ig/ref :app.metrics/metrics)
:max-age cf/deletion-delay}
:max-age (dt/duration {:hours 24})}
:app.tasks.telemetry/handler
{:pool (ig/ref :app.db/pool)

View File

@@ -112,14 +112,16 @@
order by f.created_at asc")
(s/def ::search-files
(s/keys :req-un [::profile-id ::team-id ::search-term]))
(s/keys :req-un [::profile-id ::team-id]
:opt-un [::search-term]))
(sv/defmethod ::search-files
[{:keys [pool] :as cfg} {:keys [profile-id team-id search-term] :as params}]
(db/exec! pool [sql:search-files
profile-id team-id
profile-id team-id
search-term]))
(when search-term
(db/exec! pool [sql:search-files
profile-id team-id
profile-id team-id
search-term])))
;; --- Query: Files

View File

@@ -8,12 +8,16 @@
(:require
[app.common.spec :as us]
[app.db :as db]
[app.rpc.queries.files :as files]
[app.rpc.queries.projects :as projects]
[app.rpc.queries.teams :as teams]
[app.util.services :as sv]
[clojure.spec.alpha :as s]))
;; --- Query: Team Font Variants
;; TODO: deprecated, should be removed on 1.7.x
(s/def ::team-id ::us/uuid)
(s/def ::profile-id ::us/uuid)
(s/def ::team-font-variants
@@ -27,3 +31,43 @@
{:team-id team-id
:deleted-at nil})))
;; --- Query: Font Variants
(s/def ::file-id ::us/uuid)
(s/def ::project-id ::us/uuid)
(s/def ::font-variants
(s/and
(s/keys :req-un [::profile-id]
:opt-un [::team-id
::file-id
::project-id])
(fn [o]
(or (contains? o :team-id)
(contains? o :file-id)
(contains? o :project-id)))))
(sv/defmethod ::font-variants
[{:keys [pool] :as cfg} {:keys [profile-id team-id file-id project-id] :as params}]
(with-open [conn (db/open pool)]
(cond
(uuid? team-id)
(do
(teams/check-read-permissions! conn profile-id team-id)
(db/query conn :team-font-variant
{:team-id team-id
:deleted-at nil}))
(uuid? project-id)
(let [project (db/get-by-id conn :project project-id {:columns [:id :team-id]})]
(projects/check-read-permissions! conn profile-id project-id)
(db/query conn :team-font-variant
{:team-id (:team-id project)
:deleted-at nil}))
(uuid? file-id)
(let [file (db/get-by-id conn :file file-id {:columns [:id :project-id]})
project (db/get-by-id conn :project (:project-id file) {:columns [:id :team-id]})]
(files/check-read-permissions! conn profile-id file-id)
(db/query conn :team-font-variant
{:team-id (:team-id project)
:deleted-at nil})))))

View File

@@ -50,9 +50,14 @@
libs (files/retrieve-file-libraries conn false file-id)
users (teams/retrieve-users conn (:team-id project))
fonts (db/query conn :team-font-variant
{:team-id (:team-id project)
:deleted-at nil})
bundle {:file file
:page page
:users users
:fonts fonts
:project project
:libraries libs}]

View File

@@ -319,7 +319,7 @@
where s.deleted_at is not null
and s.deleted_at < (now() - ?::interval)
order by s.deleted_at
limit 500
limit 100
)
delete from storage_object
where id in (select id from items_part)
@@ -396,7 +396,7 @@
from storage_object as so
where so.touched_at is not null
order by so.touched_at
limit 500;")
limit 100;")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Recheck Stalled Task

View File

@@ -18,7 +18,7 @@
(declare handle-deletion)
(defmethod ig/pre-init-spec ::handler [_]
(s/keys :req-un [::db/pool]))
(s/keys :req-un [::db/pool ::sto/storage]))
(defmethod ig/init-key ::handler
[_ {:keys [pool] :as cfg}]

View File

@@ -28,7 +28,7 @@
(let [interval (db/interval max-age)
result (db/exec-one! conn [sql:delete-files-xlog interval])
result (:next.jdbc/update-count result)]
(l/debug :action "trim file-change table" :removed result)
(l/debug :removed result :hint "remove old file changes")
result))))
(def ^:private

View File

@@ -64,12 +64,14 @@
(defn batch
[in {:keys [max-batch-size
max-batch-age
buffer-size
init]
:or {max-batch-size 200
max-batch-age (* 30 1000)
buffer-size 128
init #{}}
:as opts}]
(let [out (a/chan)]
(let [out (a/chan buffer-size)]
(a/go-loop [tch (a/timeout max-batch-age) buf init]
(let [[val port] (a/alts! [tch in])]
(cond

View File

@@ -98,11 +98,11 @@
;; Terminate the loop if close channel is closed or
;; event-loop-fn returns nil.
(or (= port close-ch) (nil? val))
(l/debug :msg "stop condition found")
(l/debug :hint "stop condition found")
(db/pool-closed? pool)
(do
(l/debug :msg "eventloop aborted because pool is closed")
(l/debug :hint "eventloop aborted because pool is closed")
(a/close! close-ch))
(and (instance? java.sql.SQLException val)
@@ -115,7 +115,7 @@
(and (instance? java.sql.SQLException val)
(= "40001" (.getSQLState ^java.sql.SQLException val)))
(do
(l/debug :msg "serialization failure (retrying in some instants)")
(l/debug :hint "serialization failure (retrying in some instants)")
(a/<! (a/timeout poll-ms))
(recur))
@@ -243,7 +243,7 @@
(let [task-fn (get tasks name)]
(if task-fn
(task-fn item)
(l/warn :msg "no task handler found"
(l/warn :hint "no task handler found"
:name (d/name name)))
{:status :completed :task item}))
@@ -281,19 +281,13 @@
[{:keys [tasks]} item]
(let [name (d/name (:name item))]
(try
(l/debug :action "start task"
:name name
(l/debug :action "execute task"
:id (:id item)
:name name
:retry (:retry-num item))
(handle-task tasks item)
(catch Exception e
(handle-exception e item))
(finally
(l/debug :action "end task"
:name name
:id (:id item)
:retry (:retry-num item))))))
(handle-exception e item)))))
(def sql:select-next-tasks
"select * from task as t

View File

@@ -356,8 +356,8 @@
([shape {:keys [round-coords?]
:or {round-coords? true}}]
(let [shape (apply-displacement shape)
center (gco/center-shape shape)
(let [shape (apply-displacement shape)
center (gco/center-shape shape)
modifiers (:modifiers shape)]
(if (and modifiers center)
(let [transform (modifiers->transform center modifiers)]
@@ -376,7 +376,7 @@
:y (- (:y new-selrect 0) (:y selrect 0))
:width (- (:width new-selrect 1) (:width selrect 1))
:height (- (:height new-selrect 1) (:height selrect 1))}]
(cond-> group
(and (some? svg-viewbox) (some? selrect) (some? new-selrect))
(update :svg-viewbox

View File

@@ -276,7 +276,7 @@
(if (and valid? (seq shapes))
(as-> objects $
;; Add the new shapes to the parent object.
(update $ parent-id #(add-to-parent % index shapes))
(d/update-when $ parent-id #(add-to-parent % index shapes))
;; Update each individual shape link to the new parent
(reduce update-parent-id $ shapes)

View File

@@ -25,7 +25,7 @@
;; General purpose events & IMPL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn team-fonts-loaded
(defn fonts-fetched
[fonts]
(letfn [;; Prepare font to the internal font database format.
(prepare-font [[id [item :as items]]]
@@ -74,8 +74,8 @@
(ptk/reify ::load-team-fonts
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query :team-font-variants {:team-id team-id})
(rx/map team-fonts-loaded)))))
(->> (rp/query :font-variants {:team-id team-id})
(rx/map fonts-fetched)))))
(defn process-upload
"Given a seq of blobs and the team id, creates a ready-to-use fonts

View File

@@ -12,9 +12,10 @@
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.main.constants :as c]
[app.main.data.comments :as dcm]
[app.main.data.fonts :as df]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.data.comments :as dcm]
[app.util.avatars :as avatars]
[app.util.router :as rt]
[beicon.core :as rx]
@@ -97,7 +98,10 @@
:file-id file-id}
(string? token) (assoc :token token))]
(->> (rp/query :viewer-bundle params)
(rx/map bundle-fetched))))))
(rx/mapcat
(fn [{:keys [fonts] :as bundle}]
(rx/of (df/fonts-fetched fonts)
(bundle-fetched bundle)))))))))
(defn- extract-frames
[objects]

View File

@@ -66,10 +66,10 @@
(cond-> changes
(not (empty? rops))
(update :rch conj (assoc change :operations rops))
(update :redo-changes conj (assoc change :operations rops))
(not (empty? uops))
(update :uch conj (assoc change :operations uops)))))
(update :undo-changes conj (assoc change :operations uops)))))
(defn update-shapes
([ids f] (update-shapes ids f nil))
@@ -82,25 +82,26 @@
(ptk/reify ::update-shapes
ptk/WatchEvent
(watch [it state stream]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state)
reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state)
changes {:redo-changes []
:undo-changes []
:origin it
:save-undo? save-undo?}
{redo-changes :rch undo-changes :uch}
(reduce #(update-shape-changes %1 page-id objects f keys %2)
{:rch [] :uch []} ids)]
ids (into [] (filter some?) ids)
(when-not (empty? redo-changes)
(let [redo-changes (cond-> redo-changes
reg-objects? (conj reg-objects))
changes (reduce #(update-shape-changes %1 page-id objects f keys %2) changes ids)]
undo-changes (cond-> undo-changes
reg-objects? (conj reg-objects))]
(rx/of (commit-changes {:redo-changes redo-changes
:undo-changes undo-changes
:origin it
:save-undo? save-undo?})))))))))
(when-not (empty? (:redo-changes changes))
(let [reg-objs {:type :reg-objects
:page-id page-id
:shapes ids}
changes (cond-> changes
reg-objects?
(-> (update :redo-changes conj reg-objs)
(update :undo-changes conj reg-objs)))]
(rx/of (commit-changes changes)))))))))
(defn update-indices
[page-id changes]

View File

@@ -10,24 +10,21 @@
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as geom]
[app.common.pages :as cp]
[app.common.pages :as cp]
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.main.data.messages :as dm]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.groups :as dwg]
[app.main.data.workspace.libraries-helpers :as dwlh]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.streams :as ms]
[app.util.color :as color]
[app.util.i18n :refer [tr]]
[app.util.logging :as log]
[app.util.router :as rt]
[app.util.time :as dt]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[potok.core :as ptk]))
;; Change this to :info :debug or :trace to debug this module
@@ -263,10 +260,11 @@
page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
selected (wsh/lookup-selected state)
selected (cp/clean-loops objects selected)]
(when-not (empty? selected)
selected (cp/clean-loops objects selected)
shapes (dwg/shapes-for-grouping objects selected)]
(when-not (empty? shapes)
(let [[group rchanges uchanges]
(dwlh/generate-add-component selected objects page-id file-id)]
(dwlh/generate-add-component shapes objects page-id file-id)]
(when-not (empty? rchanges)
(rx/of (dch/commit-changes {:redo-changes rchanges
:undo-changes uchanges

View File

@@ -124,10 +124,8 @@
"If there is exactly one id, and it's a group, use it as root. Otherwise,
create a group that contains all ids. Then, make a component with it,
and link all shapes to their corresponding one in the component."
[ids objects page-id file-id]
(let [shapes (dwg/shapes-for-grouping objects ids)
[group rchanges uchanges]
[shapes objects page-id file-id]
(let [[group rchanges uchanges]
(if (and (= (count shapes) 1)
(= (:type (first shapes)) :group))
[(first shapes) [] []]

View File

@@ -90,7 +90,7 @@
id (get-in state [:workspace-local :edition])
old-content (get-in state [:workspace-local :edit-path id :old-content])
shape (get-in state (st/get-path state))]
(if (and (some? old-content) (some? shape))
(if (and (some? old-content) (some? (:id shape)))
(let [[rch uch] (generate-path-changes objects page-id shape old-content (:content shape))]
(rx/of (dch/commit-changes {:redo-changes rch
:undo-changes uch

View File

@@ -7,26 +7,26 @@
(ns app.main.exports
"The main logic for SVG export functionality."
(:require
[rumext.alpha :as mf]
[cuerdas.core :as str]
[app.common.uuid :as uuid]
[app.common.pages :as cp]
[app.common.math :as mth]
[app.common.geom.shapes :as gsh]
[app.common.geom.align :as gal]
[app.common.geom.point :as gpt]
[app.common.geom.matrix :as gmt]
[app.util.timers :as ts]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.common.pages :as cp]
[app.common.uuid :as uuid]
[app.main.ui.shapes.circle :as circle]
[app.main.ui.shapes.filters :as filters]
[app.main.ui.shapes.frame :as frame]
[app.main.ui.shapes.circle :as circle]
[app.main.ui.shapes.group :as group]
[app.main.ui.shapes.image :as image]
[app.main.ui.shapes.path :as path]
[app.main.ui.shapes.rect :as rect]
[app.main.ui.shapes.text :as text]
[app.main.ui.shapes.group :as group]
[app.main.ui.shapes.shape :refer [shape-container]]
[app.main.ui.shapes.svg-raw :as svg-raw]
[app.main.ui.shapes.shape :refer [shape-container]]))
[app.main.ui.shapes.text :as text]
[app.util.timers :as ts]
[cuerdas.core :as str]
[rumext.alpha :as mf]))
(def ^:private default-color "#E8E9EA") ;; $color-canvas

View File

@@ -20,7 +20,7 @@
(cond
(= 204 status)
;; We need to send "something" so the streams listening downstream can act
(rx/of :empty)
(rx/of nil)
(= 502 status)
(rx/throw {:type :bad-gateway})

View File

@@ -329,7 +329,7 @@
(fn [e]
(reset! dragging? false)
(when (not= selected-project project-id)
(let [data {:ids selected-files
(let [data {:ids (into #{} (keys selected-files))
:project-id project-id}
mdata {:on-success on-drop-success}]
(st/emit! (dd/move-files (with-meta data mdata)))))))]

View File

@@ -79,7 +79,8 @@
:min-width? true
:top top
:left left
:options [[(tr "labels.rename") on-edit]
:options [(when-not (:is-default project)
[(tr "labels.rename") on-edit])
[(tr "dashboard.duplicate") on-duplicate]
[(tr "dashboard.pin-unpin") toggle-pin]
(when (seq teams)

View File

@@ -12,11 +12,14 @@
[app.common.math :as mth]
[app.common.pages :as cp]
[app.common.uuid :as uuid]
[app.main.store :as st]
[app.main.data.fonts :as df]
[app.main.exports :as exports]
[app.main.repo :as repo]
[app.main.ui.context :as muc]
[app.main.ui.shapes.filters :as filters]
[app.main.ui.shapes.shape :refer [shape-container]]
[app.main.ui.shapes.text.embed :refer [embed-fontfaces-style]]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[cuerdas.core :as str]
@@ -42,6 +45,9 @@
objects (reduce updt-fn objects mod-ids)
object (get objects object-id)
txt-xfm (comp (map #(get objects %))
(filter #(= :text (:type %))))
txt-objs (into [] txt-xfm mod-ids)
{:keys [width height]} (gsh/points->selrect (:points object))
@@ -72,6 +78,9 @@
]
[:& (mf/provider muc/embed-ctx) {:value true}
(when (seq txt-objs)
[:& embed-fontfaces-style {:shapes txt-objs}])
[:svg {:id "screenshot"
:view-box vbox
:width width
@@ -79,6 +88,7 @@
:version "1.1"
:xmlnsXlink "http://www.w3.org/1999/xlink"
:xmlns "http://www.w3.org/2000/svg"}
(case (:type object)
:frame [:& frame-wrapper {:shape object :view-box vbox}]
:group [:> shape-container {:shape object}
@@ -97,7 +107,6 @@
(assoc objects (:id object) object))
objects))
;; NOTE: for now, it is ok download the entire file for render only
;; single page but in a future we need consider to add a specific
;; backend entry point for download only the data of single page.
@@ -106,12 +115,19 @@
[{:keys [file-id page-id object-id] :as props}]
(let [objects (mf/use-state nil)]
(mf/use-effect
#(let [subs (->> (repo/query! :file {:id file-id})
(rx/subs (fn [{:keys [data]}]
(let [objs (get-in data [:pages-index page-id :objects])
objs (adapt-root-frame objs object-id)]
(reset! objects objs)))))]
(fn [] (rx/dispose! subs))))
(mf/deps file-id page-id object-id)
(fn []
(->> (rx/zip
(repo/query! :font-variants {:file-id file-id})
(repo/query! :file {:id file-id}))
(rx/subs
(fn [[fonts {:keys [data]} :as kaka]]
(when (seq fonts)
(st/emit! (df/fonts-fetched fonts)))
(let [objs (get-in data [:pages-index page-id :objects])
objs (adapt-root-frame objs object-id)]
(reset! objects objs)))))
(constantly nil)))
(when @objects
[:& object-svg {:objects @objects

View File

@@ -86,12 +86,6 @@
:weight weight})]
(p/resolved result))))
(defn- to-promise
[observable]
(p/create (fn [resolve reject]
(->> (rx/take 1 observable)
(rx/subs resolve reject)))))
(defn fetch-font-data
"Parses the CSS and retrieves the font data as DataURI."
[^string css]
@@ -137,10 +131,10 @@
{::mf/wrap-props false
::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]}
[props]
(let [shapes (obj/get props "shapes")
node {:children (->> shapes (map :content))}
fonts (-> node get-node-fonts memoize)
style (mf/use-state nil)]
(let [shapes (obj/get props "shapes")
node {:children (->> shapes (map :content))}
fonts (-> node get-node-fonts memoize)
style (mf/use-state nil)]
(mf/use-effect
(mf/deps fonts)

View File

@@ -75,7 +75,7 @@
(mf/defc thumbnails-summary
[{:keys [on-toggle-expand on-close total] :as props}]
[:div.thumbnails-summary
[:span.counter (str total " frames")]
[:span.counter (tr "labels.num-of-frames" (i18n/c total))]
[:span.buttons
[:span.btn-expand {:on-click on-toggle-expand} i/arrow-down]
[:span.btn-close {:on-click on-close} i/close]]])

View File

@@ -102,23 +102,20 @@
{::mf/wrap [#(mf/memo' % check-frame-props) custom-deferred]
::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects")
thumbnail? (unchecked-get props "thumbnail?")
(let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects")
thumbnail? (unchecked-get props "thumbnail?")
edition (mf/deref refs/selected-edition)
edition (mf/deref refs/selected-edition)
embed-fonts? (mf/use-ctx muc/embed-ctx)
shape (gsh/transform-shape shape)
children (mapv #(get objects %) (:shapes shape))
text-childs (->> objects
vals
(filterv #(and (= :text (:type %))
(= (:id shape) (:frame-id %)))))
shape (gsh/transform-shape shape)
children (mapv #(get objects %) (:shapes shape))
text-childs (->> (vals objects)
(filterv #(and (= :text (:type %))
(= (:id shape) (:frame-id %)))))
ds-modifier (get-in shape [:modifiers :displacement])
rendered? (mf/use-state false)
rendered? (mf/use-state false)
show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))

View File

@@ -310,7 +310,7 @@
[content points]
(let [segments-set (into #{}
(map (fn [[p1 p2 _]] [p1 p2]))
(map (fn [{:keys [start end]}] [start end]))
(get-segments content points))
create-line-command (fn [point other]
@@ -382,7 +382,7 @@
(defn group-segments [segments]
(loop [result []
[point-a point-b :as segment] (first segments)
{point-a :start point-b :end :as segment} (first segments)
segments (rest segments)]
(if (nil? segment)

View File

@@ -82,21 +82,24 @@
([state label ids] (group-shapes state label ids "Group-"))
([state label ids prefix]
(let [page (current-page state)
shapes (dwg/shapes-for-grouping (:objects page) ids)
shapes (dwg/shapes-for-grouping (:objects page) ids)]
(if (empty? shapes)
state
(let [[group rchanges uchanges]
(dwg/prepare-create-group (:objects page) (:id page) shapes prefix true)]
[group rchanges uchanges]
(dwg/prepare-create-group (:objects page) (:id page) shapes prefix true)]
(swap! idmap assoc label (:id group))
(update state :workspace-data
cp/process-changes rchanges))))
(swap! idmap assoc label (:id group))
(update state :workspace-data
cp/process-changes rchanges))))))
(defn make-component
[state label ids]
(let [page (current-page state)
objects (wsh/lookup-page-objects state page-id)
shapes (dwg/shapes-for-grouping objects ids)
[group rchanges uchanges]
(dwlh/generate-add-component ids
(dwlh/generate-add-component shapes
(:objects page)
(:id page)
current-file-id)]

View File

@@ -981,6 +981,11 @@ msgid_plural "labels.num-of-files"
msgstr[0] "1 file"
msgstr[1] "%s files"
msgid "labels.num-of-frames"
msgid_plural "labels.num-of-frames"
msgstr[0] "1 artboard"
msgstr[1] "%s artboards"
#: src/app/main/ui/dashboard/team.cljs
msgid "labels.num-of-projects"
msgid_plural "labels.num-of-projects"
@@ -1438,11 +1443,11 @@ msgstr "%s - Penpot"
#: src/app/main/ui/handoff.cljs, src/app/main/ui/viewer.cljs
msgid "viewer.empty-state"
msgstr "No frames found on the page."
msgstr "No artboards found on the page."
#: src/app/main/ui/handoff.cljs, src/app/main/ui/viewer.cljs
msgid "viewer.frame-not-found"
msgstr "Frame not found."
msgstr "Artboard not found."
#: src/app/main/ui/viewer/header.cljs
msgid "viewer.header.dont-show-interactions"

View File

@@ -983,6 +983,11 @@ msgid_plural "labels.num-of-files"
msgstr[0] "1 archivo"
msgstr[1] "%s archivos"
msgid "labels.num-of-frames"
msgid_plural "labels.num-of-frames"
msgstr[0] "1 tablero"
msgstr[1] "%s tableros"
#: src/app/main/ui/dashboard/team.cljs
msgid "labels.num-of-projects"
msgid_plural "labels.num-of-projects"

View File

@@ -1 +1 @@
1.6.2-alpha
1.6.4-alpha