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:
@@ -998,6 +998,7 @@ describe('ChicoryTV SPA scaffold', () => {
|
||||
confirm: true,
|
||||
playoutItems: [playoutItem()],
|
||||
playoutDetails: playout({ id: 20, scheduleKind: 'Classic' }),
|
||||
channelStates: [{ channelId: 7, channelNumber: '5.1', onAir: true, nowPlaying: null }],
|
||||
playouts: { page: [listPlayout({ id: 20, channelNumber: '5.1' })], totalCount: 1 }
|
||||
});
|
||||
|
||||
@@ -1009,8 +1010,9 @@ describe('ChicoryTV SPA scaffold', () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Reset' }));
|
||||
|
||||
await waitFor(() => {
|
||||
// Keyed on the resolved channel id (7), not the playout id (20) or the channel number.
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
'/api/channels/5.1/playout/reset',
|
||||
'/api/channels/7/playout/reset',
|
||||
expect.objectContaining({ method: 'POST' })
|
||||
);
|
||||
});
|
||||
|
||||
+10
-1
@@ -1829,8 +1829,17 @@ function PlayoutsScreen() {
|
||||
if (!selectedSummary) {
|
||||
return;
|
||||
}
|
||||
// The reset endpoint keys on the immutable channel id. The playout summary only carries the
|
||||
// channel number, so resolve the id from channel state (which covers every channel).
|
||||
const channelId = channelStates.find(
|
||||
(state) => state.channelNumber === selectedSummary.channelNumber
|
||||
)?.channelId;
|
||||
if (channelId == null) {
|
||||
setMutationError('Unable to resolve the channel for this playout.');
|
||||
return;
|
||||
}
|
||||
runMutation(`Reset the playout for ${selectedSummary.channelName}?`, () =>
|
||||
resetChannelPlayout(selectedSummary.channelNumber)
|
||||
resetChannelPlayout(channelId)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user