From 3d1a7190edf1209668c148c5e4bb02fa82f23c90 Mon Sep 17 00:00:00 2001 From: catborise Date: Sat, 31 Oct 2026 11:45:45 +0300 Subject: [PATCH] feat(operations): the jobs list as a card with progress, the job page as one record The Jobs list sits in a card: the count and the filters in its header, the job with its phase, its progress and its date in one cell, the state at the row's end. The job page is one card: resource, user and state on top, then the phase, Cancel and the progress, the error and the results, and a timeline that says how long the job waited and ran. Resolving an uncertain job folds into its own card. --- operations/templates/operations/job.html | 159 ++++++++++-------- operations/templates/operations/jobs.html | 138 ++++++++------- operations/templatetags/operations.py | 13 +- operations/tests/test_views.py | 45 +++-- operations/views.py | 1 + .../icon_cache/play-circle_None_None_None.svg | 11 ++ .../icon_cache/plus-circle_None_None_None.svg | 11 ++ .../icon_cache/stop-circle_None_None_None.svg | 11 ++ 8 files changed, 241 insertions(+), 148 deletions(-) create mode 100644 static/icon_cache/play-circle_None_None_None.svg create mode 100644 static/icon_cache/plus-circle_None_None_None.svg create mode 100644 static/icon_cache/stop-circle_None_None_None.svg diff --git a/operations/templates/operations/job.html b/operations/templates/operations/job.html index e786b16e..0c4ac48f 100644 --- a/operations/templates/operations/job.html +++ b/operations/templates/operations/job.html @@ -2,105 +2,122 @@ {% load i18n %} {% load bootstrap_icons %} {% load operations %} -{% load tz %} {% block title %}{{ job.label }}{% endblock %} {% block page_heading %}{{ job.label }}{% endblock page_heading %} {% block page_heading_extra %} -
- {% if job.cancellable %} -
- {% csrf_token %} - -
- {% endif %} - {% trans "Jobs" %} -
+ {% trans "Jobs" %} {% endblock page_heading_extra %} {% block content %} -
-
- {% if op.error %} - - {% endif %} -
-
{% trans "Resource" %}
{{ job.resource_label }}
-
{% trans "User" %}
{{ job.username }}
-
{% trans "State" %}
-
{% include "operations/state_badge.html" with state=op.state %}
- {% if op.phase %}
{% trans "Phase" %}
{% translate op.phase %}
{% endif %} +
+
+
+ {{ job.resource_label }} + {% include "operations/state_badge.html" with state=op.state %} +
+
{% trans "User" %}: {{ job.username }}
+
+ {% if op.phase or op.progress_total or job.cancellable or op.error or job.result.links or job.result.warning or job.result.left_behind or job.resolution %} +
+ {% if op.phase or job.cancellable %} +
+ {% if op.phase %}{% translate op.phase %}{% endif %} + {% if job.cancellable %} +
+ {% csrf_token %} + +
+ {% endif %} +
+ {% endif %} {% if op.progress_total %} {% widthratio op.progress_done|default:0 op.progress_total 100 as percent %} -
{% trans "Progress" %}
-
-
-
{{ percent }}%
-
- +
+ {% if progress_bytes %}{{ op.progress_done|default:0|filesizeformat }} / {{ op.progress_total|filesizeformat }}{% else %}{{ op.progress_done|default:0 }} / {{ op.progress_total }}{% endif %} -
+ {{ percent }}% +
+
+
+
{% endif %} - {% get_current_timezone as TIME_ZONE %} -
{% blocktrans %}Created ({{ TIME_ZONE }}){% endblocktrans %}
{{ op.created_at|date:"Y-m-d H:i:s" }}
- {% if op.started_at %}
{% trans "Started" %}
{{ op.started_at|date:"Y-m-d H:i:s" }}
{% endif %} - {% if op.finished_at %}
{% trans "Finished" %}
{{ op.finished_at|date:"Y-m-d H:i:s" }}
{% endif %} - {% if job.result.left_behind %} -
{% trans "Left behind" %}
-
-
    - {% for item in job.result.left_behind %}
  • {{ item }}
  • {% endfor %} -
-
- {% endif %} - {% if job.result.warning %} -
{% trans "Warning" %}
{{ job.result.warning }}
+ {% if op.error %} + {% endif %} {% if job.result.links %} -
{% trans "Results" %}
-
- -
+

{% trans "Results" %}

+ + {% endif %} + {% if job.result.warning %} + + {% endif %} + {% if job.result.left_behind %} +

{% trans "Left behind" %}

+
    + {% for item in job.result.left_behind %}
  • {{ item }}
  • {% endfor %} +
{% endif %} {% if job.resolution %} -
{% trans "Resolution" %}
-
{{ job.resolution|state_label }}: {{ job.resolution_note }}
+

{% trans "Resolution" %}

+

{{ job.resolution|state_label }}: {{ job.resolution_note }}

{% endif %} -
+
+ {% endif %} +
    +
  1. + {% bs_icon 'plus-circle' %} {% trans "Created" %} + {{ op.created_at|date:"Y-m-d H:i:s T" }} +
  2. + {% if op.started_at %} +
  3. + {% bs_icon 'play-circle' %} {% trans "Started" %} · {% blocktrans with time=op.created_at|duration:op.started_at %}queued for {{ time }}{% endblocktrans %} + {{ op.started_at|date:"Y-m-d H:i:s T" }} +
  4. + {% endif %} + {% if op.finished_at %} +
  5. + {% bs_icon 'stop-circle' %} {% trans "Finished" %}{% if op.started_at %} · {% blocktrans with time=op.started_at|duration:op.finished_at %}ran for {{ time }}{% endblocktrans %}{% endif %} + {{ op.finished_at|date:"Y-m-d H:i:s T" }} +
  6. + {% endif %} +
+
- {% if request.user.is_superuser and op.state == "uncertain" %} -
{% trans "Resolve" %}
+{% if request.user.is_superuser and op.state == "uncertain" %} +
+ + {% trans "Resolve" %} + {% trans "Record what you checked; the job is marked succeeded or failed." %} + +
{% csrf_token %} -
- -
- -
+
+ +
-
- -
- -
+
+ +
- {% endif %} -
-
+
+
+{% endif %} {% endblock %} {% block script %} {% if follow %}{% include "operations/follow_active.html" %}{% endif %} diff --git a/operations/templates/operations/jobs.html b/operations/templates/operations/jobs.html index 9114a8de..e14794d5 100644 --- a/operations/templates/operations/jobs.html +++ b/operations/templates/operations/jobs.html @@ -3,96 +3,106 @@ {% load django_bootstrap5 %} {% load bootstrap_icons %} {% load operations %} -{% load tz %} {% block title %}{% trans "Jobs" %}{% endblock %} {% block page_heading %}{% trans "Jobs" %}{% endblock page_heading %} {% block content %} -
-
- {% if worker_unavailable %} -
- {% bs_icon 'exclamation-triangle' %} {% trans "Worker unavailable, last seen" %} - {% if worker_last_seen %}{{ worker_last_seen|date:"Y-m-d H:i:s" }}{% else %}{% trans "never" %}{% endif %} -
- {% endif %} +{% if worker_unavailable %} +
+ {% bs_icon 'exclamation-triangle' %} {% trans "Worker unavailable, last seen" %} + {% if worker_last_seen %}{{ worker_last_seen|date:"Y-m-d H:i:s T" }}{% else %}{% trans "never" %}{% endif %} +
+{% endif %} +
+
+ {% trans "Jobs" %} {{ page.paginator.count }} {% if request.user.is_superuser %} -