Мне нужно вставить еще одно поле на странице входа в систему, поэтому еще одну запись в запросе на вход в JSON и, хотя мне удалось вставить это поле на странице входа в систему (как FormControl
с Select
с)У меня возникли проблемы при вставке выбранной опции в запрос JSON.
login.js
:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { propTypes, reduxForm, Field } from 'redux-form';
import { connect } from 'react-redux';
import compose from 'recompose/compose';
import Avatar from '@material-ui/core/Avatar';
import Button from '@material-ui/core/Button';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CircularProgress from '@material-ui/core/CircularProgress';
import TextField from '@material-ui/core/TextField';
import { withStyles } from '@material-ui/core/styles';
import LockIcon from '@material-ui/icons/Lock';
import { MenuItem, Select, FormControl, InputLabel } from '@material-ui/core';
import { Notification, translate, userLogin } from 'react-admin';
import InstitutionSelect from "./InstitutionSelect";
const styles = theme => ({
main: {
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
alignItems: 'center',
justifyContent: 'flex-start',
background: 'url(https://source.unsplash.com/random/1600x900)',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
},
card: {
minWidth: 300,
marginTop: '6em',
},
avatar: {
margin: '1em',
display: 'flex',
justifyContent: 'center',
},
icon: {
backgroundColor: theme.palette.secondary.main,
},
hint: {
marginTop: '1em',
display: 'flex',
justifyContent: 'center',
color: theme.palette.grey[500],
},
form: {
padding: '0 1em 1em 1em',
},
input: {
marginTop: '1em',
},
actions: {
padding: '0 1em 1em 1em',
},
});
// see http://redux-form.com/6.4.3/examples/material-ui/
const renderInput = ({
meta: { touched, error } = {},
input: { ...inputProps },
...props
}) => (
<TextField
error={!!(touched && error)}
helperText={touched && error}
{...inputProps}
{...props}
fullWidth
/>
);
class Login extends Component {
login = auth =>
this.props.userLogin(
auth,
this.props.location.state
? this.props.location.state.nextPathname
: '/'
);
render() {
const { classes, handleSubmit, isLoading, translate } = this.props;
return (
<div className={classes.main}>
<Card className={classes.card}>
<div className={classes.avatar}>
<Avatar className={classes.icon}>
<LockIcon />
</Avatar>
</div>
<form onSubmit={handleSubmit(this.login)}>
<div className={classes.form}>
<div className={classes.input}>
<InstitutionSelect
name="institution"
disabled={isLoading}
/>
</div>
<div className={classes.input}>
<Field
name="username"
component={renderInput}
label={translate('ra.auth.username')}
disabled={isLoading}
/>
</div>
<div className={classes.input}>
<Field
name="password"
component={renderInput}
label={translate('ra.auth.password')}
type="password"
disabled={isLoading}
/>
</div>
</div>
<CardActions className={classes.actions}>
<Button
variant="raised"
type="submit"
color="primary"
disabled={isLoading}
className={classes.button}
fullWidth
>
{isLoading && (
<CircularProgress size={25} thickness={2} />
)}
{translate('ra.auth.sign_in')}
</Button>
</CardActions>
</form>
</Card>
<Notification />
</div>
);
}
}
Login.propTypes = {
...propTypes,
authProvider: PropTypes.func,
classes: PropTypes.object,
previousRoute: PropTypes.string,
translate: PropTypes.func.isRequired,
// Insert Institution here?
userLogin: PropTypes.func.isRequired,
};
const mapStateToProps = state => ({ isLoading: state.admin.loading > 0 });
const enhance = compose(
translate,
reduxForm({
form: 'signIn',
validate: (values, props) => {
const errors = {};
const { translate } = props;
if (!values.institution) {
errors.institution = translate('ra.validation.required');
}
if (!values.username) {
errors.username = translate('ra.validation.required');
}
if (!values.password) {
errors.password = translate('ra.validation.required');
}
return errors;
},
}),
connect(
mapStateToProps,
{ userLogin }
),
withStyles(styles)
);
export default enhance(Login);
authProvider.js
:
import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_CHECK } from 'react-admin';
export default (type, params) => {
// called when the user attempts to log in
if (type === AUTH_LOGIN) {
const { institution, username, password } = params;
localStorage.setItem('username', username);
const request = new Request('194.117.29.119:3000/api/users/login', {
method: 'POST',
body: JSON.stringify({
institution,
username,
password
}),
headers: new Headers({ 'Content-Type': 'application/json' }),
})
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(({ token }) => {
localStorage.setItem('token', token);
});
}
// called when the user clicks on the logout button
if (type === AUTH_LOGOUT) {
localStorage.removeItem('username');
return Promise.resolve();
}
// called when the API returns an error
if (type === AUTH_ERROR) {
const { status } = params;
if (status === 401 || status === 403) {
localStorage.removeItem('username');
return Promise.reject();
}
return Promise.resolve();
}
// called when the user navigates to a new location
if (type === AUTH_CHECK) {
return localStorage.getItem('username')
? Promise.resolve()
: Promise.reject();
}
return Promise.reject('Unknown method');
};
InstitutionSelect.js
:
import React, { Component } from "react";
import MenuItem from "@material-ui/core/MenuItem";
import Select from "@material-ui/core/Select";
import { withStyles } from '@material-ui/core/styles';
import MuiThemeProvider from "@material-ui/core/styles/MuiThemeProvider";
import { InputLabel, FormControl } from "@material-ui/core";
const styles = theme => ({
fullWidth: {
width: "100%"
}
});
class InstitutionSelect extends Component {
constructor(props) {
super(props);
this.state = {
selectOptions: [
{
value: "blablabla",
id: "1"
},
],
selectedValue: "",
};
}
renderSelectOptions = () => {
return this.state.selectOptions.map((option, i) => (
<MenuItem key={option.id} value={option.id}>
{option.value}
</MenuItem>
));
};
handleChange = event => {
this.setState({ selectedValue: event.target.value });
};
render() {
const { classes } = this.props;
return (
<MuiThemeProvider>
<FormControl className={classes.fullWidth}>
<InputLabel>Institution</InputLabel>
<Select value={this.state.selectedValue} onChange={this.handleChange} >
{this.renderSelectOptions()}
</Select>
</FormControl>
</MuiThemeProvider>
);
}
}
export default withStyles(styles)(InstitutionSelect);