Feature: quick start (#369)

* feat: quick start modal

* refactor: end message is part of view settings

* refactor: small tweaks and type improvements
This commit is contained in:
Carlos Valente
2023-04-29 21:20:25 +02:00
committed by GitHub
parent 33b496f98e
commit 38654f8981
41 changed files with 463 additions and 282 deletions
@@ -12,7 +12,7 @@ export class DataProvider {
return data;
}
static async setEventData(newData: EventData) {
static async setEventData(newData: Partial<EventData>) {
data.eventData = { ...data.eventData, ...newData };
await this.persist();
return data.eventData;
@@ -8,7 +8,6 @@ describe('safeMerge', () => {
publicUrl: 'existing public URL',
backstageUrl: 'existing backstageUrl',
backstageInfo: 'existing backstageInfo',
endMessage: 'existing endMessage',
},
settings: {
app: 'ontime',
@@ -20,6 +19,7 @@ describe('safeMerge', () => {
},
viewSettings: {
overrideStyles: false,
endMessage: 'existing endMessage',
},
aliases: [],
userFields: {
@@ -75,7 +75,6 @@ describe('safeMerge', () => {
publicInfo: 'new public info',
backstageUrl: 'existing backstageUrl',
backstageInfo: 'existing backstageInfo',
endMessage: 'existing endMessage',
});
});
@@ -145,7 +144,6 @@ describe('safeMerge', () => {
publicInfo: '',
backstageUrl: '',
backstageInfo: '',
endMessage: '',
},
settings: {
app: 'ontime',
@@ -157,6 +155,7 @@ describe('safeMerge', () => {
},
viewSettings: {
overrideStyles: false,
endMessage: '',
},
aliases: [],
userFields: {
@@ -1,14 +1,14 @@
import { removeUndefined } from '../utils/parserUtils.js';
import { failEmptyObjects } from '../utils/routerUtils.js';
import { DataProvider } from '../classes/data-provider/DataProvider.ts';
import { DataProvider } from '../classes/data-provider/DataProvider.js';
// Create controller for GET request to 'event'
export const getEvent = async (req, res) => {
export const getEventData = async (req, res) => {
res.json(DataProvider.getEventData());
};
// Create controller for POST request to 'event'
export const postEvent = async (req, res) => {
export const postEventData = async (req, res) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -1,6 +1,6 @@
import { body, validationResult } from 'express-validator';
export const eventSanitizer = [
export const eventDataSanitizer = [
body('title').optional().isString().trim(),
body('publicUrl').optional().isString().trim(),
body('publicInfo').optional().isString().trim(),
@@ -1,7 +1,8 @@
import fs from 'fs';
import type { EventData } from 'ontime-types';
import { networkInterfaces } from 'os';
import { generateId } from 'ontime-utils';
import { fileHandler } from '../utils/parser.ts';
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';
@@ -10,6 +11,7 @@ import { eventStore } from '../stores/EventStore.js';
import { resolveDbPath } from '../setup.js';
import { oscIntegration } from '../services/integration-service/OscIntegration.js';
import { logger } from '../classes/Logger.js';
import { deleteAllEvents } from '../services/RundownService.js';
// Create controller for GET request to '/ontime/poll'
// Returns data for current state
@@ -56,9 +58,9 @@ const uploadAndParse = async (file, req, res, options) => {
try {
const result = await fileHandler(file);
if (result?.error) {
if ('error' in result && result.error) {
res.status(400).send({ message: result.message });
} else if (result.message === 'success') {
} else if ('data' in result && result.message === 'success') {
PlaybackService.stop();
// explicitly write objects
if (typeof result !== 'undefined') {
@@ -241,7 +243,10 @@ export const postViewSettings = async (req, res) => {
}
try {
const newData = { overrideStyles: req.body.overrideStyles };
const newData = {
overrideStyles: req.body.overrideStyles,
endMessage: req.body?.endMessage || '',
};
await DataProvider.setViewSettings(newData);
res.status(200).send(newData);
} catch (error) {
@@ -288,3 +293,21 @@ export const dbUpload = async (req, res) => {
const file = req.file.path;
await uploadAndParse(file, req, res, options);
};
// Create controller for POST request to '/ontime/new'
export const postNew = async (req, res) => {
try {
const newEventData: Omit<EventData, 'endMessage'> = {
title: req.body?.title ?? '',
publicUrl: req.body?.publicUrl ?? '',
publicInfo: req.body?.publicInfo ?? '',
backstageUrl: req.body?.backstageUrl ?? '',
backstageInfo: req.body?.backstageInfo ?? '',
};
const newData = await DataProvider.setEventData(newEventData);
await deleteAllEvents();
res.status(201).send(newData);
} catch (error) {
res.status(400).send(error);
}
};
@@ -6,6 +6,7 @@ import { validateOscSubscription } from '../utils/parserFunctions.js';
*/
export const viewValidator = [
check('overrideStyles').isBoolean().withMessage('overrideStyles value must be boolean'),
check('endMessage').isString().trim().withMessage('endMessage value must be string'),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
+1 -1
View File
@@ -8,7 +8,6 @@ export const dbModel: DatabaseModel = {
publicInfo: '',
backstageUrl: '',
backstageInfo: '',
endMessage: '',
},
settings: {
app: 'ontime',
@@ -20,6 +19,7 @@ export const dbModel: DatabaseModel = {
},
viewSettings: {
overrideStyles: false,
endMessage: '',
},
aliases: [],
userFields: {
+6 -6
View File
@@ -1,12 +1,12 @@
import express from 'express';
// import event controller
import { getEventData, postEventData } from '../controllers/eventDataController.ts';
import { eventDataSanitizer } from '../controllers/eventDataController.validate.ts';
export const router = express.Router();
// import event controller
import { getEvent, postEvent } from '../controllers/eventDataController.js';
import { eventSanitizer } from '../controllers/eventDataController.validate.js';
// create route between controller and 'GET /event' endpoint
router.get('/', getEvent);
router.get('/', getEventData);
// create route between controller and 'POST /event' endpoint
router.post('/', eventSanitizer, postEvent);
router.post('/', eventDataSanitizer, postEventData);
+5
View File
@@ -11,6 +11,7 @@ import {
getViewSettings,
poll,
postAliases,
postNew,
postOSC,
postSettings,
postUserFields,
@@ -24,6 +25,7 @@ import {
validateUserFields,
viewValidator,
} from '../controllers/ontimeController.validate.js';
import { eventDataSanitizer } from '../controllers/eventDataController.validate.js';
export const router = express.Router();
@@ -68,3 +70,6 @@ router.get('/osc', getOSC);
// create route between controller and '/ontime/osc' endpoint
router.post('/osc', validateOSC, postOSC);
// create route between controller and '/ontime/new' endpoint
router.post('/new', eventDataSanitizer, postNew);
+1 -1
View File
@@ -352,7 +352,7 @@ type ResponseError = { error: true; message: string };
* @param {string} file - reference to file
* @return {object} - parse result message
*/
export const fileHandler = async (file) => {
export const fileHandler = async (file): ResponseOK | ResponseError => {
let res: Partial<ResponseOK | ResponseError> = {};
// check which file type are we dealing with
+1 -1
View File
@@ -87,7 +87,6 @@ export const parseEventData = (data, enforce): EventData => {
publicInfo: e.publicInfo || dbModel.eventData.publicInfo,
backstageUrl: e.backstageUrl || dbModel.eventData.backstageUrl,
backstageInfo: e.backstageInfo || dbModel.eventData.backstageInfo,
endMessage: e.endMessage || dbModel.eventData.endMessage,
};
} else if (enforce) {
newEventData = { ...dbModel.eventData };
@@ -145,6 +144,7 @@ export const parseViewSettings = (data, enforce): ViewSettings => {
const viewSettings = {
overrideStyles: v.overrideStyles ?? dbModel.viewSettings.overrideStyles,
endMessage: v.endMessage ?? dbModel.viewSettings.endMessage,
};
// write to db