diff --git a/client/src/app-components/password-recovery.js b/client/src/app-components/password-recovery.js index 2a15f66d..4541a5fc 100644 --- a/client/src/app-components/password-recovery.js +++ b/client/src/app-components/password-recovery.js @@ -2,24 +2,32 @@ import React from 'react'; import classNames from 'classnames'; import i18n from 'lib-app/i18n'; +import API from 'lib-app/api-call'; import Form from 'core-components/form'; import FormField from 'core-components/form-field'; import Widget from 'core-components/widget'; import Button from 'core-components/button'; import SubmitButton from 'core-components/submit-button'; +import Message from 'core-components/message'; class PasswordRecovery extends React.Component { static propTypes = { recoverSent: React.PropTypes.bool, formProps: React.PropTypes.object, - onBackToLoginClick: React.PropTypes.func + onBackToLoginClick: React.PropTypes.func, + renderLogo: React.PropTypes.bool + }; + + static defaultProps = { + renderLogo: false }; render() { return ( - + + {this.renderLogo()}
@@ -36,6 +44,16 @@ class PasswordRecovery extends React.Component { ); } + renderLogo() { + let logo = null; + + if (this.props.renderLogo) { + logo = (
OpenSupports Login Panel
); + } + + return logo; + } + renderRecoverStatus() { let status = null; diff --git a/client/src/app-components/password-recovery.scss b/client/src/app-components/password-recovery.scss index cf33ab9f..85bf3d33 100644 --- a/client/src/app-components/password-recovery.scss +++ b/client/src/app-components/password-recovery.scss @@ -6,6 +6,11 @@ text-align: left; } + &__content { + margin: 0 auto; + padding: 40px; + } + &__forgot-password { margin-top: 20px; } @@ -13,4 +18,9 @@ &__message { margin-top: 18px; } + + &__image { + width: 365px; + margin-bottom: 30px; + } } diff --git a/client/src/app/admin/admin-login-page.js b/client/src/app/admin/admin-login-page.js index 358ba8f6..72e5daba 100644 --- a/client/src/app/admin/admin-login-page.js +++ b/client/src/app/admin/admin-login-page.js @@ -1,11 +1,13 @@ import React from 'react'; import _ from 'lodash'; +import classNames from 'classnames'; import {connect} from 'react-redux'; import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; import SessionActions from 'actions/session-actions'; +import PasswordRecovery from 'app-components/password-recovery.js'; import Button from 'core-components/button'; import Form from 'core-components/form'; import FormField from 'core-components/form-field'; @@ -17,31 +19,45 @@ import WidgetTransition from 'core-components/widget-transition'; class AdminLoginPage extends React.Component { state = { - sideToShow: 'front' + sideToShow: 'front', + loginFormErrors: {}, + recoverFormErrors: {}, + recoverSent: false, + loadingLogin: false, + loadingRecover: false }; + + componentDidUpdate(prevProps) { + if (!prevProps.session.failed && this.props.session.failed) { + this.refs.loginForm.refs.password.focus(); + } + } render() { - return ( - - {this.renderLogin()} - {this.renderPasswordRecovery()} - - ) + return ( +
+ + {this.renderLogin()} + {this.renderPasswordRecovery()} + +
+ ); } renderLogin() { return ( -
+
OpenSupports Admin Panel
- + {i18n('LOG_IN')}
- {this.renderMessage()} + {this.renderRecoverStatus()} + {this.renderErrorStatus()} @@ -49,48 +65,139 @@ class AdminLoginPage extends React.Component {
); } - + renderPasswordRecovery() { return ( -
- -
OpenSupports Admin Panel
-
-
- - - {i18n('LOG_IN')} - -
- {this.renderMessage()} -
+
+
); } - - onForgotPasswordClick() { - this.setState({sideToShow: 'back'}); + + renderRecoverStatus() { + let status = null; + + if (this.state.recoverSent) { + status = ( + + {i18n('RECOVER_SENT')} + + ); + } + + return status; } - renderMessage() { - let message = null; + renderErrorStatus() { + let status = null; - if(this.props.session.failed) { - message = ( + if (this.props.session.failed) { + status = ( {i18n('EMAIL_OR_PASSWORD')} ); } - return message; + return status; } - onSubmit(formState) { + getLoginFormProps() { + return { + loading: this.props.session.pending, + className: 'admin-login-page__form', + ref: 'loginForm', + onSubmit: this.onLoginFormSubmit.bind(this), + errors: this.getLoginFormErrors(), + onValidateErrors: this.onLoginFormErrorsValidation.bind(this) + }; + } + + getRecoverFormProps() { + return { + loading: this.state.loadingRecover, + className: 'admin-login-page__form', + ref: 'recoverForm', + onSubmit: this.onForgotPasswordSubmit.bind(this), + errors: this.state.recoverFormErrors, + onValidateErrors: this.onRecoverFormErrorsValidation.bind(this) + }; + } + + getLoginFormErrors() { + let errors = _.extend({}, this.state.loginFormErrors); + + if (this.props.session.failed) { + if (this.props.session.failMessage === 'INVALID_CREDENTIALS') { + errors.password = i18n('ERROR_PASSWORD'); + } else if (this.props.session.failMessage === 'UNVERIFIED_USER') { + errors.email = i18n('UNVERIFIED_EMAIL'); + } + } + + return errors; + } + + onLoginFormSubmit(formState) { this.props.dispatch(SessionActions.login(_.extend({}, formState, { staff: true }))); } + + onForgotPasswordSubmit(formState) { + this.setState({ + loadingRecover: true, + recoverSent: false + }); + + API.call({ + path: '/user/send-recover-password', + data: _.extend({}, formState, {staff: true}) + }).then(this.onRecoverPasswordSent.bind(this)).catch(this.onRecoverPasswordFail.bind(this)); + } + + onLoginFormErrorsValidation(errors) { + this.setState({ + loginFormErrors: errors + }); + } + + onRecoverFormErrorsValidation(errors) { + this.setState({ + recoverFormErrors: errors + }); + } + + onForgotPasswordClick() { + this.setState({ + sideToShow: 'back' + }); + } + + onBackToLoginClick() { + this.setState({ + sideToShow: 'front', + recoverSent: false + }); + } + + onRecoverPasswordSent() { + this.setState({ + loadingRecover: false, + recoverSent: true + }); + } + + onRecoverPasswordFail() { + this.setState({ + loadingRecover: false, + recoverFormErrors: { + email: i18n('EMAIL_NOT_EXIST') + } + }, function () { + this.refs.recoverForm.refs.email.focus(); + }.bind(this)); + } } export default connect((store) => { diff --git a/client/src/app/admin/admin-login-page.scss b/client/src/app/admin/admin-login-page.scss index 57b07631..4f9f6b14 100644 --- a/client/src/app/admin/admin-login-page.scss +++ b/client/src/app/admin/admin-login-page.scss @@ -2,6 +2,12 @@ .admin-login-page { display: flex; + margin: 0 auto; + width: 446px; + + &__container { + height: 361px; + } &__content { margin: 0 auto; @@ -21,4 +27,4 @@ &__error { margin-top: 30px; } -} \ No newline at end of file +} diff --git a/client/src/core-components/widget-transition.js b/client/src/core-components/widget-transition.js index 3ecfd4a3..218f392c 100644 --- a/client/src/core-components/widget-transition.js +++ b/client/src/core-components/widget-transition.js @@ -23,7 +23,6 @@ class WidgetTransition extends React.Component { componentDidUpdate(prevProps) { if (prevProps.sideToShow != this.props.sideToShow && this.primaryWidget && this.secondaryWidget) { - console.log("The component was updated!"); this.moveFocusToCurrentSide(); } }