from __future__ import annotations from django.urls import reverse SETTINGS_NAVIGATION_TREE = ( { "key": "general", "label": "General", "href_name": "notifications_settings", "children": ( { "key": "notifications", "label": "Notifications", "href_name": "notifications_settings", "route_names": ("notifications_settings", "notifications_update"), }, { "key": "system", "label": "System", "href_name": "system_settings", "route_names": ("system_settings",), }, { "key": "accessibility", "label": "Accessibility", "href_name": "accessibility_settings", "route_names": ("accessibility_settings",), }, ), }, { "key": "security", "label": "Security", "href_name": "encryption_settings", "children": ( { "key": "encryption", "label": "Encryption", "href_name": "encryption_settings", "route_names": ("security_settings", "encryption_settings"), }, { "key": "permissions", "label": "Permissions", "href_name": "permission_settings", "route_names": ("permission_settings",), }, { "key": "security_2fa", "label": "2FA", "href_name": "security_2fa", "route_names": ( "security_2fa", "profile", "setup", "backup_tokens", "disable", "phone_create", "phone_delete", ), }, ), }, { "key": "ai", "label": "AI", "href_name": "ai_models", "children": ( { "key": "ai_models", "label": "Models", "href_name": "ai_models", "route_names": ( "ai_settings", "ai_models", "ais", "ai_create", "ai_update", "ai_delete", ), }, { "key": "ai_traces", "label": "Traces", "href_name": "ai_execution_log", "route_names": ( "ai_execution_log", "ai_execution_run_detail", "ai_execution_run_detail_tab", ), }, ), }, { "key": "modules", "label": "Modules", "href_name": "command_routing", "children": ( { "key": "command_routing", "label": "Commands", "href_name": "command_routing", "route_names": ("modules_settings", "command_routing"), }, { "key": "business_plans", "label": "Business Plans", "href_name": "business_plan_inbox", "route_names": ("business_plan_inbox", "business_plan_editor"), }, { "key": "tasks", "label": "Task Automation", "href_name": "tasks_settings", "route_names": ("tasks_settings",), }, { "key": "translation", "label": "Translation", "href_name": "translation_settings", "route_names": ("translation_settings", "translation_preview"), }, { "key": "behavioral", "label": "Behavioral Signals", "href_name": "behavioral_signals_settings", "route_names": ( "availability_settings", "behavioral_signals_settings", ), }, ), }, ) def _route_names_for_node(node: dict) -> set[str]: route_names = { str(value).strip() for value in tuple(node.get("route_names") or ()) if str(value).strip() } for child in tuple(node.get("children") or ()): route_names.update(_route_names_for_node(child)) return route_names def _tab(label: str, href_name: str, active: bool) -> dict: return { "label": str(label or "").strip(), "href": reverse(href_name), "active": bool(active), } def _find_active_path(nodes, url_name: str) -> list[dict]: for node in tuple(nodes or ()): node_routes = _route_names_for_node(node) if url_name in node_routes: child_path = _find_active_path(node.get("children") or (), url_name) return [node, *child_path] return [] def build_settings_navigation(url_name: str) -> dict | None: current_route = str(url_name or "").strip() if not current_route: return None active_path = _find_active_path(SETTINGS_NAVIGATION_TREE, current_route) if not active_path: return None active_group = active_path[0] navigation = { "title": str(active_group.get("label") or "Settings"), "groups": [ _tab( group.get("label") or "", group.get("href_name") or "", bool(group.get("key")) == bool(active_group.get("key")) and str(group.get("key") or "") == str(active_group.get("key") or ""), ) for group in SETTINGS_NAVIGATION_TREE ], "tabs": [], "rows": [], } nodes = tuple(active_group.get("children") or ()) depth = 1 while nodes: active_key = "" if depth < len(active_path): active_key = str(active_path[depth].get("key") or "") tabs = [ _tab( node.get("label") or "", node.get("href_name") or "", str(node.get("key") or "") == active_key, ) for node in nodes ] navigation["rows"].append( { "depth": depth, "tabs": tabs, } ) if depth == 1: navigation["tabs"] = tabs current = next( ( node for node in nodes if str(node.get("key") or "") == active_key ), None, ) nodes = tuple((current or {}).get("children") or ()) depth += 1 return navigation