Compare commits

...

28 Commits

Author SHA1 Message Date
Alejandro
1eaf7b2b44 Merge pull request #3593 from penpot/niwinz-staging-bugfixes-9
🐛 Bugfixes and logging improvements
2023-09-04 11:42:27 +02:00
Andrey Antukh
903f064e87 Decrease slightly argon2id cost for improve usability
The previous values are set too high. The current value are still
valid under current recomendation but improves a little bit the
time of password verification.
2023-09-04 11:35:31 +02:00
Andrey Antukh
a23d1908e9 Improve worker logging 2023-09-04 11:35:31 +02:00
Andrey Antukh
1e8226a3fc 🐛 Fix log level setting on file migrations ns 2023-09-04 11:35:31 +02:00
Andrey Antukh
b7459726f5 Merge pull request #3592 from penpot/superalex-remember-last-team-log-out-2
 Remember last team accross logouts and sessions and fix some weird stuff
2023-09-04 11:12:42 +02:00
Alejandro Alonso
b8179d0e35 Remember last team accross logouts and sessions and fix some auth weird stuff 2023-09-04 10:34:30 +02:00
Andrey Antukh
e36b49b4f0 Merge pull request #3587 from penpot/superalex-layer-multiselection-behaviour
 Improve layers multiselection behaviour
2023-09-01 11:20:27 +02:00
Alejandro Alonso
92ff5de538 Improve layers multiselection behaviour 2023-09-01 11:20:10 +02:00
Alejandro Alonso
c83d028466 Colorpicker: remember las color mode 2023-09-01 11:18:45 +02:00
Alejandro
56a0d522dc Merge pull request #3585 from penpot/niwinz-staging-storage-gc-deleted
 Add minor improvements to logging
2023-09-01 06:40:41 +02:00
Andrey Antukh
a3495800b5 Add minor logging improvements to worker namespace 2023-08-31 21:09:18 +02:00
Andrey Antukh
750cf05784 Add minor logging related improvements to binfile namespace 2023-08-31 21:08:23 +02:00
Andrey Antukh
1384219ae7 📎 Update devenv logging file 2023-08-31 21:08:01 +02:00
Andrey Antukh
d2d9aeff25 📎 Reduce log level of worker submit operation
Start logging to as TRACE instead of DEBUG
2023-08-31 20:59:58 +02:00
Andrey Antukh
95d80c9578 Merge pull request #3582 from penpot/superalex-fix-invalid-comments-when-delete-page
🐛 Fix deleted pages comments shown in right sidebar
2023-08-31 20:02:00 +02:00
Alejandro
b523bef8ba Merge pull request #3581 from penpot/niwinz-staging-storage-gc-deleted
 Improve storage-gc-deleted task reliability
2023-08-31 15:18:15 +02:00
Alejandro Alonso
0c5c04e58a 🐛 Fix deleted pages comments shown in right sidebar 2023-08-31 15:16:55 +02:00
Andrey Antukh
a0973b9ddf Improve storage-gc-deleted task reliability 2023-08-31 14:36:31 +02:00
Alejandro
c53b6117c0 Merge pull request #3574 from penpot/azazeln28-fix-text-shapes-rendered-with-bad-proportions
🐛 Fix text shapes rendered with bad proportions
2023-08-31 12:10:36 +02:00
Aitor
bd3ddebcc4 🐛 Fix text shapes rendered with bad proportions 2023-08-31 12:06:31 +02:00
Alejandro
0441f28880 Merge pull request #3577 from penpot/hiru-hide-messages-on-exit
🐛 Fix message popup remains open when exiting workspace
2023-08-31 11:45:41 +02:00
Andrés Moya
288030888a 🐛 Fix message popup remains open when exiting workspace 2023-08-31 11:39:46 +02:00
Alejandro
203c0ed87d Merge pull request #3579 from penpot/eva-refix-lock-title
🐛 Fix lock and hide tooltip
2023-08-31 11:38:51 +02:00
Eva
09e28076cd 🐛 Fix lock and hide tooltip 2023-08-31 11:31:58 +02:00
Alejandro
ad4e489312 Merge pull request #3578 from penpot/superalex-fix-list-view-is-discarded-on-tab-change-for-assets-sidebar-tab
🐛 Fix list view is discarded on tab change for assets sidebar
2023-08-31 11:31:13 +02:00
Alejandro Alonso
50932dea54 🐛 Fix list view is discarded on tab change for assets sidebar 2023-08-31 11:25:36 +02:00
Andrey Antukh
da3c829b1b 📎 Fix clj linter issues on backend 2023-08-31 11:24:30 +02:00
Andrey Antukh
d4b4e6be7d 🐛 Fix frontend cljs linter issues 2023-08-31 10:49:09 +02:00
25 changed files with 313 additions and 206 deletions

View File

