From 10093febf1ca826a0f879e9ad2b8ddff55e667f4 Mon Sep 17 00:00:00 2001 From: sokumon Date: Sun, 16 Nov 2025 20:06:32 +0530 Subject: [PATCH] fix(patch): create a user specific sidebar for showing private workspaces --- frappe/boot.py | 26 ++++++++++- .../workspace_sidebar/workspace_sidebar.json | 9 +++- .../workspace_sidebar/workspace_sidebar.py | 45 ++++++++++++++----- frappe/public/js/frappe/ui/sidebar/sidebar.js | 10 +++-- .../js/frappe/ui/sidebar/sidebar_header.html | 2 +- .../js/frappe/ui/sidebar/sidebar_item.js | 8 +++- frappe/workspace_sidebar/my_workspaces.json | 2 +- 7 files changed, 82 insertions(+), 20 deletions(-) diff --git a/frappe/boot.py b/frappe/boot.py index d0672ff087..b4681b82c6 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -527,7 +527,10 @@ def get_sentry_dsn(): def get_sidebar_items(): - sidebars = frappe.get_all("Workspace Sidebar", fields=["name", "header_icon"]) + sidebars = frappe.get_all( + "Workspace Sidebar", fields=["name", "header_icon"], filters={"name": ["not like", "%My Workspaces%"]} + ) + add_user_specific_sidebar(sidebars) sidebar_items = {} for s in sidebars: @@ -558,7 +561,26 @@ def get_sidebar_items(): "report_type": report_type, "ref_doctype": ref_doctype, } - if si.type == "Section Break" or w.is_item_allowed(si.link_to, si.link_type): + + if ( + "My Workspaces" in s["name"] + or si.type == "Section Break" + or w.is_item_allowed(si.link_to, si.link_type) + ): sidebar_items[s["name"].lower()]["items"].append(workspace_sidebar) + old_name = f"my workspaces-{frappe.session.user}" + if old_name in sidebar_items: + sidebar_items["my workspaces"] = sidebar_items.pop(old_name) return sidebar_items + + +def add_user_specific_sidebar(sidebars): + try: + my_workspace_for_user = frappe.get_doc("Workspace Sidebar", f"My Workspaces-{frappe.session.user}") + sidebars.append( + {"name": my_workspace_for_user.name, "header_icon": my_workspace_for_user.header_icon} + ) + except frappe.DoesNotExistError: + my_workspace = frappe.get_doc("Workspace Sidebar", "My Workspaces") + sidebars.append({"name": my_workspace.name, "header_icon": my_workspace.header_icon}) diff --git a/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.json b/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.json index 827a011cd1..5c90722e5f 100644 --- a/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.json +++ b/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.json @@ -9,6 +9,7 @@ "title", "header_icon", "app", + "for_user", "items" ], "fields": [ @@ -34,12 +35,18 @@ "fieldtype": "Autocomplete", "label": "App", "options": "Installed Applications" + }, + { + "fieldname": "for_user", + "fieldtype": "Link", + "label": "For User", + "options": "User" } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "links": [], - "modified": "2025-10-26 23:21:30.166695", + "modified": "2025-11-16 10:54:04.080590", "modified_by": "Administrator", "module": "Desk", "name": "Workspace Sidebar", diff --git a/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.py b/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.py index c54ab3a110..54256cfd1a 100644 --- a/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.py +++ b/frappe/desk/doctype/workspace_sidebar/workspace_sidebar.py @@ -24,10 +24,11 @@ class WorkspaceSidebar(Document): from frappe.types import DF app: DF.Autocomplete | None + for_user: DF.Link | None items: DF.Table[WorkspaceSidebarItem] title: DF.Data | None - # end: auto-generated types + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not frappe.flags.in_migrate: @@ -181,16 +182,38 @@ def add_sidebar_items(sidebar_title, sidebar_items): def add_to_my_workspace(workspace): - private_sidebar = frappe.get_doc("Workspace Sidebar", "My Workspaces") + try: + if not workspace.for_user: + return - workspace_sidebar = { - "label": workspace.title, - "type": "Link", - "link_to": f"{workspace.title}-{workspace.for_user}", - "link_type": "Workspace", - "icon": workspace.icon, - } + sidebar_name = f"My Workspaces-{workspace.for_user}" + existing_sidebar = frappe.db.exists("Workspace Sidebar", sidebar_name) - private_sidebar.append("items", workspace_sidebar) + if existing_sidebar: + private_sidebar = frappe.get_doc("Workspace Sidebar", existing_sidebar) + else: + # clone sidebar + base_sidebar = frappe.get_doc("Workspace Sidebar", "My Workspaces") + private_sidebar = frappe.copy_doc(base_sidebar) + private_sidebar.title = sidebar_name + private_sidebar.for_user = workspace.for_user + private_sidebar.owner = workspace.for_user + private_sidebar.items = [] - private_sidebar.save() + sidebar_item = { + "label": workspace.title, + "type": "Link", + "link_to": f"{workspace.title}-{workspace.for_user}", + "link_type": "Workspace", + "icon": workspace.icon, + } + + private_sidebar.append("items", sidebar_item) + + if existing_sidebar: + private_sidebar.save() + else: + private_sidebar.insert() + + except Exception as e: + frappe.log_error(title="Error in Adding Private Workspaces", message=e) diff --git a/frappe/public/js/frappe/ui/sidebar/sidebar.js b/frappe/public/js/frappe/ui/sidebar/sidebar.js index 146adf2eec..2264076801 100644 --- a/frappe/public/js/frappe/ui/sidebar/sidebar.js +++ b/frappe/public/js/frappe/ui/sidebar/sidebar.js @@ -46,7 +46,7 @@ frappe.ui.Sidebar = class Sidebar { for (const app of frappe.boot.app_data) { if (app.workspaces.includes(this.workspace_title)) { - this.app_name = app.app_title; + this.header_subtitle = app.app_title; this.app_logo_url = app.app_logo_url; return; } @@ -54,7 +54,11 @@ frappe.ui.Sidebar = class Sidebar { const icon = frappe.boot.desktop_icons.find((i) => i.label === this.workspace_title); if (icon) { - this.app_name = icon.parent_icon; + this.header_subtitle = icon.parent_icon; + } + + if (this.workspace_title == "My Workspaces") { + this.header_subtitle = frappe.session.user; } } @@ -87,7 +91,7 @@ frappe.ui.Sidebar = class Sidebar { this.setup_complete = true; } check_for_private_workspace(workspace_title) { - if (workspace_title == "private") { + if (workspace_title == "private" || workspace_title == "Personal") { this.workspace_title = "My Workspaces"; } } diff --git a/frappe/public/js/frappe/ui/sidebar/sidebar_header.html b/frappe/public/js/frappe/ui/sidebar/sidebar_header.html index 8f73696287..1bf076fd8d 100644 --- a/frappe/public/js/frappe/ui/sidebar/sidebar_header.html +++ b/frappe/public/js/frappe/ui/sidebar/sidebar_header.html @@ -15,7 +15,7 @@ {% } %}