Files
cosma-qc/app/templates/_jobs_table.html
Flag f13d27b997 dashboard — vrai tableau + probe viser_url alive + CSS propre
1. _jobs_table.html: remplace la liste <li>flex par un vrai <table> avec
   colonnes explicites: status · preview · #id · AUV+GP · label · duree
   video · frames · hors-eau · progression · temps · actions. Stitches
   restent en <ul> compacte.

2. main.py _build_acquisitions: probe TCP le viser_url avec cache 8s
   avant de le passer au template. Si port mort -> d[viser_url]=None ->
   pas de bouton affiche. Fini les liens qui mennent a rien.

3. style.css: purge des regles flex conflictuelles, rewrite propre pour
   table.jobs-table, badges, prog-bar, btn-viser direct link.
2026-04-22 22:43:14 +00:00

111 lines
5.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% if not acquisitions %}
<p class="muted">Aucune acquisition. Ingeste un dossier via <code>scripts/ingest.py</code>.</p>
{% else %}
<div class="acq-list">
{% for acq in acquisitions %}
<section class="acq">
<h3 class="acq-title">
{{ acq.name }} <span class="total">{{ acq.total_duration }}</span>
</h3>
<table class="jobs-table">
<thead>
<tr>
<th class="col-status"></th>
<th class="col-thumb">preview</th>
<th class="col-id">#</th>
<th class="col-auv">AUV · GP</th>
<th class="col-seg">label</th>
<th class="col-dur">durée</th>
<th class="col-frames">frames</th>
<th class="col-trim">hors-eau</th>
<th class="col-progress">progression</th>
<th class="col-elapsed">temps</th>
<th class="col-actions"></th>
</tr>
</thead>
<tbody>
{% for j in acq.jobs %}
<tr class="job-row {{ j.status }}">
<td class="col-status" title="{{ j.status }}">
{% if j.status == 'done' %}<span class="badge ok"></span>
{% elif j.status in ('running','extracting') %}<span class="badge busy"></span>
{% elif j.status == 'error' %}<span class="badge err"></span>
{% elif j.status == 'skipped' %}<span class="badge muted"></span>
{% else %}<span class="badge muted"></span>{% endif %}
</td>
<td class="col-thumb">
{% if j.has_thumbnail %}<img src="jobs/{{ j.id }}/thumbnail" alt="" loading="lazy">{% else %}<span class="thumb-placeholder"></span>{% endif %}
</td>
<td class="col-id">#{{ j.id }}</td>
<td class="col-auv"><strong>{{ j.auv }}</strong> · <span title="{{ j.gopro_serial }}">{{ j.gp_label }}</span></td>
<td class="col-seg">{{ j.segment_label }}</td>
<td class="col-dur">{{ j.video_duration_fmt }}</td>
<td class="col-frames">{% if j.frame_count %}{{ j.frame_count }}{% else %}—{% endif %}</td>
<td class="col-trim">{% if j.trimmed_total %}{{ j.trimmed_total }}{% else %}—{% endif %}</td>
<td class="col-progress">
{% if j.status in ('extracting','running') %}
<span class="prog-bar"><span class="prog-fill" style="width:{{ j.progress }}%"></span></span>
<span class="prog-text">{{ j.progress }}%</span>
{% elif j.status == 'done' and j.viser_url %}
<a class="btn-viser" href="{{ j.viser_url }}" target="_blank" rel="noopener">viser ↗</a>
{% elif j.status == 'skipped' %}
<span class="muted">skipped</span>
{% elif j.status == 'error' %}
<span class="muted" title="{{ j.error }}">failed</span>
{% else %}
<span class="muted"></span>
{% endif %}
</td>
<td class="col-elapsed">{{ j._duration }}</td>
<td class="col-actions">
{% if j.status in ('queued','extracting','running') %}
<button class="mini" hx-post="jobs/{{ j.id }}/cancel" hx-target="#jobs-table" title="annuler">×</button>
{% elif j.status == 'error' %}
<button class="mini" hx-post="jobs/{{ j.id }}/retry" hx-target="#jobs-table" title="retry"></button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="stitch-section">
<div class="stitch-title">stitch</div>
{% if acq.stitches %}
<ul class="stitch-list">
{% for s in acq.stitches %}
<li class="stitch-item {{ s.status }}">
<span class="badge {% if s.status == 'done' %}ok{% elif s.status == 'running' %}busy{% elif s.status == 'error' %}err{% else %}muted{% endif %}">
{% if s.status == 'done' %}✓{% elif s.status == 'running' %}↻{% elif s.status == 'error' %}✕{% else %}■{% endif %}
</span>
<span class="stitch-label">
{% if s.level == 'per_auv' %}pair GP1↔GP2 {{ s.auv }}
{% else %}merge final{% endif %}
</span>
{% if s._duration %}<span class="muted"> · {{ s._duration }}</span>{% endif %}
{% if s.status == 'done' and s.output_ply %}
<button class="btn-viser" data-view-url="stitches/{{ s.id }}/view">viser ↗</button>
{% endif %}
{% if s.status in ('queued','running') %}
<button class="mini" hx-post="stitches/{{ s.id }}/cancel" hx-target="#jobs-table">×</button>
{% elif s.status == 'error' %}
<button class="mini" hx-post="stitches/{{ s.id }}/retry" hx-target="#jobs-table"></button>
{% endif %}
{% if s.error %}<div class="err-line">{{ s.error[:140] }}</div>{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<ul class="stitch-list">
<li class="stitch-item pending"><span class="badge muted"></span> <span class="muted">pair GP1↔GP2 per AUV</span></li>
<li class="stitch-item pending"><span class="badge muted"></span> <span class="muted">cross-AUV merge</span></li>
<li class="stitch-item pending"><span class="badge muted"></span> <span class="muted">final PLY</span></li>
</ul>
{% endif %}
</div>
</section>
{% endfor %}
</div>
{% endif %}