diff --git a/frappe/__init__.py b/frappe/__init__.py index 631cd7b70e..89792175d1 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -17,7 +17,7 @@ from faker import Faker from .exceptions import * from .utils.jinja import (get_jenv, get_template, render_template, get_email_from_template, get_jloader) -__version__ = '10.1.65' +__version__ = '10.1.67' __title__ = "Frappe Framework" local = Local() diff --git a/frappe/desk/doctype/event/event.py b/frappe/desk/doctype/event/event.py index a6769e2eb9..7749f71e17 100644 --- a/frappe/desk/doctype/event/event.py +++ b/frappe/desk/doctype/event/event.py @@ -248,3 +248,19 @@ def get_events(start, end, user=None, for_reminder=False, filters=None): del e[w] return events + +def delete_events(ref_type, ref_name, delete_event=False): + participations = frappe.get_all("Event Participants", filters={"reference_doctype": ref_type, "reference_docname": ref_name, + "parenttype": "Event"}, fields=["parent", "name"]) + + if participations: + for participation in participations: + if delete_event: + frappe.delete_doc("Event", participation.parent, for_reload=True) + else: + total_participants = frappe.get_all("Event Participants", filters={"parenttype": "Event", "parent": participation.parent}) + + if len(total_participants) <= 1: + frappe.db.sql("DELETE FROM `tabEvent` WHERE `name` = %(name)s", {'name': participation.parent}) + + frappe.db.sql("DELETE FROM `tabEvent Participants ` WHERE `name` = %(name)s", {'name': participation.name}) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index 1030440da8..c5fda2ca66 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -80,9 +80,6 @@ def generate_report_result(report, filters=None, user=None): if result: result = get_filtered_data(report.ref_doctype, columns, result, user) - if cint(report.add_total_row) and result: - result = add_total_row(result, columns) - return { "result": result, "columns": columns, diff --git a/frappe/hooks.py b/frappe/hooks.py index c0fda64590..08ec07df46 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -12,7 +12,7 @@ source_link = "https://github.com/frappe/frappe" app_license = "MIT" develop_version = '12.x.x-develop' -staging_version = '11.0.3-beta.31' +staging_version = '11.0.3-beta.33' app_email = "info@frappe.io" diff --git a/frappe/integrations/doctype/paypal_settings/paypal_settings.py b/frappe/integrations/doctype/paypal_settings/paypal_settings.py index 3d4be38467..83a1cb0aab 100644 --- a/frappe/integrations/doctype/paypal_settings/paypal_settings.py +++ b/frappe/integrations/doctype/paypal_settings/paypal_settings.py @@ -203,7 +203,7 @@ def setup_redirect(data, redirect_url, custom_redirect_to=None, redirect=True): redirect_to = custom_redirect_to if redirect_to: - redirect_url += '?' + urlencode({'redirect_to': redirect_to}) + redirect_url += '&' + urlencode({'redirect_to': redirect_to}) if redirect_message: redirect_url += '&' + urlencode({'redirect_message': redirect_message}) @@ -274,7 +274,7 @@ def confirm_payment(token): data.get("reference_docname")).run_method("on_payment_authorized", "Completed") frappe.db.commit() - redirect_url = '/integrations/payment-success' + redirect_url = '/integrations/payment-success?doctype={0}&docname={1}'.format(data.get("reference_doctype"), data.get("reference_docname")) else: redirect_url = "/integrations/payment-failed" @@ -332,7 +332,7 @@ def create_recurring_profile(token, payerid): data.get("reference_docname")).run_method("on_payment_authorized", status_changed_to) frappe.db.commit() - redirect_url = '/integrations/payment-success' + redirect_url = '/integrations/payment-success?doctype={0}&docname={1}'.format(data.get("reference_doctype"), data.get("reference_docname")) else: redirect_url = "/integrations/payment-failed" diff --git a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py index bca9291f54..cb66ed7f2a 100644 --- a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +++ b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py @@ -255,12 +255,12 @@ class RazorpaySettings(Document): if custom_redirect_to: redirect_to = custom_redirect_to - redirect_url = 'payment-success' + redirect_url = 'payment-success?doctype={0}&docname={1}'.format(self.data.reference_doctype, self.data.reference_docname) else: redirect_url = 'payment-failed' if redirect_to: - redirect_url += '?' + urlencode({'redirect_to': redirect_to}) + redirect_url += '&' + urlencode({'redirect_to': redirect_to}) if redirect_message: redirect_url += '&' + urlencode({'redirect_message': redirect_message}) diff --git a/frappe/public/js/frappe/chat.js b/frappe/public/js/frappe/chat.js index 137a24d6ee..ea7bfd3664 100644 --- a/frappe/public/js/frappe/chat.js +++ b/frappe/public/js/frappe/chat.js @@ -1565,12 +1565,16 @@ class extends Component { const alert = // TODO: ellipses content ` - + ${frappe.user.first_name(r.user)}: ${r.content} ` - - frappe.show_alert(alert, 3) + frappe.show_alert(alert, 3, { + "show-message": function (r) { + this.room.select(r.room) + this.base.firstChild._component.toggle() + }.bind(this, r) + }) } if ( r.room === state.room.name ) { diff --git a/frappe/public/js/frappe/form/dashboard.js b/frappe/public/js/frappe/form/dashboard.js index dc42a953cc..8b15715361 100644 --- a/frappe/public/js/frappe/form/dashboard.js +++ b/frappe/public/js/frappe/form/dashboard.js @@ -301,7 +301,7 @@ frappe.ui.form.Dashboard = Class.extend({ } } - frappe.set_route("List", doctype); + frappe.set_route("List", doctype, "List"); }, get_document_filter: function(doctype) { // return the default filter for the given document diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 89ec11cbfd..99d913f1cd 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -107,7 +107,7 @@ frappe.ui.form.Toolbar = Class.extend({ var p = this.frm.perm[0]; var docstatus = cint(this.frm.doc.docstatus); var is_submittable = frappe.model.is_submittable(this.frm.doc.doctype) - + var issingle = this.frm.meta.issingle; var print_settings = frappe.model.get_doc(":Print Settings", "Print Settings") var allow_print_for_draft = cint(print_settings.allow_print_for_draft); var allow_print_for_cancelled = cint(print_settings.allow_print_for_cancelled); @@ -116,7 +116,7 @@ frappe.ui.form.Toolbar = Class.extend({ if(!is_submittable || docstatus == 1 || (allow_print_for_cancelled && docstatus == 2)|| (allow_print_for_draft && docstatus == 0)) { - if(frappe.model.can_print(null, me.frm)) { + if(frappe.model.can_print(null, me.frm) && !issingle) { this.page.add_menu_item(__("Print"), function() { me.frm.print_doc();}, true); this.print_icon = this.page.add_action_icon("fa fa-print", function() { diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index 4dc58ff722..e87086b754 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -395,6 +395,10 @@ frappe.views.BaseList = class BaseList { // for child classes } + on_filter_change() { + // fired when filters are added or removed + } + toggle_result_area() { this.$result.toggle(this.data.length > 0); this.$paging_area.toggle(this.data.length > 0); @@ -483,6 +487,7 @@ class FilterArea { if (this.trigger_refresh) { this.list_view.start = 0; this.list_view.refresh(); + this.list_view.on_filter_change(); } } diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 81f473b6b1..b345685f7a 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -52,6 +52,21 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { this.sort_by = this.view_user_settings.sort_by || 'modified'; this.sort_order = this.view_user_settings.sort_order || 'desc'; + // set filters from user_settings or list_settings + if (this.view_user_settings.filters && this.view_user_settings.filters.length) { + // Priority 1: user_settings + const saved_filters = this.view_user_settings.filters; + this.filters = this.validate_filters(saved_filters); + } else { + // Priority 2: filters in listview_settings + this.filters = (this.settings.filters || []).map(f => { + if (f.length === 3) { + f = [this.doctype, f[0], f[1], f[2]]; + } + return f; + }); + } + // build menu items this.menu_items = this.menu_items.concat(this.get_menu_items()); @@ -281,6 +296,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { before_refresh() { if (frappe.route_options) { this.filters = this.parse_filters_from_route_options(); + return this.filter_area.clear(false) .then(() => this.filter_area.set(this.filters)); } @@ -288,6 +304,15 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { return Promise.resolve(); } + parse_filters_from_settings() { + return (this.settings.filters || []).map(f => { + if (f.length === 3) { + f = [this.doctype, f[0], f[1], f[2]]; + } + return f; + }); + } + toggle_result_area() { super.toggle_result_area(); this.toggle_actions_menu_button( diff --git a/frappe/public/js/frappe/views/gantt/gantt_view.js b/frappe/public/js/frappe/views/gantt/gantt_view.js index d5e430a73b..11cc9683e7 100644 --- a/frappe/public/js/frappe/views/gantt/gantt_view.js +++ b/frappe/public/js/frappe/views/gantt/gantt_view.js @@ -125,7 +125,7 @@ frappe.views.GanttView = class GanttView extends frappe.views.ListView { var html = `
${task.name}
-

${task._start.format('MMM D')} - ${task._end.format('MMM D')}

`; +

${moment(task._start).format('MMM D')} - ${moment(task._end).format('MMM D')}

`; // custom html in doctype settings var custom = me.settings.gantt_custom_popup_html; @@ -207,3 +207,4 @@ frappe.views.GanttView = class GanttView extends frappe.views.ListView { ]; } }; + diff --git a/frappe/public/js/frappe/views/kanban/kanban_view.js b/frappe/public/js/frappe/views/kanban/kanban_view.js index 7b163baf97..74dc283326 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_view.js +++ b/frappe/public/js/frappe/views/kanban/kanban_view.js @@ -32,10 +32,14 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView { this.page_title = this.board_name; this.card_meta = this.get_card_meta(); - return this.get_board() - .then(() => { - this.filters = this.board.filters_array; - }); + this.menu_items.push({ + label: __('Save filters'), + action: () => { + this.save_kanban_board_filters(); + } + }); + + return this.get_board(); } get_board() { @@ -43,9 +47,14 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView { .then(board => { this.board = board; this.board.filters_array = JSON.parse(this.board.filters || '[]'); + this.filters = this.board.filters_array; }); } + before_refresh() { + + } + setup_view() { } @@ -60,13 +69,40 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView { this.save_view_user_settings({ last_kanban_board: this.board_name }); + } + + on_filter_change() { + if (JSON.stringify(this.board.filters_array) !== JSON.stringify(this.filter_area.get())) { + this.page.set_indicator(__('Not Saved'), 'orange'); + } else { + this.page.clear_indicator(); + } + } + + save_kanban_board_filters() { + const filters = this.filter_area.get(); frappe.call({ method: 'frappe.desk.doctype.kanban_board.kanban_board.save_filters', args: { board_name: this.board_name, - filters: this.filter_area.get() + filters: filters } + }).then(r => { + if (r.exc) { + frappe.show_alert({ + indicator: 'red', + message: __('There was an error saving filters') + }); + return; + } + frappe.show_alert({ + indicator: 'green', + message: __('Filters saved') + }); + + this.board.filters_array = filters; + this.on_filter_change(); }); } diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 984699f3ad..6c3e699d85 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -347,23 +347,25 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { if (this.datatable) { this.datatable.options.treeView = this.tree_report; this.datatable.refresh(this.data, this.columns); - return; + } else { + let datatable_options = { + columns: this.columns, + data: this.data, + inlineFilters: true, + treeView: this.tree_report, + layout: 'fixed', + cellHeight: 33 + }; + + if (this.report_settings.get_datatable_options) { + datatable_options = this.report_settings.get_datatable_options(datatable_options); + } + this.datatable = new DataTable(this.$report[0], datatable_options); } - let datatable_options = { - columns: this.columns, - data: this.data, - inlineFilters: true, - treeView: this.tree_report, - layout: 'fixed', - cellHeight: 33 - }; - - if (this.report_settings.get_datatable_options) { - datatable_options = this.report_settings.get_datatable_options(datatable_options); + if (this.report_settings.after_datatable_render) { + this.report_settings.after_datatable_render(this.datatable); } - - this.datatable = new DataTable(this.$report[0], datatable_options); } get_chart_options(data) { diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 02f617e141..67f4180965 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -121,6 +121,16 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } } + on_filter_change() { + if (this.report_doc) { + if (JSON.stringify(this.filters) !== JSON.stringify(this.filter_area.get())) { + this.page.set_indicator(__('Not Saved'), 'orange'); + } else { + this.page.clear_indicator(); + } + } + } + update_row(doc, flash_row) { const to_refresh = []; @@ -899,6 +909,10 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { if(r.message != this.report_name) { frappe.set_route('List', this.doctype, 'Report', r.message); } + + // reset dirty state + this.filters = this.filter_area.get(); + this.on_filter_change(); } }); diff --git a/frappe/templates/pages/integrations/payment-success.html b/frappe/templates/pages/integrations/payment-success.html index ce382cd5e1..45bc303a75 100644 --- a/frappe/templates/pages/integrations/payment-success.html +++ b/frappe/templates/pages/integrations/payment-success.html @@ -8,9 +8,16 @@ {{ _("Success") }} -

{{ _("Your payment was successfully accepted") }}

-
- {{ _("Continue") }}
+

{{ payment_message or _("Your payment was successfully accepted") }}

+ {% if not payment_message %} +
+ + {{ _("Continue") }} + +
+ {% endif %}