From 7f9a7af50c1116439f49e29ef9f7f74c9570931f Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 16 Sep 2021 10:14:33 +0530 Subject: [PATCH] fix: Remove hardcoded tabs and make it configurable --- frappe/public/js/frappe/form/column.js | 24 +++++--- frappe/public/js/frappe/form/dashboard.js | 44 ++++----------- frappe/public/js/frappe/form/form.js | 10 ++-- frappe/public/js/frappe/form/layout.js | 68 +++++++++++------------ frappe/public/js/frappe/form/section.js | 46 ++++++--------- frappe/public/js/frappe/form/tab.js | 49 ++++++++-------- 6 files changed, 107 insertions(+), 134 deletions(-) diff --git a/frappe/public/js/frappe/form/column.js b/frappe/public/js/frappe/form/column.js index 98ca28b9f5..27231da7e5 100644 --- a/frappe/public/js/frappe/form/column.js +++ b/frappe/public/js/frappe/form/column.js @@ -9,19 +9,25 @@ export default class Column { } make() { - this.wrapper = $(`
-
-
-
`).appendTo(this.section.body) + this.wrapper = $(` +
+
+
+
+ `) + .appendTo(this.section.body) .find("form") .on("submit", function () { return false; }); if (this.df.label) { - $(``).appendTo(this.wrapper); + $(` + + `) + .appendTo(this.wrapper); } } @@ -29,7 +35,9 @@ export default class Column { // distribute all columns equally let colspan = cint(12 / this.section.wrapper.find(".form-column").length); - this.section.wrapper.find(".form-column").removeClass() + this.section.wrapper + .find(".form-column") + .removeClass() .addClass("form-column") .addClass("col-sm-" + colspan); diff --git a/frappe/public/js/frappe/form/dashboard.js b/frappe/public/js/frappe/form/dashboard.js index 8197e73b68..5626434651 100644 --- a/frappe/public/js/frappe/form/dashboard.js +++ b/frappe/public/js/frappe/form/dashboard.js @@ -2,35 +2,22 @@ // MIT License. See license.txt import Section from "./section.js"; -import Tab from "./tab.js"; frappe.ui.form.Dashboard = class FormDashboard { constructor(opts) { $.extend(this, opts); - this.setup_dashboard_tabs(); + let parent = this.tab ? this.tab.wrapper : this.frm.layout.wrapper; + this.parent = $('
'); + parent.prepend(this.parent); this.setup_dashboard_sections(); } - setup_dashboard_tabs() { - this.overview_tab = new Tab(this.frm.layout, { - label: __("Overview"), - hidden: 1, - fieldname: 'dashboard-overview' - }); - - this.connections_tab = new Tab(this.frm.layout, { - label: __("Connections"), - hidden: 1, - fieldname: 'dashboard-connection' - }); - } - setup_dashboard_sections() { this.progress_area = this.make_section({ css_class: 'progress-area', hidden: 1, is_dashboard_section: 1, - }, this.overview_tab); + }); this.heatmap_area = this.make_section({ label: __("Overview"), @@ -41,14 +28,14 @@ frappe.ui.form.Dashboard = class FormDashboard {
` - }, this.overview_tab); + }); this.chart_area = this.make_section({ label: __("Graph"), css_class: 'form-graph', hidden: 1, is_dashboard_section: 1 - }, this.overview_tab); + }); this.stats_area_row = $(`
`); this.stats_area = this.make_section({ @@ -57,7 +44,7 @@ frappe.ui.form.Dashboard = class FormDashboard { hidden: 1, is_dashboard_section: 1, body_html: this.stats_area_row - }, this.overview_tab); + }); this.transactions_area = $(`
').appendTo(this.layout_main); - this.body = $('
').appendTo(this.form_wrapper); + this.form_wrapper = $('
').appendTo(this.layout_main); + this.body = $('
').appendTo(this.form_wrapper); // only tray this.meta.section_style='Simple'; // always simple! @@ -146,9 +146,9 @@ frappe.ui.form.Form = class FrappeForm { doctype_layout: this.doctype_layout, frm: this, with_dashboard: true, - card_layout: true, - tabbed_layout: true, + card_layout: true }); + this.layout.make(); this.fields_dict = this.layout.fields_dict; @@ -156,7 +156,7 @@ frappe.ui.form.Form = class FrappeForm { this.dashboard = new frappe.ui.form.Dashboard({ frm: this, - parent: this.layout.wrapper, + tab: this.layout.tabs.length ? this.layout.tabs[0] : null }); this.tour = new frappe.ui.form.FormTour({ diff --git a/frappe/public/js/frappe/form/layout.js b/frappe/public/js/frappe/form/layout.js index 0000b9d729..41ff8508b6 100644 --- a/frappe/public/js/frappe/form/layout.js +++ b/frappe/public/js/frappe/form/layout.js @@ -20,25 +20,28 @@ frappe.ui.form.Layout = class Layout { } this.wrapper = $('
').appendTo(this.parent); this.message = $('').appendTo(this.wrapper); - this.page = $('
').appendTo(this.wrapper); - this.tabbed_layout && this.setup_tabbed_layout(); if (!this.fields) { this.fields = this.get_doctype_fields(); } - this.setup_tabbing(); + if (this.is_tabbed_layout()) { + this.setup_tabbed_layout(); + } + + this.setup_tab_events(); this.render(); } setup_tabbed_layout() { - $(`
- -
`).appendTo(this.page); + $(` +
+ +
+ `).appendTo(this.page); this.tabs_list = this.page.find('.form-tabs'); this.tabs_content = $(`
`).appendTo(this.page); - this.setup_events(); } @@ -114,16 +117,16 @@ frappe.ui.form.Layout = class Layout { this.section = null; this.column = null; - // if (this.with_dashboard) { - // this.setup_dashboard_section(); - // } - - if (this.tabbed_layout && this.no_opening_tab()) { - this.make_tab({label: __('Details'), fieldname: 'details'}); + if (this.no_opening_section() && !this.is_tabbed_layout()) { + this.fields.unshift({fieldtype: 'Section Break'}); } - if (this.no_opening_section()) { - this.make_section(); + if (this.is_tabbed_layout()) { + let default_tab = {label: __('Details'), fieldname: 'details'}; + let first_tab = this.fields[1].fieldtype === "Tab Break" ? this.fields[1] : null; + if (!first_tab) { + this.fields.splice(1, 0, default_tab); + } } fields.forEach(df => { @@ -154,10 +157,8 @@ frappe.ui.form.Layout = class Layout { return (this.fields[1] && this.fields[1].fieldtype != "Tab Break") || !this.fields.length; } - setup_dashboard_section() { - if (this.no_opening_section()) { - this.fields.unshift({fieldtype: 'Section Break'}); - } + is_tabbed_layout() { + return this.fields.find(f => f.fieldtype === "Tab Break"); } replace_field(fieldname, df, render) { @@ -190,7 +191,7 @@ frappe.ui.form.Layout = class Layout { this.section.fields_list.push(fieldobj); this.section.fields_dict[df.fieldname] = fieldobj; fieldobj.section = this.section; - fieldobj.tab = this.tab; + fieldobj.tab = this.current_tab; } init_field(df, render=false) { @@ -239,7 +240,7 @@ frappe.ui.form.Layout = class Layout { } make_section(df) { - this.section = new Section(this, df, this.tab || null); + this.section = new Section(this, df, this.current_tab || null); // append to layout fields if (df) { @@ -258,14 +259,12 @@ frappe.ui.form.Layout = class Layout { } make_tab(df) { - this.tab = new Tab(this, df); - - if (df) { - this.fields_dict[df.fieldname] = this.tab; - this.fields_list.push(this.tab); - } - - return this.tab; + this.section = null; + let tab = new Tab(this, df, this.frm, this.tabs_list, this.tabs_content); + this.current_tab = tab; + this.make_section({fieldtype: 'Section Break'}); + this.tabs.push(tab); + return tab; } refresh(doc) { @@ -421,14 +420,15 @@ frappe.ui.form.Layout = class Layout { }); } - setup_tabbing() { + setup_tab_events() { this.wrapper.on("keydown", (ev) => { if (ev.which == 9) { - let current = $(ev.target), - doctype = current.attr("data-doctype"), - fieldname = current.attr("data-fieldname"); - if (doctype) + let current = $(ev.target); + let doctype = current.attr("data-doctype"); + let fieldname = current.attr("data-fieldname"); + if (doctype) { return this.handle_tab(doctype, fieldname, ev.shiftKey); + } } }); } diff --git a/frappe/public/js/frappe/form/section.js b/frappe/public/js/frappe/form/section.js index cbc8666883..72760aad62 100644 --- a/frappe/public/js/frappe/form/section.js +++ b/frappe/public/js/frappe/form/section.js @@ -1,10 +1,7 @@ -// import '../class'; - export default class Section { - constructor(layout, df, tab) { - this.layout = layout; - this.tab = tab; - this.parent = this.tab && this.tab.wrapper || null; + constructor(parent, df) { + this.card_layout = true; + this.parent = parent; this.df = df || {}; this.fields_list = []; this.fields_dict = {}; @@ -23,18 +20,11 @@ export default class Section { } make() { - if (!this.layout.page) { - this.layout.page = $('
').appendTo(this.layout.wrapper); - } - - let make_card = this.layout.card_layout; - + let make_card = this.card_layout; this.wrapper = $(`
- `).appendTo(this.parent || this.layout.page); - - this.layout.sections.push(this); + `).appendTo(this.parent); if (this.df) { if (this.df.label) { @@ -86,17 +76,11 @@ export default class Section { } } - refresh() { + refresh(hide) { if (!this.df) return; - // hide if explicitly hidden - let hide = this.df.hidden || this.df.hidden_due_to_dependency; - if (!hide && this.layout && this.layout.frm && !this.layout.frm.get_perm(this.df.permlevel || 0, "read")) { - hide = true; - } - + hide = hide || this.df.hidden || this.df.hidden_due_to_dependency; this.wrapper.toggleClass("hide-control", !!hide); - // this.tab && this.tab.refresh(); } collapse(hide) { @@ -136,9 +120,9 @@ export default class Section { } has_missing_mandatory () { - var missing_mandatory = false; - for (var j = 0, l = this.fields_list.length; j < l; j++) { - var section_df = this.fields_list[j].df; + let missing_mandatory = false; + for (let j = 0, l = this.fields_list.length; j < l; j++) { + const section_df = this.fields_list[j].df; if (section_df.reqd && this.layout.doc[section_df.fieldname] == null) { missing_mandatory = true; break; @@ -148,11 +132,15 @@ export default class Section { } hide() { - this.wrapper.toggleClass("hide-control", true); + this.on_section_toggle(false); } show() { - this.wrapper.toggleClass("hide-control", false); - this.tab && this.tab.toggle(true); + this.on_section_toggle(true); + } + + on_section_toggle(show) { + this.wrapper.toggleClass("hide-control", !show); + this.on_section_toggle && this.on_section_toggle(show); } } diff --git a/frappe/public/js/frappe/form/tab.js b/frappe/public/js/frappe/form/tab.js index 84e50a7da1..c8ca016398 100644 --- a/frappe/public/js/frappe/form/tab.js +++ b/frappe/public/js/frappe/form/tab.js @@ -1,8 +1,12 @@ export default class Tab { - constructor(layout, df) { - this.layout = layout; + constructor(parent, df, frm, tabs_list, tabs_content) { + this.parent = parent; this.df = df || {}; - this.label = this.df && this.df.label || 'Details'; + this.frm = frm; + this.doctype = 'User'; + this.label = this.df && this.df.label; + this.tabs_list = tabs_list; + this.tabs_content = tabs_content; this.fields_list = []; this.fields_dict = {}; this.make(); @@ -10,28 +14,21 @@ export default class Tab { } make() { - if (!this.layout.page) { - this.layout.page = $('
').appendTo(this.layout.wrapper); - } - - const id = `${frappe.scrub(this.layout.doctype, '-')}-${this.df.fieldname}`; - this.parent = $(``).appendTo(this.layout.tabs_list); + const id = `${frappe.scrub(this.doctype, '-')}-${this.df.fieldname}`; + this.parent = $(` + + `).appendTo(this.tabs_list); this.wrapper = $(`
- `).appendTo(this.layout.tabs_content); - - this.layout.tabs.push(this); - } - - set_content() { - + id="${id}" role="tabpanel" aria-labelledby="${id}-tab">`).appendTo(this.tabs_content); } refresh() { @@ -39,15 +36,15 @@ export default class Tab { // hide if explicitly hidden let hide = this.df.hidden || this.df.hidden_due_to_dependency; - if (!hide && this.layout && this.layout.frm && !this.layout.frm.get_perm(this.df.permlevel || 0, "read")) { + if (!hide && this.frm && !this.frm.get_perm(this.df.permlevel || 0, "read")) { hide = true; } - + hide && this.toggle(false); } toggle(show) { - this.parent.toggleClass('hide', !show); + this.parent.toggleClass('hide', !show); this.wrapper.toggleClass('hide', !show); this.parent.toggleClass('show', show); this.wrapper.toggleClass('show', show);