From be961d8d4e5eeae275e26ef44358db4950084b71 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Sun, 13 Aug 2023 13:40:04 -0400 Subject: [PATCH] Fix #262 - more declarative method for defining navigation sections that is disabled by default --- docassemble/AssemblyLine/al_general.py | 49 +++++++++++++++ .../AssemblyLine/data/questions/al_visual.yml | 11 ++++ docassemble/AssemblyLine/test_al_general.py | 61 ++++++++++++++++++- 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/docassemble/AssemblyLine/al_general.py b/docassemble/AssemblyLine/al_general.py index 4980536f..36b5e56c 100644 --- a/docassemble/AssemblyLine/al_general.py +++ b/docassemble/AssemblyLine/al_general.py @@ -1,3 +1,4 @@ +from copy import deepcopy from typing import Dict, List, Literal, Union, Optional from docassemble.base.util import ( Address, @@ -47,6 +48,7 @@ "ALPeopleList", "Applicant", "Applicant", + "get_visible_al_nav_items", "github_modified_date", "has_parsable_pronouns", "HousingAuthority", @@ -1515,3 +1517,50 @@ def parse_custom_pronouns(pronouns: str) -> Dict[str, str]: "s": pronoun_list[1].lower(), "p": pronoun_list[2].lower(), } + +def get_visible_al_nav_items(nav_items: List[Union[str, dict]]) -> List[Union[str, dict]]: + """ + Processes a list of nav items and returns only the ones that are not hidden. + Can be used to control the visible nav items in a more declarative way while keeping + the navigation dynamic. + + Expects a list like this: + + data = [ + {"key": "value", "hidden": True}, + "top level item", + {"key2": [{"subkey": "subvalue", "hidden": False}, {"subkey": "subvalue2", "hidden": True}]}, + ] + + Args: + nav_items: a list of nav items + + Returns: + a list of nav items with hidden items removed + """ + new_list: List[Union[str, dict]] = [] + + for item in nav_items: + # For strings at top level + if isinstance(item, str): + new_list.append(item) + continue + + # For dictionaries at top level + item_copy = deepcopy(item) + if not item_copy.pop("hidden", False): # if not hidden + for key, val in item_copy.items(): + if isinstance(val, list): # if value of a key is a list + new_sublist: List[Union[str, dict]] = [] + for subitem in val: + # Add subitem strings as-is + if isinstance(subitem, str): + new_sublist.append(subitem) + # Add dictionaries if not hidden + elif isinstance(subitem, dict) and not subitem.pop("hidden", False): + new_sublist.append(subitem) + item_copy[key] = new_sublist + new_list.append(item_copy) + continue + + return new_list \ No newline at end of file diff --git a/docassemble/AssemblyLine/data/questions/al_visual.yml b/docassemble/AssemblyLine/data/questions/al_visual.yml index a50b7d2b..a0168239 100644 --- a/docassemble/AssemblyLine/data/questions/al_visual.yml +++ b/docassemble/AssemblyLine/data/questions/al_visual.yml @@ -140,6 +140,17 @@ event: al_start_over code: | command('new_session') --- +code: | + enable_al_nav_sections = False +--- +code: | + al_nav_sections = [] +--- +initial: True +code: | + if enable_al_nav_sections: + nav.set_sections(get_visible_al_nav_items(al_nav_sections)) +--- code: | send_icon = "envelope" --- diff --git a/docassemble/AssemblyLine/test_al_general.py b/docassemble/AssemblyLine/test_al_general.py index 018dd655..68bde400 100644 --- a/docassemble/AssemblyLine/test_al_general.py +++ b/docassemble/AssemblyLine/test_al_general.py @@ -1,5 +1,5 @@ import unittest -from .al_general import ALIndividual, ALAddress +from .al_general import ALIndividual, ALAddress, get_visible_al_nav_items from unittest.mock import Mock from docassemble.base.util import DADict, DAAttributeError @@ -401,6 +401,63 @@ def test_custom_pronouns(self): with self.assertRaises(DAAttributeError): self.individual.pronoun_objective() - +class test_get_visible_al_nav_items(unittest.TestCase): + + def test_case_1(self): + data = [ + "Selecting_Legal_Category", + {"personal_injury": "Gather Evidence", "hidden": False}, + {"divorce": "Collect Financial Documents", "hidden": False}, + {"business_dispute": ["Interview Witnesses", {"subtask": "Document Communication", "hidden": False}]} + ] + expected = [ + "Selecting_Legal_Category", + {"personal_injury": "Gather Evidence"}, + {"divorce": "Collect Financial Documents"}, + {"business_dispute": ["Interview Witnesses", {"subtask": "Document Communication"}]} + ] + self.assertEqual(get_visible_al_nav_items(data), expected) + + def test_case_2(self): + data = [ + "Drafting_Documents", + {"pre_nup": "List Assets"}, + "Finding_Legal_Representative", + {"business_formation": ["Choose Business Type", {"subtask": "Decide Ownership Structure", "hidden": True}]}, + {"real_estate": "Draft Lease Agreement", "hidden": True} + ] + expected = [ + "Drafting_Documents", + {"pre_nup": "List Assets"}, + "Finding_Legal_Representative", + {"business_formation": ["Choose Business Type"]} + ] + self.assertEqual(get_visible_al_nav_items(data), expected) + + def test_case_3(self): + data = [ + "Negotiating_Terms", + "Reviewing_Contracts", + {"estate_planning": ["Draft Will", {"subtask": "Designate Beneficiaries", "hidden": False}, {"subtask": "Determine Power of Attorney", "hidden": False}]} + ] + expected = [ + "Negotiating_Terms", + "Reviewing_Contracts", + {"estate_planning": ["Draft Will", {"subtask": "Designate Beneficiaries"}, {"subtask": "Determine Power of Attorney"}]} + ] + self.assertEqual(get_visible_al_nav_items(data), expected) + + def test_case_4(self): + data = [ + {"employment_law": "Understand Employee Rights", "hidden": False}, + "Preparing_for_Court", + {"criminal_defense": ["Know Your Rights", {"subtask": "Hire Defense Attorney", "hidden": True}]} + ] + expected = [ + {"employment_law": "Understand Employee Rights"}, + "Preparing_for_Court", + {"criminal_defense": ["Know Your Rights"]} + ] + self.assertEqual(get_visible_al_nav_items(data), expected) if __name__ == "__main__": unittest.main()