From 83334803b972b008802b9dcc69be017e2460b415 Mon Sep 17 00:00:00 2001 From: Peter van Arkel Date: Tue, 19 May 2026 13:44:28 +0200 Subject: [PATCH] (feature) show latest snapshot on the Django dashboard Add latest snapshot context to each dashboard host row so imported legacy snapshots are visible without opening every host page. Link the latest snapshot directly to its detail page and show its kind and status beside the host snapshot count. Cover the dashboard latest-snapshot selection with a view test. --- .../templates/pobsync_backend/dashboard.html | 11 ++++++++++- src/pobsync_backend/tests/test_views.py | 14 ++++++++++++++ src/pobsync_backend/views.py | 10 ++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/pobsync_backend/templates/pobsync_backend/dashboard.html b/src/pobsync_backend/templates/pobsync_backend/dashboard.html index ab4c56f..ae585a4 100644 --- a/src/pobsync_backend/templates/pobsync_backend/dashboard.html +++ b/src/pobsync_backend/templates/pobsync_backend/dashboard.html @@ -46,6 +46,7 @@ Address Enabled Snapshots + Latest Snapshot Runs Retention @@ -57,11 +58,19 @@ {{ host.address }} {{ host.enabled|yesno:"yes,no" }} {{ host.snapshot_count }} + + {% if host.latest_snapshot %} + {{ host.latest_snapshot.dirname }} +
{{ host.latest_snapshot.kind }} {{ host.latest_snapshot.status }}
+ {% else %} + none + {% endif %} + {{ host.run_count }} d{{ host.retention_daily }} w{{ host.retention_weekly }} m{{ host.retention_monthly }} y{{ host.retention_yearly }} {% empty %} - No hosts configured yet. + No hosts configured yet. {% endfor %} diff --git a/src/pobsync_backend/tests/test_views.py b/src/pobsync_backend/tests/test_views.py index 3d7a3f7..31feeb0 100644 --- a/src/pobsync_backend/tests/test_views.py +++ b/src/pobsync_backend/tests/test_views.py @@ -47,6 +47,20 @@ class ViewTests(TestCase): self.assertContains(response, "20260519-021500Z__ABCDEFGH") self.assertContains(response, "success") + def test_dashboard_links_latest_snapshot_for_each_host(self) -> None: + self.client.force_login(self.staff_user) + host = HostConfig.objects.create(host="web-01", address="web-01.example.test") + old_snapshot = self._snapshot(host, "20260518-021500Z__OLDSNAP") + latest_snapshot = self._snapshot(host, "20260519-021500Z__NEWSNAP") + + response = self.client.get(reverse("dashboard")) + + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Latest Snapshot") + self.assertContains(response, latest_snapshot.dirname) + self.assertContains(response, reverse("snapshot_detail", args=[latest_snapshot.id])) + self.assertNotContains(response, reverse("snapshot_detail", args=[old_snapshot.id])) + def test_dashboard_prompts_for_global_config_when_database_is_empty(self) -> None: self.client.force_login(self.staff_user) diff --git a/src/pobsync_backend/views.py b/src/pobsync_backend/views.py index abcc24b..bde74bb 100644 --- a/src/pobsync_backend/views.py +++ b/src/pobsync_backend/views.py @@ -20,12 +20,18 @@ from .snapshot_discovery import discover_snapshots, inspect_snapshot_discovery @staff_member_required def dashboard(request): - host_qs = ( + hosts = list( HostConfig.objects.annotate(snapshot_count=Count("snapshots", distinct=True), run_count=Count("runs", distinct=True)) .order_by("host") ) + for host_config in hosts: + host_config.latest_snapshot = ( + host_config.snapshots.select_related("base") + .order_by("-started_at", "-discovered_at", "-id") + .first() + ) context = { - "hosts": host_qs, + "hosts": hosts, "global_config": GlobalConfig.objects.filter(name="default").first(), "latest_runs": BackupRun.objects.select_related("host", "snapshot").order_by("-created_at")[:10], "counts": {