From 768d6e164bf0def6125eaf502f826aa14db84904 Mon Sep 17 00:00:00 2001 From: sokumon Date: Sat, 20 Dec 2025 20:03:30 +0530 Subject: [PATCH 1/4] fix(menu): translate item labels --- frappe/public/js/frappe/ui/menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/menu.js b/frappe/public/js/frappe/ui/menu.js index 2597bf5e90..875d3a9d6f 100644 --- a/frappe/public/js/frappe/ui/menu.js +++ b/frappe/public/js/frappe/ui/menu.js @@ -51,7 +51,7 @@ frappe.ui.menu = class ContextMenu { >` } - ${item.label} + ${__(item.label)} From 59a8fdc5a754a76582684c0945826fb38d64ec4e Mon Sep 17 00:00:00 2001 From: sokumon Date: Sat, 20 Dec 2025 23:37:20 +0530 Subject: [PATCH 2/4] feat: bring workspace creation controls to the breadcrumb --- frappe/public/js/frappe/views/breadcrumbs.js | 14 ++- .../js/frappe/views/workspace/workspace.js | 92 +++++++++---------- frappe/public/scss/desk/breadcrumb.scss | 3 + frappe/public/scss/desk/desktop.scss | 2 +- 4 files changed, 58 insertions(+), 53 deletions(-) diff --git a/frappe/public/js/frappe/views/breadcrumbs.js b/frappe/public/js/frappe/views/breadcrumbs.js index 04eacfcce8..ef92c1a2df 100644 --- a/frappe/public/js/frappe/views/breadcrumbs.js +++ b/frappe/public/js/frappe/views/breadcrumbs.js @@ -53,9 +53,21 @@ frappe.breadcrumbs = { this.clear(); if (!breadcrumbs) return this.toggle(false); - if (breadcrumbs.type === "Custom") { this.set_custom_breadcrumbs(breadcrumbs); + if (breadcrumbs.menu_items && breadcrumbs.menu_items.length) { + let breadcrumbs_container = $(".navbar-breadcrumbs"); + breadcrumbs_container.each((index, container) => { + let last_element = $(container) + .find("li") + .get($(container).find("li").length - 1); + $(last_element).find("a").attr("href", ""); + frappe.ui.create_menu({ + parent: $(last_element), + menu_items: breadcrumbs.menu_items, + }); + }); + } } else { // workspace this.set_workspace_breadcrumb(breadcrumbs); diff --git a/frappe/public/js/frappe/views/workspace/workspace.js b/frappe/public/js/frappe/views/workspace/workspace.js index 5d1c12a8be..89d812d65f 100644 --- a/frappe/public/js/frappe/views/workspace/workspace.js +++ b/frappe/public/js/frappe/views/workspace/workspace.js @@ -73,45 +73,7 @@ frappe.views.Workspace = class Workspace { } prepare_container() { this.body = this.wrapper.find(".layout-main-section"); - this.prepare_new_and_edit(); - } - - prepare_new_and_edit() { - this.$page = $(` -
-
-

-
-
- - `).appendTo(this.body); - - this.body.find(".btn-new-workspace").on("click", () => { - this.initialize_new_page(true); - }); - - this.body.find(".btn-edit-workspace").on("click", async () => { - if (!this.editor || !this.editor.readOnly) return; - this.is_read_only = false; - await this.editor.readOnly.toggle(); - this.editor.isReady.then(() => { - this.setup_customization_buttons(this._page); - this.make_blocks_sortable(); - }); - }); + this.$page = $(`
`).appendTo(this.body); } get_pages() { @@ -216,17 +178,46 @@ frappe.views.Workspace = class Workspace { let current_page = this.workspaces.find((p) => p.name == page.name); this._page = current_page; - if (frappe.boot.app_name_style == "Title") { - frappe.breadcrumbs.add({ - type: "Custom", - label: __(this._page.name), - }); - this.wrapper.find(".workspace-header").hide(); - this.wrapper - .find(".editor-js-container") - .get(0) - .style.setProperty("margin-top", "var(--margin-sm)"); - } + const me = this; + let header_dropdown = `${__(this._page.name)} ${frappe.utils.icon("chevron-down")}`; + frappe.breadcrumbs.add({ + type: "Custom", + label: header_dropdown, + route: "#", + menu_items: [ + { + label: "Edit", + icon: "edit", + onClick: async () => { + if (!this.editor || !this.editor.readOnly) return; + this.is_read_only = false; + await this.editor.readOnly.toggle(); + this.editor.isReady.then(() => { + this.setup_customization_buttons(this._page); + this.make_blocks_sortable(); + }); + }, + condition: () => { + return current_page.is_editable; + }, + }, + { + label: "New", + icon: "plus", + onClick: function () { + me.initialize_new_page(true); + }, + condition: () => { + return me.has_create_access; + }, + }, + ], + }); + this.wrapper.find(".workspace-header").hide(); + this.wrapper + .find(".editor-js-container") + .get(0) + .style.setProperty("margin-top", "var(--margin-sm)"); // set app let app; @@ -341,7 +332,6 @@ frappe.views.Workspace = class Workspace { // switch headers if (!this.body.hasClass("edit-mode")) { - this.wrapper.find(".page-head").addClass("hidden"); this.wrapper.find(".workspace-header").removeClass("hidden"); } } diff --git a/frappe/public/scss/desk/breadcrumb.scss b/frappe/public/scss/desk/breadcrumb.scss index 812a06ea65..e7edcad0f3 100644 --- a/frappe/public/scss/desk/breadcrumb.scss +++ b/frappe/public/scss/desk/breadcrumb.scss @@ -6,10 +6,13 @@ /*! This comment will be included even in compressed mode. */ .navbar-breadcrumbs { flex-wrap: nowrap; + align-items: center; + line-height: 1; a { text-decoration: none; color: var(--ink-gray-5); font-weight: var(--weight-medium); + font-size: var(--text-lg); letter-spacing: get_letterspacing("sm", "regular"); &:hover { color: var(--ink-gray-7); diff --git a/frappe/public/scss/desk/desktop.scss b/frappe/public/scss/desk/desktop.scss index ab9b2f3e84..1de2d3e3a4 100644 --- a/frappe/public/scss/desk/desktop.scss +++ b/frappe/public/scss/desk/desktop.scss @@ -948,8 +948,8 @@ body { } .page-head .container { - max-width: var(--page-max-width); margin: auto; + margin-left: 0px; } .layout-main-section-wrapper { From a70c7afc17f194bf3bab3c49a0cfe1d9a30f6280 Mon Sep 17 00:00:00 2001 From: sokumon Date: Sun, 21 Dec 2025 01:32:05 +0530 Subject: [PATCH 3/4] fix(test): use breadcrumb title --- cypress/integration/view_routing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/view_routing.js b/cypress/integration/view_routing.js index 794c2d6358..c6ada85af6 100644 --- a/cypress/integration/view_routing.js +++ b/cypress/integration/view_routing.js @@ -226,6 +226,6 @@ context("View", () => { it("Route to Website Workspace", () => { cy.visit("/desk/website"); - cy.get(".workspace-title").should("contain", "Website"); + cy.get(".navbar-breadcrumbs:visible").get("li > a").should("contain", "Website"); }); }); From ac9228cfec313c6333e1365f9584cf0af1241fc2 Mon Sep 17 00:00:00 2001 From: sokumon Date: Sun, 21 Dec 2025 01:54:30 +0530 Subject: [PATCH 4/4] fix(menu): add ability to control menu size --- frappe/public/js/frappe/ui/menu.js | 9 +++++++++ frappe/public/js/frappe/views/breadcrumbs.js | 1 + 2 files changed, 10 insertions(+) diff --git a/frappe/public/js/frappe/ui/menu.js b/frappe/public/js/frappe/ui/menu.js index 875d3a9d6f..160f3bd99d 100644 --- a/frappe/public/js/frappe/ui/menu.js +++ b/frappe/public/js/frappe/ui/menu.js @@ -7,6 +7,7 @@ frappe.ui.menu = class ContextMenu { this.menu_items = opts.menu_items; this.name = frappe.utils.get_random(5); this.open_on_left = opts.open_on_left; + this.size = opts.size; this.opts = opts; } @@ -28,6 +29,14 @@ frappe.ui.menu = class ContextMenu { // $(document.body).append(this.template); // } $(document.body).append(this.template); + this.set_styles(); + } + set_styles() { + if (this.size) { + this.template.css({ + width: this.size, + }); + } } add_menu_item(item) { const me = this; diff --git a/frappe/public/js/frappe/views/breadcrumbs.js b/frappe/public/js/frappe/views/breadcrumbs.js index ef92c1a2df..352121d98e 100644 --- a/frappe/public/js/frappe/views/breadcrumbs.js +++ b/frappe/public/js/frappe/views/breadcrumbs.js @@ -65,6 +65,7 @@ frappe.breadcrumbs = { frappe.ui.create_menu({ parent: $(last_element), menu_items: breadcrumbs.menu_items, + size: "fit-content", }); }); }