mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-12 02:43:50 +00:00
refactor: gather group metadata
This commit is contained in:
committed by
Carlos Valente
parent
730cb95c04
commit
876d111c61
@@ -31,9 +31,9 @@ describe('test parseDatabaseModel() with demo project (valid)', () => {
|
||||
const filteredDemoProject = structuredClone(demoDb);
|
||||
const { data } = parseDatabaseModel(filteredDemoProject);
|
||||
|
||||
it('has 16 events', () => {
|
||||
expect(data.rundowns.demo.order.length).toBe(16);
|
||||
expect(Object.keys(data.rundowns.demo.entries).length).toBe(16);
|
||||
it('has 17 events with 12 top level events', () => {
|
||||
expect(data.rundowns.default.order.length).toBe(12);
|
||||
expect(Object.keys(data.rundowns.default.entries).length).toBe(17);
|
||||
});
|
||||
|
||||
it('is the same as the demo project since all data is valid', () => {
|
||||
@@ -663,7 +663,7 @@ describe('parseExcel()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('parses link start and checks that is applicable', () => {
|
||||
it('parses link start', () => {
|
||||
const testData = [
|
||||
['Time Start', 'Time End', 'ID', 'Link Start', 'Timer type'],
|
||||
['4:30:00', '9:45:00', 'A', '', 'count-down'],
|
||||
@@ -688,22 +688,22 @@ describe('parseExcel()', () => {
|
||||
|
||||
expect(result.rundown.entries).toMatchObject({
|
||||
A: {
|
||||
linkStart: null,
|
||||
linkStart: false,
|
||||
},
|
||||
B: {
|
||||
linkStart: 'true', // <--- this will be populated by the cache generation
|
||||
linkStart: true,
|
||||
},
|
||||
C: {
|
||||
linkStart: 'true', // <--- this will be populated by the cache generation
|
||||
linkStart: true,
|
||||
},
|
||||
D: {
|
||||
linkStart: null,
|
||||
linkStart: false,
|
||||
},
|
||||
BLOCK: {
|
||||
type: SupportedEvent.Block,
|
||||
},
|
||||
E: {
|
||||
linkStart: 'true', // <--- this will be populated by the cache generation
|
||||
linkStart: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -775,7 +775,7 @@ describe('parseExcel()', () => {
|
||||
|
||||
expect(parsedData.rundown.entries['MEET3']).toMatchObject({
|
||||
duration: 90 * MILLIS_PER_MINUTE,
|
||||
linkStart: null,
|
||||
linkStart: false,
|
||||
timeWarning: 11 * MILLIS_PER_MINUTE,
|
||||
timeDanger: 5 * MILLIS_PER_MINUTE,
|
||||
});
|
||||
@@ -783,7 +783,7 @@ describe('parseExcel()', () => {
|
||||
expect(parsedData.rundown.entries['MEET4']).toMatchObject({
|
||||
duration: 30 * MILLIS_PER_MINUTE,
|
||||
timeWarning: 11 * MILLIS_PER_MINUTE,
|
||||
linkStart: 'true', // if we get a boolean, we should just use that
|
||||
linkStart: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
parseViewSettings,
|
||||
sanitiseCustomFields,
|
||||
} from '../parserFunctions.js';
|
||||
import { makeOntimeBlock, makeOntimeEvent } from '../../services/rundown-service/__mocks__/rundown.mocks.js';
|
||||
|
||||
describe('parseRundowns()', () => {
|
||||
it('returns a default project rundown if nothing is given', () => {
|
||||
@@ -166,6 +167,43 @@ describe('parseRundown()', () => {
|
||||
expect(parsedRundown.order.length).toEqual(2);
|
||||
expect(Object.keys(parsedRundown.entries).length).toEqual(2);
|
||||
});
|
||||
|
||||
it('handles empty events', () => {
|
||||
const rundown = {
|
||||
id: 'test',
|
||||
title: '',
|
||||
order: ['1', '2', '3', '4'],
|
||||
entries: {
|
||||
'1': { id: '1', type: SupportedEvent.Event } as OntimeEvent,
|
||||
'2': { id: '2', type: SupportedEvent.Event } as OntimeEvent,
|
||||
'not-mentioned': {} as OntimeEvent,
|
||||
},
|
||||
revision: 1,
|
||||
} as Rundown;
|
||||
|
||||
const parsedRundown = parseRundown(rundown, {});
|
||||
expect(parsedRundown.order.length).toEqual(2);
|
||||
expect(Object.keys(parsedRundown.entries).length).toEqual(2);
|
||||
});
|
||||
|
||||
it('parses events nested in blocks', () => {
|
||||
const rundown = {
|
||||
id: 'test',
|
||||
title: '',
|
||||
order: ['block'],
|
||||
entries: {
|
||||
block: makeOntimeBlock({ id: 'block', events: ['1', '2'] }),
|
||||
'1': makeOntimeEvent({ id: '1' }),
|
||||
'2': makeOntimeEvent({ id: '2' }),
|
||||
},
|
||||
revision: 1,
|
||||
} as Rundown;
|
||||
|
||||
const parsedRundown = parseRundown(rundown, {});
|
||||
expect(parsedRundown.order.length).toEqual(1);
|
||||
expect(parsedRundown.entries.block).toMatchObject({ events: ['1', '2'] });
|
||||
expect(Object.keys(parsedRundown.entries).length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseProject()', () => {
|
||||
@@ -381,123 +419,3 @@ describe('sanitiseCustomFields()', () => {
|
||||
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseRundown() linking', () => {
|
||||
it('returns linked events', () => {
|
||||
const rundown: Rundown = {
|
||||
id: '',
|
||||
title: '',
|
||||
revision: 1,
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'1': {
|
||||
id: '1',
|
||||
type: SupportedEvent.Event,
|
||||
skip: false,
|
||||
} as OntimeEvent,
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
linkStart: 'true',
|
||||
skip: false,
|
||||
} as OntimeEvent,
|
||||
},
|
||||
};
|
||||
|
||||
const result = parseRundown(rundown, {});
|
||||
expect(result).toMatchObject({
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'2': {
|
||||
linkStart: '1',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns unlinked if no previous', () => {
|
||||
const rundown: Rundown = {
|
||||
id: '',
|
||||
title: '',
|
||||
revision: 1,
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
linkStart: 'true',
|
||||
skip: false,
|
||||
} as OntimeEvent,
|
||||
},
|
||||
};
|
||||
|
||||
const result = parseRundown(rundown, {});
|
||||
expect(result).toMatchObject({
|
||||
order: ['2'],
|
||||
entries: {
|
||||
'2': {
|
||||
linkStart: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns linked events past blocks and delays', () => {
|
||||
const rundown: Rundown = {
|
||||
id: '',
|
||||
title: '',
|
||||
revision: 1,
|
||||
order: ['1', 'delay1', '2', 'block1', '3'],
|
||||
entries: {
|
||||
'1': {
|
||||
id: '1',
|
||||
type: SupportedEvent.Event,
|
||||
skip: false,
|
||||
} as OntimeEvent,
|
||||
delay1: {
|
||||
id: 'delay1',
|
||||
type: SupportedEvent.Delay,
|
||||
duration: 0,
|
||||
},
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
linkStart: 'true',
|
||||
skip: false,
|
||||
} as OntimeEvent,
|
||||
block1: {
|
||||
id: 'block1',
|
||||
type: SupportedEvent.Block,
|
||||
title: '',
|
||||
} as OntimeBlock,
|
||||
'3': {
|
||||
id: '3',
|
||||
type: SupportedEvent.Event,
|
||||
linkStart: 'true',
|
||||
skip: false,
|
||||
} as OntimeEvent,
|
||||
},
|
||||
};
|
||||
|
||||
const result = parseRundown(rundown, {});
|
||||
expect(result).toMatchObject({
|
||||
order: rundown.order,
|
||||
entries: {
|
||||
'1': {
|
||||
id: '1',
|
||||
cue: '1',
|
||||
},
|
||||
'2': {
|
||||
id: '2',
|
||||
cue: '2',
|
||||
linkStart: '1',
|
||||
},
|
||||
'3': {
|
||||
id: '3',
|
||||
cue: '3',
|
||||
linkStart: '2',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
type ImportMap,
|
||||
isKnownTimerType,
|
||||
validateEndAction,
|
||||
validateLinkStart,
|
||||
validateTimerType,
|
||||
validateTimes,
|
||||
} from 'ontime-utils';
|
||||
@@ -246,7 +245,7 @@ export const parseExcel = (
|
||||
} else if (j === timeStartIndex) {
|
||||
entry.timeStart = parseExcelDate(column);
|
||||
} else if (j === linkStartIndex) {
|
||||
entry.linkStart = parseBooleanString(column) ? 'true' : null;
|
||||
entry.linkStart = parseBooleanString(column);
|
||||
} else if (j === timeEndIndex) {
|
||||
entry.timeEnd = parseExcelDate(column);
|
||||
} else if (j === durationIndex) {
|
||||
@@ -412,7 +411,7 @@ export function createPatch(originalEvent: OntimeEvent, patchEvent: Partial<Onti
|
||||
timeEnd,
|
||||
duration,
|
||||
timeStrategy,
|
||||
linkStart: validateLinkStart(patchEvent.linkStart, originalEvent.linkStart),
|
||||
linkStart: typeof patchEvent.linkStart === 'boolean' ? patchEvent.linkStart : originalEvent.linkStart,
|
||||
endAction: validateEndAction(patchEvent.endAction, originalEvent.endAction),
|
||||
timerType: validateTimerType(patchEvent.timerType, originalEvent.timerType),
|
||||
countToEnd: typeof patchEvent.countToEnd === 'boolean' ? patchEvent.countToEnd : originalEvent.countToEnd,
|
||||
|
||||
@@ -75,11 +75,11 @@ export function parseRundown(
|
||||
};
|
||||
|
||||
let eventIndex = 0;
|
||||
let previousId: string | null = null;
|
||||
|
||||
for (let i = 0; i < rundown.order.length; i++) {
|
||||
const entryId = rundown.order[i];
|
||||
const event = rundown.entries[entryId];
|
||||
|
||||
if (event === undefined) {
|
||||
emitError?.('Could not find referenced event, skipping');
|
||||
continue;
|
||||
@@ -94,13 +94,7 @@ export function parseRundown(
|
||||
let newEvent: OntimeEvent | OntimeDelay | OntimeBlock | null;
|
||||
|
||||
if (isOntimeEvent(event)) {
|
||||
const maybeEvent = { ...event };
|
||||
|
||||
if (event.linkStart) {
|
||||
maybeEvent.linkStart = previousId;
|
||||
}
|
||||
|
||||
newEvent = createEvent(maybeEvent, eventIndex);
|
||||
newEvent = createEvent(event, eventIndex);
|
||||
// skip if event is invalid
|
||||
if (newEvent == null) {
|
||||
emitError?.('Skipping event without payload');
|
||||
@@ -115,11 +109,38 @@ export function parseRundown(
|
||||
}
|
||||
}
|
||||
|
||||
previousId = id;
|
||||
eventIndex += 1;
|
||||
} else if (isOntimeDelay(event)) {
|
||||
newEvent = { ...delayDef, duration: event.duration, id };
|
||||
} else if (isOntimeBlock(event)) {
|
||||
for (let i = 0; i < event.events.length; i++) {
|
||||
const nestedEventId = event.events[i];
|
||||
const nestedEvent = rundown.entries[nestedEventId];
|
||||
|
||||
if (isOntimeEvent(nestedEvent)) {
|
||||
const newNestedEvent = createEvent(nestedEvent, eventIndex);
|
||||
// skip if event is invalid
|
||||
if (newNestedEvent == null) {
|
||||
emitError?.('Skipping event without payload');
|
||||
continue;
|
||||
}
|
||||
|
||||
// for every field in custom, check that a key exists in customfields
|
||||
for (const field in newNestedEvent.custom) {
|
||||
if (!Object.hasOwn(parsedCustomFields, field)) {
|
||||
emitError?.(`Custom field ${field} not found`);
|
||||
delete newNestedEvent.custom[field];
|
||||
}
|
||||
}
|
||||
|
||||
eventIndex += 1;
|
||||
|
||||
if (newNestedEvent) {
|
||||
parsedRundown.entries[nestedEventId] = newNestedEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newEvent = {
|
||||
...blockDef,
|
||||
title: event.title,
|
||||
|
||||
Reference in New Issue
Block a user