Commit 38ae0956 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Improved loggin request consistency.

parent 749d76f5
Pipeline #42918 passed with stages
in 15 minutes and 41 seconds
import React from 'react'
import PropTypes from 'prop-types'
import { withStyles } from '@material-ui/core/styles'
import Typography from '@material-ui/core/Typography'
import { compose } from 'recompose'
import { Button, DialogTitle, DialogContent, DialogContentText, TextField, DialogActions,
Dialog, FormGroup, LinearProgress } from '@material-ui/core'
import { withApi } from './api'
class LoginLogout extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
api: PropTypes.object.isRequired,
user: PropTypes.object,
login: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired
}
static styles = theme => ({
root: {
display: 'flex',
alignItems: 'center',
'& p': {
marginRight: theme.spacing.unit * 2
}
},
errorText: {
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit
}
})
constructor(props) {
super(props)
this.handleLogout = this.handleLogout.bind(this)
this.handleChange = this.handleChange.bind(this)
}
state = {
loginDialogOpen: false,
userName: '',
password: '',
loggingIn: false,
failure: false
}
handleLoginDialogClosed(withLogin) {
this.setState({loginDialogOpen: false})
if (withLogin) {
this.setState({loggingIn: true})
this.props.login(this.state.userName, this.state.password, (success) => {
if (success) {
this.setState({loggingIn: false, loginDialogOpen: false, failure: false})
} else {
this.setState({loggingIn: false, failure: true, loginDialogOpen: true})
}
})
} else {
this.setState({loggingIn: false, failure: false, userName: '', password: '', loginDialogOpen: false})
}
}
handleChange = name => event => {
this.setState({
[name]: event.target.value
})
}
handleLogout() {
this.props.logout()
}
render() {
const { classes, user, ...otherProps } = this.props
const { loggingIn, failure } = this.state
if (user) {
return (
<div className={classes.root}>
<Typography color="inherit" variant="body1">
Welcome, {user.first_name} {user.last_name}
</Typography>
<Button className={classes.button} {...otherProps} onClick={this.handleLogout}>Logout</Button>
</div>
)
} else {
return (
<div className={classes.root}>
<Button className={classes.button} {...otherProps} onClick={() => this.setState({loginDialogOpen: true})}>Login</Button>
<Dialog
open={this.state.loginDialogOpen}
onClose={() => this.handleLoginDialogClosed(false)}
>
<DialogTitle>Login</DialogTitle>
<DialogContent>
<DialogContentText>
To login, please enter your email address and password. If you
do not have an account, please go to the nomad repository and
create one.
</DialogContentText>
{loggingIn ? <LinearProgress/> : ''}
{failure ? <DialogContentText className={classes.errorText} color="error">Wrong username or password!</DialogContentText> : ''}
<FormGroup>
<TextField
disabled={loggingIn}
autoFocus
margin="dense"
id="uaseName"
label="Email Address"
type="email"
fullWidth
value={this.state.userName}
onChange={this.handleChange('userName')}
/>
<TextField
disabled={loggingIn}
margin="dense"
id="password"
label="Password"
type="password"
fullWidth
value={this.state.password}
onChange={this.handleChange('password')}
/>
</FormGroup>
</DialogContent>
<DialogActions>
<Button onClick={() => this.handleLoginDialogClosed(false)} color="primary">
Cancel
</Button>
<Button onClick={() => this.handleLoginDialogClosed(true)} color="primary"
disabled={this.state.userName === '' || this.state.password === ''}
>
Login
</Button>
</DialogActions>
</Dialog>
</div>
)
}
}
}
export default compose(withApi(false), withStyles(LoginLogout.styles))(LoginLogout)
......@@ -23,12 +23,12 @@ import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'
import MenuIcon from '@material-ui/icons/Menu'
import { Link, withRouter } from 'react-router-dom'
import { compose } from 'recompose'
import { MuiThemeProvider, IconButton, Button, Checkbox, FormLabel, DialogTitle, DialogContent, DialogContentText, TextField, DialogActions, Dialog, FormGroup, LinearProgress } from '@material-ui/core'
import { MuiThemeProvider, IconButton, Checkbox, FormLabel } from '@material-ui/core'
import { genTheme, repoTheme, archiveTheme, encTheme, analyticsTheme } from '../config'
import { ErrorSnacks } from './errors'
import classNames from 'classnames'
import { HelpContext } from './help'
import { withApi } from './api'
import LoginLogout from './LoginLogout'
const drawerWidth = 200
......@@ -56,145 +56,6 @@ const toolbarThemes = {
'/dev': genTheme
}
class LoginLogoutComponent extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
api: PropTypes.object.isRequired,
user: PropTypes.object,
login: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired
}
static styles = theme => ({
root: {
display: 'flex',
alignItems: 'center',
'& p': {
marginRight: theme.spacing.unit * 2
},
'& button': {
borderColor: theme.palette.getContrastText(theme.palette.primary.main),
marginRight: theme.spacing.unit * 4
}
},
errorText: {
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit
}
})
constructor(props) {
super(props)
this.handleLogout = this.handleLogout.bind(this)
this.handleChange = this.handleChange.bind(this)
}
state = {
loginDialogOpen: false,
userName: '',
password: '',
loggingIn: false,
failure: false
}
handleLoginDialogClosed(withLogin) {
this.setState({loginDialogOpen: false})
if (withLogin) {
this.setState({loggingIn: true})
this.props.login(this.state.userName, this.state.password, (success) => {
if (success) {
this.setState({loggingIn: false, loginDialogOpen: false, failure: false})
} else {
this.setState({loggingIn: false, failure: true, loginDialogOpen: true})
}
})
} else {
this.setState({loggingIn: false, failure: false, userName: '', password: '', loginDialogOpen: false})
}
}
handleChange = name => event => {
this.setState({
[name]: event.target.value
})
}
handleLogout() {
this.props.logout()
}
render() {
const { classes, user } = this.props
const { loggingIn, failure } = this.state
if (user) {
return (
<div className={classes.root}>
<Typography color="inherit" variant="body1">
Welcome, {user.first_name} {user.last_name}
</Typography>
<Button color="inherit" variant="outlined" onClick={this.handleLogout}>Logout</Button>
</div>
)
} else {
return (
<div className={classes.root}>
<Button color="inherit" variant="outlined" onClick={() => this.setState({loginDialogOpen: true})}>Login</Button>
<Dialog
open={this.state.loginDialogOpen}
onClose={() => this.handleLoginDialogClosed(false)}
>
<DialogTitle>Login</DialogTitle>
<DialogContent>
<DialogContentText>
To login, please enter your email address and password. If you
do not have an account, please go to the nomad repository and
create one.
</DialogContentText>
{loggingIn ? <LinearProgress/> : ''}
{failure ? <DialogContentText className={classes.errorText} color="error">Wrong username or password!</DialogContentText> : ''}
<FormGroup>
<TextField
disabled={loggingIn}
autoFocus
margin="dense"
id="uaseName"
label="Email Address"
type="email"
fullWidth
value={this.state.userName}
onChange={this.handleChange('userName')}
/>
<TextField
disabled={loggingIn}
margin="dense"
id="password"
label="Password"
type="password"
fullWidth
value={this.state.password}
onChange={this.handleChange('password')}
/>
</FormGroup>
</DialogContent>
<DialogActions>
<Button onClick={() => this.handleLoginDialogClosed(false)} color="primary">
Cancel
</Button>
<Button onClick={() => this.handleLoginDialogClosed(true)} color="primary"
disabled={this.state.userName === '' || this.state.password === ''}
>
Login
</Button>
</DialogActions>
</Dialog>
</div>
)
}
}
}
const LoginLogout = compose(withApi(false), withStyles(LoginLogoutComponent.styles))(LoginLogoutComponent)
class Navigation extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
......@@ -301,6 +162,10 @@ class Navigation extends React.Component {
},
barSelect: {
color: `${theme.palette.getContrastText(theme.palette.primary.main)} !important`
},
barButton: {
borderColor: theme.palette.getContrastText(theme.palette.primary.main),
marginRight: theme.spacing.unit * 4
}
})
......@@ -446,7 +311,7 @@ class Navigation extends React.Component {
{selected(toolbarTitles)}
</Typography>
<div className={classes.barActions}>
<LoginLogout />
<LoginLogout variant="outlined" color="inherit" classes={{button: classes.barButton}} />
<FormLabel className={classes.barSelect} >Show help</FormLabel>
<HelpContext.Consumer>{
help => (
......
......@@ -4,7 +4,8 @@ import { withErrors } from './errors'
import { UploadRequest } from '@navjobs/upload'
import Swagger from 'swagger-client'
import { apiBase } from '../config'
import { Typography } from '@material-ui/core'
import { Typography, FormGroup, FormLabel, Button, withStyles } from '@material-ui/core'
import LoginLogout from './LoginLogout'
const ApiContext = React.createContext()
......@@ -325,6 +326,36 @@ export class ApiProvider extends React.Component {
}
}
class LoginRequiredUnstyled extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired
}
static styles = theme => ({
root: {
display: 'flex',
alignItems: 'center',
'& p': {
marginRight: theme.spacing.unit * 2
}
}
})
render() {
const {classes} = this.props
return (
<div className={classes.root}>
<Typography>
To upload data, you must have a nomad account and you must be logged in.
</Typography>
<LoginLogout variant="outlined" color="primary"/>
</div>
)
}
}
const LoginRequired = withStyles(LoginRequiredUnstyled.styles)(LoginRequiredUnstyled)
export function withApi(loginRequired) {
return function(Component) {
function WithApiComponent(props) {
......@@ -335,7 +366,7 @@ export function withApi(loginRequired) {
? <Component
{...props} api={apiContext.api} user={apiContext.user}
login={apiContext.login} logout={apiContext.logout} />
: <Typography color="error">Please login to use this functionality</Typography>
: <LoginRequired />
)}
</ApiContext.Consumer>
)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment