mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-14 03:43:50 +00:00
Feat/navigate (#81)
* feat/navigate upgrade react router * feat/navigate migrate to react router 6 * feat/navigate style modal * feat/navigate create endpoints for app settings * feat/navigate protect editor with pin * feat/navigate apply dynamic routing draft * feat/navigate upgrade relevant packages * feat/navigate restructure directory and add tests * feat/navigate test aliases validation * feat/navigate validate aliases before sending * feat/navigate create data endpoint * feat/navigate config: prettier * feat/navigate invalidate empty strings * feat/navigate create endpoints * feat/navigate parse on import * feat/navigate navigate to alias * feat/navigate user help and sample data * feat/navigate refact aliases modal * feat/navigate refact settings style * feat/navigate update sample db * feat/navigate link is relative to hostname * feat/navigate navigate to first match * feat/navigate update readme and version bump * feat/navigate config: create shared module * feat/navigate config: cheat module install * feat/navigate fix tests * feat/navigate run tests in pull request * Update ontime_cy.yml
This commit is contained in:
+210
-128
@@ -6,8 +6,8 @@ import {
|
||||
block as blockDef,
|
||||
} from '../models/eventsDefinition.js';
|
||||
import { dbModelv1 } from '../models/dataModel.js';
|
||||
import { generateId } from './generate_id.js';
|
||||
import { excelDateStringToMillis } from './time.js';
|
||||
import { generateId } from 'ontime-utils/generate_id.js';
|
||||
import { excelDateStringToMillis } from 'ontime-utils/time.js';
|
||||
|
||||
export const EXCEL_MIME =
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
@@ -36,8 +36,8 @@ export const fileHandler = async (file) => {
|
||||
|
||||
// we only look at worksheets called ontime or event schedule
|
||||
if (excelData?.data) {
|
||||
const dataFromExcel = await parseExcelv1(excelData.data);
|
||||
res.data = await parseJsonv1(dataFromExcel);
|
||||
const dataFromExcel = await parseExcel_v1(excelData.data);
|
||||
res.data = await parseJson_v1(dataFromExcel);
|
||||
res.message = 'success';
|
||||
} else {
|
||||
console.log('Error: No sheets found named ontime or event schedule');
|
||||
@@ -64,7 +64,7 @@ export const fileHandler = async (file) => {
|
||||
|
||||
if (uploadedJson.settings.version === 1) {
|
||||
try {
|
||||
res.data = await parseJsonv1(uploadedJson);
|
||||
res.data = await parseJson_v1(uploadedJson);
|
||||
res.message = 'success';
|
||||
} catch (error) {
|
||||
res = { error: true, message: `Error parsing file: ${error}` };
|
||||
@@ -75,7 +75,7 @@ export const fileHandler = async (file) => {
|
||||
}
|
||||
|
||||
// delete file
|
||||
deleteFile(file);
|
||||
await deleteFile(file);
|
||||
|
||||
return res;
|
||||
};
|
||||
@@ -85,7 +85,7 @@ export const fileHandler = async (file) => {
|
||||
* @param {array} excelData - array with excel sheet
|
||||
* @returns {object} - parsed object
|
||||
*/
|
||||
export const parseExcelv1 = async (excelData) => {
|
||||
export const parseExcel_v1 = async (excelData) => {
|
||||
let eventData = {
|
||||
title: '',
|
||||
url: '',
|
||||
@@ -200,136 +200,27 @@ export const parseExcelv1 = async (excelData) => {
|
||||
* @param {boolean} [enforce=false] - flag, tells to create an object anyway
|
||||
* @returns {object} - parsed object
|
||||
*/
|
||||
|
||||
export const parseJsonv1 = async (jsonData, enforce=false) => {
|
||||
export const parseJson_v1 = async (jsonData, enforce = false) => {
|
||||
if (!jsonData || typeof jsonData !== 'object') {
|
||||
console.log('ERROR: Invalid JSON format');
|
||||
return -1;
|
||||
}
|
||||
|
||||
let numEntries = 0;
|
||||
// object containing the parsed data
|
||||
let returnData = {};
|
||||
if ('events' in jsonData) {
|
||||
console.log('Found events definition, importing...');
|
||||
let events = [];
|
||||
let ids = [];
|
||||
for (const e of jsonData.events) {
|
||||
// double check unique ids
|
||||
if (ids.indexOf(e?.id) !== -1) {
|
||||
console.log('ERROR: ID collision on import, skipping');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.type === 'event') {
|
||||
let event = validateEventv1(e);
|
||||
if (event != null) {
|
||||
events.push(event);
|
||||
ids.push(event.id);
|
||||
numEntries++;
|
||||
}
|
||||
} else if (e.type === 'delay') {
|
||||
events.push({
|
||||
...delayDef,
|
||||
duration: e.duration,
|
||||
id: e.id || generateId(),
|
||||
});
|
||||
numEntries++;
|
||||
} else if (e.type === 'block') {
|
||||
events.push({ ...blockDef, id: e.id || generateId() });
|
||||
numEntries++;
|
||||
} else {
|
||||
console.log('ERROR: undefined event type, skipping');
|
||||
}
|
||||
}
|
||||
// write to db
|
||||
returnData.events = events;
|
||||
console.log(`Uploaded file with ${numEntries} entries`);
|
||||
} else if (enforce) {
|
||||
returnData.events = [];
|
||||
console.log(`Created events object in db`);
|
||||
}
|
||||
|
||||
if ('event' in jsonData) {
|
||||
console.log('Found event data, importing...');
|
||||
const e = jsonData.event;
|
||||
|
||||
// filter known properties and write to db
|
||||
returnData.event = {
|
||||
...dbModelv1.event,
|
||||
title: e.title || dbModelv1.event.title,
|
||||
url: e.url || dbModelv1.event.url,
|
||||
publicInfo: e.publicInfo || dbModelv1.event.publicInfo,
|
||||
backstageInfo: e.backstageInfo || dbModelv1.event.backstageInfo,
|
||||
endMessage: e.endMessage || dbModelv1.event.endMessage,
|
||||
};
|
||||
} else if (enforce) {
|
||||
returnData.event = dbModelv1.event;
|
||||
console.log(`Created event object in db`);
|
||||
}
|
||||
|
||||
// parse Events
|
||||
returnData.events = parseEvents_v1(jsonData);
|
||||
// parse Event
|
||||
returnData.event = parseEvent_v1(jsonData, enforce);
|
||||
// Settings handled partially
|
||||
if ('settings' in jsonData) {
|
||||
console.log('Found settings definition, importing...');
|
||||
const s = jsonData.settings;
|
||||
|
||||
// skip if file definition is missing
|
||||
if (s.app == null || s.version == null) {
|
||||
console.log('ERROR: unknown app version, skipping');
|
||||
} else {
|
||||
let settings = {
|
||||
lock: s.lock || null,
|
||||
};
|
||||
|
||||
// write to db
|
||||
returnData.settings = {
|
||||
...dbModelv1.settings,
|
||||
...settings,
|
||||
};
|
||||
}
|
||||
} else if (enforce) {
|
||||
returnData.settings = dbModelv1.settings;
|
||||
console.log(`Created settings object in db`);
|
||||
}
|
||||
|
||||
returnData.settings = parseSettings_v1(jsonData, enforce);
|
||||
// Import OSC settings if any
|
||||
if ('osc' in jsonData) {
|
||||
console.log('Found OSC definition, importing...');
|
||||
const s = jsonData.osc;
|
||||
let osc = {};
|
||||
|
||||
if (s.port) osc.port = s.port;
|
||||
if (s.portOut) osc.portOut = s.portOut;
|
||||
if (s.targetIP) osc.targetIP = s.targetIP;
|
||||
if (s.enabled) osc.enabled = s.enabled;
|
||||
|
||||
// write to db
|
||||
returnData.osc = {
|
||||
...dbModelv1.osc,
|
||||
...osc,
|
||||
};
|
||||
} else if (enforce) {
|
||||
returnData.osc = dbModelv1.osc;
|
||||
console.log(`Created osc object in db`);
|
||||
}
|
||||
|
||||
returnData.osc = parseOsc_v1(jsonData, enforce);
|
||||
// Import HTTP settings if any
|
||||
if ('http' in jsonData) {
|
||||
console.log('Found HTTP definition, importing...');
|
||||
const h = jsonData.osc;
|
||||
let http = {};
|
||||
|
||||
if (h.user) http.user = h.user;
|
||||
if (h.pwd) http.pwd = h.pwd;
|
||||
|
||||
// write to db
|
||||
returnData.http = {
|
||||
...dbModelv1.http,
|
||||
...http,
|
||||
};
|
||||
} else if (enforce) {
|
||||
returnData.http = dbModelv1.http;
|
||||
console.log(`Created http object in db`);
|
||||
}
|
||||
returnData.http = parseHttp_v1(jsonData, enforce);
|
||||
// Import Aliases if any
|
||||
returnData.aliases = parseAliases_v1(jsonData);
|
||||
|
||||
return returnData;
|
||||
};
|
||||
@@ -352,7 +243,7 @@ export const makeString = (val, fallback = '') => {
|
||||
* @returns {object|null} - formatted object or null in case is invalid
|
||||
*/
|
||||
|
||||
export const validateEventv1 = (eventArgs) => {
|
||||
export const validateEvent_v1 = (eventArgs) => {
|
||||
// ensure id is defined and unique
|
||||
const id = eventArgs.id || generateId();
|
||||
let event = null;
|
||||
@@ -418,3 +309,194 @@ export const validateFile = (file) => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse events array of an entry
|
||||
* @param {object} data - data object
|
||||
* @returns {object} - event object data
|
||||
*/
|
||||
export const parseEvents_v1 = (data) => {
|
||||
let newEvents = [];
|
||||
if ('events' in data) {
|
||||
console.log('Found events definition, importing...');
|
||||
let events = [];
|
||||
let ids = [];
|
||||
for (const e of data.events) {
|
||||
// double check unique ids
|
||||
if (ids.indexOf(e?.id) !== -1) {
|
||||
console.log('ERROR: ID collision on import, skipping');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.type === 'event') {
|
||||
let event = validateEvent_v1(e);
|
||||
if (event != null) {
|
||||
events.push(event);
|
||||
ids.push(event.id);
|
||||
}
|
||||
} else if (e.type === 'delay') {
|
||||
events.push({
|
||||
...delayDef,
|
||||
duration: e.duration,
|
||||
id: e.id || generateId(),
|
||||
});
|
||||
} else if (e.type === 'block') {
|
||||
events.push({ ...blockDef, id: e.id || generateId() });
|
||||
} else {
|
||||
console.log('ERROR: undefined event type, skipping');
|
||||
}
|
||||
}
|
||||
// write to db
|
||||
newEvents = events;
|
||||
console.log(`Uploaded file with ${events.length} entries`);
|
||||
}
|
||||
return newEvents;
|
||||
};
|
||||
/**
|
||||
* Parse event portion of an entry
|
||||
* @param {object} data - data object
|
||||
* @param {boolean} enforce - whether to create a definition if one is missing
|
||||
* @returns {object} - event object data
|
||||
*/
|
||||
export const parseEvent_v1 = (data, enforce) => {
|
||||
let newEvent = {};
|
||||
if ('event' in data) {
|
||||
console.log('Found event data, importing...');
|
||||
const e = data.event;
|
||||
// filter known properties and write to db
|
||||
newEvent = {
|
||||
...dbModelv1.event,
|
||||
title: e.title || dbModelv1.event.title,
|
||||
url: e.url || dbModelv1.event.url,
|
||||
publicInfo: e.publicInfo || dbModelv1.event.publicInfo,
|
||||
backstageInfo: e.backstageInfo || dbModelv1.event.backstageInfo,
|
||||
endMessage: e.endMessage || dbModelv1.event.endMessage,
|
||||
};
|
||||
} else if (enforce) {
|
||||
newEvent = dbModelv1.event;
|
||||
console.log(`Created event object in db`);
|
||||
}
|
||||
return newEvent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse settings portion of an entry
|
||||
* @param {object} data - data object
|
||||
* @param {boolean} enforce - whether to create a definition if one is missing
|
||||
* @returns {object} - event object data
|
||||
*/
|
||||
export const parseSettings_v1 = (data, enforce) => {
|
||||
let newSettings = {};
|
||||
if ('settings' in data) {
|
||||
console.log('Found settings definition, importing...');
|
||||
const s = data.settings;
|
||||
|
||||
// skip if file definition is missing
|
||||
if (s.app == null || s.version == null) {
|
||||
console.log('ERROR: unknown app version, skipping');
|
||||
} else {
|
||||
let settings = {
|
||||
lock: s.lock || null,
|
||||
pinCode: s.pinCode || null,
|
||||
};
|
||||
|
||||
// write to db
|
||||
newSettings = {
|
||||
...dbModelv1.settings,
|
||||
...settings,
|
||||
};
|
||||
}
|
||||
} else if (enforce) {
|
||||
newSettings = dbModelv1.settings;
|
||||
console.log(`Created settings object in db`);
|
||||
}
|
||||
return newSettings;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse osc portion of an entry
|
||||
* @param {object} data - data object
|
||||
* @param {boolean} enforce - whether to create a definition if one is missing
|
||||
* @returns {object} - event object data
|
||||
*/
|
||||
export const parseOsc_v1 = (data, enforce) => {
|
||||
let newOsc = {};
|
||||
if ('osc' in data) {
|
||||
console.log('Found OSC definition, importing...');
|
||||
const s = data.osc;
|
||||
let osc = {};
|
||||
|
||||
if (s.port) osc.port = s.port;
|
||||
if (s.portOut) osc.portOut = s.portOut;
|
||||
if (s.targetIP) osc.targetIP = s.targetIP;
|
||||
if (s.enabled) osc.enabled = s.enabled;
|
||||
|
||||
// write to db
|
||||
newOsc = {
|
||||
...dbModelv1.osc,
|
||||
...osc,
|
||||
};
|
||||
} else if (enforce) {
|
||||
newOsc = dbModelv1.osc;
|
||||
console.log(`Created OSC object in db`);
|
||||
}
|
||||
return newOsc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse Http portion of an entry
|
||||
* @param {object} data - data object
|
||||
* @param {boolean} enforce - whether to create a definition if one is missing
|
||||
* @returns {object} - event object data
|
||||
*/
|
||||
export const parseHttp_v1 = (data, enforce) => {
|
||||
let newHttp = {};
|
||||
if ('http' in data) {
|
||||
console.log('Found HTTP definition, importing...');
|
||||
const h = data.osc;
|
||||
let http = {};
|
||||
|
||||
if (h.user) http.user = h.user;
|
||||
if (h.pwd) http.pwd = h.pwd;
|
||||
|
||||
// write to db
|
||||
newHttp.http = {
|
||||
...dbModelv1.http,
|
||||
...http,
|
||||
};
|
||||
} else if (enforce) {
|
||||
newHttp.http = dbModelv1.http;
|
||||
console.log(`Created http object in db`);
|
||||
}
|
||||
return newHttp;
|
||||
};
|
||||
/**
|
||||
* Parse aliases portion of an entry
|
||||
* @param {object} data - data object
|
||||
* @returns {object} - event object data
|
||||
*/
|
||||
export const parseAliases_v1 = (data) => {
|
||||
let newAliases = [];
|
||||
if ('aliases' in data) {
|
||||
console.log('Found Aliases definition, importing...');
|
||||
const ids = [];
|
||||
for (const a of data.aliases) {
|
||||
// double check unique ids
|
||||
if (ids.indexOf(a?.id) !== -1) {
|
||||
console.log('ERROR: ID collision on import, skipping');
|
||||
continue;
|
||||
}
|
||||
const newAlias = {
|
||||
id: a.id || generateId(),
|
||||
enabled: a.enabled || false,
|
||||
alias: a.alias || '',
|
||||
pathAndParams: a.pathAndParams || '',
|
||||
};
|
||||
|
||||
ids.push(newAlias.id);
|
||||
newAliases.push(newAlias);
|
||||
}
|
||||
console.log(`Uploaded ${newAliases?.length || 0} alias(es)`);
|
||||
}
|
||||
return newAliases;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user