From 2fc96e1419bd9ec15c93ecd9938dd674698fa951 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 5 Mar 2018 11:02:23 +0530 Subject: [PATCH] Remember columns state for each user (#5102) * Remember columns state for each user * Chart * python 3 fix * Toggle message refactor, Tree structure DataTable update --- frappe/model/utils/user_settings.py | 4 + .../public/js/frappe/model/user_settings.js | 4 + .../js/frappe/views/reports/query_report.js | 113 +++++++++++++++--- frappe/utils/__init__.py | 2 +- yarn.lock | 2 +- 5 files changed, 104 insertions(+), 21 deletions(-) diff --git a/frappe/model/utils/user_settings.py b/frappe/model/utils/user_settings.py index bbbd9298f7..2045e3a5b2 100644 --- a/frappe/model/utils/user_settings.py +++ b/frappe/model/utils/user_settings.py @@ -48,3 +48,7 @@ def save(doctype, user_settings): user_settings = json.loads(user_settings or '{}') update_user_settings(doctype, user_settings) return user_settings + +@frappe.whitelist() +def get(doctype): + return get_user_settings(doctype) diff --git a/frappe/public/js/frappe/model/user_settings.js b/frappe/public/js/frappe/model/user_settings.js index 52c160ea77..932b6a359c 100644 --- a/frappe/public/js/frappe/model/user_settings.js +++ b/frappe/public/js/frappe/model/user_settings.js @@ -1,6 +1,10 @@ frappe.provide('frappe.model.user_settings'); $.extend(frappe.model.user_settings, { + get: function(doctype) { + return frappe.call('frappe.model.utils.user_settings.get', { doctype }) + .then(r => JSON.parse(r.message || '{}')); + }, save: function(doctype, key, value) { var user_settings = frappe.model.user_settings[doctype] || {}; diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 1fc5051d8c..8a46e305d5 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -61,8 +61,12 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { } load() { - this.toggle_freeze(true); + if (frappe.get_route().length < 2) { + this.toggle_message(true, __('Nothing to show')); + return; + } if (this.report_name !== frappe.get_route()[1]) { + this.toggle_message(true, __('Loading') + '...'); // different report this.load_report(); } else { @@ -76,7 +80,6 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { this.page_name = frappe.get_route_str(); this.report_name = this.route[1]; this.page_title = __(this.report_name); - this.user_settings = frappe.get_user_settings(this.report_name); this.menu_items = this.get_menu_items(); this.datatable = null; @@ -90,10 +93,14 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { } refresh_report() { + this.toggle_message(true, __('Loading') + '...'); + return frappe.run_serially([ () => this.setup_filters(), () => this.set_route_filters(), - () => this.refresh() + () => this.get_user_settings(), + () => this.refresh(), + () => this.save_user_settings() ]); } @@ -121,7 +128,6 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { }).then(r => { return frappe.after_ajax(() => { this.report_settings = frappe.query_reports[this.report_name]; - this.html_format = r.message.html_format; this.report_settings.html_format = r.message.html_format; }); }); @@ -213,14 +219,23 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { }, callback: resolve })).then(r => { - this.render_report(r.message); + const data = r.message; + + this.toggle_message(false); + + if (data.result && data.result.length) { + this.render_chart(r.message); + this.render_report(r.message); + } else { + this.toggle_message(true, __('Nothing to show')); + } }); } render_report(data) { - this.toggle_freeze(false); this._data = data.result; this._columns = data.columns; + if (this.datatable) { this.datatable.refresh(data.result); return; @@ -229,10 +244,47 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { columns: this.prepare_columns(data.columns), data: data.result, enableInlineFilters: true, - // layout: 'fluid' + events: { + onRemoveColumn: () => this.save_user_settings(), + onSwitchColumn: () => this.save_user_settings() + } }); } + render_chart(data) { + this.$chart.empty(); + let opts = 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; + + Object.assign(opts, { + parent: this.$chart[0], + height: 200 + }); + + this.$chart.show(); + this.chart = new Chart(opts); + } + + get_user_settings() { + return frappe.model.user_settings.get(this.report_name) + .then(user_settings => { + this.user_settings = user_settings; + }); + } + + save_user_settings(clear_settings = false) { + if (clear_settings) { + return frappe.model.user_settings.remove(this.report_name, 'column_order'); + } + if (!this.datatable) return; + const column_order = this.datatable.datamanager.getColumns(true).map(col => col.id); + return frappe.model.user_settings.save(this.report_name, 'column_order', column_order); + } + prepare_columns(columns) { columns = columns.map(column => { if (typeof column === 'string') { @@ -261,9 +313,9 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { return column; }); - return columns.map(column => { + columns = columns.map(column => { return { - id: column.fieldname, + id: column.fieldname || column.label, content: column.label, width: column.width || null, editable: false, @@ -283,6 +335,14 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { } }; }); + + if (this.user_settings.column_order && this.user_settings.column_order.length > 0) { + return this.user_settings.column_order + .map(id => columns.find(col => col.id === id)) + .filter(Boolean); + } else { + return columns; + } } get_data() { @@ -329,7 +389,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { print_report(print_settings) { frappe.render_grid({ - template: this.html_format || null, + template: this.report_settings.html_format || null, title: __(this.report_name), print_settings: print_settings, filters: this.get_filter_values(), @@ -346,8 +406,8 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { const columns = this.columns; let html; - if (this.html_format) { - const content = frappe.render(this.html_format, { + if (this.report_settings.html_format) { + const content = frappe.render(this.report_settings.html_format, { data: this.get_data_for_print(), filters: this.get_filter_values(), report: this, @@ -368,7 +428,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { title: __(this.report_name), data: this.get_data_for_print(), columns: columns - }) + }); //Render Report in HTML html = frappe.render_template("print_template", { @@ -483,6 +543,11 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { condition: () => frappe.model.can_set_user_permissions('Report'), standard: true }, + { + label: __('Clear User Settings'), + action: () => this.save_user_settings(true).then(() => this.refresh_report()), + standard: true + }, { label: __('Add to Desktop'), action: () => frappe.add_to_desktop(this.report_name, null, this.report_name), @@ -498,16 +563,26 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { setup_report_wrapper() { if (this.$report) return; + this.$chart = $('
').hide().appendTo(this.page.main); this.$report = $('
').appendTo(this.page.main); - this.$freeze = - $(`
-
${__('Loading')}...
-
`).hide().appendTo(this.page.main); + this.$message = $(this.message_div(__('Loading') + '...')).hide().appendTo(this.page.main); } - toggle_freeze(flag) { - this.$freeze.toggle(flag); + message_div(message) { + return `
+
${message}
+
`; + } + + toggle_message(flag, message) { + if (flag) { + this.$message.find('div').html(message); + this.$message.show(); + } else { + this.$message.hide(); + } this.$report.toggle(!flag); + this.$chart.toggle(!flag); } get data() { diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index d807c018f1..5ab9ccd4cd 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -151,7 +151,7 @@ def has_gravatar(email): return '' def get_gravatar_url(email): - return "https://secure.gravatar.com/avatar/{hash}?d=mm&s=200".format(hash=hashlib.md5(email).hexdigest()) + return "https://secure.gravatar.com/avatar/{hash}?d=mm&s=200".format(hash=hashlib.md5(email.encode('utf-8')).hexdigest()) def get_gravatar(email): gravatar_url = has_gravatar(email) diff --git a/yarn.lock b/yarn.lock index c58c67dbfe..cf73ac5dd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -612,7 +612,7 @@ forwarded@~0.1.2: frappe-datatable@frappe/datatable: version "0.0.2" - resolved "https://codeload.github.com/frappe/datatable/tar.gz/99701f2477b3fb8180ccafaf2c2746886b13ba53" + resolved "https://codeload.github.com/frappe/datatable/tar.gz/470ab90fef56727e860c94869d251aafaaca743e" dependencies: clusterize.js "^0.18.0" sortablejs "^1.7.0"