Show current penpot version

This commit is contained in:
Marina López
2025-08-21 13:03:23 +02:00
parent 61cfe2d142
commit 48825e1e59
8 changed files with 387 additions and 78 deletions

View File

@@ -9,6 +9,7 @@
### :heart: Community contributions (Thank you!)
### :sparkles: New features & Enhancements
- Show current Penpot version [Taiga #11603](https://tree.taiga.io/project/penpot/us/11603)
### :bug: Bugs fixed

View File

@@ -288,6 +288,14 @@ export class DashboardPage extends BaseWebSocketPage {
);
await expect(this.mainHeading).toHaveText("Libraries");
}
async openProfileMenu() {
await this.userAccount.click();
}
async clickProfileMenuItem(menuSection) {
await this.sidebarMenu.getByText(menuSection).click();
}
}
export default DashboardPage;

View File

@@ -0,0 +1,44 @@
import { test, expect } from "@playwright/test";
import DashboardPage from "../pages/DashboardPage";
test.beforeEach(async ({ page }) => {
await DashboardPage.init(page);
await DashboardPage.mockRPC(
page,
"get-profile",
"logged-in-user/get-profile-logged-in-no-onboarding.json",
);
});
test("Navigate to penpot changelog from profile menu", async ({ page }) => {
const dashboardPage = new DashboardPage(page);
await dashboardPage.goToDashboard();
await dashboardPage.openProfileMenu();
await dashboardPage.clickProfileMenuItem("About Penpot");
// Listen for the new page (tab) that opens when clicking "Penpot Changelog"
const [newPage] = await Promise.all([
page.context().waitForEvent("page"),
dashboardPage.clickProfileMenuItem("Penpot Changelog"),
]);
await newPage.waitForLoadState();
await expect(newPage).toHaveURL("https://github.com/penpot/penpot/blob/develop/CHANGES.md");
});
test("Opens release notes from current version from profile menu", async ({ page }) => {
const dashboardPage = new DashboardPage(page);
await dashboardPage.goToDashboard();
await dashboardPage.openProfileMenu();
await dashboardPage.clickProfileMenuItem("About Penpot");
await expect(
page.getByText("Version 0.0.0 notes"),
).toBeVisible();
await dashboardPage.clickProfileMenuItem("Version");
await expect(
page.getByText("new in penpot?"),
).toBeVisible();
});

View File

