fix: midnight roll (#484)

* refactor: extract utilities and types

* refactor: extract and simplify progress bar logic

* refactor: duration validation handles midnight

* fix: prevent stale event loader

* refactor: consider next event in timer invalidation

* refactor: reload changes on changed roll target

* refactor: timer load accounts for midnight

* fix: issues with midnight on roll

* refactor: prevent stale secondary event
This commit is contained in:
Carlos Valente
2023-08-12 10:42:43 +02:00
committed by GitHub
parent 8c9cb908cf
commit 023aac4ead
28 changed files with 520 additions and 271 deletions
+2 -32
View File
@@ -1,9 +1,10 @@
import { vi } from 'vitest';
import { dbModel } from '../../models/dataModel.ts';
import { parseExcel, parseJson, validateEvent } from '../parser.ts';
import { makeString, validateDuration } from '../parserUtils.js';
import { makeString } from '../parserUtils.ts';
import { parseAliases, parseUserFields, parseViewSettings } from '../parserFunctions.ts';
import { EndAction, TimerType } from 'ontime-types';
import { dayInMs } from 'ontime-utils';
describe('test json parser with valid def', () => {
const testData = {
@@ -898,34 +899,3 @@ describe('test views import', () => {
expect(parsed).toStrictEqual(expectedParsedViewSettings);
});
});
describe('test validateDuration()', () => {
describe('handles valid inputs', () => {
const valid = [
{ test: 'zero values', timeStart: 0, timeEnd: 0 },
{ test: 'end after start', timeStart: 0, timeEnd: 1 },
];
valid.forEach((t) => {
it(t.test, () => {
const d = validateDuration(t.timeStart, t.timeEnd);
expect(d).toBe(t.timeEnd - t.timeStart);
});
});
});
describe('handles edge cases', () => {
// edge cases
const testData = [
{ test: 'negative 0', timeStart: -0, timeEnd: -0, expected: 0 },
{ test: 'end before start', timeStart: 2, timeEnd: 1, expected: 0 },
];
testData.forEach((t) => {
it(t.test, () => {
const d = validateDuration(t.timeStart, t.timeEnd);
expect(d).toBe(t.expected);
});
});
});
});
@@ -5,9 +5,6 @@ describe('isEmptyObject()', () => {
const isEmpty = isEmptyObject({});
expect(isEmpty).toBe(true);
});
test('throws on other types', () => {
expect(() => isEmptyObject(12)).toThrow();
});
test('resolves an object with methods', () => {
const isEmpty = isEmptyObject({ test: 'yes' });
expect(isEmpty).toBe(false);
+3 -3
View File
@@ -3,11 +3,11 @@
import fs from 'fs';
import xlsx from 'node-xlsx';
import { generateId } from 'ontime-utils';
import { generateId, calculateDuration } from 'ontime-utils';
import { DatabaseModel, EventData, OntimeEvent, OntimeRundown, UserFields } from 'ontime-types';
import { event as eventDef } from '../models/eventsDefinition.js';
import { dbModel } from '../models/dataModel.js';
import { deleteFile, makeString, validateDuration } from './parserUtils.js';
import { deleteFile, makeString } from './parserUtils.js';
import {
parseAliases,
parseEventData,
@@ -322,7 +322,7 @@ export const validateEvent = (eventArgs) => {
timeEnd: end,
endAction: makeString(e.endAction, d.endAction),
timerType: makeString(e.timerType, d.timerType),
duration: validateDuration(start, end),
duration: calculateDuration(start, end),
isPublic: typeof e.isPublic === 'boolean' ? e.isPublic : d.isPublic,
skip: typeof e.skip === 'boolean' ? e.skip : d.skip,
note: makeString(e.note, d.note),
@@ -1,4 +1,5 @@
import fs from 'fs';
import { dayInMs } from 'ontime-utils';
/**
* @description Ensures variable is string, it skips object types
@@ -6,23 +7,12 @@ import fs from 'fs';
* @param {string} [fallback=''] - fallback value
* @returns {string} - value as string or fallback if not possible
*/
export const makeString = (val, fallback = '') => {
export const makeString = (val: any, fallback = ''): string => {
if (typeof val === 'string') return val;
else if (val == null || val.constructor === Object) return fallback;
return val.toString();
};
/**
* @description validates a duration value against options
* @param {number} timeStart
* @param {number} timeEnd
* @returns {number}
*/
export const validateDuration = (timeStart, timeEnd) => {
// Durations must be positive
return Math.max(timeEnd - timeStart, 0);
};
/**
* @description Delete file from system
* @param {string} file - reference to file
@@ -54,7 +44,7 @@ export const validateFile = (file) => {
* @description Verifies if object is empty
* @param {object} obj
*/
export const isEmptyObject = (obj) => {
export const isEmptyObject = (obj: object) => {
if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {
return Object.keys(obj).length === 0;
}
@@ -78,7 +68,7 @@ export const mergeObject = (a, b) => {
* @description Removes undefined
* @param {object} obj
*/
export const removeUndefined = (obj) => {
export const removeUndefined = (obj: object) => {
const patched = {};
Object.keys({ ...obj })
.filter((key) => typeof obj[key] !== 'undefined')
-1
View File
@@ -6,7 +6,6 @@ const mth = 1000 * 60 * 60; // millis to hours
export const timeFormat = 'HH:mm';
export const timeFormatSeconds = 'HH:mm:ss';
export const DAY_TO_MS = 86400000;
/**
* @description Converts an excel date to milliseconds