{# Plan 61/2a — Nav reorganisation. Rationale (kept here, not in the rendered HTML): Old sidebar had 5 groups with three single-item groups (Bots, Security, old Observability) — disclosure chrome with no organisational value. Wave-1 IA audit (A1) called this the second-biggest discoverability gap behind the missing cmd-K palette. New layout (rendered by base.html): Overview (Dashboard, always) Team (Members, Invitations) Machines (Machines, Schedules) ← Schedules with machines Integrations (Bots, Tunnels, Agent tokens) ← machine ↔ outside world Fleets (Fleets) ← fleet mgmt, not membership ── server-admin ── Model routing (single flat item → /admin/llm) ← Plan 61/2b W2 Observability (Logs, Security, Monitoring) ← Security stays visible until W4 merges it into Logs Members see only: Overview, Team (read-only), Machines, Integrations. Server-admins also see: Model routing, Observability. Naming changes (sidebar labels only — routes unchanged): "API Keys" → "Agent tokens" "LLM Keys"/"LLM Gateway" group → "Model routing" (single item, plan 61/2b W2) Page titles flip by Wave 2b agents as they touch each page. #} {% macro nav_item(href, label, icon, active=false) %} {# Dashboard ('/admin') matches the exact path only — otherwise it would "swallow" every /admin/* page and stay highlighted everywhere. `icon` is a lucide icon name (https://lucide.dev/icons). #} {% if href == '/admin' %} {% set is_active = request.url.path == href %} {% else %} {% set is_active = request.url.path == href or request.url.path.startswith(href + '/') %} {% endif %} {{ label }} {% endmacro %} {# Legacy static-header macro, kept for backward compatibility with any template still calling it directly. New sidebars should use `nav_group`. #} {% macro nav_section(label) %}
{{ label }}
{% endmacro %} {# Collapsible nav group. Usage: {% call nav_group('Workspace', 'workspace', ['/admin/fleets', ...]) %} {{ nav_item(...) }} ... {% endcall %} `key` is the localStorage slot id; `active_prefixes` are the hrefs whose active state forces this group open on initial paint (server-side, so the group never flashes closed when you land on a deep link). Per-group keys (vs one JSON blob) keep writes scoped — toggling one group doesn't invalidate the rest. #} {% macro nav_group(label, key, active_prefixes=[]) %} {% set ns = namespace(active=false) %} {% for p in active_prefixes %} {% if request.url.path == p or request.url.path.startswith(p ~ '/') %} {% set ns.active = true %} {% endif %} {% endfor %}
{{ caller() }}
{% endmacro %}