From 2abcfd30396b1af7a372cd3a87442c23d1c2b546 Mon Sep 17 00:00:00 2001 From: sokumon Date: Wed, 3 Sep 2025 23:51:46 +0530 Subject: [PATCH] fix: more interaction fixes --- .../desk/doctype/desktop_icon/desktop_icon.js | 2 + .../workspace_sidebar_item.json | 4 +- .../workspace_sidebar_item.py | 2 +- frappe/desk/page/desktop/desktop.css | 6 +- frappe/desk/page/desktop/desktop.js | 6 +- frappe/public/icons/timeless/icons.svg | 34 ++++++ frappe/public/js/frappe/ui/sidebar/sidebar.js | 101 ++++++++++++++---- .../js/frappe/ui/sidebar/sidebar_header.js | 4 +- 8 files changed, 124 insertions(+), 35 deletions(-) diff --git a/frappe/desk/doctype/desktop_icon/desktop_icon.js b/frappe/desk/doctype/desktop_icon/desktop_icon.js index 4437bec0c6..64f25a7d53 100644 --- a/frappe/desk/doctype/desktop_icon/desktop_icon.js +++ b/frappe/desk/doctype/desktop_icon/desktop_icon.js @@ -26,6 +26,8 @@ frappe.ui.form.on("Desktop Icon", { }); } else if (frm.doc.type == "link") { frm.doc.route = frm.doc.link; + } else if (frm.doc.type == "list") { + frm.doc.route = `/app/${frappe.router.slug(frm.doc._doctype)}`; } }, }); diff --git a/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.json b/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.json index 3c72ae30f5..31fccb6b5e 100644 --- a/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.json +++ b/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.json @@ -33,7 +33,7 @@ "fieldtype": "Select", "in_list_view": 1, "label": "Link Type", - "options": "DocType\nPage\nReport\nWorkspace" + "options": "DocType\nPage\nReport\nWorkspace\nDashboard" }, { "fieldname": "link_to", @@ -61,7 +61,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2025-08-29 12:49:51.155661", + "modified": "2025-09-03 11:58:10.222194", "modified_by": "Administrator", "module": "Desk", "name": "Workspace Sidebar Item", diff --git a/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.py b/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.py index af0a14a898..3189dcecfb 100644 --- a/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.py +++ b/frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.py @@ -17,7 +17,7 @@ class WorkspaceSidebarItem(Document): child: DF.Check label: DF.Data | None link_to: DF.DynamicLink | None - link_type: DF.Literal["DocType", "Page", "Report", "Workspace"] + link_type: DF.Literal["DocType", "Page", "Report", "Workspace", "Dashboard"] parent: DF.Data parentfield: DF.Data parenttype: DF.Data diff --git a/frappe/desk/page/desktop/desktop.css b/frappe/desk/page/desktop/desktop.css index 1995ba6ee0..0f3348e4a3 100644 --- a/frappe/desk/page/desktop/desktop.css +++ b/frappe/desk/page/desktop/desktop.css @@ -1,7 +1,7 @@ .desktop-container{ - width: 500px; - padding-left: 400px; - padding-right: 400px; + display: flex; + align-items: center; + justify-content: center; } .icon-stroke{ stroke-width: 1px; diff --git a/frappe/desk/page/desktop/desktop.js b/frappe/desk/page/desktop/desktop.js index b8f39a9e88..573af08e37 100644 --- a/frappe/desk/page/desktop/desktop.js +++ b/frappe/desk/page/desktop/desktop.js @@ -13,16 +13,12 @@ function setup() { $(".desktop-icon").each((i, el) => { let icon_name = $(el).attr("data-icon"); let icon_container = $(el.children[0]); - const link = $("", { - href: get_route($(el)), - }); const svg = frappe.utils.icon(icon_name, "xl icon-stroke"); if (svg) { - link.html(svg); + icon_container.append(svg); } - icon_container.append(link); // let color_name = icon_container.attr("data-color"); // icon_container.css("background-color", color_name); }); diff --git a/frappe/public/icons/timeless/icons.svg b/frappe/public/icons/timeless/icons.svg index b7fe923a26..3e0ff0afac 100644 --- a/frappe/public/icons/timeless/icons.svg +++ b/frappe/public/icons/timeless/icons.svg @@ -30,15 +30,49 @@ Tip: use lucide.svg in /icons for all downloaded icons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frappe/public/js/frappe/ui/sidebar/sidebar.js b/frappe/public/js/frappe/ui/sidebar/sidebar.js index be6f430d14..5141811913 100644 --- a/frappe/public/js/frappe/ui/sidebar/sidebar.js +++ b/frappe/public/js/frappe/ui/sidebar/sidebar.js @@ -1,10 +1,10 @@ frappe.ui.Sidebar = class Sidebar { constructor() { - this.items = {}; this.section_breaks = []; this.section_breaks_content = []; this.sidebar_expanded = false; this.workspace_sidebar_items = []; + this.closed_section_breaks = {}; if (!frappe.boot.setup_complete) { // no sidebar if setup is not complete return; @@ -35,9 +35,9 @@ frappe.ui.Sidebar = class Sidebar { } setup(workspace_title) { - this.workspace_title = workspace_title; - this.sidebar_header = new frappe.ui.SidebarHeader(this, workspace_title); - this.make_sidebar(workspace_title.toLowerCase()); + this.workspace_title = workspace_title.charAt(0).toUpperCase() + workspace_title.slice(1); + this.sidebar_header = new frappe.ui.SidebarHeader(this); + this.make_sidebar(); this.setup_complete = true; } setup_events() { @@ -122,9 +122,27 @@ frappe.ui.Sidebar = class Sidebar { open_all_section_breaks() { this.section_breaks.forEach((f) => { - f.find(".drop-icon").click(); - if (f.find(".nested-container").hasClass("hidden")) { - f.find(".drop-icon").click(); + const $container = $(f[0]).parent().find(".nested-container"); + const isHidden = $($container[0]).hasClass("hidden"); + const parent = $($(f[0]).children()[0]); + + if (isHidden) { + $(f[0]).find(".drop-icon").get(0).click(); + } + }); + } + + open_or_close_section_breaks() { + if (!this.sidebar_expanded) return; + this.closed_section_breaks[this.workspace_title]?.forEach((title) => { + const $section = this.wrapper.find( + `.sidebar-item-container.section-item[item-title="${title}"]` + ); + if ($section.length) { + const $container = $section.find(".nested-container"); + if (!$($container[0]).hasClass("hidden")) { + $section.find(".drop-icon").get(0).click(); + } } }); } @@ -133,6 +151,7 @@ frappe.ui.Sidebar = class Sidebar { let match = false; const that = this; $(".item-anchor").each(function () { + console.log($(this).attr("href")); if ($(this).attr("href") == window.location.pathname) { match = true; if (that.active_item) that.active_item.removeClass("active-sidebar"); @@ -171,17 +190,21 @@ frappe.ui.Sidebar = class Sidebar { if (localStorage.getItem("sidebar-expanded") !== null) { this.sidebar_expanded = JSON.parse(localStorage.getItem("sidebar-expanded")); } + if (localStorage.getItem("closed-section-breaks") !== null) { + this.closed_section_breaks = JSON.parse(localStorage.getItem("closed-section-breaks")); + } if (frappe.is_mobile()) { this.sidebar_expanded = false; } this.expand_sidebar(); this.sidebar_header; } - make_sidebar(workspace_title) { + make_sidebar() { if (this.wrapper.find(".sidebar-items")[0]) { this.wrapper.find(".sidebar-items").html(""); } - this.workspace_sidebar_items = frappe.boot.workspace_sidebar_item[workspace_title]; + this.workspace_sidebar_items = + frappe.boot.workspace_sidebar_item[this.workspace_title.toLowerCase()]; // this.build_sidebar_section("All", parent_pages); this.create_sidebar(); @@ -271,14 +294,17 @@ frappe.ui.Sidebar = class Sidebar { // this.sidebar_expanded = true direction = "right"; } + localStorage.setItem("sidebar-expanded", this.sidebar_expanded); this.wrapper .find(".body-sidebar .collapse-sidebar-link") .find("use") .attr("href", `#icon-arrow-${direction}-to-line`); - this.sidebar_header.toggle_width(this.sidebar_expanded); this.open_all_section_breaks(); this.toggle_section_break(); + this.open_or_close_section_breaks(); + + this.sidebar_header.toggle_width(this.sidebar_expanded); } append_item(item, container) { @@ -348,6 +374,7 @@ frappe.ui.Sidebar = class Sidebar { } else if (item.type === "URL") { path = item.external_link; } + console.log(path); return $( frappe.render_template("sidebar_item", { item: item, @@ -372,9 +399,10 @@ frappe.ui.Sidebar = class Sidebar { this.setup_event_listner(item_container); } setup_event_listner(item_container) { + const me = this; let $child_item_section = item_container.find(".sidebar-child-item"); let $drop_icon = item_container.find(".drop-icon"); - $drop_icon.on("click", () => { + $drop_icon.on("click", (e) => { let opened = $drop_icon.find("use").attr("href") === "#icon-chevron-down"; if (!opened) { @@ -389,6 +417,25 @@ frappe.ui.Sidebar = class Sidebar { .attr("href", "#icon-chevron-right"); } $child_item_section.toggleClass("hidden"); + + if (e.originalEvent.isTrusted) { + if (opened) { + this.closed_section_breaks[me.workspace_title] = []; + } else { + const title = $drop_icon.parent().siblings().attr("title"); + // Initialize the array if it doesn't exist + if (!this.closed_section_breaks[me.workspace_title]) { + this.closed_section_breaks[me.workspace_title] = []; + } + + // Push the new title into the array + this.closed_section_breaks[me.workspace_title].push(title); + } + localStorage.setItem( + "closed-section-breaks", + JSON.stringify(this.closed_section_breaks) + ); + } }); } toggle_sorting() { @@ -435,6 +482,7 @@ frappe.ui.Sidebar = class Sidebar { close_sidebar() { this.sidebar_expanded = false; + this.expand_sidebar(); if (frappe.is_mobile()) frappe.app.sidebar.prevent_scroll(); } @@ -475,25 +523,22 @@ frappe.ui.Sidebar = class Sidebar { } } set_workspace_sidebar() { - if (frappe.get_route()[0] == "setup-wizard") return; + let workspace_title; let route = frappe.get_route(); + if (frappe.get_route()[0] == "setup-wizard") return; let module_name; + if (route[0] == "Workspaces") { let workspace = route[1] || "Build"; frappe.app.sidebar.setup(workspace); } else if (route[0] == "List" || route[0] == "Form") { let doctype = route[1]; - let meta = frappe.get_meta(doctype); - try { - module_name = frappe.boot.module_wise_workspaces[meta.module][0] || "Build"; - } catch (error) { - module_name = "Build"; + let sidebars = this.get_correct_workspace_sidebars(doctype); + if (this.workspace_title && sidebars.includes(this.workspace_title.toLowerCase())) { + frappe.app.sidebar.setup(this.workspace_title.toLowerCase()); + } else { + frappe.app.sidebar.setup(sidebars[0] || "Build"); } - - if (doctype && doctype.includes("Setting")) { - module_name = "Settings"; - } - frappe.app.sidebar.setup(module_name); } else if (route[0] == "query-report") { frappe.model.with_doc("Report", route[1], () => { let test = frappe.get_doc("Report", route[1]); @@ -508,4 +553,16 @@ frappe.ui.Sidebar = class Sidebar { } this.set_active_workspace_item(); } + + get_correct_workspace_sidebars(link_to) { + let sidebars = []; + Object.entries(this.sidebar_items).forEach(([name, items]) => { + items.forEach((item) => { + if (item.link_to == link_to) { + sidebars.push(name); + } + }); + }); + return sidebars; + } }; diff --git a/frappe/public/js/frappe/ui/sidebar/sidebar_header.js b/frappe/public/js/frappe/ui/sidebar/sidebar_header.js index 7a6964c01c..156903e351 100644 --- a/frappe/public/js/frappe/ui/sidebar/sidebar_header.js +++ b/frappe/public/js/frappe/ui/sidebar/sidebar_header.js @@ -1,9 +1,9 @@ frappe.ui.SidebarHeader = class SidebarHeader { - constructor(sidebar, workspace_title) { + constructor(sidebar) { this.sidebar = sidebar; this.sidebar_wrapper = $(".body-sidebar"); this.drop_down_expanded = false; - this.workspace_title = workspace_title; + this.workspace_title = this.sidebar.workspace_title; const me = this; this.dropdown_items = [ {