refactor: linked documents retrieval and UX
This commit is contained in:
parent
e86df0f9cc
commit
0cdeee51ab
3 changed files with 105 additions and 52 deletions
|
|
@ -437,37 +437,19 @@ def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> di
|
|||
is_target_doctype_table = frappe.get_meta(doctype).istable
|
||||
|
||||
for linked_doctype, link_context in linkinfo.items():
|
||||
# Don't try to fetch linked documents if the user can't read the doctype
|
||||
if not frappe.has_permission(linked_doctype):
|
||||
continue
|
||||
|
||||
linked_doctype_meta = frappe.get_meta(linked_doctype)
|
||||
|
||||
if linked_doctype_meta.issingle:
|
||||
continue
|
||||
|
||||
has_permission = frappe.has_permission(linked_doctype)
|
||||
filters = []
|
||||
or_filters = []
|
||||
ret = None
|
||||
parent_info = None
|
||||
|
||||
fields = [
|
||||
d.fieldname
|
||||
for d in linked_doctype_meta.get(
|
||||
"fields",
|
||||
{
|
||||
"in_list_view": 1,
|
||||
"fieldtype": ["not in", ("Image", "HTML", "Button", *frappe.model.table_fields)],
|
||||
},
|
||||
)
|
||||
] + ["name", "modified", "docstatus"]
|
||||
|
||||
if add_fields := link_context.get("add_fields"):
|
||||
fields += add_fields
|
||||
|
||||
fields = [sf.strip() for sf in fields if sf]
|
||||
|
||||
if filters_ctx := link_context.get("filters"):
|
||||
ret = frappe.get_list(doctype=linked_doctype, fields=fields, filters=filters_ctx, order_by=None)
|
||||
filters = filters_ctx
|
||||
|
||||
elif link_context.get("get_parent"):
|
||||
# check for child table
|
||||
|
|
@ -478,13 +460,10 @@ def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> di
|
|||
doctype, name, ["parenttype", "parent"], as_dict=True, order_by=None
|
||||
)
|
||||
|
||||
if parent_info and parent_info.parenttype == linked_doctype:
|
||||
ret = frappe.get_list(
|
||||
doctype=linked_doctype,
|
||||
fields=fields,
|
||||
filters=[[linked_doctype, "name", "=", parent_info.parent]],
|
||||
order_by=None,
|
||||
)
|
||||
if not (parent_info and parent_info.parenttype == linked_doctype):
|
||||
continue
|
||||
|
||||
filters = [[linked_doctype, "name", "=", parent_info.parent]]
|
||||
|
||||
elif child_doctype := link_context.get("child_doctype"):
|
||||
or_filters = [
|
||||
|
|
@ -495,15 +474,6 @@ def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> di
|
|||
if doctype_fieldname := link_context.get("doctype_fieldname"):
|
||||
filters.append([child_doctype, doctype_fieldname, "=", doctype])
|
||||
|
||||
ret = frappe.get_list(
|
||||
doctype=linked_doctype,
|
||||
fields=fields,
|
||||
filters=filters,
|
||||
or_filters=or_filters,
|
||||
distinct=True,
|
||||
order_by=None,
|
||||
)
|
||||
|
||||
elif link_fieldnames := link_context.get("fieldname"):
|
||||
if isinstance(link_fieldnames, str):
|
||||
link_fieldnames = [link_fieldnames]
|
||||
|
|
@ -518,12 +488,51 @@ def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> di
|
|||
or frappe.db.exists(linked_doctype, {"parenttype": doctype, "parent": name})
|
||||
):
|
||||
continue
|
||||
|
||||
total_count = len(
|
||||
frappe.get_all(
|
||||
linked_doctype,
|
||||
filters=filters,
|
||||
or_filters=or_filters,
|
||||
fields=["name"],
|
||||
order_by=None,
|
||||
)
|
||||
)
|
||||
|
||||
if not total_count:
|
||||
continue
|
||||
|
||||
if has_permission:
|
||||
fields = [
|
||||
d.fieldname
|
||||
for d in linked_doctype_meta.get(
|
||||
"fields",
|
||||
{
|
||||
"in_list_view": 1,
|
||||
"fieldtype": ["not in", ("Image", "HTML", "Button", *frappe.model.table_fields)],
|
||||
},
|
||||
)
|
||||
] + ["name", "modified", "docstatus"]
|
||||
|
||||
if add_fields := link_context.get("add_fields"):
|
||||
fields += add_fields
|
||||
|
||||
fields = [sf.strip() for sf in fields if sf]
|
||||
|
||||
ret = frappe.get_list(
|
||||
doctype=linked_doctype, fields=fields, filters=filters, or_filters=or_filters, order_by=None
|
||||
doctype=linked_doctype,
|
||||
fields=fields,
|
||||
filters=filters,
|
||||
or_filters=or_filters,
|
||||
distinct=True,
|
||||
order_by=None,
|
||||
)
|
||||
|
||||
if ret:
|
||||
results[linked_doctype] = ret
|
||||
permitted_count = len(ret or [])
|
||||
results[linked_doctype] = {
|
||||
"docs": ret or [],
|
||||
"hidden_count": total_count - permitted_count,
|
||||
}
|
||||
|
||||
return results
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ frappe.ui.form.LinkedWith = class LinkedWith {
|
|||
|
||||
make_dialog() {
|
||||
this.dialog = new frappe.ui.Dialog({
|
||||
title: __("Linked With"),
|
||||
title: __("Links"),
|
||||
minimizable: true,
|
||||
});
|
||||
|
||||
this.dialog.on_page_show = () => {
|
||||
|
|
@ -39,22 +40,34 @@ frappe.ui.form.LinkedWith = class LinkedWith {
|
|||
make_html() {
|
||||
let html = "";
|
||||
const linked_docs = this.frm.__linked_docs;
|
||||
const linked_doctypes = Object.keys(linked_docs);
|
||||
const linked_doctypes = Object.keys(linked_docs).filter((dt) => {
|
||||
const entry = linked_docs[dt];
|
||||
return (entry.docs && entry.docs.length) || entry.hidden_count > 0;
|
||||
});
|
||||
|
||||
if (linked_doctypes.length === 0) {
|
||||
html = __("Not Linked to any record");
|
||||
} else {
|
||||
html = linked_doctypes
|
||||
.map((doctype) => {
|
||||
const docs = linked_docs[doctype];
|
||||
return `
|
||||
<div class="list-item-table margin-bottom">
|
||||
${this.make_doc_head(doctype)}
|
||||
${docs.map((doc) => this.make_doc_row(doc, doctype)).join("")}
|
||||
html = `
|
||||
<div class="margin-bottom">
|
||||
${__("Following documents are linked to {0}", [frappe.utils.get_form_link(this.frm.doctype, this.frm.docname, true).bold()])}
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.join("");
|
||||
${linked_doctypes
|
||||
.map((doctype) => {
|
||||
const { docs, hidden_count } = linked_docs[doctype];
|
||||
let rows = (docs || []).map((doc) => this.make_doc_row(doc, doctype)).join("");
|
||||
if (hidden_count > 0) {
|
||||
rows += this.make_hidden_count_row(hidden_count);
|
||||
}
|
||||
return `
|
||||
<div class="list-item-table margin-bottom">
|
||||
${this.make_doc_head(doctype)}
|
||||
${rows}
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.join("")}
|
||||
`;
|
||||
}
|
||||
|
||||
$(this.dialog.body).html(html);
|
||||
|
|
@ -68,6 +81,16 @@ frappe.ui.form.LinkedWith = class LinkedWith {
|
|||
`;
|
||||
}
|
||||
|
||||
make_hidden_count_row(count) {
|
||||
return `<div class="list-row-container">
|
||||
<div class="level list-row small text-muted">
|
||||
<div class="level-left">
|
||||
${count == 1 ? __("{0} restricted document", [count]) : __("{0} restricted documents", [count])}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
make_doc_row(doc, doctype) {
|
||||
return `<div class="list-row-container">
|
||||
<div class="level list-row small">
|
||||
|
|
|
|||
|
|
@ -371,6 +371,27 @@ input.list-header-checkbox {
|
|||
.list-item-table {
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 3px;
|
||||
|
||||
.list-row-head {
|
||||
border-radius: unset;
|
||||
}
|
||||
|
||||
.list-row-container {
|
||||
border-bottom: 1px solid $border-color;
|
||||
border-radius: unset;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.list-row-container:hover {
|
||||
border-radius: unset;
|
||||
}
|
||||
|
||||
.list-row-container .list-row {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue