(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.
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
<th>Address</th>
|
||||
<th>Enabled</th>
|
||||
<th>Snapshots</th>
|
||||
<th>Latest Snapshot</th>
|
||||
<th>Runs</th>
|
||||
<th>Retention</th>
|
||||
</tr>
|
||||
@@ -57,11 +58,19 @@
|
||||
<td>{{ host.address }}</td>
|
||||
<td>{{ host.enabled|yesno:"yes,no" }}</td>
|
||||
<td>{{ host.snapshot_count }}</td>
|
||||
<td>
|
||||
{% if host.latest_snapshot %}
|
||||
<a href="{% url 'snapshot_detail' host.latest_snapshot.id %}">{{ host.latest_snapshot.dirname }}</a>
|
||||
<div class="muted">{{ host.latest_snapshot.kind }} {{ host.latest_snapshot.status }}</div>
|
||||
{% else %}
|
||||
<span class="muted">none</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ host.run_count }}</td>
|
||||
<td>d{{ host.retention_daily }} w{{ host.retention_weekly }} m{{ host.retention_monthly }} y{{ host.retention_yearly }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="6" class="muted">No hosts configured yet.</td></tr>
|
||||
<tr><td colspan="7" class="muted">No hosts configured yet.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user