Merge pull request #37440 from TITANiumRox/fix-linked-with-dialog

This commit is contained in:
Suraj Shetty 2026-02-26 15:19:35 +05:30 committed by GitHub
commit cfcdf0c2aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 111 additions and 52 deletions

View file

@ -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

View file

@ -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,40 @@ 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 with {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 +87,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">

View file

@ -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 {