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 <charles@twenty.com>
This commit is contained in:
+30
-21
@@ -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 (
|
||||
<HookMockWrapper>
|
||||
<RecordTableContextProvider
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordTableId={recordTableId}
|
||||
viewBarId="instanceId"
|
||||
<ViewComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'instanceId' }}
|
||||
>
|
||||
<ObjectNamePluralSetter>
|
||||
<ViewComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'instanceId' }}
|
||||
<RecordComponentInstanceContextsWrapper
|
||||
componentInstanceId={recordTableId}
|
||||
>
|
||||
<JestRecordIndexContextProviderWrapper
|
||||
objectMetadataItem={mockPersonObjectMetadataItem}
|
||||
>
|
||||
<RecordComponentInstanceContextsWrapper
|
||||
componentInstanceId={recordTableId}
|
||||
<RecordTableContextProvider
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordTableId={recordTableId}
|
||||
viewBarId="instanceId"
|
||||
>
|
||||
<RecordTableComponentInstance recordTableId={recordTableId}>
|
||||
<RecordGroupContext.Provider
|
||||
value={{ recordGroupId: 'default' }}
|
||||
>
|
||||
{children}
|
||||
</RecordGroupContext.Provider>
|
||||
</RecordTableComponentInstance>
|
||||
</RecordComponentInstanceContextsWrapper>
|
||||
</ViewComponentInstanceContext.Provider>
|
||||
</ObjectNamePluralSetter>
|
||||
</RecordTableContextProvider>
|
||||
<ObjectNamePluralSetter>
|
||||
<RecordTableComponentInstance recordTableId={recordTableId}>
|
||||
<RecordGroupContext.Provider
|
||||
value={{ recordGroupId: 'default' }}
|
||||
>
|
||||
{children}
|
||||
</RecordGroupContext.Provider>
|
||||
</RecordTableComponentInstance>
|
||||
</ObjectNamePluralSetter>
|
||||
</RecordTableContextProvider>
|
||||
</JestRecordIndexContextProviderWrapper>
|
||||
</RecordComponentInstanceContextsWrapper>
|
||||
</ViewComponentInstanceContext.Provider>
|
||||
</HookMockWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
+15
@@ -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 (
|
||||
<RecordIndexContextProvider
|
||||
value={{
|
||||
@@ -87,6 +98,10 @@ const createStory = (contentId: ObjectOptionsContentId | null): Story => ({
|
||||
objectNameSingular: 'company',
|
||||
objectMetadataItem: companyObjectMetadataItem,
|
||||
recordIndexId: instanceId,
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
}}
|
||||
>
|
||||
<ObjectOptionsDropdownContext.Provider
|
||||
|
||||
+2
-13
@@ -1,13 +1,12 @@
|
||||
import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
|
||||
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { useRecordDragState } from '@/object-record/record-drag/shared/hooks/useRecordDragState';
|
||||
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
|
||||
import { isRecordBoardCardActiveComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardActiveComponentFamilyState';
|
||||
import { isRecordBoardCardFocusedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardFocusedComponentFamilyState';
|
||||
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import { useRecordDragState } from '@/object-record/record-drag/shared/hooks/useRecordDragState';
|
||||
|
||||
import { useActiveRecordBoardCard } from '@/object-record/record-board/hooks/useActiveRecordBoardCard';
|
||||
import { useFocusedRecordBoardCard } from '@/object-record/record-board/hooks/useFocusedRecordBoardCard';
|
||||
@@ -140,10 +139,6 @@ export const RecordBoardCard = () => {
|
||||
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 (
|
||||
<RecordBoardCardComponentInstanceContext.Provider
|
||||
value={{
|
||||
@@ -270,9 +261,7 @@ export const RecordBoardCard = () => {
|
||||
isOpen={isCardExpanded || !isCompactModeActive}
|
||||
initial={false}
|
||||
>
|
||||
<RecordBoardCardBody
|
||||
fieldDefinitions={visibleFieldDefinitionsFiltered}
|
||||
/>
|
||||
<RecordBoardCardBody />
|
||||
</AnimatedEaseInOut>
|
||||
</StyledBoardCard>
|
||||
</StyledCardContainer>
|
||||
|
||||
+58
-60
@@ -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<FieldMetadata>[];
|
||||
}) => {
|
||||
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 (
|
||||
<RecordBoardCardBodyContainer>
|
||||
{fieldDefinitionsWithReadOnly.map((fieldDefinition, index) => (
|
||||
<StopPropagationContainer key={fieldDefinition.fieldMetadataId}>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
recordId,
|
||||
maxWidth: 156,
|
||||
isLabelIdentifier: false,
|
||||
isRecordFieldReadOnly: fieldDefinition.isRecordFieldReadOnly,
|
||||
fieldDefinition: {
|
||||
disableTooltip: false,
|
||||
fieldMetadataId: fieldDefinition.fieldMetadataId,
|
||||
label: fieldDefinition.label,
|
||||
iconName: fieldDefinition.iconName,
|
||||
type: fieldDefinition.type,
|
||||
metadata: fieldDefinition.metadata,
|
||||
defaultValue: fieldDefinition.defaultValue,
|
||||
editButtonIcon: getFieldButtonIcon({
|
||||
metadata: fieldDefinition.metadata,
|
||||
type: fieldDefinition.type,
|
||||
}),
|
||||
},
|
||||
useUpdateRecord: useUpdateOneRecordHook,
|
||||
isDisplayModeFixHeight: true,
|
||||
triggerEvent: 'CLICK',
|
||||
anchorId: `${RECORD_BOARD_CARD_INPUT_ID_PREFIX}-${recordId}-${fieldDefinition.metadata.fieldName}`,
|
||||
onMouseEnter: () => handleMouseEnter(index),
|
||||
}}
|
||||
>
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
{visibleRecordFieldsExceptLabelIdentifier.map((recordField, index) => {
|
||||
const correspondingFieldDefinition =
|
||||
fieldDefinitionByFieldMetadataItemId[recordField.fieldMetadataItemId];
|
||||
|
||||
return (
|
||||
<StopPropagationContainer key={recordField.fieldMetadataItemId}>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
instanceId: getRecordFieldInputInstanceId({
|
||||
recordId,
|
||||
fieldName: fieldDefinition.metadata.fieldName,
|
||||
prefix: RECORD_BOARD_CARD_INPUT_ID_PREFIX,
|
||||
recordId,
|
||||
maxWidth: 156,
|
||||
isLabelIdentifier: false,
|
||||
isRecordFieldReadOnly: isRecordFieldReadOnly({
|
||||
isRecordReadOnly,
|
||||
objectPermissions,
|
||||
fieldMetadataItem: {
|
||||
id: recordField.fieldMetadataItemId,
|
||||
isUIReadOnly:
|
||||
correspondingFieldDefinition.metadata.isUIReadOnly ??
|
||||
false,
|
||||
},
|
||||
}),
|
||||
fieldDefinition: correspondingFieldDefinition,
|
||||
useUpdateRecord: useUpdateOneRecordHook,
|
||||
isDisplayModeFixHeight: true,
|
||||
triggerEvent: 'CLICK',
|
||||
anchorId: `${RECORD_BOARD_CARD_INPUT_ID_PREFIX}-${recordId}-${correspondingFieldDefinition.metadata.fieldName}`,
|
||||
onMouseEnter: () => handleMouseEnter(index),
|
||||
}}
|
||||
>
|
||||
<RecordInlineCell
|
||||
instanceIdPrefix={RECORD_BOARD_CARD_INPUT_ID_PREFIX}
|
||||
/>
|
||||
</RecordFieldComponentInstanceContext.Provider>
|
||||
</FieldContext.Provider>
|
||||
</StopPropagationContainer>
|
||||
))}
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: getRecordFieldInputInstanceId({
|
||||
recordId,
|
||||
fieldName: correspondingFieldDefinition.metadata.fieldName,
|
||||
prefix: RECORD_BOARD_CARD_INPUT_ID_PREFIX,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<RecordInlineCell
|
||||
instanceIdPrefix={RECORD_BOARD_CARD_INPUT_ID_PREFIX}
|
||||
/>
|
||||
</RecordFieldComponentInstanceContext.Provider>
|
||||
</FieldContext.Provider>
|
||||
</StopPropagationContainer>
|
||||
);
|
||||
})}
|
||||
</RecordBoardCardBodyContainer>
|
||||
);
|
||||
};
|
||||
|
||||
+17
-13
@@ -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;
|
||||
|
||||
|
||||
+4
-4
@@ -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,
|
||||
|
||||
-12
@@ -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<FieldMetadata>[]
|
||||
>({
|
||||
key: 'recordBoardFieldDefinitionsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
});
|
||||
-17
@@ -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,
|
||||
});
|
||||
+15
@@ -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 (
|
||||
<RecordTableComponentInstanceContext.Provider
|
||||
value={{
|
||||
@@ -37,6 +48,10 @@ const meta: Meta = {
|
||||
objectNameSingular: CoreObjectNameSingular.Company,
|
||||
objectMetadataItem: companyObjectMetadataItem,
|
||||
recordIndexId: instanceId,
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
|
||||
-15
@@ -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,
|
||||
);
|
||||
|
||||
+15
@@ -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 <NotFound />;
|
||||
}
|
||||
@@ -67,6 +78,10 @@ export const RecordIndexContainerGater = () => {
|
||||
objectMetadataItem,
|
||||
onIndexRecordsLoaded: handleIndexRecordsLoaded,
|
||||
indexIdentifierUrl,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
}}
|
||||
>
|
||||
<ViewComponentInstanceContext.Provider
|
||||
|
||||
+11
@@ -1,4 +1,8 @@
|
||||
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 ObjectPermissions } from 'twenty-shared/types';
|
||||
import { createRequiredContext } from '~/utils/createRequiredContext';
|
||||
|
||||
@@ -13,6 +17,13 @@ export type RecordIndexContextValue = {
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
recordIndexId: string;
|
||||
recordFieldByFieldMetadataItemId: Record<string, RecordField>;
|
||||
labelIdentifierFieldMetadataItem: FieldMetadataItem | undefined;
|
||||
fieldMetadataItemByFieldMetadataItemId: Record<string, FieldMetadataItem>;
|
||||
fieldDefinitionByFieldMetadataItemId: Record<
|
||||
string,
|
||||
ColumnDefinition<FieldMetadata>
|
||||
>;
|
||||
};
|
||||
|
||||
export const [RecordIndexContextProvider, useRecordIndexContextOrThrow] =
|
||||
|
||||
+18
-5
@@ -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<string, any> = {
|
||||
...allDepthOneWithoutRelationsRecordGqlFields,
|
||||
...Object.fromEntries(
|
||||
visibleFieldDefinitions.map((visibleFieldDefinition) => [
|
||||
visibleFieldDefinition.metadata.fieldName,
|
||||
visibleFieldMetadataItems.map((visibleFieldMetadataItem) => [
|
||||
visibleFieldMetadataItem.name,
|
||||
true,
|
||||
]),
|
||||
),
|
||||
|
||||
+63
@@ -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,
|
||||
};
|
||||
};
|
||||
+2
-2
@@ -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({
|
||||
|
||||
-49
@@ -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 (
|
||||
<RecordTableContextInternalProvider
|
||||
value={{
|
||||
@@ -86,11 +41,7 @@ export const RecordTableContextProvider = ({
|
||||
recordTableId,
|
||||
objectNameSingular,
|
||||
objectPermissions,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
visibleRecordFields,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
+4
-4
@@ -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,
|
||||
}}
|
||||
>
|
||||
<RecordComponentInstanceContextsWrapper componentInstanceId="recordTableId">
|
||||
@@ -156,10 +160,6 @@ const meta: Meta = {
|
||||
objectPermissions: {
|
||||
objectMetadataId: mockPerformance.objectMetadataItem.id,
|
||||
},
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
visibleRecordFields,
|
||||
}}
|
||||
>
|
||||
|
||||
-10
@@ -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<string, RecordField>;
|
||||
labelIdentifierFieldMetadataItem: FieldMetadataItem | undefined;
|
||||
fieldMetadataItemByFieldMetadataItemId: Record<string, FieldMetadataItem>;
|
||||
fieldDefinitionByFieldMetadataItemId: Record<
|
||||
string,
|
||||
ColumnDefinition<FieldMetadata>
|
||||
>;
|
||||
};
|
||||
|
||||
export const [RecordTableContextProvider, useRecordTableContextOrThrow] =
|
||||
|
||||
+6
-5
@@ -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];
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
||||
useRecordIndexContextOrThrow();
|
||||
const { recordId, isRecordReadOnly } = useRecordTableRowContextOrThrow();
|
||||
const { fieldDefinitionByFieldMetadataItemId } =
|
||||
useRecordTableContextOrThrow();
|
||||
useRecordIndexContextOrThrow();
|
||||
|
||||
const { recordField } = useContext(RecordTableCellContext);
|
||||
const { objectMetadataItem, recordTableId } = useRecordTableContextOrThrow();
|
||||
|
||||
+8
-11
@@ -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 (
|
||||
<RecordFieldComponentInstanceContext.Provider value={{ instanceId }}>
|
||||
|
||||
+2
-1
@@ -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;
|
||||
|
||||
+15
@@ -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 (
|
||||
<StyledContainer>
|
||||
<RecordIndexContextProvider
|
||||
@@ -50,6 +61,10 @@ export const SignInBackgroundMockContainer = () => {
|
||||
objectMetadataItem: objectMetadataItem ?? objectMetadataItems[0],
|
||||
onIndexRecordsLoaded: () => {},
|
||||
indexIdentifierUrl: () => '',
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
}}
|
||||
>
|
||||
<ViewComponentInstanceContext.Provider
|
||||
|
||||
+15
@@ -16,6 +16,7 @@ import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainCo
|
||||
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
|
||||
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
|
||||
import { type RecordField } from '@/object-record/record-field/types/RecordField';
|
||||
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
|
||||
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { within } from '@storybook/test';
|
||||
@@ -79,6 +80,16 @@ const meta: Meta<typeof ViewBarFilterDropdown> = {
|
||||
|
||||
setCurrentRecordFields(columns);
|
||||
|
||||
const {
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
} = useRecordIndexFieldMetadataDerivedStates(
|
||||
companyObjectMetadataItem,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
return (
|
||||
<RecordIndexContextProvider
|
||||
value={{
|
||||
@@ -89,6 +100,10 @@ const meta: Meta<typeof ViewBarFilterDropdown> = {
|
||||
objectNameSingular: CoreObjectNameSingular.Company,
|
||||
objectMetadataItem: companyObjectMetadataItem,
|
||||
recordIndexId: instanceId,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
recordFieldByFieldMetadataItemId,
|
||||
fieldDefinitionByFieldMetadataItemId,
|
||||
fieldMetadataItemByFieldMetadataItemId,
|
||||
}}
|
||||
>
|
||||
<RecordComponentInstanceContextsWrapper
|
||||
|
||||
+16
-1
@@ -11,6 +11,7 @@ import { type RecordFilterGroup } from '@/object-record/record-filter-group/type
|
||||
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
|
||||
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
|
||||
import { InputLabel } from '@/ui/input/components/InputLabel';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowFindRecordsFilters } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowFindRecordsFilters';
|
||||
@@ -70,6 +71,7 @@ export const WorkflowEditActionFindRecords = ({
|
||||
filter: action.settings.input.filter as FindRecordsActionFilter,
|
||||
});
|
||||
const isFormDisabled = actionOptions.readonly;
|
||||
const instanceId = `workflow-edit-action-record-find-records-${action.id}-${formData.objectNameSingular}`;
|
||||
|
||||
const selectedObjectMetadataItem = activeNonSystemObjectMetadataItems.find(
|
||||
(item) => 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,
|
||||
}}
|
||||
>
|
||||
<RecordFilterGroupsComponentInstanceContext.Provider
|
||||
|
||||
Reference in New Issue
Block a user