Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7852d860fe |
@@ -1,5 +1,34 @@
|
|||||||
# Changelog
|
# 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
|
## 0.31.0 — 2026-10-23
|
||||||
|
|
||||||
### Ajouté — description éditable, pièces jointes, clic fiable
|
### Ajouté — description éditable, pièces jointes, clic fiable
|
||||||
|
|||||||
+1
-1
@@ -113,7 +113,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
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:
|
def _env_bool(name: str, default: bool) -> bool:
|
||||||
|
|||||||
+1
-1
@@ -143,7 +143,7 @@ async def _mcp_session(client: httpx.AsyncClient, url: str, token: str) -> None:
|
|||||||
{
|
{
|
||||||
"protocolVersion": MCP_PROTOCOL_VERSION,
|
"protocolVersion": MCP_PROTOCOL_VERSION,
|
||||||
"capabilities": {},
|
"capabilities": {},
|
||||||
"clientInfo": {"name": "kanbante", "version": "0.31.0"},
|
"clientInfo": {"name": "kanbante", "version": "0.31.1"},
|
||||||
},
|
},
|
||||||
req_id=1,
|
req_id=1,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="csrf-token" content="{{ csrf_token }}">
|
<meta name="csrf-token" content="{{ csrf_token }}">
|
||||||
<title>{{ repo }} — Kanbante</title>
|
<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/sortable.min.js"></script>
|
||||||
<script src="/static/vendor/marked.min.js"></script>
|
<script src="/static/vendor/marked.min.js"></script>
|
||||||
<script src="/static/vendor/purify.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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% include "_header.html" %}
|
{% include "_header.html" %}
|
||||||
@@ -54,13 +54,24 @@
|
|||||||
<button type="button" id="labels-btn" class="btn-sm">🏷️ Gérer les étiquettes</button>
|
<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>
|
<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 %}
|
{% 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">
|
<form id="create-issue-form" class="composer">
|
||||||
<input type="text" id="new-issue-title" maxlength="255"
|
<div class="composer-head">
|
||||||
placeholder="➕ Nouvelle issue (titre)..." required>
|
<span class="composer-title">➕ Nouvelle issue</span>
|
||||||
<button type="button" id="new-issue-desc-toggle" class="btn-sm" title="Ajouter une description">+ Description</button>
|
<span class="composer-target">arrive dans
|
||||||
<button type="submit" class="btn-save btn-inline">Créer</button>
|
<strong>{{ column_labels.backlog }}</strong>
|
||||||
<textarea id="new-issue-body" rows="4" maxlength="100000" hidden
|
</span>
|
||||||
placeholder="Description (markdown)..."></textarea>
|
</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>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "kanbante"
|
name = "kanbante"
|
||||||
version = "0.31.0"
|
version = "0.31.1"
|
||||||
description = "Kanban project manager integrated with Gitea"
|
description = "Kanban project manager integrated with Gitea"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
+21
-1
@@ -1693,4 +1693,24 @@ body.sidebar-collapsed .ws-switch { display: none; }
|
|||||||
.asset-row a { text-decoration: none; font-weight: 600; }
|
.asset-row a { text-decoration: none; font-weight: 600; }
|
||||||
.asset-meta { color: var(--muted, #999); font-size: 0.85em; margin-right: auto; }
|
.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; }
|
.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
@@ -122,9 +122,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('new-issue-desc-toggle')?.addEventListener('click', () => {
|
createForm?.addEventListener('keydown', (e) => {
|
||||||
const area = document.getElementById('new-issue-body');
|
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
|
||||||
if (area) { area.hidden = !area.hidden; if (!area.hidden) area.focus(); }
|
e.preventDefault();
|
||||||
|
createForm.requestSubmit();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// The "Glissez une carte ici" hint is rendered by the server only
|
// The "Glissez une carte ici" hint is rendered by the server only
|
||||||
|
|||||||
@@ -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-edit-form"' in page.text
|
||||||
assert 'id="detail-assets"' in page.text
|
assert 'id="detail-assets"' in page.text
|
||||||
assert 'id="asset-form"' 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-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():
|
async def test_gitea_download_follows_browser_download_url():
|
||||||
|
|||||||
Reference in New Issue
Block a user