From d171a6d30aafdce594e6971ae3df1c5f12aca684 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sat, 15 Jul 2023 12:29:46 +0530 Subject: [PATCH 1/4] perf: lazy load sidebar stats Sidebar stats take a huge time to load on large tables and it's not required everytime you load the page. Best to only trigger it when user clicks on "tags" (or other stats filter) This is exactly how assignment and other filters work, so no need for sidebar stats to work differently. --- frappe/public/js/frappe/list/list_view.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 68030223ca..81a74c0af5 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -587,9 +587,6 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { `); this.setup_new_doc_event(); - if (this.list_view_settings && !this.list_view_settings.disable_sidebar_stats) { - this.list_sidebar && this.list_sidebar.reload_stats(); - } this.toggle_paging && this.$paging_area.toggle(true); } From 5841f296107680cfc1877d912ea90fa5902ebdf4 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sat, 15 Jul 2023 12:34:49 +0530 Subject: [PATCH 2/4] refactor: rename poorly named variables stats are actually columns in DB columns are for verifying if DB column exists hence db_columns other stats was result. Renamed everything to avoid confusion. --- frappe/desk/reportview.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 071b6e7e61..c6252250fb 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -525,47 +525,47 @@ def get_stats(stats, doctype, filters=None): if filters is None: filters = [] - tags = json.loads(stats) + columns = json.loads(stats) if filters: filters = json.loads(filters) - stats = {} + results = {} try: - columns = frappe.db.get_table_columns(doctype) + db_columns = frappe.db.get_table_columns(doctype) except (frappe.db.InternalError, frappe.db.ProgrammingError): # raised when _user_tags column is added on the fly # raised if its a virtual doctype - columns = [] + db_columns = [] - for tag in tags: - if tag not in columns: + for column in columns: + if column not in db_columns: continue try: tag_count = frappe.get_list( doctype, - fields=[tag, "count(*)"], - filters=filters + [[tag, "!=", ""]], - group_by=tag, + fields=[column, "count(*)"], + filters=filters + [[column, "!=", ""]], + group_by=column, as_list=True, distinct=1, ) - if tag == "_user_tags": - stats[tag] = scrub_user_tags(tag_count) + if column == "_user_tags": + results[column] = scrub_user_tags(tag_count) no_tag_count = frappe.get_list( doctype, - fields=[tag, "count(*)"], - filters=filters + [[tag, "in", ("", ",")]], + fields=[column, "count(*)"], + filters=filters + [[column, "in", ("", ",")]], as_list=True, - group_by=tag, - order_by=tag, + group_by=column, + order_by=column, ) no_tag_count = no_tag_count[0][1] if no_tag_count else 0 - stats[tag].append([_("No Tags"), no_tag_count]) + results[column].append([_("No Tags"), no_tag_count]) else: - stats[tag] = tag_count + results[column] = tag_count except frappe.db.SQLError: pass @@ -573,7 +573,7 @@ def get_stats(stats, doctype, filters=None): # raised when _user_tags column is added on the fly pass - return stats + return results @frappe.whitelist() From 9a9705bd1132dd0e37f87f5e68d0d5681f04af97 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sat, 15 Jul 2023 12:54:08 +0530 Subject: [PATCH 3/4] fix(UX): Show loading state while loading tags --- frappe/public/js/frappe/list/list_sidebar.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frappe/public/js/frappe/list/list_sidebar.js b/frappe/public/js/frappe/list/list_sidebar.js index fb17b17268..debf7a6766 100644 --- a/frappe/public/js/frappe/list/list_sidebar.js +++ b/frappe/public/js/frappe/list/list_sidebar.js @@ -187,6 +187,10 @@ frappe.views.ListSidebar = class ListSidebar { get_stats() { var me = this; + + let dropdown_options = me.sidebar.find(".list-stats-dropdown .stat-result"); + this.set_loading_state(dropdown_options); + frappe.call({ method: "frappe.desk.reportview.get_sidebar_stats", type: "GET", @@ -208,6 +212,14 @@ frappe.views.ListSidebar = class ListSidebar { }); } + set_loading_state(dropdown) { + dropdown.html(`
  • +
    + ${__("Loading...")} +
    +
  • `); + } + render_stat(stats) { let args = { stats: stats, From b2b0bb69bb442f890547173e8727362db2a149d8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sat, 15 Jul 2023 13:14:04 +0530 Subject: [PATCH 4/4] fix: Correct event for sidebar dropdown - Click only gets called first time and not reliable next times - Click will also get called when it's used for collapsing dropdown, which doesn't make sense here. --- frappe/public/js/frappe/list/list_sidebar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/list_sidebar.js b/frappe/public/js/frappe/list/list_sidebar.js index debf7a6766..9c395972a7 100644 --- a/frappe/public/js/frappe/list/list_sidebar.js +++ b/frappe/public/js/frappe/list/list_sidebar.js @@ -34,7 +34,7 @@ frappe.views.ListSidebar = class ListSidebar { ) { this.sidebar.find(".list-tags").remove(); } else { - this.sidebar.find(".list-stats").on("click", (e) => { + this.sidebar.find(".list-stats").on("show.bs.dropdown", (e) => { this.reload_stats(); }); }