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.
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.
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>
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.
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #297.
What
Adds
channelIdto the playout list DTO so the SPA reset button keys directly on the immutable channel id, instead of the indirectchannelStateslookup left behind by #288/#296.How
int ChannelIdthroughPlayoutNameViewModel(inserted afterChannelNumber) and every one of its construction sites:Mapper.ProjectToViewModel,GetPlayoutByIdHandler, and the fourUpdate*PlayoutHandlers (all already.Include(p => p.Channel)).int ChannelIdtoPlayoutListItemResponseModel(afterChannelName) and set it inPlayoutController.ToListItemResponse.v1.json) + TS client (v1.d.ts) viascripts/update-openapi.sh+npm run generate:api.docs/endpoint-index.mdis unchanged (this adds a field to an existing model, not an endpoint/operation).PlayoutsScreen.resetSelectedChanneltoresetChannelPlayout(selectedSummary.channelId); the generated type is non-nullable (PlayoutListItemResponseModel.cshas#nullable enable), so the old null-guard was dropped.channelStatesis still used elsewhere in the file, so the destructure is intact.Tests
PlayoutControllerTests,ChannelControllerTests) constructPlayoutNameViewModelpositionally — added theChannelIdarg so the solution compiles. 180 controller tests pass.PlayoutsScreen.test.tsx: the reset test relied on the oldchannelStatesresolution; setchannelIdon the fixture/reset row so it still asserts the correct/api/v1/channels/{id}/playout/resetcall. 46 SPA tests pass.Verification
dotnet build ErsatzTV.slnclean (0 warnings/errors); rebuilt + re-ranupdate-openapi.shpost-rebase → no artifact drift.npm run typecheckclean, PlayoutsScreen vitest 46/46. BOM-check clean on the 6 touched.csfiles.Docs
api-conventions.mdchecklist followed (additive response field, OpenAPI regenerated in-PR).endpoint-index.mdregenerated (no change). No new decision record — additive, no convention reversed.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>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).
ChannelIdinserted at the correct positional slot inPlayoutNameViewModel(afterChannelNumber) and inPlayoutListItemResponseModel(afterChannelName); all 6 VM construction sites updated (solution compiles → none missed); every handler already.IncludesChannel, so.Idis loaded (no extra query). SPA reset simplified correctly against the non-nullable generated type. OpenAPI/TS regenerated with no post-rebase drift;endpoint-index.mdcorrectly unchanged (field, not operation). Controller tests 180/180, SPA 46/46.Review-verdict: MERGEABLE @
1a3c8e27