From 86db71f8faab454252f252337b07ef4392b0ee99 Mon Sep 17 00:00:00 2001 From: sokumon Date: Fri, 7 Nov 2025 16:43:19 +0530 Subject: [PATCH] feat: move /app to /desk --- frappe/boot.py | 3 +- frappe/hooks.py | 4 +- frappe/public/js/frappe/router.js | 14 +++-- frappe/public/js/frappe/utils/utils.js | 2 +- frappe/tests/test_website.py | 6 +- frappe/website/path_resolver.py | 4 +- frappe/www/desk.html | 77 ++++++++++++++++++++++++++ frappe/www/desk.py | 68 +++++++++++++++++++++++ 8 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 frappe/www/desk.html create mode 100644 frappe/www/desk.py diff --git a/frappe/boot.py b/frappe/boot.py index 933d5add2f..80d7791176 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -364,7 +364,7 @@ def add_home_page(bootinfo, docs): bootinfo["home_page"] = page.name except (frappe.DoesNotExistError, frappe.PermissionError): frappe.clear_last_message() - bootinfo["home_page"] = "Workspaces" + bootinfo["home_page"] = "desktop" def add_timezone_info(bootinfo): @@ -544,6 +544,7 @@ def get_sidebar_items(): "keep_closed": si.keep_closed, "display_depends_on": si.display_depends_on, "url": si.url, + "show_arrow": si.show_arrow, } if si.link_type == "Report" and si.link_to: report_type, ref_doctype = frappe.db.get_value( diff --git a/frappe/hooks.py b/frappe/hooks.py index 28ab671f9f..fd1bb0629e 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -57,11 +57,11 @@ email_css = ["email.bundle.css"] website_route_rules = [ {"from_route": "/kb/", "to_route": "Help Article"}, {"from_route": "/profile", "to_route": "me"}, - {"from_route": "/app/", "to_route": "app"}, + {"from_route": "/desk/", "to_route": "desk"}, ] website_redirects = [ - {"source": r"/desk(.*)", "target": r"/app\1"}, + {"source": r"/app(.*)", "target": r"/desk\1"}, ] base_template = "templates/base.html" diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index 97967268e8..a150576d13 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -107,7 +107,7 @@ frappe.router = { if (path.substr(0, 1) === "/") path = path.substr(1); path = path.split("/"); if (path[0]) { - return path[0] === "app"; + return path[0] === "desk"; } }, @@ -461,7 +461,7 @@ frappe.router = { }).join("/"); if (path_string) { - return "/app/" + path_string; + return "/desk/" + path_string; } // Resolution order @@ -482,11 +482,13 @@ frappe.router = { if (workspace) { return ( - "/app/" + (workspace.public ? "" : "private/") + frappe.router.slug(workspace.name) + "/desk/" + + (workspace.public ? "" : "private/") + + frappe.router.slug(workspace.name) ); } - return "/app"; + return "/desk"; }, /** @@ -519,8 +521,8 @@ frappe.router = { strip_prefix(route) { if (route.substr(0, 1) == "/") route = route.substr(1); // for /app/sub - if (route == "app") route = route.substr(4); // for app - if (route.startsWith("app/")) route = route.substr(4); // for desk/sub + if (route == "desk") route = route.substr(4); // for app + if (route.startsWith("desk/")) route = route.substr(4); // for desk/sub if (route.substr(0, 1) == "/") route = route.substr(1); if (route.substr(0, 1) == "#") route = route.substr(1); if (route.substr(0, 1) == "!") route = route.substr(1); diff --git a/frappe/public/js/frappe/utils/utils.js b/frappe/public/js/frappe/utils/utils.js index 76016b9f11..2fc3fc64ac 100644 --- a/frappe/public/js/frappe/utils/utils.js +++ b/frappe/public/js/frappe/utils/utils.js @@ -1389,7 +1389,7 @@ Object.assign(frappe.utils, { // (item.doctype && frappe.model.can_read(item.doctype))) { // item.shown = true; // } - return `/app/${route}`; + return `/desk/${route}`; }, shorten_number: function (number, country, min_length = 4, max_no_of_decimals = 2) { diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 20cee8045f..14c44e7e06 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -141,7 +141,7 @@ class TestWebsite(IntegrationTestCase): def test_app(self): frappe.set_user("Administrator") - set_request(method="GET", path="/app") + set_request(method="GET", path="/desk") response = get_response() self.assertEqual(response.status_code, 200) @@ -405,8 +405,8 @@ class TestWebsite(IntegrationTestCase): frappe.conf.update({"app_include_js": ["test_app_include_via_site_config.js"]}) frappe.conf.update({"app_include_css": ["test_app_include_via_site_config.css"]}) - set_request(method="GET", path="/app") - content = get_response_content("/app") + set_request(method="GET", path="/desk") + content = get_response_content("/desk") self.assertIn('', content) self.assertIn( '', content diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index 27531d1fec..0b162f2619 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -31,8 +31,8 @@ class PathResolver: request = frappe.local.request or request # WARN: Hardcoded for better performance - if self.path == "app" or self.path.startswith("app/"): - return "app", TemplatePage("app", self.http_status_code) + if self.path == "desk" or self.path.startswith("desk/"): + return "desk", TemplatePage("desk", self.http_status_code) # check if the request url is in 404 list if request.url and can_cache() and frappe.cache.hget("website_404", request.url): diff --git a/frappe/www/desk.html b/frappe/www/desk.html new file mode 100644 index 0000000000..ec4cb99974 --- /dev/null +++ b/frappe/www/desk.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + {{ app_name }} + + + {% for include in app_include_css -%} + {{ include_style(include) }} + {%- endfor -%} + + {% if lang == "eo" %} + + + {% endif %} + + + {% include "templates/includes/splash_screen.html" %} +
+
+
+
+
+ +
+ + + + {%- for path in app_include_icons -%} + {{ include_icons(path) }} + {%- endfor -%} + + {% for include in app_include_js %} + {{ include_script(include) }} + {% endfor %} + + {% include "templates/includes/app_analytics/google_analytics.html" %} + + {% for sound in (sounds or []) %} + + {% endfor %} + + diff --git a/frappe/www/desk.py b/frappe/www/desk.py new file mode 100644 index 0000000000..114bd62292 --- /dev/null +++ b/frappe/www/desk.py @@ -0,0 +1,68 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE +import os + +no_cache = 1 + +import json +import re +from urllib.parse import urlencode + +import frappe +import frappe.sessions +from frappe import _ +from frappe.utils.jinja_globals import is_rtl + +SCRIPT_TAG_PATTERN = re.compile(r"\") +CLOSING_SCRIPT_TAG_PATTERN = re.compile(r"") + + +def get_context(context): + if frappe.session.user == "Guest": + frappe.response["status_code"] = 403 + frappe.msgprint(_("Log in to access this page.")) + frappe.redirect(f"/login?{urlencode({'redirect-to': frappe.request.path})}") + + elif frappe.session.data.user_type == "Website User": + frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError) + + try: + boot = frappe.sessions.get() + except Exception as e: + raise frappe.SessionBootFailed from e + + # this needs commit + csrf_token = frappe.sessions.get_csrf_token() + + frappe.db.commit() + + hooks = frappe.get_hooks() + app_include_js = hooks.get("app_include_js", []) + frappe.conf.get("app_include_js", []) + app_include_css = hooks.get("app_include_css", []) + frappe.conf.get("app_include_css", []) + app_include_icons = hooks.get("app_include_icons", []) + + if frappe.get_system_settings("enable_telemetry") and os.getenv("FRAPPE_SENTRY_DSN"): + app_include_js.append("sentry.bundle.js") + + context.update( + { + "no_cache": 1, + "build_version": frappe.utils.get_build_version(), + "app_include_js": app_include_js, + "app_include_css": app_include_css, + "app_include_icons": app_include_icons, + "layout_direction": "rtl" if is_rtl() else "ltr", + "lang": frappe.local.lang, + "sounds": hooks["sounds"], + "boot": boot, + "desk_theme": boot.get("desk_theme") or "Light", + "csrf_token": csrf_token, + "google_analytics_id": frappe.conf.get("google_analytics_id"), + "google_analytics_anonymize_ip": frappe.conf.get("google_analytics_anonymize_ip"), + "app_name": ( + frappe.get_website_settings("app_name") or frappe.get_system_settings("app_name") or "Frappe" + ), + } + ) + + return context