Compare commits

..
1 Commits
Author SHA1 Message Date
Spark 7852d860fe fix(0.31.1): compositeur de création refait, description en <details> natif
CI / test (push) Successful in 2m13s
- Carte compositeur : en-tête + colonne d'arrivée, champ
  pleine largeur, bouton primaire ; neutralise le
  display:flex imposé par .board-toolbar aux formulaires.
- 'Ajouter une description' devient un <details> natif :
  aucun JS requis, insensible au cache et aux erreurs de
  scripts (le bouton 0.31.0 pouvait rester inerte).
- Assets du board versionnés (?v=APP_VERSION) contre les
  mélanges de cache après redéploiement ; Ctrl+Entrée.
- Vérifié en Chromium réel sur le vrai board (captures
  contrôlées) ; 261 tests verts.
2026-10-23 09:48:17 -04:00
8 changed files with 82 additions and 18 deletions
+29
View File
@@ -1,5 +1,34 @@
# Changelog
## 0.31.1 — 2026-10-23
### Corrigé — compositeur de création refait
Retour de Bruno sur la 0.31.0 : la barre de création
n'était ni élégante ni professionnelle, et le bouton
« + Description » pouvait rester sans effet (écouteur
JavaScript non enregistré selon l'état du cache ou des
scripts de la page).
- **Compositeur en carte** : en-tête « Nouvelle issue »
avec la colonne d'arrivée (« arrive dans 📥 Backlog »,
nom personnalisé de l'espace respecté), champ titre
pleine largeur avec anneau de focus, bouton primaire
« Créer l'issue ».
- **Description en `<details>` natif** : « Ajouter une
description ▾ » déplie la zone texte sans aucun
JavaScript — impossible à casser par un script en
erreur ou un fichier en cache. Aide intégrée (Markdown,
Ctrl+Entrée pour créer, actif aussi depuis le titre).
- **Assets du board versionnés** (`?v=<version>` sur le
CSS et board.js du board) : un redéploiement invalide
le cache navigateur au lieu de servir un mélange
d'anciennes et nouvelles pièces.
- Vérifié en navigateur réel (Chromium) sur le vrai
board : captures fermé/ouvert contrôlées visuellement,
clic sur le libellé, zone visible et éditable.
## 0.31.0 — 2026-10-23
### Ajouté — description éditable, pièces jointes, clic fiable
+1 -1
View File
@@ -113,7 +113,7 @@ from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
APP_VERSION = "0.31.0"
APP_VERSION = "0.31.1"
def _env_bool(name: str, default: bool) -> bool:
+1 -1
View File
@@ -143,7 +143,7 @@ async def _mcp_session(client: httpx.AsyncClient, url: str, token: str) -> None:
{
"protocolVersion": MCP_PROTOCOL_VERSION,
"capabilities": {},
"clientInfo": {"name": "kanbante", "version": "0.31.0"},
"clientInfo": {"name": "kanbante", "version": "0.31.1"},
},
req_id=1,
)
+20 -9
View File
@@ -5,11 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token }}">
<title>{{ repo }} — Kanbante</title>
<link rel="stylesheet" href="/static/css/style.css">
<link rel="stylesheet" href="/static/css/style.css?v={{ version }}">
<script src="/static/vendor/sortable.min.js"></script>
<script src="/static/vendor/marked.min.js"></script>
<script src="/static/vendor/purify.min.js"></script>
<script src="/static/js/board.js" defer></script>
<script src="/static/js/board.js?v={{ version }}" defer></script>
</head>
<body>
{% include "_header.html" %}
@@ -54,13 +54,24 @@
<button type="button" id="labels-btn" class="btn-sm">🏷️ Gérer les étiquettes</button>
<a href="/triage/{{ full_name }}" class="btn-sm" style="text-decoration:none">📥 Triage du backlog</a>
{% if is_admin or workspace_role == 'admin' %}<a href="/admin/columns" class="btn-sm" style="text-decoration:none" title="Personnaliser les colonnes de cet espace">🧱 Colonnes</a>{% endif %}
<form id="create-issue-form">
<input type="text" id="new-issue-title" maxlength="255"
placeholder="➕ Nouvelle issue (titre)..." required>
<button type="button" id="new-issue-desc-toggle" class="btn-sm" title="Ajouter une description">+ Description</button>
<button type="submit" class="btn-save btn-inline">Créer</button>
<textarea id="new-issue-body" rows="4" maxlength="100000" hidden
placeholder="Description (markdown)..."></textarea>
<form id="create-issue-form" class="composer">
<div class="composer-head">
<span class="composer-title">➕ Nouvelle issue</span>
<span class="composer-target">arrive dans
<strong>{{ column_labels.backlog }}</strong>
</span>
</div>
<div class="composer-main">
<input type="text" id="new-issue-title" maxlength="255"
placeholder="Titre de l'issue..." required>
<button type="submit" class="btn-save btn-inline">Créer l'issue</button>
</div>
<details class="composer-desc" id="new-issue-desc">
<summary><span class="composer-desc-label">Ajouter une description</span><span class="composer-chevron" aria-hidden="true">▾</span></summary>
<textarea id="new-issue-body" rows="5" maxlength="100000"
placeholder="Description (markdown)..."></textarea>
<p class="composer-hint">Markdown accepté · Ctrl+Entrée pour créer l'issue</p>
</details>
</form>
</div>
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "kanbante"
version = "0.31.0"
version = "0.31.1"
description = "Kanban project manager integrated with Gitea"
requires-python = ">=3.11"
dependencies = [
+21 -1
View File
@@ -1693,4 +1693,24 @@ body.sidebar-collapsed .ws-switch { display: none; }
.asset-row a { text-decoration: none; font-weight: 600; }
.asset-meta { color: var(--muted, #999); font-size: 0.85em; margin-right: auto; }
.asset-form { display: flex; gap: 8px; align-items: center; margin: 8px 0 4px; flex-wrap: wrap; }
#create-issue-form textarea { flex-basis: 100%; margin-top: 6px; }
/* ── Compositeur de nouvelle issue (0.31.1) ── */
/* La toolbar impose display:flex à ses formulaires : le
compositeur est une carte, en bloc et pleine largeur. */
.board-toolbar form.composer { display: block; flex: 1 1 100%; }
.composer { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; margin: 6px 0 10px; }
.composer-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.composer-title { font-weight: 700; font-size: 0.95rem; }
.composer-target { color: var(--muted, #9aa3b5); font-size: 0.82rem; }
.composer-main { display: flex; gap: 8px; }
.composer-main input[type="text"] { flex: 1; background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 9px 12px; color: inherit; font-size: 0.95rem; }
.composer-main input[type="text"]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(124, 92, 252, 0.25); }
.composer-desc { margin-top: 10px; }
.composer-desc summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; font-size: 0.88rem; color: var(--accent-2); padding: 4px 2px; user-select: none; }
.composer-desc summary::-webkit-details-marker { display: none; }
.composer-desc summary:hover .composer-desc-label { text-decoration: underline; }
.composer-chevron { transition: transform 0.15s ease; font-size: 0.75rem; }
.composer-desc[open ] .composer-chevron { transform: rotate(180deg); }
.composer-desc textarea { width: 100%; margin-top: 8px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; color: inherit; font-family: inherit; resize: vertical; }
.composer-desc textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(124, 92, 252, 0.25); }
.composer-hint { color: var(--muted, #9aa3b5); font-size: 0.78rem; margin: 6px 0 0; }
+5 -3
View File
@@ -122,9 +122,11 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
document.getElementById('new-issue-desc-toggle')?.addEventListener('click', () => {
const area = document.getElementById('new-issue-body');
if (area) { area.hidden = !area.hidden; if (!area.hidden) area.focus(); }
createForm?.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
e.preventDefault();
createForm.requestSubmit();
}
});
// The "Glissez une carte ici" hint is rendered by the server only
+4 -2
View File
@@ -95,9 +95,11 @@ def test_board_page_has_editor_and_assets_ui(client, fake_gitea):
assert 'id="detail-edit-form"' in page.text
assert 'id="detail-assets"' in page.text
assert 'id="asset-form"' in page.text
# Création avec description dépliable.
# Création avec description dépliable (0.31.1 : <details>
# natif plutôt qu'un bouton piloté en JS).
assert 'id="new-issue-body"' in page.text
assert 'id="new-issue-desc-toggle"' in page.text
assert 'id="new-issue-desc"' in page.text
assert 'class="composer"' in page.text
async def test_gitea_download_follows_browser_download_url():