Show separate auth error messages

This commit is contained in:
Kimmo Puputti 2017-03-07 11:03:45 +02:00
parent 072a852c86
commit b70bda169e
4 changed files with 75 additions and 15 deletions

View file

@ -2,6 +2,7 @@ import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';
import { withRouter } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { Topbar } from '../../containers';
const scrollToTop = () => {
@ -21,12 +22,32 @@ class PageLayout extends Component {
}
render() {
const { className, title, children, authError } = this.props;
// TODO: use FlashMessages for authError
const { className, title, children, authInfoError, logoutError } = this.props;
// TODO: use FlashMessages for auth errors
/* eslint-disable no-console */
if (authInfoError && console && console.error) {
console.error(authInfoError);
}
if (logoutError && console && console.error) {
console.error(logoutError);
}
/* eslint-enable no-console */
return (
<div className={className}>
<Helmet title={title} />
{authError ? <p style={{ color: 'red' }}>Error in auth: {authError.message}</p> : null}
{authInfoError
? <div style={{ color: 'red' }}>
<FormattedMessage id="PageLayout.authInfoFailed" />
</div>
: null}
{logoutError
? <div style={{ color: 'red' }}>
<FormattedMessage id="PageLayout.logoutFailed" />
</div>
: null}
<Topbar />
<h1>{title}</h1>
{children}
@ -37,17 +58,21 @@ class PageLayout extends Component {
const { any, string, instanceOf, func } = PropTypes;
PageLayout.defaultProps = { className: '', children: null, authError: null };
PageLayout.defaultProps = { className: '', children: null, authInfoError: null, logoutError: null };
PageLayout.propTypes = {
className: string,
title: string.isRequired,
children: any,
authError: instanceOf(Error),
authInfoError: instanceOf(Error),
logoutError: instanceOf(Error),
// history.listen function from withRouter
listen: func.isRequired,
};
const mapStateToProps = state => ({ authError: state.Auth.error });
const mapStateToProps = state => ({
authInfoError: state.Auth.authInfoError,
logoutError: state.Auth.logoutError,
});
export default connect(mapStateToProps)(withRouter(PageLayout));

View file

@ -1,23 +1,44 @@
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { PageLayout, NamedLink, NamedRedirect } from '../../components';
import { LoginForm, SignUpForm } from '../../containers';
import { login } from '../../ducks/Auth.duck';
export const AuthenticationPageComponent = props => {
const { location, tab, isAuthenticated, onLoginSubmit, onSignUpSubmit } = props;
const {
location,
tab,
isAuthenticated,
loginError,
onLoginSubmit,
onSignUpSubmit,
} = props;
const isLogin = tab === 'login';
const from = location.state && location.state.from ? location.state.from : null;
const authRedirect = from ? <Redirect to={from} /> : <NamedRedirect name="LandingPage" />;
// TODO: use FlashMessages for auth errors
/* eslint-disable no-console */
if (loginError && console && console.error) {
console.error(loginError);
}
/* eslint-enable no-console */
return (
<PageLayout title={`Authentication page: ${tab} tab`}>
{isAuthenticated ? authRedirect : null}
{loginError
? <div style={{ color: 'red' }}>
<FormattedMessage id="AuthenticationPage.loginFailed" />
</div>
: null}
{from
? <p>
You must log in to view the page at
<FormattedMessage id="AuthenticationPage.loginRequiredFor" />
<code>{from}</code>
</p>
: null}
@ -29,19 +50,28 @@ export const AuthenticationPageComponent = props => {
);
};
AuthenticationPageComponent.defaultProps = { tab: 'signup' };
AuthenticationPageComponent.defaultProps = {
tab: 'signup',
authInfoError: null,
loginError: null,
logoutError: null,
};
const { object, oneOf, shape, bool, func } = PropTypes;
const { object, oneOf, shape, bool, func, instanceOf } = PropTypes;
AuthenticationPageComponent.propTypes = {
location: shape({ state: object }).isRequired,
tab: oneOf(['login', 'signup']),
isAuthenticated: bool.isRequired,
loginError: instanceOf(Error),
onLoginSubmit: func.isRequired,
onSignUpSubmit: func.isRequired,
};
const mapStateToProps = state => ({ isAuthenticated: state.Auth.isAuthenticated });
const mapStateToProps = state => ({
isAuthenticated: state.Auth.isAuthenticated,
loginError: state.Auth.loginError,
});
const mapDispatchToProps = dispatch => ({
onLoginSubmit: ({ email, password }) => dispatch(login(email, password)),

View file

@ -2,7 +2,9 @@ exports[`AuthenticationPageComponent matches snapshot 1`] = `
<Connect(withRouter(PageLayout))
title="Authentication page: signup tab">
<p>
You must log in to view the page at
<FormattedMessage
id="AuthenticationPage.loginRequiredFor"
values={Object {}} />
<code>
/protected
</code>

View file

@ -1,8 +1,11 @@
{
"landingpage.examplelink": "Show nice studios! (from json)",
"AuthenticationPage.loginFailed": "The email and password you entered did not match our records. Please double-check and try again.",
"AuthenticationPage.loginRequiredFor": "You must log in to view the page at",
"HeroSearchForm.placeholder": "Location search (soon)",
"HeroSearchForm.search": "Search",
"HeroSection.title": "Book Studiotime anywhere",
"HeroSection.subTitle": "The largest online community to rent music studios",
"ListingPage.loadingListingData": "Loading listing data"
"HeroSection.title": "Book Studiotime anywhere",
"ListingPage.loadingListingData": "Loading listing data",
"PageLayout.authInfoFailed": "Could not get authentication information.",
"PageLayout.logoutFailed": "Logout failed. Please try again."
}