Enhance rota run detail view with real-time log and result updates, and add "View final output" button

This commit is contained in:
Ross
2025-12-19 21:30:28 +00:00
parent 62010dd09f
commit 120dd16845
4 changed files with 62 additions and 10 deletions
+43 -6
View File
@@ -1,4 +1,5 @@
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from django.urls import reverse
from .models import RotaSchedule, Worker
@@ -758,18 +759,54 @@ def rota_run_status(request, run_id):
'hx-trigger="every 3s" hx-swap="outerHTML">'
f'<span class="tag is-info">Status: {run.get_status_display()}</span>'
f' <small>started: {run.started_at}</small>'
f' <small style="margin-left:0.5rem; color:#666;">server_time: {timezone.now().isoformat()}</small>'
"</div>"
)
return HttpResponse(html)
resp = HttpResponse(html)
# Prevent aggressive caching so polling always fetches fresh state
resp['Cache-Control'] = 'no-cache, no-store, must-revalidate'
resp['Pragma'] = 'no-cache'
return resp
# Finished/failed: return final fragment and reload the page so the
# user sees final logs/export without further polling.
final_html = (
f'<div id="run-status-final"><span class="tag is-success">Status: {run.get_status_display()}</span>'
f' <small>finished: {run.finished_at}</small></div>'
"<script>window.location.reload();</script>"
# Build out-of-band swaps to update the log and result sections in-place
from django.utils.html import escape
# Prepare pretty result if present
try:
if run.result is not None:
import json as _json
result_pretty = _json.dumps(run.result, indent=2, default=str)
else:
result_pretty = ""
except Exception:
result_pretty = str(run.result)
status_fragment = (
f'<div id="run-status"><span class="tag is-success">Status: {escape(run.get_status_display())}</span>'
f' <small>finished: {escape(str(run.finished_at))}</small></div>'
)
return HttpResponse(final_html)
# OOB swap for the log block
log_fragment = f'<div id="run-log" hx-swap-oob="true"><pre>{escape(run.log or "")}</pre></div>'
# OOB swap for the result block
result_fragment = f'<div id="run-result" hx-swap-oob="true"><pre>{escape(result_pretty or "")}</pre></div>'
# OOB swap for a 'View final output' button
view_button = (
f'<div id="view-final-output" hx-swap-oob="true">'
f'<a class="button is-link" href="{reverse("rota:rota_run_export_html", args=[run.id])}" target="_blank">View final output</a>'
"</div>"
)
body = status_fragment + log_fragment + result_fragment + view_button
resp = HttpResponse(body)
resp['Cache-Control'] = 'no-cache, no-store, must-revalidate'
resp['Pragma'] = 'no-cache'
return resp
def rota_run_export_html(request, run_id):