From 4844fbb92c6ce35edca580def989320715a01007 Mon Sep 17 00:00:00 2001 From: ci2014 Date: Fri, 14 Sep 2018 00:53:11 +0200 Subject: [PATCH 01/19] Fix recipients by document field When having multiple documents in the loop, email_by_document_field would be overridden by the mail address(es). In my case every trigger would only send one email, because for the doc following on the first one, the email_by_document_field would contain mail addresses instead of the field name. Prefixing with tmp_ solves the problem, because we only need the key in that lines. --- frappe/email/doctype/email_alert/email_alert.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/email/doctype/email_alert/email_alert.py b/frappe/email/doctype/email_alert/email_alert.py index 1da959956f..1bf867bbce 100755 --- a/frappe/email/doctype/email_alert/email_alert.py +++ b/frappe/email/doctype/email_alert/email_alert.py @@ -135,8 +135,8 @@ def get_context(context): continue if recipient.email_by_document_field: if validate_email_add(doc.get(recipient.email_by_document_field)): - recipient.email_by_document_field = doc.get(recipient.email_by_document_field).replace(",", "\n") - recipients = recipients + recipient.email_by_document_field.split("\n") + recipient.tmp_email_by_document_field = doc.get(recipient.email_by_document_field).replace(",", "\n") + recipients = recipients + recipient.tmp_email_by_document_field.split("\n") # else: # print "invalid email" From 8c302e956dd8b0ddbd7c61456ac75c0826fbb395 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 24 Sep 2018 09:30:05 +0530 Subject: [PATCH 02/19] fix(permissions.py) --- frappe/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/permissions.py b/frappe/permissions.py index 526ed4ae03..0878777c70 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -161,7 +161,7 @@ def get_role_permissions(doctype_meta, user=None, verbose=False): def has_permission_without_if_owner_enabled(ptype): return any(p.get(ptype, 0) and not p.get('if_owner', 0) for p in applicable_permissions) - applicable_permissions = list(filter(is_perm_applicable, doctype_meta.permissions)) + applicable_permissions = list(filter(is_perm_applicable, getattr(doctype_meta, 'permissions', []))) has_if_owner_enabled = any(p.get('if_owner', 0) for p in applicable_permissions) for ptype in rights: From 50915f317762d0eb8b8974c57a484a935fba28b0 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 24 Sep 2018 11:30:32 +0530 Subject: [PATCH 03/19] fix: Handle empty json in Report (#6127) --- frappe/core/doctype/report/report.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index d11d7f0a51..a7b1c4d4dc 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -73,6 +73,9 @@ class Report(Document): return True def update_report_json(self): + if not self.json: + self.json = '{}' + if self.json: data = json.loads(self.json) data["add_total_row"] = self.add_total_row @@ -121,7 +124,15 @@ class Report(Document): else: # standard report params = json.loads(self.json) - columns = params.get('columns') + + if params.get('columns'): + columns = params.get('columns') + else: + columns = [['name', self.ref_doctype]] + for df in frappe.get_meta(self.ref_doctype).fields: + if df.in_list_view: + columns.append([df.fieldname, self.ref_doctype]) + _filters = params.get('filters') or [] if filters: @@ -135,7 +146,11 @@ class Report(Document): # sort by is saved as DocType.fieldname, covert it to sql return '`tab{0}`.`{1}`'.format(*parts) - order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order') + if params.get('sort_by'): + order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order') + else: + order_by = _format(self.ref_doctype, 'modified') + ' desc' + if params.get('sort_by_next'): order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next') From a123fb45f479555b595318f261dc076508ae0225 Mon Sep 17 00:00:00 2001 From: Prateeksha Singh Date: Mon, 24 Sep 2018 12:32:47 +0530 Subject: [PATCH 04/19] [depends-on] can be a function with passed doc or a Boolean (#6117) - the function will receive the doc object - 'eval' was well intentioned to be set by database values - but when used programatically, should be better --- frappe/public/js/frappe/form/layout.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/layout.js b/frappe/public/js/frappe/form/layout.js index da4a00fd6d..37e75489a4 100644 --- a/frappe/public/js/frappe/form/layout.js +++ b/frappe/public/js/frappe/form/layout.js @@ -495,7 +495,13 @@ frappe.ui.form.Layout = Class.extend({ var parent = this.frm ? this.frm.doc : null; - if(expression.substr(0,5)=='eval:') { + if(typeof(expression) === 'boolean') { + out = expression; + + } else if(typeof(expression) === 'function') { + out = expression(doc); + + } else if(expression.substr(0,5)=='eval:') { try { out = eval(expression.substr(5)); } catch(e) { From de1d2720c67d6373b8b5a228c7834d85743b0248 Mon Sep 17 00:00:00 2001 From: Prateeksha Singh Date: Mon, 24 Sep 2018 12:33:53 +0530 Subject: [PATCH 05/19] Charts in Query Reports (#6118) * [charts][query-report] setup preview enabled chart maker - Options for y values: numeric fields - Options for x values: remaining non numeric fields * [query-report][chart] Add 'Vs' title, truncate total row --- frappe/desk/query_report.py | 14 +- .../js/frappe/views/reports/query_report.js | 178 ++++++++++++++++-- .../js/frappe/views/reports/report_view.js | 7 +- 3 files changed, 181 insertions(+), 18 deletions(-) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index ce470889bc..04b78c0741 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -59,11 +59,11 @@ def generate_report_result(report, filters=None, user=None): method_name = get_report_module_dotted_path(module, report.name) + ".execute" threshold = 10 res = [] - + start_time = datetime.datetime.now() # The JOB res = frappe.get_attr(method_name)(frappe._dict(filters)) - + end_time = datetime.datetime.now() if (end_time - start_time).seconds > threshold and not report.prepared_report: @@ -159,6 +159,8 @@ def run(report_name, filters=None, user=None): frappe.msgprint(_("Must have report permission to access this report."), raise_exception=True) + result = None + if report.prepared_report: if filters: if isinstance(filters, string_types): @@ -167,9 +169,13 @@ def run(report_name, filters=None, user=None): dn = filters.get("prepared_report_name") else: dn = "" - return get_prepared_report_result(report, filters, dn) + result = get_prepared_report_result(report, filters, dn) else: - return generate_report_result(report, filters, user) + result = generate_report_result(report, filters, user) + + result["add_total_row"] = report.add_total_row + + return result def get_prepared_report_result(report, filters, dn=""): diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 8ef31b456b..9fb153d079 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -98,10 +98,17 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { () => this.get_report_doc(), () => this.get_report_settings(), () => this.setup_page_head(), - () => this.refresh_report() + () => this.refresh_report(), + () => this.add_make_chart_button() ]); } + add_make_chart_button(){ + this.page.add_inner_button(__("Set Chart"), () => { + this.get_possible_chart_options(); + }); + } + refresh_report() { this.toggle_message(true); @@ -247,9 +254,17 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { this.add_prepared_report_buttons(data.doc); } this.toggle_message(false); + if (data.result && data.result.length) { - this.render_chart(data); - this.render_report(data); + this.prepare_report_data(data); + + const chart_options = this.get_chart_options(data); + this.$chart.empty(); + if(chart_options) { + this.render_chart(chart_options); + } + + this.render_datatable(); } else { this.toggle_nothing_to_show(true); } @@ -303,12 +318,15 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { } } - render_report(data) { + prepare_report_data(data) { + this.raw_data = data; this.columns = this.prepare_columns(data.columns); this.data = this.prepare_data(data.result); this.tree_report = this.data.some(d => 'indent' in d); + } + render_datatable() { if (this.datatable) { this.datatable.refresh(this.data, this.columns); return; @@ -323,21 +341,157 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { }); } - render_chart(data) { - this.$chart.empty(); - let opts = this.report_settings.get_chart_data + get_chart_options(data) { + let options = this.report_settings.get_chart_data ? this.report_settings.get_chart_data(data.columns, data.result) : data.chart ? data.chart - : {}; - if (!(opts.data && opts.data.labels && opts.data.labels.length > 0)) return; + : undefined; - Object.assign(opts, { - height: 200 + if (!(options && options.data && options.data.labels && options.data.labels.length > 0)) return; + + return options; + } + + render_chart(options, height=200) { + Object.assign(options, { + height: height }); + this.$chart.empty(); + this.chart = new Chart(this.$chart[0], options); this.$chart.show(); - this.chart = new Chart(this.$chart[0], opts); + } + + get_possible_chart_options() { + const columns = this.raw_data.columns; + const rows = this.raw_data.result; + const first_row = rows[0]; + const has_total_row = this.raw_data.add_total_row; + + const indices = first_row.reduce((accumulator, current_value, current_index) => { + if(!isNaN(Number(current_value))) { + accumulator.push(current_index); + } + return accumulator; + }, []); + + function get_column_values(column_name) { + const column_index = columns.indexOf(column_name); + return rows.map(row => row[column_index]); + } + + function get_chart_options({ y_field, x_field, chart_type, color }) { + const type = chart_type.toLowerCase(); + const colors = color ? [color] : undefined; + + let labels = get_column_values(x_field) + .filter(Boolean) + .map(d => d.trim()) + .filter(Boolean); + + let dataset_values = get_column_values(y_field).map(d => Number(d)); + + if(has_total_row) { + labels = labels.slice(0, -1); + dataset_values = dataset_values.slice(0, -1); + } + + return { + data: { + labels: labels, + datasets: [ + { values: dataset_values } + ] + }, + type: type, + colors: colors + }; + } + + function preview_chart() { + const wrapper = $(dialog.fields_dict["chart_preview"].wrapper); + const values = dialog.get_values(true); + let options = get_chart_options(values); + + Object.assign(options, { + height: 150 + }); + + wrapper.empty(); + new Chart(wrapper[0], options); + wrapper.find('.chart-container .title, .chart-container .sub-title').hide(); + wrapper.show(); + } + + const numeric_fields = columns.filter((col, i) => indices.includes(i)); + const non_numeric_fields = columns.filter((col, i) => !indices.includes(i)) + + const dialog = new frappe.ui.Dialog({ + title: __('Make Chart'), + fields: [ + { + fieldname: 'y_field', + label: 'Y Field', + fieldtype: 'Select', + options: numeric_fields, + default: numeric_fields[0], + onchange: preview_chart + }, + { + fieldname: 'x_field', + label: 'X Field', + fieldtype: 'Select', + options: non_numeric_fields, + default: non_numeric_fields[0], + onchange: preview_chart + }, + { + fieldname: 'cb_1', + fieldtype: 'Column Break' + }, + { + fieldname: 'chart_type', + label: 'Type of Chart', + fieldtype: 'Select', + options: ['Bar', 'Line', 'Percentage', 'Pie'], + default: 'Bar', + onchange: preview_chart + }, + { + fieldname: 'color', + label: 'Color', + fieldtype: 'Color', + depends_on: doc => ['Bar', 'Line'].includes(doc.chart_type), + onchange: preview_chart, + }, + { + fieldname: 'sb_1', + fieldtype: 'Section Break', + label: 'Chart Preview' + }, + { + fieldname: 'chart_preview', + label: 'Chart Preview', + fieldtype: 'HTML', + } + ], + primary_action_label: __('Make'), + primary_action: (values) => { + let options = get_chart_options(values); + + options.title = __(`${this.report_name}: ${values.y_field} vs ${values.x_field}`); + + this.render_chart(options); + + dialog.hide(); + } + }); + + dialog.show(); + + // load preview after dialog animation + setTimeout(preview_chart, 500); } get_user_settings() { diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 468b0c5561..eb30c2cb67 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -306,7 +306,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { this.chart = new Chart(this.$charts_wrapper[0], { title: __("{0} Chart", [this.doctype]), data: data, - type: args.chart_type, // 'bar', 'line', 'scatter', 'pie', 'percentage' + type: args.chart_type, height: 150, colors: ['violet', 'light-blue', 'orange', 'red'], @@ -365,7 +365,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { { label: __('Chart Type'), fieldtype: 'Select', - options: ['Bar', 'Line', 'Scatter', 'Pie', 'Percentage'], + options: ['Bar', 'Line', 'Pie', 'Percentage'], fieldname: 'chart_type', default: toTitle(defaults.chart_type || 'Bar') } @@ -396,6 +396,9 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { // look like strings and also // monkey patch the doc // javascript is awesome + + // O.o + return { doc: d, toString() { From de9778047dd7c232a18b381b7a5887f0fcc678e3 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 24 Sep 2018 12:34:21 +0530 Subject: [PATCH 06/19] [Fix] Not able to delete the document which has workflow (#6119) --- frappe/hooks.py | 5 ++++- .../doctype/workflow_action/workflow_action.py | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/frappe/hooks.py b/frappe/hooks.py index 26adacd0f1..954400e78c 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -125,7 +125,10 @@ doc_events = { "frappe.desk.notifications.clear_doctype_notifications", "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions" ], - "on_trash": "frappe.desk.notifications.clear_doctype_notifications", + "on_trash": [ + "frappe.desk.notifications.clear_doctype_notifications", + "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions" + ], "on_change": [ "frappe.core.doctype.feedback_trigger.feedback_trigger.trigger_feedback_request", ] diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 20b2f0f84c..33992b1a6c 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -24,17 +24,18 @@ def get_permission_query_conditions(user): return "(`tabWorkflow Action`.user='{user}')".format(user=user) - def has_permission(doc, user): if user not in ['Administrator', doc.user]: return False - def process_workflow_actions(doc, state): - workflow = get_workflow_name(doc.get('doctype')) if not workflow: return + if state == "on_trash": + clear_workflow_actions(doc.get('doctype'), doc.get('name')) + return + if is_workflow_action_already_created(doc): return clear_old_workflow_actions(doc) @@ -54,7 +55,6 @@ def process_workflow_actions(doc, state): if send_email_alert(workflow): enqueue(send_workflow_action_email, queue='short', users_data=list(user_data_map.values()), doc=doc) - @frappe.whitelist(allow_guest=True) def apply_action(action, doctype, docname, current_state, user=None, last_modified=None): if not verify_request(): @@ -234,6 +234,14 @@ def is_workflow_action_already_created(doc): 'workflow_state': get_doc_workflow_state(doc) }) +def clear_workflow_actions(doctype, name): + if not (doctype and name): + return + + frappe.db.sql('''delete from `tabWorkflow Action` + where reference_doctype=%s and reference_name=%s''', + (doctype, name)) + def get_doc_workflow_state(doc): workflow_name = get_workflow_name(doc.get('doctype')) workflow_state_field = get_workflow_state_field(workflow_name) From 97c02cae82efc778070189644fee1a9ad660b7ba Mon Sep 17 00:00:00 2001 From: Achilles Rasquinha Date: Mon, 24 Sep 2018 02:04:31 -0500 Subject: [PATCH 07/19] Installation Failure Fix for Python 3 - safe_decode bytes to string (#6130) * Installation Failure Fix for Python 3 - safe_decode bytes to string * Installation Failure Fix for Python 3 - safe_decode bytes to string * Fixed merge conflict * Use --short instead of first 7 characters --- frappe/utils/change_log.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frappe/utils/change_log.py b/frappe/utils/change_log.py index b2b91d88b5..7187b8fe1b 100644 --- a/frappe/utils/change_log.py +++ b/frappe/utils/change_log.py @@ -10,7 +10,7 @@ import requests import subprocess # nosec from frappe.utils import cstr from frappe.utils.gitutils import get_app_last_commit_ref, get_app_branch -from frappe import _ +from frappe import _, safe_decode def get_change_log(user=None): if not user: user = frappe.session.user @@ -117,15 +117,21 @@ def get_versions(): def get_app_branch(app): '''Returns branch of an app''' try: - return subprocess.check_output('cd ../apps/{0} && git rev-parse --abbrev-ref HEAD'.format(app), - shell=True).strip() + result = subprocess.check_output('cd ../apps/{0} && git rev-parse --abbrev-ref HEAD'.format(app), + shell=True) + result = safe_decode(result) + result = result.strip() + return result except Exception as e: return '' def get_app_last_commit_ref(app): try: - return subprocess.check_output('cd ../apps/{0} && git rev-parse HEAD'.format(app), - shell=True).strip()[:7] + result = subprocess.check_output('cd ../apps/{0} && git rev-parse HEAD --short 7'.format(app), + shell=True) + result = safe_decode(result) + result = result.strip() + return result except Exception as e: return '' From f169f6231dd3279c6475a65e9148c2f5f7420efa Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 24 Sep 2018 12:46:41 +0530 Subject: [PATCH 08/19] fix(ux): Reorder Print Server fields (#6115) - fix timeline overflow text --- .../print_settings/print_settings.json | 102 +++++++----------- frappe/public/less/form.less | 4 + 2 files changed, 41 insertions(+), 65 deletions(-) diff --git a/frappe/printing/doctype/print_settings/print_settings.json b/frappe/printing/doctype/print_settings/print_settings.json index d8fca5c848..4f7039c7f8 100644 --- a/frappe/printing/doctype/print_settings/print_settings.json +++ b/frappe/printing/doctype/print_settings/print_settings.json @@ -305,38 +305,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enable_print_server", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Enable Print Server", - "length": 0, - "no_copy": 0, - "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 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -473,7 +441,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:doc.enable_print_server == 1", + "depends_on": "", "fieldname": "server_printer", "fieldtype": "Section Break", "hidden": 0, @@ -499,6 +467,38 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "enable_print_server", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Enable Print Server", + "length": 0, + "no_copy": 0, + "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 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -507,6 +507,7 @@ "collapsible": 0, "columns": 0, "default": "localhost", + "depends_on": "enable_print_server", "fieldname": "server_ip", "fieldtype": "Data", "hidden": 0, @@ -539,6 +540,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "enable_print_server", "fieldname": "printer_name", "fieldtype": "Select", "hidden": 0, @@ -564,37 +566,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_17", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "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 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -603,6 +574,7 @@ "collapsible": 0, "columns": 0, "default": "631", + "depends_on": "enable_print_server", "fieldname": "port", "fieldtype": "Int", "hidden": 0, @@ -832,7 +804,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2018-06-29 01:34:57.508272", + "modified": "2018-09-20 12:10:14.440598", "modified_by": "Administrator", "module": "Printing", "name": "Print Settings", diff --git a/frappe/public/less/form.less b/frappe/public/less/form.less index ef8d0841a4..bdce9331cc 100644 --- a/frappe/public/less/form.less +++ b/frappe/public/less/form.less @@ -386,6 +386,10 @@ h6.uppercase, .h6.uppercase { } } +.timeline-item .media-body { + max-width: 100%; +} + .timeline-item.user-content { margin: 30px 0px 30px 27px; From bea46dc45cbd1d2d319c73692cd6c8332c9d062c Mon Sep 17 00:00:00 2001 From: gshmu Date: Mon, 24 Sep 2018 15:29:37 +0800 Subject: [PATCH 09/19] list clear, unselect list-select-all (#6088) --- frappe/public/js/frappe/ui/base_list.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/ui/base_list.js b/frappe/public/js/frappe/ui/base_list.js index 3a239f5bc0..7999b1b164 100644 --- a/frappe/public/js/frappe/ui/base_list.js +++ b/frappe/public/js/frappe/ui/base_list.js @@ -258,6 +258,7 @@ frappe.ui.BaseList = Class.extend({ clear: function () { this.data = []; + this.wrapper.find('.list-select-all').prop('checked', false); this.wrapper.find('.result-list').empty(); this.wrapper.find('.result').show(); this.wrapper.find('.no-result').hide(); From 5e5623d7f9bc8b059ff7811427353a43e28d7279 Mon Sep 17 00:00:00 2001 From: Sachin Mane Date: Mon, 24 Sep 2018 13:08:08 +0530 Subject: [PATCH 10/19] fix - default timeouts never picked up (#6098) --- frappe/utils/background_jobs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index daaed29cc5..fe375afae9 100755 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -23,7 +23,7 @@ queue_timeout = { redis_connection = None -def enqueue(method, queue='default', timeout=300, event=None, +def enqueue(method, queue='default', timeout=None, event=None, is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs): ''' Enqueue method to be executed using a background worker From ab81036c20728bb44bc63fb6fc47e19c891e763b Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 25 Sep 2018 13:14:20 +0530 Subject: [PATCH 11/19] fix(python3): subproess.check_output should always be decoded (#6135) --- frappe/utils/change_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/change_log.py b/frappe/utils/change_log.py index 7187b8fe1b..1d2dd26d2a 100644 --- a/frappe/utils/change_log.py +++ b/frappe/utils/change_log.py @@ -164,7 +164,7 @@ def check_release_on_github(app): # Check if repo remote is on github from subprocess import CalledProcessError try: - remote_url = subprocess.check_output("cd ../apps/{} && git ls-remote --get-url".format(app), shell=True) + remote_url = subprocess.check_output("cd ../apps/{} && git ls-remote --get-url".format(app), shell=True).decode() except CalledProcessError: # Passing this since some apps may not have git initializaed in them return None From a8423dd782499f886c085975a73d38a6aaa55521 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 25 Sep 2018 15:37:26 +0530 Subject: [PATCH 12/19] [Fix] Email not sending if reciepients is blank because of reciepients is unsubscribed (#6136) --- frappe/email/queue.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frappe/email/queue.py b/frappe/email/queue.py index f06bfa69eb..8f5a28efac 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -89,6 +89,13 @@ def send(recipients=None, sender=None, subject=None, message=None, text_content= recipients = [r for r in list(set(recipients)) if r and r not in unsubscribed] + if cc: + cc = [r for r in list(set(cc)) if r and r not in unsubscribed] + + if not recipients and not cc: + # Recipients may have been unsubscribed, exit quietly + return + email_text_context = text_content should_append_unsubscribe = (add_unsubscribe_link From a19525e695adba66d2cc35f8b801cbf683a5fcd8 Mon Sep 17 00:00:00 2001 From: Ameya Shenoy Date: Tue, 25 Sep 2018 15:40:18 +0530 Subject: [PATCH 13/19] fix(setup_global_help): allow utf-8 in filename (#6132) - fixed issue with setting up global help. Setting up global help used to fail when the filenames were in any language other than english, due to improper encoding. Used frappe.safe_decode to solve the issue Signed-off-by: Ameya Shenoy --- frappe/utils/help.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/help.py b/frappe/utils/help.py index c76e977dd8..5549b17d19 100644 --- a/frappe/utils/help.py +++ b/frappe/utils/help.py @@ -245,7 +245,7 @@ class HelpDatabase(object): links_html = "