Files
kanbante/app/templates/_header.html
T
Spark d51ef5a970
CI / test (push) Successful in 1m53s
feat(0.24.0): utilisateurs, administration, espaces, paramètres, archives (P2-P4)
- Comptes en base (PBKDF2), rôles, désactivation qui tue la
  session, audit ; secours environnement pour l'opérateur ;
  liaison draco par utilisateur ; page /profile.
- Espaces de travail : connexions, membres, sélection de
  projets ; board/notes/épingles/journal scopés par espace ;
  sélecteur d'espace, badge connexion.
- Panneaux /admin (utilisateurs, connexions, espaces,
  paramètres — l'environnement amorce, le panneau gouverne).
- /archives : archive locale réversible, archivage forge
  confirmé, purge de l'état local, export Markdown, file
  « à archiver ? » avec archivage en lot.
- Correctif session : les comptes membres résolus par la base
  (la session n'est plus limitée à l'opérateur d'environnement).
- 231 tests verts (12 nouveaux au palier 19).
2026-10-21 14:48:30 -04:00

145 lines
7.2 KiB
HTML

{% include "_draco_bar.html" %}
{# ── Cadre applicatif partagé (issue #16, refonte 0.16.0) ─────────
Barre latérale unique pour TOUTES les pages applicatives :
desktop = barre fixe repliable en rail d'icônes (état mémorisé),
mobile = tiroir hors-canvas ouvert par le burger de la topbar.
NE PAS dupliquer ce markup dans les pages.
Page active : `active_nav` (déduite du gabarit dans render()).
Fil d'Ariane : `owner`+`repo` (board) ou `full_name` (projet).
Le wallboard (TV) n'inclut pas ce partiel, volontairement. #}
{% set nav_groups = [
("principal", "Principal", [
("home", "/", "🏠", "Projets"),
("focus", "/focus", "🎯", "Focus"),
("today", "/today", "🌅", "Aujourd'hui"),
("my", "/my", "👤", "Mes issues"),
]),
("rituels", "Rituels", [
("briefing", "/briefing", "📊", "Briefing"),
("standup", "/standup", "🗣️", "Standup"),
("digest", "/digest", "🧠", "Digest"),
]),
("pilotage", "Pilotage", [
("forecast", "/forecast", "🔮", "Prévisions"),
("health", "/health", "🩺", "Santé"),
("rules", "/rules", "⚙️", "Règles"),
("activity", "/activity", "📰", "Activité"),
]),
("outils", "Outils", [
("search", "/search", "🔍", "Recherche"),
("capture", "/capture", "⚡", "Capture"),
("archives", "/archives", "🗄️", "Archives"),
("wall", "/wall", "🖥️", "Wallboard"),
]),
] %}
{% if is_admin %}
{% set nav_groups = nav_groups + [
("admin", "Administration", [
("admin", "/admin", "🛠️", "Vue d'ensemble"),
("admin_connections", "/admin/connections", "🔌", "Connexions"),
("admin_workspaces", "/admin/workspaces", "🧭", "Espaces"),
("admin_settings", "/admin/settings", "🎛️", "Paramètres"),
]),
] %}
{% endif %}
{% set active_group = namespace(key="principal") %}
{% for gkey, group, links in nav_groups %}
{% for key, href, icon, label in links %}
{% if active_nav == key %}{% set active_group.key = gkey %}{% endif %}
{% endfor %}
{% endfor %}
<script>
document.body.classList.add('with-sidebar');
try {
if (localStorage.getItem('kanbante-sidebar') === 'collapsed') {
document.body.classList.add('sidebar-collapsed');
}
/* Accordéon exclusif (0.22.0) : une seule section ouverte.
La section de la page courante prime, sinon celle
mémorisée, sinon « principal ». */
localStorage.removeItem('kanbante-nav-closed');
var openGroup = {{ active_group.key | tojson }};
var stored = localStorage.getItem('kanbante-nav-open');
var groups = ['principal', 'rituels', 'pilotage', 'outils', 'admin'];
if ({{ (active_nav != "") | tojson }}) {
localStorage.setItem('kanbante-nav-open', openGroup);
} else if (stored === '') {
openGroup = '';
} else if (stored !== null && groups.indexOf(stored) >= 0) {
openGroup = stored;
}
groups.forEach(function (k) {
if (k !== openGroup) document.body.classList.add('nav-closed-' + k);
});
} catch (e) { /* stockage indisponible : état par défaut */ }
</script>
<aside class="sidebar" id="sidebar" aria-label="Navigation principale">
<div class="side-head">
<a href="/" class="side-logo" aria-label="Kanbante — accueil">
<span class="logo-mark">📋</span>
<span class="side-label gradient-text">Kanbante</span>
</a>
<button type="button" class="side-search palette-trigger" title="Recherche & commandes (Ctrl+K)" aria-label="Recherche et commandes (Ctrl+K)">🔍</button>
<button type="button" class="side-collapse" id="side-collapse" title="Replier ou déplier le menu" aria-label="Replier ou déplier le menu"><span class="side-collapse-ico">«</span></button>
</div>
{% if current_workspace and user_workspaces and user_workspaces|length > 1 %}
<form method="post" action="/workspace/switch" class="ws-switch">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<span class="ws-dot" style="background: {{ current_workspace.color }}" aria-hidden="true"></span>
<select name="workspace_id" class="ws-select" onchange="this.form.submit()" title="Changer d'espace de travail" aria-label="Espace de travail">
{% for ws in user_workspaces %}
<option value="{{ ws.id }}"{% if ws.id == current_workspace.id %} selected{% endif %}>{{ ws.name }}</option>
{% endfor %}
</select>
</form>
{% endif %}
<nav class="side-nav">
{% for gkey, group, links in nav_groups %}
<div class="side-section" data-group="{{ gkey }}">
<button type="button" class="side-group-btn" data-group-btn="{{ gkey }}" aria-expanded="true">
<span>{{ group }}</span>
<span class="side-chevron" aria-hidden="true">▾</span>
</button>
<div class="side-acc">
<div class="side-acc-inner">
{% for key, href, icon, label in links %}
<a href="{{ href }}" class="side-link{% if active_nav == key %} active{% endif %}" title="{{ label }}">
<span class="side-ico">{{ icon }}</span>
<span class="side-label">{{ label }}</span>
</a>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</nav>
<div class="side-foot">
{% if data_freshness %}
<span class="side-fresh side-label" title="Dernière actualisation des données Gitea (instantanés d'arrière-plan)">🕐 {{ data_freshness }}</span>
{% endif %}
{% if current_user %}
<a href="/profile" class="side-logout" title="Mon profil">👤<span class="side-label"> {{ current_user.display_name or current_user.username }}</span></a>
{% endif %}
<span class="side-version side-label">v{{ version }}</span>
{% if auth_enabled %}
<a href="/logout" class="side-logout" title="Se déconnecter">⏻<span class="side-label"> Sortir</span></a>
{% endif %}
</div>
</aside>
<div class="side-backdrop" id="side-backdrop" hidden></div>
<header class="app-header topbar">
<button type="button" class="nav-burger" id="nav-burger" aria-expanded="false" aria-controls="sidebar" aria-label="Ouvrir le menu">☰</button>
{% if owner is defined and repo is defined %}
<span class="crumb"><a href="/board/{{ owner }}/{{ repo }}">{{ owner }} / <strong>{{ repo }}</strong></a></span>
{% elif full_name is defined %}
<span class="crumb"><a href="/board/{{ full_name }}">{{ full_name }}</a></span>
{% endif %}
<div class="header-actions">
{% if repo_info is defined and repo_info and repo_info.html_url %}
<a href="{{ repo_info.html_url }}" target="_blank" rel="noopener" class="nav-pill" title="Ouvrir ce dépôt dans Gitea">🔗 Gitea ↗</a>
{% endif %}
<button type="button" class="nav-pill palette-trigger topbar-search" title="Recherche et commandes (Ctrl+K)">🔍</button>
</div>
<script src="/static/js/nav.js" defer></script>
</header>