seitime-frappe/frappe/apps.py
2025-11-18 10:21:44 +05:30

114 lines
3 KiB
Python

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
import re
import frappe
from frappe import _
from frappe.core.doctype.installed_applications.installed_applications import (
get_apps_with_incomplete_dependencies,
get_setup_wizard_completed_apps,
get_setup_wizard_not_required_apps,
)
# check if route is /app or /app/* and not /app1 or /app1/*
DESK_APP_PATTERN = re.compile(r"^/app(/.*)?$")
@frappe.whitelist()
def get_apps():
apps = frappe.get_installed_apps()
app_list = []
for app in apps:
if (
app not in get_setup_wizard_completed_apps()
and app not in get_setup_wizard_not_required_apps()
and "System Manager" not in frappe.get_roles()
):
continue
if app == "frappe":
continue
app_details = frappe.get_hooks("add_to_apps_screen", app_name=app)
if not len(app_details):
continue
for app_detail in app_details:
try:
has_permission_path = app_detail.get("has_permission")
if has_permission_path and not frappe.get_attr(has_permission_path)():
continue
app_list.append(
{
"name": app,
"logo": app_detail.get("logo"),
"title": _(app_detail.get("title")),
"route": app_detail.get("route"),
}
)
except Exception:
frappe.log_error(f"Failed to call has_permission hook ({has_permission_path}) for {app}")
return app_list
def get_route(app_name):
apps = frappe.get_hooks("add_to_apps_screen", app_name=app_name)
app = next((app for app in apps if app.get("name") == app_name), None)
return app.get("route") if app and app.get("route") else "/apps"
def is_desk_apps(apps):
for app in apps:
route = app.get("route")
if route and not re.match(DESK_APP_PATTERN, route):
return False
return True
def get_default_path():
apps = get_apps()
_apps = [app for app in apps if app.get("name") != "frappe"]
if len(_apps) == 0:
return None
system_default_app = frappe.get_system_settings("default_app")
user_default_app = frappe.get_cached_value("User", frappe.session.user, "default_app")
if system_default_app and not user_default_app:
return get_route(system_default_app)
elif user_default_app:
return get_route(user_default_app)
if len(_apps) == 1:
return _apps[0].get("route") or "/desk"
elif is_desk_apps(_apps):
return "/desk"
return "/apps"
@frappe.whitelist()
def set_app_as_default(app_name):
if frappe.db.get_value("User", frappe.session.user, "default_app") == app_name:
frappe.db.set_value("User", frappe.session.user, "default_app", "")
else:
frappe.db.set_value("User", frappe.session.user, "default_app", app_name)
@frappe.whitelist()
def get_incomplete_setup_route(current_app, app_route):
pending_apps = get_apps_with_incomplete_dependencies(current_app)
if not pending_apps:
return app_route
for app in pending_apps:
if app == "frappe":
return "app"
app_details = frappe.get_hooks("add_to_apps_screen", app_name=app)
if not app_details:
continue
if route := app_details[0].get("route"):
return route
return app_route