Feat/excel (#45)

* add dependency

adding dependency to parse the excel file in the node side

* import file

ability to import file
- add extension
- safeguard file type and size

* user is able to upload json or excel

* chore: extract logic into self contained function

* associate model with version

* test id generation

* parse excel data

* prevent UI crash on bad data

* extract validation into self contained function

* chore: add more tests for bad data

* config: stop from opening browser on start

* fix comma in sample db

* handle corrupt files

* error boundary around main components

* jsdocs

* increase id length

* parse excel time string

* feat: excel parsing

* validate json db before import

* chore: test event validator

* feat: make function to clean convert strings

* chore: test parser

* chore: jsdocs

* fix: bug on upload

prevent bug where the component would prevent upload of same file twice
This commit is contained in:
Carlos Valente
2021-11-24 22:07:31 +01:00
committed by GitHub
parent bf8170a947
commit 8c740b7111
22 changed files with 1222 additions and 169 deletions
+24 -112
View File
@@ -4,13 +4,8 @@ import { fileURLToPath } from 'url';
// get database
import { db, data } from '../app.js';
import {
event as eventDef,
delay as delayDef,
block as blockDef,
} from '../models/eventsDefinition.js';
import { dbModel } from '../models/dataModel.js';
import { networkInterfaces } from 'os';
import { fileHandler } from '../utils/parser.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -19,93 +14,6 @@ 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) {
let numEntries = 0;
if ('events' in jsonData) {
console.log('Found events definition, importing...');
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,
});
numEntries++;
} else if (e.type === 'delay') {
events.push({ ...delayDef, duration: e.duration });
numEntries++;
} else if (e.type === 'block') {
events.push({ ...blockDef });
numEntries++;
}
}
// write to db
db.data.events = events;
db.write();
console.log(`Uploaded file with ${numEntries} entries`);
}
if ('event' in jsonData) {
console.log('Found event data, importing...');
const e = jsonData.event;
// filter known properties
const event = {
...dbModel.event,
title: e.title,
url: e.url,
publicInfo: e.publicInfo,
backstageInfo: e.backstageInfo,
endMessage: e.endMessage,
};
// write to db
db.data.event = event;
db.write();
}
// Settings handled partially
if ('settings' in jsonData) {
console.log('Found settings definition, importing...');
const s = jsonData.settings;
let settings = {};
if (s.oscInPort) settings.oscInPort = s.oscInPort;
if (s.oscOutPort) settings.oscOutPort = s.oscOutPort;
if (s.oscOutIP) settings.oscOutIP = s.oscOutIP;
// write to db
db.data.settings = {
...dbModel.settings,
...settings,
};
db.write();
}
}
// Create controller for GET request to '/ontime/db'
// Returns -
export const dbDownload = async (req, res) => {
@@ -121,6 +29,10 @@ export const dbDownload = async (req, res) => {
});
};
/**
* @description Controller for POST request to /ontime/db
* @returns none
*/
const upload = async (file, req, res) => {
if (!fs.existsSync(file)) {
res.status(500).send({ message: 'Upload failed' });
@@ -128,30 +40,30 @@ const upload = async (file, req, res) => {
}
try {
// get file
const rawdata = fs.readFileSync(file);
const uploadedJson = JSON.parse(rawdata);
const result = await fileHandler(file);
// delete file
deleteFile(file);
// check version
if (uploadedJson.settings.version === 1) {
try {
parsev1(uploadedJson);
global.timer.setupWithEventList(db.data.events);
} catch (error) {
res.status(400).send({ message: `Error parsing file: ${error}` });
if (result?.error) {
res.status(400).send({ message: result.message });
} else if (result.message === 'success') {
if (result.data != null) {
if (result.data?.events != null) {
data.events = result.data.events;
global.timer.setupWithEventList(result.data?.events);
}
if (result.data?.event != null) {
data.event = result.data.event;
}
if (result.data?.settings != null) {
data.settings = result.data.settings;
}
db.write();
}
res.sendStatus(200);
} else {
res.status(400).send({ message: 'Error parsing file, version unknown' });
return;
res.status(400).send({ message: 'Failed parsing, no data' });
}
res.sendStatus(200);
} catch (error) {
console.log('Error parsing file', error);
res.status(400).send({ message: error });
res.status(400).send({ message: `Failed parsing ${error}` });
}
};