@@ -1,5 +1,19 @@
# CHANGELOG
## 1.19.3
### :sparkles: New features
- Remember last color mode in colorpicker [Taiga #5508](https://tree.taiga.io/project/penpot/issue/5508)
- Improve layers multiselection behaviour [Github #5741](https://github.com/penpot/penpot/issues/5741)
- Remember last active team across logouts / sessions [Github #3325](https://github.com/penpot/penpot/issues/3325)
### :bug: Bugs fixed
- List view is discarded on tab change on Workspace Assets Sidebar tab [Github #3547](https://github.com/penpot/penpot/issues/3547)
- Fix message popup remains open when exiting workspace with browser back button [Taiga #5747](https://tree.taiga.io/project/penpot/issue/5747)
- When editing text if font is changed, the proportions of the rendered shape are wrong [Taiga #5786](https://tree.taiga.io/project/penpot/issue/5786)
## 1.19.2
### :sparkles: New features

View File

@@ -23,7 +23,7 @@
<Logger name="app.rpc.commands.binfile" level="debug" />
<Logger name="app.storage.tmp" level="debug" />
<Logger name="app.worker" level="info" />
<Logger name="app.worker" level="trace" />
<Logger name="app.msgbus" level="info" />
<Logger name="app.http.websocket" level="info" />
<Logger name="app.util.websocket" level="info" />

View File

@@ -8,14 +8,13 @@
(:require
[app.config :as cf]
[buddy.hashers :as hashers]
[cuerdas.core :as str]
[promesa.exec :as px]))
[cuerdas.core :as str]))
(def default-params
{:alg :argon2id
:memory (* 32768 2) ;; 64 MiB
:iterations 7
:parallelism (px/get-available-processors)})
:memory 32768 ;; 32 MiB
:iterations 3
:parallelism 2})
(defn derive-password
[password]

View File

@@ -382,8 +382,8 @@
;; --- GENERAL PURPOSE DYNAMIC VARS
(def ^:dynamic *state*)
(def ^:dynamic *options*)
(def ^:dynamic *state* nil)
(def ^:dynamic *options* nil)
;; --- EXPORT WRITER
@@ -773,7 +773,7 @@
(defn- lookup-index
[id]
(let [val (get-in @*state* [:index id])]
(l/debug :fn "lookup-index" :id id :val val ::l/sync? true)
(l/trc :fn "lookup-index" :id id :val val ::l/sync? true)
(when (and (not (::ignore-index-errors? *options*)) (not val))
(ex/raise :type :validation
:code :incomplete-index

View File

@@ -33,7 +33,7 @@
[cuerdas.core :as str]
[expound.alpha :as expound]))
(def ^:dynamic *conn*)
(def ^:dynamic *conn* nil)
(defn reset-password!
"Reset a password to a specific one for a concrete user or all users

View File

@@ -251,53 +251,59 @@
(defmethod ig/init-key ::gc-deleted-task
[_ {:keys [::db/pool ::storage ::min-age]}]
(letfn [(retrieve-deleted-objects-chunk [conn min-age cursor]
(let [min-age (db/interval min-age)
rows (db/exec! conn [sql:retrieve-deleted-objects-chunk min-age cursor])]
[(some-> rows peek :created-at)
(letfn [(get-to-delete-chunk [cursor]
(let [sql (str "select s.* "
" from storage_object as s "
" where s.deleted_at is not null "
" and s.deleted_at < ? "
" order by s.deleted_at desc "
" limit 25")
rows (db/exec! pool [sql cursor])]
[(some-> rows peek :deleted-at)
(some->> (seq rows) (d/group-by #(-> % :backend keyword) :id #{}) seq)]))
(retrieve-deleted-objects [conn min-age]
(d/iteration (partial retrieve-deleted-objects-chunk conn min-age)
:initk (dt/now)
(get-to-delete-chunks [min-age]
(d/iteration get-to-delete-chunk
:initk (dt/minus (dt/now) min-age)
:vf second
:kf first))
(delete-in-bulk [backend-id ids]
(let [backend (impl/resolve-backend storage backend-id)]
(delete-in-bulk! [backend-id ids]
(try
(db/with-atomic [conn pool]
(let [sql "delete from storage_object where id = ANY(?)"
ids' (db/create-array conn "uuid" ids)
(doseq [id ids]
(l/debug :hint "gc-deleted: permanently delete storage object" :backend backend-id :id id))
total (-> (db/exec-one! conn [sql ids'])
(db/get-update-count))]
(impl/del-objects-in-bulk backend ids)))]
(-> (impl/resolve-backend storage backend-id)
(impl/del-objects-in-bulk ids))
(doseq [id ids]
(l/dbg :hint "gc-deleted: permanently delete storage object" :backend backend-id :id id))
total))
(catch Throwable cause
(l/err :hint "gc-deleted: unexpected error on bulk deletion"
:ids (vec ids)
:cause cause)
0)))]
(fn [params]
(let [min-age (or (:min-age params) min-age)]
(db/with-atomic [conn pool]
(loop [total 0
groups (retrieve-deleted-objects conn min-age)]
(if-let [[backend-id ids] (first groups)]
(do
(delete-in-bulk backend-id ids)
(recur (+ total (count ids))
(rest groups)))
(do
(l/info :hint "gc-deleted: task finished" :min-age (dt/format-duration min-age) :total total)
{:deleted total}))))))))
(def sql:retrieve-deleted-objects-chunk
"with items_part as (
select s.id
from storage_object as s
where s.deleted_at is not null
and s.deleted_at < (now() - ?::interval)
and s.created_at < ?
order by s.created_at desc
limit 25
)
delete from storage_object
where id in (select id from items_part)
returning *;")
(let [min-age (or (some-> params :min-age dt/duration) min-age)]
(loop [total 0
chunks (get-to-delete-chunks min-age)]
(if-let [[backend-id ids] (first chunks)]
(let [deleted (delete-in-bulk! backend-id ids)]
(recur (+ total deleted)
(rest chunks)))
(do
(l/inf :hint "gc-deleted: task finished"
:min-age (dt/format-duration min-age)
:total total)
{:deleted total})))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Garbage Collection: Analyze touched objects

View File

@@ -87,10 +87,10 @@
(defmethod ig/init-key ::registry
[_ {:keys [::mtx/metrics ::tasks]}]
(l/info :hint "registry initialized" :tasks (count tasks))
(l/inf :hint "registry initialized" :tasks (count tasks))
(reduce-kv (fn [registry k v]
(let [tname (name k)]
(l/trace :hint "register task" :name tname)
(l/trc :hint "register task" :name tname)
(assoc registry tname (wrap-task-handler metrics tname v))))
{}
tasks))
@@ -141,18 +141,18 @@
(px/thread
{:name "penpot/executors-monitor" :virtual true}
(l/info :hint "monitor: started" :name name)
(l/inf :hint "monitor: started" :name name)
(try
(loop [steals 0]
(when-not (px/shutdown? executor)
(px/sleep interval)
(recur (long (monitor! executor steals)))))
(catch InterruptedException _cause
(l/debug :hint "monitor: interrupted" :name name))
(l/trc :hint "monitor: interrupted" :name name))
(catch Throwable cause
(l/error :hint "monitor: unexpected error" :name name :cause cause))
(l/err :hint "monitor: unexpected error" :name name :cause cause))
(finally
(l/info :hint "monitor: terminated" :name name))))))
(l/inf :hint "monitor: terminated" :name name))))))
(defmethod ig/halt-key! ::monitor
[_ thread]
@@ -207,10 +207,10 @@
(db/create-array conn "uuid" ids)]]
(db/exec-one! conn sql)
(l/debug :hist "dispatcher: queue tasks"
:queue queue
:tasks (count ids)
:queued res)))
(l/trc :hist "dispatcher: queue tasks"
:queue queue
:tasks (count ids)
:queued res)))
(run-batch! [rconn]
(try
@@ -225,35 +225,35 @@
(cond
(rds/exception? cause)
(do
(l/warn :hint "dispatcher: redis exception (will retry in an instant)" :cause cause)
(l/wrn :hint "dispatcher: redis exception (will retry in an instant)" :cause cause)
(px/sleep (::rds/timeout rconn)))
(db/sql-exception? cause)
(do
(l/warn :hint "dispatcher: database exception (will retry in an instant)" :cause cause)
(l/wrn :hint "dispatcher: database exception (will retry in an instant)" :cause cause)
(px/sleep (::rds/timeout rconn)))
:else
(do
(l/error :hint "dispatcher: unhandled exception (will retry in an instant)" :cause cause)
(l/err :hint "dispatcher: unhandled exception (will retry in an instant)" :cause cause)
(px/sleep (::rds/timeout rconn)))))))
(dispatcher []
(l/info :hint "dispatcher: started")
(l/inf :hint "dispatcher: started")
(try
(dm/with-open [rconn (rds/connect redis)]
(loop []
(run-batch! rconn)
(recur)))
(catch InterruptedException _
(l/trace :hint "dispatcher: interrupted"))
(l/trc :hint "dispatcher: interrupted"))
(catch Throwable cause
(l/error :hint "dispatcher: unexpected exception" :cause cause))
(l/err :hint "dispatcher: unexpected exception" :cause cause))
(finally
(l/info :hint "dispatcher: terminated"))))]
(l/inf :hint "dispatcher: terminated"))))]
(if (db/read-only? pool)
(l/warn :hint "dispatcher: not started (db is read-only)")
(l/wrn :hint "dispatcher: not started (db is read-only)")
(px/fn->thread dispatcher :name "penpot/worker/dispatcher" :virtual true))))
(defmethod ig/halt-key! ::dispatcher
@@ -286,7 +286,7 @@
(let [queue (d/name queue)
cfg (assoc cfg ::queue queue)]
(if (db/read-only? pool)
(l/warn :hint "worker: not started (db is read-only)" :queue queue :parallelism parallelism)
(l/wrn :hint "worker: not started (db is read-only)" :queue queue :parallelism parallelism)
(doall
(->> (range parallelism)
(map #(assoc cfg ::worker-id %))
@@ -300,7 +300,7 @@
[{:keys [::rds/redis ::worker-id ::queue] :as cfg}]
(px/thread
{:name (format "penpot/worker/runner:%s" worker-id)}
(l/info :hint "worker: started" :worker-id worker-id :queue queue)
(l/inf :hint "worker: started" :worker-id worker-id :queue queue)
(try
(dm/with-open [rconn (rds/connect redis)]
(let [tenant (cf/get :tenant "main")
@@ -320,14 +320,14 @@
:worker-id worker-id
:queue queue))
(catch Throwable cause
(l/error :hint "worker: unexpected exception"
:worker-id worker-id
:queue queue
:cause cause))
(l/err :hint "worker: unexpected exception"
:worker-id worker-id
:queue queue
:cause cause))
(finally
(l/info :hint "worker: terminated"
:worker-id worker-id
:queue queue)))))
(l/inf :hint "worker: terminated"
:worker-id worker-id
:queue queue)))))
(defn- run-worker-loop!
[{:keys [::db/pool ::rds/rconn ::timeout ::queue ::registry ::worker-id]}]
@@ -368,19 +368,19 @@
(let [task-id (t/decode payload)]
(if (uuid? task-id)
task-id
(l/error :hint "worker: received unexpected payload (uuid expected)"
:payload task-id)))
(l/err :hint "worker: received unexpected payload (uuid expected)"
:payload task-id)))
(catch Throwable cause
(l/error :hint "worker: unable to decode payload"
:payload payload
:length (alength payload)
:cause cause))))
(l/err :hint "worker: unable to decode payload"
:payload payload
:length (alength payload)
:cause cause))))
(handle-task [{:keys [name] :as task}]
(let [task-fn (get registry name)]
(if task-fn
(task-fn task)
(l/warn :hint "no task handler found" :name name))
(l/wrn :hint "no task handler found" :name name))
{:status :completed :task task}))
(handle-task-exception [cause task]
@@ -395,9 +395,9 @@
(= ::noop (:strategy edata))
(assoc :inc-by 0))
(do
(l/error :hint "worker: unhandled exception on task"
::l/context (get-error-context cause task)
:cause cause)
(l/err :hint "worker: unhandled exception on task"
::l/context (get-error-context cause task)
:cause cause)
(if (>= (:retry-num task) (:max-retries task))
{:status :failed :task task :error cause}
{:status :retry :task task :error cause})))))
@@ -414,31 +414,31 @@
(if (or (db/connection-error? task)
(db/serialization-error? task))
(do
(l/warn :hint "worker: connection error on retrieving task from database (retrying in some instants)"
:worker-id worker-id
:cause task)
(l/wrn :hint "worker: connection error on retrieving task from database (retrying in some instants)"
:worker-id worker-id
:cause task)
(px/sleep (::rds/timeout rconn))
(recur (get-task task-id)))
(do
(l/error :hint "worker: unhandled exception on retrieving task from database (retrying in some instants)"
:worker-id worker-id
:cause task)
(l/err :hint "worker: unhandled exception on retrieving task from database (retrying in some instants)"
:worker-id worker-id
:cause task)
(px/sleep (::rds/timeout rconn))
(recur (get-task task-id))))
(nil? task)
(l/warn :hint "worker: no task found on the database"
:worker-id worker-id
:task-id task-id)
(l/wrn :hint "worker: no task found on the database"
:worker-id worker-id
:task-id task-id)
:else
(try
(l/debug :hint "worker: executing task"
:name (:name task)
:id (:id task)
:queue queue
:worker-id worker-id
:retry (:retry-num task))
(l/trc :hint "executing task"
:name (:name task)
:id (str (:id task))
:queue queue
:worker-id worker-id
:retry (:retry-num task))
(handle-task task)
(catch InterruptedException cause
(throw cause))
@@ -459,13 +459,13 @@
(if (or (db/connection-error? cause)
(db/serialization-error? cause))
(do
(l/warn :hint "worker: database exeption on processing task result (retrying in some instants)"
:cause cause)
(l/wrn :hint "worker: database exeption on processing task result (retrying in some instants)"
:cause cause)
(px/sleep (::rds/timeout rconn))
(recur result))
(do
(l/error :hint "worker: unhandled exception on processing task result (retrying in some instants)"
:cause cause)
(l/err :hint "worker: unhandled exception on processing task result (retrying in some instants)"
:cause cause)
(px/sleep (::rds/timeout rconn))
(recur result))))))]
@@ -481,12 +481,12 @@
(catch Exception cause
(if (rds/timeout-exception? cause)
(do
(l/error :hint "worker: redis pop operation timeout, consider increasing redis timeout (will retry in some instants)"
:timeout timeout
:cause cause)
(l/err :hint "worker: redis pop operation timeout, consider increasing redis timeout (will retry in some instants)"
:timeout timeout
:cause cause)
(px/sleep timeout))
(l/error :hint "worker: unhandled exception" :cause cause))))))
(l/err :hint "worker: unhandled exception" :cause cause))))))
(defn- get-error-context
[_ item]
@@ -517,7 +517,7 @@
(defmethod ig/init-key ::cron
[_ {:keys [::entries ::registry ::db/pool] :as cfg}]
(if (db/read-only? pool)
(l/warn :hint "cron: not started (db is read-only)")
(l/wrn :hint "cron: not started (db is read-only)")
(let [running (atom #{})
entries (->> entries
(filter some?)
@@ -540,22 +540,22 @@
cfg (assoc cfg ::entries entries ::running running)]
(l/info :hint "cron: started" :tasks (count entries))
(synchronize-cron-entries! cfg)
(l/inf :hint "cron: started" :tasks (count entries))
(synchronize-cron-entries! cfg)
(->> (filter some? entries)
(run! (partial schedule-cron-task cfg)))
(->> (filter some? entries)
(run! (partial schedule-cron-task cfg)))
(reify
clojure.lang.IDeref
(deref [_] @running)
(reify
clojure.lang.IDeref
(deref [_] @running)
java.lang.AutoCloseable
(close [_]
(l/info :hint "cron: terminated")
(doseq [item @running]
(when-not (.isDone ^Future item)
(.cancel ^Future item true))))))))
java.lang.AutoCloseable
(close [_]
(l/inf :hint "cron: terminated")
(doseq [item @running]
(when-not (.isDone ^Future item)
(.cancel ^Future item true))))))))
(defmethod ig/halt-key! ::cron
[_ instance]
@@ -571,7 +571,7 @@
[{:keys [::db/pool ::entries]}]
(db/with-atomic [conn pool]
(doseq [{:keys [id cron]} entries]
(l/trace :hint "register cron task" :id id :cron (str cron))
(l/trc :hint "register cron task" :id id :cron (str cron))
(db/exec-one! conn [sql:upsert-cron-task id (str cron) (str cron)]))))
(defn- lock-scheduled-task!
@@ -589,7 +589,7 @@
(db/exec-one! conn ["SET statement_timeout=0;"])
(db/exec-one! conn ["SET idle_in_transaction_session_timeout=0;"])
(when (lock-scheduled-task! conn id)
(l/trace :hint "cron: execute task" :task-id id)
(l/dbg :hint "cron: execute task" :task-id id)
((:fn task) task))
(db/rollback! conn))
@@ -598,9 +598,9 @@
(catch Throwable cause
(binding [l/*context* (get-error-context cause task)]
(l/error :hint "cron: unhandled exception on running task"
:task-id id
:cause cause)))
(l/err :hint "cron: unhandled exception on running task"
:task-id id
:cause cause)))
(finally
(when-not (px/interrupted? :current)
(schedule-cron-task cfg task))))))
@@ -610,12 +610,16 @@
(s/assert dt/cron? cron)
(let [now (dt/now)
next (dt/next-valid-instant-from cron now)]
(inst-ms (dt/diff now next))))
(dt/diff now next)))
(defn- schedule-cron-task
[{:keys [::running] :as cfg} {:keys [cron] :as task}]
(let [ft (px/schedule! (ms-until-valid cron)
(partial execute-cron-task cfg task))]
[{:keys [::running] :as cfg} {:keys [cron id] :as task}]
(let [ts (ms-until-valid cron)
ft (px/schedule! ts (partial execute-cron-task cfg task))]
(l/dbg :hint "cron: schedule task" :task-id id
:ts (dt/format-duration ts)
:at (dt/format-instant (dt/in-future ts)))
(swap! running #(into #{ft} (filter p/pending?) %))))
@@ -678,13 +682,13 @@
(-> (db/exec-one! conn [sql:remove-not-started-tasks task queue label])
:next.jdbc/update-count))]
(l/debug :hint "submit task"
:name task
:queue queue
:label label
:dedupe (boolean dedupe)
:deleted (or deleted 0)
:in (dt/format-duration duration))
(l/trc :hint "submit task"
:name task
:queue queue
:label label
:dedupe (boolean dedupe)
:deleted (or deleted 0)
:in (dt/format-duration duration))
(db/exec-one! conn [sql:insert-new-task id task props queue
label priority max-retries interval])

View File

@@ -100,6 +100,7 @@
(configure-storage-backend))
content1 (sto/content "content1")
content2 (sto/content "content2")
content3 (sto/content "content3")
object1 (sto/put-object! storage {::sto/content content1
::sto/expired-at (dt/now)
:content-type "text/plain"
@@ -107,16 +108,20 @@
object2 (sto/put-object! storage {::sto/content content2
::sto/expired-at (dt/in-past {:hours 2})
:content-type "text/plain"
})
object3 (sto/put-object! storage {::sto/content content3
::sto/expired-at (dt/in-past {:hours 1})
:content-type "text/plain"
})]
(th/sleep 200)
(let [task (:app.storage/gc-deleted-task th/*system*)
res (task {})]
(let [res (th/run-task! :storage-gc-deleted {})]
(t/is (= 1 (:deleted res))))
(let [res (db/exec-one! th/*pool* ["select count(*) from storage_object;"])]
(t/is (= 1 (:count res))))))
(t/is (= 2 (:count res))))))
(t/deftest test-touched-gc-task-1
(let [storage (-> (:app.storage/storage th/*system*)

View File

@@ -12,7 +12,7 @@
[app.common.geom.shapes :as gsh]
[app.common.geom.shapes.path :as gsp]
[app.common.geom.shapes.text :as gsht]
[app.common.logging :as log]
[app.common.logging :as l]
[app.common.math :as mth]
[app.common.pages :as cp]
[app.common.pages.helpers :as cph]
@@ -25,7 +25,7 @@
(defmulti migrate :version)
(log/set-level! :info)
#?(:cljs (l/set-level! :info))
(defn migrate-data
([data] (migrate-data data cp/file-version))
@@ -33,7 +33,7 @@
(if (= (:version data) to-version)
data
(let [migrate-fn #(do
(log/trace :hint "migrate file" :id (:id %) :version-from %2 :version-to (inc %2))
(l/trc :hint "migrate file" :id (:id %) :version-from %2 :version-to (inc %2))
(migrate (assoc %1 :version (inc %2))))]
(reduce migrate-fn data (range (:version data 0) to-version))))))
@@ -450,11 +450,11 @@
;; If we cannot find any we let the frame-id as it was before
frame-id)]
(when (not= frame-id calculated-frame-id)
(log/info :hint "Fix wrong frame-id"
:shape (:name object)
:id (:id object)
:current (dm/get-in objects [frame-id :name])
:calculated (get-in objects [calculated-frame-id :name])))
(l/trc :hint "Fix wrong frame-id"
:shape (:name object)
:id (:id object)
:current (dm/get-in objects [frame-id :name])
:calculated (get-in objects [calculated-frame-id :name])))
(assoc object :frame-id calculated-frame-id)))
(update-container [container]

View File

@@ -279,8 +279,9 @@
(assoc-in (conj path :position) (:position comment-thread))
(assoc-in (conj path :frame-id) (:frame-id comment-thread))))))
(fetched [[users comments] state]
(let [pages (get-in state [:workspace-data :pages-index])
comments (filter #(some? (get pages (:page-id %))) comments)
(let [pages (-> (get-in state [:workspace-data :pages])
set)
comments (filter #(contains? pages (:page-id %)) comments)
state (-> state
(assoc :comment-threads (d/index-by :id comments))
(update :current-file-comments-users merge (d/index-by :id users)))]

View File

@@ -59,10 +59,11 @@
ptk/WatchEvent
(watch [_ state stream]
(rx/merge
;;fetch teams must be first in case the team doesn't exist
(ptk/watch (du/fetch-teams) state stream)
(ptk/watch (df/load-team-fonts id) state stream)
(ptk/watch (fetch-projects) state stream)
(ptk/watch (fetch-team-members) state stream)
(ptk/watch (du/fetch-teams) state stream)
(ptk/watch (du/fetch-users {:team-id id}) state stream)
(let [stoper (rx/filter (ptk/type? ::finalize) stream)

View File

@@ -125,7 +125,7 @@
accepting invitation, or third party auth signup or singin."
[profile]
(letfn [(get-redirect-event []
(let [team-id (:default-team-id profile)
(let [team-id (get-current-team-id profile)
redirect-url (:redirect-url @storage)]
(if (some? redirect-url)
(do
@@ -247,7 +247,9 @@
ptk/EffectEvent
(effect [_ _ _]
(reset! storage {})
;; We prefer to keek some stuff in the storage like the current-team-id
(swap! storage dissoc :redirect-url)
(swap! storage dissoc :profile)
(i18n/reset-locale)))))
(defn logout

View File

@@ -0,0 +1,28 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.main.data.workspace.assets
"Workspace assets management events and helpers."
(:require
[app.util.storage :refer [storage]]))
(defn get-current-assets-ordering
[]
(let [ordering (::ordering @storage)]
(or ordering :asc)))
(defn set-current-assets-ordering!
[ordering]
(swap! storage assoc ::ordering ordering))
(defn get-current-assets-list-style
[]
(let [list-style (::list-style @storage)]
(or list-style :thumbs)))
(defn set-current-assets-list-style!
[list-style]
(swap! storage assoc ::list-style list-style))

View File

@@ -22,6 +22,7 @@
[app.main.data.workspace.texts :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.util.color :as uc]
[app.util.storage :refer [storage]]
[beicon.core :as rx]
[potok.core :as ptk]))
@@ -647,3 +648,12 @@
:position :right})
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
:asset-type "color"}))))))
(defn get-active-color-tab
[]
(let [tab (::tab @storage)]
(or tab :ramp)))
(defn set-active-color-tab!
[tab]
(swap! storage assoc ::tab tab))

View File

@@ -122,7 +122,9 @@
(ptk/reify ::select-shape
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-local :selected] d/toggle-selection id toggle?))
(-> state
(update-in [:workspace-local :selected] d/toggle-selection id toggle?)
(assoc-in [:workspace-local :last-selected] id)))
ptk/WatchEvent
(watch [_ state _]
@@ -185,7 +187,9 @@
(ptk/reify ::deselect-shape
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-local :selected] disj id))))
(-> state
(update-in [:workspace-local :selected] disj id)
(update :workspace-local dissoc :last-selected)))))
(defn shift-select-shapes
([id]
@@ -196,12 +200,14 @@
ptk/UpdateEvent
(update [_ state]
(let [objects (or objects (wsh/lookup-page-objects state))
append-to-selection (cph/expand-region-selection objects (into #{} [(get-in state [:workspace-local :last-selected]) id]))
selection (-> state
wsh/lookup-selected
(conj id))]
(-> state
(assoc-in [:workspace-local :selected]
(cph/expand-region-selection objects selection))))))))
(set/union selection append-to-selection))
(update :workspace-local assoc :last-selected id)))))))
(defn select-shapes
[ids]

View File

@@ -153,8 +153,10 @@
(hooks/use-shortcuts ::dashboard sc/shortcuts)
(mf/with-effect [team-id]
(st/emit! (dd/initialize {:id team-id}))
(mf/with-effect [profile team-id]
(when profile
;; When doing logout we must avoid reinitializing the dashboard
(st/emit! (dd/initialize {:id team-id})))
(fn []
(dd/finalize {:id team-id})))

View File

@@ -230,8 +230,8 @@
]
(mf/with-effect [collapsed]
(when-not collapsed
(mf/with-effect [profile collapsed]
(when (and profile (not collapsed))
(st/emit! (dd/fetch-builtin-templates))))
[:div.dashboard-templates-section

View File

@@ -8,8 +8,10 @@
(:require-macros [app.main.style :refer [css]])
(:require
[app.common.data.macros :as dm]
[app.main.data.messages :as msg]
[app.main.data.modal :as modal]
[app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as dc]
[app.main.data.workspace.persistence :as dwp]
[app.main.features :as features]
[app.main.refs :as refs]
@@ -185,6 +187,9 @@
(st/emit! (dw/initialize-file project-id file-id))
(fn []
(st/emit! ::dwp/force-persist
(dc/stop-picker)
(modal/hide)
msg/hide
(dw/finalize-file project-id file-id))))
[:& (mf/provider ctx/current-file-id) {:value file-id}

View File

@@ -56,12 +56,17 @@
current-color (:current-color state)
active-tab (mf/use-state :ramp #_:harmony #_:hsva)
set-ramp-tab! (mf/use-fn #(reset! active-tab :ramp))
set-harmony-tab! (mf/use-fn #(reset! active-tab :harmony))
set-hsva-tab! (mf/use-fn #(reset! active-tab :hsva))
active-tab (mf/use-state (dc/get-active-color-tab))
drag? (mf/use-state false)
set-tab!
(mf/use-fn
(fn [event]
(let [tab (-> (dom/get-current-target event)
(dom/get-data "tab")
(keyword))]
(reset! active-tab tab)
(dc/set-active-color-tab! tab))))
handle-change-color
(mf/use-fn
@@ -81,9 +86,9 @@
(fn []
(if picking-color?
(do (modal/disallow-click-outside!)
(st/emit! (dc/stop-picker)))
(st/emit! (dc/stop-picker)))
(do (modal/allow-click-outside!)
(st/emit! (dc/start-picker))))))
(st/emit! (dc/start-picker))))))
handle-change-stop
(mf/use-fn
@@ -225,15 +230,18 @@
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
{:class (when (= @active-tab :ramp) "active")
:alt (tr "workspace.libraries.colors.rgba")
:on-click set-ramp-tab!} i/picker-ramp]
:on-click set-tab!
:data-tab "ramp"} i/picker-ramp]
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
{:class (when (= @active-tab :harmony) "active")
:alt (tr "workspace.libraries.colors.rgb-complementary")
:on-click set-harmony-tab!} i/picker-harmony]
:on-click set-tab!
:data-tab "harmony"} i/picker-harmony]
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
{:class (when (= @active-tab :hsva) "active")
:alt (tr "workspace.libraries.colors.hsv")
:on-click set-hsva-tab!} i/picker-hsv]]
:on-click set-tab!
:data-tab "hsva"} i/picker-hsv]]
(if picking-color?
[:div.picker-detail-wrapper

View File

@@ -13,7 +13,6 @@
[app.main.data.exports :as de]
[app.main.data.modal :as modal]
[app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as dc]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.shortcuts :as sc]
@@ -162,9 +161,7 @@
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version}))
(if (and (kbd/alt? event) (kbd/mod? event))
(st/emit! (modal/show {:type :onboarding}))
(st/emit! (modal/show {:type :release-notes :version version}))))))
]
(st/emit! (modal/show {:type :release-notes :version version}))))))]
[:& dropdown {:show true :on-close on-close}
[:ul.sub-menu.help-info
@@ -582,16 +579,10 @@
(dom/prevent-default event)
(reset! editing* true)))
close-modals
(mf/use-fn
#(st/emit! (dc/stop-picker)
(modal/hide)))
go-back
(mf/use-fn
(mf/deps project)
(fn []
(close-modals)
(st/emit! (dw/go-to-dashboard project))))
nav-to-viewer

View File

@@ -26,6 +26,7 @@
[app.util.object :as obj]
[app.util.text-editor :as ted]
[app.util.text-svg-position :as tsp]
[app.util.timers :as ts]
[promesa.core :as p]
[rumext.v2 :as mf]))
@@ -79,25 +80,29 @@
(defn- update-text-modifier
[{:keys [grow-type id] :as shape} node]
(->> (tsp/calc-position-data id)
(p/fmap (fn [position-data]
(let [props {:position-data position-data}]
(if (contains? #{:auto-height :auto-width} grow-type)
(let [{:keys [width height]} (-> (dom/query node ".paragraph-set") (dom/get-client-size))
width (mth/ceil width)
height (mth/ceil height)]
(if (and (not (mth/almost-zero? width)) (not (mth/almost-zero? height)))
(cond-> props
(= grow-type :auto-width)
(assoc :width width)
(p/let [position-data (tsp/calc-position-data id)
props {:position-data position-data}
props
(if (contains? #{:auto-height :auto-width} grow-type)
(let [{:keys [width height]} (-> (dom/query node ".paragraph-set") (dom/get-client-size))
width (mth/ceil width)
height (mth/ceil height)]
(if (and (not (mth/almost-zero? width)) (not (mth/almost-zero? height)))
(cond-> props
(= grow-type :auto-width)
(assoc :width width)
(or (= grow-type :auto-height) (= grow-type :auto-width))
(assoc :height height))
props))
props)]
(st/emit! (dwt/update-text-modifier id props))))
(or (= grow-type :auto-height) (= grow-type :auto-width))
(assoc :height height))
props))
props))))
(p/fmap (fn [props]
;; We need to wait for the text modifier to be updated before
;; we can update the position data. Otherwise the position data
;; will be wrong.
;; TODO: This is a hack. We need to find a better way to do this.
(st/emit! (dwt/update-text-modifier id props))
(ts/schedule 30 #(update-text-shape shape node))))))
(mf/defc text-container
{::mf/wrap-props false

View File

@@ -16,6 +16,7 @@
[app.main.data.events :as ev]
[app.main.data.modal :as modal]
[app.main.data.workspace :as dw]
[app.main.data.workspace.assets :as dwa]
[app.main.data.workspace.colors :as dc]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.media :as dwm]
@@ -2424,19 +2425,32 @@
[]
(let [components-v2 (mf/use-ctx ctx/components-v2)
read-only? (mf/use-ctx ctx/workspace-read-only?)
filters* (mf/use-state
{:term ""
:section :all
:ordering :asc
:list-style :thumbs})
:ordering (dwa/get-current-assets-ordering)
:list-style (dwa/get-current-assets-list-style)})
filters (deref filters*)
term (:term filters)
ordering (:ordering filters)
list-style (:list-style filters)
toggle-ordering
(mf/use-fn #(swap! filters* update :ordering toggle-values [:asc :desc]))
(mf/use-fn
(mf/deps ordering)
(fn []
(let [new-value (toggle-values ordering [:asc :desc])]
(swap! filters* assoc :ordering new-value)
(dwa/set-current-assets-ordering! new-value))))
toggle-list-style
(mf/use-fn #(swap! filters* update :list-style toggle-values [:thumbs :list]))
(mf/use-fn
(mf/deps list-style)
(fn []
(let [new-value (toggle-values list-style [:thumbs :list])]
(swap! filters* assoc :list-style new-value)
(dwa/set-current-assets-list-style! new-value))))
on-search-term-change
(mf/use-fn

View File

@@ -336,10 +336,16 @@
[:div.element-actions {:class (when (:shapes item) "is-parent")}
[:div.toggle-element {:class (when (:hidden item) "selected")
:title (if (:hidden item)
(tr "workspace.shape.menu.show")
(tr "workspace.shape.menu.hide"))
:on-click toggle-visibility}
(if (:hidden item) i/eye-closed i/eye)]
[:div.block-element {:class (when (:blocked item) "selected")
:on-click toggle-blocking}
:on-click toggle-blocking
:title (if (:blocked item)
(tr "workspace.shape.menu.unlock")
(tr "workspace.shape.menu.lock"))}
(if (:blocked item) i/lock i/unlock)]]
(when (:shapes item)

View File

@@ -86,7 +86,7 @@
(progress! context type file nil nil))
([context type current total]
(keyword? type)
(assert (keyword? type))
(assert (number? current))
(assert (number? total))
(progress! context type nil current total))

View File

@@ -1 +1 @@
1.19.2
1.19.3