fix: reset default value on field type switch in Settings/Data Model … (#5436)

…field form

Closes #5412
This commit is contained in:
Thaïs
2024-05-22 09:53:15 +02:00
committed by GitHub
parent 48003887ce
commit 944b2b0254
9 changed files with 68 additions and 38 deletions

View File

@ -3,23 +3,23 @@ import omit from 'lodash.omit';
import { z } from 'zod'; import { z } from 'zod';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard';
import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
import { import {
SettingsDataModelFieldBooleanForm, SettingsDataModelFieldBooleanForm,
settingsDataModelFieldBooleanFormSchema, settingsDataModelFieldBooleanFormSchema,
} from '@/settings/data-model/components/SettingsDataModelDefaultValue'; } from '@/settings/data-model/fields/forms/components/boolean/SettingsDataModelFieldBooleanForm';
import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard';
import { settingsDataModelFieldRelationFormSchema } from '@/settings/data-model/components/SettingsObjectFieldRelationForm';
import {
settingsDataModelFieldMultiSelectFormSchema,
settingsDataModelFieldSelectFormSchema,
} from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
import { import {
SettingsDataModelFieldCurrencyForm, SettingsDataModelFieldCurrencyForm,
settingsDataModelFieldCurrencyFormSchema, settingsDataModelFieldCurrencyFormSchema,
} from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldCurrencyForm'; } from '@/settings/data-model/fields/forms/components/currency/SettingsDataModelFieldCurrencyForm';
import { SettingsDataModelFieldRelationSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldRelationSettingsFormCard'; import { settingsDataModelFieldRelationFormSchema } from '@/settings/data-model/fields/forms/components/relation/SettingsDataModelFieldRelationForm';
import { SettingsDataModelFieldSelectSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSelectSettingsFormCard'; import { SettingsDataModelFieldRelationSettingsFormCard } from '@/settings/data-model/fields/forms/components/relation/SettingsDataModelFieldRelationSettingsFormCard';
import {
settingsDataModelFieldMultiSelectFormSchema,
settingsDataModelFieldSelectFormSchema,
} from '@/settings/data-model/fields/forms/components/select/SettingsDataModelFieldSelectForm';
import { SettingsDataModelFieldSelectSettingsFormCard } from '@/settings/data-model/fields/forms/components/select/SettingsDataModelFieldSelectSettingsFormCard';
import { import {
SettingsDataModelFieldPreviewCard, SettingsDataModelFieldPreviewCard,
SettingsDataModelFieldPreviewCardProps, SettingsDataModelFieldPreviewCardProps,

View File

@ -1,3 +1,4 @@
import { useEffect } from 'react';
import { Controller, useFormContext } from 'react-hook-form'; import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { IconCheck, IconX } from 'twenty-ui'; import { IconCheck, IconX } from 'twenty-ui';
@ -8,8 +9,6 @@ import { Select } from '@/ui/input/components/Select';
import { CardContent } from '@/ui/layout/card/components/CardContent'; import { CardContent } from '@/ui/layout/card/components/CardContent';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
// TODO: rename to SettingsDataModelFieldBooleanForm and move to settings/data-model/fields/forms/components
export const settingsDataModelFieldBooleanFormSchema = z.object({ export const settingsDataModelFieldBooleanFormSchema = z.object({
defaultValue: z.boolean(), defaultValue: z.boolean(),
}); });
@ -33,18 +32,23 @@ const StyledLabel = styled.span`
font-size: ${({ theme }) => theme.font.size.xs}; font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold}; font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: 6px; margin-bottom: 6px;
margin-top: ${({ theme }) => theme.spacing(1)};
`; `;
export const SettingsDataModelFieldBooleanForm = ({ export const SettingsDataModelFieldBooleanForm = ({
className, className,
fieldMetadataItem, fieldMetadataItem,
}: SettingsDataModelFieldBooleanFormProps) => { }: SettingsDataModelFieldBooleanFormProps) => {
const { control } = useFormContext<SettingsDataModelFieldBooleanFormValues>(); const { control, resetField } =
useFormContext<SettingsDataModelFieldBooleanFormValues>();
const isEditMode = isDefined(fieldMetadataItem?.defaultValue); const isEditMode = isDefined(fieldMetadataItem?.defaultValue);
const initialValue = fieldMetadataItem?.defaultValue ?? true; const initialValue = fieldMetadataItem?.defaultValue ?? true;
// Reset defaultValue on mount, so it doesn't conflict with other field types.
useEffect(() => {
resetField('defaultValue', { defaultValue: initialValue });
}, [initialValue, resetField]);
return ( return (
<StyledContainer> <StyledContainer>
<StyledLabel>Default Value</StyledLabel> <StyledLabel>Default Value</StyledLabel>

View File

@ -1,3 +1,4 @@
import { useEffect } from 'react';
import { Controller, useFormContext } from 'react-hook-form'; import { Controller, useFormContext } from 'react-hook-form';
import { z } from 'zod'; import { z } from 'zod';
@ -13,6 +14,7 @@ import { simpleQuotesStringSchema } from '~/utils/validation-schemas/simpleQuote
export const settingsDataModelFieldCurrencyFormSchema = z.object({ export const settingsDataModelFieldCurrencyFormSchema = z.object({
defaultValue: z.object({ defaultValue: z.object({
amountMicros: z.null(),
currencyCode: simpleQuotesStringSchema.refine( currencyCode: simpleQuotesStringSchema.refine(
(value) => (value) =>
currencyCodeSchema.safeParse(stripSimpleQuotesFromString(value)) currencyCodeSchema.safeParse(stripSimpleQuotesFromString(value))
@ -43,19 +45,38 @@ export const SettingsDataModelFieldCurrencyForm = ({
disabled, disabled,
fieldMetadataItem, fieldMetadataItem,
}: SettingsDataModelFieldCurrencyFormProps) => { }: SettingsDataModelFieldCurrencyFormProps) => {
const { control } = const { control, resetField } =
useFormContext<SettingsDataModelFieldCurrencyFormValues>(); useFormContext<SettingsDataModelFieldCurrencyFormValues>();
const initialValue = const initialAmountMicrosValue = null;
const initialCurrencyCode =
(fieldMetadataItem?.defaultValue?.currencyCode as CurrencyCode) ?? (fieldMetadataItem?.defaultValue?.currencyCode as CurrencyCode) ??
CurrencyCode.USD; CurrencyCode.USD;
const initialCurrencyCodeValue =
applySimpleQuotesToString(initialCurrencyCode);
// Reset defaultValue on mount, so it doesn't conflict with other field types.
useEffect(() => {
resetField('defaultValue', {
defaultValue: {
amountMicros: initialAmountMicrosValue,
currencyCode: initialCurrencyCodeValue,
},
});
}, [initialCurrencyCodeValue, resetField]);
return ( return (
<CardContent> <CardContent>
<Controller
name="defaultValue.amountMicros"
control={control}
defaultValue={initialAmountMicrosValue}
render={() => <></>}
/>
<Controller <Controller
name="defaultValue.currencyCode" name="defaultValue.currencyCode"
control={control} control={control}
defaultValue={applySimpleQuotesToString(initialValue)} defaultValue={initialCurrencyCodeValue}
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<Select <Select
fullWidth fullWidth

View File

@ -7,16 +7,13 @@ import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilte
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation'; import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation';
import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema'; import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema';
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
import { useRelationSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useRelationSettingsFormInitialValues'; import { useRelationSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useRelationSettingsFormInitialValues';
import { RelationType } from '@/settings/data-model/types/RelationType';
import { IconPicker } from '@/ui/input/components/IconPicker'; import { IconPicker } from '@/ui/input/components/IconPicker';
import { Select } from '@/ui/input/components/Select'; import { Select } from '@/ui/input/components/Select';
import { TextInput } from '@/ui/input/components/TextInput'; import { TextInput } from '@/ui/input/components/TextInput';
import { RELATION_TYPES } from '../constants/RelationTypes';
import { RelationType } from '../types/RelationType';
// TODO: rename to SettingsDataModelFieldRelationForm and move to settings/data-model/fields/forms/components
export const settingsDataModelFieldRelationFormSchema = z.object({ export const settingsDataModelFieldRelationFormSchema = z.object({
relation: z.object({ relation: z.object({
field: fieldMetadataItemSchema.pick({ field: fieldMetadataItemSchema.pick({

View File

@ -4,11 +4,11 @@ import styled from '@emotion/styled';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard'; import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard';
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
import { import {
SettingsDataModelFieldRelationForm, SettingsDataModelFieldRelationForm,
SettingsDataModelFieldRelationFormValues, SettingsDataModelFieldRelationFormValues,
} from '@/settings/data-model/components/SettingsObjectFieldRelationForm'; } from '@/settings/data-model/fields/forms/components/relation/SettingsDataModelFieldRelationForm';
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
import { useRelationSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useRelationSettingsFormInitialValues'; import { useRelationSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useRelationSettingsFormInitialValues';
import { import {
SettingsDataModelFieldPreviewCard, SettingsDataModelFieldPreviewCard,

View File

@ -1,3 +1,4 @@
import { useEffect } from 'react';
import { Controller, useFormContext } from 'react-hook-form'; import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { DropResult } from '@hello-pangea/dnd'; import { DropResult } from '@hello-pangea/dnd';
@ -23,9 +24,7 @@ import { toSpliced } from '~/utils/array/toSpliced';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString'; import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
import { simpleQuotesStringSchema } from '~/utils/validation-schemas/simpleQuotesStringSchema'; import { simpleQuotesStringSchema } from '~/utils/validation-schemas/simpleQuotesStringSchema';
import { SettingsObjectFieldSelectFormOptionRow } from './SettingsObjectFieldSelectFormOptionRow'; import { SettingsDataModelFieldSelectFormOptionRow } from './SettingsDataModelFieldSelectFormOptionRow';
// TODO: rename to SettingsDataModelFieldSelectForm and move to settings/data-model/fields/forms/components
export const settingsDataModelFieldSelectFormSchema = z.object({ export const settingsDataModelFieldSelectFormSchema = z.object({
defaultValue: simpleQuotesStringSchema.nullable(), defaultValue: simpleQuotesStringSchema.nullable(),
@ -87,6 +86,7 @@ export const SettingsDataModelFieldSelectForm = ({
setValue: setFormValue, setValue: setFormValue,
watch: watchFormValue, watch: watchFormValue,
getValues, getValues,
resetField,
} = useFormContext<SettingsDataModelFieldSelectFormValues>(); } = useFormContext<SettingsDataModelFieldSelectFormValues>();
const handleDragEnd = ( const handleDragEnd = (
@ -168,6 +168,11 @@ export const SettingsDataModelFieldSelectForm = ({
} }
}; };
// Reset defaultValue on mount or on field type change, so it doesn't conflict with other field types.
useEffect(() => {
resetField('defaultValue', { defaultValue: initialDefaultValue });
}, [initialDefaultValue, initialOptions, resetField, fieldMetadataItem.type]);
return ( return (
<> <>
<Controller <Controller
@ -195,7 +200,7 @@ export const SettingsDataModelFieldSelectForm = ({
index={index} index={index}
isDragDisabled={options.length === 1} isDragDisabled={options.length === 1}
itemComponent={ itemComponent={
<SettingsObjectFieldSelectFormOptionRow <SettingsDataModelFieldSelectFormOptionRow
key={option.id} key={option.id}
option={option} option={option}
onChange={(nextOption) => { onChange={(nextOption) => {

View File

@ -23,7 +23,7 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemSelectColor } from '@/ui/navigation/menu-item/components/MenuItemSelectColor'; import { MenuItemSelectColor } from '@/ui/navigation/menu-item/components/MenuItemSelectColor';
import { MAIN_COLOR_NAMES } from '@/ui/theme/constants/MainColorNames'; import { MAIN_COLOR_NAMES } from '@/ui/theme/constants/MainColorNames';
type SettingsObjectFieldSelectFormOptionRowProps = { type SettingsDataModelFieldSelectFormOptionRowProps = {
className?: string; className?: string;
isDefault?: boolean; isDefault?: boolean;
onChange: (value: FieldMetadataItemOption) => void; onChange: (value: FieldMetadataItemOption) => void;
@ -55,7 +55,7 @@ const StyledOptionInput = styled(TextInput)`
} }
`; `;
export const SettingsObjectFieldSelectFormOptionRow = ({ export const SettingsDataModelFieldSelectFormOptionRow = ({
className, className,
isDefault, isDefault,
onChange, onChange,
@ -63,7 +63,7 @@ export const SettingsObjectFieldSelectFormOptionRow = ({
onSetAsDefault, onSetAsDefault,
onRemoveAsDefault, onRemoveAsDefault,
option, option,
}: SettingsObjectFieldSelectFormOptionRowProps) => { }: SettingsDataModelFieldSelectFormOptionRowProps) => {
const theme = useTheme(); const theme = useTheme();
const dropdownIds = useMemo(() => { const dropdownIds = useMemo(() => {

View File

@ -8,7 +8,7 @@ import {
settingsDataModelFieldMultiSelectFormSchema, settingsDataModelFieldMultiSelectFormSchema,
SettingsDataModelFieldSelectForm, SettingsDataModelFieldSelectForm,
settingsDataModelFieldSelectFormSchema, settingsDataModelFieldSelectFormSchema,
} from '@/settings/data-model/components/SettingsObjectFieldSelectForm'; } from '@/settings/data-model/fields/forms/components/select/SettingsDataModelFieldSelectForm';
import { useSelectSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useSelectSettingsFormInitialValues'; import { useSelectSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useSelectSettingsFormInitialValues';
import { import {
SettingsDataModelFieldPreviewCard, SettingsDataModelFieldPreviewCard,

View File

@ -1,3 +1,5 @@
import { isString } from '@sniptt/guards';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
@ -23,17 +25,18 @@ export const getFieldDefaultPreviewValue = ({
relationObjectMetadataItem?: ObjectMetadataItem; relationObjectMetadataItem?: ObjectMetadataItem;
}) => { }) => {
if (fieldMetadataItem.type === FieldMetadataType.Select) { if (fieldMetadataItem.type === FieldMetadataType.Select) {
const defaultValue = fieldMetadataItem.defaultValue const defaultValue = isString(fieldMetadataItem.defaultValue)
? stripSimpleQuotesFromString(fieldMetadataItem.defaultValue) ? stripSimpleQuotesFromString(fieldMetadataItem.defaultValue)
: null; : null;
return defaultValue ?? fieldMetadataItem.options?.[0]?.value ?? null; return defaultValue ?? fieldMetadataItem.options?.[0]?.value ?? null;
} }
if (fieldMetadataItem.type === FieldMetadataType.MultiSelect) { if (fieldMetadataItem.type === FieldMetadataType.MultiSelect) {
const defaultValues = fieldMetadataItem.defaultValue?.map( const defaultValues = Array.isArray(fieldMetadataItem.defaultValue)
(defaultValue: `'${string}'`) => ? fieldMetadataItem.defaultValue?.map((defaultValue: `'${string}'`) =>
stripSimpleQuotesFromString(defaultValue), stripSimpleQuotesFromString(defaultValue),
); )
: null;
return defaultValues?.length return defaultValues?.length
? defaultValues ? defaultValues
: fieldMetadataItem.options?.map(({ value }) => value) ?? null; : fieldMetadataItem.options?.map(({ value }) => value) ?? null;