feat: export and sync workspace sidebar and desktop icon
This commit is contained in:
parent
1209487274
commit
9658ca1642
12 changed files with 133 additions and 33 deletions
|
|
@ -529,26 +529,27 @@ def get_sidebar_items():
|
|||
|
||||
for s in sidebars:
|
||||
w = frappe.get_doc("Workspace Sidebar", s)
|
||||
desktop_icon = frappe.db.get_value("Desktop Icon", w.desktop_icon, "label").lower()
|
||||
sidebar_items[desktop_icon] = []
|
||||
if frappe.db.get_value("Desktop Icon", w.desktop_icon, "label"):
|
||||
desktop_icon = frappe.db.get_value("Desktop Icon", w.desktop_icon, "label").lower()
|
||||
sidebar_items[desktop_icon] = []
|
||||
|
||||
for si in w.items:
|
||||
workspace_sidebar = {
|
||||
"label": si.label,
|
||||
"link_to": si.link_to,
|
||||
"link_type": si.link_type,
|
||||
"type": si.type,
|
||||
"icon": si.icon,
|
||||
"child": si.child,
|
||||
}
|
||||
if si.link_type == "Report":
|
||||
report_type, ref_doctype = frappe.db.get_value(
|
||||
"Report", si.link_to, ["report_type", "ref_doctype"]
|
||||
)
|
||||
workspace_sidebar["report"] = {
|
||||
"report_type": report_type,
|
||||
"ref_doctype": ref_doctype,
|
||||
for si in w.items:
|
||||
workspace_sidebar = {
|
||||
"label": si.label,
|
||||
"link_to": si.link_to,
|
||||
"link_type": si.link_type,
|
||||
"type": si.type,
|
||||
"icon": si.icon,
|
||||
"child": si.child,
|
||||
}
|
||||
sidebar_items[desktop_icon].append(workspace_sidebar)
|
||||
if si.link_type == "Report":
|
||||
report_type, ref_doctype = frappe.db.get_value(
|
||||
"Report", si.link_to, ["report_type", "ref_doctype"]
|
||||
)
|
||||
workspace_sidebar["report"] = {
|
||||
"report_type": report_type,
|
||||
"ref_doctype": ref_doctype,
|
||||
}
|
||||
sidebar_items[desktop_icon].append(workspace_sidebar)
|
||||
|
||||
return sidebar_items
|
||||
|
|
|
|||
|
|
@ -707,3 +707,8 @@ def update_onboarding_step(name, field, value):
|
|||
frappe.db.set_value("Onboarding Step", name, field, value)
|
||||
|
||||
capture(frappe.scrub(name), app="frappe_onboarding", properties={field: value})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_installed_apps():
|
||||
return frappe.get_installed_apps()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on("Desktop Icon", {
|
||||
refresh: function (frm) {
|
||||
setup: function (frm) {
|
||||
load_installed_apps();
|
||||
frm.fields_dict.color.set_data(Object.keys(frappe.palette_map));
|
||||
},
|
||||
before_save: function (frm) {
|
||||
|
|
@ -33,3 +34,14 @@ frappe.ui.form.on("Desktop Icon", {
|
|||
}
|
||||
},
|
||||
});
|
||||
|
||||
async function load_installed_apps(frm) {
|
||||
await frappe.call({
|
||||
method: "frappe.desk.desktop.get_installed_apps",
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
cur_frm.fields_dict["app"].set_data(r.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,9 +60,8 @@
|
|||
},
|
||||
{
|
||||
"fieldname": "app",
|
||||
"fieldtype": "Data",
|
||||
"label": "App",
|
||||
"read_only": 1
|
||||
"fieldtype": "Autocomplete",
|
||||
"label": "App"
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
|
|
@ -166,7 +165,7 @@
|
|||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2025-09-08 02:43:09.997790",
|
||||
"modified": "2025-09-29 01:47:25.718356",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Desktop Icon",
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@
|
|||
# License: MIT. See LICENSE
|
||||
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.modules.export_file import write_document_file
|
||||
from frappe.modules.import_file import import_file_by_path
|
||||
|
||||
|
||||
class DesktopIcon(Document):
|
||||
|
|
@ -20,7 +23,7 @@ class DesktopIcon(Document):
|
|||
|
||||
_doctype: DF.Link | None
|
||||
_report: DF.Link | None
|
||||
app: DF.Data | None
|
||||
app: DF.Autocomplete | None
|
||||
blocked: DF.Check
|
||||
category: DF.Data | None
|
||||
color: DF.Autocomplete | None
|
||||
|
|
@ -46,11 +49,49 @@ class DesktopIcon(Document):
|
|||
|
||||
def on_trash(self):
|
||||
clear_desktop_icons_cache()
|
||||
if frappe.conf.developer_mode:
|
||||
if self.standard == 1 and self.app:
|
||||
self.delete_desktop_icon_file()
|
||||
|
||||
def on_update(self):
|
||||
if frappe.conf.developer_mode:
|
||||
if self.standard == 1 and self.app:
|
||||
self.export_desktop_icon()
|
||||
|
||||
def export_desktop_icon(self):
|
||||
folder_path = create_directory_if_not_exists(self.app)
|
||||
file_path = os.path.join(folder_path, f"{frappe.scrub(self.label)}.json")
|
||||
doc_export = self.as_dict(no_nulls=True, no_private_properties=True)
|
||||
|
||||
with open(file_path, "w+") as icon_file_doc:
|
||||
icon_file_doc.write(frappe.as_json(doc_export) + "\n")
|
||||
|
||||
def delete_desktop_icon_file(self):
|
||||
folder_path = create_directory_if_not_exists(self.app)
|
||||
file_path = os.path.join(folder_path, f"{frappe.scrub(self.label)}.json")
|
||||
if not os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
|
||||
def after_insert(self):
|
||||
clear_desktop_icons_cache()
|
||||
|
||||
|
||||
def create_directory_if_not_exists(app_name):
|
||||
app_path = frappe.get_app_path(app_name)
|
||||
desktop_icon_path = os.path.join(app_path, "desktop_icon")
|
||||
|
||||
if not os.path.exists(desktop_icon_path):
|
||||
frappe.create_folder(desktop_icon_path)
|
||||
|
||||
return desktop_icon_path
|
||||
|
||||
|
||||
def get_desktop_icon_directory(app_name):
|
||||
app_path = frappe.get_app_path(app_name)
|
||||
desktop_icon_path = os.path.join(app_path, "desktop_icon")
|
||||
return desktop_icon_path
|
||||
|
||||
|
||||
def after_doctype_insert():
|
||||
frappe.db.add_unique("Desktop Icon", ("module_name", "owner", "standard"))
|
||||
|
||||
|
|
@ -401,7 +442,19 @@ def make_user_copy(module_name, user):
|
|||
def sync_desktop_icons():
|
||||
"""Sync desktop icons from all apps"""
|
||||
for app in frappe.get_installed_apps():
|
||||
sync_from_app(app)
|
||||
sync_icons(app)
|
||||
# sync_from_app(app)
|
||||
|
||||
|
||||
def sync_icons(app_name):
|
||||
icon_directory = get_desktop_icon_directory(app_name)
|
||||
if os.path.exists(icon_directory):
|
||||
icon_files = [os.path.join(icon_directory, filename) for filename in os.listdir(icon_directory)]
|
||||
for doc_path in icon_files:
|
||||
imported = import_file_by_path(doc_path)
|
||||
if imported:
|
||||
frappe.db.commit(chain=True)
|
||||
# print(icon_directory)
|
||||
|
||||
|
||||
def sync_from_app(app):
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"field_order": [
|
||||
"desktop_icon",
|
||||
"title",
|
||||
"module",
|
||||
"items"
|
||||
],
|
||||
"fields": [
|
||||
|
|
@ -30,12 +31,18 @@
|
|||
"fieldtype": "Table",
|
||||
"label": "Items",
|
||||
"options": "Workspace Sidebar Item"
|
||||
},
|
||||
{
|
||||
"fieldname": "module",
|
||||
"fieldtype": "Link",
|
||||
"label": "Module",
|
||||
"options": "Module Def"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-12 12:48:17.192321",
|
||||
"modified": "2025-09-26 02:16:29.097807",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Workspace Sidebar",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
# Copyright (c) 2025, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.desk.doctype.workspace.workspace import is_workspace_manager
|
||||
from frappe.model.document import Document
|
||||
from frappe.modules.export_file import delete_folder, export_to_files
|
||||
|
||||
|
||||
class WorkspaceSidebar(Document):
|
||||
|
|
@ -17,7 +20,18 @@ class WorkspaceSidebar(Document):
|
|||
|
||||
desktop_icon: DF.Link | None
|
||||
items: DF.Table[WorkspaceSidebarItem]
|
||||
module: DF.Link | None
|
||||
title: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
def on_update(self):
|
||||
if self.module and frappe.conf.developer_mode:
|
||||
export_to_files(record_list=[["Workspace Sidebar", self.name]], record_module=self.module)
|
||||
|
||||
def on_trash(self):
|
||||
if not is_workspace_manager():
|
||||
frappe.throw(_("You need to be Workspace Manager to delete a public workspace."))
|
||||
|
||||
def after_delete(self):
|
||||
if self.module and frappe.conf.developer_mode:
|
||||
delete_folder(self.module, "Workspace Sidebar", self.name)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-08-12 12:46:41.926121",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
|
|
@ -61,7 +60,7 @@
|
|||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-09-03 11:58:10.222194",
|
||||
"modified": "2025-09-29 02:21:36.962559",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Workspace Sidebar Item",
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ function setup_navbar(navbar_style) {
|
|||
}
|
||||
|
||||
frappe.router.on("change", function () {
|
||||
if (frappe.get_route()[0] == "desktop") setup_navbar();
|
||||
let navbar_style = $("#icon-style").attr("data-navbar-style");
|
||||
if (frappe.get_route()[0] == "desktop") setup_navbar(navbar_style);
|
||||
else $(".navbar").show();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from semantic_version import Version
|
|||
|
||||
import frappe
|
||||
from frappe.defaults import _clear_cache
|
||||
from frappe.desk.doctype.desktop_icon.desktop_icon import sync_desktop_icons
|
||||
from frappe.utils import cint, is_git_url
|
||||
from frappe.utils.dashboard import sync_dashboards
|
||||
from frappe.utils.synchronization import filelock
|
||||
|
|
@ -337,6 +338,7 @@ def install_app(name, verbose=False, set_as_patched=True, force=False):
|
|||
sync_fixtures(name)
|
||||
sync_customizations(name)
|
||||
sync_dashboards(name)
|
||||
sync_desktop_icons()
|
||||
|
||||
for after_sync in app_hooks.after_sync or []:
|
||||
frappe.get_attr(after_sync)() #
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ from frappe.core.doctype.navbar_settings.navbar_settings import sync_standard_it
|
|||
from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs
|
||||
from frappe.database.schema import add_column
|
||||
from frappe.deferred_insert import save_to_db as flush_deferred_inserts
|
||||
from frappe.desk.doctype.desktop_icon.desktop_icon import sync_desktop_icons
|
||||
from frappe.desk.notifications import clear_notifications
|
||||
from frappe.modules.patch_handler import PatchType
|
||||
from frappe.modules.utils import sync_customizations
|
||||
|
|
@ -188,6 +189,9 @@ class SiteMigration:
|
|||
print("Updating installed applications...")
|
||||
frappe.get_single("Installed Applications").update_versions()
|
||||
|
||||
print("Syncing Desktop Icons...")
|
||||
sync_desktop_icons()
|
||||
|
||||
print("Executing `after_migrate` hooks...")
|
||||
for app in frappe.get_installed_apps():
|
||||
for fn in frappe.get_hooks("after_migrate", app_name=app):
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import os
|
|||
|
||||
import frappe
|
||||
from frappe.cache_manager import clear_controller_cache
|
||||
from frappe.desk.doctype.desktop_icon.desktop_icon import sync_desktop_icons
|
||||
from frappe.model.base_document import get_controller
|
||||
from frappe.modules.import_file import import_file_by_path
|
||||
from frappe.modules.patch_handler import _patch_mode
|
||||
|
|
@ -27,6 +28,7 @@ IMPORTABLE_DOCTYPES = [
|
|||
("email", "notification"),
|
||||
("printing", "print_style"),
|
||||
("desk", "workspace"),
|
||||
("desk", "workspace_sidebar"),
|
||||
("desk", "onboarding_step"),
|
||||
("desk", "module_onboarding"),
|
||||
("desk", "form_tour"),
|
||||
|
|
@ -39,7 +41,6 @@ IMPORTABLE_DOCTYPES = [
|
|||
|
||||
def sync_all(force=0, reset_permissions=False):
|
||||
_patch_mode(True)
|
||||
|
||||
for app in frappe.get_installed_apps():
|
||||
sync_for(app, force, reset_permissions=reset_permissions)
|
||||
|
||||
|
|
@ -93,6 +94,8 @@ def sync_for(app_name, force=0, reset_permissions=False):
|
|||
"workspace_number_card",
|
||||
"workspace_custom_block",
|
||||
"workspace",
|
||||
"workspace_sidebar",
|
||||
"workspace_sidebar_item",
|
||||
]:
|
||||
files.append(os.path.join(FRAPPE_PATH, "desk", "doctype", desk_module, f"{desk_module}.json"))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue