feat: dashboard — plongée label, serial visible, GLB link, is_file thumbnail fix

This commit is contained in:
Flag
2026-04-23 20:33:46 +00:00
parent 1b467c5f03
commit 71d82018b1
2 changed files with 20 additions and 6 deletions

View File

@@ -196,7 +196,7 @@ def _build_acquisitions():
d["video_duration_fmt"] = _fmt_dur(int(j["video_duration_s"] or 0)) if (j["video_duration_s"] or 0) > 0 else "" d["video_duration_fmt"] = _fmt_dur(int(j["video_duration_s"] or 0)) if (j["video_duration_s"] or 0) > 0 else ""
d["trimmed_total"] = (j["trimmed_head"] or 0) + (j["trimmed_tail"] or 0) d["trimmed_total"] = (j["trimmed_head"] or 0) + (j["trimmed_tail"] or 0)
thumb_path = DB_PATH.parent / "thumbnails" / f"job_{j['id']}.jpg" thumb_path = DB_PATH.parent / "thumbnails" / f"job_{j['id']}.jpg"
d["has_thumbnail"] = thumb_path.exists() d["has_thumbnail"] = thumb_path.is_file()
# Bust the browser cache on the mtime so the preview refreshes as the dispatcher re-copies it. # Bust the browser cache on the mtime so the preview refreshes as the dispatcher re-copies it.
d["thumb_ts"] = int(thumb_path.stat().st_mtime) if d["has_thumbnail"] else 0 d["thumb_ts"] = int(thumb_path.stat().st_mtime) if d["has_thumbnail"] else 0
# Try the new column; fall back silently on old rows. # Try the new column; fall back silently on old rows.
@@ -207,6 +207,13 @@ def _build_acquisitions():
# Mask the viser link when the demo.py that was serving it has since died. # Mask the viser link when the demo.py that was serving it has since died.
if j["status"] == "done" and j["viser_url"] and not _viser_alive(j["viser_url"]): if j["status"] == "done" and j["viser_url"] and not _viser_alive(j["viser_url"]):
d["viser_url"] = None d["viser_url"] = None
# GLB download link: served by http.server 8300 on the worker
glb_url = None
if d.get("status") == "done" and d.get("frames_dir") and d.get("worker_host"):
frames_basename = (d["frames_dir"] or "").rstrip("/").split("/")[-1]
if frames_basename:
glb_url = f"http://{d['worker_host']}:8300/{frames_basename}/reconstruction.glb"
d["glb_url"] = glb_url
by_acq.setdefault(j["acquisition_id"], []).append(d) by_acq.setdefault(j["acquisition_id"], []).append(d)
by_acq_total[j["acquisition_id"]] = by_acq_total.get(j["acquisition_id"], 0) + dur_s by_acq_total[j["acquisition_id"]] = by_acq_total.get(j["acquisition_id"], 0) + dur_s

View File

@@ -15,7 +15,7 @@
<th class="col-thumb">preview</th> <th class="col-thumb">preview</th>
<th class="col-id">#</th> <th class="col-id">#</th>
<th class="col-auv">AUV · GP</th> <th class="col-auv">AUV · GP</th>
<th class="col-seg">label</th> <th class="col-seg">plongée</th>
<th class="col-dur">durée</th> <th class="col-dur">durée</th>
<th class="col-frames">frames</th> <th class="col-frames">frames</th>
<th class="col-trim">hors-eau</th> <th class="col-trim">hors-eau</th>
@@ -38,8 +38,8 @@
{% if j.has_thumbnail %}<img src="jobs/{{ j.id }}/thumbnail?t={{ j.thumb_ts }}" alt="" loading="lazy">{% else %}<span class="thumb-placeholder"></span>{% endif %} {% if j.has_thumbnail %}<img src="jobs/{{ j.id }}/thumbnail?t={{ j.thumb_ts }}" alt="" loading="lazy">{% else %}<span class="thumb-placeholder"></span>{% endif %}
</td> </td>
<td class="col-id">#{{ j.id }}</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-auv"><strong>{{ j.auv }}</strong> · {{ j.gp_label }}<br><small class="gopro-serial">{{ j.gopro_serial[-6:] }}</small></td>
<td class="col-seg">{{ j.segment_label }}</td> <td class="col-seg"><span title="{{ j.segment_label }}">{% if '' in j.segment_label %}↓{{ j.segment_label.split('')[0] }} ↑{{ j.segment_label.split('')[1] }}{% else %}{{ j.segment_label }}{% endif %}</span></td>
<td class="col-dur">{{ j.video_duration_fmt }}</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-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-trim">{% if j.trimmed_total %}{{ j.trimmed_total }}{% else %}—{% endif %}</td>
@@ -50,8 +50,15 @@
<span class="prog-text">{{ j.progress }}%</span> <span class="prog-text">{{ j.progress }}%</span>
</div> </div>
{% if j.step %}<div class="step-text">{{ j.step }}</div>{% endif %} {% if j.step %}<div class="step-text">{{ j.step }}</div>{% endif %}
{% elif j.status == 'done' and j.viser_url %} {% elif j.status == 'done' %}
<a class="btn-viser" href="{{ j.viser_url }}" target="_blank" rel="noopener">viser ↗</a> {% if j.viser_url %}
<a class="btn-viser" href="{{ j.viser_url }}" target="_blank" rel="noopener">viser ↗</a>
{% else %}
<button class="btn-viser" hx-post="jobs/{{ j.id }}/view" hx-target="#jobs-table" hx-swap="outerHTML" title="Charger PLY dans viser">PLY ↗</button>
{% endif %}
{% if j.glb_url %}
<a class="btn-glb" href="{{ j.glb_url }}" download>GLB ↓</a>
{% endif %}
{% elif j.status == 'skipped' %} {% elif j.status == 'skipped' %}
<span class="muted">skipped</span> <span class="muted">skipped</span>
{% elif j.status == 'error' %} {% elif j.status == 'error' %}