Commit 4d20dec2 authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

Merge pull request #1128 from blockscout/new-blocks-limit

new blocks from socket limit
parents c3676134 89e2b220
import { Alert, Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
...@@ -15,6 +15,9 @@ import ActionBar from 'ui/shared/ActionBar'; ...@@ -15,6 +15,9 @@ import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay'; import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/pagination/Pagination'; import Pagination from 'ui/shared/pagination/Pagination';
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages'; import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
const OVERLOAD_COUNT = 75;
interface Props { interface Props {
type?: BlockType; type?: BlockType;
...@@ -26,6 +29,8 @@ const BlocksContent = ({ type, query }: Props) => { ...@@ -26,6 +29,8 @@ const BlocksContent = ({ type, query }: Props) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const [ socketAlert, setSocketAlert ] = React.useState(''); const [ socketAlert, setSocketAlert ] = React.useState('');
const [ newItemsCount, setNewItemsCount ] = React.useState(0);
const handleNewBlockMessage: SocketMessage.NewBlock['handler'] = React.useCallback((payload) => { const handleNewBlockMessage: SocketMessage.NewBlock['handler'] = React.useCallback((payload) => {
const queryKey = getResourceKey('blocks', { queryParams: { type } }); const queryKey = getResourceKey('blocks', { queryParams: { type } });
...@@ -43,17 +48,22 @@ const BlocksContent = ({ type, query }: Props) => { ...@@ -43,17 +48,22 @@ const BlocksContent = ({ type, query }: Props) => {
return prevData; return prevData;
} }
if (prevData.items.length >= OVERLOAD_COUNT) {
setNewItemsCount(prev => prev + 1);
return prevData;
}
const newItems = [ payload.block, ...prevData.items ].sort((b1, b2) => b2.height - b1.height); const newItems = [ payload.block, ...prevData.items ].sort((b1, b2) => b2.height - b1.height);
return { ...prevData, items: newItems }; return { ...prevData, items: newItems };
}); });
}, [ queryClient, type ]); }, [ queryClient, type ]);
const handleSocketClose = React.useCallback(() => { const handleSocketClose = React.useCallback(() => {
setSocketAlert('Connection is lost. Please click here to load new blocks.'); setSocketAlert('Connection is lost. Please refresh the page to load new blocks.');
}, []); }, []);
const handleSocketError = React.useCallback(() => { const handleSocketError = React.useCallback(() => {
setSocketAlert('An error has occurred while fetching new blocks. Please click here to refresh the page.'); setSocketAlert('An error has occurred while fetching new blocks. Please refresh the page to load new blocks.');
}, []); }, []);
const channel = useSocketChannel({ const channel = useSocketChannel({
...@@ -70,8 +80,16 @@ const BlocksContent = ({ type, query }: Props) => { ...@@ -70,8 +80,16 @@ const BlocksContent = ({ type, query }: Props) => {
const content = query.data?.items ? ( const content = query.data?.items ? (
<> <>
{ socketAlert && <Alert status="warning" mb={ 6 } as="a" href={ window.document.location.href }>{ socketAlert }</Alert> }
<Box display={{ base: 'block', lg: 'none' }}> <Box display={{ base: 'block', lg: 'none' }}>
{ query.pagination.page === 1 && (
<SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ newItemsCount }
alert={ socketAlert }
type="block"
isLoading={ query.isPlaceholderData }
/>
) }
<BlocksList data={ query.data.items } isLoading={ query.isPlaceholderData } page={ query.pagination.page }/> <BlocksList data={ query.data.items } isLoading={ query.isPlaceholderData } page={ query.pagination.page }/>
</Box> </Box>
<Box display={{ base: 'none', lg: 'block' }}> <Box display={{ base: 'none', lg: 'block' }}>
...@@ -80,6 +98,9 @@ const BlocksContent = ({ type, query }: Props) => { ...@@ -80,6 +98,9 @@ const BlocksContent = ({ type, query }: Props) => {
top={ query.pagination.isVisible ? 80 : 0 } top={ query.pagination.isVisible ? 80 : 0 }
page={ query.pagination.page } page={ query.pagination.page }
isLoading={ query.isPlaceholderData } isLoading={ query.isPlaceholderData }
showSocketInfo={ query.pagination.page === 1 }
socketInfoNum={ newItemsCount }
socketInfoAlert={ socketAlert }
/> />
</Box> </Box>
</> </>
......
...@@ -8,6 +8,7 @@ import type { Block } from 'types/api/block'; ...@@ -8,6 +8,7 @@ import type { Block } from 'types/api/block';
import config from 'configs/app'; import config from 'configs/app';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import BlocksTableItem from 'ui/blocks/BlocksTableItem'; import BlocksTableItem from 'ui/blocks/BlocksTableItem';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import { default as Thead } from 'ui/shared/TheadSticky'; import { default as Thead } from 'ui/shared/TheadSticky';
interface Props { interface Props {
...@@ -15,9 +16,23 @@ interface Props { ...@@ -15,9 +16,23 @@ interface Props {
isLoading?: boolean; isLoading?: boolean;
top: number; top: number;
page: number; page: number;
socketInfoNum?: number;
socketInfoAlert?: string;
showSocketInfo?: boolean;
} }
const BlocksTable = ({ data, isLoading, top, page }: Props) => { const VALIDATOR_COL_WEIGHT = 23;
const GAS_COL_WEIGHT = 33;
const REWARD_COL_WEIGHT = 22;
const FEES_COL_WEIGHT = 22;
const BlocksTable = ({ data, isLoading, top, page, showSocketInfo, socketInfoNum, socketInfoAlert }: Props) => {
const widthBase =
VALIDATOR_COL_WEIGHT +
GAS_COL_WEIGHT +
(!config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.total_reward ? REWARD_COL_WEIGHT : 0) +
(!config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.burnt_fees ? FEES_COL_WEIGHT : 0);
return ( return (
<Table variant="simple" minWidth="1040px" size="md" fontWeight={ 500 }> <Table variant="simple" minWidth="1040px" size="md" fontWeight={ 500 }>
...@@ -25,16 +40,25 @@ const BlocksTable = ({ data, isLoading, top, page }: Props) => { ...@@ -25,16 +40,25 @@ const BlocksTable = ({ data, isLoading, top, page }: Props) => {
<Tr> <Tr>
<Th width="125px">Block</Th> <Th width="125px">Block</Th>
<Th width="120px">Size, bytes</Th> <Th width="120px">Size, bytes</Th>
<Th width={ config.features.rollup.isEnabled ? '37%' : '23%' } minW="160px">{ capitalize(getNetworkValidatorTitle()) }</Th> <Th width={ `${ VALIDATOR_COL_WEIGHT / widthBase * 100 }%` } minW="160px">{ capitalize(getNetworkValidatorTitle()) }</Th>
<Th width="64px" isNumeric>Txn</Th> <Th width="64px" isNumeric>Txn</Th>
<Th width={ config.features.rollup.isEnabled ? '63%' : '33%' }>Gas used</Th> <Th width={ `${ GAS_COL_WEIGHT / widthBase * 100 }%` }>Gas used</Th>
{ !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.total_reward && { !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.total_reward &&
<Th width="22%">Reward { config.chain.currency.symbol }</Th> } <Th width={ `${ REWARD_COL_WEIGHT / widthBase * 100 }%` }>Reward { config.chain.currency.symbol }</Th> }
{ !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.burnt_fees && { !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.burnt_fees &&
<Th width="22%">Burnt fees { config.chain.currency.symbol }</Th> } <Th width={ `${ FEES_COL_WEIGHT / widthBase * 100 }%` }>Burnt fees { config.chain.currency.symbol }</Th> }
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="block"
isLoading={ isLoading }
/>
) }
<AnimatePresence initial={ false }> <AnimatePresence initial={ false }>
{ data.map((item, index) => ( { data.map((item, index) => (
<BlocksTableItem <BlocksTableItem
......
...@@ -7,7 +7,7 @@ interface InjectedProps { ...@@ -7,7 +7,7 @@ interface InjectedProps {
} }
interface Props { interface Props {
type?: 'transaction' | 'token_transfer' | 'deposit'; type?: 'transaction' | 'token_transfer' | 'deposit' | 'block';
children?: (props: InjectedProps) => JSX.Element; children?: (props: InjectedProps) => JSX.Element;
className?: string; className?: string;
url: string; url: string;
...@@ -33,6 +33,9 @@ const SocketNewItemsNotice = chakra(({ children, className, url, num, alert, typ ...@@ -33,6 +33,9 @@ const SocketNewItemsNotice = chakra(({ children, className, url, num, alert, typ
case 'deposit': case 'deposit':
name = 'deposit'; name = 'deposit';
break; break;
case 'block':
name = 'block';
break;
default: default:
name = 'transaction'; name = 'transaction';
break; break;
......
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