Commit eae41d10 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Show tags for watch list txs (#1289)

watchlist - show private tag

Fixes #1209
parent 3b49f1d1
...@@ -68,8 +68,25 @@ export const base: Transaction = { ...@@ -68,8 +68,25 @@ export const base: Transaction = {
has_error_in_internal_txs: false, has_error_in_internal_txs: false,
}; };
export const withWatchListNames: Transaction = {
...base,
hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3194',
from: {
...base.from,
watchlist_names: [
{ label: 'from #1', display_name: 'from utka' },
{ label: 'kitty', display_name: 'kitty kitty kitty cat where are you' },
],
},
to: {
...base.to,
watchlist_names: [ { label: 'to #1', display_name: 'to utka' } ],
} as Transaction['to'],
};
export const withContractCreation: Transaction = { export const withContractCreation: Transaction = {
...base, ...base,
hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3195',
to: null, to: null,
created_contract: { created_contract: {
hash: '0xdda21946FF3FAa027104b15BE6970CA756439F5a', hash: '0xdda21946FF3FAa027104b15BE6970CA756439F5a',
...@@ -88,6 +105,7 @@ export const withContractCreation: Transaction = { ...@@ -88,6 +105,7 @@ export const withContractCreation: Transaction = {
export const withTokenTransfer: Transaction = { export const withTokenTransfer: Transaction = {
...base, ...base,
hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3196',
to: { to: {
hash: '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859', hash: '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859',
implementation_name: null, implementation_name: null,
......
...@@ -21,6 +21,7 @@ test.describe('mobile', () => { ...@@ -21,6 +21,7 @@ test.describe('mobile', () => {
txMock.base, txMock.base,
txMock.withContractCreation, txMock.withContractCreation,
txMock.withTokenTransfer, txMock.withTokenTransfer,
txMock.withWatchListNames,
]), ]),
})); }));
...@@ -41,6 +42,7 @@ test('default view +@dark-mode', async({ mount, page }) => { ...@@ -41,6 +42,7 @@ test('default view +@dark-mode', async({ mount, page }) => {
txMock.base, txMock.base,
txMock.withContractCreation, txMock.withContractCreation,
txMock.withTokenTransfer, txMock.withTokenTransfer,
txMock.withWatchListNames,
]), ]),
})); }));
......
...@@ -17,6 +17,7 @@ import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; ...@@ -17,6 +17,7 @@ import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon'; import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
import TxStatus from 'ui/shared/TxStatus'; import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo'; import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
import TxType from 'ui/txs/TxType'; import TxType from 'ui/txs/TxType';
...@@ -32,22 +33,24 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -32,22 +33,24 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
const columnNum = config.UI.views.tx.hiddenFields?.value && config.UI.views.tx.hiddenFields?.tx_fee ? 2 : 3; const columnNum = config.UI.views.tx.hiddenFields?.value && config.UI.views.tx.hiddenFields?.tx_fee ? 2 : 3;
return ( return (
<Box <Grid
gridTemplateColumns={ columnNum === 2 ? '3fr 2fr' : '3fr 2fr 150px' }
gridGap={ 8 }
width="100%" width="100%"
minW="700px" minW="700px"
borderTop="1px solid" borderTop="1px solid"
borderColor="divider" borderColor="divider"
p={ 4 } p={ 4 }
_last={{ borderBottom: '1px solid', borderColor: 'divider' }} _last={{ borderBottom: '1px solid', borderColor: 'divider' }}
display={{ base: 'none', lg: 'block' }} display={{ base: 'none', lg: 'grid' }}
> >
<Grid width="100%" gridTemplateColumns={ columnNum === 2 ? '3fr 2fr' : '3fr 2fr 150px' } gridGap={ 8 }>
<Flex overflow="hidden" w="100%"> <Flex overflow="hidden" w="100%">
<TxAdditionalInfo tx={ tx } isLoading={ isLoading }/> <TxAdditionalInfo tx={ tx } isLoading={ isLoading }/>
<Box ml={ 3 } w="calc(100% - 40px)"> <Box ml={ 3 } w="calc(100% - 40px)">
<HStack> <HStack flexWrap="wrap">
<TxType types={ tx.tx_types } isLoading={ isLoading }/> <TxType types={ tx.tx_types } isLoading={ isLoading }/>
<TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/> <TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/>
<TxWatchListTags tx={ tx } isLoading={ isLoading }/>
</HStack> </HStack>
<Flex <Flex
mt={ 2 } mt={ 2 }
...@@ -73,7 +76,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -73,7 +76,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
</Flex> </Flex>
</Box> </Box>
</Flex> </Flex>
<Grid alignItems="center" templateColumns="24px auto"> <Grid alignItems="center" alignSelf="flex-start" templateColumns="24px auto">
<Icon <Icon
as={ rightArrowIcon } as={ rightArrowIcon }
boxSize={ 6 } boxSize={ 6 }
...@@ -86,6 +89,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -86,6 +89,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
isLoading={ isLoading } isLoading={ isLoading }
address={ tx.from } address={ tx.from }
fontSize="sm" fontSize="sm"
lineHeight={ 6 }
fontWeight="500" fontWeight="500"
mb={ 2 } mb={ 2 }
/> />
...@@ -94,6 +98,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -94,6 +98,7 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
isLoading={ isLoading } isLoading={ isLoading }
address={ dataTo } address={ dataTo }
fontSize="sm" fontSize="sm"
lineHeight={ 6 }
fontWeight="500" fontWeight="500"
/> />
) } ) }
...@@ -114,7 +119,6 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -114,7 +119,6 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
) } ) }
</Box> </Box>
</Grid> </Grid>
</Box>
); );
}; };
......
...@@ -16,6 +16,7 @@ import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; ...@@ -16,6 +16,7 @@ import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon'; import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
import TxStatus from 'ui/shared/TxStatus'; import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo'; import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
import TxType from 'ui/txs/TxType'; import TxType from 'ui/txs/TxType';
...@@ -39,9 +40,10 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -39,9 +40,10 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
display={{ base: 'block', lg: 'none' }} display={{ base: 'block', lg: 'none' }}
> >
<Flex justifyContent="space-between"> <Flex justifyContent="space-between">
<HStack> <HStack flexWrap="wrap">
<TxType types={ tx.tx_types } isLoading={ isLoading }/> <TxType types={ tx.tx_types } isLoading={ isLoading }/>
<TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/> <TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/>
<TxWatchListTags tx={ tx } isLoading={ isLoading }/>
</HStack> </HStack>
<TxAdditionalInfo tx={ tx } isMobile isLoading={ isLoading }/> <TxAdditionalInfo tx={ tx } isMobile isLoading={ isLoading }/>
</Flex> </Flex>
......
...@@ -10,6 +10,7 @@ import { TX } from 'stubs/tx'; ...@@ -10,6 +10,7 @@ import { TX } from 'stubs/tx';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import LatestTxsItem from './LatestTxsItem'; import LatestTxsItem from './LatestTxsItem';
import LatestTxsItemMobile from './LatestTxsItemMobile';
const LatestWatchlistTxs = () => { const LatestWatchlistTxs = () => {
useRedirectForInvalidAuthToken(); useRedirectForInvalidAuthToken();
...@@ -33,7 +34,16 @@ const LatestWatchlistTxs = () => { ...@@ -33,7 +34,16 @@ const LatestWatchlistTxs = () => {
const txsUrl = route({ pathname: '/txs', query: { tab: 'watchlist' } }); const txsUrl = route({ pathname: '/txs', query: { tab: 'watchlist' } });
return ( return (
<> <>
<Box mb={{ base: 3, lg: 4 }}> <Box mb={ 3 } display={{ base: 'block', lg: 'none' }}>
{ data.slice(0, txsCount).map(((tx, index) => (
<LatestTxsItemMobile
key={ tx.hash + (isPlaceholderData ? index : '') }
tx={ tx }
isLoading={ isPlaceholderData }
/>
))) }
</Box>
<Box mb={ 4 } display={{ base: 'none', lg: 'block' }}>
{ data.slice(0, txsCount).map(((tx, index) => ( { data.slice(0, txsCount).map(((tx, index) => (
<LatestTxsItem <LatestTxsItem
key={ tx.hash + (isPlaceholderData ? index : '') } key={ tx.hash + (isPlaceholderData ? index : '') }
......
import { Flex } from '@chakra-ui/react';
import React from 'react';
import type { Transaction } from 'types/api/transaction';
import Tag from 'ui/shared/chakra/Tag';
interface Props {
tx: Transaction;
isLoading?: boolean;
}
const TxWatchListTags = ({ tx, isLoading }: Props) => {
const tags = [
...(tx.from?.watchlist_names || []),
...(tx.to?.watchlist_names || []),
].filter(Boolean);
if (tags.length === 0) {
return null;
}
return (
<Flex columnGap={ 2 } rowGap={ 2 } flexWrap="wrap" overflow="hidden" maxW="100%">
{ tags.map((tag) => (
<Tag
key={ tag.label }
isLoading={ isLoading }
isTruncated
// maxW={{ base: '115px', lg: 'initial' }}
colorScheme="gray"
variant="subtle"
>
{ tag.display_name }
</Tag>
)) }
</Flex>
);
};
export default React.memo(TxWatchListTags);
...@@ -11,7 +11,7 @@ test.use({ viewport: devices['iPhone 13 Pro'].viewport }); ...@@ -11,7 +11,7 @@ test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view +@dark-mode', async({ mount }) => { test('base view +@dark-mode', async({ mount }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<TxsListItem tx={ txMock.base } showBlockInfo/> <TxsListItem tx={ txMock.withWatchListNames } showBlockInfo/>
</TestApp>, </TestApp>,
); );
...@@ -21,7 +21,7 @@ test('base view +@dark-mode', async({ mount }) => { ...@@ -21,7 +21,7 @@ test('base view +@dark-mode', async({ mount }) => {
test('with base address', async({ mount }) => { test('with base address', async({ mount }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<TxsListItem tx={ txMock.base } showBlockInfo currentAddress={ txMock.base.from.hash }/> <TxsListItem tx={ txMock.withWatchListNames } showBlockInfo currentAddress={ txMock.base.from.hash }/>
</TestApp>, </TestApp>,
); );
......
...@@ -18,6 +18,7 @@ import BlockEntity from 'ui/shared/entities/block/BlockEntity'; ...@@ -18,6 +18,7 @@ import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
import TxStatus from 'ui/shared/TxStatus'; import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo'; import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
import TxType from 'ui/txs/TxType'; import TxType from 'ui/txs/TxType';
...@@ -44,9 +45,10 @@ const TxsListItem = ({ tx, isLoading, showBlockInfo, currentAddress, enableTimeI ...@@ -44,9 +45,10 @@ const TxsListItem = ({ tx, isLoading, showBlockInfo, currentAddress, enableTimeI
return ( return (
<ListItemMobile display="block" width="100%" isAnimated key={ tx.hash }> <ListItemMobile display="block" width="100%" isAnimated key={ tx.hash }>
<Flex justifyContent="space-between" mt={ 4 }> <Flex justifyContent="space-between" mt={ 4 }>
<HStack> <HStack flexWrap="wrap">
<TxType types={ tx.tx_types } isLoading={ isLoading }/> <TxType types={ tx.tx_types } isLoading={ isLoading }/>
<TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/> <TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/>
<TxWatchListTags tx={ tx } isLoading={ isLoading }/>
</HStack> </HStack>
<TxAdditionalInfo tx={ tx } isMobile isLoading={ isLoading }/> <TxAdditionalInfo tx={ tx } isMobile isLoading={ isLoading }/>
</Flex> </Flex>
......
...@@ -13,7 +13,7 @@ test.describe('base view', () => { ...@@ -13,7 +13,7 @@ test.describe('base view', () => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
{ /* eslint-disable-next-line react/jsx-no-bind */ } { /* eslint-disable-next-line react/jsx-no-bind */ }
<TxsTable txs={ [ txMock.base, txMock.base ] } sort={ () => () => {} } top={ 0 } showBlockInfo showSocketInfo={ false }/> <TxsTable txs={ [ txMock.base, txMock.withWatchListNames ] } sort={ () => () => {} } top={ 0 } showBlockInfo showSocketInfo={ false }/>
</TestApp>, </TestApp>,
); );
...@@ -27,7 +27,7 @@ test.describe('base view', () => { ...@@ -27,7 +27,7 @@ test.describe('base view', () => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
{ /* eslint-disable-next-line react/jsx-no-bind */ } { /* eslint-disable-next-line react/jsx-no-bind */ }
<TxsTable txs={ [ txMock.base, txMock.base ] } sort={ () => () => {} } top={ 0 } showBlockInfo showSocketInfo={ false }/> <TxsTable txs={ [ txMock.base, txMock.withWatchListNames ] } sort={ () => () => {} } top={ 0 } showBlockInfo showSocketInfo={ false }/>
</TestApp>, </TestApp>,
); );
......
...@@ -23,6 +23,7 @@ import AddressEntity from 'ui/shared/entities/address/AddressEntity'; ...@@ -23,6 +23,7 @@ import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
import TxStatus from 'ui/shared/TxStatus'; import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo'; import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
...@@ -95,6 +96,7 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement, ...@@ -95,6 +96,7 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
<VStack alignItems="start"> <VStack alignItems="start">
<TxType types={ tx.tx_types } isLoading={ isLoading }/> <TxType types={ tx.tx_types } isLoading={ isLoading }/>
<TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/> <TxStatus status={ tx.status } errorText={ tx.status === 'error' ? tx.result : undefined } isLoading={ isLoading }/>
<TxWatchListTags tx={ tx } isLoading={ isLoading }/>
</VStack> </VStack>
</Td> </Td>
<Td whiteSpace="nowrap"> <Td whiteSpace="nowrap">
......
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