@@ -33,6 +33,7 @@
show-subscription-dashboard-banner?
get-subscription-type]]
[app.main.ui.dashboard.team-form]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
[app.main.ui.icons :as deprecated-icon]
[app.util.dom :as dom]
[app.util.dom.dnd :as dnd]
@@ -762,10 +763,139 @@
[:span {:class (stl/css :empty-text)} (tr "dashboard.no-projects-placeholder")]])]]
[:div {:class (stl/css-case :separator true :overflow-separator overflow?)}]]))
(mf/defc help-learning-menu*
{::mf/props :obj
::mf/private true}
[{:keys [on-close on-click]}]
(let [handle-click-url
(mf/use-fn
(fn [event]
(let [url (-> (dom/get-current-target event)
(dom/get-data "url"))
eventname (-> (dom/get-current-target event)
(dom/get-data "eventname"))]
(st/emit! (ptk/event ::ev/event {::ev/name eventname
::ev/origin "menu:in-app"}))
(dom/open-new-window url))))
handle-feedback-click
(mf/use-fn #(on-click :settings-feedback %))]
[:> dropdown-menu* {:show true
:class (stl/css :sub-menu :help-learning)
:on-close on-close}
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://help.penpot.app"
:on-click handle-click-url
:data-eventname "explore-help-center-click"}
(tr "labels.help-center")]
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://penpot.app/learning-center"
:on-click handle-click-url
:data-eventname "explore-learning-center-click"}
(tr "labels.learning-center")]
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://penpot.app/penpothub"
:on-click handle-click-url
:data-eventname "explore-penpot-hub-click"}
(tr "labels.penpot-hub")]
(when (contains? cf/flags :user-feedback)
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:on-click handle-feedback-click}
(tr "labels.give-feedback")])]))
(mf/defc community-contributions-menu*
{::mf/props :obj
::mf/private true}
[{:keys [on-close]}]
(let [handle-click-url
(mf/use-fn
(fn [event]
(let [url (-> (dom/get-current-target event)
(dom/get-data "url"))
eventname (-> (dom/get-current-target event)
(dom/get-data "eventname"))]
(st/emit! (ptk/event ::ev/event {::ev/name eventname
::ev/origin "menu:in-app"}))
(dom/open-new-window url))))]
[:> dropdown-menu* {:show true
:class (stl/css :sub-menu :community)
:on-close on-close}
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://github.com/penpot/penpot"
:on-click handle-click-url
:data-eventname "explore-github-repository-click"}
(tr "labels.github-repo")]
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://community.penpot.app"
:on-click handle-click-url
:data-eventname "explore-community-click"}
(tr "labels.community")]]))
(mf/defc about-penpot-menu*
{::mf/props :obj
::mf/private true}
[{:keys [on-close]}]
(let [version cf/version
show-release-notes
(mf/use-fn
(fn [event]
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version (:main version)}))
(if (and (kbd/alt? event) (kbd/mod? event))
(st/emit! (modal/show {:type :onboarding}))
(st/emit! (modal/show {:type :release-notes :version (:main version)})))))
handle-click-url
(mf/use-fn
(fn [event]
(let [url (-> (dom/get-current-target event)
(dom/get-data "url"))
eventname (-> (dom/get-current-target event)
(dom/get-data "eventname"))]
(st/emit! (ptk/event ::ev/event {::ev/name eventname
::ev/origin "menu:in-app"}))
(dom/open-new-window url))))]
[:> dropdown-menu* {:show true
:class (stl/css :sub-menu :about)
:on-close on-close}
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:on-click show-release-notes}
(tr "labels.version-notes" (:base version))]
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://github.com/penpot/penpot/blob/develop/CHANGES.md"
:on-click handle-click-url
:data-eventname "explore-changelog-click"}
(tr "labels.penpot-changelog")]
[:> dropdown-menu-item* {:class (stl/css :submenu-item)
:data-url "https://penpot.app/terms"
:on-click handle-click-url
:data-eventname "explore-terms-service-click"}
(tr "auth.terms-of-service")]]))
(mf/defc profile-section*
[{:keys [profile team]}]
(let [show-profile-menu* (mf/use-state false)
show-profile-menu? (deref show-profile-menu*)
sub-menu* (mf/use-state false)
sub-menu (deref sub-menu*)
version (:full cf/version)
close-sub-menu
(mf/use-fn
(fn [event]
(dom/stop-propagation event)
(reset! sub-menu* nil)))
photo
(cf/resolve-profile-photo-url profile)
@@ -779,15 +909,6 @@
(st/emit! (rt/nav section))
(st/emit! section))))
show-release-notes
(mf/use-fn
(fn [event]
(let [version (:main cf/version)]
(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}))))))
show-comments* (mf/use-state false)
show-comments? @show-comments*
@@ -816,16 +937,6 @@
on-close
(mf/use-fn #(reset! show-profile-menu* false))
handle-click-url
(mf/use-fn
(fn [event]
(let [url (-> (dom/get-current-target event)
(dom/get-data "url"))]
(dom/open-new-window url))))
handle-feedback-click
(mf/use-fn #(on-click :settings-feedback %))
handle-logout-click
(mf/use-fn
#(on-click (da/logout) %))
@@ -834,6 +945,15 @@
(mf/use-fn
#(on-click :settings-profile %))
on-menu-click
(mf/use-fn
(fn [event]
(dom/stop-propagation event)
(let [menu (-> (dom/get-current-target event)
(dom/get-data "testid")
(keyword))]
(reset! sub-menu* menu))))
on-power-up-click
(mf/use-fn
(fn []
@@ -887,53 +1007,45 @@
[:li {:class (stl/css :profile-separator)}]
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:data-url "https://help.penpot.app"
:on-click handle-click-url
:data-testid "help-center-profile-opt"}
(tr "labels.help-center")]
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:data-url "https://community.penpot.app"
:on-click handle-click-url}
(tr "labels.community")]
[:> dropdown-menu-item* {:class (stl/css-case :profile-dropdown-item true)
:on-click on-menu-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-menu-click event)))
:on-pointer-enter on-menu-click
:data-testid "help-learning"
:id "help-learning"}
[:span {:class (stl/css :item-name)} (tr "labels.help-learning")]
[:> icon* {:icon-id i/arrow :class (stl/css :open-arrow)}]]
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:data-url "https://www.youtube.com/c/Penpot"
:on-click handle-click-url}
(tr "labels.tutorials")]
[:> dropdown-menu-item* {:class (stl/css-case :profile-dropdown-item true)
:on-click on-menu-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-menu-click event)))
:on-pointer-enter on-menu-click
:data-testid "community-contributions"
:id "community-contributions"}
[:span {:class (stl/css :item-name)} (tr "labels.community-contributions")]
[:> icon* {:icon-id i/arrow :class (stl/css :open-arrow)}]]
[:> dropdown-menu-item* {:tab-index "0"
:class (stl/css :profile-dropdown-item)
:on-click show-release-notes}
(tr "labels.release-notes")]
[:> dropdown-menu-item* {:class (stl/css-case :profile-dropdown-item true)
:on-click on-menu-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-menu-click event)))
:on-pointer-enter on-menu-click
:data-testid "about-penpot"
:id "about-penpot"}
[:div {:class (stl/css :about-penpot)}
[:span {:class (stl/css :item-name)} (tr "labels.about-penpot")]
[:span {:class (stl/css :menu-version) :title version} version]]
[:> icon* {:icon-id i/arrow :class (stl/css :open-arrow)}]]
[:li {:class (stl/css :profile-separator)}]
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:data-url "https://penpot.app/libraries-templates"
:on-click handle-click-url
:data-testid "libraries-templates-profile-opt"}
(tr "labels.libraries-and-templates")]
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:data-url "https://github.com/penpot/penpot"
:on-click handle-click-url}
(tr "labels.github-repo")]
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:data-url "https://penpot.app/terms"
:on-click handle-click-url}
(tr "auth.terms-of-service")]
[:li {:class (stl/css :profile-separator)}]
(when (contains? cf/flags :user-feedback)
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item)
:on-click handle-feedback-click
:data-testid "feedback-profile-opt"}
(tr "labels.give-feedback")])
[:> dropdown-menu-item* {:class (stl/css :profile-dropdown-item :item-with-icon)
:on-click handle-logout-click
:data-testid "logout-profile-opt"}
@@ -943,7 +1055,18 @@
(when (and team profile)
[:> comments-icon*
{:profile profile
:on-show-comments handle-show-comments}])]]))
:on-show-comments handle-show-comments}])]
(case sub-menu
:help-learning
[:> help-learning-menu* {:on-close close-sub-menu :on-click on-click}]
:community-contributions
[:> community-contributions-menu* {:on-close close-sub-menu}]
:about-penpot
[:> about-penpot-menu* {:on-close close-sub-menu}]
nil)]))
(mf/defc sidebar*
{::mf/props :obj

View File

@@ -9,6 +9,8 @@
@use "../ds/spacing.scss" as *;
@use "../ds/_borders.scss" as *;
@use "../ds/_sizes.scss" as *;
@use "../ds/_utils.scss" as *;
@use "../ds/z-index.scss" as *;
@use "common/refactor/common-dashboard";
@use "common/refactor/common-refactor.scss" as deprecated;
@@ -24,7 +26,7 @@
margin: 0 var(--sp-l) 0 0;
border-right: $b-1 solid var(--panel-border-color);
background-color: var(--panel-background-color);
z-index: deprecated.$z-index-1;
z-index: var(--z-index-dropdown);
}
//SIDEBAR CONTENT COMPONENT
@@ -392,17 +394,81 @@
.profile-dropdown {
@extend .menu-dropdown;
left: var(--sp-l);
bottom: deprecated.$s-72;
min-width: $sz-252;
inset-inline-start: var(--sp-s);
inset-block-end: px2rem(72); // 72 is the height of the profile button
min-width: calc(100% - var(--sp-s));
// TODO ADD animation fadeInUp
}
.profile-dropdown-item {
@extend .menu-item-base;
@include t.use-typography("title-small");
height: $sz-40;
padding: var(--sp-s) var(--sp-l);
@include t.use-typography("body-medium");
block-size: $sz-40;
margin-block-end: var(--sp-xs);
padding: var(--sp-s);
padding-inline-start: var(--sp-l);
&:hover {
color: var(--menu-foreground-color-hover);
.open-arrow {
--icon-stroke-color: var(--menu-foreground-color-hover);
}
}
}
.profile-dropdown-item .open-arrow {
@include deprecated.flexCenter;
}
.profile-dropdown-item .open-arrow svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
.sub-menu {
@extend .menu-dropdown;
inset-inline-start: calc(deprecated.$s-292 + var(--sp-s));
min-width: deprecated.$s-192;
}
.sub-menu.help-learning {
inset-block-end: deprecated.$s-72;
}
.sub-menu.community {
inset-block-end: deprecated.$s-120;
}
.sub-menu.about {
inset-block-end: $sz-24;
}
.submenu-item {
@extend .menu-item-base;
@include t.use-typography("body-medium");
block-size: $sz-40;
margin-block-end: var(--sp-xs);
padding-block: var(--sp-s);
padding-inline: var(--sp-l);
&:hover {
color: var(--menu-foreground-color-hover);
}
}
.about-penpot {
align-items: baseline;
display: grid;
grid-template-columns: auto 1fr;
}
.menu-version {
@include t.use-typography("code-font");
@include deprecated.textEllipsis;
color: var(--color-foreground-secondary);
margin-inline-start: var(--sp-s);
text-transform: uppercase;
}
.profile-separator {

View File

@@ -53,22 +53,46 @@
::mf/wrap [mf/memo]}
[{:keys [layout on-close]}]
(let [nav-to-helpc-center
(mf/use-fn #(dom/open-new-window "https://help.penpot.app"))
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-help-center-click"
::ev/origin "workspace-menu:in-app"}))
(dom/open-new-window "https://help.penpot.app")))
nav-to-community
(mf/use-fn #(dom/open-new-window "https://community.penpot.app"))
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-community-click"
::ev/origin "workspace-menu:in-app"}))
(dom/open-new-window "https://community.penpot.app")))
nav-to-youtube
(mf/use-fn #(dom/open-new-window "https://www.youtube.com/c/Penpot"))
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-tutorials-click"
::ev/origin "workspace-menu:in-app"}))
(dom/open-new-window "https://www.youtube.com/c/Penpot")))
nav-to-templates
(mf/use-fn #(dom/open-new-window "https://penpot.app/libraries-templates"))
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-libraries-click"
::ev/origin "workspace"}))
(dom/open-new-window "https://penpot.app/libraries-templates")))
nav-to-github
(mf/use-fn #(dom/open-new-window "https://github.com/penpot/penpot"))
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-github-repository-click"
::ev/origin "workspace-menu:in-app"}))
(dom/open-new-window "https://github.com/penpot/penpot")))
nav-to-terms
(mf/use-fn #(dom/open-new-window "https://penpot.app/terms"))
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-terms-service-click"
::ev/origin "workspace-menu:in-app"}))
(dom/open-new-window "https://penpot.app/terms")))
nav-to-feedback
(mf/use-fn #(st/emit! (dcm/go-to-feedback)))
@@ -92,6 +116,7 @@
(fn [event]
(let [version (:main cf/version)]
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version}))
(println version)
(if (and (kbd/alt? event) (kbd/mod? event))
(st/emit! (modal/show {:type :onboarding}))
(st/emit! (modal/show {:type :release-notes :version version}))))))]

