From ddd45a71bc6f71be277647e69cbe60ebf9cc11e8 Mon Sep 17 00:00:00 2001 From: Daizy Date: Mon, 7 Feb 2022 19:35:12 +0530 Subject: [PATCH 1/8] feat: Allow users to customize their own reports --- frappe/core/doctype/report/test_report.py | 52 ++++++++++++++++++ frappe/desk/reportview.py | 42 +++++++++++---- .../js/frappe/views/reports/report_view.js | 53 +++++++++++++++---- 3 files changed, 129 insertions(+), 18 deletions(-) diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index 36e3b09254..cd4c2f4553 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -4,6 +4,7 @@ import frappe, json, os import unittest from frappe.desk.query_report import run, save_report +from frappe.desk.reportview import delete_report, save_report as save_as_report from frappe.custom.doctype.customize_form.customize_form import reset_customization test_records = frappe.get_test_records('Report') @@ -30,6 +31,57 @@ class TestReport(unittest.TestCase): self.assertEqual(columns[1].get('label'), 'Module') self.assertTrue('User' in [d.get('name') for d in data]) + def test_can_save_or_delete_report(self): + '''Test case to test if if users can create, save or delete their own report of type Report Builder''' + frappe.set_user("Administrator") + + report = frappe.get_doc({ + 'doctype': 'Report', + 'ref_doctype': 'User', + 'report_name': 'Test Delete Report', + 'report_type': 'Report Builder', + 'is_standard': 'No', + }).insert() + + frappe.set_user("test@example.com") + self.assertRaisesRegex(frappe.exceptions.ValidationError, "Only Report owner or Report Manager can delete the reports", delete_report, report.name) + + frappe.set_user("Administrator") + + report.report_type = 'Custom Report' # change report type to validate + report.save() + + self.assertRaisesRegex(frappe.exceptions.ValidationError, "Only reports of type Report Builder can be deleted", delete_report, report.name) + + report.is_standard = 'Yes' # change is_standard to validate + report.save() + + self.assertRaisesRegex(frappe.exceptions.ValidationError, "Standard Reports can not be deleted", delete_report, report.name) + + frappe.set_user("test@example.com") + + report_name = save_as_report( + 'Dummy Report', + 'User', + json.dumps([{ + 'fieldname': 'email', + 'fieldtype': 'Data', + 'label': 'Email', + 'insert_after_index': 0, + 'link_field': 'name', + 'doctype': 'User', + 'options': 'Email', + 'width': 100, + 'id':'email', + 'name': 'Email' + }]) + ) + + doc = frappe.get_doc("Report", report_name) + + delete_report(doc.name) + + def test_custom_report(self): reset_customization('User') custom_report_name = save_report( diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index c45fc9bfdd..d1eaf00452 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -262,23 +262,47 @@ def compress(data, args=None): } @frappe.whitelist() -def save_report(): - """save report""" +def save_report(name, doctype, report_settings): + """save report if report type is report builder""" - data = frappe.local.form_dict - if frappe.db.exists('Report', data['name']): - d = frappe.get_doc('Report', data['name']) + if frappe.db.exists('Report', name): + d = frappe.get_doc('Report', name) + if d.is_standard == "Yes": + frappe.throw(_("Standard Reports can not be edited")) + + if d.report_type != "Report Builder": + frappe.throw(_("Only reports of type Report Builder can be created")) + + if d.owner != frappe.session.user: + frappe.throw(_("Only Report owner or Report Manager can save the reports")) else: d = frappe.new_doc('Report') - d.report_name = data['name'] - d.ref_doctype = data['doctype'] + d.report_name = name + d.ref_doctype = doctype d.report_type = "Report Builder" - d.json = data['json'] - frappe.get_doc(d).save() + d.json = report_settings + frappe.get_doc(d).save(ignore_permissions=True) frappe.msgprint(_("{0} is saved").format(d.name), alert=True) return d.name +@frappe.whitelist() +def delete_report(name): + """delete report type of report builder if user is report owner or has role Report Manager""" + + report_doc = frappe.get_doc("Report", name) + if report_doc.is_standard == "Yes": + frappe.throw(_("Standard Reports can not be deleted")) + + if report_doc.report_type != "Report Builder": + frappe.throw(_("Only reports of type Report Builder can be deleted")) + + if report_doc.owner != frappe.session.user: + frappe.throw(_("Only Report owner or Report Manager can delete the reports")) + + report_doc.delete(ignore_permissions=True) + frappe.msgprint(_("{0} is Deleted").format(report_doc.name), alert=True) + @frappe.whitelist() @frappe.read_only() def export_query(): diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 23e415ed3e..560657f36d 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -18,14 +18,14 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { setup_defaults() { super.setup_defaults(); this.page_title = __('Report:') + ' ' + this.page_title; - this.menu_items = this.report_menu_items(); - this.view = 'Report'; const route = frappe.get_route(); if (route.length === 4) { this.report_name = route[3]; } + this.view = 'Report'; + if (this.report_name) { return this.get_report_doc() .then(doc => { @@ -39,6 +39,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { this.page_length = this.report_doc.json.page_length || 20; this.order_by = this.report_doc.json.order_by || 'modified desc'; this.chart_args = this.report_doc.json.chart_args; + this.menu_items = this.report_menu_items(); }); } else { this.add_totals_row = this.view_user_settings.add_totals_row || 0; @@ -1207,7 +1208,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { args: { name: name, doctype: this.doctype, - json: JSON.stringify(report_settings) + report_settings: JSON.stringify(report_settings) }, callback:(r) => { if(r.exc) { @@ -1244,6 +1245,25 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } } + delete_report() { + const _delete_report = (name) => { + return frappe.call({ + method: 'frappe.desk.reportview.delete_report', + args: { name }, + callback: (r) => { + if (r.exc) { + frappe.msgprint(__("Report was not deleted (there were errors)")); + return; + } + } + }); + } + + if (this.report_name) { + _delete_report(this.report_name); + } + } + get_column_widths() { if (this.datatable) { return this.datatable @@ -1465,12 +1485,27 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } }); - // save buttons - if(frappe.user.is_report_manager()) { - items = items.concat([ - { label: __('Save'), action: () => this.save_report('save') }, - { label: __('Save As'), action: () => this.save_report('save_as') } - ]); + const can_save_or_delete = this.report_doc.owner === frappe.session.user || frappe.user.is_report_manager() + // A user with role Report Manager or Report Owner can save + if (can_save_or_delete) { + items.push({ + label: __("Save"), + action: () => this.save_report('save') + }); + } + + // anyone can save as + items.push({ + label: __('Save As'), + action: () => this.save_report('save_as') + }); + + // A user with role Report Manager or Report Owner can delete + if (can_save_or_delete) { + items.push({ + label: __("Delete"), + action: () => this.delete_report() + }); } // user permissions From f0a10efa629698195cdc07719d6002950d57316e Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 12:21:58 +0530 Subject: [PATCH 2/8] fix: improved validations --- frappe/core/doctype/report/test_report.py | 90 ++++++++++--------- frappe/desk/reportview.py | 68 ++++++++------ .../js/frappe/views/reports/report_view.js | 56 ++++++------ 3 files changed, 120 insertions(+), 94 deletions(-) diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index cd4c2f4553..f275b25c43 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -4,7 +4,7 @@ import frappe, json, os import unittest from frappe.desk.query_report import run, save_report -from frappe.desk.reportview import delete_report, save_report as save_as_report +from frappe.desk.reportview import delete_report, save_report as _save_report from frappe.custom.doctype.customize_form.customize_form import reset_customization test_records = frappe.get_test_records('Report') @@ -31,55 +31,59 @@ class TestReport(unittest.TestCase): self.assertEqual(columns[1].get('label'), 'Module') self.assertTrue('User' in [d.get('name') for d in data]) - def test_can_save_or_delete_report(self): - '''Test case to test if if users can create, save or delete their own report of type Report Builder''' - frappe.set_user("Administrator") + def test_save_or_delete_report(self): + '''Test for validations when editing / deleting report of type Report Builder''' - report = frappe.get_doc({ - 'doctype': 'Report', - 'ref_doctype': 'User', - 'report_name': 'Test Delete Report', - 'report_type': 'Report Builder', - 'is_standard': 'No', - }).insert() + try: + report = frappe.get_doc({ + 'doctype': 'Report', + 'ref_doctype': 'User', + 'report_name': 'Test Delete Report', + 'report_type': 'Report Builder', + 'is_standard': 'No', + }).insert() - frappe.set_user("test@example.com") - self.assertRaisesRegex(frappe.exceptions.ValidationError, "Only Report owner or Report Manager can delete the reports", delete_report, report.name) + # Check for PermissionError + frappe.set_user("test@example.com") + self.assertRaises(frappe.PermissionError, delete_report, report.name) - frappe.set_user("Administrator") + # Check for Report Type + frappe.set_user("Administrator") + report.db_set("report_type", "Custom Report") + self.assertRaisesRegex( + frappe.ValidationError, + "Only reports of type Report Builder can be deleted", + delete_report, + report.name + ) - report.report_type = 'Custom Report' # change report type to validate - report.save() + # Cleanup + frappe.delete_doc(report.doctype, report.name) - self.assertRaisesRegex(frappe.exceptions.ValidationError, "Only reports of type Report Builder can be deleted", delete_report, report.name) + # Check if creating and deleting works with proper validations + frappe.set_user("test@example.com") + report_name = _save_report( + 'Dummy Report', + 'User', + json.dumps([{ + 'fieldname': 'email', + 'fieldtype': 'Data', + 'label': 'Email', + 'insert_after_index': 0, + 'link_field': 'name', + 'doctype': 'User', + 'options': 'Email', + 'width': 100, + 'id':'email', + 'name': 'Email' + }]) + ) - report.is_standard = 'Yes' # change is_standard to validate - report.save() + doc = frappe.get_doc("Report", report_name) + delete_report(doc.name) - self.assertRaisesRegex(frappe.exceptions.ValidationError, "Standard Reports can not be deleted", delete_report, report.name) - - frappe.set_user("test@example.com") - - report_name = save_as_report( - 'Dummy Report', - 'User', - json.dumps([{ - 'fieldname': 'email', - 'fieldtype': 'Data', - 'label': 'Email', - 'insert_after_index': 0, - 'link_field': 'name', - 'doctype': 'User', - 'options': 'Email', - 'width': 100, - 'id':'email', - 'name': 'Email' - }]) - ) - - doc = frappe.get_doc("Report", report_name) - - delete_report(doc.name) + finally: + frappe.set_user("Administrator") def test_custom_report(self): diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index d1eaf00452..a351bb4ff3 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -263,45 +263,61 @@ def compress(data, args=None): @frappe.whitelist() def save_report(name, doctype, report_settings): - """save report if report type is report builder""" + """Save reports of type Report Builder from Report View""" if frappe.db.exists('Report', name): - d = frappe.get_doc('Report', name) - if d.is_standard == "Yes": - frappe.throw(_("Standard Reports can not be edited")) + report = frappe.get_doc('Report', name) + if report.is_standard == "Yes": + frappe.throw(_("Standard Reports cannot be edited")) - if d.report_type != "Report Builder": - frappe.throw(_("Only reports of type Report Builder can be created")) + if report.report_type != "Report Builder": + frappe.throw(_("Only reports of type Report Builder can be edited")) - if d.owner != frappe.session.user: - frappe.throw(_("Only Report owner or Report Manager can save the reports")) + if ( + report.owner != frappe.session.user + and not frappe.has_permission("Report", "write") + ): + frappe.throw( + _("Insufficient Permissions for editing Report"), + frappe.PermissionError + ) else: - d = frappe.new_doc('Report') - d.report_name = name - d.ref_doctype = doctype + report = frappe.new_doc('Report') + report.report_name = name + report.ref_doctype = doctype - d.report_type = "Report Builder" - d.json = report_settings - frappe.get_doc(d).save(ignore_permissions=True) - frappe.msgprint(_("{0} is saved").format(d.name), alert=True) - return d.name + report.report_type = "Report Builder" + report.json = report_settings + report.save(ignore_permissions=True) + frappe.msgprint(_("{0} saved").format(frappe.bold(report.name)), alert=True) + return report.name @frappe.whitelist() def delete_report(name): - """delete report type of report builder if user is report owner or has role Report Manager""" - - report_doc = frappe.get_doc("Report", name) - if report_doc.is_standard == "Yes": - frappe.throw(_("Standard Reports can not be deleted")) + """Save reports of type Report Builder from Report View""" - if report_doc.report_type != "Report Builder": + report = frappe.get_doc("Report", name) + if report.is_standard == "Yes": + frappe.throw(_("Standard Reports cannot be deleted")) + + if report.report_type != "Report Builder": frappe.throw(_("Only reports of type Report Builder can be deleted")) - if report_doc.owner != frappe.session.user: - frappe.throw(_("Only Report owner or Report Manager can delete the reports")) + if ( + report.owner != frappe.session.user + and not frappe.has_permission("Report", "delete") + ): + frappe.throw( + _("Insufficient Permissions for deleting Report"), + frappe.PermissionError + ) - report_doc.delete(ignore_permissions=True) - frappe.msgprint(_("{0} is Deleted").format(report_doc.name), alert=True) + report.delete(ignore_permissions=True) + frappe.msgprint( + _("{0} deleted").format(frappe.bold(report.name)), + indicator="red", + alert=True, + ) @frappe.whitelist() @frappe.read_only() diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 560657f36d..41c8f07e2f 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -18,14 +18,13 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { setup_defaults() { super.setup_defaults(); this.page_title = __('Report:') + ' ' + this.page_title; + this.view = 'Report'; const route = frappe.get_route(); if (route.length === 4) { this.report_name = route[3]; } - this.view = 'Report'; - if (this.report_name) { return this.get_report_doc() .then(doc => { @@ -39,7 +38,6 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { this.page_length = this.report_doc.json.page_length || 20; this.order_by = this.report_doc.json.order_by || 'modified desc'; this.chart_args = this.report_doc.json.chart_args; - this.menu_items = this.report_menu_items(); }); } else { this.add_totals_row = this.view_user_settings.add_totals_row || 0; @@ -53,6 +51,11 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { this.page.main.addClass('report-view'); } + setup_page() { + this.menu_items = this.report_menu_items(); + super.setup_page(); + } + toggle_side_bar() { super.toggle_side_bar(); // refresh datatable when sidebar is toggled to accomodate extra space @@ -1246,22 +1249,14 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } delete_report() { - const _delete_report = (name) => { - return frappe.call({ - method: 'frappe.desk.reportview.delete_report', - args: { name }, - callback: (r) => { - if (r.exc) { - frappe.msgprint(__("Report was not deleted (there were errors)")); - return; - } - } - }); - } - - if (this.report_name) { - _delete_report(this.report_name); - } + return frappe.call({ + method: 'frappe.desk.reportview.delete_report', + args: { name: this.report_name }, + callback(response) { + if (response.exc) return; + window.history.back(); + } + }); } get_column_widths() { @@ -1485,9 +1480,20 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } }); - const can_save_or_delete = this.report_doc.owner === frappe.session.user || frappe.user.is_report_manager() + function can_edit_or_delete(action) { + const method = action == "delete" ? "can_delete" : "can_write"; + return ( + this.report_doc + && this.report_doc.is_standard !== "Yes" + && ( + frappe.model[method]("Report") + || this.report_doc.owner === frappe.session.user + ) + ); + } + // A user with role Report Manager or Report Owner can save - if (can_save_or_delete) { + if (can_edit_or_delete()) { items.push({ label: __("Save"), action: () => this.save_report('save') @@ -1495,13 +1501,13 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } // anyone can save as - items.push({ - label: __('Save As'), - action: () => this.save_report('save_as') + items.push({ + label: __('Save As'), + action: () => this.save_report('save_as') }); // A user with role Report Manager or Report Owner can delete - if (can_save_or_delete) { + if (can_edit_or_delete("delete")) { items.push({ label: __("Delete"), action: () => this.delete_report() From a49a07e4192f95776bff044a61798af47e709d83 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 12:35:44 +0530 Subject: [PATCH 3/8] fix: sider issues --- frappe/desk/reportview.py | 2 +- .../public/js/frappe/views/reports/report_view.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index a351bb4ff3..ab411fddfe 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -298,7 +298,7 @@ def delete_report(name): report = frappe.get_doc("Report", name) if report.is_standard == "Yes": - frappe.throw(_("Standard Reports cannot be deleted")) + frappe.throw(_("Standard Reports cannot be deleted")) if report.report_type != "Report Builder": frappe.throw(_("Only reports of type Report Builder can be deleted")) diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 41c8f07e2f..7971b029f2 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -1257,7 +1257,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { window.history.back(); } }); - } + } get_column_widths() { if (this.datatable) { @@ -1495,9 +1495,9 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { // A user with role Report Manager or Report Owner can save if (can_edit_or_delete()) { items.push({ - label: __("Save"), - action: () => this.save_report('save') - }); + label: __("Save"), + action: () => this.save_report('save') + }); } // anyone can save as @@ -1509,9 +1509,9 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { // A user with role Report Manager or Report Owner can delete if (can_edit_or_delete("delete")) { items.push({ - label: __("Delete"), - action: () => this.delete_report() - }); + label: __("Delete"), + action: () => this.delete_report() + }); } // user permissions From d8fc39659a0086d54728b1ac966f1bc356dec963 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 12:37:41 +0530 Subject: [PATCH 4/8] fix: docstring --- frappe/desk/reportview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index ab411fddfe..880afae489 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -294,7 +294,7 @@ def save_report(name, doctype, report_settings): @frappe.whitelist() def delete_report(name): - """Save reports of type Report Builder from Report View""" + """Delete reports of type Report Builder from Report View""" report = frappe.get_doc("Report", name) if report.is_standard == "Yes": From f777700372afffc98307b5b5bf8332f5854500b4 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 13:14:11 +0530 Subject: [PATCH 5/8] test: create new user --- frappe/core/doctype/report/test_report.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index f275b25c43..5a22304f32 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -6,6 +6,7 @@ import unittest from frappe.desk.query_report import run, save_report from frappe.desk.reportview import delete_report, save_report as _save_report from frappe.custom.doctype.customize_form.customize_form import reset_customization +from frappe.core.doctype.user_permission.test_user_permission import create_user test_records = frappe.get_test_records('Report') test_dependencies = ['User'] @@ -44,7 +45,8 @@ class TestReport(unittest.TestCase): }).insert() # Check for PermissionError - frappe.set_user("test@example.com") + create_user("test_report_owner@example.com", "Website Manager") + frappe.set_user("test_report_owner@example.com") self.assertRaises(frappe.PermissionError, delete_report, report.name) # Check for Report Type @@ -57,9 +59,6 @@ class TestReport(unittest.TestCase): report.name ) - # Cleanup - frappe.delete_doc(report.doctype, report.name) - # Check if creating and deleting works with proper validations frappe.set_user("test@example.com") report_name = _save_report( @@ -84,6 +83,7 @@ class TestReport(unittest.TestCase): finally: frappe.set_user("Administrator") + frappe.db.rollback() def test_custom_report(self): From a18703a0b1eef958ac112153fdd2d0f79e1e36fa Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 13:52:37 +0530 Subject: [PATCH 6/8] fix: access to `this` and better UX --- frappe/public/js/frappe/views/reports/report_view.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js index 7971b029f2..f6aa17da8e 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -1480,7 +1480,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { } }); - function can_edit_or_delete(action) { + const can_edit_or_delete = (action) => { const method = action == "delete" ? "can_delete" : "can_write"; return ( this.report_doc @@ -1510,7 +1510,11 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { if (can_edit_or_delete("delete")) { items.push({ label: __("Delete"), - action: () => this.delete_report() + action: () => frappe.confirm( + "Are you sure you want to delete this report?", + () => this.delete_report(), + ), + shortcut: "Shift+Ctrl+D" }); } From e21275f06034a5843085c7373dd7015d66153c7d Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 14:05:40 +0530 Subject: [PATCH 7/8] style: add missing semicolon --- 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 f6aa17da8e..1291e63543 100644 --- a/frappe/public/js/frappe/views/reports/report_view.js +++ b/frappe/public/js/frappe/views/reports/report_view.js @@ -1490,7 +1490,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { || this.report_doc.owner === frappe.session.user ) ); - } + }; // A user with role Report Manager or Report Owner can save if (can_edit_or_delete()) { From 976c3bedc393a2be78e0492b142aa6a820842bc1 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Feb 2022 15:45:30 +0530 Subject: [PATCH 8/8] fix: use correct indicator --- frappe/desk/reportview.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 880afae489..b0e1f901aa 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -289,7 +289,11 @@ def save_report(name, doctype, report_settings): report.report_type = "Report Builder" report.json = report_settings report.save(ignore_permissions=True) - frappe.msgprint(_("{0} saved").format(frappe.bold(report.name)), alert=True) + frappe.msgprint( + _("Report {0} saved").format(frappe.bold(report.name)), + indicator="green", + alert=True, + ) return report.name @frappe.whitelist() @@ -314,8 +318,8 @@ def delete_report(name): report.delete(ignore_permissions=True) frappe.msgprint( - _("{0} deleted").format(frappe.bold(report.name)), - indicator="red", + _("Report {0} deleted").format(frappe.bold(report.name)), + indicator="green", alert=True, )