Commit bd4c82b1 authored by tom's avatar tom

disable pagination buttons when page is loading

parent ae968845
import React from 'react';
export default function useIsInitialLoading(isLoading: boolean | undefined) {
const [ isInitialLoading, setIsInitialLoading ] = React.useState(Boolean(isLoading));
React.useEffect(() => {
if (!isLoading) {
setIsInitialLoading(false);
}
}, [ isLoading ]);
return isInitialLoading;
}
......@@ -6,6 +6,7 @@ import type { CsvExportType } from 'types/client/address';
import appConfig from 'configs/app/config';
import svgFileIcon from 'icons/files/csv.svg';
import useIsInitialLoading from 'lib/hooks/useIsInitialLoading';
import useIsMobile from 'lib/hooks/useIsMobile';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -18,12 +19,13 @@ interface Props {
const AddressCsvExportLink = ({ className, address, type, isLoading }: Props) => {
const isMobile = useIsMobile();
const isInitialLoading = useIsInitialLoading(isLoading);
if (!appConfig.reCaptcha.siteKey) {
return null;
}
if (isLoading) {
if (isInitialLoading) {
return (
<Flex className={ className } flexShrink={ 0 } alignItems="center">
<Skeleton boxSize={{ base: '32px', lg: 6 }} borderRadius="base"/>
......
......@@ -10,6 +10,7 @@ import React from 'react';
import type { AddressFromToFilter } from 'types/api/address';
import useIsInitialLoading from 'lib/hooks/useIsInitialLoading';
import FilterButton from 'ui/shared/filters/FilterButton';
interface Props {
......@@ -21,13 +22,14 @@ interface Props {
const AddressTxsFilter = ({ onFilterChange, defaultFilter, isActive, isLoading }: Props) => {
const { isOpen, onToggle } = useDisclosure();
const isInitialLoading = useIsInitialLoading(isLoading);
return (
<Menu>
<MenuButton>
<FilterButton
isActive={ isOpen || isActive }
isLoading={ isLoading }
isLoading={ isInitialLoading }
onClick={ onToggle }
as="div"
/>
......
......@@ -9,6 +9,7 @@ import React from 'react';
import type { AddressFromToFilter } from 'types/api/address';
import type { TokenType } from 'types/api/token';
import useIsInitialLoading from 'lib/hooks/useIsInitialLoading';
import PopoverFilter from 'ui/shared/filters/PopoverFilter';
import TokenTypeFilter from 'ui/shared/filters/TokenTypeFilter';
......@@ -31,9 +32,10 @@ const TokenTransferFilter = ({
defaultAddressFilter,
isLoading,
}: Props) => {
const isInitialLoading = useIsInitialLoading(isLoading);
return (
<PopoverFilter appliedFiltersNum={ appliedFiltersNum } contentProps={{ w: '200px' }} isLoading={ isLoading }>
<PopoverFilter appliedFiltersNum={ appliedFiltersNum } contentProps={{ w: '200px' }} isLoading={ isInitialLoading }>
{ withAddressFilter && (
<>
<Text variant="secondary" fontWeight={ 600 }>Address</Text>
......
......@@ -9,29 +9,31 @@ interface Props extends PaginationParams {
className?: string;
}
const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasNextPage, className, canGoBackwards, isLoading, isVisible }: Props) => {
const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasPages, hasNextPage, className, canGoBackwards, isLoading, isVisible }: Props) => {
if (!isVisible) {
return null;
}
const showSkeleton = page === 1 && !hasPages && isLoading;
return (
<Flex
className={ className }
fontSize="sm"
alignItems="center"
>
<Skeleton isLoaded={ !isLoading } display="inline-block" mr={ 4 } borderRadius="base">
<Skeleton isLoaded={ !showSkeleton } display="inline-block" mr={ 4 } borderRadius="base">
<Button
variant="outline"
size="sm"
onClick={ resetPage }
isDisabled={ page === 1 }
isDisabled={ page === 1 || isLoading }
>
First
</Button>
</Skeleton>
<Skeleton isLoaded={ !isLoading } display="inline-block" mr={ 3 } borderRadius="base">
<Skeleton isLoaded={ !showSkeleton } display="inline-block" mr={ 3 } borderRadius="base">
<IconButton
variant="outline"
onClick={ onPrevPageClick }
......@@ -39,10 +41,10 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasNext
aria-label="Prev page"
w="36px"
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 }/> }
isDisabled={ !canGoBackwards || page === 1 }
isDisabled={ !canGoBackwards || page === 1 || isLoading }
/>
</Skeleton>
<Skeleton isLoaded={ !isLoading } display="inline-block" borderRadius="base">
<Skeleton isLoaded={ !showSkeleton } display="inline-block" borderRadius="base">
<Button
variant="outline"
size="sm"
......@@ -50,12 +52,13 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasNext
borderWidth="1px"
fontWeight={ 400 }
h={ 8 }
minW="36px"
cursor="unset"
>
{ page }
</Button>
</Skeleton>
<Skeleton isLoaded={ !isLoading } display="inline-block" ml={ 3 } borderRadius="base">
<Skeleton isLoaded={ !showSkeleton } display="inline-block" ml={ 3 } borderRadius="base">
<IconButton
variant="outline"
onClick={ onNextPageClick }
......@@ -63,7 +66,7 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasNext
aria-label="Next page"
w="36px"
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 } transform="rotate(180deg)"/> }
isDisabled={ !hasNextPage }
isDisabled={ !hasNextPage || isLoading }
/>
</Skeleton>
{ /* not implemented yet */ }
......
......@@ -3,6 +3,7 @@ export interface PaginationParams {
onNextPageClick: () => void;
onPrevPageClick: () => void;
resetPage: () => void;
hasPages: boolean;
hasNextPage: boolean;
canGoBackwards: boolean;
isLoading: boolean;
......
......@@ -68,6 +68,7 @@ it('returns correct data if there is only one page', async() => {
hasNextPage: false,
isLoading: false,
isVisible: false,
hasPages: false,
});
});
......@@ -127,6 +128,7 @@ describe('if there are multiple pages', () => {
hasNextPage: true,
isLoading: false,
isVisible: true,
hasPages: true,
});
expect(routerPush).toHaveBeenCalledTimes(1);
......@@ -164,6 +166,7 @@ describe('if there are multiple pages', () => {
hasNextPage: false,
isLoading: false,
isVisible: true,
hasPages: true,
});
expect(routerPush).toHaveBeenCalledTimes(2);
......@@ -207,6 +210,7 @@ describe('if there are multiple pages', () => {
hasNextPage: true,
isLoading: false,
isVisible: true,
hasPages: true,
});
expect(routerPush).toHaveBeenCalledTimes(3);
......@@ -254,6 +258,7 @@ describe('if there are multiple pages', () => {
hasNextPage: true,
isLoading: false,
isVisible: true,
hasPages: true,
});
expect(routerPush).toHaveBeenCalledTimes(4);
......@@ -305,6 +310,7 @@ describe('if there are multiple pages', () => {
hasNextPage: true,
isLoading: false,
isVisible: true,
hasPages: true,
});
expect(routerPush).toHaveBeenCalledTimes(3);
......@@ -368,6 +374,7 @@ describe('if there is page query param in URL', () => {
hasNextPage: false,
isLoading: false,
isVisible: true,
hasPages: true,
});
});
......@@ -397,6 +404,7 @@ describe('if there is page query param in URL', () => {
hasNextPage: false,
isLoading: false,
isVisible: true,
hasPages: true,
});
expect(routerPush).toHaveBeenCalledTimes(1);
......@@ -447,6 +455,7 @@ describe('queries with filters', () => {
hasNextPage: true,
isLoading: false,
isVisible: true,
hasPages: false,
});
expect(routerPush).toHaveBeenCalledTimes(2);
......
......@@ -55,7 +55,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
const [ pageParams, setPageParams ] = React.useState<Record<number, NextPageParams>>({
[page]: getPaginationParamsFromQuery(router.query.next_page_params),
});
const [ hasPagination, setHasPagination ] = React.useState(page > 1);
const [ hasPages, setHasPages ] = React.useState(page > 1);
const isMounted = React.useRef(false);
const canGoBackwards = React.useRef(!router.query.page);
......@@ -93,7 +93,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
next_page_params: encodeURIComponent(JSON.stringify(data.next_page_params)),
};
setHasPagination(true);
setHasPages(true);
scrollToTop();
router.push({ pathname: router.pathname, query: nextPageQuery }, undefined, { shallow: true });
}, [ data?.next_page_params, page, router, scrollToTop ]);
......@@ -116,7 +116,6 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
setPage(prev => prev - 1);
page === 2 && queryClient.removeQueries({ queryKey: [ resourceName ] });
});
setHasPagination(true);
}, [ router, page, pageParams, scrollToTop, queryClient, resourceName ]);
const resetPage = useCallback(() => {
......@@ -135,8 +134,6 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
queryClient.removeQueries({ queryKey: [ resourceName ], type: 'inactive' });
}, 100);
});
setHasPagination(true);
}, [ queryClient, resourceName, router, scrollToTop ]);
const onFilterChange = useCallback((newFilters: PaginationFilters<Resource> | undefined) => {
......@@ -148,7 +145,6 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
}
});
}
setHasPagination(false);
scrollToTop();
router.push(
{
......@@ -158,6 +154,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
undefined,
{ shallow: true },
).then(() => {
setHasPages(false);
setPage(1);
setPageParams({});
});
......@@ -171,10 +168,11 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
onNextPageClick,
onPrevPageClick,
resetPage,
hasPages,
hasNextPage,
canGoBackwards: canGoBackwards.current,
isLoading: queryResult.isPlaceholderData && !hasPagination,
isVisible: hasPagination || (!queryResult.isLoading && !queryResult.isError && hasNextPage),
isLoading: queryResult.isPlaceholderData,
isVisible: hasPages || hasNextPage,
};
React.useEffect(() => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment