diff --git a/CHANGES.md b/CHANGES.md index 09ea41efc..83dac4172 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,14 @@ - Add support for WEBP format on shape export [Github #6053](https://github.com/penpot/penpot/pull/6053) and [Github #6074](https://github.com/penpot/penpot/pull/6074) +### :bug: Bugs fixed + +- Fix feature loading on workspace when opening a file in a background + tab [Taiga #10377](https://tree.taiga.io/project/penpot/issue/10377) +- Fix minor inconsistencies on RPC `get-file-libraries` and `get-file` + methods (add missing team-id prop) + + ## 2.5.3 ### :bug: Bugs fixed diff --git a/backend/src/app/rpc/commands/files.clj b/backend/src/app/rpc/commands/files.clj index bc512c0b7..e3e29ddf0 100644 --- a/backend/src/app/rpc/commands/files.clj +++ b/backend/src/app/rpc/commands/files.clj @@ -323,6 +323,7 @@ file (-> (get-file cfg id :project-id project-id) (assoc :permissions perms) + (assoc :team-id (:id team)) (check-version!))] (-> (cfeat/get-team-enabled-features cf/flags team) @@ -613,6 +614,7 @@ SELECT l.id, l.features, l.project_id, + p.team_id, l.created_at, l.modified_at, l.deleted_at, @@ -622,6 +624,7 @@ l.synced_at, l.is_shared FROM libs AS l + INNER JOIN project AS p ON (p.id = l.project_id) WHERE l.deleted_at IS NULL OR l.deleted_at > now();") (defn get-file-libraries diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index b3ebe6ace..564e97dd9 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -38,7 +38,9 @@ (declare process-message) (defn initialize - [] + [team-id] + (assert (uuid? team-id) "expected uuid instance for `team-id`") + (ptk/reify ::initialize ptk/WatchEvent (watch [_ state stream] @@ -46,8 +48,8 @@ profile-id (:profile-id state)] (->> (rx/merge - (rx/of (fetch-projects) - (df/fetch-fonts)) + (rx/of (fetch-projects team-id) + (df/fetch-fonts team-id)) (->> stream (rx/filter (ptk/type? ::dws/message)) (rx/map deref) @@ -60,8 +62,8 @@ (rx/take-until stopper)))))) (defn finalize - [] - (ptk/data-event ::finalize {})) + [team-id] + (ptk/data-event ::finalize {:team-id team-id})) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data Fetching (context aware: current team) @@ -69,7 +71,7 @@ ;; --- EVENT: fetch-projects -(defn projects-fetched +(defn- projects-fetched [projects] (ptk/reify ::projects-fetched ptk/UpdateEvent @@ -80,13 +82,12 @@ projects)))) (defn fetch-projects - [] + [team-id] (ptk/reify ::fetch-projects ptk/WatchEvent - (watch [_ state _] - (let [team-id (:current-team-id state)] - (->> (rp/cmd! :get-projects {:team-id team-id}) - (rx/map projects-fetched)))))) + (watch [_ _ _] + (->> (rp/cmd! :get-projects {:team-id team-id}) + (rx/map projects-fetched))))) ;; --- EVENT: search @@ -115,7 +116,7 @@ ;; --- EVENT: recent-files -(defn recent-files-fetched +(defn- recent-files-fetched [files] (ptk/reify ::recent-files-fetched ptk/UpdateEvent @@ -126,13 +127,14 @@ (update :files d/merge files)))))) (defn fetch-recent-files - [] - (ptk/reify ::fetch-recent-files - ptk/WatchEvent - (watch [_ state _] - (let [team-id (:current-team-id state)] - (->> (rp/cmd! :get-team-recent-files {:team-id team-id}) - (rx/map recent-files-fetched)))))) + ([] (fetch-recent-files nil)) + ([team-id] + (ptk/reify ::fetch-recent-files + ptk/WatchEvent + (watch [_ state _] + (when-let [team-id (or team-id (:current-team-id state))] + (->> (rp/cmd! :get-team-recent-files {:team-id team-id}) + (rx/map recent-files-fetched))))))) ;; --- EVENT: fetch-template-files diff --git a/frontend/src/app/main/data/fonts.cljs b/frontend/src/app/main/data/fonts.cljs index a1aba3d67..4706e7c5c 100644 --- a/frontend/src/app/main/data/fonts.cljs +++ b/frontend/src/app/main/data/fonts.cljs @@ -73,13 +73,12 @@ (fonts/register! :custom fonts)))))) (defn fetch-fonts - [] - (ptk/reify ::load-team-fonts + [team-id] + (ptk/reify ::fetch-fonts ptk/WatchEvent - (watch [_ state _] - (let [team-id (:current-team-id state)] - (->> (rp/cmd! :get-font-variants {:team-id team-id}) - (rx/map fonts-fetched)))))) + (watch [_ _ _] + (->> (rp/cmd! :get-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 diff --git a/frontend/src/app/main/data/team.cljs b/frontend/src/app/main/data/team.cljs index 50af94a44..43e169025 100644 --- a/frontend/src/app/main/data/team.cljs +++ b/frontend/src/app/main/data/team.cljs @@ -64,13 +64,14 @@ (update :profiles merge (d/index-by :id members)))))) (defn fetch-members - [] - (ptk/reify ::fetch-members - ptk/WatchEvent - (watch [_ state _] - (let [team-id (:current-team-id state)] - (->> (rp/cmd! :get-team-members {:team-id team-id}) - (rx/map (partial members-fetched team-id))))))) + ([] (fetch-members nil)) + ([team-id] + (ptk/reify ::fetch-members + ptk/WatchEvent + (watch [_ state _] + (when-let [team-id (or team-id (:current-team-id state))] + (->> (rp/cmd! :get-team-members {:team-id team-id}) + (rx/map (partial members-fetched team-id)))))))) (defn- invitations-fetched [team-id invitations] @@ -88,41 +89,20 @@ (->> (rp/cmd! :get-team-invitations {:team-id team-id}) (rx/map (partial invitations-fetched team-id))))))) -(defn set-current-team - [{:keys [id permissions features] :as team}] - (ptk/reify ::set-current-team - ptk/UpdateEvent - (update [_ state] - (-> state - ;; FIXME: redundant operation, only necessary on workspace - ;; until workspace initialization is refactored - (update-in [:teams id] merge team) - (assoc :permissions permissions) - ;; FIXME: this is a redundant operation that only needed by - ;; workspace; ti will not be needed after workspace - ;; bootstrap & urls refactor - (assoc :current-team-id id))) - - ptk/WatchEvent - (watch [_ _ _] - (rx/of (features/initialize (or features #{})))) - - ptk/EffectEvent - (effect [_ _ _] - (swap! storage/global assoc ::current-team-id id)))) - (defn- team-initialized - [] + [team-id] (ptk/reify ::team-initialized ptk/WatchEvent (watch [_ state _] - (let [team-id (:current-team-id state) - teams (get state :teams) - team (get teams team-id)] + (let [teams (get state :teams) + team (get teams team-id)] (if (not team) (rx/throw (ex/error :type :authentication)) - (rx/of (set-current-team team) - (fetch-members))))))) + (let [permissions (get team :permissions) + features (get team :features)] + (rx/of #(assoc % :permissions permissions) + (features/initialize (or features #{})) + (fetch-members team-id)))))))) (defn initialize-team [team-id] @@ -138,8 +118,7 @@ (rx/of (fetch-teams)) (->> stream (rx/filter (ptk/type? ::teams-fetched)) - (rx/observe-on :async) - (rx/map team-initialized))) + (rx/map (partial team-initialized team-id)))) (rx/take-until stopper)))))) (defn finalize-team @@ -169,7 +148,7 @@ params (assoc params :team-id team-id)] (->> (rp/cmd! :update-team-member-role params) (rx/mapcat (fn [_] - (rx/of (fetch-members) + (rx/of (fetch-members team-id) (fetch-teams) (ptk/data-event ::ev/event {::ev/name "update-team-member-role" @@ -187,7 +166,7 @@ params (assoc params :team-id team-id)] (->> (rp/cmd! :delete-team-member params) (rx/mapcat (fn [_] - (rx/of (fetch-members) + (rx/of (fetch-members team-id) (fetch-teams) (ptk/data-event ::ev/event {::ev/name "delete-team-member" diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 168e305c1..fc8295433 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -291,7 +291,8 @@ (watch [_ state stream] (let [features (features/get-team-enabled-features state) render-wasm? (contains? features "render-wasm/v1") - stopper-s (rx/filter (ptk/type? ::finalize-workspace) stream)] + stopper-s (rx/filter (ptk/type? ::finalize-workspace) stream) + team-id (:current-team-id state)] (->> (rx/concat ;; Firstly load wasm module if it is enabled and fonts @@ -305,7 +306,7 @@ (rx/filter (ptk/type? ::df/fonts-loaded)) (rx/take 1) (rx/ignore)) - (rx/of (df/fetch-fonts))) + (rx/of (df/fetch-fonts team-id))) ;; Then fetch file and thumbnails (->> (rx/zip (rp/cmd! :get-file {:id file-id :features features}) @@ -335,7 +336,7 @@ ptk/WatchEvent (watch [_ state stream] - (log/debug :hint "initialize-workspace" :file-id file-id) + (log/debug :hint "initialize-workspace" :file-id (dm/str file-id)) (let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream) rparams (rt/get-params state)] diff --git a/frontend/src/app/main/ui/dashboard.cljs b/frontend/src/app/main/ui/dashboard.cljs index d0d7bafde..9dbe96ae0 100644 --- a/frontend/src/app/main/ui/dashboard.cljs +++ b/frontend/src/app/main/ui/dashboard.cljs @@ -210,42 +210,45 @@ (swap! storage/session dissoc :plugin-url)))))) (defn use-templates-import - [can-edit? template-url default-project-id] - (mf/with-layout-effect - [can-edit? template-url default-project-id] - (when (and (some? template-url) (some? default-project-id)) - (if can-edit? - (let [valid-url? (and (str/ends-with? template-url ".penpot") - (str/starts-with? template-url cf/templates-uri)) - template-name (when valid-url? (subs template-url (count cf/templates-uri))) - on-import #(st/emit! (dpj/fetch-files default-project-id) - (dd/fetch-recent-files) - (dd/fetch-projects) - (dd/clear-selected-files) - (ptk/event ::ev/event {::ev/name "install-template-from-link-finished" - :name template-name - :url template-url}))] - (if valid-url? - (do - (st/emit! (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url})) - (->> (http/send! {:method :get - :uri template-url - :response-type :blob - :omit-default-headers true}) - (rx/subs! - (fn [result] - (if (or (< (:status result) 200) (>= (:status result) 300)) - (st/emit! (notif/error (tr "dashboard.import.error"))) - (st/emit! (modal/show - {:type :import - :project-id default-project-id - :entries [{:name template-name :uri (wapi/create-uri (:body result))}] - :on-finish-import on-import}))))))) - (st/emit! (notif/error (tr "dashboard.import.bad-url"))))) - (st/emit! (notif/error (tr "dashboard.import.no-perms")))) + [can-edit? template-url project] + (let [project-id (get project :id) + team-id (get project :team-id)] + (mf/with-layout-effect [can-edit? template-url project-id team-id] + (when (and (some? template-url) + (some? project-id) + (some? team-id)) + (if can-edit? + (let [valid-url? (and (str/ends-with? template-url ".penpot") + (str/starts-with? template-url cf/templates-uri)) + template-name (when valid-url? (subs template-url (count cf/templates-uri))) + on-import #(st/emit! (dpj/fetch-files project-id) + (dd/fetch-recent-files team-id) + (dd/fetch-projects team-id) + (dd/clear-selected-files) + (ptk/event ::ev/event {::ev/name "install-template-from-link-finished" + :name template-name + :url template-url}))] + (if valid-url? + (do + (st/emit! (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url})) + (->> (http/send! {:method :get + :uri template-url + :response-type :blob + :omit-default-headers true}) + (rx/subs! + (fn [result] + (if (or (< (:status result) 200) (>= (:status result) 300)) + (st/emit! (notif/error (tr "dashboard.import.error"))) + (st/emit! (modal/show + {:type :import + :project-id project-id + :entries [{:name template-name :uri (wapi/create-uri (:body result))}] + :on-finish-import on-import}))))))) + (st/emit! (notif/error (tr "dashboard.import.bad-url"))))) + (st/emit! (notif/error (tr "dashboard.import.no-perms")))) - (binding [storage/*sync* true] - (swap! storage/session dissoc :template-url))))) + (binding [storage/*sync* true] + (swap! storage/session dissoc :template-url)))))) (mf/defc dashboard* {::mf/props :obj} @@ -270,10 +273,10 @@ (hooks/use-shortcuts ::dashboard sc/shortcuts) - (mf/with-effect [] - (st/emit! (dd/initialize)) + (mf/with-effect [team-id] + (st/emit! (dd/initialize team-id)) (fn [] - (st/emit! (dd/finalize)))) + (st/emit! (dd/finalize team-id)))) (mf/with-effect [] (let [key (events/listen goog/global "keydown" @@ -285,7 +288,7 @@ (events/unlistenByKey key)))) (use-plugin-register plugin-url team-id (:id default-project)) - (use-templates-import can-edit? template-url (:id default-project)) + (use-templates-import can-edit? template-url default-project) [:& (mf/provider ctx/current-project-id) {:value project-id} [:> modal-container*] diff --git a/frontend/src/app/main/ui/dashboard/file_menu.cljs b/frontend/src/app/main/ui/dashboard/file_menu.cljs index f882c2179..6e10ede27 100644 --- a/frontend/src/app/main/ui/dashboard/file_menu.cljs +++ b/frontend/src/app/main/ui/dashboard/file_menu.cljs @@ -133,7 +133,7 @@ (st/emit! (dcm/go-to-dashboard-files {:project-id project-id :team-id team-id})) - (st/emit! (dd/fetch-recent-files) + (st/emit! (dd/fetch-recent-files team-id) (dd/clear-selected-files)))) on-move-accept diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 4a3112ca2..2a2bf20f7 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -566,8 +566,9 @@ on-finish-import (mf/use-fn + (mf/deps team-id) (fn [] - (st/emit! (dd/fetch-recent-files) + (st/emit! (dd/fetch-recent-files team-id) (dd/clear-selected-files)))) import-files (use-import-file project-id on-finish-import) @@ -608,9 +609,10 @@ on-drop-success (mf/use-fn + (mf/deps team-id) (fn [] (st/emit! (ntf/success (tr "dashboard.success-move-file")) - (dd/fetch-recent-files) + (dd/fetch-recent-files team-id) (dd/clear-selected-files)))) on-drop diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index c9fb7df2b..ce6b83afb 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -344,11 +344,13 @@ continue-template (mf/use-fn + (mf/deps on-finish-import) (fn [template] (let [on-success (fn [_event] (reset! status* :import-success) - (st/emit! (dd/fetch-recent-files))) + (when (fn? on-finish-import) + (on-finish-import))) on-error (fn [cause] @@ -479,8 +481,6 @@ [:> import-entry* {:entry (assoc template :status status) :can-be-deleted false}])] - ;; (prn "import-dialog" status) - [:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :action-buttons)} (when (= :analyze status) diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 12f22309b..3aaa590f8 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -105,7 +105,8 @@ [{:keys [project is-first team files can-edit]}] (let [locale (mf/deref i18n/locale) - project-id (:id project) + project-id (get project :id) + team-id (get team :id) file-count (or (:count project) 0) is-draft? (:is-default project) @@ -191,11 +192,11 @@ on-import (mf/use-fn - (mf/deps project-id) + (mf/deps project-id team-id) (fn [] (st/emit! (dpj/fetch-files project-id) - (dd/fetch-recent-files) - (dd/fetch-projects) + (dd/fetch-recent-files team-id) + (dd/fetch-projects team-id) (dd/clear-selected-files)))) handle-create-click @@ -317,6 +318,8 @@ (sort-by :modified-at) (reverse))) + team-id (get team :id) + recent-map (mf/deref ref:recent-files) permisions (:permissions team) @@ -327,7 +330,7 @@ show-team-hero* (mf/use-state #(get storage/global ::show-team-hero true)) show-team-hero? (deref show-team-hero*) - is-my-penpot (= (:default-team-id profile) (:id team)) + is-my-penpot (= (:default-team-id profile) team-id) is-defalt-team? (:is-default team) on-close @@ -346,8 +349,8 @@ (:name team))] (dom/set-html-title (tr "title.dashboard.projects" tname)))) - (mf/with-effect [] - (st/emit! (dd/fetch-recent-files) + (mf/with-effect [team-id] + (st/emit! (dd/fetch-recent-files team-id) (dd/clear-selected-files))) (when (seq projects) diff --git a/frontend/src/app/main/ui/dashboard/templates.cljs b/frontend/src/app/main/ui/dashboard/templates.cljs index b33694236..cef2fcc91 100644 --- a/frontend/src/app/main/ui/dashboard/templates.cljs +++ b/frontend/src/app/main/ui/dashboard/templates.cljs @@ -37,6 +37,7 @@ [template team-id project-id default-project-id section] (letfn [(on-finish [] (st/emit! + (dd/fetch-recent-files team-id) (ptk/event ::ev/event {::ev/name "import-template-finish" ::ev/origin "dashboard" :template (:name template) diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index 90d9111b2..0c6a8b8fe 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -568,7 +568,6 @@ [{:keys [starting-tab file-id] :as props :or {starting-tab :libraries}}] (let [files (mf/deref refs/files) file (get files file-id) - team-id (:team-id file) shared? (:is-shared file) linked-libraries @@ -616,8 +615,8 @@ :id "updates" :content updates-tab}]] - (mf/with-effect [team-id] - (st/emit! (dtm/fetch-shared-files team-id))) + (mf/with-effect [] + (st/emit! (dtm/fetch-shared-files))) [:div {:class (stl/css :modal-overlay) :on-click close-dialog-outside diff --git a/frontend/src/app/render.cljs b/frontend/src/app/render.cljs index d8a3d8650..258c98812 100644 --- a/frontend/src/app/render.cljs +++ b/frontend/src/app/render.cljs @@ -14,7 +14,6 @@ [app.common.types.components-list :as ctkl] [app.common.uri :as u] [app.main.data.fonts :as df] - [app.main.data.team :as dtm] [app.main.features :as features] [app.main.render :as render] [app.main.repo :as repo] @@ -30,6 +29,20 @@ (log/setup! {:app :info}) +(defn set-current-team + [{:keys [id permissions features] :as team}] + (ptk/reify ::set-current-team + ptk/UpdateEvent + (update [_ state] + (-> state + (assoc :permissions permissions) + (update :teams assoc id team) + (assoc :current-team-id id))) + + ptk/WatchEvent + (watch [_ _ _] + (rx/of (features/initialize (or features #{})))))) + (defn- fetch-team [& {:keys [file-id]}] (ptk/reify ::fetch-team @@ -37,7 +50,7 @@ (watch [_ _ _] (->> (repo/cmd! :get-team {:file-id file-id}) (rx/mapcat (fn [team] - (rx/of (dtm/set-current-team team) + (rx/of (set-current-team team) (ptk/data-event ::team-fetched team)))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;