From b3128bd32b1df718edb950ee05a7c6bb3163a5cc Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 10 Aug 2023 10:51:51 +0200 Subject: [PATCH 01/10] :bug: Fix overlay manual positioning --- frontend/src/app/main/ui/viewer/shapes.cljs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 13f9c1048..5c41de921 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -38,11 +38,10 @@ (defn- find-relative-to-base-frame [shape objects overlays-ids base-frame] - (if (or (empty? overlays-ids) (nil? shape) (cph/root? shape)) - base-frame - (if (contains? overlays-ids (:id shape)) - shape - (find-relative-to-base-frame (cph/get-parent objects (:id shape)) objects overlays-ids base-frame)))) + (cond + (cph/frame-shape? shape) shape + (or (empty? overlays-ids) (nil? shape) (cph/root? shape)) base-frame + :else (find-relative-to-base-frame (cph/get-parent objects (:id shape)) objects overlays-ids base-frame))) (defn- activate-interaction [interaction shape base-frame frame-offset objects overlays] From e5dedb1e3db3bce9e1da12f5808904a5788c6d45 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 10 Aug 2023 11:07:28 +0200 Subject: [PATCH 02/10] :tada: Add push notifications support --- backend/src/app/http/websocket.clj | 6 +- backend/src/app/srepl/main.clj | 108 ++++++++++++++++++ .../resources/styles/common/framework.scss | 4 + frontend/src/app/main/data/common.cljs | 33 ++++++ frontend/src/app/main/data/dashboard.cljs | 20 +++- frontend/src/app/main/data/messages.cljs | 11 ++ .../main/data/workspace/notifications.cljs | 6 +- frontend/translations/en.po | 4 + 8 files changed, 189 insertions(+), 3 deletions(-) diff --git a/backend/src/app/http/websocket.clj b/backend/src/app/http/websocket.clj index 3351566ca..bb29839a1 100644 --- a/backend/src/app/http/websocket.clj +++ b/backend/src/app/http/websocket.clj @@ -11,6 +11,7 @@ [app.common.logging :as l] [app.common.pprint :as pp] [app.common.spec :as us] + [app.common.uuid :as uuid] [app.db :as db] [app.http.session :as session] [app.metrics :as mtx] @@ -99,7 +100,10 @@ (sp/pipe ch output-ch false) ;; Subscribe to the profile topic on msgbus/redis - (mbus/sub! msgbus :topic profile-id :chan ch))) + (mbus/sub! msgbus :topic profile-id :chan ch) + + ;; Subscribe to the system topic on msgbus/redis + (mbus/sub! msgbus :topic (str uuid/zero) :chan ch))) (defmethod handle-message :close [{:keys [::mbus/msgbus]} {:keys [::ws/id ::ws/state ::profile-id ::session-id]} _] diff --git a/backend/src/app/srepl/main.clj b/backend/src/app/srepl/main.clj index 77413995b..4977829c4 100644 --- a/backend/src/app/srepl/main.clj +++ b/backend/src/app/srepl/main.clj @@ -8,10 +8,15 @@ "A collection of adhoc fixes scripts." #_:clj-kondo/ignore (:require + [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.logging :as l] [app.common.pprint :as p] [app.common.spec :as us] + [app.common.uuid :as uuid] + [app.config :as cf] [app.db :as db] + [app.msgbus :as mbus] [app.rpc.commands.auth :as auth] [app.rpc.commands.profile :as profile] [app.srepl.fixes :as f] @@ -164,3 +169,106 @@ (alter-var-root var (fn [f] (or (::original (meta f)) f)))) +(defn notify! + [{:keys [::mbus/msgbus ::db/pool]} & {:keys [dest code message level] + :or {code :generic level :info} + :as params}] + (dm/verify! + ["invalid level %" level] + (contains? #{:success :error :info :warning} level)) + + (dm/verify! + ["invalid code: %" code] + (contains? #{:generic :upgrade-version} code)) + + (letfn [(send [dest] + (l/inf :hint "sending notification" :dest (str dest)) + (let [message {:type :notification + :code code + :level level + :version (:full cf/version) + :subs-id dest + :message message} + message (->> (dissoc params :dest :code :message :level) + (merge message))] + (mbus/pub! msgbus + :topic (str dest) + :message message))) + + (resolve-profile [email] + (some-> (db/get* pool :profile {:email (str/lower email)} {:columns [:id]}) :id vector)) + + (resolve-team [team-id] + (->> (db/query pool :team-profile-rel + {:team-id team-id} + {:columns [:profile-id]}) + (map :profile-id))) + + (parse-uuid [v] + (if (uuid? v) + v + (d/parse-uuid v))) + + (resolve-dest [dest] + (cond + (uuid? dest) + [dest] + + (string? dest) + (some-> dest parse-uuid resolve-dest) + + (nil? dest) + (resolve-dest uuid/zero) + + (map? dest) + (sequence (comp + (map vec) + (mapcat resolve-dest)) + dest) + + (and (coll? dest) + (every? coll? dest)) + (sequence (comp + (map vec) + (mapcat resolve-dest)) + dest) + + (vector? dest) + (let [[op param] dest] + (cond + (= op :email) + (cond + (and (coll? param) + (every? string? param)) + (sequence (comp + (keep resolve-profile) + (mapcat identity)) + param) + + (string? param) + (resolve-profile param)) + + (= op :team-id) + (cond + (coll? param) + (sequence (comp + (mapcat resolve-team) + (keep parse-uuid)) + param) + + (uuid? param) + (resolve-team param) + + (string? param) + (some-> param parse-uuid resolve-team)) + + (= op :profile-id) + (if (coll? param) + (sequence (keep parse-uuid) param) + (resolve-dest param)))))) + ] + + (->> (resolve-dest dest) + (filter some?) + (into #{}) + (run! send)))) diff --git a/frontend/resources/styles/common/framework.scss b/frontend/resources/styles/common/framework.scss index 257ea2e31..660f29c4a 100644 --- a/frontend/resources/styles/common/framework.scss +++ b/frontend/resources/styles/common/framework.scss @@ -1157,6 +1157,7 @@ input[type="range"]:focus::-ms-fill-upper { .wrapper { display: flex; + align-items: center; .icon { padding: $size-2; @@ -1173,6 +1174,9 @@ input[type="range"]:focus::-ms-fill-upper { padding: $size-2; width: 100%; align-items: center; + + padding: 10px 15px; + min-height: 48px; } } diff --git a/frontend/src/app/main/data/common.cljs b/frontend/src/app/main/data/common.cljs index 684f2747c..b8106252a 100644 --- a/frontend/src/app/main/data/common.cljs +++ b/frontend/src/app/main/data/common.cljs @@ -7,7 +7,10 @@ (ns app.main.data.common "A general purpose events." (:require + [app.config :as cf] + [app.main.data.messages :as msg] [app.main.repo :as rp] + [app.util.i18n :refer [tr]] [beicon.core :as rx] [potok.core :as ptk])) @@ -43,3 +46,33 @@ (watch [_ _ _] (->> (rp/cmd! :delete-share-link {:id id}) (rx/ignore))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NOTIFICATIONS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn force-reload! + [] + (.reload js/location)) + +(defn handle-notification + [{:keys [message code level] :as params}] + (ptk/reify ::show-notification + ptk/WatchEvent + (watch [_ _ _] + (case code + :upgrade-version + (when (or (not= (:version params) (:full cf/version)) + (true? (:force params))) + (rx/of (msg/dialog + :content (tr "notifications.by-code.upgrade-version") + :controls :inline-actions + :type level + :actions [{:label "Refresh" :callback force-reload!}] + :tag :notification))) + + (rx/of (msg/dialog + :content message + :controls :close + :type level + :tag :notification)))))) diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 725e014a4..7d0e4cce8 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -13,10 +13,12 @@ [app.common.uri :as u] [app.common.uuid :as uuid] [app.config :as cf] + [app.main.data.common :refer [handle-notification]] [app.main.data.events :as ev] [app.main.data.fonts :as df] [app.main.data.media :as di] [app.main.data.users :as du] + [app.main.data.websocket :as dws] [app.main.features :as features] [app.main.repo :as rp] [app.util.dom :as dom] @@ -61,7 +63,23 @@ (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))))) + (ptk/watch (du/fetch-users {:team-id id}) state stream) + + (let [stoper (rx/filter (ptk/type? ::finalize) stream) + profile-id (:profile-id state)] + (->> stream + (rx/filter (ptk/type? ::dws/message)) + (rx/map deref) + (rx/filter (fn [{:keys [subs-id type] :as msg}] + (and (or (= subs-id uuid/zero) + (= subs-id profile-id)) + (= :notification type)))) + (rx/map handle-notification) + (rx/take-until stoper))))))) + +(defn finalize + [params] + (ptk/data-event ::finalize params)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data Fetching (context aware: current team) diff --git a/frontend/src/app/main/data/messages.cljs b/frontend/src/app/main/data/messages.cljs index bc1c7c7ad..8ace43228 100644 --- a/frontend/src/app/main/data/messages.cljs +++ b/frontend/src/app/main/data/messages.cljs @@ -120,6 +120,17 @@ :position :fixed :timeout timeout}))) +(defn dialog + [& {:keys [content controls actions position tag type] + :or {controls :none position :floating type :info}}] + (show (d/without-nils + {:content content + :type type + :position position + :controls controls + :actions actions + :tag tag}))) + (defn info-dialog ([content controls actions] (info-dialog content controls actions nil)) diff --git a/frontend/src/app/main/data/workspace/notifications.cljs b/frontend/src/app/main/data/workspace/notifications.cljs index 840d1aec9..e7ab37432 100644 --- a/frontend/src/app/main/data/workspace/notifications.cljs +++ b/frontend/src/app/main/data/workspace/notifications.cljs @@ -10,6 +10,8 @@ [app.common.data.macros :as dm] [app.common.pages.changes :as cpc] [app.common.schema :as sm] + [app.common.uuid :as uuid] + [app.main.data.common :refer [handle-notification]] [app.main.data.websocket :as dws] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.libraries :as dwl] @@ -57,8 +59,9 @@ (rx/filter (ptk/type? ::dws/message)) (rx/map deref) (rx/filter (fn [{:keys [subs-id] :as msg}] - (or (= subs-id team-id) + (or (= subs-id uuid/zero) (= subs-id profile-id) + (= subs-id team-id) (= subs-id file-id)))) (rx/map process-message)) @@ -96,6 +99,7 @@ :pointer-update (handle-pointer-update msg) :file-change (handle-file-change msg) :library-change (handle-library-change msg) + :notification (handle-notification msg) nil)) (defn- handle-pointer-send diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 13b41ee30..27fc40870 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -4960,3 +4960,7 @@ msgstr "Marketing" #: src/app/main/ui/onboarding/questions.cljs msgid "questions.student-teacher" msgstr "Student or teacher" + +#: src/app/main/data/common.cljs +msgid "notifications.by-code.upgrade-version" +msgstr "A new version is available, please refresh the page" From 5d5d238fec4ed965b30d064cc03de87b4276f959 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 10 Aug 2023 11:07:47 +0200 Subject: [PATCH 03/10] :lipstick: Add minor cosmetic improvements on dashboard ui component --- frontend/src/app/main/ui/dashboard.cljs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard.cljs b/frontend/src/app/main/ui/dashboard.cljs index 209705c45..263feec1c 100644 --- a/frontend/src/app/main/ui/dashboard.cljs +++ b/frontend/src/app/main/ui/dashboard.cljs @@ -154,18 +154,18 @@ (hooks/use-shortcuts ::dashboard sc/shortcuts) (mf/with-effect [team-id] - (st/emit! (dd/initialize {:id team-id}))) + (st/emit! (dd/initialize {:id team-id})) + (fn [] + (dd/finalize {:id team-id}))) - (mf/use-effect - (fn [] - (let [events [(events/listen goog/global "keydown" - (fn [event] - (when (kbd/enter? event) - (dom/stop-propagation event) - (st/emit! (dd/open-selected-file)))))]] - (fn [] - (doseq [key events] - (events/unlistenByKey key)))))) + (mf/with-effect [] + (let [key (events/listen goog/global "keydown" + (fn [event] + (when (kbd/enter? event) + (dom/stop-propagation event) + (st/emit! (dd/open-selected-file)))))] + (fn [] + (events/unlistenByKey key)))) [:& (mf/provider ctx/current-team-id) {:value team-id} [:& (mf/provider ctx/current-project-id) {:value project-id} From da62a6809c9f047056bda9cf6c649b03532236ae Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 10 Aug 2023 12:01:55 +0200 Subject: [PATCH 04/10] :sparkles: Stop report oidc failed operations as exceptions --- backend/src/app/auth/oidc.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 89fe77ef3..733665151 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -567,7 +567,7 @@ profile (get-profile cfg info)] (generate-redirect cfg request info profile)) (catch Throwable cause - (l/error :hint "error on oauth process" :cause cause) + (l/warn :hint "error on oauth process" :cause cause) (generate-error-redirect cfg cause)))) (def provider-lookup From 28836d82cdfb086c7c9b16ce0e8e109a9d4bad2f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 10 Aug 2023 15:44:11 +0200 Subject: [PATCH 05/10] :sparkles: Add minor improvements to error report template --- backend/resources/app/templates/error-report.v3.tmpl | 9 +++++---- backend/resources/app/templates/styles.css | 5 +++++ backend/src/app/http/debug.clj | 6 ++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/resources/app/templates/error-report.v3.tmpl b/backend/resources/app/templates/error-report.v3.tmpl index 66e2ad2ed..0892e77b3 100644 --- a/backend/resources/app/templates/error-report.v3.tmpl +++ b/backend/resources/app/templates/error-report.v3.tmpl @@ -7,7 +7,7 @@ Report: {{hint|abbreviate:150}} - {{id}} - Penpot Error Report (v3) {% block content %}