From 1694958d11405feec633b6ddf32af0fb99041a8c Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Thu, 29 Aug 2024 18:05:43 +0200 Subject: [PATCH 1/2] Moved fetch more loader in a better place in the tree and added a state to hide it once everything is loaded --- .../hooks/useLoadRecordIndexTable.ts | 2 + .../components/RecordTableRows.tsx | 20 ++++++-- .../components/RecordTableBody.tsx | 6 --- .../components/RecordTableBodyEffect.tsx | 31 ++++++++---- .../RecordTableBodyFetchMoreLoader.tsx | 48 +++++++++---------- ...dTableFetchedAllRecordsComponentStateV2.ts | 9 ++++ 6 files changed, 71 insertions(+), 45 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts index dbf4eada7d43..36947097459e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts @@ -53,6 +53,7 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => { totalCount, fetchMoreRecords, queryStateIdentifier, + hasNextPage, } = useFindManyRecords({ ...params, recordGqlFields, @@ -74,5 +75,6 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => { fetchMoreRecords, queryStateIdentifier, setRecordTableData, + hasNextPage, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRows.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRows.tsx index 40db65bbb80c..688bfd0f0acf 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRows.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRows.tsx @@ -1,6 +1,7 @@ import { useRecoilValue } from 'recoil'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; +import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader'; import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow'; export const RecordTableRows = () => { @@ -8,9 +9,18 @@ export const RecordTableRows = () => { const tableRowIds = useRecoilValue(tableRowIdsState); - return tableRowIds.map((recordId, rowIndex) => { - return ( - - ); - }); + return ( + <> + {tableRowIds.map((recordId, rowIndex) => { + return ( + + ); + })} + + + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx index 2a6e46c21987..c3adb621d776 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx @@ -1,21 +1,16 @@ import { useRecoilValue } from 'recoil'; import { RecordTableRows } from '@/object-record/record-table/components/RecordTableRows'; -import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { RecordTableBodyDragDropContext } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContext'; import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable'; -import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader'; import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading'; import { RecordTablePendingRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRow'; -import { useContext } from 'react'; export const RecordTableBody = () => { const { tableRowIdsState, isRecordTableInitialLoadingState } = useRecordTableStates(); - const { objectNameSingular } = useContext(RecordTableContext); - const tableRowIds = useRecoilValue(tableRowIdsState); const isRecordTableInitialLoading = useRecoilValue( @@ -32,7 +27,6 @@ export const RecordTableBody = () => { - ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx index d53d6499027b..16f38e63c5f0 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx @@ -7,6 +7,7 @@ import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useL import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight'; import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; +import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2'; import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState'; import { isRecordTableScrolledTopComponentState } from '@/object-record/record-table/states/isRecordTableScrolledTopComponentState'; import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState'; @@ -22,12 +23,13 @@ export const RecordTableBodyEffect = () => { const [hasInitializedScroll, setHasInitiazedScroll] = useState(false); const { - fetchMoreRecords: fetchMoreObjects, + fetchMoreRecords, records, totalCount, setRecordTableData, loading, queryStateIdentifier, + hasNextPage, } = useLoadRecordIndexTable(objectNameSingular); const isFetchingMoreObjects = useRecoilValue( @@ -43,6 +45,9 @@ export const RecordTableBodyEffect = () => { isRecordTableScrolledTopComponentState, ); + const setHasRecordTableFetchedAllRecordsComponents = + useSetRecoilComponentState(hasRecordTableFetchedAllRecordsComponentStateV2); + // TODO: move this outside because it might cause way too many re-renders for other hooks useEffect(() => { setIsRecordTableScrolledTop(scrollTop === 0); @@ -108,9 +113,7 @@ export const RecordTableBodyEffect = () => { } }, [ loading, - isFetchingMoreObjects, lastShowPageRecordId, - fetchMoreObjects, records, scrollToPosition, hasInitializedScroll, @@ -125,14 +128,26 @@ export const RecordTableBodyEffect = () => { const fetchMoreDebouncedIfRequested = useDebouncedCallback(async () => { // We are debouncing here to give the user some room to scroll if they want to within this throttle window - await fetchMoreObjects(); - }, 100); + await fetchMoreRecords(); + }, 2000); useEffect(() => { - if (!isFetchingMoreObjects && tableLastRowVisible) { - fetchMoreDebouncedIfRequested(); - } + const allRecordsHaveBeenFetched = !hasNextPage; + + setHasRecordTableFetchedAllRecordsComponents(allRecordsHaveBeenFetched); + }, [hasNextPage, setHasRecordTableFetchedAllRecordsComponents]); + + useEffect(() => { + (async () => { + if (!isFetchingMoreObjects && tableLastRowVisible && hasNextPage) { + await fetchMoreDebouncedIfRequested(); + } + })(); }, [ + hasNextPage, + records, + lastShowPageRecordId, + scrollToPosition, fetchMoreDebouncedIfRequested, isFetchingMoreObjects, tableLastRowVisible, diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader.tsx index 32df8cf268f2..4e15bb733f05 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader.tsx @@ -1,17 +1,13 @@ import styled from '@emotion/styled'; import { useContext } from 'react'; import { useInView } from 'react-intersection-observer'; -import { useRecoilCallback, useRecoilValue } from 'recoil'; +import { useRecoilCallback } from 'recoil'; import { GRAY_SCALE } from 'twenty-ui'; -import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLoadRecordIndexTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState'; +import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2'; import { RecordTableWithWrappersScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts'; - -type RecordTableBodyFetchMoreLoaderProps = { - objectNameSingular: string; -}; +import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; const StyledText = styled.div` align-items: center; @@ -23,16 +19,9 @@ const StyledText = styled.div` padding-left: ${({ theme }) => theme.spacing(2)}; `; -export const RecordTableBodyFetchMoreLoader = ({ - objectNameSingular, -}: RecordTableBodyFetchMoreLoaderProps) => { - const { queryStateIdentifier } = useLoadRecordIndexTable(objectNameSingular); +export const RecordTableBodyFetchMoreLoader = () => { const { setRecordTableLastRowVisible } = useRecordTable(); - const isFetchingMoreRecords = useRecoilValue( - isFetchingMoreRecordsFamilyState(queryStateIdentifier), - ); - const onLastRowVisible = useRecoilCallback( () => async (inView: boolean) => { setRecordTableLastRowVisible(inView); @@ -44,24 +33,31 @@ export const RecordTableBodyFetchMoreLoader = ({ RecordTableWithWrappersScrollWrapperContext, ); + const hasRecordTableFetchedAllRecordsComponents = useRecoilComponentValue( + hasRecordTableFetchedAllRecordsComponentStateV2, + ); + + const showLoadingMoreRow = !hasRecordTableFetchedAllRecordsComponents; + const { ref: tbodyRef } = useInView({ onChange: onLastRowVisible, + delay: 1000, rootMargin: '1000px', root: scrollWrapperRef?.ref.current?.querySelector( - '[data-overlayscrollbars-viewport="scrollbarHidden"]', + '[data-overlayscrollbars-viewport]', ), }); + if (!showLoadingMoreRow) { + return <>; + } + return ( - - {isFetchingMoreRecords && ( - - - Loading more... - - - - )} - + + + Loading more... + + + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts b/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts new file mode 100644 index 000000000000..f8b6716a8659 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts @@ -0,0 +1,9 @@ +import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; + +export const hasRecordTableFetchedAllRecordsComponentStateV2 = + createComponentStateV2({ + key: 'hasRecordTableFetchedAllRecordsComponentStateV2', + componentContext: RecordTableScopeInternalContext, + defaultValue: false, + }); From 64626ad4c1afe9cf84134a564fe6f75c589a0d65 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Thu, 29 Aug 2024 18:21:28 +0200 Subject: [PATCH 2/2] Fix --- .../record-table-body/components/RecordTableBodyEffect.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx index 16f38e63c5f0..9550dac39bb5 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx @@ -129,7 +129,7 @@ export const RecordTableBodyEffect = () => { const fetchMoreDebouncedIfRequested = useDebouncedCallback(async () => { // We are debouncing here to give the user some room to scroll if they want to within this throttle window await fetchMoreRecords(); - }, 2000); + }, 100); useEffect(() => { const allRecordsHaveBeenFetched = !hasNextPage;