{% extends "layout.html.tera" %}
{% block content %}
<h1 class="text-2xl font-semibold mb-4">{{ title | default(value="Queue") }}</h1>
<div class="card overflow-hidden">
<table class="table">
<thead class="bg-slate-50/60 dark:bg-slate-900/30">
<tr>
<th class="th">ID</th>
<th class="th">Type</th>
<th class="th">Status</th>
<th class="th">Created</th>
<th class="th">Run at</th>
<th class="th">Failed at</th>
<th class="th">Error</th>
<th class="th">Actions</th>
</tr>
</thead>
<tbody>
{% for job in jobs %}
<tr class="hover:bg-slate-50/60 dark:hover:bg-slate-900/30">
<td class="td font-mono text-xs">{{ job.id }}</td>
<td class="td">{{ job.job_type }}</td>
<td class="td">
{% set s = job.status | default(value="queued") %}
<span class="{% if s == "success" %}chip-green{% elif s == "failed" %}chip-red{% elif s == "queued" %}chip-sky{% else %}chip-amber{% endif %}">{{ s }}</span>
</td>
<td class="td">{{ job.created_at | default(value="—") }}</td>
<td class="td">{{ job.run_at | default(value="—") }}</td>
<td class="td">{{ job.failed_at | default(value="—") }}</td>
<td class="td max-w-[20rem] truncate" title="{{ job.error | default(value="") }}">{{ job.error | default(value="") }}</td>
<td class="td">
<button class="btn" onclick="jobAction('retry','{{ job.id }}')">Retry</button>
<button class="btn-danger" onclick="jobAction('delete','{{ job.id }}')">Delete</button>
</td>
</tr>
{% else %}
<tr><td class="td" colspan="8">No jobs.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
{% if page is defined %}
{% set prev = page.current - 1 %}
{% set next = page.current + 1 %}
<div class="mt-4 flex items-center justify-between text-sm">
<div class="text-slate-500 dark:text-slate-400">Showing {{ page.start }}–{{ page.end }} of {{ page.total }}</div>
<div class="flex gap-2">
<a class="btn {% if not page.has_prev %}opacity-50 pointer-events-none{% endif %}" href="?page={{ prev }}&{{ page.query }}">Prev</a>
<a class="btn {% if not page.has_next %}opacity-50 pointer-events-none{% endif %}" href="?page={{ next }}&{{ page.query }}">Next</a>
</div>
</div>
{% endif %}
<script>
async function jobAction(action, job_id){
try{
const r = await fetch('/qrush/metrics/jobs/action', {
method: 'POST', headers: {'Content-Type':'application/json'},
body: JSON.stringify({ action, job_id })
});
if(r.ok){ location.reload(); } else { alert('Action failed'); }
} catch(e){ alert('Action error'); }
}
</script>
{% endblock content %}