diff --git a/apps/client/src/features/app-settings/panel/project-settings-panel/CustomFieldEntry.tsx b/apps/client/src/features/app-settings/panel/project-settings-panel/CustomFieldEntry.tsx index 63e076439..fcc340477 100644 --- a/apps/client/src/features/app-settings/panel/project-settings-panel/CustomFieldEntry.tsx +++ b/apps/client/src/features/app-settings/panel/project-settings-panel/CustomFieldEntry.tsx @@ -11,6 +11,7 @@ import CustomFieldForm from './CustomFieldForm'; import style from './ProjectSettingsPanel.module.scss'; interface CustomFieldEntryProps { + field: string; colour: string; label: string; onEdit: (label: CustomFieldLabel, patch: CustomField) => Promise; @@ -18,13 +19,11 @@ interface CustomFieldEntryProps { } export default function CustomFieldEntry(props: CustomFieldEntryProps) { - const { colour, label, onEdit, onDelete } = props; - + const { colour, label, onEdit, onDelete, field } = props; const [isEditing, setIsEditing] = useState(false); const handleEdit = async (patch: CustomField) => { - const oldLabel = label; - await onEdit(oldLabel, patch); + await onEdit(field, patch); setIsEditing(false); }; @@ -64,7 +63,7 @@ export default function CustomFieldEntry(props: CustomFieldEntryProps) { color='#FA5656' // $red-500 icon={} aria-label='Delete entry' - onClick={() => onDelete(label)} + onClick={() => onDelete(field)} /> diff --git a/apps/client/src/features/app-settings/panel/project-settings-panel/ProjectSettingsPanel.tsx b/apps/client/src/features/app-settings/panel/project-settings-panel/ProjectSettingsPanel.tsx index b926ad94b..dc605e5b6 100644 --- a/apps/client/src/features/app-settings/panel/project-settings-panel/ProjectSettingsPanel.tsx +++ b/apps/client/src/features/app-settings/panel/project-settings-panel/ProjectSettingsPanel.tsx @@ -84,6 +84,7 @@ export default function ProjectSettingsPanel() { return ( { it('creates a field from given parameters', async () => { const expected = { lighting: { - label: 'lighting', + label: 'Lighting', type: 'string', colour: 'blue', }, }; - const customField = await createCustomField({ label: 'lighting', type: 'string', colour: 'blue' }); + const customField = await createCustomField({ label: 'Lighting', type: 'string', colour: 'blue' }); expect(customField).toStrictEqual(expected); }); }); describe('editCustomField()', () => { it('edits a field with a given label', async () => { - await createCustomField({ label: 'sound', type: 'string', colour: 'blue' }); + await createCustomField({ label: 'Sound', type: 'string', colour: 'blue' }); const expected = { lighting: { - label: 'lighting', + label: 'Lighting', type: 'string', colour: 'blue', }, sound: { - label: 'sound', + label: 'Sound', type: 'string', - colour: 'blue', + colour: 'green', }, }; - const customField = await editCustomField('sound', { label: 'sound', type: 'string', colour: 'blue' }); + const customField = await editCustomField('sound', { label: 'Sound', type: 'string', colour: 'green' }); expect(customField).toStrictEqual(expected); }); @@ -879,7 +879,7 @@ describe('custom fields', () => { it('deletes a field with a given label', async () => { const expected = { lighting: { - label: 'lighting', + label: 'Lighting', type: 'string', colour: 'blue', }, diff --git a/apps/server/src/services/rundown-service/rundownCache.ts b/apps/server/src/services/rundown-service/rundownCache.ts index fa20e3692..254cc0d91 100644 --- a/apps/server/src/services/rundown-service/rundownCache.ts +++ b/apps/server/src/services/rundown-service/rundownCache.ts @@ -60,6 +60,7 @@ export async function init(initialRundown: Readonly, customFields persistedCustomFields = structuredClone(customFields); generate(); await DataProvider.setRundown(persistedRundown); + await DataProvider.setCustomFields(customFields); } /** @@ -428,16 +429,16 @@ function scheduleCustomFieldPersist(persistedCustomFields: CustomFields) { */ export const createCustomField = async (field: CustomField) => { const { label, type, colour } = field; - + const key = label.toLowerCase(); // check if label already exists - const alreadyExists = Object.hasOwn(persistedCustomFields, label); + const alreadyExists = Object.hasOwn(persistedCustomFields, key); if (alreadyExists) { throw new Error('Label already exists'); } // update object and persist - persistedCustomFields[label] = { label, type, colour }; + persistedCustomFields[key] = { label, type, colour }; scheduleCustomFieldPersist(persistedCustomFields); @@ -446,29 +447,30 @@ export const createCustomField = async (field: CustomField) => { /** * Edits an existing custom field in the database - * @param label + * @param key * @param newField * @returns */ -export const editCustomField = async (label: string, newField: Partial) => { - if (!(label in persistedCustomFields)) { +export const editCustomField = async (key: string, newField: Partial) => { + if (!(key in persistedCustomFields)) { throw new Error('Could not find label'); } - const existingField = persistedCustomFields[label]; + const existingField = persistedCustomFields[key]; if (existingField.type !== newField.type) { throw new Error('Change of field type is not allowed'); } - persistedCustomFields[newField.label] = { ...existingField, ...newField }; + const newKey = newField.label.toLowerCase(); + persistedCustomFields[newKey] = { ...existingField, ...newField }; - if (existingField.label !== newField.label) { - delete persistedCustomFields[existingField.label]; - customFieldChangelog[label] = newField.label; + if (key !== newKey) { + delete persistedCustomFields[key]; + customFieldChangelog[key] = newKey; } scheduleCustomFieldPersist(persistedCustomFields); - invalidateIfUsed(label); + invalidateIfUsed(key); return persistedCustomFields; }; diff --git a/apps/server/src/utils/__tests__/parser.test.ts b/apps/server/src/utils/__tests__/parser.test.ts index 1b968141f..988b1a7b5 100644 --- a/apps/server/src/utils/__tests__/parser.test.ts +++ b/apps/server/src/utils/__tests__/parser.test.ts @@ -796,7 +796,7 @@ describe('parseExcel()', () => { 'Skip', 'Notes', 't0', - 'UpperCaseFromSheet', + 'Test1', 'test2', 'test3', 'test4', @@ -859,8 +859,8 @@ describe('parseExcel()', () => { const importMap = { custom: { user0: 't0', - user1: 'UpperCaseFromSheet', - UpperCaseFromOntime: 'test2', + User1: 'Test1', + user2: 'test2', user3: 'test3', user4: 'test4', user5: 'test5', @@ -885,7 +885,7 @@ describe('parseExcel()', () => { custom: { user0: { value: 'a0' }, user1: { value: 'a1' }, - UpperCaseFromOntime: { value: 'a2' }, + user2: { value: 'a2' }, user3: { value: 'a3' }, user4: { value: 'a4' }, user5: { value: 'a5' }, @@ -927,12 +927,12 @@ describe('parseExcel()', () => { user1: { type: 'string', colour: '', - label: 'user1', + label: 'User1', }, - UpperCaseFromOntime: { + user2: { type: 'string', colour: '', - label: 'UpperCaseFromOntime', + label: 'user2', }, user3: { type: 'string', diff --git a/apps/server/src/utils/parser.ts b/apps/server/src/utils/parser.ts index f8bb1b660..71963aa5e 100644 --- a/apps/server/src/utils/parser.ts +++ b/apps/server/src/utils/parser.ts @@ -49,15 +49,15 @@ export function getCustomFieldData(importMap: ImportMap): { } { const customFields = {}; const customFieldImportKeys = {}; - for (const key in importMap.custom) { - const ontimeName = key; - const importName = importMap.custom[key]; - customFields[ontimeName] = { + for (const ontimeLabel in importMap.custom) { + const ontimeKey = ontimeLabel.toLowerCase(); + const importLabel = importMap.custom[ontimeLabel].toLowerCase(); + customFields[ontimeKey] = { type: 'string', colour: '', - label: ontimeName, + label: ontimeLabel, }; - customFieldImportKeys[importName] = ontimeName; + customFieldImportKeys[importLabel] = ontimeKey; } return { customFields, customFieldImportKeys }; } @@ -230,8 +230,8 @@ export const parseExcel = (excelData: unknown[][], options?: Partial) } // check if it is a custom field - if (column in customFieldImportKeys) { - handlers.custom(rowIndex, j, column); + if (columnText in customFieldImportKeys) { + handlers.custom(rowIndex, j, columnText); } // else. we don't know how to handle this column