diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx index 69a4e43499..64f8afeb67 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx @@ -17,6 +17,7 @@ import { moveArrayItem } from '~/utils/array/moveArrayItem'; import { toSpliced } from '~/utils/array/toSpliced'; import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString'; +import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById'; import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsWrapper'; import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; import { useTheme } from '@emotion/react'; @@ -119,6 +120,10 @@ export const SettingsDataModelFieldSelectForm = ({ useSelectSettingsFormInitialValues({ fieldMetadataId: existingFieldMetadataId, }); + const { fieldMetadataItem } = useFieldMetadataItemById( + existingFieldMetadataId, + ); + const isNullable = fieldMetadataItem?.isNullable; const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState); @@ -340,6 +345,7 @@ export const SettingsDataModelFieldSelectForm = ({ onChange(nextOptions); }} isDefault={isOptionDefaultValue(option.value)} + fieldIsNullable={!!isNullable} onSetAsDefault={() => { if (disabled) { return; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx index 8ca14e602a..e43b0b8337 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx @@ -32,6 +32,7 @@ type SettingsDataModelFieldSelectFormOptionRowProps = { onInputEnter?: () => void; option: FieldMetadataItemOption; isNewRow?: boolean; + fieldIsNullable?: boolean; }; const StyledRow = styled.div` @@ -76,6 +77,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({ onInputEnter, option, isNewRow, + fieldIsNullable, }: SettingsDataModelFieldSelectFormOptionRowProps) => { const theme = useTheme(); const SELECT_COLOR_DROPDOWN_ID = `select-color-dropdown-${option.id}`; @@ -84,6 +86,8 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({ const { closeDropdown: closeColorDropdown } = useCloseDropdown(); const { closeDropdown: closeActionsDropdown } = useCloseDropdown(); + const shouldForbidRemoveAsDefault = isDefault && !fieldIsNullable; + const handleInputEnter = () => { onInputEnter?.(); }; @@ -157,43 +161,49 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({ dropdownId={SELECT_ACTIONS_DROPDOWN_ID} dropdownPlacement="right-start" clickableComponent={ - + } dropdownComponents={ - - - {isDefault ? ( - { - onRemoveAsDefault?.(); - closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID); - }} - /> - ) : ( - { - onSetAsDefault?.(); - closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID); - }} - /> - )} - {!!onRemove && !isDefault && ( - { - onRemove(); - closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID); - }} - /> - )} - - + shouldForbidRemoveAsDefault ? null : ( + + + {isDefault ? ( + { + onRemoveAsDefault?.(); + closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID); + }} + /> + ) : ( + { + onSetAsDefault?.(); + closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID); + }} + /> + )} + {!!onRemove && !isDefault && ( + { + onRemove(); + closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID); + }} + /> + )} + + + ) } /> diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts index 6023ca3d9b..66bae5fffa 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts @@ -158,6 +158,17 @@ export class FlatFieldMetadataValidatorService { }); } + if ( + flatFieldMetadataToValidate.isNullable === false && + flatFieldMetadataToValidate.defaultValue === null + ) { + validationResult.errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: 'Default value cannot be null for non-nullable fields', + userFriendlyMessage: msg`Default value cannot be null.`, + }); + } + const fieldMetadataTypeValidationErrors = this.flatFieldMetadataTypeValidatorService.validateFlatFieldMetadataTypeSpecificities( {