-
+
-
+
diff --git a/client/src/features/info/Info.module.scss b/client/src/features/info/Info.module.scss
index fe1634c09..26a64cafb 100644
--- a/client/src/features/info/Info.module.scss
+++ b/client/src/features/info/Info.module.scss
@@ -85,8 +85,3 @@
padding: 0 0.5em;
margin: 0 0.5em;
}
-
-ul > li {
- font-size: 0.9em;
- color: $text-white;
-}
diff --git a/client/src/features/menu/EventListMenu.jsx b/client/src/features/menu/EventListMenu.jsx
index 6cc9a6139..d436f498a 100644
--- a/client/src/features/menu/EventListMenu.jsx
+++ b/client/src/features/menu/EventListMenu.jsx
@@ -85,14 +85,14 @@ const EventListMenu = ({ eventsHandler }) => {
clickHandler={() => actionHandler('cursorUp')}
icon={
}
tooltip='Move cursor up Alt + ↑'
- _hover={{ bg: 'pink.400' }}
+ _hover={{ bg: 'pink.400', color: 'white' }}
/>
actionHandler('cursorDown')}
icon={}
tooltip='Move cursor down Alt + ↓'
- _hover={{ bg: 'pink.400' }}
+ _hover={{ bg: 'pink.400', color: 'white' }}
/>
{
tooltip='Lock cursor to current'
width='3em'
backgroundColor={isCursorLocked && 'pink.400'}
- _hover={{ bg: 'pink.300' }}
+ color={isCursorLocked && 'white'}
+ _hover={{ bg: 'pink.400', color: 'white' }}
variant={isCursorLocked ? 'solid' : 'outline'}
/>
diff --git a/client/src/features/menu/MenuBar.jsx b/client/src/features/menu/MenuBar.jsx
index f1d19c6f5..e69de29bb 100644
--- a/client/src/features/menu/MenuBar.jsx
+++ b/client/src/features/menu/MenuBar.jsx
@@ -1,188 +0,0 @@
-import { useCallback, useContext, useEffect, useRef } from 'react';
-import { VStack } from '@chakra-ui/react';
-import { FiDownload } from '@react-icons/all-files/fi/FiDownload';
-import { FiHelpCircle } from '@react-icons/all-files/fi/FiHelpCircle';
-import { FiMaximize } from '@react-icons/all-files/fi/FiMaximize';
-import { FiMinimize } from '@react-icons/all-files/fi/FiMinimize';
-import { FiSettings } from '@react-icons/all-files/fi/FiSettings';
-import { FiUpload } from '@react-icons/all-files/fi/FiUpload';
-import { useMutation, useQueryClient } from '@tanstack/react-query';
-import { EVENTS_TABLE } from 'common/api/apiConstants';
-import { downloadEvents, uploadEvents } from 'common/api/ontimeApi';
-import PropTypes from 'prop-types';
-
-import QuitIconBtn from '../../common/components/buttons/QuitIconBtn';
-import TooltipActionBtn from '../../common/components/buttons/TooltipActionBtn';
-import { LoggingContext } from '../../common/context/LoggingContext';
-
-import style from './MenuBar.module.scss';
-
-export default function MenuBar(props) {
- const { isOpen, onOpen, onClose } = props;
- const { emitError } = useContext(LoggingContext);
- const hiddenFileInput = useRef(null);
- const queryClient = useQueryClient();
- const uploaddb = useMutation(uploadEvents, {
- onSettled: () => {
- queryClient.invalidateQueries(EVENTS_TABLE);
- },
- });
-
- const handleClick = useCallback(() => {
- if (hiddenFileInput && hiddenFileInput.current) {
- hiddenFileInput.current.click();
- }
- }, [hiddenFileInput]);
-
- const buttonStyle = {
- fontSize: '1.5em',
- size: 'lg',
- colorScheme: 'white',
- };
-
- const handleUpload = useCallback(
- (event) => {
- const fileUploaded = event.target.files[0];
- if (fileUploaded == null) return;
-
- // Limit file size to 1MB
- if (fileUploaded.size > 1000000) {
- emitError('Error: File size limit (1MB) exceeded');
- return;
- }
-
- // Check file extension
- if (fileUploaded.name.endsWith('.xlsx') || fileUploaded.name.endsWith('.json')) {
- try {
- uploaddb.mutate(fileUploaded);
- } catch (error) {
- emitError(`Failed uploading file: ${error}`);
- }
- } else {
- emitError('Error: File type unknown');
- }
-
- // reset input value
- hiddenFileInput.current.value = '';
- },
- [emitError, uploaddb]
- );
-
- const handleIPC = useCallback((action) => {
- // Stop crashes when testing locally
- if (typeof window.process?.type === 'undefined') {
- if (action === 'help') {
- window.open('https://cpvalente.gitbook.io/ontime/');
- }
- return;
- }
-
- if (window.process?.type === 'renderer') {
- switch (action) {
- case 'min':
- window.ipcRenderer.send('set-window', 'to-tray');
- break;
- case 'max':
- window.ipcRenderer.send('set-window', 'to-max');
- break;
- case 'shutdown':
- window.ipcRenderer.send('shutdown', 'now');
- break;
- case 'help':
- window.ipcRenderer.send('send-to-link', 'help');
- break;
- default:
- break;
- }
- }
- }, []);
-
- // Handle keyboard shortcuts
- const handleKeyPress = useCallback(
- (e) => {
- // handle held key
- if (e.repeat) return;
- // check if the alt key is pressed
- if (e.ctrlKey) {
- if (e.key === ',') {
- // if we are in electron
- if (window.process?.type === undefined) return;
- if (window.process.type === 'renderer') {
- // open if not open
- isOpen ? onClose() : onOpen();
- }
- }
- }
- },
- [isOpen, onClose, onOpen]
- );
-
- useEffect(() => {
- // attach the event listener
- document.addEventListener('keydown', handleKeyPress);
-
- // remove the event listener
- return () => {
- document.removeEventListener('keydown', handleKeyPress);
- };
- }, [handleKeyPress]);
-
- return (
-
- handleIPC('shutdown')} />
- }
- clickHandler={() => handleIPC('max')}
- tooltip='Show full window'
- />
- }
- clickHandler={() => handleIPC('min')}
- tooltip='Close to tray'
- />
-
- }
- clickHandler={() => handleIPC('help')}
- tooltip='Help'
- />
- }
- className={isOpen ? style.open : ''}
- clickHandler={onOpen}
- tooltip='Settings'
- isRound
- />
-
-
- }
- clickHandler={handleClick}
- tooltip='Import event list'
- />
- }
- clickHandler={downloadEvents}
- tooltip='Export event list'
- />
-
- );
-}
-
-MenuBar.propTypes = {
- isOpen: PropTypes.bool,
- onOpen: PropTypes.func.isRequired,
- onClose: PropTypes.func.isRequired,
-};
diff --git a/client/src/features/menu/MenuBar.tsx b/client/src/features/menu/MenuBar.tsx
new file mode 100644
index 000000000..77b23d9ed
--- /dev/null
+++ b/client/src/features/menu/MenuBar.tsx
@@ -0,0 +1,145 @@
+import { useCallback, useEffect } from 'react';
+import { VStack } from '@chakra-ui/react';
+import { FiHelpCircle } from '@react-icons/all-files/fi/FiHelpCircle';
+import { FiMaximize } from '@react-icons/all-files/fi/FiMaximize';
+import { FiMinimize } from '@react-icons/all-files/fi/FiMinimize';
+import { FiSave } from '@react-icons/all-files/fi/FiSave';
+import { FiSettings } from '@react-icons/all-files/fi/FiSettings';
+import { FiUpload } from '@react-icons/all-files/fi/FiUpload';
+import { downloadEvents } from 'common/api/ontimeApi';
+
+import QuitIconBtn from '../../common/components/buttons/QuitIconBtn';
+import TooltipActionBtn from '../../common/components/buttons/TooltipActionBtn';
+import useElectronEvent from '../../common/hooks/useElectronEvent';
+
+import style from './MenuBar.module.scss';
+
+interface MenuBarProps {
+ isSettingsOpen: boolean;
+ onSettingsOpen: () => void;
+ onSettingsClose: () => void;
+ isUploadOpen: boolean;
+ onUploadOpen: () => void;
+}
+
+type Actions = 'min' | 'max' | 'shutdown' | 'help';
+
+const buttonStyle = {
+ fontSize: '1.5em',
+ size: 'lg',
+ colorScheme: 'white',
+};
+
+export default function MenuBar(props: MenuBarProps) {
+ const { isSettingsOpen, onSettingsOpen, onSettingsClose, isUploadOpen, onUploadOpen } = props;
+ const { isElectron, sendToElectron } = useElectronEvent();
+
+ const actionHandler = useCallback((action: Actions) => {
+ // Stop crashes when testing locally
+ if (!isElectron) {
+ if (action === 'help') {
+ window.open('https://cpvalente.gitbook.io/ontime/');
+ }
+ } else {
+ switch (action) {
+ case 'min':
+ sendToElectron('set-window', 'to-tray');
+ break;
+ case 'max':
+ sendToElectron('set-window', 'to-max');
+ break;
+ case 'shutdown':
+ sendToElectron('shutdown', 'now');
+ break;
+ case 'help':
+ sendToElectron('send-to-link', 'help');
+ break;
+ default:
+ break;
+ }
+ }
+ }, [sendToElectron, isElectron]);
+
+ // Handle keyboard shortcuts
+ const handleKeyPress = useCallback(
+ (event: KeyboardEvent) => {
+ // skip if not electron
+ if (!isElectron) return;
+ // handle held key
+ if (event.repeat) return;
+
+ // check if the ctrl key is pressed
+ if (event.ctrlKey) {
+ // ctrl + , (settings)
+ if (event.key === ',') {
+ if (isElectron) {
+ // open if not open
+ isSettingsOpen ? onSettingsClose() : onSettingsOpen();
+ }
+ }
+ }
+ },
+ [isElectron, isSettingsOpen, onSettingsClose, onSettingsOpen]
+ );
+
+ useEffect(() => {
+ document.addEventListener('keydown', handleKeyPress);
+ return () => {
+ document.removeEventListener('keydown', handleKeyPress);
+ };
+ }, [handleKeyPress]);
+
+ return (
+
+ actionHandler('shutdown')} />
+ }
+ clickHandler={() => actionHandler('max')}
+ tooltip='Show full window'
+ aria-label=''
+ />
+ }
+ clickHandler={() => actionHandler('min')}
+ tooltip='Close to tray'
+ aria-label=''
+ />
+
+ }
+ clickHandler={() => actionHandler('help')}
+ tooltip='Help'
+ aria-label=''
+ />
+ }
+ className={isSettingsOpen ? style.open : ''}
+ clickHandler={onSettingsOpen}
+ tooltip='Settings'
+ isRound
+ aria-label=''
+ />
+
+ }
+ className={isUploadOpen ? style.open : ''}
+ clickHandler={onUploadOpen}
+ tooltip='Upload event list'
+ isRound
+ aria-label=''
+ />
+ }
+ clickHandler={downloadEvents}
+ tooltip='Export event list'
+ aria-label=''
+ />
+
+ );
+}
diff --git a/client/src/features/menu/__tests__/MenuBar.test.js b/client/src/features/menu/__tests__/MenuBar.test.tsx
similarity index 77%
rename from client/src/features/menu/__tests__/MenuBar.test.js
rename to client/src/features/menu/__tests__/MenuBar.test.tsx
index 54aefd185..1b8b1ae3b 100644
--- a/client/src/features/menu/__tests__/MenuBar.test.js
+++ b/client/src/features/menu/__tests__/MenuBar.test.tsx
@@ -6,11 +6,13 @@ import MenuBar from '../MenuBar';
const onOpenHandler = jest.fn();
const onCloseHandler = jest.fn();
+const isOpen = false;
+const onUploadOpenHandler = jest.fn();
const renderInMock = () => {
render(
-
+
);
};
diff --git a/server/src/classes/data-provider/DataProvider.js b/server/src/classes/data-provider/DataProvider.js
new file mode 100644
index 000000000..df1796d57
--- /dev/null
+++ b/server/src/classes/data-provider/DataProvider.js
@@ -0,0 +1,36 @@
+/**
+ * Class Event Provider adds functions specific for handling event data
+ */
+export class DataProvider {
+ /**
+ * Merges two data objects
+ * @param {object} existing
+ * @param {object} newData
+ */
+ static safeMerge(existing, newData) {
+ const mergedData = { ...existing };
+
+ if (typeof newData?.events !== 'undefined') {
+ mergedData.events = newData.events;
+ }
+ if (typeof newData?.event !== 'undefined') {
+ mergedData.event = { ...newData.event };
+ }
+ if (typeof newData?.settings !== 'undefined') {
+ mergedData.settings = { ...newData.settings };
+ }
+ if (typeof newData?.osc !== 'undefined') {
+ mergedData.osc = { ...newData.osc };
+ }
+ if (typeof newData?.http !== 'undefined') {
+ mergedData.http = { ...newData.http };
+ }
+ if (typeof newData?.aliases !== 'undefined') {
+ mergedData.aliases = [...newData.aliases];
+ }
+ if (typeof newData?.userFields !== 'undefined') {
+ mergedData.userFields = { ...existing.userFields, ...newData.userFields };
+ }
+ return mergedData;
+ }
+}
diff --git a/server/src/classes/data-provider/__tests__/DataProvider.test.js b/server/src/classes/data-provider/__tests__/DataProvider.test.js
new file mode 100644
index 000000000..a84a5523a
--- /dev/null
+++ b/server/src/classes/data-provider/__tests__/DataProvider.test.js
@@ -0,0 +1,97 @@
+import { DataProvider } from '../DataProvider';
+
+describe('DataProvider', () => {
+ describe('safeMerge()', () => {
+ it('merges two objects ', () => {
+ const oldData = {
+ events: [{ event: 'old event' }],
+ event: {
+ title: 'old title',
+ url: 'old url',
+ endMessage: 'old end message',
+ },
+ osc: {
+ port: 'old port',
+ },
+ settings: {
+ app: 'ontime',
+ version: 1,
+ serverPort: 4001,
+ lock: null,
+ pinCode: null,
+ timeFormat: '24',
+ },
+ userFields: {
+ user0: 'old 0',
+ user1: 'old 1',
+ user2: 'old 2',
+ user3: 'old 3',
+ user4: 'old 4',
+ user5: 'old 5',
+ user6: 'old 6',
+ user7: 'old 7',
+ user8: 'old 8',
+ user9: 'old 9',
+ },
+ };
+ const newData = {
+ events: [{ event: 'new event' }],
+ event: {
+ title: 'new title',
+ url: 'new url',
+ endMessage: 'old end message',
+ publicInfo: 'new public info',
+ },
+ settings: {
+ app: 'ontime',
+ version: 1,
+ serverPort: 4001,
+ lock: null,
+ pinCode: null,
+ timeFormat: '24',
+ },
+ userFields: {
+ user6: 'new 6',
+ user7: 'new 7',
+ user8: 'new 8',
+ user9: 'new 9',
+ },
+ };
+
+ const expected = {
+ events: [{ event: 'new event' }],
+ event: {
+ title: 'new title',
+ url: 'new url',
+ publicInfo: 'new public info',
+ endMessage: 'old end message',
+ },
+ osc: {
+ port: 'old port',
+ },
+ settings: {
+ app: 'ontime',
+ version: 1,
+ serverPort: 4001,
+ lock: null,
+ pinCode: null,
+ timeFormat: '24',
+ },
+ userFields: {
+ user0: 'old 0',
+ user1: 'old 1',
+ user2: 'old 2',
+ user3: 'old 3',
+ user4: 'old 4',
+ user5: 'old 5',
+ user6: 'new 6',
+ user7: 'new 7',
+ user8: 'new 8',
+ user9: 'new 9',
+ },
+ };
+ const merged = DataProvider.safeMerge(oldData, newData);
+ expect(merged).toStrictEqual(expected);
+ });
+ });
+});
diff --git a/server/src/controllers/ontimeController.js b/server/src/controllers/ontimeController.js
index f12080890..7dd1f19b6 100644
--- a/server/src/controllers/ontimeController.js
+++ b/server/src/controllers/ontimeController.js
@@ -4,6 +4,7 @@ import { networkInterfaces } from 'os';
import { fileHandler } from '../utils/parser.js';
import { generateId } from '../utils/generate_id.js';
import { resolveDbPath } from '../modules/loadDb.js';
+import { DataProvider } from '../classes/data-provider/DataProvider.js';
// Create controller for GET request to '/ontime/poll'
// Returns data for current state
@@ -33,11 +34,7 @@ export const dbDownload = async (req, res) => {
});
};
-/**
- * @description Controller for POST request to /ontime/db
- * @returns none
- */
-const upload = async (file, req, res) => {
+const uploadAndParse = async (file, req, res, options) => {
if (!fs.existsSync(file)) {
res.status(500).send({ message: 'Upload failed' });
return;
@@ -50,29 +47,18 @@ const upload = async (file, req, res) => {
res.status(400).send({ message: result.message });
} else if (result.message === 'success') {
// explicitly write objects
- if (typeof result.data !== 'undefined') {
- if (typeof result.data?.events !== 'undefined') {
- data.events = result.data.events;
- global.timer.setupWithEventList(result.data?.events);
- }
- if (typeof result.data?.event !== 'undefined') {
- data.event = result.data.event;
- }
- if (typeof result.data?.settings !== 'undefined') {
- data.settings = result.data.settings;
- }
- if (typeof result.data?.osc !== 'undefined') {
- data.osc = result.data.osc;
- }
- if (typeof result.data?.http !== 'undefined') {
- data.http = result.data.http;
- }
- if (typeof result.data?.aliases !== 'undefined') {
- data.aliases = result.data.aliases;
- }
- if (typeof result.data?.userFields !== 'undefined') {
- data.userFields = result.data.userFields;
+ if (typeof result !== 'undefined') {
+ if (!options.onlyEvents) {
+ const mergedData = DataProvider.safeMerge(data, result.data);
+ data.event = mergedData.event;
+ data.settings = mergedData.settings;
+ data.osc = mergedData.osc;
+ data.http = mergedData.http;
+ data.aliases = mergedData.aliases;
+ data.userFields = mergedData.userFields;
}
+ data.events = result.data.events || [];
+ global.timer.setupWithEventList(result.data.events || []);
await db.write();
}
res.sendStatus(200);
@@ -297,9 +283,9 @@ export const dbUpload = async (req, res) => {
res.status(400).send({ message: 'File not found' });
return;
}
-
+ const options = req.query;
const file = req.file.path;
- upload(file, req, res);
+ uploadAndParse(file, req, res, options);
};
// Create controller for POST request to '/ontime/dbpath'
@@ -309,5 +295,5 @@ export const dbPathToUpload = async (req, res) => {
res.status(400).send({ message: 'Path to file not found' });
return;
}
- upload(req.body.path, req, res);
+ uploadAndParse(req.body.path, req, res);
};
diff --git a/server/src/utils/__tests__/parser.tests.js b/server/src/utils/__tests__/parser.tests.js
index 90a38275e..ddc77361a 100644
--- a/server/src/utils/__tests__/parser.tests.js
+++ b/server/src/utils/__tests__/parser.tests.js
@@ -564,6 +564,9 @@ describe('test parseExcel function', () => {
[],
['Event Name', 'Test Event'],
['Event URL', 'www.carlosvalente.com'],
+ ['Public Info', 'test public info'],
+ ['Backstage Info', 'test backstage info'],
+ ['End Message', 'test end message'],
[],
[],
[
@@ -640,6 +643,14 @@ describe('test parseExcel function', () => {
[],
];
+ const expectedParsedEvent = {
+ title: 'Test Event',
+ url: 'www.carlosvalente.com',
+ publicInfo: 'test public info',
+ backstageInfo: 'test backstage info',
+ endMessage: 'test end message',
+ };
+
const expectedParsedEvents = [
{
timeStart: 25200000,
@@ -681,6 +692,7 @@ describe('test parseExcel function', () => {
const parsedData = await parseExcel_v1(testdata);
+ expect(parsedData.event).toStrictEqual(expectedParsedEvent);
expect(parsedData.events).toBeDefined();
expect(parsedData.events.title).toBe(expectedParsedEvents.title);
expect(parsedData.events.presenter).toBe(expectedParsedEvents.presenter);
diff --git a/server/src/utils/parser.js b/server/src/utils/parser.js
index b37ffa58e..c26fb7a7e 100644
--- a/server/src/utils/parser.js
+++ b/server/src/utils/parser.js
@@ -68,6 +68,9 @@ export const parseExcel_v1 = async (excelData) => {
.forEach((row) => {
let eventTitleNext = false;
let eventUrlNext = false;
+ let publicInfoNext = false;
+ let backstageInfoNext = false;
+ let endMessageNext = false;
const event = {};
row.forEach((column, j) => {
@@ -78,6 +81,15 @@ export const parseExcel_v1 = async (excelData) => {
} else if (eventUrlNext) {
eventData.url = column;
eventUrlNext = false;
+ } else if (publicInfoNext) {
+ eventData.publicInfo = column;
+ publicInfoNext = false;
+ } else if (backstageInfoNext) {
+ eventData.backstageInfo = column;
+ backstageInfoNext = false;
+ } else if (endMessageNext) {
+ eventData.endMessage = column;
+ endMessageNext = false;
} else if (j === timeStartIndex) {
event.timeStart = parseExcelDate(column);
} else if (j === timeEndIndex) {
@@ -128,6 +140,15 @@ export const parseExcel_v1 = async (excelData) => {
case 'event url':
eventUrlNext = true;
break;
+ case 'public info':
+ publicInfoNext = true;
+ break;
+ case 'backstage info':
+ backstageInfoNext = true;
+ break;
+ case 'end message':
+ endMessageNext = true;
+ break;
case 'time start':
case 'start':
timeStartIndex = j;
@@ -329,7 +350,6 @@ export const fileHandler = async (file) => {
let res = {};
// check which file type are we dealing with
-
if (file.endsWith('.xlsx')) {
try {
const excelData = xlsx
@@ -341,7 +361,10 @@ export const fileHandler = async (file) => {
// we only look at worksheets called ontime or event schedule
if (excelData?.data) {
const dataFromExcel = await parseExcel_v1(excelData.data);
- res.data = await parseJson_v1(dataFromExcel);
+ res.data = {};
+ res.data.events = parseEvents_v1(dataFromExcel);
+ res.data.event = parseEvent_v1(dataFromExcel, true);
+ res.data.userFields = parseUserFields_v1(dataFromExcel);
res.message = 'success';
} else {
console.log('Error: No sheets found named ontime or event schedule');
diff --git a/server/src/utils/parserUtils_v1.js b/server/src/utils/parserUtils_v1.js
index 7968d996c..d20078b3e 100644
--- a/server/src/utils/parserUtils_v1.js
+++ b/server/src/utils/parserUtils_v1.js
@@ -14,37 +14,41 @@ export const parseEvents_v1 = (data) => {
if ('events' in data) {
console.log('Found events definition, importing...');
const events = [];
- const ids = [];
- for (const e of data.events) {
- // cap number of events
- if (events.length >= MAX_EVENTS) {
- console.log(`ERROR: Reached limit number of ${MAX_EVENTS} events`);
- break;
- }
-
- // double check unique ids
- if (ids.indexOf(e?.id) !== -1) {
- console.log('ERROR: ID collision on import, skipping');
- continue;
- }
-
- if (e.type === 'event') {
- const event = validateEvent_v1(e);
- if (event != null) {
- events.push(event);
- ids.push(event.id);
+ try {
+ const ids = [];
+ for (const e of data.events) {
+ // cap number of events
+ if (events.length >= MAX_EVENTS) {
+ console.log(`ERROR: Reached limit number of ${MAX_EVENTS} events`);
+ break;
+ }
+
+ // double check unique ids
+ if (ids.indexOf(e?.id) !== -1) {
+ console.log('ERROR: ID collision on import, skipping');
+ continue;
+ }
+
+ if (e.type === 'event') {
+ const 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');
}
- } 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');
}
+ } catch (error) {
+ console.log(`Error ${error}`);
}
// write to db
newEvents = events;
@@ -73,7 +77,7 @@ export const parseEvent_v1 = (data, enforce) => {
endMessage: e.endMessage || dbModelv1.event.endMessage,
};
} else if (enforce) {
- newEvent = dbModelv1.event;
+ newEvent = { ...dbModelv1.event };
console.log(`Created event object in db`);
}
return newEvent;
@@ -137,7 +141,7 @@ export const parseOsc_v1 = (data, enforce) => {
...osc,
};
} else if (enforce) {
- newOsc = dbModelv1.osc;
+ newOsc = { ...dbModelv1.osc };
console.log(`Created OSC object in db`);
}
return newOsc;
@@ -165,7 +169,7 @@ export const parseHttp_v1 = (data, enforce) => {
...http,
};
} else if (enforce) {
- newHttp.http = dbModelv1.http;
+ newHttp.http = { ...dbModelv1.http };
console.log(`Created http object in db`);
}
return newHttp;
@@ -181,23 +185,27 @@ export const parseAliases_v1 = (data) => {
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 || '',
- };
+ try {
+ 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);
+ ids.push(newAlias.id);
+ newAliases.push(newAlias);
+ }
+ console.log(`Uploaded ${newAliases?.length || 0} alias(es)`);
+ } catch (error) {
+ console.log(`Error: ${error}`);
}
- console.log(`Uploaded ${newAliases?.length || 0} alias(es)`);
}
return newAliases;
};
@@ -208,19 +216,23 @@ export const parseAliases_v1 = (data) => {
* @returns {object} - event object data
*/
export const parseUserFields_v1 = (data) => {
- const newUserFields = dbModelv1.userFields;
+ const newUserFields = { ...dbModelv1.userFields };
if ('userFields' in data) {
console.log('Found User Fields definition, importing...');
// we will only be importing the fields we know, so look for that
- let fieldsFound = 0;
- for (const n in newUserFields) {
- if (n in data.userFields) {
- fieldsFound++;
- newUserFields[n] = data.userFields[n];
+ try {
+ let fieldsFound = 0;
+ for (const n in newUserFields) {
+ if (n in data.userFields) {
+ fieldsFound++;
+ newUserFields[n] = data.userFields[n];
+ }
}
+ console.log(`Uploaded ${fieldsFound} user fields`);
+ } catch (error) {
+ console.log(`Error: ${error}`);
}
- console.log(`Uploaded ${fieldsFound} user fields`);
}
- return { ...dbModelv1.userFields, ...newUserFields };
+ return { ...newUserFields };
};