From ab5291b8d34a2e18769f9c30da118bb81d032db7 Mon Sep 17 00:00:00 2001 From: Peter van Arkel Date: Thu, 21 May 2026 13:59:16 +0200 Subject: [PATCH] (ui) Show host runs and snapshots as record cards Replace the database-style Latest Runs and Snapshots tables on the host detail page with scannable record cards and host-filtered View all links. Refs #26 --- .../templates/pobsync_backend/base.html | 47 +++++++ .../pobsync_backend/host_detail.html | 130 +++++++++++------- src/pobsync_backend/tests/test_views.py | 2 + 3 files changed, 129 insertions(+), 50 deletions(-) diff --git a/src/pobsync_backend/templates/pobsync_backend/base.html b/src/pobsync_backend/templates/pobsync_backend/base.html index 8f70d1b..f2453d6 100644 --- a/src/pobsync_backend/templates/pobsync_backend/base.html +++ b/src/pobsync_backend/templates/pobsync_backend/base.html @@ -310,6 +310,53 @@ display: grid; gap: 8px; } + .record-list { + display: grid; + gap: 10px; + } + .record-card { + border: 1px solid var(--border); + border-radius: var(--radius); + display: grid; + gap: 10px; + padding: 12px; + } + .record-card-header { + align-items: start; + display: flex; + gap: 12px; + justify-content: space-between; + } + .record-title { + display: grid; + gap: 3px; + min-width: 0; + } + .record-title a { + font-weight: 750; + overflow-wrap: anywhere; + } + .record-facts { + display: grid; + gap: 8px 16px; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + } + .record-fact { + display: grid; + gap: 2px; + min-width: 0; + } + .record-fact .label { + color: var(--muted); + font-size: 11px; + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + } + .record-fact strong, + .record-fact span { + overflow-wrap: anywhere; + } .action-row, .activity-row, .schedule-row { diff --git a/src/pobsync_backend/templates/pobsync_backend/host_detail.html b/src/pobsync_backend/templates/pobsync_backend/host_detail.html index 1ffd285..10eb2f4 100644 --- a/src/pobsync_backend/templates/pobsync_backend/host_detail.html +++ b/src/pobsync_backend/templates/pobsync_backend/host_detail.html @@ -406,58 +406,88 @@
-

Latest Runs

- - - - - - - - - - - - {% for run in latest_runs %} - - - - - - - - {% empty %} - - {% endfor %} - -
StatusStartedEndedSnapshotBase
{{ run.status }}{{ run.started_at|default:"" }}{{ run.ended_at|default:"" }}{% if run.snapshot %}{{ run.snapshot.dirname }}{% else %}{{ run.snapshot_path }}{% endif %}{{ run.base_path|default:"" }}
No backup runs recorded for this host.
+

Latest Runs View all

+
+ {% for run in latest_runs %} +
+
+
+ Run {{ run.id }} + {{ run.run_type }}{% if run.result.duration_seconds %} ยท {{ run.result.duration_seconds }}s{% endif %} +
+ {{ run.status }} +
+
+
+ Started + {{ run.started_at|default:run.created_at }} +
+
+ Ended + {{ run.ended_at|default:"running or queued" }} +
+
+ Snapshot + {% if run.snapshot %} + {{ run.snapshot.dirname }} + {% elif run.snapshot_path %} + {{ run.snapshot_path }} + {% else %} + none + {% endif %} +
+
+ Base + {{ run.base_path|default:"none" }} +
+
+
+ {% empty %} +

No backup runs recorded for this host.

+ {% endfor %} +
-

Snapshots

- - - - - - - - - - - - {% for snapshot in snapshots %} - - - - - - - - {% empty %} - - {% endfor %} - -
KindStatusStartedDirnameBase
{{ snapshot.kind }}{{ snapshot.status }}{{ snapshot.started_at|default:"" }}{{ snapshot.dirname }}{% if snapshot.base %}{{ snapshot.base.dirname }}{% else %}{{ snapshot.base_dirname }}{% endif %}
No snapshots discovered for this host.
+

Snapshots View all

+
+ {% for snapshot in snapshots %} +
+
+
+ {{ snapshot.dirname }} + {{ snapshot.kind }} +
+ {{ snapshot.status }} +
+
+
+ Started + {{ snapshot.started_at|default:"unknown" }} +
+
+ Ended + {{ snapshot.ended_at|default:"unknown" }} +
+
+ Base + {% if snapshot.base %} + {{ snapshot.base.dirname }} + {% elif snapshot.base_dirname %} + {{ snapshot.base_dirname }} + {% else %} + none + {% endif %} +
+
+ Path + {{ snapshot.path|default:"not recorded" }} +
+
+
+ {% empty %} +

No snapshots discovered for this host.

+ {% endfor %} +
{% endblock %} diff --git a/src/pobsync_backend/tests/test_views.py b/src/pobsync_backend/tests/test_views.py index c5d73ae..1f63df6 100644 --- a/src/pobsync_backend/tests/test_views.py +++ b/src/pobsync_backend/tests/test_views.py @@ -940,6 +940,8 @@ class ViewTests(TestCase): self.assertContains(response, reverse("queue_manual_backup", args=[host.host])) self.assertContains(response, reverse("run_detail", args=[BackupRun.objects.get().id])) self.assertContains(response, reverse("snapshot_detail", args=[snapshot.id])) + self.assertContains(response, f'{reverse("runs_list")}?host={host.host}', html=False) + self.assertContains(response, f'{reverse("snapshots_list")}?host={host.host}', html=False) def test_host_detail_renders_effective_config_preview(self) -> None: self.client.force_login(self.staff_user)