[NEW-UI] Add basic login page (#592)

Refactoring and basic login page
main
Artyom Zankevich 7 years ago committed by Boris Sekachev
parent 3a91571bbc
commit 5dd4f3981e

@ -1,13 +1,33 @@
export const login = (isAuthenticated: boolean) => (dispatch: any) => {
export const login = () => (dispatch: any) => {
dispatch({
type: 'LOGIN',
payload: isAuthenticated,
});
}
export const logout = (isAuthenticated: boolean) => (dispatch: any) => {
export const loginSuccess = () => (dispatch: any) => {
dispatch({
type: 'LOGOUT',
payload: isAuthenticated,
type: 'LOGIN_SUCCESS',
});
}
export const loginError = (error = {}) => (dispatch: any) => {
dispatch({
type: 'LOGIN_ERROR',
payload: error,
});
}
export const loginAsync = (username: string, password: string) => {
return (dispatch: any) => {
dispatch(login());
return (window as any).cvat.server.login(username, password).then(
(authenticated: any) => {
dispatch(loginSuccess());
},
(error: any) => {
dispatch(loginError(error));
},
);
};
}

@ -1,18 +1,68 @@
export const getTasks = (tasks: []) => (dispatch: any) => {
export const getTasks = () => (dispatch: any, getState: any) => {
dispatch({
type: 'GET_TASKS',
});
}
export const getTasksSuccess = (tasks: []) => (dispatch: any, getState: any) => {
dispatch({
type: 'GET_TASKS_SUCCESS',
payload: tasks,
});
}
export const getTasksError = (error: {}) => (dispatch: any, getState: any) => {
dispatch({
type: 'GET_TASKS_ERROR',
payload: error,
});
}
export const deleteTask = () => (dispatch: any, getState: any) => {
dispatch({
type: 'DELETE_TASK',
});
}
export const deleteTaskSuccess = () => (dispatch: any, getState: any) => {
dispatch({
type: 'DELETE_TASK_SUCCESS',
});
}
export const deleteTaskError = (error: {}) => (dispatch: any, getState: any) => {
dispatch({
type: 'DELETE_TASK_ERROR',
payload: error,
});
}
export const getTasksAsync = (queryObject = {}) => {
return (dispatch: any) => {
dispatch(getTasks());
return (window as any).cvat.tasks.get(queryObject).then(
(tasks: any) => {
dispatch(getTasks(tasks));
dispatch(getTasksSuccess(tasks));
},
(error: any) => {
dispatch(getTasksError(error));
},
);
};
}
export const deleteTaskAsync = (task: any) => {
return (dispatch: any) => {
dispatch(deleteTask());
return task.delete().then(
(deleted: any) => {
dispatch(deleteTaskSuccess());
dispatch(getTasksAsync());
},
(error: any) => {
console.log(error);
dispatch(deleteTaskError(error));
},
);
};

@ -2,24 +2,23 @@ import React, { PureComponent } from 'react';
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { login, logout } from '../../actions/auth.actions';
import { loginAsync } from '../../actions/auth.actions';
import Dashboard from '../dashboard/dashboard';
import Login from '../login/login';
import NotFound from '../not-found/not-found';
import './app.scss';
declare const window: any;
class App extends PureComponent<any, any> {
componentDidMount() {
window.cvat.server.login(process.env.REACT_APP_LOGIN, process.env.REACT_APP_PASSWORD).then(
(_response: any) => {
this.props.dispatch(login(true));
},
(_error: any) => {
this.props.dispatch(logout(false));
}
// TODO: remove when proper login flow (with router) will be implemented
this.props.dispatch(
loginAsync(
process.env.REACT_APP_LOGIN as string,
process.env.REACT_APP_PASSWORD as string,
),
);
}
@ -29,6 +28,7 @@ class App extends PureComponent<any, any> {
<Switch>
<Redirect path="/" exact to="/dashboard" />
<Route path="/dashboard" component={ Dashboard } />
<Route path="/login" component={ Login } />
<Route component={ NotFound } />
</Switch>
</Router>

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getTasksAsync } from '../../../actions/tasks.actions';
import { deleteTaskAsync } from '../../../actions/tasks.actions';
import { Layout, Empty, Button, Modal, Col, Row } from 'antd';
import Title from 'antd/lib/typography/Title';
@ -119,13 +119,8 @@ class DashboardContent extends Component<any, any> {
okText: 'Yes',
okType: 'danger',
centered: true,
onOk(closeFunction: Function) {
return task.delete().then(
() => {
self.props.dispatch(getTasksAsync());
closeFunction();
},
);
onOk() {
return self.props.dispatch(deleteTaskAsync(task));
},
cancelText: 'No',
onCancel() {

@ -0,0 +1,10 @@
.login-form {
display: flex;
flex-direction: column;
justify-content: center;
height: 100vh;
&__title {
}
}

@ -0,0 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Login from './login';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<Login />, div);
ReactDOM.unmountComponentAtNode(div);
});

@ -0,0 +1,76 @@
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { loginAsync } from '../../actions/auth.actions';
import { Button, Icon, Input, Form, Col, Row } from 'antd';
import './login.scss';
import Title from 'antd/lib/typography/Title';
class LoginForm extends PureComponent<any, any> {
render() {
const { getFieldDecorator } = this.props.form;
return (
<Row type="flex" justify="center" align="middle">
<Col span={4}>
<Form className="login-form" onSubmit={ this.onSubmit }>
<Title className="login-form__title">Login</Title>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please enter your username!' }],
})(
<Input
prefix={ <Icon type="user" /> }
type="text"
name="username"
placeholder="Username"
/>,
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please enter your password!' }],
})(
<Input
prefix={ <Icon type="lock" /> }
type="password"
name="password"
placeholder="Password"
/>,
)}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={ this.props.isFetching }>
Log in
</Button>
</Form.Item>
Have not registered yet? <a href="/register">Register here.</a>
</Form>
</Col>
</Row>
);
}
private onSubmit = (event: any) => {
event.preventDefault();
this.props.form.validateFields((error: any, values: any) => {
if (!error) {
this.props.dispatch(loginAsync(values.username, values.password))
}
});
}
}
const mapStateToProps = (state: any) => {
return state.authContext;
};
export default Form.create()(connect(mapStateToProps)(LoginForm));

@ -1,9 +1,27 @@
export default (state = {}, action: any) => {
export default (
state = {
isAuthenticated: false,
isFetching: false,
error: null,
},
action: any,
) => {
switch (action.type) {
case 'LOGIN':
return { ...state, isAuthenticated: action.payload };
case 'LOGOUT':
return { ...state, isAuthenticated: action.payload };
return Object.assign({}, state, {
isFetching: true,
});
case 'LOGIN_SUCCESS':
return Object.assign({}, state, {
isFetching: false,
isAuthenticated: true,
});
case 'LOGIN_ERROR':
return Object.assign({}, state, {
isFetching: false,
isAuthenticated: false,
error: action.payload,
});
default:
return state;
}

@ -1,11 +1,16 @@
export default (state = { searchQuery: '', currentPage: 1 }, action: any) => {
export default (
state = {
searchQuery: '',
currentPage: 1
},
action: any,
) => {
switch (action.type) {
case 'FILTER_TASKS':
return {
...state,
return Object.assign({}, state, {
searchQuery: action.payload.search,
currentPage: action.payload.page,
};
});
default:
return state;
}

@ -1,11 +1,44 @@
export default (state: any = { tasks: [], tasksCount: 0 }, action: any) => {
export default (
state: any = {
tasks: [],
tasksCount: 0,
isFetching: false,
error: null,
},
action: any,
) => {
switch (action.type) {
case 'GET_TASKS':
return {
...state,
return Object.assign({}, state, {
isFetching: true,
});
case 'GET_TASKS_SUCCESS':
return Object.assign({}, state, {
isFetching: false,
tasks: Array.from(action.payload.values()),
tasksCount: action.payload.count,
};
});
case 'GET_TASKS_ERROR':
return Object.assign({}, state, {
isFetching: false,
error: action.payload,
});
case 'DELETE_TASK':
return Object.assign({}, state, {
isFetching: true,
});
case 'DELETE_TASK_SUCCESS':
return Object.assign({}, state, {
isFetching: false,
});
case 'DELETE_TASK_ERROR':
return Object.assign({}, state, {
isFetching: false,
error: action.payload,
});
default:
return state;
}

Loading…
Cancel
Save