mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-15 04:13:47 +00:00
feat: event cue (#473)
* feat: parse cue * refactor: get delay from backend * feat: add cue to UI * refactor: remove deprecated delay logic * refactor: extract studio clock specific logic * refactor: extract utilities * refactor: fix issue with missing key * style: prevent cue overflow * style: prevent whitespace wrap * feat: add support for cues in integrations
This commit is contained in:
@@ -62,6 +62,21 @@ export class PlaybackService {
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* starts first event matching given cue
|
||||
* @param {string} cue
|
||||
* @return {boolean} success
|
||||
*/
|
||||
static startByCue(cue: string): boolean {
|
||||
const event = EventLoader.getEventWithCue(cue);
|
||||
const success = PlaybackService.loadEvent(event);
|
||||
if (success) {
|
||||
logger.info(LogOrigin.Playback, `Loaded event with ID ${event.id}`);
|
||||
PlaybackService.start();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* loads event matching given ID
|
||||
* @param {string} eventId
|
||||
@@ -90,6 +105,20 @@ export class PlaybackService {
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* loads first event matching given cue
|
||||
* @param {string} cue
|
||||
* @return {boolean} success
|
||||
*/
|
||||
static loadByCue(cue: string): boolean {
|
||||
const event = EventLoader.getEventWithCue(cue);
|
||||
const success = PlaybackService.loadEvent(event);
|
||||
if (success) {
|
||||
logger.info(LogOrigin.Playback, `Loaded event with ID ${event.id}`);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads event before currently selected
|
||||
*/
|
||||
|
||||
@@ -8,9 +8,9 @@ import {
|
||||
Playback,
|
||||
SupportedEvent,
|
||||
} from 'ontime-types';
|
||||
import { generateId } from 'ontime-utils';
|
||||
import { generateId, getCueCandidate } from 'ontime-utils';
|
||||
import { DataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||
import { block as blockDef, delay as delayDef, event as eventDef } from '../../models/eventsDefinition.js';
|
||||
import { block as blockDef, delay as delayDef } from '../../models/eventsDefinition.js';
|
||||
import { MAX_EVENTS } from '../../settings.js';
|
||||
import { EventLoader, eventLoader } from '../../classes/event-loader/EventLoader.js';
|
||||
import { eventTimer } from '../TimerService.js';
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
delayedRundownCacheKey,
|
||||
} from './delayedRundown.utils.js';
|
||||
import { logger } from '../../classes/Logger.js';
|
||||
import { validateEvent } from '../../utils/parser.js';
|
||||
import { clock } from '../Clock.js';
|
||||
|
||||
/**
|
||||
@@ -164,30 +165,30 @@ export async function addEvent(eventData: Partial<OntimeEvent> | Partial<OntimeD
|
||||
let newEvent: Partial<OntimeBaseEvent> = {};
|
||||
const id = generateId();
|
||||
|
||||
// TODO: filter the parameters that exist in the event, use the parserUtils
|
||||
switch (eventData.type) {
|
||||
case SupportedEvent.Event:
|
||||
newEvent = { ...eventDef, ...eventData, id };
|
||||
break;
|
||||
case SupportedEvent.Delay:
|
||||
newEvent = { ...delayDef, ...eventData, id };
|
||||
break;
|
||||
case SupportedEvent.Block:
|
||||
newEvent = { ...blockDef, ...eventData, id };
|
||||
break;
|
||||
}
|
||||
|
||||
let insertIndex = 0;
|
||||
if (typeof newEvent?.after !== 'undefined') {
|
||||
const index = DataProvider.getIndexOf(newEvent.after);
|
||||
if (eventData?.after !== 'undefined') {
|
||||
const index = DataProvider.getIndexOf(eventData.after);
|
||||
if (index < 0) {
|
||||
logger.warning(LogOrigin.Server, `Could not find event with id ${newEvent.after}`);
|
||||
logger.warning(LogOrigin.Server, `Could not find event with id ${eventData.after}`);
|
||||
} else {
|
||||
insertIndex = index + 1;
|
||||
}
|
||||
delete newEvent.after;
|
||||
}
|
||||
|
||||
switch (eventData.type) {
|
||||
case SupportedEvent.Event: {
|
||||
newEvent = validateEvent(eventData, getCueCandidate(DataProvider.getRundown(), eventData?.after)) as OntimeEvent;
|
||||
break;
|
||||
}
|
||||
case SupportedEvent.Delay:
|
||||
newEvent = { ...delayDef, duration: eventData.duration, id } as OntimeDelay;
|
||||
break;
|
||||
case SupportedEvent.Block:
|
||||
newEvent = { ...blockDef, title: eventData.title, id } as OntimeBlock;
|
||||
break;
|
||||
}
|
||||
delete eventData.after;
|
||||
|
||||
// modify rundown
|
||||
await cachedAdd(insertIndex, newEvent as OntimeEvent | OntimeDelay | OntimeBlock);
|
||||
|
||||
@@ -204,6 +205,10 @@ export async function addEvent(eventData: Partial<OntimeEvent> | Partial<OntimeD
|
||||
}
|
||||
|
||||
export async function editEvent(eventData: Partial<OntimeEvent> | Partial<OntimeBlock> | Partial<OntimeDelay>) {
|
||||
if (eventData.type === SupportedEvent.Event && eventData?.cue === '') {
|
||||
throw new Error(`Cue value invalid`);
|
||||
}
|
||||
|
||||
const newEvent = await cachedEdit(eventData.id, eventData);
|
||||
|
||||
// notify timer service of changed events
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EndAction, OntimeRundown, SupportedEvent, TimerType } from 'ontime-types';
|
||||
import { EndAction, OntimeEvent, OntimeRundown, SupportedEvent, TimerType } from 'ontime-types';
|
||||
|
||||
import { calculateRuntimeDelays, calculateRuntimeDelaysFrom, getDelayAt } from '../delayedRundown.utils.js';
|
||||
|
||||
@@ -31,6 +31,7 @@ describe('calculateRuntimeDelays', () => {
|
||||
type: SupportedEvent.Event,
|
||||
revision: 0,
|
||||
id: '659e1',
|
||||
cue: '1',
|
||||
},
|
||||
{
|
||||
duration: 600000,
|
||||
@@ -64,6 +65,7 @@ describe('calculateRuntimeDelays', () => {
|
||||
type: SupportedEvent.Event,
|
||||
revision: 0,
|
||||
id: '1c48f',
|
||||
cue: '2',
|
||||
},
|
||||
{
|
||||
duration: 1200000,
|
||||
@@ -97,6 +99,7 @@ describe('calculateRuntimeDelays', () => {
|
||||
type: SupportedEvent.Event,
|
||||
revision: 0,
|
||||
id: 'd48c2',
|
||||
cue: '3',
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
@@ -129,16 +132,17 @@ describe('calculateRuntimeDelays', () => {
|
||||
type: SupportedEvent.Event,
|
||||
revision: 0,
|
||||
id: '2f185',
|
||||
cue: '4',
|
||||
},
|
||||
];
|
||||
|
||||
const updatedRundown = calculateRuntimeDelays(rundown);
|
||||
|
||||
expect(rundown.length).toBe(updatedRundown.length);
|
||||
expect(updatedRundown[0].delay).toBe(0);
|
||||
expect(updatedRundown[2].delay).toBe(600000);
|
||||
expect(updatedRundown[4].delay).toBe(600000 + 1200000);
|
||||
expect(updatedRundown[6].delay).toBe(0);
|
||||
expect((updatedRundown[0] as OntimeEvent).delay).toBe(0);
|
||||
expect((updatedRundown[2] as OntimeEvent).delay).toBe(600000);
|
||||
expect((updatedRundown[4] as OntimeEvent).delay).toBe(600000 + 1200000);
|
||||
expect((updatedRundown[6] as OntimeEvent).delay).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -171,6 +175,7 @@ describe('getDelayAt()', () => {
|
||||
revision: 0,
|
||||
id: '659e1',
|
||||
delay: 0,
|
||||
cue: '1',
|
||||
},
|
||||
{
|
||||
duration: 600000,
|
||||
@@ -205,6 +210,7 @@ describe('getDelayAt()', () => {
|
||||
revision: 0,
|
||||
id: '1c48f',
|
||||
delay: 600000,
|
||||
cue: '2',
|
||||
},
|
||||
{
|
||||
duration: 1200000,
|
||||
@@ -239,6 +245,7 @@ describe('getDelayAt()', () => {
|
||||
revision: 0,
|
||||
id: 'd48c2',
|
||||
delay: 1800000,
|
||||
cue: '3',
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
@@ -272,6 +279,7 @@ describe('getDelayAt()', () => {
|
||||
revision: 0,
|
||||
id: '2f185',
|
||||
delay: 0,
|
||||
cue: '4',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -331,6 +339,7 @@ describe('calculateRuntimeDelaysFrom()', () => {
|
||||
revision: 0,
|
||||
id: '659e1',
|
||||
delay: 0,
|
||||
cue: '1',
|
||||
},
|
||||
{
|
||||
duration: 600000,
|
||||
@@ -365,6 +374,7 @@ describe('calculateRuntimeDelaysFrom()', () => {
|
||||
revision: 0,
|
||||
id: '1c48f',
|
||||
delay: 0,
|
||||
cue: '2',
|
||||
},
|
||||
{
|
||||
duration: 1200000,
|
||||
@@ -399,6 +409,7 @@ describe('calculateRuntimeDelaysFrom()', () => {
|
||||
revision: 0,
|
||||
id: 'd48c2',
|
||||
delay: 1800000,
|
||||
cue: '3',
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
@@ -432,14 +443,15 @@ describe('calculateRuntimeDelaysFrom()', () => {
|
||||
revision: 0,
|
||||
id: '2f185',
|
||||
delay: 0,
|
||||
cue: '4',
|
||||
},
|
||||
];
|
||||
|
||||
const updatedRundown = calculateRuntimeDelaysFrom('07986', delayedRundown);
|
||||
|
||||
// we only update from the 4th on
|
||||
expect(updatedRundown[0].delay).toBe(0);
|
||||
expect((updatedRundown[0] as OntimeEvent).delay).toBe(0);
|
||||
// 1 + 3
|
||||
expect(updatedRundown[4].delay).toBe(600000 + 1200000);
|
||||
expect((updatedRundown[4] as OntimeEvent).delay).toBe(600000 + 1200000);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user