Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
a8c723ca
Unverified
Commit
a8c723ca
authored
Nov 08, 2023
by
Igor Stuev
Committed by
GitHub
Nov 08, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
watchlist and private tags pagination (#1333)
Co-authored-by:
isstuev
<
natix.naf@gmail.com
>
parent
15cfad34
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
145 additions
and
69 deletions
+145
-69
resources.ts
lib/api/resources.ts
+14
-10
account.ts
types/api/account.ts
+24
-0
Watchlist.tsx
ui/pages/Watchlist.tsx
+32
-16
AddressTagTable.tsx
ui/privateTags/AddressTagTable/AddressTagTable.tsx
+6
-4
DeletePrivateTagModal.tsx
ui/privateTags/DeletePrivateTagModal.tsx
+9
-6
PrivateAddressTags.tsx
ui/privateTags/PrivateAddressTags.tsx
+24
-12
PrivateTransactionTags.tsx
ui/privateTags/PrivateTransactionTags.tsx
+23
-12
TransactionTagTable.tsx
ui/privateTags/TransactionTagTable/TransactionTagTable.tsx
+6
-4
useQueryWithPages.ts
ui/shared/pagination/useQueryWithPages.ts
+1
-1
WatchlistTable.tsx
ui/watchlist/WatchlistTable/WatchlistTable.tsx
+6
-4
No files found.
lib/api/resources.ts
View file @
a8c723ca
...
@@ -3,13 +3,13 @@ import type {
...
@@ -3,13 +3,13 @@ import type {
UserInfo
,
UserInfo
,
CustomAbis
,
CustomAbis
,
PublicTags
,
PublicTags
,
AddressTags
,
TransactionTags
,
ApiKeys
,
ApiKeys
,
WatchlistAddress
,
VerifiedAddressResponse
,
VerifiedAddressResponse
,
TokenInfoApplicationConfig
,
TokenInfoApplicationConfig
,
TokenInfoApplications
,
TokenInfoApplications
,
WatchlistResponse
,
TransactionTagsResponse
,
AddressTagsResponse
,
}
from
'
types/api/account
'
;
}
from
'
types/api/account
'
;
import
type
{
import
type
{
Address
,
Address
,
...
@@ -90,20 +90,23 @@ export const RESOURCES = {
...
@@ -90,20 +90,23 @@ export const RESOURCES = {
pathParams
:
[
'
id
'
as
const
],
pathParams
:
[
'
id
'
as
const
],
},
},
watchlist
:
{
watchlist
:
{
path
:
'
/api/account/v
1
/user/watchlist/:id?
'
,
path
:
'
/api/account/v
2
/user/watchlist/:id?
'
,
pathParams
:
[
'
id
'
as
const
],
pathParams
:
[
'
id
'
as
const
],
filterFields
:
[
],
},
},
public_tags
:
{
public_tags
:
{
path
:
'
/api/account/v1/user/public_tags/:id?
'
,
path
:
'
/api/account/v1/user/public_tags/:id?
'
,
pathParams
:
[
'
id
'
as
const
],
pathParams
:
[
'
id
'
as
const
],
},
},
private_tags_address
:
{
private_tags_address
:
{
path
:
'
/api/account/v
1
/user/tags/address/:id?
'
,
path
:
'
/api/account/v
2
/user/tags/address/:id?
'
,
pathParams
:
[
'
id
'
as
const
],
pathParams
:
[
'
id
'
as
const
],
filterFields
:
[
],
},
},
private_tags_tx
:
{
private_tags_tx
:
{
path
:
'
/api/account/v
1
/user/tags/transaction/:id?
'
,
path
:
'
/api/account/v
2
/user/tags/transaction/:id?
'
,
pathParams
:
[
'
id
'
as
const
],
pathParams
:
[
'
id
'
as
const
],
filterFields
:
[
],
},
},
api_keys
:
{
api_keys
:
{
path
:
'
/api/account/v1/user/api_keys/:id?
'
,
path
:
'
/api/account/v1/user/api_keys/:id?
'
,
...
@@ -579,7 +582,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
...
@@ -579,7 +582,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'
verified_contracts
'
|
'
verified_contracts
'
|
'
l2_output_roots
'
|
'
l2_withdrawals
'
|
'
l2_txn_batches
'
|
'
l2_deposits
'
|
'
l2_output_roots
'
|
'
l2_withdrawals
'
|
'
l2_txn_batches
'
|
'
l2_deposits
'
|
'
zkevm_l2_txn_batches
'
|
'
zkevm_l2_txn_batch_txs
'
|
'
zkevm_l2_txn_batches
'
|
'
zkevm_l2_txn_batch_txs
'
|
'
withdrawals
'
|
'
address_withdrawals
'
|
'
block_withdrawals
'
;
'
withdrawals
'
|
'
address_withdrawals
'
|
'
block_withdrawals
'
|
'
watchlist
'
|
'
private_tags_address
'
|
'
private_tags_tx
'
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
...
@@ -588,10 +592,10 @@ export type ResourcePayload<Q extends ResourceName> =
...
@@ -588,10 +592,10 @@ export type ResourcePayload<Q extends ResourceName> =
Q
extends
'
user_info
'
?
UserInfo
:
Q
extends
'
user_info
'
?
UserInfo
:
Q
extends
'
custom_abi
'
?
CustomAbis
:
Q
extends
'
custom_abi
'
?
CustomAbis
:
Q
extends
'
public_tags
'
?
PublicTags
:
Q
extends
'
public_tags
'
?
PublicTags
:
Q
extends
'
private_tags_address
'
?
AddressTags
:
Q
extends
'
private_tags_address
'
?
AddressTags
Response
:
Q
extends
'
private_tags_tx
'
?
TransactionTags
:
Q
extends
'
private_tags_tx
'
?
TransactionTags
Response
:
Q
extends
'
api_keys
'
?
ApiKeys
:
Q
extends
'
api_keys
'
?
ApiKeys
:
Q
extends
'
watchlist
'
?
Array
<
WatchlistAddress
>
:
Q
extends
'
watchlist
'
?
WatchlistResponse
:
Q
extends
'
verified_addresses
'
?
VerifiedAddressResponse
:
Q
extends
'
verified_addresses
'
?
VerifiedAddressResponse
:
Q
extends
'
token_info_applications_config
'
?
TokenInfoApplicationConfig
:
Q
extends
'
token_info_applications_config
'
?
TokenInfoApplicationConfig
:
Q
extends
'
token_info_applications
'
?
TokenInfoApplications
:
Q
extends
'
token_info_applications
'
?
TokenInfoApplications
:
...
...
types/api/account.ts
View file @
a8c723ca
...
@@ -8,6 +8,14 @@ export interface AddressTag {
...
@@ -8,6 +8,14 @@ export interface AddressTag {
export
type
AddressTags
=
Array
<
AddressTag
>
export
type
AddressTags
=
Array
<
AddressTag
>
export
type
AddressTagsResponse
=
{
items
:
AddressTags
;
next_page_params
:
{
id
:
number
;
items_count
:
number
;
}
|
null
;
}
export
interface
ApiKey
{
export
interface
ApiKey
{
api_key
:
string
;
api_key
:
string
;
name
:
string
;
name
:
string
;
...
@@ -48,6 +56,14 @@ export interface TransactionTag {
...
@@ -48,6 +56,14 @@ export interface TransactionTag {
export
type
TransactionTags
=
Array
<
TransactionTag
>
export
type
TransactionTags
=
Array
<
TransactionTag
>
export
type
TransactionTagsResponse
=
{
items
:
TransactionTags
;
next_page_params
:
{
id
:
number
;
items_count
:
number
;
}
|
null
;
}
export
type
Transactions
=
Array
<
Transaction
>
export
type
Transactions
=
Array
<
Transaction
>
export
interface
UserInfo
{
export
interface
UserInfo
{
...
@@ -78,6 +94,14 @@ export interface WatchlistAddressNew {
...
@@ -78,6 +94,14 @@ export interface WatchlistAddressNew {
export
type
WatchlistAddresses
=
Array
<
WatchlistAddress
>
export
type
WatchlistAddresses
=
Array
<
WatchlistAddress
>
export
type
WatchlistResponse
=
{
items
:
WatchlistAddresses
;
next_page_params
:
{
id
:
number
;
items_count
:
number
;
}
|
null
;
}
export
interface
PublicTag
{
export
interface
PublicTag
{
website
:
string
;
website
:
string
;
tags
:
string
;
// tag_1;tag_2;tag_3 etc.
tags
:
string
;
// tag_1;tag_2;tag_3 etc.
...
...
ui/pages/Watchlist.tsx
View file @
a8c723ca
...
@@ -2,24 +2,29 @@ import { Box, Button, Skeleton, useDisclosure } from '@chakra-ui/react';
...
@@ -2,24 +2,29 @@ import { Box, Button, Skeleton, useDisclosure } from '@chakra-ui/react';
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
type
{
WatchlistAddress
}
from
'
types/api/account
'
;
import
type
{
WatchlistAddress
,
WatchlistResponse
}
from
'
types/api/account
'
;
import
{
resourceKey
}
from
'
lib/api/resources
'
;
import
{
resourceKey
}
from
'
lib/api/resources
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useRedirectForInvalidAuthToken
from
'
lib/hooks/useRedirectForInvalidAuthToken
'
;
import
useRedirectForInvalidAuthToken
from
'
lib/hooks/useRedirectForInvalidAuthToken
'
;
import
{
WATCH_LIST_ITEM_WITH_TOKEN_INFO
}
from
'
stubs/account
'
;
import
{
WATCH_LIST_ITEM_WITH_TOKEN_INFO
}
from
'
stubs/account
'
;
import
AccountPageDescription
from
'
ui/shared/AccountPageDescription
'
;
import
AccountPageDescription
from
'
ui/shared/AccountPageDescription
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
AddressModal
from
'
ui/watchlist/AddressModal/AddressModal
'
;
import
AddressModal
from
'
ui/watchlist/AddressModal/AddressModal
'
;
import
DeleteAddressModal
from
'
ui/watchlist/DeleteAddressModal
'
;
import
DeleteAddressModal
from
'
ui/watchlist/DeleteAddressModal
'
;
import
WatchListItem
from
'
ui/watchlist/WatchlistTable/WatchListItem
'
;
import
WatchListItem
from
'
ui/watchlist/WatchlistTable/WatchListItem
'
;
import
WatchlistTable
from
'
ui/watchlist/WatchlistTable/WatchlistTable
'
;
import
WatchlistTable
from
'
ui/watchlist/WatchlistTable/WatchlistTable
'
;
const
WatchList
:
React
.
FC
=
()
=>
{
const
WatchList
:
React
.
FC
=
()
=>
{
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
watchlist
'
,
{
queryOptions
:
{
const
{
data
,
isPlaceholderData
,
isError
,
pagination
}
=
useQueryWithPages
({
placeholderData
:
Array
(
3
).
fill
(
WATCH_LIST_ITEM_WITH_TOKEN_INFO
),
resourceName
:
'
watchlist
'
,
options
:
{
placeholderData
:
{
items
:
Array
(
5
).
fill
(
WATCH_LIST_ITEM_WITH_TOKEN_INFO
),
next_page_params
:
null
},
},
},
});
});
const
queryClient
=
useQueryClient
();
const
queryClient
=
useQueryClient
();
...
@@ -58,9 +63,11 @@ const WatchList: React.FC = () => {
...
@@ -58,9 +63,11 @@ const WatchList: React.FC = () => {
},
[
deleteModalProps
]);
},
[
deleteModalProps
]);
const
onDeleteSuccess
=
useCallback
(
async
()
=>
{
const
onDeleteSuccess
=
useCallback
(
async
()
=>
{
queryClient
.
setQueryData
([
resourceKey
(
'
watchlist
'
)
],
(
prevData
:
Array
<
WatchlistAddress
>
|
undefined
)
=>
{
queryClient
.
setQueryData
(
getResourceKey
(
'
watchlist
'
),
(
prevData
:
WatchlistResponse
|
undefined
)
=>
{
return
prevData
?.
filter
((
item
)
=>
item
.
id
!==
deleteModalData
?.
id
);
const
newItems
=
prevData
?.
items
.
filter
((
item
:
WatchlistAddress
)
=>
item
.
id
!==
deleteModalData
?.
id
);
});
return
{
...
prevData
,
items
:
newItems
};
},
);
},
[
deleteModalData
?.
id
,
queryClient
]);
},
[
deleteModalData
?.
id
,
queryClient
]);
const
description
=
(
const
description
=
(
...
@@ -69,15 +76,17 @@ const WatchList: React.FC = () => {
...
@@ -69,15 +76,17 @@ const WatchList: React.FC = () => {
</
AccountPageDescription
>
</
AccountPageDescription
>
);
);
if
(
isError
)
{
return
<
DataFetchAlert
/>;
}
const
content
=
(()
=>
{
const
content
=
(()
=>
{
const
actionBar
=
pagination
.
isVisible
?
(
<
ActionBar
mt=
{
-
6
}
>
<
Pagination
ml=
"auto"
{
...
pagination
}
/>
</
ActionBar
>
)
:
null
;
const
list
=
(
const
list
=
(
<>
<>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
{
data
?.
map
((
item
,
index
)
=>
(
{
data
?.
items
.
map
((
item
,
index
)
=>
(
<
WatchListItem
<
WatchListItem
key=
{
item
.
address_hash
+
(
isPlaceholderData
?
index
:
''
)
}
key=
{
item
.
address_hash
+
(
isPlaceholderData
?
index
:
''
)
}
item=
{
item
}
item=
{
item
}
...
@@ -89,10 +98,11 @@ const WatchList: React.FC = () => {
...
@@ -89,10 +98,11 @@ const WatchList: React.FC = () => {
</
Box
>
</
Box
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
WatchlistTable
<
WatchlistTable
data=
{
data
}
data=
{
data
?.
items
}
isLoading=
{
isPlaceholderData
}
isLoading=
{
isPlaceholderData
}
onDeleteClick=
{
onDeleteClick
}
onDeleteClick=
{
onDeleteClick
}
onEditClick=
{
onEditClick
}
onEditClick=
{
onEditClick
}
top=
{
pagination
.
isVisible
?
80
:
0
}
/>
/>
</
Box
>
</
Box
>
</>
</>
...
@@ -101,7 +111,13 @@ const WatchList: React.FC = () => {
...
@@ -101,7 +111,13 @@ const WatchList: React.FC = () => {
return
(
return
(
<>
<>
{
description
}
{
description
}
{
Boolean
(
data
?.
length
)
&&
list
}
<
DataListDisplay
isError=
{
isError
}
items=
{
data
?.
items
}
emptyText=
""
content=
{
list
}
actionBar=
{
actionBar
}
/>
<
Skeleton
mt=
{
8
}
isLoaded=
{
!
isPlaceholderData
}
display=
"inline-block"
>
<
Skeleton
mt=
{
8
}
isLoaded=
{
!
isPlaceholderData
}
display=
"inline-block"
>
<
Button
<
Button
size=
"lg"
size=
"lg"
...
...
ui/privateTags/AddressTagTable/AddressTagTable.tsx
View file @
a8c723ca
import
{
import
{
Table
,
Table
,
Thead
,
Tbody
,
Tbody
,
Tr
,
Tr
,
Th
,
Th
,
...
@@ -9,6 +8,8 @@ import React from 'react';
...
@@ -9,6 +8,8 @@ import React from 'react';
import
type
{
AddressTags
,
AddressTag
}
from
'
types/api/account
'
;
import
type
{
AddressTags
,
AddressTag
}
from
'
types/api/account
'
;
import
TheadSticky
from
'
ui/shared/TheadSticky
'
;
import
AddressTagTableItem
from
'
./AddressTagTableItem
'
;
import
AddressTagTableItem
from
'
./AddressTagTableItem
'
;
interface
Props
{
interface
Props
{
...
@@ -16,18 +17,19 @@ interface Props {
...
@@ -16,18 +17,19 @@ interface Props {
onEditClick
:
(
data
:
AddressTag
)
=>
void
;
onEditClick
:
(
data
:
AddressTag
)
=>
void
;
onDeleteClick
:
(
data
:
AddressTag
)
=>
void
;
onDeleteClick
:
(
data
:
AddressTag
)
=>
void
;
isLoading
:
boolean
;
isLoading
:
boolean
;
top
:
number
;
}
}
const
AddressTagTable
=
({
data
,
onDeleteClick
,
onEditClick
,
isLoading
}:
Props
)
=>
{
const
AddressTagTable
=
({
data
,
onDeleteClick
,
onEditClick
,
isLoading
,
top
}:
Props
)
=>
{
return
(
return
(
<
Table
variant=
"simple"
minWidth=
"600px"
>
<
Table
variant=
"simple"
minWidth=
"600px"
>
<
Thead
>
<
Thead
Sticky
top=
{
top
}
>
<
Tr
>
<
Tr
>
<
Th
width=
"60%"
>
Address
</
Th
>
<
Th
width=
"60%"
>
Address
</
Th
>
<
Th
width=
"40%"
>
Private tag
</
Th
>
<
Th
width=
"40%"
>
Private tag
</
Th
>
<
Th
width=
"116px"
></
Th
>
<
Th
width=
"116px"
></
Th
>
</
Tr
>
</
Tr
>
</
Thead
>
</
Thead
Sticky
>
<
Tbody
>
<
Tbody
>
{
data
?.
map
((
item
:
AddressTag
,
index
:
number
)
=>
(
{
data
?.
map
((
item
:
AddressTag
,
index
:
number
)
=>
(
<
AddressTagTableItem
<
AddressTagTableItem
...
...
ui/privateTags/DeletePrivateTagModal.tsx
View file @
a8c723ca
...
@@ -2,10 +2,10 @@ import { Text } from '@chakra-ui/react';
...
@@ -2,10 +2,10 @@ import { Text } from '@chakra-ui/react';
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
}
from
'
react
'
;
import
React
,
{
useCallback
}
from
'
react
'
;
import
type
{
AddressTag
,
TransactionTag
,
AddressTags
,
TransactionTags
}
from
'
types/api/account
'
;
import
type
{
AddressTag
,
TransactionTag
,
AddressTags
Response
,
TransactionTagsResponse
}
from
'
types/api/account
'
;
import
{
resourceKey
}
from
'
lib/api/resources
'
;
import
useApiFetch
from
'
lib/api/useApiFetch
'
;
import
useApiFetch
from
'
lib/api/useApiFetch
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
DeleteModal
from
'
ui/shared/DeleteModal
'
;
import
DeleteModal
from
'
ui/shared/DeleteModal
'
;
type
Props
=
{
type
Props
=
{
...
@@ -32,12 +32,15 @@ const DeletePrivateTagModal: React.FC<Props> = ({ isOpen, onClose, data, type })
...
@@ -32,12 +32,15 @@ const DeletePrivateTagModal: React.FC<Props> = ({ isOpen, onClose, data, type })
const
onSuccess
=
useCallback
(
async
()
=>
{
const
onSuccess
=
useCallback
(
async
()
=>
{
if
(
type
===
'
address
'
)
{
if
(
type
===
'
address
'
)
{
queryClient
.
setQueryData
([
resourceKey
(
'
private_tags_address
'
)
],
(
prevData
:
AddressTags
|
undefined
)
=>
{
queryClient
.
setQueryData
(
getResourceKey
(
'
private_tags_address
'
),
(
prevData
:
AddressTagsResponse
|
undefined
)
=>
{
return
prevData
?.
filter
((
item
:
AddressTag
)
=>
item
.
id
!==
id
);
const
newItems
=
prevData
?.
items
.
filter
((
item
:
AddressTag
)
=>
item
.
id
!==
id
);
return
{
...
prevData
,
items
:
newItems
};
});
});
}
else
{
}
else
{
queryClient
.
setQueryData
([
resourceKey
(
'
private_tags_tx
'
)
],
(
prevData
:
TransactionTags
|
undefined
)
=>
{
queryClient
.
setQueryData
(
getResourceKey
(
'
private_tags_tx
'
),
(
prevData
:
TransactionTagsResponse
|
undefined
)
=>
{
return
prevData
?.
filter
((
item
:
TransactionTag
)
=>
item
.
id
!==
id
);
const
newItems
=
prevData
?.
items
.
filter
((
item
:
TransactionTag
)
=>
item
.
id
!==
id
);
return
{
...
prevData
,
items
:
newItems
};
});
});
}
}
},
[
type
,
id
,
queryClient
]);
},
[
type
,
id
,
queryClient
]);
...
...
ui/privateTags/PrivateAddressTags.tsx
View file @
a8c723ca
...
@@ -3,11 +3,13 @@ import React, { useCallback, useState } from 'react';
...
@@ -3,11 +3,13 @@ import React, { useCallback, useState } from 'react';
import
type
{
AddressTag
}
from
'
types/api/account
'
;
import
type
{
AddressTag
}
from
'
types/api/account
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
PAGE_TYPE_DICT
}
from
'
lib/mixpanel/getPageType
'
;
import
{
PAGE_TYPE_DICT
}
from
'
lib/mixpanel/getPageType
'
;
import
{
PRIVATE_TAG_ADDRESS
}
from
'
stubs/account
'
;
import
{
PRIVATE_TAG_ADDRESS
}
from
'
stubs/account
'
;
import
AccountPageDescription
from
'
ui/shared/AccountPageDescription
'
;
import
AccountPageDescription
from
'
ui/shared/AccountPageDescription
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
AddressModal
from
'
./AddressModal/AddressModal
'
;
import
AddressModal
from
'
./AddressModal/AddressModal
'
;
import
AddressTagListItem
from
'
./AddressTagTable/AddressTagListItem
'
;
import
AddressTagListItem
from
'
./AddressTagTable/AddressTagListItem
'
;
...
@@ -15,10 +17,11 @@ import AddressTagTable from './AddressTagTable/AddressTagTable';
...
@@ -15,10 +17,11 @@ import AddressTagTable from './AddressTagTable/AddressTagTable';
import
DeletePrivateTagModal
from
'
./DeletePrivateTagModal
'
;
import
DeletePrivateTagModal
from
'
./DeletePrivateTagModal
'
;
const
PrivateAddressTags
=
()
=>
{
const
PrivateAddressTags
=
()
=>
{
const
{
data
:
addressTagsData
,
isError
,
isPlaceholderData
,
refetch
}
=
useApiQuery
(
'
private_tags_address
'
,
{
const
{
data
:
addressTagsData
,
isError
,
isPlaceholderData
,
refetch
,
pagination
}
=
useQueryWithPages
({
queryOptions
:
{
resourceName
:
'
private_tags_address
'
,
options
:
{
refetchOnMount
:
false
,
refetchOnMount
:
false
,
placeholderData
:
Array
(
3
).
fill
(
PRIVATE_TAG_ADDRESS
)
,
placeholderData
:
{
items
:
Array
(
5
).
fill
(
PRIVATE_TAG_ADDRESS
),
next_page_params
:
null
}
,
},
},
});
});
...
@@ -52,14 +55,10 @@ const PrivateAddressTags = () => {
...
@@ -52,14 +55,10 @@ const PrivateAddressTags = () => {
deleteModalProps
.
onClose
();
deleteModalProps
.
onClose
();
},
[
deleteModalProps
]);
},
[
deleteModalProps
]);
if
(
isError
)
{
return
<
DataFetchAlert
/>;
}
const
list
=
(
const
list
=
(
<>
<>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
{
addressTagsData
?.
map
((
item
:
AddressTag
,
index
:
number
)
=>
(
{
addressTagsData
?.
items
.
map
((
item
:
AddressTag
,
index
:
number
)
=>
(
<
AddressTagListItem
<
AddressTagListItem
item=
{
item
}
item=
{
item
}
key=
{
item
.
id
+
(
isPlaceholderData
?
index
:
''
)
}
key=
{
item
.
id
+
(
isPlaceholderData
?
index
:
''
)
}
...
@@ -72,21 +71,34 @@ const PrivateAddressTags = () => {
...
@@ -72,21 +71,34 @@ const PrivateAddressTags = () => {
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
AddressTagTable
<
AddressTagTable
isLoading=
{
isPlaceholderData
}
isLoading=
{
isPlaceholderData
}
data=
{
addressTagsData
}
data=
{
addressTagsData
?.
items
}
onDeleteClick=
{
onDeleteClick
}
onDeleteClick=
{
onDeleteClick
}
onEditClick=
{
onEditClick
}
onEditClick=
{
onEditClick
}
top=
{
pagination
.
isVisible
?
80
:
0
}
/>
/>
</
Box
>
</
Box
>
</>
</>
);
);
const
actionBar
=
pagination
.
isVisible
?
(
<
ActionBar
mt=
{
-
6
}
>
<
Pagination
ml=
"auto"
{
...
pagination
}
/>
</
ActionBar
>
)
:
null
;
return
(
return
(
<>
<>
<
AccountPageDescription
>
<
AccountPageDescription
>
Use private address tags to track any addresses of interest.
Use private address tags to track any addresses of interest.
Private tags are saved in your account and are only visible when you are logged in.
Private tags are saved in your account and are only visible when you are logged in.
</
AccountPageDescription
>
</
AccountPageDescription
>
{
Boolean
(
addressTagsData
?.
length
)
&&
list
}
<
DataListDisplay
isError=
{
isError
}
items=
{
addressTagsData
?.
items
}
emptyText=
""
content=
{
list
}
actionBar=
{
actionBar
}
/>
<
Skeleton
mt=
{
8
}
isLoaded=
{
!
isPlaceholderData
}
display=
"inline-block"
>
<
Skeleton
mt=
{
8
}
isLoaded=
{
!
isPlaceholderData
}
display=
"inline-block"
>
<
Button
<
Button
size=
"lg"
size=
"lg"
...
...
ui/privateTags/PrivateTransactionTags.tsx
View file @
a8c723ca
...
@@ -3,10 +3,12 @@ import React, { useCallback, useState } from 'react';
...
@@ -3,10 +3,12 @@ import React, { useCallback, useState } from 'react';
import
type
{
TransactionTag
}
from
'
types/api/account
'
;
import
type
{
TransactionTag
}
from
'
types/api/account
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
PRIVATE_TAG_TX
}
from
'
stubs/account
'
;
import
{
PRIVATE_TAG_TX
}
from
'
stubs/account
'
;
import
AccountPageDescription
from
'
ui/shared/AccountPageDescription
'
;
import
AccountPageDescription
from
'
ui/shared/AccountPageDescription
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
DeletePrivateTagModal
from
'
./DeletePrivateTagModal
'
;
import
DeletePrivateTagModal
from
'
./DeletePrivateTagModal
'
;
import
TransactionModal
from
'
./TransactionModal/TransactionModal
'
;
import
TransactionModal
from
'
./TransactionModal/TransactionModal
'
;
...
@@ -14,10 +16,11 @@ import TransactionTagListItem from './TransactionTagTable/TransactionTagListItem
...
@@ -14,10 +16,11 @@ import TransactionTagListItem from './TransactionTagTable/TransactionTagListItem
import
TransactionTagTable
from
'
./TransactionTagTable/TransactionTagTable
'
;
import
TransactionTagTable
from
'
./TransactionTagTable/TransactionTagTable
'
;
const
PrivateTransactionTags
=
()
=>
{
const
PrivateTransactionTags
=
()
=>
{
const
{
data
:
transactionTagsData
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
private_tags_tx
'
,
{
const
{
data
:
transactionTagsData
,
isPlaceholderData
,
isError
,
pagination
}
=
useQueryWithPages
({
queryOptions
:
{
resourceName
:
'
private_tags_tx
'
,
options
:
{
refetchOnMount
:
false
,
refetchOnMount
:
false
,
placeholderData
:
Array
(
3
).
fill
(
PRIVATE_TAG_TX
)
,
placeholderData
:
{
items
:
Array
(
3
).
fill
(
PRIVATE_TAG_TX
),
next_page_params
:
null
}
,
},
},
});
});
...
@@ -54,14 +57,10 @@ const PrivateTransactionTags = () => {
...
@@ -54,14 +57,10 @@ const PrivateTransactionTags = () => {
</
AccountPageDescription
>
</
AccountPageDescription
>
);
);
if
(
isError
)
{
return
<
DataFetchAlert
/>;
}
const
list
=
(
const
list
=
(
<>
<>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
{
transactionTagsData
?.
map
((
item
,
index
)
=>
(
{
transactionTagsData
?.
items
.
map
((
item
,
index
)
=>
(
<
TransactionTagListItem
<
TransactionTagListItem
key=
{
item
.
id
+
(
isPlaceholderData
?
index
:
''
)
}
key=
{
item
.
id
+
(
isPlaceholderData
?
index
:
''
)
}
item=
{
item
}
item=
{
item
}
...
@@ -73,19 +72,31 @@ const PrivateTransactionTags = () => {
...
@@ -73,19 +72,31 @@ const PrivateTransactionTags = () => {
</
Box
>
</
Box
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
TransactionTagTable
<
TransactionTagTable
data=
{
transactionTagsData
}
data=
{
transactionTagsData
?.
items
}
isLoading=
{
isPlaceholderData
}
isLoading=
{
isPlaceholderData
}
onDeleteClick=
{
onDeleteClick
}
onDeleteClick=
{
onDeleteClick
}
onEditClick=
{
onEditClick
}
onEditClick=
{
onEditClick
}
top=
{
pagination
.
isVisible
?
80
:
0
}
/>
/>
</
Box
>
</
Box
>
</>
</>
);
);
const
actionBar
=
pagination
.
isVisible
?
(
<
ActionBar
mt=
{
-
6
}
>
<
Pagination
ml=
"auto"
{
...
pagination
}
/>
</
ActionBar
>
)
:
null
;
return
(
return
(
<>
<>
{
description
}
{
description
}
{
Boolean
(
transactionTagsData
?.
length
)
&&
list
}
<
DataListDisplay
isError=
{
isError
}
items=
{
transactionTagsData
?.
items
}
emptyText=
""
content=
{
list
}
actionBar=
{
actionBar
}
/>
<
Skeleton
mt=
{
8
}
isLoaded=
{
!
isPlaceholderData
}
display=
"inline-block"
>
<
Skeleton
mt=
{
8
}
isLoaded=
{
!
isPlaceholderData
}
display=
"inline-block"
>
<
Button
<
Button
size=
"lg"
size=
"lg"
...
...
ui/privateTags/TransactionTagTable/TransactionTagTable.tsx
View file @
a8c723ca
import
{
import
{
Table
,
Table
,
Thead
,
Tbody
,
Tbody
,
Tr
,
Tr
,
Th
,
Th
,
...
@@ -9,6 +8,8 @@ import React from 'react';
...
@@ -9,6 +8,8 @@ import React from 'react';
import
type
{
TransactionTags
,
TransactionTag
}
from
'
types/api/account
'
;
import
type
{
TransactionTags
,
TransactionTag
}
from
'
types/api/account
'
;
import
TheadSticky
from
'
ui/shared/TheadSticky
'
;
import
TransactionTagTableItem
from
'
./TransactionTagTableItem
'
;
import
TransactionTagTableItem
from
'
./TransactionTagTableItem
'
;
interface
Props
{
interface
Props
{
...
@@ -16,18 +17,19 @@ interface Props {
...
@@ -16,18 +17,19 @@ interface Props {
isLoading
:
boolean
;
isLoading
:
boolean
;
onEditClick
:
(
data
:
TransactionTag
)
=>
void
;
onEditClick
:
(
data
:
TransactionTag
)
=>
void
;
onDeleteClick
:
(
data
:
TransactionTag
)
=>
void
;
onDeleteClick
:
(
data
:
TransactionTag
)
=>
void
;
top
:
number
;
}
}
const
AddressTagTable
=
({
data
,
isLoading
,
onDeleteClick
,
onEditClick
}:
Props
)
=>
{
const
AddressTagTable
=
({
data
,
isLoading
,
onDeleteClick
,
onEditClick
,
top
}:
Props
)
=>
{
return
(
return
(
<
Table
variant=
"simple"
minWidth=
"600px"
>
<
Table
variant=
"simple"
minWidth=
"600px"
>
<
Thead
>
<
Thead
Sticky
top=
{
top
}
>
<
Tr
>
<
Tr
>
<
Th
width=
"75%"
>
Transaction
</
Th
>
<
Th
width=
"75%"
>
Transaction
</
Th
>
<
Th
width=
"25%"
>
Private tag
</
Th
>
<
Th
width=
"25%"
>
Private tag
</
Th
>
<
Th
width=
"108px"
></
Th
>
<
Th
width=
"108px"
></
Th
>
</
Tr
>
</
Tr
>
</
Thead
>
</
Thead
Sticky
>
<
Tbody
>
<
Tbody
>
{
data
?.
map
((
item
,
index
)
=>
(
{
data
?.
map
((
item
,
index
)
=>
(
<
TransactionTagTableItem
<
TransactionTagTableItem
...
...
ui/shared/pagination/useQueryWithPages.ts
View file @
a8c723ca
...
@@ -70,7 +70,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
...
@@ -70,7 +70,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
const
queryResult
=
useApiQuery
(
resourceName
,
{
const
queryResult
=
useApiQuery
(
resourceName
,
{
pathParams
,
pathParams
,
queryParams
,
queryParams
:
Object
.
keys
(
queryParams
).
length
?
queryParams
:
undefined
,
queryOptions
:
{
queryOptions
:
{
staleTime
:
page
===
1
?
0
:
Infinity
,
staleTime
:
page
===
1
?
0
:
Infinity
,
...
options
,
...
options
,
...
...
ui/watchlist/WatchlistTable/WatchlistTable.tsx
View file @
a8c723ca
import
{
import
{
Table
,
Table
,
Thead
,
Tbody
,
Tbody
,
Tr
,
Tr
,
Th
,
Th
,
...
@@ -9,6 +8,8 @@ import React from 'react';
...
@@ -9,6 +8,8 @@ import React from 'react';
import
type
{
WatchlistAddress
}
from
'
types/api/account
'
;
import
type
{
WatchlistAddress
}
from
'
types/api/account
'
;
import
TheadSticky
from
'
ui/shared/TheadSticky
'
;
import
WatchlistTableItem
from
'
./WatchListTableItem
'
;
import
WatchlistTableItem
from
'
./WatchListTableItem
'
;
interface
Props
{
interface
Props
{
...
@@ -16,19 +17,20 @@ interface Props {
...
@@ -16,19 +17,20 @@ interface Props {
isLoading
?:
boolean
;
isLoading
?:
boolean
;
onEditClick
:
(
data
:
WatchlistAddress
)
=>
void
;
onEditClick
:
(
data
:
WatchlistAddress
)
=>
void
;
onDeleteClick
:
(
data
:
WatchlistAddress
)
=>
void
;
onDeleteClick
:
(
data
:
WatchlistAddress
)
=>
void
;
top
:
number
;
}
}
const
WatchlistTable
=
({
data
,
isLoading
,
onDeleteClick
,
onEditClick
}:
Props
)
=>
{
const
WatchlistTable
=
({
data
,
isLoading
,
onDeleteClick
,
onEditClick
,
top
}:
Props
)
=>
{
return
(
return
(
<
Table
variant=
"simple"
minWidth=
"600px"
>
<
Table
variant=
"simple"
minWidth=
"600px"
>
<
Thead
>
<
Thead
Sticky
top=
{
top
}
>
<
Tr
>
<
Tr
>
<
Th
width=
"70%"
>
Address
</
Th
>
<
Th
width=
"70%"
>
Address
</
Th
>
<
Th
width=
"30%"
>
Private tag
</
Th
>
<
Th
width=
"30%"
>
Private tag
</
Th
>
<
Th
width=
"160px"
>
Email notification
</
Th
>
<
Th
width=
"160px"
>
Email notification
</
Th
>
<
Th
width=
"108px"
></
Th
>
<
Th
width=
"108px"
></
Th
>
</
Tr
>
</
Tr
>
</
Thead
>
</
Thead
Sticky
>
<
Tbody
>
<
Tbody
>
{
data
?.
map
((
item
,
index
)
=>
(
{
data
?.
map
((
item
,
index
)
=>
(
<
WatchlistTableItem
<
WatchlistTableItem
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment