From 6babd025423719e5d5a5e17ef43489fad51ce57a Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 4 Dec 2023 13:07:35 +0530 Subject: [PATCH 1/6] feat: add include disabled check --- frappe/public/js/frappe/views/treeview.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frappe/public/js/frappe/views/treeview.js b/frappe/public/js/frappe/views/treeview.js index 22810e8e35..0096a333bd 100644 --- a/frappe/public/js/frappe/views/treeview.js +++ b/frappe/public/js/frappe/views/treeview.js @@ -106,6 +106,17 @@ frappe.views.TreeView = class TreeView { $(this.page[0]).addClass("frappe-card"); } + if (frappe.meta.has_field(me.doctype, "disabled")) { + $( + "
" + ).appendTo(this.page.inner_toolbar); + this.page.inner_toolbar + .addClass("flex align-center") + .on("click", "input[type='checkbox']", function () { + me.rebuild_tree(); + }); + } + if (this.opts.show_expand_all) { this.page.add_inner_button(__("Collapse All"), function () { me.tree.load_children(me.tree.root_node, false); @@ -189,6 +200,9 @@ frappe.views.TreeView = class TreeView { if (use_value == null) { use_value = use_label; } + this.args["include_disabled"] = this.page.inner_toolbar + .find("input[type='checkbox']") + .prop("checked"); this.tree = new frappe.ui.Tree({ parent: this.body, label: use_label, From f8d4014a0024d27137034a9ca65d432ef2b72ed3 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 4 Dec 2023 13:08:33 +0530 Subject: [PATCH 2/6] feat: add disabled filter in get_children --- frappe/desk/treeview.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index f8b2a67c82..9bc195fa9b 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -37,13 +37,15 @@ def get_all_nodes(doctype, label, parent, tree_method, **filters): @frappe.whitelist() -def get_children(doctype, parent="", **filters): - return _get_children(doctype, parent) +def get_children(doctype, parent="", include_disabled=False, **filters): + return _get_children(doctype, parent, include_disabled) -def _get_children(doctype, parent="", ignore_permissions=False): +def _get_children(doctype, include_disabled, parent="", ignore_permissions=False): parent_field = "parent_" + doctype.lower().replace(" ", "_") filters = [[f"ifnull(`{parent_field}`,'')", "=", parent], ["docstatus", "<", 2]] + if frappe.db.has_column(doctype, "disabled") and not include_disabled: + filters.append(["disabled", "=", False]) meta = frappe.get_meta(doctype) From 76a200028ed25fec99e7f28ca81673015e0a4150 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 4 Dec 2023 19:00:24 +0530 Subject: [PATCH 3/6] fix: make internal parameter optional --- frappe/desk/treeview.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index 9bc195fa9b..4a77c6560b 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -38,10 +38,12 @@ def get_all_nodes(doctype, label, parent, tree_method, **filters): @frappe.whitelist() def get_children(doctype, parent="", include_disabled=False, **filters): - return _get_children(doctype, parent, include_disabled) + if isinstance(include_disabled, str): + include_disabled = bool(include_disabled) + return _get_children(doctype, parent, include_disabled=include_disabled) -def _get_children(doctype, include_disabled, parent="", ignore_permissions=False): +def _get_children(doctype, parent="", ignore_permissions=False, include_disabled=False): parent_field = "parent_" + doctype.lower().replace(" ", "_") filters = [[f"ifnull(`{parent_field}`,'')", "=", parent], ["docstatus", "<", 2]] if frappe.db.has_column(doctype, "disabled") and not include_disabled: From 796e958910724dafe904827c13b1029d5f3c5a03 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 15 Dec 2023 15:00:36 +0530 Subject: [PATCH 4/6] test: treeview for disabled records --- frappe/tests/test_nestedset.py | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/frappe/tests/test_nestedset.py b/frappe/tests/test_nestedset.py index 340b53bf38..53304a5bb3 100644 --- a/frappe/tests/test_nestedset.py +++ b/frappe/tests/test_nestedset.py @@ -5,6 +5,7 @@ from unittest.mock import patch import frappe from frappe.core.doctype.doctype.test_doctype import new_doctype +from frappe.desk.treeview import get_children from frappe.query_builder import Field from frappe.query_builder.functions import Max from frappe.tests.utils import FrappeTestCase @@ -296,3 +297,43 @@ class TestNestedSet(FrappeTestCase): self.assertNotIn(record, str(frappe.qb.get_query(table=linked_doctype, filters=exclusive_link))) self.assertIn(record, str(frappe.qb.get_query(table=linked_doctype, filters=inclusive_link))) + + def test_disabled_records_in_treeview(self): + """ + Tests the `get_children` util for showing / skipping disabled records in treeview + """ + doctype = ( + new_doctype( + fields=[ + { + "label": "Some Field", + "fieldname": "some_fieldname", + "fieldtype": "Data", + }, + { + "label": "Disabled", + "fieldname": "disabled", + "fieldtype": "Check", + }, + ], + is_tree=True, + autoname="field:some_fieldname", + ) + .insert() + .name + ) + + for record in [ + {"some_fieldname": "Root", "disabled": 0, "is_group": 1}, + {"some_fieldname": "Sub Tree 1", "disabled": 1, "parent_" + doctype: "Root", "is_group": 0}, + ]: + d = frappe.new_doc(doctype) + d.update(record) + d.insert() + + # Check if all records are fetched when flag is set to True + self.assertEqual(len(get_children(doctype, include_disabled=True)), 2) + + # Check if disabled records are skipped is set to False + # Children of disabled records are automatically skipped in recursion + self.assertEqual(len(get_children(doctype)), 1) From a15b1dee9582dcaba361529ec99efed4cd425b40 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Thu, 21 Dec 2023 18:30:16 +0530 Subject: [PATCH 5/6] fix: correctly typecast disabled flag --- frappe/desk/treeview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index 4a77c6560b..77f86e2662 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -39,7 +39,7 @@ def get_all_nodes(doctype, label, parent, tree_method, **filters): @frappe.whitelist() def get_children(doctype, parent="", include_disabled=False, **filters): if isinstance(include_disabled, str): - include_disabled = bool(include_disabled) + include_disabled = frappe.json.loads(include_disabled) return _get_children(doctype, parent, include_disabled=include_disabled) From 0fadb6d9fc925a904819315d0ccebcd67d57b576 Mon Sep 17 00:00:00 2001 From: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com> Date: Wed, 27 Dec 2023 18:40:44 +0530 Subject: [PATCH 6/6] fix: use sbool for better typecasting Co-authored-by: Akhil Narang --- frappe/desk/treeview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index 77f86e2662..77a8454849 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -39,7 +39,7 @@ def get_all_nodes(doctype, label, parent, tree_method, **filters): @frappe.whitelist() def get_children(doctype, parent="", include_disabled=False, **filters): if isinstance(include_disabled, str): - include_disabled = frappe.json.loads(include_disabled) + include_disabled = frappe.sbool(include_disabled) return _get_children(doctype, parent, include_disabled=include_disabled)