mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 19:33:46 +00:00
V2 monorepo (#285)
* refactor(project structure): UI * refactor(project structure): extract utilities * refactor(project structure): remove unused * refactor(project structure): electron * refactor(project structure): server refactor: migrate to vitest refactor: monorepo config * refactor: extract application menu * refactor: exit process * refactor: extract tray menu * chore: electron build * Added Seconds in studio clock #282 --------- Co-authored-by: Fabian Posenau <fabian@fphome.de> --------- Co-authored-by: Fabian Posenau <fabian.p99@gmx.de> Co-authored-by: Fabian Posenau <fabian@fphome.de>
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
import { Server } from 'node-osc';
|
||||
import { PlaybackService } from '../services/PlaybackService.js';
|
||||
import { messageManager } from '../classes/message-manager/MessageManager.js';
|
||||
import { socketProvider } from '../classes/socket/SocketController.js';
|
||||
import { ADDRESS_MESSAGE_CONTROL } from '../classes/socket/socketConfig.js';
|
||||
|
||||
let oscServer = null;
|
||||
|
||||
/**
|
||||
* @description utility function to shut down osc server
|
||||
*/
|
||||
export const shutdownOSCServer = () => {
|
||||
if (oscServer != null) oscServer.close();
|
||||
};
|
||||
|
||||
/**
|
||||
* @description initialises OSC server
|
||||
* @param {object} config
|
||||
*/
|
||||
export const initiateOSC = (config) => {
|
||||
oscServer = new Server(config.port, '0.0.0.0');
|
||||
|
||||
oscServer.on('error', console.error);
|
||||
|
||||
oscServer.on('message', function (msg) {
|
||||
// message should look like /ontime/{path} {args} where
|
||||
// ontime: fixed message for app
|
||||
// path: command to be called
|
||||
// args: extra data, only used on some API entries (delay, goto)
|
||||
|
||||
// split message
|
||||
const [, address, path] = msg[0].split('/');
|
||||
const args = msg[1];
|
||||
|
||||
// get first part before (ontime)
|
||||
if (address !== 'ontime') {
|
||||
console.error('RX', `OSC IN: Message address ${address} not recognised`);
|
||||
return;
|
||||
}
|
||||
|
||||
// get second part (command)
|
||||
if (!path) {
|
||||
console.error('RX', 'OSC IN: No path found');
|
||||
return;
|
||||
}
|
||||
|
||||
switch (path.toLowerCase()) {
|
||||
case 'onair': {
|
||||
const featureData = messageManager.setOnAir(true);
|
||||
socketProvider.send(ADDRESS_MESSAGE_CONTROL, featureData);
|
||||
break;
|
||||
}
|
||||
case 'offair': {
|
||||
const featureData = messageManager.setOnAir(false);
|
||||
socketProvider.send(ADDRESS_MESSAGE_CONTROL, featureData);
|
||||
break;
|
||||
}
|
||||
case 'play': {
|
||||
PlaybackService.start();
|
||||
break;
|
||||
}
|
||||
case 'start': {
|
||||
try {
|
||||
const eventIndex = Number(args);
|
||||
if (isNaN(eventIndex)) {
|
||||
socketProvider.error('RX', `OSC IN: event index not recognised ${args}`);
|
||||
return;
|
||||
}
|
||||
PlaybackService.startByIndex(eventIndex);
|
||||
} catch (error) {
|
||||
console.log('Error loading event: ', error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'startid': {
|
||||
if (!args) {
|
||||
socketProvider.error('RX', `OSC IN: No ID in request`);
|
||||
return;
|
||||
}
|
||||
PlaybackService.loadById(args);
|
||||
break;
|
||||
}
|
||||
case 'pause': {
|
||||
PlaybackService.pause();
|
||||
break;
|
||||
}
|
||||
case 'prev': {
|
||||
PlaybackService.loadPrevious();
|
||||
break;
|
||||
}
|
||||
case 'next': {
|
||||
PlaybackService.loadNext();
|
||||
break;
|
||||
}
|
||||
case 'unload':
|
||||
case 'stop': {
|
||||
PlaybackService.stop();
|
||||
break;
|
||||
}
|
||||
case 'reload': {
|
||||
PlaybackService.reload();
|
||||
break;
|
||||
}
|
||||
case 'roll': {
|
||||
PlaybackService.roll();
|
||||
break;
|
||||
}
|
||||
case 'delay': {
|
||||
try {
|
||||
const delayTime = Number(args);
|
||||
if (isNaN(delayTime)) {
|
||||
socketProvider.error('RX', `OSC IN: delay time not recognised ${args}`);
|
||||
return;
|
||||
}
|
||||
PlaybackService.setDelay(delayTime);
|
||||
} catch (error) {
|
||||
console.log('Error adding delay: ', error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'goto':
|
||||
case 'load': {
|
||||
try {
|
||||
const eventIndex = Number(args);
|
||||
if (isNaN(eventIndex) || eventIndex <= 0) {
|
||||
socketProvider.error(
|
||||
'RX',
|
||||
`OSC IN: event index not recognised or out of range ${eventIndex}`
|
||||
);
|
||||
} else {
|
||||
PlaybackService.loadByIndex(eventIndex - 1);
|
||||
}
|
||||
} catch (error) {
|
||||
socketProvider.error('RX', `OSC IN: error calling goto ${error}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'gotoid':
|
||||
case 'loadid': {
|
||||
if (!args) {
|
||||
socketProvider.error('RX', `OSC IN: event ID not recognised: ${args}}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PlaybackService.loadById(args.toString().toLowerCase());
|
||||
} catch (error) {
|
||||
socketProvider.error('RX', `OSC IN: error calling goto ${error}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'get-playback': {
|
||||
const playback = global.timer.state;
|
||||
global.timer.sendOsc('playback', playback);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
socketProvider.warning('RX', `OSC IN: unhandled message ${path}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import { removeUndefined } from '../utils/parserUtils.js';
|
||||
import { failEmptyObjects } from '../utils/routerUtils.js';
|
||||
import { DataProvider } from '../classes/data-provider/DataProvider.js';
|
||||
|
||||
// Create controller for GET request to 'event'
|
||||
export const getEvent = async (req, res) => {
|
||||
res.json(DataProvider.getEventData());
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event'
|
||||
export const postEvent = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const newEvent = removeUndefined({
|
||||
title: req.body?.title,
|
||||
url: req.body?.url,
|
||||
publicInfo: req.body?.publicInfo,
|
||||
backstageInfo: req.body?.backstageInfo,
|
||||
endMessage: req.body?.endMessage,
|
||||
});
|
||||
const newData = await DataProvider.setEventData(newEvent);
|
||||
res.status(200).send(newData);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
import { body, validationResult } from 'express-validator';
|
||||
|
||||
export const eventSanitizer = [
|
||||
body('title').optional().isString().trim(),
|
||||
body('url').optional().isString().trim(),
|
||||
body('publicInfo').optional().isString().trim(),
|
||||
body('backstageInfo').optional().isString().trim(),
|
||||
body('endMessage').optional().isString().trim(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,293 @@
|
||||
import fs from 'fs';
|
||||
import { networkInterfaces } from 'os';
|
||||
import { generateId } from 'ontime-utils';
|
||||
import { fileHandler } from '../utils/parser.js';
|
||||
import { DataProvider } from '../classes/data-provider/DataProvider.js';
|
||||
import { failEmptyObjects, failIsNotArray } from '../utils/routerUtils.js';
|
||||
import { mergeObject } from '../utils/parserUtils.js';
|
||||
import { PlaybackService } from '../services/PlaybackService.js';
|
||||
import { runtimeState } from '../stores/EventStore.js';
|
||||
import { resolveDbPath } from '../setup.js';
|
||||
|
||||
// Create controller for GET request to '/ontime/poll'
|
||||
// Returns data for current state
|
||||
export const poll = async (req, res) => {
|
||||
try {
|
||||
const s = runtimeState.poll();
|
||||
res.status(200).send(s);
|
||||
} catch (error) {
|
||||
res.status(500).send({
|
||||
message: `Could not get sync data: ${error}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/ontime/db'
|
||||
// Returns -
|
||||
export const dbDownload = async (req, res) => {
|
||||
const { title } = DataProvider.getEventData();
|
||||
const fileTitle = title || 'ontime data';
|
||||
const dbInDisk = resolveDbPath();
|
||||
|
||||
res.download(dbInDisk, `${fileTitle}.json`, (err) => {
|
||||
if (err) {
|
||||
res.status(500).send({
|
||||
message: `Could not download the file: ${err}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* handles file upload
|
||||
* @param file
|
||||
* @param req
|
||||
* @param res
|
||||
* @param options
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const uploadAndParse = async (file, req, res, options) => {
|
||||
if (!fs.existsSync(file)) {
|
||||
res.status(500).send({ message: 'Upload failed' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await fileHandler(file);
|
||||
|
||||
if (result?.error) {
|
||||
res.status(400).send({ message: result.message });
|
||||
} else if (result.message === 'success') {
|
||||
PlaybackService.stop();
|
||||
// explicitly write objects
|
||||
if (typeof result !== 'undefined') {
|
||||
const newRundown = result.data.rundown || [];
|
||||
if (options?.onlyRundown === 'true') {
|
||||
await DataProvider.setRundown(newRundown);
|
||||
} else {
|
||||
await DataProvider.mergeIntoData(result.data);
|
||||
}
|
||||
}
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
res.status(400).send({ message: 'Failed parsing, no data' });
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(400).send({ message: `Failed parsing ${error}` });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Gets information on IPV4 non-internal interfaces
|
||||
* @returns {array} - Array of objects {name: ip}
|
||||
*/
|
||||
const getNetworkInterfaces = () => {
|
||||
const nets = networkInterfaces();
|
||||
const results = [];
|
||||
|
||||
for (const name of Object.keys(nets)) {
|
||||
for (const net of nets[name]) {
|
||||
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
|
||||
if (net.family === 'IPv4' && !net.internal) {
|
||||
results.push({
|
||||
name: name,
|
||||
address: net.address,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/info'
|
||||
// Returns -
|
||||
export const getInfo = async (req, res) => {
|
||||
const { version, serverPort } = DataProvider.getSettings();
|
||||
const osc = DataProvider.getOsc();
|
||||
|
||||
// get nif and inject localhost
|
||||
const ni = getNetworkInterfaces();
|
||||
ni.unshift({ name: 'localhost', address: '127.0.0.1' });
|
||||
|
||||
// send object with network information
|
||||
res.status(200).send({
|
||||
networkInterfaces: ni,
|
||||
version,
|
||||
serverPort,
|
||||
osc,
|
||||
});
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/aliases'
|
||||
// Returns -
|
||||
export const getAliases = async (req, res) => {
|
||||
const aliases = DataProvider.getAliases();
|
||||
res.status(200).send(aliases);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/aliases'
|
||||
// Returns ACK message
|
||||
export const postAliases = async (req, res) => {
|
||||
if (failIsNotArray(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const newAliases = [];
|
||||
req.body.forEach((a) => {
|
||||
newAliases.push({
|
||||
id: generateId(),
|
||||
enabled: a.enabled,
|
||||
alias: a.alias,
|
||||
pathAndParams: a.pathAndParams,
|
||||
});
|
||||
});
|
||||
await DataProvider.setAliases(newAliases);
|
||||
res.status(200).send(newAliases);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/ontime/userfields'
|
||||
// Returns -
|
||||
export const getUserFields = async (req, res) => {
|
||||
const userFields = DataProvider.getUserFields();
|
||||
res.status(200).send(userFields);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/userfields'
|
||||
// Returns ACK message
|
||||
export const postUserFields = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const persistedData = DataProvider.getUserFields();
|
||||
const newData = mergeObject(persistedData, req.body);
|
||||
await DataProvider.setUserFields(newData);
|
||||
res.status(200).send(newData);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/settings'
|
||||
// Returns -
|
||||
export const getSettings = async (req, res) => {
|
||||
const { version, serverPort, pinCode, timeFormat } = DataProvider.getSettings();
|
||||
|
||||
res.status(200).send({
|
||||
version,
|
||||
serverPort,
|
||||
pinCode,
|
||||
timeFormat,
|
||||
});
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/settings'
|
||||
// Returns ACK message
|
||||
export const postSettings = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const settings = DataProvider.getSettings();
|
||||
let pin = settings.pinCode;
|
||||
if (typeof req.body?.pinCode === 'string') {
|
||||
if (req.body?.pinCode.length === 0) {
|
||||
pin = null;
|
||||
} else if (req.body?.pinCode.length <= 4) {
|
||||
pin = req.body?.pinCode;
|
||||
}
|
||||
}
|
||||
|
||||
let format = settings.timeFormat;
|
||||
if (typeof req.body?.timeFormat === 'string') {
|
||||
if (req.body?.timeFormat === '12' || req.body?.timeFormat === '24') {
|
||||
format = req.body.timeFormat;
|
||||
}
|
||||
}
|
||||
|
||||
const newData = {
|
||||
...settings,
|
||||
pinCode: pin,
|
||||
timeFormat: format,
|
||||
};
|
||||
await DataProvider.setSettings(newData);
|
||||
res.status(200).send(newData);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Get view Settings
|
||||
* @method GET
|
||||
*/
|
||||
export const getViewSettings = async (req, res) => {
|
||||
const views = DataProvider.getViews();
|
||||
res.status(200).send(views);
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Change view Settings
|
||||
* @method POST
|
||||
*/
|
||||
export const postViewSettings = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const newData = { overrideStyles: req.body.overrideStyles };
|
||||
await DataProvider.setViews(newData);
|
||||
res.status(200).send(newData);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/osc'
|
||||
// Returns -
|
||||
export const getOSC = async (req, res) => {
|
||||
const osc = DataProvider.getOsc();
|
||||
res.status(200).send(osc);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/osc'
|
||||
// Returns ACK message
|
||||
export const postOSC = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await DataProvider.setOsc(req.body);
|
||||
res.send(req.body).status(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/db'
|
||||
// Returns -
|
||||
export const dbUpload = async (req, res) => {
|
||||
if (!req.file) {
|
||||
res.status(400).send({ message: 'File not found' });
|
||||
return;
|
||||
}
|
||||
const options = req.query;
|
||||
const file = req.file.path;
|
||||
await uploadAndParse(file, req, res, options);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/dbpath'
|
||||
// Returns -
|
||||
export const dbPathToUpload = async (req, res) => {
|
||||
if (!req.body.path) {
|
||||
res.status(400).send({ message: 'Path to file not found' });
|
||||
return;
|
||||
}
|
||||
await uploadAndParse(req.body.path, req, res);
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
import { body, check, validationResult } from 'express-validator';
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/views
|
||||
*/
|
||||
export const viewValidator = [
|
||||
check('overrideStyles').isBoolean().withMessage('overrideStyles value must be boolean'),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/aliases
|
||||
*/
|
||||
export const validateAliases = [
|
||||
body().isArray(),
|
||||
body('*.enabled').isBoolean(),
|
||||
body('*.alias').isString().trim(),
|
||||
body('*.pathAndParams').isString().trim(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/userfields
|
||||
*/
|
||||
export const validateUserFields = [
|
||||
body('user0').exists().isString().trim(),
|
||||
body('user1').exists().isString().trim(),
|
||||
body('user2').exists().isString().trim(),
|
||||
body('user3').exists().isString().trim(),
|
||||
body('user4').exists().isString().trim(),
|
||||
body('user5').exists().isString().trim(),
|
||||
body('user6').exists().isString().trim(),
|
||||
body('user7').exists().isString().trim(),
|
||||
body('user8').exists().isString().trim(),
|
||||
body('user9').exists().isString().trim(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/settings
|
||||
*/
|
||||
export const validateSettings = [
|
||||
body('pinCode').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }),
|
||||
body('timeFormat').isString().isIn(['12', '24']),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/osc
|
||||
*/
|
||||
export const validateOSC = [
|
||||
body('port').exists().isInt({ min: 0, max: 65353 }),
|
||||
body('portOut').exists().isInt({ min: 0, max: 65353 }),
|
||||
body('targetIP').exists().isIP(),
|
||||
body('enabled').exists().isBoolean(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,99 @@
|
||||
// Create controller for GET request to '/playback'
|
||||
// Returns ACK message
|
||||
import { PlaybackService } from '../services/PlaybackService.js';
|
||||
|
||||
// Create controller for POST request to '/playback'
|
||||
// Returns playback state
|
||||
export const pbGet = async (req, res) => {
|
||||
res.send({ playback: global.timer.state });
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/start'
|
||||
// Starts timer object
|
||||
export const pbStart = async (req, res) => {
|
||||
const { eventId, eventIndex } = req.query;
|
||||
if (eventId) {
|
||||
const success = PlaybackService.startById(eventId);
|
||||
success ? res.sendStatus(202) : res.status(400).send('Invalid event ID');
|
||||
} else if (eventIndex) {
|
||||
const index = Number(eventIndex);
|
||||
if (!isNaN(index)) {
|
||||
const success = PlaybackService.startByIndex(eventIndex - 1);
|
||||
success ? res.sendStatus(202) : res.status(400).send('Invalid event index');
|
||||
} else {
|
||||
res.status(400).send('Invalid event index');
|
||||
}
|
||||
} else {
|
||||
PlaybackService.start();
|
||||
res.sendStatus(202);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/pause'
|
||||
// Pauses timer object
|
||||
export const pbPause = async (req, res) => {
|
||||
PlaybackService.pause();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/stop'
|
||||
// Stops timer object
|
||||
export const pbStop = async (req, res) => {
|
||||
PlaybackService.stop();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/roll'
|
||||
// Sets timer object to roll mode
|
||||
export const pbRoll = async (req, res) => {
|
||||
PlaybackService.roll();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/previous'
|
||||
// Loads previous event
|
||||
export const pbPrevious = async (req, res) => {
|
||||
PlaybackService.loadPrevious();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/next'
|
||||
// Loads Next event
|
||||
export const pbNext = async (req, res) => {
|
||||
PlaybackService.loadNext();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/load'
|
||||
// Load requested event
|
||||
export const pbLoad = async (req, res) => {
|
||||
const { eventId, eventIndex } = req.query;
|
||||
if (eventId) {
|
||||
const success = PlaybackService.loadById(eventId);
|
||||
success ? res.sendStatus(202) : res.status(400).send('Invalid event ID');
|
||||
} else if (eventIndex) {
|
||||
const index = Number(eventIndex);
|
||||
if (!isNaN(index)) {
|
||||
const success = PlaybackService.loadByIndex(eventIndex - 1);
|
||||
success ? res.sendStatus(202) : res.status(400).send('Invalid event index');
|
||||
} else {
|
||||
res.status(400).send('Invalid event index');
|
||||
}
|
||||
} else {
|
||||
res.status(400).send('No event given');
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/unload'
|
||||
// Unloads any events
|
||||
export const pbUnload = async (req, res) => {
|
||||
PlaybackService.stop();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/playback/reload'
|
||||
// Reloads current event
|
||||
export const pbReload = async (req, res) => {
|
||||
PlaybackService.reload();
|
||||
res.sendStatus(202);
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
import { DataProvider } from '../classes/data-provider/DataProvider.js';
|
||||
import { failEmptyObjects } from '../utils/routerUtils.js';
|
||||
import {
|
||||
addEvent,
|
||||
applyDelay,
|
||||
deleteAllEvents,
|
||||
deleteEvent,
|
||||
editEvent,
|
||||
reorderEvent,
|
||||
} from '../services/RundownService.js';
|
||||
|
||||
// Create controller for GET request to '/eventlist'
|
||||
// Returns -
|
||||
export const rundownGetAll = async (req, res) => {
|
||||
res.json(DataProvider.getRundown());
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/eventlist/:eventId'
|
||||
// Returns -
|
||||
export const getEventById = async (req, res) => {
|
||||
res.json(DataProvider.getEventById(req.params?.eventId));
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/eventlist/'
|
||||
// Returns -
|
||||
export const rundownPost = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const newEvent = await addEvent(req.body);
|
||||
res.status(201).send(newEvent);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for PUT request to '/eventlist/'
|
||||
// Returns -
|
||||
export const rundownPut = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const event = await editEvent(req.body);
|
||||
res.status(200).send(event);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const rundownReorder = async (req, res) => {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { eventId, from, to } = req.body;
|
||||
const event = await reorderEvent(eventId, from, to);
|
||||
res.status(200).send(event);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for PATCH request to '/eventlist/applydelay/:eventId'
|
||||
// Returns -
|
||||
export const rundownApplyDelay = async (req, res) => {
|
||||
try {
|
||||
await applyDelay(req.params.eventId);
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for DELETE request to '/eventlist/:eventId'
|
||||
// Returns -
|
||||
export const deleteEventById = async (req, res) => {
|
||||
try {
|
||||
await deleteEvent(req.params.eventId);
|
||||
res.sendStatus(204);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for DELETE request to '/eventlist/'
|
||||
// Returns -
|
||||
export const rundownDelete = async (req, res) => {
|
||||
try {
|
||||
await deleteAllEvents();
|
||||
res.sendStatus(204);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import { body, param, validationResult } from 'express-validator';
|
||||
|
||||
export const rundownPostValidator = [
|
||||
body('type').isString().exists().isIn(['event', 'delay', 'block']),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
export const rundownPutValidator = [
|
||||
body('id').isString().exists(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
export const rundownReorderValidator = [
|
||||
body('eventId').isString().exists(),
|
||||
body('from').isNumeric().exists(),
|
||||
body('to').isNumeric().exists(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
export const paramsMustHaveEventId = [
|
||||
param('eventId').exists(),
|
||||
(req, res, next) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user