From dae244bee2b2e4cf28ff1a9bbc9720a866b96fa7 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 1 Aug 2016 16:15:52 -0300 Subject: [PATCH] Ivan - Add SubmitButton with loading [skip ci] --- .../main-home/main-home-page-login-widget.js | 48 +++++++++++++-- .../main-recover-password-page.js | 19 ++++-- client/src/core-components/button.js | 5 +- client/src/core-components/button.scss | 4 ++ client/src/core-components/form.js | 12 ++++ client/src/core-components/submit-button.js | 58 +++++++++++++++++++ client/src/core-components/submit-button.scss | 46 +++++++++++++++ client/src/data/fixtures/user-fixtures.js | 4 +- client/src/stores/user-store.js | 1 - 9 files changed, 180 insertions(+), 17 deletions(-) create mode 100644 client/src/core-components/submit-button.js create mode 100644 client/src/core-components/submit-button.scss diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index ff8cf267..54c8ca38 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -8,6 +8,7 @@ import UserStore from 'stores/user-store'; import focus from 'lib-core/focus'; import i18n from 'lib-app/i18n'; +import SubmitButton from 'core-components/submit-button'; import Button from 'core-components/button'; import Form from 'core-components/form'; import Input from 'core-components/input'; @@ -25,7 +26,8 @@ let MainHomePageLoginWidget = React.createClass({ sideToShow: 'front', loginFormErrors: {}, recoverFormErrors: {}, - recoverSent: false + recoverSent: false, + loading: false }; }, @@ -41,14 +43,14 @@ let MainHomePageLoginWidget = React.createClass({ renderLogin() { return ( -
+
- + LOG IN
+ {i18n('RECOVER_PASSWORD')} + {i18n('SUBMIT')} {this.renderRecoverStatus()} @@ -74,16 +75,22 @@ const MainRecoverPasswordPage = React.createClass({ recoverData.email = this.props.location.query.email; UserActions.recoverPassword(formState); + this.setState({ + loading: true + }); }, onUserStoreChanged(event) { if (event === 'VALID_RECOVER') { + setTimeout(CommonActions.loggedOut, 2000); this.setState({ - recoverStatus: 'valid' + recoverStatus: 'valid', + loading: false }); } else { this.setState({ - recoverStatus: 'invalid' + recoverStatus: 'invalid', + loading: false }); } } diff --git a/client/src/core-components/button.js b/client/src/core-components/button.js index f2cfbf5e..8b30ded0 100644 --- a/client/src/core-components/button.js +++ b/client/src/core-components/button.js @@ -6,7 +6,7 @@ import classNames from 'classnames'; // CORE LIBS import callback from 'lib-core/callback'; -let Button = React.createClass({ +const Button = React.createClass({ contextTypes: { router: React.PropTypes.object @@ -54,7 +54,8 @@ let Button = React.createClass({ getClass() { let classes = { - 'button': true + 'button': true, + 'button_disabled': this.props.disabled }; classes['button-' + this.props.type] = (this.props.type); diff --git a/client/src/core-components/button.scss b/client/src/core-components/button.scss index e177b896..974cf04e 100644 --- a/client/src/core-components/button.scss +++ b/client/src/core-components/button.scss @@ -27,4 +27,8 @@ outline: none; } } + + &_disabled { + background-color: #ec9696; + } } \ No newline at end of file diff --git a/client/src/core-components/form.js b/client/src/core-components/form.js index 530edca8..91409714 100644 --- a/client/src/core-components/form.js +++ b/client/src/core-components/form.js @@ -10,11 +10,22 @@ const Checkbox = require('core-components/checkbox'); const Form = React.createClass({ propTypes: { + loading: React.PropTypes.bool, errors: React.PropTypes.object, onValidateErrors: React.PropTypes.func, onSubmit: React.PropTypes.func }, + childContextTypes: { + loading: React.PropTypes.bool + }, + + getChildContext() { + return { + loading: this.props.loading + }; + }, + getInitialState() { return { form: {}, @@ -41,6 +52,7 @@ const Form = React.createClass({ props.onSubmit = this.handleSubmit; delete props.errors; + delete props.loading; delete props.onValidateErrors; return props; diff --git a/client/src/core-components/submit-button.js b/client/src/core-components/submit-button.js new file mode 100644 index 00000000..e901c9ac --- /dev/null +++ b/client/src/core-components/submit-button.js @@ -0,0 +1,58 @@ +// VENDOR LIBS +import React from 'react'; +import _ from 'lodash'; +import classNames from 'classnames'; + +// CORE LIBS +import Button from 'core-components/button'; + +const SubmitButton = React.createClass({ + + contextTypes: { + loading: React.PropTypes.bool + }, + + propTypes: { + children: React.PropTypes.node + }, + + getDefaultProps() { + return { + type: 'primary' + }; + }, + + render() { + return ( + + ); + }, + + renderLoading() { + return ( +
+ ); + }, + + getProps() { + return _.extend({}, this.props, { + disabled: this.context.loading, + className: this.getClass() + }); + }, + + getClass() { + let classes = { + 'submit-button': true, + 'submit-button_loading': this.context.loading + }; + + classes[this.props.className] = (this.props.className); + + return classNames(classes); + } +}); + +export default SubmitButton; diff --git a/client/src/core-components/submit-button.scss b/client/src/core-components/submit-button.scss new file mode 100644 index 00000000..f75110f1 --- /dev/null +++ b/client/src/core-components/submit-button.scss @@ -0,0 +1,46 @@ +.submit-button { + position: relative; + + &__loader { + position: absolute; + top: 7px; + left: 103px; + + font-size: 4px; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #ffffff; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: turnAnimation 1.1s infinite linear; + animation: turnAnimation 1.1s infinite linear; + } + &__loader, + &__loader:after { + border-radius: 50%; + width: 30px; + height: 30px; + } + @-webkit-keyframes turnAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @keyframes turnAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } +} \ No newline at end of file diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index b17b4842..11523e1a 100644 --- a/client/src/data/fixtures/user-fixtures.js +++ b/client/src/data/fixtures/user-fixtures.js @@ -49,7 +49,7 @@ module.exports = [ }, { path: 'user/send-recover-password', - time: 100, + time: 2000, response: function (data) { if (data.email.length > 10) { @@ -68,7 +68,7 @@ module.exports = [ }, { path: 'user/recover-password', - time: 100, + time: 1000, response: function (data) { if (data.password.length > 6) { diff --git a/client/src/stores/user-store.js b/client/src/stores/user-store.js index 07ae890a..00df5c96 100644 --- a/client/src/stores/user-store.js +++ b/client/src/stores/user-store.js @@ -72,7 +72,6 @@ const UserStore = Reflux.createStore({ data: recoverData }).then(() => { this.trigger('VALID_RECOVER'); - setTimeout(CommonActions.loggedOut, 1000); }, () => { this.trigger('INVALID_RECOVER') });