mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-30 02:32:58 +05:30
#397: ensure, that recaptcha.render will be called with an existing el ref
This commit is contained in:
parent
cc50dab0e4
commit
fde1d36287
@ -1,25 +1,21 @@
|
||||
// @flow
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import buttons from 'components/ui/buttons.scss';
|
||||
import { COLOR_GREEN } from 'components/ui';
|
||||
|
||||
import type { Color } from 'components/ui';
|
||||
import FormComponent from './FormComponent';
|
||||
|
||||
import type { Color } from 'components/ui';
|
||||
|
||||
export default class Button extends FormComponent {
|
||||
props: {
|
||||
label: string | {id: string},
|
||||
block: bool,
|
||||
small: bool,
|
||||
loading: bool,
|
||||
className: string,
|
||||
color: Color
|
||||
};
|
||||
|
||||
export default class Button extends FormComponent<{
|
||||
label: string | MessageDescriptor,
|
||||
block: bool,
|
||||
small: bool,
|
||||
loading: bool,
|
||||
className: string,
|
||||
color: Color
|
||||
}> {
|
||||
static defaultProps = {
|
||||
color: COLOR_GREEN
|
||||
};
|
||||
|
@ -1,35 +1,41 @@
|
||||
import PropTypes from 'prop-types';
|
||||
// @flow
|
||||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { CaptchaID } from 'services/captcha';
|
||||
import type { Skin } from 'components/ui';
|
||||
import captcha from 'services/captcha';
|
||||
import logger from 'services/logger';
|
||||
import { skins, SKIN_DARK } from 'components/ui';
|
||||
import { ComponentLoader } from 'components/ui/loader';
|
||||
|
||||
import styles from './form.scss';
|
||||
import FormInputComponent from './FormInputComponent';
|
||||
|
||||
export default class Captcha extends FormInputComponent {
|
||||
static displayName = 'Captcha';
|
||||
|
||||
static propTypes = {
|
||||
skin: PropTypes.oneOf(skins),
|
||||
delay: PropTypes.number
|
||||
};
|
||||
export default class Captcha extends FormInputComponent<{
|
||||
delay: number,
|
||||
skin: Skin,
|
||||
}, {
|
||||
code: string,
|
||||
}> {
|
||||
el: ?HTMLDivElement;
|
||||
captchaId: CaptchaID;
|
||||
|
||||
static defaultProps = {
|
||||
skin: SKIN_DARK,
|
||||
skin: 'dark',
|
||||
delay: 0
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
setTimeout(() => {
|
||||
captcha.render(this.el, {
|
||||
this.el && captcha.render(this.el, {
|
||||
skin: this.props.skin,
|
||||
onSetCode: this.setCode
|
||||
}).then((captchaId) => this.captchaId = captchaId, (error) => logger.error('Error rendering captcha', { error }));
|
||||
})
|
||||
.then((captchaId) => {this.captchaId = captchaId;})
|
||||
.catch((error) => {
|
||||
logger.error('Failed rendering captcha', {
|
||||
error
|
||||
});
|
||||
});
|
||||
}, this.props.delay);
|
||||
}
|
||||
|
||||
@ -64,5 +70,5 @@ export default class Captcha extends FormInputComponent {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
setCode = (code) => this.setState({code});
|
||||
setCode = (code: string) => this.setState({code});
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
// @flow
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import { Component } from 'react';
|
||||
|
||||
import { intlShape } from 'react-intl';
|
||||
|
||||
export default class FormComponent extends Component {
|
||||
static displayName = 'FormComponent';
|
||||
|
||||
export default class FormComponent<P, S = void> extends Component<P, S> {
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired
|
||||
};
|
||||
@ -16,7 +15,7 @@ export default class FormComponent extends Component {
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
formatMessage(message) {
|
||||
formatMessage(message: string | MessageDescriptor) {
|
||||
if (message && message.id && this.context && this.context.intl) {
|
||||
message = this.context.intl.formatMessage(message);
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
import PropTypes from 'prop-types';
|
||||
// @flow
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import React from 'react';
|
||||
|
||||
import FormComponent from './FormComponent';
|
||||
import FormError from './FormError';
|
||||
|
||||
export default class FormInputComponent extends FormComponent {
|
||||
static displayName = 'FormInputComponent';
|
||||
type Error = string | MessageDescriptor;
|
||||
|
||||
static propTypes = {
|
||||
error: PropTypes.string
|
||||
};
|
||||
export default class FormInputComponent<P, S = void> extends FormComponent<P & {
|
||||
error?: Error,
|
||||
}, S & {
|
||||
error?: Error,
|
||||
}> {
|
||||
el: ?HTMLDivElement;
|
||||
|
||||
componentWillReceiveProps() {
|
||||
if (this.state && this.state.error) {
|
||||
@ -19,7 +22,7 @@ export default class FormInputComponent extends FormComponent {
|
||||
}
|
||||
}
|
||||
|
||||
setEl = (el) => {
|
||||
setEl = (el: ?HTMLDivElement) => {
|
||||
this.el = el;
|
||||
};
|
||||
|
||||
@ -29,7 +32,7 @@ export default class FormInputComponent extends FormComponent {
|
||||
return <FormError error={error} />;
|
||||
}
|
||||
|
||||
setError(error) {
|
||||
setError(error: Error) {
|
||||
this.setState({error});
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export default class FormModel {
|
||||
|
||||
const props: Object = {
|
||||
name,
|
||||
ref: (el: ?FormInputComponent) => {
|
||||
ref: (el: ?FormInputComponent<any>) => {
|
||||
if (el) {
|
||||
if (!(el instanceof FormInputComponent)) {
|
||||
throw new Error('Expected FormInputComponent component');
|
||||
|
@ -1,3 +1,4 @@
|
||||
// @flow
|
||||
import { loadScript } from 'functions';
|
||||
import options from 'services/api/options';
|
||||
|
||||
@ -5,6 +6,8 @@ let readyPromise;
|
||||
let lang = 'en';
|
||||
let sitekey;
|
||||
|
||||
export opaque type CaptchaID = string;
|
||||
|
||||
export default {
|
||||
/**
|
||||
* @param {DOMNode|string} el - dom node or id of element where to render captcha
|
||||
@ -14,7 +17,10 @@ export default {
|
||||
*
|
||||
* @return {Promise} - resolves to captchaId
|
||||
*/
|
||||
render(el, {skin: theme, onSetCode: callback}) {
|
||||
render(el: HTMLElement, {skin: theme, onSetCode: callback}: {
|
||||
skin: 'dark' | 'light',
|
||||
onSetCode: (string) => void,
|
||||
}): Promise<CaptchaID> {
|
||||
return this.loadApi().then(() =>
|
||||
window.grecaptcha.render(el, {
|
||||
sitekey,
|
||||
@ -27,7 +33,7 @@ export default {
|
||||
/**
|
||||
* @param {string} captchaId - captcha id, returned from render promise
|
||||
*/
|
||||
reset(captchaId) {
|
||||
reset(captchaId: CaptchaID) {
|
||||
this.loadApi().then(() => window.grecaptcha.reset(captchaId));
|
||||
},
|
||||
|
||||
@ -36,7 +42,7 @@ export default {
|
||||
*
|
||||
* @see https://developers.google.com/recaptcha/docs/language
|
||||
*/
|
||||
setLang(newLang) {
|
||||
setLang(newLang: string) {
|
||||
lang = newLang;
|
||||
},
|
||||
|
||||
@ -45,7 +51,7 @@ export default {
|
||||
*
|
||||
* @see http://www.google.com/recaptcha/admin
|
||||
*/
|
||||
setApiKey(apiKey) {
|
||||
setApiKey(apiKey: string) {
|
||||
sitekey = apiKey;
|
||||
},
|
||||
|
||||
@ -54,14 +60,14 @@ export default {
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
loadApi() {
|
||||
loadApi(): Promise<void> {
|
||||
if (!readyPromise) {
|
||||
readyPromise = Promise.all([
|
||||
new Promise((resolve) => {
|
||||
window.onReCaptchaReady = resolve;
|
||||
}),
|
||||
options.get().then((resp) => this.setApiKey(resp.reCaptchaPublicKey))
|
||||
]);
|
||||
]).then(() => {});
|
||||
|
||||
loadScript(`https://recaptcha.net/recaptcha/api.js?onload=onReCaptchaReady&render=explicit&hl=${lang}`);
|
||||
}
|
||||
@ -69,4 +75,3 @@ export default {
|
||||
return readyPromise;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user