View File

@@ -2172,11 +2172,26 @@ msgstr "Go back"
msgid "labels.graphic-design"
msgstr "Graphic design"
#: src/app/main/ui/dashboard/sidebar.cljs:894, src/app/main/ui/workspace/main_menu.cljs:108, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1084, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1109, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1295
msgid "labels.help-learning"
msgstr "Help & Learning"
msgid "labels.community-contributions"
msgstr "Community & Contributions"
msgid "labels.about-penpot"
msgstr "About Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:1039, src/app/main/ui/workspace/main_menu.cljs:107, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1084, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1109, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1295
msgid "labels.help-center"
msgstr "Help Center"
#: src/app/main/ui/dashboard/templates.cljs:91
msgid "labels.learning-center"
msgstr "Learning Center"
msgid "labels.penpot-hub"
msgstr "Penpot hub"
#: src/app/main/ui/dashboard/templates.cljs:90
msgid "labels.hide"
msgstr "Hide"
@@ -2394,6 +2409,12 @@ msgstr "Refresh"
msgid "labels.release-notes"
msgstr "Release notes"
msgid "labels.version-notes"
msgstr "Version %s notes"
msgid "labels.penpot-changelog"
msgstr "Penpot Changelog"
#: src/app/main/ui/workspace.cljs
#, unused
msgid "labels.reload-file"

