feat: configurable default views (#18409)
Co-authored-by: hrwx <himanshuwarekar@yahoo.com> Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
parent
cfbab92249
commit
b0c1e400ea
20 changed files with 673 additions and 92 deletions
|
|
@ -24,6 +24,7 @@ context("Folder Navigation", () => {
|
|||
|
||||
it("Navigating the nested folders, checking if the URL formed is correct, checking if the added content in the child folder is correct", () => {
|
||||
//Navigating inside the Attachments folder
|
||||
cy.wait(500);
|
||||
cy.get('[title="Attachments"] > span').click();
|
||||
|
||||
//To check if the URL formed after visiting the attachments folder is correct
|
||||
|
|
@ -36,6 +37,7 @@ context("Folder Navigation", () => {
|
|||
cy.click_modal_primary_button("Create");
|
||||
|
||||
//Navigating inside the added folder in the Attachments folder
|
||||
cy.wait(500);
|
||||
cy.get('[title="Test Folder"] > span').click();
|
||||
|
||||
//To check if the URL is correct after visiting the Test Folder
|
||||
|
|
@ -51,7 +53,12 @@ context("Folder Navigation", () => {
|
|||
cy.click_modal_primary_button("Upload");
|
||||
|
||||
//To check if the added file is present in the Test Folder
|
||||
cy.get("span.level-item > span").should("contain", "Test Folder");
|
||||
cy.visit("/app/file/view/home/Attachments");
|
||||
cy.wait(500);
|
||||
cy.get("span.level-item > a > span").should("contain", "Test Folder");
|
||||
cy.visit("/app/file/view/home/Attachments/Test%20Folder");
|
||||
|
||||
cy.wait(500);
|
||||
cy.get(".list-row-container").eq(0).should("contain.text", "72402.jpg");
|
||||
cy.get(".list-row-checkbox").eq(0).click();
|
||||
|
||||
|
|
|
|||
231
cypress/integration/view_routing.js
Normal file
231
cypress/integration/view_routing.js
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
context("View", () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit("/app/website");
|
||||
});
|
||||
|
||||
it("Route to ToDo List View", () => {
|
||||
cy.visit("/app/todo/view/list");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("List");
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to ToDo Report View", () => {
|
||||
cy.visit("/app/todo/view/report");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to ToDo Dashboard View", () => {
|
||||
cy.visit("/app/todo/view/dashboard");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Dashboard");
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to ToDo Gantt View", () => {
|
||||
cy.visit("/app/todo/view/gantt");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Gantt");
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to ToDo Kanban View", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.create_kanban").then(() => {
|
||||
cy.visit("/app/note/view/kanban/_Note _Kanban");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Kanban");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to ToDo Calendar View", () => {
|
||||
cy.visit("/app/todo/view/calendar");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Calendar");
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to Custom Tree View", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_tree_doctype").then(() => {
|
||||
cy.visit("/app/custom-tree/view/tree");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_tree")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Tree");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to Custom Image View", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_image_doctype").then(() => {
|
||||
cy.visit("app/custom-image/view/image");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Image");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to Communication Inbox View", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_inbox").then(() => {
|
||||
cy.visit("app/communication/view/inbox");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Inbox");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to File View", () => {
|
||||
cy.visit("app/file");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("File");
|
||||
expect(list.current_folder).to.equal("Home");
|
||||
});
|
||||
|
||||
cy.visit("app/file/view/home/Attachments");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("File");
|
||||
expect(list.current_folder).to.equal("Home/Attachments");
|
||||
});
|
||||
});
|
||||
|
||||
it("Re-route to default view", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", { view: "Report" }).then(() => {
|
||||
cy.visit("app/event");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to default view from app/{doctype}", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", { view: "Report" }).then(() => {
|
||||
cy.visit("/app/event");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to default view from app/{doctype}/view", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", { view: "Report" }).then(() => {
|
||||
cy.visit("/app/event/view");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Force Route to default view from app/{doctype}", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", {
|
||||
view: "Report",
|
||||
force_reroute: true,
|
||||
}).then(() => {
|
||||
cy.visit("/app/event");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Force Route to default view from app/{doctype}/view", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", {
|
||||
view: "Report",
|
||||
force_reroute: true,
|
||||
}).then(() => {
|
||||
cy.visit("/app/event/view");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Force Route to default view from app/{doctype}/view", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", {
|
||||
view: "Report",
|
||||
force_reroute: true,
|
||||
}).then(() => {
|
||||
cy.visit("/app/event/view/list");
|
||||
cy.wait(500);
|
||||
cy.window()
|
||||
.its("cur_list")
|
||||
.then((list) => {
|
||||
expect(list.view_name).to.equal("Report");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Validate Route History for Default View", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.setup_default_view", { view: "Report" }).then(() => {
|
||||
cy.visit("/app/event");
|
||||
cy.visit("/app/event/view/list");
|
||||
cy.location("pathname").should("eq", "/app/event/view/list");
|
||||
cy.go("back");
|
||||
cy.location("pathname").should("eq", "/app/event");
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to Form", () => {
|
||||
cy.call("frappe.tests.ui_test_helpers.create_note").then(() => {
|
||||
cy.visit("/app/note/Routing Test");
|
||||
cy.window()
|
||||
.its("cur_frm")
|
||||
.then((frm) => {
|
||||
expect(frm.doc.title).to.equal("Routing Test");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Route to Settings Workspace", () => {
|
||||
cy.visit("/app/settings");
|
||||
cy.get(".title-text").should("contain", "Settings");
|
||||
});
|
||||
});
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"creation": "2013-01-29 10:47:14",
|
||||
"default_view": "Inbox",
|
||||
"description": "Keeps track of all communications",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
|
|
@ -198,7 +199,6 @@
|
|||
"label": "More Information"
|
||||
},
|
||||
{
|
||||
"bold": 0,
|
||||
"default": "Now",
|
||||
"fieldname": "communication_date",
|
||||
"fieldtype": "Datetime",
|
||||
|
|
@ -395,7 +395,7 @@
|
|||
"icon": "fa fa-comment",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2022-03-30 11:24:25.728637",
|
||||
"modified": "2022-05-09 00:13:45.310564",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Communication",
|
||||
|
|
@ -454,8 +454,9 @@
|
|||
"sender_field": "sender",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"subject_field": "subject",
|
||||
"title_field": "subject",
|
||||
"track_changes": 1,
|
||||
"track_seen": 1
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ frappe.ui.form.on("DocType", {
|
|||
|
||||
if (frm.is_new()) {
|
||||
frm.events.set_default_permission(frm);
|
||||
frm.set_value("default_view", "List");
|
||||
} else {
|
||||
frm.toggle_enable("engine", 0);
|
||||
}
|
||||
|
|
@ -66,12 +67,14 @@ frappe.ui.form.on("DocType", {
|
|||
|
||||
frm.cscript.autoname(frm);
|
||||
frm.cscript.set_naming_rule_description(frm);
|
||||
frm.trigger("setup_default_views");
|
||||
},
|
||||
|
||||
istable: (frm) => {
|
||||
if (frm.doc.istable && frm.is_new()) {
|
||||
frm.set_value("autoname", "autoincrement");
|
||||
frm.set_value("allow_rename", 0);
|
||||
frm.set_value("default_view", null);
|
||||
} else if (!frm.doc.istable && !frm.is_new()) {
|
||||
frm.events.set_default_permission(frm);
|
||||
}
|
||||
|
|
@ -82,6 +85,18 @@ frappe.ui.form.on("DocType", {
|
|||
frm.add_child("permissions", { role: "System Manager" });
|
||||
}
|
||||
},
|
||||
|
||||
is_tree: (frm) => {
|
||||
frm.trigger("setup_default_views");
|
||||
},
|
||||
|
||||
is_calendar_and_gantt: (frm) => {
|
||||
frm.trigger("setup_default_views");
|
||||
},
|
||||
|
||||
setup_default_views: (frm) => {
|
||||
frappe.model.set_default_views_for_doctype(frm.doc.name, frm);
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("DocField", {
|
||||
|
|
@ -171,6 +186,10 @@ frappe.ui.form.on("DocField", {
|
|||
fieldtype: function (frm) {
|
||||
frm.trigger("max_attachments");
|
||||
},
|
||||
|
||||
fields_add: (frm) => {
|
||||
frm.trigger("setup_default_views");
|
||||
},
|
||||
});
|
||||
|
||||
extend_cscript(cur_frm.cscript, new frappe.model.DocTypeController({ frm: cur_frm }));
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"istable",
|
||||
"issingle",
|
||||
"is_tree",
|
||||
"is_calendar_and_gantt",
|
||||
"editable_grid",
|
||||
"quick_entry",
|
||||
"cb01",
|
||||
|
|
@ -53,6 +54,8 @@
|
|||
"default_print_format",
|
||||
"sort_field",
|
||||
"sort_order",
|
||||
"default_view",
|
||||
"force_re_route_to_default_view",
|
||||
"column_break_29",
|
||||
"document_type",
|
||||
"icon",
|
||||
|
|
@ -606,6 +609,24 @@
|
|||
"fieldname": "make_attachments_public",
|
||||
"fieldtype": "Check",
|
||||
"label": "Make Attachments Public by Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_view",
|
||||
"fieldtype": "Select",
|
||||
"label": "Default View"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "force_re_route_to_default_view",
|
||||
"fieldtype": "Check",
|
||||
"label": "Force Re-route to Default View"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Enables Calendar and Gantt views.",
|
||||
"fieldname": "is_calendar_and_gantt",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Calendar and Gantt"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-bolt",
|
||||
|
|
@ -688,7 +709,7 @@
|
|||
"link_fieldname": "reference_doctype"
|
||||
}
|
||||
],
|
||||
"modified": "2022-09-02 12:05:59.589751",
|
||||
"modified": "2022-10-12 14:13:27.315351",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocType",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"creation": "2012-12-12 11:19:22",
|
||||
"default_view": "File",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
|
|
@ -169,10 +170,11 @@
|
|||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"force_re_route_to_default_view": 1,
|
||||
"icon": "fa fa-file",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2022-09-13 15:50:15.508250",
|
||||
"modified": "2022-09-13 15:50:15.508251",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "File",
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ frappe.ui.form.on("Customize Form", {
|
|||
} else {
|
||||
frm.refresh();
|
||||
frm.trigger("setup_sortable");
|
||||
frm.trigger("setup_default_views");
|
||||
}
|
||||
}
|
||||
localStorage["customize_doctype"] = frm.doc.doc_type;
|
||||
|
|
@ -82,8 +83,12 @@ frappe.ui.form.on("Customize Form", {
|
|||
}
|
||||
},
|
||||
|
||||
is_calendar_and_gantt: function (frm) {
|
||||
frm.trigger("setup_default_views");
|
||||
},
|
||||
|
||||
setup_sortable: function (frm) {
|
||||
frm.doc.fields.forEach(function (f, i) {
|
||||
frm.doc.fields.forEach(function (f) {
|
||||
if (!f.is_custom_field) {
|
||||
f._sortable = false;
|
||||
}
|
||||
|
|
@ -222,6 +227,10 @@ frappe.ui.form.on("Customize Form", {
|
|||
frm.set_df_property("sort_field", "options", fields);
|
||||
}
|
||||
},
|
||||
|
||||
setup_default_views(frm) {
|
||||
frappe.model.set_default_views_for_doctype(frm.doc.doc_type, frm);
|
||||
},
|
||||
});
|
||||
|
||||
// can't delete standard fields
|
||||
|
|
@ -237,6 +246,7 @@ frappe.ui.form.on("Customize Form Field", {
|
|||
var f = frappe.model.get_doc(cdt, cdn);
|
||||
f.is_system_generated = false;
|
||||
f.is_custom_field = true;
|
||||
frm.trigger("setup_default_views");
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
"search_fields",
|
||||
"column_break_5",
|
||||
"istable",
|
||||
"is_calendar_and_gantt",
|
||||
"editable_grid",
|
||||
"quick_entry",
|
||||
"track_changes",
|
||||
|
|
@ -35,6 +36,8 @@
|
|||
"show_title_field_in_link",
|
||||
"translated_doctype",
|
||||
"default_print_format",
|
||||
"default_view",
|
||||
"force_re_route_to_default_view",
|
||||
"column_break_29",
|
||||
"show_preview_popup",
|
||||
"email_settings_section",
|
||||
|
|
@ -337,6 +340,25 @@
|
|||
"fieldname": "make_attachments_public",
|
||||
"fieldtype": "Check",
|
||||
"label": "Make Attachments Public by Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_view",
|
||||
"fieldtype": "Select",
|
||||
"label": "Default View"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "default_view",
|
||||
"fieldname": "force_re_route_to_default_view",
|
||||
"fieldtype": "Check",
|
||||
"label": "Force Re-route to Default View"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Enables Calendar and Gantt views.",
|
||||
"fieldname": "is_calendar_and_gantt",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Calendar and Gantt"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
|
|
@ -345,7 +367,7 @@
|
|||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2022-08-24 06:57:47.966331",
|
||||
"modified": "2022-08-30 11:45:16.772277",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Custom",
|
||||
"name": "Customize Form",
|
||||
|
|
|
|||
|
|
@ -586,6 +586,10 @@ doctype_properties = {
|
|||
"naming_rule": "Data",
|
||||
"autoname": "Data",
|
||||
"show_title_field_in_link": "Check",
|
||||
"translate_link_fields": "Check",
|
||||
"is_calendar_and_gantt": "Check",
|
||||
"default_view": "Select",
|
||||
"force_re_route_to_default_view": "Check",
|
||||
"translated_doctype": "Check",
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ frappe.views.BaseList = class BaseList {
|
|||
Map: "map",
|
||||
};
|
||||
|
||||
if (frappe.boot.desk_settings.view_switcher) {
|
||||
if (frappe.boot.desk_settings.view_switcher && !this.meta.force_re_route_to_default_view) {
|
||||
/* @preserve
|
||||
for translation, don't remove
|
||||
__("List View") __("Report View") __("Dashboard View") __("Gantt View"),
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ $.extend(frappe.model, {
|
|||
|
||||
is_tree: function (doctype) {
|
||||
if (!doctype) return false;
|
||||
return frappe.boot.treeviews.indexOf(doctype) != -1;
|
||||
return locals.DocType[doctype] && locals.DocType[doctype].is_tree;
|
||||
},
|
||||
|
||||
is_fresh(doc) {
|
||||
|
|
@ -754,6 +754,42 @@ $.extend(frappe.model, {
|
|||
}
|
||||
return frappe.model.numeric_fieldtypes.includes(fieldtype);
|
||||
},
|
||||
|
||||
set_default_views_for_doctype(doctype, frm) {
|
||||
frappe.model.with_doctype(doctype, () => {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
let default_views = ["List", "Report", "Dashboard", "Kanban"];
|
||||
|
||||
if (meta.is_calendar_and_gantt && frappe.views.calendar[doctype]) {
|
||||
let views = ["Calendar", "Gantt"];
|
||||
default_views.push(...views);
|
||||
}
|
||||
|
||||
if (meta.is_tree) {
|
||||
default_views.push("Tree");
|
||||
}
|
||||
|
||||
if (frm.doc.image_field) {
|
||||
default_views.push("Image");
|
||||
}
|
||||
|
||||
if (doctype === "Communication" && frappe.boot.email_accounts.length) {
|
||||
default_views.push("Inbox");
|
||||
}
|
||||
|
||||
if (
|
||||
(frm.doc.fields.find((i) => i.fieldname === "latitude") &&
|
||||
frm.doc.fields.find((i) => i.fieldname === "longitude")) ||
|
||||
frm.doc.fields.find(
|
||||
(i) => i.fieldname === "location" && i.fieldtype == "Geolocation"
|
||||
)
|
||||
) {
|
||||
default_views.push("Map");
|
||||
}
|
||||
|
||||
frm.set_df_property("default_view", "options", default_views);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// legacy
|
||||
|
|
|
|||
|
|
@ -89,6 +89,18 @@ frappe.router = {
|
|||
"image",
|
||||
"inbox",
|
||||
],
|
||||
list_views_route: {
|
||||
list: "List",
|
||||
kanban: "Kanban",
|
||||
report: "Report",
|
||||
calendar: "Calendar",
|
||||
tree: "Tree",
|
||||
gantt: "Gantt",
|
||||
dashboard: "Dashboard",
|
||||
image: "Image",
|
||||
inbox: "Inbox",
|
||||
file: "Home",
|
||||
},
|
||||
layout_mapped: {},
|
||||
|
||||
is_app_route(path) {
|
||||
|
|
@ -115,7 +127,7 @@ frappe.router = {
|
|||
}
|
||||
},
|
||||
|
||||
route() {
|
||||
async route() {
|
||||
// resolve the route from the URL or hash
|
||||
// translate it so the objects are well defined
|
||||
// and render the page as required
|
||||
|
|
@ -126,22 +138,22 @@ frappe.router = {
|
|||
if (this.re_route(sub_path)) return;
|
||||
|
||||
this.current_sub_path = sub_path;
|
||||
this.current_route = this.parse();
|
||||
this.current_route = await this.parse();
|
||||
this.set_history(sub_path);
|
||||
this.render();
|
||||
this.set_title(sub_path);
|
||||
this.trigger("change");
|
||||
},
|
||||
|
||||
parse(route) {
|
||||
async parse(route) {
|
||||
route = this.get_sub_path_string(route).split("/");
|
||||
if (!route) return [];
|
||||
route = $.map(route, this.decode_component);
|
||||
this.set_route_options_from_url();
|
||||
return this.convert_to_standard_route(route);
|
||||
return await this.convert_to_standard_route(route);
|
||||
},
|
||||
|
||||
convert_to_standard_route(route) {
|
||||
async convert_to_standard_route(route) {
|
||||
// /app/settings = ["Workspaces", "Settings"]
|
||||
// /app/private/settings = ["Workspaces", "private", "Settings"]
|
||||
// /app/user = ["List", "User"]
|
||||
|
|
@ -161,7 +173,7 @@ frappe.router = {
|
|||
route = ["Workspaces", "private", frappe.workspaces[private_workspace].title];
|
||||
} else if (this.routes[route[0]]) {
|
||||
// route
|
||||
route = this.set_doctype_route(route);
|
||||
route = await this.set_doctype_route(route);
|
||||
}
|
||||
|
||||
return route;
|
||||
|
|
@ -174,36 +186,85 @@ frappe.router = {
|
|||
|
||||
set_doctype_route(route) {
|
||||
let doctype_route = this.routes[route[0]];
|
||||
// doctype route
|
||||
if (route[1]) {
|
||||
if (route[2] && route[1] === "view") {
|
||||
route = this.get_standard_route_for_list(route, doctype_route);
|
||||
} else {
|
||||
|
||||
return frappe.model.with_doctype(doctype_route.doctype).then(() => {
|
||||
// doctype route
|
||||
let meta = frappe.get_meta(doctype_route.doctype);
|
||||
|
||||
if (route[1] && route[1] === "view" && route[2]) {
|
||||
route = this.get_standard_route_for_list(
|
||||
route,
|
||||
doctype_route,
|
||||
meta.force_re_route_to_default_view && meta.default_view
|
||||
? meta.default_view
|
||||
: null
|
||||
);
|
||||
} else if (route[1] && route[1] !== "view" && !route[2]) {
|
||||
let docname = route[1];
|
||||
if (route.length > 2) {
|
||||
docname = route.slice(1).join("/");
|
||||
}
|
||||
route = ["Form", doctype_route.doctype, docname];
|
||||
} else if (frappe.model.is_single(doctype_route.doctype)) {
|
||||
route = ["Form", doctype_route.doctype, doctype_route.doctype];
|
||||
} else if (meta.default_view) {
|
||||
route = [
|
||||
"List",
|
||||
doctype_route.doctype,
|
||||
this.list_views_route[meta.default_view.toLowerCase()],
|
||||
];
|
||||
} else {
|
||||
route = ["List", doctype_route.doctype, "List"];
|
||||
}
|
||||
} else if (frappe.model.is_single(doctype_route.doctype)) {
|
||||
route = ["Form", doctype_route.doctype, doctype_route.doctype];
|
||||
} else {
|
||||
route = ["List", doctype_route.doctype, "List"];
|
||||
}
|
||||
// reset the layout to avoid using incorrect views
|
||||
this.doctype_layout = doctype_route.doctype_layout;
|
||||
return route;
|
||||
// reset the layout to avoid using incorrect views
|
||||
this.doctype_layout = doctype_route.doctype_layout;
|
||||
return route;
|
||||
});
|
||||
},
|
||||
|
||||
get_standard_route_for_list(route, doctype_route) {
|
||||
get_standard_route_for_list(route, doctype_route, default_view) {
|
||||
let standard_route;
|
||||
if (route[2].toLowerCase() === "tree") {
|
||||
let _route = default_view || route[2] || "";
|
||||
|
||||
if (_route.toLowerCase() === "tree") {
|
||||
standard_route = ["Tree", doctype_route.doctype];
|
||||
} else {
|
||||
standard_route = ["List", doctype_route.doctype, frappe.utils.to_title_case(route[2])];
|
||||
let new_route = this.list_views_route[_route.toLowerCase()];
|
||||
let re_route = route[2].toLowerCase() !== new_route.toLowerCase();
|
||||
|
||||
if (re_route) {
|
||||
/**
|
||||
* In case of force_re_route, the url of the route should change,
|
||||
* if the _route and route[2] are different, it means there is a default_view
|
||||
* with force_re_route enabled.
|
||||
*
|
||||
* To change the url, to the correct view, the route[2] is changed with default_view
|
||||
*
|
||||
* Eg: If default_view is set to Report with force_re_route enabled and user routes
|
||||
* to List,
|
||||
* route: [todo, view, list]
|
||||
* default_view: report
|
||||
*
|
||||
* replaces the list to report and re-routes to the new route but should be replaced in
|
||||
* the history since the list route should not exist in history as we are rerouting it to
|
||||
* report
|
||||
*/
|
||||
frappe.route_flags.replace_route = true;
|
||||
|
||||
route[2] = _route.toLowerCase();
|
||||
this.set_route(route);
|
||||
}
|
||||
|
||||
standard_route = [
|
||||
"List",
|
||||
doctype_route.doctype,
|
||||
this.list_views_route[_route.toLowerCase()],
|
||||
];
|
||||
|
||||
// calendar / kanban / dashboard / folder
|
||||
if (route[3]) standard_route.push(...route.slice(3, route.length));
|
||||
}
|
||||
|
||||
return standard_route;
|
||||
},
|
||||
|
||||
|
|
@ -345,6 +406,7 @@ frappe.router = {
|
|||
} else if (view === "tree") {
|
||||
new_route = [this.slug(route[1]), "view", "tree"];
|
||||
}
|
||||
|
||||
return new_route;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -208,13 +208,10 @@ frappe.search.utils = {
|
|||
},
|
||||
});
|
||||
}
|
||||
if (in_list(frappe.boot.treeviews, item)) {
|
||||
out.push(option("Tree", ["Tree", item], 0.05));
|
||||
} else {
|
||||
out.push(option("List", ["List", item], 0.05));
|
||||
if (frappe.model.can_get_report(item)) {
|
||||
out.push(option("Report", ["List", item, "Report"], 0.04));
|
||||
}
|
||||
|
||||
out.push(option("List", ["List", item], 0.05));
|
||||
if (frappe.model.can_get_report(item)) {
|
||||
out.push(option("Report", ["List", item, "Report"], 0.04));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1260,20 +1260,12 @@ Object.assign(frappe.utils, {
|
|||
if (frappe.model.is_single(item.doctype)) {
|
||||
route = doctype_slug;
|
||||
} else {
|
||||
if (!item.doc_view) {
|
||||
if (frappe.model.is_tree(item.doctype)) {
|
||||
item.doc_view = "Tree";
|
||||
} else {
|
||||
item.doc_view = "List";
|
||||
}
|
||||
}
|
||||
|
||||
switch (item.doc_view) {
|
||||
case "List":
|
||||
if (item.filters) {
|
||||
frappe.route_options = item.filters;
|
||||
}
|
||||
route = doctype_slug;
|
||||
route = `${doctype_slug}/view/list`;
|
||||
break;
|
||||
case "Tree":
|
||||
route = `${doctype_slug}/view/tree`;
|
||||
|
|
@ -1290,12 +1282,11 @@ Object.assign(frappe.utils, {
|
|||
case "Calendar":
|
||||
route = `${doctype_slug}/view/calendar/default`;
|
||||
break;
|
||||
case "Kanban":
|
||||
route = `${doctype_slug}/view/kanban`;
|
||||
break;
|
||||
default:
|
||||
frappe.throw({
|
||||
message: __("Not a valid view:") + item.doc_view,
|
||||
title: __("Unknown View"),
|
||||
});
|
||||
route = "";
|
||||
route = doctype_slug;
|
||||
}
|
||||
}
|
||||
} else if (type === "report") {
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ frappe.breadcrumbs = {
|
|||
} else {
|
||||
let route;
|
||||
const doctype_route = frappe.router.slug(frappe.router.doctype_layout || doctype);
|
||||
if (frappe.boot.treeviews.indexOf(doctype) !== -1) {
|
||||
if (doctype_meta.is_tree) {
|
||||
let view = frappe.model.user_settings[doctype].last_view || "Tree";
|
||||
route = `${doctype_route}/view/${view}`;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ frappe.views.FileView = class FileView extends frappe.views.ListView {
|
|||
this.page_title = __("File Manager");
|
||||
|
||||
const route = frappe.get_route();
|
||||
this.current_folder = route.slice(2).join("/");
|
||||
this.current_folder = route.slice(2).join("/") || "Home";
|
||||
this.filters = [["File", "folder", "=", this.current_folder, true]];
|
||||
this.order_by = this.view_user_settings.order_by || "file_name asc";
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ frappe.views.FileView = class FileView extends frappe.views.ListView {
|
|||
}
|
||||
|
||||
get_breadcrumbs_html() {
|
||||
const route = frappe.router.parse();
|
||||
const route = frappe.get_route();
|
||||
const folders = route.slice(2);
|
||||
|
||||
return folders
|
||||
|
|
|
|||
|
|
@ -9,14 +9,9 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView {
|
|||
const doctype = route[1];
|
||||
const user_settings = frappe.get_user_settings(doctype)["Kanban"] || {};
|
||||
if (!user_settings.last_kanban_board) {
|
||||
frappe.msgprint({
|
||||
title: __("Error"),
|
||||
indicator: "red",
|
||||
message: __("Missing parameter Kanban Board Name"),
|
||||
});
|
||||
frappe.set_route("List", doctype, "List");
|
||||
return true;
|
||||
return new frappe.views.KanbanView({ doctype: doctype });
|
||||
}
|
||||
|
||||
route.push(user_settings.last_kanban_board);
|
||||
frappe.set_route(route);
|
||||
return true;
|
||||
|
|
@ -28,9 +23,35 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView {
|
|||
return "Kanban";
|
||||
}
|
||||
|
||||
show() {
|
||||
frappe.views.KanbanView.get_kanbans(this.doctype).then((kanbans) => {
|
||||
if (!kanbans.length) {
|
||||
return frappe.views.KanbanView.show_kanban_dialog(this.doctype, true);
|
||||
} else if (kanbans.length && frappe.get_route().length !== 4) {
|
||||
return frappe.views.KanbanView.show_kanban_dialog(this.doctype, true);
|
||||
} else {
|
||||
this.kanbans = kanbans;
|
||||
|
||||
return frappe.run_serially([
|
||||
() => this.show_skeleton(),
|
||||
() => this.fetch_meta(),
|
||||
() => this.hide_skeleton(),
|
||||
() => this.check_permissions(),
|
||||
() => this.init(),
|
||||
() => this.before_refresh(),
|
||||
() => this.refresh(),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
return super.setup_defaults().then(() => {
|
||||
this.board_name = frappe.get_route()[3];
|
||||
let get_board_name = () => {
|
||||
return this.kanbans.length && this.kanbans[0].name;
|
||||
};
|
||||
|
||||
this.board_name = frappe.get_route()[3] || get_board_name() || null;
|
||||
this.page_title = __(this.board_name);
|
||||
this.card_meta = this.get_card_meta();
|
||||
this.page_length = 0;
|
||||
|
|
@ -143,21 +164,22 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView {
|
|||
|
||||
render() {
|
||||
const board_name = this.board_name;
|
||||
if (this.kanban && board_name === this.kanban.board_name) {
|
||||
this.kanban.update(this.data);
|
||||
return;
|
||||
if (!this.kanban) {
|
||||
this.kanban = new frappe.views.KanbanBoard({
|
||||
doctype: this.doctype,
|
||||
board: this.board,
|
||||
board_name: board_name,
|
||||
cards: this.data,
|
||||
card_meta: this.card_meta,
|
||||
wrapper: this.$result,
|
||||
cur_list: this,
|
||||
user_settings: this.view_user_settings,
|
||||
});
|
||||
}
|
||||
|
||||
this.kanban = new frappe.views.KanbanBoard({
|
||||
doctype: this.doctype,
|
||||
board: this.board,
|
||||
board_name: board_name,
|
||||
cards: this.data,
|
||||
card_meta: this.card_meta,
|
||||
wrapper: this.$result,
|
||||
cur_list: this,
|
||||
user_settings: this.view_user_settings,
|
||||
});
|
||||
if (this.kanban && board_name === this.kanban.board_name) {
|
||||
this.kanban.update(this.data);
|
||||
}
|
||||
}
|
||||
|
||||
get_card_meta() {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ frappe.views.TreeFactory = class TreeFactory extends frappe.views.Factory {
|
|||
let treeview = frappe.views.trees[route[1]];
|
||||
treeview && treeview.make_tree();
|
||||
}
|
||||
|
||||
get view_name() {
|
||||
return "Tree";
|
||||
}
|
||||
};
|
||||
|
||||
frappe.views.TreeView = class TreeView {
|
||||
|
|
@ -196,6 +200,7 @@ frappe.views.TreeView = class TreeView {
|
|||
});
|
||||
|
||||
cur_tree = this.tree;
|
||||
cur_tree.view_name = "Tree";
|
||||
this.post_render();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -384,18 +384,22 @@ class ShortcutDialog extends WidgetDialog {
|
|||
onchange: () => {
|
||||
if (this.dialog.get_value("type") == "DocType") {
|
||||
let doctype = this.dialog.get_value("link_to");
|
||||
if (doctype && frappe.boot.single_types.includes(doctype)) {
|
||||
this.hide_filters();
|
||||
} else if (doctype) {
|
||||
this.setup_filter(doctype);
|
||||
this.show_filters();
|
||||
}
|
||||
frappe.model.with_doctype(doctype, () => {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
|
||||
const views = ["List", "Report Builder", "Dashboard", "New"];
|
||||
if (frappe.boot.treeviews.includes(doctype)) views.push("Tree");
|
||||
if (frappe.boot.calendars.includes(doctype)) views.push("Calendar");
|
||||
if (doctype && frappe.boot.single_types.includes(doctype)) {
|
||||
this.hide_filters();
|
||||
} else if (doctype) {
|
||||
this.setup_filter(doctype);
|
||||
this.show_filters();
|
||||
}
|
||||
|
||||
this.dialog.set_df_property("doc_view", "options", views.join("\n"));
|
||||
const views = ["List", "Report Builder", "Dashboard", "New"];
|
||||
if (meta.is_tree === "Tree") views.push("Tree");
|
||||
if (frappe.boot.calendars.includes(doctype)) views.push("Calendar");
|
||||
|
||||
this.dialog.set_df_property("doc_view", "options", views.join("\n"));
|
||||
});
|
||||
} else {
|
||||
this.hide_filters();
|
||||
}
|
||||
|
|
@ -405,7 +409,7 @@ class ShortcutDialog extends WidgetDialog {
|
|||
fieldtype: "Select",
|
||||
fieldname: "doc_view",
|
||||
label: "DocType View",
|
||||
options: "List\nReport Builder\nDashboard\nTree\nNew\nCalendar",
|
||||
options: "List\nReport Builder\nDashboard\nTree\nNew\nCalendar\nKanban",
|
||||
description: __(
|
||||
"Which view of the associated DocType should this shortcut take you to?"
|
||||
),
|
||||
|
|
|
|||
|
|
@ -43,16 +43,32 @@ def create_todo_records():
|
|||
frappe.db.truncate("ToDo")
|
||||
|
||||
frappe.get_doc(
|
||||
{"doctype": "ToDo", "date": add_to_date(now(), days=7), "description": "this is first todo"}
|
||||
{
|
||||
"doctype": "ToDo",
|
||||
"date": add_to_date(now(), days=7),
|
||||
"description": "this is first todo",
|
||||
}
|
||||
).insert()
|
||||
frappe.get_doc(
|
||||
{"doctype": "ToDo", "date": add_to_date(now(), days=-7), "description": "this is second todo"}
|
||||
{
|
||||
"doctype": "ToDo",
|
||||
"date": add_to_date(now(), days=-7),
|
||||
"description": "this is second todo",
|
||||
}
|
||||
).insert()
|
||||
frappe.get_doc(
|
||||
{"doctype": "ToDo", "date": add_to_date(now(), months=2), "description": "this is third todo"}
|
||||
{
|
||||
"doctype": "ToDo",
|
||||
"date": add_to_date(now(), months=2),
|
||||
"description": "this is third todo",
|
||||
}
|
||||
).insert()
|
||||
frappe.get_doc(
|
||||
{"doctype": "ToDo", "date": add_to_date(now(), months=-2), "description": "this is fourth todo"}
|
||||
{
|
||||
"doctype": "ToDo",
|
||||
"date": add_to_date(now(), months=-2),
|
||||
"description": "this is fourth todo",
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
|
|
@ -431,3 +447,134 @@ def create_test_user():
|
|||
user.append("roles", {"role": role})
|
||||
|
||||
user.save()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def setup_tree_doctype():
|
||||
frappe.delete_doc_if_exists("DocType", "Custom Tree")
|
||||
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"module": "Core",
|
||||
"custom": 1,
|
||||
"fields": [
|
||||
{"fieldname": "tree", "fieldtype": "Data", "label": "Tree"},
|
||||
],
|
||||
"permissions": [{"role": "System Manager", "read": 1}],
|
||||
"name": "Custom Tree",
|
||||
"is_tree": True,
|
||||
"naming_rule": "By fieldname",
|
||||
"autoname": "field:tree",
|
||||
}
|
||||
).insert()
|
||||
|
||||
if not frappe.db.exists("Custom Tree", "All Trees"):
|
||||
frappe.get_doc({"doctype": "Custom Tree", "tree": "All Trees"}).insert()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def setup_image_doctype():
|
||||
frappe.delete_doc_if_exists("DocType", "Custom Image")
|
||||
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"module": "Core",
|
||||
"custom": 1,
|
||||
"fields": [
|
||||
{"fieldname": "image", "fieldtype": "Attach Image", "label": "Image"},
|
||||
],
|
||||
"permissions": [{"role": "System Manager", "read": 1}],
|
||||
"name": "Custom Image",
|
||||
"image_field": "image",
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def setup_inbox():
|
||||
frappe.db.sql("DELETE FROM `tabUser Email`")
|
||||
|
||||
user = frappe.get_doc("User", frappe.session.user)
|
||||
user.append("user_emails", {"email_account": "Email Linking"})
|
||||
user.save()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def setup_default_view(view, force_reroute=None):
|
||||
frappe.delete_doc_if_exists("Property Setter", "Event-main-default_view")
|
||||
frappe.delete_doc_if_exists("Property Setter", "Event-main-force_re_route_to_default_view")
|
||||
|
||||
frappe.get_doc(
|
||||
{
|
||||
"is_system_generated": 0,
|
||||
"doctype_or_field": "DocType",
|
||||
"doc_type": "Event",
|
||||
"property": "default_view",
|
||||
"property_type": "Select",
|
||||
"value": view,
|
||||
"doctype": "Property Setter",
|
||||
}
|
||||
).insert()
|
||||
|
||||
if force_reroute:
|
||||
frappe.get_doc(
|
||||
{
|
||||
"is_system_generated": 0,
|
||||
"doctype_or_field": "DocType",
|
||||
"doc_type": "Event",
|
||||
"property": "force_re_route_to_default_view",
|
||||
"property_type": "Check",
|
||||
"value": "1",
|
||||
"doctype": "Property Setter",
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_note():
|
||||
if not frappe.db.exists("Note", "Routing Test"):
|
||||
frappe.get_doc({"doctype": "Note", "title": "Routing Test"}).insert()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_kanban():
|
||||
if not frappe.db.exists("Custom Field", "Note-kanban"):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"is_system_generated": 0,
|
||||
"dt": "Note",
|
||||
"label": "Kanban",
|
||||
"fieldname": "kanban",
|
||||
"insert_after": "seen_by",
|
||||
"fieldtype": "Select",
|
||||
"options": "Open\nClosed",
|
||||
"doctype": "Custom Field",
|
||||
}
|
||||
).insert()
|
||||
|
||||
if not frappe.db.exists("Kanban Board", "_Note _Kanban"):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Kanban Board",
|
||||
"name": "_Note _Kanban",
|
||||
"kanban_board_name": "_Note _Kanban",
|
||||
"reference_doctype": "Note",
|
||||
"field_name": "kanban",
|
||||
"private": 1,
|
||||
"show_labels": 0,
|
||||
"columns": [
|
||||
{
|
||||
"column_name": "Open",
|
||||
"status": "Active",
|
||||
"indicator": "Gray",
|
||||
},
|
||||
{
|
||||
"column_name": "Closed",
|
||||
"status": "Active",
|
||||
"indicator": "Gray",
|
||||
},
|
||||
],
|
||||
}
|
||||
).insert()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue