diff --git a/server/backend/internal/httpapi/playerstatus.go b/server/backend/internal/httpapi/playerstatus.go index e865a47..4eb8471 100644 --- a/server/backend/internal/httpapi/playerstatus.go +++ b/server/backend/internal/httpapi/playerstatus.go @@ -158,6 +158,8 @@ func handleListLatestPlayerStatuses(store playerStatusStore) http.HandlerFunc { func buildScreenStatusOverview(store playerStatusStore, query url.Values) (screenStatusOverview, error) { records := store.List() + screenIDFilter := strings.ToLower(strings.TrimSpace(query.Get("q"))) + wantConnectivity := strings.TrimSpace(query.Get("server_connectivity")) switch wantConnectivity { case "", "online", "degraded", "offline", "unknown": @@ -202,6 +204,9 @@ func buildScreenStatusOverview(store playerStatusStore, query url.Values) (scree if records[i].Stale { overview.Summary.Stale++ } + if screenIDFilter != "" && !strings.Contains(strings.ToLower(records[i].ScreenID), screenIDFilter) { + continue + } if updatedSince != nil && !isUpdatedSince(records[i], *updatedSince) { continue } diff --git a/server/backend/internal/httpapi/playerstatus_test.go b/server/backend/internal/httpapi/playerstatus_test.go index 8002ca6..eb90963 100644 --- a/server/backend/internal/httpapi/playerstatus_test.go +++ b/server/backend/internal/httpapi/playerstatus_test.go @@ -579,6 +579,55 @@ func TestHandleListLatestPlayerStatusesAppliesLimit(t *testing.T) { } } +func TestHandleListLatestPlayerStatusesFiltersByScreenIDSubstring(t *testing.T) { + store := newInMemoryPlayerStatusStore() + store.Save(playerStatusRecord{ScreenID: "info01-dev", Timestamp: "2026-03-22T16:00:00Z", Status: "running", ServerConnectivity: "online"}) + store.Save(playerStatusRecord{ScreenID: "info02-dev", Timestamp: "2026-03-22T16:00:00Z", Status: "running", ServerConnectivity: "online"}) + store.Save(playerStatusRecord{ScreenID: "lobby-main", Timestamp: "2026-03-22T16:00:00Z", Status: "running", ServerConnectivity: "online"}) + + req := httptest.NewRequest(http.MethodGet, "/api/v1/screens/status?q=info", nil) + w := httptest.NewRecorder() + + handleListLatestPlayerStatuses(store)(w, req) + + var response struct { + Screens []playerStatusRecord `json:"screens"` + } + if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { + t.Fatalf("Unmarshal() error = %v", err) + } + + if got, want := len(response.Screens), 2; got != want { + t.Fatalf("len(response.Screens) = %d, want %d", got, want) + } +} + +func TestHandleListLatestPlayerStatusesScreenIDFilterIsCaseInsensitive(t *testing.T) { + store := newInMemoryPlayerStatusStore() + store.Save(playerStatusRecord{ScreenID: "INFO01-DEV", Timestamp: "2026-03-22T16:00:00Z", Status: "running", ServerConnectivity: "online"}) + store.Save(playerStatusRecord{ScreenID: "lobby-main", Timestamp: "2026-03-22T16:00:00Z", Status: "running", ServerConnectivity: "online"}) + + req := httptest.NewRequest(http.MethodGet, "/api/v1/screens/status?q=info01", nil) + w := httptest.NewRecorder() + + handleListLatestPlayerStatuses(store)(w, req) + + var response struct { + Screens []playerStatusRecord `json:"screens"` + } + if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { + t.Fatalf("Unmarshal() error = %v", err) + } + + if got, want := len(response.Screens), 1; got != want { + t.Fatalf("len(response.Screens) = %d, want %d", got, want) + } + + if got, want := response.Screens[0].ScreenID, "INFO01-DEV"; got != want { + t.Fatalf("response.Screens[0].ScreenID = %q, want %q", got, want) + } +} + func TestHandleListLatestPlayerStatusesRejectsInvalidServerConnectivity(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/api/v1/screens/status?server_connectivity=garbage", nil) w := httptest.NewRecorder() diff --git a/server/backend/internal/httpapi/statuspage.go b/server/backend/internal/httpapi/statuspage.go index 00d1757..a88bcd9 100644 --- a/server/backend/internal/httpapi/statuspage.go +++ b/server/backend/internal/httpapi/statuspage.go @@ -19,6 +19,7 @@ type statusPageData struct { } type statusPageFilters struct { + ScreenIDFilter string ServerConnectivity string Stale string UpdatedSince string @@ -499,6 +500,11 @@ var statusPageTemplate = template.Must(template.New("status-page").Funcs(statusT