From 788887367203e5074af3a41798dec4ee7e7aee58 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 15 Oct 2019 14:54:01 +0530 Subject: [PATCH 001/173] feat: allow email append to for other doctypes --- .../doctype/customize_form/customize_form.json | 9 ++++++++- .../custom/doctype/customize_form/customize_form.py | 3 ++- frappe/email/doctype/email_account/email_account.py | 12 +++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index 0b1df62f9d..4778bf524f 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -20,6 +20,7 @@ "allow_auto_repeat", "allow_import", "image_view", + "allow_in_email_append_to", "column_break_5", "title_field", "image_field", @@ -174,13 +175,19 @@ "fieldname": "allow_import", "fieldtype": "Check", "label": "Allow Import (via Data Import Tool)" + }, + { + "default": "0", + "fieldname": "allow_in_email_append_to", + "fieldtype": "Check", + "label": "Allow in Email Append To" } ], "hide_toolbar": 1, "icon": "fa fa-glass", "idx": 1, "issingle": 1, - "modified": "2019-10-08 11:16:36.698006", + "modified": "2019-10-15 14:20:51.272870", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index b851d40b83..190d4cb567 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -31,7 +31,8 @@ doctype_properties = { 'track_changes': 'Check', 'track_views': 'Check', 'allow_auto_repeat': 'Check', - 'allow_import': 'Check' + 'allow_import': 'Check', + 'allow_in_email_append_to': 'Check' } docfield_properties = { diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index f10f08664c..73e85659b3 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -652,7 +652,17 @@ class EmailAccount(Document): @frappe.whitelist() def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None): if not txt: txt = "" - return [[d] for d in frappe.get_hooks("email_append_to") if txt in d] + + email_append_to_list = frappe.get_hooks("email_append_to") + custom_email_append_to_list = frappe.get_list("Property Setter", filters={ + "property": "allow_in_email_append_to", + "value": 1 + }, fields=["doc_type"]) + + for doctype in custom_email_append_to_list: + email_append_to_list.append(doctype.doc_type) + + return [[d] for d in set(email_append_to_list) if txt in d] def test_internet(host="8.8.8.8", port=53, timeout=3): """Returns True if internet is connected From f207d98d784ac7ab2f2b2882fbb5640e273c4120 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 15 Oct 2019 15:21:42 +0530 Subject: [PATCH 002/173] fix: check if subject and status exists --- frappe/custom/doctype/customize_form/customize_form.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 190d4cb567..57d0251f72 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -165,6 +165,7 @@ class CustomizeForm(Document): self.flags.update_db = False self.flags.rebuild_doctype_for_global_search = False + self.check_email_append_to() self.set_property_setters() self.update_custom_fields() self.set_name_translation() @@ -249,6 +250,13 @@ class CustomizeForm(Document): self.make_property_setter(property=property, value=df.get(property), property_type=docfield_properties[property], fieldname=df.fieldname) + def check_email_append_to(self): + meta = frappe.get_meta(self.doc_type) + + if self.allow_in_email_append_to and not (meta.has_field("subject") and meta.has_field("status")): + frappe.throw(_("Add custom fields for Subject and Status in Document Type \ + {0} to enable Email Append To").format(self.doc_type)) + def update_custom_fields(self): for i, df in enumerate(self.get("fields")): if df.get("is_custom_field"): From 93e64e4ce659c5c0919694b8ff7927bd6486da5c Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sat, 26 Oct 2019 18:14:47 +0530 Subject: [PATCH 003/173] fix: check if meta has subject and status --- .../doctype/email_account/email_account.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 73e85659b3..703835e87b 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -653,16 +653,20 @@ class EmailAccount(Document): def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None): if not txt: txt = "" + if frappe.cache().hget("email_append_to", "email_append_to_dts"): + return frappe.cache().hget("email_append_to", "email_append_to_dts") + email_append_to_list = frappe.get_hooks("email_append_to") - custom_email_append_to_list = frappe.get_list("Property Setter", filters={ - "property": "allow_in_email_append_to", - "value": 1 - }, fields=["doc_type"]) - for doctype in custom_email_append_to_list: - email_append_to_list.append(doctype.doc_type) + for dt in frappe.get_list("DocType", filters={"istable": 0, "issingle": 0}): + meta = frappe.get_meta(dt.name) + if meta.allow_in_email_append_to and meta.has_field("subject") and meta.has_field("status"): + email_append_to_list.append(dt.name) - return [[d] for d in set(email_append_to_list) if txt in d] + email_append = [[d] for d in set(email_append_to_list) if txt in d] + frappe.cache().hset("email_append_to", "email_append_to_dts", email_append) + + return email_append def test_internet(host="8.8.8.8", port=53, timeout=3): """Returns True if internet is connected From 7e7c14e2e72652a2d6641596543848ecf59bc7ce Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 21 Nov 2019 12:21:30 +0530 Subject: [PATCH 004/173] fix: statushsould have open and closed in options --- .../doctype/customize_form/customize_form.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 57d0251f72..7f853324b5 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -253,9 +253,17 @@ class CustomizeForm(Document): def check_email_append_to(self): meta = frappe.get_meta(self.doc_type) - if self.allow_in_email_append_to and not (meta.has_field("subject") and meta.has_field("status")): - frappe.throw(_("Add custom fields for Subject and Status in Document Type \ - {0} to enable Email Append To").format(self.doc_type)) + if self.allow_in_email_append_to: + if not meta.has_field("subject"): + frappe.throw(_("Add custom fields for Subject in Document Type {0} to enable Email Append To").format(self.doc_type)) + + if not meta.has_field("status"): + frappe.throw(_("Add custom fields for Status in Document Type {0} to enable Email Append To").format(self.doc_type)) + else: + status = meta.get_field("status") + for option in ["Open", "Closed"]: + if not option in status.options: + frappe.throw(_("Status field should have status {0} in options").format(option)) def update_custom_fields(self): for i, df in enumerate(self.get("fields")): From 12c1d6cc57533107d27df3937b230f349c9f8aa3 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 21 Nov 2019 13:55:11 +0530 Subject: [PATCH 005/173] fix: check if property exists --- frappe/email/doctype/email_account/email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 703835e87b..e1f5a2adeb 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -660,7 +660,7 @@ def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len for dt in frappe.get_list("DocType", filters={"istable": 0, "issingle": 0}): meta = frappe.get_meta(dt.name) - if meta.allow_in_email_append_to and meta.has_field("subject") and meta.has_field("status"): + if meta.get("allow_in_email_append_to") and meta.allow_in_email_append_to: email_append_to_list.append(dt.name) email_append = [[d] for d in set(email_append_to_list) if txt in d] From 87eb7243fd61175b9f63e320ab31130a6612b0c0 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 21 Nov 2019 15:31:30 +0530 Subject: [PATCH 006/173] fix: allow custom doctypes --- frappe/email/doctype/email_account/email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index e1f5a2adeb..c45dab110d 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -660,7 +660,7 @@ def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len for dt in frappe.get_list("DocType", filters={"istable": 0, "issingle": 0}): meta = frappe.get_meta(dt.name) - if meta.get("allow_in_email_append_to") and meta.allow_in_email_append_to: + if meta.custom or (meta.get("allow_in_email_append_to") and meta.allow_in_email_append_to): email_append_to_list.append(dt.name) email_append = [[d] for d in set(email_append_to_list) if txt in d] From 8c9918bc96ef630a9d75589474c6e8f8e66d5814 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Dec 2019 12:46:21 +0530 Subject: [PATCH 007/173] feat: allow document creation via email --- frappe/core/doctype/doctype/doctype.json | 28 ++++++++++- frappe/core/doctype/doctype/doctype.py | 46 +++++++++++++++++++ .../customize_form/customize_form.json | 28 +++++++++-- .../doctype/customize_form/customize_form.py | 24 +++------- frappe/database/mariadb/framework_mariadb.sql | 4 ++ .../database/postgres/framework_postgres.sql | 4 ++ .../doctype/email_account/email_account.py | 26 +++-------- 7 files changed, 118 insertions(+), 42 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 4e3f2fd84a..0fa90ac5df 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -35,6 +35,9 @@ "timeline_field", "nsm_parent_field", "max_attachments", + "subject_field", + "sender_field", + "status_field", "column_break_23", "hide_toolbar", "allow_copy", @@ -42,6 +45,7 @@ "allow_import", "allow_events_in_timeline", "allow_auto_repeat", + "email_append_to", "view_settings", "title_field", "search_fields", @@ -488,11 +492,33 @@ "fieldtype": "Table", "label": "Links", "options": "DocType Link" + }, + { + "fieldname": "subject_field", + "fieldtype": "Data", + "label": "Subject Field" + }, + { + "fieldname": "sender_field", + "fieldtype": "Data", + "label": "Sender Field" + }, + { + "default": "0", + "fieldname": "email_append_to", + "fieldtype": "Check", + "label": "Allow document creation via Email" + }, + { + "fieldname": "status_field", + "fieldtype": "Data", + "label": "Status Field" } ], "icon": "fa fa-bolt", "idx": 6, - "modified": "2019-11-25 17:24:03.690192", + "links": [], + "modified": "2019-12-12 12:05:39.317311", "modified_by": "Administrator", "module": "Core", "name": "DocType", diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 1223d50878..35cbdfa992 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -93,6 +93,8 @@ class DocType(Document): if not self.is_new(): self.setup_fields_to_fetch() + check_email_append_to(self) + if self.default_print_format and not self.custom: frappe.throw(_('Standard DocType cannot have default print format, use Customize Form')) @@ -1144,3 +1146,47 @@ def check_if_fieldname_conflicts_with_methods(doctype, fieldname): def clear_linked_doctype_cache(): frappe.cache().delete_value('linked_doctypes_without_ignore_user_permissions_enabled') + +def check_email_append_to(doc): + if not doc.email_append_to: + return + + # Subject Field + doc.subject_field = doc.subject_field.strip() if doc.subject_field else None + subject_field = get_field(doc, doc.subject_field) + + if not (doc.subject_field or subject_field): + frappe.throw(_("Add Subject Field for creating documents from Email")) + + if subject_field.fieldtype not in ["Data", "Text", "Long Text", "Small Text", "Text Editor"]: + frappe.throw(_("Subject Field type should be Data, Text, Long Text, Small Text, Text Editor")) + + # Sender Field + doc.sender_field = doc.sender_field.strip() if doc.sender_field else None + sender_field = get_field(doc, doc.sender_field) + + if not (doc.sender_field or sender_field): + frappe.throw(_("Add Sender Field for creating documents from Email")) + + # Status Field + doc.status_field = doc.status_field.strip() if doc.status_field else None + status_field = get_field(doc, doc.status_field) + + if not (doc.status_field or status_field): + frappe.throw(_("Add Status Field for creating documents from Email")) + + if status_field.fieldtype != "Select": + frappe.throw(_("Status Field type should be Select")) + + for option in ["Open", "Closed"]: + if not option in status_field.options: + frappe.throw(_("Status field should have status Open and Closed in options")) + + +def get_field(doc, fieldname): + if not (doc or fieldname): + return + + for field in doc.fields: + if field.fieldname == fieldname: + return field diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index 4778bf524f..3e547fb22f 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "DL.####", "creation": "2013-01-29 17:55:08", "doctype": "DocType", @@ -20,11 +21,14 @@ "allow_auto_repeat", "allow_import", "image_view", - "allow_in_email_append_to", + "email_append_to", "column_break_5", "title_field", "image_field", "search_fields", + "subject_field", + "sender_field", + "status_field", "section_break_8", "sort_field", "column_break_10", @@ -176,18 +180,34 @@ "fieldtype": "Check", "label": "Allow Import (via Data Import Tool)" }, + { + "fieldname": "subject_field", + "fieldtype": "Data", + "label": "Subject Field" + }, + { + "fieldname": "sender_field", + "fieldtype": "Data", + "label": "Sender Field" + }, { "default": "0", - "fieldname": "allow_in_email_append_to", + "fieldname": "email_append_to", "fieldtype": "Check", - "label": "Allow in Email Append To" + "label": "Allow document creation via Email" + }, + { + "fieldname": "status_field", + "fieldtype": "Data", + "label": "Status Field" } ], "hide_toolbar": 1, "icon": "fa fa-glass", "idx": 1, "issingle": 1, - "modified": "2019-10-15 14:20:51.272870", + "links": [], + "modified": "2019-12-12 12:44:02.674456", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 7f853324b5..5e5a9f0c9f 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -12,7 +12,7 @@ from frappe import _ from frappe.utils import cint from frappe.model.document import Document from frappe.model import no_value_fields, core_doctypes_list -from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype +from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype, check_email_append_to from frappe.custom.doctype.custom_field.custom_field import create_custom_field from frappe.model.docfield import supports_translation @@ -32,7 +32,10 @@ doctype_properties = { 'track_views': 'Check', 'allow_auto_repeat': 'Check', 'allow_import': 'Check', - 'allow_in_email_append_to': 'Check' + 'email_append_to': 'Check', + 'subject_field': 'Data', + 'sender_field': 'Data', + 'status_field': 'Data' } docfield_properties = { @@ -165,7 +168,7 @@ class CustomizeForm(Document): self.flags.update_db = False self.flags.rebuild_doctype_for_global_search = False - self.check_email_append_to() + check_email_append_to(self) self.set_property_setters() self.update_custom_fields() self.set_name_translation() @@ -250,21 +253,6 @@ class CustomizeForm(Document): self.make_property_setter(property=property, value=df.get(property), property_type=docfield_properties[property], fieldname=df.fieldname) - def check_email_append_to(self): - meta = frappe.get_meta(self.doc_type) - - if self.allow_in_email_append_to: - if not meta.has_field("subject"): - frappe.throw(_("Add custom fields for Subject in Document Type {0} to enable Email Append To").format(self.doc_type)) - - if not meta.has_field("status"): - frappe.throw(_("Add custom fields for Status in Document Type {0} to enable Email Append To").format(self.doc_type)) - else: - status = meta.get_field("status") - for option in ["Open", "Closed"]: - if not option in status.options: - frappe.throw(_("Status field should have status {0} in options").format(option)) - def update_custom_fields(self): for i, df in enumerate(self.get("fields")): if df.get("is_custom_field"): diff --git a/frappe/database/mariadb/framework_mariadb.sql b/frappe/database/mariadb/framework_mariadb.sql index b1a769b189..10e2ef7e7d 100644 --- a/frappe/database/mariadb/framework_mariadb.sql +++ b/frappe/database/mariadb/framework_mariadb.sql @@ -215,6 +215,10 @@ CREATE TABLE `tabDocType` ( `allow_guest_to_view` int(1) NOT NULL DEFAULT 0, `route` varchar(255) DEFAULT NULL, `is_published_field` varchar(255) DEFAULT NULL, + `email_append_to` int(1) NOT NULL DEFAULT 0, + `subject_field` varchar(255) DEFAULT NULL, + `sender_field` varchar(255) DEFAULT NULL, + `status_field` varchar(255) DEFAULT NULL, PRIMARY KEY (`name`), KEY `parent` (`parent`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/frappe/database/postgres/framework_postgres.sql b/frappe/database/postgres/framework_postgres.sql index cd2f02d8e4..c89c9a8b16 100644 --- a/frappe/database/postgres/framework_postgres.sql +++ b/frappe/database/postgres/framework_postgres.sql @@ -220,6 +220,10 @@ CREATE TABLE "tabDocType" ( "allow_guest_to_view" smallint NOT NULL DEFAULT 0, "route" varchar(255) DEFAULT NULL, "is_published_field" varchar(255) DEFAULT NULL, + `email_append_to` smallint NOT NULL DEFAULT 0, + `subject_field` varchar(255) DEFAULT NULL, + `sender_field` varchar(255) DEFAULT NULL, + `status_field` varchar(255) DEFAULT NULL, PRIMARY KEY ("name") ) ; diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 4dde4826bf..b520c92399 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -419,42 +419,30 @@ class EmailAccount(Document): If no thread id is found and `append_to` is set for the email account, it will create a new parent transaction (e.g. Issue)""" - parent = None - - parent = self.find_parent_from_in_reply_to(communication, email) + parent = self.find_parent_from_in_reply_to(communication, email) or None if not parent and self.append_to: self.set_sender_field_and_subject_field() - - if not parent and self.append_to: parent = self.find_parent_based_on_subject_and_sender(communication, email) - if not parent and self.append_to and self.append_to!="Communication": - parent = self.create_new_parent(communication, email) + if self.append_to!="Communication": + parent = self.create_new_parent(communication, email) if parent: communication.reference_doctype = parent.doctype communication.reference_name = parent.name # check if message is notification and disable notifications for this message - isnotification = email.mail.get("isnotification") - if isnotification: - if "notification" in isnotification: - communication.unread_notification_sent = 1 + if email.mail.get("isnotification") and "notification" in email.mail.get("isnotification"): + communication.unread_notification_sent = 1 def set_sender_field_and_subject_field(self): '''Identify the sender and subject fields from the `append_to` DocType''' # set subject_field and sender_field - meta_module = frappe.get_meta_module(self.append_to) meta = frappe.get_meta(self.append_to) - self.subject_field = getattr(meta_module, "subject_field", "subject") - if not meta.get_field(self.subject_field): - self.subject_field = None - - self.sender_field = getattr(meta_module, "sender_field", "sender") - if not meta.get_field(self.sender_field): - self.sender_field = None + self.subject_field = meta.subject_field if meta.subject_field else None + self.sender_field = meta.sender_field if meta.sender_field else None def find_parent_based_on_subject_and_sender(self, communication, email): '''Find parent document based on subject and sender match''' From ec89d275a2bad2de14c7d4249cd17dc7b9a69dd4 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Dec 2019 15:04:56 +0530 Subject: [PATCH 008/173] feat: remove hooks for email_append_to --- .../doctype/communication/communication.json | 8 ++++++- frappe/desk/doctype/event/event.json | 15 +++++++++++- frappe/desk/doctype/todo/todo.json | 10 ++++++-- frappe/desk/doctype/todo/todo.py | 2 -- .../doctype/email_account/email_account.py | 23 +++++++++++-------- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/frappe/core/doctype/communication/communication.json b/frappe/core/doctype/communication/communication.json index 5e34804b93..3418fc073b 100644 --- a/frappe/core/doctype/communication/communication.json +++ b/frappe/core/doctype/communication/communication.json @@ -1,9 +1,11 @@ { + "actions": [], "allow_import": 1, "creation": "2013-01-29 10:47:14", "description": "Keeps track of all communications", "doctype": "DocType", "document_type": "Setup", + "email_append_to": 1, "engine": "InnoDB", "field_order": [ "subject", @@ -383,7 +385,8 @@ ], "icon": "fa fa-comment", "idx": 1, - "modified": "2019-10-09 14:22:27.664645", + "links": [], + "modified": "2019-12-12 13:01:23.716052", "modified_by": "Administrator", "module": "Core", "name": "Communication", @@ -430,8 +433,11 @@ } ], "search_fields": "subject", + "sender_field": "sender", "sort_field": "modified", "sort_order": "DESC", + "status_field": "status", + "subject_field": "subject", "title_field": "subject", "track_changes": 1, "track_seen": 1 diff --git a/frappe/desk/doctype/event/event.json b/frappe/desk/doctype/event/event.json index 032030ddef..8a0372b13f 100644 --- a/frappe/desk/doctype/event/event.json +++ b/frappe/desk/doctype/event/event.json @@ -1,9 +1,11 @@ { + "actions": [], "allow_import": 1, "autoname": "EV.#####", "creation": "2013-06-10 13:17:47", "doctype": "DocType", "document_type": "Document", + "email_append_to": 1, "engine": "InnoDB", "field_order": [ "details", @@ -17,6 +19,7 @@ "starts_on", "ends_on", "status", + "sender", "all_day", "sync_with_google_calendar", "sb_00", @@ -262,11 +265,18 @@ "fieldtype": "Check", "label": "Pulled from Google Calendar", "read_only": 1 + }, + { + "fieldname": "sender", + "fieldtype": "Data", + "label": "Sender", + "read_only": 1 } ], "icon": "fa fa-calendar", "idx": 1, - "modified": "2019-08-08 16:01:19.489396", + "links": [], + "modified": "2019-12-12 12:58:36.621861", "modified_by": "Administrator", "module": "Desk", "name": "Event", @@ -297,8 +307,11 @@ } ], "read_only": 1, + "sender_field": "sender", "sort_field": "modified", "sort_order": "DESC", + "status_field": "status", + "subject_field": "subject", "title_field": "subject", "track_changes": 1, "track_seen": 1, diff --git a/frappe/desk/doctype/todo/todo.json b/frappe/desk/doctype/todo/todo.json index 508720a488..f80a785ccd 100644 --- a/frappe/desk/doctype/todo/todo.json +++ b/frappe/desk/doctype/todo/todo.json @@ -1,8 +1,10 @@ { + "actions": [], "autoname": "hash", "creation": "2012-07-03 13:30:35", "doctype": "DocType", "document_type": "Setup", + "email_append_to": 1, "engine": "InnoDB", "field_order": [ "description_and_status", @@ -154,7 +156,8 @@ ], "icon": "fa fa-check", "idx": 2, - "modified": "2019-09-10 14:34:59.161750", + "links": [], + "modified": "2019-12-12 12:53:17.565139", "modified_by": "Administrator", "module": "Desk", "name": "ToDo", @@ -185,9 +188,12 @@ ], "quick_entry": 1, "search_fields": "description, reference_type, reference_name", + "sender_field": "sender", "sort_field": "modified", "sort_order": "DESC", + "status_field": "status", + "subject_field": "description", "title_field": "description", "track_changes": 1, "track_seen": 1 -} +} \ No newline at end of file diff --git a/frappe/desk/doctype/todo/todo.py b/frappe/desk/doctype/todo/todo.py index 5d04f412c0..034afd3184 100644 --- a/frappe/desk/doctype/todo/todo.py +++ b/frappe/desk/doctype/todo/todo.py @@ -8,8 +8,6 @@ import json from frappe.model.document import Document from frappe.utils import get_fullname -subject_field = "description" -sender_field = "sender" exclude_from_linked_with = True class ToDo(Document): diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index b520c92399..626ecbf378 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -637,21 +637,24 @@ class EmailAccount(Document): frappe.throw(_("Automatic Linking can be activated only for one Email Account.")) @frappe.whitelist() -def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None): - if not txt: txt = "" +def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None, reset_cache=False): - if frappe.cache().hget("email_append_to", "email_append_to_dts"): - return frappe.cache().hget("email_append_to", "email_append_to_dts") + if frappe.cache().hget("email_append_to", "email_append_to_doctypes") and not reset_cache: + return frappe.cache().hget("email_append_to", "email_append_to_doctypes") - email_append_to_list = frappe.get_hooks("email_append_to") + txt = txt if txt else "" + email_append_to_list = [] - for dt in frappe.get_list("DocType", filters={"istable": 0, "issingle": 0}): - meta = frappe.get_meta(dt.name) - if meta.custom or (meta.get("allow_in_email_append_to") and meta.allow_in_email_append_to): + for dt in frappe.get_all("DocType", filters={"istable": 0, "issingle": 0}, fields=["name", "email_append_to"]): + if dt.get("email_append_to") and dt.email_append_to: email_append_to_list.append(dt.name) + else: + meta = frappe.get_meta(dt.name) + if meta.get("email_append_to") and meta.email_append_to: + email_append_to_list.append(dt.name) - email_append = [[d] for d in set(email_append_to_list) if txt in d] - frappe.cache().hset("email_append_to", "email_append_to_dts", email_append) + email_append_to = [[d] for d in set(email_append_to_list) if txt in d] + frappe.cache().hset("email_append_to", "email_append_to_doctypes", email_append_to) return email_append From b98ea6415016d5f4f08c6d15ec57f5b65506eab0 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Dec 2019 19:23:22 +0530 Subject: [PATCH 009/173] fix: remove status field --- frappe/core/doctype/doctype/doctype.json | 8 +------- frappe/core/doctype/doctype/doctype.py | 14 -------------- .../doctype/customize_form/customize_form.json | 8 +------- .../doctype/customize_form/customize_form.py | 3 +-- 4 files changed, 3 insertions(+), 30 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 0fa90ac5df..9a8177d3a3 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -37,7 +37,6 @@ "max_attachments", "subject_field", "sender_field", - "status_field", "column_break_23", "hide_toolbar", "allow_copy", @@ -508,17 +507,12 @@ "fieldname": "email_append_to", "fieldtype": "Check", "label": "Allow document creation via Email" - }, - { - "fieldname": "status_field", - "fieldtype": "Data", - "label": "Status Field" } ], "icon": "fa fa-bolt", "idx": 6, "links": [], - "modified": "2019-12-12 12:05:39.317311", + "modified": "2019-12-12 19:16:50.130503", "modified_by": "Administrator", "module": "Core", "name": "DocType", diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 35cbdfa992..5610fa4f89 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1168,20 +1168,6 @@ def check_email_append_to(doc): if not (doc.sender_field or sender_field): frappe.throw(_("Add Sender Field for creating documents from Email")) - # Status Field - doc.status_field = doc.status_field.strip() if doc.status_field else None - status_field = get_field(doc, doc.status_field) - - if not (doc.status_field or status_field): - frappe.throw(_("Add Status Field for creating documents from Email")) - - if status_field.fieldtype != "Select": - frappe.throw(_("Status Field type should be Select")) - - for option in ["Open", "Closed"]: - if not option in status_field.options: - frappe.throw(_("Status field should have status Open and Closed in options")) - def get_field(doc, fieldname): if not (doc or fieldname): diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index 3e547fb22f..49e8dee366 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -28,7 +28,6 @@ "search_fields", "subject_field", "sender_field", - "status_field", "section_break_8", "sort_field", "column_break_10", @@ -195,11 +194,6 @@ "fieldname": "email_append_to", "fieldtype": "Check", "label": "Allow document creation via Email" - }, - { - "fieldname": "status_field", - "fieldtype": "Data", - "label": "Status Field" } ], "hide_toolbar": 1, @@ -207,7 +201,7 @@ "idx": 1, "issingle": 1, "links": [], - "modified": "2019-12-12 12:44:02.674456", + "modified": "2019-12-12 19:17:08.426469", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 5e5a9f0c9f..4c5fe76bed 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -34,8 +34,7 @@ doctype_properties = { 'allow_import': 'Check', 'email_append_to': 'Check', 'subject_field': 'Data', - 'sender_field': 'Data', - 'status_field': 'Data' + 'sender_field': 'Data' } docfield_properties = { From 78f506226a12aa4cf32d769293cdb41d1ec994b4 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Dec 2019 21:14:26 +0530 Subject: [PATCH 010/173] fix: return correct variable --- frappe/email/doctype/email_account/email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 626ecbf378..7d9c2bb8fb 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -656,7 +656,7 @@ def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len email_append_to = [[d] for d in set(email_append_to_list) if txt in d] frappe.cache().hset("email_append_to", "email_append_to_doctypes", email_append_to) - return email_append + return email_append_to def test_internet(host="8.8.8.8", port=53, timeout=3): """Returns True if internet is connected From 2fe3430e743a2d4311018b02bc5d8737fc2b9ecc Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 27 Dec 2019 14:30:24 +0530 Subject: [PATCH 011/173] fix: create a new section for email append to --- frappe/core/doctype/doctype/doctype.js | 12 +++++++++++- frappe/core/doctype/doctype/doctype.json | 17 +++++++++++++---- .../doctype/customize_form/customize_form.js | 9 +++++++++ .../doctype/customize_form/customize_form.json | 17 ++++++++++++++--- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js index 9a19185cfc..379f7cdd9e 100644 --- a/frappe/core/doctype/doctype/doctype.js +++ b/frappe/core/doctype/doctype/doctype.js @@ -53,7 +53,17 @@ frappe.ui.form.on('DocType', { frm.events.autoname(frm); }, - autoname(frm) { + email_append_to: function (frm) { + frm.set_df_property("subject_field", "reqd", 0); + frm.set_df_property("sender_field", "reqd", 0); + + if (frm.doc.email_append_to) { + frm.set_df_property("subject_field", "reqd", 1); + frm.set_df_property("sender_field", "reqd", 1); + } + }, + + autoname: function(frm) { frm.set_df_property('fields', 'reqd', frm.doc.autoname !== 'Prompt'); } }) diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 9a8177d3a3..59fd55c402 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -35,8 +35,6 @@ "timeline_field", "nsm_parent_field", "max_attachments", - "subject_field", - "sender_field", "column_break_23", "hide_toolbar", "allow_copy", @@ -44,7 +42,6 @@ "allow_import", "allow_events_in_timeline", "allow_auto_repeat", - "email_append_to", "view_settings", "title_field", "search_fields", @@ -57,6 +54,10 @@ "color", "show_preview_popup", "show_name_in_global_search", + "email_settings_sb", + "email_append_to", + "subject_field", + "sender_field", "sb2", "permissions", "restrict_to_domain", @@ -493,11 +494,13 @@ "options": "DocType Link" }, { + "depends_on": "email_append_to", "fieldname": "subject_field", "fieldtype": "Data", "label": "Subject Field" }, { + "depends_on": "email_append_to", "fieldname": "sender_field", "fieldtype": "Data", "label": "Sender Field" @@ -507,12 +510,18 @@ "fieldname": "email_append_to", "fieldtype": "Check", "label": "Allow document creation via Email" + }, + { + "collapsible": 1, + "fieldname": "email_settings_sb", + "fieldtype": "Section Break", + "label": "Email Settings" } ], "icon": "fa fa-bolt", "idx": 6, "links": [], - "modified": "2019-12-12 19:16:50.130503", + "modified": "2019-12-27 13:28:06.201814", "modified_by": "Administrator", "module": "Core", "name": "DocType", diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index f1eadaaf2e..4ade51ae5b 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -132,6 +132,15 @@ frappe.ui.form.on("Customize Form", { }, + email_append_to: function(frm) { + frm.set_df_property("subject_field", "reqd", 0); + frm.set_df_property("sender_field", "reqd", 0); + + if (frm.doc.email_append_to) { + frm.set_df_property("subject_field", "reqd", 1); + frm.set_df_property("sender_field", "reqd", 1); + } + } }); frappe.ui.form.on("Customize Form Field", { diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index 49e8dee366..f719add96c 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -26,12 +26,14 @@ "title_field", "image_field", "search_fields", - "subject_field", - "sender_field", "section_break_8", "sort_field", "column_break_10", "sort_order", + "section_break_23", + "subject_field", + "cb_01", + "sender_field", "fields_section_break", "fields" ], @@ -194,6 +196,15 @@ "fieldname": "email_append_to", "fieldtype": "Check", "label": "Allow document creation via Email" + }, + { + "depends_on": "doc_type", + "fieldname": "section_break_23", + "fieldtype": "Section Break" + }, + { + "fieldname": "cb_01", + "fieldtype": "Column Break" } ], "hide_toolbar": 1, @@ -201,7 +212,7 @@ "idx": 1, "issingle": 1, "links": [], - "modified": "2019-12-12 19:17:08.426469", + "modified": "2019-12-27 14:29:49.097980", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", From 9543b7d4afca27c4e7f618d3f65b3e4fe6541c52 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 27 Dec 2019 14:48:46 +0530 Subject: [PATCH 012/173] fix: remove status field --- .../doctype/communication/communication.json | 3 +-- frappe/database/mariadb/framework_mariadb.sql | 1 - frappe/database/postgres/framework_postgres.sql | 1 - frappe/desk/doctype/event/event.json | 3 +-- frappe/desk/doctype/todo/todo.json | 3 +-- .../email/doctype/email_account/email_account.py | 16 ++++++---------- 6 files changed, 9 insertions(+), 18 deletions(-) diff --git a/frappe/core/doctype/communication/communication.json b/frappe/core/doctype/communication/communication.json index 3418fc073b..ae6fb164ec 100644 --- a/frappe/core/doctype/communication/communication.json +++ b/frappe/core/doctype/communication/communication.json @@ -386,7 +386,7 @@ "icon": "fa fa-comment", "idx": 1, "links": [], - "modified": "2019-12-12 13:01:23.716052", + "modified": "2019-12-27 14:44:04.880373", "modified_by": "Administrator", "module": "Core", "name": "Communication", @@ -436,7 +436,6 @@ "sender_field": "sender", "sort_field": "modified", "sort_order": "DESC", - "status_field": "status", "subject_field": "subject", "title_field": "subject", "track_changes": 1, diff --git a/frappe/database/mariadb/framework_mariadb.sql b/frappe/database/mariadb/framework_mariadb.sql index 10e2ef7e7d..bf9e0e33c8 100644 --- a/frappe/database/mariadb/framework_mariadb.sql +++ b/frappe/database/mariadb/framework_mariadb.sql @@ -218,7 +218,6 @@ CREATE TABLE `tabDocType` ( `email_append_to` int(1) NOT NULL DEFAULT 0, `subject_field` varchar(255) DEFAULT NULL, `sender_field` varchar(255) DEFAULT NULL, - `status_field` varchar(255) DEFAULT NULL, PRIMARY KEY (`name`), KEY `parent` (`parent`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/frappe/database/postgres/framework_postgres.sql b/frappe/database/postgres/framework_postgres.sql index c89c9a8b16..6bd20d241b 100644 --- a/frappe/database/postgres/framework_postgres.sql +++ b/frappe/database/postgres/framework_postgres.sql @@ -223,7 +223,6 @@ CREATE TABLE "tabDocType" ( `email_append_to` smallint NOT NULL DEFAULT 0, `subject_field` varchar(255) DEFAULT NULL, `sender_field` varchar(255) DEFAULT NULL, - `status_field` varchar(255) DEFAULT NULL, PRIMARY KEY ("name") ) ; diff --git a/frappe/desk/doctype/event/event.json b/frappe/desk/doctype/event/event.json index 8a0372b13f..59ba7689db 100644 --- a/frappe/desk/doctype/event/event.json +++ b/frappe/desk/doctype/event/event.json @@ -276,7 +276,7 @@ "icon": "fa fa-calendar", "idx": 1, "links": [], - "modified": "2019-12-12 12:58:36.621861", + "modified": "2019-12-27 14:45:51.332025", "modified_by": "Administrator", "module": "Desk", "name": "Event", @@ -310,7 +310,6 @@ "sender_field": "sender", "sort_field": "modified", "sort_order": "DESC", - "status_field": "status", "subject_field": "subject", "title_field": "subject", "track_changes": 1, diff --git a/frappe/desk/doctype/todo/todo.json b/frappe/desk/doctype/todo/todo.json index f80a785ccd..cb6dc2fc03 100644 --- a/frappe/desk/doctype/todo/todo.json +++ b/frappe/desk/doctype/todo/todo.json @@ -157,7 +157,7 @@ "icon": "fa fa-check", "idx": 2, "links": [], - "modified": "2019-12-12 12:53:17.565139", + "modified": "2019-12-27 14:45:25.161055", "modified_by": "Administrator", "module": "Desk", "name": "ToDo", @@ -191,7 +191,6 @@ "sender_field": "sender", "sort_field": "modified", "sort_order": "DESC", - "status_field": "status", "subject_field": "description", "title_field": "description", "track_changes": 1, diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 0bd4beed0b..74285e2182 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -637,24 +637,20 @@ class EmailAccount(Document): frappe.throw(_("Automatic Linking can be activated only for one Email Account.")) @frappe.whitelist() -def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None, reset_cache=False): - - if frappe.cache().hget("email_append_to", "email_append_to_doctypes") and not reset_cache: - return frappe.cache().hget("email_append_to", "email_append_to_doctypes") - +def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None): txt = txt if txt else "" email_append_to_list = [] + # Set Email Append To DocTypes via DocType for dt in frappe.get_all("DocType", filters={"istable": 0, "issingle": 0}, fields=["name", "email_append_to"]): if dt.get("email_append_to") and dt.email_append_to: email_append_to_list.append(dt.name) - else: - meta = frappe.get_meta(dt.name) - if meta.get("email_append_to") and meta.email_append_to: - email_append_to_list.append(dt.name) + + # Set Email Append To DocTypes set via Customize Form + for dt in frappe.get_list("Property Setter", filters={"property": "email_append_to", "value": 1}, fields=["doc_type"]): + email_append_to_list.append(dt.doc_type) email_append_to = [[d] for d in set(email_append_to_list) if txt in d] - frappe.cache().hset("email_append_to", "email_append_to_doctypes", email_append_to) return email_append_to From 3b517023dfd767f7ac96c7a89bcd59bf7e8f8bfc Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 13 Jan 2020 17:10:45 +0530 Subject: [PATCH 013/173] feat: make sender_field mandatory --- frappe/core/doctype/doctype/doctype.js | 2 -- frappe/core/doctype/doctype/doctype.py | 15 +++++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js index 379f7cdd9e..844d49ed21 100644 --- a/frappe/core/doctype/doctype/doctype.js +++ b/frappe/core/doctype/doctype/doctype.js @@ -54,11 +54,9 @@ frappe.ui.form.on('DocType', { }, email_append_to: function (frm) { - frm.set_df_property("subject_field", "reqd", 0); frm.set_df_property("sender_field", "reqd", 0); if (frm.doc.email_append_to) { - frm.set_df_property("subject_field", "reqd", 1); frm.set_df_property("sender_field", "reqd", 1); } }, diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index b8e0bbbe7b..9a4b09b24b 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1155,18 +1155,21 @@ def check_email_append_to(doc): doc.subject_field = doc.subject_field.strip() if doc.subject_field else None subject_field = get_field(doc, doc.subject_field) - if not (doc.subject_field or subject_field): - frappe.throw(_("Add Subject Field for creating documents from Email")) + if doc.subject_field and not subject_field: + frappe.throw(_("Select a valid Subject field for creating documents from Email")) - if subject_field.fieldtype not in ["Data", "Text", "Long Text", "Small Text", "Text Editor"]: + if subject_field and subject_field.fieldtype not in ["Data", "Text", "Long Text", "Small Text", "Text Editor"]: frappe.throw(_("Subject Field type should be Data, Text, Long Text, Small Text, Text Editor")) - # Sender Field + # Sender Field is mandatory doc.sender_field = doc.sender_field.strip() if doc.sender_field else None sender_field = get_field(doc, doc.sender_field) - if not (doc.sender_field or sender_field): - frappe.throw(_("Add Sender Field for creating documents from Email")) + if doc.sender_field and not sender_field: + frappe.throw(_("Select a valid Sender Field for creating documents from Email")) + + if not sender_field.options == "Email": + frappe.throw(_("Sender Field should have Email in options")) def get_field(doc, fieldname): From f62f80f33c0ceced29e9c245ba37ad74245b4c6e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 13 Jan 2020 23:54:47 +0530 Subject: [PATCH 014/173] fix: check if meta hasattr for subject and email --- frappe/email/doctype/email_account/email_account.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index ef8fb0ab28..ad11a50b29 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -432,7 +432,7 @@ class EmailAccount(Document): self.set_sender_field_and_subject_field() parent = self.find_parent_based_on_subject_and_sender(communication, email) - if self.append_to!="Communication": + if not self.append_to == "Communication": parent = self.create_new_parent(communication, email) if parent: @@ -447,9 +447,14 @@ class EmailAccount(Document): '''Identify the sender and subject fields from the `append_to` DocType''' # set subject_field and sender_field meta = frappe.get_meta(self.append_to) + self.subject_field = None + self.sender_field = None - self.subject_field = meta.subject_field if meta.subject_field else None - self.sender_field = meta.sender_field if meta.sender_field else None + if hasattr(meta, "subject_field"): + self.subject_field = meta.subject_field + + if hasattr(meta, "sender_field"): + self.sender_field = meta.sender_field def find_parent_based_on_subject_and_sender(self, communication, email): '''Find parent document based on subject and sender match''' From 84d740af100723bdff63099c509b09d6759b0705 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 14 Jan 2020 17:18:29 +0530 Subject: [PATCH 015/173] fix: add Email in options --- frappe/custom/doctype/customize_form/test_customize_form.py | 2 +- frappe/desk/doctype/todo/todo.json | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frappe/custom/doctype/customize_form/test_customize_form.py b/frappe/custom/doctype/customize_form/test_customize_form.py index 1cd71ea05d..cace25a03d 100644 --- a/frappe/custom/doctype/customize_form/test_customize_form.py +++ b/frappe/custom/doctype/customize_form/test_customize_form.py @@ -46,7 +46,7 @@ class TestCustomizeForm(unittest.TestCase): d = self.get_customize_form("Event") self.assertEquals(d.doc_type, "Event") - self.assertEquals(len(d.get("fields")), 35) + self.assertEquals(len(d.get("fields")), 36) d = self.get_customize_form("Event") self.assertEquals(d.doc_type, "Event") diff --git a/frappe/desk/doctype/todo/todo.json b/frappe/desk/doctype/todo/todo.json index cb6dc2fc03..15e0e4abe1 100644 --- a/frappe/desk/doctype/todo/todo.json +++ b/frappe/desk/doctype/todo/todo.json @@ -144,7 +144,8 @@ "fieldname": "sender", "fieldtype": "Data", "hidden": 1, - "label": "Sender" + "label": "Sender", + "options": "Email" }, { "fieldname": "assignment_rule", @@ -157,7 +158,7 @@ "icon": "fa fa-check", "idx": 2, "links": [], - "modified": "2019-12-27 14:45:25.161055", + "modified": "2020-01-14 17:04:36.971002", "modified_by": "Administrator", "module": "Desk", "name": "ToDo", From b2d70447fd8aa49c35924d7db28fe4a7bbba0fc6 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 14 Jan 2020 22:20:05 +0530 Subject: [PATCH 016/173] fix: update event json and check attr --- frappe/core/doctype/doctype/doctype.py | 2 +- frappe/desk/doctype/event/event.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 9a4b09b24b..a60acaaeb8 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1148,7 +1148,7 @@ def clear_linked_doctype_cache(): frappe.cache().delete_value('linked_doctypes_without_ignore_user_permissions_enabled') def check_email_append_to(doc): - if not doc.email_append_to: + if not hasattr(doc, "email_append_to") or not doc.email_append_to: return # Subject Field diff --git a/frappe/desk/doctype/event/event.json b/frappe/desk/doctype/event/event.json index 59ba7689db..5768f00f32 100644 --- a/frappe/desk/doctype/event/event.json +++ b/frappe/desk/doctype/event/event.json @@ -270,13 +270,14 @@ "fieldname": "sender", "fieldtype": "Data", "label": "Sender", + "options": "Email", "read_only": 1 } ], "icon": "fa fa-calendar", "idx": 1, "links": [], - "modified": "2019-12-27 14:45:51.332025", + "modified": "2020-01-14 21:47:15.825287", "modified_by": "Administrator", "module": "Desk", "name": "Event", From 858784d558fab178ff82db1e3d3385c8e836e950 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 19 Jan 2020 12:07:21 +0530 Subject: [PATCH 017/173] chore: revert code changes --- .../email/doctype/email_account/email_account.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index ad11a50b29..e4a3b41a56 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -426,22 +426,28 @@ class EmailAccount(Document): If no thread id is found and `append_to` is set for the email account, it will create a new parent transaction (e.g. Issue)""" - parent = self.find_parent_from_in_reply_to(communication, email) or None + parent = None + + parent = self.find_parent_from_in_reply_to(communication, email) if not parent and self.append_to: self.set_sender_field_and_subject_field() + + if not parent and self.append_to: parent = self.find_parent_based_on_subject_and_sender(communication, email) - if not self.append_to == "Communication": - parent = self.create_new_parent(communication, email) + if not parent and self.append_to and self.append_to!="Communication": + parent = self.create_new_parent(communication, email) if parent: communication.reference_doctype = parent.doctype communication.reference_name = parent.name # check if message is notification and disable notifications for this message - if email.mail.get("isnotification") and "notification" in email.mail.get("isnotification"): - communication.unread_notification_sent = 1 + isnotification = email.mail.get("isnotification") + if isnotification: + if "notification" in isnotification: + communication.unread_notification_sent = 1 def set_sender_field_and_subject_field(self): '''Identify the sender and subject fields from the `append_to` DocType''' From 230073ebf2131bfb6f176352416659703146f0d5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 19 Jan 2020 14:54:18 +0530 Subject: [PATCH 018/173] fix: change to quotes in postgres.sql file --- frappe/database/postgres/framework_postgres.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/database/postgres/framework_postgres.sql b/frappe/database/postgres/framework_postgres.sql index 16114f8cf8..26760dbcc9 100644 --- a/frappe/database/postgres/framework_postgres.sql +++ b/frappe/database/postgres/framework_postgres.sql @@ -222,9 +222,9 @@ CREATE TABLE "tabDocType" ( "allow_guest_to_view" smallint NOT NULL DEFAULT 0, "route" varchar(255) DEFAULT NULL, "is_published_field" varchar(255) DEFAULT NULL, - `email_append_to` smallint NOT NULL DEFAULT 0, - `subject_field` varchar(255) DEFAULT NULL, - `sender_field` varchar(255) DEFAULT NULL, + "email_append_to" smallint NOT NULL DEFAULT 0, + "subject_field" varchar(255) DEFAULT NULL, + "sender_field" varchar(255) DEFAULT NULL, PRIMARY KEY ("name") ) ; From a9133ebcf611f5fc4c303eca148fefa447909fef Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 31 Jan 2020 12:57:35 +0530 Subject: [PATCH 019/173] feat: Optionally trigger doc events while updating doc from notification --- frappe/email/doctype/notification/notification.json | 11 ++++++++++- frappe/email/doctype/notification/notification.py | 13 ++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/frappe/email/doctype/notification/notification.json b/frappe/email/doctype/notification/notification.json index 14eff2251a..40d8de4d29 100644 --- a/frappe/email/doctype/notification/notification.json +++ b/frappe/email/doctype/notification/notification.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_rename": 1, "autoname": "Prompt", "creation": "2014-07-11 17:18:09.923399", @@ -30,6 +31,7 @@ "property_section", "set_property_after_alert", "property_value", + "trigger_document_events", "column_break_5", "recipients", "message_sb", @@ -260,10 +262,17 @@ "fieldtype": "Link", "label": "Print Format", "options": "Print Format" + }, + { + "default": "0", + "fieldname": "trigger_document_events", + "fieldtype": "Check", + "label": "Trigger Document Events" } ], "icon": "fa fa-envelope", - "modified": "2019-07-15 13:17:02.585013", + "links": [], + "modified": "2020-01-24 11:26:48.454013", "modified_by": "Administrator", "module": "Email", "name": "Notification", diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index d40f64b8bd..a614b7e873 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -129,11 +129,14 @@ def get_context(context): allow_update = True if doc.docstatus == 1 and not doc.meta.get_field(self.set_property_after_alert).allow_on_submit: allow_update = False - - if allow_update: - frappe.db.set_value(doc.doctype, doc.name, self.set_property_after_alert, - self.property_value, update_modified = False) - doc.set(self.set_property_after_alert, self.property_value) + try: + if allow_update: + frappe.db.set_value(doc.doctype, doc.name, self.set_property_after_alert, + self.property_value, update_modified = False) + doc.set(self.set_property_after_alert, self.property_value) + doc.save() + except Exception as e: + frappe.log_error(title=_('Document update failed'), message=frappe.get_traceback()) def send_an_email(self, doc, context): from email.utils import formataddr From 8e4544567adb3fd7ad319e2175cd79702154b8ff Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 3 Feb 2020 08:11:20 +0530 Subject: [PATCH 020/173] fix: Optionally call doc.save() method --- frappe/email/doctype/notification/notification.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index a614b7e873..bdc1a4a75d 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -134,7 +134,8 @@ def get_context(context): frappe.db.set_value(doc.doctype, doc.name, self.set_property_after_alert, self.property_value, update_modified = False) doc.set(self.set_property_after_alert, self.property_value) - doc.save() + if self.trigger_document_events: + doc.save() except Exception as e: frappe.log_error(title=_('Document update failed'), message=frappe.get_traceback()) From c132938883f911e921329b236bd084245d478bd2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Feb 2020 10:41:48 +0530 Subject: [PATCH 021/173] fix: Do doc.save() on every update from notification --- frappe/email/doctype/notification/notification.json | 11 +---------- frappe/email/doctype/notification/notification.py | 5 +---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/frappe/email/doctype/notification/notification.json b/frappe/email/doctype/notification/notification.json index 40d8de4d29..14eff2251a 100644 --- a/frappe/email/doctype/notification/notification.json +++ b/frappe/email/doctype/notification/notification.json @@ -1,5 +1,4 @@ { - "actions": [], "allow_rename": 1, "autoname": "Prompt", "creation": "2014-07-11 17:18:09.923399", @@ -31,7 +30,6 @@ "property_section", "set_property_after_alert", "property_value", - "trigger_document_events", "column_break_5", "recipients", "message_sb", @@ -262,17 +260,10 @@ "fieldtype": "Link", "label": "Print Format", "options": "Print Format" - }, - { - "default": "0", - "fieldname": "trigger_document_events", - "fieldtype": "Check", - "label": "Trigger Document Events" } ], "icon": "fa fa-envelope", - "links": [], - "modified": "2020-01-24 11:26:48.454013", + "modified": "2019-07-15 13:17:02.585013", "modified_by": "Administrator", "module": "Email", "name": "Notification", diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 381c18b95a..997aba3069 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -131,11 +131,8 @@ def get_context(context): allow_update = False try: if allow_update: - frappe.db.set_value(doc.doctype, doc.name, self.set_property_after_alert, - self.property_value, update_modified = False) doc.set(self.set_property_after_alert, self.property_value) - if self.trigger_document_events: - doc.save() + doc.save() except Exception as e: frappe.log_error(title=_('Document update failed'), message=frappe.get_traceback()) From 253cc87f2426acfc5845af2139d0651e68ece18b Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Feb 2020 10:43:44 +0530 Subject: [PATCH 022/173] feat: Display system updater reference on timeline --- frappe/core/doctype/version/version.py | 6 ++- .../doctype/notification/notification.py | 4 ++ .../public/js/frappe/form/footer/timeline.js | 38 ++++++++++++------- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/frappe/core/doctype/version/version.py b/frappe/core/doctype/version/version.py index 05cc102ab9..3a97582376 100644 --- a/frappe/core/doctype/version/version.py +++ b/frappe/core/doctype/version/version.py @@ -45,7 +45,11 @@ def get_diff(old, new, for_child=False): # capture data import if set data_import = new.flags.via_data_import - out = frappe._dict(changed = [], added = [], removed = [], row_changed = [], data_import=data_import) + updater_reference = new.flags.updater_reference + + out = frappe._dict(changed = [], added = [], removed = [], + row_changed = [], data_import=data_import, updater_reference=updater_reference) + for df in new.meta.fields: if df.fieldtype in no_value_fields and df.fieldtype not in table_fields: continue diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 997aba3069..31a39724ef 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -132,6 +132,10 @@ def get_context(context): try: if allow_update: doc.set(self.set_property_after_alert, self.property_value) + doc.flags.updater_reference = { + 'doctype': self.doctype, + 'docname': self.name + } doc.save() except Exception as e: frappe.log_error(title=_('Document update failed'), message=frappe.get_traceback()) diff --git a/frappe/public/js/frappe/form/footer/timeline.js b/frappe/public/js/frappe/form/footer/timeline.js index e7f5f4023f..5b02f06728 100644 --- a/frappe/public/js/frappe/form/footer/timeline.js +++ b/frappe/public/js/frappe/form/footer/timeline.js @@ -560,12 +560,24 @@ frappe.ui.form.Timeline = class Timeline { return; } - let data_import_link = frappe.utils.get_form_link( - 'Data Import Beta', - data.data_import, - true, - __('via Data Import') - ); + let updater_reference_link = null; + + if (data.data_import) { + updater_reference_link = frappe.utils.get_form_link( + 'Data Import Beta', + data.data_import, + true, + __('via Data Import') + ); + } else if (!$.isEmptyObject(data.updater_reference)) { + let updater_reference = data.updater_reference; + updater_reference_link = frappe.utils.get_form_link( + updater_reference.doctype, + updater_reference.docname, + true, + __('via {0}', [updater_reference.doctype]) + ); + } // value changed in parent if (data.changed && data.changed.length) { @@ -573,13 +585,13 @@ frappe.ui.form.Timeline = class Timeline { data.changed.every(function(p) { if (p[0]==='docstatus') { if (p[2]==1) { - let message = data.data_import - ? __('submitted this document {0}', [data_import_link]) + let message = updater_reference_link + ? __('submitted this document {0}', [updater_reference_link]) : __('submitted this document'); out.push(me.get_version_comment(version, message)); } else if (p[2]==2) { - let message = data.data_import - ? __('cancelled this document {0}', [data_import_link]) + let message = updater_reference_link + ? __('cancelled this document {0}', [updater_reference_link]) : __('cancelled this document'); out.push(me.get_version_comment(version, message)); } @@ -600,10 +612,10 @@ frappe.ui.form.Timeline = class Timeline { } return parts.length < 3; }); - if(parts.length) { + if (parts.length) { let message; - if (data.data_import) { - message = __("changed value of {0} {1}", [parts.join(', ').bold(), data_import_link]); + if (updater_reference_link) { + message = __("changed value of {0} {1}", [parts.join(', ').bold(), updater_reference_link]); } else { message = __("changed value of {0}", [parts.join(', ').bold()]); } From 503ce9a0d97d20418230ca5032d8fde6752c9b12 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 7 Feb 2020 13:14:18 +0530 Subject: [PATCH 023/173] fix: Remove Data Import specific code from timeline --- .../core/doctype/data_import/importer_new.py | 6 +++++- .../public/js/frappe/form/footer/timeline.js | 18 ++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/frappe/core/doctype/data_import/importer_new.py b/frappe/core/doctype/data_import/importer_new.py index 22c4778147..a2d82d6133 100644 --- a/frappe/core/doctype/data_import/importer_new.py +++ b/frappe/core/doctype/data_import/importer_new.py @@ -799,7 +799,11 @@ class Importer: id_fieldname = self.get_id_fieldname(self.doctype) id_value = doc[id_fieldname] existing_doc = frappe.get_doc(self.doctype, id_value) - existing_doc.flags.via_data_import = self.data_import.name + existing_doc.flags.updater_reference = { + 'doctype': self.data_import.doctype, + 'docname': self.data_import.name, + 'label': _('via Data Import') + } existing_doc.update(doc) existing_doc.save() return existing_doc diff --git a/frappe/public/js/frappe/form/footer/timeline.js b/frappe/public/js/frappe/form/footer/timeline.js index 5b02f06728..593f987a9a 100644 --- a/frappe/public/js/frappe/form/footer/timeline.js +++ b/frappe/public/js/frappe/form/footer/timeline.js @@ -562,20 +562,14 @@ frappe.ui.form.Timeline = class Timeline { let updater_reference_link = null; - if (data.data_import) { - updater_reference_link = frappe.utils.get_form_link( - 'Data Import Beta', - data.data_import, - true, - __('via Data Import') - ); - } else if (!$.isEmptyObject(data.updater_reference)) { + if (!$.isEmptyObject(data.updater_reference)) { + let label = updater_reference.label || __('via {0}', [updater_reference.doctype]); let updater_reference = data.updater_reference; updater_reference_link = frappe.utils.get_form_link( updater_reference.doctype, updater_reference.docname, true, - __('via {0}', [updater_reference.doctype]) + label ); } @@ -650,10 +644,10 @@ frappe.ui.form.Timeline = class Timeline { }); return parts.length < 3; }); - if(parts.length) { + if (parts.length) { let message; - if (data.data_import) { - message = __("changed values for {0} {1}", [parts.join(', '), data_import_link]); + if (updater_reference_link) { + message = __("changed values for {0} {1}", [parts.join(', '), updater_reference_link]); } else { message = __("changed values for {0}", [parts.join(', ')]); } From df669a88cb44ddbf912d021e01e2a436330b401b Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 7 Feb 2020 13:28:18 +0530 Subject: [PATCH 024/173] fix: Trigger notification save after doc update --- frappe/email/doctype/notification/notification.py | 5 +++-- frappe/model/document.py | 7 +++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 31a39724ef..cd8e85324a 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -134,7 +134,8 @@ def get_context(context): doc.set(self.set_property_after_alert, self.property_value) doc.flags.updater_reference = { 'doctype': self.doctype, - 'docname': self.name + 'docname': self.name, + 'label': _('via Notification') } doc.save() except Exception as e: @@ -307,7 +308,7 @@ def evaluate_alert(doc, alert, event): if event=="Value Change" and not doc.is_new(): try: - db_value = frappe.db.get_value(doc.doctype, doc.name, alert.value_changed) + db_value = doc._doc_before_save.get(alert.value_changed) except Exception as e: if frappe.db.is_missing_column(e): alert.db_set('enabled', 0) diff --git a/frappe/model/document.py b/frappe/model/document.py index 68a65e0401..68062b2d13 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -842,9 +842,7 @@ class Document(BaseDocument): if not self.flags.in_insert: # value change is not applicable in insert - event_map['validate'] = 'Value Change' - event_map['before_change'] = 'Value Change' - event_map['before_update_after_submit'] = 'Value Change' + event_map['on_change'] = 'Value Change' for alert in self.flags.notifications: event = event_map.get(method, None) @@ -941,7 +939,6 @@ class Document(BaseDocument): elif self._action=="update_after_submit": self.run_method("on_update_after_submit") - self.run_method('on_change') self.clear_cache() self.notify_update() @@ -951,6 +948,8 @@ class Document(BaseDocument): if getattr(self.meta, 'track_changes', False) and self._doc_before_save and not self.flags.ignore_version: self.save_version() + self.run_method('on_change') + if (self.doctype, self.name) in frappe.flags.currently_saving: frappe.flags.currently_saving.remove((self.doctype, self.name)) From d240acaa41a35a37c5b9c6050a4c6496cd464916 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 7 Feb 2020 14:48:35 +0530 Subject: [PATCH 025/173] fix: Value change check --- .../doctype/notification/notification.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index cd8e85324a..a766e88d55 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -307,18 +307,18 @@ def evaluate_alert(doc, alert, event): return if event=="Value Change" and not doc.is_new(): - try: - db_value = doc._doc_before_save.get(alert.value_changed) - except Exception as e: - if frappe.db.is_missing_column(e): - alert.db_set('enabled', 0) - frappe.log_error('Notification {0} has been disabled due to missing field'.format(alert.name)) - return - else: - raise - db_value = parse_val(db_value) - if (doc.get(alert.value_changed) == db_value) or (not db_value and not doc.get(alert.value_changed)): - return # value not changed + if not frappe.db.has_column(doc.doctype, alert.value_changed): + alert.db_set('enabled', 0) + frappe.log_error('Notification {0} has been disabled due to missing field'.format(alert.name)) + return + + doc_before_save = doc.get_doc_before_save() + field_value_before_save = doc_before_save.get(alert.value_changed) if doc_before_save else None + + field_value_before_save = parse_val(field_value_before_save) + if (doc.get(alert.value_changed) == field_value_before_save): + # value not changed + return if event != "Value Change" and not doc.is_new(): # reload the doc for the latest values & comments, From 592e5a88eee102ae790172ca72df4f6a63ce10bd Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 7 Feb 2020 14:53:00 +0530 Subject: [PATCH 026/173] fix: Do not translate error log title --- frappe/email/doctype/notification/notification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index a766e88d55..ad6c79131c 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -139,7 +139,7 @@ def get_context(context): } doc.save() except Exception as e: - frappe.log_error(title=_('Document update failed'), message=frappe.get_traceback()) + frappe.log_error(title='Document update failed', message=frappe.get_traceback()) def send_an_email(self, doc, context): from email.utils import formataddr From 8627cce88e13d34a85a444d0abf4d091ca9cfb07 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 19 Feb 2020 12:36:25 +0530 Subject: [PATCH 027/173] feat: added in_setup_wizard flag --- .../doctype/assignment_rule/assignment_rule.py | 2 +- .../milestone_tracker/milestone_tracker.py | 4 ++++ frappe/cache_manager.py | 18 +++++++++++++++--- frappe/desk/page/setup_wizard/setup_wizard.py | 3 +++ frappe/model/document.py | 2 +- .../energy_point_rule/energy_point_rule.py | 3 ++- 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/frappe/automation/doctype/assignment_rule/assignment_rule.py b/frappe/automation/doctype/assignment_rule/assignment_rule.py index 5d8dab90ce..0a5d85636f 100644 --- a/frappe/automation/doctype/assignment_rule/assignment_rule.py +++ b/frappe/automation/doctype/assignment_rule/assignment_rule.py @@ -165,7 +165,7 @@ def reopen_closed_assignment(doc): return True def apply(doc, method=None, doctype=None, name=None): - if frappe.flags.in_patch or frappe.flags.in_install: + if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_setup_wizard: return if not doc and doctype and name: diff --git a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py index baa1bcc075..154cb599e1 100644 --- a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py @@ -30,6 +30,10 @@ class MilestoneTracker(Document): )).insert(ignore_permissions=True) def evaluate_milestone(doc, event): + if (frappe.flags.in_install + or frappe.flags.in_migrate + or frappe.flags.in_setup_wizard): + return for d in frappe.cache_manager.get_doctype_map('Milestone Tracker', doc.doctype, dict(document_type = doc.doctype, disabled=0)): frappe.get_doc('Milestone Tracker', d.name).apply(doc) diff --git a/frappe/cache_manager.py b/frappe/cache_manager.py index 1faa02ec63..2578d652b4 100644 --- a/frappe/cache_manager.py +++ b/frappe/cache_manager.py @@ -117,7 +117,11 @@ def clear_doctype_map(doctype, name): frappe.cache().hdel(cache_key, name) def build_table_count_cache(*args, **kwargs): - if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_import: + if (frappe.flags.in_patch + or frappe.flags.in_install + or frappe.flags.in_migrate + or frappe.flags.in_import + or frappe.flags.in_setup_wizard): return _cache = frappe.cache() data = frappe.db.multisql({ @@ -138,7 +142,11 @@ def build_table_count_cache(*args, **kwargs): return counts def build_domain_restriced_doctype_cache(*args, **kwargs): - if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_import: + if (frappe.flags.in_patch + or frappe.flags.in_install + or frappe.flags.in_migrate + or frappe.flags.in_import + or frappe.flags.in_setup_wizard): return _cache = frappe.cache() active_domains = frappe.get_active_domains() @@ -149,7 +157,11 @@ def build_domain_restriced_doctype_cache(*args, **kwargs): return doctypes def build_domain_restriced_page_cache(*args, **kwargs): - if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_import: + if (frappe.flags.in_patch + or frappe.flags.in_install + or frappe.flags.in_migrate + or frappe.flags.in_import + or frappe.flags.in_setup_wizard): return _cache = frappe.cache() active_domains = frappe.get_active_domains() diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py index 43d4e8dde4..a8b4b4f280 100755 --- a/frappe/desk/page/setup_wizard/setup_wizard.py +++ b/frappe/desk/page/setup_wizard/setup_wizard.py @@ -61,6 +61,7 @@ def setup_complete(args): stages = get_setup_stages(args) try: + frappe.flags.in_setup_wizard = True current_task = None for idx, stage in enumerate(stages): frappe.publish_realtime('setup_task', {"progress": [idx, len(stages)], @@ -75,6 +76,8 @@ def setup_complete(args): else: run_setup_success(args) return {'status': 'ok'} + finally: + frappe.flags.in_setup_wizard = False def update_global_settings(args): if args.language and args.language != "English": diff --git a/frappe/model/document.py b/frappe/model/document.py index 80f18c74c4..e147bc42b0 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -268,7 +268,7 @@ class Document(BaseDocument): if hasattr(self, "__islocal"): delattr(self, "__islocal") - if not (frappe.flags.in_migrate or frappe.local.flags.in_install): + if not (frappe.flags.in_migrate or frappe.local.flags.in_install or frappe.flags.in_setup_wizard): follow_document(self.doctype, self.name, frappe.session.user) return self diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.py b/frappe/social/doctype/energy_point_rule/energy_point_rule.py index 6615c2ab1d..b603cb2b24 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -84,7 +84,8 @@ def process_energy_points(doc, state): if (frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_migrate - or frappe.flags.in_import): + or frappe.flags.in_import + or frappe.flags.in_setup_wizard): return if not is_energy_point_enabled(): From 07b0886272922d0d4d4a9729338e80a2b5687bd1 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 19 Feb 2020 12:36:37 +0530 Subject: [PATCH 028/173] feat: rebuild table count cache on trash --- frappe/hooks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/hooks.py b/frappe/hooks.py index a132eb69d5..6389985086 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -140,6 +140,7 @@ doc_events = { "frappe.social.doctype.energy_point_rule.energy_point_rule.process_energy_points" ], "after_insert": "frappe.cache_manager.build_table_count_cache", + "on_trash": "frappe.cache_manager.build_table_count_cache", }, "Event": { "after_insert": "frappe.integrations.doctype.google_calendar.google_calendar.insert_event_in_google_calendar", From 9e68e0285f7835635aacf483a0192e9152290f9e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 19 Feb 2020 12:34:07 +0530 Subject: [PATCH 029/173] feat: added timing decorator --- frappe/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frappe/__init__.py b/frappe/__init__.py index 12e5204001..e6b4000524 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -10,6 +10,8 @@ from six import iteritems, binary_type, text_type, string_types, PY2 from werkzeug.local import Local, release_local import os, sys, importlib, inspect, json from past.builtins import cmp +from functools import wraps +from time import time from faker import Faker @@ -512,6 +514,18 @@ def whitelist(allow_guest=False, xss_safe=False): return innerfn +def timing(f): + + @wraps(f) + def wrap(*args, **kw): + ts = time() + result = f(*args, **kw) + te = time() + print('TIMING: {0} > {1} took: {2:2.4f} sec'.format(f.__module__, f.__name__, te-ts)) + return result + + return wrap + def read_only(): def innfn(fn): def wrapper_fn(*args, **kwargs): From 3f056e4c6e7675dc398e6cf3ea82e3ed40bf6f06 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 19 Feb 2020 13:08:15 +0530 Subject: [PATCH 030/173] feat: enabled logging for setup wizard --- frappe/desk/page/setup_wizard/setup_wizard.py | 5 +++++ frappe/hooks.py | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py index a8b4b4f280..2db6a64e5d 100755 --- a/frappe/desk/page/setup_wizard/setup_wizard.py +++ b/frappe/desk/page/setup_wizard/setup_wizard.py @@ -352,6 +352,11 @@ def email_setup_wizard_exception(traceback, args): message=message, delayed=False) +def log_setup_wizard_exception(traceback, args): + with open('../logs/setup-wizard.log', 'w+') as setup_log: + setup_log.write(traceback) + setup_log.write(json.dumps(args)) + def get_language_code(lang): return frappe.db.get_value('Language', {'language_name':lang}) diff --git a/frappe/hooks.py b/frappe/hooks.py index 6389985086..d48ac420b1 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -257,7 +257,10 @@ bot_parsers = [ 'frappe.utils.bot.CountBot' ] -setup_wizard_exception = "frappe.desk.page.setup_wizard.setup_wizard.email_setup_wizard_exception" +setup_wizard_exception = [ + "frappe.desk.page.setup_wizard.setup_wizard.email_setup_wizard_exception", + "frappe.desk.page.setup_wizard.setup_wizard.log_setup_wizard_exception" +] before_migrate = ['frappe.patches.v11_0.sync_user_permission_doctype_before_migrate.execute'] after_migrate = ['frappe.website.doctype.website_theme.website_theme.generate_theme_files_if_not_exist'] From 2e6e32bfc20726e7cb31b48c53073bbc6f366664 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 24 Feb 2020 10:51:59 +0530 Subject: [PATCH 031/173] fix: Avoid recursive save --- frappe/email/doctype/notification/notification.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index ad6c79131c..582cb5d3c4 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -130,14 +130,16 @@ def get_context(context): if doc.docstatus == 1 and not doc.meta.get_field(self.set_property_after_alert).allow_on_submit: allow_update = False try: - if allow_update: + if allow_update and not doc.flags.in_notification_update: doc.set(self.set_property_after_alert, self.property_value) doc.flags.updater_reference = { 'doctype': self.doctype, 'docname': self.name, 'label': _('via Notification') } - doc.save() + doc.flags.in_notification_update = True + doc.save(ignore_permissions=True) + doc.flags.in_notification_update = False except Exception as e: frappe.log_error(title='Document update failed', message=frappe.get_traceback()) @@ -323,7 +325,7 @@ def evaluate_alert(doc, alert, event): if event != "Value Change" and not doc.is_new(): # reload the doc for the latest values & comments, # except for validate type event. - doc = frappe.get_doc(doc.doctype, doc.name) + doc.reload() alert.send(doc) except TemplateError: frappe.throw(_("Error while evaluating Notification {0}. Please fix your template.").format(alert)) From ca815a8776e2cdd2da833e05fecc4070bae5bba1 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 6 Mar 2020 21:40:51 +0530 Subject: [PATCH 032/173] feat: add flag minimizable to msgprint and throw --- frappe/__init__.py | 9 ++++++--- frappe/public/js/frappe/form/linked_with.js | 1 - frappe/public/js/frappe/router.js | 2 +- frappe/public/js/frappe/ui/messages.js | 5 +++-- frappe/public/less/desk.less | 5 ++++- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index b6f8fa8d9c..895798dcab 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -289,7 +289,7 @@ def log(msg): debug_log.append(as_unicode(msg)) -def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, alert=False, primary_action=None): +def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, alert=False, primary_action=None, is_minimizable=None): """Print a message to the user (via HTTP response). Messages are sent in the `__server_messages` property in the response JSON and shown in a pop-up / modal. @@ -344,6 +344,9 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, if indicator: out.indicator = indicator + if is_minimizable: + out.is_minimizable = is_minimizable + if alert: out.alert = 1 @@ -374,12 +377,12 @@ def clear_last_message(): if len(local.message_log) > 0: local.message_log = local.message_log[:-1] -def throw(msg, exc=ValidationError, title=None): +def throw(msg, exc=ValidationError, title=None, is_minimizable=None): """Throw execption and show message (`msgprint`). :param msg: Message. :param exc: Exception class. Default `frappe.ValidationError`""" - msgprint(msg, raise_exception=exc, title=title, indicator='red') + msgprint(msg, raise_exception=exc, title=title, indicator='red', is_minimizable=is_minimizable) def emit_js(js, user=False, **kwargs): if user == False: diff --git a/frappe/public/js/frappe/form/linked_with.js b/frappe/public/js/frappe/form/linked_with.js index e52e3f9b28..d8e07f8303 100644 --- a/frappe/public/js/frappe/form/linked_with.js +++ b/frappe/public/js/frappe/form/linked_with.js @@ -23,7 +23,6 @@ frappe.ui.form.LinkedWith = class LinkedWith { make_dialog() { this.dialog = new frappe.ui.Dialog({ - hide_on_page_refresh: true, title: __("Linked With") }); diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index fa91f58fbb..d60a0c9d7c 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -201,7 +201,7 @@ $(window).on('hashchange', function() { return; // hide open dialog - if(window.cur_dialog && cur_dialog.hide_on_page_refresh) { + if(window.cur_dialog) { if (!cur_dialog.minimizable) { cur_dialog.hide(); } else if (!cur_dialog.is_minimized) { diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index 2265203ef9..e96d147860 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -79,7 +79,7 @@ frappe.prompt = function(fields, callback, title, primary_label) { return d; } -frappe.msgprint = function(msg, title) { +frappe.msgprint = function(msg, title, minimizable) { if(!msg) return; if($.isPlainObject(msg)) { @@ -117,7 +117,8 @@ frappe.msgprint = function(msg, title) { frappe.msg_dialog.custom_onhide(); } frappe.msg_dialog.msg_area.empty(); - } + }, + minimizable: data.is_minimizable || minimizable }); // class "msgprint" is used in tests diff --git a/frappe/public/less/desk.less b/frappe/public/less/desk.less index 6736fcc3c4..bc06ca7e5f 100644 --- a/frappe/public/less/desk.less +++ b/frappe/public/less/desk.less @@ -1132,7 +1132,7 @@ body.no-sidebar { white-space: nowrap; } -.modal-minimize { +.modal-minimize { position: initial; .modal-backdrop { display: none; @@ -1144,6 +1144,9 @@ body.no-sidebar { bottom: 0; margin: 0; max-width: 500px; + .modal-content { + min-height: 0; + } } .modal-body { display: none; From a9fcbf83d5aaaef5247459c51a00bd53ecc89210 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 6 Mar 2020 21:42:44 +0530 Subject: [PATCH 033/173] fix: use same flag name --- frappe/public/js/frappe/ui/messages.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index e96d147860..c25dbd7076 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -79,7 +79,7 @@ frappe.prompt = function(fields, callback, title, primary_label) { return d; } -frappe.msgprint = function(msg, title, minimizable) { +frappe.msgprint = function(msg, title, is_minimizable) { if(!msg) return; if($.isPlainObject(msg)) { @@ -118,7 +118,7 @@ frappe.msgprint = function(msg, title, minimizable) { } frappe.msg_dialog.msg_area.empty(); }, - minimizable: data.is_minimizable || minimizable + minimizable: data.is_minimizable || is_minimizable }); // class "msgprint" is used in tests From 7e6a22ac72a64b90daa84992acb9b39c10dd3163 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 6 Mar 2020 21:54:17 +0530 Subject: [PATCH 034/173] feat: add button to go to list in customize form --- frappe/custom/doctype/customize_form/customize_form.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 63b094615a..5c9fa37ef5 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -85,6 +85,10 @@ frappe.ui.form.on("Customize Form", { if(frm.doc.doc_type) { frappe.customize_form.set_primary_action(frm); + frm.add_custom_button(__('Go to {0} List', [frm.doc.doc_type]), function() { + frappe.set_route('List', frm.doc.doc_type); + }); + frm.add_custom_button(__('Refresh Form'), function() { frm.script_manager.trigger("doc_type"); }, "fa fa-refresh", "btn-default"); From fcb54701510fddf8ac511c9a16d5835333c932af Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 11 Mar 2020 12:32:40 +0530 Subject: [PATCH 035/173] fix: use tabs --- frappe/__init__.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index e6b4000524..7cad075e90 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -515,16 +515,14 @@ def whitelist(allow_guest=False, xss_safe=False): return innerfn def timing(f): - - @wraps(f) - def wrap(*args, **kw): - ts = time() - result = f(*args, **kw) - te = time() - print('TIMING: {0} > {1} took: {2:2.4f} sec'.format(f.__module__, f.__name__, te-ts)) - return result - - return wrap + @wraps(f) + def wrap(*args, **kw): + ts = time() + result = f(*args, **kw) + te = time() + print('TIMING: {0} > {1} took: {2:2.4f} sec'.format(f.__module__, f.__name__, te-ts)) + return result + return wrap def read_only(): def innfn(fn): From 3389042656014c79b7c12482daaec7786d492ccf Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 12 Mar 2020 14:33:50 +0530 Subject: [PATCH 036/173] fix: currency field not found in print formats --- frappe/model/meta.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 927a56b6b8..fafaefbfd1 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -529,7 +529,9 @@ def get_field_currency(df, doc=None): if currency: ref_docname = doc.name else: - currency = frappe.db.get_value(doc.parenttype, doc.parent, df.get("options")) + if frappe.get_meta(doc.parenttype).has_field(df.get("options")): + # only get_value if parent has currency field + currency = frappe.db.get_value(doc.parenttype, doc.parent, df.get("options")) if currency: frappe.local.field_currency.setdefault((doc.doctype, ref_docname), frappe._dict())\ From 1c5ee0530014d696ec77a20741cfd731cc814639 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Thu, 12 Mar 2020 18:27:29 +0530 Subject: [PATCH 037/173] Revert __init__.py --- frappe/__init__.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 7cad075e90..f942e53018 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -10,8 +10,6 @@ from six import iteritems, binary_type, text_type, string_types, PY2 from werkzeug.local import Local, release_local import os, sys, importlib, inspect, json from past.builtins import cmp -from functools import wraps -from time import time from faker import Faker @@ -439,7 +437,7 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message :param recipients: List of recipients. - :param sender: Email sender. Default is current user. + :param sender: Email sender. Default is current user or default outgoing account. :param subject: Email Subject. :param message: (or `content`) Email Content. :param as_markdown: Convert content markdown to HTML. @@ -461,7 +459,6 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message :param args: Arguments for rendering the template :param header: Append header in email """ - text_content = None if template: message, text_content = get_email_from_template(template, args) @@ -514,16 +511,6 @@ def whitelist(allow_guest=False, xss_safe=False): return innerfn -def timing(f): - @wraps(f) - def wrap(*args, **kw): - ts = time() - result = f(*args, **kw) - te = time() - print('TIMING: {0} > {1} took: {2:2.4f} sec'.format(f.__module__, f.__name__, te-ts)) - return result - return wrap - def read_only(): def innfn(fn): def wrapper_fn(*args, **kwargs): @@ -556,7 +543,7 @@ def only_for(roles, message=False): myroles = set(get_roles()) if not roles.intersection(myroles): if message: - msgprint(_('Only for {}').format(', '.join(roles))) + msgprint(_('This action is only allowed for {}').format(bold(', '.join(roles))), _('Not Permitted')) raise PermissionError def get_domain_data(module): From 52eb708cc53f670bf2ffdc3f41fb10605ac33b77 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Thu, 12 Mar 2020 18:42:05 +0530 Subject: [PATCH 038/173] style: Remove extra space --- frappe/public/less/desk.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/less/desk.less b/frappe/public/less/desk.less index 58be4d2e1b..6d44fc5192 100644 --- a/frappe/public/less/desk.less +++ b/frappe/public/less/desk.less @@ -1136,7 +1136,7 @@ body.no-sidebar { white-space: nowrap; } -.modal-minimize { +.modal-minimize { position: initial; .modal-backdrop { display: none; From b937311ab3ed32ec4be25e043a958a7adfc5126e Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Thu, 12 Mar 2020 20:07:27 +0530 Subject: [PATCH 039/173] chore(mergify): configuration update (#9682) --- .mergify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index d8f1c09bee..d810898eee 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -3,7 +3,7 @@ pull_request_rules: conditions: - status-success=Codacy/PR Quality Review - status-success=Semantic Pull Request - - status-success=continuous-integration/travis-ci/pr + - status-success=Travis CI - Pull Request - status-success=security/snyk - package.json (frappe) - status-success=security/snyk - requirements.txt (frappe) - label!=don't-merge @@ -16,7 +16,7 @@ pull_request_rules: conditions: - status-success=Codacy/PR Quality Review - status-success=Semantic Pull Request - - status-success=continuous-integration/travis-ci/pr + - status-success=Travis CI - Pull Request - status-success=security/snyk - package.json (frappe) - status-success=security/snyk - requirements.txt (frappe) - label!=don't-merge From 1e1cc1b6c0e840a76cef9d169e89e9da83488c42 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 11:57:34 +0530 Subject: [PATCH 040/173] fix(dashboard chart): Hide filters if hide_actions is set (#9679) * refactor: remove print statement * fix: hide filters if hide_actions is set * refactor (cyoress): wait after clearing field Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- cypress/support/commands.js | 2 +- frappe/desk/desktop.py | 1 - frappe/public/js/frappe/ui/dashboard_chart.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 02f0bf236e..2d31d9a988 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -180,7 +180,7 @@ Cypress.Commands.add('fill_field', (fieldname, value, fieldtype = 'Data') => { cy.get('.datepickers-container .datepicker.active').should('exist'); } if (fieldtype === 'Time') { - cy.get('@input').clear(); + cy.get('@input').clear().wait(200); } if (fieldtype === 'Select') { diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 65febe3595..6a0d5acc37 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -78,7 +78,6 @@ class Workspace: cards = self.doc.cards + get_custom_reports_and_doctypes(self.doc.module) if len(self.extended_cards): cards = cards + self.extended_cards - print(cards) default_country = frappe.db.get_default("country") def _doctype_contains_a_record(name): diff --git a/frappe/public/js/frappe/ui/dashboard_chart.js b/frappe/public/js/frappe/ui/dashboard_chart.js index cc19c707f3..45150fe81c 100644 --- a/frappe/public/js/frappe/ui/dashboard_chart.js +++ b/frappe/public/js/frappe/ui/dashboard_chart.js @@ -14,9 +14,9 @@ frappe.ui.DashboardChart = class DashboardChart { this.get_settings().then(() => { this.prepare_chart_object(); this.prepare_container(); - this.setup_filter_button(); if (!this.options.hide_actions || this.options.hide_actions == undefined) { + this.setup_filter_button(); if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { this.render_time_series_filters(); } From fcdb923d2edb4d7ebf1232c90e52f08467c9e580 Mon Sep 17 00:00:00 2001 From: Andy Zhu Date: Fri, 13 Mar 2020 20:36:36 +1300 Subject: [PATCH 041/173] fix: Missing bucket name check (#9546) * fix: missing bucket name check when user make changes on s3 backup setting Problem: If the user changed the backup limit, then press save. The validate function will give an error message that the bucket name already exists. It would be inconvenient for the user to use a different bucket name to save any changes. So I implemented a flag ''bucket_name_exist'' to indicate if the bucket name exists, if not, then go to the flow of trying to create a bucket. * fix: extra line removed * fix: Use head_bucket Boto3 API 1. Head_bucket will return 200 Ok if the bucket exists and you have permission to access it. 2. Error code 403 Forbidden, Error code 404 Not Found. 3. Use bucket_name_exist to check if need to create bucket. Thanks @Mangesh-Khairnar suggestions. Reference: 1. https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.head_bucket 2. https://boto3.amazonaws.com/v1/documentation/api/latest/guide/migrations3.html#accessing-a-bucket Further improvements: 1. Use 'GET' Requestion to check if the Access Key ID and Secret Access Key is valid (Because AWS tier has 20,000 GET requests while only 2,000 LIST requests) 2. Edge case on Error prompts when head_bucket returns an error code other than '403' or '404'. * fix: add an extra line to align with original code style * Update frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py Co-Authored-By: Chinmay Pai * fix: remove the flag and redundant exception When we got a 404 error, we can just create the bucket as 1. The bucket name does not exist in the current bucket. 2. we have permission to access the bucket. * Update frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py Co-Authored-By: Himanshu * Update frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py Co-Authored-By: Chinmay Pai * fix: missing handling the error code '400' - 'Bad Request' * fix: applied with DeepSource analysis 1. Lines too long 2. Doc Lines too long 3. Expected 2 blank lines between class and method 4. Unused variable removed Co-authored-by: Chinmay Pai Co-authored-by: Himanshu --- .../s3_backup_settings/s3_backup_settings.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py index bf1821d04b..55b9e63a4d 100755 --- a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py @@ -35,10 +35,16 @@ class S3BackupSettings(Document): frappe.throw(_("Invalid Access Key ID or Secret Access Key.")) try: - conn.create_bucket(Bucket=bucket_lower, CreateBucketConfiguration={ - 'LocationConstraint': self.region}) - except ClientError: - frappe.throw(_("Unable to create bucket: {0}. Change it to a more unique name.").format(bucket_lower)) + # Head_bucket returns a 200 OK if the bucket exists and have access to it. + conn.head_bucket(Bucket=bucket_lower) + except ClientError as e: + error_code = e.response['Error']['Code'] + if error_code == '403': + frappe.throw(_("Do not have permission to access {0} bucket.").format(bucket_lower)) + else: # '400'-Bad request or '404'-Not Found return + # try to create bucket + conn.create_bucket(Bucket=bucket_lower, CreateBucketConfiguration={ + 'LocationConstraint': self.region}) @frappe.whitelist() From 6a25a33d4998e70908950cfa689fc8a8db2a7285 Mon Sep 17 00:00:00 2001 From: gavin Date: Fri, 13 Mar 2020 15:02:47 +0530 Subject: [PATCH 042/173] fix: delete as much indexes from each table (#9684) in cases of customization, errors such as pymysql.err.InternalError: (1091, "Can't DROP 'unique_item'; check that column/key exists") may rise up --- .../patches/v12_0/delete_duplicate_indexes.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/frappe/patches/v12_0/delete_duplicate_indexes.py b/frappe/patches/v12_0/delete_duplicate_indexes.py index 7f9e4369a2..ea73d49efc 100644 --- a/frappe/patches/v12_0/delete_duplicate_indexes.py +++ b/frappe/patches/v12_0/delete_duplicate_indexes.py @@ -1,12 +1,14 @@ import frappe +from pymysql import InternalError # This patch deletes all the duplicate indexes created for same column # The patch only checks for indexes with UNIQUE constraints def execute(): - if frappe.db.db_type != 'mariadb': return - all_tables = frappe.db.get_tables() + if frappe.db.db_type != 'mariadb': + return + all_tables = frappe.db.get_tables() final_deletion_map = frappe._dict() for table in all_tables: @@ -34,11 +36,14 @@ def execute(): # build drop index query for (table_name, index_list) in final_deletion_map.items(): - query = "ALTER TABLE `{}` ".format(table_name) - query_parts = [] + query_list = [] + alter_query = "ALTER TABLE `{}`".format(table_name) + for index in index_list: - query_parts.append("DROP INDEX `{}`".format(index)) + query_list.append("{} DROP INDEX `{}`".format(alter_query, index)) - query = query + ', '.join(query_parts) - - frappe.db.sql(query) + for query in query_list: + try: + frappe.db.sql(query) + except InternalError: + pass From 839114b7ff67c2ca3a2b795bd5b6c29040bb351b Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 13 Mar 2020 15:10:59 +0530 Subject: [PATCH 043/173] fix: Add db-password option to new-site (#9685) --- frappe/commands/site.py | 9 +++++---- frappe/installer.py | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index eb5aed4a2e..fd43cc8cf3 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -12,6 +12,7 @@ from six import text_type @click.command('new-site') @click.argument('site') @click.option('--db-name', help='Database name') +@click.option('--db-password', help='Database password') @click.option('--db-type', default='mariadb', type=click.Choice(['mariadb', 'postgres']), help='Optional "postgres" or "mariadb". Default is "mariadb"') @click.option('--db-host', help='Database Host') @click.option('--db-port', type=int, help='Database Port') @@ -25,21 +26,21 @@ from six import text_type @click.option('--install-app', multiple=True, help='Install app after installation') def new_site(site, mariadb_root_username=None, mariadb_root_password=None, admin_password=None, verbose=False, install_apps=None, source_sql=None, force=None, no_mariadb_socket=False, - install_app=None, db_name=None, db_type=None, db_host=None, db_port=None): + install_app=None, db_name=None, db_password=None, db_type=None, db_host=None, db_port=None): "Create a new site" frappe.init(site=site, new_site=True) _new_site(db_name, site, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, admin_password=admin_password, verbose=verbose, install_apps=install_app, source_sql=source_sql, force=force, - no_mariadb_socket=no_mariadb_socket, db_type=db_type, db_host=db_host, db_port=db_port) + no_mariadb_socket=no_mariadb_socket, db_password=db_password, db_type=db_type, db_host=db_host, db_port=db_port) if len(frappe.utils.get_sites()) == 1: use(site) def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=None, admin_password=None, verbose=False, install_apps=None, source_sql=None, force=False, - no_mariadb_socket=False, reinstall=False, db_type=None, db_host=None, db_port=None): + no_mariadb_socket=False, reinstall=False, db_password=None, db_type=None, db_host=None, db_port=None): """Install a new Frappe site""" if not force and os.path.exists(site): @@ -73,7 +74,7 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N install_db(root_login=mariadb_root_username, root_password=mariadb_root_password, db_name=db_name, admin_password=admin_password, verbose=verbose, - source_sql=source_sql, force=force, reinstall=reinstall, db_type=db_type, db_host=db_host, db_port=db_port, no_mariadb_socket=no_mariadb_socket) + source_sql=source_sql, force=force, reinstall=reinstall, db_password=db_password, db_type=db_type, db_host=db_host, db_port=db_port, no_mariadb_socket=no_mariadb_socket) apps_to_install = ['frappe'] + (frappe.conf.get("install_apps") or []) + (list(install_apps) or []) for app in apps_to_install: diff --git a/frappe/installer.py b/frappe/installer.py index f995e6eff5..54402f0087 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -22,12 +22,12 @@ from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs def install_db(root_login="root", root_password=None, db_name=None, source_sql=None, admin_password=None, verbose=True, force=0, site_config=None, reinstall=False, - db_type=None, db_host=None, db_port=None, no_mariadb_socket=False): + db_password=None, db_type=None, db_host=None, db_port=None, no_mariadb_socket=False): if not db_type: db_type = frappe.conf.db_type or 'mariadb' - make_conf(db_name, site_config=site_config, db_type=db_type, db_host=db_host, db_port=db_port) + make_conf(db_name, site_config=site_config, db_password=db_password, db_type=db_type, db_host=db_host, db_port=db_port) frappe.flags.in_install_db = True frappe.flags.root_login = root_login From c5c9ae46e605977101ee6d5f53552d621306ded1 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 6 Mar 2020 19:46:20 +0530 Subject: [PATCH 044/173] feat: change fieldtype in db with customize form --- .../doctype/customize_form/customize_form.py | 32 +++++++++++++++++-- frappe/database/schema.py | 8 +++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 8d47a075ba..b35bfddf76 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -166,11 +166,10 @@ class CustomizeForm(Document): self.flags.update_db = False self.flags.rebuild_doctype_for_global_search = False - + validate_fields_for_doctype(self.doc_type) self.set_property_setters() self.update_custom_fields() self.set_name_translation() - validate_fields_for_doctype(self.doc_type) if self.flags.update_db: frappe.db.updatedb(self.doc_type) @@ -362,13 +361,42 @@ class CustomizeForm(Document): def validate_fieldtype_change(self, df, old_value, new_value): allowed = False + self.check_length_for_fieldtypes = [] for allowed_changes in allowed_fieldtype_change: if (old_value in allowed_changes and new_value in allowed_changes): allowed = True + self.flags.update_db = True + if frappe.db.type_map.get(old_value)[1] > frappe.db.type_map.get(new_value)[1]: + + self.check_length_for_fieldtypes.append({'df': df, 'old_value': old_value}) + self.validate_fieldtype_length() break if not allowed: frappe.throw(_("Fieldtype cannot be changed from {0} to {1} in row {2}").format(old_value, new_value, df.idx)) + def validate_fieldtype_length(self): + for field in self.check_length_for_fieldtypes: + df = field.get('df') + max_length = frappe.db.type_map.get(df.fieldtype)[1] + fieldname = df.fieldname + docs = frappe.db.sql('''select name, {fieldname}, length({fieldname}) as len + from `tab{doctype}` + where length({fieldname}) > {max_length} + '''.format( + fieldname = fieldname, + doctype = self.doc_type, + max_length = max_length + ), as_dict = True) + links = [] + label = df.label + for doc in docs: + links.append(frappe.utils.get_link_to_form(self.doc_type, doc.name)) + links_str = ', '.join(links) + + if len(docs): + frappe.throw(_('Value for field {label} is too long in {links_str}. Length should be lesser than {max_length}') + .format(label=label, max_length=max_length, links_str=links_str), title='Data Too Long') + def reset_to_defaults(self): if not self.doc_type: return diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 88cda9340b..73bdf32761 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -69,6 +69,7 @@ class DBTable: lengths = {} precisions = {} uniques = {} + fieldtype = '' # optional fields like _comments if not self.meta.istable: @@ -100,7 +101,7 @@ class DBTable: filters={ "doc_type": self.doctype, "doctype_or_field": "DocField", - "property": ["in", ["precision", "length", "unique"]] + "property": ["in", ["precision", "length", "unique", "fieldtype"]] }): if ps.property=="length": @@ -112,10 +113,13 @@ class DBTable: elif ps.property=="unique": uniques[ps.field_name] = cint(ps.value) + if ps.property=="fieldtype": + fieldtype = ps.value + for f in fl: self.columns[f['fieldname']] = DbColumn(self, f['fieldname'], - f['fieldtype'], + fieldtype or f['fieldtype'], lengths.get(f["fieldname"]) or f.get('length'), f.get('default'), f.get('search_index'), From 7bb014ee9a4a7b61c8ccf13ab5e84b8b5c5fe5a1 Mon Sep 17 00:00:00 2001 From: prssanna Date: Sat, 7 Mar 2020 15:15:12 +0530 Subject: [PATCH 045/173] fix: update db type map --- frappe/custom/doctype/customize_form/customize_form.py | 10 ++++++---- frappe/database/mariadb/database.py | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index b35bfddf76..a38e8f4fa7 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -166,10 +166,10 @@ class CustomizeForm(Document): self.flags.update_db = False self.flags.rebuild_doctype_for_global_search = False - validate_fields_for_doctype(self.doc_type) self.set_property_setters() self.update_custom_fields() self.set_name_translation() + validate_fields_for_doctype(self.doc_type) if self.flags.update_db: frappe.db.updatedb(self.doc_type) @@ -365,11 +365,11 @@ class CustomizeForm(Document): for allowed_changes in allowed_fieldtype_change: if (old_value in allowed_changes and new_value in allowed_changes): allowed = True - self.flags.update_db = True if frappe.db.type_map.get(old_value)[1] > frappe.db.type_map.get(new_value)[1]: - self.check_length_for_fieldtypes.append({'df': df, 'old_value': old_value}) self.validate_fieldtype_length() + else: + self.flags.update_db = True break if not allowed: frappe.throw(_("Fieldtype cannot be changed from {0} to {1} in row {2}").format(old_value, new_value, df.idx)) @@ -394,8 +394,10 @@ class CustomizeForm(Document): links_str = ', '.join(links) if len(docs): - frappe.throw(_('Value for field {label} is too long in {links_str}. Length should be lesser than {max_length}') + frappe.throw(_('Value for field {label} is too long in {links_str}. Length should be lesser than {max_length} characters') .format(label=label, max_length=max_length, links_str=links_str), title='Data Too Long') + else: + self.flags.update_db = True def reset_to_defaults(self): if not self.doc_type: diff --git a/frappe/database/mariadb/database.py b/frappe/database/mariadb/database.py index cd053569f0..926425f857 100644 --- a/frappe/database/mariadb/database.py +++ b/frappe/database/mariadb/database.py @@ -33,7 +33,7 @@ class MariaDBDatabase(Database): 'Float': ('decimal', '18,6'), 'Percent': ('decimal', '18,6'), 'Check': ('int', '1'), - 'Small Text': ('text', ''), + 'Small Text': ('text', 65535), 'Long Text': ('longtext', ''), 'Code': ('longtext', ''), 'Text Editor': ('longtext', ''), @@ -42,7 +42,7 @@ class MariaDBDatabase(Database): 'Date': ('date', ''), 'Datetime': ('datetime', '6'), 'Time': ('time', '6'), - 'Text': ('text', ''), + 'Text': ('text', 65535), 'Data': ('varchar', self.VARCHAR_LEN), 'Link': ('varchar', self.VARCHAR_LEN), 'Dynamic Link': ('varchar', self.VARCHAR_LEN), From a8861c8ed40a07f2136aa564954ad17967bbc543 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 13 Mar 2020 15:14:54 +0530 Subject: [PATCH 046/173] fix: code formatting --- .../custom/doctype/customize_form/customize_form.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index a38e8f4fa7..61d00984fd 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -379,9 +379,10 @@ class CustomizeForm(Document): df = field.get('df') max_length = frappe.db.type_map.get(df.fieldtype)[1] fieldname = df.fieldname - docs = frappe.db.sql('''select name, {fieldname}, length({fieldname}) as len - from `tab{doctype}` - where length({fieldname}) > {max_length} + docs = frappe.db.sql(''' + SELECT name, {fieldname}, LENGTH({fieldname}) AS len + FROM `tab{doctype}` + WHERE LENGTH({fieldname}) > {max_length} '''.format( fieldname = fieldname, doctype = self.doc_type, @@ -394,8 +395,8 @@ class CustomizeForm(Document): links_str = ', '.join(links) if len(docs): - frappe.throw(_('Value for field {label} is too long in {links_str}. Length should be lesser than {max_length} characters') - .format(label=label, max_length=max_length, links_str=links_str), title='Data Too Long') + frappe.throw(_('Value for field {0} is too long in {1}. Length should be lesser than {2} characters') + .format(frappe.bold(label), links_str, frappe.bold(max_length)), title='Data Too Long') else: self.flags.update_db = True From 83677236f55cc0b58a0ab42b7e87d1a0257e09f3 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 13 Mar 2020 15:23:17 +0530 Subject: [PATCH 047/173] fix: set is_minimizable as true for error dialog --- frappe/custom/doctype/customize_form/customize_form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 61d00984fd..0cef12fd7e 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -396,7 +396,7 @@ class CustomizeForm(Document): if len(docs): frappe.throw(_('Value for field {0} is too long in {1}. Length should be lesser than {2} characters') - .format(frappe.bold(label), links_str, frappe.bold(max_length)), title='Data Too Long') + .format(frappe.bold(label), links_str, frappe.bold(max_length)), title='Data Too Long', is_minimizable=True) else: self.flags.update_db = True From 35ae0244ae7c38388b188b05d5758ff683e2c5b1 Mon Sep 17 00:00:00 2001 From: Prssanna Desai Date: Fri, 13 Mar 2020 17:18:02 +0530 Subject: [PATCH 048/173] fix: translate dialog title Co-Authored-By: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- frappe/custom/doctype/customize_form/customize_form.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 0cef12fd7e..c8d1bb18b4 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -394,11 +394,11 @@ class CustomizeForm(Document): links.append(frappe.utils.get_link_to_form(self.doc_type, doc.name)) links_str = ', '.join(links) - if len(docs): - frappe.throw(_('Value for field {0} is too long in {1}. Length should be lesser than {2} characters') - .format(frappe.bold(label), links_str, frappe.bold(max_length)), title='Data Too Long', is_minimizable=True) - else: - self.flags.update_db = True + if docs: + frappe.throw(_('Value for field {0} is too long in {1}. Length should be lesser than {2} characters') + .format(frappe.bold(label), links_str, frappe.bold(max_length)), title=_('Data Too Long'), is_minimizable=len(docs) > 1) + + self.flags.update_db = True def reset_to_defaults(self): if not self.doc_type: From d7fd4ecfcc1cc0d95319c2c9e3130b5366476a49 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:26:11 +0530 Subject: [PATCH 049/173] refactor: move widgets to a separate folder --- .../js/frappe/views/widgets/chart_widget.js | 60 ------------------- .../frappe/{views => }/widgets/base_widget.js | 4 +- .../{views => }/widgets/links_widget.js | 0 .../{views => }/widgets/onboarding_widget.js | 0 .../{views => }/widgets/shortcut_widget.js | 0 .../js/frappe/{views => }/widgets/utils.js | 0 .../{views => }/widgets/widget_group.js | 6 +- 7 files changed, 8 insertions(+), 62 deletions(-) delete mode 100644 frappe/public/js/frappe/views/widgets/chart_widget.js rename frappe/public/js/frappe/{views => }/widgets/base_widget.js (93%) rename frappe/public/js/frappe/{views => }/widgets/links_widget.js (100%) rename frappe/public/js/frappe/{views => }/widgets/onboarding_widget.js (100%) rename frappe/public/js/frappe/{views => }/widgets/shortcut_widget.js (100%) rename frappe/public/js/frappe/{views => }/widgets/utils.js (100%) rename frappe/public/js/frappe/{views => }/widgets/widget_group.js (96%) diff --git a/frappe/public/js/frappe/views/widgets/chart_widget.js b/frappe/public/js/frappe/views/widgets/chart_widget.js deleted file mode 100644 index 25a70fb525..0000000000 --- a/frappe/public/js/frappe/views/widgets/chart_widget.js +++ /dev/null @@ -1,60 +0,0 @@ -import Widget from "./base_widget.js"; - -export default class ChartWidget extends Widget { - constructor(opts) { - super(opts); - } - - refresh() { - // - } - - customize() { - this.setup_customize_actions(); - } - - make_chart() { - this.body.empty() - frappe.model.with_doc("Dashboard Chart", this.chart_name).then(chart_doc => { - chart_doc.width = 'Full' - this.dashboard = new frappe.ui.DashboardChart(chart_doc, this.body, { hide_title: true, hide_last_sync: true, hide_actions: true }); - this.dashboard.show(); - }); - - this.summary && this.set_summary(); - } - - set_body() { - this.widget.addClass('dashboard-widget-box') - this.make_chart(); - } - - set_summary() { - let summary = $(`$ 54,231`); - this.title_field.addClass('text-muted') - summary.appendTo(this.body); - } - - setup_events() { - // - } - - setup_customize_actions() { - this.action_area.empty() - const buttons = $(` - `); - buttons.appendTo(this.action_area); - } - - set_actions() { - return - this.action_area.empty() - const buttons = $(`
- - - -
- `); - buttons.appendTo(this.action_area); - } -} \ No newline at end of file diff --git a/frappe/public/js/frappe/views/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js similarity index 93% rename from frappe/public/js/frappe/views/widgets/base_widget.js rename to frappe/public/js/frappe/widgets/base_widget.js index 1a082f7615..f0d6a22c53 100644 --- a/frappe/public/js/frappe/views/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -5,7 +5,9 @@ export default class Widget { } refresh() { - // + this.set_title(); + this.set_actions(); + this.set_body(); } customize() { diff --git a/frappe/public/js/frappe/views/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js similarity index 100% rename from frappe/public/js/frappe/views/widgets/links_widget.js rename to frappe/public/js/frappe/widgets/links_widget.js diff --git a/frappe/public/js/frappe/views/widgets/onboarding_widget.js b/frappe/public/js/frappe/widgets/onboarding_widget.js similarity index 100% rename from frappe/public/js/frappe/views/widgets/onboarding_widget.js rename to frappe/public/js/frappe/widgets/onboarding_widget.js diff --git a/frappe/public/js/frappe/views/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js similarity index 100% rename from frappe/public/js/frappe/views/widgets/shortcut_widget.js rename to frappe/public/js/frappe/widgets/shortcut_widget.js diff --git a/frappe/public/js/frappe/views/widgets/utils.js b/frappe/public/js/frappe/widgets/utils.js similarity index 100% rename from frappe/public/js/frappe/views/widgets/utils.js rename to frappe/public/js/frappe/widgets/utils.js diff --git a/frappe/public/js/frappe/views/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js similarity index 96% rename from frappe/public/js/frappe/views/widgets/widget_group.js rename to frappe/public/js/frappe/widgets/widget_group.js index 15adb3eebb..36fb2c9efc 100644 --- a/frappe/public/js/frappe/views/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -4,6 +4,8 @@ import ShortcutWidget from "../widgets/shortcut_widget"; import LinksWidget from "../widgets/links_widget"; import OnboardingWidget from "../widgets/onboarding_widget"; +frappe.provide('frappe.widget') + const widget_factory = { chart: ChartWidget, base: BaseWidget, @@ -86,4 +88,6 @@ export default class WidgetGroup { // onStart: (evt) => this.sortable_config.on_start(evt, container) }); } -} \ No newline at end of file +} + +frappe.widget.WidgetGroup = WidgetGroup; \ No newline at end of file From fa32227c270ad595a60204ed6b18fe0a26147f39 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:26:36 +0530 Subject: [PATCH 050/173] feat: merge dashboard chart and chart_widget --- .../chart_widget.js} | 147 ++++++++++-------- 1 file changed, 80 insertions(+), 67 deletions(-) rename frappe/public/js/frappe/{ui/dashboard_chart.js => widgets/chart_widget.js} (76%) diff --git a/frappe/public/js/frappe/ui/dashboard_chart.js b/frappe/public/js/frappe/widgets/chart_widget.js similarity index 76% rename from frappe/public/js/frappe/ui/dashboard_chart.js rename to frappe/public/js/frappe/widgets/chart_widget.js index 45150fe81c..1609ce4e8f 100644 --- a/frappe/public/js/frappe/ui/dashboard_chart.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -1,16 +1,36 @@ -frappe.provide('ui') +import Widget from "./base_widget.js"; frappe.provide('frappe.dashboards'); frappe.provide('frappe.dashboards.chart_sources'); -frappe.ui.DashboardChart = class DashboardChart { - constructor(chart_doc, chart_container, options) { - this.chart_doc = chart_doc; - this.container = chart_container; - this.options = options || {}; - this.chart_args = {}; +export default class ChartWidget extends Widget { + constructor(opts) { + super(opts); } - show() { + refresh() { + this.make_chart(); + } + + customize() { + this.setup_customize_actions(); + } + + set_body() { + this.widget.addClass('dashboard-widget-box') + if (this.width == "Full") { + this.widget.addClass('full-width') + } + this.make_chart(); + } + + set_summary() { + let summary = $(`$ 54,231`); + this.title_field.addClass('text-muted') + summary.prependTo(this.body); + } + + make_chart() { + this.body.empty() this.get_settings().then(() => { this.prepare_chart_object(); this.prepare_container(); @@ -20,41 +40,40 @@ frappe.ui.DashboardChart = class DashboardChart { if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { this.render_time_series_filters(); } - - this.prepare_chart_actions(); } - this.fetch(this.filters).then( data => { + this.action_area.empty(); + this.prepare_chart_actions(); + // this.setup_refresh_button(); + // this.setup_filter_button(); + // if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { + // this.render_time_series_filters(); + // } + + this.fetch(this.filters).then(data => { if (this.chart_doc.chart_type == 'Report') { data = this.get_report_chart_data(data); } - if (!this.options.hide_last_sync || this.options.hide_last_sync == undefined) { - this.update_last_synced(); - } + this.update_last_synced(); this.data = data; + // Delete existing chart when refreshing + delete this.dashboardchart; this.render(); }); }); } - prepare_container() { - const column_width_map = { - "Half": "6", - "Full": "12", - }; - let columns = column_width_map[this.chart_doc.width]; - this.chart_container = $(`
-
-
${__("Loading...")}
-
${__("No Data")}
-
-
`); - this.chart_container.appendTo(this.container); + setup_customize_actions() { + this.action_area.empty() + const buttons = $(` + `); + buttons.appendTo(this.action_area); + } - if (!this.options.hide_last_sync || this.options.hide_last_sync == undefined) { - let last_synced_text = $(``); - last_synced_text.prependTo(this.chart_container); - } + setup_refresh_button() { + const refresh_button = $(``); + refresh_button.appendTo(this.action_area); + refresh_button.on('click', () => this.refresh()); } render_time_series_filters() { @@ -85,7 +104,7 @@ frappe.ui.DashboardChart = class DashboardChart { }, ]; - frappe.dashboard_utils.render_chart_filters(filters, 'chart-actions', this.chart_container, 1); + frappe.dashboard_utils.render_chart_filters(filters, 'chart-actions', this.action_area, 1); } fetch_and_update_chart() { @@ -111,7 +130,7 @@ frappe.ui.DashboardChart = class DashboardChart { if (!this.date_field_wrapper || !this.date_field_wrapper.is(':visible')) { this.date_field_wrapper = $(`
`) - .insertBefore(this.chart_container.find('.chart-wrapper')); + .appendTo(this.action_area); this.date_range_field = frappe.ui.form.make_control({ df: { @@ -177,6 +196,7 @@ frappe.ui.DashboardChart = class DashboardChart { } } ]; + if (this.chart_doc.document_type) { actions.push({ label: __("{0} List", [this.chart_doc.document_type]), @@ -198,11 +218,10 @@ frappe.ui.DashboardChart = class DashboardChart { } setup_filter_button() { - this.is_document_type = this.chart_doc.chart_type!== 'Report' && this.chart_doc.chart_type!=='Custom'; this.filter_button = $(`
${__("Filter")}
`); - this.filter_button.prependTo(this.chart_container); + this.filter_button.appendTo(this.action_area); this.filter_button.on('click', () => { let fields; @@ -295,11 +314,11 @@ frappe.ui.DashboardChart = class DashboardChart { const action = o.dataset.action; $(o).click(actions.find(a => a.action === action)); }); - this.chart_actions.prependTo(this.chart_container); + this.chart_actions.appendTo(this.action_area); } fetch(filters, refresh=false, args) { - this.chart_container.find('.chart-loading-state').removeClass('hide'); + // this.chart_container.find('.chart-loading-state').removeClass('hide'); let method = this.settings ? this.settings.method : 'frappe.desk.doctype.dashboard_chart.dashboard_chart.get'; @@ -343,17 +362,8 @@ frappe.ui.DashboardChart = class DashboardChart { colors = [this.chart_doc.color || "light-blue"]; } - this.chart_container.find('.chart-loading-state').addClass('hide'); - if (!this.data) { - this.chart_container.find('.chart-empty-state').removeClass('hide'); - } else { - let title = null; - if (!this.options.hide_title || this.options.hide_title == undefined) { - title = this.chart_doc.chart_name; - } - + if (this.data) { let chart_args = { - title: title, data: this.data, type: chart_type_map[this.chart_doc.type], colors: colors, @@ -362,10 +372,10 @@ frappe.ui.DashboardChart = class DashboardChart { shortenYAxisNumbers: 1 } }; - if (!this.chart) { - this.chart = new frappe.Chart(this.chart_container.find(".chart-wrapper")[0], chart_args); + if (!this.dashboardchart) { + this.dashboardchart = new frappe.Chart(this.body[0], chart_args); } else { - this.chart.update(this.data); + this.dashboardchart.update(this.data); } } } @@ -388,25 +398,28 @@ frappe.ui.DashboardChart = class DashboardChart { } get_settings() { - if (this.chart_doc.chart_type == 'Custom') { - // custom source - if (frappe.dashboards.chart_sources[this.chart_doc.source]) { - this.settings = frappe.dashboards.chart_sources[this.chart_doc.source]; + return frappe.model.with_doc("Dashboard Chart", this.chart_name).then(chart_doc => { + this.chart_doc = chart_doc; + if (this.chart_doc.chart_type == 'Custom') { + // custom source + if (frappe.dashboards.chart_sources[this.chart_doc.source]) { + this.settings = frappe.dashboards.chart_sources[this.chart_doc.source]; + return Promise.resolve(); + } else { + const method = 'frappe.desk.doctype.dashboard_chart_source.dashboard_chart_source.get_config'; + return frappe.xcall(method, {name: this.chart_doc.source}).then(config => { + frappe.dom.eval(config); + this.settings = frappe.dashboards.chart_sources[this.chart_doc.source]; + }); + } + } else if (this.chart_doc.chart_type == 'Report') { + this.settings = { + 'method': 'frappe.desk.query_report.run' + }; return Promise.resolve(); } else { - const method = 'frappe.desk.doctype.dashboard_chart_source.dashboard_chart_source.get_config'; - return frappe.xcall(method, {name: this.chart_doc.source}).then(config => { - frappe.dom.eval(config); - this.settings = frappe.dashboards.chart_sources[this.chart_doc.source]; - }); + return Promise.resolve(); } - } else if (this.chart_doc.chart_type == 'Report') { - this.settings = { - 'method': 'frappe.desk.query_report.run' - }; - return Promise.resolve(); - } else { - return Promise.resolve(); - } + }); } } \ No newline at end of file From 2ebf0a456cf14f9c1125b4977c01ce77543f971e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:26:49 +0530 Subject: [PATCH 051/173] chore: update build --- frappe/public/build.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/public/build.json b/frappe/public/build.json index 9f0ed63c89..a11b6143df 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -222,6 +222,8 @@ "public/js/frappe/views/communication.js", "public/js/frappe/views/translation_manager.js", + "public/js/frappe/widgets/widget_group.js", + "public/js/frappe/ui/sort_selector.html", "public/js/frappe/ui/sort_selector.js", @@ -237,7 +239,6 @@ "public/js/frappe/utils/energy_point_utils.js", "public/js/frappe/utils/dashboard_utils.js", "public/js/frappe/ui/chart.js", - "public/js/frappe/ui/dashboard_chart.js", "public/js/frappe/barcode_scanner/index.js" ], "css/module.min.css": [ From bbd283827d4b9bebea8101ba4ccfc798538e01f6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:27:10 +0530 Subject: [PATCH 052/173] refactor: patch desktop for new widget api --- frappe/public/js/frappe/views/desktop/desktop.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 13490c656f..e9d9493df9 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -1,6 +1,3 @@ -import ChartWidget from "../widgets/chart_widget"; -import WidgetGroup from "../widgets/widget_group"; - export default class Desktop { constructor({ wrapper }) { this.wrapper = wrapper; @@ -185,7 +182,7 @@ class DesktopPage { this.make_page(); this.get_data().then(res => { this.data = res.message; - // this.make_onboarding() + // this.make_onboarding(); if (!this.data) { delete localStorage.current_desk_page; frappe.set_route('workspace'); @@ -216,7 +213,7 @@ class DesktopPage { } make_onboarding() { - this.sections["onboarding"] = new WidgetGroup({ + this.sections["onboarding"] = new frappe.widget.WidgetGroup({ title: `Getting Started`, container: this.page, type: "onboarding", @@ -253,7 +250,8 @@ class DesktopPage { } make_charts() { - this.sections["charts"] = new WidgetGroup({ + console.log(this.data.charts.items) + this.sections["charts"] = new frappe.widget.WidgetGroup({ title: this.data.charts.label || `${this.page_name} Dashboard`, container: this.page, type: "chart", @@ -264,7 +262,7 @@ class DesktopPage { } make_shortcuts() { - this.sections["shortcuts"] = new WidgetGroup({ + this.sections["shortcuts"] = new frappe.widget.WidgetGroup({ title: this.data.shortcuts.label || `Your Shortcuts`, container: this.page, type: "bookmark", @@ -275,7 +273,7 @@ class DesktopPage { } make_cards() { - let cards = new WidgetGroup({ + let cards = new frappe.widget.WidgetGroup({ title: this.data.cards.label || `Reports & Masters`, container: this.page, type: "links", @@ -284,7 +282,7 @@ class DesktopPage { widgets: this.data.cards.items }); - this.sections["cards"] = cards; + this.sections['cards'] = cards; const legend = [ { From 67b71f78b44e98a4f32811079bad5d92c2a76f7c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:27:24 +0530 Subject: [PATCH 053/173] feat: remove dashboard.css --- frappe/core/page/dashboard/dashboard.css | 62 ---------------------- frappe/public/less/desktop.less | 65 ++++++++++++++---------- 2 files changed, 38 insertions(+), 89 deletions(-) diff --git a/frappe/core/page/dashboard/dashboard.css b/frappe/core/page/dashboard/dashboard.css index cf1a581c6d..e69de29bb2 100644 --- a/frappe/core/page/dashboard/dashboard.css +++ b/frappe/core/page/dashboard/dashboard.css @@ -1,62 +0,0 @@ -.chart-wrapper { - border: 1px solid #d1d8dd; - border-radius: 4px; - margin: 15px 0; - padding-left: 15px; - padding-right: 15px; - height: 320px; -} - -.chart-container { - top: 50%; - transform: translateY(-50%); -} - -.frappe-chart > text.title { - margin: 0px; - font-size: 14px !important; - font-weight: bold; -} - -.chart-loading-state, .chart-empty-state { - height: 100%; - margin-top: 160px; - text-align: center; -} - -.chart-actions { - position: relative; - right: 0px; - top: 20px; - margin-right: 5px; -} - -.filter-chart { - position: relative; - right: 5px; - top: 20px; -} - -.dashboard-date-field { - width: 14%; - height: 0; - margin-right: 10px; - position: relative; - top: 0px; -} - -.chart-column-container { - position: relative; -} - -.last-synced-text { - position: absolute; - top: 28px; - left: 50px; - font-size: 12px; -} - -.dashboard-graph { - padding-top: 15px; - overflow: hidden; -} \ No newline at end of file diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index af371c94bb..72e9dbb4cd 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -76,31 +76,6 @@ position: relative; min-height: 1px; padding-right: 15px; - - .dashboard-summary { - font-size: 32px !important; - margin-top: 0px !important; - margin-bottom: 8px !important; - font-weight: 500; - } - - .grid-col-3 { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); - // grid-auto-rows: minmax(62px, 1fr); - column-gap: 15px; - row-gap: 15px; - align-items: center; - } - - .grid-col-1 { - display: grid; - grid-template-columns: repeat(1fr); - // grid-auto-rows: minmax(62px, 1fr); - column-gap: 15px; - row-gap: 15px; - align-items: center; - } } @media (max-width: 768px) { @@ -138,6 +113,38 @@ } } + .grid-col-3 { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + // grid-auto-rows: minmax(62px, 1fr); + column-gap: 15px; + row-gap: 15px; + align-items: center; + } + + .grid-col-2 { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(550px, 1fr)); + // grid-auto-rows: minmax(62px, 1fr); + column-gap: 15px; + row-gap: 15px; + align-items: center; + + .full-width { + grid-column-start: 1; + grid-column-end: 3; + } + } + + .grid-col-1 { + display: grid; + grid-template-columns: repeat(1fr); + // grid-auto-rows: minmax(62px, 1fr); + column-gap: 15px; + row-gap: 15px; + align-items: center; + } + @media (max-width: 768px) { .legend { display: flex; @@ -184,14 +191,18 @@ // Overrides for each widgets &.dashboard-widget-box { padding-bottom: 10px !important; + min-height: 260px; .chart-column-container { padding-right: 0px !important; padding-left: 0px !important; } - .chart-wrapper { - border-bottom: none !important; + .dashboard-summary { + font-size: 32px !important; + margin-top: 0px !important; + margin-bottom: 8px !important; + font-weight: 500; } } From ed0a8009eeb0988f884525f887ca4e9088e5c8ae Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:28:03 +0530 Subject: [PATCH 054/173] feat: use widgets to make dashboards --- frappe/core/page/dashboard/dashboard.js | 26 +++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/frappe/core/page/dashboard/dashboard.js b/frappe/core/page/dashboard/dashboard.js index ac9221265b..e2da785f4e 100644 --- a/frappe/core/page/dashboard/dashboard.js +++ b/frappe/core/page/dashboard/dashboard.js @@ -22,7 +22,7 @@ class Dashboard { constructor(wrapper) { this.wrapper = $(wrapper); $(`
-
+
`).appendTo(this.wrapper.find(".page-content").empty()); this.container = this.wrapper.find(".dashboard-graph"); this.page = wrapper.page; @@ -78,16 +78,22 @@ class Dashboard { refresh() { this.get_dashboard_doc().then((doc) => { this.dashboard_doc = doc; - this.charts = this.dashboard_doc.charts; + this.charts = this.dashboard_doc.charts + .map(chart => { + return { + chart_name: chart.chart, + label: chart.chart, + ...chart + } + }); - this.charts.map((chart) => { - let chart_container = $("
"); - chart_container.appendTo(this.container); - - frappe.model.with_doc("Dashboard Chart", chart.chart).then( chart_doc => { - let dashboard_chart = new frappe.ui.DashboardChart(chart_doc, chart_container); - dashboard_chart.show(); - }); + this.chart_group = new frappe.widget.WidgetGroup({ + title: null, + container: this.container, + type: "chart", + columns: 2, + allow_sorting: true, + widgets: this.charts, }); }); } From 4e7ccff375a5b9d6f6798ab671a35e0dba983d8e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:28:20 +0530 Subject: [PATCH 055/173] feat: move height config to dashboard page --- .../dashboard_chart/dashboard_chart.json | 10 +-- .../dashboard_chart_link.json | 72 +++++-------------- 2 files changed, 19 insertions(+), 63 deletions(-) diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.json b/frappe/desk/doctype/dashboard_chart/dashboard_chart.json index f181f6d7e4..0a017a0de2 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.json +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.json @@ -31,7 +31,6 @@ "filters_json", "chart_options_section", "type", - "width", "column_break_2", "color", "section_break_10", @@ -127,13 +126,6 @@ "options": "Line\nBar\nPercentage\nPie", "reqd": 1 }, - { - "fieldname": "width", - "fieldtype": "Select", - "label": "Width", - "options": "Half\nFull", - "reqd": 1 - }, { "fieldname": "column_break_2", "fieldtype": "Column Break" @@ -223,7 +215,7 @@ } ], "links": [], - "modified": "2020-03-01 22:08:47.135523", + "modified": "2020-03-13 19:19:37.162771", "modified_by": "Administrator", "module": "Desk", "name": "Dashboard Chart", diff --git a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.json b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.json index df278fb4c1..51b5ed3036 100644 --- a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.json +++ b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.json @@ -1,77 +1,41 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, + "actions": [], "creation": "2019-03-12 15:00:57.052684", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "chart", + "width" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "columns": 8, "fieldname": "chart", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Chart", - "length": 0, - "no_copy": 0, - "options": "Dashboard Chart", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Dashboard Chart" + }, + { + "default": "Half", + "fieldname": "width", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Width", + "options": "Half\nFull" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, "istable": 1, - "max_attachments": 0, - "modified": "2019-03-12 15:01:31.639414", + "links": [], + "modified": "2020-03-13 19:23:05.561687", "modified_by": "Administrator", "module": "Desk", "name": "Dashboard Chart Link", - "name_case": "", "owner": "Administrator", "permissions": [], "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "ASC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file From ff5aa8c96edadbc5fb2d8994dff4d53e0a26fdcd Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:45:05 +0530 Subject: [PATCH 056/173] fix (linting): remove unused code --- frappe/public/js/frappe/views/desktop/desktop.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index e9d9493df9..4391a572af 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -19,7 +19,7 @@ export default class Desktop { this.fetch_desktop_settings().then(() => { this.route(); this.make_sidebar(); - this.setup_events(); + // this.setup_events(); // this.hide_loading_state(); }); } @@ -153,11 +153,11 @@ export default class Desktop { } setup_events() { - $(document).keydown(e => { - if (e.keyCode == 9) { - console.log("navigate"); - } - }); + // $(document).keydown(e => { + // if (e.keyCode == 9) { + // console.log("navigate"); + // } + // }); } } @@ -250,7 +250,6 @@ class DesktopPage { } make_charts() { - console.log(this.data.charts.items) this.sections["charts"] = new frappe.widget.WidgetGroup({ title: this.data.charts.label || `${this.page_name} Dashboard`, container: this.page, From 324403ca3a14dfc7c2c7962fbc9b962cf3e84861 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 13 Mar 2020 19:46:20 +0530 Subject: [PATCH 057/173] chore (linting): added semicolon --- frappe/public/js/frappe/widgets/chart_widget.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 1609ce4e8f..69cad2b8fb 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -16,21 +16,21 @@ export default class ChartWidget extends Widget { } set_body() { - this.widget.addClass('dashboard-widget-box') + this.widget.addClass('dashboard-widget-box'); if (this.width == "Full") { - this.widget.addClass('full-width') + this.widget.addClass('full-width'); } this.make_chart(); } set_summary() { let summary = $(`$ 54,231`); - this.title_field.addClass('text-muted') + this.title_field.addClass('text-muted'); summary.prependTo(this.body); } make_chart() { - this.body.empty() + this.body.empty(); this.get_settings().then(() => { this.prepare_chart_object(); this.prepare_container(); @@ -47,7 +47,7 @@ export default class ChartWidget extends Widget { // this.setup_refresh_button(); // this.setup_filter_button(); // if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { - // this.render_time_series_filters(); + // this.render_time_series_filters(); // } this.fetch(this.filters).then(data => { @@ -64,7 +64,7 @@ export default class ChartWidget extends Widget { } setup_customize_actions() { - this.action_area.empty() + this.action_area.empty(); const buttons = $(` `); buttons.appendTo(this.action_area); From 1f82f051efb258eb8925ab23eea6eb66b05bc927 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 13 Mar 2020 19:56:12 +0530 Subject: [PATCH 058/173] fix: mve email_append_to to a section --- frappe/custom/doctype/customize_form/customize_form.js | 10 ---------- .../custom/doctype/customize_form/customize_form.json | 9 ++++++--- frappe/email/doctype/email_account/email_account.py | 6 +++--- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 858cf565be..444d9dc495 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -139,16 +139,6 @@ frappe.ui.form.on("Customize Form", { }, 1000); } - }, - - email_append_to: function(frm) { - frm.set_df_property("subject_field", "reqd", 0); - frm.set_df_property("sender_field", "reqd", 0); - - if (frm.doc.email_append_to) { - frm.set_df_property("subject_field", "reqd", 1); - frm.set_df_property("sender_field", "reqd", 1); - } } }); diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index f719add96c..bfc31d60e6 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -21,7 +21,6 @@ "allow_auto_repeat", "allow_import", "image_view", - "email_append_to", "column_break_5", "title_field", "image_field", @@ -31,6 +30,7 @@ "column_break_10", "sort_order", "section_break_23", + "email_append_to", "subject_field", "cb_01", "sender_field", @@ -182,14 +182,17 @@ "label": "Allow Import (via Data Import Tool)" }, { + "depends_on": "email_append_to", "fieldname": "subject_field", "fieldtype": "Data", "label": "Subject Field" }, { + "depends_on": "email_append_to", "fieldname": "sender_field", "fieldtype": "Data", - "label": "Sender Field" + "label": "Sender Field", + "mandatory_depends_on": "email_append_to" }, { "default": "0", @@ -212,7 +215,7 @@ "idx": 1, "issingle": 1, "links": [], - "modified": "2019-12-27 14:29:49.097980", + "modified": "2020-03-13 19:54:39.652134", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index cddc5dd25d..c0a198f5e5 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -678,9 +678,9 @@ def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len email_append_to_list = [] # Set Email Append To DocTypes via DocType - for dt in frappe.get_all("DocType", filters={"istable": 0, "issingle": 0}, fields=["name", "email_append_to"]): - if dt.get("email_append_to") and dt.email_append_to: - email_append_to_list.append(dt.name) + filters = {"istable": 0, "issingle": 0, "email_append_to": 1} + for dt in frappe.get_all("DocType", filters=filters, fields=["name", "email_append_to"]): + email_append_to_list.append(dt.name) # Set Email Append To DocTypes set via Customize Form for dt in frappe.get_list("Property Setter", filters={"property": "email_append_to", "value": 1}, fields=["doc_type"]): From b3b94197a181c8734c29374444623d50bea8beaf Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2020 12:43:49 +0530 Subject: [PATCH 059/173] chore(deps): [security] bump acorn from 5.7.3 to 5.7.4 (#9695) Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4. **This update includes a security fix.** - [Release notes](https://github.com/acornjs/acorn/releases) - [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6de2bd96b2..1b3d0a2176 100644 --- a/yarn.lock +++ b/yarn.lock @@ -392,9 +392,9 @@ ace-builds@^1.4.8: integrity sha512-8ZVAxwyCGAxQX8mOp9imSXH0hoSPkGfy8igJy+WO/7axL30saRhKgg1XPACSmxxPA7nfHVwM+ShWXT+vKsNuFg== acorn@^5.2.1: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + version "5.7.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" + integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== acorn@^6.1.1: version "6.1.1" From 98f5366fac3ff4cada8d00340214bbdeaf82b733 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Sat, 14 Mar 2020 16:16:16 +0530 Subject: [PATCH 060/173] fix: Remove duplicate on_trash key --- frappe/hooks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/hooks.py b/frappe/hooks.py index f8dde91c7b..cdc6e00bdd 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -134,13 +134,13 @@ doc_events = { ], "on_trash": [ "frappe.desk.notifications.clear_doctype_notifications", - "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions" + "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions", + "frappe.cache_manager.build_table_count_cache" ], "on_change": [ "frappe.social.doctype.energy_point_rule.energy_point_rule.process_energy_points" ], - "after_insert": "frappe.cache_manager.build_table_count_cache", - "on_trash": "frappe.cache_manager.build_table_count_cache", + "after_insert": "frappe.cache_manager.build_table_count_cache" }, "Event": { "after_insert": "frappe.integrations.doctype.google_calendar.google_calendar.insert_event_in_google_calendar", From 82038e0d02a2c25b3e64977f52c14c7cdbd64535 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Sat, 14 Mar 2020 17:11:50 +0530 Subject: [PATCH 061/173] refactor: filter alignments --- .../public/js/frappe/widgets/chart_widget.js | 23 +++++++------------ frappe/public/less/desktop.less | 7 ++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 69cad2b8fb..4226c8463e 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -33,22 +33,15 @@ export default class ChartWidget extends Widget { this.body.empty(); this.get_settings().then(() => { this.prepare_chart_object(); - this.prepare_container(); - - if (!this.options.hide_actions || this.options.hide_actions == undefined) { - this.setup_filter_button(); - if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { - this.render_time_series_filters(); - } - } + // this.prepare_container(); this.action_area.empty(); this.prepare_chart_actions(); // this.setup_refresh_button(); - // this.setup_filter_button(); - // if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { - // this.render_time_series_filters(); - // } + this.setup_filter_button(); + if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { + this.render_time_series_filters(); + } this.fetch(this.filters).then(data => { if (this.chart_doc.chart_type == 'Report') { @@ -104,7 +97,7 @@ export default class ChartWidget extends Widget { }, ]; - frappe.dashboard_utils.render_chart_filters(filters, 'chart-actions', this.action_area, 1); + frappe.dashboard_utils.render_chart_filters(filters, 'chart-actions', this.action_area, 0); } fetch_and_update_chart() { @@ -298,9 +291,9 @@ export default class ChartWidget extends Widget { this.filter_group.add_filters_to_filter_group(this.filters); }); } - +// set_chart_actions(actions) { - this.chart_actions = $(``); this.title_field = this.widget.find(".widget-title"); this.body = this.widget.find(".widget-body"); this.action_area = this.widget.find(".widget-control"); this.head = this.widget.find(".widget-head"); + this.footer = this.widget.find(".widget-footer"); this.set_title(); this.set_actions(); this.set_body(); diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index fc11eec93f..eca4903e88 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -211,6 +211,11 @@ margin-bottom: 8px !important; font-weight: 500; } + + .widget-footer { + font-size: 85%; + color: @text-muted; + } } &.onboarding-widget-box { From 1c65e4ba04d8e60018fbb25801503d527da16b44 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Sun, 15 Mar 2020 19:00:13 +0530 Subject: [PATCH 063/173] feat: show last sync --- frappe/public/js/frappe/widgets/chart_widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 4226c8463e..326b455dac 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -291,7 +291,7 @@ export default class ChartWidget extends Widget { this.filter_group.add_filters_to_filter_group(this.filters); }); } -// + set_chart_actions(actions) { this.chart_actions = $(`
- + + From 57bac6fff88c07f70303bf00a49596acb653ce21 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 17 Mar 2020 19:24:03 +0530 Subject: [PATCH 086/173] fix: Avoid unnecessary cint calls --- frappe/model/meta.py | 2 +- frappe/public/js/frappe/form/formatters.js | 4 ++-- frappe/public/js/frappe/model/meta.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/model/meta.py b/frappe/model/meta.py index d208797644..424856b5cf 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -549,7 +549,7 @@ def get_field_precision(df, doc=None, currency=None): elif df.fieldtype == "Currency": if df.precision and cint(df.precision) == 0: - precision = cint(df.precision) + precision = 0 else: precision = cint(frappe.db.get_default("currency_precision")) if not precision: diff --git a/frappe/public/js/frappe/form/formatters.js b/frappe/public/js/frappe/form/formatters.js index 5db4bbaced..ef6976e896 100644 --- a/frappe/public/js/frappe/form/formatters.js +++ b/frappe/public/js/frappe/form/formatters.js @@ -63,8 +63,8 @@ frappe.form.formatters = { var currency = frappe.meta.get_field_currency(docfield, doc); var precision; - if (docfield.precision === 0) { - precision = docfield.precision; + if (docfield.precision && cint(docfield.precision) === 0) { + precision = 0; } else { precision = docfield.precision || cint(frappe.boot.sysdefaults.currency_precision) || 2; } diff --git a/frappe/public/js/frappe/model/meta.js b/frappe/public/js/frappe/model/meta.js index c252e6821b..fc815c1d92 100644 --- a/frappe/public/js/frappe/model/meta.js +++ b/frappe/public/js/frappe/model/meta.js @@ -257,7 +257,7 @@ $.extend(frappe.meta, { precision = cint(df.precision); } else if(df && df.fieldtype === "Currency") { if (df.precision && cint(df.precision) === 0) { - precision = cint(df.precision); + precision = 0; } else { precision = cint(frappe.defaults.get_default("currency_precision")); if(!precision) { From f46b3d89a92ac89b2d609f1e52eb820394e37a6a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 17 Mar 2020 21:20:44 +0530 Subject: [PATCH 087/173] fix: Pass zero precision as string --- frappe/model/meta.py | 13 +++++-------- frappe/public/js/frappe/form/formatters.js | 8 +------- frappe/public/js/frappe/model/meta.js | 16 ++++++---------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 424856b5cf..1938a4a96c 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -544,17 +544,14 @@ def get_field_precision(df, doc=None, currency=None): """get precision based on DocField options and fieldvalue in doc""" from frappe.utils import get_number_format_info - if cint(df.precision): + if df.precision: precision = cint(df.precision) elif df.fieldtype == "Currency": - if df.precision and cint(df.precision) == 0: - precision = 0 - else: - precision = cint(frappe.db.get_default("currency_precision")) - if not precision: - number_format = frappe.db.get_default("number_format") or "#,###.##" - decimal_str, comma_str, precision = get_number_format_info(number_format) + precision = cint(frappe.db.get_default("currency_precision")) + if not precision: + number_format = frappe.db.get_default("number_format") or "#,###.##" + decimal_str, comma_str, precision = get_number_format_info(number_format) else: precision = cint(frappe.db.get_default("float_precision")) or 3 diff --git a/frappe/public/js/frappe/form/formatters.js b/frappe/public/js/frappe/form/formatters.js index ef6976e896..d178c59100 100644 --- a/frappe/public/js/frappe/form/formatters.js +++ b/frappe/public/js/frappe/form/formatters.js @@ -61,13 +61,7 @@ frappe.form.formatters = { }, Currency: function (value, docfield, options, doc) { var currency = frappe.meta.get_field_currency(docfield, doc); - var precision; - - if (docfield.precision && cint(docfield.precision) === 0) { - precision = 0; - } else { - precision = docfield.precision || cint(frappe.boot.sysdefaults.currency_precision) || 2; - } + var precision = docfield.precision || cint(frappe.boot.sysdefaults.currency_precision) || 2; // If you change anything below, it's going to hurt a company in UAE, a bit. if (precision > 2) { diff --git a/frappe/public/js/frappe/model/meta.js b/frappe/public/js/frappe/model/meta.js index fc815c1d92..b7ad52838c 100644 --- a/frappe/public/js/frappe/model/meta.js +++ b/frappe/public/js/frappe/model/meta.js @@ -253,18 +253,14 @@ $.extend(frappe.meta, { get_field_precision: function(df, doc) { var precision = null; - if (df && cint(df.precision)) { + if (df && df.precision) { precision = cint(df.precision); } else if(df && df.fieldtype === "Currency") { - if (df.precision && cint(df.precision) === 0) { - precision = 0; - } else { - precision = cint(frappe.defaults.get_default("currency_precision")); - if(!precision) { - var number_format = get_number_format(); - var number_format_info = get_number_format_info(number_format); - precision = number_format_info.precision; - } + precision = cint(frappe.defaults.get_default("currency_precision")); + if(!precision) { + var number_format = get_number_format(); + var number_format_info = get_number_format_info(number_format); + precision = number_format_info.precision; } } else { precision = cint(frappe.defaults.get_default("float_precision")) || 3; From f5b5c69b8ff5a57d73c06c85040f36682fdda31a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 17 Mar 2020 22:04:50 +0530 Subject: [PATCH 088/173] fix: duplicate entry error while renaming item (#9652) From aeb9d87cb7c77886b66ba8393541d7ff089300b7 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 10:16:03 +0530 Subject: [PATCH 089/173] fix: breadcrumbs for new desk --- frappe/public/js/frappe/views/breadcrumbs.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/views/breadcrumbs.js b/frappe/public/js/frappe/views/breadcrumbs.js index 339052342d..2aef1a8218 100644 --- a/frappe/public/js/frappe/views/breadcrumbs.js +++ b/frappe/public/js/frappe/views/breadcrumbs.js @@ -18,7 +18,8 @@ frappe.breadcrumbs = { 'Workflow': 'Settings', 'Printing': 'Settings', 'Setup': 'Settings', - 'Event Streaming': 'Automation' + 'Event Streaming': 'Tools', + 'Automation': 'Tools', }, set_doctype_module: function(doctype, module) { @@ -95,7 +96,7 @@ frappe.breadcrumbs = { if(module_info && !module_info.blocked && frappe.visible_modules.includes(module_info.module_name)) { - $(repl('
  • %(label)s
  • ', + $(repl('
  • %(label)s
  • ', { module: breadcrumbs.module, label: __(label) })) .appendTo($breadcrumbs); } From 83a957bbb85f17427d143c17a055f18307571a1b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 10:28:17 +0530 Subject: [PATCH 090/173] feat: remove ModuleView --- frappe/public/js/frappe/views/pageview.js | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/frappe/public/js/frappe/views/pageview.js b/frappe/public/js/frappe/views/pageview.js index 71f1e8e9a8..66e9356106 100644 --- a/frappe/public/js/frappe/views/pageview.js +++ b/frappe/public/js/frappe/views/pageview.js @@ -164,26 +164,4 @@ frappe.show_message_page = function(opts) { ); frappe.container.change_to(opts.page_name); -}; - -frappe.views.ModulesFactory = class ModulesFactory extends frappe.views.Factory { - show() { - if (frappe.pages.modules) { - frappe.container.change_to('modules'); - } else { - this.make('modules'); - } - } - - make(page_name) { - const assets = [ - '/assets/js/modules.min.js' - ]; - - frappe.require(assets, () => { - frappe.modules.home = new frappe.modules.Home({ - parent: this.make_page(true, page_name) - }); - }); - } }; \ No newline at end of file From 53bf9989fbaded7598f11d42ad96296945a13388 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 10:33:56 +0530 Subject: [PATCH 091/173] feat: remove module.min.css --- frappe/hooks.py | 1 - frappe/public/build.json | 3 - frappe/public/css/module.css | 113 ------------------------- frappe/public/less/module.less | 147 --------------------------------- 4 files changed, 264 deletions(-) delete mode 100644 frappe/public/css/module.css delete mode 100644 frappe/public/less/module.less diff --git a/frappe/hooks.py b/frappe/hooks.py index cdc6e00bdd..c44c05fdf4 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -42,7 +42,6 @@ app_include_css = [ "assets/css/list.min.css", "assets/css/form.min.css", "assets/css/report.min.css", - "assets/css/module.min.css" ] web_include_js = [ diff --git a/frappe/public/build.json b/frappe/public/build.json index 9f0ed63c89..2999b9b343 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -240,9 +240,6 @@ "public/js/frappe/ui/dashboard_chart.js", "public/js/frappe/barcode_scanner/index.js" ], - "css/module.min.css": [ - "public/less/module.less" - ], "css/form.min.css": [ "public/less/form_grid.less" ], diff --git a/frappe/public/css/module.css b/frappe/public/css/module.css deleted file mode 100644 index 9e937b0957..0000000000 --- a/frappe/public/css/module.css +++ /dev/null @@ -1,113 +0,0 @@ -.module-head { - padding: 15px 30px; - border-bottom: 1px solid #EBEFF2; -} -.module-head h1 { - padding: 0px; - margin: 0px; -} -.module-body { - padding: 0px 15px; -} -.module-body .section-head { - margin-bottom: 15px; - margin-top: 0px; -} -.module-section { - border-bottom: 1px solid #EBEFF2; -} -.module-section .module-section-link { - line-height: 1.5em; -} -.module-section-column { - padding: 30px; -} -@media (min-width: 767px) { - .module-section:nth-child(even) { - background-color: #fafbfc; - } - .module-section:last-child { - border-bottom: none; - } -} -@media (max-width: 991px) { - .module-body { - margin-top: 15px; - border-top: 1px solid #d1d8dd; - } -} -@media (max-width: 767px) { - .module-body { - margin-top: 0; - border-top: 1px solid transparent; - } -} -@media (max-width: 767px) { - .module-section { - border: none; - } - .module-section-column { - border-bottom: 1px solid #EBEFF2; - } - .module-section-column:nth-child(even) { - background-color: #fafbfc; - } - .module-section:last-child .module-section-column:last-child { - border-bottom: none; - } -} -.module-item { - margin: 0px; - padding: 7px; - font-weight: 400; - border-bottom: 1px solid #d1d8dd; - cursor: pointer; - transition: 0.2s; - -webkit-transition: 0.2s; -} -.module-item h4 { - display: inline-block; -} -.module-item .module-item-description { - margin-top: -5px; -} -.module-item .badge { - margin-top: -2px; - margin-left: 3px; -} -.module-item:hover, -.module-item:focus { - background-color: #F7FAFC; -} -.module-item:last-child { - border: none; -} -.module-link.active .icon-chevron-right { - margin-top: 4px; - display: block !important; -} -.module-item-progress { - margin-bottom: 10px; - height: 17px; -} -.module-item-progress-total { - height: 7px; - background-color: #999999; - width: 0px; -} -.module-item-progress-open { - height: 7px; - background-color: red; - width: 0px; -} -@media (max-width: 767px) { - body[data-route^="Module"] .page-title { - width: 100%; - } - body[data-route^="Module"] .page-actions { - display: none !important; - } - body[data-route^="Module"] .layout-main-section { - border-bottom: 0px; - } -} diff --git a/frappe/public/less/module.less b/frappe/public/less/module.less deleted file mode 100644 index f924778864..0000000000 --- a/frappe/public/less/module.less +++ /dev/null @@ -1,147 +0,0 @@ -@import "variables.less"; - -.module-head { - padding: 15px 30px; - border-bottom: 1px solid @light-border-color; -} - -.module-head h1 { - padding: 0px; - margin: 0px; -} - -.module-body { - padding: 0px 15px; - - .section-head { - margin-bottom: 15px; - margin-top: 0px; - } -} - -.module-section { - border-bottom: 1px solid @light-border-color; - - .module-section-link { - line-height: 1.5em; - // font-size: 14px; - } -} - -.module-section-column { - padding: 30px; -} - -@media(min-width: @screen-xs) { - .module-section:nth-child(even) { - background-color: @light-bg; - } - - .module-section:last-child { - border-bottom: none; - } -} - -@media(max-width: @screen-sm) { - .module-body { - margin-top: 15px; - border-top: 1px solid @border-color; - } -} - -@media(max-width: @screen-xs) { - .module-body { - margin-top: 0; - border-top: 1px solid transparent; - } -} - -@media(max-width: @screen-xs) { - .module-section { - border: none; - } - - .module-section-column { - border-bottom: 1px solid @light-border-color; - } - - .module-section-column:nth-child(even) { - background-color: @light-bg; - } - - .module-section:last-child .module-section-column:last-child { - border-bottom: none; - } -} - - -.module-item { - margin: 0px; - padding: 7px; - font-weight: 400; - border-bottom: 1px solid @border-color; - cursor: pointer; - transition: 0.2s; - -webkit-transition: 0.2s; -} - -.module-item h4 { - display: inline-block; -} - -.module-item .module-item-description { - margin-top: -5px; -} - -.module-item .badge { - margin-top: -2px; - margin-left: 3px; -} - -.module-item:hover, .module-item:focus { - background-color: @panel-bg; -} - -.module-item:last-child { - border: none; -} - -.module-link.active .icon-chevron-right { - margin-top: 4px; - display: block !important; -} - -.module-item-progress { - margin-bottom: 10px; - height: 17px; -} - -.module-item-progress-total { - height: 7px; - background-color: #999999; - width: 0px; -} - -.module-item-progress-open { - height: 7px; - background-color: red; - width: 0px; -} - -@media(max-width: @screen-xs) { - - body[data-route^="Module"] { - .page-title { - width: 100%; - } - - - .page-actions { - display: none !important; - } - - .layout-main-section { - border-bottom: 0px; - } - } -} From 3f31981e7eaa86b10598d2f7d11d6d383f9f3792 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 12:53:43 +0530 Subject: [PATCH 092/173] refactor: fix padding for dashboard widget --- frappe/public/less/desktop.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index ad1f973713..354dad7c5e 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -197,7 +197,7 @@ // Overrides for each widgets &.dashboard-widget-box { - padding-bottom: 10px !important; + padding: 10px 15px !important; min-height: 260px; .chart-column-container { From 8e392d2dc52f38dc3e69f42c03cc6f6b0e9d3c83 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 13:57:48 +0530 Subject: [PATCH 093/173] refactor: show summary only in full width --- frappe/public/js/frappe/widgets/chart_widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index ca92b1a9d9..e8cfa06108 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -58,7 +58,7 @@ export default class ChartWidget extends Widget { // Delete existing chart when refreshing delete this.dashboardchart; this.render(); - this.set_summary(); + this.width == "Full" && this.set_summary(); }); }); } From ad489fd97d64e89cbc24234dd91063b1f37434c9 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 15:03:57 +0530 Subject: [PATCH 094/173] fix: linitng fixes --- frappe/public/js/frappe/widgets/chart_widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index e8cfa06108..b21f9665d8 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -48,7 +48,7 @@ export default class ChartWidget extends Widget { } this.fetch(this.filters).then(data => { - this.summary = [] + this.summary = []; if (this.chart_doc.chart_type == 'Report') { this.summary = data.report_summary; data = this.get_report_chart_data(data); From 763395d34ba4d3a14e7b92de1728f04644fa0b33 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 18 Mar 2020 15:22:23 +0530 Subject: [PATCH 095/173] fix: update summary when filters are applied on a chart --- frappe/public/js/frappe/widgets/chart_widget.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index b21f9665d8..cc9e97b877 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -25,12 +25,16 @@ export default class ChartWidget extends Widget { } set_summary() { - let $summary = $(`
    `).hide().prependTo(this.body); + if (!this.$summary) { + this.$summary = $(`
    `).hide().prependTo(this.body); + } else { + this.$summary.empty(); + } this.summary.forEach((summary) => { - build_summary_item(summary).appendTo($summary); + build_summary_item(summary).appendTo(this.$summary); }) - this.summary.length && $summary.show(); + this.summary.length && this.$summary.show(); } make_chart() { @@ -58,7 +62,7 @@ export default class ChartWidget extends Widget { // Delete existing chart when refreshing delete this.dashboardchart; this.render(); - this.width == "Full" && this.set_summary(); + this.width == "Full" && this.summary && this.set_summary(); }); }); } @@ -117,12 +121,14 @@ export default class ChartWidget extends Widget { this.fetch(this.filters, true, this.args).then(data => { if (this.chart_doc.chart_type == 'Report') { + this.summary = data.report_summary; data = this.get_report_chart_data(data); } this.update_chart_object(); this.data = data; this.render(); + this.summary && this.set_summary(); }); } From b9bb6e651302ca7a9451df982c7c7e72f995d6a3 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 18 Mar 2020 16:30:53 +0530 Subject: [PATCH 096/173] fix: Updated value of _seen in db while resetting _seen --- frappe/model/document.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/model/document.py b/frappe/model/document.py index cfb8afac4d..41f946efd9 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -978,7 +978,7 @@ class Document(BaseDocument): def reset_seen(self): """Clear _seen property and set current user as seen""" if getattr(self.meta, 'track_seen', False): - self._seen = json.dumps([frappe.session.user]) + self.db_set('_seen', json.dumps([frappe.session.user]), update_modified=False) def notify_update(self): """Publish realtime that the current document is modified""" From 878101d16b37b7503d832f2e1ef9c7dee2cd8096 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 18 Mar 2020 16:46:32 +0530 Subject: [PATCH 097/173] style: Fix codacy --- frappe/email/doctype/notification/notification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 582cb5d3c4..6a3dd89873 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -140,7 +140,7 @@ def get_context(context): doc.flags.in_notification_update = True doc.save(ignore_permissions=True) doc.flags.in_notification_update = False - except Exception as e: + except Exception: frappe.log_error(title='Document update failed', message=frappe.get_traceback()) def send_an_email(self, doc, context): From 02925d8d34b73f8fd1975de39e87d9e9a213ee8e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 18:30:47 +0530 Subject: [PATCH 098/173] chore: remove commented code --- frappe/public/js/frappe/views/desktop/desktop.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 4391a572af..656c5ce021 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -152,13 +152,7 @@ export default class Desktop { return $page; } - setup_events() { - // $(document).keydown(e => { - // if (e.keyCode == 9) { - // console.log("navigate"); - // } - // }); - } + setup_events() { } } class DesktopPage { From 3ac988441b5353d9092dab7e19eed8a1161b766c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 18:30:55 +0530 Subject: [PATCH 099/173] refactor: better variable names --- frappe/public/js/frappe/widgets/chart_widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index cc9e97b877..d92fb80f62 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -60,7 +60,7 @@ export default class ChartWidget extends Widget { this.update_last_synced(); this.data = data; // Delete existing chart when refreshing - delete this.dashboardchart; + delete this.dashboard_chart; this.render(); this.width == "Full" && this.summary && this.set_summary(); }); @@ -378,10 +378,10 @@ export default class ChartWidget extends Widget { shortenYAxisNumbers: 1 } }; - if (!this.dashboardchart) { - this.dashboardchart = new frappe.Chart(this.body[0], chart_args); + if (!this.dashboard_chart) { + this.dashboard_chart = new frappe.Chart(this.body[0], chart_args); } else { - this.dashboardchart.update(this.data); + this.dashboard_chart.update(this.data); } } } From 05599645c86ef8c57e04c17290079a82eb3dadc6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 18:59:30 +0530 Subject: [PATCH 100/173] refactor: commonify fetch and render --- frappe/public/js/frappe/widgets/chart_widget.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index d92fb80f62..1d5f267cf1 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -50,20 +50,7 @@ export default class ChartWidget extends Widget { if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { this.render_time_series_filters(); } - - this.fetch(this.filters).then(data => { - this.summary = []; - if (this.chart_doc.chart_type == 'Report') { - this.summary = data.report_summary; - data = this.get_report_chart_data(data); - } - this.update_last_synced(); - this.data = data; - // Delete existing chart when refreshing - delete this.dashboard_chart; - this.render(); - this.width == "Full" && this.summary && this.set_summary(); - }); + this.fetch_and_update_chart(); }); } From 5fb0cb3c431d6c2270569baad06f6c292ee9b2bc Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 18 Mar 2020 19:31:37 +0530 Subject: [PATCH 101/173] feat: added loading state and empty state --- .../public/js/frappe/widgets/chart_widget.js | 21 ++++++++++++++----- frappe/public/less/desktop.less | 6 ++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 1d5f267cf1..2b73f54d50 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -24,9 +24,15 @@ export default class ChartWidget extends Widget { this.make_chart(); } + set_loading_state() { + this.loading = $(`
    ${__("Loading...")}
    `) + this.loading.appendTo(this.body) + } + set_summary() { if (!this.$summary) { - this.$summary = $(`
    `).hide().prependTo(this.body); + this.$summary = $(`
    `).hide(); + this.head.after(this.$summary); } else { this.$summary.empty(); } @@ -40,6 +46,7 @@ export default class ChartWidget extends Widget { make_chart() { this.body.empty(); this.get_settings().then(() => { + this.set_loading_state(); this.prepare_chart_object(); // this.prepare_container(); @@ -114,8 +121,8 @@ export default class ChartWidget extends Widget { this.update_chart_object(); this.data = data; + this.loading.remove(); this.render(); - this.summary && this.set_summary(); }); } @@ -178,7 +185,8 @@ export default class ChartWidget extends Widget { label: __("Refresh"), action: 'action-refresh', handler: () => { - this.fetch_and_update_chart(); + delete this.dashboard_chart; + this.make_chart(); } }, { @@ -311,7 +319,6 @@ export default class ChartWidget extends Widget { } fetch(filters, refresh=false, args) { - // this.chart_container.find('.chart-loading-state').removeClass('hide'); let method = this.settings ? this.settings.method : 'frappe.desk.doctype.dashboard_chart.dashboard_chart.get'; @@ -355,7 +362,10 @@ export default class ChartWidget extends Widget { colors = [this.chart_doc.color || "light-blue"]; } - if (this.data) { + if (!this.data || !Object.keys(this.data).length) { + const empty = $(`
    ${__("No Data...")}
    `) + empty.appendTo(this.body) + } else { let chart_args = { data: this.data, type: chart_type_map[this.chart_doc.type], @@ -370,6 +380,7 @@ export default class ChartWidget extends Widget { } else { this.dashboard_chart.update(this.data); } + this.width == "Full" && this.summary && this.set_summary(); } } diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index 354dad7c5e..05f1f11113 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -210,6 +210,12 @@ color: @text-muted; } + .chart-loading-state { + display: flex; + justify-content: center; + align-items: center; + } + .report-summary { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); border: none; From ce5eaf91198d899c77449a25e261d37fcc490375 Mon Sep 17 00:00:00 2001 From: Marica Date: Wed, 18 Mar 2020 22:02:50 +0530 Subject: [PATCH 102/173] fix: Handling datetime objects in Data Import Beta (#9656) * fix: Handling datetime objects in Data Import Co-Authored-By: Shivam Mishra * fix: Avoid calling parse_date_format if already datetime. * fix: Changed type check to isinstance and syntactical improvements * chore: use predefined datetime format Signed-off-by: Chinmay D. Pai * chore: fix deepsource issues Signed-off-by: Chinmay D. Pai Co-authored-by: Shivam Mishra Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Co-authored-by: Chinmay D. Pai --- .../core/doctype/data_import/importer_new.py | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/frappe/core/doctype/data_import/importer_new.py b/frappe/core/doctype/data_import/importer_new.py index 5e36c8ad62..1f446cfb39 100644 --- a/frappe/core/doctype/data_import/importer_new.py +++ b/frappe/core/doctype/data_import/importer_new.py @@ -9,7 +9,7 @@ import timeit import frappe from datetime import datetime from frappe import _ -from frappe.utils import cint, flt, update_progress_bar, cstr +from frappe.utils import cint, flt, update_progress_bar, cstr, DATETIME_FORMAT from frappe.utils.csvutils import read_csv_content from frappe.utils.xlsxutils import ( read_xlsx_file_from_attached_file, @@ -345,6 +345,9 @@ class Importer: return columns_with_serial_no, data_with_serial_no def parse_value(self, value, df): + if isinstance(value, datetime) and df.fieldtype in ["Date", "Datetime"]: + return value + value = cstr(value) # convert boolean values to 0 or 1 @@ -362,14 +365,13 @@ class Importer: return value def parse_date_format(self, value, df): - date_format = self.get_date_format_for_df(df) - if date_format: - try: - return datetime.strptime(value, date_format) - except: - # ignore date values that dont match the format - # import will break for these values later - pass + date_format = self.get_date_format_for_df(df) or DATETIME_FORMAT + try: + return datetime.strptime(value, date_format) + except ValueError: + # ignore date values that dont match the format + # import will break for these values later + pass return value def get_date_format_for_df(self, df): @@ -396,7 +398,8 @@ class Importer: date_values = [ row[column_index] for row in self.data[:PARSE_ROW_COUNT] if row[column_index] ] - date_formats = [guess_date_format(d) for d in date_values] + date_formats = [guess_date_format(d) if isinstance(d, str) else None + for d in date_values] if not date_formats: return max_occurred_date_format = max(set(date_formats), key=date_formats.count) From b6e6d274f7f7af3e3ececc58aca944f22ca8eb6a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 19 Mar 2020 10:30:40 +0530 Subject: [PATCH 103/173] fix (codacy): added semicolon --- frappe/public/js/frappe/widgets/chart_widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 2b73f54d50..a9b6b319d1 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -25,8 +25,8 @@ export default class ChartWidget extends Widget { } set_loading_state() { - this.loading = $(`
    ${__("Loading...")}
    `) - this.loading.appendTo(this.body) + this.loading = $(`
    ${__("Loading...")}
    `); + this.loading.appendTo(this.body); } set_summary() { @@ -363,8 +363,8 @@ export default class ChartWidget extends Widget { } if (!this.data || !Object.keys(this.data).length) { - const empty = $(`
    ${__("No Data...")}
    `) - empty.appendTo(this.body) + const empty = $(`
    ${__("No Data...")}
    `); + empty.appendTo(this.body); } else { let chart_args = { data: this.data, From 8c9d55edcaa3b9e95e2d50528a59b19730b6350b Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Thu, 19 Mar 2020 13:25:54 +0530 Subject: [PATCH 104/173] Revert "feat: change fieldtype in db with customize form" --- .../doctype/customize_form/customize_form.py | 33 +------------------ frappe/database/mariadb/database.py | 4 +-- frappe/database/schema.py | 8 ++--- 3 files changed, 5 insertions(+), 40 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index c8d1bb18b4..8d47a075ba 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -166,6 +166,7 @@ class CustomizeForm(Document): self.flags.update_db = False self.flags.rebuild_doctype_for_global_search = False + self.set_property_setters() self.update_custom_fields() self.set_name_translation() @@ -361,45 +362,13 @@ class CustomizeForm(Document): def validate_fieldtype_change(self, df, old_value, new_value): allowed = False - self.check_length_for_fieldtypes = [] for allowed_changes in allowed_fieldtype_change: if (old_value in allowed_changes and new_value in allowed_changes): allowed = True - if frappe.db.type_map.get(old_value)[1] > frappe.db.type_map.get(new_value)[1]: - self.check_length_for_fieldtypes.append({'df': df, 'old_value': old_value}) - self.validate_fieldtype_length() - else: - self.flags.update_db = True break if not allowed: frappe.throw(_("Fieldtype cannot be changed from {0} to {1} in row {2}").format(old_value, new_value, df.idx)) - def validate_fieldtype_length(self): - for field in self.check_length_for_fieldtypes: - df = field.get('df') - max_length = frappe.db.type_map.get(df.fieldtype)[1] - fieldname = df.fieldname - docs = frappe.db.sql(''' - SELECT name, {fieldname}, LENGTH({fieldname}) AS len - FROM `tab{doctype}` - WHERE LENGTH({fieldname}) > {max_length} - '''.format( - fieldname = fieldname, - doctype = self.doc_type, - max_length = max_length - ), as_dict = True) - links = [] - label = df.label - for doc in docs: - links.append(frappe.utils.get_link_to_form(self.doc_type, doc.name)) - links_str = ', '.join(links) - - if docs: - frappe.throw(_('Value for field {0} is too long in {1}. Length should be lesser than {2} characters') - .format(frappe.bold(label), links_str, frappe.bold(max_length)), title=_('Data Too Long'), is_minimizable=len(docs) > 1) - - self.flags.update_db = True - def reset_to_defaults(self): if not self.doc_type: return diff --git a/frappe/database/mariadb/database.py b/frappe/database/mariadb/database.py index 926425f857..cd053569f0 100644 --- a/frappe/database/mariadb/database.py +++ b/frappe/database/mariadb/database.py @@ -33,7 +33,7 @@ class MariaDBDatabase(Database): 'Float': ('decimal', '18,6'), 'Percent': ('decimal', '18,6'), 'Check': ('int', '1'), - 'Small Text': ('text', 65535), + 'Small Text': ('text', ''), 'Long Text': ('longtext', ''), 'Code': ('longtext', ''), 'Text Editor': ('longtext', ''), @@ -42,7 +42,7 @@ class MariaDBDatabase(Database): 'Date': ('date', ''), 'Datetime': ('datetime', '6'), 'Time': ('time', '6'), - 'Text': ('text', 65535), + 'Text': ('text', ''), 'Data': ('varchar', self.VARCHAR_LEN), 'Link': ('varchar', self.VARCHAR_LEN), 'Dynamic Link': ('varchar', self.VARCHAR_LEN), diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 73bdf32761..88cda9340b 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -69,7 +69,6 @@ class DBTable: lengths = {} precisions = {} uniques = {} - fieldtype = '' # optional fields like _comments if not self.meta.istable: @@ -101,7 +100,7 @@ class DBTable: filters={ "doc_type": self.doctype, "doctype_or_field": "DocField", - "property": ["in", ["precision", "length", "unique", "fieldtype"]] + "property": ["in", ["precision", "length", "unique"]] }): if ps.property=="length": @@ -113,13 +112,10 @@ class DBTable: elif ps.property=="unique": uniques[ps.field_name] = cint(ps.value) - if ps.property=="fieldtype": - fieldtype = ps.value - for f in fl: self.columns[f['fieldname']] = DbColumn(self, f['fieldname'], - fieldtype or f['fieldtype'], + f['fieldtype'], lengths.get(f["fieldname"]) or f.get('length'), f.get('default'), f.get('search_index'), From ba10ca1a99949b9d09b6d9bbc075185f41488bf2 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 19 Mar 2020 19:12:13 +0530 Subject: [PATCH 105/173] refactor: remove code for loading state --- .../public/js/frappe/views/desktop/desktop.js | 22 ------ frappe/public/less/desktop.less | 77 ------------------- 2 files changed, 99 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 656c5ce021..2d2b1a7353 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -15,12 +15,9 @@ export default class Desktop { make() { this.make_container(); - // this.show_loading_state(); this.fetch_desktop_settings().then(() => { this.route(); this.make_sidebar(); - // this.setup_events(); - // this.hide_loading_state(); }); } @@ -40,25 +37,6 @@ export default class Desktop { this.body = this.container.find(".desk-body"); } - show_loading_state() { - // Add skeleton - let loading_sidebar = $( - '
    ' - ); - let loading_body = $( - `
    ` - ); - - // Append skeleton to body - loading_sidebar.appendTo(this.sidebar); - loading_body.appendTo(this.body); - } - - hide_loading_state() { - // Remove all skeleton - this.container.find(".skeleton").remove(); - } - fetch_desktop_settings() { return frappe .call("frappe.desk.desktop.get_desk_sidebar_items") diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index 05f1f11113..f9e40106a6 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -351,81 +351,4 @@ .pill-orange { background: @orange; -} - -// .pill-green { -// background: @green-light; -// color: @green-dark; -// } - -// .pill-red { -// background: @red-light; -// color: @red-dark; -// } - -// .pill-blue { -// background: @blue-light; -// color: @blue-dark; -// } - -// .pill-yellow { -// background: @yellow-light; -// color: @yellow-dark; -// } - -// .pill-orange { -// background: @orange-light; -// color: @orange-dark; -// } - -.skeleton { - width: 100%; - background-image: linear-gradient(90deg, @btn-bg, @panel-bg, @btn-bg); - // background-image: linear-gradient(90deg, black, white, black); - animation: shine-lines 0.8s infinite cubic-bezier(.65,.05,.36,1) -} - -.skeleton.skeleton-full { - flex: 1 1 auto; -} - -// .skeleton.skeleton-100 { -// height: 90%; -// } - -// .skeleton.skeleton-50 { -// height: 50%; -// } - -// .skeleton.skeleton-40 { -// height: 40%; -// } - -// .skeleton.skeleton-30 { -// height: 30%; -// } - -// .skeleton.skeleton-20 { -// height: 20%; -// } - -// .skeleton.skeleton-10 { -// height: 10%; -// } - -// .skeleton.skeleton-8 { -// height: 8%; -// } - -// .skeleton.skeleton-3 { -// height: 3%; -// } - -@keyframes shine-lines { - 0% { - background-position: -100px; - } - 100% { - background-position: 100px; - } } \ No newline at end of file From 9c42d0f5d6d6e8139030c894b7ab294339007674 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 10:05:15 +0530 Subject: [PATCH 106/173] refactor: remove size option --- frappe/desk/doctype/desk_chart/desk_chart.json | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/frappe/desk/doctype/desk_chart/desk_chart.json b/frappe/desk/doctype/desk_chart/desk_chart.json index c32e774454..c3c9231353 100644 --- a/frappe/desk/doctype/desk_chart/desk_chart.json +++ b/frappe/desk/doctype/desk_chart/desk_chart.json @@ -6,8 +6,7 @@ "engine": "InnoDB", "field_order": [ "chart_name", - "label", - "size" + "label" ], "fields": [ { @@ -23,18 +22,11 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Label" - }, - { - "fieldname": "size", - "fieldtype": "Select", - "in_list_view": 1, - "label": "Size", - "options": "Full\nHalf" } ], "istable": 1, "links": [], - "modified": "2020-01-23 16:47:16.265651", + "modified": "2020-03-20 10:04:13.992228", "modified_by": "Administrator", "module": "Desk", "name": "Desk Chart", From 52ae6bda7b655324ce02fdcab2403cbaf76ccd39 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 11:17:43 +0530 Subject: [PATCH 107/173] fix: dashboard filters spacing --- frappe/public/less/desktop.less | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index f9e40106a6..b95e72c471 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -183,10 +183,23 @@ display: flex; flex-direction: row-reverse; - .btn { + // Any immidiate child + >* { align-self: center; margin-left: 5px; } + + .dashboard-date-field { + .clearfix, + .help-box { + display: none; + } + + .frappe-control, + .form-group { + margin-bottom: 0px !important; + } + } } } From 7f3b14f9f4e89f312c35568e13d2af560beb41d2 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 11:27:15 +0530 Subject: [PATCH 108/173] refactor (style): format code --- frappe/public/js/frappe/views/desktop/desktop.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 2d2b1a7353..54a25c3771 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -112,7 +112,9 @@ export default class Desktop { } get_page_to_show() { - const default_page = this.desktop_settings ? this.desktop_settings["Modules"][0].name : "Website"; + const default_page = this.desktop_settings + ? this.desktop_settings["Modules"][0].name + : "Website"; let page = frappe.get_route()[1] || localStorage.current_desk_page || @@ -130,7 +132,7 @@ export default class Desktop { return $page; } - setup_events() { } + setup_events() {} } class DesktopPage { @@ -138,7 +140,7 @@ class DesktopPage { this.container = container; this.page_name = page_name; this.sections = {}; - this.allow_customization = false + this.allow_customization = false; this.make(); } @@ -157,7 +159,7 @@ class DesktopPage { // this.make_onboarding(); if (!this.data) { delete localStorage.current_desk_page; - frappe.set_route('workspace'); + frappe.set_route("workspace"); return; } @@ -253,7 +255,7 @@ class DesktopPage { widgets: this.data.cards.items }); - this.sections['cards'] = cards; + this.sections["cards"] = cards; const legend = [ { @@ -279,4 +281,4 @@ class DesktopPage { ${legend.join("\n")}
    `).insertAfter(cards.body); } -} \ No newline at end of file +} From 07f1427bdde011b87b3301b70a06c635a809093f Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 11:27:25 +0530 Subject: [PATCH 109/173] fix: default chart label --- frappe/desk/desktop.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 108d02f529..bb9aa44213 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -139,12 +139,17 @@ class Workspace: return new_data def get_charts(self): + all_charts = [] if frappe.has_permission("Dashboard Chart", throw=False): charts = self.doc.charts if len(self.extended_charts): charts = charts + self.extended_charts - return [chart for chart in charts] - return [] + + for chart in charts: + chart.label = chart.label if chart.label else chart.chart_name + all_charts.append(chart) + + return all_charts def get_shortcuts(self): From f8cfe70b3009cf562bcbd5b2a363742248d59d2b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 11:27:53 +0530 Subject: [PATCH 110/173] refactor (style): format code --- .../public/js/frappe/widgets/chart_widget.js | 281 +++++++++++------- 1 file changed, 179 insertions(+), 102 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index a9b6b319d1..5e6585924f 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -1,7 +1,7 @@ import Widget from "./base_widget.js"; import { build_summary_item } from "./utils"; -frappe.provide('frappe.dashboards'); -frappe.provide('frappe.dashboards.chart_sources'); +frappe.provide("frappe.dashboards"); +frappe.provide("frappe.dashboards.chart_sources"); export default class ChartWidget extends Widget { constructor(opts) { @@ -17,15 +17,19 @@ export default class ChartWidget extends Widget { } set_body() { - this.widget.addClass('dashboard-widget-box'); + this.widget.addClass("dashboard-widget-box"); if (this.width == "Full") { - this.widget.addClass('full-width'); + this.widget.addClass("full-width"); } this.make_chart(); } set_loading_state() { - this.loading = $(`
    ${__("Loading...")}
    `); + this.loading = $( + `
    ${__( + "Loading..." + )}
    ` + ); this.loading.appendTo(this.body); } @@ -37,9 +41,9 @@ export default class ChartWidget extends Widget { this.$summary.empty(); } - this.summary.forEach((summary) => { + this.summary.forEach(summary => { build_summary_item(summary).appendTo(this.$summary); - }) + }); this.summary.length && this.$summary.show(); } @@ -54,7 +58,10 @@ export default class ChartWidget extends Widget { this.prepare_chart_actions(); // this.setup_refresh_button(); this.setup_filter_button(); - if (this.chart_doc.timeseries && this.chart_doc.chart_type !== 'Custom') { + if ( + this.chart_doc.timeseries && + this.chart_doc.chart_type !== "Custom" + ) { this.render_time_series_filters(); } this.fetch_and_update_chart(); @@ -69,40 +76,54 @@ export default class ChartWidget extends Widget { } setup_refresh_button() { - const refresh_button = $(``); + const refresh_button = $( + `` + ); refresh_button.appendTo(this.action_area); - refresh_button.on('click', () => this.refresh()); + refresh_button.on("click", () => this.refresh()); } render_time_series_filters() { let filters = [ { label: this.chart_doc.timespan, - options: ['Select Date Range', 'Last Year', 'Last Quarter', 'Last Month', 'Last Week'], - action: (selected_item) => { + options: [ + "Select Date Range", + "Last Year", + "Last Quarter", + "Last Month", + "Last Week" + ], + action: selected_item => { this.selected_timespan = selected_item; - if (this.selected_timespan === 'Select Date Range') { + if (this.selected_timespan === "Select Date Range") { this.render_date_range_fields(); } else { this.selected_from_date = null; this.selected_to_date = null; - if (this.date_field_wrapper) this.date_field_wrapper.hide(); + if (this.date_field_wrapper) + this.date_field_wrapper.hide(); this.fetch_and_update_chart(); } } }, { label: this.chart_doc.time_interval, - options: ['Yearly', 'Quarterly', 'Monthly', 'Weekly', 'Daily'], - action: (selected_item) => { + options: ["Yearly", "Quarterly", "Monthly", "Weekly", "Daily"], + action: selected_item => { this.selected_time_interval = selected_item; this.fetch_and_update_chart(); } - }, + } ]; - frappe.dashboard_utils.render_chart_filters(filters, 'chart-actions', this.action_area, 0); + frappe.dashboard_utils.render_chart_filters( + filters, + "chart-actions", + this.action_area, + 0 + ); } fetch_and_update_chart() { @@ -114,7 +135,7 @@ export default class ChartWidget extends Widget { }; this.fetch(this.filters, true, this.args).then(data => { - if (this.chart_doc.chart_type == 'Report') { + if (this.chart_doc.chart_type == "Report") { this.summary = data.report_summary; data = this.get_report_chart_data(data); } @@ -127,24 +148,30 @@ export default class ChartWidget extends Widget { } render_date_range_fields() { - if (!this.date_field_wrapper || !this.date_field_wrapper.is(':visible')) { - this.date_field_wrapper = - $(`
    `) - .appendTo(this.action_area); + if ( + !this.date_field_wrapper || + !this.date_field_wrapper.is(":visible") + ) { + this.date_field_wrapper = $( + `
    ` + ).appendTo(this.action_area); this.date_range_field = frappe.ui.form.make_control({ df: { - fieldtype: 'DateRange', - fieldname: 'from_date', - placeholder: 'Date Range', - input_class: 'input-xs', + fieldtype: "DateRange", + fieldname: "from_date", + placeholder: "Date Range", + input_class: "input-xs", reqd: 1, change: () => { let selected_date_range = this.date_range_field.get_value(); this.selected_from_date = selected_date_range[0]; this.selected_to_date = selected_date_range[1]; - if (selected_date_range && selected_date_range.length == 2) { + if ( + selected_date_range && + selected_date_range.length == 2 + ) { this.fetch_and_update_chart(); } } @@ -160,7 +187,7 @@ export default class ChartWidget extends Widget { return result.chart.data; } else { let y_fields = []; - this.chart_doc.y_axis.map( field => { + this.chart_doc.y_axis.map(field => { y_fields.push(field.y_field); }); @@ -170,11 +197,15 @@ export default class ChartWidget extends Widget { chart_type: this.chart_doc.type, color: this.chart_doc.color }; - let columns = result.columns.map((col)=> { + let columns = result.columns.map(col => { return frappe.report_utils.prepare_field_from_column(col); }); - let data = frappe.report_utils.make_chart_options(columns, result, chart_fields).data; + let data = frappe.report_utils.make_chart_options( + columns, + result, + chart_fields + ).data; return data; } } @@ -183,7 +214,7 @@ export default class ChartWidget extends Widget { let actions = [ { label: __("Refresh"), - action: 'action-refresh', + action: "action-refresh", handler: () => { delete this.dashboard_chart; this.make_chart(); @@ -191,9 +222,13 @@ export default class ChartWidget extends Widget { }, { label: __("Edit..."), - action: 'action-edit', + action: "action-edit", handler: () => { - frappe.set_route('Form', 'Dashboard Chart', this.chart_doc.name); + frappe.set_route( + "Form", + "Dashboard Chart", + this.chart_doc.name + ); } } ]; @@ -201,40 +236,51 @@ export default class ChartWidget extends Widget { if (this.chart_doc.document_type) { actions.push({ label: __("{0} List", [this.chart_doc.document_type]), - action: 'action-list', + action: "action-list", handler: () => { - frappe.set_route('List', this.chart_doc.document_type); + frappe.set_route("List", this.chart_doc.document_type); } }); - } else if (this.chart_doc.chart_type === 'Report') { + } else if (this.chart_doc.chart_type === "Report") { actions.push({ label: __("{0} Report", [this.chart_doc.report_name]), - action: 'action-list', + action: "action-list", handler: () => { - frappe.set_route('query-report', this.chart_doc.report_name); + frappe.set_route( + "query-report", + this.chart_doc.report_name + ); } - }) + }); } this.set_chart_actions(actions); } setup_filter_button() { - this.is_document_type = this.chart_doc.chart_type!== 'Report' && this.chart_doc.chart_type!=='Custom'; - this.filter_button = - $(`
    ${__("Filter")}
    `); + this.is_document_type = + this.chart_doc.chart_type !== "Report" && + this.chart_doc.chart_type !== "Custom"; + this.filter_button = $( + `
    ${__( + "Filter" + )}
    ` + ); this.filter_button.appendTo(this.action_area); - this.filter_button.on('click', () => { + this.filter_button.on("click", () => { let fields; - frappe.dashboard_utils.get_filters_for_chart_type(this.chart_doc) + frappe.dashboard_utils + .get_filters_for_chart_type(this.chart_doc) .then(filters => { if (!this.is_document_type) { if (!filters) { - fields = [{ - fieldtype: "HTML", - options: __("No Filters Set") - }]; + fields = [ + { + fieldtype: "HTML", + options: __("No Filters Set") + } + ]; } else { fields = filters.filter(f => { if (f.on_change && !f.reqd) { @@ -247,10 +293,12 @@ export default class ChartWidget extends Widget { }); } } else { - fields = [{ - fieldtype: 'HTML', - fieldname: 'filter_area', - }]; + fields = [ + { + fieldtype: "HTML", + fieldname: "filter_area" + } + ]; } this.setup_filter_dialog(fields); @@ -259,7 +307,6 @@ export default class ChartWidget extends Widget { } setup_filter_dialog(fields) { - let me = this; let dialog = new frappe.ui.Dialog({ title: __(`Set Filters for ${this.chart_doc.chart_name}`), @@ -280,19 +327,20 @@ export default class ChartWidget extends Widget { }); if (this.is_document_type) { - this.create_filter_group_and_add_filters(dialog.get_field('filter_area').$wrapper); + this.create_filter_group_and_add_filters( + dialog.get_field("filter_area").$wrapper + ); } dialog.show(); dialog.set_values(this.filters); - } create_filter_group_and_add_filters(parent) { this.filter_group = new frappe.ui.FilterGroup({ parent: parent, doctype: this.chart_doc.document_type, - on_change: () => {}, + on_change: () => {} }); frappe.model.with_doctype(this.chart_doc.document_type, () => { @@ -306,7 +354,14 @@ export default class ChartWidget extends Widget {
    `); @@ -318,52 +373,55 @@ export default class ChartWidget extends Widget { this.chart_actions.appendTo(this.action_area); } - fetch(filters, refresh=false, args) { - let method = this.settings ? this.settings.method - : 'frappe.desk.doctype.dashboard_chart.dashboard_chart.get'; + fetch(filters, refresh = false, args) { + let method = this.settings + ? this.settings.method + : "frappe.desk.doctype.dashboard_chart.dashboard_chart.get"; - if (this.chart_doc.chart_type == 'Report') { + if (this.chart_doc.chart_type == "Report") { args = { report_name: this.chart_doc.report_name, - filters: filters, + filters: filters }; } else { args = { chart_name: this.chart_doc.name, filters: filters, refresh: refresh ? 1 : 0, - time_interval: args && args.time_interval? args.time_interval: null, - timespan: args && args.timespan? args.timespan: null, - from_date: args && args.from_date? args.from_date: null, - to_date: args && args.to_date? args.to_date: null, + time_interval: + args && args.time_interval ? args.time_interval : null, + timespan: args && args.timespan ? args.timespan : null, + from_date: args && args.from_date ? args.from_date : null, + to_date: args && args.to_date ? args.to_date : null }; } - return frappe.xcall( - method, - args - ); + return frappe.xcall(method, args); } render() { const chart_type_map = { - 'Line': 'line', - 'Bar': 'bar', - 'Percentage': 'percentage', - 'Pie': 'pie' + Line: "line", + Bar: "bar", + Percentage: "percentage", + Pie: "pie" }; let colors = []; if (this.chart_doc.y_axis.length) { - this.chart_doc.y_axis.map( field => { + this.chart_doc.y_axis.map(field => { colors.push(field.color); }); - } else if (['Line', 'Bar'].includes(this.chart_doc.type)) { + } else if (["Line", "Bar"].includes(this.chart_doc.type)) { colors = [this.chart_doc.color || "light-blue"]; } - if (!this.data || !Object.keys(this.data).length) { - const empty = $(`
    ${__("No Data...")}
    `); + if (!this.data.labels || !this.data || !Object.keys(this.data).length) { + const empty = $( + `
    ${__( + "No Data..." + )}
    ` + ); empty.appendTo(this.body); } else { let chart_args = { @@ -376,7 +434,10 @@ export default class ChartWidget extends Widget { } }; if (!this.dashboard_chart) { - this.dashboard_chart = new frappe.Chart(this.body[0], chart_args); + this.dashboard_chart = new frappe.Chart( + this.body[0], + chart_args + ); } else { this.dashboard_chart.update(this.data); } @@ -385,7 +446,9 @@ export default class ChartWidget extends Widget { } update_last_synced() { - let last_synced_text = __("Last synced {0}", [comment_when(this.chart_doc.last_synced_on)]); + let last_synced_text = __("Last synced {0}", [ + comment_when(this.chart_doc.last_synced_on) + ]); this.footer.html(last_synced_text); } @@ -398,32 +461,46 @@ export default class ChartWidget extends Widget { } prepare_chart_object() { - this.filters = this.filters || JSON.parse(this.chart_doc.filters_json || '[]'); + this.filters = + this.filters || JSON.parse(this.chart_doc.filters_json || "[]"); } get_settings() { - return frappe.model.with_doc("Dashboard Chart", this.chart_name).then(chart_doc => { - this.chart_doc = chart_doc; - if (this.chart_doc.chart_type == 'Custom') { - // custom source - if (frappe.dashboards.chart_sources[this.chart_doc.source]) { - this.settings = frappe.dashboards.chart_sources[this.chart_doc.source]; + return frappe.model + .with_doc("Dashboard Chart", this.chart_name) + .then(chart_doc => { + this.chart_doc = chart_doc; + if (this.chart_doc.chart_type == "Custom") { + // custom source + if ( + frappe.dashboards.chart_sources[this.chart_doc.source] + ) { + this.settings = + frappe.dashboards.chart_sources[ + this.chart_doc.source + ]; + return Promise.resolve(); + } else { + const method = + "frappe.desk.doctype.dashboard_chart_source.dashboard_chart_source.get_config"; + return frappe + .xcall(method, { name: this.chart_doc.source }) + .then(config => { + frappe.dom.eval(config); + this.settings = + frappe.dashboards.chart_sources[ + this.chart_doc.source + ]; + }); + } + } else if (this.chart_doc.chart_type == "Report") { + this.settings = { + method: "frappe.desk.query_report.run" + }; return Promise.resolve(); } else { - const method = 'frappe.desk.doctype.dashboard_chart_source.dashboard_chart_source.get_config'; - return frappe.xcall(method, {name: this.chart_doc.source}).then(config => { - frappe.dom.eval(config); - this.settings = frappe.dashboards.chart_sources[this.chart_doc.source]; - }); + return Promise.resolve(); } - } else if (this.chart_doc.chart_type == 'Report') { - this.settings = { - 'method': 'frappe.desk.query_report.run' - }; - return Promise.resolve(); - } else { - return Promise.resolve(); - } - }); + }); } } \ No newline at end of file From 26d9a378e16e39fdf18d1b622a3c9d08a4ad6d23 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 11:28:16 +0530 Subject: [PATCH 111/173] fix: improved grid rules --- frappe/public/less/desktop.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index b95e72c471..d79c4ce726 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -124,7 +124,7 @@ .grid-col-2 { display: grid; - grid-template-columns: repeat(auto-fill, minmax(550px, 1fr)); + grid-template-columns: 1fr 1fr; // grid-auto-rows: minmax(62px, 1fr); column-gap: 15px; row-gap: 15px; @@ -138,7 +138,7 @@ .grid-col-1 { display: grid; - grid-template-columns: repeat(1fr); + grid-template-columns: repeat(auto-fill, minmax(550px, 1fr)); // grid-auto-rows: minmax(62px, 1fr); column-gap: 15px; row-gap: 15px; From 6721a4274d4bdb4a723796d78c03ed2dead0c3ca Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 11:43:33 +0530 Subject: [PATCH 112/173] feat: hide title when date range field is shown for half width widget --- frappe/public/js/frappe/widgets/chart_widget.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 5e6585924f..4f29006550 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -102,8 +102,15 @@ export default class ChartWidget extends Widget { } else { this.selected_from_date = null; this.selected_to_date = null; - if (this.date_field_wrapper) + if (this.date_field_wrapper) { this.date_field_wrapper.hide(); + + // Title maybe hidden becuase of date range fields + // in half width chart + this.title_field.show(); + this.head.css('flex-direction', "row"); + } + this.fetch_and_update_chart(); } } @@ -156,6 +163,11 @@ export default class ChartWidget extends Widget { `
    ` ).appendTo(this.action_area); + if(this.width != "Full" && this.widget.width() < 700) { + this.title_field.hide(); + this.head.css('flex-direction', "row-reverse"); + } + this.date_range_field = frappe.ui.form.make_control({ df: { fieldtype: "DateRange", From 0bfcd4d57460a68d622519d181122e9301c63d83 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 12:29:11 +0530 Subject: [PATCH 113/173] fix: better logic for managing UI states --- .../public/js/frappe/widgets/chart_widget.js | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 4f29006550..3f1afab67a 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -6,6 +6,7 @@ frappe.provide("frappe.dashboards.chart_sources"); export default class ChartWidget extends Widget { constructor(opts) { super(opts); + this.height = 240; } refresh() { @@ -24,13 +25,25 @@ export default class ChartWidget extends Widget { this.make_chart(); } - set_loading_state() { + setup_container() { + this.body.empty(); + this.loading = $( - `
    ${__( + `
    ${__( "Loading..." )}
    ` ); - this.loading.appendTo(this.body); + this.loading.hide().appendTo(this.body); + + this.empty = $( + `
    ${__( + "No Data..." + )}
    ` + ); + this.empty.hide().appendTo(this.body); + + this.chart_wrapper = $(`
    `); + this.chart_wrapper.appendTo(this.body); } set_summary() { @@ -48,22 +61,20 @@ export default class ChartWidget extends Widget { } make_chart() { - this.body.empty(); this.get_settings().then(() => { - this.set_loading_state(); + this.setup_container(); this.prepare_chart_object(); - // this.prepare_container(); - this.action_area.empty(); this.prepare_chart_actions(); - // this.setup_refresh_button(); this.setup_filter_button(); + if ( this.chart_doc.timeseries && this.chart_doc.chart_type !== "Custom" ) { this.render_time_series_filters(); } + this.fetch_and_update_chart(); }); } @@ -75,14 +86,6 @@ export default class ChartWidget extends Widget { buttons.appendTo(this.action_area); } - setup_refresh_button() { - const refresh_button = $( - `` - ); - refresh_button.appendTo(this.action_area); - refresh_button.on("click", () => this.refresh()); - } - render_time_series_filters() { let filters = [ { @@ -149,7 +152,6 @@ export default class ChartWidget extends Widget { this.update_chart_object(); this.data = data; - this.loading.remove(); this.render(); }); } @@ -428,18 +430,20 @@ export default class ChartWidget extends Widget { colors = [this.chart_doc.color || "light-blue"]; } - if (!this.data.labels || !this.data || !Object.keys(this.data).length) { - const empty = $( - `
    ${__( - "No Data..." - )}
    ` - ); - empty.appendTo(this.body); + if (!this.data || !this.data.labels.length || !Object.keys(this.data).length) { + this.chart_wrapper.hide(); + this.loading.hide(); + this.empty.show(); } else { + this.loading.hide(); + this.empty.hide(); + this.chart_wrapper.show(); + let chart_args = { data: this.data, type: chart_type_map[this.chart_doc.type], colors: colors, + height: this.height, axisOptions: { xIsSeries: this.chart_doc.timeseries, shortenYAxisNumbers: 1 @@ -447,7 +451,7 @@ export default class ChartWidget extends Widget { }; if (!this.dashboard_chart) { this.dashboard_chart = new frappe.Chart( - this.body[0], + this.chart_wrapper[0], chart_args ); } else { From 6afe5552c55d19f7e9d4437e1969e394c4f2e627 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 13:23:40 +0530 Subject: [PATCH 114/173] fix (codacy): linitng fixes --- frappe/public/js/frappe/widgets/chart_widget.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 3f1afab67a..2f3c70ec15 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -165,7 +165,7 @@ export default class ChartWidget extends Widget { `
    ` ).appendTo(this.action_area); - if(this.width != "Full" && this.widget.width() < 700) { + if (this.width != "Full" && this.widget.width() < 700) { this.title_field.hide(); this.head.css('flex-direction', "row-reverse"); } @@ -363,6 +363,7 @@ export default class ChartWidget extends Widget { } set_chart_actions(actions) { + /* eslint-disable indent */ this.chart_actions = $(`${values.dashboard}`; - let message = + let message = __(`Dashboard Chart ${values.chart_name} add to Dashboard ` + dashboard_route_html); frappe.msgprint(message); }); - + d.hide(); } }); @@ -119,15 +119,13 @@ frappe.ui.form.on('Dashboard Chart', { frm.trigger('set_chart_field_options'); } else { frappe.report_utils.get_report_filters(report_name).then(filters => { - frappe.after_ajax(()=> { - if (filters) { - frm.chart_filters = filters; - let filter_values = frappe.report_utils.get_filter_values(filters); - frm.set_value('filters_json', JSON.stringify(filter_values)); - } - frm.trigger('show_filters'); - frm.trigger('set_chart_field_options'); - }); + if (filters) { + frm.chart_filters = filters; + let filter_values = frappe.report_utils.get_filter_values(filters); + frm.set_value('filters_json', JSON.stringify(filter_values)); + } + frm.trigger('show_filters'); + frm.trigger('set_chart_field_options'); }); } @@ -140,7 +138,8 @@ frappe.ui.form.on('Dashboard Chart', { 'frappe.desk.query_report.run', { report_name: frm.doc.report_name, - filters: filters + filters: filters, + ignore_prepared_report: 1 } ).then(data => { frm.report_data = data; @@ -228,13 +227,11 @@ frappe.ui.form.on('Dashboard Chart', { show_filters: function(frm) { frm.chart_filters = []; frappe.dashboard_utils.get_filters_for_chart_type(frm.doc).then(filters => { - frappe.after_ajax(() => { if (filters) { frm.chart_filters = filters; } frm.trigger('render_filters_table'); - }); }); }, @@ -269,7 +266,7 @@ frappe.ui.form.on('Dashboard Chart', { if (filters.length > 0) { filters.forEach( filter => { - const filter_row = + const filter_row = $(` ${filter[1]} ${filter[2] || ""} @@ -295,7 +292,7 @@ frappe.ui.form.on('Dashboard Chart', { fields.map( f => { if (filters[f.fieldname]) { let condition = '='; - const filter_row = + const filter_row = $(` ${f.label} ${condition} diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 2f3c70ec15..0b19987e7c 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -397,7 +397,8 @@ export default class ChartWidget extends Widget { if (this.chart_doc.chart_type == "Report") { args = { report_name: this.chart_doc.report_name, - filters: filters + filters: filters, + ignore_prepared_report: 1 }; } else { args = { From f79603e47b61bf3fa9fa0760b92ec1d6c1f20059 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 15:27:44 +0530 Subject: [PATCH 118/173] refactor: use after_ajax to return filters --- frappe/public/js/frappe/views/reports/report_utils.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/views/reports/report_utils.js b/frappe/public/js/frappe/views/reports/report_utils.js index bd01d63c47..218017244e 100644 --- a/frappe/public/js/frappe/views/reports/report_utils.js +++ b/frappe/public/js/frappe/views/reports/report_utils.js @@ -112,13 +112,14 @@ frappe.report_utils = { return frappe.xcall( 'frappe.desk.query_report.get_script', - { + { report_name: report_name } ).then(r => { frappe.dom.eval(r.script || ''); - let filters = frappe.query_reports[report_name].filters; - return Promise.resolve(filters); + frappe.after_ajax(() => { + return frappe.query_reports[report_name].filters; + }) }); }, From 1abc0264c0af9be2cf06fceca06df03fd7e88cbe Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 20 Mar 2020 15:32:43 +0530 Subject: [PATCH 119/173] fix: missing return statement --- frappe/public/js/frappe/views/reports/report_utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/reports/report_utils.js b/frappe/public/js/frappe/views/reports/report_utils.js index 218017244e..a8149b9134 100644 --- a/frappe/public/js/frappe/views/reports/report_utils.js +++ b/frappe/public/js/frappe/views/reports/report_utils.js @@ -117,7 +117,7 @@ frappe.report_utils = { } ).then(r => { frappe.dom.eval(r.script || ''); - frappe.after_ajax(() => { + return frappe.after_ajax(() => { return frappe.query_reports[report_name].filters; }) }); From de1d8d0acda7a086a703920372b98b3b6b3b5bcb Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 20 Mar 2020 15:36:39 +0530 Subject: [PATCH 120/173] fix: hide summary if no data --- frappe/public/js/frappe/widgets/chart_widget.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 0b19987e7c..3388890776 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -436,6 +436,7 @@ export default class ChartWidget extends Widget { if (!this.data || !this.data.labels.length || !Object.keys(this.data).length) { this.chart_wrapper.hide(); this.loading.hide(); + this.$summary.hide(); this.empty.show(); } else { this.loading.hide(); From c615042d259797d4110df4e69da38c5983786df4 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Fri, 20 Mar 2020 16:10:58 +0530 Subject: [PATCH 121/173] fix: develop version as 12.0.0.dev instead of 12.1.0 (#9746) * fix: develop version as 12.x.x instead of 12.1.0 * fix: develop version as 12.0.0.dev * fix: develop version as 12.0.0-dev --- frappe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index e2d8041992..e19327fcff 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ if PY2: reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '12.1.0' +__version__ = '12.0.0-dev' __title__ = "Frappe Framework" local = Local() From 17f25fafcb082a70d8cc062753180f12766a6b80 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 18:57:40 +0530 Subject: [PATCH 122/173] fix: responsive dashboards --- frappe/public/less/desktop.less | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index d79c4ce726..a221e4c3d6 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -154,6 +154,14 @@ margin-right: 20px; } } + + .grid-col-2 { + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + .full-width { + grid-column-start: 1; + grid-column-end: 2; + } + } } } From 3f1ba29620ae1b55ce41480e5cd67523c21cdd89 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 19:04:00 +0530 Subject: [PATCH 123/173] fix: responsive chart widget in desk --- frappe/public/less/desktop.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index a221e4c3d6..9df4addf61 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -162,6 +162,10 @@ grid-column-end: 2; } } + + .grid-col-1 { + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + } } } From 641892b0cc81e5d2c0a8f9a53da91c4a930753dc Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 20 Mar 2020 19:44:14 +0530 Subject: [PATCH 124/173] feat: disable sortable on dashboard --- frappe/core/page/dashboard/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/page/dashboard/dashboard.js b/frappe/core/page/dashboard/dashboard.js index e2da785f4e..511aac7010 100644 --- a/frappe/core/page/dashboard/dashboard.js +++ b/frappe/core/page/dashboard/dashboard.js @@ -92,7 +92,7 @@ class Dashboard { container: this.container, type: "chart", columns: 2, - allow_sorting: true, + allow_sorting: false, widgets: this.charts, }); }); From 64150d471721d4ef8ac40ad3b09bf722db5a880d Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 20 Mar 2020 21:13:35 +0530 Subject: [PATCH 125/173] fix: fix dropdown caret spacing in list sidebar --- frappe/public/js/frappe/list/list_sidebar.html | 2 +- frappe/public/js/frappe/list/list_sidebar_group_by.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/list/list_sidebar.html b/frappe/public/js/frappe/list/list_sidebar.html index f8e868da20..90189ccdea 100644 --- a/frappe/public/js/frappe/list/list_sidebar.html +++ b/frappe/public/js/frappe/list/list_sidebar.html @@ -64,7 +64,7 @@