From 62b6ca8a22549bbf2019b5218181585b69e53278 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 16 Mar 2021 17:33:05 +0530 Subject: [PATCH 1/8] feat: Client Script for List views --- .../doctype/client_script/client_script.json | 10 ++++++++- .../doctype/client_script/client_script.py | 18 +++++++++++++-- frappe/desk/form/meta.py | 22 ++++++++++++++++--- frappe/public/js/frappe/model/model.js | 3 +++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/frappe/custom/doctype/client_script/client_script.json b/frappe/custom/doctype/client_script/client_script.json index 57e6c68094..eca4fdb4b7 100644 --- a/frappe/custom/doctype/client_script/client_script.json +++ b/frappe/custom/doctype/client_script/client_script.json @@ -8,6 +8,7 @@ "engine": "InnoDB", "field_order": [ "dt", + "apply_to_view", "enabled", "script", "sample" @@ -43,13 +44,20 @@ "fieldname": "enabled", "fieldtype": "Check", "label": "Enabled" + }, + { + "default": "Form", + "fieldname": "apply_to_view", + "fieldtype": "Select", + "label": "Apply To", + "options": "List\nForm" } ], "icon": "fa fa-glass", "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2021-02-04 13:57:56.509437", + "modified": "2021-03-16 17:09:25.918859", "modified_by": "Administrator", "module": "Custom", "name": "Client Script", diff --git a/frappe/custom/doctype/client_script/client_script.py b/frappe/custom/doctype/client_script/client_script.py index e252e2a750..a84b9ce6e4 100644 --- a/frappe/custom/doctype/client_script/client_script.py +++ b/frappe/custom/doctype/client_script/client_script.py @@ -3,15 +3,29 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document + class ClientScript(Document): def autoname(self): - self.name = self.dt + self.name = f"{self.dt}-{self.apply_to_view}" + + def validate(self): + if not self.is_new(): + return + + exists = frappe.db.exists( + "Client Script", {"dt": self.dt, "apply_to_view": self.apply_to_view} + ) + if exists: + frappe.throw( + _("Client Script for {0} {1} already exists").format(frappe.bold(self.dt), self.apply_to_view), + frappe.DuplicateEntryError, + ) def on_update(self): frappe.clear_cache(doctype=self.dt) def on_trash(self): frappe.clear_cache(doctype=self.dt) - diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index c63da93a33..fc741b0f64 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -63,7 +63,7 @@ class FormMeta(Meta): "__linked_with", "__messages", "__print_formats", "__workflow_docs", "__form_grid_templates", "__listview_template", "__tree_js", "__dashboard", "__kanban_column_fields", '__templates', - '__custom_js'): + '__custom_js', '__custom_list_js'): d[k] = self.get(k) # d['fields'] = d.get('fields', []) @@ -130,9 +130,25 @@ class FormMeta(Meta): def add_custom_script(self): """embed all require files""" # custom script - custom = frappe.db.get_value("Client Script", {"dt": self.name, "enabled": 1}, "script") or "" + client_scripts = frappe.db.get_all("Client Script", + filters={"dt": self.name, "enabled": 1}, + fields=["script", "apply_to_view"], + order_by="creation asc" + ) or "" - self.set("__custom_js", custom) + print(client_scripts) + + list_script = '' + form_script = '' + for script in client_scripts: + if script.apply_to_view == 'List': + list_script += script.script + + if script.apply_to_view == 'Form': + form_script += script.script + + self.set("__custom_js", form_script) + self.set("__custom_list_js", list_script) def add_search_fields(self): """add search fields found in the doctypes indicated by link fields' options""" diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index 9ec7b0e931..22a5180a2b 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -181,6 +181,9 @@ $.extend(frappe.model, { if(meta.__list_js) { eval(meta.__list_js); } + if(meta.__custom_list_js) { + eval(meta.__custom_list_js); + } if(meta.__calendar_js) { eval(meta.__calendar_js); } From 10737a8a6149cc304fe7b0f2b9f64eb3da863184 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 16 Mar 2021 17:42:40 +0530 Subject: [PATCH 2/8] fix: remove print statement --- frappe/desk/form/meta.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index fc741b0f64..cd0e1b6fa1 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -136,8 +136,6 @@ class FormMeta(Meta): order_by="creation asc" ) or "" - print(client_scripts) - list_script = '' form_script = '' for script in client_scripts: From 6f89e29b4690b819f484dbbf1c56d7d46eb5d54c Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 16 Mar 2021 17:48:12 +0530 Subject: [PATCH 3/8] fix: rename field to simply "view" --- frappe/custom/doctype/client_script/client_script.json | 6 +++--- frappe/custom/doctype/client_script/client_script.py | 6 +++--- frappe/desk/form/meta.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frappe/custom/doctype/client_script/client_script.json b/frappe/custom/doctype/client_script/client_script.json index eca4fdb4b7..782f2a1185 100644 --- a/frappe/custom/doctype/client_script/client_script.json +++ b/frappe/custom/doctype/client_script/client_script.json @@ -8,7 +8,7 @@ "engine": "InnoDB", "field_order": [ "dt", - "apply_to_view", + "view", "enabled", "script", "sample" @@ -47,7 +47,7 @@ }, { "default": "Form", - "fieldname": "apply_to_view", + "fieldname": "view", "fieldtype": "Select", "label": "Apply To", "options": "List\nForm" @@ -57,7 +57,7 @@ "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2021-03-16 17:09:25.918859", + "modified": "2021-03-16 17:47:02.758919", "modified_by": "Administrator", "module": "Custom", "name": "Client Script", diff --git a/frappe/custom/doctype/client_script/client_script.py b/frappe/custom/doctype/client_script/client_script.py index a84b9ce6e4..049f979263 100644 --- a/frappe/custom/doctype/client_script/client_script.py +++ b/frappe/custom/doctype/client_script/client_script.py @@ -9,18 +9,18 @@ from frappe.model.document import Document class ClientScript(Document): def autoname(self): - self.name = f"{self.dt}-{self.apply_to_view}" + self.name = f"{self.dt}-{self.view}" def validate(self): if not self.is_new(): return exists = frappe.db.exists( - "Client Script", {"dt": self.dt, "apply_to_view": self.apply_to_view} + "Client Script", {"dt": self.dt, "view": self.view} ) if exists: frappe.throw( - _("Client Script for {0} {1} already exists").format(frappe.bold(self.dt), self.apply_to_view), + _("Client Script for {0} {1} already exists").format(frappe.bold(self.dt), self.view), frappe.DuplicateEntryError, ) diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index cd0e1b6fa1..e637f4969a 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -132,17 +132,17 @@ class FormMeta(Meta): # custom script client_scripts = frappe.db.get_all("Client Script", filters={"dt": self.name, "enabled": 1}, - fields=["script", "apply_to_view"], + fields=["script", "view"], order_by="creation asc" ) or "" list_script = '' form_script = '' for script in client_scripts: - if script.apply_to_view == 'List': + if script.view == 'List': list_script += script.script - if script.apply_to_view == 'Form': + if script.view == 'Form': form_script += script.script self.set("__custom_js", form_script) From fc64532f3a7d3b51d478a7620ff503a7efb7b163 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 16 Mar 2021 18:25:35 +0530 Subject: [PATCH 4/8] fix: List view formatters should override standard formatters --- frappe/public/js/frappe/list/list_view.js | 48 +++++++++++++---------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 396cd983fb..6e6635caf6 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -707,25 +707,18 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { const field_html = () => { let html; let _value; - // listview_setting formatter - if ( - this.settings.formatters && - this.settings.formatters[fieldname] - ) { - _value = this.settings.formatters[fieldname](value, df, doc); + let strip_html_required = + df.fieldtype == "Text Editor" || + (df.fetch_from && + ["Text", "Small Text"].includes(df.fieldtype)); + + if (strip_html_required) { + _value = strip_html(value); } else { - let strip_html_required = - df.fieldtype == "Text Editor" || - (df.fetch_from && - ["Text", "Small Text"].includes(df.fieldtype)); - if (strip_html_required) { - _value = strip_html(value); - } else { - _value = - typeof value === "string" - ? frappe.utils.escape_html(value) - : value; - } + _value = + typeof value === "string" + ? frappe.utils.escape_html(value) + : value; } if (df.fieldtype === "Image") { @@ -781,7 +774,15 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { Subject: this.get_subject_html(doc), Field: field_html(), }; - const column_html = html_map[col.type]; + let column_html = html_map[col.type]; + + // listview_setting formatter + if ( + this.settings.formatters && + this.settings.formatters[fieldname] + ) { + column_html = this.settings.formatters[fieldname](value, df, doc); + } return `
@@ -912,7 +913,14 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { get_subject_html(doc) { let subject_field = this.columns[0].df; - let value = doc[subject_field.fieldname] || doc.name; + let value = doc[subject_field.fieldname]; + if (this.settings.formatters && this.settings.formatters[subject_field.fieldname]) { + let formatter = this.settings.formatters[subject_field.fieldname]; + value = formatter(value, subject_field, doc); + } + if (!value) { + value = doc.name; + } let subject = strip_html(value.toString()); let escaped_subject = frappe.utils.escape_html(subject); From 41a472fa3b1f053f12345c2f25e52776ca6769ca Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 16 Mar 2021 18:36:39 +0530 Subject: [PATCH 5/8] fix: Don't add child table button for List script --- .../doctype/client_script/client_script.js | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/frappe/custom/doctype/client_script/client_script.js b/frappe/custom/doctype/client_script/client_script.js index 21e7334b82..3ef1932ff3 100644 --- a/frappe/custom/doctype/client_script/client_script.js +++ b/frappe/custom/doctype/client_script/client_script.js @@ -8,40 +8,42 @@ frappe.ui.form.on('Client Script', { () => frappe.set_route('List', frm.doc.dt, 'List')); } - frm.add_custom_button(__('Add script for Child Table'), () => { - frappe.model.with_doctype(frm.doc.dt, () => { - const child_tables = frappe.meta.get_docfields(frm.doc.dt, null, { - fieldtype: 'Table' - }).map(df => df.options); + if (frm.doc.view == 'Form') { + frm.add_custom_button(__('Add script for Child Table'), () => { + frappe.model.with_doctype(frm.doc.dt, () => { + const child_tables = frappe.meta.get_docfields(frm.doc.dt, null, { + fieldtype: 'Table' + }).map(df => df.options); - const d = new frappe.ui.Dialog({ - title: __('Select Child Table'), - fields: [ - { - label: __('Select Child Table'), - fieldtype: 'Link', - fieldname: 'cdt', - options: 'DocType', - get_query: () => { - return { - filters: { - istable: 1, - name: ['in', child_tables] - } - }; + const d = new frappe.ui.Dialog({ + title: __('Select Child Table'), + fields: [ + { + label: __('Select Child Table'), + fieldtype: 'Link', + fieldname: 'cdt', + options: 'DocType', + get_query: () => { + return { + filters: { + istable: 1, + name: ['in', child_tables] + } + }; + } } + ], + primary_action: ({ cdt }) => { + cdt = d.get_field('cdt').value; + frm.events.add_script_for_doctype(frm, cdt); + d.hide(); } - ], - primary_action: ({ cdt }) => { - cdt = d.get_field('cdt').value; - frm.events.add_script_for_doctype(frm, cdt); - d.hide(); - } - }); + }); - d.show(); + d.show(); + }); }); - }); + } frm.set_query('dt', { filters: { From 7abf44a68f8080fe44955387da176cd224a2c017 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 16 Mar 2021 20:34:39 +0530 Subject: [PATCH 6/8] fix: DocType and Apply To should be set only once --- frappe/custom/doctype/client_script/client_script.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frappe/custom/doctype/client_script/client_script.json b/frappe/custom/doctype/client_script/client_script.json index 782f2a1185..db02d8d4bc 100644 --- a/frappe/custom/doctype/client_script/client_script.json +++ b/frappe/custom/doctype/client_script/client_script.json @@ -23,7 +23,8 @@ "oldfieldname": "dt", "oldfieldtype": "Link", "options": "DocType", - "reqd": 1 + "reqd": 1, + "set_only_once": 1 }, { "fieldname": "script", @@ -50,14 +51,15 @@ "fieldname": "view", "fieldtype": "Select", "label": "Apply To", - "options": "List\nForm" + "options": "List\nForm", + "set_only_once": 1 } ], "icon": "fa fa-glass", "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2021-03-16 17:47:02.758919", + "modified": "2021-03-16 20:33:51.400191", "modified_by": "Administrator", "module": "Custom", "name": "Client Script", From fbaacd1c46ad805006865b5dd09015f5f02fa2aa Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 17 Mar 2021 11:30:42 +0530 Subject: [PATCH 7/8] fix: Hide Apply To for Single doctypes --- frappe/custom/doctype/client_script/client_script.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/custom/doctype/client_script/client_script.js b/frappe/custom/doctype/client_script/client_script.js index 3ef1932ff3..c9de85e449 100644 --- a/frappe/custom/doctype/client_script/client_script.js +++ b/frappe/custom/doctype/client_script/client_script.js @@ -53,6 +53,8 @@ frappe.ui.form.on('Client Script', { }, dt(frm) { + frm.toggle_display('view', !frappe.boot.single_types.includes(frm.doc.dt)); + if (!frm.doc.script) { frm.events.add_script_for_doctype(frm, frm.doc.dt); } From 3d7f4991629c23254271775a9ac6d16e8a51b2e8 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 17 Mar 2021 12:06:54 +0530 Subject: [PATCH 8/8] fix: Reset form boilerplate if view is List --- frappe/custom/doctype/client_script/client_script.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frappe/custom/doctype/client_script/client_script.js b/frappe/custom/doctype/client_script/client_script.js index c9de85e449..27d11af4d1 100644 --- a/frappe/custom/doctype/client_script/client_script.js +++ b/frappe/custom/doctype/client_script/client_script.js @@ -65,7 +65,18 @@ frappe.ui.form.on('Client Script', { } }, + view(frm) { + let has_form_boilerplate = frm.doc.script.includes('frappe.ui.form.on') + if (frm.doc.view === 'List' && has_form_boilerplate) { + frm.set_value('script', ''); + } + if (frm.doc.view === 'Form' && !has_form_boilerplate) { + frm.trigger('dt'); + } + }, + add_script_for_doctype(frm, doctype) { + if (!doctype) return; let boilerplate = ` frappe.ui.form.on('${doctype}', { refresh(frm) {