feat(live): board dynamique sans refresh (issue #15)
Diffusion SSE sur toutes les mutations (move, création, capture,
étiquettes) via _publish_board_changed; GET /api/board/{o}/{r}
(fragments _card.html rendus serveur, même pipeline que la page);
board-live.js: diff en place par colonne avec animation FLIP,
application différée pendant un drag, filtres/compteurs réappliqués,
repli par sondage 45 s sans webhooks. Carte extraite en partiel
_card.html partagé page/API.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<div class="kanban-card"
|
||||
data-issue="{{ issue.number }}"
|
||||
data-repo="{{ full_name }}"
|
||||
data-title="{{ issue.title|lower }}"
|
||||
data-labels="{{ issue.labels|map(attribute='name')|join(',')|lower }}">
|
||||
<div class="card-id">
|
||||
#{{ issue.number }}
|
||||
{% if issue.html_url %}
|
||||
<a href="{{ issue.html_url }}" target="_blank" title="Ouvrir dans Gitea">↗</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-title">{{ issue.title }}</div>
|
||||
{% if issue.labels %}
|
||||
<div class="card-labels">
|
||||
{% for label in issue.labels %}
|
||||
<span class="label-tag" style="background: #{{ label.color }}30; color: #{{ label.color }}">
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-meta">
|
||||
{% if issue.assignee %}
|
||||
<img src="{{ issue.assignee.avatar_url }}" class="avatar" alt="{{ issue.assignee.login }}">
|
||||
{% endif %}
|
||||
<span class="card-date">{{ issue.created_at[:10] }}</span>
|
||||
{% set age = ages.get(issue.number) %}
|
||||
{% if age and age.days >= aging_days %}
|
||||
<span class="age-badge{% if age.days >= aging_days * 2 %} stale{% endif %}"
|
||||
title="Dans cette colonne depuis le {{ age.since[:10] }}">⏳ {{ age.days }} j</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,39 +90,7 @@
|
||||
<p class="column-empty">Glissez une carte ici</p>
|
||||
{% endif %}
|
||||
{% for issue in columns[col] %}
|
||||
<div class="kanban-card"
|
||||
data-issue="{{ issue.number }}"
|
||||
data-repo="{{ full_name }}"
|
||||
data-title="{{ issue.title|lower }}"
|
||||
data-labels="{{ issue.labels|map(attribute='name')|join(',')|lower }}">
|
||||
<div class="card-id">
|
||||
#{{ issue.number }}
|
||||
{% if issue.html_url %}
|
||||
<a href="{{ issue.html_url }}" target="_blank" title="Ouvrir dans Gitea">↗</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-title">{{ issue.title }}</div>
|
||||
{% if issue.labels %}
|
||||
<div class="card-labels">
|
||||
{% for label in issue.labels %}
|
||||
<span class="label-tag" style="background: #{{ label.color }}30; color: #{{ label.color }}">
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-meta">
|
||||
{% if issue.assignee %}
|
||||
<img src="{{ issue.assignee.avatar_url }}" class="avatar" alt="{{ issue.assignee.login }}">
|
||||
{% endif %}
|
||||
<span class="card-date">{{ issue.created_at[:10] }}</span>
|
||||
{% set age = ages.get(issue.number) %}
|
||||
{% if age and age.days >= aging_days %}
|
||||
<span class="age-badge{% if age.days >= aging_days * 2 %} stale{% endif %}"
|
||||
title="Dans cette colonne depuis le {{ age.since[:10] }}">⏳ {{ age.days }} j</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "_card.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -206,7 +174,7 @@
|
||||
<span>Mis à jour {{ repo_info.updated_at[:10] }}</span>
|
||||
{% endif %}
|
||||
</footer>
|
||||
<script src="/static/js/live.js" defer></script>
|
||||
<script src="/static/js/board-live.js" defer></script>
|
||||
{% include "_palette.html" %}
|
||||
<script src="/static/js/palette.js" defer></script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user