v0.5.0 (Kanban complet):
- Card detail modal avec checklists + commentaires Gitea
- Création d'issues inline (formulaire + POST /api/issues)
- Édition inline (contenteditable)
v0.6.0 (Table view):
- table_view.html: colonnes Name/Status/Assign/Deadline/Team/Keywords
- Tri par colonne (clic en-tête, asc/desc)
- Groupes rétractables (Design/Engineering)
v0.7.0 (Filtres & Tri):
- Filtres cumulables AND (backend _apply_filters + UI pastilles)
- Status dropdown avec checkboxes + dots colorés
- Sort panel multi-critères (+ Add sort / Delete sort)
- Backend _apply_sorts avec asc/desc
v0.8.0 (Vues spéciales):
- status_overview.html: SVG donut chart + légende + pourcentages
- team_load.html: barres empilées par avatar
- detailed_board.html: cartes avec toutes propriétés
Backend:
- /board/{o}/{r}/view/{view} — 5 fragments HTMX
- /api/issues/{o}/{r}/{id}?format=html — modal HTML
- _map_issue_to_card, STATUS_COLORS/LABELS exportés
44 lines
1.7 KiB
HTML
44 lines
1.7 KiB
HTML
<!-- Status Overview — Notion-style Donut Chart -->
|
|
<div id="view-content" class="status-overview">
|
|
<div class="donut-container">
|
|
<svg viewBox="0 0 200 200" width="200" height="200">
|
|
{% set total = status_data.values()|sum %}
|
|
{% set offset = namespace(val=0) %}
|
|
{% for status, count in status_data.items() %}
|
|
{% set pct = (count / total * 100) if total > 0 else 0 %}
|
|
{% set dash = (pct / 100 * 251.3)|round(1) %}
|
|
<circle cx="100" cy="100" r="40" fill="none"
|
|
stroke="{{ status_colors[status] }}" stroke-width="20"
|
|
stroke-dasharray="{{ dash }} 251.3"
|
|
stroke-dashoffset="{{ -offset.val * 251.3 / 100 }}"
|
|
transform="rotate(-90 100 100)"
|
|
style="transition: stroke-dasharray 0.5s ease;" />
|
|
{% set offset.val = offset.val + pct %}
|
|
{% endfor %}
|
|
{% if total == 0 %}
|
|
<circle cx="100" cy="100" r="40" fill="none"
|
|
stroke="var(--bg-tertiary)" stroke-width="20"
|
|
stroke-dasharray="251.3 251.3"
|
|
transform="rotate(-90 100 100)" />
|
|
{% endif %}
|
|
</svg>
|
|
<div class="donut-center">
|
|
<div class="donut-total">{{ total }}</div>
|
|
<div class="donut-label">Total</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="status-legend">
|
|
{% for status, count in status_data.items() %}
|
|
<div class="legend-item">
|
|
<span class="legend-dot" style="background:{{ status_colors[status] }};"></span>
|
|
<span>{{ status_labels[status] }}</span>
|
|
<span style="font-weight:600; color:var(--text-primary);">{{ count }}</span>
|
|
<span class="text-dim">
|
|
({{ "%.1f"|format(count / total * 100) if total > 0 else 0 }}%)
|
|
</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|