diff --git a/meteor/client/lib/__tests__/rundownTiming.test.ts b/meteor/client/lib/__tests__/rundownTiming.test.ts index 8ab6e5b17e..4557beec47 100644 --- a/meteor/client/lib/__tests__/rundownTiming.test.ts +++ b/meteor/client/lib/__tests__/rundownTiming.test.ts @@ -656,13 +656,13 @@ describe('rundown Timing Calculator', () => { partInstanceId: currentPartInstanceId, rundownId: protectString(rundownId1), manuallySelected: false, - consumesNextSegmentId: false, + consumesQueuedSegmentId: false, } playlist.nextPartInfo = { partInstanceId: nextPartInstanceId, rundownId: protectString(rundownId1), manuallySelected: false, - consumesNextSegmentId: false, + consumesQueuedSegmentId: false, } const rundown = makeMockRundown(rundownId1, playlist) const rundowns = [rundown] @@ -813,13 +813,13 @@ describe('rundown Timing Calculator', () => { partInstanceId: currentPartInstanceId, rundownId: protectString(rundownId1), manuallySelected: false, - consumesNextSegmentId: false, + consumesQueuedSegmentId: false, } playlist.nextPartInfo = { partInstanceId: nextPartInstanceId, rundownId: protectString(rundownId1), manuallySelected: false, - consumesNextSegmentId: false, + consumesQueuedSegmentId: false, } const rundown = makeMockRundown(rundownId1, playlist) const rundowns = [rundown] diff --git a/meteor/client/ui/MediaStatus/MediaStatus.tsx b/meteor/client/ui/MediaStatus/MediaStatus.tsx index 3c44fca9cf..a8eb61656e 100644 --- a/meteor/client/ui/MediaStatus/MediaStatus.tsx +++ b/meteor/client/ui/MediaStatus/MediaStatus.tsx @@ -96,7 +96,7 @@ function useRundownPlaylists(playlistIds: RundownPlaylistId[]) { metaData: 0, modified: 0, nextPartInfo: 0, - nextSegmentId: 0, + queuedSegmentId: 0, nextTimeOffset: 0, previousPartInfo: 0, previousPersistentState: 0, diff --git a/meteor/client/ui/RundownView.tsx b/meteor/client/ui/RundownView.tsx index 45bde2dcf8..12fa41923c 100644 --- a/meteor/client/ui/RundownView.tsx +++ b/meteor/client/ui/RundownView.tsx @@ -2086,7 +2086,7 @@ export const RundownView = translateWithTracker(( onSetNextSegment = (segmentId: SegmentId, e: any) => { const { t } = this.props - if (this.state.studioMode && (segmentId || segmentId === null) && this.props.playlist) { + if (this.state.studioMode && segmentId && this.props.playlist) { const playlistId = this.props.playlist._id doUserAction( t, diff --git a/meteor/client/ui/SegmentScratchpad/SegmentScratchpadContainer.tsx b/meteor/client/ui/SegmentScratchpad/SegmentScratchpadContainer.tsx index f87101e409..7074116dcc 100644 --- a/meteor/client/ui/SegmentScratchpad/SegmentScratchpadContainer.tsx +++ b/meteor/client/ui/SegmentScratchpad/SegmentScratchpadContainer.tsx @@ -243,7 +243,7 @@ export const SegmentScratchpadContainer = withResolvedSegment(function S playlist={props.playlist} isLiveSegment={isLiveSegment} isNextSegment={isNextSegment} - isQueuedSegment={props.playlist.nextSegmentId === props.segmentui._id} + isQueuedSegment={props.playlist.queuedSegmentId === props.segmentui._id} hasRemoteItems={props.hasRemoteItems} hasGuestItems={props.hasGuestItems} currentPartWillAutoNext={currentPartWillAutoNext} diff --git a/meteor/client/ui/SegmentTimeline/SegmentContextMenu.tsx b/meteor/client/ui/SegmentTimeline/SegmentContextMenu.tsx index ead5367927..d93884c88e 100644 --- a/meteor/client/ui/SegmentTimeline/SegmentContextMenu.tsx +++ b/meteor/client/ui/SegmentTimeline/SegmentContextMenu.tsx @@ -13,7 +13,7 @@ import { SegmentOrphanedReason } from '@sofie-automation/corelib/dist/dataModel/ interface IProps { onSetNext: (part: DBPart | undefined, e: any, offset?: number, take?: boolean) => void - onSetNextSegment: (segmentId: SegmentId | null, e: any) => void + onSetNextSegment: (segmentId: SegmentId, e: any) => void onQueueNextSegment: (segmentId: SegmentId | null, e: any) => void playlist?: DBRundownPlaylist studioMode: boolean diff --git a/meteor/server/api/rest/v1/playlists.ts b/meteor/server/api/rest/v1/playlists.ts index 0151cf4ff0..29dd6a6429 100644 --- a/meteor/server/api/rest/v1/playlists.ts +++ b/meteor/server/api/rest/v1/playlists.ts @@ -26,7 +26,7 @@ import { } from '../../../collections' import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist' import { ServerClientAPI } from '../../client' -import { StudioJobs } from '@sofie-automation/corelib/dist/worker/studio' +import { QueueNextSegmentResult, StudioJobs } from '@sofie-automation/corelib/dist/worker/studio' import { getCurrentTime } from '../../../../lib/lib' import { TriggerReloadDataResponse } from '../../../../lib/api/userActions' import { ServerRundownAPI } from '../../rundown' @@ -310,7 +310,7 @@ class PlaylistsServerAPI implements PlaylistsRestAPI { event: string, rundownPlaylistId: RundownPlaylistId, segmentId: SegmentId - ): Promise> { + ): Promise> { return ServerClientAPI.runUserActionInLogForPlaylistOnWorker( this.context.getMethodContext(connection), event, @@ -350,6 +350,29 @@ class PlaylistsServerAPI implements PlaylistsRestAPI { ) } + async queueNextSegment( + connection: Meteor.Connection, + event: string, + rundownPlaylistId: RundownPlaylistId, + segmentId: SegmentId + ): Promise> { + return ServerClientAPI.runUserActionInLogForPlaylistOnWorker( + this.context.getMethodContext(connection), + event, + getCurrentTime(), + rundownPlaylistId, + () => { + check(rundownPlaylistId, String) + check(segmentId, String) + }, + StudioJobs.QueueNextSegment, + { + playlistId: rundownPlaylistId, + queuedSegmentId: segmentId, + } + ) + } + async take( connection: Meteor.Connection, event: string, @@ -606,8 +629,8 @@ export function registerRoutes(registerRoute: APIRegisterHook) } ) - registerRoute<{ playlistId: string }, { segmentId: string }, void>( - 'put', + registerRoute<{ playlistId: string }, { segmentId: string }, PartId | null>( + 'post', '/playlists/:playlistId/set-next-segment', new Map([ [404, [UserErrorMessage.RundownPlaylistNotFound]], @@ -625,6 +648,25 @@ export function registerRoutes(registerRoute: APIRegisterHook) } ) + registerRoute<{ playlistId: string }, { segmentId: string }, QueueNextSegmentResult>( + 'post', + '/playlists/:playlistId/queue-next-segment', + new Map([ + [404, [UserErrorMessage.RundownPlaylistNotFound]], + [412, [UserErrorMessage.PartNotFound]], + ]), + playlistsAPIFactory, + async (serverAPI, connection, event, params, body) => { + const rundownPlaylistId = protectString(params.playlistId) + const segmentId = protectString(body.segmentId) + logger.info(`API POST: set-next-segment ${rundownPlaylistId} ${segmentId}`) + + check(rundownPlaylistId, String) + check(segmentId, String) + return await serverAPI.queueNextSegment(connection, event, rundownPlaylistId, segmentId) + } + ) + registerRoute<{ playlistId: string }, { fromPartInstanceId?: string }, void>( 'post', '/playlists/:playlistId/take',