diff --git a/internal/server/http/dashboard_filter_test.go b/internal/server/http/dashboard_filter_test.go index 61b2b47..bc58b85 100644 --- a/internal/server/http/dashboard_filter_test.go +++ b/internal/server/http/dashboard_filter_test.go @@ -11,6 +11,7 @@ import ( "time" "gitea.dcglab.co.uk/steve/restic-manager/internal/store" + "gitea.dcglab.co.uk/steve/restic-manager/internal/version" ) func makeFilterHosts() []store.Host { @@ -98,6 +99,23 @@ func TestSortDashboardHostsColumns(t *testing.T) { } } +// TestFilterAndSortDashboardUpdatesBehind: ?updates=behind narrows +// to hosts whose agent_version is non-empty AND != server's version. +func TestFilterAndSortDashboardUpdatesBehind(t *testing.T) { + t.Parallel() + hosts := []store.Host{ + {ID: "01a", Name: "alpha", AgentVersion: "v0.0.1", Status: "online"}, + {ID: "01b", Name: "bravo", AgentVersion: version.Version, Status: "online"}, + {ID: "01c", Name: "charlie", AgentVersion: "", Status: "online"}, // never seen + {ID: "01d", Name: "delta", AgentVersion: "v0.0.1", Status: "offline"}, + } + got := filterAndSortDashboardHosts(hosts, dashboardFilter{Updates: "behind", Sort: "name", Dir: "asc"}) + // alpha + delta both behind; bravo (current) and charlie (empty) excluded. + if len(got) != 2 || got[0].Name != "alpha" || got[1].Name != "delta" { + t.Errorf("updates=behind: got %v", namesOf(got)) + } +} + // TestParseDashboardFilterDefaults: empty query gives sort=name asc. func TestParseDashboardFilterDefaults(t *testing.T) { t.Parallel() diff --git a/web/templates/pages/dashboard.html b/web/templates/pages/dashboard.html index b4ffb23..e29dbc8 100644 --- a/web/templates/pages/dashboard.html +++ b/web/templates/pages/dashboard.html @@ -66,6 +66,16 @@ + {{/* ---------- Hosts-behind hero tile (P6-18) ---------- */}} + {{if gt $page.UpdatesBehind 0}} +
+ + {{$page.UpdatesBehind}} + {{if eq $page.UpdatesBehind 1}}host behind{{else}}hosts behind{{end}} · review → + +
+ {{end}} + {{/* ---------- Pending hosts (announce-and-approve queue) ---------- */}} {{if gt (len $page.PendingHosts) 0}}