Skip to content

Commit

Permalink
refactor: use react-hook-form for Field type config forms (#5326)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
thaisguigon committed May 7, 2024
1 parent b7a2e72 commit bb995d5
Show file tree
Hide file tree
Showing 34 changed files with 710 additions and 1,064 deletions.
2 changes: 2 additions & 0 deletions packages/twenty-front/src/generated-metadata/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,9 @@ export type User = {
id: Scalars['UUID']['output'];
lastName: Scalars['String']['output'];
passwordHash?: Maybe<Scalars['String']['output']>;
/** @deprecated field migrated into the AppTokens Table ref: https://github.com/twentyhq/twenty/issues/5021 */
passwordResetToken?: Maybe<Scalars['String']['output']>;
/** @deprecated field migrated into the AppTokens Table ref: https://github.com/twentyhq/twenty/issues/5021 */
passwordResetTokenExpiresAt?: Maybe<Scalars['DateTime']['output']>;
supportUserHash?: Maybe<Scalars['String']['output']>;
updatedAt: Scalars['DateTime']['output'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => (
Expand Down Expand Up @@ -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,
});
});
});
});
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 ?? '',
});
};

Expand All @@ -92,6 +51,5 @@ export const useFieldMetadataItem = () => {
createMetadataField,
disableMetadataField,
eraseMetadataField,
editMetadataField,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe('formatFieldMetadataItemInput', () => {
value: 'OPTION_2',
},
],
defaultValue: 'OPTION_1',
defaultValue: "'OPTION_1'",
};

const result = formatFieldMetadataItemInput(input);
Expand Down Expand Up @@ -140,7 +140,7 @@ describe('formatFieldMetadataItemInput', () => {
value: 'OPTION_2',
},
],
defaultValue: ['OPTION_1', 'OPTION_2'],
defaultValue: ["'OPTION_1'", "'OPTION_2'"],
};

const result = formatFieldMetadataItemInput(input);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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;
}

Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}'`);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const MultiSelectFieldDisplay = ({
const { fieldValues, fieldDefinition } = useMultiSelectField();

const selectedOptions = fieldValues
? fieldDefinition.metadata.options.filter((option) =>
? fieldDefinition.metadata.options?.filter((option) =>
fieldValues.includes(option.value),
)
: [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import { useRelationField } from '../../hooks/useRelationField';
export const RelationFieldDisplay = () => {
const { fieldValue, fieldDefinition, maxWidth } = useRelationField();

if (!fieldValue || !fieldDefinition) return null;
if (
!fieldValue ||
!fieldDefinition?.metadata.relationObjectMetadataNameSingular
)
return null;

return (
<RecordChip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useSelectField } from '../../hooks/useSelectField';
export const SelectFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useSelectField();

const selectedOption = fieldDefinition.metadata.options.find(
const selectedOption = fieldDefinition.metadata.options?.find(
(option) => option.value === fieldValue,
);

Expand Down

0 comments on commit bb995d5

Please sign in to comment.