225 lines
6.6 KiB
Python
225 lines
6.6 KiB
Python
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
|