dashboard — colonnes par acquisition, checklist verticale hierarchique

This commit is contained in:
2026-04-21 10:08:38 +00:00
parent 47b082fd9d
commit 3b005a4994
3 changed files with 174 additions and 75 deletions

View File

@@ -1,44 +1,61 @@
{% if not jobs %}
<p class="muted">Aucun job. Ingeste un dossier d'acquisition via <code>scripts/ingest.py</code>.</p>
{% macro duration(job) -%}
{%- if job.started_at and job.finished_at -%}
{{ job._duration }}
{%- elif job.started_at and not job.finished_at -%}
{{ job._duration }}
{%- else -%}&nbsp;
{%- endif -%}
{%- endmacro %}
{% if not acquisitions %}
<p class="muted">Aucune acquisition. Ingeste un dossier via <code>scripts/ingest.py</code>.</p>
{% else %}
<table class="jobs">
<thead>
<tr>
<th>#</th><th>Acquisition</th><th>AUV</th><th>GoPro</th><th>Segment</th>
<th>Frames</th><th>Status</th><th>Worker</th><th>Progress</th><th>Actions</th>
</tr>
</thead>
<tbody>
{% for j in jobs %}
<tr class="status-{{ j.status }}">
<td>{{ j.id }}</td>
<td>{{ j.acquisition_name }}</td>
<td>{{ j.auv }}</td>
<td><code>{{ j.gopro_serial }}</code></td>
<td>{{ j.segment_label }}</td>
<td>{{ j.frame_count or "—" }}</td>
<td><span class="pill {{ j.status }}">{{ j.status }}</span></td>
<td>{{ j.worker_host or "—" }}</td>
<td>
{% if j.status == 'running' or j.status == 'extracting' %}
<progress value="{{ j.progress }}" max="100"></progress> {{ j.progress }}%
{% elif j.status == 'done' and j.viser_url %}
<a href="{{ j.viser_url }}" target="_blank">viser</a>
{% if j.ply_path %} · <a href="/api/jobs/{{ j.id }}/ply">PLY</a>{% endif %}
{% else %}—{% endif %}
</td>
<td>
{% if j.status in ['queued','extracting','running'] %}
<button hx-post="/jobs/{{ j.id }}/cancel" hx-target="#jobs-table" hx-swap="outerHTML">Stop</button>
{% elif j.status == 'error' %}
<button hx-post="/jobs/{{ j.id }}/retry" hx-target="#jobs-table" hx-swap="outerHTML">Retry</button>
{% endif %}
</td>
</tr>
{% if j.error %}
<tr class="err-row"><td colspan="10"><small>{{ j.error }}</small></td></tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<div class="acq-grid">
{% for acq in acquisitions %}
<div class="acq-col">
<h3 class="acq-title">
{{ acq.name }} <span class="total">{{ acq.total_duration }}</span>
</h3>
<ul class="job-list">
{% for j in acq.jobs %}
<li class="job-item {{ j.status }}">
<span class="icon">
{% if j.status == 'done' %}<span class="check"></span>
{% elif j.status in ('running','extracting') %}<span class="spin"></span>
{% elif j.status == 'error' %}<span class="err"></span>
{% else %}<span class="sq"></span>{% endif %}
</span>
<span class="label">
{{ j.auv }}/{{ j.gopro_serial }}/{{ j.segment_label }}
{% if j.status == 'done' and j.viser_url %}
<a class="ext" href="{{ j.viser_url }}" target="_blank">viser</a>
{% endif %}
</span>
<span class="dur">{{ j._duration }}</span>
{% if j.status in ('queued','extracting','running') %}
<button class="mini" hx-post="/jobs/{{ j.id }}/cancel" hx-target="#jobs-table">×</button>
{% elif j.status == 'error' %}
<button class="mini" hx-post="/jobs/{{ j.id }}/retry" hx-target="#jobs-table"></button>
{% endif %}
</li>
{% if j.error %}<li class="err-line">{{ j.error }}</li>{% endif %}
{% endfor %}
</ul>
{# Stitch section (placeholder — wired up once multi-job stitching lands) #}
<div class="stitch-section">
<div class="stitch-title">
<span class="icon"><span class="sq"></span></span>
<span>stitch</span>
</div>
<ul class="stitch-children">
<li class="sub pending"><span class="sq"></span> pair GP1↔GP2 per AUV</li>
<li class="sub pending"><span class="sq"></span> cross-AUV merge</li>
<li class="sub pending"><span class="sq"></span> final PLY</li>
</ul>
</div>
</div>
{% endfor %}
</div>
{% endif %}