diff --git a/packages/twenty-front/src/modules/settings/components/SettingsMorphRelationMultiSelect.tsx b/packages/twenty-front/src/modules/settings/components/SettingsMorphRelationMultiSelect.tsx index 60b2216f52..911f9d58e2 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsMorphRelationMultiSelect.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsMorphRelationMultiSelect.tsx @@ -165,8 +165,8 @@ export const SettingsMorphRelationMultiSelect = ({ {isDisabled ? ( = { Basic: 'All the basic field types you need to start', Advanced: 'More advanced fields for advanced projects', - Relation: 'Create a relation with another object', + Relation: 'Create a relation with other objects', }; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx index 5825202cfb..fb56567b91 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx @@ -15,15 +15,11 @@ import { settingsDataModelFieldCurrencyFormSchema } from '@/settings/data-model/ import { SettingsDataModelFieldCurrencySettingsFormCard } from '@/settings/data-model/fields/forms/currency/components/SettingsDataModelFieldCurrencySettingsFormCard'; import { settingsDataModelFieldDateFormSchema } from '@/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm'; import { SettingsDataModelFieldDateSettingsFormCard } from '@/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateSettingsFormCard'; -import { settingsDataModelFieldMorphRelationFormSchema } from '@/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldMorphRelationForm'; - -import { SettingsDataModelFieldMorphRelationFormCard } from '@/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldMorphRelationFormCard'; +import { settingsDataModelFieldMorphRelationFormSchema } from '@/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldRelationForm'; import { settingsDataModelFieldNumberFormSchema } from '@/settings/data-model/fields/forms/number/components/SettingsDataModelFieldNumberForm'; import { SettingsDataModelFieldNumberSettingsFormCard } from '@/settings/data-model/fields/forms/number/components/SettingsDataModelFieldNumberSettingsFormCard'; import { settingsDataModelFieldPhonesFormSchema } from '@/settings/data-model/fields/forms/phones/components/SettingsDataModelFieldPhonesForm'; import { SettingsDataModelFieldPhonesSettingsFormCard } from '@/settings/data-model/fields/forms/phones/components/SettingsDataModelFieldPhonesSettingsFormCard'; -import { settingsDataModelFieldRelationFormSchema } from '@/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationForm'; -import { SettingsDataModelFieldRelationSettingsFormCard } from '@/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationSettingsFormCard'; import { settingsDataModelFieldMultiSelectFormSchema, settingsDataModelFieldSelectFormSchema, @@ -31,7 +27,9 @@ import { import { SettingsDataModelFieldSelectSettingsFormCard } from '@/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectSettingsFormCard'; import { settingsDataModelFieldMaxValuesSchema } from '@/settings/data-model/fields/forms/utils/settingsDataModelFieldMaxValuesSchema'; import { SettingsDataModelFieldPreviewWidget } from '@/settings/data-model/fields/preview/components/SettingsDataModelFieldPreviewWidget'; + import { Separator } from '@/settings/components/Separator'; +import { SettingsDataModelFieldRelationFormCard } from '@/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldRelationFormCard'; import { useFormContext } from 'react-hook-form'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { type SettingsDataModelFieldEditFormValues } from '~/pages/settings/data-model/SettingsObjectFieldEdit'; @@ -58,12 +56,10 @@ const dateTimeFieldFormSchema = z .extend(settingsDataModelFieldDateFormSchema.shape) .extend(isUniqueFieldFormSchema.shape); -const relationFieldFormSchema = z - .object({ type: z.literal(FieldMetadataType.RELATION) }) - .extend(settingsDataModelFieldRelationFormSchema.shape); - const morphRelationFieldFormSchema = z - .object({ type: z.literal(FieldMetadataType.MORPH_RELATION) }) + .object({ + type: z.literal(FieldMetadataType.MORPH_RELATION), + }) .extend(settingsDataModelFieldMorphRelationFormSchema.shape); const selectFieldFormSchema = z @@ -115,7 +111,6 @@ const otherFieldsFormSchema = z omit(SETTINGS_FIELD_TYPE_CONFIGS, [ FieldMetadataType.BOOLEAN, FieldMetadataType.CURRENCY, - FieldMetadataType.RELATION, FieldMetadataType.MORPH_RELATION, FieldMetadataType.SELECT, FieldMetadataType.MULTI_SELECT, @@ -141,7 +136,6 @@ export const settingsDataModelFieldSettingsFormSchema = z.discriminatedUnion( currencyFieldFormSchema, dateFieldFormSchema, dateTimeFieldFormSchema, - relationFieldFormSchema, morphRelationFieldFormSchema, selectFieldFormSchema, multiSelectFieldFormSchema, @@ -231,19 +225,12 @@ export const SettingsDataModelFieldSettingsFormCard = ({ ); } - if (fieldType === FieldMetadataType.RELATION) { + if ( + fieldType === FieldMetadataType.RELATION || + fieldType === FieldMetadataType.MORPH_RELATION + ) { return ( - - ); - } - - if (fieldType === FieldMetadataType.MORPH_RELATION) { - return ( - {' '} @@ -136,12 +132,18 @@ export const SettingsObjectNewFieldSelector = ({ {fieldTypeConfigs .filter(([, config]) => config.category === category) - .filter(([key]) => { - return ( - key !== FieldMetadataType.MORPH_RELATION || - isMorphRelationEnabled - ); - }) + // by default, we hide the relation type and create only the morph relation type + // on submit the new field, we choose the relation type based on the amount of target object + .filter(([key]) => key !== FieldMetadataType.RELATION) + .map( + ([key, config]) => + [ + key, + key === FieldMetadataType.MORPH_RELATION + ? { ...config, label: 'Relation' } + : config, + ] as [string, SettingsFieldTypeConfig], + ) .map(([key, config]) => ( ` + display: grid; + gap: ${({ theme }) => theme.spacing(4)}; + grid-template-columns: ${({ isMobile }) => (isMobile ? '1fr' : '1fr 1fr')}; + margin-bottom: ${({ theme }) => theme.spacing(4)}; +`; +const StyledInputsLabel = styled.span` + color: ${({ theme }) => theme.font.color.light}; + display: block; + font-size: ${({ theme }) => theme.font.size.xs}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + margin-bottom: ${({ theme }) => theme.spacing(1)}; +`; + +const StyledInputsContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + width: 100%; +`; + +const RELATION_TYPE_OPTIONS = Object.entries(RELATION_TYPES).map( + ([value, { label, Icon }]) => ({ + label, + value: value as RelationType, + Icon, + }), +); export const settingsDataModelFieldMorphRelationFormSchema = z.object({ - morphRelationObjectMetadataIds: z.array(z.uuid()).min(2), + morphRelationObjectMetadataIds: z.array(z.uuid()).min(1), relationType: z.enum( Object.keys(RELATION_TYPES) as [RelationType, ...RelationType[]], ), @@ -37,29 +65,29 @@ export type SettingsDataModelFieldMorphRelationFormValues = z.infer< typeof settingsDataModelFieldMorphRelationFormSchema >; -type SettingsDataModelFieldMorphRelationFormProps = { +type SettingsDataModelFieldRelationFormProps = { existingFieldMetadataId: string; disabled?: boolean; }; -export const SettingsDataModelFieldMorphRelationForm = ({ +export const SettingsDataModelFieldRelationForm = ({ existingFieldMetadataId, disabled = false, -}: SettingsDataModelFieldMorphRelationFormProps) => { +}: SettingsDataModelFieldRelationFormProps) => { const { t } = useLingui(); const { control } = useFormContext(); - + const { getIcon } = useIcons(); const { fieldMetadataItem: existingFieldMetadataItem } = useFieldMetadataItemById(existingFieldMetadataId); const disableRelationEdition = isDefined(existingFieldMetadataItem); - const disableFieldEdition = isDefined(existingFieldMetadataItem) - ? fieldMetadataItemDisableFieldEdition(existingFieldMetadataItem) - : false; + const disableFieldEdition = useFieldMetadataItemDisableFieldEdition( + existingFieldMetadataItem, + ); const initialRelationObjectMetadataItems = - useMorphRelationSettingsFormInitialTargetMetadatas({ + useRelationSettingsFormInitialTargetObjectMetadatas({ fieldMetadataItem: existingFieldMetadataItem, }); @@ -68,7 +96,7 @@ export const SettingsDataModelFieldMorphRelationForm = ({ RelationType.ONE_TO_MANY; const { label: defaultLabelOnDestination, icon: defaultIconOnDestination } = - useMorphRelationSettingsFormDefaultValuesOnDestination({ + useRelationSettingsFormDefaultValuesTargetFieldMetadata({ fieldMetadataItem: existingFieldMetadataItem, objectMetadataItem: initialRelationObjectMetadataItems[0], relationType: initialRelationType, @@ -80,6 +108,12 @@ export const SettingsDataModelFieldMorphRelationForm = ({ ); const isMobile = useIsMobile(); + const isMorphRelationEnabled = useIsFeatureEnabled( + FeatureFlagKey.IS_MORPH_RELATION_ENABLED, + ); + + const { activeObjectMetadataItems } = useFilteredObjectMetadataItems(); + return ( @@ -104,17 +138,40 @@ export const SettingsDataModelFieldMorphRelationForm = ({ name="morphRelationObjectMetadataIds" control={control} defaultValue={initialMorphRelationsObjectMetadataIds} - render={({ field: { onChange, value } }) => ( - - )} + render={({ field: { onChange, value } }) => + isMorphRelationEnabled ? ( + + ) : ( + - )} - /> - ( -