View File

@@ -2178,11 +2178,26 @@ msgstr "Volver"
msgid "labels.graphic-design"
msgstr "Diseño gráfico"
#: src/app/main/ui/dashboard/sidebar.cljs:894, src/app/main/ui/workspace/main_menu.cljs:108, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1084, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1109, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1295
msgid "labels.help-learning"
msgstr "Ayuda y aprendizaje"
msgid "labels.community-contributions"
msgstr "Comunidad y contribuciones"
msgid "labels.about-penpot"
msgstr "Acerca de Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:1039, src/app/main/ui/workspace/main_menu.cljs:107, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1084, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1109, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1295
msgid "labels.help-center"
msgstr "Centro de ayuda"
#: src/app/main/ui/dashboard/templates.cljs:91
msgid "labels.learning-center"
msgstr "Centro de aprendizaje"
msgid "labels.penpot-hub"
msgstr "Penpot hub"
#: src/app/main/ui/dashboard/templates.cljs:90
msgid "labels.hide"
msgstr "Ocultar"
@@ -2392,6 +2407,12 @@ msgstr "Referencia"
msgid "labels.release-notes"
msgstr "Notas de versión"
msgid "labels.version-notes"
msgstr "Notas versión %s"
msgid "labels.penpot-changelog"
msgstr "Registro de cambios de Penpot"
#: src/app/main/ui/workspace.cljs
#, unused
msgid "labels.reload-file"