mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-21 06:59:09 +00:00
Prefeat/skip (#188)
* refactor: refactor size of event list * refactor: optimise event mutations * refactor: prepare skip feature * refactor: update tests * refactor: simplify type assertion
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime",
|
"name": "ontime",
|
||||||
"version": "1.4.0",
|
"version": "1.4.1",
|
||||||
"author": "Carlos Valente",
|
"author": "Carlos Valente",
|
||||||
"description": "Time keeping for live events",
|
"description": "Time keeping for live events",
|
||||||
"repository": "https://github.com/cpvalente/ontime",
|
"repository": "https://github.com/cpvalente/ontime",
|
||||||
|
|||||||
@@ -67,8 +67,7 @@ export class EventTimer extends Timer {
|
|||||||
// call general title reset
|
// call general title reset
|
||||||
this._resetSelection();
|
this._resetSelection();
|
||||||
|
|
||||||
this.numEvents = 0;
|
this._eventlist = [];
|
||||||
this._eventlist = null;
|
|
||||||
this.onAir = false;
|
this.onAir = false;
|
||||||
|
|
||||||
// initialise socketIO server
|
// initialise socketIO server
|
||||||
@@ -154,16 +153,17 @@ export class EventTimer extends Timer {
|
|||||||
* Broadcasts complete object state
|
* Broadcasts complete object state
|
||||||
*/
|
*/
|
||||||
broadcastState() {
|
broadcastState() {
|
||||||
|
const numEvents = this._eventlist.length;
|
||||||
this.broadcastTimer();
|
this.broadcastTimer();
|
||||||
this.io.emit('playstate', this.state);
|
this.io.emit('playstate', this.state);
|
||||||
this.io.emit('selected', {
|
this.io.emit('selected', {
|
||||||
id: this.selectedEventId,
|
id: this.selectedEventId,
|
||||||
index: this.selectedEventIndex,
|
index: this.selectedEventIndex,
|
||||||
total: this.numEvents,
|
total: numEvents,
|
||||||
});
|
});
|
||||||
this.io.emit('selected-id', this.selectedEventId);
|
this.io.emit('selected-id', this.selectedEventId);
|
||||||
this.io.emit('next-id', this.nextEventId);
|
this.io.emit('next-id', this.nextEventId);
|
||||||
this.io.emit('numevents', this.numEvents);
|
this.io.emit('numevents', numEvents);
|
||||||
this.io.emit('publicselected-id', this.selectedPublicEventId);
|
this.io.emit('publicselected-id', this.selectedPublicEventId);
|
||||||
this.io.emit('publicnext-id', this.nextPublicEventId);
|
this.io.emit('publicnext-id', this.nextPublicEventId);
|
||||||
this.io.emit('titles', this.titles);
|
this.io.emit('titles', this.titles);
|
||||||
@@ -188,16 +188,17 @@ export class EventTimer extends Timer {
|
|||||||
*/
|
*/
|
||||||
trigger(action, payload) {
|
trigger(action, payload) {
|
||||||
let success = true;
|
let success = true;
|
||||||
|
const numEvents = this._eventlist.length;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'start': {
|
case 'start': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Play Mode Start');
|
this.info('PLAYBACK', 'Play Mode Start');
|
||||||
this.start();
|
this.start();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'startById': {
|
case 'startById': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
const loaded = this.loadEventById(payload);
|
const loaded = this.loadEventById(payload);
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
this.info('PLAYBACK', `Loaded event with ID ${payload}`);
|
this.info('PLAYBACK', `Loaded event with ID ${payload}`);
|
||||||
@@ -209,7 +210,7 @@ export class EventTimer extends Timer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'startByIndex': {
|
case 'startByIndex': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
const loaded = this.loadEventByIndex(payload);
|
const loaded = this.loadEventByIndex(payload);
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
this.info('PLAYBACK', `Loaded event with index ${payload}`);
|
this.info('PLAYBACK', `Loaded event with index ${payload}`);
|
||||||
@@ -221,42 +222,42 @@ export class EventTimer extends Timer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'pause': {
|
case 'pause': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Play Mode Pause');
|
this.info('PLAYBACK', 'Play Mode Pause');
|
||||||
this.pause();
|
this.pause();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'stop': {
|
case 'stop': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Play Mode Stop');
|
this.info('PLAYBACK', 'Play Mode Stop');
|
||||||
this.stop();
|
this.stop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'roll': {
|
case 'roll': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Play Mode Roll');
|
this.info('PLAYBACK', 'Play Mode Roll');
|
||||||
this.roll();
|
this.roll();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'previous': {
|
case 'previous': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Play Mode Previous');
|
this.info('PLAYBACK', 'Play Mode Previous');
|
||||||
this.previous();
|
this.previous();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'next': {
|
case 'next': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Play Mode Next');
|
this.info('PLAYBACK', 'Play Mode Next');
|
||||||
this.next();
|
this.next();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'loadById': {
|
case 'loadById': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
const loaded = this.loadEventById(payload);
|
const loaded = this.loadEventById(payload);
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
this.info('PLAYBACK', `Loaded event with ID ${payload}`);
|
this.info('PLAYBACK', `Loaded event with ID ${payload}`);
|
||||||
@@ -266,7 +267,7 @@ export class EventTimer extends Timer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'loadByIndex': {
|
case 'loadByIndex': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
const loaded = this.loadEventByIndex(payload);
|
const loaded = this.loadEventByIndex(payload);
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
this.info('PLAYBACK', `Loaded event with index ${payload}`);
|
this.info('PLAYBACK', `Loaded event with index ${payload}`);
|
||||||
@@ -276,14 +277,14 @@ export class EventTimer extends Timer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'unload': {
|
case 'unload': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Events unloaded');
|
this.info('PLAYBACK', 'Events unloaded');
|
||||||
this.unload();
|
this.unload();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'reload': {
|
case 'reload': {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return false;
|
if (!numEvents) return false;
|
||||||
// Call action and force update
|
// Call action and force update
|
||||||
this.info('PLAYBACK', 'Reloaded event');
|
this.info('PLAYBACK', 'Reloaded event');
|
||||||
this.reload();
|
this.reload();
|
||||||
@@ -637,6 +638,20 @@ export class EventTimer extends Timer {
|
|||||||
socket.emit('playstate', this.state);
|
socket.emit('playstate', this.state);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('set-loadid', (data) => {
|
||||||
|
this.trigger('loadById', data);
|
||||||
|
socket.emit('playstate', this.state);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('set-loadindex', (data) => {
|
||||||
|
const eventIndex = Number(data);
|
||||||
|
if (isNaN(eventIndex)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.trigger('loadByIndex', data);
|
||||||
|
socket.emit('playstate', this.state);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('set-pause', () => {
|
socket.on('set-pause', () => {
|
||||||
this.trigger('pause');
|
this.trigger('pause');
|
||||||
socket.emit('playstate', this.state);
|
socket.emit('playstate', this.state);
|
||||||
@@ -732,7 +747,7 @@ export class EventTimer extends Timer {
|
|||||||
socket.emit('selected', {
|
socket.emit('selected', {
|
||||||
id: this.selectedEventId,
|
id: this.selectedEventId,
|
||||||
index: this.selectedEventIndex,
|
index: this.selectedEventIndex,
|
||||||
total: this.numEvents,
|
total: this._eventlist.length,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -741,7 +756,7 @@ export class EventTimer extends Timer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on('get-numevents', () => {
|
socket.on('get-numevents', () => {
|
||||||
socket.emit('numevents', this.numEvents);
|
socket.emit('numevents', this._eventlist.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('get-next-id', () => {
|
socket.on('get-next-id', () => {
|
||||||
@@ -831,13 +846,12 @@ export class EventTimer extends Timer {
|
|||||||
|
|
||||||
// set general
|
// set general
|
||||||
this._eventlist = [];
|
this._eventlist = [];
|
||||||
this.numEvents = 0;
|
|
||||||
|
|
||||||
// update lifecycle: onStop
|
// update lifecycle: onStop
|
||||||
this.ontimeCycle = this.cycleState.onStop;
|
this.ontimeCycle = this.cycleState.onStop;
|
||||||
|
|
||||||
// update clients
|
// update clients
|
||||||
this.broadcastThis('numevents', this.numEvents);
|
this.broadcastThis('numevents', this._eventlist.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -845,7 +859,7 @@ export class EventTimer extends Timer {
|
|||||||
* @param {array} eventlist
|
* @param {array} eventlist
|
||||||
*/
|
*/
|
||||||
setupWithEventList(eventlist) {
|
setupWithEventList(eventlist) {
|
||||||
if (!Array.isArray(eventlist) || eventlist.length < 1) return;
|
if (!Array.isArray(eventlist) || !eventlist.length) return;
|
||||||
|
|
||||||
// filter only events
|
// filter only events
|
||||||
const events = eventlist.filter((e) => e.type === 'event');
|
const events = eventlist.filter((e) => e.type === 'event');
|
||||||
@@ -853,7 +867,6 @@ export class EventTimer extends Timer {
|
|||||||
|
|
||||||
// set general
|
// set general
|
||||||
this._eventlist = events;
|
this._eventlist = events;
|
||||||
this.numEvents = numEvents;
|
|
||||||
|
|
||||||
// list may contain no events
|
// list may contain no events
|
||||||
if (numEvents < 1) return;
|
if (numEvents < 1) return;
|
||||||
@@ -873,16 +886,14 @@ export class EventTimer extends Timer {
|
|||||||
* @param {array} eventlist
|
* @param {array} eventlist
|
||||||
*/
|
*/
|
||||||
updateEventList(eventlist) {
|
updateEventList(eventlist) {
|
||||||
// filter only events
|
if (!Array.isArray(eventlist) || !eventlist.length) return;
|
||||||
const events = eventlist.filter((e) => e.type === 'event');
|
|
||||||
const numEvents = events.length;
|
|
||||||
|
|
||||||
// is this the first event
|
// filter only events
|
||||||
const first = this.numEvents === 0;
|
const events = eventlist.filter((e) => e.type === 'event' && !e.skip);
|
||||||
|
const numEvents = events.length;
|
||||||
|
|
||||||
// set general
|
// set general
|
||||||
this._eventlist = events;
|
this._eventlist = events;
|
||||||
this.numEvents = numEvents;
|
|
||||||
|
|
||||||
// list may be empty
|
// list may be empty
|
||||||
if (numEvents < 1) {
|
if (numEvents < 1) {
|
||||||
@@ -890,8 +901,8 @@ export class EventTimer extends Timer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto load if is the only event
|
// auto load if is the there was nothing before
|
||||||
if (first) {
|
if (!this._eventlist.length) {
|
||||||
this.loadEvent(0);
|
this.loadEvent(0);
|
||||||
} else if (this.selectedEventId != null) {
|
} else if (this.selectedEventId != null) {
|
||||||
// handle reload selected
|
// handle reload selected
|
||||||
@@ -925,7 +936,20 @@ export class EventTimer extends Timer {
|
|||||||
updateSingleEvent(id, entry) {
|
updateSingleEvent(id, entry) {
|
||||||
// find object in events
|
// find object in events
|
||||||
const eventIndex = this._eventlist.findIndex((e) => e.id === id);
|
const eventIndex = this._eventlist.findIndex((e) => e.id === id);
|
||||||
if (eventIndex === -1) return;
|
if (eventIndex === -1) {
|
||||||
|
throw 'Event not found';
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if event is set to be skipped
|
||||||
|
if (entry.skip) {
|
||||||
|
// stop event if running
|
||||||
|
if (id === this.selectedEventId) {
|
||||||
|
this.trigger('stop');
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete event
|
||||||
|
this.deleteId(id);
|
||||||
|
}
|
||||||
|
|
||||||
// update event in memory
|
// update event in memory
|
||||||
const e = this._eventlist[eventIndex];
|
const e = this._eventlist[eventIndex];
|
||||||
@@ -961,6 +985,71 @@ export class EventTimer extends Timer {
|
|||||||
this.runCycle();
|
this.runCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description inserts an event after a given id
|
||||||
|
* @param event
|
||||||
|
* @param previousId
|
||||||
|
*/
|
||||||
|
insertEventAfterId(event, previousId) {
|
||||||
|
// find object in events
|
||||||
|
const previousIndex = this._eventlist.findIndex((e) => e.id === previousId);
|
||||||
|
if (previousIndex === -1) {
|
||||||
|
throw 'Event not found';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousIndex + 1 >= this._eventlist.length) {
|
||||||
|
this._eventlist.push(event);
|
||||||
|
} else {
|
||||||
|
this._eventlist.splice(previousIndex + 1, 0, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// check if entry is running
|
||||||
|
if (event.id === this.selectedEventId) {
|
||||||
|
// handle reload selected
|
||||||
|
// Reload data if running
|
||||||
|
const type =
|
||||||
|
this.selectedEventId === event.id && this._startedAt != null ? 'reload' : 'load';
|
||||||
|
this.loadEvent(this.selectedEventIndex, type);
|
||||||
|
} else if (event.id === this.nextEventId) {
|
||||||
|
// roll needs to recalculate
|
||||||
|
if (this.state === 'roll') {
|
||||||
|
this.rollLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load titles
|
||||||
|
if ('title' in event || 'subtitle' in event || 'presenter' in event) {
|
||||||
|
this._loadTitlesNext();
|
||||||
|
this._loadTitlesNow();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.error('SERVER', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update clients
|
||||||
|
this.broadcastState();
|
||||||
|
|
||||||
|
// run cycle
|
||||||
|
this.runCycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description inserts an event in the first position of the list
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
insertEventAtStart(event) {
|
||||||
|
// Insert at beginning
|
||||||
|
this._eventlist.unshift(event);
|
||||||
|
|
||||||
|
// update clients
|
||||||
|
this.broadcastState();
|
||||||
|
|
||||||
|
// run cycle
|
||||||
|
this.runCycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deleted an event from the list by its id
|
* Deleted an event from the list by its id
|
||||||
* @param {string} eventId
|
* @param {string} eventId
|
||||||
@@ -972,7 +1061,6 @@ export class EventTimer extends Timer {
|
|||||||
|
|
||||||
// delete event and update count
|
// delete event and update count
|
||||||
this._eventlist.splice(eventIndex, 1);
|
this._eventlist.splice(eventIndex, 1);
|
||||||
this.numEvents = this._eventlist.length;
|
|
||||||
|
|
||||||
// reload data if necessary
|
// reload data if necessary
|
||||||
if (eventId === this.selectedEventId) {
|
if (eventId === this.selectedEventId) {
|
||||||
@@ -1017,7 +1105,7 @@ export class EventTimer extends Timer {
|
|||||||
* @param {number} eventIndex - Index of event in eventlist
|
* @param {number} eventIndex - Index of event in eventlist
|
||||||
*/
|
*/
|
||||||
loadEventByIndex(eventIndex) {
|
loadEventByIndex(eventIndex) {
|
||||||
if (eventIndex === -1 || eventIndex > this.numEvents) return false;
|
if (eventIndex === -1 || eventIndex > this._eventlist.length) return false;
|
||||||
this.pause();
|
this.pause();
|
||||||
this.loadEvent(eventIndex, 'load');
|
this.loadEvent(eventIndex, 'load');
|
||||||
// run cycle
|
// run cycle
|
||||||
@@ -1194,11 +1282,13 @@ export class EventTimer extends Timer {
|
|||||||
this.titlesPublic.presenterNext = null;
|
this.titlesPublic.presenterNext = null;
|
||||||
this.nextPublicEventId = null;
|
this.nextPublicEventId = null;
|
||||||
|
|
||||||
if (this.selectedEventIndex < this.numEvents - 1) {
|
const numEvents = this._eventlist.length;
|
||||||
|
|
||||||
|
if (this.selectedEventIndex < numEvents - 1) {
|
||||||
let nextPublic = false;
|
let nextPublic = false;
|
||||||
let nextPrivate = false;
|
let nextPrivate = false;
|
||||||
|
|
||||||
for (let i = this.selectedEventIndex + 1; i < this.numEvents; i++) {
|
for (let i = this.selectedEventIndex + 1; i < numEvents; i++) {
|
||||||
// check that is the right type
|
// check that is the right type
|
||||||
if (this._eventlist[i].type === 'event') {
|
if (this._eventlist[i].type === 'event') {
|
||||||
// if we have not set private
|
// if we have not set private
|
||||||
@@ -1410,7 +1500,7 @@ export class EventTimer extends Timer {
|
|||||||
// do we need to change
|
// do we need to change
|
||||||
if (this.state === 'roll') return;
|
if (this.state === 'roll') return;
|
||||||
|
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return;
|
if (!this._eventlist.length) return;
|
||||||
|
|
||||||
// set state
|
// set state
|
||||||
this.state = 'roll';
|
this.state = 'roll';
|
||||||
@@ -1424,7 +1514,7 @@ export class EventTimer extends Timer {
|
|||||||
|
|
||||||
previous() {
|
previous() {
|
||||||
// check that we have events to run
|
// check that we have events to run
|
||||||
if (this.numEvents < 1) return;
|
if (!this._eventlist.length) return;
|
||||||
|
|
||||||
// maybe this is the first event?
|
// maybe this is the first event?
|
||||||
if (this.selectedEventIndex === 0) return;
|
if (this.selectedEventIndex === 0) return;
|
||||||
@@ -1446,20 +1536,19 @@ export class EventTimer extends Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
|
const numEvents = this._eventlist.length;
|
||||||
// check that we have events to run
|
// check that we have events to run
|
||||||
if (this.numEvents < 1) return;
|
if (!numEvents) return;
|
||||||
|
|
||||||
// maybe this is the last event?
|
// maybe this is the last event?
|
||||||
if (this.selectedEventIndex === this.numEvents - 1) return;
|
if (this.selectedEventIndex === numEvents - 1) return;
|
||||||
|
|
||||||
// if there is no event running, go to first
|
// if there is no event running, go to first
|
||||||
if (this.selectedEventIndex === null) {
|
if (this.selectedEventIndex === null) {
|
||||||
this.loadEvent(0);
|
this.loadEvent(0);
|
||||||
} else {
|
} else {
|
||||||
const gotoEvent =
|
const gotoEvent =
|
||||||
this.selectedEventIndex < this.numEvents - 1
|
this.selectedEventIndex < numEvents - 1 ? this.selectedEventIndex + 1 : numEvents - 1;
|
||||||
? this.selectedEventIndex + 1
|
|
||||||
: this.numEvents - 1;
|
|
||||||
if (gotoEvent === this.selectedEventIndex) return;
|
if (gotoEvent === this.selectedEventIndex) return;
|
||||||
this.loadEvent(gotoEvent);
|
this.loadEvent(gotoEvent);
|
||||||
}
|
}
|
||||||
@@ -1489,7 +1578,7 @@ export class EventTimer extends Timer {
|
|||||||
* @description reloads current event
|
* @description reloads current event
|
||||||
*/
|
*/
|
||||||
reload() {
|
reload() {
|
||||||
if (this.numEvents === 0 || this.numEvents == null) return;
|
if (!this._eventlist.length) return;
|
||||||
|
|
||||||
// change playstate
|
// change playstate
|
||||||
this.pause();
|
this.pause();
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ test('object instantiates correctly', async () => {
|
|||||||
expect(t.nextEventId).toBeNull();
|
expect(t.nextEventId).toBeNull();
|
||||||
expect(t.selectedPublicEventId).toBeNull();
|
expect(t.selectedPublicEventId).toBeNull();
|
||||||
expect(t.nextPublicEventId).toBeNull();
|
expect(t.nextPublicEventId).toBeNull();
|
||||||
expect(t.numEvents).toBe(0);
|
expect(t._eventlist.length).toBe(0);
|
||||||
expect(t._eventlist).toBeNull();
|
expect(t._eventlist).toStrictEqual([]);
|
||||||
expect(t.onAir).toBeFalsy();
|
expect(t.onAir).toBeFalsy();
|
||||||
|
|
||||||
t.shutdown();
|
t.shutdown();
|
||||||
@@ -85,7 +85,7 @@ describe('test triggers behaviour', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('does not allow triggering events with an empty list', (done) => {
|
test('does not allow triggering events with an empty list', (done) => {
|
||||||
expect(t.numEvents).toBe(0);
|
expect(t._eventlist.length).toBe(0);
|
||||||
|
|
||||||
expect(t.trigger('start')).toBeFalsy();
|
expect(t.trigger('start')).toBeFalsy();
|
||||||
expect(t.trigger('pause')).toBeFalsy();
|
expect(t.trigger('pause')).toBeFalsy();
|
||||||
@@ -104,7 +104,7 @@ describe('test triggers behaviour', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('...and is consistent by calling the class methods', (done) => {
|
test('...and is consistent by calling the class methods', (done) => {
|
||||||
expect(t.numEvents).toBe(0);
|
expect(t._eventlist.length).toBe(0);
|
||||||
expect(t.state).toBe('stop');
|
expect(t.state).toBe('stop');
|
||||||
|
|
||||||
t.start();
|
t.start();
|
||||||
|
|||||||
@@ -9,6 +9,22 @@ import {
|
|||||||
} from '../models/eventsDefinition.js';
|
} from '../models/eventsDefinition.js';
|
||||||
import { generateId } from '../utils/generate_id.js';
|
import { generateId } from '../utils/generate_id.js';
|
||||||
import { MAX_EVENTS } from '../settings.js';
|
import { MAX_EVENTS } from '../settings.js';
|
||||||
|
import { getPreviousPlayable } from '../utils/eventUtils.js';
|
||||||
|
|
||||||
|
async function _insertAndSync(newEvent) {
|
||||||
|
if (newEvent.order) {
|
||||||
|
const events = data.events;
|
||||||
|
await _insertAt(newEvent, newEvent.order);
|
||||||
|
const previousId = events?.[newEvent.order - 1]?.id;
|
||||||
|
_insertEventInTimerAfterId(newEvent, previousId);
|
||||||
|
} else if (newEvent.after) {
|
||||||
|
await _insertAfterId(newEvent, newEvent.after);
|
||||||
|
_insertEventInTimerAfterId(newEvent, newEvent.after);
|
||||||
|
} else {
|
||||||
|
await _insertAt(newEvent, 0);
|
||||||
|
_insertEventInTimerAfterId(newEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insets an event after a given index
|
* Insets an event after a given index
|
||||||
@@ -83,9 +99,32 @@ function _updateTimers() {
|
|||||||
global.timer.updateEventList(results);
|
global.timer.updateEventList(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates timer object single event
|
/**
|
||||||
function _updateTimersSingle(id, entry) {
|
* @description Adds an event to the timer after an event with given id
|
||||||
global.timer.updateSingleEvent(id, entry);
|
* @param {object} event
|
||||||
|
* @param {string} [previousId]
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _insertEventInTimerAfterId(event, previousId) {
|
||||||
|
if (typeof previousId === 'undefined') {
|
||||||
|
global.timer.insertEventAtStart(event);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
global.timer.insertEventAfterId(event, previousId);
|
||||||
|
} catch (error) {
|
||||||
|
global.timer.error('SERVER', `Unable to update object: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Updates timer object single event
|
||||||
|
* @param {string} id
|
||||||
|
* @param {object} event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _updateTimersSingle(id, event) {
|
||||||
|
global.timer.updateSingleEvent(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete a single entry in timer object
|
// Delete a single entry in timer object
|
||||||
@@ -148,22 +187,9 @@ export const eventsPost = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// get place where event should be
|
_insertAndSync(newEvent);
|
||||||
if (newEvent.order) {
|
|
||||||
await _insertAt(newEvent, newEvent.order);
|
|
||||||
} else if (newEvent.after) {
|
|
||||||
await _insertAfterId(newEvent, newEvent.after);
|
|
||||||
} else {
|
|
||||||
await _insertAt(newEvent, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update timers
|
|
||||||
_updateTimers();
|
|
||||||
|
|
||||||
// reply OK
|
|
||||||
res.sendStatus(201);
|
res.sendStatus(201);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
res.status(400).send(error);
|
res.status(400).send(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -183,30 +209,41 @@ export const eventsPut = async (req, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const eventIndex = data.events.findIndex((e) => e.id === eventId);
|
||||||
const eventIndex = data.events.findIndex((e) => e.id === eventId);
|
if (eventIndex === -1) {
|
||||||
if (eventIndex === -1) {
|
res.status(400).send(`No Id found found`);
|
||||||
res.status(400).send(`No Id found found`);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
const e = data.events[eventIndex];
|
const e = data.events[eventIndex];
|
||||||
data.events[eventIndex] = { ...e, ...req.body };
|
data.events[eventIndex] = { ...e, ...req.body };
|
||||||
data.events[eventIndex].revision++;
|
data.events[eventIndex].revision++;
|
||||||
await db.write();
|
await db.write();
|
||||||
|
|
||||||
// update timer
|
if (data.events[eventIndex].skip) {
|
||||||
_updateTimersSingle(eventId, req.body);
|
_deleteTimerId(eventId);
|
||||||
|
// if it is a skip, i make sure it is deleted from timer
|
||||||
|
// event id might already not exist
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
_updateTimersSingle(eventId, req.body);
|
||||||
|
} catch (error) {
|
||||||
|
if (error === 'Event not found') {
|
||||||
|
const { id: previousId } = getPreviousPlayable(data.events, e.id);
|
||||||
|
_insertEventInTimerAfterId(data.events[eventIndex], previousId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
res.status(400).send(error);
|
res.status(400).send(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create controller for PATCH request to '/events/'
|
// Create controller for PATCH request to '/events/'
|
||||||
// Returns -
|
// Returns -
|
||||||
|
// DEPRECATED
|
||||||
export const eventsPatch = async (req, res) => {
|
export const eventsPatch = async (req, res) => {
|
||||||
// Code is the same as put, call that
|
// Code is the same as put, call that
|
||||||
await eventsPut(req, res);
|
await eventsPut(req, res);
|
||||||
@@ -247,7 +284,6 @@ export const eventsReorder = async (req, res) => {
|
|||||||
|
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
res.status(400).send(error);
|
res.status(400).send(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const event = {
|
|||||||
timeType: 'start-end',
|
timeType: 'start-end',
|
||||||
duration: 0,
|
duration: 0,
|
||||||
isPublic: false,
|
isPublic: false,
|
||||||
|
skip: false,
|
||||||
colour: '',
|
colour: '',
|
||||||
user0: '',
|
user0: '',
|
||||||
user1: '',
|
user1: '',
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ router.post('/', eventsPost);
|
|||||||
router.put('/', eventsPut);
|
router.put('/', eventsPut);
|
||||||
|
|
||||||
// create route between controller and '/events/' endpoint
|
// create route between controller and '/events/' endpoint
|
||||||
|
// DEPRECATED
|
||||||
router.patch('/', eventsPatch);
|
router.patch('/', eventsPatch);
|
||||||
|
|
||||||
// create route between controller and '/events/reorder' endpoint
|
// create route between controller and '/events/reorder' endpoint
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import jest from 'jest-mock';
|
import jest from 'jest-mock';
|
||||||
import { dbModelv1, dbModelv1 as dbModel } from '../../models/dataModel.js';
|
import { dbModelv1, dbModelv1 as dbModel } from '../../models/dataModel.js';
|
||||||
import { parseExcel_v1, parseJson_v1, validateEvent_v1 } from '../parser.js';
|
import { isStringEmpty, parseExcel_v1, parseJson_v1, validateEvent_v1 } from '../parser.js';
|
||||||
import { makeString, validateDuration } from '../parserUtils.js';
|
import { makeString, validateDuration } from '../parserUtils.js';
|
||||||
import { parseAliases_v1, parseUserFields_v1 } from '../parserUtils_v1.js';
|
import { parseAliases_v1, parseUserFields_v1 } from '../parserUtils_v1.js';
|
||||||
|
|
||||||
@@ -42,7 +42,8 @@ describe('test json parser with valid def', () => {
|
|||||||
timeType: 'start-end',
|
timeType: 'start-end',
|
||||||
duration: 36000000 - 32400000,
|
duration: 36000000 - 32400000,
|
||||||
isPublic: true,
|
isPublic: true,
|
||||||
colour: '',
|
skip: true,
|
||||||
|
colour: 'red',
|
||||||
type: 'event',
|
type: 'event',
|
||||||
revision: 0,
|
revision: 0,
|
||||||
id: 'f24d',
|
id: 'f24d',
|
||||||
@@ -92,6 +93,7 @@ describe('test json parser with valid def', () => {
|
|||||||
timeType: 'start-end',
|
timeType: 'start-end',
|
||||||
duration: 39000000 - 37200000,
|
duration: 39000000 - 37200000,
|
||||||
isPublic: true,
|
isPublic: true,
|
||||||
|
skip: false,
|
||||||
colour: '',
|
colour: '',
|
||||||
type: 'event',
|
type: 'event',
|
||||||
revision: 0,
|
revision: 0,
|
||||||
@@ -208,6 +210,7 @@ describe('test json parser with valid def', () => {
|
|||||||
timeType: 'start-end',
|
timeType: 'start-end',
|
||||||
duration: 32400000 - 31500000,
|
duration: 32400000 - 31500000,
|
||||||
isPublic: false,
|
isPublic: false,
|
||||||
|
skip: false,
|
||||||
colour: '',
|
colour: '',
|
||||||
type: 'event',
|
type: 'event',
|
||||||
revision: 0,
|
revision: 0,
|
||||||
@@ -226,6 +229,37 @@ describe('test json parser with valid def', () => {
|
|||||||
expect(first).toStrictEqual(expected);
|
expect(first).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('second event is as a match', () => {
|
||||||
|
const second = parseResponse?.events[1];
|
||||||
|
const expected = {
|
||||||
|
title: 'Good Morning',
|
||||||
|
subtitle: 'Days schedule',
|
||||||
|
presenter: 'Carlos Valente',
|
||||||
|
note: '',
|
||||||
|
timeStart: 32400000,
|
||||||
|
timeEnd: 36000000,
|
||||||
|
timeType: 'start-end',
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
it('loaded event settings', () => {
|
it('loaded event settings', () => {
|
||||||
const eventTitle = parseResponse?.event?.title;
|
const eventTitle = parseResponse?.event?.title;
|
||||||
expect(eventTitle).toBe('This is a test definition');
|
expect(eventTitle).toBe('This is a test definition');
|
||||||
@@ -436,6 +470,7 @@ describe('test event validator', () => {
|
|||||||
timeStart: expect.any(Number),
|
timeStart: expect.any(Number),
|
||||||
timeEnd: expect.any(Number),
|
timeEnd: expect.any(Number),
|
||||||
isPublic: expect.any(Boolean),
|
isPublic: expect.any(Boolean),
|
||||||
|
skip: expect.any(Boolean),
|
||||||
revision: expect.any(Number),
|
revision: expect.any(Number),
|
||||||
type: expect.any(String),
|
type: expect.any(String),
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
@@ -534,6 +569,7 @@ describe('test parseExcel function', () => {
|
|||||||
'Presenter Name',
|
'Presenter Name',
|
||||||
'Event Subtitle',
|
'Event Subtitle',
|
||||||
'Is Public? (x)',
|
'Is Public? (x)',
|
||||||
|
'Skip? (x)',
|
||||||
'Notes',
|
'Notes',
|
||||||
'User0:test0',
|
'User0:test0',
|
||||||
'User1:test1',
|
'User1:test1',
|
||||||
@@ -554,6 +590,7 @@ describe('test parseExcel function', () => {
|
|||||||
'Carlos',
|
'Carlos',
|
||||||
'Getting things started',
|
'Getting things started',
|
||||||
'x',
|
'x',
|
||||||
|
'',
|
||||||
'Ballyhoo',
|
'Ballyhoo',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
@@ -578,6 +615,7 @@ describe('test parseExcel function', () => {
|
|||||||
'Still Carlos',
|
'Still Carlos',
|
||||||
'Derailing early',
|
'Derailing early',
|
||||||
'',
|
'',
|
||||||
|
'',
|
||||||
'Rainbow chase',
|
'Rainbow chase',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
@@ -606,6 +644,7 @@ describe('test parseExcel function', () => {
|
|||||||
presenter: 'Carlos',
|
presenter: 'Carlos',
|
||||||
subtitle: 'Getting things started',
|
subtitle: 'Getting things started',
|
||||||
isPublic: true,
|
isPublic: true,
|
||||||
|
skip: false,
|
||||||
note: 'Ballyhoo',
|
note: 'Ballyhoo',
|
||||||
user0: 'a0',
|
user0: 'a0',
|
||||||
user1: 'a1',
|
user1: 'a1',
|
||||||
@@ -627,6 +666,7 @@ describe('test parseExcel function', () => {
|
|||||||
presenter: 'Still Carlos',
|
presenter: 'Still Carlos',
|
||||||
subtitle: 'Derailing early',
|
subtitle: 'Derailing early',
|
||||||
isPublic: false,
|
isPublic: false,
|
||||||
|
skip: true,
|
||||||
note: 'Rainbow chase',
|
note: 'Rainbow chase',
|
||||||
user0: 'b0',
|
user0: 'b0',
|
||||||
user5: 'b5',
|
user5: 'b5',
|
||||||
@@ -642,6 +682,7 @@ describe('test parseExcel function', () => {
|
|||||||
expect(parsedData.events.presenter).toBe(expectedParsedEvents.presenter);
|
expect(parsedData.events.presenter).toBe(expectedParsedEvents.presenter);
|
||||||
expect(parsedData.events.subtitle).toBe(expectedParsedEvents.subtitle);
|
expect(parsedData.events.subtitle).toBe(expectedParsedEvents.subtitle);
|
||||||
expect(parsedData.events.isPublic).toBe(expectedParsedEvents.isPublic);
|
expect(parsedData.events.isPublic).toBe(expectedParsedEvents.isPublic);
|
||||||
|
expect(parsedData.events.skip).toBe(expectedParsedEvents.skip);
|
||||||
expect(parsedData.events.note).toBe(expectedParsedEvents.note);
|
expect(parsedData.events.note).toBe(expectedParsedEvents.note);
|
||||||
expect(parsedData.events.type).toBe(expectedParsedEvents.type);
|
expect(parsedData.events.type).toBe(expectedParsedEvents.type);
|
||||||
});
|
});
|
||||||
@@ -790,3 +831,24 @@ describe('test validateDuration()', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('isStringEmpty() function', () => {
|
||||||
|
describe('returns true with any non empty', () => {
|
||||||
|
const notEmpty = ['test', 'thisalso', '123', '#'];
|
||||||
|
for (const testValue of notEmpty) {
|
||||||
|
it(testValue, () => {
|
||||||
|
const isEmpty = isStringEmpty(testValue);
|
||||||
|
expect(isEmpty).toBe(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
describe('returns true empty string or undefined', () => {
|
||||||
|
const empty = ['', ' ', undefined, null];
|
||||||
|
for (const testValue of empty) {
|
||||||
|
it(`handles ${testValue}`, () => {
|
||||||
|
const isEmpty = isStringEmpty(testValue);
|
||||||
|
expect(isEmpty).toBe(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* @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 };
|
||||||
|
}
|
||||||
@@ -18,6 +18,19 @@ import { generateId } from './generate_id.js';
|
|||||||
export const EXCEL_MIME = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
export const EXCEL_MIME = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||||
export const JSON_MIME = 'application/json';
|
export const JSON_MIME = 'application/json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Whether a string is considered empty
|
||||||
|
* @param value
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
export const isStringEmpty = (value) => {
|
||||||
|
let v = value;
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
v = value.replace(/\s+/g, '');
|
||||||
|
}
|
||||||
|
return v === '' || !v;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Excel array parser
|
* @description Excel array parser
|
||||||
* @param {array} excelData - array with excel sheet
|
* @param {array} excelData - array with excel sheet
|
||||||
@@ -36,6 +49,7 @@ export const parseExcel_v1 = async (excelData) => {
|
|||||||
let presenterIndex = null;
|
let presenterIndex = null;
|
||||||
let subtitleIndex = null;
|
let subtitleIndex = null;
|
||||||
let isPublicIndex = null;
|
let isPublicIndex = null;
|
||||||
|
let skipIndex = null;
|
||||||
let notesIndex = null;
|
let notesIndex = null;
|
||||||
let colourIndex = null;
|
let colourIndex = null;
|
||||||
let user0Index = null;
|
let user0Index = null;
|
||||||
@@ -75,12 +89,9 @@ export const parseExcel_v1 = async (excelData) => {
|
|||||||
} else if (j === subtitleIndex) {
|
} else if (j === subtitleIndex) {
|
||||||
event.subtitle = column;
|
event.subtitle = column;
|
||||||
} else if (j === isPublicIndex) {
|
} else if (j === isPublicIndex) {
|
||||||
// whether column is not empty
|
event.isPublic = isStringEmpty(column);
|
||||||
let c = column;
|
} else if (j === skipIndex) {
|
||||||
if (typeof column === 'string') {
|
event.skip = isStringEmpty(column);
|
||||||
c = column.replace(/\s+/g, '');
|
|
||||||
}
|
|
||||||
event.isPublic = c !== '';
|
|
||||||
} else if (j === notesIndex) {
|
} else if (j === notesIndex) {
|
||||||
event.note = column;
|
event.note = column;
|
||||||
} else if (j === colourIndex) {
|
} else if (j === colourIndex) {
|
||||||
@@ -144,6 +155,11 @@ export const parseExcel_v1 = async (excelData) => {
|
|||||||
case 'public':
|
case 'public':
|
||||||
isPublicIndex = j;
|
isPublicIndex = j;
|
||||||
break;
|
break;
|
||||||
|
case 'skip? (x)':
|
||||||
|
case 'skip?':
|
||||||
|
case 'skip':
|
||||||
|
skipIndex = j;
|
||||||
|
break;
|
||||||
case 'notes':
|
case 'notes':
|
||||||
notesIndex = j;
|
notesIndex = j;
|
||||||
break;
|
break;
|
||||||
@@ -278,7 +294,8 @@ export const validateEvent_v1 = (eventArgs) => {
|
|||||||
timeEnd: end,
|
timeEnd: end,
|
||||||
timeType: 'start-end',
|
timeType: 'start-end',
|
||||||
duration: validateDuration(start, end),
|
duration: validateDuration(start, end),
|
||||||
isPublic: e.isPublic != null && typeof e.isPublic === 'boolean' ? e.isPublic : d.isPublic,
|
isPublic: typeof e.isPublic === 'boolean' ? e.isPublic : d.isPublic,
|
||||||
|
skip: typeof e.skip === 'boolean' ? e.skip : d.skip,
|
||||||
note: makeString(e.note, d.note),
|
note: makeString(e.note, d.note),
|
||||||
user0: makeString(e.user0, d.user0),
|
user0: makeString(e.user0, d.user0),
|
||||||
user1: makeString(e.user1, d.user1),
|
user1: makeString(e.user1, d.user1),
|
||||||
|
|||||||
Reference in New Issue
Block a user