mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
csv export link for address data
This commit is contained in:
+2
-1
@@ -20,5 +20,6 @@
|
||||
"search_results": "/search-results",
|
||||
"auth": "/auth/auth0",
|
||||
"stats": "/stats",
|
||||
"visualize_sol2uml": "/visualize/sol2uml"
|
||||
"visualize_sol2uml": "/visualize/sol2uml",
|
||||
"csv_export": "/csv-export"
|
||||
}
|
||||
|
||||
@@ -99,6 +99,10 @@ export const ROUTES = {
|
||||
pattern: PATHS.visualize_sol2uml,
|
||||
},
|
||||
|
||||
csv_export: {
|
||||
pattern: PATHS.csv_export,
|
||||
},
|
||||
|
||||
// AUTH
|
||||
auth: {
|
||||
pattern: PATHS.auth,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { chakra, Icon, Link, Tooltip } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import svgFileIcon from 'icons/svg_file.svg';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import link from 'lib/link/link';
|
||||
|
||||
interface Props {
|
||||
address: string;
|
||||
type: 'transactions' | 'internal-transactions' | 'token-transfers';
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AddressCsvExportLink = ({ className, address, type }: Props) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<Tooltip isDisabled={ !isMobile } label="Download CSV">
|
||||
<Link
|
||||
className={ className }
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
href={ link('csv_export', undefined, { type, address }) }
|
||||
>
|
||||
<Icon as={ svgFileIcon } boxSize={ 6 }/>
|
||||
{ !isMobile && <chakra.span ml={ 1 }>Download CSV</chakra.span> }
|
||||
</Link>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(chakra(AddressCsvExportLink));
|
||||
@@ -17,6 +17,7 @@ import ActionBar from 'ui/shared/ActionBar';
|
||||
import DataFetchAlert from 'ui/shared/DataFetchAlert';
|
||||
import Pagination from 'ui/shared/Pagination';
|
||||
|
||||
import AddressCsvExportLink from './AddressCsvExportLink';
|
||||
import AddressTxsFilter from './AddressTxsFilter';
|
||||
import AddressIntTxsList from './internals/AddressIntTxsList';
|
||||
|
||||
@@ -80,13 +81,14 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionBar mt={ -6 }>
|
||||
<ActionBar mt={ -6 } justifyContent="left">
|
||||
<AddressTxsFilter
|
||||
defaultFilter={ filterValue }
|
||||
onFilterChange={ handleFilterChange }
|
||||
isActive={ Boolean(filterValue) }
|
||||
/>
|
||||
{ isPaginationVisible && <Pagination ml="auto" { ...pagination }/> }
|
||||
<AddressCsvExportLink address={ queryIdStr } type="internal-transactions" ml={{ base: 2, lg: 'auto' }}/>
|
||||
{ isPaginationVisible && <Pagination ml={{ base: 'auto', lg: 8 }} { ...pagination }/> }
|
||||
</ActionBar>
|
||||
{ content }
|
||||
</>
|
||||
|
||||
@@ -28,6 +28,8 @@ import TokenTransferFilter from 'ui/shared/TokenTransfer/TokenTransferFilter';
|
||||
import TokenTransferList from 'ui/shared/TokenTransfer/TokenTransferList';
|
||||
import TokenTransferTable from 'ui/shared/TokenTransfer/TokenTransferTable';
|
||||
|
||||
import AddressCsvExportLink from './AddressCsvExportLink';
|
||||
|
||||
type Filters = {
|
||||
type: Array<TokenType>;
|
||||
filter: AddressFromToFilter | undefined;
|
||||
@@ -217,7 +219,8 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
|
||||
onAddressFilterChange={ handleAddressFilterChange }
|
||||
defaultAddressFilter={ filters.filter }
|
||||
/>
|
||||
{ isPaginationVisible && <Pagination ml="auto" { ...pagination }/> }
|
||||
{ currentAddress && <AddressCsvExportLink address={ currentAddress } type="token-transfers" ml={{ base: 2, lg: 'auto' }}/> }
|
||||
{ isPaginationVisible && <Pagination ml={{ base: 'auto', lg: 8 }} { ...pagination }/> }
|
||||
</ActionBar>
|
||||
) }
|
||||
{ content }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import castArray from 'lodash/castArray';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
@@ -17,6 +16,7 @@ import ActionBar from 'ui/shared/ActionBar';
|
||||
import Pagination from 'ui/shared/Pagination';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
|
||||
import AddressCsvExportLink from './AddressCsvExportLink';
|
||||
import AddressTxsFilter from './AddressTxsFilter';
|
||||
|
||||
const OVERLOAD_COUNT = 75;
|
||||
@@ -31,12 +31,13 @@ const AddressTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}
|
||||
const [ newItemsCount, setNewItemsCount ] = React.useState(0);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const currentAddress = router.query.id?.toString();
|
||||
|
||||
const [ filterValue, setFilterValue ] = React.useState<AddressFromToFilter>(getFilterValue(router.query.filter));
|
||||
|
||||
const addressTxsQuery = useQueryWithPages({
|
||||
resourceName: 'address_txs',
|
||||
pathParams: { id: castArray(router.query.id)[0] },
|
||||
pathParams: { id: currentAddress },
|
||||
filters: { filter: filterValue },
|
||||
scrollRef,
|
||||
});
|
||||
@@ -51,8 +52,6 @@ const AddressTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}
|
||||
const handleNewSocketMessage: SocketMessage.AddressTxs['handler'] = (payload) => {
|
||||
setSocketAlert('');
|
||||
|
||||
const currentAddress = router.query.id?.toString();
|
||||
|
||||
if (addressTxsQuery.data?.items && addressTxsQuery.data.items.length >= OVERLOAD_COUNT) {
|
||||
if (
|
||||
!filterValue ||
|
||||
@@ -109,7 +108,7 @@ const AddressTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}
|
||||
}, []);
|
||||
|
||||
const channel = useSocketChannel({
|
||||
topic: `addresses:${ (router.query.id as string).toLowerCase() }`,
|
||||
topic: `addresses:${ currentAddress?.toLowerCase() }`,
|
||||
onSocketClose: handleSocketClose,
|
||||
onSocketError: handleSocketError,
|
||||
isDisabled: addressTxsQuery.pagination.page !== 1,
|
||||
@@ -140,13 +139,14 @@ const AddressTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}
|
||||
{ !isMobile && (
|
||||
<ActionBar mt={ -6 }>
|
||||
{ filter }
|
||||
{ addressTxsQuery.isPaginationVisible && <Pagination { ...addressTxsQuery.pagination }/> }
|
||||
{ currentAddress && <AddressCsvExportLink address={ currentAddress } type="transactions" ml="auto"/> }
|
||||
{ addressTxsQuery.isPaginationVisible && <Pagination { ...addressTxsQuery.pagination } ml={ 8 }/> }
|
||||
</ActionBar>
|
||||
) }
|
||||
<TxsContent
|
||||
filter={ filter }
|
||||
query={ addressTxsQuery }
|
||||
currentAddress={ typeof router.query.id === 'string' ? router.query.id : undefined }
|
||||
currentAddress={ typeof currentAddress === 'string' ? currentAddress : undefined }
|
||||
enableTimeIncrement
|
||||
showSocketInfo={ addressTxsQuery.pagination.page === 1 }
|
||||
socketInfoAlert={ socketAlert }
|
||||
|
||||
@@ -5,6 +5,7 @@ import React from 'react';
|
||||
import type { TxsResponse } from 'types/api/transaction';
|
||||
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import AddressCsvExportLink from 'ui/address/AddressCsvExportLink';
|
||||
import DataFetchAlert from 'ui/shared/DataFetchAlert';
|
||||
import type { Props as PaginationProps } from 'ui/shared/Pagination';
|
||||
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
|
||||
@@ -123,6 +124,7 @@ const TxsContent = ({
|
||||
paginationProps={ query.pagination }
|
||||
showPagination={ query.isPaginationVisible }
|
||||
filterComponent={ filter }
|
||||
linkSlot={ currentAddress ? <AddressCsvExportLink address={ currentAddress } type="transactions" ml={ 2 }/> : null }
|
||||
/>
|
||||
) }
|
||||
{ content }
|
||||
|
||||
@@ -18,9 +18,10 @@ type Props = {
|
||||
className?: string;
|
||||
showPagination?: boolean;
|
||||
filterComponent?: React.ReactNode;
|
||||
linkSlot?: React.ReactNode;
|
||||
}
|
||||
|
||||
const TxsHeaderMobile = ({ filterComponent, sorting, setSorting, paginationProps, className, showPagination = true }: Props) => {
|
||||
const TxsHeaderMobile = ({ filterComponent, sorting, setSorting, paginationProps, className, showPagination = true, linkSlot }: Props) => {
|
||||
return (
|
||||
<ActionBar className={ className }>
|
||||
<HStack>
|
||||
@@ -38,6 +39,7 @@ const TxsHeaderMobile = ({ filterComponent, sorting, setSorting, paginationProps
|
||||
size="xs"
|
||||
placeholder="Search by addresses, hash, method..."
|
||||
/> */ }
|
||||
{ linkSlot }
|
||||
</HStack>
|
||||
{ showPagination && <Pagination { ...paginationProps }/> }
|
||||
</ActionBar>
|
||||
|
||||
Reference in New Issue
Block a user