Files
kanbante/app/templates/admin_columns.html
T
Spark 28322c12cf
CI / test (push) Successful in 2m17s
feat(0.30.0): colonnes personnalisables par espace + mapping étiquette ↔ colonne
- Table board_columns par espace (clé immuable, nom/couleur/
  ordre libres, étiquette mappée + alias, drapeau Focus) ;
  définitions semées paresseusement depuis les valeurs
  historiques — sans personnalisation, comportement identique.
- Service app/board_columns.py : résolution, mapping
  étiquette→colonne (alias compris, ex. kanban_a_faire de
  Flowdeck), colonnes Focus/Wallboard.
- Board, API, adoption, miroirs d'étiquettes, déplacements,
  capture, santé, focus, wall, dashboard branchés sur les
  colonnes de l'espace ; validations dynamiques dans models
  (move_issue, set_column_order) et rules.
- Administration → Colonnes : ajouter (avant Terminé),
  renommer, réordonner, mapper, supprimer avec migration des
  cartes vers une colonne choisie, réinitialiser ; bouton
  🧱 Colonnes sur le board ; journal d'audit.
- Backlog et Terminé : colonnes système non supprimables.
- 254 tests verts (7 nouveaux, palier 20) ; smoke réel contre
  le vrai Gitea : création, affichage au board, suppression.
2026-10-23 08:38:02 -04:00

100 lines
6.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>Colonnes — Administration — 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>🧱 Colonnes du board</h1>
<p class="page-sub">Espace : <strong>{{ workspace.name }}</strong> (change d'espace par le sélecteur en haut pour régler un autre board). Les colonnes sont propres à chaque espace : nom, couleur, ordre et <strong>mapping étiquette ↔ colonne</strong>. La <strong>clé</strong> d'une colonne ne change jamais (les cartes y sont rattachées) ; le <strong>nom affiché</strong>, lui, est libre.</p>
</div>
{% if msg %}<p class="chip-ok">✅ {{ msg }}</p>{% endif %}
{% if err %}<p class="chip-warn">⚠️ {{ err }}</p>{% endif %}
<section class="briefing-card">
<h2>Comment marche le mapping</h2>
<p class="notes-hint">
<strong>Miroir</strong> : quand une carte entre dans une colonne, son <em>étiquette mappée</em> est posée sur l'issue de la forge (et les étiquettes mappées des autres colonnes sont retirées).<br>
<strong>Adoption</strong> : si une issue porte <em>exactement une</em> étiquette reconnue (étiquette mappée ou alias d'une colonne), le board adopte cette colonne — c'est ce qui permet à d'autres outils de piloter le board par étiquettes.<br>
<strong>Alias</strong> : étiquettes supplémentaires reconnues pour cette colonne, séparées par des virgules — par exemple les étiquettes Flowdeck <code>kanban_a_faire</code> sur la colonne À faire.<br>
<strong>Focus</strong> : les colonnes cochées « Focus » alimentent la vue Focus du jour et le wallboard.
</p>
</section>
{% for c in columns %}
<section class="briefing-card">
<h2>
<span class="ws-dot" style="background: {{ c.color }}"></span>
{{ c.name }}
<span class="muted"><code>{{ c.key }}</code> · {{ counts[c.key] }} carte(s) dans cet espace</span>
{% if c.kind == 'backlog' %}<span class="chip">système — défaut des cartes neuves</span>{% endif %}
{% if c.kind == 'done' %}<span class="chip">système — issues fermées</span>{% endif %}
</h2>
<form method="post" action="/admin/columns/{{ c.key }}" class="admin-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<label>Nom affiché <input type="text" name="name" value="{{ c.name }}"></label>
<label>Couleur <input type="color" name="color" value="{{ c.color }}"></label>
{% if c.kind == 'flow' %}
<label>Étiquette mappée <input type="text" name="label" value="{{ c.label }}" placeholder="kanban:{{ c.key }}"></label>
<label>Alias (virgules) <input type="text" name="aliases" value="{{ c.aliases }}" placeholder="kanban_a_faire, a-faire"></label>
<label><input type="checkbox" name="in_focus" value="1"{% if c.in_focus %} checked{% endif %}> Dans Focus / Wallboard</label>
{% endif %}
<button type="submit" class="btn-save btn-inline">Enregistrer</button>
</form>
<p class="admin-actions">
<form method="post" action="/admin/columns/{{ c.key }}/move" class="inline-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="direction" value="up">
<button type="submit" class="btn-mini" title="Monter">⬆️</button>
</form>
<form method="post" action="/admin/columns/{{ c.key }}/move" class="inline-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="direction" value="down">
<button type="submit" class="btn-mini" title="Descendre">⬇️</button>
</form>
{% if c.kind == 'flow' %}
<form method="post" action="/admin/columns/{{ c.key }}/delete" class="inline-form" onsubmit="return confirm('Supprimer cette colonne ? Ses cartes iront dans la colonne choisie.');">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<label>Déplacer ses cartes vers
<select name="target">
{% for other in columns %}{% if other.key != c.key %}<option value="{{ other.key }}">{{ other.name }}</option>{% endif %}{% endfor %}
</select>
</label>
<button type="submit" class="btn-mini btn-danger">Supprimer la colonne</button>
</form>
{% endif %}
</p>
</section>
{% endfor %}
<section class="briefing-card">
<h2>➕ Nouvelle colonne</h2>
<form method="post" action="/admin/columns" class="admin-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<label>Nom affiché <input type="text" name="name" required placeholder="🛠️ En développement"></label>
<label>Couleur <input type="color" name="color" value="#7c5cfc"></label>
<label>Étiquette mappée <input type="text" name="label" placeholder="(défaut : kanban:<clé>)"></label>
<label>Alias (virgules) <input type="text" name="aliases" placeholder=""></label>
<button type="submit" class="btn-save btn-inline">Ajouter (avant Terminé)</button>
</form>
</section>
<section class="briefing-card">
<h2>↩️ Réinitialiser</h2>
<p class="notes-hint">Revenir aux six colonnes historiques de cet espace. Les cartes placées dans des colonnes personnalisées retomberont au Backlog à l'affichage.</p>
<form method="post" action="/admin/columns/reset" class="inline-form" onsubmit="return confirm('Réinitialiser les colonnes de cet espace aux valeurs par défaut ?');">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit" class="btn-mini btn-danger">Réinitialiser les colonnes</button>
</form>
</section>
</main>
</body>
</html>