refactor: use react-hook-form for Field type config forms (#5326)
Closes #4295 Note: for the sake of an easier code review, I did not rename/move some files and added "todo" comments instead so Github is able to match those files with their previous version.
This commit is contained in:
@ -69,18 +69,7 @@ export const variables = {
|
||||
disableMetadataField: {
|
||||
idToUpdate: fieldId,
|
||||
updatePayload: { isActive: false, label: undefined },
|
||||
},
|
||||
editMetadataField: {
|
||||
idToUpdate: '2c43466a-fe9e-4005-8d08-c5836067aa6c',
|
||||
updatePayload: {
|
||||
defaultValue: undefined,
|
||||
description: null,
|
||||
icon: undefined,
|
||||
label: 'New label',
|
||||
name: 'newLabel',
|
||||
options: undefined,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const defaultResponseData = {
|
||||
|
||||
@ -68,17 +68,6 @@ const mocks = [
|
||||
},
|
||||
})),
|
||||
},
|
||||
{
|
||||
request: {
|
||||
query: queries.activateMetadataField,
|
||||
variables: variables.editMetadataField,
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
updateOneField: responseData.default,
|
||||
},
|
||||
})),
|
||||
},
|
||||
];
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
@ -149,22 +138,4 @@ describe('useFieldMetadataItem', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should editMetadataField', async () => {
|
||||
const { result } = renderHook(() => useFieldMetadataItem(), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
const res = await result.current.editMetadataField({
|
||||
id: fieldMetadataItem.id,
|
||||
label: 'New label',
|
||||
type: FieldMetadataType.Text,
|
||||
});
|
||||
|
||||
expect(res.data).toEqual({
|
||||
updateOneField: responseData.default,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { FieldMetadataOption } from '@/object-metadata/types/FieldMetadataOption';
|
||||
import { getDefaultValueForBackend } from '@/object-metadata/utils/getDefaultValueForBackend';
|
||||
import { Field } from '~/generated/graphql';
|
||||
|
||||
import { FieldMetadataItem } from '../types/FieldMetadataItem';
|
||||
@ -26,49 +22,12 @@ export const useFieldMetadataItem = () => {
|
||||
) => {
|
||||
const formattedInput = formatFieldMetadataItemInput(input);
|
||||
|
||||
const defaultValue = getDefaultValueForBackend(
|
||||
input.defaultValue ?? formattedInput.defaultValue,
|
||||
input.type,
|
||||
);
|
||||
|
||||
return createOneFieldMetadataItem({
|
||||
...formattedInput,
|
||||
defaultValue,
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
type: input.type,
|
||||
});
|
||||
};
|
||||
|
||||
const editMetadataField = (
|
||||
input: Pick<
|
||||
Field,
|
||||
| 'id'
|
||||
| 'label'
|
||||
| 'icon'
|
||||
| 'description'
|
||||
| 'defaultValue'
|
||||
| 'type'
|
||||
| 'options'
|
||||
>,
|
||||
) => {
|
||||
// In Edit mode, all options need an id,
|
||||
// so we generate an id for newly created options.
|
||||
const inputOptions = input.options?.map((option: FieldMetadataOption) =>
|
||||
option.id ? option : { ...option, id: v4() },
|
||||
);
|
||||
const formattedInput = formatFieldMetadataItemInput({
|
||||
...input,
|
||||
options: inputOptions,
|
||||
});
|
||||
|
||||
const defaultValue = input.defaultValue ?? formattedInput.defaultValue;
|
||||
|
||||
return updateOneFieldMetadataItem({
|
||||
fieldMetadataIdToUpdate: input.id,
|
||||
updatePayload: {
|
||||
...formattedInput,
|
||||
defaultValue,
|
||||
},
|
||||
label: formattedInput.label ?? '',
|
||||
name: formattedInput.name ?? '',
|
||||
});
|
||||
};
|
||||
|
||||
@ -92,6 +51,5 @@ export const useFieldMetadataItem = () => {
|
||||
createMetadataField,
|
||||
disableMetadataField,
|
||||
eraseMetadataField,
|
||||
editMetadataField,
|
||||
};
|
||||
};
|
||||
|
||||
@ -12,7 +12,14 @@ import { FieldMetadataItem } from '../types/FieldMetadataItem';
|
||||
export const useGetRelationMetadata = () =>
|
||||
useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
({ fieldMetadataItem }: { fieldMetadataItem: FieldMetadataItem }) => {
|
||||
({
|
||||
fieldMetadataItem,
|
||||
}: {
|
||||
fieldMetadataItem: Pick<
|
||||
FieldMetadataItem,
|
||||
'fromRelationMetadata' | 'toRelationMetadata' | 'type'
|
||||
>;
|
||||
}) => {
|
||||
if (fieldMetadataItem.type !== FieldMetadataType.Relation) return null;
|
||||
|
||||
const relationMetadata =
|
||||
|
||||
@ -77,7 +77,7 @@ describe('formatFieldMetadataItemInput', () => {
|
||||
value: 'OPTION_2',
|
||||
},
|
||||
],
|
||||
defaultValue: 'OPTION_1',
|
||||
defaultValue: "'OPTION_1'",
|
||||
};
|
||||
|
||||
const result = formatFieldMetadataItemInput(input);
|
||||
@ -140,7 +140,7 @@ describe('formatFieldMetadataItemInput', () => {
|
||||
value: 'OPTION_2',
|
||||
},
|
||||
],
|
||||
defaultValue: ['OPTION_1', 'OPTION_2'],
|
||||
defaultValue: ["'OPTION_1'", "'OPTION_2'"],
|
||||
};
|
||||
|
||||
const result = formatFieldMetadataItemInput(input);
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import { validateMetadataLabel } from '@/object-metadata/utils/validateMetadataLabel';
|
||||
|
||||
describe('validateMetadataLabel', () => {
|
||||
it('should work as expected', () => {
|
||||
const res = validateMetadataLabel('Pipeline Step');
|
||||
expect(res).toBe(true);
|
||||
});
|
||||
});
|
||||
@ -1,6 +1,8 @@
|
||||
import toSnakeCase from 'lodash.snakecase';
|
||||
|
||||
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getDefaultValueForBackend } from '@/object-metadata/utils/getDefaultValueForBackend';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { formatMetadataLabelToMetadataNameOrThrows } from '~/pages/settings/data-model/utils/format-metadata-label-to-name.util';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
@ -21,25 +23,24 @@ export const getOptionValueFromLabel = (label: string) => {
|
||||
};
|
||||
|
||||
export const formatFieldMetadataItemInput = (
|
||||
input: Pick<
|
||||
Field,
|
||||
'label' | 'icon' | 'description' | 'defaultValue' | 'options'
|
||||
> & { type?: FieldMetadataType },
|
||||
input: Partial<
|
||||
Pick<
|
||||
FieldMetadataItem,
|
||||
'type' | 'label' | 'defaultValue' | 'icon' | 'description'
|
||||
>
|
||||
> & { options?: FieldMetadataOption[] },
|
||||
) => {
|
||||
const options = input.options as FieldMetadataOption[];
|
||||
const options = input.options as FieldMetadataOption[] | undefined;
|
||||
let defaultValue = input.defaultValue;
|
||||
if (input.type === FieldMetadataType.MultiSelect) {
|
||||
const defaultOptions = options?.filter((option) => option.isDefault);
|
||||
if (isDefined(defaultOptions)) {
|
||||
defaultValue = defaultOptions.map(
|
||||
(defaultOption) => `${getOptionValueFromLabel(defaultOption.label)}`,
|
||||
);
|
||||
}
|
||||
defaultValue = options
|
||||
?.filter((option) => option.isDefault)
|
||||
?.map((defaultOption) => getOptionValueFromLabel(defaultOption.label));
|
||||
}
|
||||
if (input.type === FieldMetadataType.Select) {
|
||||
const defaultOption = options?.find((option) => option.isDefault);
|
||||
defaultValue = isDefined(defaultOption)
|
||||
? `${getOptionValueFromLabel(defaultOption.label)}`
|
||||
? getOptionValueFromLabel(defaultOption.label)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
@ -59,12 +60,17 @@ export const formatFieldMetadataItemInput = (
|
||||
}
|
||||
}
|
||||
|
||||
const label = input.label?.trim();
|
||||
|
||||
return {
|
||||
defaultValue,
|
||||
defaultValue:
|
||||
isDefined(defaultValue) && input.type
|
||||
? getDefaultValueForBackend(defaultValue, input.type)
|
||||
: undefined,
|
||||
description: input.description?.trim() ?? null,
|
||||
icon: input.icon,
|
||||
label: input.label.trim(),
|
||||
name: formatMetadataLabelToMetadataNameOrThrows(input.label.trim()),
|
||||
label,
|
||||
name: label ? formatMetadataLabelToMetadataNameOrThrows(label) : undefined,
|
||||
options: options?.map((option, index) => ({
|
||||
color: option.color,
|
||||
id: option.id,
|
||||
|
||||
@ -35,14 +35,14 @@ export const formatRelationMetadataInput = (
|
||||
const {
|
||||
description: fromDescription,
|
||||
icon: fromIcon,
|
||||
label: fromLabel,
|
||||
name: fromName,
|
||||
label: fromLabel = '',
|
||||
name: fromName = '',
|
||||
} = formatFieldMetadataItemInput(fromField);
|
||||
const {
|
||||
description: toDescription,
|
||||
icon: toIcon,
|
||||
label: toLabel,
|
||||
name: toName,
|
||||
label: toLabel = '',
|
||||
name: toName = '',
|
||||
} = formatFieldMetadataItemInput(toField);
|
||||
|
||||
return {
|
||||
|
||||
@ -13,7 +13,7 @@ export const getDefaultValueForBackend = (
|
||||
currencyCode: `'${currencyDefaultValue.currencyCode}'` as CurrencyCode,
|
||||
} satisfies FieldCurrencyValue;
|
||||
} else if (fieldMetadataType === FieldMetadataType.Select) {
|
||||
return `'${defaultValue}'`;
|
||||
return defaultValue ? `'${defaultValue}'` : null;
|
||||
} else if (fieldMetadataType === FieldMetadataType.MultiSelect) {
|
||||
return defaultValue.map((value: string) => `'${value}'`);
|
||||
}
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
const metadataLabelValidationPattern = /^[^0-9].*$/;
|
||||
|
||||
export const validateMetadataLabel = (value: string) =>
|
||||
!!value.match(metadataLabelValidationPattern);
|
||||
Reference in New Issue
Block a user