Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(ui): add login, register pages
  • Loading branch information
Vikort committed Dec 2, 2021
commit e4ed722b6e1622fa34c722c76285f23d4b637661
23 changes: 23 additions & 0 deletions web/frontend/src/ui/AppHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import {AppBar, Box, Button, Toolbar, Typography} from "@material-ui/core";

class HeaderImpl extends React.Component {
render() {
return (
<Box sx={{ flexGrow: 1, height: '6%'}}>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is height in %?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because with this height value, Header looks normal.

<AppBar position="relative">
<Toolbar>
<Typography variant="h6" component="div" style={{flex: 1}}>
OSTIS Neo4j Platform
</Typography>
<Button component={NavLink} to="/login" color="inherit">Login</Button>
</Toolbar>
</AppBar>
</Box>
);
}
}

export const AppHeader = connect()(HeaderImpl);
32 changes: 32 additions & 0 deletions web/frontend/src/ui/AppMain.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Redirect } from 'react-router';
import { Route, Switch } from 'react-router-dom';
import { Login } from './LoginPage';
import {Register} from "./RegisterPage";
import {Loader} from "./loader";

class MainImpl extends React.Component {
render() {
return (
<div className="main">
<Switch>
<Route path="/" exact>
<Redirect to="/login" />
</Route>
<Route path="/login">
<Login />
</Route>
<Route path="/register">
<Register />
</Route>
<Route path="/loader">
<Loader msg='Loading...'/>
</Route>
</Switch>
</div>
);
}
}

export const AppMain = connect()(MainImpl);
177 changes: 177 additions & 0 deletions web/frontend/src/ui/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import {NavLink, useHistory} from "react-router-dom";
import {Box, Button, Container, TextField, Typography} from "@material-ui/core";
import * as React from "react";
import {connect} from "react-redux";
import * as store from '../store';

interface LoginErrors {
login: string,
password: string
}

export interface LoginProps {
services: store.services.Services,
login: string;
password: string;
online: boolean;
errors: LoginErrors
}

function mapStateToProps(state: store.Store): LoginProps {
return {
services: state.services,
login: state.user.login,
password: state.user.password,
online: state.user.online,
errors: {login: state.errors.erLoginMsg, password: state.errors.erPasswordMsg}
};
}

const LoginImpl: React.FC<LoginProps> = (props: LoginProps) => {
const history = useHistory()
const login = props.login
const password = props.password
const services = props.services
const errors = props.errors


async function postRequest(data: object) {
const url: string = "http://127.0.0.1:5000/users/login"
const doPost = async () => {
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": "Bearer dev",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
if (response.ok) {
return Promise.resolve(response.json())
} else {
return Promise.reject("Bad login or password")
}
}

doPost().then((response) => {
if (response["message"] === undefined) {
services.authService.updateUser(
{
// id: response['id'],
// firstName: response['first_name'],
// lastName: response['last_name'],
access_token: response['access_token'],
online: true,
}
)
history.push('/loader');
}
}).catch((e) => {
services.authService.updateErrors({
erLoginMsg: e,
erPasswordMsg: e
})
})
}

const handleSubmit = (event) => {
postRequest({
'username': login,
'password': password
})
event.preventDefault()
}

const handleChange = (event) => {
if (event.target.name == "login") {
services.authService.validateLogin(event.target.value)
services.authService.updateUser({
login: event.target.value
})
} else if (event.target.name == "password") {
services.authService.validatePassword(event.target.value)
services.authService.updateUser({
password: event.target.value
})
}
}

return (
<Box
sx={{
backgroundColor: 'background.default',
display: 'flex',
flexDirection: 'column',
height: '94%',
justifyContent: 'center'
} as React.CSSProperties}
>
<Container maxWidth="sm">
<form onSubmit={handleSubmit} autoComplete='off'>
<Box sx={{mb: 3}}>
<Typography
color="textPrimary"
variant="h2"
>
Sign in
</Typography>
</Box>
<TextField
error={Boolean(errors.login)}
fullWidth
helperText={errors.login}
label="Login"
margin="normal"
name="login"
onChange={handleChange}
value={login}
variant="outlined"
/>
<TextField
error={Boolean(errors.password)}
fullWidth
helperText={errors.password}
label="Password"
margin="normal"
name="password"
onChange={handleChange}
type="password"
value={password}
variant="outlined"
/>
<Box sx={{py: 2}}>
<Button
color="primary"
fullWidth
size="large"
type="submit"
variant="contained"
>
Sign in
</Button>
</Box>
<Typography
color="textSecondary"
variant="body1"
>
Don&apos;t have an account?
{' '}
<NavLink to="/register" variant="h6" underline="hover" onClick={() => {
services.authService.updateUser({
firstName: "",
lastName: "",
login: "",
password: "",
online: false,
})
}}>
Sign up
</NavLink>
</Typography>
</form>
</Container>
</Box>
);
};

export const Login = connect(mapStateToProps)(LoginImpl);
Loading