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
158081b7
Commit
158081b7
authored
Aug 20, 2022
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add some validations and form fixes
parent
17ea4d81
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
124 additions
and
57 deletions
+124
-57
addressValidations.ts
lib/addressValidations.ts
+5
-0
transactionValidations.ts
lib/transactionValidations.ts
+5
-0
ApiKeyForm.tsx
ui/apiKey/ApiKeyModal/ApiKeyForm.tsx
+9
-9
AddressForm.tsx
ui/privateTags/AddressModal/AddressForm.tsx
+11
-10
TransactionForm.tsx
ui/privateTags/TransactionModal/TransactionForm.tsx
+12
-9
PublicTagFormAddressInput.tsx
ui/publicTags/PublicTagsForm/PublicTagFormAddressInput.tsx
+2
-0
PublicTagFormComment.tsx
ui/publicTags/PublicTagsForm/PublicTagFormComment.tsx
+3
-0
PublicTagsForm.tsx
ui/publicTags/PublicTagsForm/PublicTagsForm.tsx
+38
-12
PublicTagsFormInput.tsx
ui/publicTags/PublicTagsForm/PublicTagsFormInput.tsx
+16
-2
AddressInput.tsx
ui/shared/AddressInput.tsx
+1
-1
AddressForm.tsx
ui/watchlist/AddressModal/AddressForm.tsx
+22
-14
No files found.
lib/addressValidations.ts
0 → 100644
View file @
158081b7
// maybe it depends on the network??
export
const
ADDRESS_REGEXP
=
/^0x
[
a-fA-F
\d]{40}
$/
;
export
const
ADDRESS_LENGTH
=
42
;
lib/transactionValidations.ts
0 → 100644
View file @
158081b7
// maybe it depends on the network??
export
const
TRANSACTION_HASH_REGEXP
=
/^0x
[
a-fA-F
\d]{64}
$/
;
export
const
TRANSACTION_HASH_LENGTH
=
66
;
ui/apiKey/ApiKeyModal/ApiKeyForm.tsx
View file @
158081b7
...
...
@@ -7,7 +7,7 @@ import {
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
import
{
useMutation
,
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
useEffect
}
from
'
react
'
;
import
React
,
{
useCallback
}
from
'
react
'
;
import
type
{
SubmitHandler
,
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useForm
,
Controller
}
from
'
react-hook-form
'
;
...
...
@@ -23,19 +23,19 @@ type Inputs = {
name
:
string
;
}
// idk, maybe there is no limit
const
NAME_MAX_LENGTH
=
100
;
const
NAME_MAX_LENGTH
=
255
;
const
ApiKeyForm
:
React
.
FC
<
Props
>
=
({
data
,
onClose
})
=>
{
const
{
control
,
handleSubmit
,
formState
:
{
errors
},
setValue
}
=
useForm
<
Inputs
>
();
const
{
control
,
handleSubmit
,
formState
:
{
errors
}
}
=
useForm
<
Inputs
>
({
mode
:
'
all
'
,
defaultValues
:
{
token
:
data
?.
api_key
||
''
,
name
:
data
?.
name
||
''
,
},
});
const
queryClient
=
useQueryClient
();
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
useEffect
(()
=>
{
setValue
(
'
token
'
,
data
?.
api_key
||
''
);
setValue
(
'
name
'
,
data
?.
name
||
''
);
},
[
setValue
,
data
]);
const
updateApiKey
=
(
data
:
Inputs
)
=>
{
const
body
=
JSON
.
stringify
({
name
:
data
.
name
});
...
...
ui/privateTags/AddressModal/AddressForm.tsx
View file @
158081b7
...
...
@@ -4,16 +4,16 @@ import {
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
import
{
useMutation
,
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
use
Effect
,
use
State
}
from
'
react
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
type
{
SubmitHandler
,
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useForm
,
Controller
}
from
'
react-hook-form
'
;
import
type
{
AddressTag
}
from
'
types/api/account
'
;
import
{
ADDRESS_REGEXP
}
from
'
lib/addressValidations
'
;
import
AddressInput
from
'
ui/shared/AddressInput
'
;
import
TagInput
from
'
ui/shared/TagInput
'
;
const
ADDRESS_LENGTH
=
42
;
const
TAG_MAX_LENGTH
=
35
;
type
Props
=
{
...
...
@@ -28,13 +28,15 @@ type Inputs = {
const
AddressForm
:
React
.
FC
<
Props
>
=
({
data
,
onClose
})
=>
{
const
[
pending
,
setPending
]
=
useState
(
false
);
const
{
control
,
handleSubmit
,
formState
:
{
errors
},
setValue
}
=
useForm
<
Inputs
>
();
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
const
{
control
,
handleSubmit
,
formState
:
{
errors
}
}
=
useForm
<
Inputs
>
({
mode
:
'
all
'
,
defaultValues
:
{
address
:
data
?.
address_hash
||
''
,
tag
:
data
?.
name
||
''
,
},
});
useEffect
(()
=>
{
setValue
(
'
address
'
,
data
?.
address_hash
||
''
);
setValue
(
'
tag
'
,
data
?.
name
||
''
);
},
[
setValue
,
data
]);
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
const
queryClient
=
useQueryClient
();
...
...
@@ -83,8 +85,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose }) => {
name=
"address"
control=
{
control
}
rules=
{
{
maxLength
:
ADDRESS_LENGTH
,
minLength
:
ADDRESS_LENGTH
,
pattern
:
ADDRESS_REGEXP
,
}
}
render=
{
renderAddressInput
}
/>
...
...
ui/privateTags/TransactionModal/TransactionForm.tsx
View file @
158081b7
...
...
@@ -4,16 +4,16 @@ import {
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
import
{
useMutation
,
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
use
Effect
,
use
State
}
from
'
react
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
type
{
SubmitHandler
,
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useForm
,
Controller
}
from
'
react-hook-form
'
;
import
type
{
TransactionTag
}
from
'
types/api/account
'
;
import
{
TRANSACTION_HASH_LENGTH
,
TRANSACTION_HASH_REGEXP
}
from
'
lib/transactionValidations
'
;
import
TagInput
from
'
ui/shared/TagInput
'
;
import
TransactionInput
from
'
ui/shared/TransactionInput
'
;
const
HASH_LENGTH
=
66
;
const
TAG_MAX_LENGTH
=
35
;
type
Props
=
{
...
...
@@ -28,13 +28,15 @@ type Inputs = {
const
TransactionForm
:
React
.
FC
<
Props
>
=
({
data
,
onClose
})
=>
{
const
[
pending
,
setPending
]
=
useState
(
false
);
const
{
control
,
handleSubmit
,
formState
:
{
errors
},
setValue
}
=
useForm
<
Inputs
>
();
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
useEffect
(()
=>
{
setValue
(
'
transaction
'
,
data
?.
transaction_hash
||
''
);
setValue
(
'
tag
'
,
data
?.
name
||
''
);
},
[
setValue
,
data
]);
const
{
control
,
handleSubmit
,
formState
:
{
errors
}
}
=
useForm
<
Inputs
>
({
mode
:
'
all
'
,
defaultValues
:
{
transaction
:
data
?.
transaction_hash
||
''
,
tag
:
data
?.
name
||
''
,
},
});
const
queryClient
=
useQueryClient
();
...
...
@@ -84,8 +86,9 @@ const TransactionForm: React.FC<Props> = ({ data, onClose }) => {
name=
"transaction"
control=
{
control
}
rules=
{
{
maxLength
:
HASH_LENGTH
,
minLength
:
HASH_LENGTH
,
maxLength
:
TRANSACTION_HASH_LENGTH
,
minLength
:
TRANSACTION_HASH_LENGTH
,
pattern
:
TRANSACTION_HASH_REGEXP
,
}
}
render=
{
renderTransactionInput
}
/>
...
...
ui/publicTags/PublicTagsForm/PublicTagFormAddressInput.tsx
View file @
158081b7
...
...
@@ -5,6 +5,7 @@ import { Controller } from 'react-hook-form';
import
MinusIcon
from
'
icons/minus.svg
'
;
import
PlusIcon
from
'
icons/plus.svg
'
;
import
{
ADDRESS_REGEXP
}
from
'
lib/addressValidations
'
;
import
AddressInput
from
'
ui/shared/AddressInput
'
;
import
type
{
Inputs
}
from
'
./PublicTagsForm
'
;
...
...
@@ -38,6 +39,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, hasE
name=
{
`addresses.${ index }.address`
}
control=
{
control
}
render=
{
renderAddressInput
}
rules=
{
{
pattern
:
ADDRESS_REGEXP
}
}
/>
{
index
===
fieldsLength
-
1
&&
fieldsLength
<
MAX_INPUTS_NUM
&&
(
<
IconButton
...
...
ui/publicTags/PublicTagsForm/PublicTagFormComment.tsx
View file @
158081b7
...
...
@@ -5,6 +5,8 @@ import { Controller } from 'react-hook-form';
import
type
{
Inputs
}
from
'
./PublicTagsForm
'
;
const
TEXT_INPUT_MAX_LENGTH
=
255
;
interface
Props
{
control
:
Control
<
Inputs
>
;
}
...
...
@@ -27,6 +29,7 @@ export default function PublicTagFormComment({ control }: Props) {
name=
"comment"
control=
{
control
}
render=
{
renderComment
}
rules=
{
{
maxLength
:
TEXT_INPUT_MAX_LENGTH
}
}
/>
);
}
ui/publicTags/PublicTagsForm/PublicTagsForm.tsx
View file @
158081b7
...
...
@@ -50,15 +50,16 @@ const ADDRESS_INPUT_BUTTONS_WIDTH = 170;
const
PublicTagsForm
=
({
changeToDataScreen
,
data
}:
Props
)
=>
{
const
{
control
,
handleSubmit
,
formState
:
{
errors
}
}
=
useForm
<
Inputs
>
({
defaultValues
:
{
userName
:
data
?.
userName
,
userEmail
:
data
?.
userEmail
,
companyName
:
data
?.
companyName
,
companyUrl
:
data
?.
companyUrl
,
tag
:
data
?.
tags
.
map
((
tag
:
TPublicTag
)
=>
tag
.
name
).
join
(
'
;
'
),
userName
:
data
?.
userName
||
''
,
userEmail
:
data
?.
userEmail
||
''
,
companyName
:
data
?.
companyName
||
''
,
companyUrl
:
data
?.
companyUrl
||
''
,
tag
:
data
?.
tags
.
map
((
tag
:
TPublicTag
)
=>
tag
.
name
).
join
(
'
;
'
)
||
''
,
addresses
:
data
?.
addresses
.
map
((
adr
:
TPublicTagAddress
,
index
:
number
)
=>
({
name
:
`address.
${
index
}
.address`
,
address
:
adr
.
address
}))
||
[
{
name
:
'
address.0.address
'
,
address
:
''
}
],
comment
:
data
?.
comment
,
comment
:
data
?.
comment
||
''
,
},
mode
:
'
all
'
,
});
const
{
fields
,
append
,
remove
}
=
useFieldArray
({
...
...
@@ -78,16 +79,36 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
<
Text
size=
"sm"
variant=
"secondary"
paddingBottom=
{
5
}
>
Company info
</
Text
>
<
Grid
templateColumns=
"1fr 1fr"
rowGap=
{
4
}
columnGap=
{
5
}
>
<
GridItem
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="userName" control=
{
control
}
label=
{
placeholders
.
userName
}
required/
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="userName"
control=
{
control
}
label=
{
placeholders
.
userName
}
required
/
>
</
GridItem
>
<
GridItem
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="companyName" control=
{
control
}
label=
{
placeholders
.
companyName
}
/
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="companyName"
control=
{
control
}
label=
{
placeholders
.
companyName
}
/
>
</
GridItem
>
<
GridItem
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="userEmail" control=
{
control
}
label=
{
placeholders
.
userEmail
}
required/
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="userEmail"
control=
{
control
}
label=
{
placeholders
.
userEmail
}
pattern=
{
/^
[\w
.%+-
]
+@
[
a-zA-Z
\d
-
]
+
(?:\.[
a-zA-Z
\d
-
]
+
)
+$/
}
hasError=
{
Boolean
(
errors
.
userEmail
)
}
required
/
>
</
GridItem
>
<
GridItem
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="companyUrl" control=
{
control
}
label=
{
placeholders
.
companyUrl
}
/
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="companyUrl"
control=
{
control
}
label=
{
placeholders
.
companyUrl
}
/
>
</
GridItem
>
</
Grid
>
<
Box
marginTop=
{
4
}
marginBottom=
{
8
}
>
...
...
@@ -95,14 +116,19 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
</
Box
>
<
Text
size=
"sm"
variant=
"secondary"
marginBottom=
{
5
}
>
Public tags (2 tags maximum, please use
"
;
"
as a divider)
</
Text
>
<
Box
marginBottom=
{
4
}
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="tag" control=
{
control
}
label=
{
placeholders
.
tag
}
required/
>
<
PublicTagsFormInput
<
Inputs
>
fieldName="tag"
control=
{
control
}
label=
{
placeholders
.
tag
}
hasError=
{
Boolean
(
errors
.
tag
)
}
required/
>
</
Box
>
{
fields
.
map
((
field
,
index
)
=>
{
return
(
<
Box
position=
"relative"
key=
{
field
.
id
}
marginBottom=
{
4
}
>
<
PublicTagFormAddressInput
control=
{
control
}
hasError=
{
Boolean
(
errors
.
addresses
)
}
hasError=
{
Boolean
(
errors
?.
addresses
?.[
index
]
)
}
index=
{
index
}
fieldsLength=
{
fields
.
length
}
onAddFieldClick=
{
onAddFieldClick
}
...
...
ui/publicTags/PublicTagsForm/PublicTagsFormInput.tsx
View file @
158081b7
...
...
@@ -3,14 +3,25 @@ import React, { useCallback } from 'react';
import
type
{
ControllerRenderProps
,
FieldValues
,
Path
,
Control
}
from
'
react-hook-form
'
;
import
{
Controller
}
from
'
react-hook-form
'
;
const
TEXT_INPUT_MAX_LENGTH
=
255
;
interface
Props
<
TInputs
extends
FieldValues
>
{
fieldName
:
Path
<
TInputs
>
;
label
:
string
;
required
?:
boolean
;
control
:
Control
<
TInputs
,
object
>
;
pattern
?:
RegExp
;
hasError
?:
boolean
;
}
export
default
function
PublicTagsFormInput
<
Inputs
extends
FieldValues
>
({
label
,
control
,
required
,
fieldName
}:
Props
<
Inputs
>
)
{
export
default
function
PublicTagsFormInput
<
Inputs
extends
FieldValues
>
({
label
,
control
,
required
,
fieldName
,
pattern
,
hasError
,
}:
Props
<
Inputs
>
)
{
const
renderInput
=
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
Inputs
,
typeof
fieldName
>
})
=>
{
return
(
<
FormControl
variant=
"floating"
id=
{
field
.
name
}
isRequired=
{
required
}
size=
"lg"
>
...
...
@@ -18,16 +29,19 @@ export default function PublicTagsFormInput<Inputs extends FieldValues>({ label,
{
...
field
}
size=
"lg"
required=
{
required
}
isInvalid=
{
hasError
}
maxLength=
{
TEXT_INPUT_MAX_LENGTH
}
/>
<
FormLabel
>
{
label
}
</
FormLabel
>
</
FormControl
>
);
},
[
label
,
required
]);
},
[
label
,
required
,
hasError
]);
return
(
<
Controller
name=
{
fieldName
}
control=
{
control
}
render=
{
renderInput
}
rules=
{
{
pattern
}
}
/>
);
}
ui/shared/AddressInput.tsx
View file @
158081b7
...
...
@@ -6,7 +6,7 @@ import {
import
React
from
'
react
'
;
import
type
{
ControllerRenderProps
,
FieldValues
,
Path
}
from
'
react-hook-form
'
;
const
ADDRESS_LENGTH
=
42
;
import
{
ADDRESS_LENGTH
}
from
'
lib/addressValidations
'
;
type
Props
<
TInputs
extends
FieldValues
,
TInputName
extends
Path
<
TInputs
>>
=
{
field
:
ControllerRenderProps
<
TInputs
,
TInputName
>
;
...
...
ui/watchlist/AddressModal/AddressForm.tsx
View file @
158081b7
...
...
@@ -8,18 +8,20 @@ import {
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
import
{
useMutation
,
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
use
Effect
,
use
State
}
from
'
react
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
type
{
SubmitHandler
,
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useForm
,
Controller
}
from
'
react-hook-form
'
;
import
type
{
TWatchlistItem
}
from
'
types/client/account
'
;
import
{
ADDRESS_REGEXP
}
from
'
lib/addressValidations
'
;
import
AddressInput
from
'
ui/shared/AddressInput
'
;
import
TagInput
from
'
ui/shared/TagInput
'
;
// does it depend on the network?
const
NOTIFICATIONS
=
[
'
native
'
,
'
ERC-20
'
,
'
ERC-721
'
]
as
const
;
const
NOTIFICATIONS_NAMES
=
[
'
xDAI
'
,
'
ERC-20
'
,
'
ERC-721, ERC-1155 (NFT)
'
];
const
ADDRESS_LENGTH
=
42
;
const
TAG_MAX_LENGTH
=
35
;
type
Props
=
{
...
...
@@ -59,9 +61,25 @@ type Checkboxes = 'notification' |
const
AddressForm
:
React
.
FC
<
Props
>
=
({
data
,
onClose
})
=>
{
const
[
pending
,
setPending
]
=
useState
(
false
);
const
{
control
,
handleSubmit
,
formState
:
{
errors
},
setValue
}
=
useForm
<
Inputs
>
();
const
formBackgroundColor
=
useColorModeValue
(
'
white
'
,
'
gray.900
'
);
let
notificationsDefault
=
{}
as
Inputs
[
'
notification_settings
'
];
if
(
!
data
)
{
NOTIFICATIONS
.
forEach
(
n
=>
notificationsDefault
[
n
]
=
{
incoming
:
true
,
outcoming
:
true
});
}
else
{
notificationsDefault
=
data
.
notification_settings
;
}
const
{
control
,
handleSubmit
,
formState
:
{
errors
}
}
=
useForm
<
Inputs
>
({
defaultValues
:
{
address
:
data
?.
address_hash
||
''
,
tag
:
data
?.
name
||
''
,
notification
:
data
?
data
.
notification_methods
.
email
:
true
,
notification_settings
:
notificationsDefault
,
},
mode
:
'
all
'
,
});
const
queryClient
=
useQueryClient
();
const
{
mutate
}
=
useMutation
((
formData
:
Inputs
)
=>
{
...
...
@@ -98,15 +116,6 @@ const AddressForm: React.FC<Props> = ({ data, onClose }) => {
mutate
(
formData
);
};
useEffect
(()
=>
{
const
notificationsDefault
=
{}
as
Inputs
[
'
notification_settings
'
];
NOTIFICATIONS
.
forEach
(
n
=>
notificationsDefault
[
n
]
=
{
incoming
:
true
,
outcoming
:
true
});
setValue
(
'
address
'
,
data
?.
address_hash
||
''
);
setValue
(
'
tag
'
,
data
?.
name
||
''
);
setValue
(
'
notification
'
,
data
?
data
.
notification_methods
.
email
:
true
);
setValue
(
'
notification_settings
'
,
data
?
data
.
notification_settings
:
notificationsDefault
);
},
[
setValue
,
data
]);
const
renderAddressInput
=
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
Inputs
,
'
address
'
>
})
=>
{
return
<
AddressInput
<
Inputs
,
'
address
'
>
field=
{
field
}
isInvalid=
{
Boolean
(
errors
.
address
)
}
backgroundColor=
{
formBackgroundColor
}
/
>
;
}, [ errors, formBackgroundColor ]);
...
...
@@ -135,8 +144,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose }) => {
name=
"address"
control=
{
control
}
rules=
{
{
maxLength
:
ADDRESS_LENGTH
,
minLength
:
ADDRESS_LENGTH
,
pattern
:
ADDRESS_REGEXP
,
}
}
render=
{
renderAddressInput
}
/>
...
...
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