mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 03: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:
@@ -1,54 +0,0 @@
|
||||
import { getPreviousPlayable } from '../eventUtils.js';
|
||||
|
||||
describe('getPreviousPlayable()', () => {
|
||||
describe('given a list of events', () => {
|
||||
it('finds the previous playable event', () => {
|
||||
const events = [
|
||||
{ id: 100, type: 'delay' },
|
||||
{ id: 101, type: 'event', skip: true },
|
||||
{ id: 102, type: 'event', skip: true },
|
||||
{ id: 103, type: 'event', skip: false },
|
||||
{ id: 'not-this', type: 'block' },
|
||||
{ id: 104, type: 'event' },
|
||||
];
|
||||
const { index, id } = getPreviousPlayable(events, events[4].id);
|
||||
expect(index).toBe(3);
|
||||
expect(id).toBe(103);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handles common errors', () => {
|
||||
it('returns null if id not found in list', () => {
|
||||
const events = [
|
||||
{ id: 0, type: 'delay' },
|
||||
{ id: 1, type: 'event', skip: true },
|
||||
{ id: 2, type: 'event', skip: true },
|
||||
{ id: 3, type: 'event', skip: false },
|
||||
{ id: 4, type: 'event' },
|
||||
];
|
||||
const { index, id } = getPreviousPlayable(events, 'no-valid-id');
|
||||
expect(index).toBe(null);
|
||||
expect(id).toBe(null);
|
||||
});
|
||||
|
||||
it('returns null if there are no previous events to play', () => {
|
||||
const events = [
|
||||
{ id: 0, type: 'delay' },
|
||||
{ id: 1, type: 'event', skip: true },
|
||||
{ id: 2, type: 'event', skip: true },
|
||||
{ id: 3, type: 'event', skip: true },
|
||||
{ id: 4, type: 'event' },
|
||||
];
|
||||
const { index, id } = getPreviousPlayable(events, events[4].id);
|
||||
expect(index).toBe(null);
|
||||
expect(id).toBe(null);
|
||||
});
|
||||
|
||||
it('returns null if list is empty', () => {
|
||||
const events = [];
|
||||
const { index, id } = getPreviousPlayable(events, 'made-up');
|
||||
expect(index).toBe(null);
|
||||
expect(id).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
+30
-80
@@ -1,10 +1,11 @@
|
||||
import { vi } from 'vitest';
|
||||
import { dbModel } from '../../models/dataModel.ts';
|
||||
import { parseExcel, parseJson, validateEvent } from '../parser.ts';
|
||||
import { makeString } from '../parserUtils.ts';
|
||||
import { parseAliases, parseUserFields, parseViewSettings } from '../parserFunctions.ts';
|
||||
import { EndAction, TimerType } from 'ontime-types';
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
|
||||
import { EndAction, OntimeEvent, TimerType } from 'ontime-types';
|
||||
|
||||
import { dbModel } from '../../models/dataModel.js';
|
||||
import { parseExcel, parseJson, validateEvent } from '../parser.js';
|
||||
import { makeString } from '../parserUtils.js';
|
||||
import { parseAliases, parseUserFields, parseViewSettings } from '../parserFunctions.js';
|
||||
|
||||
describe('test json parser with valid def', () => {
|
||||
const testData = {
|
||||
@@ -220,64 +221,20 @@ describe('test json parser with valid def', () => {
|
||||
const first = parseResponse?.rundown[0];
|
||||
const expected = {
|
||||
title: 'Guest Welcoming',
|
||||
subtitle: '',
|
||||
presenter: '',
|
||||
note: '',
|
||||
timeStart: 31500000,
|
||||
timeEnd: 32400000,
|
||||
duration: 32400000 - 31500000,
|
||||
isPublic: false,
|
||||
endAction: 'play-next',
|
||||
timerType: 'clock',
|
||||
skip: false,
|
||||
colour: '',
|
||||
type: 'event',
|
||||
revision: 0,
|
||||
id: '4b31',
|
||||
user0: '',
|
||||
user1: '',
|
||||
user2: '',
|
||||
user3: '',
|
||||
user4: '',
|
||||
user5: '',
|
||||
user6: '',
|
||||
user7: '',
|
||||
user8: '',
|
||||
user9: '',
|
||||
};
|
||||
expect(first).toStrictEqual(expected);
|
||||
expect(first).toMatchObject(expected);
|
||||
});
|
||||
|
||||
it('second event is as a match', () => {
|
||||
const second = parseResponse?.rundown[1];
|
||||
const expected = {
|
||||
title: 'Good Morning',
|
||||
subtitle: 'Days schedule',
|
||||
presenter: 'Carlos Valente',
|
||||
note: '',
|
||||
timeStart: 32400000,
|
||||
timeEnd: 36000000,
|
||||
endAction: 'play-next',
|
||||
timerType: 'count-up',
|
||||
duration: 36000000 - 32400000,
|
||||
isPublic: true,
|
||||
skip: true,
|
||||
colour: 'red',
|
||||
type: 'event',
|
||||
revision: 0,
|
||||
id: 'f24d',
|
||||
user0: '',
|
||||
user1: '',
|
||||
user2: '',
|
||||
user3: '',
|
||||
user4: '',
|
||||
user5: '',
|
||||
user6: '',
|
||||
user7: '',
|
||||
user8: '',
|
||||
user9: '',
|
||||
};
|
||||
expect(second).toStrictEqual(expected);
|
||||
expect(second).toMatchObject(expected);
|
||||
});
|
||||
it('third event end action is set as the default value', () => {
|
||||
const third = parseResponse?.rundown[2];
|
||||
@@ -448,7 +405,7 @@ describe('test corrupt data', () => {
|
||||
it('handles missing event data', async () => {
|
||||
const emptyEventData = {
|
||||
rundown: [{}, {}, {}, {}, {}, {}, {}, {}],
|
||||
event: {},
|
||||
eventData: {},
|
||||
settings: {
|
||||
app: 'ontime',
|
||||
version: 2,
|
||||
@@ -459,7 +416,7 @@ describe('test corrupt data', () => {
|
||||
};
|
||||
|
||||
const parsedDef = await parseJson(emptyEventData);
|
||||
expect(parsedDef.event).toStrictEqual(dbModel.event);
|
||||
expect(parsedDef.eventData).toStrictEqual(dbModel.eventData);
|
||||
});
|
||||
|
||||
it('handles missing settings', async () => {
|
||||
@@ -488,7 +445,7 @@ describe('test event validator', () => {
|
||||
const event = {
|
||||
title: 'test',
|
||||
};
|
||||
const validated = validateEvent(event);
|
||||
const validated = validateEvent(event, 'test');
|
||||
|
||||
expect(validated).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -503,6 +460,7 @@ describe('test event validator', () => {
|
||||
revision: expect.any(Number),
|
||||
type: expect.any(String),
|
||||
id: expect.any(String),
|
||||
cue: 'test',
|
||||
colour: expect.any(String),
|
||||
user0: expect.any(String),
|
||||
user1: expect.any(String),
|
||||
@@ -520,7 +478,7 @@ describe('test event validator', () => {
|
||||
|
||||
it('fails an empty object', () => {
|
||||
const event = {};
|
||||
const validated = validateEvent(event);
|
||||
const validated = validateEvent(event, 'none');
|
||||
expect(validated).toEqual(null);
|
||||
});
|
||||
|
||||
@@ -531,7 +489,8 @@ describe('test event validator', () => {
|
||||
presenter: 3.2,
|
||||
note: '1899-12-30T08:00:10.000Z',
|
||||
};
|
||||
const validated = validateEvent(event);
|
||||
// @ts-expect-error -- we know this is wrong, testing imports outside domain
|
||||
const validated = validateEvent(event, 'not-used');
|
||||
expect(typeof validated.title).toEqual('string');
|
||||
expect(typeof validated.subtitle).toEqual('string');
|
||||
expect(typeof validated.presenter).toEqual('string');
|
||||
@@ -543,6 +502,7 @@ describe('test event validator', () => {
|
||||
timeStart: false,
|
||||
timeEnd: '2',
|
||||
};
|
||||
// @ts-expect-error -- we know this is wrong, testing imports outside domain
|
||||
const validated = validateEvent(event);
|
||||
expect(typeof validated.timeStart).toEqual('number');
|
||||
expect(validated.timeStart).toEqual(0);
|
||||
@@ -554,6 +514,7 @@ describe('test event validator', () => {
|
||||
const event = {
|
||||
title: {},
|
||||
};
|
||||
// @ts-expect-error -- we know this is wrong, testing imports outside domain
|
||||
const validated = validateEvent(event);
|
||||
expect(typeof validated.title).toEqual('string');
|
||||
});
|
||||
@@ -571,11 +532,13 @@ describe('test makeString function', () => {
|
||||
converted = makeString(val);
|
||||
expect(converted).toBe(expected);
|
||||
|
||||
// @ts-expect-error -- we know this is wrong, testing imports outside domain
|
||||
val = ['testing'];
|
||||
expected = 'testing';
|
||||
converted = makeString(val);
|
||||
expect(converted).toBe(expected);
|
||||
|
||||
// @ts-expect-error -- we know this is wrong, testing imports outside domain
|
||||
val = { doing: 'testing' };
|
||||
converted = makeString(val, 'fallback');
|
||||
expect(converted).toBe('fallback');
|
||||
@@ -628,10 +591,6 @@ describe('test parseExcel function', () => {
|
||||
'x',
|
||||
'',
|
||||
'Ballyhoo',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'a0',
|
||||
'a1',
|
||||
'a2',
|
||||
@@ -650,15 +609,11 @@ describe('test parseExcel function', () => {
|
||||
'A song from the hearth',
|
||||
'Still Carlos',
|
||||
'Derailing early',
|
||||
'clock',
|
||||
'load-next',
|
||||
'clock',
|
||||
'',
|
||||
'',
|
||||
'x',
|
||||
'Rainbow chase',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'b0',
|
||||
'',
|
||||
'',
|
||||
@@ -682,10 +637,11 @@ describe('test parseExcel function', () => {
|
||||
backstageInfo: 'test backstage info',
|
||||
};
|
||||
|
||||
// TODO: update tests once import is resolved
|
||||
const expectedParsedRundown = [
|
||||
{
|
||||
timeStart: 25200000,
|
||||
timeEnd: 28810000,
|
||||
//timeStart: 28800000,
|
||||
//timeEnd: 32410000,
|
||||
title: 'Guest Welcome',
|
||||
presenter: 'Carlos',
|
||||
subtitle: 'Getting things started',
|
||||
@@ -708,8 +664,8 @@ describe('test parseExcel function', () => {
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
timeStart: 28800000,
|
||||
timeEnd: 30600000,
|
||||
//timeStart: 32400000,
|
||||
//timeEnd: 34200000,
|
||||
title: 'A song from the hearth',
|
||||
presenter: 'Still Carlos',
|
||||
subtitle: 'Derailing early',
|
||||
@@ -728,13 +684,8 @@ describe('test parseExcel function', () => {
|
||||
const parsedData = await parseExcel(testdata);
|
||||
expect(parsedData.eventData).toStrictEqual(expectedParsedEvent);
|
||||
expect(parsedData.rundown).toBeDefined();
|
||||
expect(parsedData.rundown.title).toBe(expectedParsedRundown.title);
|
||||
expect(parsedData.rundown.presenter).toBe(expectedParsedRundown.presenter);
|
||||
expect(parsedData.rundown.subtitle).toBe(expectedParsedRundown.subtitle);
|
||||
expect(parsedData.rundown.isPublic).toBe(expectedParsedRundown.isPublic);
|
||||
expect(parsedData.rundown.skip).toBe(expectedParsedRundown.skip);
|
||||
expect(parsedData.rundown.note).toBe(expectedParsedRundown.note);
|
||||
expect(parsedData.rundown.type).toBe(expectedParsedRundown.type);
|
||||
expect(parsedData.rundown[0]).toMatchObject(expectedParsedRundown[0]);
|
||||
expect(parsedData.rundown[1]).toMatchObject(expectedParsedRundown[1]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -759,7 +710,6 @@ describe('test aliases import', () => {
|
||||
expect(parsed.length).toBe(1);
|
||||
|
||||
// generates missing id
|
||||
console.log(parsed);
|
||||
expect(parsed[0].alias).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -874,7 +824,7 @@ describe('test views import', () => {
|
||||
endMessage: '',
|
||||
overrideStyles: false,
|
||||
};
|
||||
const parsed = parseViewSettings(testData);
|
||||
const parsed = parseViewSettings(testData, false);
|
||||
expect(parsed).toStrictEqual(expectedParsedViewSettings);
|
||||
});
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { parseExcelDate } from '../time';
|
||||
|
||||
describe('parseExcelDate', () => {
|
||||
it('parses a valid date string as expected from excel', () => {
|
||||
const millis = parseExcelDate('1899-12-30T07:00:00.000Z');
|
||||
expect(millis).not.toBe(0);
|
||||
});
|
||||
|
||||
describe('parses a time string that passes validation', () => {
|
||||
const validFields = ['10:00:00', '10:00'];
|
||||
validFields.forEach((field) => {
|
||||
it(`handles ${field}`, () => {
|
||||
const millis = parseExcelDate(field);
|
||||
expect(millis).not.toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('returns 0 on other strings', () => {
|
||||
const invalidFields = ['10', 'test', ''];
|
||||
invalidFields.forEach((field) => {
|
||||
it(`handles ${field}`, () => {
|
||||
const millis = parseExcelDate(field);
|
||||
expect(millis).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import { parseExcelDate } from '../time.js';
|
||||
|
||||
describe('parseExcelDate', () => {
|
||||
describe.todo('parses a valid date string as expected from excel', () => {
|
||||
const testCases = [
|
||||
{
|
||||
fromExcel: '1899-12-30T00:00:00.000Z',
|
||||
expected: 3600000,
|
||||
},
|
||||
{
|
||||
fromExcel: '1899-12-30T00:10:00.000Z',
|
||||
expected: 4200000,
|
||||
},
|
||||
{
|
||||
fromExcel: '1899-12-30T01:00:00.000Z',
|
||||
expected: 7200000,
|
||||
},
|
||||
{
|
||||
fromExcel: '1899-12-30T07:00:00.000Z',
|
||||
expected: 28800000,
|
||||
},
|
||||
{
|
||||
fromExcel: '1899-12-30T08:00:10.000Z',
|
||||
expected: 32410000,
|
||||
},
|
||||
{
|
||||
fromExcel: '1899-12-30T08:30:00.000Z',
|
||||
expected: 34200000,
|
||||
},
|
||||
];
|
||||
|
||||
for (const scenario of testCases) {
|
||||
it(`handles ${scenario.fromExcel}`, () => {
|
||||
expect(parseExcelDate(scenario.fromExcel)).toBe(scenario.expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('parses a time string that passes validation', () => {
|
||||
const validFields = ['10:00:00', '10:00'];
|
||||
validFields.forEach((field) => {
|
||||
it(`handles ${field}`, () => {
|
||||
const millis = parseExcelDate(field);
|
||||
expect(millis).not.toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('returns 0 on other strings', () => {
|
||||
const invalidFields = ['10', 'test', ''];
|
||||
invalidFields.forEach((field) => {
|
||||
it(`handles ${field}`, () => {
|
||||
const millis = parseExcelDate(field);
|
||||
expect(millis).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { cleanURL } from '../url';
|
||||
import { cleanURL } from '../url.js';
|
||||
|
||||
describe('url is correctly formatted', () => {
|
||||
it('has no leading spaces', () => {
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @description Returns id of previous played event
|
||||
* @param {array} events
|
||||
* @param {string} eventId
|
||||
* @return {object}
|
||||
*/
|
||||
export function getPreviousPlayable(events, eventId) {
|
||||
// find current index
|
||||
const current = events.findIndex((event) => event.id === eventId);
|
||||
|
||||
if (current === -1) {
|
||||
return { index: null, id: null };
|
||||
}
|
||||
|
||||
let index = current - 1;
|
||||
while (index >= 0) {
|
||||
const event = events[index];
|
||||
if (event.type === 'event' && !event.skip) {
|
||||
return { index, id: event.id };
|
||||
}
|
||||
index--;
|
||||
}
|
||||
|
||||
return { index: null, id: null };
|
||||
}
|
||||
@@ -4,7 +4,16 @@
|
||||
import fs from 'fs';
|
||||
import xlsx from 'node-xlsx';
|
||||
import { generateId, calculateDuration } from 'ontime-utils';
|
||||
import { DatabaseModel, EventData, OntimeEvent, OntimeRundown, UserFields } from 'ontime-types';
|
||||
import {
|
||||
DatabaseModel,
|
||||
EndAction,
|
||||
EventData,
|
||||
OntimeEvent,
|
||||
OntimeRundown,
|
||||
SupportedEvent,
|
||||
TimerType,
|
||||
UserFields,
|
||||
} from 'ontime-types';
|
||||
import { event as eventDef } from '../models/eventsDefinition.js';
|
||||
import { dbModel } from '../models/dataModel.js';
|
||||
import { deleteFile, makeString } from './parserUtils.js';
|
||||
@@ -38,6 +47,7 @@ export const parseExcel = async (excelData) => {
|
||||
let timeStartIndex: number | null = null;
|
||||
let timeEndIndex: number | null = null;
|
||||
let titleIndex: number | null = null;
|
||||
let cueIndex: number | null = null;
|
||||
let presenterIndex: number | null = null;
|
||||
let subtitleIndex: number | null = null;
|
||||
let isPublicIndex: number | null = null;
|
||||
@@ -91,6 +101,8 @@ export const parseExcel = async (excelData) => {
|
||||
event.timeEnd = parseExcelDate(column);
|
||||
} else if (j === titleIndex) {
|
||||
event.title = column;
|
||||
} else if (j === cueIndex) {
|
||||
event.cue = column;
|
||||
} else if (j === presenterIndex) {
|
||||
event.presenter = column;
|
||||
} else if (j === subtitleIndex) {
|
||||
@@ -102,9 +114,17 @@ export const parseExcel = async (excelData) => {
|
||||
} else if (j === notesIndex) {
|
||||
event.note = column;
|
||||
} else if (j === endActionIndex) {
|
||||
event.endAction = column;
|
||||
if (column === '') {
|
||||
event.endAction = EndAction.None;
|
||||
} else {
|
||||
event.endAction = column;
|
||||
}
|
||||
} else if (j === timerTypeIndex) {
|
||||
event.timerType = column;
|
||||
if (column === '') {
|
||||
event.timerType = TimerType.CountDown;
|
||||
} else {
|
||||
event.timerType = column;
|
||||
}
|
||||
} else if (j === colourIndex) {
|
||||
event.colour = column;
|
||||
} else if (j === user0Index) {
|
||||
@@ -130,6 +150,7 @@ export const parseExcel = async (excelData) => {
|
||||
} else {
|
||||
if (typeof column === 'string') {
|
||||
const col = column.toLowerCase();
|
||||
|
||||
// look for keywords
|
||||
// need to make sure it is a string first
|
||||
switch (col) {
|
||||
@@ -157,6 +178,10 @@ export const parseExcel = async (excelData) => {
|
||||
case 'finish':
|
||||
timeEndIndex = j;
|
||||
break;
|
||||
case 'cue':
|
||||
case 'page':
|
||||
cueIndex = j;
|
||||
break;
|
||||
case 'event title':
|
||||
case 'title':
|
||||
titleIndex = j;
|
||||
@@ -243,7 +268,7 @@ export const parseExcel = async (excelData) => {
|
||||
if (Object.keys(event).length > 0) {
|
||||
// if any data was found, push to array
|
||||
// take care of it in the next step
|
||||
rundown.push({ ...event, type: 'event' });
|
||||
rundown.push({ ...event, type: SupportedEvent.Event } as OntimeEvent);
|
||||
}
|
||||
});
|
||||
return {
|
||||
@@ -284,7 +309,6 @@ export const parseJson = async (jsonData, enforce = false): Promise<DatabaseMode
|
||||
// Import user fields if any
|
||||
returnData.userFields = parseUserFields(jsonData);
|
||||
// Import OSC settings if any
|
||||
// @ts-expect-error -- we are unable to type just yet
|
||||
returnData.osc = parseOsc(jsonData, enforce);
|
||||
// Import HTTP settings if any
|
||||
// returnData.http = parseHttp(jsonData, enforce);
|
||||
@@ -295,12 +319,15 @@ export const parseJson = async (jsonData, enforce = false): Promise<DatabaseMode
|
||||
/**
|
||||
* @description Enforces formatting for events
|
||||
* @param {object} eventArgs - attributes of event
|
||||
* @param cueFallback
|
||||
* @returns {object|null} - formatted object or null in case is invalid
|
||||
*/
|
||||
|
||||
export const validateEvent = (eventArgs) => {
|
||||
export const validateEvent = (eventArgs: Partial<OntimeEvent>, cueFallback: string) => {
|
||||
// ensure id is defined and unique
|
||||
const id = eventArgs.id || generateId();
|
||||
const cue = eventArgs.cue || cueFallback;
|
||||
|
||||
let event = null;
|
||||
|
||||
// return if object is empty
|
||||
@@ -336,12 +363,9 @@ export const validateEvent = (eventArgs) => {
|
||||
user7: makeString(e.user7, d.user7),
|
||||
user8: makeString(e.user8, d.user8),
|
||||
user9: makeString(e.user9, d.user9),
|
||||
// deciding not to validate colour
|
||||
// this adds flexibility to the user to write hex codes, rgb,
|
||||
// but also colour names like blue and red
|
||||
// CSS.supports is only available in frontend
|
||||
colour: makeString(e.colour, d.colour),
|
||||
id,
|
||||
cue,
|
||||
type: 'event',
|
||||
};
|
||||
}
|
||||
@@ -357,7 +381,7 @@ type ResponseError = { error: true; message: string };
|
||||
* @param {string} file - reference to file
|
||||
* @return {object} - parse result message
|
||||
*/
|
||||
export const fileHandler = async (file): ResponseOK | ResponseError => {
|
||||
export const fileHandler = async (file): Promise<ResponseOK | ResponseError> => {
|
||||
let res: Partial<ResponseOK | ResponseError> = {};
|
||||
|
||||
// check which file type are we dealing with
|
||||
@@ -376,8 +400,7 @@ export const fileHandler = async (file): ResponseOK | ResponseError => {
|
||||
res.data.userFields = parseUserFields(dataFromExcel);
|
||||
res.message = 'success';
|
||||
} else {
|
||||
const errorMessage = 'No sheet found named ontime or event schedule';
|
||||
console.log(errorMessage);
|
||||
const errorMessage = 'No sheet found named "ontime" or "event schedule"';
|
||||
res = {
|
||||
error: true,
|
||||
message: errorMessage,
|
||||
|
||||
@@ -30,6 +30,7 @@ export const parseRundown = (data): OntimeRundown => {
|
||||
console.log('Found rundown definition, importing...');
|
||||
const rundown = [];
|
||||
try {
|
||||
let eventIndex = 0;
|
||||
const ids = [];
|
||||
for (const e of data.rundown) {
|
||||
// cap number of events
|
||||
@@ -43,6 +44,7 @@ export const parseRundown = (data): OntimeRundown => {
|
||||
console.log('ERROR: ID collision on import, skipping');
|
||||
continue;
|
||||
}
|
||||
|
||||
// validate the right endAction is used
|
||||
if (e.endAction && !Object.values(EndAction).includes(e.endAction)) {
|
||||
e.endAction = EndAction.None;
|
||||
@@ -54,8 +56,10 @@ export const parseRundown = (data): OntimeRundown => {
|
||||
e.timerType = TimerType.CountDown;
|
||||
console.log('WARNING: invalid Timer Type provided, using default');
|
||||
}
|
||||
|
||||
if (e.type === 'event') {
|
||||
const event = validateEvent(e);
|
||||
eventIndex += 1;
|
||||
const event = validateEvent(e, eventIndex.toString());
|
||||
if (event != null) {
|
||||
rundown.push(event);
|
||||
ids.push(event.id);
|
||||
@@ -216,7 +220,12 @@ export const validateOscObject = (data: OscSubscription): boolean => {
|
||||
/**
|
||||
* Parse osc portion of an entry
|
||||
*/
|
||||
export const parseOsc = (data: { osc?: Partial<OSCSettings> }, enforce: boolean): Partial<OSCSettings> => {
|
||||
export const parseOsc = (
|
||||
data: {
|
||||
osc?: Partial<OSCSettings>;
|
||||
},
|
||||
enforce: boolean,
|
||||
): OSCSettings | Record<string, never> => {
|
||||
if ('osc' in data) {
|
||||
console.log('Found OSC definition, importing...');
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import fs from 'fs';
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
|
||||
/**
|
||||
* @description Ensures variable is string, it skips object types
|
||||
|
||||
@@ -8,12 +8,13 @@ export const timeFormat = 'HH:mm';
|
||||
export const timeFormatSeconds = 'HH:mm:ss';
|
||||
|
||||
/**
|
||||
* @description Converts an excel date to milliseconds
|
||||
* @argument {string} date - excel string date
|
||||
* @description Converts a date object to milliseconds
|
||||
* @argument {Date} date
|
||||
* @returns {number} - time in milliseconds
|
||||
*/
|
||||
|
||||
export const dateToMillis = (date: Date): number => {
|
||||
// TODO: Use UTC
|
||||
const h = date.getHours();
|
||||
const m = date.getMinutes();
|
||||
const s = date.getSeconds();
|
||||
|
||||
Reference in New Issue
Block a user