fix: fix several field bugs (#5339)
After discussing with @charlesBochet, several fixes are needed on fields: - [x] Disable Boolean field `defaultValue` edition for now (On `defaultValue` update, newly created records are not taking the updated `defaultValue` into account. Setting the `defaultValue` on creation is fine.) - [x] Disable Phone field creation for now - [x] For the Person object, display the "Phone" field as a field of type Phone (right now its type is Text; later we'll migrate it to a proper Phone field). - [x] Fix RawJson field display (displaying `[object Object]` in Record Table cells). - [x] In Settings/Data Model, on Relation field creation/edition, "Object destination" select is not working properly if an object was not manually selected (displays Companies by default but creates a relation to another random object than Companies).
This commit is contained in:
@ -0,0 +1,109 @@
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard';
|
||||
import {
|
||||
SettingsDataModelFieldRelationForm,
|
||||
SettingsDataModelFieldRelationFormValues,
|
||||
} from '@/settings/data-model/components/SettingsObjectFieldRelationForm';
|
||||
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
|
||||
import { useRelationSettingsFormInitialValues } from '@/settings/data-model/fields/forms/hooks/useRelationSettingsFormInitialValues';
|
||||
import {
|
||||
SettingsDataModelFieldPreviewCard,
|
||||
SettingsDataModelFieldPreviewCardProps,
|
||||
} from '@/settings/data-model/fields/preview/components/SettingsDataModelFieldPreviewCard';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
type SettingsDataModelFieldRelationSettingsFormCardProps = {
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'icon' | 'label' | 'type'> &
|
||||
Partial<Omit<FieldMetadataItem, 'icon' | 'label' | 'type'>>;
|
||||
relationFieldMetadataItem?: FieldMetadataItem;
|
||||
} & Pick<SettingsDataModelFieldPreviewCardProps, 'objectMetadataItem'>;
|
||||
|
||||
const StyledFieldPreviewCard = styled(SettingsDataModelFieldPreviewCard)`
|
||||
display: grid;
|
||||
flex: 1 1 100%;
|
||||
`;
|
||||
|
||||
const StyledPreviewContent = styled.div`
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
`;
|
||||
|
||||
const StyledRelationImage = styled.img<{ flip?: boolean }>`
|
||||
transform: ${({ flip }) => (flip ? 'scaleX(-1)' : 'none')};
|
||||
width: 54px;
|
||||
`;
|
||||
|
||||
export const SettingsDataModelFieldRelationSettingsFormCard = ({
|
||||
fieldMetadataItem,
|
||||
objectMetadataItem,
|
||||
}: SettingsDataModelFieldRelationSettingsFormCardProps) => {
|
||||
const { watch: watchFormValue } =
|
||||
useFormContext<SettingsDataModelFieldRelationFormValues>();
|
||||
const { findObjectMetadataItemById } = useFilteredObjectMetadataItems();
|
||||
|
||||
const {
|
||||
initialRelationObjectMetadataItem,
|
||||
initialRelationType,
|
||||
initialRelationFieldMetadataItem,
|
||||
} = useRelationSettingsFormInitialValues({ fieldMetadataItem });
|
||||
|
||||
const relationObjectMetadataId = watchFormValue(
|
||||
'relation.objectMetadataId',
|
||||
initialRelationObjectMetadataItem?.id,
|
||||
);
|
||||
const relationObjectMetadataItem = findObjectMetadataItemById(
|
||||
relationObjectMetadataId,
|
||||
);
|
||||
|
||||
if (!relationObjectMetadataItem) return null;
|
||||
|
||||
const relationType = watchFormValue('relation.type', initialRelationType);
|
||||
const relationTypeConfig = RELATION_TYPES[relationType];
|
||||
|
||||
return (
|
||||
<SettingsDataModelPreviewFormCard
|
||||
preview={
|
||||
<StyledPreviewContent>
|
||||
<StyledFieldPreviewCard
|
||||
fieldMetadataItem={fieldMetadataItem}
|
||||
shrink
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
relationObjectMetadataItem={relationObjectMetadataItem}
|
||||
/>
|
||||
<StyledRelationImage
|
||||
src={relationTypeConfig.imageSrc}
|
||||
flip={relationTypeConfig.isImageFlipped}
|
||||
alt={relationTypeConfig.label}
|
||||
/>
|
||||
<StyledFieldPreviewCard
|
||||
fieldMetadataItem={{
|
||||
...initialRelationFieldMetadataItem,
|
||||
icon: watchFormValue(
|
||||
'relation.field.icon',
|
||||
initialRelationFieldMetadataItem.icon,
|
||||
),
|
||||
label:
|
||||
watchFormValue(
|
||||
'relation.field.label',
|
||||
initialRelationFieldMetadataItem.label,
|
||||
) || 'Field name',
|
||||
type: FieldMetadataType.Relation,
|
||||
}}
|
||||
shrink
|
||||
objectMetadataItem={relationObjectMetadataItem}
|
||||
relationObjectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
</StyledPreviewContent>
|
||||
}
|
||||
form={
|
||||
<SettingsDataModelFieldRelationForm
|
||||
fieldMetadataItem={fieldMetadataItem}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -3,7 +3,6 @@ import styled from '@emotion/styled';
|
||||
import omit from 'lodash.omit';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import {
|
||||
SettingsDataModelFieldBooleanForm,
|
||||
@ -14,16 +13,13 @@ import {
|
||||
SettingsDataModelFieldCurrencyForm,
|
||||
settingsDataModelFieldCurrencyFormSchema,
|
||||
} from '@/settings/data-model/components/SettingsObjectFieldCurrencyForm';
|
||||
import {
|
||||
SettingsDataModelFieldRelationForm,
|
||||
settingsDataModelFieldRelationFormSchema,
|
||||
} from '@/settings/data-model/components/SettingsObjectFieldRelationForm';
|
||||
import { settingsDataModelFieldRelationFormSchema } from '@/settings/data-model/components/SettingsObjectFieldRelationForm';
|
||||
import {
|
||||
SettingsDataModelFieldSelectForm,
|
||||
settingsDataModelFieldSelectFormSchema,
|
||||
} from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
|
||||
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
|
||||
import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
|
||||
import { SettingsDataModelFieldRelationSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldRelationSettingsFormCard';
|
||||
import {
|
||||
SettingsDataModelFieldPreviewCard,
|
||||
SettingsDataModelFieldPreviewCardProps,
|
||||
@ -81,7 +77,6 @@ type SettingsDataModelFieldSettingsFormCardProps = {
|
||||
disableCurrencyForm?: boolean;
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'icon' | 'label' | 'type'> &
|
||||
Partial<Omit<FieldMetadataItem, 'icon' | 'label' | 'type'>>;
|
||||
relationFieldMetadataItem?: FieldMetadataItem;
|
||||
} & Pick<SettingsDataModelFieldPreviewCardProps, 'objectMetadataItem'>;
|
||||
|
||||
const StyledFieldPreviewCard = styled(SettingsDataModelFieldPreviewCard)`
|
||||
@ -94,11 +89,6 @@ const StyledPreviewContent = styled.div`
|
||||
gap: 6px;
|
||||
`;
|
||||
|
||||
const StyledRelationImage = styled.img<{ flip?: boolean }>`
|
||||
transform: ${({ flip }) => (flip ? 'scaleX(-1)' : 'none')};
|
||||
width: 54px;
|
||||
`;
|
||||
|
||||
const previewableTypes = [
|
||||
FieldMetadataType.Boolean,
|
||||
FieldMetadataType.Currency,
|
||||
@ -121,23 +111,20 @@ export const SettingsDataModelFieldSettingsFormCard = ({
|
||||
disableCurrencyForm,
|
||||
fieldMetadataItem,
|
||||
objectMetadataItem,
|
||||
relationFieldMetadataItem,
|
||||
}: SettingsDataModelFieldSettingsFormCardProps) => {
|
||||
const { watch: watchFormValue } =
|
||||
useFormContext<SettingsDataModelFieldSettingsFormValues>();
|
||||
const { findObjectMetadataItemById } = useFilteredObjectMetadataItems();
|
||||
|
||||
if (!previewableTypes.includes(fieldMetadataItem.type)) return null;
|
||||
|
||||
const relationObjectMetadataId = watchFormValue('relation.objectMetadataId');
|
||||
const relationObjectMetadataItem = relationObjectMetadataId
|
||||
? findObjectMetadataItemById(relationObjectMetadataId)
|
||||
: undefined;
|
||||
|
||||
const relationType = watchFormValue('relation.type');
|
||||
const relationTypeConfig = relationType
|
||||
? RELATION_TYPES[relationType]
|
||||
: undefined;
|
||||
if (fieldMetadataItem.type === FieldMetadataType.Relation) {
|
||||
return (
|
||||
<SettingsDataModelFieldRelationSettingsFormCard
|
||||
fieldMetadataItem={fieldMetadataItem}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsDataModelPreviewFormCard
|
||||
@ -145,34 +132,9 @@ export const SettingsDataModelFieldSettingsFormCard = ({
|
||||
<StyledPreviewContent>
|
||||
<StyledFieldPreviewCard
|
||||
fieldMetadataItem={fieldMetadataItem}
|
||||
shrink={fieldMetadataItem.type === FieldMetadataType.Relation}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
relationObjectMetadataItem={relationObjectMetadataItem}
|
||||
selectOptions={watchFormValue('options')}
|
||||
/>
|
||||
{fieldMetadataItem.type === FieldMetadataType.Relation &&
|
||||
!!relationObjectMetadataItem &&
|
||||
!!relationTypeConfig && (
|
||||
<>
|
||||
<StyledRelationImage
|
||||
src={relationTypeConfig.imageSrc}
|
||||
flip={relationTypeConfig.isImageFlipped}
|
||||
alt={relationTypeConfig.label}
|
||||
/>
|
||||
<StyledFieldPreviewCard
|
||||
fieldMetadataItem={{
|
||||
...relationFieldMetadataItem,
|
||||
icon: watchFormValue('relation.field.icon'),
|
||||
label:
|
||||
watchFormValue('relation.field.label') || 'Field name',
|
||||
type: FieldMetadataType.Relation,
|
||||
}}
|
||||
shrink
|
||||
objectMetadataItem={relationObjectMetadataItem}
|
||||
relationObjectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</StyledPreviewContent>
|
||||
}
|
||||
form={
|
||||
@ -185,10 +147,6 @@ export const SettingsDataModelFieldSettingsFormCard = ({
|
||||
disabled={disableCurrencyForm}
|
||||
fieldMetadataItem={fieldMetadataItem}
|
||||
/>
|
||||
) : fieldMetadataItem.type === FieldMetadataType.Relation ? (
|
||||
<SettingsDataModelFieldRelationForm
|
||||
fieldMetadataItem={fieldMetadataItem}
|
||||
/>
|
||||
) : fieldMetadataItem.type === FieldMetadataType.Select ||
|
||||
fieldMetadataItem.type === FieldMetadataType.MultiSelect ? (
|
||||
<SettingsDataModelFieldSelectForm
|
||||
|
||||
@ -7,10 +7,7 @@ import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorato
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockedCompanyObjectMetadataItem,
|
||||
mockedPersonObjectMetadataItem,
|
||||
} from '~/testing/mock-data/metadata';
|
||||
import { mockedCompanyObjectMetadataItem } from '~/testing/mock-data/metadata';
|
||||
|
||||
import { SettingsDataModelFieldSettingsFormCard } from '../SettingsDataModelFieldSettingsFormCard';
|
||||
|
||||
@ -49,9 +46,6 @@ export const WithRelationForm: Story = {
|
||||
fieldMetadataItem: mockedCompanyObjectMetadataItem.fields.find(
|
||||
({ name }) => name === 'people',
|
||||
),
|
||||
relationFieldMetadataItem: mockedPersonObjectMetadataItem.fields.find(
|
||||
({ name }) => name === 'company',
|
||||
)!,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation';
|
||||
import { RelationMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useRelationSettingsFormInitialValues = ({
|
||||
fieldMetadataItem,
|
||||
}: {
|
||||
fieldMetadataItem?: Pick<
|
||||
FieldMetadataItem,
|
||||
'fromRelationMetadata' | 'toRelationMetadata' | 'type'
|
||||
>;
|
||||
}) => {
|
||||
const { objectMetadataItems } = useFilteredObjectMetadataItems();
|
||||
|
||||
const getRelationMetadata = useGetRelationMetadata();
|
||||
const {
|
||||
relationFieldMetadataItem,
|
||||
relationObjectMetadataItem: relationObjectMetadataItemFromFieldMetadata,
|
||||
relationType: relationTypeFromFieldMetadata,
|
||||
} = useMemo(
|
||||
() =>
|
||||
fieldMetadataItem ? getRelationMetadata({ fieldMetadataItem }) : null,
|
||||
[fieldMetadataItem, getRelationMetadata],
|
||||
) ?? {};
|
||||
|
||||
const initialRelationObjectMetadataItem = useMemo(
|
||||
() =>
|
||||
relationObjectMetadataItemFromFieldMetadata ??
|
||||
objectMetadataItems.find(
|
||||
({ nameSingular }) => nameSingular === CoreObjectNameSingular.Person,
|
||||
) ??
|
||||
objectMetadataItems.filter(isObjectMetadataAvailableForRelation)[0],
|
||||
[objectMetadataItems, relationObjectMetadataItemFromFieldMetadata],
|
||||
);
|
||||
|
||||
const initialRelationType =
|
||||
relationTypeFromFieldMetadata ?? RelationMetadataType.OneToMany;
|
||||
|
||||
return {
|
||||
disableFieldEdition:
|
||||
relationFieldMetadataItem && !relationFieldMetadataItem.isCustom,
|
||||
disableRelationEdition: !!relationFieldMetadataItem,
|
||||
initialRelationFieldMetadataItem: relationFieldMetadataItem ?? {
|
||||
icon: initialRelationObjectMetadataItem.icon ?? 'IconUsers',
|
||||
label: '',
|
||||
},
|
||||
initialRelationObjectMetadataItem,
|
||||
initialRelationType,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user