From db5897d4d02a9e50e7a39828da7f9917ad2ffb8e Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Sat, 30 Aug 2025 13:36:28 +0200 Subject: [PATCH] Refactor board field definitions to use record fields (#14165) This PR removes board field definitions usage in favor of record fields, like we've already done on table with table columns. This PR also introduces a first step in the refactoring of the RecordIndexContext as a new way to store in-memory a normalized cache for some states used pretty much everywhere like field metadata items or field definition (for now but it will soon be removed). Since most of those states do not change if we don't modify the metadata, then we can safely store them in a context, which has the fastest access time in React. Co-authored-by: Charles Bochet --- .../useRecordIndexTableQuery.test.tsx | 51 ++++---- .../ObjectOptionsDropdownContent.stories.tsx | 15 +++ .../components/RecordBoardCard.tsx | 15 +-- .../components/RecordBoardCardBody.tsx | 118 +++++++++--------- .../useRecordBoardCardMetadataFromPosition.ts | 30 +++-- .../RecordBoardColumnCardsContainer.tsx | 8 +- ...cordBoardFieldDefinitionsComponentState.ts | 12 -- ...isibleFieldDefinitionsComponentSelector.ts | 17 --- .../perf/ChipFieldDisplay.perf.stories.tsx | 15 +++ .../RecordIndexBoardDataLoaderEffect.tsx | 15 --- .../components/RecordIndexContainerGater.tsx | 15 +++ .../contexts/RecordIndexContext.ts | 11 ++ .../hooks/useRecordBoardRecordGqlFields.ts | 23 +++- ...seRecordIndexFieldMetadataDerivedStates.ts | 63 ++++++++++ .../hooks/useRecordTableRecordGqlFields.ts | 4 +- .../components/RecordTableContextProvider.tsx | 49 -------- .../perf/RecordTableCell.perf.stories.tsx | 8 +- .../contexts/RecordTableContext.ts | 10 -- .../RecordTableCellFieldContextGeneric.tsx | 11 +- ...rdTableCellFieldContextLabelIdentifier.tsx | 2 +- .../RecordTableCellFieldContextWrapper.tsx | 19 ++- .../components/RecordTableHeaderCell.tsx | 3 +- .../SignInBackgroundMockContainer.tsx | 15 +++ .../ViewBarFilterDropdown.stories.tsx | 15 +++ .../WorkflowEditActionFindRecords.tsx | 17 ++- .../decorators/RecordTableDecorator.tsx | 8 +- .../JestRecordIndexContextProviderWrapper.tsx | 40 ++++++ ...dataAndApolloMocksAndActionMenuWrapper.tsx | 65 ++++------ 28 files changed, 386 insertions(+), 288 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/record-board/states/recordBoardFieldDefinitionsComponentState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates.ts create mode 100644 packages/twenty-front/src/testing/jest/JestRecordIndexContextProviderWrapper.tsx diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useRecordIndexTableQuery.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useRecordIndexTableQuery.test.tsx index d735bd52555..58bae629fff 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useRecordIndexTableQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useRecordIndexTableQuery.test.tsx @@ -11,10 +11,15 @@ import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewCompon import { type MockedResponse } from '@apollo/client/testing'; import gql from 'graphql-tag'; import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper'; -import { peopleQueryResult } from '~/testing/mock-data/people'; +import { JestRecordIndexContextProviderWrapper } from '~/testing/jest/JestRecordIndexContextProviderWrapper'; +import { + getMockPersonObjectMetadataItem, + peopleQueryResult, +} from '~/testing/mock-data/people'; const recordTableId = 'people'; const objectNameSingular = 'person'; +const mockPersonObjectMetadataItem = getMockPersonObjectMetadataItem(); const ObjectNamePluralSetter = ({ children }: { children: ReactNode }) => { return <>{children}; @@ -660,29 +665,33 @@ jest.mock('react-router-dom', () => ({ const Wrapper = ({ children }: { children: ReactNode }) => { return ( - - - + - - - - {children} - - - - - - + + + + {children} + + + + + + + ); }; diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx index 7e8a013c547..3ae9fe7602b 100644 --- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx @@ -7,6 +7,7 @@ import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropd import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext'; import { type ObjectOptionsContentId } from '@/object-record/object-options-dropdown/types/ObjectOptionsContentId'; import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; @@ -77,6 +78,16 @@ const createStory = (contentId: ObjectOptionsContentId | null): Story => ({ (item) => item.nameSingular === 'company', )!; + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates( + companyObjectMetadataItem, + instanceId, + ); + return ( ({ objectNameSingular: 'company', objectMetadataItem: companyObjectMetadataItem, recordIndexId: instanceId, + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, }} > { multiDragState.originalSelection.includes(recordId) && recordId !== multiDragState.primaryDraggedRecordId; - const visibleFieldDefinitions = useRecoilComponentValue( - recordBoardVisibleFieldDefinitionsComponentSelector, - ); - const isCompactModeActive = useRecoilComponentValue( isRecordBoardCompactModeActiveComponentState, ); @@ -223,10 +218,6 @@ export const RecordBoardCard = () => { rootMargin: '1000px', }); - const visibleFieldDefinitionsFiltered = visibleFieldDefinitions.filter( - (boardField) => !boardField.isLabelIdentifier, - ); - return ( { isOpen={isCardExpanded || !isCompactModeActive} initial={false} > - + diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCardBody.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCardBody.tsx index d146d57eacb..d19e02afca3 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCardBody.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCardBody.tsx @@ -5,29 +5,30 @@ import { StopPropagationContainer } from '@/object-record/record-board/record-bo import { RECORD_BOARD_CARD_INPUT_ID_PREFIX } from '@/object-record/record-board/record-board-card/constants/RecordBoardCardInputIdPrefix'; import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext'; import { recordBoardCardHoverPositionComponentState } from '@/object-record/record-board/record-board-card/states/recordBoardCardHoverPositionComponentState'; -import { type RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition'; +import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; import { FieldContext, type RecordUpdateHook, type RecordUpdateHookParams, } from '@/object-record/record-field/ui/contexts/FieldContext'; import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext'; -import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata'; -import { getFieldButtonIcon } from '@/object-record/record-field/ui/utils/getFieldButtonIcon'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell'; import { getRecordFieldInputInstanceId } from '@/object-record/utils/getRecordFieldInputId'; +import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { useContext } from 'react'; -export const RecordBoardCardBody = ({ - fieldDefinitions, -}: { - fieldDefinitions: RecordBoardFieldDefinition[]; -}) => { +export const RecordBoardCardBody = () => { const { recordId, isRecordReadOnly } = useContext(RecordBoardCardContext); const { updateOneRecord, objectPermissions } = useContext(RecordBoardContext); + const { + labelIdentifierFieldMetadataItem, + fieldDefinitionByFieldMetadataItemId, + } = useRecordIndexContextOrThrow(); + const useUpdateOneRecordHook: RecordUpdateHook = () => { const updateEntity = ({ variables }: RecordUpdateHookParams) => { updateOneRecord?.({ @@ -39,18 +40,13 @@ export const RecordBoardCardBody = ({ return [updateEntity, { loading: false }]; }; - const fieldDefinitionsWithReadOnly = fieldDefinitions.map( - (fieldDefinition) => ({ - ...fieldDefinition, - isRecordFieldReadOnly: isRecordFieldReadOnly({ - isRecordReadOnly, - objectPermissions, - fieldMetadataItem: { - id: fieldDefinition.fieldMetadataId, - isUIReadOnly: fieldDefinition.metadata.isUIReadOnly ?? false, - }, - }), - }), + const visibleRecordFields = useRecoilComponentValue( + visibleRecordFieldsComponentSelector, + ); + + const visibleRecordFieldsExceptLabelIdentifier = visibleRecordFields.filter( + (recordField) => + recordField.fieldMetadataItemId !== labelIdentifierFieldMetadataItem?.id, ); const setRecordBoardCardHoverPosition = useSetRecoilComponentState( @@ -63,50 +59,52 @@ export const RecordBoardCardBody = ({ return ( - {fieldDefinitionsWithReadOnly.map((fieldDefinition, index) => ( - - handleMouseEnter(index), - }} - > - { + const correspondingFieldDefinition = + fieldDefinitionByFieldMetadataItemId[recordField.fieldMetadataItemId]; + + return ( + + handleMouseEnter(index), }} > - - - - - ))} + + + + + + ); + })} ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/hooks/useRecordBoardCardMetadataFromPosition.ts b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/hooks/useRecordBoardCardMetadataFromPosition.ts index 40c0c70769d..92934003ea3 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/hooks/useRecordBoardCardMetadataFromPosition.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/hooks/useRecordBoardCardMetadataFromPosition.ts @@ -1,7 +1,8 @@ import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; import { recordBoardCardEditModePositionComponentState } from '@/object-record/record-board/record-board-card/states/recordBoardCardEditModePositionComponentState'; import { recordBoardCardHoverPositionComponentState } from '@/object-record/record-board/record-board-card/states/recordBoardCardHoverPositionComponentState'; -import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector'; +import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { useContext } from 'react'; import { isDefined } from 'twenty-shared/utils'; @@ -17,33 +18,36 @@ export const useRecordBoardCardMetadataFromPosition = () => { recordBoardCardEditModePositionComponentState, ); - const visibleFieldDefinitions = useRecoilComponentValue( - recordBoardVisibleFieldDefinitionsComponentSelector, + const visibleRecordFields = useRecoilComponentValue( + visibleRecordFieldsComponentSelector, ); - const visibleFieldDefinitionsFiltered = visibleFieldDefinitions.filter( - (boardField) => !boardField.isLabelIdentifier, + const { labelIdentifierFieldMetadataItem } = useRecordIndexContextOrThrow(); + + const visibleRecordFieldsFiltered = visibleRecordFields.filter( + (recordField) => + labelIdentifierFieldMetadataItem?.id !== recordField.fieldMetadataItemId, ); - const hoveredFieldDefinition = isDefined(hoverPosition) - ? visibleFieldDefinitionsFiltered.at(hoverPosition) + const hoveredRecordField = isDefined(hoverPosition) + ? visibleRecordFieldsFiltered.at(hoverPosition) : undefined; - const editedFieldDefinition = isDefined(editModePosition) - ? visibleFieldDefinitionsFiltered.at(editModePosition) + const editedRecordField = isDefined(editModePosition) + ? visibleRecordFieldsFiltered.at(editModePosition) : undefined; - const hoveredFieldMetadataItem = isDefined(hoveredFieldDefinition) + const hoveredFieldMetadataItem = isDefined(hoveredRecordField) ? objectMetadataItem.fields.find( (fieldMetadataItem) => - fieldMetadataItem.id === hoveredFieldDefinition.fieldMetadataId, + fieldMetadataItem.id === hoveredRecordField.fieldMetadataItemId, ) : undefined; - const editedFieldMetadataItem = isDefined(editedFieldDefinition) + const editedFieldMetadataItem = isDefined(editedRecordField) ? objectMetadataItem.fields.find( (fieldMetadataItem) => - fieldMetadataItem.id === editedFieldDefinition.fieldMetadataId, + fieldMetadataItem.id === editedRecordField.fieldMetadataItemId, ) : undefined; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx index 0201aa0fc48..6d4e13b5b72 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx @@ -10,7 +10,7 @@ import { RecordBoardColumnNewRecordButton } from '@/object-record/record-board/r import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; import { getNumberOfCardsPerColumnForSkeletonLoading } from '@/object-record/record-board/record-board-column/utils/getNumberOfCardsPerColumnForSkeletonLoading'; import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState'; -import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector'; +import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; import { isRecordIndexBoardColumnLoadingFamilyState } from '@/object-record/states/isRecordBoardColumnLoadingFamilyState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; @@ -52,11 +52,11 @@ export const RecordBoardColumnCardsContainer = ({ isRecordIndexBoardColumnLoadingFamilyState(columnId), ); - const visibleFieldDefinitions = useRecoilComponentValue( - recordBoardVisibleFieldDefinitionsComponentSelector, + const visibleRecordFields = useRecoilComponentValue( + visibleRecordFieldsComponentSelector, ); - const numberOfFields = visibleFieldDefinitions.length; + const numberOfFields = visibleRecordFields.length; const isCompactModeActive = useRecoilComponentValue( isRecordBoardCompactModeActiveComponentState, diff --git a/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardFieldDefinitionsComponentState.ts b/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardFieldDefinitionsComponentState.ts deleted file mode 100644 index 5c8995e7d4b..00000000000 --- a/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardFieldDefinitionsComponentState.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext'; -import { type RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition'; -import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata'; -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const recordBoardFieldDefinitionsComponentState = createComponentState< - RecordBoardFieldDefinition[] ->({ - key: 'recordBoardFieldDefinitionsComponentState', - defaultValue: [], - componentInstanceContext: RecordBoardComponentInstanceContext, -}); diff --git a/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector.ts b/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector.ts deleted file mode 100644 index f4a4af43361..00000000000 --- a/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext'; -import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState'; -import { createComponentSelector } from '@/ui/utilities/state/component-state/utils/createComponentSelector'; - -export const recordBoardVisibleFieldDefinitionsComponentSelector = - createComponentSelector({ - key: 'recordBoardVisibleFieldDefinitionsComponentSelector', - get: - ({ instanceId }) => - ({ get }) => - get( - recordBoardFieldDefinitionsComponentState.atomFamily({ instanceId }), - ) - .filter((field) => field.isVisible) - .sort((a, b) => a.position - b.position), - componentInstanceContext: RecordBoardComponentInstanceContext, - }); diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx index 5a4dc5be194..842e5fa37e5 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx @@ -4,6 +4,7 @@ import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlur import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { ChipFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/ChipFieldDisplay'; import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { ComponentDecorator } from 'twenty-ui/testing'; import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator'; @@ -22,6 +23,16 @@ const meta: Meta = { (item) => item.nameSingular === CoreObjectNameSingular.Company, )!; + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates( + companyObjectMetadataItem, + instanceId, + ); + return ( diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx index 5645c761a1d..5ae0781cdb2 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx @@ -3,9 +3,7 @@ import { useRecoilValue } from 'recoil'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState'; -import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState'; import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector'; -import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; @@ -17,19 +15,10 @@ type RecordIndexBoardDataLoaderEffectProps = { export const RecordIndexBoardDataLoaderEffect = ({ recordBoardId, }: RecordIndexBoardDataLoaderEffectProps) => { - const recordIndexFieldDefinitions = useRecoilValue( - recordIndexFieldDefinitionsState, - ); - const recordIndexIsCompactModeActive = useRecoilValue( recordIndexIsCompactModeActiveState, ); - const setRecordBoardFieldDefinitions = useSetRecoilComponentState( - recordBoardFieldDefinitionsComponentState, - recordBoardId, - ); - const selectedRecordIds = useRecoilComponentValue( recordBoardSelectedRecordIdsComponentSelector, recordBoardId, @@ -44,10 +33,6 @@ export const RecordIndexBoardDataLoaderEffect = ({ setIsCompactModeActive(recordIndexIsCompactModeActive); }, [recordIndexIsCompactModeActive, setIsCompactModeActive]); - useEffect(() => { - setRecordBoardFieldDefinitions(recordIndexFieldDefinitions); - }, [recordIndexFieldDefinitions, setRecordBoardFieldDefinitions]); - const setContextStoreTargetedRecords = useSetRecoilComponentState( contextStoreTargetedRecordsRuleComponentState, ); diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx index daf0a761b0b..0754007daa7 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx @@ -11,6 +11,7 @@ import { RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect } from '@ import { RecordIndexLoadBaseOnContextStoreEffect } from '@/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect'; import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader'; import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick'; +import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates'; import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore'; import { PageBody } from '@/ui/layout/page/components/PageBody'; import { RECORD_INDEX_DRAG_SELECT_BOUNDARY_CLASS } from '@/ui/utilities/drag-select/constants/RecordIndecDragSelectBoundaryClass'; @@ -52,6 +53,16 @@ export const RecordIndexContainerGater = () => { const hasObjectReadPermissions = objectPermissions.canReadObjectRecords; + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates( + objectMetadataItem, + recordIndexId, + ); + if (!hasObjectReadPermissions) { return ; } @@ -67,6 +78,10 @@ export const RecordIndexContainerGater = () => { objectMetadataItem, onIndexRecordsLoaded: handleIndexRecordsLoaded, indexIdentifierUrl, + recordFieldByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + fieldMetadataItemByFieldMetadataItemId, + fieldDefinitionByFieldMetadataItemId, }} > ; recordIndexId: string; + recordFieldByFieldMetadataItemId: Record; + labelIdentifierFieldMetadataItem: FieldMetadataItem | undefined; + fieldMetadataItemByFieldMetadataItemId: Record; + fieldDefinitionByFieldMetadataItemId: Record< + string, + ColumnDefinition + >; }; export const [RecordIndexContextProvider, useRecordIndexContextOrThrow] = diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordBoardRecordGqlFields.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordBoardRecordGqlFields.ts index 3940fd7d1e3..54fd0cffa71 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordBoardRecordGqlFields.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordBoardRecordGqlFields.ts @@ -3,8 +3,9 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; import { generateDepthOneWithoutRelationsRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneWithoutRelationsRecordGqlFields'; -import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector'; +import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { isDefined } from 'twenty-shared/utils'; @@ -15,11 +16,14 @@ export const useRecordBoardRecordGqlFields = ({ recordBoardId: string; objectMetadataItem: ObjectMetadataItem; }) => { - const visibleFieldDefinitions = useRecoilComponentValue( - recordBoardVisibleFieldDefinitionsComponentSelector, + const visibleRecordFields = useRecoilComponentValue( + visibleRecordFieldsComponentSelector, recordBoardId, ); + const { fieldMetadataItemByFieldMetadataItemId } = + useRecordIndexContextOrThrow(); + const recordGroupFieldMetadata = useRecoilComponentValue( recordGroupFieldMetadataComponentState, recordBoardId, @@ -40,11 +44,20 @@ export const useRecordBoardRecordGqlFields = ({ objectMetadataItem, }); + const visibleFieldMetadataItems = visibleRecordFields + .map( + (recordField) => + fieldMetadataItemByFieldMetadataItemId[ + recordField.fieldMetadataItemId + ] ?? null, + ) + .filter(isDefined); + const recordGqlFields: Record = { ...allDepthOneWithoutRelationsRecordGqlFields, ...Object.fromEntries( - visibleFieldDefinitions.map((visibleFieldDefinition) => [ - visibleFieldDefinition.metadata.fieldName, + visibleFieldMetadataItems.map((visibleFieldMetadataItem) => [ + visibleFieldMetadataItem.name, true, ]), ), diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates.ts new file mode 100644 index 00000000000..1c2bf74f208 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates.ts @@ -0,0 +1,63 @@ +import { labelIdentifierFieldMetadataItemSelector } from '@/object-metadata/states/labelIdentifierFieldMetadataItemSelector'; +import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; +import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState'; +import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-shared/utils'; + +export const useRecordIndexFieldMetadataDerivedStates = ( + objectMetadataItem: ObjectMetadataItem | undefined, + recordIndexId?: string | undefined, +) => { + const fieldMetadataItems = objectMetadataItem?.fields ?? []; + + const fieldMetadataItemByFieldMetadataItemId = Object.fromEntries( + fieldMetadataItems.map((fieldMetadataItem) => [ + fieldMetadataItem.id, + fieldMetadataItem, + ]), + ); + + const currentRecordFields = useRecoilComponentValue( + currentRecordFieldsComponentState, + recordIndexId, + ); + + const recordFieldByFieldMetadataItemId = Object.fromEntries( + currentRecordFields.map((recordField) => [ + recordField.fieldMetadataItemId, + recordField, + ]), + ); + + const fieldDefinitionByFieldMetadataItemId = isDefined(objectMetadataItem) + ? Object.fromEntries( + fieldMetadataItems.map((fieldMetadataItem) => [ + fieldMetadataItem.id, + formatFieldMetadataItemAsColumnDefinition({ + field: fieldMetadataItem, + objectMetadataItem, + position: + recordFieldByFieldMetadataItemId[fieldMetadataItem.id] + ?.position ?? 0, + labelWidth: + recordFieldByFieldMetadataItemId[fieldMetadataItem.id]?.size ?? 0, + }), + ]), + ) + : {}; + + const labelIdentifierFieldMetadataItem = useRecoilValue( + labelIdentifierFieldMetadataItemSelector({ + objectMetadataItemId: objectMetadataItem?.id ?? '', + }), + ); + + return { + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + fieldDefinitionByFieldMetadataItemId, + recordFieldByFieldMetadataItemId, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts index 02ab21e1dff..fcc85e3b8e1 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts @@ -4,7 +4,7 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; import { generateDepthOneWithoutRelationsRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneWithoutRelationsRecordGqlFields'; import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; -import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { FieldMetadataType } from 'twenty-shared/types'; import { computeMorphRelationFieldName, isDefined } from 'twenty-shared/utils'; @@ -19,7 +19,7 @@ export const useRecordTableRecordGqlFields = ({ ); const { fieldMetadataItemByFieldMetadataItemId } = - useRecordTableContextOrThrow(); + useRecordIndexContextOrThrow(); const { objectMetadataItem: noteTargetObjectMetadataItem } = useObjectMetadataItem({ diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContextProvider.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContextProvider.tsx index cfa33ea4cdb..d3a86333470 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContextProvider.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContextProvider.tsx @@ -3,13 +3,9 @@ import { type ReactNode } from 'react'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { RecordTableContextProvider as RecordTableContextInternalProvider } from '@/object-record/record-table/contexts/RecordTableContext'; -import { labelIdentifierFieldMetadataItemSelector } from '@/object-metadata/states/labelIdentifierFieldMetadataItemSelector'; -import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject'; -import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState'; import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import { useRecoilValue } from 'recoil'; type RecordTableContextProviderProps = { viewBarId: string; @@ -37,47 +33,6 @@ export const RecordTableContextProvider = ({ recordTableId, ); - const currentRecordFields = useRecoilComponentValue( - currentRecordFieldsComponentState, - recordTableId, - ); - - const fieldMetadataItems = objectMetadataItem.fields; - - const fieldMetadataItemByFieldMetadataItemId = Object.fromEntries( - fieldMetadataItems.map((fieldMetadataItem) => [ - fieldMetadataItem.id, - fieldMetadataItem, - ]), - ); - - const recordFieldByFieldMetadataItemId = Object.fromEntries( - currentRecordFields.map((recordField) => [ - recordField.fieldMetadataItemId, - recordField, - ]), - ); - - const fieldDefinitionByFieldMetadataItemId = Object.fromEntries( - fieldMetadataItems.map((fieldMetadataItem) => [ - fieldMetadataItem.id, - formatFieldMetadataItemAsColumnDefinition({ - field: fieldMetadataItem, - objectMetadataItem, - position: - recordFieldByFieldMetadataItemId[fieldMetadataItem.id]?.position ?? 0, - labelWidth: - recordFieldByFieldMetadataItemId[fieldMetadataItem.id]?.size ?? 0, - }), - ]), - ); - - const labelIdentifierFieldMetadataItem = useRecoilValue( - labelIdentifierFieldMetadataItemSelector({ - objectMetadataItemId: objectMetadataItem.id, - }), - ); - return ( {children} diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx index 985a249271b..d7f3c037f33 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx @@ -142,6 +142,10 @@ const meta: Meta = { // TODO: update performance mocks with new data, and merge with common mocks if possible objectMetadataItem: mockPerformance.objectMetadataItem as any, recordIndexId: 'recordIndexId', + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, }} > @@ -156,10 +160,6 @@ const meta: Meta = { objectPermissions: { objectMetadataId: mockPerformance.objectMetadataItem.id, }, - fieldDefinitionByFieldMetadataItemId, - fieldMetadataItemByFieldMetadataItemId, - labelIdentifierFieldMetadataItem, - recordFieldByFieldMetadataItemId, visibleRecordFields, }} > diff --git a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts index d5b45b2a4e9..80fd218572a 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts @@ -1,8 +1,5 @@ -import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { type RecordField } from '@/object-record/record-field/types/RecordField'; -import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata'; -import { type ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { type ObjectPermission } from '~/generated/graphql'; import { createRequiredContext } from '~/utils/createRequiredContext'; @@ -13,13 +10,6 @@ type RecordTableContextValue = { objectMetadataItem: ObjectMetadataItem; objectPermissions: ObjectPermission; visibleRecordFields: RecordField[]; - recordFieldByFieldMetadataItemId: Record; - labelIdentifierFieldMetadataItem: FieldMetadataItem | undefined; - fieldMetadataItemByFieldMetadataItemId: Record; - fieldDefinitionByFieldMetadataItemId: Record< - string, - ColumnDefinition - >; }; export const [RecordTableContextProvider, useRecordTableContextOrThrow] = diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextGeneric.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextGeneric.tsx index a66d086441b..6ce6b5e39dd 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextGeneric.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextGeneric.tsx @@ -22,13 +22,14 @@ export const RecordTableCellFieldContextGeneric = ({ }: RecordTableCellFieldContextGenericProps) => { const { recordId, isRecordReadOnly } = useRecordTableRowContextOrThrow(); + const { objectMetadataItem, objectPermissions } = + useRecordTableContextOrThrow(); + const { - objectMetadataItem, - objectPermissions, + indexIdentifierUrl, + objectPermissionsByObjectMetadataId, fieldDefinitionByFieldMetadataItemId, - } = useRecordTableContextOrThrow(); - const { indexIdentifierUrl, objectPermissionsByObjectMetadataId } = - useRecordIndexContextOrThrow(); + } = useRecordIndexContextOrThrow(); const fieldDefinition = fieldDefinitionByFieldMetadataItemId[recordField.fieldMetadataItemId]; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextLabelIdentifier.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextLabelIdentifier.tsx index 0fda493f415..0c59cdbade3 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextLabelIdentifier.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextLabelIdentifier.tsx @@ -28,7 +28,7 @@ export const RecordTableCellFieldContextLabelIdentifier = ({ useRecordIndexContextOrThrow(); const { recordId, isRecordReadOnly } = useRecordTableRowContextOrThrow(); const { fieldDefinitionByFieldMetadataItemId } = - useRecordTableContextOrThrow(); + useRecordIndexContextOrThrow(); const { recordField } = useContext(RecordTableCellContext); const { objectMetadataItem, recordTableId } = useRecordTableContextOrThrow(); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx index e9c2cc5324a..e05682d6da9 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx @@ -1,8 +1,7 @@ -import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; import { type RecordField } from '@/object-record/record-field/types/RecordField'; import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { RECORD_TABLE_CELL_INPUT_ID_PREFIX } from '@/object-record/record-table/constants/RecordTableCellInputIdPrefix'; -import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext'; import { RecordTableCellFieldContextGeneric } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextGeneric'; import { RecordTableCellFieldContextLabelIdentifier } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextLabelIdentifier'; @@ -19,8 +18,11 @@ export const RecordTableCellFieldContextWrapper = ({ children, }: RecordTableCellFieldContextWrapperProps) => { const { recordId } = useRecordTableRowContextOrThrow(); - const { objectMetadataItem, fieldMetadataItemByFieldMetadataItemId } = - useRecordTableContextOrThrow(); + + const { + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + } = useRecordIndexContextOrThrow(); const fieldMetadataItem = fieldMetadataItemByFieldMetadataItemId[recordField.fieldMetadataItemId]; @@ -31,13 +33,8 @@ export const RecordTableCellFieldContextWrapper = ({ prefix: RECORD_TABLE_CELL_INPUT_ID_PREFIX, }); - const isLabelIdentifier = isLabelIdentifierField({ - fieldMetadataItem: { - id: recordField.fieldMetadataItemId, - name: fieldMetadataItem.name, - }, - objectMetadataItem, - }); + const isLabelIdentifier = + labelIdentifierFieldMetadataItem?.id === recordField.fieldMetadataItemId; return ( diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx index f86f09109d7..c7e2af55113 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx @@ -6,6 +6,7 @@ import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObje import { useUpdateRecordField } from '@/object-record/record-field/hooks/useUpdateRecordField'; import { type RecordField } from '@/object-record/record-field/types/RecordField'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord'; import { RecordTableColumnHeadWithDropdown } from '@/object-record/record-table/record-table-header/components/RecordTableColumnHeadWithDropdown'; @@ -207,7 +208,7 @@ export const RecordTableHeaderCell = ({ const isMobile = useIsMobile(); - const { labelIdentifierFieldMetadataItem } = useRecordTableContextOrThrow(); + const { labelIdentifierFieldMetadataItem } = useRecordIndexContextOrThrow(); const isLabelIdentifier = recordField.fieldMetadataItemId === labelIdentifierFieldMetadataItem?.id; diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx index 3114e5dd07a..fae745ec5df 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx @@ -7,6 +7,7 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/con import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper'; import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates'; import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; @@ -39,6 +40,16 @@ export const SignInBackgroundMockContainer = () => { (objectMetadataItem) => objectMetadataItem.id === objectMetadataItemId, ); + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates( + objectMetadataItem, + recordIndexId, + ); + return ( { objectMetadataItem: objectMetadataItem ?? objectMetadataItems[0], onIndexRecordsLoaded: () => {}, indexIdentifierUrl: () => '', + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, }} > = { setCurrentRecordFields(columns); + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates( + companyObjectMetadataItem, + instanceId, + ); + return ( = { objectNameSingular: CoreObjectNameSingular.Company, objectMetadataItem: companyObjectMetadataItem, recordIndexId: instanceId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, }} > item.nameSingular === formData.objectNameSingular, @@ -80,6 +82,16 @@ export const WorkflowEditActionFindRecords = ({ const { objectPermissionsByObjectMetadataId } = useObjectPermissions(); + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates( + selectedObjectMetadataItem, + instanceId, + ); + const saveAction = useDebouncedCallback( async (formData: FindRecordsFormData) => { if (actionOptions.readonly === true) { @@ -118,7 +130,6 @@ export const WorkflowEditActionFindRecords = ({ action, defaultTitle: 'Search Records', }); - const instanceId = `workflow-edit-action-record-find-records-${action.id}-${formData.objectNameSingular}`; return ( <> @@ -174,6 +185,10 @@ export const WorkflowEditActionFindRecords = ({ objectMetadataItem: selectedObjectMetadataItem, recordIndexId: instanceId, objectPermissionsByObjectMetadataId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, }} > { + const { + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + } = useRecordIndexFieldMetadataDerivedStates(objectMetadataItem); + + return ( + 'indexIdentifierUrl', + onIndexRecordsLoaded: () => {}, + objectNamePlural: objectMetadataItem.namePlural, + objectNameSingular: objectMetadataItem.nameSingular, + objectMetadataItem: objectMetadataItem, + recordIndexId: 'recordIndexId', + labelIdentifierFieldMetadataItem, + recordFieldByFieldMetadataItemId, + fieldDefinitionByFieldMetadataItemId, + fieldMetadataItemByFieldMetadataItemId, + }} + > + {children} + + ); +}; diff --git a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx index 5b68c52cca8..4fbe6625d51 100644 --- a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx +++ b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx @@ -1,7 +1,5 @@ import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; -import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper'; -import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; import { type MockedResponse } from '@apollo/client/testing'; import { type ReactNode } from 'react'; import { type MutableSnapshot } from 'recoil'; @@ -10,6 +8,7 @@ import { JestContextStoreSetter, type JestContextStoreSetterMocks, } from '~/testing/jest/JestContextStoreSetter'; +import { JestRecordIndexContextProviderWrapper } from '~/testing/jest/JestRecordIndexContextProviderWrapper'; import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper'; import { getMockObjectMetadataItemOrThrow } from '~/testing/utils/getMockObjectMetadataItemOrThrow'; @@ -49,48 +48,34 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({ return ({ children }: { children: ReactNode }) => ( - - - - 'indexIdentifierUrl', - onIndexRecordsLoaded: () => {}, - objectNamePlural: mockObjectMetadataItem.namePlural, - objectNameSingular: mockObjectMetadataItem.nameSingular, - objectMetadataItem: mockObjectMetadataItem, - recordIndexId: 'recordIndexId', - }} + - - {children} - - - - - + {children} + + + + ); };