Merge pull request #23623 from barredterra/bulk-submit-cancel
feat: scoped progress bar on bulk submit/cancel
This commit is contained in:
commit
bbeeebbbbb
3 changed files with 51 additions and 30 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue