diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py index 4c54d1be4a..ccb681804f 100644 --- a/frappe/desk/form/linked_with.py +++ b/frappe/desk/form/linked_with.py @@ -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 diff --git a/frappe/public/js/frappe/form/linked_with.js b/frappe/public/js/frappe/form/linked_with.js index 12c5dc4f6b..2aaa3dcb95 100644 --- a/frappe/public/js/frappe/form/linked_with.js +++ b/frappe/public/js/frappe/form/linked_with.js @@ -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 ` -