feat(297): add channelId to PlayoutListItemResponseModel; SPA reset keys directly #562

Merged
timothy merged 1 commits from issue-297-playout-channelid into main 2026-07-22 19:30:25 +02:00
Owner

Fixes #297.

What

Adds channelId to the playout list DTO so the SPA reset button keys directly on the immutable channel id, instead of the indirect channelStates lookup left behind by #288/#296.

How

  • Threaded int ChannelId through PlayoutNameViewModel (inserted after ChannelNumber) and every one of its construction sites: Mapper.ProjectToViewModel, GetPlayoutByIdHandler, and the four Update*PlayoutHandlers (all already .Include(p => p.Channel)).
  • Added int ChannelId to PlayoutListItemResponseModel (after ChannelName) and set it in PlayoutController.ToListItemResponse.
  • Regenerated OpenAPI (v1.json) + TS client (v1.d.ts) via scripts/update-openapi.sh + npm run generate:api. docs/endpoint-index.md is unchanged (this adds a field to an existing model, not an endpoint/operation).
  • Simplified PlayoutsScreen.resetSelectedChannel to resetChannelPlayout(selectedSummary.channelId); the generated type is non-nullable (PlayoutListItemResponseModel.cs has #nullable enable), so the old null-guard was dropped. channelStates is still used elsewhere in the file, so the destructure is intact.

Tests

  • Two controller test helpers (PlayoutControllerTests, ChannelControllerTests) construct PlayoutNameViewModel positionally — added the ChannelId arg so the solution compiles. 180 controller tests pass.
  • PlayoutsScreen.test.tsx: the reset test relied on the old channelStates resolution; set channelId on the fixture/reset row so it still asserts the correct /api/v1/channels/{id}/playout/reset call. 46 SPA tests pass.

Verification

  • dotnet build ErsatzTV.sln clean (0 warnings/errors); rebuilt + re-ran update-openapi.sh post-rebase → no artifact drift.
  • Controller tests 180/180, npm run typecheck clean, PlayoutsScreen vitest 46/46. BOM-check clean on the 6 touched .cs files.
  • Additive read-DTO field, not a write-path handler change, ~12 substantive lines → within the leaf carve-out of the independent-review rubric; author cold-review done.

Docs

api-conventions.md checklist followed (additive response field, OpenAPI regenerated in-PR). endpoint-index.md regenerated (no change). No new decision record — additive, no convention reversed.

Fixes #297. ## What Adds `channelId` to the playout list DTO so the SPA reset button keys directly on the immutable channel id, instead of the indirect `channelStates` lookup left behind by #288/#296. ## How - Threaded `int ChannelId` through `PlayoutNameViewModel` (inserted after `ChannelNumber`) and every one of its construction sites: `Mapper.ProjectToViewModel`, `GetPlayoutByIdHandler`, and the four `Update*PlayoutHandler`s (all already `.Include(p => p.Channel)`). - Added `int ChannelId` to `PlayoutListItemResponseModel` (after `ChannelName`) and set it in `PlayoutController.ToListItemResponse`. - Regenerated OpenAPI (`v1.json`) + TS client (`v1.d.ts`) via `scripts/update-openapi.sh` + `npm run generate:api`. `docs/endpoint-index.md` is unchanged (this adds a field to an existing model, not an endpoint/operation). - Simplified `PlayoutsScreen.resetSelectedChannel` to `resetChannelPlayout(selectedSummary.channelId)`; the generated type is non-nullable (`PlayoutListItemResponseModel.cs` has `#nullable enable`), so the old null-guard was dropped. `channelStates` is still used elsewhere in the file, so the destructure is intact. ## Tests - Two controller test helpers (`PlayoutControllerTests`, `ChannelControllerTests`) construct `PlayoutNameViewModel` positionally — added the `ChannelId` arg so the solution compiles. 180 controller tests pass. - `PlayoutsScreen.test.tsx`: the reset test relied on the old `channelStates` resolution; set `channelId` on the fixture/reset row so it still asserts the correct `/api/v1/channels/{id}/playout/reset` call. 46 SPA tests pass. ## Verification - `dotnet build ErsatzTV.sln` clean (0 warnings/errors); rebuilt + re-ran `update-openapi.sh` post-rebase → no artifact drift. - Controller tests 180/180, `npm run typecheck` clean, PlayoutsScreen vitest 46/46. BOM-check clean on the 6 touched `.cs` files. - Additive read-DTO field, not a write-path handler change, ~12 substantive lines → within the leaf carve-out of the independent-review rubric; author cold-review done. ## Docs `api-conventions.md` checklist followed (additive response field, OpenAPI regenerated in-PR). `endpoint-index.md` regenerated (no change). No new decision record — additive, no convention reversed.
timothy added the apipriority: lowfrontend labels 2026-07-22 18:59:08 +02:00
timothy added 1 commit 2026-07-22 18:59:09 +02:00
feat(297): add channelId to PlayoutListItemResponseModel; SPA reset keys directly
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 11s
PR Gates / Docs update reminder (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 20s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m37s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 21s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 4m54s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 19m41s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 16m43s
1a3c8e277f
Added ChannelId to PlayoutNameViewModel and all 6 construction sites
(Mapper, GetPlayoutByIdHandler, and the Update{,Scripted,ExternalJson,Sequential}
PlayoutHandler commands), plus the list DTO PlayoutListItemResponseModel and the
PlayoutController list projection. Regenerated OpenAPI (v1.json) and the TS client
(v1.d.ts); endpoint-index.md unchanged (no endpoint/operation delta). Simplified
PlayoutsScreen resetSelectedChannel to key directly on selectedSummary.channelId
instead of resolving via channelStates. Updated controller + SPA tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Cold author review of the diff (additive read-DTO field; not a write-path handler change; ~12 substantive lines → leaf carve-out of the independent-review rubric). ChannelId inserted at the correct positional slot in PlayoutNameViewModel (after ChannelNumber) and in PlayoutListItemResponseModel (after ChannelName); all 6 VM construction sites updated (solution compiles → none missed); every handler already .Includes Channel, so .Id is loaded (no extra query). SPA reset simplified correctly against the non-nullable generated type. OpenAPI/TS regenerated with no post-rebase drift; endpoint-index.md correctly unchanged (field, not operation). Controller tests 180/180, SPA 46/46.

Review-verdict: MERGEABLE @ 1a3c8e27

Cold author review of the diff (additive read-DTO field; not a write-path handler change; ~12 substantive lines → leaf carve-out of the independent-review rubric). `ChannelId` inserted at the correct positional slot in `PlayoutNameViewModel` (after `ChannelNumber`) and in `PlayoutListItemResponseModel` (after `ChannelName`); all 6 VM construction sites updated (solution compiles → none missed); every handler already `.Include`s `Channel`, so `.Id` is loaded (no extra query). SPA reset simplified correctly against the non-nullable generated type. OpenAPI/TS regenerated with no post-rebase drift; `endpoint-index.md` correctly unchanged (field, not operation). Controller tests 180/180, SPA 46/46. Review-verdict: MERGEABLE @ 1a3c8e27
timothy merged commit 04ca7ae981 into main 2026-07-22 19:30:25 +02:00
timothy deleted branch issue-297-playout-channelid 2026-07-22 19:30:26 +02:00
Sign in to join this conversation.