diff --git a/packages/blueprints-integration/src/context/partsAndPieceActionContext.ts b/packages/blueprints-integration/src/context/partsAndPieceActionContext.ts index b14601908a..22af1b509f 100644 --- a/packages/blueprints-integration/src/context/partsAndPieceActionContext.ts +++ b/packages/blueprints-integration/src/context/partsAndPieceActionContext.ts @@ -1,3 +1,4 @@ +import { ReadonlyDeep } from 'type-fest' import { IBlueprintMutatablePart, IBlueprintPart, @@ -48,6 +49,13 @@ export interface IPartAndPieceActionContext { /** Gets the Segment. This primarily allows for accessing metadata */ getSegment(segment: 'current' | 'next'): Promise + /** Get a list of the upcoming Parts in the Rundown, in the order that they will be Taken + * + * @param limit The max number of parts returned. Default is 5. + * @returns An array of Parts. If there is no next part, the array will be empty. + */ + getUpcomingParts(limit?: number): Promise> + /** * Creative actions */ diff --git a/packages/job-worker/src/blueprints/__tests__/context-OnTakeContext.test.ts b/packages/job-worker/src/blueprints/__tests__/context-OnTakeContext.test.ts index 2a7877bde9..af2ce8c190 100644 --- a/packages/job-worker/src/blueprints/__tests__/context-OnTakeContext.test.ts +++ b/packages/job-worker/src/blueprints/__tests__/context-OnTakeContext.test.ts @@ -1,14 +1,16 @@ /* eslint-disable @typescript-eslint/unbound-method */ import { IBlueprintMutatablePart, IBlueprintPiece } from '@sofie-automation/blueprints-integration' -import { PlayoutModel } from '../../playout/model/PlayoutModel.js' import { WatchedPackagesHelper } from '../context/watchedPackages.js' import { JobContext, ProcessedShowStyleCompound } from '../../jobs/index.js' import { mock } from 'jest-mock-extended' import { PartAndPieceInstanceActionService } from '../context/services/PartAndPieceInstanceActionService.js' import { OnTakeContext } from '../context/index.js' +import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part' +import { PlayoutModelImpl } from '../../playout/model/implementation/PlayoutModelImpl.js' describe('Test blueprint api context', () => { async function getTestee() { + const mockPlayoutModel = mock() const mockActionService = mock() const context = new OnTakeContext( { @@ -16,7 +18,7 @@ describe('Test blueprint api context', () => { identifier: 'action', }, mock(), - mock(), + mockPlayoutModel, mock(), mock(), mockActionService @@ -25,6 +27,7 @@ describe('Test blueprint api context', () => { return { context, mockActionService, + mockPlayoutModel, } } @@ -99,6 +102,20 @@ describe('Test blueprint api context', () => { expect(mockActionService.getPartForPreviousPiece).toHaveBeenCalledWith({ _id: 'pieceId' }) }) + test('getUpcomingParts', async () => { + const { context, mockPlayoutModel } = await getTestee() + + mockPlayoutModel.getAllOrderedParts.mockReturnValue( + mock([ + { _id: 'part1', title: 'Part 1', invalid: false, floated: false } as unknown as DBPart, + { _id: 'part2', title: 'Part 2', invalid: false, floated: false } as unknown as DBPart, + ]) + ) + + const parts = await context.getUpcomingParts() + expect(parts.map((i) => i.title)).toEqual(['Part 1', 'Part 2']) + }) + test('insertPiece', async () => { const { context, mockActionService } = await getTestee() diff --git a/packages/job-worker/src/blueprints/context/OnTakeContext.ts b/packages/job-worker/src/blueprints/context/OnTakeContext.ts index 578f038c33..6eb6e5a6ee 100644 --- a/packages/job-worker/src/blueprints/context/OnTakeContext.ts +++ b/packages/job-worker/src/blueprints/context/OnTakeContext.ts @@ -25,6 +25,7 @@ import { JobContext, ProcessedShowStyleCompound } from '../../jobs/index.js' import { executePeripheralDeviceAction, listPlayoutDevices } from '../../peripheralDevice.js' import { ActionPartChange, PartAndPieceInstanceActionService } from './services/PartAndPieceInstanceActionService.js' import { BlueprintQuickLookInfo } from '@sofie-automation/blueprints-integration/dist/context/quickLoopInfo' +import { getOrderedPartsAfterPlayhead } from '../../playout/lookahead/util.js' export class OnTakeContext extends ShowStyleUserContext implements IOnTakeContext, IEventContext { public isTakeAborted: boolean @@ -52,6 +53,10 @@ export class OnTakeContext extends ShowStyleUserContext implements IOnTakeContex this.isTakeAborted = false } + async getUpcomingParts(limit: number = 5): Promise> { + return getOrderedPartsAfterPlayhead(this._context, this._playoutModel, limit) + } + abortTake(): void { this.isTakeAborted = true } diff --git a/packages/job-worker/src/blueprints/context/adlibActions.ts b/packages/job-worker/src/blueprints/context/adlibActions.ts index 60a8aa328e..0c574ecd5f 100644 --- a/packages/job-worker/src/blueprints/context/adlibActions.ts +++ b/packages/job-worker/src/blueprints/context/adlibActions.ts @@ -32,6 +32,7 @@ import { executePeripheralDeviceAction, listPlayoutDevices } from '../../periphe import { ActionPartChange, PartAndPieceInstanceActionService } from './services/PartAndPieceInstanceActionService.js' import { BlueprintQuickLookInfo } from '@sofie-automation/blueprints-integration/dist/context/quickLoopInfo' import { setNextPartFromPart } from '../../playout/setNext.js' +import { getOrderedPartsAfterPlayhead } from '../../playout/lookahead/util.js' export class DatastoreActionExecutionContext extends ShowStyleUserContext @@ -102,6 +103,10 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct super(contextInfo, _context, showStyle, watchedPackages) } + async getUpcomingParts(limit: number = 5): Promise> { + return getOrderedPartsAfterPlayhead(this._context, this._playoutModel, limit) + } + async getPartInstance(part: 'current' | 'next'): Promise { return this.partAndPieceInstanceService.getPartInstance(part) }