fix relation fields preview in settings (#11745)

Fixes :
- display relation fields in preview settings
- display note and task relation field in preview settings - 
- fix design (align and background color)

closes https://github.com/twentyhq/twenty/issues/7084

---------

Co-authored-by: guillim <guigloo@msn.com>
This commit is contained in:
Etienne
2025-04-25 18:26:27 +02:00
committed by GitHub
parent 11d9d964cc
commit 0b1b81429e
15 changed files with 112 additions and 30 deletions

View File

@ -17,6 +17,7 @@ import {
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import {
FieldMetadataType,
RelationDefinition,
RelationDefinitionType,
} from '~/generated-metadata/graphql';
type SettingsDataModelFieldRelationSettingsFormCardProps = {
@ -80,12 +81,22 @@ export const SettingsDataModelFieldRelationSettingsFormCard = ({
const relationType = watchFormValue('relation.type', initialRelationType);
const relationTypeConfig = RELATION_TYPES[relationType];
const oppositeRelationType =
relationType === RelationDefinitionType.MANY_TO_ONE
? RelationDefinitionType.ONE_TO_MANY
: RelationDefinitionType.MANY_TO_ONE;
return (
<SettingsDataModelPreviewFormCard
preview={
<StyledPreviewContent isMobile={isMobile}>
<StyledFieldPreviewCard
fieldMetadataItem={fieldMetadataItem}
fieldMetadataItem={{
...fieldMetadataItem,
relationDefinition: {
direction: relationType,
} as RelationDefinition,
}}
shrink
objectMetadataItem={objectMetadataItem}
relationObjectMetadataItem={relationObjectMetadataItem}
@ -113,6 +124,9 @@ export const SettingsDataModelFieldRelationSettingsFormCard = ({
initialRelationFieldMetadataItem.label,
) || 'Field name',
type: FieldMetadataType.RELATION,
relationDefinition: {
direction: oppositeRelationType,
} as RelationDefinition,
}}
shrink
objectMetadataItem={relationObjectMetadataItem}

View File

@ -13,13 +13,20 @@ import { SettingsDataModelSetFieldValueEffect } from '@/settings/data-model/fiel
import { SettingsDataModelSetPreviewRecordEffect } from '@/settings/data-model/fields/preview/components/SettingsDataModelSetRecordEffect';
import { useFieldPreviewValue } from '@/settings/data-model/fields/preview/hooks/useFieldPreviewValue';
import { usePreviewRecord } from '@/settings/data-model/fields/preview/hooks/usePreviewRecord';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export type SettingsDataModelFieldPreviewProps = {
fieldMetadataItem: Pick<
FieldMetadataItem,
'icon' | 'label' | 'type' | 'defaultValue' | 'options' | 'settings'
| 'icon'
| 'label'
| 'type'
| 'defaultValue'
| 'options'
| 'settings'
| 'relationDefinition'
> & {
id?: string;
name?: string;
@ -31,7 +38,7 @@ export type SettingsDataModelFieldPreviewProps = {
};
const StyledFieldPreview = styled.div<{ shrink?: boolean }>`
align-items: flex-start;
align-items: center;
background-color: ${({ theme }) => theme.background.primary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
@ -95,7 +102,7 @@ export const SettingsDataModelFieldPreview = ({
fieldMetadataItem.name || `${fieldMetadataItem.type}-new-field`;
const recordId =
previewRecord?.id ??
`${objectMetadataItem.nameSingular}-${fieldName}-preview`;
`${objectMetadataItem.nameSingular}-${fieldName}-${fieldMetadataItem.relationDefinition?.direction}-preview`;
return (
<>
@ -104,7 +111,7 @@ export const SettingsDataModelFieldPreview = ({
instanceId: 'record-field-component-instance-id',
}}
>
{previewRecord ? (
{isDefined(previewRecord) ? (
<SettingsDataModelSetPreviewRecordEffect
fieldName={fieldName}
record={previewRecord}
@ -142,10 +149,11 @@ export const SettingsDataModelFieldPreview = ({
relationObjectMetadataItem?.nameSingular,
options: fieldMetadataItem.options ?? [],
settings: fieldMetadataItem.settings,
relationType: fieldMetadataItem.relationDefinition?.direction,
},
defaultValue: fieldMetadataItem.defaultValue,
},
isReadOnly: false,
isReadOnly: true,
}}
>
{fieldMetadataItem.type === FieldMetadataType.BOOLEAN ? (

View File

@ -92,14 +92,16 @@ describe('useFieldPreviewValue', () => {
);
// Then
expect(result.current).toEqual({
__typename: 'Person',
id: '',
name: {
firstName: 'John',
lastName: 'Doe',
expect(result.current).toEqual([
{
__typename: 'Person',
id: '',
name: {
firstName: 'John',
lastName: 'Doe',
},
},
});
]);
});
it("returns the field's preview value for a Select field", () => {

View File

@ -8,12 +8,15 @@ import { getFieldPreviewValue } from '@/settings/data-model/fields/preview/utils
import { getMultiSelectFieldPreviewValue } from '@/settings/data-model/fields/preview/utils/getMultiSelectFieldPreviewValue';
import { getPhonesFieldPreviewValue } from '@/settings/data-model/fields/preview/utils/getPhonesFieldPreviewValue';
import { getSelectFieldPreviewValue } from '@/settings/data-model/fields/preview/utils/getSelectFieldPreviewValue';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import {
FieldMetadataType,
RelationDefinitionType,
} from '~/generated-metadata/graphql';
type UseFieldPreviewParams = {
fieldMetadataItem: Pick<
FieldMetadataItem,
'type' | 'options' | 'defaultValue'
'type' | 'options' | 'defaultValue' | 'relationDefinition'
>;
relationObjectMetadataItem?: ObjectMetadataItem;
skip?: boolean;
@ -43,7 +46,10 @@ export const useFieldPreviewValue = ({
case FieldMetadataType.CURRENCY:
return getCurrencyFieldPreviewValue({ fieldMetadataItem });
case FieldMetadataType.RELATION:
return relationFieldPreviewValue;
return fieldMetadataItem.relationDefinition?.direction ===
RelationDefinitionType.MANY_TO_ONE
? relationFieldPreviewValue
: [relationFieldPreviewValue];
case FieldMetadataType.SELECT:
return getSelectFieldPreviewValue({ fieldMetadataItem });
case FieldMetadataType.MULTI_SELECT:

View File

@ -1,12 +1,13 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { isFieldValueEmpty } from '@/object-record/record-field/utils/isFieldValueEmpty';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getFieldPreviewValue } from '@/settings/data-model/fields/preview/utils/getFieldPreviewValue';
import { isDefined } from 'twenty-shared/utils';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { pascalCase } from '~/utils/string/pascalCase';
import { isDefined } from 'twenty-shared/utils';
type UsePreviewRecordParams = {
objectMetadataItem: Pick<
@ -27,8 +28,15 @@ export const usePreviewRecord = ({
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
const skip = skipFromProps || !labelIdentifierFieldMetadataItem;
let recordGqlFields: Record<string, boolean> | undefined = undefined;
if (objectMetadataItem.nameSingular === CoreObjectNameSingular.NoteTarget)
recordGqlFields = { id: true, note: true };
if (objectMetadataItem.nameSingular === CoreObjectNameSingular.TaskTarget)
recordGqlFields = { id: true, task: true };
const { records } = useFindManyRecords({
objectNameSingular: objectMetadataItem.nameSingular,
recordGqlFields,
limit: 1,
skip,
});