diff --git a/README.md b/README.md index 4886249f3..306b51591 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,11 @@ Lock will emit events during its lifecycle. - `authenticated`: emitted after a successful authentication. Has the authentication result as the only argument. - `authorization_error`: emitted when authorization fails. Has error as the only argument. - `hash_parsed`: every time a new Auth0Lock object is initialized in redirect mode (the default), it will attempt to parse the hash part of the url looking for the result of a login attempt. This is a _low level_ event for advanced use cases and _authenticated_ and _authorization_error_ should be preferred when possible. After that this event will be emitted with `null` if it couldn't find anything in the hash. It will be emitted with the same argument as the `authenticated` event after a successful login or with the same argument as `authorization_error` if something went wrong. This event won't be emitted in popup mode because there is no need to parse the url's hash part. +- `forgot_password ready`: emitted when the "Forgot password" screen is shown. +- `forgot_password submit`: emitted when the user clicks on the submit button of the "Forgot password" screen. +- `signin submit`: emitted when the user clicks on the submit button of the "Login" screen. +- `signup submit`: emitted when the user clicks on the submit button of the "Sign up" screen. +- `federated login`: emitted when the user clicks on a social connection button. Has the connection name and the strategy as arguments. ### show(options) diff --git a/src/__tests__/field/social_buttons_pane.test.jsx b/src/__tests__/field/social_buttons_pane.test.jsx index 3e76a7e0f..3c247b1d5 100644 --- a/src/__tests__/field/social_buttons_pane.test.jsx +++ b/src/__tests__/field/social_buttons_pane.test.jsx @@ -16,6 +16,7 @@ describe('SocialButtonsPane', () => { signUp: false, disabled: false }; + beforeEach(() => { jest.resetModules(); @@ -37,7 +38,8 @@ describe('SocialButtonsPane', () => { })); jest.mock('core/index', () => ({ - id: () => 1 + id: () => 1, + emitEvent: jest.fn() })); }); diff --git a/src/core.js b/src/core.js index bfdf21eb3..3aa728b2a 100644 --- a/src/core.js +++ b/src/core.js @@ -40,7 +40,13 @@ export default class Base extends EventEmitter { 'authorization_error', 'hash_parsed', 'signin ready', - 'signup ready' + 'signup ready', + + 'forgot_password ready', + 'forgot_password submit', + 'signin submit', + 'signup submit', + 'federated login' ]; this.id = idu.incremental(); @@ -125,6 +131,8 @@ export default class Base extends EventEmitter { l.emitEvent(m, 'signin ready'); } else if (screen.name === 'main.signUp') { l.emitEvent(m, 'signup ready'); + } else if (screen.name === 'forgotPassword') { + l.emitEvent(m, 'forgot_password ready'); } } this.oldScreenName = screen.name; diff --git a/src/core/index.js b/src/core/index.js index cb9a97945..e785910f3 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -217,7 +217,8 @@ function extractAuthOptions(options) { sso, state, nonce - } = options.auth || {}; + } = + options.auth || {}; let { oidcConformant } = options; diff --git a/src/field/social/event.js b/src/field/social/event.js new file mode 100644 index 000000000..68f348a9f --- /dev/null +++ b/src/field/social/event.js @@ -0,0 +1,17 @@ +import * as l from '../../core/index'; + +export function emitFederatedLoginEvent(lock, provider, isSignUp) { + let prov; + + try { + prov = provider.toJS(); + } catch (e) { + prov = provider; + } + + l.emitEvent(lock, 'federated login', { + name: prov.name, + strategy: prov.strategy, + action: isSignUp ? 'signup' : 'signin' + }); +} diff --git a/src/field/social/social_buttons_pane.jsx b/src/field/social/social_buttons_pane.jsx index d1e0c47c6..9856c78fe 100644 --- a/src/field/social/social_buttons_pane.jsx +++ b/src/field/social/social_buttons_pane.jsx @@ -4,8 +4,14 @@ import AuthButton from '../../ui/button/auth_button'; import * as l from '../../core/index'; import { logIn } from '../../quick-auth/actions'; import { displayName, socialConnections, authButtonsTheme } from '../../connection/social/index'; +import { emitFederatedLoginEvent } from './event'; export default class SocialButtonsPane extends React.Component { + handleSubmit(provider, isSignUp) { + emitFederatedLoginEvent(this.props.lock, provider, isSignUp); + return logIn(l.id(this.props.lock), provider); + } + render() { // TODO: i don't like that it receives the instructions tanslated // but it also takes the t fn @@ -31,7 +37,7 @@ export default class SocialButtonsPane extends React.Component { signUp ? 'signUpWithLabel' : 'loginWithLabel', connectionName || displayName(x) )} - onClick={() => logIn(l.id(lock), x)} + onClick={() => this.handleSubmit(x, signUp)} strategy={x.get('strategy')} primaryColor={primaryColor} foregroundColor={foregroundColor} diff --git a/src/ui/box/chrome.jsx b/src/ui/box/chrome.jsx index 1d54f34ed..06c843272 100644 --- a/src/ui/box/chrome.jsx +++ b/src/ui/box/chrome.jsx @@ -4,6 +4,7 @@ import ReactDOM from 'react-dom'; import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; import MultisizeSlide from './multisize_slide'; import GlobalMessage from './global_message'; +import * as l from '../../core/index'; import Header from './header'; const submitSvg = @@ -12,6 +13,23 @@ const submitText = ''; class SubmitButton extends React.Component { + handleSubmit() { + const { label, screenName, contentProps } = this.props; + const { model } = contentProps; + + if (screenName === 'main.signUp') { + l.emitEvent(model, 'signup submit'); + } else if (screenName === 'main.login') { + l.emitEvent(model, 'signin submit'); + } else if (screenName === 'forgotPassword') { + l.emitEvent(model, 'forgot_password submit'); + } + + if (this.props.onSubmit) { + this.props.onSubmit(label, screenName); + } + } + focus() { ReactDOM.findDOMNode(this).focus(); } @@ -30,6 +48,7 @@ class SubmitButton extends React.Component { className="auth0-lock-submit" disabled={disabled} style={{ backgroundColor: color }} + onClick={::this.handleSubmit} type="submit" >