You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.7 KiB
TypeScript
162 lines
5.7 KiB
TypeScript
// Copyright (C) 2020-2022 Intel Corporation
|
|
// Copyright (C) 2022 CVAT.ai Corporation
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import React, { useCallback, useState } from 'react';
|
|
import Form from 'antd/lib/form';
|
|
import Button from 'antd/lib/button';
|
|
import Input from 'antd/lib/input';
|
|
import Icon from '@ant-design/icons';
|
|
import {
|
|
BackArrowIcon, ClearIcon,
|
|
} from 'icons';
|
|
import { Col, Row } from 'antd/lib/grid';
|
|
import Title from 'antd/lib/typography/Title';
|
|
import Text from 'antd/lib/typography/Text';
|
|
import { Link } from 'react-router-dom';
|
|
|
|
export interface LoginData {
|
|
credential: string;
|
|
password: string;
|
|
}
|
|
|
|
interface Props {
|
|
renderResetPassword: boolean;
|
|
fetching: boolean;
|
|
socialAuthentication: JSX.Element | null;
|
|
onSubmit(loginData: LoginData): void;
|
|
}
|
|
|
|
function LoginFormComponent(props: Props): JSX.Element {
|
|
const {
|
|
fetching, onSubmit, renderResetPassword, socialAuthentication,
|
|
} = props;
|
|
const [form] = Form.useForm();
|
|
const [credential, setCredential] = useState('');
|
|
|
|
const inputReset = useCallback((name: string):void => {
|
|
form.setFieldsValue({ [name]: '' });
|
|
}, [form]);
|
|
const forgotPasswordLink = (
|
|
<Col className='cvat-credentials-link'>
|
|
<Text strong>
|
|
<Link to={credential.includes('@') ?
|
|
`/auth/password/reset?credential=${credential}` : '/auth/password/reset'}
|
|
>
|
|
Forgot password?
|
|
</Link>
|
|
</Text>
|
|
</Col>
|
|
);
|
|
return (
|
|
<div className='cvat-login-form-wrapper'>
|
|
<Row justify='space-between' className='cvat-credentials-navigation'>
|
|
{
|
|
credential && (
|
|
<Col>
|
|
<Icon
|
|
component={BackArrowIcon}
|
|
onClick={() => {
|
|
setCredential('');
|
|
form.setFieldsValue({ credential: '' });
|
|
}}
|
|
/>
|
|
</Col>
|
|
)
|
|
}
|
|
{
|
|
!credential && (
|
|
<Row>
|
|
<Col className='cvat-credentials-link'>
|
|
<Text strong>
|
|
New user?
|
|
<Link to='/auth/register'>Create an account</Link>
|
|
</Text>
|
|
</Col>
|
|
</Row>
|
|
)
|
|
}
|
|
{
|
|
renderResetPassword && forgotPasswordLink
|
|
}
|
|
</Row>
|
|
<Col>
|
|
<Title level={2}> Sign in </Title>
|
|
</Col>
|
|
<Form
|
|
className={`cvat-login-form ${credential ? 'cvat-login-form-extended' : ''}`}
|
|
form={form}
|
|
onFinish={(loginData: LoginData) => {
|
|
onSubmit(loginData);
|
|
}}
|
|
>
|
|
<Form.Item
|
|
className='cvat-credentials-form-item'
|
|
name='credential'
|
|
>
|
|
<Input
|
|
autoComplete='credential'
|
|
placeholder='enter your email or username'
|
|
prefix={<Text>Email or username</Text>}
|
|
suffix={(
|
|
credential && (
|
|
<Icon
|
|
component={ClearIcon}
|
|
onClick={() => {
|
|
setCredential('');
|
|
inputReset('credential');
|
|
}}
|
|
/>
|
|
)
|
|
)}
|
|
onChange={(event) => {
|
|
const { value } = event.target;
|
|
setCredential(value);
|
|
if (!value) inputReset('credential');
|
|
}}
|
|
/>
|
|
</Form.Item>
|
|
{
|
|
credential && (
|
|
<Form.Item
|
|
className='cvat-credentials-form-item'
|
|
name='password'
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please specify a password',
|
|
},
|
|
]}
|
|
>
|
|
<Input.Password
|
|
autoComplete='current-password'
|
|
placeholder='enter your password'
|
|
prefix={
|
|
<Text>Password</Text>
|
|
}
|
|
/>
|
|
</Form.Item>
|
|
)
|
|
}
|
|
{
|
|
credential || !socialAuthentication ? (
|
|
<Form.Item>
|
|
<Button
|
|
className='cvat-credentials-action-button'
|
|
loading={fetching}
|
|
disabled={!credential}
|
|
htmlType='submit'
|
|
>
|
|
Next
|
|
</Button>
|
|
</Form.Item>
|
|
) : socialAuthentication
|
|
}
|
|
</Form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default React.memo(LoginFormComponent);
|