feat(api): #288/#197 wrap ChannelViewModel + re-key playout/reset to {id}

GetById/Create/Update return ChannelResponseModel via new GetChannelByIdForApi
read-side query; POST /api/channels/{id:int}/playout/reset (new
GetPlayoutIdByChannelId; by-number kept for HlsSessionWorker broadcast).

Refs #288 #197

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 02:08:12 +02:00
co-authored by Claude Opus 4.8
parent 9e2d160884
commit 5f89bfc1a0
13 changed files with 273 additions and 53 deletions
+3 -12
View File
@@ -115,25 +115,16 @@ describe('playouts api client', () => {
expect(init).toMatchObject({ method: 'DELETE' });
});
it('resetChannelPlayout POSTs to the channel playout reset route without a mode', async () => {
it('resetChannelPlayout POSTs to the id-keyed channel playout reset route without a mode', async () => {
const fetchMock = vi.spyOn(window, 'fetch').mockResolvedValue(jsonResponse({}));
await resetChannelPlayout('12.3');
await resetChannelPlayout(20);
const [url, init] = fetchMock.mock.calls[0];
expect(url).toBe('/api/channels/12.3/playout/reset');
expect(url).toBe('/api/channels/20/playout/reset');
expect(init).toMatchObject({ method: 'POST' });
});
it('resetChannelPlayout url-encodes the channel number', async () => {
const fetchMock = vi.spyOn(window, 'fetch').mockResolvedValue(jsonResponse({}));
await resetChannelPlayout('a b');
const [url] = fetchMock.mock.calls[0];
expect(url).toBe('/api/channels/a%20b/playout/reset');
});
it('erasePlayoutItems POSTs to the erase-items route', async () => {
const fetchMock = vi.spyOn(window, 'fetch').mockResolvedValue(noContentResponse());
+3 -2
View File
@@ -123,8 +123,9 @@ export function deletePlayout(playoutId: number): Promise<void> {
// Resets the given channel's playout. The server picks the correct default mode per schedule kind
// (Classic → Refresh, others → Reset), matching the Blazor "Reset Playout" action — so no mode is sent.
export function resetChannelPlayout(channelNumber: string): Promise<void> {
return request<void>(`/api/channels/${encodeURIComponent(channelNumber)}/playout/reset`, { method: 'POST' });
// Keyed on the immutable channel id (not the user-mutable number), matching the /api/channels/{id} contract.
export function resetChannelPlayout(channelId: number): Promise<void> {
return request<void>(`/api/channels/${channelId}/playout/reset`, { method: 'POST' });
}
export function erasePlayoutItems(playoutId: number): Promise<void> {