Removed use-context-selector completely (#12139)
This PR removes use-context-selector completely, so that any bug associated with state synchronization between recoil and use-context-selector disappears. There might be a slight performance decrease on the table, but since we have already improved the average performance per line by a lot, and that the performance bottleneck right now is the fetch more logic and the windowing solution we use, it is not relevant. Also the DX has become so hindered by this parallel state logic recently (think [cache invalidation](https://martinfowler.com/bliki/TwoHardThings.html)), that the main benefit we gain from this removal is the DX improvement. Fixes https://github.com/twentyhq/twenty/issues/12123 Fixes https://github.com/twentyhq/twenty/issues/12109
This commit is contained in:
@ -2,7 +2,6 @@ import { useContext } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFieldValue';
|
||||
|
||||
@ -17,8 +16,6 @@ export const useClearField = () => {
|
||||
|
||||
const [updateRecord] = useUpdateRecord();
|
||||
|
||||
const setRecordFieldValue = useSetRecordFieldValue();
|
||||
|
||||
const clearField = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
() => {
|
||||
@ -51,8 +48,6 @@ export const useClearField = () => {
|
||||
emptyFieldValue,
|
||||
);
|
||||
|
||||
setRecordFieldValue(recordId, fieldName, emptyFieldValue);
|
||||
|
||||
updateRecord?.({
|
||||
variables: {
|
||||
where: { id: recordId },
|
||||
@ -62,7 +57,7 @@ export const useClearField = () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
[recordId, fieldDefinition, updateRecord, setRecordFieldValue],
|
||||
[recordId, fieldDefinition, updateRecord],
|
||||
);
|
||||
|
||||
return clearField;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { isFieldValueEmpty } from '@/object-record/record-field/utils/isFieldValueEmpty';
|
||||
import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
|
||||
export const useIsFieldEmpty = () => {
|
||||
const { recordId, fieldDefinition, overridenIsFieldEmpty } =
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { RelationFromManyFieldDisplay } from '@/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay';
|
||||
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import {
|
||||
RecordFieldValueSelectorContextProvider,
|
||||
useSetRecordFieldValue,
|
||||
} from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
|
||||
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
|
||||
import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
|
||||
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
import {
|
||||
fieldValue,
|
||||
otherPersonMock,
|
||||
relationFromManyFieldDisplayMock,
|
||||
} from './relationFromManyFieldDisplayMock';
|
||||
|
||||
const RelationFieldValueSetterEffect = () => {
|
||||
const setEntity = useSetRecoilState(
|
||||
recordStoreFamilyState(relationFromManyFieldDisplayMock.recordId),
|
||||
);
|
||||
|
||||
const setRelationEntity = useSetRecoilState(
|
||||
recordStoreFamilyState(relationFromManyFieldDisplayMock.relationRecordId),
|
||||
);
|
||||
|
||||
const setRecordFieldValue = useSetRecordFieldValue();
|
||||
|
||||
useEffect(() => {
|
||||
setEntity(relationFromManyFieldDisplayMock.entityValue);
|
||||
setRelationEntity(relationFromManyFieldDisplayMock.relationFieldValue);
|
||||
|
||||
setRecordFieldValue(
|
||||
relationFromManyFieldDisplayMock.entityValue.id,
|
||||
'company',
|
||||
[relationFromManyFieldDisplayMock.entityValue],
|
||||
);
|
||||
setRecordFieldValue(otherPersonMock.entityValue.id, 'company', [
|
||||
relationFromManyFieldDisplayMock.entityValue,
|
||||
]);
|
||||
setRecordFieldValue(
|
||||
relationFromManyFieldDisplayMock.relationFieldValue.id,
|
||||
'company',
|
||||
relationFromManyFieldDisplayMock.relationFieldValue,
|
||||
);
|
||||
}, [setEntity, setRelationEntity, setRecordFieldValue]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Display/RelationFromManyFieldDisplay',
|
||||
decorators: [
|
||||
MemoryRouterDecorator,
|
||||
ChipGeneratorsDecorator,
|
||||
(Story) => (
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
recordId: relationFromManyFieldDisplayMock.recordId,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition: {
|
||||
...relationFromManyFieldDisplayMock.fieldDefinition,
|
||||
} as unknown as FieldDefinition<FieldMetadata>,
|
||||
isReadOnly: false,
|
||||
}}
|
||||
>
|
||||
<RelationFieldValueSetterEffect />
|
||||
<Story />
|
||||
</FieldContext.Provider>
|
||||
</RecordFieldValueSelectorContextProvider>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
component: RelationFromManyFieldDisplay,
|
||||
argTypes: { value: { control: 'date' } },
|
||||
args: { fieldValue: fieldValue },
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof RelationFromManyFieldDisplay>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
// TODO: optimize this component once we have morph many
|
||||
export const Performance = getProfilingStory({
|
||||
componentName: 'RelationFromManyFieldDisplay',
|
||||
averageThresholdInMs: 1,
|
||||
numberOfRuns: 20,
|
||||
numberOfTestsPerRun: 100,
|
||||
});
|
||||
@ -1,13 +1,13 @@
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { PreComputedChipGeneratorsContext } from '@/object-metadata/contexts/PreComputedChipGeneratorsContext';
|
||||
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
||||
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
||||
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
||||
import { useRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isFieldActor } from '@/object-record/record-field/types/guards/isFieldActor';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
|
||||
@ -38,7 +38,7 @@ export const useChipFieldDisplay = () => {
|
||||
? fieldDefinition.metadata.objectMetadataNameSingular
|
||||
: undefined;
|
||||
|
||||
const recordValue = useRecordValue(recordId);
|
||||
const recordValue = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
|
||||
if (!isNonEmptyString(objectNameSingular)) {
|
||||
throw new Error('Object metadata name singular is not a non-empty string');
|
||||
|
||||
@ -11,7 +11,6 @@ import { recordIndexViewTypeState } from '@/object-record/record-index/states/re
|
||||
|
||||
import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||
|
||||
import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect';
|
||||
@ -48,48 +47,46 @@ export const RecordIndexContainer = () => {
|
||||
<>
|
||||
<StyledContainer>
|
||||
<InformationBannerWrapper />
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<SpreadsheetImportProvider>
|
||||
<ViewBar
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<ObjectOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
viewType={recordIndexViewType ?? ViewType.Table}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<RecordIndexViewBarEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
<SpreadsheetImportProvider>
|
||||
<ViewBar
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<ObjectOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
viewType={recordIndexViewType ?? ViewType.Table}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<RecordIndexViewBarEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</SpreadsheetImportProvider>
|
||||
<RecordIndexFiltersToContextStoreEffect />
|
||||
{recordIndexViewType === ViewType.Table && (
|
||||
<>
|
||||
<RecordIndexTableContainer
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</SpreadsheetImportProvider>
|
||||
<RecordIndexFiltersToContextStoreEffect />
|
||||
{recordIndexViewType === ViewType.Table && (
|
||||
<>
|
||||
<RecordIndexTableContainer
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexTableContainerEffect />
|
||||
</>
|
||||
)}
|
||||
{recordIndexViewType === ViewType.Kanban && (
|
||||
<StyledContainerWithPadding>
|
||||
<RecordIndexBoardContainer
|
||||
recordBoardId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
<RecordIndexBoardDataLoader
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexBoardDataLoaderEffect recordBoardId={recordIndexId} />
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
</RecordFieldValueSelectorContextProvider>
|
||||
<RecordIndexTableContainerEffect />
|
||||
</>
|
||||
)}
|
||||
{recordIndexViewType === ViewType.Kanban && (
|
||||
<StyledContainerWithPadding>
|
||||
<RecordIndexBoardContainer
|
||||
recordBoardId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
<RecordIndexBoardDataLoader
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexBoardDataLoaderEffect recordBoardId={recordIndexId} />
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
</StyledContainer>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -14,7 +14,7 @@ import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hook
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { useSetRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -32,7 +32,6 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
recordBoardId,
|
||||
columnId,
|
||||
}: UseLoadRecordIndexBoardProps) => {
|
||||
const setRecordValueInContextSelector = useSetRecordValue();
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
@ -102,10 +101,7 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
|
||||
useEffect(() => {
|
||||
upsertRecordsInStore(records);
|
||||
for (const record of records) {
|
||||
setRecordValueInContextSelector(record.id, record);
|
||||
}
|
||||
}, [records, upsertRecordsInStore, setRecordValueInContextSelector]);
|
||||
}, [records, upsertRecordsInStore]);
|
||||
|
||||
return {
|
||||
records,
|
||||
|
||||
@ -2,7 +2,6 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { buildFindOneRecordForShowPageOperationSignature } from '@/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory';
|
||||
import { useSetRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { useEffect } from 'react';
|
||||
@ -19,7 +18,6 @@ export const RecordShowEffect = ({
|
||||
}: RecordShowEffectProps) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular });
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const setRecordValueInContextSelector = useSetRecordValue();
|
||||
|
||||
const FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE =
|
||||
buildFindOneRecordForShowPageOperationSignature({
|
||||
@ -44,10 +42,8 @@ export const RecordShowEffect = ({
|
||||
if (JSON.stringify(previousRecordValue) !== JSON.stringify(newRecord)) {
|
||||
set(recordStoreFamilyState(recordId), newRecord);
|
||||
}
|
||||
|
||||
setRecordValueInContextSelector(recordId, newRecord);
|
||||
},
|
||||
[recordId, setRecordValueInContextSelector],
|
||||
[recordId],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -3,7 +3,7 @@ import { useContext, useEffect } from 'react';
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { useSetRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@ -14,8 +14,6 @@ type RecordDetailRelationRecordsListItemEffectProps = {
|
||||
export const RecordDetailRelationRecordsListItemEffect = ({
|
||||
relationRecordId,
|
||||
}: RecordDetailRelationRecordsListItemEffectProps) => {
|
||||
const setRecordValueInContextSelector = useSetRecordValue();
|
||||
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
|
||||
const { relationObjectMetadataNameSingular } =
|
||||
@ -31,9 +29,8 @@ export const RecordDetailRelationRecordsListItemEffect = ({
|
||||
useEffect(() => {
|
||||
if (isDefined(record)) {
|
||||
upsertRecords([record]);
|
||||
setRecordValueInContextSelector(record.id, record);
|
||||
}
|
||||
}, [record, upsertRecords, setRecordValueInContextSelector]);
|
||||
}, [record, upsertRecords]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -1,78 +1,16 @@
|
||||
import { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { createContext, useContextSelector } from 'use-context-selector';
|
||||
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
|
||||
export type RecordFieldValue = {
|
||||
[recordId: string]: {
|
||||
[fieldName: string]: any;
|
||||
};
|
||||
};
|
||||
|
||||
export const RecordFieldValueSelectorContext = createContext<
|
||||
[RecordFieldValue, Dispatch<SetStateAction<RecordFieldValue>>]
|
||||
>([{}, () => {}]);
|
||||
|
||||
export const useSetRecordValue = () => {
|
||||
const setTableValue = useContextSelector(
|
||||
RecordFieldValueSelectorContext,
|
||||
(value) => value[1],
|
||||
);
|
||||
|
||||
return (recordId: string, newRecord: any) => {
|
||||
setTableValue((currentTable) => ({
|
||||
...currentTable,
|
||||
[recordId]: newRecord,
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
export const useRecordValue = (recordId: string) => {
|
||||
const tableValue = useContextSelector(
|
||||
RecordFieldValueSelectorContext,
|
||||
(value) => value[0]?.[recordId],
|
||||
);
|
||||
|
||||
return tableValue as ObjectRecord | undefined;
|
||||
};
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const useRecordFieldValue = <T,>(
|
||||
recordId: string,
|
||||
fieldName: string,
|
||||
) => {
|
||||
const recordFieldValue = useContextSelector(
|
||||
RecordFieldValueSelectorContext,
|
||||
(value) => value[0]?.[recordId]?.[fieldName],
|
||||
const recordFieldValue = useRecoilValue(
|
||||
recordStoreFamilySelector({
|
||||
recordId,
|
||||
fieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
return recordFieldValue as T | undefined;
|
||||
};
|
||||
|
||||
export const useSetRecordFieldValue = () => {
|
||||
const setTableValue = useContextSelector(
|
||||
RecordFieldValueSelectorContext,
|
||||
(value) => value[1],
|
||||
);
|
||||
|
||||
return (recordId: string, fieldName: string, newValue: any) => {
|
||||
setTableValue((currentTable) => ({
|
||||
...currentTable,
|
||||
[recordId]: {
|
||||
...currentTable[recordId],
|
||||
[fieldName]: newValue,
|
||||
},
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
export const RecordFieldValueSelectorContextProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: any;
|
||||
}) => (
|
||||
<RecordFieldValueSelectorContext.Provider
|
||||
value={useState<RecordFieldValue>({})}
|
||||
>
|
||||
{children}
|
||||
</RecordFieldValueSelectorContext.Provider>
|
||||
);
|
||||
|
||||
@ -6,10 +6,6 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
|
||||
import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage';
|
||||
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import {
|
||||
RecordFieldValueSelectorContextProvider,
|
||||
useSetRecordValue,
|
||||
} from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
|
||||
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
||||
@ -36,22 +32,14 @@ const RelationFieldValueSetterEffect = () => {
|
||||
recordStoreFamilyState(mockPerformance.relationRecordId),
|
||||
);
|
||||
|
||||
const setRecordValue = useSetRecordValue();
|
||||
|
||||
const [, setObjectMetadataItems] = useRecoilState(objectMetadataItemsState);
|
||||
|
||||
useEffect(() => {
|
||||
setEntity(mockPerformance.entityValue);
|
||||
setRelationEntity(mockPerformance.relationFieldValue);
|
||||
|
||||
setRecordValue(mockPerformance.entityValue.id, mockPerformance.entityValue);
|
||||
setRecordValue(
|
||||
mockPerformance.relationFieldValue.id,
|
||||
mockPerformance.relationFieldValue,
|
||||
);
|
||||
|
||||
setObjectMetadataItems(generatedMockObjectMetadataItems);
|
||||
}, [setEntity, setRelationEntity, setRecordValue, setObjectMetadataItems]);
|
||||
}, [setEntity, setRelationEntity, setObjectMetadataItems]);
|
||||
|
||||
return null;
|
||||
};
|
||||
@ -63,95 +51,93 @@ const meta: Meta = {
|
||||
ChipGeneratorsDecorator,
|
||||
(Story) => {
|
||||
return (
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<RecordIndexContextProvider
|
||||
<RecordIndexContextProvider
|
||||
value={{
|
||||
indexIdentifierUrl: (_recordId: string) => '',
|
||||
onIndexRecordsLoaded: () => {},
|
||||
objectNamePlural: 'companies',
|
||||
objectNameSingular: 'company',
|
||||
objectMetadataItem: mockPerformance.objectMetadataItem as any,
|
||||
recordIndexId: 'recordIndexId',
|
||||
}}
|
||||
>
|
||||
<RecordTableContextProvider
|
||||
value={{
|
||||
indexIdentifierUrl: (_recordId: string) => '',
|
||||
onIndexRecordsLoaded: () => {},
|
||||
objectNamePlural: 'companies',
|
||||
objectNameSingular: 'company',
|
||||
recordTableId: 'recordTableId',
|
||||
viewBarId: mockPerformance.recordId,
|
||||
objectMetadataItem: mockPerformance.objectMetadataItem as any,
|
||||
recordIndexId: 'recordIndexId',
|
||||
visibleTableColumns: mockPerformance.visibleTableColumns as any,
|
||||
objectNameSingular:
|
||||
mockPerformance.objectMetadataItem.nameSingular,
|
||||
}}
|
||||
>
|
||||
<RecordTableContextProvider
|
||||
value={{
|
||||
recordTableId: 'recordTableId',
|
||||
viewBarId: mockPerformance.recordId,
|
||||
objectMetadataItem: mockPerformance.objectMetadataItem as any,
|
||||
visibleTableColumns: mockPerformance.visibleTableColumns as any,
|
||||
objectNameSingular:
|
||||
mockPerformance.objectMetadataItem.nameSingular,
|
||||
}}
|
||||
<RecordTableComponentInstance
|
||||
recordTableId="asd"
|
||||
onColumnsChange={() => {}}
|
||||
>
|
||||
<RecordTableComponentInstance
|
||||
recordTableId="asd"
|
||||
onColumnsChange={() => {}}
|
||||
<RecordTableBodyContextProvider
|
||||
value={{
|
||||
onOpenTableCell: () => {},
|
||||
onMoveFocus: () => {},
|
||||
onCloseTableCell: () => {},
|
||||
onMoveHoverToCurrentCell: () => {},
|
||||
onActionMenuDropdownOpened: () => {},
|
||||
onCellMouseEnter: () => {},
|
||||
}}
|
||||
>
|
||||
<RecordTableBodyContextProvider
|
||||
<RecordTableRowContextProvider
|
||||
value={{
|
||||
onOpenTableCell: () => {},
|
||||
onMoveFocus: () => {},
|
||||
onCloseTableCell: () => {},
|
||||
onMoveHoverToCurrentCell: () => {},
|
||||
onActionMenuDropdownOpened: () => {},
|
||||
onCellMouseEnter: () => {},
|
||||
objectNameSingular:
|
||||
mockPerformance.entityValue.__typename.toLocaleLowerCase(),
|
||||
recordId: mockPerformance.recordId,
|
||||
rowIndex: 0,
|
||||
pathToShowPage:
|
||||
getBasePathToShowPage({
|
||||
objectNameSingular:
|
||||
mockPerformance.entityValue.__typename.toLocaleLowerCase(),
|
||||
}) + mockPerformance.recordId,
|
||||
isSelected: false,
|
||||
inView: true,
|
||||
}}
|
||||
>
|
||||
<RecordTableRowContextProvider
|
||||
<RecordTableRowDraggableContextProvider
|
||||
value={{
|
||||
objectNameSingular:
|
||||
mockPerformance.entityValue.__typename.toLocaleLowerCase(),
|
||||
recordId: mockPerformance.recordId,
|
||||
rowIndex: 0,
|
||||
pathToShowPage:
|
||||
getBasePathToShowPage({
|
||||
objectNameSingular:
|
||||
mockPerformance.entityValue.__typename.toLocaleLowerCase(),
|
||||
}) + mockPerformance.recordId,
|
||||
isSelected: false,
|
||||
inView: true,
|
||||
isDragging: false,
|
||||
dragHandleProps: null,
|
||||
}}
|
||||
>
|
||||
<RecordTableRowDraggableContextProvider
|
||||
<RecordTableCellContext.Provider
|
||||
value={{
|
||||
isDragging: false,
|
||||
dragHandleProps: null,
|
||||
columnDefinition: mockPerformance.fieldDefinition,
|
||||
cellPosition: { row: 0, column: 0 },
|
||||
}}
|
||||
>
|
||||
<RecordTableCellContext.Provider
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
columnDefinition: mockPerformance.fieldDefinition,
|
||||
cellPosition: { row: 0, column: 0 },
|
||||
recordId: mockPerformance.recordId,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition: {
|
||||
...mockPerformance.fieldDefinition,
|
||||
},
|
||||
isReadOnly: false,
|
||||
}}
|
||||
>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
recordId: mockPerformance.recordId,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition: {
|
||||
...mockPerformance.fieldDefinition,
|
||||
},
|
||||
isReadOnly: false,
|
||||
}}
|
||||
>
|
||||
<RelationFieldValueSetterEffect />
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<Story />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</FieldContext.Provider>
|
||||
</RecordTableCellContext.Provider>
|
||||
</RecordTableRowDraggableContextProvider>
|
||||
</RecordTableRowContextProvider>
|
||||
</RecordTableBodyContextProvider>
|
||||
</RecordTableComponentInstance>
|
||||
</RecordTableContextProvider>
|
||||
</RecordIndexContextProvider>
|
||||
</RecordFieldValueSelectorContextProvider>
|
||||
<RelationFieldValueSetterEffect />
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<Story />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</FieldContext.Provider>
|
||||
</RecordTableCellContext.Provider>
|
||||
</RecordTableRowDraggableContextProvider>
|
||||
</RecordTableRowContextProvider>
|
||||
</RecordTableBodyContextProvider>
|
||||
</RecordTableComponentInstance>
|
||||
</RecordTableContextProvider>
|
||||
</RecordIndexContextProvider>
|
||||
);
|
||||
},
|
||||
ComponentDecorator,
|
||||
|
||||
@ -2,7 +2,7 @@ import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
||||
import { useSetRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useSetIsRecordTableFocusActive } from '@/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive';
|
||||
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
|
||||
@ -27,8 +27,6 @@ export const useSetRecordTableData = ({
|
||||
recordTableId,
|
||||
onEntityCountChange,
|
||||
}: useSetRecordTableDataProps) => {
|
||||
const setRecordValueInContextSelector = useSetRecordValue();
|
||||
|
||||
const recordIndexRecordIdsByGroupFamilyState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
recordIndexRecordIdsByGroupComponentFamilyState,
|
||||
@ -82,7 +80,6 @@ export const useSetRecordTableData = ({
|
||||
};
|
||||
|
||||
set(recordStoreFamilyState(record.id), newRecord);
|
||||
setRecordValueInContextSelector(record.id, newRecord);
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +127,6 @@ export const useSetRecordTableData = ({
|
||||
setRecordTableHoverPosition,
|
||||
onEntityCountChange,
|
||||
isRowSelectedFamilyState,
|
||||
setRecordValueInContextSelector,
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { INLINE_CELL_HOTKEY_SCOPE_MEMOIZE_KEY } from '@/object-record/record-inline-cell/constants/InlineCellHotkeyScopeMemoizeKey';
|
||||
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
|
||||
import { useRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { TitleInputHotkeyScope } from '@/ui/input/types/TitleInputHotkeyScope';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { Theme, withTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
|
||||
|
||||
const StyledDiv = styled.div`
|
||||
@ -33,7 +34,9 @@ const StyledEmptyText = withTheme(styled.div<{ theme: Theme }>`
|
||||
|
||||
export const RecordTitleCellSingleTextDisplayMode = () => {
|
||||
const { recordId, fieldDefinition } = useContext(FieldContext);
|
||||
const recordValue = useRecordValue(recordId);
|
||||
|
||||
const recordValue = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
|
||||
const isEmpty =
|
||||
recordValue?.[fieldDefinition.metadata.fieldName]?.trim() === '';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user