mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
Webatrice: i18n login screen (#4584)
* i18n: login container and form * i18n: activate, host, and register forms * i18n: reset password forms * i18n: login dialogs, ICU formatting * i18n: login containers and components Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
parent
baaf261116
commit
f5b973e15c
35 changed files with 424 additions and 99 deletions
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"AccountActivationForm": {
|
||||
"error": {
|
||||
"failed": "Account activation failed"
|
||||
},
|
||||
"label": {
|
||||
"activate": "Activate Account"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import React, { useState } from "react";
|
|||
import { connect } from 'react-redux';
|
||||
import { Form, Field } from 'react-final-form';
|
||||
import { OnChange } from 'react-final-form-listeners';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
|
@ -16,6 +17,7 @@ import { ServerTypes } from 'store';
|
|||
|
||||
const AccountActivationForm = ({ onSubmit }) => {
|
||||
const [errorMessage, setErrorMessage] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useReduxEffect(() => {
|
||||
setErrorMessage(true);
|
||||
|
|
@ -33,7 +35,7 @@ const AccountActivationForm = ({ onSubmit }) => {
|
|||
const errors: any = {};
|
||||
|
||||
if (!values.token) {
|
||||
errors.token = 'Required';
|
||||
errors.token = t('Common.validation.required');
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
@ -45,17 +47,17 @@ const AccountActivationForm = ({ onSubmit }) => {
|
|||
return (
|
||||
<form className="AccountActivationForm" onSubmit={handleSubmit}>
|
||||
<div className="AccountActivationForm-item">
|
||||
<Field label="Token" name="token" component={InputField} />
|
||||
<Field label={t('Common.label.token')} name="token" component={InputField} />
|
||||
</div>
|
||||
|
||||
{errorMessage && (
|
||||
<div className="AccountActivationForm-error">
|
||||
<Typography color="error">Account activation failed</Typography>
|
||||
<Typography color="error">{ t('AccountActivationForm.error.failed') }</Typography>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Button className="AccountActivationForm-submit rounded tall" color="primary" variant="contained" type="submit">
|
||||
Activate Account
|
||||
{ t('AccountActivationForm.label.activate') }
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"KnownHostForm": {
|
||||
"help": "Need help adding a new host?",
|
||||
"label": {
|
||||
"add": "Add Host",
|
||||
"find": "Find Host"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
import React, { useState } from "react";
|
||||
import { connect } from 'react-redux';
|
||||
import { Form, Field } from 'react-final-form'
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import AnchorLink from '@material-ui/core/Link';
|
||||
|
|
@ -12,20 +13,21 @@ import './KnownHostForm.css';
|
|||
|
||||
const KnownHostForm = ({ host, onRemove, onSubmit }) => {
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const validate = values => {
|
||||
const errors: any = {};
|
||||
|
||||
if (!values.name) {
|
||||
errors.name = 'Required'
|
||||
errors.name = t('Common.validation.required');
|
||||
}
|
||||
|
||||
if (!values.host) {
|
||||
errors.host = 'Required'
|
||||
errors.host = t('Common.validation.required');
|
||||
}
|
||||
|
||||
if (!values.port) {
|
||||
errors.port = 'Required'
|
||||
errors.port = t('Common.validation.required');
|
||||
}
|
||||
|
||||
if (Object.keys(errors).length) {
|
||||
|
|
@ -54,29 +56,29 @@ const KnownHostForm = ({ host, onRemove, onSubmit }) => {
|
|||
{({ handleSubmit }) => (
|
||||
<form className="KnownHostForm" onSubmit={handleSubmit}>
|
||||
<div className="KnownHostForm-item">
|
||||
<Field label="Host Name" name="name" component={InputField} />
|
||||
<Field label={t('Common.label.hostName')} name="name" component={InputField} />
|
||||
</div>
|
||||
<div className="KnownHostForm-item">
|
||||
<Field label="Host Address" name="host" component={InputField} />
|
||||
<Field label={t('Common.label.hostAddress')} name="host" component={InputField} />
|
||||
</div>
|
||||
<div className="KnownHostForm-item">
|
||||
<Field label="Port" name="port" type="number" component={InputField} />
|
||||
<Field label={t('Common.label.port')} name="port" type="number" component={InputField} />
|
||||
</div>
|
||||
|
||||
<Button className="KnownHostForm-submit" color="primary" variant="contained" type="submit">
|
||||
{host ? 'Save Changes' : 'Add Host' }
|
||||
{host ? t('Common.label.saveChanges') : t('KnownHostForm.label.add') }
|
||||
</Button>
|
||||
|
||||
<div className="KnownHostForm-actions">
|
||||
<div className="KnownHostForm-actions__delete">
|
||||
{ host && (
|
||||
<Button color="inherit" onClick={() => !confirmDelete ? setConfirmDelete(true) : onRemove(host)}>
|
||||
{ !confirmDelete ? 'Delete' : 'Are you sure?' }
|
||||
{ !confirmDelete ? t('Common.label.delete') : t('Common.label.confirmSure') }
|
||||
</Button>
|
||||
) }
|
||||
</div>
|
||||
<AnchorLink href='https://github.com/Cockatrice/Cockatrice/wiki/Public-Servers' target='_blank'>
|
||||
Need help adding a new host?
|
||||
{ t('KnownHostForm.label.find') }
|
||||
</AnchorLink>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
11
webclient/src/forms/LoginForm/LoginForm.i18n.json
Normal file
11
webclient/src/forms/LoginForm/LoginForm.i18n.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"LoginForm": {
|
||||
"label": {
|
||||
"autoConnect": "Auto Connect",
|
||||
"forgot": "Forgot Password",
|
||||
"login": "Login",
|
||||
"savePassword": "Save Password",
|
||||
"savedPassword": "Saved Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Form, Field } from 'react-final-form';
|
||||
import { OnChange } from 'react-final-form-listeners';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
|
|
@ -12,22 +13,24 @@ import { APP_USER } from 'types';
|
|||
|
||||
import './LoginForm.css';
|
||||
|
||||
const PASSWORD_LABEL = 'Password';
|
||||
const STORED_PASSWORD_LABEL = '* Saved Password *';
|
||||
|
||||
const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginFormProps) => {
|
||||
const { t } = useTranslation();
|
||||
const PASSWORD_LABEL = t('Common.label.password');
|
||||
const STORED_PASSWORD_LABEL = `* ${t('LoginForm.label.savedPassword')} *`;
|
||||
|
||||
const [host, setHost] = useState(null);
|
||||
const [passwordLabel, setPasswordLabel] = useState(PASSWORD_LABEL);
|
||||
const [autoConnect, setAutoConnect] = useAutoConnect();
|
||||
|
||||
|
||||
const validate = values => {
|
||||
const errors: any = {};
|
||||
|
||||
if (!values.userName) {
|
||||
errors.userName = 'Required';
|
||||
errors.userName = t('Common.validation.required');
|
||||
}
|
||||
if (!values.selectedHost) {
|
||||
errors.selectedHost = 'Required';
|
||||
errors.selectedHost = t('Common.validation.required');
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
@ -112,7 +115,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
|
|||
<form className='loginForm' onSubmit={handleSubmit}>
|
||||
<div className='loginForm-items'>
|
||||
<div className='loginForm-item'>
|
||||
<Field label='Username' name='userName' component={InputField} autoComplete='username' />
|
||||
<Field label={t('Common.label.username')} name='userName' component={InputField} autoComplete='username' />
|
||||
<OnChange name="userName">{onUserNameChange}</OnChange>
|
||||
</div>
|
||||
<div className='loginForm-item'>
|
||||
|
|
@ -127,17 +130,19 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
|
|||
/>
|
||||
</div>
|
||||
<div className='loginForm-actions'>
|
||||
<Field label='Save Password' name='remember' component={CheckboxField} />
|
||||
<Field label={t('LoginForm.label.savePassword')} name='remember' component={CheckboxField} />
|
||||
<OnChange name="remember">{onRememberChange}</OnChange>
|
||||
|
||||
<Button color='primary' onClick={onResetPassword}>Forgot Password</Button>
|
||||
<Button color='primary' onClick={onResetPassword}>
|
||||
{ t('LoginForm.label.forgot') }
|
||||
</Button>
|
||||
</div>
|
||||
<div className='loginForm-item'>
|
||||
<Field name='selectedHost' component={KnownHosts} />
|
||||
<OnChange name="selectedHost">{setHost}</OnChange>
|
||||
</div>
|
||||
<div className='loginForm-actions'>
|
||||
<Field label='Auto Connect' name='autoConnect' component={CheckboxField} />
|
||||
<Field label={t('LoginForm.label.autoConnect')} name='autoConnect' component={CheckboxField} />
|
||||
<OnChange name="autoConnect">{onAutoConnectChange}</OnChange>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -148,7 +153,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
|
|||
type='submit'
|
||||
disabled={disableSubmitButton}
|
||||
>
|
||||
Login
|
||||
{ t('LoginForm.label.login') }
|
||||
</Button>
|
||||
</form>
|
||||
)
|
||||
|
|
|
|||
10
webclient/src/forms/RegisterForm/RegisterForm.i18n.json
Normal file
10
webclient/src/forms/RegisterForm/RegisterForm.i18n.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"RegisterForm": {
|
||||
"label": {
|
||||
"register": "Register"
|
||||
},
|
||||
"toast": {
|
||||
"registerSuccess": "Registration Successful!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { useState } from 'react';
|
||||
import { Form, Field } from 'react-final-form';
|
||||
import { OnChange } from 'react-final-form-listeners';
|
||||
import setFieldTouched from 'final-form-set-field-touched'
|
||||
import setFieldTouched from 'final-form-set-field-touched';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
|
@ -14,12 +15,13 @@ import './RegisterForm.css';
|
|||
import { useToast } from 'components/Toast';
|
||||
|
||||
const RegisterForm = ({ onSubmit }: RegisterFormProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [emailRequired, setEmailRequired] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [emailError, setEmailError] = useState(null);
|
||||
const [passwordError, setPasswordError] = useState(null);
|
||||
const [userNameError, setUserNameError] = useState(null);
|
||||
const { openToast } = useToast({ key: 'registration-success', children: 'Registration Successful!' })
|
||||
const { openToast } = useToast({ key: 'registration-success', children: t('RegisterForm.toast.registerSuccess') })
|
||||
|
||||
const onHostChange = (host) => setEmailRequired(false);
|
||||
const onEmailChange = () => emailError && setEmailError(null);
|
||||
|
|
@ -64,31 +66,31 @@ const RegisterForm = ({ onSubmit }: RegisterFormProps) => {
|
|||
const errors: any = {};
|
||||
|
||||
if (!values.userName) {
|
||||
errors.userName = 'Required';
|
||||
errors.userName = t('Common.validation.required');
|
||||
} else if (userNameError) {
|
||||
errors.userName = userNameError;
|
||||
}
|
||||
|
||||
if (!values.password) {
|
||||
errors.password = 'Required';
|
||||
errors.password = t('Common.validation.required');
|
||||
} else if (values.password.length < 8) {
|
||||
errors.password = 'Minimum of 8 characters required';
|
||||
errors.password = t('Common.validation.minChars', { count: 8 });
|
||||
} else if (passwordError) {
|
||||
errors.password = passwordError;
|
||||
}
|
||||
|
||||
if (!values.passwordConfirm) {
|
||||
errors.passwordConfirm = 'Required';
|
||||
errors.passwordConfirm = t('Common.validation.required');
|
||||
} else if (values.password !== values.passwordConfirm) {
|
||||
errors.passwordConfirm = 'Passwords don\'t match'
|
||||
errors.passwordConfirm = t('Common.validation.passwordsMustMatch');
|
||||
}
|
||||
|
||||
if (!values.selectedHost) {
|
||||
errors.selectedHost = 'Required';
|
||||
errors.selectedHost = t('Common.validation.required');
|
||||
}
|
||||
|
||||
if (emailRequired && !values.email) {
|
||||
errors.email = 'Required';
|
||||
errors.email = t('Common.validation.required');
|
||||
} else if (emailError) {
|
||||
errors.email = emailError;
|
||||
}
|
||||
|
|
@ -111,16 +113,22 @@ const RegisterForm = ({ onSubmit }: RegisterFormProps) => {
|
|||
<form className="RegisterForm" onSubmit={handleSubmit}>
|
||||
<div className="RegisterForm-column">
|
||||
<div className="RegisterForm-item">
|
||||
<Field label="Player Name" name="userName" component={InputField} autoComplete="username" />
|
||||
<Field label={t('Common.label.username')} name="userName" component={InputField} autoComplete="username" />
|
||||
<OnChange name="userName">{onUserNameChange}</OnChange>
|
||||
</div>
|
||||
<div className="RegisterForm-item">
|
||||
<Field label="Password" name="password" type="password" component={InputField} autoComplete='new-password' />
|
||||
<Field
|
||||
label={t('Common.label.password')}
|
||||
name="password"
|
||||
type="password"
|
||||
component={InputField}
|
||||
autoComplete='new-password'
|
||||
/>
|
||||
<OnChange name="password">{onPasswordChange}</OnChange>
|
||||
</div>
|
||||
<div className="RegisterForm-item">
|
||||
<Field
|
||||
label="Confirm Password"
|
||||
label={t('Common.label.confirmPassword')}
|
||||
name="passwordConfirm"
|
||||
type="password"
|
||||
component={InputField}
|
||||
|
|
@ -134,17 +142,17 @@ const RegisterForm = ({ onSubmit }: RegisterFormProps) => {
|
|||
</div>
|
||||
<div className="RegisterForm-column" >
|
||||
<div className="RegisterForm-item">
|
||||
<Field label="Real Name" name="realName" component={InputField} />
|
||||
<Field label={t('Common.label.realName')} name="realName" component={InputField} />
|
||||
</div>
|
||||
<div className="RegisterForm-item">
|
||||
<Field label="Email" name="email" type="email" component={InputField} />
|
||||
<Field label={t('Common.label.email')} name="email" type="email" component={InputField} />
|
||||
<OnChange name="email">{onEmailChange}</OnChange>
|
||||
</div>
|
||||
<div className="RegisterForm-item">
|
||||
<Field label="Country" name="country" component={CountryDropdown} />
|
||||
<Field label={t('Common.label.country')} name="country" component={CountryDropdown} />
|
||||
</div>
|
||||
<Button className="RegisterForm-submit tall" color="primary" variant="contained" type="submit">
|
||||
Register
|
||||
{ t('RegisterForm.label.register') }
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"RequestPasswordResetForm": {
|
||||
"error": "Request password reset failed",
|
||||
"mfaEnabled": "Server has multi-factor authentication enabled",
|
||||
"request": "Request Reset Token",
|
||||
"skipRequest": "I already have a reset token"
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import React, { useState } from "react";
|
|||
import { connect } from 'react-redux';
|
||||
import { Form, Field } from 'react-final-form';
|
||||
import { OnChange } from 'react-final-form-listeners';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
|
@ -17,6 +18,7 @@ import { ServerTypes } from 'store';
|
|||
const RequestPasswordResetForm = ({ onSubmit, skipTokenRequest }) => {
|
||||
const [errorMessage, setErrorMessage] = useState(false);
|
||||
const [isMFA, setIsMFA] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useReduxEffect(() => {
|
||||
setErrorMessage(true);
|
||||
|
|
@ -39,13 +41,13 @@ const RequestPasswordResetForm = ({ onSubmit, skipTokenRequest }) => {
|
|||
const errors: any = {};
|
||||
|
||||
if (!values.userName) {
|
||||
errors.userName = 'Required';
|
||||
errors.userName = t('Common.validation.required');
|
||||
}
|
||||
if (isMFA && !values.email) {
|
||||
errors.email = 'Required';
|
||||
errors.email = t('Common.validation.required');
|
||||
}
|
||||
if (!values.selectedHost) {
|
||||
errors.selectedHost = 'Required';
|
||||
errors.selectedHost = t('Common.validation.required');
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
@ -63,12 +65,12 @@ const RequestPasswordResetForm = ({ onSubmit, skipTokenRequest }) => {
|
|||
<form className="RequestPasswordResetForm" onSubmit={handleSubmit}>
|
||||
<div className="RequestPasswordResetForm-items">
|
||||
<div className="RequestPasswordResetForm-item">
|
||||
<Field label="Username" name="userName" component={InputField} autoComplete="username" disabled={isMFA} />
|
||||
<Field label={t('Common.label.username')} name="userName" component={InputField} autoComplete="username" disabled={isMFA} />
|
||||
</div>
|
||||
{isMFA ? (
|
||||
<div className="RequestPasswordResetForm-item">
|
||||
<Field label="Email" name="email" type="email" component={InputField} autoComplete="email" />
|
||||
<div>Server has multi-factor authentication enabled</div>
|
||||
<Field label={t('Common.label.email')} name="email" type="email" component={InputField} autoComplete="email" />
|
||||
<div>{ t('RequestPasswordResetForm.mfaEnabled') }</div>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="RequestPasswordResetForm-item selectedHost">
|
||||
|
|
@ -78,18 +80,18 @@ const RequestPasswordResetForm = ({ onSubmit, skipTokenRequest }) => {
|
|||
|
||||
{errorMessage && (
|
||||
<div className="RequestPasswordResetForm-item">
|
||||
<Typography color="error">Request password reset failed</Typography>
|
||||
<Typography color="error">{ t('RequestPasswordResetForm.error') }</Typography>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Button className="RequestPasswordResetForm-submit rounded tall" color="primary" variant="contained" type="submit">
|
||||
Request Reset Token
|
||||
{ t('RequestPasswordResetForm.request') }
|
||||
</Button>
|
||||
|
||||
<div>
|
||||
<Button color="primary" onClick={() => skipTokenRequest(form.getState().values.userName)}>
|
||||
I already have a reset token
|
||||
{ t('RequestPasswordResetForm.skipRequest') }
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"ResetPasswordForm": {
|
||||
"error": "Password reset failed",
|
||||
"label": {
|
||||
"reset": "Reset Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Form, Field } from 'react-final-form'
|
||||
import { OnChange } from 'react-final-form-listeners'
|
||||
import { OnChange } from 'react-final-form-listeners';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
|
@ -16,6 +17,7 @@ import { ServerTypes } from '../../store';
|
|||
|
||||
const ResetPasswordForm = ({ onSubmit, userName }) => {
|
||||
const [errorMessage, setErrorMessage] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useReduxEffect(() => {
|
||||
setErrorMessage(true);
|
||||
|
|
@ -25,25 +27,25 @@ const ResetPasswordForm = ({ onSubmit, userName }) => {
|
|||
const errors: any = {};
|
||||
|
||||
if (!values.userName) {
|
||||
errors.userName = 'Required';
|
||||
errors.userName = t('Common.validation.required');
|
||||
}
|
||||
if (!values.token) {
|
||||
errors.token = 'Required';
|
||||
errors.token = t('Common.validation.required');
|
||||
}
|
||||
|
||||
if (!values.newPassword) {
|
||||
errors.newPassword = 'Required';
|
||||
errors.newPassword = t('Common.validation.required');
|
||||
} else if (values.newPassword.length < 8) {
|
||||
errors.newPassword = 'Minimum of 8 characters required';
|
||||
errors.newPassword = t('Common.validation.minChars', { count: 8 });
|
||||
}
|
||||
|
||||
if (!values.passwordAgain) {
|
||||
errors.passwordAgain = 'Required';
|
||||
errors.passwordAgain = t('Common.validation.required');
|
||||
} else if (values.newPassword !== values.passwordAgain) {
|
||||
errors.passwordAgain = 'Passwords don\'t match'
|
||||
errors.passwordAgain = t('Common.validation.passwordsMustMatch');
|
||||
}
|
||||
if (!values.selectedHost) {
|
||||
errors.selectedHost = 'Required';
|
||||
errors.selectedHost = t('Common.validation.required');
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
@ -62,16 +64,34 @@ const ResetPasswordForm = ({ onSubmit, userName }) => {
|
|||
<form className='ResetPasswordForm' onSubmit={handleSubmit}>
|
||||
<div className='ResetPasswordForm-items'>
|
||||
<div className='ResetPasswordForm-item'>
|
||||
<Field label='Username' name='userName' component={InputField} autoComplete='username' disabled={!!userName} />
|
||||
<Field
|
||||
label={t('Common.label.username')}
|
||||
name='userName'
|
||||
component={InputField}
|
||||
autoComplete='username'
|
||||
disabled={!!userName}
|
||||
/>
|
||||
</div>
|
||||
<div className='ResetPasswordForm-item'>
|
||||
<Field label='Token' name='token' component={InputField} />
|
||||
<Field label={t('Common.label.token')} name='token' component={InputField} />
|
||||
</div>
|
||||
<div className='ResetPasswordForm-item'>
|
||||
<Field label='Password' name='newPassword' type='password' component={InputField} autoComplete='new-password' />
|
||||
<Field
|
||||
label={t('Common.label.password')}
|
||||
name='newPassword'
|
||||
type='password'
|
||||
component={InputField}
|
||||
autoComplete='new-password'
|
||||
/>
|
||||
</div>
|
||||
<div className='ResetPasswordForm-item'>
|
||||
<Field label='Password Again' name='passwordAgain' type='password' component={InputField} autoComplete='new-password' />
|
||||
<Field
|
||||
label={t('Common.label.passwordAgain')}
|
||||
name='passwordAgain'
|
||||
type='password'
|
||||
component={InputField}
|
||||
autoComplete='new-password'
|
||||
/>
|
||||
</div>
|
||||
<div className='ResetPasswordForm-item'>
|
||||
<Field name='selectedHost' component={KnownHosts} disabled />
|
||||
|
|
@ -79,12 +99,12 @@ const ResetPasswordForm = ({ onSubmit, userName }) => {
|
|||
|
||||
{errorMessage && (
|
||||
<div className='ResetPasswordForm-item'>
|
||||
<Typography color="error">Password reset failed</Typography>
|
||||
<Typography color="error">{ t('ResetPasswordForm.error') }</Typography>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Button className='ResetPasswordForm-submit rounded tall' color='primary' variant='contained' type='submit'>
|
||||
Reset Password
|
||||
{ t('ResetPasswordForm.label.reset') }
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue