mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-16 12:53:32 +00:00
make custom fields case sensitive (#1242)
* remove custom field lowercasing * don't allow custom field form to submit duplicate field * remove unused * update custom field tests * also keep upper case when editing * show key in UI * also kep upper case when creating a new field * fix test * allow old forced case keys to stay as is * allow space * add extension to import * supply initial key to CustomFieldForm * refactor: improve element contrast * refactor: style and composition * consistent use of `customFieldLabelToKey` * fix CopyTag * remove log --------- Co-authored-by: arc-alex <ac@omnivox.dk> Co-authored-by: Carlos Valente <carlosvalente@pm.me>
This commit is contained in:
@@ -85,7 +85,7 @@ export class OscIntegration implements IIntegration<OscSubscription, OSCSettings
|
||||
private initTX(enabledOut: boolean, targetIP: string, portOut: number, subscriptions: OscSubscription[]) {
|
||||
this.initSubscriptions(subscriptions);
|
||||
|
||||
if (!enabledOut && this.enabledOut) {
|
||||
if (!enabledOut) {
|
||||
this.targetIP = targetIP;
|
||||
this.portOut = portOut;
|
||||
this.enabledOut = enabledOut;
|
||||
@@ -104,6 +104,7 @@ export class OscIntegration implements IIntegration<OscSubscription, OSCSettings
|
||||
|
||||
try {
|
||||
this.oscClient = new Client(targetIP, portOut);
|
||||
logger.info(LogOrigin.Tx, `Starting OSC Clint on port: ${portOut}`);
|
||||
} catch (error) {
|
||||
this.oscClient = null;
|
||||
throw new Error(`Failed initialising OSC client: ${error}`);
|
||||
@@ -111,7 +112,7 @@ export class OscIntegration implements IIntegration<OscSubscription, OSCSettings
|
||||
}
|
||||
|
||||
private initRX(enabledIn: boolean, portIn: number) {
|
||||
if (!enabledIn && this.enabledIn) {
|
||||
if (!enabledIn) {
|
||||
this.shutdownRX();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -925,7 +925,7 @@ describe('custom fields', () => {
|
||||
describe('createCustomField()', () => {
|
||||
it('creates a field from given parameters', async () => {
|
||||
const expected = {
|
||||
lighting: {
|
||||
Lighting: {
|
||||
label: 'Lighting',
|
||||
type: 'string',
|
||||
colour: 'blue',
|
||||
@@ -942,19 +942,19 @@ describe('custom fields', () => {
|
||||
await createCustomField({ label: 'Sound', type: 'string', colour: 'blue' });
|
||||
|
||||
const expected = {
|
||||
lighting: {
|
||||
Lighting: {
|
||||
label: 'Lighting',
|
||||
type: 'string',
|
||||
colour: 'blue',
|
||||
},
|
||||
sound: {
|
||||
Sound: {
|
||||
label: 'Sound',
|
||||
type: 'string',
|
||||
colour: 'green',
|
||||
},
|
||||
};
|
||||
|
||||
const customField = await editCustomField('sound', { label: 'Sound', type: 'string', colour: 'green' });
|
||||
const customField = await editCustomField('Sound', { label: 'Sound', type: 'string', colour: 'green' });
|
||||
expect(customFieldChangelog).toStrictEqual(new Map());
|
||||
|
||||
expect(customField).toStrictEqual(expected);
|
||||
@@ -964,17 +964,17 @@ describe('custom fields', () => {
|
||||
const created = await createCustomField({ label: 'Video', type: 'string', colour: 'red' });
|
||||
|
||||
const expected = {
|
||||
lighting: {
|
||||
Lighting: {
|
||||
label: 'Lighting',
|
||||
type: 'string',
|
||||
colour: 'blue',
|
||||
},
|
||||
sound: {
|
||||
Sound: {
|
||||
label: 'Sound',
|
||||
type: 'string',
|
||||
colour: 'green',
|
||||
},
|
||||
video: {
|
||||
Video: {
|
||||
label: 'Video',
|
||||
type: 'string',
|
||||
colour: 'red',
|
||||
@@ -984,17 +984,17 @@ describe('custom fields', () => {
|
||||
expect(created).toStrictEqual(expected);
|
||||
|
||||
const expectedAfter = {
|
||||
lighting: {
|
||||
Lighting: {
|
||||
label: 'Lighting',
|
||||
type: 'string',
|
||||
colour: 'blue',
|
||||
},
|
||||
sound: {
|
||||
Sound: {
|
||||
label: 'Sound',
|
||||
type: 'string',
|
||||
colour: 'green',
|
||||
},
|
||||
av: {
|
||||
AV: {
|
||||
label: 'AV',
|
||||
type: 'string',
|
||||
colour: 'red',
|
||||
@@ -1003,10 +1003,10 @@ describe('custom fields', () => {
|
||||
|
||||
// We need to flush all scheduled tasks for the generate function to settle
|
||||
vi.useFakeTimers();
|
||||
const customField = await editCustomField('video', { label: 'AV', type: 'string', colour: 'red' });
|
||||
const customField = await editCustomField('Video', { label: 'AV', type: 'string', colour: 'red' });
|
||||
expect(customField).toStrictEqual(expectedAfter);
|
||||
expect(customFieldChangelog).toStrictEqual(new Map([['video', 'av']]));
|
||||
await editCustomField('av', { label: 'video' });
|
||||
expect(customFieldChangelog).toStrictEqual(new Map([['Video', 'AV']]));
|
||||
await editCustomField('AV', { label: 'Video' });
|
||||
vi.runAllTimers();
|
||||
expect(customFieldChangelog).toStrictEqual(new Map());
|
||||
vi.useRealTimers();
|
||||
@@ -1016,19 +1016,19 @@ describe('custom fields', () => {
|
||||
describe('removeCustomField()', () => {
|
||||
it('deletes a field with a given label', async () => {
|
||||
const expected = {
|
||||
lighting: {
|
||||
Lighting: {
|
||||
label: 'Lighting',
|
||||
type: 'string',
|
||||
colour: 'blue',
|
||||
},
|
||||
video: {
|
||||
label: 'video',
|
||||
Video: {
|
||||
label: 'Video',
|
||||
type: 'string',
|
||||
colour: 'red',
|
||||
},
|
||||
};
|
||||
|
||||
const customField = await removeCustomField('sound');
|
||||
const customField = await removeCustomField('Sound');
|
||||
|
||||
expect(customField).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,15 @@ import {
|
||||
OntimeRundownEntry,
|
||||
PlayableEvent,
|
||||
} from 'ontime-types';
|
||||
import { generateId, insertAtIndex, reorderArray, swapEventData, getTimeFromPrevious, isNewLatest } from 'ontime-utils';
|
||||
import {
|
||||
generateId,
|
||||
insertAtIndex,
|
||||
reorderArray,
|
||||
swapEventData,
|
||||
getTimeFromPrevious,
|
||||
isNewLatest,
|
||||
customFieldLabelToKey,
|
||||
} from 'ontime-utils';
|
||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||
import { createPatch } from '../../utils/parser.js';
|
||||
import { apply } from './delayUtils.js';
|
||||
@@ -447,7 +455,7 @@ function scheduleCustomFieldPersist(persistedCustomFields: CustomFields) {
|
||||
*/
|
||||
export const createCustomField = async (field: CustomField) => {
|
||||
const { label, type, colour } = field;
|
||||
const key = label.toLowerCase();
|
||||
const key = customFieldLabelToKey(label);
|
||||
// check if label already exists
|
||||
const alreadyExists = Object.hasOwn(persistedCustomFields, key);
|
||||
|
||||
@@ -479,7 +487,7 @@ export const editCustomField = async (key: string, newField: Partial<CustomField
|
||||
throw new Error('Change of field type is not allowed');
|
||||
}
|
||||
|
||||
const newKey = newField.label.toLowerCase();
|
||||
const newKey = customFieldLabelToKey(newField.label);
|
||||
persistedCustomFields[newKey] = { ...existingField, ...newField };
|
||||
|
||||
if (key !== newKey) {
|
||||
|
||||
Reference in New Issue
Block a user