mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-03 13:29:06 +00:00
refactor: fixes to custom field
This commit is contained in:
+2
-2
@@ -7,8 +7,8 @@ import { getURLSearchParamsFromObj, makeOptionsFromCustomFields } from '../viewP
|
|||||||
|
|
||||||
describe('makeOptionsFromCustomFields()', () => {
|
describe('makeOptionsFromCustomFields()', () => {
|
||||||
const testCustomFields: CustomFields = {
|
const testCustomFields: CustomFields = {
|
||||||
field1: { label: 'Field 1', colour: 'red', type: 'string' },
|
field1: { label: 'Field 1', colour: 'red', type: 'text' },
|
||||||
field2: { label: 'Field 2', colour: 'blue', type: 'string' },
|
field2: { label: 'Field 2', colour: 'blue', type: 'text' },
|
||||||
};
|
};
|
||||||
|
|
||||||
it('creates an array of options to use in a select', () => {
|
it('creates an array of options to use in a select', () => {
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ interface CustomFieldEntryProps {
|
|||||||
colour: string;
|
colour: string;
|
||||||
label: string;
|
label: string;
|
||||||
fieldKey: string;
|
fieldKey: string;
|
||||||
type: 'string' | 'image';
|
type: CustomField['type'];
|
||||||
onEdit: (key: CustomFieldKey, patch: CustomField) => Promise<void>;
|
onEdit: (key: CustomFieldKey, patch: CustomField) => Promise<void>;
|
||||||
onDelete: (key: CustomFieldKey) => Promise<void>;
|
onDelete: (key: CustomFieldKey) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -42,7 +42,7 @@ export default function CustomFieldForm(props: CustomFieldsFormProps) {
|
|||||||
watch,
|
watch,
|
||||||
formState: { errors, isSubmitting, isValid, isDirty },
|
formState: { errors, isSubmitting, isValid, isDirty },
|
||||||
} = useForm<CustomFieldFormData>({
|
} = useForm<CustomFieldFormData>({
|
||||||
defaultValues: { type: 'string', label: initialLabel || '', colour: initialColour || '' },
|
defaultValues: { type: 'text', label: initialLabel || '', colour: initialColour || '' },
|
||||||
resetOptions: {
|
resetOptions: {
|
||||||
keepDirtyValues: true,
|
keepDirtyValues: true,
|
||||||
},
|
},
|
||||||
@@ -96,7 +96,7 @@ export default function CustomFieldForm(props: CustomFieldsFormProps) {
|
|||||||
onValueChange={(value) => setValue('type', value, { shouldDirty: true })}
|
onValueChange={(value) => setValue('type', value, { shouldDirty: true })}
|
||||||
value={watch('type')}
|
value={watch('type')}
|
||||||
items={[
|
items={[
|
||||||
{ value: 'string', label: 'Text' },
|
{ value: 'text', label: 'Text' },
|
||||||
{ value: 'image', label: 'Image' },
|
{ value: 'image', label: 'Image' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default function EntryEditorCustomFields({
|
|||||||
const { backgroundColor, color } = getAccessibleColour(customFields[fieldKey].colour);
|
const { backgroundColor, color } = getAccessibleColour(customFields[fieldKey].colour);
|
||||||
const labelText = customFields[fieldKey].label;
|
const labelText = customFields[fieldKey].label;
|
||||||
|
|
||||||
if (customFields[fieldKey].type === 'string') {
|
if (customFields[fieldKey].type === 'text') {
|
||||||
return (
|
return (
|
||||||
<EventTextArea
|
<EventTextArea
|
||||||
key={key}
|
key={key}
|
||||||
|
|||||||
+1
-1
@@ -183,7 +183,7 @@ export function makeCuesheetColumns(customFields: CustomFields): ColumnDef<Ontim
|
|||||||
id: key,
|
id: key,
|
||||||
header: customFields[key].label,
|
header: customFields[key].label,
|
||||||
meta: { colour: customFields[key].colour, type: customFields[key].type },
|
meta: { colour: customFields[key].colour, type: customFields[key].type },
|
||||||
cell: customFields[key].type === 'string' ? MakeCustomField : LazyImage,
|
cell: customFields[key].type === 'text' ? MakeCustomField : LazyImage,
|
||||||
size: 250,
|
size: 250,
|
||||||
minSize: 75,
|
minSize: 75,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ describe('parseCustomFields()', () => {
|
|||||||
const errorEmitter = vi.fn();
|
const errorEmitter = vi.fn();
|
||||||
// @ts-expect-error -- data is external, we check bad types
|
// @ts-expect-error -- data is external, we check bad types
|
||||||
const customFields = {
|
const customFields = {
|
||||||
1: { label: 'test', type: 'string', colour: 'red' }, // ok
|
1: { label: 'test', type: 'text', colour: 'red' }, // ok
|
||||||
2: { label: 'test', type: 'string' }, // duplicate label
|
2: { label: 'test', type: 'text' }, // duplicate label
|
||||||
3: { label: '', type: 'string' }, // missing colour
|
3: { label: '', type: 'text' }, // missing colour
|
||||||
4: { type: 'string', colour: '' }, // missing label
|
4: { type: 'text', colour: '' }, // missing label
|
||||||
} as CustomFields;
|
} as CustomFields;
|
||||||
|
|
||||||
const result = parseCustomFields({ customFields }, errorEmitter);
|
const result = parseCustomFields({ customFields }, errorEmitter);
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
test: {
|
test: {
|
||||||
label: 'test',
|
label: 'test',
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -39,9 +39,9 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
|
|
||||||
it('returns an object of valid entries', () => {
|
it('returns an object of valid entries', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
test: { label: 'test', type: 'string', colour: 'red' },
|
test: { label: 'test', type: 'text', colour: 'red' },
|
||||||
test2: { label: 'test2', type: 'string', colour: 'green' },
|
test2: { label: 'test2', type: 'text', colour: 'green' },
|
||||||
Test3: { label: 'Test3', type: 'string', colour: '' },
|
Test3: { label: 'Test3', type: 'text', colour: '' },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual(customFields);
|
expect(sanitationResult).toStrictEqual(customFields);
|
||||||
@@ -51,18 +51,18 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
const testTypes = sanitiseCustomFields({
|
const testTypes = sanitiseCustomFields({
|
||||||
test1: { label: 'test1', type: 'another', colour: 'red' },
|
test1: { label: 'test1', type: 'another', colour: 'red' },
|
||||||
test2: { label: 'test2', type: 'image', colour: 'red' },
|
test2: { label: 'test2', type: 'image', colour: 'red' },
|
||||||
test3: { label: 'test3', type: 'string', colour: 'red' },
|
test3: { label: 'test3', type: 'text', colour: 'red' },
|
||||||
});
|
});
|
||||||
expect(testTypes).toMatchObject({
|
expect(testTypes).toMatchObject({
|
||||||
test2: { label: 'test2', type: 'image', colour: 'red' },
|
test2: { label: 'test2', type: 'image', colour: 'red' },
|
||||||
test3: { label: 'test3', type: 'string', colour: 'red' },
|
test3: { label: 'test3', type: 'text', colour: 'red' },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('colour must be a string', () => {
|
it('colour must be a string', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
// @ts-expect-error intentional bad data
|
// @ts-expect-error intentional bad data
|
||||||
test: { label: 'test', type: 'string', colour: 5 },
|
test: { label: 'test', type: 'text', colour: 5 },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual({});
|
expect(sanitationResult).toStrictEqual({});
|
||||||
@@ -70,7 +70,7 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
|
|
||||||
it('label can not be empty', () => {
|
it('label can not be empty', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
'': { label: '', type: 'string', colour: 'red' },
|
'': { label: '', type: 'text', colour: 'red' },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual({});
|
expect(sanitationResult).toStrictEqual({});
|
||||||
@@ -79,10 +79,10 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
it('remove extra stuff', () => {
|
it('remove extra stuff', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
// @ts-expect-error intentional bad data
|
// @ts-expect-error intentional bad data
|
||||||
test: { label: 'test', type: 'string', colour: 'red', extra: 'should be removed' },
|
test: { label: 'test', type: 'text', colour: 'red', extra: 'should be removed' },
|
||||||
};
|
};
|
||||||
const expectedCustomFields: CustomFields = {
|
const expectedCustomFields: CustomFields = {
|
||||||
test: { label: 'test', type: 'string', colour: 'red' },
|
test: { label: 'test', type: 'text', colour: 'red' },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
||||||
@@ -90,10 +90,10 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
|
|
||||||
it('enforce name cohesion', () => {
|
it('enforce name cohesion', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
test: { label: 'NewName', type: 'string', colour: 'red' },
|
test: { label: 'NewName', type: 'text', colour: 'red' },
|
||||||
};
|
};
|
||||||
const expectedCustomFields: CustomFields = {
|
const expectedCustomFields: CustomFields = {
|
||||||
NewName: { label: 'NewName', type: 'string', colour: 'red' },
|
NewName: { label: 'NewName', type: 'text', colour: 'red' },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
||||||
@@ -101,10 +101,10 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
|
|
||||||
it('labels with space', () => {
|
it('labels with space', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
Test_with_Space: { label: 'Test with Space', type: 'string', colour: 'red' },
|
Test_with_Space: { label: 'Test with Space', type: 'text', colour: 'red' },
|
||||||
};
|
};
|
||||||
const expectedCustomFields: CustomFields = {
|
const expectedCustomFields: CustomFields = {
|
||||||
Test_with_Space: { label: 'Test with Space', type: 'string', colour: 'red' },
|
Test_with_Space: { label: 'Test with Space', type: 'text', colour: 'red' },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
||||||
@@ -112,15 +112,15 @@ describe('sanitiseCustomFields()', () => {
|
|||||||
|
|
||||||
it('filters invalid entries', () => {
|
it('filters invalid entries', () => {
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
test: { label: 'test', type: 'string', colour: 'red' },
|
test: { label: 'test', type: 'text', colour: 'red' },
|
||||||
test2: { label: 'test2', type: 'string', colour: 'green' },
|
test2: { label: 'test2', type: 'text', colour: 'green' },
|
||||||
bad: { label: '', type: 'string', colour: '' },
|
bad: { label: '', type: 'text', colour: '' },
|
||||||
Test3: { label: 'Test3', type: 'string', colour: '' },
|
Test3: { label: 'Test3', type: 'text', colour: '' },
|
||||||
};
|
};
|
||||||
const expectedCustomFields: CustomFields = {
|
const expectedCustomFields: CustomFields = {
|
||||||
test: { label: 'test', type: 'string', colour: 'red' },
|
test: { label: 'test', type: 'text', colour: 'red' },
|
||||||
test2: { label: 'test2', type: 'string', colour: 'green' },
|
test2: { label: 'test2', type: 'text', colour: 'green' },
|
||||||
Test3: { label: 'Test3', type: 'string', colour: '' },
|
Test3: { label: 'Test3', type: 'text', colour: '' },
|
||||||
};
|
};
|
||||||
const sanitationResult = sanitiseCustomFields(customFields);
|
const sanitationResult = sanitiseCustomFields(customFields);
|
||||||
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
expect(sanitationResult).toStrictEqual(expectedCustomFields);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function sanitiseCustomFields(data: object): CustomFields {
|
|||||||
'colour' in data &&
|
'colour' in data &&
|
||||||
typeof data.colour === 'string' &&
|
typeof data.colour === 'string' &&
|
||||||
'type' in data &&
|
'type' in data &&
|
||||||
(data.type === 'string' || data.type === 'image')
|
(data.type === 'text' || data.type === 'image')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const validateCustomField = [
|
|||||||
.custom((value) => {
|
.custom((value) => {
|
||||||
return isAlphanumericWithSpace(value);
|
return isAlphanumericWithSpace(value);
|
||||||
}),
|
}),
|
||||||
body('type').isIn(['string', 'image']),
|
body('type').isIn(['text', 'image']),
|
||||||
body('colour').isString().trim(),
|
body('colour').isString().trim(),
|
||||||
|
|
||||||
requestValidationFunction,
|
requestValidationFunction,
|
||||||
@@ -26,7 +26,7 @@ export const validateEditCustomField = [
|
|||||||
.custom((value) => {
|
.custom((value) => {
|
||||||
return isAlphanumericWithSpace(value);
|
return isAlphanumericWithSpace(value);
|
||||||
}),
|
}),
|
||||||
body('type').isIn(['string', 'image']),
|
body('type').isIn(['text', 'image']),
|
||||||
body('colour').isString().trim(),
|
body('colour').isString().trim(),
|
||||||
|
|
||||||
requestValidationFunction,
|
requestValidationFunction,
|
||||||
|
|||||||
@@ -18,30 +18,30 @@ describe('parseExcel()', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const existingCustomFields: CustomFields = {
|
const existingCustomFields: CustomFields = {
|
||||||
user0: { type: 'string', colour: 'red', label: 'user0' },
|
user0: { type: 'text', colour: 'red', label: 'user0' },
|
||||||
user1: { type: 'string', colour: 'green', label: 'user1' },
|
user1: { type: 'text', colour: 'green', label: 'user1' },
|
||||||
user2: { type: 'string', colour: 'blue', label: 'user2' },
|
user2: { type: 'text', colour: 'blue', label: 'user2' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const parsedData = parseExcel(dataFromExcelTemplate, existingCustomFields, 'testSheet', importMap);
|
const parsedData = parseExcel(dataFromExcelTemplate, existingCustomFields, 'testSheet', importMap);
|
||||||
expect(parsedData.customFields).toStrictEqual({
|
expect(parsedData.customFields).toStrictEqual({
|
||||||
user0: {
|
user0: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'user0',
|
label: 'user0',
|
||||||
},
|
},
|
||||||
user1: {
|
user1: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'green',
|
colour: 'green',
|
||||||
label: 'user1',
|
label: 'user1',
|
||||||
},
|
},
|
||||||
user2: {
|
user2: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'blue',
|
colour: 'blue',
|
||||||
label: 'user2',
|
label: 'user2',
|
||||||
},
|
},
|
||||||
user3: {
|
user3: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'user3',
|
label: 'user3',
|
||||||
},
|
},
|
||||||
@@ -97,12 +97,12 @@ describe('parseExcel()', () => {
|
|||||||
const parsedData = parseExcel(dataFromExcelTemplate, {}, 'testSheet', importMap);
|
const parsedData = parseExcel(dataFromExcelTemplate, {}, 'testSheet', importMap);
|
||||||
expect(parsedData.customFields).toStrictEqual({
|
expect(parsedData.customFields).toStrictEqual({
|
||||||
niu1: {
|
niu1: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'niu1',
|
label: 'niu1',
|
||||||
},
|
},
|
||||||
niu2: {
|
niu2: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'niu2',
|
label: 'niu2',
|
||||||
},
|
},
|
||||||
@@ -448,17 +448,17 @@ describe('getCustomFieldData()', () => {
|
|||||||
const result = getCustomFieldData(importMap, {});
|
const result = getCustomFieldData(importMap, {});
|
||||||
expect(result.mergedCustomFields).toStrictEqual({
|
expect(result.mergedCustomFields).toStrictEqual({
|
||||||
lighting: {
|
lighting: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'lighting',
|
label: 'lighting',
|
||||||
},
|
},
|
||||||
sound: {
|
sound: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'sound',
|
label: 'sound',
|
||||||
},
|
},
|
||||||
video: {
|
video: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'video',
|
label: 'video',
|
||||||
},
|
},
|
||||||
@@ -499,30 +499,30 @@ describe('getCustomFieldData()', () => {
|
|||||||
} as ImportMap;
|
} as ImportMap;
|
||||||
|
|
||||||
const existingCustomFields: CustomFields = {
|
const existingCustomFields: CustomFields = {
|
||||||
lighting: { label: 'lighting', type: 'string', colour: 'red' },
|
lighting: { label: 'lighting', type: 'text', colour: 'red' },
|
||||||
sound: { label: 'sound', type: 'string', colour: 'green' },
|
sound: { label: 'sound', type: 'text', colour: 'green' },
|
||||||
ontime_key: { label: 'ontime key', type: 'string', colour: 'blue' },
|
ontime_key: { label: 'ontime key', type: 'text', colour: 'blue' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = getCustomFieldData(importMap, existingCustomFields);
|
const result = getCustomFieldData(importMap, existingCustomFields);
|
||||||
expect(result.mergedCustomFields).toStrictEqual({
|
expect(result.mergedCustomFields).toStrictEqual({
|
||||||
lighting: {
|
lighting: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'lighting',
|
label: 'lighting',
|
||||||
},
|
},
|
||||||
sound: {
|
sound: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'green',
|
colour: 'green',
|
||||||
label: 'sound',
|
label: 'sound',
|
||||||
},
|
},
|
||||||
video: {
|
video: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'video',
|
label: 'video',
|
||||||
},
|
},
|
||||||
ontime_key: {
|
ontime_key: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'blue',
|
colour: 'blue',
|
||||||
label: 'ontime key',
|
label: 'ontime key',
|
||||||
},
|
},
|
||||||
@@ -550,17 +550,17 @@ describe('getCustomFieldData()', () => {
|
|||||||
const result = getCustomFieldData(importMap, {});
|
const result = getCustomFieldData(importMap, {});
|
||||||
expect(result.mergedCustomFields).toStrictEqual({
|
expect(result.mergedCustomFields).toStrictEqual({
|
||||||
Lighting: {
|
Lighting: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'Lighting',
|
label: 'Lighting',
|
||||||
},
|
},
|
||||||
Sound: {
|
Sound: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'Sound',
|
label: 'Sound',
|
||||||
},
|
},
|
||||||
video: {
|
video: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '',
|
colour: '',
|
||||||
label: 'video',
|
label: 'video',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ export function getCustomFieldData(
|
|||||||
|
|
||||||
// 1. add the custom field to the merged custom fields
|
// 1. add the custom field to the merged custom fields
|
||||||
mergedCustomFields[keyInCustomFields] = {
|
mergedCustomFields[keyInCustomFields] = {
|
||||||
type: 'string', // we currently only support string custom fields
|
type: 'text', // we currently only support text custom fields
|
||||||
colour: maybeExistingColour,
|
colour: maybeExistingColour,
|
||||||
label: ontimeLabel,
|
label: ontimeLabel,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export function makeRundown(patch: Partial<Rundown>): Rundown {
|
|||||||
|
|
||||||
export function makeCustomField(patch: Partial<CustomField>): CustomField {
|
export function makeCustomField(patch: Partial<CustomField>): CustomField {
|
||||||
return {
|
return {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '#000000',
|
colour: '#000000',
|
||||||
label: 'Custom Field',
|
label: 'Custom Field',
|
||||||
...patch,
|
...patch,
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ describe('createTransaction', () => {
|
|||||||
rundown.title = 'Another Title';
|
rundown.title = 'Another Title';
|
||||||
customFields['newField'] = {
|
customFields['newField'] = {
|
||||||
label: 'New Field',
|
label: 'New Field',
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'blue',
|
colour: 'blue',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -524,12 +524,12 @@ describe('processRundown()', () => {
|
|||||||
const customProperties: CustomFields = {
|
const customProperties: CustomFields = {
|
||||||
lighting: {
|
lighting: {
|
||||||
label: 'lighting',
|
label: 'lighting',
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
},
|
},
|
||||||
sound: {
|
sound: {
|
||||||
label: 'sound',
|
label: 'sound',
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -197,12 +197,12 @@ describe('parseRundown()', () => {
|
|||||||
|
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
lighting: {
|
lighting: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'lighting',
|
label: 'lighting',
|
||||||
},
|
},
|
||||||
sound: {
|
sound: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'sound',
|
label: 'sound',
|
||||||
},
|
},
|
||||||
@@ -229,7 +229,7 @@ describe('parseRundown()', () => {
|
|||||||
|
|
||||||
const customFields: CustomFields = {
|
const customFields: CustomFields = {
|
||||||
lighting: {
|
lighting: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'lighting',
|
label: 'lighting',
|
||||||
},
|
},
|
||||||
@@ -308,12 +308,12 @@ describe('handleCustomField()', () => {
|
|||||||
it('creates a map of where custom fields are used', () => {
|
it('creates a map of where custom fields are used', () => {
|
||||||
const customFields = {
|
const customFields = {
|
||||||
lighting: {
|
lighting: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'lighting',
|
label: 'lighting',
|
||||||
},
|
},
|
||||||
sound: {
|
sound: {
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: 'red',
|
colour: 'red',
|
||||||
label: 'sound',
|
label: 'sound',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -121,38 +121,28 @@ export function createTransaction(options: TransactionOptions): Transaction {
|
|||||||
await getDataProvider().setRundown(cachedRundown.id, cachedRundown);
|
await getDataProvider().setRundown(cachedRundown.id, cachedRundown);
|
||||||
});
|
});
|
||||||
|
|
||||||
// increment the revision number
|
// update fields which are agnostic of whether the rundown is processed
|
||||||
cachedRundown.revision = cachedRundown.revision + 1;
|
cachedRundown.revision = cachedRundown.revision + 1;
|
||||||
|
cachedRundown.title = rundown.title;
|
||||||
|
|
||||||
/**
|
|
||||||
* Some mutations do not require processing the rundown
|
|
||||||
* We simply increment the revision and return the rundown
|
|
||||||
*/
|
|
||||||
if (!shouldProcess) {
|
if (!shouldProcess) {
|
||||||
cachedRundown.title = rundown.title;
|
// if we dont need to process, we just reassign the commit data to the cache
|
||||||
cachedRundown.entries = rundown.entries;
|
cachedRundown.entries = rundown.entries;
|
||||||
cachedRundown.order = rundown.order;
|
cachedRundown.order = rundown.order;
|
||||||
cachedRundown.flatOrder = rundown.flatOrder;
|
cachedRundown.flatOrder = rundown.flatOrder;
|
||||||
return {
|
} else {
|
||||||
rundown: cachedRundown,
|
const processedData = processRundown(rundown, projectCustomFields);
|
||||||
rundownMetadata, // metadata doesnt change as long as we dont process the rundown
|
// update the cache values
|
||||||
customFields: projectCustomFields,
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- we are not interested in the iteration data
|
||||||
revision: cachedRundown.revision,
|
const { previousEvent, latestEvent, previousEntry, entries, order, assignedCustomFields, ...metadata } =
|
||||||
};
|
processedData;
|
||||||
|
|
||||||
|
cachedRundown.entries = entries;
|
||||||
|
cachedRundown.order = order;
|
||||||
|
cachedRundown.flatOrder = metadata.flatEntryOrder;
|
||||||
|
customFieldsMetadata.assigned = assignedCustomFields;
|
||||||
|
rundownMetadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
const processedData = processRundown(rundown, projectCustomFields);
|
|
||||||
// update the cache values
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- we are not interested in the iteration data
|
|
||||||
const { previousEvent, latestEvent, previousEntry, entries, order, assignedCustomFields, ...metadata } =
|
|
||||||
processedData;
|
|
||||||
|
|
||||||
cachedRundown.title = rundown.title;
|
|
||||||
cachedRundown.entries = entries;
|
|
||||||
cachedRundown.order = order;
|
|
||||||
cachedRundown.flatOrder = metadata.flatEntryOrder;
|
|
||||||
customFieldsMetadata.assigned = assignedCustomFields;
|
|
||||||
rundownMetadata = metadata;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the customFields are mutable we persist the changes
|
// if the customFields are mutable we persist the changes
|
||||||
|
|||||||
@@ -464,9 +464,14 @@ export async function editCustomField(key: CustomFieldKey, newField: Partial<Cus
|
|||||||
|
|
||||||
const { oldKey, newKey } = customFieldMutation.edit(customFields, key, existingField, newField);
|
const { oldKey, newKey } = customFieldMutation.edit(customFields, key, existingField, newField);
|
||||||
|
|
||||||
// if key has changed we remove the old reference
|
// if key has changed
|
||||||
if (oldKey !== newKey && oldKey in customFieldsMetadata.assigned) {
|
if (oldKey !== newKey) {
|
||||||
customFieldMutation.renameUsages(rundown, customFieldsMetadata.assigned, oldKey, newKey);
|
// 1. delete the old key
|
||||||
|
customFieldMutation.remove(customFields, oldKey);
|
||||||
|
if (oldKey in customFieldsMetadata.assigned) {
|
||||||
|
// 2. reassign references
|
||||||
|
customFieldMutation.renameUsages(rundown, customFieldsMetadata.assigned, oldKey, newKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the custom fields have been removed and there is no processing to be done
|
// the custom fields have been removed and there is no processing to be done
|
||||||
|
|||||||
@@ -101,21 +101,21 @@ describe('safeMerge', () => {
|
|||||||
it('merges customFields into existing object', () => {
|
it('merges customFields into existing object', () => {
|
||||||
const existing = {
|
const existing = {
|
||||||
customFields: {
|
customFields: {
|
||||||
lighting: { type: 'string', label: 'lighting' },
|
lighting: { type: 'text', label: 'lighting' },
|
||||||
sound: { type: 'string', label: 'sound' },
|
sound: { type: 'text', label: 'sound' },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const newData = {
|
const newData = {
|
||||||
customFields: {
|
customFields: {
|
||||||
switcher: { type: 'string', label: 'switcher' },
|
switcher: { type: 'text', label: 'switcher' },
|
||||||
vfx: { type: 'string', label: 'vfx' },
|
vfx: { type: 'text', label: 'vfx' },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
switcher: { type: 'string', label: 'switcher' },
|
switcher: { type: 'text', label: 'switcher' },
|
||||||
vfx: { type: 'string', label: 'vfx' },
|
vfx: { type: 'text', label: 'vfx' },
|
||||||
};
|
};
|
||||||
|
|
||||||
//@ts-expect-error -- testing partial merge
|
//@ts-expect-error -- testing partial merge
|
||||||
|
|||||||
@@ -528,12 +528,12 @@ export const demoDb: DatabaseModel = {
|
|||||||
customFields: {
|
customFields: {
|
||||||
Song: {
|
Song: {
|
||||||
label: 'Song',
|
label: 'Song',
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '#339E4E',
|
colour: '#339E4E',
|
||||||
},
|
},
|
||||||
Artist: {
|
Artist: {
|
||||||
label: 'Artist',
|
label: 'Artist',
|
||||||
type: 'string',
|
type: 'text',
|
||||||
colour: '#3E75E8',
|
colour: '#3E75E8',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -477,12 +477,12 @@
|
|||||||
"customFields": {
|
"customFields": {
|
||||||
"song": {
|
"song": {
|
||||||
"label": "Song",
|
"label": "Song",
|
||||||
"type": "string",
|
"type": "text",
|
||||||
"colour": "#339E4E"
|
"colour": "#339E4E"
|
||||||
},
|
},
|
||||||
"artist": {
|
"artist": {
|
||||||
"label": "Artist",
|
"label": "Artist",
|
||||||
"type": "string",
|
"type": "text",
|
||||||
"colour": "#3E75E8"
|
"colour": "#3E75E8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Vendored
+2
-2
@@ -494,12 +494,12 @@
|
|||||||
"customFields": {
|
"customFields": {
|
||||||
"Song": {
|
"Song": {
|
||||||
"label": "Song",
|
"label": "Song",
|
||||||
"type": "string",
|
"type": "text",
|
||||||
"colour": "#339E4E"
|
"colour": "#339E4E"
|
||||||
},
|
},
|
||||||
"Artist": {
|
"Artist": {
|
||||||
"label": "Artist",
|
"label": "Artist",
|
||||||
"type": "string",
|
"type": "text",
|
||||||
"colour": "#3E75E8"
|
"colour": "#3E75E8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export type CustomFieldKey = string;
|
export type CustomFieldKey = string;
|
||||||
|
|
||||||
export type CustomField = {
|
export type CustomField = {
|
||||||
type: 'string' | 'image';
|
type: 'text' | 'image';
|
||||||
colour: string;
|
colour: string;
|
||||||
label: string;
|
label: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user