Commit 4f948605 authored by tom's avatar tom

skeletons for validated blocks by address

parent c91f469d
...@@ -11,6 +11,8 @@ import { getResourceKey } from 'lib/api/useApiQuery'; ...@@ -11,6 +11,8 @@ import { getResourceKey } from 'lib/api/useApiQuery';
import useQueryWithPages from 'lib/hooks/useQueryWithPages'; import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import { BLOCK } from 'stubs/block';
import { generateListStub } from 'stubs/utils';
import ActionBar from 'ui/shared/ActionBar'; import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay'; import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination'; import Pagination from 'ui/shared/Pagination';
...@@ -34,6 +36,18 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => { ...@@ -34,6 +36,18 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
resourceName: 'address_blocks_validated', resourceName: 'address_blocks_validated',
pathParams: { hash: addressHash }, pathParams: { hash: addressHash },
scrollRef, scrollRef,
options: {
placeholderData: generateListStub<'address_blocks_validated'>(
BLOCK,
50,
{
next_page_params: {
block_number: 9060562,
items_count: 50,
},
},
),
},
}); });
const handleSocketError = React.useCallback(() => { const handleSocketError = React.useCallback(() => {
...@@ -61,7 +75,7 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => { ...@@ -61,7 +75,7 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
topic: `blocks:${ addressHash.toLowerCase() }`, topic: `blocks:${ addressHash.toLowerCase() }`,
onSocketClose: handleSocketError, onSocketClose: handleSocketError,
onSocketError: handleSocketError, onSocketError: handleSocketError,
isDisabled: !addressHash || query.pagination.page !== 1, isDisabled: !addressHash || query.isPlaceholderData || query.pagination.page !== 1,
}); });
useSocketMessage({ useSocketMessage({
channel, channel,
...@@ -84,22 +98,32 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => { ...@@ -84,22 +98,32 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
{ query.data.items.map((item) => ( { query.data.items.map((item, index) => (
<AddressBlocksValidatedTableItem key={ item.height } { ...item } page={ query.pagination.page }/> <AddressBlocksValidatedTableItem
key={ item.height + (query.isPlaceholderData ? String(index) : '') }
{ ...item }
page={ query.pagination.page }
isLoading={ query.isPlaceholderData }
/>
)) } )) }
</Tbody> </Tbody>
</Table> </Table>
</Hide> </Hide>
<Show below="lg" ssr={ false }> <Show below="lg" ssr={ false }>
{ query.data.items.map((item) => ( { query.data.items.map((item, index) => (
<AddressBlocksValidatedListItem key={ item.height } { ...item } page={ query.pagination.page }/> <AddressBlocksValidatedListItem
key={ item.height + (query.isPlaceholderData ? String(index) : '') }
{ ...item }
page={ query.pagination.page }
isLoading={ query.isPlaceholderData }
/>
)) } )) }
</Show> </Show>
</> </>
) : null; ) : null;
const actionBar = query.isPaginationVisible ? ( const actionBar = query.isPaginationVisible ? (
<ActionBar mt={ -6 } showShadow={ query.isLoading }> <ActionBar mt={ -6 }>
<Pagination ml="auto" { ...query.pagination }/> <Pagination ml="auto" { ...query.pagination }/>
</ActionBar> </ActionBar>
) : null; ) : null;
...@@ -107,7 +131,7 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => { ...@@ -107,7 +131,7 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
return ( return (
<DataListDisplay <DataListDisplay
isError={ query.isError } isError={ query.isError }
isLoading={ query.isLoading } isLoading={ false }
items={ query.data?.items } items={ query.data?.items }
skeletonProps={{ isLongSkeleton: true, skeletonDesktopColumns: [ '17%', '17%', '16%', '25%', '25%' ] }} skeletonProps={{ isLongSkeleton: true, skeletonDesktopColumns: [ '17%', '17%', '16%', '25%', '25%' ] }}
emptyText="There are no validated blocks for this address." emptyText="There are no validated blocks for this address."
......
import { Text, Flex } from '@chakra-ui/react'; import { Flex, Skeleton } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import React from 'react'; import React from 'react';
...@@ -14,6 +14,7 @@ import Utilization from 'ui/shared/Utilization/Utilization'; ...@@ -14,6 +14,7 @@ import Utilization from 'ui/shared/Utilization/Utilization';
type Props = Block & { type Props = Block & {
page: number; page: number;
isLoading: boolean;
}; };
const AddressBlocksValidatedListItem = (props: Props) => { const AddressBlocksValidatedListItem = (props: Props) => {
...@@ -24,21 +25,31 @@ const AddressBlocksValidatedListItem = (props: Props) => { ...@@ -24,21 +25,31 @@ const AddressBlocksValidatedListItem = (props: Props) => {
return ( return (
<ListItemMobile rowGap={ 2 } isAnimated> <ListItemMobile rowGap={ 2 } isAnimated>
<Flex justifyContent="space-between" w="100%"> <Flex justifyContent="space-between" w="100%">
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
<LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal> <LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal>
<Text variant="secondary">{ timeAgo }</Text> </Skeleton>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
<span>{ timeAgo }</span>
</Skeleton>
</Flex> </Flex>
<Flex columnGap={ 2 } w="100%"> <Flex columnGap={ 2 } w="100%">
<Text fontWeight={ 500 } flexShrink={ 0 }>Txn</Text> <Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Txn</Skeleton>
<Text variant="secondary">{ props.tx_count }</Text> <Skeleton isLoaded={ !props.isLoading } display="inline-block" color="Skeleton_secondary">
<span>{ props.tx_count }</span>
</Skeleton>
</Flex> </Flex>
<Flex columnGap={ 2 } w="100%"> <Flex columnGap={ 2 } w="100%">
<Text fontWeight={ 500 } flexShrink={ 0 }>Gas used</Text> <Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Gas used</Skeleton>
<Text variant="secondary">{ BigNumber(props.gas_used || 0).toFormat() }</Text> <Skeleton isLoaded={ !props.isLoading } variant="secondary">{ BigNumber(props.gas_used || 0).toFormat() }</Skeleton>
<Utilization colorScheme="gray" value={ BigNumber(props.gas_used || 0).dividedBy(BigNumber(props.gas_limit)).toNumber() }/> <Utilization
colorScheme="gray"
value={ BigNumber(props.gas_used || 0).dividedBy(BigNumber(props.gas_limit)).toNumber() }
isLoading={ props.isLoading }
/>
</Flex> </Flex>
<Flex columnGap={ 2 } w="100%"> <Flex columnGap={ 2 } w="100%">
<Text fontWeight={ 500 } flexShrink={ 0 }>Reward { appConfig.network.currency.symbol }</Text> <Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Reward { appConfig.network.currency.symbol }</Skeleton>
<Text variant="secondary">{ totalReward.toFixed() }</Text> <Skeleton isLoaded={ !props.isLoading } variant="secondary">{ totalReward.toFixed() }</Skeleton>
</Flex> </Flex>
</ListItemMobile> </ListItemMobile>
); );
......
import { Td, Tr, Text, Box, Flex } from '@chakra-ui/react'; import { Td, Tr, Flex, Skeleton } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import React from 'react'; import React from 'react';
...@@ -12,6 +12,7 @@ import Utilization from 'ui/shared/Utilization/Utilization'; ...@@ -12,6 +12,7 @@ import Utilization from 'ui/shared/Utilization/Utilization';
type Props = Block & { type Props = Block & {
page: number; page: number;
isLoading: boolean;
}; };
const AddressBlocksValidatedTableItem = (props: Props) => { const AddressBlocksValidatedTableItem = (props: Props) => {
...@@ -22,22 +23,36 @@ const AddressBlocksValidatedTableItem = (props: Props) => { ...@@ -22,22 +23,36 @@ const AddressBlocksValidatedTableItem = (props: Props) => {
return ( return (
<Tr> <Tr>
<Td> <Td>
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
<LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal> <LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal>
</Skeleton>
</Td> </Td>
<Td> <Td>
<Text variant="secondary">{ timeAgo }</Text> <Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
<span>{ timeAgo }</span>
</Skeleton>
</Td> </Td>
<Td> <Td>
<Text fontWeight="500">{ props.tx_count }</Text> <Skeleton isLoaded={ !props.isLoading } display="inline-block" fontWeight="500">
<span>{ props.tx_count }</span>
</Skeleton>
</Td> </Td>
<Td> <Td>
<Flex alignItems="center" columnGap={ 2 }> <Flex alignItems="center" columnGap={ 2 }>
<Box flexBasis="80px">{ BigNumber(props.gas_used || 0).toFormat() }</Box> <Skeleton isLoaded={ !props.isLoading } flexBasis="80px">
<Utilization colorScheme="gray" value={ BigNumber(props.gas_used || 0).dividedBy(BigNumber(props.gas_limit)).toNumber() }/> { BigNumber(props.gas_used || 0).toFormat() }
</Skeleton>
<Utilization
colorScheme="gray"
value={ BigNumber(props.gas_used || 0).dividedBy(BigNumber(props.gas_limit)).toNumber() }
isLoading={ props.isLoading }
/>
</Flex> </Flex>
</Td> </Td>
<Td isNumeric display="flex" justifyContent="end"> <Td isNumeric display="flex" justifyContent="end">
{ totalReward.toFixed() } <Skeleton isLoaded={ !props.isLoading } display="inline-block">
<span>{ totalReward.toFixed() }</span>
</Skeleton>
</Td> </Td>
</Tr> </Tr>
); );
......
...@@ -193,7 +193,7 @@ const TxDetails = () => { ...@@ -193,7 +193,7 @@ const TxDetails = () => {
</Skeleton> </Skeleton>
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
<DetailsSponsoredItem/> <DetailsSponsoredItem isLoading={ isPlaceholderData }/>
{ divider } { divider }
......
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