chore: more renames to /desk

This commit is contained in:
sokumon 2025-12-18 17:02:50 +05:30
parent 0e3ff92996
commit dd2dc053ca
65 changed files with 138 additions and 136 deletions

View file

@ -118,7 +118,7 @@ context("Attach Control", () => {
//Navigating to the new form for the newly created doctype //Navigating to the new form for the newly created doctype
let doctype = "Test Attach Control"; let doctype = "Test Attach Control";
let dt_in_route = doctype.toLowerCase().replace(/ /g, "-"); let dt_in_route = doctype.toLowerCase().replace(/ /g, "-");
cy.visit(`/app/${dt_in_route}/new`, { cy.visit(`/desk/${dt_in_route}/new`, {
onBeforeLoad(win) { onBeforeLoad(win) {
// Mock "window.navigator.mediaDevices" property // Mock "window.navigator.mediaDevices" property
// to return mock mediaDevices object // to return mock mediaDevices object
@ -144,7 +144,7 @@ context("Attach Control", () => {
//Navigating to the new form for the newly created doctype //Navigating to the new form for the newly created doctype
let doctype = "Test Attach Control"; let doctype = "Test Attach Control";
let dt_in_route = doctype.toLowerCase().replace(/ /g, "-"); let dt_in_route = doctype.toLowerCase().replace(/ /g, "-");
cy.visit(`/app/${dt_in_route}/new`, { cy.visit(`/desk/${dt_in_route}/new`, {
onBeforeLoad(win) { onBeforeLoad(win) {
// Delete "window.navigator.mediaDevices" property // Delete "window.navigator.mediaDevices" property
delete win.navigator.mediaDevices; delete win.navigator.mediaDevices;

View file

@ -42,7 +42,7 @@ describe("Dashboard view", { scrollBehavior: false }, () => {
true true
); );
cy.visit(`/app/dashboard-view/${dashboard}`); cy.visit(`/desk/dashboard-view/${dashboard}`);
// expect chart to be loaded // expect chart to be loaded
cy.findByText(chart).should("be.visible"); cy.findByText(chart).should("be.visible");

View file

@ -27,7 +27,7 @@ context("Dashboard links", () => {
cy.visit("/desk/contact"); cy.visit("/desk/contact");
cy.clear_filters(); cy.clear_filters();
cy.visit(`/app/user/${cy.config("testUser")}`); cy.visit(`/desk/user/${cy.config("testUser")}`);
//To check if initially the dashboard contains only the "Contact" link and there is no counter //To check if initially the dashboard contains only the "Contact" link and there is no counter
cy.select_form_tab("Connections"); cy.select_form_tab("Connections");
@ -40,7 +40,7 @@ context("Dashboard links", () => {
cy.findByRole("button", { name: "Add Contact" }).click(); cy.findByRole("button", { name: "Add Contact" }).click();
cy.get('[data-doctype="Contact"][data-fieldname="first_name"]').type("Admin"); cy.get('[data-doctype="Contact"][data-fieldname="first_name"]').type("Admin");
cy.findByRole("button", { name: "Save" }).click(); cy.findByRole("button", { name: "Save" }).click();
cy.visit(`/app/user/${cy.config("testUser")}`); cy.visit(`/desk/user/${cy.config("testUser")}`);
//To check if the counter for contact doc is "2" after adding additional contact //To check if the counter for contact doc is "2" after adding additional contact
cy.select_form_tab("Connections"); cy.select_form_tab("Connections");
@ -62,7 +62,7 @@ context("Dashboard links", () => {
}); });
it("Report link in dashboard", () => { it("Report link in dashboard", () => {
cy.visit(`/app/user/${cy.config("testUser")}`); cy.visit(`/desk/user/${cy.config("testUser")}`);
cy.select_form_tab("Connections"); cy.select_form_tab("Connections");
cy.get('.document-link[data-doctype="Contact"]').contains("Contact"); cy.get('.document-link[data-doctype="Contact"]').contains("Contact");
cy.window() cy.window()

View file

@ -20,7 +20,7 @@ context("Form Builder", () => {
}); });
it("Save without change, check form dirty", () => { it("Save without change, check form dirty", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
// Save without change // Save without change
@ -37,7 +37,7 @@ context("Form Builder", () => {
it("Check if Filters are applied to the link field", () => { it("Check if Filters are applied to the link field", () => {
// Visit the Form Builder // Visit the Form Builder
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
cy.get("[data-fieldname='gender']").click(); cy.get("[data-fieldname='gender']").click();
@ -81,7 +81,7 @@ context("Form Builder", () => {
}); });
it("Add empty section and save", () => { it("Add empty section and save", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
let first_section = ".tab-content.active .form-section-container:first"; let first_section = ".tab-content.active .form-section-container:first";
@ -97,7 +97,9 @@ context("Form Builder", () => {
}); });
it("Add Table field and check if columns are rendered", () => { it("Add Table field and check if columns are rendered", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
let first_column = ".tab-content.active .section-columns-container:first .column:first"; let first_column = ".tab-content.active .section-columns-container:first .column:first";
@ -157,7 +159,7 @@ context("Form Builder", () => {
}); });
// not important and was flaky on CI // not important and was flaky on CI
it.skip("Drag Field/Column/Section & Tab", () => { it.skip("Drag Field/Column/Section & Tab", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
let first_column = ".tab-content.active .section-columns-container:first .column:first"; let first_column = ".tab-content.active .section-columns-container:first .column:first";
@ -218,7 +220,7 @@ context("Form Builder", () => {
}); });
it("Add New Tab/Section/Column to Form", () => { it("Add New Tab/Section/Column to Form", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
let first_section = ".tab-content.active .form-section-container:first"; let first_section = ".tab-content.active .form-section-container:first";
@ -261,7 +263,7 @@ context("Form Builder", () => {
}); });
it("Update Title field Label to New Title through Customize Form", () => { it("Update Title field Label to New Title through Customize Form", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
let first_field = let first_field =
@ -279,7 +281,7 @@ context("Form Builder", () => {
}); });
it("Validate Duplicate Name & reqd + hidden without default logic", () => { it("Validate Duplicate Name & reqd + hidden without default logic", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
let first_column = ".tab-content.active .section-columns-container:first .column:first"; let first_column = ".tab-content.active .section-columns-container:first .column:first";
@ -325,7 +327,7 @@ context("Form Builder", () => {
}); });
it.skip("Undo/Redo", () => { it.skip("Undo/Redo", () => {
cy.visit(`/app/doctype/${doctype_name}`); cy.visit(`/desk/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click(); cy.findByRole("tab", { name: "Form" }).click();
// click on second tab // click on second tab

View file

@ -70,7 +70,7 @@ context("Grid Pagination", () => {
cy.get("@table").find(".current-page-number").should("have.value", "1"); cy.get("@table").find(".current-page-number").should("have.value", "1");
}); });
// it('deletes all rows', ()=> { // it('deletes all rows', ()=> {
// cy.visit('/app/contact/Test Contact'); // cy.visit('/desk/contact/Test Contact');
// cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table'); // cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
// cy.get('@table').find('.grid-heading-row .grid-row-check').click({force: true}); // cy.get('@table').find('.grid-heading-row .grid-row-check').click({force: true});
// cy.get('@table').find('button.grid-remove-all-rows').click(); // cy.get('@table').find('button.grid-remove-all-rows').click();

View file

@ -4,13 +4,13 @@
// context('Relative Timeframe', () => { // context('Relative Timeframe', () => {
// before(() => { // before(() => {
// cy.login(); // cy.login();
// cy.visit('/app/website'); // cy.visit('/desk/website');
// cy.window().its('frappe').then(frappe => { // cy.window().its('frappe').then(frappe => {
// frappe.call("frappe.tests.ui_test_helpers.create_todo_records"); // frappe.call("frappe.tests.ui_test_helpers.create_todo_records");
// }); // });
// }); // });
// it('sets relative timespan filter for last week and filters list', () => { // it('sets relative timespan filter for last week and filters list', () => {
// cy.visit('/app/List/ToDo/List'); // cy.visit('/desk/List/ToDo/List');
// cy.clear_filters(); // cy.clear_filters();
// cy.get('.list-row:contains("this is fourth todo")').should('exist'); // cy.get('.list-row:contains("this is fourth todo")').should('exist');
// cy.add_filter(); // cy.add_filter();
@ -29,7 +29,7 @@
// cy.wait('@save_user_settings'); // cy.wait('@save_user_settings');
// }); // });
// it('sets relative timespan filter for next week and filters list', () => { // it('sets relative timespan filter for next week and filters list', () => {
// cy.visit('/app/List/ToDo/List'); // cy.visit('/desk/List/ToDo/List');
// cy.clear_filters(); // cy.clear_filters();
// cy.get('.list-row:contains("this is fourth todo")').should('exist'); // cy.get('.list-row:contains("this is fourth todo")').should('exist');
// cy.add_filter(); // cy.add_filter();

View file

@ -21,7 +21,7 @@ context("Report View", () => {
it("Field with enabled allow_on_submit should be editable.", () => { it("Field with enabled allow_on_submit should be editable.", () => {
cy.intercept("POST", "api/method/frappe.client.set_value").as("value-update"); cy.intercept("POST", "api/method/frappe.client.set_value").as("value-update");
cy.visit(`/app/List/${doctype_name}/Report`); cy.visit(`/desk/List/${doctype_name}/Report`);
// check status column added from docstatus // check status column added from docstatus
cy.get(".dt-row-0 > .dt-cell--col-3").should("contain", "Submitted"); cy.get(".dt-row-0 > .dt-cell--col-3").should("contain", "Submitted");

View file

@ -1,5 +1,5 @@
const verify_attachment_visibility = (document, is_private) => { const verify_attachment_visibility = (document, is_private) => {
cy.visit(`/app/${document}`); cy.visit(`/desk/${document}`);
const assertion = is_private ? "be.checked" : "not.be.checked"; const assertion = is_private ? "be.checked" : "not.be.checked";
cy.get(".add-attachment-btn").click(); cy.get(".add-attachment-btn").click();
@ -60,7 +60,7 @@ context("Sidebar", () => {
cy.call("frappe.tests.ui_test_helpers.create_todo_with_attachment_limit", { cy.call("frappe.tests.ui_test_helpers.create_todo_with_attachment_limit", {
description: "Sidebar Attachment Access Test ToDo", description: "Sidebar Attachment Access Test ToDo",
}).then((todo) => { }).then((todo) => {
cy.visit(`/app/todo/${todo.message.name}`); cy.visit(`/desk/todo/${todo.message.name}`);
attach_file("cypress/fixtures/sample_image.jpg"); attach_file("cypress/fixtures/sample_image.jpg");
cy.get(".explore-link").should("be.visible"); cy.get(".explore-link").should("be.visible");

View file

@ -13,7 +13,7 @@ context("Realtime updates", () => {
it("Shows version conflict warning", { scrollBehavior: false }, () => { it("Shows version conflict warning", { scrollBehavior: false }, () => {
cy.insert_doc("ToDo", { description: "old" }).then((doc) => { cy.insert_doc("ToDo", { description: "old" }).then((doc) => {
cy.visit(`/app/todo/${doc.name}`); cy.visit(`/desk/todo/${doc.name}`);
// make form dirty // make form dirty
cy.fill_field("status", "Cancelled", "Select"); cy.fill_field("status", "Cancelled", "Select");

View file

@ -143,7 +143,7 @@ context("Workspace Blocks", () => {
}); });
it("Number Card Block", () => { it("Number Card Block", () => {
cy.visit("/app/private/test-block-page"); cy.visit("/desk/private/test-block-page");
cy.create_records([ cy.create_records([
{ {
doctype: "Number Card", doctype: "Number Card",

View file

@ -263,7 +263,7 @@ Cypress.Commands.add("awesomebar", (text) => {
Cypress.Commands.add("new_form", (doctype) => { Cypress.Commands.add("new_form", (doctype) => {
let dt_in_route = doctype.toLowerCase().replace(/ /g, "-"); let dt_in_route = doctype.toLowerCase().replace(/ /g, "-");
cy.visit(`/app/${dt_in_route}/new`); cy.visit(`/desk/${dt_in_route}/new`);
cy.get("body").should(($body) => { cy.get("body").should(($body) => {
const dataRoute = $body.attr("data-route"); const dataRoute = $body.attr("data-route");
expect(dataRoute).to.match(new RegExp(`^Form/${doctype}/new-${dt_in_route}-`)); expect(dataRoute).to.match(new RegExp(`^Form/${doctype}/new-${dt_in_route}-`));
@ -277,7 +277,7 @@ Cypress.Commands.add("select_form_tab", (label) => {
Cypress.Commands.add("go_to_list", (doctype) => { Cypress.Commands.add("go_to_list", (doctype) => {
let dt_in_route = doctype.toLowerCase().replace(/ /g, "-"); let dt_in_route = doctype.toLowerCase().replace(/ /g, "-");
cy.visit(`/app/${dt_in_route}`); cy.visit(`/desk/${dt_in_route}`);
}); });
Cypress.Commands.add("clear_cache", () => { Cypress.Commands.add("clear_cache", () => {

View file

@ -1483,9 +1483,9 @@ def get_desk_link(doctype, name, show_title_with_name=False, open_in_new_tab=Fal
encoded_name = quote(name) encoded_name = quote(name)
if show_title_with_name and name != title: if show_title_with_name and name != title:
html = '<a href="/app/Form/{doctype}/{encoded_name}"{target} style="font-weight: bold;">{doctype_local} {name}: {title_local}</a>' html = '<a href="/desk/Form/{doctype}/{encoded_name}"{target} style="font-weight: bold;">{doctype_local} {name}: {title_local}</a>'
else: else:
html = '<a href="/app/Form/{doctype}/{encoded_name}"{target} style="font-weight: bold;">{doctype_local} {title_local}</a>' html = '<a href="/desk/Form/{doctype}/{encoded_name}"{target} style="font-weight: bold;">{doctype_local} {title_local}</a>'
return html.format( return html.format(
doctype=doctype, doctype=doctype,

View file

@ -11,8 +11,8 @@ from frappe.core.doctype.installed_applications.installed_applications import (
get_setup_wizard_not_required_apps, get_setup_wizard_not_required_apps,
) )
# check if route is /app or /app/* and not /app1 or /app1/* # check if route is /desk or /desk/* and not /app1 or /app1/*
DESK_APP_PATTERN = re.compile(r"^/app(/.*)?$") DESK_APP_PATTERN = re.compile(r"^/desk(/.*)?$")
@frappe.whitelist() @frappe.whitelist()

View file

@ -30,7 +30,7 @@ frappe.ui.form.on("Auto Repeat", {
refresh: function (frm) { refresh: function (frm) {
// auto repeat message // auto repeat message
if (frm.is_new()) { if (frm.is_new()) {
let customize_form_link = `<a href="/app/customize-form">${__("Customize Form")}</a>`; let customize_form_link = `<a href="/desk/customize-form">${__("Customize Form")}</a>`;
frm.dashboard.set_headline( frm.dashboard.set_headline(
__('To configure Auto Repeat, enable "Allow Auto Repeat" from {0}.', [ __('To configure Auto Repeat, enable "Allow Auto Repeat" from {0}.', [
customize_form_link, customize_form_link,

View file

@ -11,7 +11,7 @@ frappe.listview_settings["Deleted Document"] = {
if (r.message) { if (r.message) {
let body = (docnames) => { let body = (docnames) => {
const html = docnames.map((docname) => { const html = docnames.map((docname) => {
return `<li><a href='/app/deleted-document/${docname}'>${docname}</a></li>`; return `<li><a href='/desk/deleted-document/${docname}'>${docname}</a></li>`;
}); });
return "<br><ul>" + html.join(""); return "<br><ul>" + html.join("");
}; };

View file

@ -54,11 +54,11 @@ frappe.ui.form.on("DocType", {
? __("Go to {0}", [__(frm.doc.name)]) ? __("Go to {0}", [__(frm.doc.name)])
: __("Go to {0} List", [__(frm.doc.name)]); : __("Go to {0} List", [__(frm.doc.name)]);
frm.add_custom_button(button_text, () => { frm.add_custom_button(button_text, () => {
window.open(`/app/${frappe.router.slug(frm.doc.name)}`); window.open(`/desk/${frappe.router.slug(frm.doc.name)}`);
}); });
} }
const customize_form_link = `<a href="/app/customize-form">${__("Customize Form")}</a>`; const customize_form_link = `<a href="/desk/customize-form">${__("Customize Form")}</a>`;
if (!frappe.boot.developer_mode && !frm.doc.custom) { if (!frappe.boot.developer_mode && !frm.doc.custom) {
// make the document read-only // make the document read-only
frm.set_read_only(); frm.set_read_only();

View file

@ -123,7 +123,7 @@ def has_unseen_error_log():
return { return {
"show_alert": True, "show_alert": True,
"message": _("You have unseen {0}").format( "message": _("You have unseen {0}").format(
'<a href="/app/List/Error%20Log/List"> Error Logs </a>' '<a href="/desk/List/Error%20Log/List"> Error Logs </a>'
), ),
} }

View file

@ -136,7 +136,7 @@ order by creation desc
<hr> <hr>
<h4>Workflow Task</h4> <h4>Workflow Task</h4>
<p>Execute when a particular <a href="/app/workflow-action-master">Workflow Action Master</a> is executed.</p> <p>Execute when a particular <a href="/desk/workflow-action-master">Workflow Action Master</a> is executed.</p>
<p>Gets the document which the action is being applied on in the <code>doc</code> variable.</p> <p>Gets the document which the action is being applied on in the <code>doc</code> variable.</p>
<pre><code class="language-python"> <pre><code class="language-python">
# create a customer with the same name as the given document # create a customer with the same name as the given document

View file

@ -132,7 +132,7 @@ class SubmissionQueue(Document):
{ {
"message": message.format( "message": message.format(
*message_replacements, *message_replacements,
f"<a href='/app/{quote(doctype.lower().replace(' ', '-'))}/{quote(docname)}'><b>here</b></a>", f"<a href='/desk/{quote(doctype.lower().replace(' ', '-'))}/{quote(docname)}'><b>here</b></a>",
), ),
"alert": True, "alert": True,
"indicator": "red" if submission_status == "Failed" else "green", "indicator": "red" if submission_status == "Failed" else "green",
@ -170,7 +170,7 @@ def queue_submission(doc: Document, action: str, alert: bool = True):
frappe.msgprint( frappe.msgprint(
_( _(
"This document has already been queued for submission. You can track the progress over {0}." "This document has already been queued for submission. You can track the progress over {0}."
).format(f"<a href='/app/submission-queue/{existing_queue}'><b>here</b></a>"), ).format(f"<a href='/desk/submission-queue/{existing_queue}'><b>here</b></a>"),
indicator="orange", indicator="orange",
alert=True, alert=True,
) )
@ -184,7 +184,7 @@ def queue_submission(doc: Document, action: str, alert: bool = True):
if alert: if alert:
frappe.msgprint( frappe.msgprint(
_("Queued for Submission. You can track the progress over {0}.").format( _("Queued for Submission. You can track the progress over {0}.").format(
f"<a href='/app/submission-queue/{queue.name}'><b>here</b></a>" f"<a href='/desk/submission-queue/{queue.name}'><b>here</b></a>"
), ),
indicator="green", indicator="green",
alert=True, alert=True,

View file

@ -5,8 +5,8 @@
<li>{%= __("Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.") %}</li> <li>{%= __("Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.") %}</li>
<li>{%= __("Permissions get applied on Users based on what Roles they are assigned.") %}</li> <li>{%= __("Permissions get applied on Users based on what Roles they are assigned.") %}</li>
<li>{%= __("Roles can be set for users from their User page.") %} <li>{%= __("Roles can be set for users from their User page.") %}
<a href="/app/List/User">{%= __("Setup > User") %}</a></li> <a href="/desk/List/User">{%= __("Setup > User") %}</a></li>
<li>{%= __("The system provides many pre-defined roles. You can add new roles to set finer permissions.") %}<a href="/app/List/Role"> {%= __("Add a New Role") %}</a></li> <li>{%= __("The system provides many pre-defined roles. You can add new roles to set finer permissions.") %}<a href="/desk/List/Role"> {%= __("Add a New Role") %}</a></li>
<li>{%= __("Permissions are automatically applied to Standard Reports and searches.") %}</li> <li>{%= __("Permissions are automatically applied to Standard Reports and searches.") %}</li>
<li>{%= __("As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.") %}</li> <li>{%= __("As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.") %}</li>
</ol> </ol>
@ -24,13 +24,13 @@
<li>{%= __("Permissions at level 0 are Document Level permissions, i.e. they are primary for access to the document.") %}</li> <li>{%= __("Permissions at level 0 are Document Level permissions, i.e. they are primary for access to the document.") %}</li>
<li>{%= __("If a Role does not have access at Level 0, then higher levels are meaningless.") %}</li> <li>{%= __("If a Role does not have access at Level 0, then higher levels are meaningless.") %}</li>
<li>{%= __("Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.") %}</li> <li>{%= __("Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.") %}</li>
<li>{%= __("You can use Customize Form to set levels on fields.") %} <a href="/app/Form/Customize Form">{%= __("Setup > Customize Form") %}</a></li> <li>{%= __("You can use Customize Form to set levels on fields.") %} <a href="/desk/Form/Customize Form">{%= __("Setup > Customize Form") %}</a></li>
</ol> </ol>
<hr> <hr>
<h4>{%= __("User Permissions") %}:</h4> <h4>{%= __("User Permissions") %}:</h4>
<ol> <ol>
<li>{%= __("User Permissions are used to limit users to specific records.") %} <li>{%= __("User Permissions are used to limit users to specific records.") %}
<a href="/app/List/User Permission">{%= __("Setup > User Permissions") %}</a></li> <a href="/desk/List/User Permission">{%= __("Setup > User Permissions") %}</a></li>
<li>{%= __("Select Document Types to set which User Permissions are used to limit access.") %}</li> <li>{%= __("Select Document Types to set which User Permissions are used to limit access.") %}</li>
<li>{%= __("Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).") %}</li> <li>{%= __("Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).") %}</li>
<li>{%= __("Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.") %}</li> <li>{%= __("Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.") %}</li>

View file

@ -335,7 +335,7 @@ class TestCustomizeForm(IntegrationTestCase):
self.assertFalse([d.name for d in (user_group.links or []) if d.link_doctype == "User Group Member"]) self.assertFalse([d.name for d in (user_group.links or []) if d.link_doctype == "User Group Member"])
def test_custom_action(self): def test_custom_action(self):
test_route = "/app/List/DocType" test_route = "/desk/List/DocType"
# create a dummy action (route) # create a dummy action (route)
d = self.get_customize_form("Event") d = self.get_customize_form("Event")

View file

@ -40,7 +40,7 @@ frappe.ui.form.on("DocType Layout", {
add_buttons(frm) { add_buttons(frm) {
if (!frm.is_new()) { if (!frm.is_new()) {
frm.add_custom_button(__("Go to {0} List", [frm.doc.name]), () => { frm.add_custom_button(__("Go to {0} List", [frm.doc.name]), () => {
window.open(`/app/${frappe.router.slug(frm.doc.name)}`); window.open(`/desk/${frappe.router.slug(frm.doc.name)}`);
}); });
frm.add_custom_button(__("Sync {0} Fields", [frm.doc.name]), async () => { frm.add_custom_button(__("Sync {0} Fields", [frm.doc.name]), async () => {

View file

@ -122,7 +122,7 @@ def get_non_standard_warning_message(non_standard_docs_map):
def get_html(docs, doctype): def get_html(docs, doctype):
html = f"<p>{frappe.bold(doctype)}</p>" html = f"<p>{frappe.bold(doctype)}</p>"
for doc in docs: for doc in docs:
html += f'<div><a href="/app/Form/{doctype}/{doc}">{doc}</a></div>' html += f'<div><a href="/desk/Form/{doctype}/{doc}">{doc}</a></div>'
html += "<br>" html += "<br>"
return html return html

View file

@ -61,7 +61,7 @@
}, },
{ {
"bold": 1, "bold": 1,
"description": "Help: To link to another record in the system, use \"/app/note/[Note Name]\" as the Link URL. (don't use \"http://\")", "description": "Help: To link to another record in the system, use \"/desk/note/[Note Name]\" as the Link URL. (don't use \"http://\")",
"fieldname": "content", "fieldname": "content",
"fieldtype": "Text Editor", "fieldtype": "Text Editor",
"in_global_search": 1, "in_global_search": 1,

View file

@ -77,7 +77,7 @@
"options": "System Health Report Workers" "options": "System Health Report Workers"
}, },
{ {
"documentation_url": "/app/rq-worker", "documentation_url": "/desk/rq-worker",
"fieldname": "total_background_workers", "fieldname": "total_background_workers",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Total Background Workers" "label": "Total Background Workers"
@ -89,7 +89,7 @@
"label": "Background Jobs" "label": "Background Jobs"
}, },
{ {
"documentation_url": "/app/rq-job", "documentation_url": "/desk/rq-job",
"fieldname": "scheduler_status", "fieldname": "scheduler_status",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Scheduler Status" "label": "Scheduler Status"
@ -140,7 +140,7 @@
"label": "Outgoing Emails (Last 7 days)" "label": "Outgoing Emails (Last 7 days)"
}, },
{ {
"documentation_url": "/app/email-queue?status=Error", "documentation_url": "/desk/email-queue?status=Error",
"fieldname": "failed_emails", "fieldname": "failed_emails",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Failed Emails" "label": "Failed Emails"
@ -151,7 +151,7 @@
"label": "Total Outgoing Emails" "label": "Total Outgoing Emails"
}, },
{ {
"documentation_url": "/app/email-queue?status=Not+Sent", "documentation_url": "/desk/email-queue?status=Not+Sent",
"fieldname": "pending_emails", "fieldname": "pending_emails",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Pending Emails" "label": "Pending Emails"
@ -162,13 +162,13 @@
"label": "Incoming Emails (Last 7 days)" "label": "Incoming Emails (Last 7 days)"
}, },
{ {
"documentation_url": "/app/unhandled-email", "documentation_url": "/desk/unhandled-email",
"fieldname": "unhandled_emails", "fieldname": "unhandled_emails",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Unhandled Emails" "label": "Unhandled Emails"
}, },
{ {
"documentation_url": "/app/communication?communication_type=Communication&sent_or_received=Received", "documentation_url": "/desk/communication?communication_type=Communication&sent_or_received=Received",
"fieldname": "handled_emails", "fieldname": "handled_emails",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Handled Emails" "label": "Handled Emails"
@ -179,7 +179,7 @@
"label": "Errors" "label": "Errors"
}, },
{ {
"documentation_url": "/app/error-log", "documentation_url": "/desk/error-log",
"fieldname": "total_errors", "fieldname": "total_errors",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Total Errors (last 1 day)" "label": "Total Errors (last 1 day)"
@ -205,7 +205,7 @@
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{ {
"documentation_url": "/app/query-report/Database Storage Usage By Tables", "documentation_url": "/desk/query-report/Database Storage Usage By Tables",
"fieldname": "top_db_tables", "fieldname": "top_db_tables",
"fieldtype": "Table", "fieldtype": "Table",
"label": "Storage Usage By Table", "label": "Storage Usage By Table",
@ -265,13 +265,13 @@
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{ {
"documentation_url": "/app/backups", "documentation_url": "/desk/backups",
"fieldname": "onsite_backups", "fieldname": "onsite_backups",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Number of onsite backups" "label": "Number of onsite backups"
}, },
{ {
"documentation_url": "/app/user", "documentation_url": "/desk/user",
"fieldname": "total_users", "fieldname": "total_users",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Total Users" "label": "Total Users"
@ -286,7 +286,7 @@
"label": "New Users (Last 30 days)" "label": "New Users (Last 30 days)"
}, },
{ {
"documentation_url": "/app/activity-log?status=Failed&operation=Login", "documentation_url": "/desk/activity-log?status=Failed&operation=Login",
"fieldname": "failed_logins", "fieldname": "failed_logins",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Failed Logins (Last 30 days)" "label": "Failed Logins (Last 30 days)"
@ -353,7 +353,7 @@
"label": "Realtime (SocketIO)" "label": "Realtime (SocketIO)"
}, },
{ {
"documentation_url": "/app/rq-job", "documentation_url": "/desk/rq-job",
"fieldname": "background_jobs_check", "fieldname": "background_jobs_check",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Background Jobs Check" "label": "Background Jobs Check"

View file

@ -9,7 +9,7 @@ frappe.ui.form.on("Workspace", {
refresh: function (frm) { refresh: function (frm) {
frm.enable_save(); frm.enable_save();
let url = `/app/${ let url = `/desk/${
frm.doc.public frm.doc.public
? frappe.router.slug(frm.doc.title) ? frappe.router.slug(frm.doc.title)
: "private/" + frappe.router.slug(frm.doc.title) : "private/" + frappe.router.slug(frm.doc.title)

View file

@ -46,7 +46,7 @@ def execute(filters=None):
for todo in todo_list: for todo in todo_list:
if todo.owner == frappe.session.user or todo.assigned_by == frappe.session.user: if todo.owner == frappe.session.user or todo.assigned_by == frappe.session.user:
if todo.reference_type: if todo.reference_type:
todo.reference = """<a href="/app/Form/{}/{}">{}: {}</a>""".format( todo.reference = """<a href="/desk/Form/{}/{}">{}: {}</a>""".format(
todo.reference_type, todo.reference_type,
todo.reference_name, todo.reference_name,
todo.reference_type, todo.reference_type,

View file

@ -7,7 +7,7 @@
"icon_type": "App", "icon_type": "App",
"idx": 0, "idx": 0,
"label": "Framework", "label": "Framework",
"link": "/app/build", "link": "/desk/build",
"link_type": "External", "link_type": "External",
"logo_url": "/assets/frappe/images/frappe-framework-logo.svg", "logo_url": "/assets/frappe/images/frappe-framework-logo.svg",
"modified": "2025-12-12 07:36:09.059666", "modified": "2025-12-12 07:36:09.059666",

View file

@ -257,7 +257,7 @@ frappe.ui.form.on("Notification", {
frm.set_df_property( frm.set_df_property(
"channel", "channel",
"description", "description",
`To use SMS Channel, initialize <a href="/app/sms-settings">SMS Settings</a>.` `To use SMS Channel, initialize <a href="/desk/sms-settings">SMS Settings</a>.`
); );
} else { } else {
frm.set_df_property("channel", "description", ` `); frm.set_df_property("channel", "description", ` `);

View file

@ -544,7 +544,7 @@ standard_help_items = [
{ {
"item_label": "System Health", "item_label": "System Health",
"item_type": "Route", "item_type": "Route",
"route": "/app/system-health-report", "route": "/desk/system-health-report",
"is_standard": 1, "is_standard": 1,
}, },
{ {

View file

@ -6,7 +6,7 @@ frappe.ui.form.on("Google Calendar", {
if (frm.is_new()) { if (frm.is_new()) {
frm.dashboard.set_headline( frm.dashboard.set_headline(
__("To use Google Calendar, enable {0}.", [ __("To use Google Calendar, enable {0}.", [
`<a href='/app/google-settings'>${__("Google Settings")}</a>`, `<a href='/desk/google-settings'>${__("Google Settings")}</a>`,
]) ])
); );
} }

View file

@ -6,7 +6,7 @@ frappe.ui.form.on("Google Contacts", {
if (!frm.doc.enable) { if (!frm.doc.enable) {
frm.dashboard.set_headline( frm.dashboard.set_headline(
__("To use Google Contacts, enable {0}.", [ __("To use Google Contacts, enable {0}.", [
`<a href='/app/google-settings'>${__("Google Settings")}</a>`, `<a href='/desk/google-settings'>${__("Google Settings")}</a>`,
]) ])
); );
} }

View file

@ -64,7 +64,7 @@ def authorize_access(g_contact, reauthorize=False, code=None):
return oauth_obj.get_authentication_url( return oauth_obj.get_authentication_url(
{ {
"g_contact": g_contact, "g_contact": g_contact,
"redirect": f"/app/Form/{quote('Google Contacts')}/{quote(g_contact)}", "redirect": f"/desk/Form/{quote('Google Contacts')}/{quote(g_contact)}",
}, },
) )

View file

@ -49,7 +49,7 @@ class GoogleOAuth:
self.validate_google_settings() self.validate_google_settings()
def validate_google_settings(self): def validate_google_settings(self):
google_settings = "<a href='/app/google-settings'>Google Settings</a>" google_settings = "<a href='/desk/google-settings'>Google Settings</a>"
if not self.google_settings.enable: if not self.google_settings.enable:
frappe.throw(frappe._("Please enable {} before continuing.").format(google_settings)) frappe.throw(frappe._("Please enable {} before continuing.").format(google_settings))

View file

@ -128,7 +128,7 @@ frappe.ui.form.PrintView = class {
description = description =
"<div class='form-message yellow p-3 mt-3'>" + "<div class='form-message yellow p-3 mt-3'>" +
__("Footer might not be visible as {0} option is disabled</div>", [ __("Footer might not be visible as {0} option is disabled</div>", [
`<a href="/app/print-settings/Print Settings">${__( `<a href="/desk/print-settings/Print Settings">${__(
"Repeat Header and Footer" "Repeat Header and Footer"
)}</a>`, )}</a>`,
]); ]);
@ -202,7 +202,7 @@ frappe.ui.form.PrintView = class {
if (!cint(frappe.boot.sysdefaults.disable_product_suggestion)) { if (!cint(frappe.boot.sysdefaults.disable_product_suggestion)) {
if (Object.keys(frappe.boot.versions).includes("print_designer")) { if (Object.keys(frappe.boot.versions).includes("print_designer")) {
this.page.add_inner_message(` this.page.add_inner_message(`
<a style="line-height: 2.4" href="/app/print-designer?doctype=${this.frm.doctype}"> <a style="line-height: 2.4" href="/desk/print-designer?doctype=${this.frm.doctype}">
${__("Try the new Print Designer")} ${__("Try the new Print Designer")}
</a> </a>
`); `);

View file

@ -184,7 +184,7 @@ function is_filter_applied() {
function open_child_doctype() { function open_child_doctype() {
if (!props.field?.df?.options) return; if (!props.field?.df?.options) return;
window.open(`/app/doctype/${props.field.df.options}`, "_blank"); window.open(`/desk/doctype/${props.field.df.options}`, "_blank");
} }
onMounted(() => selected.value && label_input.value.focus_on_label()); onMounted(() => selected.value && label_input.value.focus_on_label());

View file

@ -1930,7 +1930,7 @@ frappe.ui.form.Form = class FrappeForm {
return ` return `
<a class="indicator ${get_color(doc || {})}" <a class="indicator ${get_color(doc || {})}"
href="/app/${frappe.router.slug(df.options)}/${escaped_name}" href="/desk/${frappe.router.slug(df.options)}/${escaped_name}"
data-doctype="${df.options}" data-doctype="${df.options}"
data-name="${frappe.utils.escape_html(value)}"> data-name="${frappe.utils.escape_html(value)}">
${label} ${label}
@ -2240,7 +2240,7 @@ frappe.ui.form.Form = class FrappeForm {
secondary = ` secondary = `
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<a href='/app/submission-queue?ref_doctype=${encodeURIComponent( <a href='/desk/submission-queue?ref_doctype=${encodeURIComponent(
this.doctype this.doctype
)}&ref_docname=${encodeURIComponent(this.docname)}'>${__( )}&ref_docname=${encodeURIComponent(this.docname)}'>${__(
"All Submissions" "All Submissions"
@ -2251,7 +2251,7 @@ frappe.ui.form.Form = class FrappeForm {
let html = ` let html = `
<div class="row"> <div class="row">
<div class="${div_class}"> <div class="${div_class}">
<a href='/app/submission-queue/${r.message.latest_submission}'>${submission_label} (${r.message.status})</a>${secondary} <a href='/desk/submission-queue/${r.message.latest_submission}'>${submission_label} (${r.message.status})</a>${secondary}
</div> </div>
</div> </div>
`; `;

View file

@ -202,7 +202,7 @@ frappe.form.formatters = {
} else if (docfield && doctype) { } else if (docfield && doctype) {
if (frappe.model.can_read(doctype)) { if (frappe.model.can_read(doctype)) {
const a = document.createElement("a"); const a = document.createElement("a");
a.href = `/app/${encodeURIComponent( a.href = `/desk/${encodeURIComponent(
frappe.router.slug(doctype) frappe.router.slug(doctype)
)}/${encodeURIComponent(original_value)}`; )}/${encodeURIComponent(original_value)}`;
a.dataset.doctype = doctype; a.dataset.doctype = doctype;

View file

@ -72,7 +72,7 @@ frappe.ui.form.LinkedWith = class LinkedWith {
return `<div class="list-row-container"> return `<div class="list-row-container">
<div class="level list-row small"> <div class="level list-row small">
<div class="level-left bold"> <div class="level-left bold">
<a href="/app/${frappe.router.slug(doctype)}/${doc.name}">${doc.name}</a> <a href="/desk/${frappe.router.slug(doctype)}/${doc.name}">${doc.name}</a>
</div> </div>
</div> </div>
</div>`; </div>`;

View file

@ -469,7 +469,7 @@ frappe.ui.form.MultiSelectDialog = class MultiSelectDialog {
result[column] || "" result[column] || ""
)}">${__(result[column] || "")}</span>` )}">${__(result[column] || "")}</span>`
: `<a href="${ : `<a href="${
"/app/" + frappe.router.slug(me.doctype) + "/" + result[column] || "/desk/" + frappe.router.slug(me.doctype) + "/" + result[column] ||
"" ""
}" class="list-id ellipsis" title="${__(result[column] || "")}"> }" class="list-id ellipsis" title="${__(result[column] || "")}">
${__(result[column] || "")}</a>` ${__(result[column] || "")}</a>`

View file

@ -31,7 +31,7 @@
</a> </a>
<ul class="dropdown-menu print-format-dropdown" style="max-height: 300px; <ul class="dropdown-menu print-format-dropdown" style="max-height: 300px;
overflow-y: auto; left: auto;"> overflow-y: auto; left: auto;">
<li><a class="dropdown-item" href="/app/Form/Print Settings"> <li><a class="dropdown-item" href="/desk/Form/Print Settings">
{%= __("Print Settings") %}</a></li> {%= __("Print Settings") %}</a></li>
<li><a class="btn-printer-setting dropdown-item" style="display: none;"> <li><a class="btn-printer-setting dropdown-item" style="display: none;">
{%= __("Raw Printing Settings") %}</a></li> {%= __("Raw Printing Settings") %}</a></li>

View file

@ -62,14 +62,14 @@ frappe.views.ListFactory = class ListFactory extends frappe.views.Factory {
last_route[1] === doctype last_route[1] === doctype
) { ) {
// last route same as this route, so going back. // last route same as this route, so going back.
// this happens because /app/List/Item will redirect to /app/List/Item/List // this happens because /desk/List/Item will redirect to /desk/List/Item/List
// while coming from back button, the last 2 routes will be same, so // while coming from back button, the last 2 routes will be same, so
// we know user is coming in the reverse direction (via back button) // we know user is coming in the reverse direction (via back button)
// example: // example:
// Step 1: /app/List/Item redirects to /app/List/Item/List // Step 1: /desk/List/Item redirects to /desk/List/Item/List
// Step 2: User hits "back" comes back to /app/List/Item // Step 2: User hits "back" comes back to /desk/List/Item
// Step 3: Now we cannot send the user back to /app/List/Item/List so go back one more step // Step 3: Now we cannot send the user back to /desk/List/Item/List so go back one more step
window.history.go(-1); window.history.go(-1);
return true; return true;
} }

View file

@ -204,8 +204,8 @@ frappe.views.ListViewSelect = class ListViewSelect {
if (!r.ref_doctype || r.ref_doctype == this.doctype) { if (!r.ref_doctype || r.ref_doctype == this.doctype) {
const report_type = const report_type =
r.report_type === "Report Builder" r.report_type === "Report Builder"
? `/app/list/${r.ref_doctype}/report` ? `/desk/list/${r.ref_doctype}/report`
: "/app/query-report"; : "/desk/query-report";
const route = r.route || report_type + "/" + (r.title || r.name); const route = r.route || report_type + "/" + (r.title || r.name);
@ -286,13 +286,13 @@ frappe.views.ListViewSelect = class ListViewSelect {
// has standard calendar view // has standard calendar view
calendars.push({ calendars.push({
name: "Default", name: "Default",
route: `/app/${this.slug()}/view/calendar/default`, route: `/desk/${this.slug()}/view/calendar/default`,
}); });
} }
result.map((calendar) => { result.map((calendar) => {
calendars.push({ calendars.push({
name: calendar.name, name: calendar.name,
route: `/app/${this.slug()}/view/calendar/${calendar.name}`, route: `/desk/${this.slug()}/view/calendar/${calendar.name}`,
}); });
}); });
@ -306,7 +306,7 @@ frappe.views.ListViewSelect = class ListViewSelect {
accounts.forEach((account) => { accounts.forEach((account) => {
let email_account = let email_account =
account.email_id == "All Accounts" ? "All Accounts" : account.email_account; account.email_id == "All Accounts" ? "All Accounts" : account.email_account;
let route = `/app/communication/view/inbox/${email_account}`; let route = `/desk/communication/view/inbox/${email_account}`;
let display_name = ["All Accounts", "Sent Mail", "Spam", "Trash"].includes( let display_name = ["All Accounts", "Sent Mail", "Spam", "Trash"].includes(
account.email_id account.email_id
) )

View file

@ -17,7 +17,7 @@ frappe.utils.logtypes.show_log_retention_message = (doctype) => {
$(`<div>${message}</div>`).appendTo(sidebar_entry); $(`<div>${message}</div>`).appendTo(sidebar_entry);
}; };
const log_settings_link = `<a href='/app/log-settings'>${__("Log Settings")}</a>`; const log_settings_link = `<a href='/desk/log-settings'>${__("Log Settings")}</a>`;
const cta = __("You can change the retention policy from {0}.", [log_settings_link]); const cta = __("You can change the retention policy from {0}.", [log_settings_link]);
let message = __("{0} records are not automatically deleted.", [__(doctype)]); let message = __("{0} records are not automatically deleted.", [__(doctype)]);

View file

@ -160,14 +160,14 @@ frappe.router = {
}, },
async convert_to_standard_route(route) { async convert_to_standard_route(route) {
// /app/settings = ["Workspaces", "Settings"] // /desk/settings = ["Workspaces", "Settings"]
// /app/private/settings = ["Workspaces", "private", "Settings"] // /desk/private/settings = ["Workspaces", "private", "Settings"]
// /app/user = ["List", "User"] // /desk/user = ["List", "User"]
// /app/user/view/report = ["List", "User", "Report"] // /desk/user/view/report = ["List", "User", "Report"]
// /app/user/view/tree = ["Tree", "User"] // /desk/user/view/tree = ["Tree", "User"]
// /app/user/user-001 = ["Form", "User", "user-001"] // /desk/user/user-001 = ["Form", "User", "user-001"]
// /app/user/user-001 = ["Form", "User", "user-001"] // /desk/user/user-001 = ["Form", "User", "user-001"]
// /app/event/view/calendar/default = ["List", "Event", "Calendar", "Default"] // /desk/event/view/calendar/default = ["List", "Event", "Calendar", "Default"]
if (frappe.workspaces[route[0]]) { if (frappe.workspaces[route[0]]) {
// public workspace // public workspace
route = ["Workspaces", frappe.workspaces[route[0]].name]; route = ["Workspaces", frappe.workspaces[route[0]].name];
@ -499,7 +499,7 @@ frappe.router = {
* Changes the URL and calls the router. * Changes the URL and calls the router.
* *
* @param {string} path - The desired URI path to replace or push, * @param {string} path - The desired URI path to replace or push,
* without query string. Example: "/app/todo" * without query string. Example: "/desk/todo"
* @param {string} query_params - The desired query parameter string. * @param {string} query_params - The desired query parameter string.
* @returns {void} * @returns {void}
*/ */
@ -524,7 +524,7 @@ frappe.router = {
}, },
strip_prefix(route) { strip_prefix(route) {
if (route.substr(0, 1) == "/") route = route.substr(1); // for /app/sub if (route.substr(0, 1) == "/") route = route.substr(1); // for /desk/sub
if (route == "desk") route = route.substr(4); // for app if (route == "desk") route = route.substr(4); // for app
if (route.startsWith("desk/")) route = route.substr(4); // for desk/sub 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);

View file

@ -136,7 +136,7 @@ export class DropdownConsole {
this.dialog.set_value("output", output); this.dialog.set_value("output", output);
const time_taken = moment(end).diff(start, "milliseconds"); const time_taken = moment(end).diff(start, "milliseconds");
output_field.set_description(`Executed in ${time_taken} milliseconds. output_field.set_description(`Executed in ${time_taken} milliseconds.
<a target="_blank" href="/app/console-log?owner=${frappe.session.user}" >View Logs</a>`); <a target="_blank" href="/desk/console-log?owner=${frappe.session.user}" >View Logs</a>`);
} }
async load_completions() { async load_completions() {

View file

@ -249,7 +249,7 @@ class NotificationsView extends BaseNotificationsView {
if (this.container.find(".activity-status")) { if (this.container.find(".activity-status")) {
this.container.find(".activity-status").replaceWith( this.container.find(".activity-status").replaceWith(
`<a class="recent-item text-center text-muted" `<a class="recent-item text-center text-muted"
href="/app/List/Notification Log"> href="/desk/List/Notification Log">
<div class="full-log-btn">${__("View Full Log")}</div> <div class="full-log-btn">${__("View Full Log")}</div>
</a>` </a>`
); );
@ -338,7 +338,7 @@ class NotificationsView extends BaseNotificationsView {
this.container.append(this.get_dropdown_item_html(notification_log)); this.container.append(this.get_dropdown_item_html(notification_log));
}); });
this.container.append(`<a class="list-footer" this.container.append(`<a class="list-footer"
href="/app/List/Notification Log"> href="/desk/List/Notification Log">
<div class="full-log-btn">${__("See all Activity")}</div> <div class="full-log-btn">${__("See all Activity")}</div>
</a>`); </a>`);
} else { } else {
@ -459,7 +459,7 @@ class EventsView extends BaseNotificationsView {
location = `, ${event.location}`; location = `, ${event.location}`;
} }
return `<a class="recent-item event" href="/app/event/${event.name}"> return `<a class="recent-item event" href="/desk/event/${event.name}">
<div class="event-border" style="border-color: ${event.color}"></div> <div class="event-border" style="border-color: ${event.color}"></div>
<div class="event-item"> <div class="event-item">
<div class="event-subject">${event.subject}</div> <div class="event-subject">${event.subject}</div>

View file

@ -106,7 +106,7 @@ frappe.ui.toolbar.Toolbar = class {
if (!frappe.is_mobile()) return; if (!frappe.is_mobile()) return;
this.navbar = $(".navbar-brand"); this.navbar = $(".navbar-brand");
let doctype = frappe.get_route()[1]; let doctype = frappe.get_route()[1];
let list_view_route = `/app/${frappe.router.convert_from_standard_route([ let list_view_route = `/desk/${frappe.router.convert_from_standard_route([
"list", "list",
doctype, doctype,
])}`; ])}`;

View file

@ -272,7 +272,7 @@ frappe.dashboard_utils = {
values.name = docname; values.name = docname;
values.set_standard = frappe.boot.developer_mode; values.set_standard = frappe.boot.developer_mode;
frappe.xcall(method, { args: values }).then(() => { frappe.xcall(method, { args: values }).then(() => {
let dashboard_route_html = `<a href = "/app/dashboard/${values.dashboard}">${values.dashboard}</a>`; let dashboard_route_html = `<a href = "/desk/dashboard/${values.dashboard}">${values.dashboard}</a>`;
let message = __("{0} {1} added to Dashboard {2}", [ let message = __("{0} {1} added to Dashboard {2}", [
doctype, doctype,
values.name, values.name,

View file

@ -65,7 +65,7 @@ frappe.views.FileView = class FileView extends frappe.views.ListView {
frappe.breadcrumbs.add({ frappe.breadcrumbs.add({
type: "Custom", type: "Custom",
label: __("Home"), label: __("Home"),
route: "/app/List/File/Home", route: "/desk/List/File/Home",
}); });
} }
@ -351,7 +351,7 @@ frappe.views.FileView = class FileView extends frappe.views.ListView {
acc += "/" + curr; acc += "/" + curr;
} }
return acc; return acc;
}, "/app/file/view"); }, "/desk/file/view");
return `<a href="${route}">${title}</a>`; return `<a href="${route}">${title}</a>`;
}) })
@ -391,7 +391,7 @@ frappe.views.FileView = class FileView extends frappe.views.ListView {
} }
get_route_url(file) { get_route_url(file) {
return file.is_folder ? "/app/List/File/" + file.name : this.get_form_link(file); return file.is_folder ? "/desk/List/File/" + file.name : this.get_form_link(file);
} }
get_creation_date(file) { get_creation_date(file) {

View file

@ -8,7 +8,7 @@
<div class="image-view-body"> <div class="image-view-body">
<a data-name="{{ data.name }}" <a data-name="{{ data.name }}"
title="{{ data.name }}" title="{{ data.name }}"
href="/app/Form/{{ data.doctype }}/{{ data.name }}" href="/desk/Form/{{ data.doctype }}/{{ data.name }}"
> >
<div class="image-field" <div class="image-field"
data-name="{{ data.name }}" data-name="{{ data.name }}"

View file

@ -304,7 +304,7 @@ frappe.views.KanbanView.get_kanbans = function (doctype) {
return get_kanban_boards().then((kanban_boards) => { return get_kanban_boards().then((kanban_boards) => {
if (kanban_boards) { if (kanban_boards) {
kanban_boards.forEach((board) => { kanban_boards.forEach((board) => {
let route = `/app/${frappe.router.slug(board.reference_doctype)}/view/kanban/${ let route = `/desk/${frappe.router.slug(board.reference_doctype)}/view/kanban/${
board.name board.name
}`; }`;
kanbans.push({ name: board.name, route: route }); kanbans.push({ name: board.name, route: route });

View file

@ -380,7 +380,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
frappe.xcall(method, { args: args }).then(() => { frappe.xcall(method, { args: args }).then(() => {
let message; let message;
if (dashboard_name) { if (dashboard_name) {
let dashboard_route_html = `<a href="/app/dashboard-view/${dashboard_name}">${dashboard_name}</a>`; let dashboard_route_html = `<a href="/desk/dashboard-view/${dashboard_name}">${dashboard_name}</a>`;
message = __("New {0} {1} added to Dashboard {2}", [ message = __("New {0} {1} added to Dashboard {2}", [
__(doctype), __(doctype),
name, name,
@ -870,7 +870,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
<span> <span>
${part1} ${part1}
${part2} ${part2}
<a href="/app/List/Prepared%20Report?report_name=${this.report_name}"> ${part3}</a> <a href="/desk/List/Prepared%20Report?report_name=${this.report_name}"> ${part3}</a>
</span> </span>
</div> </div>
`); `);
@ -960,7 +960,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
} }
get_queued_prepared_reports_warning_message(reports) { get_queued_prepared_reports_warning_message(reports) {
const route = `/app/List/Prepared Report/List?status=Queued&report_name=${this.report_name}`; const route = `/desk/List/Prepared Report/List?status=Queued&report_name=${this.report_name}`;
const report_link_html = const report_link_html =
reports.length == 1 reports.length == 1
? `<a class="underline" href="${route}">${__("1 Report")}</a>` ? `<a class="underline" href="${route}">${__("1 Report")}</a>`
@ -984,7 +984,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
</p>`; </p>`;
let get_item_html = (item) => let get_item_html = (item) =>
`<a class="underline" href="/app/prepared-report/${item.name}">${item.name}</a>`; `<a class="underline" href="/desk/prepared-report/${item.name}">${item.name}</a>`;
warning_message += reports.map(get_item_html).join(", "); warning_message += reports.map(get_item_html).join(", ");
@ -1020,7 +1020,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
// Rememeber the name of Prepared Report doc // Rememeber the name of Prepared Report doc
this.prepared_report_doc_name = data.name; this.prepared_report_doc_name = data.name;
let alert_message = let alert_message =
`<a href='/app/prepared-report/${data.name}'>` + `<a href='/desk/prepared-report/${data.name}'>` +
__("Report initiated, click to view status") + __("Report initiated, click to view status") +
`</a>`; `</a>`;
frappe.show_alert({ message: alert_message, indicator: "orange" }, 10); frappe.show_alert({ message: alert_message, indicator: "orange" }, 10);

View file

@ -103,7 +103,7 @@ export default class OnboardingWidget extends Widget {
"Watch Video": (step) => this.show_video(step), "Watch Video": (step) => this.show_video(step),
"Create Entry": (step) => { "Create Entry": (step) => {
if (step.is_complete) { if (step.is_complete) {
frappe.set_route(`/app/List/${step.reference_document}`); frappe.set_route(`/desk/List/${step.reference_document}`);
} else { } else {
if (step.show_full_form) { if (step.show_full_form) {
this.create_entry(step); this.create_entry(step);
@ -146,7 +146,7 @@ export default class OnboardingWidget extends Widget {
if (step.action === "Create Entry") { if (step.action === "Create Entry") {
// add a secondary action to view list // add a secondary action to view list
content += `<p> content += `<p>
<a href='/app/${frappe.router.slug(step.reference_document)}'> <a href='/desk/${frappe.router.slug(step.reference_document)}'>
${__("Show {0} List", [__(step.reference_document)])}</a> ${__("Show {0} List", [__(step.reference_document)])}</a>
</p>`; </p>`;
} }

View file

@ -127,8 +127,8 @@ export const useStore = defineStore("workflow-builder-store", () => {
function setup_breadcrumbs() { function setup_breadcrumbs() {
let breadcrumbs = ` let breadcrumbs = `
<li><a href="/app/workflow">${__("Workflow")}</a></li> <li><a href="/desk/workflow">${__("Workflow")}</a></li>
<li><a href="/app/workflow/${workflow_name.value}">${__(workflow_name.value)}</a></li> <li><a href="/desk/workflow/${workflow_name.value}">${__(workflow_name.value)}</a></li>
<li class="disabled"><a href="#">${__("Workflow Builder")}</a></li> <li class="disabled"><a href="#">${__("Workflow Builder")}</a></li>
`; `;
frappe.breadcrumbs.clear(); frappe.breadcrumbs.clear();

View file

@ -502,8 +502,8 @@ class TestResponse(FrappeAPITestCase):
def test_login_redirects(self): def test_login_redirects(self):
expected_redirects = { expected_redirects = {
"/app/user": "http://localhost/app/user", "/desk/user": "http://localhost/desk/user",
"/app/user?enabled=1": "http://localhost/app/user?enabled=1", "/desk/user?enabled=1": "http://localhost/desk/user?enabled=1",
"http://example.com": "http://localhost/desk", # No external redirect "http://example.com": "http://localhost/desk", # No external redirect
"https://google.com": "http://localhost/desk", "https://google.com": "http://localhost/desk",
"http://localhost:8000": "http://localhost/desk", "http://localhost:8000": "http://localhost/desk",

View file

@ -1252,8 +1252,8 @@ class TestMiscUtils(IntegrationTestCase):
self.assertGreaterEqual(len(info["users"]), 1) self.assertGreaterEqual(len(info["users"]), 1)
def test_get_url_to_form(self): def test_get_url_to_form(self):
self.assertTrue(get_url_to_form("System Settings").endswith("/app/system-settings")) self.assertTrue(get_url_to_form("System Settings").endswith("/desk/system-settings"))
self.assertTrue(get_url_to_form("User", "Test User").endswith("/app/user/Test%20User")) self.assertTrue(get_url_to_form("User", "Test User").endswith("/desk/user/Test%20User"))
def test_safe_json_load(self): def test_safe_json_load(self):
self.assertEqual(safe_json_loads("{}"), {}) self.assertEqual(safe_json_loads("{}"), {})

View file

@ -199,7 +199,7 @@ def import_doc(d, doctype, overwrite, row_idx, submit=False, ignore_links=False)
def getlink(doctype, name): def getlink(doctype, name):
return '<a href="/app/Form/{doctype}/{name}">{name}</a>'.format(**locals()) return '<a href="/desk/Form/{doctype}/{name}">{name}</a>'.format(**locals())
def get_csv_content_from_google_sheets(url): def get_csv_content_from_google_sheets(url):

View file

@ -1904,7 +1904,7 @@ def get_link_to_form(doctype: str, name: str | None = None, label: str | None =
"""Return the HTML link to the given document's form view. """Return the HTML link to the given document's form view.
e.g. get_link_to_form("Sales Invoice", "INV-0001", "Link Label") returns: e.g. get_link_to_form("Sales Invoice", "INV-0001", "Link Label") returns:
'<a href="https://frappe.io/app/sales-invoice/INV-0001">Link Label</a>'. '<a href="https://frappe.io/desk/sales-invoice/INV-0001">Link Label</a>'.
""" """
from frappe import _ from frappe import _
@ -1924,7 +1924,7 @@ def get_link_to_report(
"""Return the HTML link to the given report. """Return the HTML link to the given report.
e.g. get_link_to_report("Revenue Report", "Link Label") returns: e.g. get_link_to_report("Revenue Report", "Link Label") returns:
'<a href="https://frappe.io/app/query-report/Revenue%20Report">Link Label</a>'. '<a href="https://frappe.io/desk/query-report/Revenue%20Report">Link Label</a>'.
""" """
from frappe import _ from frappe import _
@ -1967,7 +1967,7 @@ def get_link_to_report(
def get_absolute_url(doctype: str, name: str) -> str: def get_absolute_url(doctype: str, name: str) -> str:
"""Return the absolute route for the form view of the given document in the desk. """Return the absolute route for the form view of the given document in the desk.
e.g. when doctype="Sales Invoice" and name="INV-00001", returns '/app/sales-invoice/INV-00001' e.g. when doctype="Sales Invoice" and name="INV-00001", returns '/desk/sales-invoice/INV-00001'
""" """
return f"/desk/{quoted(slug(doctype))}/{quoted(name)}" return f"/desk/{quoted(slug(doctype))}/{quoted(name)}"
@ -1976,7 +1976,7 @@ def get_url_to_form(doctype: str, name: str | None = None) -> str:
"""Return the absolute URL for the form view of the given document in the desk. """Return the absolute URL for the form view of the given document in the desk.
e.g. when doctype="Sales Invoice" and your site URL is "https://frappe.io", e.g. when doctype="Sales Invoice" and your site URL is "https://frappe.io",
returns 'https://frappe.io/app/sales-invoice/INV-00001' returns 'https://frappe.io/desk/sales-invoice/INV-00001'
""" """
if not name: if not name:
uri = f"/desk/{quoted(slug(doctype))}" uri = f"/desk/{quoted(slug(doctype))}"
@ -1990,7 +1990,7 @@ def get_url_to_list(doctype: str) -> str:
"""Return the absolute URL for the list view of the given document in the desk. """Return the absolute URL for the list view of the given document in the desk.
e.g. when doctype="Sales Invoice" and your site URL is "https://frappe.io", e.g. when doctype="Sales Invoice" and your site URL is "https://frappe.io",
returns 'https://frappe.io/app/sales-invoice' returns 'https://frappe.io/desk/sales-invoice'
""" """
return get_url(uri=f"/desk/{quoted(slug(doctype))}") return get_url(uri=f"/desk/{quoted(slug(doctype))}")
@ -1999,11 +1999,11 @@ def get_url_to_report(name, report_type: str | None = None, doctype: str | None
"""Return the absolute URL for the report in the desk. """Return the absolute URL for the report in the desk.
e.g. when name="Sales Register" and your site URL is "https://frappe.io", e.g. when name="Sales Register" and your site URL is "https://frappe.io",
returns 'https://frappe.io/app/query-report/Sales%20Register' returns 'https://frappe.io/desk/query-report/Sales%20Register'
You can optionally pass `report_type` and `doctype` to get the URL for a Report Builder report. You can optionally pass `report_type` and `doctype` to get the URL for a Report Builder report.
get_url_to_report("Revenue", "Report Builder", "Sales Invoice") -> 'https://frappe.io/app/sales-invoice/view/report/Revenue' get_url_to_report("Revenue", "Report Builder", "Sales Invoice") -> 'https://frappe.io/desk/sales-invoice/view/report/Revenue'
""" """
if report_type == "Report Builder": if report_type == "Report Builder":
return get_url(uri=f"/desk/{quoted(slug(doctype))}/view/report/{quoted(name)}") return get_url(uri=f"/desk/{quoted(slug(doctype))}/view/report/{quoted(name)}")

View file

@ -344,7 +344,7 @@ def redirect_post_login(desk_user: bool, redirect_to: str | None = None, provide
frappe.local.response["type"] = "redirect" frappe.local.response["type"] = "redirect"
if not redirect_to: if not redirect_to:
desk_uri = "/app/workspace" if provider == "facebook" else get_default_path() desk_uri = "/desk/workspace" if provider == "facebook" else get_default_path()
redirect_to = frappe.utils.get_url(desk_uri if desk_user else "/me") redirect_to = frappe.utils.get_url(desk_uri if desk_user else "/me")
frappe.local.response["location"] = redirect_to frappe.local.response["location"] = redirect_to

View file

@ -24,7 +24,7 @@ def authorize_access(reauthorize=False, code=None):
if not oauth_code or reauthorize: if not oauth_code or reauthorize:
return oauth_obj.get_authentication_url( return oauth_obj.get_authentication_url(
{ {
"redirect": f"/app/Form/{quote('Website Settings')}", "redirect": f"/desk/Form/{quote('Website Settings')}",
}, },
) )

View file

@ -280,7 +280,7 @@
}, },
{ {
"default": "0", "default": "0",
"description": "To use Google Indexing, enable <a href=\"/app/google-settings\">Google Settings</a>.", "description": "To use Google Indexing, enable <a href=\"/desk/google-settings\">Google Settings</a>.",
"fieldname": "enable_google_indexing", "fieldname": "enable_google_indexing",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Enable Google indexing" "label": "Enable Google indexing"

View file

@ -17,7 +17,7 @@ class NotPermittedPage(TemplatePage):
def render(self): def render(self):
action = f"/login?redirect-to={quote_plus(frappe.request.path)}" action = f"/login?redirect-to={quote_plus(frappe.request.path)}"
if frappe.request.path.startswith("/app/") or frappe.request.path == "/desk": if frappe.request.path.startswith("/desk/") or frappe.request.path == "/desk":
action = "/login" action = "/login"
frappe.local.message_title = _("Not Permitted") frappe.local.message_title = _("Not Permitted")
frappe.local.response["context"] = dict( frappe.local.response["context"] = dict(

View file

@ -7,7 +7,7 @@ frappe.ui.form.on("Workflow", {
refresh: function (frm) { refresh: function (frm) {
frm.layout.message.empty(); frm.layout.message.empty();
let title, note; let title, note;
let workflow_builder_url = "/app/workflow-builder"; let workflow_builder_url = "/desk/workflow-builder";
let msg = __( let msg = __(
"Workflow Builder allows you to create workflows visually. You can drag and drop states and link them to create transitions. Also you can update their properties from the sidebar." "Workflow Builder allows you to create workflows visually. You can drag and drop states and link them to create transitions. Also you can update their properties from the sidebar."
); );

View file

@ -34,7 +34,7 @@
</div> </div>
<script> <script>
frappe.ready(function() { frappe.ready(function() {
if (window.location.hash || window.location.href.includes('/app')) { if (window.location.hash || window.location.href.includes('/desk')) {
localStorage.setItem('session_last_route', window.location.pathname); localStorage.setItem('session_last_route', window.location.pathname);
} }