{% extends "base.html" %}
{% block title %}Queues - Queue Manager{% endblock %}
{% block content %}
<div class="space-y-6">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold text-white">Queue Browser</h1>
<div class="flex items-center gap-3">
<select name="source" id="source-select"
class="bg-gray-800 border border-gray-700 text-white text-sm rounded px-3 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
onchange="navigateWithSource(this.value)">
<option value="queue" {% if t.is_queue_source %}selected{% endif %}>Queue</option>
<option value="dlq" {% if t.is_dlq_source %}selected{% endif %}>DLQ</option>
<option value="archive" {% if t.is_archive_source %}selected{% endif %}>Archive</option>
</select>
<form method="get" id="filter-form" class="flex items-center gap-3">
<input type="hidden" name="source" value="{{ t.selected_source }}">
<select name="queue"
class="bg-gray-800 border border-gray-700 text-white text-sm rounded px-3 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
onchange="this.form.submit()">
<option value="">All Queues</option>
{% for (q, sel) in queues %}
<option value="{{ q }}" {% if sel %}selected{% endif %}>{{ q }}</option>
{% endfor %}
</select>
<select name="status"
class="bg-gray-800 border border-gray-700 text-white text-sm rounded px-3 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
onchange="this.form.submit()">
<option value="">All Statuses</option>
<option value="pending" {% if t.sel_pending %}selected{% endif %}>Pending</option>
<option value="running" {% if t.sel_running %}selected{% endif %}>Running</option>
<option value="completed" {% if t.sel_completed %}selected{% endif %}>Completed</option>
<option value="failed" {% if t.sel_failed %}selected{% endif %}>Failed</option>
</select>
</form>
</div>
</div>
<div id="job-table-wrapper">
<div class="bg-gray-900 rounded-lg border border-gray-800 overflow-hidden">
{% if t.jobs.is_empty() %}
<div class="px-4 py-12 text-center text-gray-500">No jobs found</div>
{% else %}
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="text-left text-gray-400 text-xs uppercase tracking-wider">
<th class="px-4 py-3">ID</th>
<th class="px-4 py-3"><a href="{{ t.sort_link_status }}" class="hover:text-white">Status</a></th>
<th class="px-4 py-3"><a href="{{ t.sort_link_attempt }}" class="hover:text-white">Atmpt</a></th>
<th class="px-4 py-3"><a href="{{ t.sort_link_reprocess_count }}" class="hover:text-white">Reproc</a></th>
<th class="px-4 py-3"><a href="{{ t.sort_link_created_at }}" class="hover:text-white">Created At</a></th>
<th class="px-4 py-3"><a href="{{ t.sort_link_run_at }}" class="hover:text-white">Run At</a></th>
<th class="px-4 py-3"><a href="{{ t.sort_link_updated_at }}" class="hover:text-white">Updated At</a></th>
<th class="px-4 py-3">Actions</th>
</tr>
</thead>
<tbody>
{% for job in t.jobs %}
<tr class="border-t border-gray-800 hover:bg-gray-800/50">
<td class="px-4 py-2">
<a href="/jobs/{{ job.id }}?source={{ job.source }}"
class="text-blue-400 hover:text-blue-300 font-mono text-xs">
{{ job.short_id }}
</a>
</td>
<td class="px-4 py-2">
<span class="text-xs px-2 py-0.5 rounded
{% if job.status == "pending" %}bg-yellow-900/50 text-yellow-300
{% else if job.status == "running" %}bg-blue-900/50 text-blue-300
{% else if job.status == "completed" %}bg-green-900/50 text-green-300
{% else if job.status == "failed" %}bg-red-900/50 text-red-300
{% else if job.status == "cancelled" %}bg-gray-800 text-gray-500
{% else %}bg-gray-800 text-gray-400{% endif %}">
{{ job.status }}
</span>
</td>
<td class="px-4 py-2 text-gray-300 font-mono text-xs">{{ job.attempt }}/{{ job.max_attempts }}</td>
<td class="px-4 py-2 text-gray-400 font-mono text-xs">{{ job.reprocess_count }}</td>
<td class="px-4 py-2 text-xs"><div class="leading-none">{{ job.created_at_date }}</div><div class="text-[10px] text-gray-500 leading-none mt-0.5">{{ job.created_at_time }}</div></td>
<td class="px-4 py-2 text-xs"><div class="leading-none">{{ job.run_at_date }}</div><div class="text-[10px] text-gray-500 leading-none mt-0.5">{{ job.run_at_time }}</div></td>
<td class="px-4 py-2 text-xs"><div class="leading-none">{{ job.updated_at_date }}</div><div class="text-[10px] text-gray-500 leading-none mt-0.5">{{ job.updated_at_time }}</div></td>
<td class="px-4 py-2">
<div class="flex items-center gap-1">
<a href="/jobs/{{ job.id }}?source={{ job.source }}"
class="text-xs text-blue-400 hover:text-blue-300 px-2 py-1">Inspect</a>
{% if t.is_queue_source %}
<form method="post" action="/jobs/{{ job.id }}/restart?queue={{ t.selected_queue }}&page={{ t.page }}&source=queue"
class="inline" onsubmit="return confirm('Restart this job?')">
<button type="submit" class="text-xs text-yellow-400 hover:text-yellow-300 px-2 py-1">Restart</button>
</form>
<form method="post" action="/jobs/{{ job.id }}/cancel?queue={{ t.selected_queue }}&page={{ t.page }}&source=queue"
class="inline" onsubmit="return confirm('Cancel this job?')">
<button type="submit" class="text-xs text-red-400 hover:text-red-300 px-2 py-1">Cancel</button>
</form>
{% endif %}
{% if t.is_dlq_source || t.is_archive_source %}
<form method="post" action="/jobs/{{ job.id }}/requeue?queue={{ t.selected_queue }}&page={{ t.page }}&source={{ t.selected_source }}"
class="inline" onsubmit="return confirm('Move this job to queue as pending?')">
<button type="submit" class="text-xs text-green-400 hover:text-green-300 px-2 py-1">Requeue</button>
</form>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="px-4 py-3 border-t border-gray-800 flex items-center justify-between text-sm">
<div class="text-gray-400">
{{ t.show_from }}-{{ t.show_to }} of {{ t.total }}
</div>
<div class="flex items-center gap-2">
{% if t.page > 1 %}
<a href="/queues/browse?queue={{ t.selected_queue }}&source={{ t.selected_source }}&sort_by={{ t.sort_by }}&sort_dir={{ t.sort_dir }}&page={{ t.page - 1 }}"
class="px-3 py-1 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded text-xs transition-colors">
Prev
</a>
{% endif %}
<span class="text-gray-500 text-xs">Page {{ t.page }} of {{ t.total_pages }}</span>
{% if t.page < t.total_pages %}
<a href="/queues/browse?queue={{ t.selected_queue }}&source={{ t.selected_source }}&sort_by={{ t.sort_by }}&sort_dir={{ t.sort_dir }}&page={{ t.page + 1 }}"
class="px-3 py-1 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded text-xs transition-colors">
Next
</a>
{% endif %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
<script>
function navigateWithSource(source) {
const params = new URLSearchParams(window.location.search);
params.set('source', source);
window.location.search = params.toString();
}
</script>
{% endblock %}