{# Shared job macros: row display, card, status badges, formatters. #} {% macro timestamp_cell(ts, class='') %} {% if ts and ts != 'None' and ts != '' %} {{ ts | time_ago }} {% else %}{% endif %} {% endmacro %} {% macro status_badge(status) %} {% set colors = { 'pending': 'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300', 'scheduled': 'bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300', 'running': 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900 dark:text-yellow-300', 'succeeded': 'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300', 'failed': 'bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300', 'cancelled': 'bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300', 'crashed': 'bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300', 'abandoned': 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400', } %} {{ status }} {% endmacro %} {% macro duration_fmt(ms) %} {% set s = (ms / 1000) | round(1) %} {% if s < 1 %}{{ ms | int }}ms {% elif s < 60 %}{{ s }}s {% elif s < 3600 %}{{ (s // 60) | int }}m {{ (s % 60) | int }}s {% else %}{{ (s // 3600) | int }}h {{ ((s % 3600) // 60) | int }}m {% endif %} {% endmacro %} {% macro time_ago(ts) %} {% if ts is none or ts == 'None' or ts == '' %}—{% else %} {% set now_ts = now().timestamp() if now is defined else 0 %} {% if ts is string %} {% set job_ts = ts %} {% else %} {% set job_ts = ts %} {% endif %} {{ ts[:19] if ts is string and ts | length >= 19 else ts }} {% endif %} {% endmacro %} {% macro job_row(job) %} {{ job.id }} {{ job.actor }} {{ status_badge(job.status) }} {{ job.scheduled_at }} {{ job.attempt }}/{{ job.max_attempts }} {% endmacro %} {% macro job_card(job) %}
ID
{{ job.id }}
Status
{{ status_badge(job.status) }}
Queue
{{ job.queue }}
Actor
{{ job.actor }}
Priority
{{ job.priority }}
Attempt
{{ job.attempt }} / {{ job.max_attempts }}
Scheduled At
{{ job.scheduled_at }}
Started At
{{ job.started_at or '—' }}
Finished At
{{ job.finished_at or '—' }}
{% endmacro %}