From 7da18a13e810ac11a432e18448de027827062814 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Thu, 16 Nov 2023 17:09:50 +0100 Subject: [PATCH] Feat/filter available field definition v2 (#2547) * Added react-dev-inspector * Add field relation type parsing and filter available fields for record table and show page * Revert "Added react-dev-inspector" This reverts commit 7a78964c2c3996ce2e27f6f8d0c0b5e1f3283e17. --- ...rmatFieldMetadataItemAsColumnDefinition.ts | 2 + .../utils/parseFieldRelationType.ts | 39 +++++++++++++++++++ .../components/RecordShowPage.tsx | 2 + .../components/RecordTableEffect.tsx | 7 +++- .../utils/filterAvailableFieldMetadataItem.ts | 21 ++++++++++ .../utils/filterAvailableTableColumns.ts | 19 +++++++++ .../ui/object/field/hooks/usePersistField.ts | 4 +- .../ui/object/field/types/FieldDefinition.ts | 6 +++ 8 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 front/src/modules/object-metadata/utils/parseFieldRelationType.ts create mode 100644 front/src/modules/object-record/utils/filterAvailableFieldMetadataItem.ts create mode 100644 front/src/modules/object-record/utils/filterAvailableTableColumns.ts diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts index 2f605fd82..7f961ee72 100644 --- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts +++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts @@ -1,3 +1,4 @@ +import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType'; import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; @@ -30,4 +31,5 @@ export const formatFieldMetadataItemAsColumnDefinition = ({ Icon: icons[field.icon ?? 'Icon123'], isVisible: true, basePathToShowPage: `/object/${objectMetadataItem.nameSingular}/`, + relationType: parseFieldRelationType(field), }); diff --git a/front/src/modules/object-metadata/utils/parseFieldRelationType.ts b/front/src/modules/object-metadata/utils/parseFieldRelationType.ts new file mode 100644 index 000000000..fa5b9465e --- /dev/null +++ b/front/src/modules/object-metadata/utils/parseFieldRelationType.ts @@ -0,0 +1,39 @@ +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { FieldDefinitionRelationType } from '@/ui/object/field/types/FieldDefinition'; +import { isDefined } from '~/utils/isDefined'; + +export const parseFieldRelationType = ( + field: FieldMetadataItem | undefined, +): FieldDefinitionRelationType | undefined => { + if (field && field.type === 'RELATION') { + if ( + isDefined(field.fromRelationMetadata) && + field.fromRelationMetadata.relationType === 'ONE_TO_MANY' + ) { + return 'FROM_NAMY_OBJECTS'; + } else if ( + isDefined(field.toRelationMetadata) && + field.toRelationMetadata.relationType === 'ONE_TO_MANY' + ) { + return 'TO_ONE_OBJECT'; + } else if ( + isDefined(field.fromRelationMetadata) && + field.fromRelationMetadata.relationType === 'MANY_TO_MANY' + ) { + return 'FROM_NAMY_OBJECTS'; + } else if ( + isDefined(field.toRelationMetadata) && + field.toRelationMetadata.relationType === 'MANY_TO_MANY' + ) { + return 'TO_MANY_OBJECTS'; + } + + throw new Error( + `Cannot determine field relation type for field : ${JSON.stringify( + field, + )}.`, + ); + } else { + return undefined; + } +}; diff --git a/front/src/modules/object-record/components/RecordShowPage.tsx b/front/src/modules/object-record/components/RecordShowPage.tsx index 3a71e2b19..f90deb294 100644 --- a/front/src/modules/object-record/components/RecordShowPage.tsx +++ b/front/src/modules/object-record/components/RecordShowPage.tsx @@ -6,6 +6,7 @@ import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargeta import { useFavorites } from '@/favorites/hooks/useFavorites'; import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; +import { filterAvailableFieldMetadataItem } from '@/object-record/utils/filterAvailableFieldMetadataItem'; import { IconBuildingSkyscraper } from '@/ui/display/icon'; import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { PageBody } from '@/ui/layout/page/PageBody'; @@ -156,6 +157,7 @@ export const RecordShowPage = () => { .diff(DateTime.fromISO(b.createdAt)) .toMillis(), ) + .filter(filterAvailableFieldMetadataItem) .map((metadataField, index) => { return ( { setAvailableFilterDefinitions?.(filterDefinitions); setAvailableFieldDefinitions?.(columnDefinitions); - setAvailableTableColumns(columnDefinitions); + const availableTableColumns = columnDefinitions.filter( + filterAvailableTableColumns, + ); + + setAvailableTableColumns(availableTableColumns); }, [ setViewObjectMetadataId, setViewType, diff --git a/front/src/modules/object-record/utils/filterAvailableFieldMetadataItem.ts b/front/src/modules/object-record/utils/filterAvailableFieldMetadataItem.ts new file mode 100644 index 000000000..ab37057b5 --- /dev/null +++ b/front/src/modules/object-record/utils/filterAvailableFieldMetadataItem.ts @@ -0,0 +1,21 @@ +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType'; + +export const filterAvailableFieldMetadataItem = ( + fieldMetadataItem: FieldMetadataItem, +): boolean => { + if (fieldMetadataItem.type === 'RELATION') { + const fieldMetadataItemRelationType = + parseFieldRelationType(fieldMetadataItem); + + if (fieldMetadataItemRelationType !== 'TO_ONE_OBJECT') { + return false; + } + } + + if (fieldMetadataItem.type === 'UUID') { + return false; + } + + return true; +}; diff --git a/front/src/modules/object-record/utils/filterAvailableTableColumns.ts b/front/src/modules/object-record/utils/filterAvailableTableColumns.ts new file mode 100644 index 000000000..008673f19 --- /dev/null +++ b/front/src/modules/object-record/utils/filterAvailableTableColumns.ts @@ -0,0 +1,19 @@ +import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; +import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; + +export const filterAvailableTableColumns = ( + columnDefinition: ColumnDefinition, +): boolean => { + if ( + columnDefinition.type === 'RELATION' && + columnDefinition.relationType !== 'TO_ONE_OBJECT' + ) { + return false; + } + + if (columnDefinition.type === 'UUID') { + return false; + } + + return true; +}; diff --git a/front/src/modules/ui/object/field/hooks/usePersistField.ts b/front/src/modules/ui/object/field/hooks/usePersistField.ts index 90b797e7e..69172b63a 100644 --- a/front/src/modules/ui/object/field/hooks/usePersistField.ts +++ b/front/src/modules/ui/object/field/hooks/usePersistField.ts @@ -109,7 +109,9 @@ export const usePersistField = () => { variables: { where: { id: entityId }, data: { - [fieldName]: valueToPersist?.id ?? null, + // TODO: find a more elegant way to do this ? + // Maybe have a link between the RELATION field and the UUID field ? + [`${fieldName}Id`]: valueToPersist?.id ?? null, }, }, }); diff --git a/front/src/modules/ui/object/field/types/FieldDefinition.ts b/front/src/modules/ui/object/field/types/FieldDefinition.ts index 37b6a618d..ba41ebfb6 100644 --- a/front/src/modules/ui/object/field/types/FieldDefinition.ts +++ b/front/src/modules/ui/object/field/types/FieldDefinition.ts @@ -4,6 +4,11 @@ import { AvatarType } from '@/users/components/Avatar'; import { FieldMetadata } from './FieldMetadata'; import { FieldType } from './FieldType'; +export type FieldDefinitionRelationType = + | 'TO_ONE_OBJECT' + | 'FROM_NAMY_OBJECTS' + | 'TO_MANY_OBJECTS'; + export type FieldDefinition = { fieldMetadataId: string; label: string; @@ -17,4 +22,5 @@ export type FieldDefinition = { pictureUrl?: string; avatarType: AvatarType; }; + relationType?: FieldDefinitionRelationType; };