Commit 1c78a12c authored by tom's avatar tom

highlight similar addresses in the table views

parent e1cf276c
import React from 'react';
interface AddressHighlightProviderProps {
children: React.ReactNode;
}
interface TAddressHighlightContext {
highlightedAddress: string | null;
onMouseEnter: (event: React.MouseEvent) => void;
onMouseLeave: (event: React.MouseEvent) => void;
}
export const AddressHighlightContext = React.createContext<TAddressHighlightContext | null>(null);
export function AddressHighlightProvider({ children }: AddressHighlightProviderProps) {
const [ highlightedAddress, setHighlightedAddress ] = React.useState<string | null>(null);
const onMouseEnter = React.useCallback((event: React.MouseEvent) => {
// TODO @tom2drum add throttling
const hash = event.currentTarget.getAttribute('data-hash');
hash && setHighlightedAddress(hash);
}, []);
const onMouseLeave = React.useCallback(() => {
setHighlightedAddress(null);
}, []);
const value = React.useMemo(() => {
return {
highlightedAddress,
onMouseEnter,
onMouseLeave,
};
}, [ highlightedAddress, onMouseEnter, onMouseLeave ]);
return (
<AddressHighlightContext.Provider value={ value }>
{ children }
</AddressHighlightContext.Provider>
);
}
export function useAddressHighlightContext() {
const context = React.useContext(AddressHighlightContext);
if (context === undefined) {
return null;
}
return context;
}
......@@ -4,6 +4,7 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import { default as Thead } from 'ui/shared/TheadSticky';
import AddressIntTxsTableItem from './AddressIntTxsTableItem';
......@@ -16,31 +17,34 @@ interface Props {
const AddressIntTxsTable = ({ data, currentAddress, isLoading }: Props) => {
return (
<Table variant="simple" size="sm">
<Thead top={ 80 }>
<Tr>
<Th width="15%">Parent txn hash</Th>
<Th width="15%">Type</Th>
<Th width="10%">Block</Th>
<Th width="20%">From</Th>
<Th width="48px" px={ 0 }/>
<Th width="20%">To</Th>
<Th width="20%" isNumeric>
<AddressHighlightProvider>
<Table variant="simple" size="sm">
<Thead top={ 80 }>
<Tr>
<Th width="15%">Parent txn hash</Th>
<Th width="15%">Type</Th>
<Th width="10%">Block</Th>
<Th width="20%">From</Th>
<Th width="48px" px={ 0 }/>
<Th width="20%">To</Th>
<Th width="20%" isNumeric>
Value { config.chain.currency.symbol }
</Th>
</Tr>
</Thead>
<Tbody>
{ data.map((item, index) => (
<AddressIntTxsTableItem
key={ item.transaction_hash + '_' + index }
{ ...item }
currentAddress={ currentAddress }
isLoading={ isLoading }
/>
)) }
</Tbody>
</Table>
</Th>
</Tr>
</Thead>
<Tbody>
{ data.map((item, index) => (
<AddressIntTxsTableItem
key={ item.transaction_hash + '_' + index }
{ ...item }
currentAddress={ currentAddress }
isLoading={ isLoading }
/>
)) }
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
......@@ -83,6 +83,7 @@ const AddressIntTxsTableItem = ({
isLoading={ isLoading }
noLink={ isOut }
noCopy={ isOut }
w="min-content"
/>
</Td>
<Td px={ 0 } verticalAlign="middle">
......@@ -98,6 +99,7 @@ const AddressIntTxsTableItem = ({
isLoading={ isLoading }
noLink={ isIn }
noCopy={ isIn }
w="min-content"
/>
) }
</Td>
......
......@@ -6,6 +6,7 @@ import React from 'react';
import type { Block } from 'types/api/block';
import config from 'configs/app';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import BlocksTableItem from 'ui/blocks/BlocksTableItem';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
......@@ -37,43 +38,45 @@ const BlocksTable = ({ data, isLoading, top, page, showSocketInfo, socketInfoNum
(!isRollup && !config.UI.views.block.hiddenFields?.burnt_fees ? FEES_COL_WEIGHT : 0);
return (
<Table variant="simple" minWidth="1040px" size="md" fontWeight={ 500 }>
<Thead top={ top }>
<Tr>
<Th width="125px">Block</Th>
<Th width="120px">Size, bytes</Th>
{ !config.UI.views.block.hiddenFields?.miner &&
<AddressHighlightProvider>
<Table variant="simple" minWidth="1040px" size="md" fontWeight={ 500 }>
<Thead top={ top }>
<Tr>
<Th width="125px">Block</Th>
<Th width="120px">Size, bytes</Th>
{ !config.UI.views.block.hiddenFields?.miner &&
<Th width={ `${ VALIDATOR_COL_WEIGHT / widthBase * 100 }%` } minW="160px">{ capitalize(getNetworkValidatorTitle()) }</Th> }
<Th width="64px" isNumeric>Txn</Th>
<Th width={ `${ GAS_COL_WEIGHT / widthBase * 100 }%` }>Gas used</Th>
{ !isRollup && !config.UI.views.block.hiddenFields?.total_reward &&
<Th width="64px" isNumeric>Txn</Th>
<Th width={ `${ GAS_COL_WEIGHT / widthBase * 100 }%` }>Gas used</Th>
{ !isRollup && !config.UI.views.block.hiddenFields?.total_reward &&
<Th width={ `${ REWARD_COL_WEIGHT / widthBase * 100 }%` }>Reward { config.chain.currency.symbol }</Th> }
{ !isRollup && !config.UI.views.block.hiddenFields?.burnt_fees &&
{ !isRollup && !config.UI.views.block.hiddenFields?.burnt_fees &&
<Th width={ `${ FEES_COL_WEIGHT / widthBase * 100 }%` }>Burnt fees { config.chain.currency.symbol }</Th> }
</Tr>
</Thead>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="block"
isLoading={ isLoading }
/>
) }
<AnimatePresence initial={ false }>
{ data.map((item, index) => (
<BlocksTableItem
key={ item.height + (isLoading ? `${ index }_${ page }` : '') }
data={ item }
enableTimeIncrement={ page === 1 && !isLoading }
</Tr>
</Thead>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="block"
isLoading={ isLoading }
/>
)) }
</AnimatePresence>
</Tbody>
</Table>
) }
<AnimatePresence initial={ false }>
{ data.map((item, index) => (
<BlocksTableItem
key={ item.height + (isLoading ? `${ index }_${ page }` : '') }
data={ item }
enableTimeIncrement={ page === 1 && !isLoading }
isLoading={ isLoading }
/>
)) }
</AnimatePresence>
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
......@@ -4,6 +4,7 @@ import React from 'react';
import { route } from 'nextjs-routes';
import useApiQuery from 'lib/api/useApiQuery';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import useIsMobile from 'lib/hooks/useIsMobile';
import useNewTxsSocket from 'lib/hooks/useNewTxsSocket';
import { TX } from 'stubs/tx';
......@@ -42,15 +43,17 @@ const LatestTransactions = () => {
/>
))) }
</Box>
<Box mb={ 4 } display={{ base: 'none', lg: 'block' }}>
{ data.slice(0, txsCount).map(((tx, index) => (
<LatestTxsItem
key={ tx.hash + (isPlaceholderData ? index : '') }
tx={ tx }
isLoading={ isPlaceholderData }
/>
))) }
</Box>
<AddressHighlightProvider>
<Box mb={ 4 } display={{ base: 'none', lg: 'block' }}>
{ data.slice(0, txsCount).map(((tx, index) => (
<LatestTxsItem
key={ tx.hash + (isPlaceholderData ? index : '') }
tx={ tx }
isLoading={ isPlaceholderData }
/>
))) }
</Box>
</AddressHighlightProvider>
<Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ txsUrl }>View all transactions</LinkInternal>
</Flex>
......
......@@ -35,7 +35,10 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
return (
<Grid
gridTemplateColumns={ columnNum === 2 ? '3fr 2fr' : '3fr 2fr 150px' }
gridTemplateColumns={{
lg: columnNum === 2 ? '3fr minmax(auto, 160px)' : '3fr minmax(auto, 160px) 150px',
xl: columnNum === 2 ? '3fr minmax(auto, 250px)' : '3fr minmax(auto, 250px) 150px',
}}
gridGap={ 8 }
width="100%"
minW="700px"
......@@ -77,15 +80,16 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
</Flex>
</Box>
</Flex>
<Grid alignItems="center" alignSelf="flex-start" templateColumns="24px auto">
<Flex alignItems="center" alignSelf="flex-start">
<Icon
as={ rightArrowIcon }
boxSize={ 6 }
color="gray.500"
transform="rotate(90deg)"
isLoading={ isLoading }
flexShrink={ 0 }
/>
<Box overflow="hidden" ml={ 1 }>
<Box ml={ 1 } maxW="calc(100% - 24px)">
<AddressEntity
isLoading={ isLoading }
address={ tx.from }
......@@ -104,7 +108,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
/>
) }
</Box>
</Grid>
</Flex>
<Box>
{ !config.UI.views.tx.hiddenFields?.value && (
<Skeleton isLoaded={ !isLoading } mb={ 2 }>
......
......@@ -3,6 +3,7 @@ import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import { default as Thead } from 'ui/shared/TheadSticky';
import TokenTransferTableItem from 'ui/shared/TokenTransfer/TokenTransferTableItem';
......@@ -32,41 +33,43 @@ const TokenTransferTable = ({
}: Props) => {
return (
<Table variant="simple" size="sm" minW="950px">
<Thead top={ top }>
<Tr>
{ showTxInfo && <Th width="44px"></Th> }
<Th width="185px">Token</Th>
<Th width="160px">Token ID</Th>
{ showTxInfo && <Th width="25%">Txn hash</Th> }
<Th width="25%">From</Th>
{ baseAddress && <Th width="50px" px={ 0 }/> }
<Th width="25%">To</Th>
<Th width="25%" isNumeric>Value</Th>
</Tr>
</Thead>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="token_transfer"
isLoading={ isLoading }
/>
) }
{ data.map((item, index) => (
<TokenTransferTableItem
key={ item.tx_hash + item.block_hash + item.log_index + (isLoading ? index : '') }
{ ...item }
baseAddress={ baseAddress }
showTxInfo={ showTxInfo }
enableTimeIncrement={ enableTimeIncrement }
isLoading={ isLoading }
/>
)) }
</Tbody>
</Table>
<AddressHighlightProvider>
<Table variant="simple" size="sm" minW="950px">
<Thead top={ top }>
<Tr>
{ showTxInfo && <Th width="44px"></Th> }
<Th width="185px">Token</Th>
<Th width="160px">Token ID</Th>
{ showTxInfo && <Th width="25%">Txn hash</Th> }
<Th width="25%">From</Th>
{ baseAddress && <Th width="50px" px={ 0 }/> }
<Th width="25%">To</Th>
<Th width="25%" isNumeric>Value</Th>
</Tr>
</Thead>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="token_transfer"
isLoading={ isLoading }
/>
) }
{ data.map((item, index) => (
<TokenTransferTableItem
key={ item.tx_hash + item.block_hash + item.log_index + (isLoading ? index : '') }
{ ...item }
baseAddress={ baseAddress }
showTxInfo={ showTxInfo }
enableTimeIncrement={ enableTimeIncrement }
isLoading={ isLoading }
/>
)) }
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
import type { As } from '@chakra-ui/react';
import { Box, Flex, Skeleton, Tooltip, chakra, VStack } from '@chakra-ui/react';
import { Box, Flex, Skeleton, Tooltip, chakra, VStack, useColorModeValue } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react';
......@@ -10,6 +10,7 @@ import { route } from 'nextjs-routes';
import iconSafe from 'icons/brands/safe.svg';
import iconContractVerified from 'icons/contract_verified.svg';
import iconContract from 'icons/contract.svg';
import { useAddressHighlightContext } from 'lib/contexts/addressHighlight';
import * as EntityBase from 'ui/shared/entities/base/components';
import { getIconProps } from '../base/utils';
......@@ -148,8 +149,32 @@ const AddressEntry = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
const context = useAddressHighlightContext();
const highlightedBgColor = useColorModeValue('blue.50', 'blue.900');
const highlightedBorderColor = useColorModeValue('blue.200', 'blue.600');
return (
<Container className={ props.className }>
<Container
className={ props.className }
data-hash={ props.address.hash }
onMouseEnter={ context?.onMouseEnter }
onMouseLeave={ context?.onMouseLeave }
position="relative"
_before={ !props.isLoading && context?.highlightedAddress === props.address.hash ? {
content: `" "`,
position: 'absolute',
top: '-7px',
left: '-5px',
width: `calc(100% + ${ props.noCopy ? 10 : 5 }px)`,
height: 'calc(100% + 12px)',
borderRadius: 'base',
borderColor: highlightedBorderColor,
borderWidth: '1px',
borderStyle: 'dashed',
bgColor: highlightedBgColor,
zIndex: -1,
} : undefined }
>
<Icon { ...partsProps }/>
<Link { ...linkProps }>
<Content { ...partsProps }/>
......
......@@ -32,14 +32,17 @@ export interface EntityBaseProps {
export interface ContainerBaseProps extends Pick<EntityBaseProps, 'className'> {
children: React.ReactNode;
onMouseEnter?: (event: React.MouseEvent) => void;
onMouseLeave?: (event: React.MouseEvent) => void;
}
const Container = chakra(({ className, children }: ContainerBaseProps) => {
const Container = chakra(({ className, children, ...props }: ContainerBaseProps) => {
return (
<Flex
className={ className }
alignItems="center"
minWidth={ 0 } // for content truncation - https://css-tricks.com/flexbox-truncated-text/
{ ...props }
>
{ children }
</Flex>
......
......@@ -5,6 +5,7 @@ import React from 'react';
import type { TokenInfo } from 'types/api/token';
import type { ResourceError } from 'lib/api/resources';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import useIsMobile from 'lib/hooks/useIsMobile';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
......@@ -58,21 +59,23 @@ const TokenInventory = ({ inventoryQuery, tokenQuery, ownerFilter }: Props) => {
const token = tokenQuery.data;
const content = items && token ? (
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
rowGap={{ base: 3, lg: 6 }}
gridTemplateColumns={{ base: 'repeat(2, calc((100% - 12px)/2))', lg: 'repeat(auto-fill, minmax(210px, 1fr))' }}
>
{ items.map((item, index) => (
<TokenInventoryItem
key={ token.address + '_' + item.id + (inventoryQuery.isPlaceholderData ? '_' + index : '') }
item={ item }
isLoading={ inventoryQuery.isPlaceholderData || tokenQuery.isPlaceholderData }
token={ token }
/>
)) }
</Grid>
<AddressHighlightProvider>
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
rowGap={{ base: 3, lg: 6 }}
gridTemplateColumns={{ base: 'repeat(2, calc((100% - 12px)/2))', lg: 'repeat(auto-fill, minmax(210px, 1fr))' }}
>
{ items.map((item, index) => (
<TokenInventoryItem
key={ token.address + '_' + item.id + (inventoryQuery.isPlaceholderData ? '_' + index : '') }
item={ item }
isLoading={ inventoryQuery.isPlaceholderData || tokenQuery.isPlaceholderData }
token={ token }
/>
)) }
</Grid>
</AddressHighlightProvider>
) : null;
return (
......
......@@ -4,6 +4,7 @@ import React from 'react';
import type { TokenInfo } from 'types/api/token';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import { default as Thead } from 'ui/shared/TheadSticky';
import TruncatedValue from 'ui/shared/TruncatedValue';
......@@ -24,42 +25,44 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
const tokenType = data[0].token.type;
return (
<Table variant="simple" size="sm" minW="950px">
<Thead top={ top }>
<Tr>
<Th width={ tokenType === 'ERC-1155' ? '60%' : '80%' }>Txn hash</Th>
<Th width="164px">Method</Th>
<Th width="160px">From</Th>
<Th width="36px" px={ 0 }/>
<Th width="218px" >To</Th>
{ (tokenType === 'ERC-721' || tokenType === 'ERC-1155') && <Th width="20%" isNumeric={ tokenType === 'ERC-721' }>Token ID</Th> }
{ (tokenType === 'ERC-20' || tokenType === 'ERC-1155') && (
<Th width="20%" isNumeric>
<TruncatedValue value={ `Value ${ token?.symbol || '' }` } w="100%" verticalAlign="middle"/>
</Th>
<AddressHighlightProvider>
<Table variant="simple" size="sm" minW="950px">
<Thead top={ top }>
<Tr>
<Th width={ tokenType === 'ERC-1155' ? '60%' : '80%' }>Txn hash</Th>
<Th width="164px">Method</Th>
<Th width="160px">From</Th>
<Th width="36px" px={ 0 }/>
<Th width="218px" >To</Th>
{ (tokenType === 'ERC-721' || tokenType === 'ERC-1155') && <Th width="20%" isNumeric={ tokenType === 'ERC-721' }>Token ID</Th> }
{ (tokenType === 'ERC-20' || tokenType === 'ERC-1155') && (
<Th width="20%" isNumeric>
<TruncatedValue value={ `Value ${ token?.symbol || '' }` } w="100%" verticalAlign="middle"/>
</Th>
) }
</Tr>
</Thead>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="token_transfer"
isLoading={ isLoading }
/>
) }
</Tr>
</Thead>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
type="token_transfer"
isLoading={ isLoading }
/>
) }
{ data.map((item, index) => (
<TokenTransferTableItem
key={ item.tx_hash + item.block_hash + item.log_index + '_' + index }
{ ...item }
tokenId={ tokenId }
isLoading={ isLoading }
/>
)) }
</Tbody>
</Table>
{ data.map((item, index) => (
<TokenTransferTableItem
key={ item.tx_hash + item.block_hash + item.log_index + '_' + index }
{ ...item }
tokenId={ tokenId }
isLoading={ isLoading }
/>
)) }
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
......@@ -67,6 +67,7 @@ const TokenTransferTableItem = ({
truncation="constant"
tokenHash={ token.address }
my="5px"
w="min-content"
/>
</Td>
<Td px={ 0 }>
......@@ -81,6 +82,7 @@ const TokenTransferTableItem = ({
truncation="constant"
tokenHash={ token.address }
my="5px"
w="min-content"
/>
</Td>
{ (token.type === 'ERC-721' || token.type === 'ERC-1155') && (
......
......@@ -5,6 +5,7 @@ import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app';
import arrowIcon from 'icons/arrows/east.svg';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import { default as Thead } from 'ui/shared/TheadSticky';
import TxInternalsTableItem from 'ui/tx/internals/TxInternalsTableItem';
import type { Sort, SortField } from 'ui/tx/internals/utils';
......@@ -21,33 +22,35 @@ const TxInternalsTable = ({ data, sort, onSortToggle, top, isLoading }: Props) =
const sortIconTransform = sort?.includes('asc') ? 'rotate(-90deg)' : 'rotate(90deg)';
return (
<Table variant="simple" size="sm">
<Thead top={ top }>
<Tr>
<Th width="28%">Type</Th>
<Th width="20%">From</Th>
<Th width="24px" px={ 0 }/>
<Th width="20%">To</Th>
<Th width="16%" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('value') } columnGap={ 1 }>
{ sort?.includes('value') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
<AddressHighlightProvider>
<Table variant="simple" size="sm">
<Thead top={ top }>
<Tr>
<Th width="28%">Type</Th>
<Th width="20%">From</Th>
<Th width="24px" px={ 0 }/>
<Th width="20%">To</Th>
<Th width="16%" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('value') } columnGap={ 1 }>
{ sort?.includes('value') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
Value { config.chain.currency.symbol }
</Link>
</Th>
<Th width="16%" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('gas-limit') } columnGap={ 1 }>
{ sort?.includes('gas-limit') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
</Link>
</Th>
<Th width="16%" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('gas-limit') } columnGap={ 1 }>
{ sort?.includes('gas-limit') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
Gas limit { config.chain.currency.symbol }
</Link>
</Th>
</Tr>
</Thead>
<Tbody>
{ data.map((item, index) => (
<TxInternalsTableItem key={ item.transaction_hash + (isLoading ? index : '') } { ...item } isLoading={ isLoading }/>
)) }
</Tbody>
</Table>
</Link>
</Th>
</Tr>
</Thead>
<Tbody>
{ data.map((item, index) => (
<TxInternalsTableItem key={ item.transaction_hash + (isLoading ? index : '') } { ...item } isLoading={ isLoading }/>
)) }
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
......@@ -8,6 +8,7 @@ import React from 'react';
import type { TxStateChange } from 'types/api/txStateChanges';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import { default as Thead } from 'ui/shared/TheadSticky';
import TxStateTableItem from 'ui/tx/state/TxStateTableItem';
......@@ -19,21 +20,23 @@ interface Props {
const TxStateTable = ({ data, isLoading, top }: Props) => {
return (
<Table variant="simple" minWidth="1000px" size="sm" w="100%">
<Thead top={ top }>
<Tr>
<Th width="140px">Type</Th>
<Th width="160px">Address</Th>
<Th width="33%" isNumeric>Before</Th>
<Th width="33%" isNumeric>After</Th>
<Th width="33%" isNumeric>Change</Th>
<Th width="150px" minW="80px" maxW="150px">Token ID</Th>
</Tr>
</Thead>
<Tbody>
{ data.map((item, index) => <TxStateTableItem data={ item } key={ index } isLoading={ isLoading }/>) }
</Tbody>
</Table>
<AddressHighlightProvider>
<Table variant="simple" minWidth="1000px" size="sm" w="100%">
<Thead top={ top }>
<Tr>
<Th width="140px">Type</Th>
<Th width="160px">Address</Th>
<Th width="33%" isNumeric>Before</Th>
<Th width="33%" isNumeric>After</Th>
<Th width="33%" isNumeric>Change</Th>
<Th width="150px" minW="80px" maxW="150px">Token ID</Th>
</Tr>
</Thead>
<Tbody>
{ data.map((item, index) => <TxStateTableItem data={ item } key={ index } isLoading={ isLoading }/>) }
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
......@@ -27,7 +27,8 @@ const TxStateTableItem = ({ data, isLoading }: Props) => {
address={ data.address }
isLoading={ isLoading }
truncation="constant"
py="7px"
my="7px"
w="min-content"
/>
</Td>
<Td isNumeric><Box py="7px">{ before }</Box></Td>
......
......@@ -6,6 +6,7 @@ import type { Transaction, TransactionsSortingField, TransactionsSortingValue }
import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import TheadSticky from 'ui/shared/TheadSticky';
......@@ -39,65 +40,67 @@ const TxsTable = ({
isLoading,
}: Props) => {
return (
<Table variant="simple" minWidth="950px" size="xs">
<TheadSticky top={ top }>
<Tr>
<Th width="54px"></Th>
<Th width="22%">Txn hash</Th>
<Th width="160px">Type</Th>
<Th width="20%">Method</Th>
{ showBlockInfo && <Th width="18%">Block</Th> }
<Th width={{ xl: '152px', base: '86px' }}>
<Show above="xl" ssr={ false }>From</Show>
<Hide above="xl" ssr={ false }>From / To</Hide>
</Th>
<Th width={{ xl: currentAddress ? '48px' : '36px', base: currentAddress ? '52px' : '28px' }}></Th>
<Th width={{ xl: '152px', base: '86px' }}>
<Show above="xl" ssr={ false }>To</Show>
</Th>
{ !config.UI.views.tx.hiddenFields?.value && (
<Th width="20%" isNumeric>
<Link onClick={ sort('value') } display="flex" justifyContent="end">
{ sorting === 'value-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
{ sorting === 'value-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
{ `Value ${ config.chain.currency.symbol }` }
</Link>
<AddressHighlightProvider>
<Table variant="simple" minWidth="950px" size="xs">
<TheadSticky top={ top }>
<Tr>
<Th width="54px"></Th>
<Th width="22%">Txn hash</Th>
<Th width="160px">Type</Th>
<Th width="20%">Method</Th>
{ showBlockInfo && <Th width="18%">Block</Th> }
<Th width={{ xl: '152px', base: '86px' }}>
<Show above="xl" ssr={ false }>From</Show>
<Hide above="xl" ssr={ false }>From / To</Hide>
</Th>
) }
{ !config.UI.views.tx.hiddenFields?.tx_fee && (
<Th width="20%" isNumeric pr={ 5 }>
<Link onClick={ sort('fee') } display="flex" justifyContent="end">
{ sorting === 'fee-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
{ sorting === 'fee-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
{ `Fee${ config.UI.views.tx.hiddenFields?.fee_currency ? '' : ` ${ config.chain.currency.symbol }` }` }
</Link>
<Th width={{ xl: currentAddress ? '48px' : '36px', base: currentAddress ? '52px' : '28px' }}></Th>
<Th width={{ xl: '152px', base: '86px' }}>
<Show above="xl" ssr={ false }>To</Show>
</Th>
) }
</Tr>
</TheadSticky>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
isLoading={ isLoading }
/>
) }
<AnimatePresence initial={ false }>
{ txs.map((item, index) => (
<TxsTableItem
key={ item.hash + (isLoading ? index : '') }
tx={ item }
showBlockInfo={ showBlockInfo }
currentAddress={ currentAddress }
enableTimeIncrement={ enableTimeIncrement }
{ !config.UI.views.tx.hiddenFields?.value && (
<Th width="20%" isNumeric>
<Link onClick={ sort('value') } display="flex" justifyContent="end">
{ sorting === 'value-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
{ sorting === 'value-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
{ `Value ${ config.chain.currency.symbol }` }
</Link>
</Th>
) }
{ !config.UI.views.tx.hiddenFields?.tx_fee && (
<Th width="20%" isNumeric pr={ 5 }>
<Link onClick={ sort('fee') } display="flex" justifyContent="end">
{ sorting === 'fee-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
{ sorting === 'fee-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
{ `Fee${ config.UI.views.tx.hiddenFields?.fee_currency ? '' : ` ${ config.chain.currency.symbol }` }` }
</Link>
</Th>
) }
</Tr>
</TheadSticky>
<Tbody>
{ showSocketInfo && (
<SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert }
num={ socketInfoNum }
isLoading={ isLoading }
/>
)) }
</AnimatePresence>
</Tbody>
</Table>
) }
<AnimatePresence initial={ false }>
{ txs.map((item, index) => (
<TxsTableItem
key={ item.hash + (isLoading ? index : '') }
tx={ item }
showBlockInfo={ showBlockInfo }
currentAddress={ currentAddress }
enableTimeIncrement={ enableTimeIncrement }
isLoading={ isLoading }
/>
)) }
</AnimatePresence>
</Tbody>
</Table>
</AddressHighlightProvider>
);
};
......
......@@ -52,7 +52,8 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
noCopy={ isOut }
noLink={ isOut }
truncation="constant"
w="100%"
w="min-content"
maxW="100%"
py="2px"
/>
);
......@@ -64,7 +65,8 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
truncation="constant"
noCopy={ isIn }
noLink={ isIn }
w="100%"
w="min-content"
maxW="100%"
py="2px"
/>
) : '-';
......@@ -150,7 +152,7 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
isLoading={ isLoading }
/>
) }
<VStack alignItems="start" overflow="hidden" ml={ 1 }>
<VStack alignItems="start" ml={ 1 } w="calc(100% - 48px)">
{ addressFrom }
{ addressTo }
</VStack>
......
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