From e730200873cb1cc999dafde84bb829fe477b01fe Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Aug 2025 12:07:19 +0200 Subject: [PATCH 1/3] :bug: Fix pinned project ordering on dashboard sidebar (#7060) --- CHANGES.md | 1 + .../src/app/main/ui/dashboard/sidebar.cljs | 102 +++++++++--------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 16ed1f9aea..832b1be0ad 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -54,6 +54,7 @@ - Fix the context menu always closes after any action [Taiga #11624](https://tree.taiga.io/project/penpot/issue/11624) - Fix X & Y position do not sincronize with tokens [Taiga #11617](https://tree.taiga.io/project/penpot/issue/11617) - Fix tooltip position after first time [Taiga #11688](https://tree.taiga.io/project/penpot/issue/11688) +- Fix inconsistent ordering of pinned projects on dashboard sidebar [Taiga #11674](https://tree.taiga.io/project/penpot/issue/11674) - Fix export button width on inspect tab [Taiga #11394](https://tree.taiga.io/project/penpot/issue/11394) - Fix stroke width token application [Taiga #11724](https://tree.taiga.io/project/penpot/issue/11724) - Fix number token application on shape [Taiga #11331](https://tree.taiga.io/project/penpot/task/11331) diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index 4c6a3c6191..7e88c005b3 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -34,7 +34,6 @@ [app.util.dom.dnd :as dnd] [app.util.i18n :as i18n :refer [tr]] [app.util.keyboard :as kbd] - [app.util.object :as obj] [app.util.timers :as ts] [beicon.v2.core :as rx] [cljs.spec.alpha :as s] @@ -196,7 +195,7 @@ :on-edit on-edit-open :on-menu-close on-menu-close}]])) -(mf/defc sidebar-search +(mf/defc sidebar-search* [{:keys [search-term team-id] :as props}] (let [search-term (or search-term "") focused? (mf/use-state false) @@ -586,8 +585,8 @@ :data-testid "delete-team"} (tr "dashboard.delete-team")])])) -(mf/defc sidebar-team-switch - [{:keys [team profile] :as props}] +(mf/defc sidebar-team-switch* + [{:keys [team profile]}] (let [teams (mf/deref refs/teams) teams-without-default (into {} (filter (fn [[_ v]] (= false (:is-default v))) teams)) team-ids (map #(str "teams-selector-" %) (keys teams-without-default)) @@ -606,10 +605,6 @@ (when (get-in team [:permissions :is-owner]) "teams-options-delete-team")] - - ;; _ (prn "--------------- sidebar-team-switch") - ;; _ (app.common.pprint/pprint teams) - handle-show-team-click (fn [event] (dom/stop-propagation event) @@ -716,8 +711,7 @@ :profile profile}]]])) (mf/defc sidebar-content* - {::mf/private true - ::mf/props :obj} + {::mf/private true} [{:keys [projects profile section team project search-term default-project] :as props}] (let [default-project-id (get default-project :id) @@ -730,6 +724,7 @@ drafts? (and (= section :dashboard-files) (= (:id project) default-project-id)) container (mf/use-ref nil) + overflow* (mf/use-state false) overflow? (deref overflow*) @@ -740,13 +735,14 @@ (mf/use-fn (mf/deps team-id) (fn [] - (st/emit! (dcm/go-to-dashboard-recent :team-id team-id) - (ts/schedule-on-idle - (fn [] - (when-let [projects-title (dom/get-element "dashboard-projects-title")] - (dom/set-attribute! projects-title "tabindex" "0") - (dom/focus! projects-title) - (dom/set-attribute! projects-title "tabindex" "-1"))))))) + (st/emit! + (dcm/go-to-dashboard-recent :team-id team-id) + (ts/schedule-on-idle + (fn [] + (when-let [projects-title (dom/get-element "dashboard-projects-title")] + (dom/set-attribute! projects-title "tabindex" "0") + (dom/focus! projects-title) + (dom/set-attribute! projects-title "tabindex" "-1"))))))) go-fonts (mf/use-fn @@ -756,14 +752,17 @@ go-fonts-with-key (mf/use-fn (mf/deps team) - #(st/emit! (dcm/go-to-dashboard-fonts :team-id team-id) - (ts/schedule-on-idle - (fn [] - (let [font-title (dom/get-element "dashboard-fonts-title")] - (when font-title - (dom/set-attribute! font-title "tabindex" "0") - (dom/focus! font-title) - (dom/set-attribute! font-title "tabindex" "-1"))))))) + (fn [] + (st/emit! + (dcm/go-to-dashboard-fonts :team-id team-id) + (ts/schedule-on-idle + (fn [] + (let [font-title (dom/get-element "dashboard-fonts-title")] + (when font-title + (dom/set-attribute! font-title "tabindex" "0") + (dom/focus! font-title) + (dom/set-attribute! font-title "tabindex" "-1")))))))) + go-drafts (mf/use-fn (mf/deps team-id default-project-id) @@ -785,39 +784,43 @@ go-libs (mf/use-fn (mf/deps team-id) - #(st/emit! (dcm/go-to-dashboard-libraries :team-id team-id))) + (fn [] (st/emit! (dcm/go-to-dashboard-libraries :team-id team-id)))) go-libs-with-key (mf/use-fn (mf/deps team-id) - #(st/emit! (dcm/go-to-dashboard-libraries :team-id team-id) - (ts/schedule-on-idle - (fn [] - (let [libs-title (dom/get-element "dashboard-libraries-title")] - (when libs-title - (dom/set-attribute! libs-title "tabindex" "0") - (dom/focus! libs-title) - (dom/set-attribute! libs-title "tabindex" "-1"))))))) - pinned-projects - (->> projects - (remove :is-default) - (filter :is-pinned))] + (fn [] + (st/emit! + (dcm/go-to-dashboard-libraries :team-id team-id) + (ts/schedule-on-idle + (fn [] + (let [libs-title (dom/get-element "dashboard-libraries-title")] + (when libs-title + (dom/set-attribute! libs-title "tabindex" "0") + (dom/focus! libs-title) + (dom/set-attribute! libs-title "tabindex" "-1")))))))) - (mf/use-layout-effect - (mf/deps pinned-projects) - (fn [] - (let [dom (mf/ref-val container) - client-height (obj/get dom "clientHeight") - scroll-height (obj/get dom "scrollHeight")] - (reset! overflow* (> scroll-height client-height))))) + pinned-projects + (mf/with-memo [projects] + (->> projects + (remove :is-default) + (filter :is-pinned) + (sort-by :name) + (not-empty)))] + + (mf/with-layout-effect [pinned-projects] + (let [node (mf/ref-val container) + client-height (.-clientHeight ^js node) + scroll-height (.-scrollHeight ^js node)] + (reset! overflow* (> scroll-height client-height)))) [:* [:div {:class (stl/css-case :sidebar-content true) :ref container} - [:& sidebar-team-switch {:team team :profile profile}] + [:> sidebar-team-switch* {:team team :profile profile}] - [:& sidebar-search {:search-term search-term - :team-id (:id team)}] + [:> sidebar-search* {:search-term search-term + :team-id (:id team)}] [:div {:class (stl/css :sidebar-content-section)} [:ul {:class (stl/css :sidebar-nav)} @@ -861,7 +864,7 @@ :data-testid "pinned-projects"} [:div {:class (stl/css :sidebar-section-title)} (tr "labels.pinned-projects")] - (if (seq pinned-projects) + (if (some? pinned-projects) [:ul {:class (stl/css :sidebar-nav :pinned-projects)} (for [item pinned-projects] [:& sidebar-project @@ -876,7 +879,6 @@ [:div {:class (stl/css-case :separator true :overflow-separator overflow?)}]])) (mf/defc profile-section* - {::mf/props :obj} [{:keys [profile team]}] (let [show* (mf/use-state false) show (deref show*) From ded8e39e73207574f4cd7b525c025b26a1e9fc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marina=20L=C3=B3pez?= Date: Mon, 4 Aug 2025 13:16:58 +0200 Subject: [PATCH 2/3] :bug: Fix hidden button in subscribe modal when there is a large number of teams (#7061) --- frontend/src/app/main/ui/settings/subscription.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/app/main/ui/settings/subscription.scss b/frontend/src/app/main/ui/settings/subscription.scss index f7602758d7..b69ea7a115 100644 --- a/frontend/src/app/main/ui/settings/subscription.scss +++ b/frontend/src/app/main/ui/settings/subscription.scss @@ -251,6 +251,8 @@ list-style-type: disc; margin-inline-start: var(--sp-xl); margin-block: var(--sp-xxl); + max-height: $s-216; + overflow-y: auto; } .input-field { From 85f6cf32ae5d82439a7adba5b51fff2c7272d559 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 Aug 2025 13:54:29 +0200 Subject: [PATCH 3/3] :bug: Several bugfixes (#7062) * :bug: Fix incorrect status validation on subscription internal api * :bug: Make the shortcuts overwritting optional --- backend/src/app/srepl/cli.clj | 2 +- frontend/src/app/main/data/shortcuts.cljs | 20 +++++++++---------- .../ui/workspace/colorpicker/shortcuts.cljs | 1 + frontend/vendor/mousetrap/index.js | 16 ++++++++------- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/backend/src/app/srepl/cli.clj b/backend/src/app/srepl/cli.clj index e9c441d240..18c4d982f9 100644 --- a/backend/src/app/srepl/cli.clj +++ b/backend/src/app/srepl/cli.clj @@ -186,7 +186,7 @@ "canceled" "incomplete" "incomplete_expired" - "pass_due" + "past_due" "paused" "trialing" "unpaid"]] diff --git a/frontend/src/app/main/data/shortcuts.cljs b/frontend/src/app/main/data/shortcuts.cljs index febed4486e..0509da896a 100644 --- a/frontend/src/app/main/data/shortcuts.cljs +++ b/frontend/src/app/main/data/shortcuts.cljs @@ -148,17 +148,17 @@ (defn- bind! [shortcuts] - (let [msbind (fn [command callback type] + (->> shortcuts + (remove #(:disabled (second %))) + (run! (fn [[key {:keys [command fn type overwrite]}]] + (let [callback (wrap-cb key fn) + undefined (js* "(void 0)") + commands (if (vector? command) + (into-array command) + #js [command])] (if type - (mousetrap/bind command callback type) - (mousetrap/bind command callback)))] - (->> shortcuts - (remove #(:disabled (second %))) - (run! (fn [[key {:keys [command fn type]}]] - (let [callback (wrap-cb key fn)] - (if (vector? command) - (run! #(msbind % callback type) command) - (msbind command callback type)))))))) + (mousetrap/bind commands callback type overwrite) + (mousetrap/bind commands callback undefined overwrite))))))) (defn- reset! ([] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/shortcuts.cljs b/frontend/src/app/main/ui/workspace/colorpicker/shortcuts.cljs index 8a25ee1d50..edea0f64d8 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/shortcuts.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/shortcuts.cljs @@ -24,5 +24,6 @@ {:delete-stop {:tooltip (ds/supr) :command ["del" "backspace"] :subsections [:edit] + :overwrite true :fn #(st/emit! (dwc/remove-gradient-stop))}})) diff --git a/frontend/vendor/mousetrap/index.js b/frontend/vendor/mousetrap/index.js index 06866e6a5b..5a0bc3e0bc 100644 --- a/frontend/vendor/mousetrap/index.js +++ b/frontend/vendor/mousetrap/index.js @@ -821,7 +821,7 @@ function Mousetrap(targetElement) { * @param {number=} level - what part of the sequence the command is * @returns void */ - function _bindSingle(combination, callback, action, sequenceName, level) { + function _bindSingle(combination, callback, action, sequenceName, level, overwrite) { // store a direct mapped reference for use with Mousetrap.trigger self._directMap[combination + ':' + action] = callback; @@ -845,8 +845,10 @@ function Mousetrap(targetElement) { // a callback is added for this key self._callbacks[info.key] = self._callbacks[info.key] || []; - // // remove an existing match if there is one - // _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level); + // remove an existing match if there is one + if (overwrite) { + _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level); + } // add this call back to the array // if it is a sequence put it at the beginning @@ -872,9 +874,9 @@ function Mousetrap(targetElement) { * @param {string|undefined} action * @returns void */ - self._bindMultiple = function(combinations, callback, action) { + self._bindMultiple = function(combinations, callback, action, overwrite) { for (var i = 0; i < combinations.length; ++i) { - _bindSingle(combinations[i], callback, action); + _bindSingle(combinations[i], callback, action, undefined, undefined, overwrite); } }; @@ -899,10 +901,10 @@ function Mousetrap(targetElement) { * @param {string=} action - 'keypress', 'keydown', or 'keyup' * @returns void */ -Mousetrap.prototype.bind = function(keys, callback, action) { +Mousetrap.prototype.bind = function(keys, callback, action, overwrite) { var self = this; keys = keys instanceof Array ? keys : [keys]; - self._bindMultiple.call(self, keys, callback, action); + self._bindMultiple.call(self, keys, callback, action, overwrite); return self; };