mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 19:33:46 +00:00
Fix/195 (#200)
* refactor: add typescript dependencies * chore: update chakra-ui * refactor: typescript config * refactor: convert <MenuBar> component to typescript * refactor: convert <TooltipActionBtn> component to typescript * refactor: improve UX in file upload * refactor: upgrade dependencies * refactor: prepare data provider * refactor: prevent importing bad fields * refactor: extract merge to provider * refactor(upload): parser merges only given fields * refactor(upload): add event fields to excel * refactor(upload): improve styling on modal open * style: improve styling in menu * style: prevent global pollution * feat(upload): add upload options * fix: avoid potential bug in log queue
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user