#6094 Prevent creating a custom field with an existing name (#6100)

Fixes #6094 
Description: Added logic inside SettingsObjectNewFieldStep2.tsx to
prevent form submission
Current Behaviours:
<img width="947" alt="Screenshot 2024-07-03 at 1 45 31 PM"
src="https://github.com/twentyhq/twenty/assets/95612797/bef54bc4-fc83-48f3-894a-34445ec64723">

---------

Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu>
This commit is contained in:
Deval Minocha
2024-07-17 15:13:57 +05:30
committed by GitHub
parent 37ae99390e
commit 94c2358c89
11 changed files with 212 additions and 151 deletions

View File

@ -1,22 +1,27 @@
import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { Controller, useFormContext } from 'react-hook-form';
import { z } from 'zod';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema';
import { getErrorMessageFromError } from '@/settings/data-model/fields/forms/utils/errorMessages';
import { IconPicker } from '@/ui/input/components/IconPicker';
import { TextArea } from '@/ui/input/components/TextArea';
import { TextInput } from '@/ui/input/components/TextInput';
export const settingsDataModelFieldAboutFormSchema =
fieldMetadataItemSchema.pick({
export const settingsDataModelFieldAboutFormSchema = (
existingLabels?: string[],
) => {
return fieldMetadataItemSchema(existingLabels || []).pick({
description: true,
icon: true,
label: true,
});
};
// Correctly infer the type from the returned schema
type SettingsDataModelFieldAboutFormValues = z.infer<
typeof settingsDataModelFieldAboutFormSchema
ReturnType<typeof settingsDataModelFieldAboutFormSchema>
>;
type SettingsDataModelFieldAboutFormProps = {
@ -32,13 +37,18 @@ const StyledInputsContainer = styled.div`
width: 100%;
`;
const LABEL = 'label';
export const SettingsDataModelFieldAboutForm = ({
disabled,
fieldMetadataItem,
maxLength,
}: SettingsDataModelFieldAboutFormProps) => {
const { control } = useFormContext<SettingsDataModelFieldAboutFormValues>();
const {
control,
trigger,
formState: { errors },
} = useFormContext<SettingsDataModelFieldAboutFormValues>();
return (
<>
<StyledInputsContainer>
@ -56,14 +66,18 @@ export const SettingsDataModelFieldAboutForm = ({
)}
/>
<Controller
name="label"
name={LABEL}
control={control}
defaultValue={fieldMetadataItem?.label}
render={({ field: { onChange, value } }) => (
<TextInput
placeholder="Employees"
value={value}
onChange={onChange}
onChange={(e) => {
onChange(e);
trigger(LABEL);
}}
error={getErrorMessageFromError(errors.label?.message)}
disabled={disabled}
maxLength={maxLength}
fullWidth

View File

@ -17,7 +17,7 @@ import { TextInput } from '@/ui/input/components/TextInput';
export const settingsDataModelFieldRelationFormSchema = z.object({
relation: z.object({
field: fieldMetadataItemSchema.pick({
field: fieldMetadataItemSchema().pick({
icon: true,
label: true,
}),

View File

@ -0,0 +1,18 @@
export enum errors {
LabelNotUnique = 'LABEL_NOT_UNIQUE',
LabelNotFormattable = 'LABEL_NOT_FORMATTABLE',
LabelEmpty = 'LABEL_EMPTY',
}
export const getErrorMessageFromError = (error?: string) => {
switch (error) {
case errors.LabelEmpty:
return 'Name cannot be empty.';
case errors.LabelNotFormattable:
return 'Name should start with a letter.';
case errors.LabelNotUnique:
return 'This name is already used.';
default:
return '';
}
};

View File

@ -4,8 +4,10 @@ import { settingsDataModelFieldAboutFormSchema } from '@/settings/data-model/fie
import { settingsDataModelFieldSettingsFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
import { settingsDataModelFieldTypeFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect';
export const settingsFieldFormSchema = z
.object({})
.merge(settingsDataModelFieldAboutFormSchema)
.merge(settingsDataModelFieldTypeFormSchema)
.and(settingsDataModelFieldSettingsFormSchema);
export const settingsFieldFormSchema = (existingLabels?: string[]) => {
return z
.object({})
.merge(settingsDataModelFieldAboutFormSchema(existingLabels))
.merge(settingsDataModelFieldTypeFormSchema)
.and(settingsDataModelFieldSettingsFormSchema);
};