mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 03:13:47 +00:00
Feat/studio clock (#60)
This commit is contained in:
@@ -0,0 +1,410 @@
|
||||
import {formatEventList, getEventsWithDelay, trimEventlist} from "../eventsManager";
|
||||
|
||||
test('getEventsWithDelay function', () => {
|
||||
|
||||
const testData = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"timeStart": 28800000,
|
||||
"timeEnd": 30600000,
|
||||
"type": "event",
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"duration": 60000,
|
||||
"type": "delay",
|
||||
"id": "24240"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"timeStart": 34920000,
|
||||
"timeEnd": 35520000,
|
||||
"type": "event",
|
||||
"id": "8ee5"
|
||||
},
|
||||
{
|
||||
"title": "Use simpler times to create a timer",
|
||||
"timeStart": 120000,
|
||||
"timeEnd": 720000,
|
||||
"type": "event",
|
||||
"id": "8222"
|
||||
},
|
||||
{
|
||||
"duration": 900000,
|
||||
"type": "delay",
|
||||
"revision": 0,
|
||||
"id": "a386"
|
||||
},
|
||||
{
|
||||
"title": "Add delay blocks to affect all events",
|
||||
"timeStart": 37320000,
|
||||
"timeEnd": 38520000,
|
||||
"type": "event",
|
||||
"id": "6dce"
|
||||
},
|
||||
{
|
||||
"title": "Add and remove events with [+] and [-]",
|
||||
"timeStart": 38520000,
|
||||
"timeEnd": 45120000,
|
||||
"type": "event",
|
||||
"id": "2651"
|
||||
},
|
||||
{
|
||||
"type": "block",
|
||||
"id": "e6a1"
|
||||
},
|
||||
{
|
||||
"title": "And control whether they are public",
|
||||
"timeStart": 46800000,
|
||||
"timeEnd": 57600000,
|
||||
"type": "event",
|
||||
"id": "1358"
|
||||
}
|
||||
];
|
||||
|
||||
const expected = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"timeStart": 28800000,
|
||||
"timeEnd": 30600000,
|
||||
"type": "event",
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"timeStart": 34920000+60000,
|
||||
"timeEnd": 35520000+60000,
|
||||
"type": "event",
|
||||
"id": "8ee5"
|
||||
},
|
||||
{
|
||||
"title": "Use simpler times to create a timer",
|
||||
"timeStart": 120000+60000,
|
||||
"timeEnd": 720000+60000,
|
||||
"type": "event",
|
||||
"id": "8222"
|
||||
},
|
||||
{
|
||||
"title": "Add delay blocks to affect all events",
|
||||
"timeStart": 37320000+60000+900000,
|
||||
"timeEnd": 38520000+60000+900000,
|
||||
"type": "event",
|
||||
"id": "6dce"
|
||||
},
|
||||
{
|
||||
"title": "Add and remove events with [+] and [-]",
|
||||
"timeStart": 38520000+60000+900000,
|
||||
"timeEnd": 45120000+60000+900000,
|
||||
"type": "event",
|
||||
"id": "2651"
|
||||
},
|
||||
{
|
||||
"title": "And control whether they are public",
|
||||
"timeStart": 46800000,
|
||||
"timeEnd": 57600000,
|
||||
"type": "event",
|
||||
"id": "1358"
|
||||
}
|
||||
]
|
||||
|
||||
expect(getEventsWithDelay(testData)).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
describe('getEventsWithDelay edge cases', () => {
|
||||
|
||||
test('given an empty array', () => {
|
||||
const emptyArray = {
|
||||
test: [],
|
||||
expect: [],
|
||||
}
|
||||
|
||||
expect(getEventsWithDelay(emptyArray.test)).toStrictEqual(emptyArray.expect);
|
||||
});
|
||||
|
||||
test('given an undefined object', () => {
|
||||
const withUndefined = {
|
||||
test: undefined,
|
||||
expect: [],
|
||||
}
|
||||
|
||||
expect(getEventsWithDelay(withUndefined.test)).toStrictEqual(withUndefined.expect);
|
||||
});
|
||||
|
||||
test('given a corrupted event object', () => {
|
||||
const testData = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"timeEnd": 30600000,
|
||||
"type": "event",
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"duration": 60000,
|
||||
"type": "delay",
|
||||
"id": "24240"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"timeStart": 34920000,
|
||||
"timeEnd": 35520000,
|
||||
"type": "event",
|
||||
"id": "8ee5"
|
||||
}
|
||||
];
|
||||
const expected = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"timeEnd": 30600000,
|
||||
"type": "event",
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"timeStart": 34920000+60000,
|
||||
"timeEnd": 35520000+60000,
|
||||
"type": "event",
|
||||
"id": "8ee5"
|
||||
}
|
||||
];
|
||||
|
||||
expect(getEventsWithDelay(testData)).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('given a corrupted delay object', () => {
|
||||
const testData = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"timeStart": 28800000,
|
||||
"timeEnd": 30600000,
|
||||
"type": "event",
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"type": "delay",
|
||||
"id": "24240"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"timeStart": 34920000,
|
||||
"timeEnd": 35520000,
|
||||
"type": "event",
|
||||
"id": "8ee5"
|
||||
}
|
||||
];
|
||||
const expected = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"timeStart": 28800000,
|
||||
"timeEnd": 30600000,
|
||||
"type": "event",
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"timeStart": 34920000,
|
||||
"timeEnd": 35520000,
|
||||
"type": "event",
|
||||
"id": "8ee5"
|
||||
}
|
||||
];
|
||||
|
||||
expect(getEventsWithDelay(testData)).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test trimEventlist function', () => {
|
||||
|
||||
const limit = 8;
|
||||
const testData = [
|
||||
{id: '1'},
|
||||
{id: '2'},
|
||||
{id: '3'},
|
||||
{id: '4'},
|
||||
{id: '5'},
|
||||
{id: '6'},
|
||||
{id: '7'},
|
||||
{id: '8'},
|
||||
{id: '9'},
|
||||
{id: '10'},
|
||||
{id: '11'},
|
||||
{id: '12'},
|
||||
];
|
||||
|
||||
|
||||
test('when we use the first item', () => {
|
||||
const selectedId = '1';
|
||||
const expected = [
|
||||
{id: '1'},
|
||||
{id: '2'},
|
||||
{id: '3'},
|
||||
{id: '4'},
|
||||
{id: '5'},
|
||||
{id: '6'},
|
||||
{id: '7'},
|
||||
{id: '8'},
|
||||
];
|
||||
|
||||
const l = trimEventlist(testData, selectedId, limit);
|
||||
expect(l.length).toBe(limit);
|
||||
expect(l).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('when we use the third item', () => {
|
||||
const selectedId = '3';
|
||||
const expected = [
|
||||
{id: '1'},
|
||||
{id: '2'},
|
||||
{id: '3'},
|
||||
{id: '4'},
|
||||
{id: '5'},
|
||||
{id: '6'},
|
||||
{id: '7'},
|
||||
{id: '8'}
|
||||
];
|
||||
|
||||
const l = trimEventlist(testData, selectedId, limit);
|
||||
expect(l.length).toBe(limit);
|
||||
expect(l).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('when we use the fourth item', () => {
|
||||
const selectedId = '4';
|
||||
const expected = [
|
||||
{id: '2'},
|
||||
{id: '3'},
|
||||
{id: '4'},
|
||||
{id: '5'},
|
||||
{id: '6'},
|
||||
{id: '7'},
|
||||
{id: '8'},
|
||||
{id: '9'}
|
||||
];
|
||||
|
||||
const l = trimEventlist(testData, selectedId, limit);
|
||||
expect(l.length).toBe(limit);
|
||||
expect(l).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('if selected is not found', () => {
|
||||
const selectedId = '15';
|
||||
const expected = [
|
||||
{id: '1'},
|
||||
{id: '2'},
|
||||
{id: '3'},
|
||||
{id: '4'},
|
||||
{id: '5'},
|
||||
{id: '6'},
|
||||
{id: '7'},
|
||||
{id: '8'},
|
||||
];
|
||||
|
||||
const l = trimEventlist(testData, selectedId, limit);
|
||||
expect(l.length).toBe(limit);
|
||||
expect(l).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test formatEvents function', () => {
|
||||
const testEvent = [
|
||||
{
|
||||
"title": "Welcome to Ontime",
|
||||
"subtitle": "Subtitles are useful",
|
||||
"presenter": "cpvalente",
|
||||
"note": "Maybe a running note for the operator?",
|
||||
"timeStart": 28800000,
|
||||
"timeEnd": 30600000,
|
||||
"isPublic": false,
|
||||
"type": "event",
|
||||
"revision": 0,
|
||||
"id": "5946"
|
||||
},
|
||||
{
|
||||
"title": "Unless recalled by the OSC address",
|
||||
"subtitle": "",
|
||||
"presenter": "",
|
||||
"note": "In green, below",
|
||||
"timeStart": 34800000,
|
||||
"timeEnd": 35400000,
|
||||
"isPublic": false,
|
||||
"type": "event",
|
||||
"revision": 0,
|
||||
"id": "8ee5"
|
||||
}
|
||||
];
|
||||
|
||||
test ('it parses correctly', () => {
|
||||
const selectedId = 'otherEvent';
|
||||
const nextId = 'notHere';
|
||||
const expected = [
|
||||
{
|
||||
id: '5946',
|
||||
time: '08:00 - 08:30',
|
||||
title: 'Welcome to Ontime',
|
||||
isNow: false,
|
||||
isNext: false,
|
||||
},
|
||||
{
|
||||
id: '8ee5',
|
||||
time: '09:40 - 09:50',
|
||||
title: 'Unless recalled by the OSC address',
|
||||
isNow: false,
|
||||
isNext: false,
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
const parsed = formatEventList(testEvent, selectedId, nextId, true);
|
||||
expect(parsed).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test ('it handles selected correctly', () => {
|
||||
const selectedId = '5946';
|
||||
const nextId = '8ee5';
|
||||
const expected = [
|
||||
{
|
||||
id: '5946',
|
||||
time: '08:00 - 08:30',
|
||||
title: 'Welcome to Ontime',
|
||||
isNow: true,
|
||||
isNext: false,
|
||||
},
|
||||
{
|
||||
id: '8ee5',
|
||||
time: '09:40 - 09:50',
|
||||
title: 'Unless recalled by the OSC address',
|
||||
isNow: false,
|
||||
isNext: true,
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
const parsed = formatEventList(testEvent, selectedId, nextId,true);
|
||||
expect(parsed).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test ('it handles next correctly', () => {
|
||||
const selectedId = '8ee5';
|
||||
const nextId = 'notHere';
|
||||
|
||||
const expected = [
|
||||
{
|
||||
id: '5946',
|
||||
time: '08:00 - 08:30',
|
||||
title: 'Welcome to Ontime',
|
||||
isNow: false,
|
||||
isNext: false,
|
||||
},
|
||||
{
|
||||
id: '8ee5',
|
||||
time: '09:40 - 09:50',
|
||||
title: 'Unless recalled by the OSC address',
|
||||
isNow: true,
|
||||
isNext: false,
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
const parsed = formatEventList(testEvent, selectedId, nextId, true);
|
||||
expect(parsed).toStrictEqual(expected);
|
||||
});
|
||||
})
|
||||
@@ -40,11 +40,11 @@ export const stringFromMillis = (
|
||||
* another go at simpler string formatting (counters)
|
||||
* @description Converts seconds to string representing time
|
||||
* @param {number} seconds - time in seconds
|
||||
* @param {boolean} hideZero - wether to show hours in case its 00
|
||||
* @param {boolean} [hideZero] - whether to show hours in case its 00
|
||||
* @returns {string} String representing absolute time 00:12:02
|
||||
*/
|
||||
|
||||
export function formatDisplay(seconds, hideZero) {
|
||||
export function formatDisplay(seconds, hideZero=false) {
|
||||
// add an extra 0 if necessary
|
||||
const format = (val) => `0${Math.floor(val)}`.slice(-2);
|
||||
|
||||
@@ -59,7 +59,6 @@ export function formatDisplay(seconds, hideZero) {
|
||||
/**
|
||||
* @description Converts milliseconds to seconds
|
||||
* @param {number} millis - time in seconds
|
||||
* @param {boolean} hideZero - wether to show hours in case its 00
|
||||
* @returns {number} Amount in seconds
|
||||
*/
|
||||
|
||||
@@ -71,7 +70,6 @@ export const millisToSeconds = (millis) => {
|
||||
/**
|
||||
* @description Converts milliseconds to seconds
|
||||
* @param {number} millis - time in seconds
|
||||
* @param {boolean} hideZero - wether to show hours in case its 00
|
||||
* @returns {number} Amount in seconds
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @description From a list of events, returns only events of type event with calculated delays
|
||||
* @param {Object[]} events - given events
|
||||
* @returns {Object[]} Filtered events with calculated delays
|
||||
*/
|
||||
import {stringFromMillis} from "./dateConfig";
|
||||
|
||||
export const getEventsWithDelay = (events) => {
|
||||
|
||||
if (events == null) return [];
|
||||
|
||||
const unfilteredEvents = [...events];
|
||||
|
||||
// Add running delay
|
||||
let delay = 0;
|
||||
for (const e of unfilteredEvents) {
|
||||
if (e.type === 'block') delay = 0;
|
||||
else if (e.type === 'delay') delay = delay + e.duration;
|
||||
else if (e.type === 'event' && delay > 0) {
|
||||
e.timeStart += delay;
|
||||
e.timeEnd += delay;
|
||||
}
|
||||
}
|
||||
|
||||
// filter just events
|
||||
return unfilteredEvents.filter((e) => e.type === 'event');
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Returns trimmed event list array
|
||||
* @param {Object[]} events - given events
|
||||
* @param {string} selectedId - id of currently selected event
|
||||
* @param {number} limit - max number of events to return
|
||||
* @returns {Object[]} Event list with maximum <limit> objects
|
||||
*/
|
||||
export const trimEventlist = (events, selectedId, limit) => {
|
||||
if (events == null) return [];
|
||||
|
||||
const BEFORE = 2;
|
||||
const trimmedEvents = [...events];
|
||||
|
||||
// limit events length if necessary
|
||||
if (limit != null) {
|
||||
while (trimmedEvents.length > limit) {
|
||||
const idx = trimmedEvents.findIndex((e) => e.id === selectedId);
|
||||
if (idx <= BEFORE) { trimmedEvents.pop(); }
|
||||
else { trimmedEvents.shift(); }
|
||||
}
|
||||
}
|
||||
return trimmedEvents;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Returns list of events formatted to be displayed
|
||||
* @param {Object[]} events - given events
|
||||
* @param {string} selectedId - id of currently selected event
|
||||
* @param {string} nextId - id of next event
|
||||
* @param {boolean} [showEnd] - whether to show the end time
|
||||
* @returns {Object[]} Formatted list of events [{time: -, title: -, isNow, isNext}]
|
||||
*/
|
||||
export const formatEventList = (events, selectedId, nextId, showEnd = false) => {
|
||||
if (events == null) return [];
|
||||
|
||||
const givenEvents = [...events];
|
||||
|
||||
// format list
|
||||
let formattedEvents = [];
|
||||
for (const g of givenEvents) {
|
||||
const start = stringFromMillis(g.timeStart, false);
|
||||
const end = stringFromMillis(g.timeEnd, false);
|
||||
|
||||
formattedEvents.push({
|
||||
id: g.id,
|
||||
time: showEnd ? `${start} - ${end}` : start,
|
||||
title: g.title,
|
||||
isNow: g.id === selectedId,
|
||||
isNext: g.id === nextId,
|
||||
});
|
||||
}
|
||||
|
||||
return formattedEvents;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user