feat(api): playout read endpoints (#100 #101 #107 #110) #116

Merged
timothy merged 1 commits from feat/playouts-read-api into main 2026-07-03 22:50:06 +02:00
Owner

Playout read API — unblocks #87 (Playouts screen).

Endpoints

  • GET /api/playouts — paged list (query/pageNum/pageSize) via existing GetPagedPlayouts; list items carry id, channelNumber/Name, scheduleKind/Name, dailyRebuildTime, nullable buildStatus (#100, #107)
  • GET /api/playouts/{id}/items — paged future items (showFiller/pageNum/pageSize) via GetFuturePlayoutItemsById; nullable fillerKind for gaps; 404 for unknown playout id (ScheduleController precedent) with OpenApiErrorResponseContractTests entry (#101)
  • GET /api/playouts/warnings/count (#107)
  • POST /api/playouts/reset-all — 202 Accepted → ResetAllPlayouts (#110)
  • POST /api/channels/{channelNumber}/playout/reset — optional mode param, defaulting per ScheduleKind (Classic→Refresh, others→Reset), matching Playouts.razor (#110)
  • GET /api/playouts/{id} now includes buildStatus (.Include(BuildStatus) + PlayoutResponseModel.From) (#107)

Notes

  • Salvaged WIP 49a6d4ee audited, rebased onto main, fixed: nonexistent Option<FillerKind>.ToNullable() → MatchUnsafe (Health/Mapper idiom); ChannelControllerTests.ResetPlayout signature break; added mode-defaulting + 404 + DailyRebuildTime test coverage.
  • Adversarial review verdict: FIX-FIRST → fixed. Major (fixed): DTOs lacked #nullable enable, so OpenAPI wrongly documented buildStatus/scheduleFile non-nullable — would have broken SPA typegen. Nit fixed: Name=ResetAllPlayouts. Deferred as backlog notes: lightweight exists-check for the items 404 pre-check; pageSize clamping (matches existing convention).
  • ./scripts/update-openapi.sh re-run (regen authoritative); build 0 errors; TZ=UTC tests 289/289 green.

fixes #100, fixes #101, fixes #107, fixes #110

🤖 Generated with Claude Code

Playout read API — unblocks #87 (Playouts screen). ## Endpoints - `GET /api/playouts` — paged list (query/pageNum/pageSize) via existing `GetPagedPlayouts`; list items carry id, channelNumber/Name, scheduleKind/Name, dailyRebuildTime, nullable buildStatus (#100, #107) - `GET /api/playouts/{id}/items` — paged future items (showFiller/pageNum/pageSize) via `GetFuturePlayoutItemsById`; nullable fillerKind for gaps; **404** for unknown playout id (ScheduleController precedent) with OpenApiErrorResponseContractTests entry (#101) - `GET /api/playouts/warnings/count` (#107) - `POST /api/playouts/reset-all` — 202 Accepted → `ResetAllPlayouts` (#110) - `POST /api/channels/{channelNumber}/playout/reset` — optional `mode` param, defaulting per ScheduleKind (Classic→Refresh, others→Reset), matching Playouts.razor (#110) - `GET /api/playouts/{id}` now includes buildStatus (`.Include(BuildStatus)` + `PlayoutResponseModel.From`) (#107) ## Notes - Salvaged WIP 49a6d4ee audited, rebased onto main, fixed: nonexistent `Option<FillerKind>.ToNullable()` → `MatchUnsafe` (Health/Mapper idiom); `ChannelControllerTests.ResetPlayout` signature break; added mode-defaulting + 404 + DailyRebuildTime test coverage. - Adversarial review verdict: FIX-FIRST → fixed. Major (fixed): DTOs lacked `#nullable enable`, so OpenAPI wrongly documented buildStatus/scheduleFile non-nullable — would have broken SPA typegen. Nit fixed: `Name=ResetAllPlayouts`. Deferred as backlog notes: lightweight exists-check for the items 404 pre-check; pageSize clamping (matches existing convention). - `./scripts/update-openapi.sh` re-run (regen authoritative); build 0 errors; `TZ=UTC` tests 289/289 green. fixes #100, fixes #101, fixes #107, fixes #110 🤖 Generated with [Claude Code](https://claude.com/claude-code)
timothy added 1 commit 2026-07-03 22:28:28 +02:00
feat(api): playout read endpoints + reset-all (#100 #101 #107 #110)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 2m59s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m2s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
20ca71b388
- GET /api/playouts — paged list over GetPagedPlayouts (query/pageNum/pageSize), list DTO with buildStatus (#100, #107)
- GET /api/playouts/{id}/items — paged future items + UNSCHEDULED gaps over GetFuturePlayoutItemsById; 404 ProblemDetails for unknown playout (matches /api/schedules/{id}/items precedent) (#101)
- buildStatus {lastBuild, success, message} on GET /api/playouts/{id} (BuildStatus now included by GetPlayoutByIdHandler) (#107)
- GET /api/playouts/warnings/count — failed-build count for the warnings badge (#107)
- POST /api/playouts/reset-all — 202 Accepted, wraps ResetAllPlayouts (#110)
- POST /api/channels/{channelNumber}/playout/reset — optional ?mode= override; default branches by ScheduleKind (Classic→Refresh, others→Reset) to match Blazor semantics (#110)
- Option<FillerKind>→FillerKind? projection uses MatchUnsafe (Match throws on null-returning branch; idiom per Health/Mapper.cs)
- Tests: controller unit tests (routes, projections, 404s, reset-mode defaults), OpenAPI ProblemDetails contract entry for /api/playouts/{id}/items get 404
- Regenerated wwwroot/openapi/v1.json

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
timothy merged commit abd8ca34c9 into main 2026-07-03 22:50:06 +02:00
Sign in to join this conversation.