@ -1,9 +1,8 @@
|
|||||||
import { expect } from '@storybook/test';
|
import { renderHook, waitFor } from '@testing-library/react';
|
||||||
import { renderHook } from '@testing-library/react';
|
import { ReactNode } from 'react';
|
||||||
import { ReactNode, act } from 'react';
|
|
||||||
|
|
||||||
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
|
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
|
||||||
import { useLazyLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLazyLoadRecordIndexTable';
|
import { useRecordIndexTableQuery } from '@/object-record/record-index/hooks/useRecordIndexTableQuery';
|
||||||
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
|
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
|
||||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||||
import { MockedResponse } from '@apollo/client/testing';
|
import { MockedResponse } from '@apollo/client/testing';
|
||||||
@ -679,16 +678,14 @@ const Wrapper = ({ children }: { children: ReactNode }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('useLazyLoadRecordIndexTable', () => {
|
describe('useRecordIndexTableQuery', () => {
|
||||||
it('should fetch', async () => {
|
it('should fetch', async () => {
|
||||||
const { result } = renderHook(
|
const { result } = renderHook(
|
||||||
() => {
|
() => {
|
||||||
const { findManyRecords, ...result } =
|
const { records } = useRecordIndexTableQuery(objectNameSingular);
|
||||||
useLazyLoadRecordIndexTable(objectNameSingular);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
findManyRecords,
|
records,
|
||||||
...result,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -696,12 +693,8 @@ describe('useLazyLoadRecordIndexTable', () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.current.loading).toBe(false);
|
await waitFor(() => {
|
||||||
|
|
||||||
await act(async () => {
|
|
||||||
await result.current.findManyRecords();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.current.records).toHaveLength(16);
|
expect(result.current.records).toHaveLength(16);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@ -24,10 +24,10 @@ import { OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyReco
|
|||||||
import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor';
|
import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor';
|
||||||
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
|
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
|
||||||
|
|
||||||
|
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||||
import { cursorFamilyState } from '../states/cursorFamilyState';
|
import { cursorFamilyState } from '../states/cursorFamilyState';
|
||||||
import { hasNextPageFamilyState } from '../states/hasNextPageFamilyState';
|
import { hasNextPageFamilyState } from '../states/hasNextPageFamilyState';
|
||||||
import { isFetchingMoreRecordsFamilyState } from '../states/isFetchingMoreRecordsFamilyState';
|
import { isFetchingMoreRecordsFamilyState } from '../states/isFetchingMoreRecordsFamilyState';
|
||||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
|
||||||
|
|
||||||
export type UseFindManyRecordsParams<T> = ObjectMetadataItemIdentifier &
|
export type UseFindManyRecordsParams<T> = ObjectMetadataItemIdentifier &
|
||||||
RecordGqlOperationVariables & {
|
RecordGqlOperationVariables & {
|
||||||
|
|||||||
@ -119,7 +119,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
fetchMoreRecords,
|
fetchMoreRecords,
|
||||||
queryStateIdentifier: queryIdentifier,
|
queryIdentifier,
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
pageInfo,
|
pageInfo,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||||
@ -6,6 +6,7 @@ import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/
|
|||||||
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
|
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
|
||||||
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
|
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
|
||||||
import { OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyRecordsCompleted';
|
import { OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyRecordsCompleted';
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
export const useHandleFindManyRecordsCompleted = <T>({
|
export const useHandleFindManyRecordsCompleted = <T>({
|
||||||
@ -17,15 +18,14 @@ export const useHandleFindManyRecordsCompleted = <T>({
|
|||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem;
|
||||||
onCompleted?: OnFindManyRecordsCompleted<T>;
|
onCompleted?: OnFindManyRecordsCompleted<T>;
|
||||||
}) => {
|
}) => {
|
||||||
const [, setLastCursor] = useRecoilState(cursorFamilyState(queryIdentifier));
|
const setLastCursor = useSetRecoilState(cursorFamilyState(queryIdentifier));
|
||||||
|
|
||||||
const [, setHasNextPage] = useRecoilState(
|
const setHasNextPage = useSetRecoilState(
|
||||||
hasNextPageFamilyState(queryIdentifier),
|
hasNextPageFamilyState(queryIdentifier),
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFindManyRecordsCompleted = (
|
const handleFindManyRecordsCompleted = useCallback(
|
||||||
data: RecordGqlOperationFindManyResult,
|
(data: RecordGqlOperationFindManyResult) => {
|
||||||
) => {
|
|
||||||
if (!isDefined(data)) {
|
if (!isDefined(data)) {
|
||||||
onCompleted?.([]);
|
onCompleted?.([]);
|
||||||
}
|
}
|
||||||
@ -45,7 +45,9 @@ export const useHandleFindManyRecordsCompleted = <T>({
|
|||||||
setLastCursor(pageInfo.endCursor ?? '');
|
setLastCursor(pageInfo.endCursor ?? '');
|
||||||
setHasNextPage(pageInfo.hasNextPage ?? false);
|
setHasNextPage(pageInfo.hasNextPage ?? false);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[onCompleted, objectMetadataItem.namePlural, setLastCursor, setHasNextPage],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleFindManyRecordsCompleted,
|
handleFindManyRecordsCompleted,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
|||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { logError } from '~/utils/logError';
|
import { logError } from '~/utils/logError';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
export const useHandleFindManyRecordsError = ({
|
export const useHandleFindManyRecordsError = ({
|
||||||
handleError,
|
handleError,
|
||||||
@ -14,7 +15,8 @@ export const useHandleFindManyRecordsError = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
|
||||||
const handleFindManyRecordsError = (error: ApolloError) => {
|
const handleFindManyRecordsError = useCallback(
|
||||||
|
(error: ApolloError) => {
|
||||||
logError(
|
logError(
|
||||||
`useFindManyRecords for "${objectMetadataItem.namePlural}" error : ` +
|
`useFindManyRecords for "${objectMetadataItem.namePlural}" error : ` +
|
||||||
error,
|
error,
|
||||||
@ -23,7 +25,9 @@ export const useHandleFindManyRecordsError = ({
|
|||||||
variant: SnackBarVariant.Error,
|
variant: SnackBarVariant.Error,
|
||||||
});
|
});
|
||||||
handleError?.(error);
|
handleError?.(error);
|
||||||
};
|
},
|
||||||
|
[enqueueSnackBar, handleError, objectMetadataItem.namePlural],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleFindManyRecordsError,
|
handleFindManyRecordsError,
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export const useLazyFetchAllRecords = <T>({
|
|||||||
const [progress, setProgress] = useState<ExportProgress>({
|
const [progress, setProgress] = useState<ExportProgress>({
|
||||||
displayType: 'number',
|
displayType: 'number',
|
||||||
});
|
});
|
||||||
const { fetchMore, findManyRecords } = useLazyFindManyRecords({
|
const { fetchMoreRecordsLazy, findManyRecordsLazy } = useLazyFindManyRecords({
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
filter,
|
filter,
|
||||||
orderBy,
|
orderBy,
|
||||||
@ -47,12 +47,12 @@ export const useLazyFetchAllRecords = <T>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const fetchAllRecords = useCallback(async () => {
|
const fetchAllRecords = useCallback(async () => {
|
||||||
if (!isDefined(findManyRecords)) {
|
if (!isDefined(findManyRecordsLazy)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
setIsDownloading(true);
|
setIsDownloading(true);
|
||||||
|
|
||||||
const findManyRecordsDataResult = await findManyRecords();
|
const findManyRecordsDataResult = await findManyRecordsLazy();
|
||||||
|
|
||||||
const firstQueryResult =
|
const firstQueryResult =
|
||||||
findManyRecordsDataResult?.data?.[objectMetadataItem.namePlural];
|
findManyRecordsDataResult?.data?.[objectMetadataItem.namePlural];
|
||||||
@ -84,7 +84,7 @@ export const useLazyFetchAllRecords = <T>({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(fetchMore)) {
|
if (!isDefined(fetchMoreRecordsLazy)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,12 +92,7 @@ export const useLazyFetchAllRecords = <T>({
|
|||||||
await sleep(delayMs);
|
await sleep(delayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawResult = await fetchMore({
|
const rawResult = await fetchMoreRecordsLazy();
|
||||||
variables: {
|
|
||||||
lastCursor: lastCursor,
|
|
||||||
limit,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetchMoreResult = rawResult?.data?.[objectMetadataItem.namePlural];
|
const fetchMoreResult = rawResult?.data?.[objectMetadataItem.namePlural];
|
||||||
|
|
||||||
@ -126,8 +121,8 @@ export const useLazyFetchAllRecords = <T>({
|
|||||||
return records;
|
return records;
|
||||||
}, [
|
}, [
|
||||||
delayMs,
|
delayMs,
|
||||||
fetchMore,
|
fetchMoreRecordsLazy,
|
||||||
findManyRecords,
|
findManyRecordsLazy,
|
||||||
objectMetadataItem.namePlural,
|
objectMetadataItem.namePlural,
|
||||||
limit,
|
limit,
|
||||||
maximumRequests,
|
maximumRequests,
|
||||||
|
|||||||
@ -0,0 +1,194 @@
|
|||||||
|
import {
|
||||||
|
ApolloError,
|
||||||
|
ApolloQueryResult,
|
||||||
|
FetchMoreQueryOptions,
|
||||||
|
OperationVariables,
|
||||||
|
WatchQueryFetchPolicy,
|
||||||
|
} from '@apollo/client';
|
||||||
|
import { isNonEmptyArray } from '@apollo/client/utilities';
|
||||||
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
|
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||||
|
import { isAggregationEnabled } from '@/object-metadata/utils/isAggregationEnabled';
|
||||||
|
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||||
|
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
|
||||||
|
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
|
||||||
|
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||||
|
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||||
|
import { useHandleFindManyRecordsError } from '@/object-record/hooks/useHandleFindManyRecordsError';
|
||||||
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
|
import { OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyRecordsCompleted';
|
||||||
|
import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor';
|
||||||
|
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
|
||||||
|
|
||||||
|
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||||
|
import { cursorFamilyState } from '../states/cursorFamilyState';
|
||||||
|
import { hasNextPageFamilyState } from '../states/hasNextPageFamilyState';
|
||||||
|
|
||||||
|
export type UseFindManyRecordsParams<T> = ObjectMetadataItemIdentifier &
|
||||||
|
RecordGqlOperationVariables & {
|
||||||
|
onCompleted?: OnFindManyRecordsCompleted<T>;
|
||||||
|
skip?: boolean;
|
||||||
|
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||||
|
fetchPolicy?: WatchQueryFetchPolicy;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UseFindManyRecordsStateParams<
|
||||||
|
T,
|
||||||
|
TData = RecordGqlOperationFindManyResult,
|
||||||
|
> = Omit<
|
||||||
|
UseFindManyRecordsParams<T>,
|
||||||
|
'skip' | 'recordGqlFields' | 'fetchPolicy' | 'onCompleted'
|
||||||
|
> & {
|
||||||
|
data: RecordGqlOperationFindManyResult | undefined;
|
||||||
|
error: ApolloError | undefined;
|
||||||
|
fetchMore<
|
||||||
|
TFetchData = TData,
|
||||||
|
TFetchVars extends OperationVariables = OperationVariables,
|
||||||
|
>(
|
||||||
|
fetchMoreOptions: FetchMoreQueryOptions<TFetchVars, TFetchData> & {
|
||||||
|
updateQuery?: (
|
||||||
|
previousQueryResult: TData,
|
||||||
|
options: {
|
||||||
|
fetchMoreResult: TFetchData;
|
||||||
|
variables: TFetchVars;
|
||||||
|
},
|
||||||
|
) => TData;
|
||||||
|
},
|
||||||
|
): Promise<ApolloQueryResult<TFetchData>>;
|
||||||
|
objectMetadataItem: ObjectMetadataItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useLazyFetchMoreRecordsWithPagination = <
|
||||||
|
T extends ObjectRecord = ObjectRecord,
|
||||||
|
>({
|
||||||
|
objectNameSingular,
|
||||||
|
filter,
|
||||||
|
orderBy,
|
||||||
|
limit,
|
||||||
|
error,
|
||||||
|
fetchMore,
|
||||||
|
objectMetadataItem,
|
||||||
|
}: UseFindManyRecordsStateParams<T>) => {
|
||||||
|
const queryIdentifier = getQueryIdentifier({
|
||||||
|
objectNameSingular,
|
||||||
|
filter,
|
||||||
|
limit,
|
||||||
|
orderBy,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { handleFindManyRecordsError } = useHandleFindManyRecordsError({
|
||||||
|
objectMetadataItem,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: put this into a util inspired from https://github.com/apollographql/apollo-client/blob/master/src/utilities/policies/pagination.ts
|
||||||
|
// This function is equivalent to merge function + read function in field policy
|
||||||
|
const fetchMoreRecordsLazy = useRecoilCallback(
|
||||||
|
({ snapshot, set }) =>
|
||||||
|
async () => {
|
||||||
|
const hasNextPageLocal = snapshot
|
||||||
|
.getLoadable(hasNextPageFamilyState(queryIdentifier))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const lastCursorLocal = snapshot
|
||||||
|
.getLoadable(cursorFamilyState(queryIdentifier))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
// Remote objects does not support hasNextPage. We cannot rely on it to fetch more records.
|
||||||
|
if (
|
||||||
|
hasNextPageLocal ||
|
||||||
|
(!isAggregationEnabled(objectMetadataItem) && !error)
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const { data: fetchMoreDataResult } = await fetchMore({
|
||||||
|
variables: {
|
||||||
|
filter,
|
||||||
|
orderBy,
|
||||||
|
lastCursor: isNonEmptyString(lastCursorLocal)
|
||||||
|
? lastCursorLocal
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
updateQuery: (prev, { fetchMoreResult }) => {
|
||||||
|
const previousEdges =
|
||||||
|
prev?.[objectMetadataItem.namePlural]?.edges;
|
||||||
|
const nextEdges =
|
||||||
|
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
|
||||||
|
|
||||||
|
let newEdges: RecordGqlEdge[] = previousEdges ?? [];
|
||||||
|
|
||||||
|
if (isNonEmptyArray(nextEdges)) {
|
||||||
|
newEdges = filterUniqueRecordEdgesByCursor([
|
||||||
|
...newEdges,
|
||||||
|
...(fetchMoreResult?.[objectMetadataItem.namePlural]
|
||||||
|
?.edges ?? []),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageInfo =
|
||||||
|
fetchMoreResult?.[objectMetadataItem.namePlural]?.pageInfo;
|
||||||
|
|
||||||
|
if (isDefined(pageInfo)) {
|
||||||
|
set(
|
||||||
|
cursorFamilyState(queryIdentifier),
|
||||||
|
pageInfo.endCursor ?? '',
|
||||||
|
);
|
||||||
|
set(
|
||||||
|
hasNextPageFamilyState(queryIdentifier),
|
||||||
|
pageInfo.hasNextPage ?? false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign({}, prev, {
|
||||||
|
[objectMetadataItem.namePlural]: {
|
||||||
|
__typename: `${capitalize(
|
||||||
|
objectMetadataItem.nameSingular,
|
||||||
|
)}Connection`,
|
||||||
|
edges: newEdges,
|
||||||
|
pageInfo:
|
||||||
|
fetchMoreResult?.[objectMetadataItem.namePlural].pageInfo,
|
||||||
|
totalCount:
|
||||||
|
fetchMoreResult?.[objectMetadataItem.namePlural]
|
||||||
|
.totalCount,
|
||||||
|
},
|
||||||
|
} as RecordGqlOperationFindManyResult);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: fetchMoreDataResult?.[objectMetadataItem.namePlural],
|
||||||
|
totalCount:
|
||||||
|
fetchMoreDataResult?.[objectMetadataItem.namePlural]
|
||||||
|
?.totalCount,
|
||||||
|
records: getRecordsFromRecordConnection({
|
||||||
|
recordConnection: {
|
||||||
|
edges:
|
||||||
|
fetchMoreDataResult?.[objectMetadataItem.namePlural]?.edges,
|
||||||
|
pageInfo:
|
||||||
|
fetchMoreDataResult?.[objectMetadataItem.namePlural]
|
||||||
|
?.pageInfo,
|
||||||
|
},
|
||||||
|
}) as T[],
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
handleFindManyRecordsError(error as ApolloError);
|
||||||
|
return { error: error as ApolloError };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
queryIdentifier,
|
||||||
|
objectMetadataItem,
|
||||||
|
error,
|
||||||
|
fetchMore,
|
||||||
|
filter,
|
||||||
|
orderBy,
|
||||||
|
handleFindManyRecordsError,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
fetchMoreRecordsLazy,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -2,12 +2,13 @@ import { useLazyQuery } from '@apollo/client';
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
|
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||||
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
|
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
|
||||||
import { useFetchMoreRecordsWithPagination } from '@/object-record/hooks/useFetchMoreRecordsWithPagination';
|
|
||||||
import { UseFindManyRecordsParams } from '@/object-record/hooks/useFindManyRecords';
|
import { UseFindManyRecordsParams } from '@/object-record/hooks/useFindManyRecords';
|
||||||
import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery';
|
import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery';
|
||||||
import { useHandleFindManyRecordsCompleted } from '@/object-record/hooks/useHandleFindManyRecordsCompleted';
|
import { useHandleFindManyRecordsCompleted } from '@/object-record/hooks/useHandleFindManyRecordsCompleted';
|
||||||
import { useHandleFindManyRecordsError } from '@/object-record/hooks/useHandleFindManyRecordsError';
|
import { useHandleFindManyRecordsError } from '@/object-record/hooks/useHandleFindManyRecordsError';
|
||||||
|
import { useLazyFetchMoreRecordsWithPagination } from '@/object-record/hooks/useLazyFetchMoreRecordsWithPagination';
|
||||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||||
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
|
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
|
||||||
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
|
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
|
||||||
@ -16,7 +17,7 @@ import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
|
|||||||
|
|
||||||
type UseLazyFindManyRecordsParams<T> = Omit<
|
type UseLazyFindManyRecordsParams<T> = Omit<
|
||||||
UseFindManyRecordsParams<T>,
|
UseFindManyRecordsParams<T>,
|
||||||
'skip'
|
'skip' | 'onCompleted' | 'onError'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||||
@ -25,9 +26,6 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
orderBy,
|
orderBy,
|
||||||
limit,
|
limit,
|
||||||
recordGqlFields,
|
recordGqlFields,
|
||||||
fetchPolicy,
|
|
||||||
onCompleted,
|
|
||||||
onError,
|
|
||||||
}: UseLazyFindManyRecordsParams<T>) => {
|
}: UseLazyFindManyRecordsParams<T>) => {
|
||||||
const { objectMetadataItem } = useObjectMetadataItem({
|
const { objectMetadataItem } = useObjectMetadataItem({
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
@ -40,7 +38,6 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
|
|
||||||
const { handleFindManyRecordsError } = useHandleFindManyRecordsError({
|
const { handleFindManyRecordsError } = useHandleFindManyRecordsError({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
handleError: onError,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryIdentifier = getQueryIdentifier({
|
const queryIdentifier = getQueryIdentifier({
|
||||||
@ -53,7 +50,6 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
const { handleFindManyRecordsCompleted } = useHandleFindManyRecordsCompleted({
|
const { handleFindManyRecordsCompleted } = useHandleFindManyRecordsCompleted({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
queryIdentifier,
|
queryIdentifier,
|
||||||
onCompleted,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const objectPermissions = useObjectPermissionsForObject(
|
const objectPermissions = useObjectPermissionsForObject(
|
||||||
@ -62,25 +58,23 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
|
|
||||||
const hasReadPermission = objectPermissions.canReadObjectRecords;
|
const hasReadPermission = objectPermissions.canReadObjectRecords;
|
||||||
|
|
||||||
const [findManyRecords, { data, loading, error, fetchMore }] =
|
const [findManyRecords, { data, error, fetchMore }] =
|
||||||
useLazyQuery<RecordGqlOperationFindManyResult>(findManyRecordsQuery, {
|
useLazyQuery<RecordGqlOperationFindManyResult>(findManyRecordsQuery, {
|
||||||
variables: {
|
variables: {
|
||||||
filter,
|
filter,
|
||||||
limit,
|
limit,
|
||||||
orderBy,
|
orderBy,
|
||||||
},
|
},
|
||||||
fetchPolicy: fetchPolicy,
|
fetchPolicy: 'network-only',
|
||||||
onCompleted: handleFindManyRecordsCompleted,
|
onCompleted: handleFindManyRecordsCompleted,
|
||||||
onError: handleFindManyRecordsError,
|
onError: handleFindManyRecordsError,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { fetchMoreRecords, totalCount, records, hasNextPage } =
|
const { fetchMoreRecordsLazy } = useLazyFetchMoreRecordsWithPagination<T>({
|
||||||
useFetchMoreRecordsWithPagination<T>({
|
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
filter,
|
filter,
|
||||||
orderBy,
|
orderBy,
|
||||||
limit,
|
limit,
|
||||||
onCompleted,
|
|
||||||
fetchMore,
|
fetchMore,
|
||||||
data,
|
data,
|
||||||
error,
|
error,
|
||||||
@ -96,9 +90,10 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
data: null,
|
data: null,
|
||||||
loading: false,
|
records: [],
|
||||||
|
totalCount: 0,
|
||||||
|
hasNextPage: false,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
called: true,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +110,29 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
set(hasNextPageFamilyState(queryIdentifier), hasNextPage);
|
set(hasNextPageFamilyState(queryIdentifier), hasNextPage);
|
||||||
set(cursorFamilyState(queryIdentifier), lastCursor);
|
set(cursorFamilyState(queryIdentifier), lastCursor);
|
||||||
|
|
||||||
return result;
|
const records = getRecordsFromRecordConnection({
|
||||||
|
recordConnection: {
|
||||||
|
edges: result?.data?.[objectMetadataItem.namePlural]?.edges ?? [],
|
||||||
|
pageInfo: result?.data?.[objectMetadataItem.namePlural]
|
||||||
|
?.pageInfo ?? {
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: '',
|
||||||
|
endCursor: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalCount =
|
||||||
|
result?.data?.[objectMetadataItem.namePlural]?.totalCount ?? 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: result?.data,
|
||||||
|
records,
|
||||||
|
totalCount,
|
||||||
|
hasNextPage,
|
||||||
|
error: result?.error,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
hasReadPermission,
|
hasReadPermission,
|
||||||
@ -126,16 +143,8 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
objectMetadataItem,
|
findManyRecordsLazy,
|
||||||
records,
|
fetchMoreRecordsLazy,
|
||||||
totalCount,
|
queryIdentifier,
|
||||||
loading: hasReadPermission ? loading : false,
|
|
||||||
error: hasReadPermission ? error : undefined,
|
|
||||||
fetchMore,
|
|
||||||
fetchMoreRecords,
|
|
||||||
queryStateIdentifier: queryIdentifier,
|
|
||||||
findManyRecords: findManyRecordsLazy,
|
|
||||||
hasNextPage,
|
|
||||||
hasReadPermission,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,8 +6,6 @@ import { useRecoilValue } from 'recoil';
|
|||||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||||
import { isRecordBoardFetchingRecordsByColumnFamilyState } from '@/object-record/record-board/states/isRecordBoardFetchingRecordsByColumnFamilyState';
|
import { isRecordBoardFetchingRecordsByColumnFamilyState } from '@/object-record/record-board/states/isRecordBoardFetchingRecordsByColumnFamilyState';
|
||||||
import { recordBoardShouldFetchMoreInColumnComponentFamilyState } from '@/object-record/record-board/states/recordBoardShouldFetchMoreInColumnComponentFamilyState';
|
import { recordBoardShouldFetchMoreInColumnComponentFamilyState } from '@/object-record/record-board/states/recordBoardShouldFetchMoreInColumnComponentFamilyState';
|
||||||
import { isRecordIndexLoadMoreLockedComponentState } from '@/object-record/record-index/states/isRecordIndexLoadMoreLockedComponentState';
|
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
|
||||||
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
||||||
import { GRAY_SCALE } from 'twenty-ui/theme';
|
import { GRAY_SCALE } from 'twenty-ui/theme';
|
||||||
|
|
||||||
@ -33,23 +31,11 @@ export const RecordBoardColumnFetchMoreLoader = () => {
|
|||||||
columnDefinition.id,
|
columnDefinition.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isLoadMoreLocked = useRecoilComponentValueV2(
|
|
||||||
isRecordIndexLoadMoreLockedComponentState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { ref, inView } = useInView();
|
const { ref, inView } = useInView();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoadMoreLocked) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setShouldFetchMore(inView);
|
setShouldFetchMore(inView);
|
||||||
}, [setShouldFetchMore, inView, isLoadMoreLocked]);
|
}, [setShouldFetchMore, inView]);
|
||||||
|
|
||||||
if (isLoadMoreLocked) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
|
||||||
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
|
|
||||||
import { useFindManyRecordIndexTableParams } from '@/object-record/record-index/hooks/useFindManyRecordIndexTableParams';
|
|
||||||
import { useRecordTableRecordGqlFields } from '@/object-record/record-index/hooks/useRecordTableRecordGqlFields';
|
|
||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
|
||||||
import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies';
|
|
||||||
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
|
||||||
|
|
||||||
export const useLazyLoadRecordIndexTable = (objectNameSingular: string) => {
|
|
||||||
const showAuthModal = useShowAuthModal();
|
|
||||||
|
|
||||||
const { objectMetadataItem } = useObjectMetadataItem({
|
|
||||||
objectNameSingular,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { setRecordTableData, setIsRecordTableInitialLoading } =
|
|
||||||
useRecordTable();
|
|
||||||
|
|
||||||
const params = useFindManyRecordIndexTableParams(objectNameSingular);
|
|
||||||
|
|
||||||
const recordGqlFields = useRecordTableRecordGqlFields({ objectMetadataItem });
|
|
||||||
|
|
||||||
const {
|
|
||||||
findManyRecords,
|
|
||||||
records,
|
|
||||||
loading,
|
|
||||||
totalCount,
|
|
||||||
fetchMoreRecords,
|
|
||||||
queryStateIdentifier,
|
|
||||||
hasNextPage,
|
|
||||||
} = useLazyFindManyRecords({
|
|
||||||
...params,
|
|
||||||
recordGqlFields,
|
|
||||||
onCompleted: () => {
|
|
||||||
setIsRecordTableInitialLoading(false);
|
|
||||||
},
|
|
||||||
onError: () => {
|
|
||||||
setIsRecordTableInitialLoading(false);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
findManyRecords,
|
|
||||||
records: !showAuthModal ? records : SIGN_IN_BACKGROUND_MOCK_COMPANIES,
|
|
||||||
totalCount: totalCount,
|
|
||||||
loading,
|
|
||||||
fetchMoreRecords,
|
|
||||||
queryStateIdentifier,
|
|
||||||
setRecordTableData,
|
|
||||||
hasNextPage,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -84,13 +84,8 @@ export const useLoadRecordIndexBoardColumn = ({
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const {
|
const { records, loading, fetchMoreRecords, queryIdentifier, hasNextPage } =
|
||||||
records,
|
useFindManyRecords({
|
||||||
loading,
|
|
||||||
fetchMoreRecords,
|
|
||||||
queryStateIdentifier,
|
|
||||||
hasNextPage,
|
|
||||||
} = useFindManyRecords({
|
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
filter: combinedFilters,
|
filter: combinedFilters,
|
||||||
orderBy,
|
orderBy,
|
||||||
@ -110,7 +105,7 @@ export const useLoadRecordIndexBoardColumn = ({
|
|||||||
records,
|
records,
|
||||||
loading,
|
loading,
|
||||||
fetchMoreRecords,
|
fetchMoreRecords,
|
||||||
queryStateIdentifier,
|
queryIdentifier,
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
|
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
|
||||||
|
import { useFindManyRecordIndexTableParams } from '@/object-record/record-index/hooks/useFindManyRecordIndexTableParams';
|
||||||
|
import { useRecordTableRecordGqlFields } from '@/object-record/record-index/hooks/useRecordTableRecordGqlFields';
|
||||||
|
|
||||||
|
export const useRecordIndexTableFetchMore = (objectNameSingular: string) => {
|
||||||
|
const { objectMetadataItem } = useObjectMetadataItem({
|
||||||
|
objectNameSingular,
|
||||||
|
});
|
||||||
|
|
||||||
|
const params = useFindManyRecordIndexTableParams(objectNameSingular);
|
||||||
|
|
||||||
|
const recordGqlFields = useRecordTableRecordGqlFields({ objectMetadataItem });
|
||||||
|
|
||||||
|
const { fetchMoreRecordsLazy, queryIdentifier } = useLazyFindManyRecords({
|
||||||
|
...params,
|
||||||
|
recordGqlFields,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
fetchMoreRecordsLazy,
|
||||||
|
queryIdentifier,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
|
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||||
|
import { useFindManyRecordIndexTableParams } from '@/object-record/record-index/hooks/useFindManyRecordIndexTableParams';
|
||||||
|
import { useRecordTableRecordGqlFields } from '@/object-record/record-index/hooks/useRecordTableRecordGqlFields';
|
||||||
|
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
|
import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies';
|
||||||
|
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
||||||
|
|
||||||
|
export const useRecordIndexTableQuery = (objectNameSingular: string) => {
|
||||||
|
const { recordTableId } = useRecordTableContextOrThrow();
|
||||||
|
const { objectMetadataItem } = useObjectMetadataItem({
|
||||||
|
objectNameSingular,
|
||||||
|
});
|
||||||
|
|
||||||
|
const showAuthModal = useShowAuthModal();
|
||||||
|
|
||||||
|
const params = useFindManyRecordIndexTableParams(objectNameSingular);
|
||||||
|
|
||||||
|
const recordGqlFields = useRecordTableRecordGqlFields({ objectMetadataItem });
|
||||||
|
|
||||||
|
const { records, hasNextPage, queryIdentifier, loading } = useFindManyRecords(
|
||||||
|
{
|
||||||
|
...params,
|
||||||
|
recordGqlFields,
|
||||||
|
skip: showAuthModal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
records: showAuthModal ? SIGN_IN_BACKGROUND_MOCK_COMPANIES : records,
|
||||||
|
loading: showAuthModal ? false : loading,
|
||||||
|
hasNextPage,
|
||||||
|
queryIdentifier,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
|
||||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
|
||||||
|
|
||||||
export const isRecordIndexLoadMoreLockedComponentState =
|
|
||||||
createComponentStateV2<boolean>({
|
|
||||||
key: 'isRecordIndexLoadMoreLockedComponentState',
|
|
||||||
componentInstanceContext: ViewComponentInstanceContext,
|
|
||||||
defaultValue: false,
|
|
||||||
});
|
|
||||||
@ -6,7 +6,6 @@ import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefin
|
|||||||
|
|
||||||
type RecordTableComponentInstanceEffectProps = {
|
type RecordTableComponentInstanceEffectProps = {
|
||||||
onColumnsChange: (columns: ColumnDefinition<FieldMetadata>[]) => void;
|
onColumnsChange: (columns: ColumnDefinition<FieldMetadata>[]) => void;
|
||||||
onEntityCountChange?: (count: number) => void | Promise<void>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RecordTableComponentInstanceEffect = ({
|
export const RecordTableComponentInstanceEffect = ({
|
||||||
|
|||||||
@ -11,24 +11,20 @@ import { recordTableHoverPositionComponentState } from '@/object-record/record-t
|
|||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||||
|
import { useRecoilComponentFamilyCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyCallbackStateV2';
|
||||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
|
|
||||||
type useSetRecordTableDataProps = {
|
type useSetRecordTableDataProps = {
|
||||||
recordTableId?: string;
|
recordTableId?: string;
|
||||||
onEntityCountChange: (
|
|
||||||
entityCount?: number,
|
|
||||||
currentRecordGroupId?: string,
|
|
||||||
) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSetRecordTableData = ({
|
export const useSetRecordTableData = ({
|
||||||
recordTableId,
|
recordTableId,
|
||||||
onEntityCountChange,
|
|
||||||
}: useSetRecordTableDataProps) => {
|
}: useSetRecordTableDataProps) => {
|
||||||
const recordIndexRecordIdsByGroupFamilyState =
|
const recordIndexRecordIdsByGroupFamilyState =
|
||||||
useRecoilComponentCallbackStateV2(
|
useRecoilComponentFamilyCallbackStateV2(
|
||||||
recordIndexRecordIdsByGroupComponentFamilyState,
|
recordIndexRecordIdsByGroupComponentFamilyState,
|
||||||
recordTableId,
|
recordTableId,
|
||||||
);
|
);
|
||||||
@ -38,7 +34,7 @@ export const useSetRecordTableData = ({
|
|||||||
recordTableId,
|
recordTableId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isRowSelectedFamilyState = useRecoilComponentCallbackStateV2(
|
const isRowSelectedFamilyState = useRecoilComponentFamilyCallbackStateV2(
|
||||||
isRowSelectedComponentFamilyState,
|
isRowSelectedComponentFamilyState,
|
||||||
recordTableId,
|
recordTableId,
|
||||||
);
|
);
|
||||||
@ -61,11 +57,9 @@ export const useSetRecordTableData = ({
|
|||||||
<T extends ObjectRecord>({
|
<T extends ObjectRecord>({
|
||||||
records,
|
records,
|
||||||
currentRecordGroupId,
|
currentRecordGroupId,
|
||||||
totalCount,
|
|
||||||
}: {
|
}: {
|
||||||
records: T[];
|
records: T[];
|
||||||
currentRecordGroupId?: string;
|
currentRecordGroupId?: string;
|
||||||
totalCount?: number;
|
|
||||||
}) => {
|
}) => {
|
||||||
for (const record of records) {
|
for (const record of records) {
|
||||||
// TODO: refactor with scoped state later
|
// TODO: refactor with scoped state later
|
||||||
@ -115,8 +109,6 @@ export const useSetRecordTableData = ({
|
|||||||
} else {
|
} else {
|
||||||
set(recordIndexAllRecordIdsSelector, recordIds);
|
set(recordIndexAllRecordIdsSelector, recordIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
onEntityCountChange(totalCount, currentRecordGroupId);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
@ -125,7 +117,6 @@ export const useSetRecordTableData = ({
|
|||||||
hasUserSelectedAllRowsState,
|
hasUserSelectedAllRowsState,
|
||||||
setIsFocusActiveForCurrentPosition,
|
setIsFocusActiveForCurrentPosition,
|
||||||
setRecordTableHoverPosition,
|
setRecordTableHoverPosition,
|
||||||
onEntityCountChange,
|
|
||||||
isRowSelectedFamilyState,
|
isRowSelectedFamilyState,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -11,18 +11,15 @@ import { availableTableColumnsComponentState } from '@/object-record/record-tabl
|
|||||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||||
import { onColumnsChangeComponentState } from '@/object-record/record-table/states/onColumnsChangeComponentState';
|
import { onColumnsChangeComponentState } from '@/object-record/record-table/states/onColumnsChangeComponentState';
|
||||||
import { onEntityCountChangeComponentState } from '@/object-record/record-table/states/onEntityCountChangeComponentState';
|
|
||||||
|
|
||||||
import { useRecordTableMove } from '@/object-record/record-table/hooks/useRecordTableMove';
|
import { useRecordTableMove } from '@/object-record/record-table/hooks/useRecordTableMove';
|
||||||
import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState';
|
import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState';
|
||||||
import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState';
|
|
||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
import { useLeaveTableFocus } from './internal/useLeaveTableFocus';
|
import { useLeaveTableFocus } from './internal/useLeaveTableFocus';
|
||||||
import { useResetTableRowSelection } from './internal/useResetTableRowSelection';
|
import { useResetTableRowSelection } from './internal/useResetTableRowSelection';
|
||||||
import { useSelectAllRows } from './internal/useSelectAllRows';
|
import { useSelectAllRows } from './internal/useSelectAllRows';
|
||||||
import { useSetRecordTableData } from './internal/useSetRecordTableData';
|
|
||||||
import { useSetRecordTableFocusPosition } from './internal/useSetRecordTableFocusPosition';
|
import { useSetRecordTableFocusPosition } from './internal/useSetRecordTableFocusPosition';
|
||||||
import { useSetRowSelectedState } from './internal/useSetRowSelectedState';
|
import { useSetRowSelectedState } from './internal/useSetRowSelectedState';
|
||||||
type useRecordTableProps = {
|
type useRecordTableProps = {
|
||||||
@ -56,11 +53,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
[availableTableColumnsState],
|
[availableTableColumnsState],
|
||||||
);
|
);
|
||||||
|
|
||||||
const setOnEntityCountChange = useSetRecoilComponentStateV2(
|
|
||||||
onEntityCountChangeComponentState,
|
|
||||||
recordTableId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const setOnColumnsChange = useSetRecoilComponentStateV2(
|
const setOnColumnsChange = useSetRecoilComponentStateV2(
|
||||||
onColumnsChangeComponentState,
|
onColumnsChangeComponentState,
|
||||||
recordTableId,
|
recordTableId,
|
||||||
@ -76,11 +68,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
recordTableId,
|
recordTableId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setRecordTableLastRowVisible = useSetRecoilComponentStateV2(
|
|
||||||
tableLastRowVisibleComponentState,
|
|
||||||
recordTableId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const onColumnsChangeState = useRecoilComponentCallbackStateV2(
|
const onColumnsChangeState = useRecoilComponentCallbackStateV2(
|
||||||
onColumnsChangeComponentState,
|
onColumnsChangeComponentState,
|
||||||
recordTableId,
|
recordTableId,
|
||||||
@ -99,29 +86,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
[onColumnsChangeState],
|
[onColumnsChangeState],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onEntityCountChangeState = useRecoilComponentCallbackStateV2(
|
|
||||||
onEntityCountChangeComponentState,
|
|
||||||
recordTableId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEntityCountChange = useRecoilCallback(
|
|
||||||
({ snapshot }) =>
|
|
||||||
(count?: number, currentRecordGroupId?: string) => {
|
|
||||||
const onEntityCountChange = getSnapshotValue(
|
|
||||||
snapshot,
|
|
||||||
onEntityCountChangeState,
|
|
||||||
);
|
|
||||||
|
|
||||||
onEntityCountChange?.(count, currentRecordGroupId);
|
|
||||||
},
|
|
||||||
[onEntityCountChangeState],
|
|
||||||
);
|
|
||||||
|
|
||||||
const setRecordTableData = useSetRecordTableData({
|
|
||||||
recordTableId,
|
|
||||||
onEntityCountChange,
|
|
||||||
});
|
|
||||||
|
|
||||||
const leaveTableFocus = useLeaveTableFocus(recordTableId);
|
const leaveTableFocus = useLeaveTableFocus(recordTableId);
|
||||||
|
|
||||||
const setRowSelected = useSetRowSelectedState(recordTableId);
|
const setRowSelected = useSetRowSelectedState(recordTableId);
|
||||||
@ -139,8 +103,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
return {
|
return {
|
||||||
onColumnsChange,
|
onColumnsChange,
|
||||||
setAvailableTableColumns,
|
setAvailableTableColumns,
|
||||||
setOnEntityCountChange,
|
|
||||||
setRecordTableData,
|
|
||||||
leaveTableFocus,
|
leaveTableFocus,
|
||||||
setRowSelected,
|
setRowSelected,
|
||||||
resetTableRowSelection,
|
resetTableRowSelection,
|
||||||
@ -148,7 +110,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
selectAllRows,
|
selectAllRows,
|
||||||
setOnColumnsChange,
|
setOnColumnsChange,
|
||||||
setIsRecordTableInitialLoading,
|
setIsRecordTableInitialLoading,
|
||||||
setRecordTableLastRowVisible,
|
|
||||||
setFocusPosition,
|
setFocusPosition,
|
||||||
setHasUserSelectedAllRows,
|
setHasUserSelectedAllRows,
|
||||||
setOnToggleColumnSort,
|
setOnToggleColumnSort,
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useInView } from 'react-intersection-observer';
|
import { useInView } from 'react-intersection-observer';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { isRecordIndexLoadMoreLockedComponentState } from '@/object-record/record-index/states/isRecordIndexLoadMoreLockedComponentState';
|
import { useRecordIndexTableFetchMore } from '@/object-record/record-index/hooks/useRecordIndexTableFetchMore';
|
||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2';
|
import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2';
|
||||||
|
import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState';
|
||||||
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { GRAY_SCALE } from 'twenty-ui/theme';
|
import { GRAY_SCALE } from 'twenty-ui/theme';
|
||||||
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
|
|
||||||
const StyledText = styled.div`
|
const StyledText = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -20,21 +22,13 @@ const StyledText = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const RecordTableBodyFetchMoreLoader = () => {
|
export const RecordTableBodyFetchMoreLoader = () => {
|
||||||
const { setRecordTableLastRowVisible } = useRecordTable();
|
const { recordTableId, objectNameSingular } = useRecordTableContextOrThrow();
|
||||||
|
|
||||||
const isRecordTableLoadMoreLocked = useRecoilComponentValueV2(
|
const { fetchMoreRecordsLazy } =
|
||||||
isRecordIndexLoadMoreLockedComponentState,
|
useRecordIndexTableFetchMore(objectNameSingular);
|
||||||
);
|
|
||||||
|
|
||||||
const onLastRowVisible = useRecoilCallback(
|
const [isFetchingMoreRecords, setIsFetchingMoreRecords] = useRecoilState(
|
||||||
() => async (inView: boolean) => {
|
isFetchingMoreRecordsFamilyState(recordTableId),
|
||||||
if (isRecordTableLoadMoreLocked) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setRecordTableLastRowVisible(inView);
|
|
||||||
},
|
|
||||||
[setRecordTableLastRowVisible, isRecordTableLoadMoreLocked],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const { scrollWrapperHTMLElement } = useScrollWrapperElement();
|
const { scrollWrapperHTMLElement } = useScrollWrapperElement();
|
||||||
@ -43,11 +37,22 @@ export const RecordTableBodyFetchMoreLoader = () => {
|
|||||||
hasRecordTableFetchedAllRecordsComponentStateV2,
|
hasRecordTableFetchedAllRecordsComponentStateV2,
|
||||||
);
|
);
|
||||||
|
|
||||||
const showLoadingMoreRow =
|
const showLoadingMoreRow = !hasRecordTableFetchedAllRecordsComponents;
|
||||||
!hasRecordTableFetchedAllRecordsComponents && !isRecordTableLoadMoreLocked;
|
const debouncedFetchMoreRecordsLazy = useDebouncedCallback(
|
||||||
|
fetchMoreRecordsLazy,
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
|
||||||
const { ref: tbodyRef } = useInView({
|
const { ref: tbodyRef } = useInView({
|
||||||
onChange: onLastRowVisible,
|
onChange: async (inView) => {
|
||||||
|
if (isFetchingMoreRecords || !inView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsFetchingMoreRecords(true);
|
||||||
|
await debouncedFetchMoreRecordsLazy();
|
||||||
|
setIsFetchingMoreRecords(false);
|
||||||
|
},
|
||||||
delay: 1000,
|
delay: 1000,
|
||||||
rootMargin: '1000px',
|
rootMargin: '1000px',
|
||||||
root: scrollWrapperHTMLElement,
|
root: scrollWrapperHTMLElement,
|
||||||
|
|||||||
@ -1,67 +1,73 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
|
||||||
|
|
||||||
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
|
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
|
||||||
import { useLazyLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLazyLoadRecordIndexTable';
|
import { useRecordIndexTableQuery } from '@/object-record/record-index/hooks/useRecordIndexTableQuery';
|
||||||
import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight';
|
import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight';
|
||||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
import { useSetRecordTableData } from '@/object-record/record-table/hooks/internal/useSetRecordTableData';
|
||||||
import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2';
|
import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2';
|
||||||
import { tableEncounteredUnrecoverableErrorComponentState } from '@/object-record/record-table/states/tableEncounteredUnrecoverableErrorComponentState';
|
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||||
import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState';
|
|
||||||
import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState';
|
import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState';
|
||||||
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
||||||
import { useScrollToPosition } from '@/ui/utilities/scroll/hooks/useScrollToPosition';
|
import { useScrollToPosition } from '@/ui/utilities/scroll/hooks/useScrollToPosition';
|
||||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
|
||||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
|
||||||
export const RecordTableNoRecordGroupBodyEffect = () => {
|
export const RecordTableNoRecordGroupBodyEffect = () => {
|
||||||
const { objectNameSingular } = useRecordTableContextOrThrow();
|
const { objectNameSingular, recordTableId } = useRecordTableContextOrThrow();
|
||||||
|
|
||||||
const { setIsRecordTableInitialLoading } = useRecordTable();
|
const { records, loading, hasNextPage } =
|
||||||
|
useRecordIndexTableQuery(objectNameSingular);
|
||||||
|
|
||||||
|
const setRecordTableData = useSetRecordTableData({
|
||||||
|
recordTableId,
|
||||||
|
});
|
||||||
|
|
||||||
const showAuthModal = useShowAuthModal();
|
const showAuthModal = useShowAuthModal();
|
||||||
|
|
||||||
const [hasInitializedScroll, setHasInitializedScroll] = useState(false);
|
const [hasInitializedScroll, setHasInitializedScroll] = useState(false);
|
||||||
|
|
||||||
const {
|
|
||||||
findManyRecords,
|
|
||||||
fetchMoreRecords,
|
|
||||||
records,
|
|
||||||
totalCount,
|
|
||||||
setRecordTableData,
|
|
||||||
loading,
|
|
||||||
queryStateIdentifier,
|
|
||||||
hasNextPage,
|
|
||||||
} = useLazyLoadRecordIndexTable(objectNameSingular);
|
|
||||||
|
|
||||||
const isFetchingMoreObjects = useRecoilValue(
|
|
||||||
isFetchingMoreRecordsFamilyState(queryStateIdentifier),
|
|
||||||
);
|
|
||||||
|
|
||||||
const tableLastRowVisible = useRecoilComponentValueV2(
|
|
||||||
tableLastRowVisibleComponentState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [encounteredUnrecoverableError, setEncounteredUnrecoverableError] =
|
|
||||||
useRecoilComponentStateV2(tableEncounteredUnrecoverableErrorComponentState);
|
|
||||||
|
|
||||||
const setHasRecordTableFetchedAllRecordsComponents =
|
const setHasRecordTableFetchedAllRecordsComponents =
|
||||||
useSetRecoilComponentStateV2(
|
useSetRecoilComponentStateV2(
|
||||||
hasRecordTableFetchedAllRecordsComponentStateV2,
|
hasRecordTableFetchedAllRecordsComponentStateV2,
|
||||||
);
|
);
|
||||||
|
const setIsRecordTableInitialLoading = useSetRecoilComponentStateV2(
|
||||||
const [lastShowPageRecordId, setLastShowPageRecordId] = useRecoilState(
|
isRecordTableInitialLoadingComponentState,
|
||||||
lastShowPageRecordIdState,
|
|
||||||
);
|
);
|
||||||
|
const isFetchingMoreRecords = useRecoilValue(
|
||||||
|
isFetchingMoreRecordsFamilyState(recordTableId),
|
||||||
|
);
|
||||||
|
|
||||||
|
const [lastShowPageRecordId] = useRecoilState(lastShowPageRecordIdState);
|
||||||
|
|
||||||
const { scrollToPosition } = useScrollToPosition();
|
const { scrollToPosition } = useScrollToPosition();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isNonEmptyString(lastShowPageRecordId) && !hasInitializedScroll) {
|
if (!loading && !isFetchingMoreRecords) {
|
||||||
|
setRecordTableData({
|
||||||
|
records,
|
||||||
|
});
|
||||||
|
setHasRecordTableFetchedAllRecordsComponents(!hasNextPage);
|
||||||
|
setIsRecordTableInitialLoading(false);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
hasNextPage,
|
||||||
|
isFetchingMoreRecords,
|
||||||
|
loading,
|
||||||
|
records,
|
||||||
|
setHasRecordTableFetchedAllRecordsComponents,
|
||||||
|
setIsRecordTableInitialLoading,
|
||||||
|
setRecordTableData,
|
||||||
|
showAuthModal,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (hasInitializedScroll) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNonEmptyString(lastShowPageRecordId)) {
|
||||||
const isRecordAlreadyFetched = records.some(
|
const isRecordAlreadyFetched = records.some(
|
||||||
(record) => record.id === lastShowPageRecordId,
|
(record) => record.id === lastShowPageRecordId,
|
||||||
);
|
);
|
||||||
@ -78,76 +84,7 @@ export const RecordTableNoRecordGroupBodyEffect = () => {
|
|||||||
setHasInitializedScroll(true);
|
setHasInitializedScroll(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [hasInitializedScroll, lastShowPageRecordId, records, scrollToPosition]);
|
||||||
loading,
|
|
||||||
lastShowPageRecordId,
|
|
||||||
records,
|
|
||||||
scrollToPosition,
|
|
||||||
hasInitializedScroll,
|
|
||||||
setLastShowPageRecordId,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!loading) {
|
|
||||||
setRecordTableData({
|
|
||||||
records,
|
|
||||||
totalCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [records, totalCount, setRecordTableData, loading]);
|
|
||||||
|
|
||||||
const fetchMoreDebouncedIfRequested = useDebouncedCallback(async () => {
|
|
||||||
// We are debouncing here to give the user some room to scroll if they want to within this throttle window
|
|
||||||
return await fetchMoreRecords();
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const allRecordsHaveBeenFetched = !hasNextPage;
|
|
||||||
|
|
||||||
setHasRecordTableFetchedAllRecordsComponents(allRecordsHaveBeenFetched);
|
|
||||||
}, [hasNextPage, setHasRecordTableFetchedAllRecordsComponents]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (
|
|
||||||
!isFetchingMoreObjects &&
|
|
||||||
tableLastRowVisible &&
|
|
||||||
hasNextPage &&
|
|
||||||
!encounteredUnrecoverableError
|
|
||||||
) {
|
|
||||||
const result = await fetchMoreDebouncedIfRequested();
|
|
||||||
|
|
||||||
const isForbidden =
|
|
||||||
result?.error?.graphQLErrors.some(
|
|
||||||
(e) => e.extensions?.code === 'FORBIDDEN',
|
|
||||||
) ?? false;
|
|
||||||
|
|
||||||
if (isForbidden) {
|
|
||||||
setEncounteredUnrecoverableError(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [
|
|
||||||
hasNextPage,
|
|
||||||
records,
|
|
||||||
lastShowPageRecordId,
|
|
||||||
scrollToPosition,
|
|
||||||
fetchMoreDebouncedIfRequested,
|
|
||||||
isFetchingMoreObjects,
|
|
||||||
tableLastRowVisible,
|
|
||||||
encounteredUnrecoverableError,
|
|
||||||
setEncounteredUnrecoverableError,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsRecordTableInitialLoading(false);
|
|
||||||
|
|
||||||
if (showAuthModal) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
findManyRecords();
|
|
||||||
}, [findManyRecords, setIsRecordTableInitialLoading, showAuthModal]);
|
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,37 +1,35 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
|
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
|
||||||
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
||||||
import { useLazyLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLazyLoadRecordIndexTable';
|
import { useRecordIndexTableQuery } from '@/object-record/record-index/hooks/useRecordIndexTableQuery';
|
||||||
import { recordIndexHasFetchedAllRecordsByGroupComponentState } from '@/object-record/record-index/states/recordIndexHasFetchedAllRecordsByGroupComponentState';
|
import { recordIndexHasFetchedAllRecordsByGroupComponentState } from '@/object-record/record-index/states/recordIndexHasFetchedAllRecordsByGroupComponentState';
|
||||||
import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight';
|
import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight';
|
||||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
|
import { useSetRecordTableData } from '@/object-record/record-table/hooks/internal/useSetRecordTableData';
|
||||||
|
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||||
import { useScrollToPosition } from '@/ui/utilities/scroll/hooks/useScrollToPosition';
|
import { useScrollToPosition } from '@/ui/utilities/scroll/hooks/useScrollToPosition';
|
||||||
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
||||||
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
import { OnboardingStatus } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export const RecordTableRecordGroupBodyEffect = () => {
|
export const RecordTableRecordGroupBodyEffect = () => {
|
||||||
const { objectNameSingular } = useRecordTableContextOrThrow();
|
const { objectNameSingular } = useRecordTableContextOrThrow();
|
||||||
|
const { recordTableId } = useRecordTableContextOrThrow();
|
||||||
|
|
||||||
const [hasInitialized, setHasInitialized] = useState(false);
|
const setRecordTableData = useSetRecordTableData({
|
||||||
|
recordTableId,
|
||||||
|
});
|
||||||
|
|
||||||
const onboardingStatus = useOnboardingStatus();
|
const setIsRecordTableInitialLoading = useSetRecoilComponentStateV2(
|
||||||
|
isRecordTableInitialLoadingComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
const recordGroupId = useCurrentRecordGroupId();
|
const recordGroupId = useCurrentRecordGroupId();
|
||||||
|
|
||||||
const [hasInitializedScroll, setHasInitializedScroll] = useState(false);
|
const { records, loading, hasNextPage } =
|
||||||
|
useRecordIndexTableQuery(objectNameSingular);
|
||||||
const {
|
|
||||||
findManyRecords,
|
|
||||||
records,
|
|
||||||
totalCount,
|
|
||||||
setRecordTableData,
|
|
||||||
loading,
|
|
||||||
hasNextPage,
|
|
||||||
} = useLazyLoadRecordIndexTable(objectNameSingular);
|
|
||||||
|
|
||||||
const setHasRecordFetchedAllRecordsComponents =
|
const setHasRecordFetchedAllRecordsComponents =
|
||||||
useSetRecoilComponentFamilyStateV2(
|
useSetRecoilComponentFamilyStateV2(
|
||||||
@ -44,7 +42,26 @@ export const RecordTableRecordGroupBodyEffect = () => {
|
|||||||
const { scrollToPosition } = useScrollToPosition();
|
const { scrollToPosition } = useScrollToPosition();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isNonEmptyString(lastShowPageRecordId) && !hasInitializedScroll) {
|
if (!loading) {
|
||||||
|
setRecordTableData({
|
||||||
|
records,
|
||||||
|
currentRecordGroupId: recordGroupId,
|
||||||
|
});
|
||||||
|
setIsRecordTableInitialLoading(false);
|
||||||
|
setHasRecordFetchedAllRecordsComponents(!hasNextPage);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
hasNextPage,
|
||||||
|
loading,
|
||||||
|
records,
|
||||||
|
recordGroupId,
|
||||||
|
setHasRecordFetchedAllRecordsComponents,
|
||||||
|
setIsRecordTableInitialLoading,
|
||||||
|
setRecordTableData,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isNonEmptyString(lastShowPageRecordId)) {
|
||||||
const recordPosition = records.findIndex(
|
const recordPosition = records.findIndex(
|
||||||
(record) => record.id === lastShowPageRecordId,
|
(record) => record.id === lastShowPageRecordId,
|
||||||
);
|
);
|
||||||
@ -53,44 +70,9 @@ export const RecordTableRecordGroupBodyEffect = () => {
|
|||||||
const positionInPx = recordPosition * ROW_HEIGHT;
|
const positionInPx = recordPosition * ROW_HEIGHT;
|
||||||
|
|
||||||
scrollToPosition(positionInPx);
|
scrollToPosition(positionInPx);
|
||||||
|
|
||||||
setHasInitializedScroll(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [lastShowPageRecordId, records, scrollToPosition]);
|
||||||
loading,
|
|
||||||
lastShowPageRecordId,
|
|
||||||
records,
|
|
||||||
scrollToPosition,
|
|
||||||
hasInitializedScroll,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!loading) {
|
|
||||||
setRecordTableData({
|
|
||||||
records,
|
|
||||||
currentRecordGroupId: recordGroupId,
|
|
||||||
totalCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [records, totalCount, setRecordTableData, loading, recordGroupId]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const allRecordsHaveBeenFetched = !hasNextPage;
|
|
||||||
|
|
||||||
setHasRecordFetchedAllRecordsComponents(allRecordsHaveBeenFetched);
|
|
||||||
}, [hasNextPage, setHasRecordFetchedAllRecordsComponents]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (onboardingStatus !== OnboardingStatus.COMPLETED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasInitialized) {
|
|
||||||
findManyRecords();
|
|
||||||
setHasInitialized(true);
|
|
||||||
}
|
|
||||||
}, [onboardingStatus, findManyRecords, hasInitialized]);
|
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
||||||
import { useLazyLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLazyLoadRecordIndexTable';
|
import { useRecordIndexTableFetchMore } from '@/object-record/record-index/hooks/useRecordIndexTableFetchMore';
|
||||||
import { isRecordIndexLoadMoreLockedComponentState } from '@/object-record/record-index/states/isRecordIndexLoadMoreLockedComponentState';
|
|
||||||
import { recordIndexHasFetchedAllRecordsByGroupComponentState } from '@/object-record/record-index/states/recordIndexHasFetchedAllRecordsByGroupComponentState';
|
import { recordIndexHasFetchedAllRecordsByGroupComponentState } from '@/object-record/record-index/states/recordIndexHasFetchedAllRecordsByGroupComponentState';
|
||||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
||||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
@ -14,26 +13,23 @@ export const RecordTableRecordGroupSectionLoadMore = () => {
|
|||||||
|
|
||||||
const currentRecordGroupId = useCurrentRecordGroupId();
|
const currentRecordGroupId = useCurrentRecordGroupId();
|
||||||
|
|
||||||
const { fetchMoreRecords } = useLazyLoadRecordIndexTable(objectNameSingular);
|
const { fetchMoreRecordsLazy } =
|
||||||
|
useRecordIndexTableFetchMore(objectNameSingular);
|
||||||
|
|
||||||
const hasFetchedAllRecords = useRecoilComponentFamilyValueV2(
|
const hasFetchedAllRecords = useRecoilComponentFamilyValueV2(
|
||||||
recordIndexHasFetchedAllRecordsByGroupComponentState,
|
recordIndexHasFetchedAllRecordsByGroupComponentState,
|
||||||
currentRecordGroupId,
|
currentRecordGroupId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isLoadMoreLocked = useRecoilComponentValueV2(
|
|
||||||
isRecordIndexLoadMoreLockedComponentState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const recordIds = useRecoilComponentValueV2(
|
const recordIds = useRecoilComponentValueV2(
|
||||||
recordIndexAllRecordIdsComponentSelector,
|
recordIndexAllRecordIdsComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleLoadMore = () => {
|
const handleLoadMore = () => {
|
||||||
fetchMoreRecords();
|
fetchMoreRecordsLazy();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hasFetchedAllRecords || isLoadMoreLocked) {
|
if (hasFetchedAllRecords) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
|
||||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
|
||||||
|
|
||||||
export const onEntityCountChangeComponentState = createComponentStateV2<
|
|
||||||
((entityCount?: number, currentRecordGroupId?: string) => void) | undefined
|
|
||||||
>({
|
|
||||||
key: 'onEntityCountChangeComponentState',
|
|
||||||
defaultValue: undefined,
|
|
||||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
|
||||||
});
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
|
||||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
|
||||||
|
|
||||||
export const tableEncounteredUnrecoverableErrorComponentState =
|
|
||||||
createComponentStateV2<boolean>({
|
|
||||||
key: 'tableEncounteredUnrecoverableErrorComponentState',
|
|
||||||
defaultValue: false,
|
|
||||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
|
||||||
});
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
|
||||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
|
||||||
|
|
||||||
export const tableLastRowVisibleComponentState =
|
|
||||||
createComponentStateV2<boolean>({
|
|
||||||
key: 'tableLastRowVisibleComponentState',
|
|
||||||
defaultValue: false,
|
|
||||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
|
||||||
});
|
|
||||||
@ -1,11 +1,15 @@
|
|||||||
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
export const useScrollToPosition = () => {
|
export const useScrollToPosition = () => {
|
||||||
const { scrollWrapperHTMLElement } = useScrollWrapperElement();
|
const { scrollWrapperHTMLElement } = useScrollWrapperElement();
|
||||||
|
|
||||||
const scrollToPosition = (scrollPositionInPx: number) => {
|
const scrollToPosition = useCallback(
|
||||||
|
(scrollPositionInPx: number) => {
|
||||||
scrollWrapperHTMLElement?.scrollTo({ top: scrollPositionInPx });
|
scrollWrapperHTMLElement?.scrollTo({ top: scrollPositionInPx });
|
||||||
};
|
},
|
||||||
|
[scrollWrapperHTMLElement],
|
||||||
|
);
|
||||||
|
|
||||||
return { scrollToPosition };
|
return { scrollToPosition };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,97 @@
|
|||||||
|
/* eslint-disable prefer-arrow/prefer-arrow-functions */
|
||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2';
|
||||||
|
import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2';
|
||||||
|
import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { RecoilState, RecoilValueReadOnly, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
export function useRecoilComponentFamilyCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilyState: ComponentFamilyStateV2<ValueType, FamilyKey>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentFamilyCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilySelector: ComponentFamilySelectorV2<ValueType, FamilyKey>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentFamilyCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilyReadOnlySelector: ComponentFamilyReadOnlySelectorV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey
|
||||||
|
>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilValueReadOnly<ValueType>;
|
||||||
|
export function useRecoilComponentFamilyCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilyState: ComponentFamilyStateV2<ValueType, FamilyKey>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentFamilyCallbackStateV2<
|
||||||
|
ComponentState extends
|
||||||
|
| ComponentFamilyStateV2<ValueType, FamilyKey>
|
||||||
|
| ComponentFamilySelectorV2<ValueType, FamilyKey>
|
||||||
|
| ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>,
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam = never,
|
||||||
|
>(
|
||||||
|
componentState: ComponentState,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
):
|
||||||
|
| RecoilState<ValueType>
|
||||||
|
| RecoilValueReadOnly<ValueType>
|
||||||
|
| ((familyKey: FamilyKey) => RecoilState<ValueType>)
|
||||||
|
| ((familyKey: FamilyKey) => RecoilValueReadOnly<ValueType>) {
|
||||||
|
const componentStateKey = componentState.key;
|
||||||
|
|
||||||
|
const componentInstanceContext =
|
||||||
|
globalComponentInstanceContextMap.get(componentStateKey);
|
||||||
|
|
||||||
|
if (!componentInstanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentStateKey}" is not defined, check the component state declaration.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
componentInstanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
return useCallback(
|
||||||
|
(familyKey: FamilyKey) => {
|
||||||
|
switch (componentState.type) {
|
||||||
|
case 'ComponentFamilyState': {
|
||||||
|
return componentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
familyKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentFamilySelector': {
|
||||||
|
return componentState.selectorFamily({
|
||||||
|
instanceId,
|
||||||
|
familyKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentFamilyReadOnlySelector': {
|
||||||
|
return componentState.selectorFamily({
|
||||||
|
instanceId,
|
||||||
|
familyKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[componentState, instanceId],
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -26,9 +26,9 @@ import { mapRecordFilterGroupToViewFilterGroup } from '@/views/utils/mapRecordFi
|
|||||||
import { mapRecordFilterToViewFilter } from '@/views/utils/mapRecordFilterToViewFilter';
|
import { mapRecordFilterToViewFilter } from '@/views/utils/mapRecordFilterToViewFilter';
|
||||||
import { mapRecordSortToViewSort } from '@/views/utils/mapRecordSortToViewSort';
|
import { mapRecordSortToViewSort } from '@/views/utils/mapRecordSortToViewSort';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
|
||||||
|
|
||||||
export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||||
@ -52,7 +52,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
|||||||
|
|
||||||
const { objectMetadataItem } = useRecordIndexContextOrThrow();
|
const { objectMetadataItem } = useRecordIndexContextOrThrow();
|
||||||
|
|
||||||
const { findManyRecords } = useLazyFindManyRecords({
|
const { findManyRecordsLazy } = useLazyFindManyRecords({
|
||||||
objectNameSingular: CoreObjectNameSingular.View,
|
objectNameSingular: CoreObjectNameSingular.View,
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
});
|
});
|
||||||
@ -204,14 +204,14 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
|||||||
await createViewSortRecords(viewSortsToCreate, newView);
|
await createViewSortRecords(viewSortsToCreate, newView);
|
||||||
}
|
}
|
||||||
|
|
||||||
await findManyRecords();
|
await findManyRecordsLazy();
|
||||||
set(isPersistingViewFieldsState, false);
|
set(isPersistingViewFieldsState, false);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
currentViewIdCallbackState,
|
currentViewIdCallbackState,
|
||||||
createOneRecord,
|
createOneRecord,
|
||||||
createViewFieldRecords,
|
createViewFieldRecords,
|
||||||
findManyRecords,
|
findManyRecordsLazy,
|
||||||
objectMetadataItem.fields,
|
objectMetadataItem.fields,
|
||||||
createViewGroupRecords,
|
createViewGroupRecords,
|
||||||
createViewSortRecords,
|
createViewSortRecords,
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export const useRefreshCachedViews = () => {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { findManyRecords: refreshCachedViews } = useLazyFindManyRecords({
|
const { findManyRecordsLazy: refreshCachedViews } = useLazyFindManyRecords({
|
||||||
objectNameSingular: CoreObjectNameSingular.View,
|
objectNameSingular: CoreObjectNameSingular.View,
|
||||||
filter: findAllViewsOperationSignature.variables.filter,
|
filter: findAllViewsOperationSignature.variables.filter,
|
||||||
recordGqlFields: findAllViewsOperationSignature.fields,
|
recordGqlFields: findAllViewsOperationSignature.fields,
|
||||||
|
|||||||
@ -12,8 +12,11 @@ import { RecordIndexContextProvider } from '@/object-record/record-index/context
|
|||||||
import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates';
|
import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates';
|
||||||
import { RecordSortsComponentInstanceContext } from '@/object-record/record-sort/states/context/RecordSortsComponentInstanceContext';
|
import { RecordSortsComponentInstanceContext } from '@/object-record/record-sort/states/context/RecordSortsComponentInstanceContext';
|
||||||
import { RecordTableBodyContextProvider } from '@/object-record/record-table/contexts/RecordTableBodyContext';
|
import { RecordTableBodyContextProvider } from '@/object-record/record-table/contexts/RecordTableBodyContext';
|
||||||
import { RecordTableContextProvider } from '@/object-record/record-table/contexts/RecordTableContext';
|
import {
|
||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
RecordTableContextProvider,
|
||||||
|
useRecordTableContextOrThrow,
|
||||||
|
} from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
|
import { useSetRecordTableData } from '@/object-record/record-table/hooks/internal/useSetRecordTableData';
|
||||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||||
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
|
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
|
||||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||||
@ -31,9 +34,12 @@ const InternalTableStateLoaderEffect = ({
|
|||||||
}: {
|
}: {
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { recordTableId } = useRecordTableContextOrThrow();
|
||||||
const { loadRecordIndexStates } = useLoadRecordIndexStates();
|
const { loadRecordIndexStates } = useLoadRecordIndexStates();
|
||||||
|
|
||||||
const { setRecordTableData } = useRecordTable();
|
const setRecordTableData = useSetRecordTableData({
|
||||||
|
recordTableId,
|
||||||
|
});
|
||||||
|
|
||||||
const view = useMemo(() => {
|
const view = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
@ -48,7 +54,6 @@ const InternalTableStateLoaderEffect = ({
|
|||||||
loadRecordIndexStates(view, objectMetadataItem);
|
loadRecordIndexStates(view, objectMetadataItem);
|
||||||
setRecordTableData({
|
setRecordTableData({
|
||||||
records: getCompaniesMock(),
|
records: getCompaniesMock(),
|
||||||
totalCount: getCompaniesMock().length,
|
|
||||||
});
|
});
|
||||||
}, [loadRecordIndexStates, objectMetadataItem, setRecordTableData, view]);
|
}, [loadRecordIndexStates, objectMetadataItem, setRecordTableData, view]);
|
||||||
|
|
||||||
@ -149,12 +154,12 @@ export const RecordTableDecorator: Decorator = (Story, context) => {
|
|||||||
instanceId: getActionMenuIdFromRecordIndexId(recordIndexId),
|
instanceId: getActionMenuIdFromRecordIndexId(recordIndexId),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<InternalTableStateLoaderEffect
|
|
||||||
objectMetadataItem={objectMetadataItem}
|
|
||||||
/>
|
|
||||||
<InternalTableContextProviders
|
<InternalTableContextProviders
|
||||||
objectMetadataItem={objectMetadataItem}
|
objectMetadataItem={objectMetadataItem}
|
||||||
>
|
>
|
||||||
|
<InternalTableStateLoaderEffect
|
||||||
|
objectMetadataItem={objectMetadataItem}
|
||||||
|
/>
|
||||||
<Story />
|
<Story />
|
||||||
</InternalTableContextProviders>
|
</InternalTableContextProviders>
|
||||||
</ActionMenuComponentInstanceContext.Provider>
|
</ActionMenuComponentInstanceContext.Provider>
|
||||||
|
|||||||
Reference in New Issue
Block a user