refactor: make app level folders first class
This commit is contained in:
parent
541f8f3360
commit
c057c730c5
6 changed files with 89 additions and 42 deletions
|
|
@ -80,7 +80,8 @@
|
|||
"depends_on": "eval: doc.standard == 1",
|
||||
"fieldname": "app",
|
||||
"fieldtype": "Autocomplete",
|
||||
"label": "App"
|
||||
"label": "App",
|
||||
"options": "Installed Applications"
|
||||
},
|
||||
{
|
||||
"fieldname": "link_to",
|
||||
|
|
@ -102,7 +103,7 @@
|
|||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2025-10-24 01:21:38.915511",
|
||||
"modified": "2025-10-26 23:18:18.367410",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Desktop Icon",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ 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
|
||||
from frappe.modules.utils import create_directory_on_app_path, get_app_level_directory_path
|
||||
|
||||
|
||||
class DesktopIcon(Document):
|
||||
|
|
@ -51,7 +52,7 @@ class DesktopIcon(Document):
|
|||
self.export_desktop_icon()
|
||||
|
||||
def export_desktop_icon(self):
|
||||
folder_path = create_directory_if_not_exists(self.app)
|
||||
folder_path = create_directory_on_app_path("desktop_icon", 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)
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ class DesktopIcon(Document):
|
|||
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)
|
||||
folder_path = create_directory_on_app_path("desktop_icon", 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)
|
||||
|
|
@ -68,22 +69,6 @@ class DesktopIcon(Document):
|
|||
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():
|
||||
pass
|
||||
|
||||
|
|
@ -440,7 +425,7 @@ def sync_desktop_icons():
|
|||
|
||||
|
||||
def sync_icons(app_name):
|
||||
icon_directory = get_desktop_icon_directory(app_name)
|
||||
icon_directory = get_app_level_directory_path("desktop_icon", 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:
|
||||
|
|
@ -671,8 +656,9 @@ def create_desktop_icons_from_workspace():
|
|||
):
|
||||
frappe.db.set_value("Desktop Icon", parent_icon, "icon", icon.icon)
|
||||
insert = False
|
||||
if insert:
|
||||
if insert and not frappe.db.exists("Desktop Icon", [{"label": icon.label, "type": icon.type}]):
|
||||
icon.insert(ignore_if_duplicate=True)
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
def generate_color():
|
||||
|
|
@ -687,7 +673,6 @@ def create_desktop_icons_from_installed_apps():
|
|||
app_details = frappe.get_hooks("add_to_apps_screen", app_name=a)
|
||||
if len(app_details) != 0:
|
||||
icon = frappe.new_doc("Desktop Icon")
|
||||
icon.route = app_details[0]["route"]
|
||||
icon.label = app_details[0]["title"]
|
||||
icon.type = "External"
|
||||
icon.standard = 1
|
||||
|
|
@ -695,8 +680,10 @@ def create_desktop_icons_from_installed_apps():
|
|||
icon.icon_type = "App"
|
||||
icon.link = app_details[0]["route"]
|
||||
icon.logo_url = app_details[0]["logo"]
|
||||
icon.save()
|
||||
if not frappe.db.exists("Desktop Icon", [{"label": icon.label, "type": icon.type}]):
|
||||
icon.save()
|
||||
index += 1
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
@ -713,6 +700,4 @@ def set_sequence(desktop_icons):
|
|||
|
||||
def create_desktop_icon():
|
||||
create_desktop_icons_from_installed_apps()
|
||||
frappe.db.commit()
|
||||
create_desktop_icons_from_workspace()
|
||||
frappe.db.commit()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"title",
|
||||
"module",
|
||||
"header_icon",
|
||||
"app",
|
||||
"items"
|
||||
],
|
||||
"fields": [
|
||||
|
|
@ -24,16 +25,21 @@
|
|||
"options": "Workspace Sidebar Item"
|
||||
},
|
||||
{
|
||||
"fieldname": "module",
|
||||
"fieldtype": "Link",
|
||||
"label": "Module",
|
||||
"options": "Module Def"
|
||||
"fieldname": "header_icon",
|
||||
"fieldtype": "Icon",
|
||||
"label": "Header Icon"
|
||||
},
|
||||
{
|
||||
"fieldname": "app",
|
||||
"fieldtype": "Autocomplete",
|
||||
"label": "App",
|
||||
"options": "Installed Applications"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-10-01 07:52:51.149158",
|
||||
"modified": "2025-10-26 23:21:30.166695",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Workspace Sidebar",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
# Copyright (c) 2025, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import os
|
||||
from json import JSONDecodeError, dumps, loads
|
||||
|
||||
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
|
||||
from frappe.modules.utils import create_directory_on_app_path
|
||||
|
||||
|
||||
class WorkspaceSidebar(Document):
|
||||
|
|
@ -20,30 +21,54 @@ class WorkspaceSidebar(Document):
|
|||
from frappe.desk.doctype.workspace_sidebar_item.workspace_sidebar_item import WorkspaceSidebarItem
|
||||
from frappe.types import DF
|
||||
|
||||
app: DF.Autocomplete | None
|
||||
items: DF.Table[WorkspaceSidebarItem]
|
||||
title: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
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)
|
||||
if frappe.conf.developer_mode:
|
||||
if self.app:
|
||||
self.export_sidebar()
|
||||
|
||||
def export_sidebar(self):
|
||||
folder_path = create_directory_on_app_path("workspace_sidebar", self.app)
|
||||
file_path = os.path.join(folder_path, f"{frappe.scrub(self.title)}.json")
|
||||
doc_export = self.as_dict(no_nulls=True, no_private_properties=True)
|
||||
with open(file_path, "w+") as doc_file:
|
||||
doc_file.write(frappe.as_json(doc_export) + "\n")
|
||||
|
||||
def delete_desktop_icon_file(self):
|
||||
folder_path = create_directory_on_app_path("workspace_sidebar", self.app)
|
||||
file_path = os.path.join(folder_path, f"{frappe.scrub(self.title)}.json")
|
||||
if not os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
|
||||
def on_trash(self):
|
||||
if not is_workspace_manager():
|
||||
if is_workspace_manager():
|
||||
if frappe.conf.developer_mode and self.standard == 1 and self.app:
|
||||
self.delete_desktop_icon_file()
|
||||
else:
|
||||
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)
|
||||
|
||||
|
||||
def create_workspace_sidebar_for_workspaces():
|
||||
all_workspaces = frappe.get_all("Workspace", pluck="name")
|
||||
from frappe.query_builder import DocType
|
||||
|
||||
workspace = DocType("Workspace")
|
||||
|
||||
all_workspaces = (
|
||||
frappe.qb.from_(workspace)
|
||||
.select(workspace.name)
|
||||
.where((workspace.public == 1) & (workspace.name != "Welcome Workspace"))
|
||||
).run(pluck=True)
|
||||
|
||||
existing_sidebars = frappe.get_all("Workspace Sidebar", pluck="title")
|
||||
for workspace in all_workspaces:
|
||||
if workspace not in existing_sidebars:
|
||||
sidebar = frappe.new_doc("Workspace Sidebar")
|
||||
sidebar.title = workspace
|
||||
sidebar.header_icon = frappe.db.get_value("Workspace", workspace, "icon")
|
||||
sidebar.save()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ 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
|
||||
from frappe.modules.utils import get_app_level_directory_path
|
||||
from frappe.utils import update_progress_bar
|
||||
|
||||
IMPORTABLE_DOCTYPES = [
|
||||
|
|
@ -108,8 +109,15 @@ def sync_for(app_name, force=0, reset_permissions=False):
|
|||
folder = os.path.dirname(frappe.get_module(app_name + "." + module_name).__file__)
|
||||
files = get_doc_files(files=files, start_path=folder)
|
||||
|
||||
l = len(files)
|
||||
app_level_folders = ["desktop_icon", "workspace_sidebar"]
|
||||
for folder_name in app_level_folders:
|
||||
directory_path = get_app_level_directory_path(folder_name, app_name)
|
||||
if os.path.exists(directory_path):
|
||||
icon_files = [os.path.join(directory_path, filename) for filename in os.listdir(directory_path)]
|
||||
for doc_path in icon_files:
|
||||
files.append(doc_path)
|
||||
|
||||
l = len(files)
|
||||
if l:
|
||||
for i, doc_path in enumerate(files):
|
||||
imported = import_file_by_path(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ Utilities for using modules
|
|||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from textwrap import dedent, indent
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
|
|
@ -358,3 +359,24 @@ def make_boilerplate(
|
|||
custom_controller=controller_body,
|
||||
)
|
||||
target.write(frappe.as_unicode(controller_file_content))
|
||||
|
||||
|
||||
def create_directory_on_app_path(folder_name, app_name):
|
||||
app_path = frappe.get_app_path(app_name)
|
||||
folder_path = os.path.join(app_path, folder_name)
|
||||
|
||||
if not os.path.exists(folder_path):
|
||||
frappe.create_folder(folder_path)
|
||||
|
||||
return folder_path
|
||||
|
||||
|
||||
def get_app_level_directory_path(folder_name, app_name):
|
||||
app_path = frappe.get_app_path(app_name)
|
||||
path = os.path.join(app_path, folder_name)
|
||||
return path
|
||||
|
||||
|
||||
def delete_app_level_folder(folder_name, app_name):
|
||||
path = get_app_level_directory_path(folder_name, app_name)
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue