CI / test (push) Successful in 1m53s
- 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).
140 lines
8.3 KiB
HTML
140 lines
8.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr" data-theme="dark">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="csrf-token" content="{{ csrf_token }}">
|
|
<title>Archives — Kanbante</title>
|
|
<link rel="stylesheet" href="/static/css/style.css?v={{ version }}">
|
|
</head>
|
|
<body>
|
|
{% include "_header.html" %}
|
|
|
|
<main class="focus-main">
|
|
<div class="page-head">
|
|
<h1>🗄️ Archives</h1>
|
|
<p class="page-sub">Espace : <strong>{{ workspace.name if workspace else '—' }}</strong>. Deux sortes d'archives : <strong>locale</strong> (le projet disparaît des vues de cet espace, la forge n'est pas touchée, réversible en un clic) et <strong>sur la forge</strong> (propriété du dépôt, lecture seule là-bas). Les archives sortent des rituels et des instantanés, mais restent cherchables.</p>
|
|
</div>
|
|
{% if msg %}<p class="chip-ok">✅ {{ msg }}</p>{% endif %}
|
|
{% if err %}<p class="chip-warn">⚠️ {{ err }}</p>{% endif %}
|
|
|
|
{% macro actions(row, kind) %}
|
|
{% if can_write %}
|
|
{% if kind == 'suggested' or kind == 'forge' or kind == 'other' %}
|
|
<form method="post" action="/archives/local" class="inline-form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="conn_id" value="{{ row.conn_id }}">
|
|
<input type="hidden" name="repo_full_name" value="{{ row.full_name }}">
|
|
<input type="hidden" name="archived" value="1">
|
|
<button type="submit" class="btn-mini">📥 Archiver ici</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if kind == 'local' %}
|
|
<form method="post" action="/archives/local" class="inline-form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="conn_id" value="{{ row.conn_id }}">
|
|
<input type="hidden" name="repo_full_name" value="{{ row.full_name }}">
|
|
<input type="hidden" name="archived" value="0">
|
|
<button type="submit" class="btn-mini">♻️ Restaurer</button>
|
|
</form>
|
|
<form method="post" action="/archives/purge" class="inline-form" onsubmit="return confirm('Purger l\'état local (board, notes, épingles) de ce projet dans cet espace ? La forge n\'est pas touchée.');">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="conn_id" value="{{ row.conn_id }}">
|
|
<input type="hidden" name="repo_full_name" value="{{ row.full_name }}">
|
|
<button type="submit" class="btn-mini btn-danger">Purger l'état local</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if kind != 'forge' and not row.missing %}
|
|
<form method="post" action="/archives/forge" class="inline-form" onsubmit="return confirm('Archiver ce projet SUR LA FORGE ? Il y devient en lecture seule.');">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="conn_id" value="{{ row.conn_id }}">
|
|
<input type="hidden" name="repo_full_name" value="{{ row.full_name }}">
|
|
<input type="hidden" name="archived" value="1">
|
|
<button type="submit" class="btn-mini">🔒 Archiver sur la forge</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if kind == 'forge' %}
|
|
<form method="post" action="/archives/forge" class="inline-form" onsubmit="return confirm('Désarchiver ce projet sur la forge ?');">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="conn_id" value="{{ row.conn_id }}">
|
|
<input type="hidden" name="repo_full_name" value="{{ row.full_name }}">
|
|
<input type="hidden" name="archived" value="0">
|
|
<button type="submit" class="btn-mini">🔓 Désarchiver sur la forge</button>
|
|
</form>
|
|
{% endif %}
|
|
<form method="post" action="/archives/export" class="inline-form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="conn_id" value="{{ row.conn_id }}">
|
|
<input type="hidden" name="repo_full_name" value="{{ row.full_name }}">
|
|
<button type="submit" class="btn-mini">⬇️ Récap (.md)</button>
|
|
</form>
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{% macro rowline(row, kind) %}
|
|
<tr>
|
|
<td>
|
|
{% if row.conn_kind == 'github' %}🐙{% else %}🍵{% endif %}
|
|
<strong>{{ row.full_name }}</strong>
|
|
{% if row.conn_slug %}<span class="conn-badge">{{ row.conn_slug }}</span>{% endif %}
|
|
{% if row.missing %}<span class="chip-warn">introuvable sur la forge</span>{% endif %}
|
|
</td>
|
|
<td>{{ row.updated_at or '—' }}{% if row.idle_days is not none %} <span class="muted">(il y a {{ row.idle_days }} j)</span>{% endif %}</td>
|
|
<td>{% if row.open_issues %}⚠️ {{ row.open_issues }} ouverte(s){% else %}0{% endif %}</td>
|
|
<td class="admin-actions">{{ actions(row, kind) }}</td>
|
|
</tr>
|
|
{% endmacro %}
|
|
|
|
<section class="briefing-card">
|
|
<h2>💤 À archiver ? (inactifs depuis {{ suggest_days }} jours et plus)</h2>
|
|
{% if groups.suggested %}
|
|
<form method="post" action="/archives/local-bulk">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<table class="proj-table">
|
|
<thead><tr><th></th><th>Projet</th><th>Dernière activité</th><th>Issues ouvertes</th><th>Actions</th></tr></thead>
|
|
<tbody>
|
|
{% for row in groups.suggested %}
|
|
<tr>
|
|
<td><input type="checkbox" name="item" value="{{ row.conn_id }}:{{ row.full_name }}" checked></td>
|
|
<td>{% if row.conn_kind == 'github' %}🐙{% else %}🍵{% endif %} <strong>{{ row.full_name }}</strong> {% if row.conn_slug %}<span class="conn-badge">{{ row.conn_slug }}</span>{% endif %}</td>
|
|
<td>{{ row.updated_at }} <span class="muted">(il y a {{ row.idle_days }} j)</span></td>
|
|
<td>{% if row.open_issues %}⚠️ {{ row.open_issues }} ouverte(s){% else %}0{% endif %}</td>
|
|
<td class="admin-actions">{{ actions(row, 'suggested') }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
<p><button type="submit" class="btn-save btn-inline">📥 Archiver localement la sélection</button></p>
|
|
</form>
|
|
{% else %}
|
|
<p class="muted">Rien à proposer : aucun projet inactif au-delà du seuil (réglable : <code>archive_suggest_days</code> dans Administration → Paramètres).</p>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section class="briefing-card">
|
|
<h2>📥 Archives locales de cet espace ({{ groups.local|length }})</h2>
|
|
{% if groups.local %}
|
|
<table class="proj-table">
|
|
<thead><tr><th>Projet</th><th>Dernière activité</th><th>Issues ouvertes</th><th>Actions</th></tr></thead>
|
|
<tbody>{% for row in groups.local %}{{ rowline(row, 'local') }}{% endfor %}</tbody>
|
|
</table>
|
|
{% else %}
|
|
<p class="muted">Aucune archive locale. « Archiver ici » masque un projet de cet espace sans toucher à la forge.</p>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section class="briefing-card">
|
|
<h2>🔒 Archivés sur la forge ({{ groups.forge|length }})</h2>
|
|
{% if groups.forge %}
|
|
<table class="proj-table">
|
|
<thead><tr><th>Projet</th><th>Dernière activité</th><th>Issues ouvertes</th><th>Actions</th></tr></thead>
|
|
<tbody>{% for row in groups.forge %}{{ rowline(row, 'forge') }}{% endfor %}</tbody>
|
|
</table>
|
|
{% else %}
|
|
<p class="muted">Aucun dépôt archivé sur les forges de cet espace.</p>
|
|
{% endif %}
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|