#14: reset captcha if there are errors in form

This commit is contained in:
SleepWalker 2016-08-14 13:10:59 +03:00
parent a91e2e99b3
commit 016cccf4c9
5 changed files with 60 additions and 21 deletions

View File

@ -18,10 +18,21 @@ export default class BaseAuthBody extends Component {
payload: PropTypes.object
})]),
scopes: PropTypes.array
}),
}).isRequired,
user: userShape
};
componentWillReceiveProps(nextProps, nextContext) {
// TODO: we must not access Form#fields. This is a temporary
// solution to reset Captcha, when the form does not handle errors
if (nextContext.auth.error
&& this.form.fields.captcha
&& nextContext.auth.error !== this.context.auth.error
) {
this.form.fields.captcha.reset();
}
}
renderErrors() {
return this.context.auth.error
? <AuthError error={this.context.auth.error} onClose={this.onClearErrors} />

View File

@ -241,12 +241,12 @@ class PanelTransition extends Component {
willLeave = (config) => this.getTransitionStyles(config, {isLeave: true});
/**
* @param {Object} config
* @param {string} config.key
* @param {Object} [options]
* @param {Object} [options.isLeave=false] - true, if this is a leave transition
* @param {object} config
* @param {string} config.key
* @param {object} [options]
* @param {object} [options.isLeave=false] - true, if this is a leave transition
*
* @return {Object}
* @return {object}
*/
getTransitionStyles({key}, options = {}) {
const {isLeave = false} = options;
@ -298,7 +298,7 @@ class PanelTransition extends Component {
/**
* Tries to auto focus form fields after transition end
*
* @param {number} length number of panels transitioned
* @param {number} length number of panels transitioned
*/
tryToAutoFocus(length) {
if (!this.body) {
@ -337,7 +337,11 @@ class PanelTransition extends Component {
};
const backButton = (
<button style={sideScrollStyle} type="button" onClick={this.onGoBack} className={panelStyles.headerControl}>
<button style={sideScrollStyle}
className={panelStyles.headerControl}
type="button"
onClick={this.onGoBack}
>
<span className={icons.arrowLeft} />
</button>
);
@ -412,11 +416,11 @@ class PanelTransition extends Component {
}
/**
* @param {string} key
* @param {Object} style
* @param {number} style.opacitySpring
* @param {string} key
* @param {object} style
* @param {number} style.opacitySpring
*
* @return {Object}
* @return {object}
*/
getDefaultTransitionStyles(key, {opacitySpring}) {
return {
@ -430,11 +434,11 @@ class PanelTransition extends Component {
}
/**
* @param {number} value
* @param {string} direction='X' - X|Y
* @param {string} unit='%' - %|px etc
* @param {number} value
* @param {string} direction='X' - X|Y
* @param {string} unit='%' - %|px etc
*
* @return {Object}
* @return {object}
*/
translate(value, direction = 'X', unit = '%') {
return {

View File

@ -23,10 +23,14 @@ export default class Captcha extends FormInputComponent {
};
componentDidMount() {
setTimeout(() => captcha.render(this.el, {
skin: this.props.skin,
onSetCode: this.setCode
}), this.props.delay);
setTimeout(() =>
captcha.render(this.el, {
skin: this.props.skin,
onSetCode: this.setCode
})
.then((captchaId) => this.captchaId = captchaId),
this.props.delay
);
}
render() {
@ -37,10 +41,12 @@ export default class Captcha extends FormInputComponent {
<div className={styles.captchaLoader}>
<ComponentLoader />
</div>
<div ref={this.setEl} className={classNames(
styles.captcha,
styles[`${skin}Captcha`]
)} />
{this.renderError()}
</div>
);
@ -50,5 +56,15 @@ export default class Captcha extends FormInputComponent {
return this.state && this.state.code;
}
reset() {
captcha.reset(this.captchaId);
}
setError(error) {
super.setError(error);
this.reset();
}
setCode = (code) => this.setState({code});
}

View File

@ -12,7 +12,7 @@ export default {
* @param {function} options.onSetCode - the callback, that will be called with
* captcha verification code, after user successfully solves captcha
*
* @return {Promise}
* @return {Promise} - resolves to captchaId
*/
render(el, {skin: theme, onSetCode: callback}) {
return this.loadApi().then(() =>
@ -24,6 +24,13 @@ export default {
);
},
/**
* @param {string} captchaId - captcha id, returned from render promise
*/
reset(captchaId) {
this.loadApi().then(() => window.grecaptcha.reset(captchaId));
},
/**
* @param {stirng} newLang
*

View File

@ -77,6 +77,7 @@ const errorsMap = {
'error.account_already_activated': () => <Message {...messages.accountAlreadyActivated} />,
'error.captcha_required': () => <Message {...messages.captchaRequired} />,
'error.captcha_invalid': () => errorsMap['error.captcha_required'](),
suggestResetPassword: () => (
<span>