From 96661b5f563f56674e08f8bcd50fcf17b28ea0e9 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Wed, 15 Nov 2023 19:37:29 +0100 Subject: [PATCH] Add support for UUID fields in tables (#2529) --- .../object/field/components/FieldDisplay.tsx | 4 ++ .../display/components/UuidFieldDisplay.tsx | 8 ++++ .../field/meta-types/hooks/useUuidField.ts | 40 +++++++++++++++++++ .../isEntityFieldEmptyFamilySelector.ts | 2 + .../ui/object/field/types/FieldMetadata.ts | 7 ++++ .../ui/object/field/types/FieldType.ts | 1 + .../field/types/guards/assertFieldMetadata.ts | 3 ++ .../object/field/types/guards/isFieldUuid.ts | 6 +++ 8 files changed, 71 insertions(+) create mode 100644 front/src/modules/ui/object/field/meta-types/display/components/UuidFieldDisplay.tsx create mode 100644 front/src/modules/ui/object/field/meta-types/hooks/useUuidField.ts create mode 100644 front/src/modules/ui/object/field/types/guards/isFieldUuid.ts diff --git a/front/src/modules/ui/object/field/components/FieldDisplay.tsx b/front/src/modules/ui/object/field/components/FieldDisplay.tsx index 091f78126..9c0d3b934 100644 --- a/front/src/modules/ui/object/field/components/FieldDisplay.tsx +++ b/front/src/modules/ui/object/field/components/FieldDisplay.tsx @@ -1,6 +1,8 @@ import { useContext } from 'react'; import { RelationFieldDisplay } from '@/ui/object/field/meta-types/display/components/RelationFieldDisplay'; +import { UuidFieldDisplay } from '@/ui/object/field/meta-types/display/components/UuidFieldDisplay'; +import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid'; import { FieldContext } from '../contexts/FieldContext'; import { ChipFieldDisplay } from '../meta-types/display/components/ChipFieldDisplay'; @@ -38,6 +40,8 @@ export const FieldDisplay = () => { ) : isFieldText(fieldDefinition) ? ( + ) : isFieldUuid(fieldDefinition) ? ( + ) : isFieldEmail(fieldDefinition) ? ( ) : isFieldDate(fieldDefinition) ? ( diff --git a/front/src/modules/ui/object/field/meta-types/display/components/UuidFieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/UuidFieldDisplay.tsx new file mode 100644 index 000000000..6d7784be8 --- /dev/null +++ b/front/src/modules/ui/object/field/meta-types/display/components/UuidFieldDisplay.tsx @@ -0,0 +1,8 @@ +import { TextDisplay } from '@/ui/object/field/meta-types/display/content-display/components/TextDisplay'; +import { useUuidField } from '@/ui/object/field/meta-types/hooks/useUuidField'; + +export const UuidFieldDisplay = () => { + const { fieldValue } = useUuidField(); + + return ; +}; diff --git a/front/src/modules/ui/object/field/meta-types/hooks/useUuidField.ts b/front/src/modules/ui/object/field/meta-types/hooks/useUuidField.ts new file mode 100644 index 000000000..913867fec --- /dev/null +++ b/front/src/modules/ui/object/field/meta-types/hooks/useUuidField.ts @@ -0,0 +1,40 @@ +import { useContext } from 'react'; +import { useRecoilState } from 'recoil'; + +import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid'; + +import { FieldContext } from '../../contexts/FieldContext'; +import { useFieldInitialValue } from '../../hooks/useFieldInitialValue'; +import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector'; +import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; +import { isFieldTextValue } from '../../types/guards/isFieldTextValue'; + +export const useUuidField = () => { + const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext); + + assertFieldMetadata('UUID', isFieldUuid, fieldDefinition); + + const fieldName = fieldDefinition.metadata.fieldName; + + const [fieldValue, setFieldValue] = useRecoilState( + entityFieldsFamilySelector({ + entityId: entityId, + fieldName: fieldName, + }), + ); + const fieldTextValue = isFieldTextValue(fieldValue) ? fieldValue : ''; + + const fieldInitialValue = useFieldInitialValue(); + + const initialValue = fieldInitialValue?.isEmpty + ? '' + : fieldInitialValue?.value ?? fieldTextValue; + + return { + fieldDefinition, + fieldValue: fieldTextValue, + initialValue, + setFieldValue, + hotkeyScope, + }; +}; diff --git a/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts b/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts index 8b1f479ea..3f959634d 100644 --- a/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts +++ b/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts @@ -1,5 +1,6 @@ import { selectorFamily } from 'recoil'; +import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid'; import { assertNotNull } from '~/utils/assert'; import { FieldDefinition } from '../../types/FieldDefinition'; @@ -39,6 +40,7 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({ }) => { return ({ get }) => { if ( + isFieldUuid(fieldDefinition) || isFieldText(fieldDefinition) || isFieldURL(fieldDefinition) || isFieldDate(fieldDefinition) || diff --git a/front/src/modules/ui/object/field/types/FieldMetadata.ts b/front/src/modules/ui/object/field/types/FieldMetadata.ts index 3efcd46a1..d8e39a259 100644 --- a/front/src/modules/ui/object/field/types/FieldMetadata.ts +++ b/front/src/modules/ui/object/field/types/FieldMetadata.ts @@ -1,6 +1,11 @@ import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; +export type FieldUuidMetadata = { + placeHolder: string; + fieldName: string; +}; + export type FieldTextMetadata = { placeHolder: string; fieldName: string; @@ -86,6 +91,7 @@ export type FieldBooleanMetadata = { }; export type FieldMetadata = + | FieldUuidMetadata | FieldTextMetadata | FieldRelationMetadata | FieldChipMetadata @@ -103,6 +109,7 @@ export type FieldMetadata = | FieldBooleanMetadata; export type FieldTextValue = string; +export type FieldUUidValue = string; export type FieldChipValue = string; export type FieldDateValue = string | null; diff --git a/front/src/modules/ui/object/field/types/FieldType.ts b/front/src/modules/ui/object/field/types/FieldType.ts index 431d8367f..cc42ee693 100644 --- a/front/src/modules/ui/object/field/types/FieldType.ts +++ b/front/src/modules/ui/object/field/types/FieldType.ts @@ -1,4 +1,5 @@ export type FieldType = + | 'UUID' | 'TEXT' | 'RELATION' | 'CHIP' diff --git a/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts b/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts index dc094b207..ff3189c71 100644 --- a/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts +++ b/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts @@ -16,6 +16,7 @@ import { FieldTextMetadata, FieldURLMetadata, FieldURLV2Metadata, + FieldUuidMetadata, } from '../FieldMetadata'; import { FieldType } from '../FieldType'; @@ -23,6 +24,8 @@ type AssertFieldMetadataFunction = < E extends FieldType, T extends E extends 'TEXT' ? FieldTextMetadata + : E extends 'UUID' + ? FieldUuidMetadata : E extends 'RELATION' ? FieldRelationMetadata : E extends 'CHIP' diff --git a/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts b/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts new file mode 100644 index 000000000..b70efe0ea --- /dev/null +++ b/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts @@ -0,0 +1,6 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldUuidMetadata } from '../FieldMetadata'; + +export const isFieldUuid = ( + field: FieldDefinition, +): field is FieldDefinition => field.type === 'UUID';