diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 4625f0aa8e..6716999dcb 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1320,6 +1320,11 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { } setup_realtime_updates() { + this.pending_document_refreshes = []; + setInterval(() => { + this.process_document_refreshes(); + }, 1000); + if (this.list_view_settings && this.list_view_settings.disable_auto_refresh) { return; } @@ -1333,28 +1338,42 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { return; } - const { doctype, name } = data; - if (doctype !== this.doctype) return; + this.pending_document_refreshes.push(data); + }); + } - // filters to get only the doc with this name - const call_args = this.get_call_args(); - call_args.args.filters.push([this.doctype, "name", "=", name]); - call_args.args.start = 0; + process_document_refreshes() { + if (!this.pending_document_refreshes.length) return; - frappe.call(call_args).then(({ message }) => { - if (!message) return; - const data = frappe.utils.dict(message.keys, message.values); - if (!(data && data.length)) { - // this doc was changed and should not be visible - // in the listview according to filters applied - // let's remove it manually - this.data = this.data.filter((d) => d.name !== name); - this.render_list(); - return; - } + const names = this.pending_document_refreshes + .filter((d) => d.doctype === this.doctype) + .map((d) => d.name); + this.pending_document_refreshes = this.pending_document_refreshes.filter( + (d) => names.indexOf(d.name) === -1 + ); - const datum = data[0]; - const index = this.data.findIndex((d) => d.name === datum.name); + if (!names.length) return; + + // filters to get only the doc with this name + const call_args = this.get_call_args(); + call_args.args.filters.push([this.doctype, "name", "in", names]); + call_args.args.start = 0; + + frappe.call(call_args).then(({ message }) => { + if (!message) return; + const data = frappe.utils.dict(message.keys, message.values); + + if (!(data && data.length)) { + // this doc was changed and should not be visible + // in the listview according to filters applied + // let's remove it manually + this.data = this.data.filter((d) => names.indexOf(d.name) === -1); + this.render_list(); + return; + } + + data.forEach((datum) => { + const index = this.data.findIndex((doc) => doc.name === datum.name); if (index === -1) { // append new data @@ -1363,31 +1382,31 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { // update this data in place this.data[index] = datum; } - - this.data.sort((a, b) => { - const a_value = a[this.sort_by] || ""; - const b_value = b[this.sort_by] || ""; - - let return_value = 0; - if (a_value > b_value) { - return_value = 1; - } - - if (b_value > a_value) { - return_value = -1; - } - - if (this.sort_order === "desc") { - return_value = -return_value; - } - return return_value; - }); - this.toggle_result_area(); - this.render_list(); - if (this.$checks && this.$checks.length) { - this.set_rows_as_checked(); - } }); + + this.data.sort((a, b) => { + const a_value = a[this.sort_by] || ""; + const b_value = b[this.sort_by] || ""; + + let return_value = 0; + if (a_value > b_value) { + return_value = 1; + } + + if (b_value > a_value) { + return_value = -1; + } + + if (this.sort_order === "desc") { + return_value = -return_value; + } + return return_value; + }); + if (this.$checks && this.$checks.length) { + this.set_rows_as_checked(); + } + this.toggle_result_area(); + this.render_list(); }); }