From 369e4ff5782ef30d8e01506d4b3c58a1ec71d18f Mon Sep 17 00:00:00 2001 From: Himanshu Date: Tue, 29 Oct 2019 15:22:38 +0530 Subject: [PATCH 01/43] Patch(Tags): Check if column exists (#8682) * fix: tags patch * fix: auto_commit_on_many_writes * fix: check if tag exists * fix: check if tag or tag link exists * fix: check if column exists * fix: set autocommit false * fix: use ignore in insert query for bulk insert * fix: add option to ignore duplicates --- frappe/database/database.py | 5 +++-- frappe/patches.txt | 1 + frappe/patches/v12_0/setup_tags.py | 19 +++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/frappe/database/database.py b/frappe/database/database.py index 95096ed2d9..1e6a85236e 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -968,7 +968,7 @@ class Database(object): frappe.flags.touched_tables = set() frappe.flags.touched_tables.update(tables) - def bulk_insert(self, doctype, fields, values): + def bulk_insert(self, doctype, fields, values, ignore_duplicates=False): """ Insert multiple records at a time @@ -982,7 +982,8 @@ class Database(object): for idx, value in enumerate(values): insert_list.append(tuple(value)) if idx and (idx%10000 == 0 or idx < len(values)-1): - self.sql("""INSERT INTO `tab{doctype}` ({fields}) VALUES {values}""".format( + self.sql("""INSERT {ignore_duplicates} INTO `tab{doctype}` ({fields}) VALUES {values}""".format( + ignore_duplicates="IGNORE" if ignore_duplicates else "", doctype=doctype, fields=fields, values=", ".join(['%s'] * len(insert_list)) diff --git a/frappe/patches.txt b/frappe/patches.txt index 8321debf3a..621a2107df 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -254,3 +254,4 @@ frappe.patches.v12_0.delete_duplicate_indexes frappe.patches.v12_0.set_default_incoming_email_port frappe.patches.v12_0.update_global_search execute:frappe.reload_doc('desk', 'doctype', 'notification_settings') +frappe.patches.v12_0.setup_tags diff --git a/frappe/patches/v12_0/setup_tags.py b/frappe/patches/v12_0/setup_tags.py index cd50b0d505..d663cb2e0e 100644 --- a/frappe/patches/v12_0/setup_tags.py +++ b/frappe/patches/v12_0/setup_tags.py @@ -12,19 +12,22 @@ def execute(): time = frappe.utils.get_datetime() for doctype in frappe.get_list("DocType", filters={"istable": 0, "issingle": 0}): - for dt_tags in frappe.db.sql("select `name`, `_user_tags` from `tab{0}`".format(doctype.name), as_dict=True): - tags = dt_tags.get("_user_tags").split(",") if dt_tags.get("_user_tags") else None - if not tags: + if not frappe.db.count(doctype.name) or not frappe.db.has_column(doctype.name, "_user_tags"): + continue + + for _user_tags in frappe.db.sql("select `name`, `_user_tags` from `tab{0}`".format(doctype.name), as_dict=True): + if not _user_tags.get("_user_tags"): continue - for tag in tags: + for tag in _user_tags.get("_user_tags").split(",") if _user_tags.get("_user_tags") else []: if not tag: continue tag_list.append((tag.strip(), time, time, 'Administrator')) - tag_link_name = frappe.generate_hash(dt_tags.name + tag.strip() + doctype.name, 10), - tag_links.append((tag_link_name, doctype.name, dt_tags.name, tag.strip(), time, time, 'Administrator')) + tag_link_name = frappe.generate_hash(_user_tags.name + tag.strip() + doctype.name, 10) + tag_links.append((tag_link_name, doctype.name, _user_tags.name, tag.strip(), time, time, 'Administrator')) - frappe.db.bulk_insert("Tag", fields=["name", "creation", "modified", "modified_by"], values=set(tag_list)) - frappe.db.bulk_insert("Tag Link", fields=["name", "document_type", "document_name", "tag", "creation", "modified", "modified_by"], values=set(tag_links)) \ No newline at end of file + + frappe.db.bulk_insert("Tag", fields=["name", "creation", "modified", "modified_by"], values=set(tag_list), ignore_duplicates=True) + frappe.db.bulk_insert("Tag Link", fields=["name", "document_type", "document_name", "tag", "creation", "modified", "modified_by"], values=set(tag_links), ignore_duplicates=True) From f185ed979088bf4e0906f721bc033f06c30dd7b9 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Wed, 30 Oct 2019 13:09:26 +0550 Subject: [PATCH 02/43] bumped to version 12.0.18 --- frappe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 6424dcd9b5..77207e017f 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ if sys.version[0] == '2': reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '12.0.17' +__version__ = '12.0.18' __title__ = "Frappe Framework" local = Local() From 2693b357aa1c8c13bf222a79a9b383472271c8ba Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Wed, 30 Oct 2019 13:09:26 +0550 Subject: [PATCH 03/43] bumped to version 12.0.18 --- frappe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 6424dcd9b5..77207e017f 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ if sys.version[0] == '2': reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '12.0.17' +__version__ = '12.0.18' __title__ = "Frappe Framework" local = Local() From f8da1dffc3840ffbff0b76274f6c0a2c7e38500e Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Fri, 15 Nov 2019 14:22:08 +0530 Subject: [PATCH 04/43] fix(notification_log): skip enqueue_create_notification during new site creation --- frappe/desk/doctype/notification_log/notification_log.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index 8f43cdc2b9..9425e105e4 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -26,6 +26,15 @@ def get_permission_query_conditions(for_user): return '''(`tabNotification Log`.for_user = '{user}')'''.format(user=for_user) def enqueue_create_notification(users, doc): + ''' + During installation of new site, enqueue_create_notification tries to connect to Redis. + This breaks new site creation if Redis server is not running. + We do not need any notifications in fresh installation + ''' + + if frappe.flags.in_install: + return + doc = frappe._dict(doc) if isinstance(users, frappe.string_types): From eaa2cfda594782de96f130f2f16fd909f4f02918 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Tue, 19 Nov 2019 10:06:15 +0530 Subject: [PATCH 05/43] fix: revert "unique" fields in chat_*.json --- frappe/chat/doctype/chat_profile/chat_profile.json | 3 +-- frappe/chat/doctype/chat_token/chat_token.json | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/frappe/chat/doctype/chat_profile/chat_profile.json b/frappe/chat/doctype/chat_profile/chat_profile.json index f585924930..eb36f803fe 100644 --- a/frappe/chat/doctype/chat_profile/chat_profile.json +++ b/frappe/chat/doctype/chat_profile/chat_profile.json @@ -22,8 +22,7 @@ "fieldtype": "Link", "label": "User", "options": "User", - "reqd": 1, - "unique": 1 + "reqd": 1 }, { "default": "Online", diff --git a/frappe/chat/doctype/chat_token/chat_token.json b/frappe/chat/doctype/chat_token/chat_token.json index 40b85c5c6e..b73505ac2c 100644 --- a/frappe/chat/doctype/chat_token/chat_token.json +++ b/frappe/chat/doctype/chat_token/chat_token.json @@ -16,8 +16,7 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Token", - "reqd": 1, - "unique": 1 + "reqd": 1 }, { "fieldname": "ip_address", From a1b94fca7161bd797df1ac47b6fefdd1d88f74d5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 19 Nov 2019 15:40:16 +0530 Subject: [PATCH 06/43] fix: change code type to data in standard filter --- frappe/public/js/frappe/list/base_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index 648a3d6d55..2c5e1df1df 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -614,7 +614,7 @@ class FilterArea { let options = df.options; let condition = '='; let fieldtype = df.fieldtype; - if (['Text', 'Small Text', 'Text Editor', 'Data'].includes(fieldtype)) { + if (['Text', 'Small Text', 'Text Editor', 'Data', 'Code'].includes(fieldtype)) { fieldtype = 'Data'; condition = 'like'; } From f629d7fd01af09de3e547b769b41c8024e04ad4d Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 20 Nov 2019 15:31:13 +0530 Subject: [PATCH 07/43] fix: MultiSelect backspace on input - Dont clear values if backspace is pressed on input --- frappe/public/js/frappe/form/controls/multiselect_list.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frappe/public/js/frappe/form/controls/multiselect_list.js b/frappe/public/js/frappe/form/controls/multiselect_list.js index c9ea23e9da..0313ee70d7 100644 --- a/frappe/public/js/frappe/form/controls/multiselect_list.js +++ b/frappe/public/js/frappe/form/controls/multiselect_list.js @@ -61,6 +61,9 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ }); this.$list_wrapper.on('keydown', e => { + if ($(e.target).is('input')) { + return; + } if (e.key === 'Backspace') { this.set_value([]); } From 175b974910faf36fffea1cc064f4964584adca62 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 15 Nov 2019 15:44:39 +0530 Subject: [PATCH 08/43] fix(pdf): Remove unnecessary argument https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote https://docs.python.org/2/library/urllib.html#urllib.quote --- frappe/utils/response.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/response.py b/frappe/utils/response.py index 886baf2c37..8169986e44 100644 --- a/frappe/utils/response.py +++ b/frappe/utils/response.py @@ -90,7 +90,7 @@ def as_json(): def as_pdf(): response = Response() response.mimetype = "application/pdf" - encoded_filename = quote(frappe.response['filename'].replace(' ', '_'), encoding='utf-8') + encoded_filename = quote(frappe.response['filename'].replace(' ', '_')) response.headers["Content-Disposition"] = ("filename=\"%s\"" % frappe.response['filename'].replace(' ', '_') + ";filename*=utf-8''%s" % encoded_filename).encode("utf-8") response.data = frappe.response['filecontent'] return response From 1e26a73b8e44db5a3c24d41295e1553776474ed6 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Sat, 16 Nov 2019 18:59:36 +0530 Subject: [PATCH 09/43] fix: Fallback for label in Table --- frappe/public/js/frappe/form/grid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index 90e0f90be7..3de62daf64 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -52,7 +52,7 @@ export default class Grid { let template = `
- +
From 2e95a1be140875c6cdc992965063aa657cbb8786 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 19 Nov 2019 13:39:01 +0530 Subject: [PATCH 10/43] fix: Only execute enabled server scripts --- frappe/core/doctype/server_script/server_script_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/server_script/server_script_utils.py b/frappe/core/doctype/server_script/server_script_utils.py index 0399dea106..878810f459 100644 --- a/frappe/core/doctype/server_script/server_script_utils.py +++ b/frappe/core/doctype/server_script/server_script_utils.py @@ -56,8 +56,10 @@ def get_server_script_map(): script_map = frappe.cache().get_value('server_script_map') if script_map is None: script_map = {} - for script in frappe.get_all('Server Script', ('name', 'reference_doctype', 'doctype_event', - 'api_method', 'script_type')): + enabled_server_scripts = frappe.get_all('Server Script', + fields=('name', 'reference_doctype', 'doctype_event','api_method', 'script_type'), + filters={'disabled': 0}) + for script in enabled_server_scripts: if script.script_type == 'DocType Event': script_map.setdefault(script.reference_doctype, {}).setdefault(script.doctype_event, []).append(script.name) else: From 1e68dde420b41903c26905ed3747f569c2c9e7ca Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 18 Nov 2019 15:52:23 +0530 Subject: [PATCH 11/43] fix: permission issue for activity --- frappe/core/doctype/activity_log/feed.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/activity_log/feed.py b/frappe/core/doctype/activity_log/feed.py index 22a7a3ee14..f51692fe9f 100644 --- a/frappe/core/doctype/activity_log/feed.py +++ b/frappe/core/doctype/activity_log/feed.py @@ -81,9 +81,9 @@ def get_feed_match_conditions(user=None, doctype='Comment'): if user_permissions: can_read_docs = [] - for doctype, obj in user_permissions.items(): + for dt, obj in user_permissions.items(): for n in obj: - can_read_docs.append('{}|{}'.format(doctype, frappe.db.escape(n.get('doc', '')))) + can_read_docs.append('{}|{}'.format(frappe.db.escape(dt), frappe.db.escape(n.get('doc', '')))) if can_read_docs: conditions.append("concat_ws('|', `tab{doctype}`.reference_doctype, `tab{doctype}`.reference_name) in ({values})".format( From e61f973788006da5dc422efb7b0fff69a9b356ea Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 15 Nov 2019 17:08:46 +0530 Subject: [PATCH 12/43] fix: Cache can_import list for all users and not just System Managers --- frappe/core/doctype/data_import/data_import.js | 7 ++++--- frappe/core/doctype/data_import/data_import.py | 5 ++--- frappe/utils/user.py | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frappe/core/doctype/data_import/data_import.js b/frappe/core/doctype/data_import/data_import.js index c5bd4e99c9..9391b262d7 100644 --- a/frappe/core/doctype/data_import/data_import.js +++ b/frappe/core/doctype/data_import/data_import.js @@ -3,19 +3,20 @@ frappe.ui.form.on('Data Import', { onload: function(frm) { - if(frm.doc.__islocal) { + if (frm.doc.__islocal) { frm.set_value("action", ""); } frappe.call({ - method: "frappe.core.doctype.data_import.data_import.get_importable_doc", + method: "frappe.core.doctype.data_import.data_import.get_importable_doctypes", callback: function (r) { + let importable_doctypes = r.message; frm.set_query("reference_doctype", function () { return { "filters": { "issingle": 0, "istable": 0, - "name": ['in', r.message] + "name": ['in', importable_doctypes] } }; }); diff --git a/frappe/core/doctype/data_import/data_import.py b/frappe/core/doctype/data_import/data_import.py index 80f8553121..ecf34d24b0 100644 --- a/frappe/core/doctype/data_import/data_import.py +++ b/frappe/core/doctype/data_import/data_import.py @@ -30,9 +30,8 @@ class DataImport(Document): @frappe.whitelist() -def get_importable_doc(): - import_lst = frappe.cache().hget("can_import", frappe.session.user) - return import_lst +def get_importable_doctypes(): + return frappe.cache().hget("can_import", frappe.session.user) @frappe.whitelist() def import_data(data_import): diff --git a/frappe/utils/user.py b/frappe/utils/user.py index e0c943d7c5..fa114d0e3c 100755 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -161,7 +161,8 @@ class UserPermissions: for docname in docs: if frappe.get_meta(docname, cached=True).allow_import == 1: self.can_import.append(docname) - frappe.cache().hset("can_import", frappe.session.user, self.can_import) + + frappe.cache().hset("can_import", frappe.session.user, self.can_import) def get_defaults(self): import frappe.defaults From 327d27b83d998b0b52bfd453fd63e8e7cea2a500 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 13 Nov 2019 11:48:20 +0530 Subject: [PATCH 13/43] fix(List): save checked rows on auto refresh --- frappe/public/js/frappe/list/list_view.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 6912065e1c..a1fe886484 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1077,10 +1077,20 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { }); this.toggle_result_area(); this.render_list(); + if (this.$checks.length) { + this.set_rows_as_checked(); + } }); }); } + set_rows_as_checked() { + $.each(this.$checks, (i, el) => { + let docname = $(el).attr('data-name'); + this.$result.find(`.list-row-checkbox[data-name='${docname}']`).click(); + }); + } + on_row_checked() { this.$list_head_subject = this.$list_head_subject || this.$result.find('header .list-header-subject'); this.$checkbox_actions = this.$checkbox_actions || this.$result.find('header .checkbox-actions'); From 63c703389d74160c4571fed156b3a938bf80afb2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 15 Nov 2019 13:47:32 +0530 Subject: [PATCH 14/43] fix: Make code explicit .click() could have unchecked already checked row (this case may never occur but it's better to explicitly set it as checked) --- frappe/public/js/frappe/list/list_view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index a1fe886484..b52b1db542 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1087,7 +1087,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { set_rows_as_checked() { $.each(this.$checks, (i, el) => { let docname = $(el).attr('data-name'); - this.$result.find(`.list-row-checkbox[data-name='${docname}']`).click(); + this.$result.find(`.list-row-checkbox[data-name='${docname}']`).prop('checked', true); }); } From de9452387be40d619bdb1079cbbf940442a615c6 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 15 Nov 2019 13:53:47 +0530 Subject: [PATCH 15/43] fix: Trigger on_row_checked after checking rows --- frappe/public/js/frappe/list/list_view.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index b52b1db542..b980ae7684 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1089,6 +1089,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { let docname = $(el).attr('data-name'); this.$result.find(`.list-row-checkbox[data-name='${docname}']`).prop('checked', true); }); + this.on_row_checked(); } on_row_checked() { From 5af3dd8dcbba043737aee460d40e300177b4b050 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 14 Nov 2019 20:11:21 +0530 Subject: [PATCH 16/43] fix: Show total row in print only if add total row is checked --- .../public/js/frappe/views/reports/query_report.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 4b72a6b7b5..560cb3d17b 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -975,12 +975,15 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { return this.data[index]; } }).filter(Boolean); - let totalRow = this.datatable.bodyRenderer.getTotalRow().reduce((row, cell) => { - row[cell.column.id] = cell.content; - return row; - }, {}); - rows.push(totalRow); + if (this.raw_data.add_total_row) { + let totalRow = this.datatable.bodyRenderer.getTotalRow().reduce((row, cell) => { + row[cell.column.id] = cell.content; + return row; + }, {}); + + rows.push(totalRow); + } return rows; } From 9cb1869c9a116f4a40c2b02cecf4924b55bc80b9 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 18 Nov 2019 19:00:33 +0530 Subject: [PATCH 17/43] fix: pass doc to frappe.format so doc currency is set for the row, not system default currency --- frappe/public/js/frappe/views/reports/report_view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 7f6e24595a..94c8e122c8 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -996,7 +996,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { content: d[cdt_field(col.field)], editable: Boolean(name && this.is_editable(col.docfield, d)), format: value => { - return frappe.format(value, col.docfield, { always_show_decimals: true }); + return frappe.format(value, col.docfield, { always_show_decimals: true }, d); } }; } From 499d0a94711ffc41b9050f7a4c1f2799f8bb1cc5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 18 Nov 2019 13:10:01 +0530 Subject: [PATCH 18/43] fix: spacing for modal --- frappe/public/scss/website.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/public/scss/website.scss b/frappe/public/scss/website.scss index bef504d70e..a297054ee2 100644 --- a/frappe/public/scss/website.scss +++ b/frappe/public/scss/website.scss @@ -101,6 +101,10 @@ h4.modal-title { font-size: 1em; } +h5.modal-title { + margin: 0px !important; +} + .col-xs-1 { @extend .col-1; } .col-xs-2 { @extend .col-2; } .col-xs-3 { @extend .col-3; } From bee23f07251e7ced80b2099bcd97eba0d25755b6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 18 Nov 2019 13:10:16 +0530 Subject: [PATCH 19/43] fix: allow setting message title from server --- frappe/website/js/website.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/website/js/website.js b/frappe/website/js/website.js index f9766bae1d..98959e114f 100644 --- a/frappe/website/js/website.js +++ b/frappe/website/js/website.js @@ -132,12 +132,12 @@ $.extend(frappe, { if (data._server_messages) { var server_messages = JSON.parse(data._server_messages || '[]'); - server_messages = $.map(server_messages, function(v) { + server_messages.map((msg) => { // temp fix for messages sent as dict try { - return JSON.parse(v).message; + return JSON.parse(msg); } catch (e) { - return v; + return msg; } }).join('
'); From 31bc8b3aa4112ae0ef10796a220ab0f485dcba03 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 15 Nov 2019 10:37:41 +0530 Subject: [PATCH 20/43] fix: Allow creation of new point log if old logs were reverted --- frappe/social/doctype/energy_point_log/energy_point_log.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.py b/frappe/social/doctype/energy_point_log/energy_point_log.py index 33a6717cb9..cd3d641d53 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/energy_point_log.py @@ -149,7 +149,8 @@ def check_if_log_exists(ref_doctype, ref_name, rule, user=None): filters = frappe._dict({ 'rule': rule, 'reference_doctype': ref_doctype, - 'reference_name': ref_name + 'reference_name': ref_name, + 'reverted': 0 }) if user: From e19b8dbff283379e6700b9543d4d326dc371d099 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 15 Nov 2019 10:50:40 +0530 Subject: [PATCH 21/43] test: Check allowance of new log over reverted log --- .../energy_point_log/test_energy_point_log.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/frappe/social/doctype/energy_point_log/test_energy_point_log.py b/frappe/social/doctype/energy_point_log/test_energy_point_log.py index a1d67789aa..9e4d0e6425 100644 --- a/frappe/social/doctype/energy_point_log/test_energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/test_energy_point_log.py @@ -249,6 +249,27 @@ class TestEnergyPointLog(unittest.TestCase): # point should not be awarded more than once for same doc (irrespective of user) self.assertEqual(second_user_points_after_closing_todo, second_user_points) + def test_allow_creation_of_new_log_if_the_previous_log_was_reverted(self): + frappe.set_user('test@example.com') + todo_point_rule = create_energy_point_rule_for_todo() + energy_point_of_user = get_points('test@example.com') + + created_todo = create_a_todo() + + created_todo.status = 'Closed' + created_todo.save() + points_after_closing_todo = get_points('test@example.com') + + log_name = frappe.db.exists('Energy Point Log', {'reference_name': created_todo.name}) + frappe.get_doc('Energy Point Log', log_name).revert('Just for test') + points_after_reverting_todo = get_points('test@example.com') + created_todo.save() + points_after_saving_todo_again = get_points('test@example.com') + + rule_points = todo_point_rule.points + self.assertEqual(points_after_closing_todo, energy_point_of_user + rule_points) + self.assertEqual(points_after_reverting_todo, points_after_closing_todo - rule_points) + self.assertEqual(points_after_saving_todo_again, points_after_reverting_todo + rule_points) def create_energy_point_rule_for_todo(multiplier_field=None, for_doc_event='Custom', max_points=None, for_assigned_users=0, field_to_check=None, apply_once=False, user_field='owner'): From d9dae005c36a38902ae8311749abf147ffa09ef2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 15 Nov 2019 10:50:52 +0530 Subject: [PATCH 22/43] refactor: Move revert functionality to controller --- .../energy_point_log/energy_point_log.js | 9 +-- .../energy_point_log/energy_point_log.py | 57 ++++++++++--------- .../energy_point_rule/energy_point_rule.py | 4 +- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.js b/frappe/social/doctype/energy_point_log/energy_point_log.js index 3090f3659d..9822998a30 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.js +++ b/frappe/social/doctype/energy_point_log/energy_point_log.js @@ -21,14 +21,15 @@ frappe.ui.form.on('Energy Point Log', { reqd: 1 }], primary_action: (values) => { - return frappe.xcall('frappe.social.doctype.energy_point_log.energy_point_log.revert', { - 'name': frm.doc.name, + return frm.call('revert', { 'reason': values.reason - }).then(revert_log => { + }).then(res => { + let revert_log = res.message; revert_dialog.hide(); revert_dialog.clear(); frappe.model.docinfo[frm.doc.reference_doctype][frm.doc.reference_name].energy_point_logs.unshift(revert_log); - }).catch(() => {}); + frm.refresh(); + }); }, primary_action_label: __('Submit') }); diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.py b/frappe/social/doctype/energy_point_log/energy_point_log.py index cd3d641d53..cfba5884cf 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/energy_point_log.py @@ -44,6 +44,35 @@ class EnergyPointLog(Document): enqueue_create_notification(self.user, notification_doc) + def on_trash(self): + if self.type == 'Revert': + reference_log = frappe.get_doc('Energy Point Log', self.revert_of) + reference_log.reverted = 0 + reference_log.save() + + def revert(self, reason): + frappe.only_for('System Manager') + if self.type != 'Auto': + frappe.throw(_('This document cannot be reverted')) + + if self.reverted: return + + self.reverted = 1 + self.save(ignore_permissions=True) + + revert_log = frappe.get_doc({ + 'doctype': 'Energy Point Log', + 'points': -(self.points), + 'type': 'Revert', + 'user': self.user, + 'reason': reason, + 'reference_doctype': self.reference_doctype, + 'reference_name': self.reference_name, + 'revert_of': self.name + }).insert(ignore_permissions=True) + + return revert_log + def get_notification_message(doc): owner_name = get_fullname(doc.owner) points = doc.points @@ -258,32 +287,6 @@ def get_reviews(doctype, docname): 'type': ['in', ('Appreciation', 'Criticism')], }, fields=['points', 'owner', 'type', 'user', 'reason', 'creation']) -@frappe.whitelist() -def revert(name, reason): - frappe.only_for('System Manager') - doc_to_revert = frappe.get_doc('Energy Point Log', name) - - if doc_to_revert.type != 'Auto': - frappe.throw(_('This document cannot be reverted')) - - if doc_to_revert.reverted: return - - doc_to_revert.reverted = 1 - doc_to_revert.save(ignore_permissions=True) - - revert_log = frappe.get_doc({ - 'doctype': 'Energy Point Log', - 'points': -(doc_to_revert.points), - 'type': 'Revert', - 'user': doc_to_revert.user, - 'reason': reason, - 'reference_doctype': doc_to_revert.reference_doctype, - 'reference_name': doc_to_revert.reference_name, - 'revert_of': doc_to_revert.name - }).insert(ignore_permissions=True) - - return revert_log - def send_weekly_summary(): send_summary('Weekly') @@ -326,5 +329,3 @@ def get_footer_message(timespan): return _("Stats based on last month's performance (from {0} to {1})") else: return _("Stats based on last week's performance (from {0} to {1})") - - 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 38995887f0..0d66691a1b 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -8,7 +8,7 @@ from frappe import _ import frappe.cache_manager from frappe.model.document import Document from frappe.social.doctype.energy_point_settings.energy_point_settings import is_energy_point_enabled -from frappe.social.doctype.energy_point_log.energy_point_log import create_energy_points_log, revert +from frappe.social.doctype.energy_point_log.energy_point_log import create_energy_points_log class EnergyPointRule(Document): def on_update(self): @@ -106,7 +106,7 @@ def revert_points_for_cancelled_doc(doc): 'type': 'Auto' }) for log in energy_point_logs: - revert(log.name, _('Reference document has been cancelled')) + frappe.get_doc('Energy Point Log', log.name).revert(_('Reference document has been cancelled')) def get_energy_point_doctypes(): From afb0a501892a4dab9123253c77b063ab2260ede3 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 15 Nov 2019 11:00:05 +0530 Subject: [PATCH 23/43] style: Fix codacy --- frappe/social/doctype/energy_point_log/energy_point_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.py b/frappe/social/doctype/energy_point_log/energy_point_log.py index cfba5884cf..eb8bccf96a 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/energy_point_log.py @@ -55,7 +55,7 @@ class EnergyPointLog(Document): if self.type != 'Auto': frappe.throw(_('This document cannot be reverted')) - if self.reverted: return + if self.get('reverted'): return self.reverted = 1 self.save(ignore_permissions=True) From 95c116e71a43e2d69430ed7ec9df1cdb9af4b749 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 15 Nov 2019 11:15:53 +0530 Subject: [PATCH 24/43] style: Fix deepsource --- frappe/social/doctype/energy_point_log/energy_point_log.py | 3 ++- .../social/doctype/energy_point_rule/energy_point_rule.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.py b/frappe/social/doctype/energy_point_log/energy_point_log.py index eb8bccf96a..8353c3aa5f 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/energy_point_log.py @@ -55,7 +55,8 @@ class EnergyPointLog(Document): if self.type != 'Auto': frappe.throw(_('This document cannot be reverted')) - if self.get('reverted'): return + if self.get('reverted'): + return self.reverted = 1 self.save(ignore_permissions=True) 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 0d66691a1b..5986e90bfb 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -8,7 +8,8 @@ from frappe import _ import frappe.cache_manager from frappe.model.document import Document from frappe.social.doctype.energy_point_settings.energy_point_settings import is_energy_point_enabled -from frappe.social.doctype.energy_point_log.energy_point_log import create_energy_points_log +from frappe.social.doctype.energy_point_log.energy_point_log import \ + create_energy_points_log class EnergyPointRule(Document): def on_update(self): @@ -106,7 +107,8 @@ def revert_points_for_cancelled_doc(doc): 'type': 'Auto' }) for log in energy_point_logs: - frappe.get_doc('Energy Point Log', log.name).revert(_('Reference document has been cancelled')) + reference_log = frappe.get_doc('Energy Point Log', log.name) + reference_log.revert(_('Reference document has been cancelled')) def get_energy_point_doctypes(): From 7b55f1657b840d11204c4c76f06e681b2c0eb6a7 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 6 Nov 2019 15:10:48 +0530 Subject: [PATCH 25/43] fix: Barcode Control - Fix render caching in forms - Handle raw and svg value --- .../public/js/frappe/form/controls/barcode.js | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/barcode.js b/frappe/public/js/frappe/form/controls/barcode.js index 1cd1411b49..8245962d7e 100644 --- a/frappe/public/js/frappe/form/controls/barcode.js +++ b/frappe/public/js/frappe/form/controls/barcode.js @@ -1,18 +1,27 @@ -import JsBarcode from "jsbarcode"; +import JsBarcode from 'jsbarcode'; frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ make_wrapper() { // Create the elements for barcode area this._super(); + this.default_svg = ''; let $input_wrapper = this.$wrapper.find('.control-input-wrapper'); - this.barcode_area = $(`
`); + this.barcode_area = $( + `
${this.default_svg}
` + ); this.barcode_area.appendTo($input_wrapper); }, parse(value) { // Parse raw value - return value ? this.get_barcode_html(value) : ""; + if (value) { + if (value.startsWith(' Date: Mon, 18 Nov 2019 16:21:01 +0530 Subject: [PATCH 26/43] test: UI test for Barcode Control --- cypress/integration/control_barcode.js | 55 +++++++++++++++++++ .../public/js/frappe/form/controls/barcode.js | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 cypress/integration/control_barcode.js diff --git a/cypress/integration/control_barcode.js b/cypress/integration/control_barcode.js new file mode 100644 index 0000000000..8d720f6b6c --- /dev/null +++ b/cypress/integration/control_barcode.js @@ -0,0 +1,55 @@ +context('Control Barcide', () => { + beforeEach(() => { + cy.login(); + cy.visit('/desk'); + }); + + function get_dialog_with_barcode() { + return cy.dialog({ + title: 'Barcode', + fields: [ + { + label: 'Barcode', + fieldname: 'barcode', + fieldtype: 'Barcode' + } + ] + }); + } + + it('should generate barcode on setting a value', () => { + get_dialog_with_barcode().as('dialog'); + + cy.get('.frappe-control[data-fieldname=barcode] input') + .focus() + .type('123456789') + .blur(); + cy.get('.frappe-control[data-fieldname=barcode] svg[data-barcode-value="123456789"]') + .should('exist'); + + cy.get('@dialog').then(dialog => { + let value = dialog.get_value('barcode'); + expect(value).to.contain(' { + get_dialog_with_barcode().as('dialog'); + + cy.get('.frappe-control[data-fieldname=barcode] input') + .focus() + .type('123456789') + .blur(); + cy.get('.frappe-control[data-fieldname=barcode] input') + .clear() + .blur(); + cy.get('.frappe-control[data-fieldname=barcode] svg[data-barcode-value="123456789"]') + .should('not.exist'); + + cy.get('@dialog').then(dialog => { + let value = dialog.get_value('barcode'); + expect(value).to.equal(''); + }); + }); +}); diff --git a/frappe/public/js/frappe/form/controls/barcode.js b/frappe/public/js/frappe/form/controls/barcode.js index 8245962d7e..08bb7b763f 100644 --- a/frappe/public/js/frappe/form/controls/barcode.js +++ b/frappe/public/js/frappe/form/controls/barcode.js @@ -29,7 +29,7 @@ frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ let svg = value; const barcode_value = $(svg).attr('data-barcode-value'); - if (!barcode_value) { + if (!barcode_value && this.doc) { svg = this.get_barcode_html(value); this.doc[this.df.fieldname] = svg; } From 30e3e1a5b8690181f471f024c8829b0dfa04a699 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 19 Nov 2019 11:37:43 +0530 Subject: [PATCH 27/43] fix: typo Co-Authored-By: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- cypress/integration/control_barcode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/control_barcode.js b/cypress/integration/control_barcode.js index 8d720f6b6c..ac2a687bae 100644 --- a/cypress/integration/control_barcode.js +++ b/cypress/integration/control_barcode.js @@ -1,4 +1,4 @@ -context('Control Barcide', () => { +context('Control Barcode', () => { beforeEach(() => { cy.login(); cy.visit('/desk'); From 22aa7cef78c15e43885f310d74f2af3ed6ab3f50 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 20 Nov 2019 12:53:52 +0530 Subject: [PATCH 28/43] fix(web-forms): view addresses only by session user --- frappe/contacts/doctype/address/address.py | 28 ++++------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index 6795011745..21ed88addb 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -145,30 +145,10 @@ def get_list_context(context=None): def get_address_list(doctype, txt, filters, limit_start, limit_page_length = 20, order_by = None): from frappe.www.list import get_list user = frappe.session.user - ignore_permissions = False - if is_website_user(): - if not filters: filters = [] - add_name = [] - contact = frappe.db.sql(""" - select - address.name - from - `tabDynamic Link` as link - join - `tabAddress` as address on link.parent = address.name - where - link.parenttype = 'Address' and - link_name in( - select - link.link_name from `tabContact` as contact - join - `tabDynamic Link` as link on contact.name = link.parent - where - contact.user = %s)""",(user)) - for c in contact: - add_name.append(c[0]) - filters.append(("Address", "name", "in", add_name)) - ignore_permissions = True + ignore_permissions = True + + if not filters: filters = [] + filters.append(("Address", "owner", "=", user)) return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=ignore_permissions) From cbde4643199bf8c642ec97fba51ac06d41341cd3 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 21 Nov 2019 17:01:33 +0530 Subject: [PATCH 29/43] fix: Add Notification Settings --- frappe/config/settings.py | 9 ++++++++- .../notification_settings/notification_settings.js | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 frappe/desk/doctype/notification_settings/notification_settings.js diff --git a/frappe/config/settings.py b/frappe/config/settings.py index 2422f2fae2..a0a7dcd65f 100644 --- a/frappe/config/settings.py +++ b/frappe/config/settings.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals +import frappe from frappe import _ from frappe.desk.moduleview import add_setup_section @@ -88,7 +89,7 @@ def get_data(): ] }, { - "label": _("Email"), + "label": _("Email / Notifications"), "icon": "fa fa-envelope", "items": [ { @@ -120,6 +121,12 @@ def get_data(): "type": "doctype", "name": "Newsletter", "description": _("Create and manage newsletter") + }, + { + "type": "doctype", + "route": "Form/Notification Settings/{}".format(frappe.session.user), + "name": "Notification Settings", + "description": _("Configure notifications for mentions, assignments, energy points and more.") } ] }, diff --git a/frappe/desk/doctype/notification_settings/notification_settings.js b/frappe/desk/doctype/notification_settings/notification_settings.js new file mode 100644 index 0000000000..d4e3b08def --- /dev/null +++ b/frappe/desk/doctype/notification_settings/notification_settings.js @@ -0,0 +1,12 @@ +// Copyright (c) 2019, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Notification Settings', { + onload: () => { + frappe.breadcrumbs.add({ + label: __('Settings'), + route: '#modules/Settings', + type: 'Custom' + }); + } +}); From 3505e680819632ac7cbf6619694860f6a08a714a Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 19 Nov 2019 14:38:24 +0530 Subject: [PATCH 30/43] fix: standard filters with default value are saved when changed --- frappe/public/js/frappe/list/base_list.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index 2c5e1df1df..d713ae6c3e 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -625,17 +625,13 @@ class FilterArea { options = options.join("\n"); } } - let default_value = (fieldtype === 'Link') ? frappe.defaults.get_user_default(options) : null; - if (['__default', '__global'].includes(default_value)) { - default_value = null; - } + return { fieldtype: fieldtype, label: __(df.label), options: options, fieldname: df.fieldname, condition: condition, - default: default_value, onchange: () => this.refresh_list_view(), ignore_link_validation: fieldtype === 'Dynamic Link' }; @@ -650,6 +646,10 @@ class FilterArea { for (let key in fields_dict) { let field = fields_dict[key]; let value = field.get_value(); + let default_value = (field.df.fieldtype === 'Link') + ? frappe.defaults.get_user_default(field.df.options) + : null; + if (value) { if (field.df.condition === 'like' && !value.includes('%')) { value = '%' + value + '%'; @@ -660,6 +660,13 @@ class FilterArea { field.df.condition || '=', value ]); + } else if (default_value) { + filters.push([ + this.list_view.doctype, + field.df.fieldname, + field.df.condition, + default_value + ]); } } From fdf37115aaf6e750c0cb9b1048344959e1aacd95 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 21 Nov 2019 00:33:32 +0530 Subject: [PATCH 31/43] fix: check for __default, __global default values --- frappe/public/js/frappe/list/base_list.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index d713ae6c3e..c0eaf5845c 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -649,6 +649,9 @@ class FilterArea { let default_value = (field.df.fieldtype === 'Link') ? frappe.defaults.get_user_default(field.df.options) : null; + if (['__default', '__global'].includes(default_value)) { + default_value = null; + } if (value) { if (field.df.condition === 'like' && !value.includes('%')) { From 3d15be73fab267375cf6cf46bb99d41e24f6b922 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 21 Nov 2019 08:49:30 +0530 Subject: [PATCH 32/43] style: Remove trailing tabs --- frappe/public/js/frappe/list/base_list.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index c0eaf5845c..0ea9a801fb 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -646,11 +646,11 @@ class FilterArea { for (let key in fields_dict) { let field = fields_dict[key]; let value = field.get_value(); - let default_value = (field.df.fieldtype === 'Link') - ? frappe.defaults.get_user_default(field.df.options) - : null; - if (['__default', '__global'].includes(default_value)) { - default_value = null; + let default_value = (field.df.fieldtype === 'Link') ? + frappe.defaults.get_user_default(field.df.options) : null; + + if (['__default', '__global'].includes(default_value)) { + default_value = null; } if (value) { From 7e6f5ea07ebfc7bd78b1d6ac7f7743292cd8772e Mon Sep 17 00:00:00 2001 From: Jack Date: Thu, 21 Nov 2019 10:59:06 +0000 Subject: [PATCH 33/43] Misspelt, when selecting ALL emails it was being set to UNSEEN. This rectifies the issue. --- frappe/email/doctype/email_account/email_account.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.js b/frappe/email/doctype/email_account/email_account.js index 7a175e7192..71f9cccb0d 100644 --- a/frappe/email/doctype/email_account/email_account.js +++ b/frappe/email/doctype/email_account/email_account.js @@ -184,7 +184,7 @@ frappe.ui.form.on("Email Account", { read as well as unread message from server. This may also cause the duplication\ of Communication (emails)."); frappe.confirm(msg, null, function() { - frm.set_value("email_sync_option", "UNSEEN"); + frm.set_value("email_sync_option", "ALL"); }); } } From 2759689ea972645c15de658f99fb155746fcbe21 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 22 Nov 2019 11:34:20 +0530 Subject: [PATCH 34/43] fix: reload notification subscribed document (#8868) --- frappe/patches/v12_0/create_notification_settings_for_user.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/patches/v12_0/create_notification_settings_for_user.py b/frappe/patches/v12_0/create_notification_settings_for_user.py index 170931bdf3..63eeccc07a 100644 --- a/frappe/patches/v12_0/create_notification_settings_for_user.py +++ b/frappe/patches/v12_0/create_notification_settings_for_user.py @@ -4,6 +4,7 @@ from frappe.desk.doctype.notification_settings.notification_settings import crea def execute(): frappe.reload_doc('desk', 'doctype', 'notification_settings') + frappe.reload_doc('desk', 'doctype', 'notification_subscribed_document') users = frappe.db.get_all('User', fields=['name']) for user in users: From 3a73cf6e7d2ea8997a839b36c0c6d20ed110c741 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 22 Nov 2019 15:13:19 +0530 Subject: [PATCH 35/43] feat: Handle server and client side primary action in msgprint (#8870) * feat: Handle server and client side primary action in msgprint - Added provision to pass primary action from server side msgprint - msgprint on client side handles server side and client side methods as primary actions * chore: Code cleanup * fix: Codacy * fix: patch --- frappe/__init__.py | 6 +++++- frappe/public/js/frappe/ui/messages.js | 30 ++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 77207e017f..c937cc8548 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -290,7 +290,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): +def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, alert=False, primary_action=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. @@ -299,6 +299,7 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, :param title: [optional] Message title. :param raise_exception: [optional] Raise given exception and show message. :param as_table: [optional] If `msg` is a list of lists, render as HTML table. + :param primary_action: [optional] Bind a primary server/client side action. """ from frappe.utils import encode @@ -338,6 +339,9 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, if alert: out.alert = 1 + if primary_action: + out.primary_action = primary_action + message_log.append(json.dumps(out)) if raise_exception and hasattr(raise_exception, '__name__'): diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index f804648834..26bee50f18 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -122,8 +122,34 @@ frappe.msgprint = function(msg, title) { // setup and bind an action to the primary button if (data.primary_action) { - frappe.msg_dialog.set_primary_action(__(data.primary_action.label || "Done"), - data.primary_action.action); + if (data.primary_action.server_action && typeof data.primary_action.server_action === 'string') { + data.primary_action.action = () => { + frappe.call({ + method: data.primary_action.server_action, + args: { + args: data.primary_action.args + } + }); + } + } + + if (data.primary_action.client_action && typeof data.primary_action.client_action === 'string') { + let parts = data.primary_action.client_action.split('.'); + let obj = window; + for (let part of parts) { + obj = obj[part]; + } + data.primary_action.action = () => { + if (typeof obj === 'function') { + obj(data.primary_action.args); + } + } + } + + frappe.msg_dialog.set_primary_action( + __(data.primary_action.label || "Done"), + data.primary_action.action + ); } // class "msgprint" is used in tests From 95577018151c949ff616a53c63a281f540889d56 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 25 Nov 2019 13:31:06 +0530 Subject: [PATCH 36/43] fix: Actions in msgprint (#8877) --- frappe/public/js/frappe/ui/messages.js | 69 ++++++++++++++------------ 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index 26bee50f18..08711a8237 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -120,38 +120,6 @@ frappe.msgprint = function(msg, title) { } }); - // setup and bind an action to the primary button - if (data.primary_action) { - if (data.primary_action.server_action && typeof data.primary_action.server_action === 'string') { - data.primary_action.action = () => { - frappe.call({ - method: data.primary_action.server_action, - args: { - args: data.primary_action.args - } - }); - } - } - - if (data.primary_action.client_action && typeof data.primary_action.client_action === 'string') { - let parts = data.primary_action.client_action.split('.'); - let obj = window; - for (let part of parts) { - obj = obj[part]; - } - data.primary_action.action = () => { - if (typeof obj === 'function') { - obj(data.primary_action.args); - } - } - } - - frappe.msg_dialog.set_primary_action( - __(data.primary_action.label || "Done"), - data.primary_action.action - ); - } - // class "msgprint" is used in tests frappe.msg_dialog.msg_area = $('
') .appendTo(frappe.msg_dialog.body); @@ -163,6 +131,43 @@ frappe.msgprint = function(msg, title) { frappe.msg_dialog.indicator = frappe.msg_dialog.header.find('.indicator'); } + // setup and bind an action to the primary button + if (data.primary_action) { + if (data.primary_action.server_action && typeof data.primary_action.server_action === 'string') { + data.primary_action.action = () => { + frappe.call({ + method: data.primary_action.server_action, + args: { + args: data.primary_action.args + } + }); + } + } + + if (data.primary_action.client_action && typeof data.primary_action.client_action === 'string') { + let parts = data.primary_action.client_action.split('.'); + let obj = window; + for (let part of parts) { + obj = obj[part]; + } + data.primary_action.action = () => { + if (typeof obj === 'function') { + obj(data.primary_action.args); + } + } + } + + frappe.msg_dialog.set_primary_action( + __(data.primary_action.label || "Done"), + data.primary_action.action + ); + } else { + if (frappe.msg_dialog.has_primary_action) { + frappe.msg_dialog.get_primary_btn().addClass('hide'); + frappe.msg_dialog.has_primary_action = false; + } + } + if(data.message==null) { data.message = ''; } From fd39f2ac708d11dcded08ba3e4ede9b4a7ba2ef2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 25 Nov 2019 15:18:22 +0550 Subject: [PATCH 37/43] bumped to version 12.0.19 --- frappe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index c937cc8548..74a60794d8 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ if sys.version[0] == '2': reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '12.0.18' +__version__ = '12.0.19' __title__ = "Frappe Framework" local = Local() From 121656d57921ff7e3dbcc8fe49888a272560ad10 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Tue, 26 Nov 2019 12:07:45 +0530 Subject: [PATCH 38/43] fix: Module view page issue (#8879) - Filter link based on the name of the link config, because label can be different if user switches the language. - Return the value instead of label while updating links for module - Show Customize option in DeskModuleBox even if there are no links selected by the user. --- frappe/desk/moduleview.py | 13 ++++++---- .../frappe/views/components/DeskModuleBox.vue | 2 +- .../frappe/views/components/DeskSection.vue | 24 +++++++++++++------ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index c5e5ea7c2b..0bad171b04 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -234,8 +234,11 @@ def get_config(app, module): for item in section["items"]: if item["type"]=="report" and item["name"] in disabled_reports: continue + # some module links might not have name + if not item.get("name"): + item["name"] = item.get("label") if not item.get("label"): - item["label"] = _(item["name"]) + item["label"] = _(item.get("name")) items.append(item) section['items'] = items @@ -297,7 +300,7 @@ def get_onboard_items(app, module): @frappe.whitelist() def get_links_for_module(app, module): - return [l.get('label') for l in get_links(app, module)] + return [{'value': l.get('name'), 'label': l.get('label')} for l in get_links(app, module)] def get_links(app, module): try: @@ -330,13 +333,13 @@ def get_desktop_settings(): def apply_user_saved_links(module): module = frappe._dict(module) all_links = get_links(module.app, module.module_name) - module_links_by_label = {} + module_links_by_name = {} for link in all_links: - module_links_by_label[link['label']] = link + module_links_by_name[link['name']] = link if module.module_name in user_saved_links_by_module: user_links = frappe.parse_json(user_saved_links_by_module[module.module_name]) - module.links = [module_links_by_label[l] for l in user_links if l in module_links_by_label] + module.links = [module_links_by_name[l] for l in user_links if l in module_links_by_name] return module diff --git a/frappe/public/js/frappe/views/components/DeskModuleBox.vue b/frappe/public/js/frappe/views/components/DeskModuleBox.vue index 355a447475..0d809508ee 100644 --- a/frappe/public/js/frappe/views/components/DeskModuleBox.vue +++ b/frappe/public/js/frappe/views/components/DeskModuleBox.vue @@ -63,7 +63,7 @@ export default { } }, dropdown_links() { - return this.links.length > 0 ? this.links + return this.type === 'module' ? this.links .filter(link => !link.hidden) .concat([ { label: __('Customize'), action: () => this.$emit('customize'), class: 'border-top' } diff --git a/frappe/public/js/frappe/views/components/DeskSection.vue b/frappe/public/js/frappe/views/components/DeskSection.vue index 9b24f75294..83670a3e82 100644 --- a/frappe/public/js/frappe/views/components/DeskSection.vue +++ b/frappe/public/js/frappe/views/components/DeskSection.vue @@ -26,7 +26,8 @@ export default { }, data() { return { - dragging: false + dragging: false, + fetched_module_links: {} } }, mounted() { @@ -53,6 +54,7 @@ export default { }) }, show_module_card_customize_dialog(module) { + const me = this; const d = new frappe.ui.Dialog({ title: __('Customize Shortcuts'), fields: [ @@ -60,11 +62,19 @@ export default { label: __('Shortcuts'), fieldname: 'links', fieldtype: 'MultiSelectPills', - get_data() { - return frappe.call('frappe.desk.moduleview.get_links_for_module', { - app: module.app, - module: module.module_name, - }).then(r => r.message); + get_data: () => { + const module_links = me.fetched_module_links[module.module_name]; + if (!module_links) { + return frappe.xcall('frappe.desk.moduleview.get_links_for_module', { + app: module.app, + module: module.module_name, + }).then(links => { + me.fetched_module_links[module.module_name] = links; + return links; + }); + } else { + return module_links; + } }, default: module.links.filter(l => !l.hidden).map(l => l.name) } @@ -73,7 +83,7 @@ export default { primary_action: ({ links }) => { frappe.call('frappe.desk.moduleview.update_links_for_module', { module_name: module.module_name, - links + links: links || [] }).then(r => { this.$emit('update-desktop-settings', r.message); }); From 54f2da5a528af0f0f2f38d14752b0225a4221636 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Mon, 25 Nov 2019 19:29:14 +0530 Subject: [PATCH 39/43] fix(security): Make all Prepared Report file attachments private --- frappe/core/doctype/prepared_report/prepared_report.py | 3 ++- frappe/patches.txt | 1 + .../make_all_prepared_report_attachments_private.py | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 frappe/patches/v11_0/make_all_prepared_report_attachments_private.py diff --git a/frappe/core/doctype/prepared_report/prepared_report.py b/frappe/core/doctype/prepared_report/prepared_report.py index 071bb4afc0..c61e374744 100644 --- a/frappe/core/doctype/prepared_report/prepared_report.py +++ b/frappe/core/doctype/prepared_report/prepared_report.py @@ -85,7 +85,8 @@ def create_json_gz_file(data, dt, dn): "file_name": json_filename, "attached_to_doctype": dt, "attached_to_name": dn, - "content": compressed_content + "content": compressed_content, + "is_private": 1 }) _file.save(ignore_permissions=True) diff --git a/frappe/patches.txt b/frappe/patches.txt index 9473323059..1aa1d34e97 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -257,3 +257,4 @@ frappe.patches.v12_0.setup_tags frappe.patches.v12_0.update_auto_repeat_status_and_not_submittable frappe.patches.v12_0.copy_to_parent_for_tags frappe.patches.v12_0.create_notification_settings_for_user +frappe.patches.v11_0.make_all_prepared_report_attachments_private diff --git a/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py b/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py new file mode 100644 index 0000000000..2338d6f2e7 --- /dev/null +++ b/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py @@ -0,0 +1,10 @@ +from __future__ import unicode_literals +import frappe + + +def execute(): + files = frappe.get_all("File", filters={"attached_to_doctype": "Prepared Report", "is_private": 0}) + for file_name in files: + file_doc = frappe.get_doc("File", file_name) + file_doc.is_private = 1 + file_doc.save() From 2cb9f22e53c61ee30e76d518b5d435c74959fb92 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Tue, 26 Nov 2019 14:05:07 +0530 Subject: [PATCH 40/43] Revert "fix(List): standard filters with default value are saved when changed" --- frappe/public/js/frappe/list/base_list.js | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index 0ea9a801fb..2c5e1df1df 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -625,13 +625,17 @@ class FilterArea { options = options.join("\n"); } } - + let default_value = (fieldtype === 'Link') ? frappe.defaults.get_user_default(options) : null; + if (['__default', '__global'].includes(default_value)) { + default_value = null; + } return { fieldtype: fieldtype, label: __(df.label), options: options, fieldname: df.fieldname, condition: condition, + default: default_value, onchange: () => this.refresh_list_view(), ignore_link_validation: fieldtype === 'Dynamic Link' }; @@ -646,13 +650,6 @@ class FilterArea { for (let key in fields_dict) { let field = fields_dict[key]; let value = field.get_value(); - let default_value = (field.df.fieldtype === 'Link') ? - frappe.defaults.get_user_default(field.df.options) : null; - - if (['__default', '__global'].includes(default_value)) { - default_value = null; - } - if (value) { if (field.df.condition === 'like' && !value.includes('%')) { value = '%' + value + '%'; @@ -663,13 +660,6 @@ class FilterArea { field.df.condition || '=', value ]); - } else if (default_value) { - filters.push([ - this.list_view.doctype, - field.df.fieldname, - field.df.condition, - default_value - ]); } } From 83124d8eee307f16a2dfa231d312f0dd4862a852 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 25 Nov 2019 14:49:05 +0530 Subject: [PATCH 41/43] fix: Suppress unwanted quill warnings --- frappe/public/js/frappe/form/controls/comment.js | 2 +- .../js/frappe/form/controls/quill-mention/blots/mention.js | 2 +- .../js/frappe/form/controls/quill-mention/quill.mention.js | 2 +- frappe/public/js/frappe/form/controls/text_editor.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/comment.js b/frappe/public/js/frappe/form/controls/comment.js index eba82fd7b2..a64df56bca 100644 --- a/frappe/public/js/frappe/form/controls/comment.js +++ b/frappe/public/js/frappe/form/controls/comment.js @@ -1,7 +1,7 @@ import Quill from 'quill'; import Mention from './quill-mention/quill.mention'; -Quill.register('modules/mention', Mention); +Quill.register('modules/mention', Mention, true); frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ make_wrapper() { diff --git a/frappe/public/js/frappe/form/controls/quill-mention/blots/mention.js b/frappe/public/js/frappe/form/controls/quill-mention/blots/mention.js index 26485adcc0..1c5787f854 100644 --- a/frappe/public/js/frappe/form/controls/quill-mention/blots/mention.js +++ b/frappe/public/js/frappe/form/controls/quill-mention/blots/mention.js @@ -35,4 +35,4 @@ MentionBlot.blotName = 'mention'; MentionBlot.tagName = 'span'; MentionBlot.className = 'mention'; -Quill.register(MentionBlot); +Quill.register(MentionBlot, true); diff --git a/frappe/public/js/frappe/form/controls/quill-mention/quill.mention.js b/frappe/public/js/frappe/form/controls/quill-mention/quill.mention.js index 0b50ffd758..80ee5a6c6d 100644 --- a/frappe/public/js/frappe/form/controls/quill-mention/quill.mention.js +++ b/frappe/public/js/frappe/form/controls/quill-mention/quill.mention.js @@ -361,6 +361,6 @@ class Mention { } } -Quill.register('modules/mention', Mention); +Quill.register('modules/mention', Mention, true); export default Mention; diff --git a/frappe/public/js/frappe/form/controls/text_editor.js b/frappe/public/js/frappe/form/controls/text_editor.js index 1b9078ae03..b35c92c1ae 100644 --- a/frappe/public/js/frappe/form/controls/text_editor.js +++ b/frappe/public/js/frappe/form/controls/text_editor.js @@ -36,7 +36,7 @@ class MyLink extends Link { } } -Quill.register(MyLink); +Quill.register(MyLink, true); // image uploader const Uploader = Quill.import('modules/uploader'); From 130b0f6cfd9b79781f59a37fe7cb777e05fe4f4d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 25 Nov 2019 09:09:08 +0530 Subject: [PATCH 42/43] fix: Escape HTML for the value of field with fieldtype HTML Editor --- frappe/public/js/frappe/list/list_view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index b980ae7684..9fd7aa3f36 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -577,7 +577,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { data-filter="${fieldname},=,${value}"> ${_value} `; - } else if (['Text Editor', 'Text', 'Small Text'].includes(df.fieldtype)) { + } else if (['Text Editor', 'Text', 'Small Text', 'HTML Editor'].includes(df.fieldtype)) { html = ` ${_value} `; @@ -589,7 +589,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { } return ` + title="${__(label)}: ${escape(_value)}"> ${html} `; }; From 747fab000396414ee0ed1523b8e1a587bde2a87d Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 26 Nov 2019 15:43:01 +0550 Subject: [PATCH 43/43] bumped to version 12.0.20 --- frappe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 74a60794d8..18ec5c0ee7 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ if sys.version[0] == '2': reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '12.0.19' +__version__ = '12.0.20' __title__ = "Frappe Framework" local = Local()