Merge pull request #23623 from barredterra/bulk-submit-cancel

feat: scoped progress bar on bulk submit/cancel
This commit is contained in:
Ankush Menat 2023-12-06 18:35:24 +05:30 committed by GitHub
commit bbeeebbbbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 30 deletions

View file

@ -6,6 +6,7 @@ from frappe import _
from frappe.core.doctype.submission_queue.submission_queue import queue_submission
from frappe.model.document import Document
from frappe.utils import cint
from frappe.utils.deprecations import deprecated
from frappe.utils.scheduler import is_scheduler_inactive
@ -24,6 +25,7 @@ class BulkUpdate(Document):
limit: DF.Int
update_value: DF.SmallText
# end: auto-generated types
@frappe.whitelist()
def bulk_update(self):
self.check_permission("write")
@ -45,12 +47,12 @@ class BulkUpdate(Document):
@frappe.whitelist()
def submit_cancel_or_update_docs(doctype, docnames, action="submit", data=None):
def submit_cancel_or_update_docs(doctype, docnames, action="submit", data=None, task_id=None):
if isinstance(docnames, str):
docnames = frappe.parse_json(docnames)
if len(docnames) < 20:
return _bulk_action(doctype, docnames, action, data)
return _bulk_action(doctype, docnames, action, data, task_id)
elif len(docnames) <= 500:
frappe.msgprint(_("Bulk operation is enqueued in background."), alert=True)
frappe.enqueue(
@ -59,6 +61,7 @@ def submit_cancel_or_update_docs(doctype, docnames, action="submit", data=None):
docnames=docnames,
action=action,
data=data,
task_id=task_id,
queue="short",
timeout=1000,
)
@ -68,14 +71,15 @@ def submit_cancel_or_update_docs(doctype, docnames, action="submit", data=None):
)
def _bulk_action(doctype, docnames, action, data):
def _bulk_action(doctype, docnames, action, data, task_id=None):
if data:
data = frappe.parse_json(data)
failed = []
num_documents = len(docnames)
for i, d in enumerate(docnames, 1):
doc = frappe.get_doc(doctype, d)
for idx, docname in enumerate(docnames, 1):
doc = frappe.get_doc(doctype, docname)
try:
message = ""
if action == "submit" and doc.docstatus.is_draft():
@ -93,17 +97,23 @@ def _bulk_action(doctype, docnames, action, data):
doc.save()
message = _("Updating {0}").format(doctype)
else:
failed.append(d)
failed.append(docname)
frappe.db.commit()
show_progress(docnames, message, i, d)
frappe.publish_progress(
percent=idx / num_documents * 100,
title=message,
description=docname,
task_id=task_id,
)
except Exception:
failed.append(d)
failed.append(docname)
frappe.db.rollback()
return failed
@deprecated
def show_progress(docnames, message, i, description):
n = len(docnames)
frappe.publish_progress(float(i) * 100 / n, title=message, description=description)

View file

@ -209,28 +209,36 @@ export default class BulkOperations {
submit_or_cancel(docnames, action = "submit", done = null) {
action = action.toLowerCase();
frappe
.call({
method: "frappe.desk.doctype.bulk_update.bulk_update.submit_cancel_or_update_docs",
args: {
doctype: this.doctype,
action: action,
docnames: docnames,
},
const task_id = Math.random().toString(36).slice(-5);
frappe.realtime.task_subscribe(task_id);
return frappe
.xcall("frappe.desk.doctype.bulk_update.bulk_update.submit_cancel_or_update_docs", {
doctype: this.doctype,
action: action,
docnames: docnames,
task_id: task_id,
})
.then((r) => {
let failed = r.message;
if (!failed) failed = [];
if (failed.length && !r._server_messages) {
frappe.throw(
__("Cannot {0} {1}", [action, failed.map((f) => f.bold()).join(", ")])
);
.then((failed_docnames) => {
if (failed_docnames?.length) {
const comma_separated_records = frappe.utils.comma_and(failed_docnames);
switch (action) {
case "submit":
frappe.throw(__("Cannot submit {0}.", [comma_separated_records]));
break;
case "cancel":
frappe.throw(__("Cannot cancel {0}.", [comma_separated_records]));
break;
default:
frappe.throw(__("Cannot {0} {1}.", [action, comma_separated_records]));
}
}
if (failed.length < docnames.length) {
if (failed_docnames?.length < docnames.length) {
frappe.utils.play_sound(action);
if (done) done();
}
})
.finally(() => {
frappe.realtime.task_unsubscribe(task_id);
});
}

View file

@ -9,13 +9,16 @@ import frappe
from frappe.utils.data import cstr
def publish_progress(percent, title=None, doctype=None, docname=None, description=None):
def publish_progress(
percent, title=None, doctype=None, docname=None, description=None, task_id=None
):
publish_realtime(
"progress",
{"percent": percent, "title": title, "description": description},
user=None if doctype and docname else frappe.session.user,
doctype=doctype,
docname=docname,
task_id=task_id,
)
@ -41,8 +44,11 @@ def publish_realtime(
if message is None:
message = {}
if not task_id and hasattr(frappe.local, "task_id"):
task_id = frappe.local.task_id
if event is None:
event = "task_progress" if frappe.local.task_id else "global"
event = "task_progress" if task_id else "global"
elif event == "msgprint" and not user:
user = frappe.session.user
elif event == "list_update":
@ -51,9 +57,6 @@ def publish_realtime(
elif event == "docinfo_update":
room = get_doc_room(doctype, docname)
if not task_id and hasattr(frappe.local, "task_id"):
task_id = frappe.local.task_id
if not room:
if task_id:
after_commit = False