mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-14 03:43:50 +00:00
Merge remote-tracking branch 'origin/master' into feat/electron
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
// get config
|
||||
const config = require('./config.json');
|
||||
|
||||
// init database
|
||||
const low = require('lowdb');
|
||||
const FileSync = require('lowdb/adapters/FileSync');
|
||||
|
||||
const adapter = new FileSync(config.database.filename);
|
||||
const db = low(adapter);
|
||||
|
||||
// dependencies
|
||||
const express = require('express');
|
||||
const http = require('http');
|
||||
const cors = require('cors');
|
||||
const { dbModel } = require('./data/dataModel.js');
|
||||
const path = require('path');
|
||||
|
||||
db.defaults(dbModel).write();
|
||||
|
||||
// export db
|
||||
module.exports.db = db;
|
||||
|
||||
// Import Routes
|
||||
const eventsRouter = require('./routes/eventsRouter.js');
|
||||
const eventRouter = require('./routes/eventRouter.js');
|
||||
// No settings yet
|
||||
// const settingsRouter = require('./routes/settingsRouter.js');
|
||||
|
||||
// Setup default port
|
||||
const port = process.env.PORT || config.server.port;
|
||||
|
||||
// Global Objects
|
||||
const EventTimer = require('./classes/EventTimer.js');
|
||||
|
||||
// Create express APP
|
||||
const app = express();
|
||||
|
||||
// setup cors for all routes
|
||||
app.use(cors());
|
||||
|
||||
// enable pre-flight cors
|
||||
app.options('*', cors());
|
||||
|
||||
// Implement middleware
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json());
|
||||
|
||||
// Implement route endpoints
|
||||
app.use('/events', eventsRouter);
|
||||
app.use('/event', eventRouter);
|
||||
|
||||
// serve react
|
||||
app.use(express.static(path.join(__dirname, '../client/build')));
|
||||
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'));
|
||||
});
|
||||
|
||||
// Implement route for errors
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
res.status(500).send(err.stack);
|
||||
});
|
||||
|
||||
// create HTTP server
|
||||
const server = http.createServer(app);
|
||||
|
||||
// get data (if any)
|
||||
const eventlist = db.get('events').value();
|
||||
|
||||
// init timer
|
||||
global.timer = new EventTimer(server, config);
|
||||
global.timer.setupWithEventList(eventlist);
|
||||
|
||||
// Start server
|
||||
server.listen(port, '0.0.0.0', () =>
|
||||
console.log(`HTTP Server is listening on port ${port}`)
|
||||
);
|
||||
|
||||
// Start OSC server
|
||||
const { initiateOSC } = require('./controllers/OscController.js');
|
||||
|
||||
initiateOSC(config.osc);
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"timer": {
|
||||
"refresh": 1000
|
||||
},
|
||||
"server": {
|
||||
"port": 4001
|
||||
},
|
||||
"database": {
|
||||
"filename": "db.json",
|
||||
"tablename": "events"
|
||||
},
|
||||
"osc": {
|
||||
"port": 8888
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
// get database
|
||||
const { db } = require('../app.js');
|
||||
|
||||
const table = 'event';
|
||||
|
||||
function getSettings() {
|
||||
return db.get(table).value();
|
||||
}
|
||||
|
||||
// Create controller for GET request to 'event'
|
||||
// Returns ACK message
|
||||
exports.getAll = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
if (settings) res.json(settings);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event'
|
||||
// Returns ACK message
|
||||
exports.post = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table)
|
||||
.assign({ ...req.body })
|
||||
.write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/title'
|
||||
// Returns ACK message
|
||||
exports.titleGet = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
if (settings) res.json(settings.title);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event/title'
|
||||
// Returns ACK message
|
||||
exports.titlePost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ title: req.body.title }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/event/url'
|
||||
// Returns ACK message
|
||||
exports.urlGet = async (req, res) => {
|
||||
const event = getSettings();
|
||||
|
||||
if (event) res.json(event.url);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/event/url'
|
||||
// Returns ACK message
|
||||
exports.urlPost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ url: req.body.url }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/publicInfo'
|
||||
// Returns ACK message
|
||||
exports.publicInfoGet = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
if (settings) res.json(settings.publicInfo);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/event/publicInfo'
|
||||
// Returns ACK message
|
||||
exports.publicInfoPost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ publicInfo: req.body.publicInfo }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/backstageInfo'
|
||||
// Returns ACK message
|
||||
exports.backstageInfoGet = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
if (settings) res.json(settings.backstageInfo);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/event/info'
|
||||
// Returns ACK message
|
||||
exports.backstageInfoPost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ backstageInfo: req.body.backstageInfo }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/osc'
|
||||
// Returns ACK message
|
||||
exports.osc = async (req, res) => {
|
||||
res.send('Not yet implemented').status(500);
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id":"xxxxx0",
|
||||
"duration": 300000,
|
||||
"type": "delay"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx1",
|
||||
"title": "Is the internet a fad?",
|
||||
"subtitle": "It is",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 32400000,
|
||||
"timeEnd": 34200000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx2",
|
||||
"duration": 1500000,
|
||||
"type": "delay"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx3",
|
||||
"title": "Is reddit a dictatorship?",
|
||||
"subtitle": "It is",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 34200000,
|
||||
"timeEnd": 36000000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx4",
|
||||
"title": "Out of words",
|
||||
"subtitle": "",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 36000000,
|
||||
"timeEnd": 39600000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx5",
|
||||
"title": "Really",
|
||||
"subtitle": "",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 39600000,
|
||||
"timeEnd": 41400000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx6",
|
||||
"title": "...",
|
||||
"subtitle": "",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": null,
|
||||
"timeEnd": null,
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"current": null,
|
||||
"next": null,
|
||||
"currentTimer": null,
|
||||
"numEvents": 0,
|
||||
"state": "pause",
|
||||
"prevState": "pause"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
+4
-2
@@ -3,14 +3,16 @@
|
||||
"version": "0.1.0",
|
||||
"author": "Carlos Valente",
|
||||
"description": "Time keeping for live events",
|
||||
"type": "module",
|
||||
"main": "main.js",
|
||||
"dependencies": {
|
||||
"body-parser": "~1.19.0",
|
||||
"express": "~4.17.1",
|
||||
"express-session": "~1.17.1",
|
||||
"lowdb": "^1.0.0",
|
||||
"lowdb": "2.1.0",
|
||||
"multer": "^1.4.2",
|
||||
"nanoid": "^3.1.22",
|
||||
"node-osc": "^6.0.1",
|
||||
"node-osc": "6.0.2",
|
||||
"passport": "~0.4.1",
|
||||
"passport-local": "~1.0.0",
|
||||
"socket.io": "^4.0.0"
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
// import event controller
|
||||
const eventController = require('../controllers/eventController');
|
||||
|
||||
// create route between controller and '/settings' endpoint
|
||||
router.get('/', eventController.getAll);
|
||||
|
||||
// create route between controller and '/settings' endpoint
|
||||
router.post('/', eventController.post);
|
||||
|
||||
// create route between controller and '/event/title' endpoint
|
||||
router.get('/title', eventController.titleGet);
|
||||
|
||||
// create route between controller and '/event/title' endpoint
|
||||
router.post('/title', eventController.titlePost);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.get('/publicInfo', eventController.publicInfoGet);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.post('/publicInfo', eventController.publicInfoPost);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.get('/backstageInfo', eventController.backstageInfoGet);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.post('/backstageInfo', eventController.backstageInfoPost);
|
||||
|
||||
// create route between controller and '/event/url' endpoint
|
||||
router.get('/url', eventController.urlGet);
|
||||
|
||||
// create route between controller and '/event/url' endpoint
|
||||
router.post('/url', eventController.urlPost);
|
||||
|
||||
module.exports = router;
|
||||
@@ -1,31 +0,0 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
// import events controller
|
||||
const eventsController = require('../controllers/eventsController');
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.get('/', eventsController.eventsGetAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.get('/:eventId', eventsController.eventsGetById);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.post('/', eventsController.eventsPost);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.put('/', eventsController.eventsPut);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.patch('/', eventsController.eventsPatch);
|
||||
|
||||
// create route between controller and '/events/reorder' endpoint
|
||||
router.patch('/reorder/', eventsController.eventsReorder);
|
||||
|
||||
// create route between controller and '/events/applydelay/:eventId' endpoint
|
||||
router.patch('/applydelay/:eventId', eventsController.eventsApplyDelay);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.delete('/:eventId', eventsController.eventsDelete);
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,89 @@
|
||||
// get config
|
||||
import { config } from './config/config.js';
|
||||
|
||||
// init database
|
||||
import { Low, JSONFile } from 'lowdb';
|
||||
import { join } from 'path';
|
||||
|
||||
const file = join('data/', config.database.filename);
|
||||
const adapter = new JSONFile(file);
|
||||
export const db = new Low(adapter);
|
||||
|
||||
// dependencies
|
||||
import express from 'express';
|
||||
import http from 'http';
|
||||
import cors from 'cors';
|
||||
import { dbModel } from './data/dataModel.js';
|
||||
|
||||
// Read data from JSON file, this will set db.data content
|
||||
await db.read();
|
||||
|
||||
// If file.json doesn't exist, db.data will be null
|
||||
// Set default data
|
||||
// db.data ||= { events: [] }; NODE v15 - v16
|
||||
if (db.data == null) {
|
||||
db.data = dbModel;
|
||||
db.write();
|
||||
}
|
||||
|
||||
// get data
|
||||
export const data = db.data;
|
||||
|
||||
// Import Routes
|
||||
import { router as eventsRouter } from './routes/eventsRouter.js';
|
||||
import { router as eventRouter } from './routes/eventRouter.js';
|
||||
import { router as ontimeRouter } from './routes/ontimeRouter.js';
|
||||
|
||||
// Setup default port
|
||||
const port = process.env.PORT || config.server.port;
|
||||
|
||||
// Global Objects
|
||||
import { EventTimer } from './classes/EventTimer.js';
|
||||
|
||||
// Create express APP
|
||||
const app = express();
|
||||
|
||||
// setup cors for all routes
|
||||
app.use(cors());
|
||||
|
||||
// enable pre-flight cors
|
||||
app.options('*', cors());
|
||||
|
||||
// Implement middleware
|
||||
app.use('/uploads', express.static('uploads'));
|
||||
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json({ limit: '1mb' }));
|
||||
|
||||
// Implement route endpoints
|
||||
app.use('/events', eventsRouter);
|
||||
app.use('/event', eventRouter);
|
||||
app.use('/ontime', ontimeRouter);
|
||||
|
||||
// implement general router
|
||||
app.get('/', (req, res) => {
|
||||
res.send('ontime API');
|
||||
});
|
||||
|
||||
// Implement route for errors
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
res.status(500).send('Something broke!');
|
||||
});
|
||||
|
||||
// create HTTP server
|
||||
const server = http.createServer(app);
|
||||
|
||||
// init timer
|
||||
global.timer = new EventTimer(server, config);
|
||||
global.timer.setupWithEventList(data.events);
|
||||
|
||||
// Start server
|
||||
server.listen(port, () =>
|
||||
console.log(`HTTP Server is listening on port ${port}`)
|
||||
);
|
||||
|
||||
// Start OSC server
|
||||
import { initiateOSC } from './controllers/OscController.js';
|
||||
|
||||
initiateOSC(config.osc);
|
||||
@@ -1,5 +1,5 @@
|
||||
const Timer = require('./Timer');
|
||||
const socketIo = require('socket.io');
|
||||
import { Timer } from './Timer.js';
|
||||
import { Server } from 'socket.io';
|
||||
|
||||
/*
|
||||
* EventTimer adds functions specific to APP
|
||||
@@ -9,7 +9,7 @@ const socketIo = require('socket.io');
|
||||
*
|
||||
*/
|
||||
|
||||
class EventTimer extends Timer {
|
||||
export class EventTimer extends Timer {
|
||||
// AUX
|
||||
DAYMS = 86400000;
|
||||
|
||||
@@ -57,12 +57,12 @@ class EventTimer extends Timer {
|
||||
numEvents = null;
|
||||
_eventlist = null;
|
||||
|
||||
constructor(server, config) {
|
||||
constructor(httpServer, config) {
|
||||
// call super constructor
|
||||
super();
|
||||
|
||||
// initialise socketIO server
|
||||
this.io = socketIo(server, {
|
||||
this.io = new Server(httpServer, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||
@@ -90,6 +90,10 @@ class EventTimer extends Timer {
|
||||
broadcastState() {
|
||||
this.io.emit('timer', this.getObject());
|
||||
this.io.emit('playstate', this.state);
|
||||
this.io.emit('selected', {
|
||||
id: this.selectedEventId,
|
||||
index: this.selectedEventIndex,
|
||||
});
|
||||
this.io.emit('selected-id', this.selectedEventId);
|
||||
this.io.emit('next-id', this.nextEventId);
|
||||
this.io.emit('publicselected-id', this.selectedPublicEventId);
|
||||
@@ -105,8 +109,29 @@ class EventTimer extends Timer {
|
||||
|
||||
update() {
|
||||
// if there is nothing selected, no nothing
|
||||
if (this.selectedEventId == null) return;
|
||||
super.update();
|
||||
if (this.selectedEventId == null && this.state !== 'roll') return;
|
||||
|
||||
// only implement roll here
|
||||
if (this.state !== 'roll') {
|
||||
super.update();
|
||||
return;
|
||||
}
|
||||
|
||||
// get current time
|
||||
const now = this._getCurrentTime();
|
||||
this.clock = now;
|
||||
|
||||
if (this.selectedEventId && this.current > 0) {
|
||||
// update timer as usual
|
||||
this.current = this._finishAt - now;
|
||||
} else {
|
||||
// look for event if none is loaded
|
||||
if (this.current <= 0 || this.secondaryTimer <= 0) this.rollLoad();
|
||||
|
||||
// count to next event
|
||||
// TODO: replace with proper counter
|
||||
if (this.secondaryTimer != null) this.secondaryTimer -= 1000;
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -136,10 +161,11 @@ class EventTimer extends Timer {
|
||||
else if (payload === 'next') this.next();
|
||||
else if (payload === 'reload') this.reload();
|
||||
else if (payload === 'unload') this.unload();
|
||||
else if (payload === 'roll') this.roll();
|
||||
|
||||
// Not yet implemented
|
||||
// else if (payload === 'roll') this.roll();
|
||||
|
||||
// TODO: Cleanup
|
||||
// here tdo this.broadcastState;
|
||||
// remove broadcast from functions
|
||||
this.broadcastThis('playstate', this.state);
|
||||
this.broadcastThis('selected-id', this.selectedEventId);
|
||||
this.broadcastThis('titles', this.titles);
|
||||
@@ -259,6 +285,13 @@ class EventTimer extends Timer {
|
||||
|
||||
/*******************************************/
|
||||
// selection data
|
||||
socket.on('get-selected', () => {
|
||||
socket.emit('selected', {
|
||||
id: this.selectedEventId,
|
||||
index: this.selectedEventIndex,
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('get-selected-id', () => {
|
||||
socket.emit('selected-id', this.selectedEventId);
|
||||
});
|
||||
@@ -342,6 +375,8 @@ class EventTimer extends Timer {
|
||||
}
|
||||
|
||||
setupWithEventList(eventlist) {
|
||||
if (!Array.isArray(eventlist) || eventlist.length < 1) return;
|
||||
|
||||
// filter only events
|
||||
const events = eventlist.filter((e) => e.type === 'event');
|
||||
const numEvents = events.length;
|
||||
@@ -441,7 +476,7 @@ class EventTimer extends Timer {
|
||||
|
||||
// update selected event index
|
||||
this.selectedEventIndex = this._eventlist.findIndex(
|
||||
(e) => e.id === eventId
|
||||
(e) => e.id === this.selectedEventId
|
||||
);
|
||||
|
||||
// reload titles if necessary
|
||||
@@ -459,18 +494,15 @@ class EventTimer extends Timer {
|
||||
|
||||
if (eventIndex === -1) return;
|
||||
this.pause();
|
||||
this.loadEvent(eventIndex);
|
||||
|
||||
this.broadcastState();
|
||||
this.loadEvent(eventIndex, 'load', true);
|
||||
}
|
||||
|
||||
// Loads a given event
|
||||
// load timers
|
||||
// load selectedEventIndex
|
||||
// load titles
|
||||
loadEvent(eventIndex, type = 'load') {
|
||||
loadEvent(eventIndex, type = 'load', broadcastChange = 'false') {
|
||||
const e = this._eventlist[eventIndex];
|
||||
|
||||
if (e == null) return;
|
||||
|
||||
const start = e.timeStart == null || e.timeStart === '' ? 0 : e.timeStart;
|
||||
@@ -501,6 +533,10 @@ class EventTimer extends Timer {
|
||||
|
||||
// look for event after
|
||||
this._loadTitlesNext();
|
||||
|
||||
if (broadcastChange)
|
||||
// broadcast current state
|
||||
this.broadcastState();
|
||||
}
|
||||
|
||||
_loadTitlesNow() {
|
||||
@@ -508,18 +544,12 @@ class EventTimer extends Timer {
|
||||
if (e == null) return;
|
||||
|
||||
// private title is always current
|
||||
this.titles.titleNow = e.title;
|
||||
this.titles.subtitleNow = e.subtitle;
|
||||
this.titles.presenterNow = e.presenter;
|
||||
this.selectedEventId = e.id;
|
||||
|
||||
// check if current is also public
|
||||
if (e.isPublic) {
|
||||
this.titlesPublic.titleNow = e.title;
|
||||
this.titlesPublic.subtitleNow = e.subtitle;
|
||||
this.titlesPublic.presenterNow = e.presenter;
|
||||
this.selectedPublicEventId = e.id;
|
||||
this._loadThisTitles(e, 'now');
|
||||
} else {
|
||||
this._loadThisTitles(e, 'now-private');
|
||||
|
||||
// assume there is no public event
|
||||
this.titlesPublic.titleNow = null;
|
||||
this.titlesPublic.subtitleNow = null;
|
||||
@@ -535,16 +565,77 @@ class EventTimer extends Timer {
|
||||
this._eventlist[i].type === 'event' &&
|
||||
this._eventlist[i].isPublic
|
||||
) {
|
||||
this.titlesPublic.titleNow = this._eventlist[i].title;
|
||||
this.titlesPublic.subtitleNow = this._eventlist[i].subtitle;
|
||||
this.titlesPublic.presenterNow = this._eventlist[i].presenter;
|
||||
this.selectedPublicEventId = this._eventlist[i].id;
|
||||
this._loadThisTitles(this._eventlist[i], 'now-public');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loadThisTitles(e, type) {
|
||||
if (e == null) return;
|
||||
|
||||
switch (type) {
|
||||
// now, load to both public and private
|
||||
case 'now':
|
||||
// public
|
||||
this.titlesPublic.titleNow = e.title;
|
||||
this.titlesPublic.subtitleNow = e.subtitle;
|
||||
this.titlesPublic.presenterNow = e.presenter;
|
||||
this.selectedPublicEventId = e.id;
|
||||
|
||||
// private
|
||||
this.titles.titleNow = e.title;
|
||||
this.titles.subtitleNow = e.subtitle;
|
||||
this.titles.presenterNow = e.presenter;
|
||||
this.selectedEventId = e.id;
|
||||
|
||||
break;
|
||||
case 'now-public':
|
||||
this.titlesPublic.titleNow = e.title;
|
||||
this.titlesPublic.subtitleNow = e.subtitle;
|
||||
this.titlesPublic.presenterNow = e.presenter;
|
||||
this.selectedPublicEventId = e.id;
|
||||
break;
|
||||
case 'now-private':
|
||||
this.titles.titleNow = e.title;
|
||||
this.titles.subtitleNow = e.subtitle;
|
||||
this.titles.presenterNow = e.presenter;
|
||||
this.selectedEventId = e.id;
|
||||
break;
|
||||
|
||||
// next, load to both public and private
|
||||
case 'next':
|
||||
// public
|
||||
this.titlesPublic.titleNext = e.title;
|
||||
this.titlesPublic.subtitleNext = e.subtitle;
|
||||
this.titlesPublic.presenterNext = e.presenter;
|
||||
this.nextPublicEventId = e.id;
|
||||
|
||||
// private
|
||||
this.titles.titleNext = e.title;
|
||||
this.titles.subtitleNext = e.subtitle;
|
||||
this.titles.presenterNext = e.presenter;
|
||||
this.nextEventId = e.id;
|
||||
break;
|
||||
case 'next-public':
|
||||
this.titlesPublic.titleNext = e.title;
|
||||
this.titlesPublic.subtitleNext = e.subtitle;
|
||||
this.titlesPublic.presenterNext = e.presenter;
|
||||
this.nextPublicEventId = e.id;
|
||||
break;
|
||||
case 'next-private':
|
||||
this.titles.titleNext = e.title;
|
||||
this.titles.subtitleNext = e.subtitle;
|
||||
this.titles.presenterNext = e.presenter;
|
||||
this.nextEventId = e.id;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_loadTitlesNext() {
|
||||
// maybe there is nothing to load
|
||||
if (this.selectedEventIndex == null) return;
|
||||
@@ -569,19 +660,13 @@ class EventTimer extends Timer {
|
||||
if (this._eventlist[i].type === 'event') {
|
||||
// if we have not set private
|
||||
if (!nextPrivate) {
|
||||
this.titles.titleNext = this._eventlist[i].title;
|
||||
this.titles.subtitleNext = this._eventlist[i].subtitle;
|
||||
this.titles.presenterNext = this._eventlist[i].presenter;
|
||||
this.nextEventId = this._eventlist[i].id;
|
||||
this._loadThisTitles(this._eventlist[i], 'next-private');
|
||||
nextPrivate = true;
|
||||
}
|
||||
|
||||
// if event is public
|
||||
if (this._eventlist[i].isPublic) {
|
||||
this.titlesPublic.titleNext = this._eventlist[i].title;
|
||||
this.titlesPublic.subtitleNext = this._eventlist[i].subtitle;
|
||||
this.titlesPublic.presenterNext = this._eventlist[i].presenter;
|
||||
this.nextPublicEventId = this._eventlist[i].id;
|
||||
this._loadThisTitles(this._eventlist[i], 'next-public');
|
||||
nextPublic = true;
|
||||
}
|
||||
}
|
||||
@@ -628,6 +713,7 @@ class EventTimer extends Timer {
|
||||
state = ${this.state}
|
||||
current = ${this.current}
|
||||
duration = ${this.duration}
|
||||
secondaryTimer = ${this.secondaryTimer}
|
||||
|
||||
Events
|
||||
------------------------------
|
||||
@@ -716,10 +802,77 @@ class EventTimer extends Timer {
|
||||
this.broadcastState();
|
||||
}
|
||||
|
||||
rollLoad() {
|
||||
const now = this._getCurrentTime();
|
||||
this._resetTimers(true);
|
||||
this._resetSelection();
|
||||
|
||||
let foundNow = null;
|
||||
let nextIndex = null;
|
||||
let nextStart = null;
|
||||
|
||||
// loop through events, look for where we should be
|
||||
for (const [index, e] of this._eventlist.entries()) {
|
||||
if (!foundNow) {
|
||||
if (e.timeStart <= now && now < e.timeEnd) {
|
||||
// set flag
|
||||
foundNow = true;
|
||||
|
||||
// set timers
|
||||
this._startedAt = e.timeStart;
|
||||
this._finishAt = e.timeEnd;
|
||||
this.duration = e.timeEnd - e.timeStart;
|
||||
this.current = e.timeEnd - now;
|
||||
|
||||
// set selection
|
||||
this.selectedEventId = e.id;
|
||||
this.selectedEventIndex = index;
|
||||
|
||||
// set titles
|
||||
this._loadTitlesNow();
|
||||
|
||||
// skip this entry for next
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// check how far the start is from now
|
||||
let wait = e.timeStart - now;
|
||||
if (wait > 0) {
|
||||
if (nextStart == null || wait < nextStart) {
|
||||
nextStart = wait;
|
||||
nextIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nothing to play next, unload
|
||||
if (!foundNow && !nextIndex) {
|
||||
this.unload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextIndex) {
|
||||
// load titles
|
||||
this._loadThisTitles(nextIndex, 'next');
|
||||
|
||||
if (!foundNow) {
|
||||
// timer counts to nextStart
|
||||
this.secondaryTimer = nextStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
roll() {
|
||||
console.log('roll: not yet implemented');
|
||||
return false;
|
||||
// do we need to change
|
||||
if (this.state === 'roll') return;
|
||||
|
||||
// load into event
|
||||
this.rollLoad();
|
||||
|
||||
// set state
|
||||
this.state = 'roll';
|
||||
|
||||
this.broadcastState();
|
||||
}
|
||||
|
||||
previous() {
|
||||
@@ -731,14 +884,15 @@ class EventTimer extends Timer {
|
||||
this.loadEvent(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// change playstate
|
||||
this.pause();
|
||||
|
||||
const gotoEvent =
|
||||
this.selectedEventIndex > 0 ? this.selectedEventIndex - 1 : 0;
|
||||
|
||||
if (gotoEvent === this.selectedEventIndex) return;
|
||||
this.loadEvent(gotoEvent);
|
||||
|
||||
// change playstate
|
||||
this.pause();
|
||||
}
|
||||
|
||||
next() {
|
||||
@@ -751,6 +905,9 @@ class EventTimer extends Timer {
|
||||
return;
|
||||
}
|
||||
|
||||
// change playstate
|
||||
this.pause();
|
||||
|
||||
const gotoEvent =
|
||||
this.selectedEventIndex < this.numEvents - 1
|
||||
? this.selectedEventIndex + 1
|
||||
@@ -758,9 +915,6 @@ class EventTimer extends Timer {
|
||||
|
||||
if (gotoEvent === this.selectedEventIndex) return;
|
||||
this.loadEvent(gotoEvent);
|
||||
|
||||
// change playstate
|
||||
this.pause();
|
||||
}
|
||||
|
||||
unload() {
|
||||
@@ -775,12 +929,10 @@ class EventTimer extends Timer {
|
||||
}
|
||||
|
||||
reload() {
|
||||
// reload data
|
||||
this.loadEvent(this.selectedEventIndex);
|
||||
|
||||
// reset playstate
|
||||
this.pause();
|
||||
|
||||
// reload data
|
||||
this.loadEvent(this.selectedEventIndex);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EventTimer;
|
||||
@@ -4,10 +4,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class Timer {
|
||||
export class Timer {
|
||||
clock = null;
|
||||
duration = null;
|
||||
current = null;
|
||||
secondaryTimer = null;
|
||||
_finishAt = null;
|
||||
_finishedAt = null;
|
||||
_startedAt = null;
|
||||
@@ -50,6 +51,9 @@ class Timer {
|
||||
// check playstate
|
||||
switch (this.state) {
|
||||
case 'start':
|
||||
// ensure we have a start time
|
||||
if (this._startedAt == null) this._startedAt = now;
|
||||
|
||||
// update current timer
|
||||
this.current =
|
||||
this._startedAt + this.duration + this._pausedTotal - now;
|
||||
@@ -110,8 +114,10 @@ class Timer {
|
||||
);
|
||||
}
|
||||
|
||||
_resetTimers() {
|
||||
_resetTimers(total = false) {
|
||||
if (total) this.duration = null;
|
||||
this.current = this.duration;
|
||||
this.secondaryTimer = null;
|
||||
this._finishAt = null;
|
||||
this._finishedAt = null;
|
||||
this._startedAt = null;
|
||||
@@ -132,7 +138,7 @@ class Timer {
|
||||
return {
|
||||
clock: this.clock,
|
||||
running: Timer.toSeconds(this.current),
|
||||
currentSeconds: Timer.toSeconds(Math.max(this.current, 0)),
|
||||
secondary: Timer.toSeconds(this.secondaryTimer),
|
||||
durationSeconds: Timer.toSeconds(this.duration),
|
||||
expectedFinish: this._getExpectedFinish(),
|
||||
startedAt: this._startedAt,
|
||||
@@ -210,6 +216,4 @@ class Timer {
|
||||
this._finishedAt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Timer;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export const config = {
|
||||
timer: {
|
||||
refresh: 1000,
|
||||
},
|
||||
server: {
|
||||
port: 4001,
|
||||
},
|
||||
database: {
|
||||
filename: 'db.json',
|
||||
tablename: 'events',
|
||||
},
|
||||
osc: {
|
||||
port: 8888,
|
||||
},
|
||||
};
|
||||
@@ -1,10 +1,13 @@
|
||||
const osc = require('node-osc');
|
||||
import { Server } from 'node-osc';
|
||||
|
||||
const initiateOSC = (config) => {
|
||||
const oscServer = new osc.Server(config.port, '0.0.0.0', () => {
|
||||
export const initiateOSC = (config) => {
|
||||
const oscServer = new Server(config.port, '0.0.0.0', () => {
|
||||
console.log(`OSC Server is listening on port ${config.port}`);
|
||||
});
|
||||
|
||||
// error
|
||||
oscServer.on('error', console.error);
|
||||
|
||||
oscServer.on('message', function (msg) {
|
||||
// message should look like /ontime/{path}/{args} where
|
||||
// ontime: fixed message for app
|
||||
@@ -20,7 +23,7 @@ const initiateOSC = (config) => {
|
||||
if (address !== 'ontime') return;
|
||||
|
||||
// get second part (command)
|
||||
switch (path) {
|
||||
switch (path.toLocaleLowerCase()) {
|
||||
case 'start':
|
||||
case 'play':
|
||||
console.log('calling play');
|
||||
@@ -61,7 +64,19 @@ const initiateOSC = (config) => {
|
||||
case 'goto':
|
||||
console.log('calling goto with', args);
|
||||
try {
|
||||
global.timer.loadEventById(args.toLowerCase());
|
||||
let eventIndex = parseInt(args);
|
||||
if (isNaN(eventIndex) || eventIndex <= 0 || eventIndex == null)
|
||||
return;
|
||||
global.timer.loadEvent(eventIndex - 1, undefined, true);
|
||||
} catch (error) {
|
||||
console.log('error calling goto: ', error);
|
||||
}
|
||||
break;
|
||||
case 'gotoid':
|
||||
console.log('calling gotoid with', args);
|
||||
if (args == null) return;
|
||||
try {
|
||||
global.timer.loadEventById(args.toString().toLowerCase());
|
||||
} catch (error) {
|
||||
console.log('error calling goto: ', error);
|
||||
}
|
||||
@@ -73,5 +88,3 @@ const initiateOSC = (config) => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = { initiateOSC };
|
||||
@@ -0,0 +1,26 @@
|
||||
// get database
|
||||
import { db, data } from '../app.js';
|
||||
|
||||
// Create controller for GET request to 'event'
|
||||
// Returns ACK message
|
||||
export const getEvent = async (req, res) => {
|
||||
res.json(data.event);
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event'
|
||||
// Returns ACK message
|
||||
export const postEvent = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
// TODO: validate data
|
||||
try {
|
||||
data.event = { ...data.event, ...req.body };
|
||||
await db.write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
+68
-36
@@ -1,22 +1,26 @@
|
||||
// get database
|
||||
const db = require('../app.js').db;
|
||||
import { db, data } from '../app.js';
|
||||
|
||||
// utils
|
||||
const customAlphabet = require('nanoid').customAlphabet;
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('1234567890abcdef', 4);
|
||||
const eventDefs = require('../data/eventsDefinition.js');
|
||||
import {
|
||||
event as eventDef,
|
||||
delay as delayDef,
|
||||
block as blockDef,
|
||||
} from '../data/eventsDefinition.js';
|
||||
|
||||
function _getEventsCount() {
|
||||
return db.get('events').size().value();
|
||||
return Array.from(data.events).length;
|
||||
}
|
||||
|
||||
function _pushNew(entry) {
|
||||
return db.get('events').push(entry).write();
|
||||
return data.events.push(entry).write();
|
||||
}
|
||||
|
||||
function _insertAt(entry, index) {
|
||||
async function _insertAt(entry, index) {
|
||||
// get events
|
||||
let events = db.get('events').value();
|
||||
let events = data.events;
|
||||
let count = events.length;
|
||||
let order = entry.order;
|
||||
|
||||
@@ -39,15 +43,18 @@ function _insertAt(entry, index) {
|
||||
}
|
||||
|
||||
// save events
|
||||
db.set('events', events).write();
|
||||
data.events = events;
|
||||
await db.write();
|
||||
}
|
||||
|
||||
function _removeById(eventId) {
|
||||
return db.get('events').remove({ id: eventId }).write();
|
||||
async function _removeById(eventId) {
|
||||
data.events = Array.from(data.events).filter((e) => e.id != eventId);
|
||||
await db.write();
|
||||
}
|
||||
|
||||
function getEventEvents() {
|
||||
return db.get('events').chain().filter({ type: 'event' }).value();
|
||||
// return data.events.filter((e) => e.type === 'event');
|
||||
return Array.from(data.events).filter((e) => e.type === 'event');
|
||||
}
|
||||
|
||||
// Updates timer object
|
||||
@@ -68,21 +75,21 @@ function _deleteTimerId(entryId) {
|
||||
|
||||
// Create controller for GET request to '/events'
|
||||
// Returns -
|
||||
exports.eventsGetAll = async (req, res) => {
|
||||
const results = db.get('events').value();
|
||||
res.json(results);
|
||||
export const eventsGetAll = async (req, res) => {
|
||||
res.json(data.events);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/events/:eventId'
|
||||
// Returns -
|
||||
exports.eventsGetById = async (req, res) => {
|
||||
const e = db.get('events').find({ id: req.params.eventId }).value();
|
||||
export const eventsGetById = async (req, res) => {
|
||||
const e = data.events.find({ id: req.params.eventId }).value();
|
||||
console.log('event by id', e);
|
||||
res.json(e);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/events/'
|
||||
// Returns -
|
||||
exports.eventsPost = async (req, res) => {
|
||||
export const eventsPost = async (req, res) => {
|
||||
// TODO: Validate event
|
||||
if (!req.body) {
|
||||
res.status(400).send(`No object found in request`);
|
||||
@@ -95,13 +102,13 @@ exports.eventsPost = async (req, res) => {
|
||||
|
||||
switch (req.body.type) {
|
||||
case 'event':
|
||||
newEvent = { ...eventDefs.event, ...req.body };
|
||||
newEvent = { ...eventDef, ...req.body };
|
||||
break;
|
||||
case 'delay':
|
||||
newEvent = { ...eventDefs.delay, ...req.body };
|
||||
newEvent = { ...delayDef, ...req.body };
|
||||
break;
|
||||
case 'block':
|
||||
newEvent = { ...eventDefs.block, ...req.body };
|
||||
newEvent = { ...blockDef, ...req.body };
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -131,7 +138,7 @@ exports.eventsPost = async (req, res) => {
|
||||
|
||||
// Create controller for PUT request to '/events/'
|
||||
// Returns -
|
||||
exports.eventsPut = async (req, res) => {
|
||||
export const eventsPut = async (req, res) => {
|
||||
// no valid params
|
||||
if (!req.body) {
|
||||
res.status(400).send(`No object found`);
|
||||
@@ -145,29 +152,35 @@ exports.eventsPut = async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
db.get('events')
|
||||
.find({ id: req.body.id })
|
||||
.assign({ ...req.body })
|
||||
.update('revision', (n) => n + 1)
|
||||
.write();
|
||||
const eventIndex = data.events.findIndex((e) => e.id === eventId);
|
||||
if (eventIndex === -1) {
|
||||
res.status(400).send(`No Id found found`);
|
||||
return;
|
||||
}
|
||||
|
||||
const e = data.events[eventIndex];
|
||||
data.events[eventIndex] = { ...e, ...req.body };
|
||||
data.events[eventIndex].revision++;
|
||||
db.write();
|
||||
|
||||
// update timer
|
||||
_updateTimersSingle(req.body.id, req.body);
|
||||
_updateTimersSingle(eventId, req.body);
|
||||
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for PATCH request to '/events/'
|
||||
// Returns -
|
||||
exports.eventsPatch = async (req, res) => {
|
||||
export const eventsPatch = async (req, res) => {
|
||||
// Code is the same as put, call that
|
||||
this.eventsPut(req, res);
|
||||
eventsPut(req, res);
|
||||
};
|
||||
|
||||
exports.eventsReorder = async (req, res) => {
|
||||
export const eventsReorder = async (req, res) => {
|
||||
// TODO: Validate event
|
||||
if (!req.body) {
|
||||
res.status(400).send(`No object found in request`);
|
||||
@@ -177,7 +190,7 @@ exports.eventsReorder = async (req, res) => {
|
||||
const { index, from, to } = req.body;
|
||||
|
||||
// get events
|
||||
let events = db.get('events').value();
|
||||
let events = data.events;
|
||||
let idx = events.findIndex((e) => e.id === index, from);
|
||||
|
||||
// Check if item is at given index
|
||||
@@ -194,7 +207,8 @@ exports.eventsReorder = async (req, res) => {
|
||||
events.splice(to, 0, reorderedItem);
|
||||
|
||||
// save events
|
||||
db.set('events', events).write();
|
||||
data.events = events;
|
||||
db.write();
|
||||
|
||||
// TODO: would it be more efficient to reorder at timer?
|
||||
// update timer
|
||||
@@ -209,7 +223,7 @@ exports.eventsReorder = async (req, res) => {
|
||||
|
||||
// Create controller for PATCH request to '/events/applydelay/:eventId'
|
||||
// Returns -
|
||||
exports.eventsApplyDelay = async (req, res) => {
|
||||
export const eventsApplyDelay = async (req, res) => {
|
||||
// no valid params
|
||||
if (!req.params.eventId) {
|
||||
res.status(400).send(`No id found in request`);
|
||||
@@ -218,7 +232,7 @@ exports.eventsApplyDelay = async (req, res) => {
|
||||
|
||||
try {
|
||||
// get events
|
||||
let events = db.get('events').value();
|
||||
let events = data.events;
|
||||
|
||||
// AUX
|
||||
let delayIndex = null;
|
||||
@@ -259,7 +273,8 @@ exports.eventsApplyDelay = async (req, res) => {
|
||||
if (blockIndex) events.splice(blockIndex - 1, 1);
|
||||
|
||||
// update events
|
||||
db.set('events', events).write();
|
||||
data.events = events;
|
||||
db.write();
|
||||
|
||||
// update timer
|
||||
_updateTimers();
|
||||
@@ -274,7 +289,7 @@ exports.eventsApplyDelay = async (req, res) => {
|
||||
|
||||
// Create controller for DELETE request to '/events/:eventId'
|
||||
// Returns -
|
||||
exports.eventsDelete = async (req, res) => {
|
||||
export const eventsDelete = async (req, res) => {
|
||||
// no valid params
|
||||
if (!req.params.eventId) {
|
||||
res.status(400).send(`No id found in request`);
|
||||
@@ -295,3 +310,20 @@ exports.eventsDelete = async (req, res) => {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for DELETE request to '/events/:eventId'
|
||||
// Returns -
|
||||
export const eventsDeleteAll = async (req, res) => {
|
||||
try {
|
||||
// set with nothing
|
||||
data.events = [];
|
||||
db.write();
|
||||
|
||||
// update timer object
|
||||
_updateTimersSingle();
|
||||
|
||||
res.sendStatus(201);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
// get database
|
||||
import { db, data } from '../app.js';
|
||||
import fs from 'fs';
|
||||
import {
|
||||
event as eventDef,
|
||||
delay as delayDef,
|
||||
block as blockDef,
|
||||
} from '../data/eventsDefinition.js';
|
||||
import { dbModel } from '../data/dataModel.js';
|
||||
|
||||
function getEventTitle() {
|
||||
return data.event.title;
|
||||
}
|
||||
|
||||
async function deleteFile(file) {
|
||||
// delete a file
|
||||
fs.unlink(file, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// parses version 1 of the data system
|
||||
async function parsev1(jsonData) {
|
||||
if ('events' in jsonData) {
|
||||
let events = [];
|
||||
let ids = [];
|
||||
for (const e of jsonData.events) {
|
||||
if (e.type === 'event') {
|
||||
// doublecheck unique ids
|
||||
if (e.id == null || ids.indexOf(e.id) !== -1) continue;
|
||||
ids.push(e.id);
|
||||
|
||||
// make sure all properties exits
|
||||
// dont load any extra properties than the ones known
|
||||
events.push({
|
||||
...eventDef,
|
||||
title: e.title,
|
||||
subtitle: e.subtitle,
|
||||
presenter: e.presenter,
|
||||
note: e.note,
|
||||
timeStart: e.timeStart,
|
||||
timeEnd: e.timeEnd,
|
||||
isPublic: e.isPublic,
|
||||
id: e.id,
|
||||
});
|
||||
} else if (e.type === 'delay') {
|
||||
events.push({ ...delayDef, duration: e.duration });
|
||||
} else if (e.type === 'block') {
|
||||
events.push({ ...blockDef });
|
||||
}
|
||||
}
|
||||
// write to db
|
||||
db.data.events = events;
|
||||
db.write();
|
||||
}
|
||||
|
||||
if ('event' in jsonData) {
|
||||
const e = jsonData.event;
|
||||
// filter known properties
|
||||
const event = {
|
||||
...dbModel.event,
|
||||
title: e.title,
|
||||
url: e.url,
|
||||
publicInfo: e.publicInfo,
|
||||
backstageInfo: e.backstageInfo,
|
||||
};
|
||||
|
||||
// write to db
|
||||
db.data.event = event;
|
||||
db.write();
|
||||
}
|
||||
|
||||
// Not handling settings yet
|
||||
// let settings = {};
|
||||
// if ('settings' in jsonData) {
|
||||
// }
|
||||
}
|
||||
|
||||
// Create controller for GET request to '/ontime/db'
|
||||
// Returns -
|
||||
export const dbDownload = async (req, res) => {
|
||||
const fileTitle = getEventTitle() || 'ontime events';
|
||||
res.download('db.json', `${fileTitle}.json`, (err) => {
|
||||
if (err) {
|
||||
res.status(500).send({
|
||||
message: 'Could not download the file. ' + err,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 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 file = req.file.path;
|
||||
if (!fs.existsSync(file)) {
|
||||
res.status(500).send({ message: 'Upload failed' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// get file
|
||||
let rawdata = fs.readFileSync(file);
|
||||
let uploadedJson = JSON.parse(rawdata);
|
||||
|
||||
// delete file
|
||||
deleteFile(file);
|
||||
|
||||
// check version
|
||||
if (uploadedJson.settings.version === 1) parsev1(uploadedJson);
|
||||
else {
|
||||
res.status(400).send({ message: 'Error parsing file, version unknown' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
console.log('Error parsing file', error);
|
||||
res.status(400).send({ message: error });
|
||||
}
|
||||
};
|
||||
+11
-11
@@ -1,64 +1,64 @@
|
||||
// Create controller for GET request to '/playback'
|
||||
// Returns ACK message
|
||||
exports.pbGet = async (req, res) => {
|
||||
export const pbGet = async (req, res) => {
|
||||
res.send(global.timer.playState);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/start'
|
||||
// Starts timer object
|
||||
exports.pbStart = async (req, res) => {
|
||||
export const pbStart = async (req, res) => {
|
||||
global.timer.start();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/pause'
|
||||
// Pauses timer object
|
||||
exports.pbPause = async (req, res) => {
|
||||
export const pbPause = async (req, res) => {
|
||||
global.timer.pause();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/stop'
|
||||
// Stops timer object
|
||||
exports.pbStop = async (req, res) => {
|
||||
export const pbStop = async (req, res) => {
|
||||
global.timer.stop();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/roll'
|
||||
// Sets timer object to roll mode
|
||||
exports.pbRoll = async (req, res) => {
|
||||
export const pbRoll = async (req, res) => {
|
||||
global.timer.roll();
|
||||
res.sendStatus(501);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/previous'
|
||||
// Sets timer object to roll mode
|
||||
exports.pbPrevious = async (req, res) => {
|
||||
export const pbPrevious = async (req, res) => {
|
||||
global.timer.previous();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/next'
|
||||
// Sets timer object to roll mode
|
||||
exports.pbNext = async (req, res) => {
|
||||
export const pbNext = async (req, res) => {
|
||||
global.timer.next();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/unload'
|
||||
// Unloads any events
|
||||
exports.pbUnload = async (req, res) => {
|
||||
export const pbUnload = async (req, res) => {
|
||||
global.timer.unload();
|
||||
console.log('debug: unload called')
|
||||
console.log('debug: unload called');
|
||||
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/reload'
|
||||
// Reloads current event
|
||||
exports.pbReload = async (req, res) => {
|
||||
export const pbReload = async (req, res) => {
|
||||
global.timer.reload();
|
||||
console.log('debug: reload called')
|
||||
console.log('debug: reload called');
|
||||
res.sendStatus(200);
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
const dbModel = {
|
||||
export const dbModel = {
|
||||
events: [],
|
||||
event: {
|
||||
title: '',
|
||||
url: '',
|
||||
publicInfo: '',
|
||||
backStageInfo: '',
|
||||
backstageInfo: '',
|
||||
},
|
||||
settings: {
|
||||
app: 'ontime',
|
||||
@@ -14,5 +14,3 @@ const dbModel = {
|
||||
lock: false,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = { dbModel };
|
||||
@@ -1,4 +1,4 @@
|
||||
const event = {
|
||||
export const event = {
|
||||
title: '',
|
||||
subtitle: '',
|
||||
presenter: '',
|
||||
@@ -10,13 +10,12 @@ const event = {
|
||||
revision: 0,
|
||||
};
|
||||
|
||||
const delay = {
|
||||
export const delay = {
|
||||
duration: 0,
|
||||
type: 'delay',
|
||||
revision: 0,
|
||||
};
|
||||
|
||||
const block = {
|
||||
export const block = {
|
||||
type: 'block',
|
||||
};
|
||||
|
||||
module.exports = { event, delay, block };
|
||||
@@ -0,0 +1,11 @@
|
||||
import express from 'express';
|
||||
export const router = express.Router();
|
||||
|
||||
// import event controller
|
||||
import { getEvent, postEvent } from '../controllers/eventController.js';
|
||||
|
||||
// create route between controller and 'GET /event' endpoint
|
||||
router.get('/', getEvent);
|
||||
|
||||
// create route between controller and 'POST /event' endpoint
|
||||
router.post('/', postEvent);
|
||||
@@ -0,0 +1,42 @@
|
||||
import express from 'express';
|
||||
export const router = express.Router();
|
||||
|
||||
// import events controller
|
||||
import {
|
||||
eventsGetAll,
|
||||
eventsGetById,
|
||||
eventsPost,
|
||||
eventsPut,
|
||||
eventsPatch,
|
||||
eventsReorder,
|
||||
eventsApplyDelay,
|
||||
eventsDeleteAll,
|
||||
eventsDelete,
|
||||
} from '../controllers/eventsController.js';
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.get('/', eventsGetAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.get('/:eventId', eventsGetById);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.post('/', eventsPost);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.put('/', eventsPut);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.patch('/', eventsPatch);
|
||||
|
||||
// create route between controller and '/events/reorder' endpoint
|
||||
router.patch('/reorder/', eventsReorder);
|
||||
|
||||
// create route between controller and '/events/applydelay/:eventId' endpoint
|
||||
router.patch('/applydelay/:eventId', eventsApplyDelay);
|
||||
|
||||
// create route between controller and '/events/all' endpoint
|
||||
router.delete('/all', eventsDeleteAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.delete('/:eventId', eventsDelete);
|
||||
@@ -0,0 +1,11 @@
|
||||
import express from 'express';
|
||||
import uploadJson from '../utils/upload.js';
|
||||
export const router = express.Router();
|
||||
|
||||
import { dbDownload, dbUpload } from '../controllers/ontimeController.js';
|
||||
|
||||
// create route between controller and '/ontime/db' endpoint
|
||||
router.get('/db', dbDownload);
|
||||
|
||||
// create route between controller and '/ontime/db' endpoint
|
||||
router.post('/db', uploadJson, dbUpload);
|
||||
@@ -1,5 +1,5 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
import express from 'express';
|
||||
export const router = express.Router();
|
||||
|
||||
// import event controller
|
||||
const playbackController = require('../controllers/playbackController');
|
||||
@@ -30,5 +30,3 @@ router.get('/unload', playbackController.pbUnload);
|
||||
|
||||
// create route between controller and '/playback/reload' endpoint
|
||||
router.get('/reload', playbackController.pbReload);
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,23 @@
|
||||
import multer from 'multer';
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
cb(null, 'uploads/');
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
cb(null, Date.now() + '--' + file.originalname);
|
||||
},
|
||||
});
|
||||
|
||||
// filter only json
|
||||
const filterJson = (req, file, cb) => {
|
||||
if (file.mimetype.includes('application/json')) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(null, false);
|
||||
}
|
||||
};
|
||||
|
||||
const uploadJson = multer({ storage: storage, fileFilter: filterJson });
|
||||
|
||||
export default uploadJson.single('jsondb');
|
||||
Reference in New Issue
Block a user