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
40981a37
Commit
40981a37
authored
Apr 12, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
handle add private tag
parent
d8ec4dad
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
119 additions
and
39 deletions
+119
-39
useRedirectIfNotAuth.tsx
lib/hooks/useRedirectIfNotAuth.tsx
+24
-0
AddressFavoriteButton.tsx
ui/address/details/AddressFavoriteButton.tsx
+4
-12
AddressForm.tsx
ui/privateTags/AddressModal/AddressForm.tsx
+8
-11
AddressModal.tsx
ui/privateTags/AddressModal/AddressModal.tsx
+7
-6
PrivateAddressTags.tsx
ui/privateTags/PrivateAddressTags.tsx
+6
-2
Menu.tsx
ui/shared/AddressActions/Menu.tsx
+11
-5
PrivateTagMenuItem.tsx
ui/shared/AddressActions/PrivateTagMenuItem.tsx
+57
-0
TokenContractInfo.tsx
ui/token/TokenContractInfo.tsx
+2
-3
No files found.
lib/hooks/useRedirectIfNotAuth.tsx
0 → 100644
View file @
40981a37
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
type
{
UserInfo
}
from
'
types/api/account
'
;
import
{
resourceKey
}
from
'
lib/api/resources
'
;
import
useLoginUrl
from
'
lib/hooks/useLoginUrl
'
;
export
default
function
useRedirectIfNotAuth
()
{
const
queryClient
=
useQueryClient
();
const
profileData
=
queryClient
.
getQueryData
<
UserInfo
>
([
resourceKey
(
'
user_info
'
)
]);
const
isAuth
=
Boolean
(
profileData
);
const
loginUrl
=
useLoginUrl
();
return
React
.
useCallback
(()
=>
{
if
(
!
isAuth
)
{
window
.
location
.
assign
(
loginUrl
);
return
true
;
}
return
false
;
},
[
isAuth
,
loginUrl
]);
}
ui/address/details/AddressFavoriteButton.tsx
View file @
40981a37
...
@@ -3,14 +3,11 @@ import { useQueryClient } from '@tanstack/react-query';
...
@@ -3,14 +3,11 @@ import { useQueryClient } from '@tanstack/react-query';
import
{
useRouter
}
from
'
next/router
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
UserInfo
}
from
'
types/api/account
'
;
import
starFilledIcon
from
'
icons/star_filled.svg
'
;
import
starFilledIcon
from
'
icons/star_filled.svg
'
;
import
starOutlineIcon
from
'
icons/star_outline.svg
'
;
import
starOutlineIcon
from
'
icons/star_outline.svg
'
;
import
{
resourceKey
}
from
'
lib/api/resources
'
;
import
useApiQuery
,
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useApiQuery
,
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useLoginUrl
from
'
lib/hooks/useLoginUrl
'
;
import
usePreventFocusAfterModalClosing
from
'
lib/hooks/usePreventFocusAfterModalClosing
'
;
import
usePreventFocusAfterModalClosing
from
'
lib/hooks/usePreventFocusAfterModalClosing
'
;
import
useRedirectIfNotAuth
from
'
lib/hooks/useRedirectIfNotAuth
'
;
import
WatchlistAddModal
from
'
ui/watchlist/AddressModal/AddressModal
'
;
import
WatchlistAddModal
from
'
ui/watchlist/AddressModal/AddressModal
'
;
import
DeleteAddressModal
from
'
ui/watchlist/DeleteAddressModal
'
;
import
DeleteAddressModal
from
'
ui/watchlist/DeleteAddressModal
'
;
...
@@ -25,20 +22,15 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
...
@@ -25,20 +22,15 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
const
deleteModalProps
=
useDisclosure
();
const
deleteModalProps
=
useDisclosure
();
const
queryClient
=
useQueryClient
();
const
queryClient
=
useQueryClient
();
const
router
=
useRouter
();
const
router
=
useRouter
();
const
redirectIfNotAuth
=
useRedirectIfNotAuth
();
const
profileData
=
queryClient
.
getQueryData
<
UserInfo
>
([
resourceKey
(
'
user_info
'
)
]);
const
isAuth
=
Boolean
(
profileData
);
const
loginUrl
=
useLoginUrl
();
const
watchListQuery
=
useApiQuery
(
'
watchlist
'
,
{
queryOptions
:
{
enabled
:
isAdded
}
});
const
watchListQuery
=
useApiQuery
(
'
watchlist
'
,
{
queryOptions
:
{
enabled
:
isAdded
}
});
const
handleClick
=
React
.
useCallback
(()
=>
{
const
handleClick
=
React
.
useCallback
(()
=>
{
if
(
!
isAuth
)
{
if
(
redirectIfNotAuth
())
{
window
.
location
.
assign
(
loginUrl
);
return
;
return
;
}
}
isAdded
?
deleteModalProps
.
onOpen
()
:
addModalProps
.
onOpen
();
isAdded
?
deleteModalProps
.
onOpen
()
:
addModalProps
.
onOpen
();
},
[
addModalProps
,
deleteModalProps
,
isAdded
,
isAuth
,
loginUrl
]);
},
[
addModalProps
,
deleteModalProps
,
isAdded
,
redirectIfNotAuth
]);
const
handleAddOrDeleteSuccess
=
React
.
useCallback
(
async
()
=>
{
const
handleAddOrDeleteSuccess
=
React
.
useCallback
(
async
()
=>
{
const
queryKey
=
getResourceKey
(
'
address
'
,
{
pathParams
:
{
hash
:
router
.
query
.
hash
?.
toString
()
}
});
const
queryKey
=
getResourceKey
(
'
address
'
,
{
pathParams
:
{
hash
:
router
.
query
.
hash
?.
toString
()
}
});
...
...
ui/privateTags/AddressModal/AddressForm.tsx
View file @
40981a37
...
@@ -3,7 +3,7 @@ import {
...
@@ -3,7 +3,7 @@ import {
Button
,
Button
,
useColorModeValue
,
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
}
from
'
@chakra-ui/react
'
;
import
{
useMutation
,
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
{
useMutation
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
type
{
SubmitHandler
,
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
type
{
SubmitHandler
,
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useForm
,
Controller
}
from
'
react-hook-form
'
;
import
{
useForm
,
Controller
}
from
'
react-hook-form
'
;
...
@@ -11,7 +11,6 @@ import { useForm, Controller } from 'react-hook-form';
...
@@ -11,7 +11,6 @@ import { useForm, Controller } from 'react-hook-form';
import
type
{
AddressTag
,
AddressTagErrors
}
from
'
types/api/account
'
;
import
type
{
AddressTag
,
AddressTagErrors
}
from
'
types/api/account
'
;
import
type
{
ResourceErrorAccount
}
from
'
lib/api/resources
'
;
import
type
{
ResourceErrorAccount
}
from
'
lib/api/resources
'
;
import
{
resourceKey
}
from
'
lib/api/resources
'
;
import
useApiFetch
from
'
lib/api/useApiFetch
'
;
import
useApiFetch
from
'
lib/api/useApiFetch
'
;
import
getErrorMessage
from
'
lib/getErrorMessage
'
;
import
getErrorMessage
from
'
lib/getErrorMessage
'
;
import
{
ADDRESS_REGEXP
}
from
'
lib/validations/address
'
;
import
{
ADDRESS_REGEXP
}
from
'
lib/validations/address
'
;
...
@@ -21,8 +20,9 @@ import TagInput from 'ui/shared/TagInput';
...
@@ -21,8 +20,9 @@ import TagInput from 'ui/shared/TagInput';
const
TAG_MAX_LENGTH
=
35
;
const
TAG_MAX_LENGTH
=
35
;
type
Props
=
{
type
Props
=
{
data
?:
AddressTag
;
data
?:
Partial
<
AddressTag
>
;
onClose
:
()
=>
void
;
onClose
:
()
=>
void
;
onSuccess
:
()
=>
Promise
<
void
>
;
setAlertVisible
:
(
isAlertVisible
:
boolean
)
=>
void
;
setAlertVisible
:
(
isAlertVisible
:
boolean
)
=>
void
;
}
}
...
@@ -31,7 +31,7 @@ type Inputs = {
...
@@ -31,7 +31,7 @@ type Inputs = {
tag
:
string
;
tag
:
string
;
}
}
const
AddressForm
:
React
.
FC
<
Props
>
=
({
data
,
onClose
,
setAlertVisible
})
=>
{
const
AddressForm
:
React
.
FC
<
Props
>
=
({
data
,
onClose
,
onSuccess
,
setAlertVisible
})
=>
{
const
apiFetch
=
useApiFetch
();
const
apiFetch
=
useApiFetch
();
const
[
pending
,
setPending
]
=
useState
(
false
);
const
[
pending
,
setPending
]
=
useState
(
false
);
const
{
control
,
handleSubmit
,
formState
:
{
errors
,
isDirty
},
setError
}
=
useForm
<
Inputs
>
({
const
{
control
,
handleSubmit
,
formState
:
{
errors
,
isDirty
},
setError
}
=
useForm
<
Inputs
>
({
...
@@ -44,8 +44,6 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
...
@@ -44,8 +44,6 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
const
queryClient
=
useQueryClient
();
const
{
mutate
}
=
useMutation
((
formData
:
Inputs
)
=>
{
const
{
mutate
}
=
useMutation
((
formData
:
Inputs
)
=>
{
const
body
=
{
const
body
=
{
name
:
formData
?.
tag
,
name
:
formData
?.
tag
,
...
@@ -74,11 +72,10 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
...
@@ -74,11 +72,10 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
setAlertVisible
(
true
);
setAlertVisible
(
true
);
}
}
},
},
onSuccess
:
()
=>
{
onSuccess
:
async
()
=>
{
queryClient
.
refetchQueries
([
resourceKey
(
'
private_tags_address
'
)
]).
then
(()
=>
{
await
onSuccess
();
onClose
();
onClose
();
setPending
(
false
);
setPending
(
false
);
});
},
},
});
});
...
...
ui/privateTags/AddressModal/AddressModal.tsx
View file @
40981a37
...
@@ -9,18 +9,19 @@ import AddressForm from './AddressForm';
...
@@ -9,18 +9,19 @@ import AddressForm from './AddressForm';
type
Props
=
{
type
Props
=
{
isOpen
:
boolean
;
isOpen
:
boolean
;
onClose
:
()
=>
void
;
onClose
:
()
=>
void
;
data
?:
AddressTag
;
onSuccess
:
()
=>
Promise
<
void
>
;
data
?:
Partial
<
AddressTag
>
;
}
}
const
AddressModal
:
React
.
FC
<
Props
>
=
({
isOpen
,
onClose
,
data
})
=>
{
const
AddressModal
:
React
.
FC
<
Props
>
=
({
isOpen
,
onClose
,
onSuccess
,
data
})
=>
{
const
title
=
data
?
'
Edit address tag
'
:
'
New address tag
'
;
const
title
=
data
?.
id
?
'
Edit address tag
'
:
'
New address tag
'
;
const
text
=
!
data
?
'
Label any address with a private address tag (up to 35 chars) to customize your explorer experience.
'
:
''
;
const
text
=
!
data
?.
id
?
'
Label any address with a private address tag (up to 35 chars) to customize your explorer experience.
'
:
''
;
const
[
isAlertVisible
,
setAlertVisible
]
=
useState
(
false
);
const
[
isAlertVisible
,
setAlertVisible
]
=
useState
(
false
);
const
renderForm
=
useCallback
(()
=>
{
const
renderForm
=
useCallback
(()
=>
{
return
<
AddressForm
data=
{
data
}
onClose=
{
onClose
}
setAlertVisible=
{
setAlertVisible
}
/>;
return
<
AddressForm
data=
{
data
}
onClose=
{
onClose
}
onSuccess=
{
onSuccess
}
setAlertVisible=
{
setAlertVisible
}
/>;
},
[
data
,
onClose
]);
},
[
data
,
onClose
,
onSuccess
]);
return
(
return
(
<
FormModal
<
AddressTag
>
<
FormModal
<
AddressTag
>
isOpen=
{
isOpen
}
isOpen=
{
isOpen
}
...
...
ui/privateTags/PrivateAddressTags.tsx
View file @
40981a37
...
@@ -16,7 +16,7 @@ import AddressTagTable from './AddressTagTable/AddressTagTable';
...
@@ -16,7 +16,7 @@ import AddressTagTable from './AddressTagTable/AddressTagTable';
import
DeletePrivateTagModal
from
'
./DeletePrivateTagModal
'
;
import
DeletePrivateTagModal
from
'
./DeletePrivateTagModal
'
;
const
PrivateAddressTags
=
()
=>
{
const
PrivateAddressTags
=
()
=>
{
const
{
data
:
addressTagsData
,
isLoading
,
isError
}
=
useApiQuery
(
'
private_tags_address
'
,
{
queryOptions
:
{
refetchOnMount
:
false
}
});
const
{
data
:
addressTagsData
,
isLoading
,
isError
,
refetch
}
=
useApiQuery
(
'
private_tags_address
'
,
{
queryOptions
:
{
refetchOnMount
:
false
}
});
const
addressModalProps
=
useDisclosure
();
const
addressModalProps
=
useDisclosure
();
const
deleteModalProps
=
useDisclosure
();
const
deleteModalProps
=
useDisclosure
();
...
@@ -30,6 +30,10 @@ const PrivateAddressTags = () => {
...
@@ -30,6 +30,10 @@ const PrivateAddressTags = () => {
addressModalProps
.
onOpen
();
addressModalProps
.
onOpen
();
},
[
addressModalProps
]);
},
[
addressModalProps
]);
const
onAddOrEditSuccess
=
useCallback
(
async
()
=>
{
await
refetch
();
},
[
refetch
]);
const
onAddressModalClose
=
useCallback
(()
=>
{
const
onAddressModalClose
=
useCallback
(()
=>
{
setAddressModalData
(
undefined
);
setAddressModalData
(
undefined
);
addressModalProps
.
onClose
();
addressModalProps
.
onClose
();
...
@@ -103,7 +107,7 @@ const PrivateAddressTags = () => {
...
@@ -103,7 +107,7 @@ const PrivateAddressTags = () => {
Add address tag
Add address tag
</
Button
>
</
Button
>
</
Box
>
</
Box
>
<
AddressModal
{
...
addressModalProps
}
onClose=
{
onAddressModalClose
}
data=
{
addressModalData
}
/>
<
AddressModal
{
...
addressModalProps
}
onClose=
{
onAddressModalClose
}
data=
{
addressModalData
}
onSuccess=
{
onAddOrEditSuccess
}
/>
{
deleteModalData
&&
(
{
deleteModalData
&&
(
<
DeletePrivateTagModal
<
DeletePrivateTagModal
{
...
deleteModalProps
}
{
...
deleteModalProps
}
...
...
ui/
token/TokenDetails/TokenDetailsActions
.tsx
→
ui/
shared/AddressActions/Menu
.tsx
View file @
40981a37
import
{
Button
,
Menu
,
MenuButton
,
MenuItem
,
MenuList
,
Icon
,
Flex
}
from
'
@chakra-ui/react
'
;
import
{
Button
,
Menu
,
MenuButton
,
MenuItem
,
MenuList
,
Icon
,
Flex
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
iconArrow
from
'
icons/arrows/east-mini.svg
'
;
import
iconArrow
from
'
icons/arrows/east-mini.svg
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
PrivateTagMenuItem
from
'
./PrivateTagMenuItem
'
;
const
AddressActions
=
()
=>
{
const
router
=
useRouter
();
const
hash
=
getQueryParamString
(
router
.
query
.
hash
);
const
TokenDetailsActions
=
()
=>
{
return
(
return
(
<
Menu
>
<
Menu
>
<
MenuButton
<
MenuButton
...
@@ -24,12 +32,10 @@ const TokenDetailsActions = () => {
...
@@ -24,12 +32,10 @@ const TokenDetailsActions = () => {
<
MenuItem
py=
{
2
}
px=
{
4
}
>
<
MenuItem
py=
{
2
}
px=
{
4
}
>
Add public tag
Add public tag
</
MenuItem
>
</
MenuItem
>
<
MenuItem
py=
{
2
}
px=
{
4
}
>
<
PrivateTagMenuItem
py=
{
2
}
px=
{
4
}
hash=
{
hash
}
/>
Add private tag
</
MenuItem
>
</
MenuList
>
</
MenuList
>
</
Menu
>
</
Menu
>
);
);
};
};
export
default
React
.
memo
(
TokenDetail
sActions
);
export
default
React
.
memo
(
Addres
sActions
);
ui/shared/AddressActions/PrivateTagMenuItem.tsx
0 → 100644
View file @
40981a37
import
{
MenuItem
,
chakra
,
useDisclosure
}
from
'
@chakra-ui/react
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
type
{
Address
}
from
'
types/api/address
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useRedirectIfNotAuth
from
'
lib/hooks/useRedirectIfNotAuth
'
;
import
PrivateTagModal
from
'
ui/privateTags/AddressModal/AddressModal
'
;
interface
Props
{
className
?:
string
;
hash
:
string
;
}
const
PrivateTagMenuItem
=
({
className
,
hash
}:
Props
)
=>
{
const
modal
=
useDisclosure
();
const
queryClient
=
useQueryClient
();
const
redirectIfNotAuth
=
useRedirectIfNotAuth
();
const
queryKey
=
getResourceKey
(
'
address
'
,
{
pathParams
:
{
hash
}
});
const
addressData
=
queryClient
.
getQueryData
<
Address
>
(
queryKey
);
const
handleClick
=
React
.
useCallback
(()
=>
{
if
(
redirectIfNotAuth
())
{
return
;
}
modal
.
onOpen
();
},
[
modal
,
redirectIfNotAuth
]);
const
handleAddPrivateTag
=
React
.
useCallback
(
async
()
=>
{
await
queryClient
.
refetchQueries
({
queryKey
});
modal
.
onClose
();
},
[
queryClient
,
queryKey
,
modal
]);
const
formData
=
React
.
useMemo
(()
=>
{
return
{
address_hash
:
hash
,
};
},
[
hash
]);
if
(
addressData
?.
private_tags
?.
length
)
{
return
null
;
}
return
(
<>
<
MenuItem
className=
{
className
}
onClick=
{
handleClick
}
>
Add private tag
</
MenuItem
>
<
PrivateTagModal
isOpen=
{
modal
.
isOpen
}
onClose=
{
modal
.
onClose
}
onSuccess=
{
handleAddPrivateTag
}
data=
{
formData
}
/>
</>
);
};
export
default
React
.
memo
(
chakra
(
PrivateTagMenuItem
));
ui/token/TokenContractInfo.tsx
View file @
40981a37
...
@@ -7,10 +7,9 @@ import type { TokenInfo } from 'types/api/token';
...
@@ -7,10 +7,9 @@ import type { TokenInfo } from 'types/api/token';
import
appConfig
from
'
configs/app/config
'
;
import
appConfig
from
'
configs/app/config
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
AddressActionsMenu
from
'
ui/shared/AddressActions/Menu
'
;
import
AddressHeadingInfo
from
'
ui/shared/AddressHeadingInfo
'
;
import
AddressHeadingInfo
from
'
ui/shared/AddressHeadingInfo
'
;
import
TokenDetailsActions
from
'
./TokenDetails/TokenDetailsActions
'
;
interface
Props
{
interface
Props
{
tokenQuery
:
UseQueryResult
<
TokenInfo
>
;
tokenQuery
:
UseQueryResult
<
TokenInfo
>
;
}
}
...
@@ -51,7 +50,7 @@ const TokenContractInfo = ({ tokenQuery }: Props) => {
...
@@ -51,7 +50,7 @@ const TokenContractInfo = ({ tokenQuery }: Props) => {
<
AddressHeadingInfo
<
AddressHeadingInfo
address=
{
address
}
address=
{
address
}
token=
{
contractQuery
.
data
?.
token
}
token=
{
contractQuery
.
data
?.
token
}
after=
{
appConfig
.
isAccountSupported
?
<
TokenDetailsActions
/>
:
null
}
after=
{
appConfig
.
isAccountSupported
?
<
AddressActionsMenu
/>
:
null
}
/>
/>
);
);
};
};
...
...
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