diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/auth/Invite.js | 82 | ||||
-rw-r--r-- | src/containers/settings/InviteScreen.js | 19 | ||||
-rw-r--r-- | src/stores/UserStore.js | 4 |
3 files changed, 54 insertions, 51 deletions
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js index 9f85c3152..285ebebcf 100644 --- a/src/components/auth/Invite.js +++ b/src/components/auth/Invite.js | |||
@@ -36,19 +36,19 @@ const messages = defineMessages({ | |||
36 | inviteSuccessInfo: { | 36 | inviteSuccessInfo: { |
37 | id: 'invite.successInfo', | 37 | id: 'invite.successInfo', |
38 | defaultMessage: '!!!Invitations sent successfully', | 38 | defaultMessage: '!!!Invitations sent successfully', |
39 | } | 39 | }, |
40 | }); | 40 | }); |
41 | 41 | ||
42 | @observer | 42 | @observer |
43 | export default class Invite extends Component { | 43 | export default class Invite extends Component { |
44 | static propTypes = { | 44 | static propTypes = { |
45 | onSubmit: PropTypes.func.isRequired, | 45 | onSubmit: PropTypes.func.isRequired, |
46 | from: PropTypes.string, | ||
47 | embed: PropTypes.bool, | 46 | embed: PropTypes.bool, |
47 | isInviteSuccessful: PropTypes.bool.isRequired, | ||
48 | isLoadingInvite: PropTypes.bool.isRequired, | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | static defaultProps = { | 51 | static defaultProps = { |
51 | from: '/', | ||
52 | embed: false, | 52 | embed: false, |
53 | }; | 53 | }; |
54 | 54 | ||
@@ -59,9 +59,9 @@ export default class Invite extends Component { | |||
59 | state = { showSuccessInfo: false }; | 59 | state = { showSuccessInfo: false }; |
60 | 60 | ||
61 | handlers = { | 61 | handlers = { |
62 | onChange: (field) => { | 62 | onChange: () => { |
63 | this.setState({ showSuccessInfo: false }) | 63 | this.setState({ showSuccessInfo: false }); |
64 | } | 64 | }, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | form = new Form({ | 67 | form = new Form({ |
@@ -87,15 +87,15 @@ export default class Invite extends Component { | |||
87 | 87 | ||
88 | submit(e) { | 88 | submit(e) { |
89 | e.preventDefault(); | 89 | e.preventDefault(); |
90 | 90 | ||
91 | this.form.submit({ | 91 | this.form.submit({ |
92 | onSuccess: (form) => { | 92 | onSuccess: (form) => { |
93 | this.props.onSubmit({ invites: form.values().invite }); | 93 | this.props.onSubmit({ invites: form.values().invite }); |
94 | 94 | ||
95 | this.form.clear() | 95 | this.form.clear(); |
96 | // this.form.$('invite.0.name').focus() // path accepted but does not focus ;( | 96 | // this.form.$('invite.0.name').focus(); // path accepted but does not focus ;( |
97 | document.querySelector('input:first-child').focus() | 97 | document.querySelector('input:first-child').focus(); |
98 | this.setState({ showSuccessInfo: true }) | 98 | this.setState({ showSuccessInfo: true }); |
99 | }, | 99 | }, |
100 | onError: () => {}, | 100 | onError: () => {}, |
101 | }); | 101 | }); |
@@ -127,37 +127,37 @@ export default class Invite extends Component { | |||
127 | </Infobox> | 127 | </Infobox> |
128 | </Appear>)} | 128 | </Appear>)} |
129 | 129 | ||
130 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> | 130 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
131 | {!embed && (<img | 131 | {!embed && (<img |
132 | src="./assets/images/logo.svg" | 132 | src="./assets/images/logo.svg" |
133 | className="auth__logo" | 133 | className="auth__logo" |
134 | alt="" | 134 | alt="" |
135 | />)} | 135 | />)} |
136 | <h1 className={embed && 'invite__embed'}> | 136 | <h1 className={embed && 'invite__embed'}> |
137 | {intl.formatMessage(messages.headline)} | 137 | {intl.formatMessage(messages.headline)} |
138 | </h1> | 138 | </h1> |
139 | {form.$('invite').map(invite => ( | 139 | {form.$('invite').map(invite => ( |
140 | <div className="grid" key={invite.key}> | 140 | <div className="grid" key={invite.key}> |
141 | <div className="grid__row"> | 141 | <div className="grid__row"> |
142 | <Input field={invite.$('name')} showLabel={false} /> | 142 | <Input field={invite.$('name')} showLabel={false} /> |
143 | <Input field={invite.$('email')} showLabel={false} /> | 143 | <Input field={invite.$('email')} showLabel={false} /> |
144 | </div> | ||
144 | </div> | 145 | </div> |
145 | </div> | 146 | ))} |
146 | ))} | 147 | <Button |
147 | <Button | 148 | type="submit" |
148 | type="submit" | 149 | className={sendButtonClassName} |
149 | className={sendButtonClassName} | 150 | disabled={!atLeastOneEmailAddress} |
150 | disabled={!atLeastOneEmailAddress} | 151 | label={intl.formatMessage(messages.submitButtonLabel)} |
151 | label={intl.formatMessage(messages.submitButtonLabel)} | 152 | loaded={!isLoadingInvite} |
152 | loaded={!isLoadingInvite} | 153 | /> |
153 | /> | 154 | {!embed && (<Link |
154 | {!embed && (<Link | 155 | to="/" |
155 | to="/" | 156 | className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" |
156 | className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" | 157 | > |
157 | > | 158 | {intl.formatMessage(messages.skipButtonLabel)} |
158 | {intl.formatMessage(messages.skipButtonLabel)} | 159 | </Link>)} |
159 | </Link>)} | 160 | </form> |
160 | </form> | ||
161 | </div> | 161 | </div> |
162 | ); | 162 | ); |
163 | } | 163 | } |
diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js index 63e88765e..1947e79f0 100644 --- a/src/containers/settings/InviteScreen.js +++ b/src/containers/settings/InviteScreen.js | |||
@@ -1,9 +1,10 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { inject, observer } from 'mobx-react'; | 3 | import { inject, observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | |||
4 | import Invite from '../../components/auth/Invite'; | 6 | import Invite from '../../components/auth/Invite'; |
5 | import { gaPage } from '../../lib/analytics'; | 7 | import { gaPage } from '../../lib/analytics'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | ||
7 | 8 | ||
8 | const messages = defineMessages({ | 9 | const messages = defineMessages({ |
9 | headline: { | 10 | headline: { |
@@ -22,13 +23,12 @@ export default class InviteScreen extends Component { | |||
22 | gaPage('Settings/Invite'); | 23 | gaPage('Settings/Invite'); |
23 | } | 24 | } |
24 | 25 | ||
25 | 26 | componentWillUnmount() { | |
26 | componentWillUnmount () { | 27 | this.props.stores.user.inviteRequest.reset(); |
27 | this.props.stores.user.inviteRequest.reset() | ||
28 | } | 28 | } |
29 | 29 | ||
30 | render() { | 30 | render() { |
31 | const { actions, location } = this.props; | 31 | const { actions } = this.props; |
32 | const { user } = this.props.stores; | 32 | const { user } = this.props.stores; |
33 | 33 | ||
34 | return ( | 34 | return ( |
@@ -40,8 +40,8 @@ export default class InviteScreen extends Component { | |||
40 | <Invite | 40 | <Invite |
41 | onSubmit={actions.user.invite} | 41 | onSubmit={actions.user.invite} |
42 | isLoadingInvite={user.inviteRequest.isExecuting} | 42 | isLoadingInvite={user.inviteRequest.isExecuting} |
43 | isInviteSuccessful={user.inviteRequest.wasExecuted && !user.inviteRequest.isError} | 43 | isInviteSuccessful={user.inviteRequest.wasExecuted && !user.inviteRequest.isError} |
44 | embed={true} | 44 | embed |
45 | /> | 45 | /> |
46 | </div> | 46 | </div> |
47 | </div> | 47 | </div> |
@@ -55,4 +55,9 @@ InviteScreen.wrappedComponent.propTypes = { | |||
55 | invite: PropTypes.func.isRequired, | 55 | invite: PropTypes.func.isRequired, |
56 | }).isRequired, | 56 | }).isRequired, |
57 | }).isRequired, | 57 | }).isRequired, |
58 | stores: PropTypes.shape({ | ||
59 | user: PropTypes.shape({ | ||
60 | inviteRequest: PropTypes.object, | ||
61 | }).isRequired, | ||
62 | }).isRequired, | ||
58 | }; | 63 | }; |
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 54627440a..abec4df5d 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -8,8 +8,6 @@ import Request from './lib/Request'; | |||
8 | import CachedRequest from './lib/CachedRequest'; | 8 | import CachedRequest from './lib/CachedRequest'; |
9 | import { gaEvent } from '../lib/analytics'; | 9 | import { gaEvent } from '../lib/analytics'; |
10 | 10 | ||
11 | import { matchPath } from 'react-router' | ||
12 | |||
13 | // TODO: split stores into UserStore and AuthStore | 11 | // TODO: split stores into UserStore and AuthStore |
14 | export default class UserStore extends Store { | 12 | export default class UserStore extends Store { |
15 | BASE_ROUTE = '/auth'; | 13 | BASE_ROUTE = '/auth'; |
@@ -168,7 +166,7 @@ export default class UserStore extends Store { | |||
168 | 166 | ||
169 | const response = await this.inviteRequest.execute(data)._promise; | 167 | const response = await this.inviteRequest.execute(data)._promise; |
170 | 168 | ||
171 | this.actionStatus = response.status || [] | 169 | this.actionStatus = response.status || []; |
172 | 170 | ||
173 | // we do not wait for a server response before redirecting the user ONLY DURING SIGNUP | 171 | // we do not wait for a server response before redirecting the user ONLY DURING SIGNUP |
174 | if (this.stores.router.location.pathname.includes(this.INVITE_ROUTE)) { | 172 | if (this.stores.router.location.pathname.includes(this.INVITE_ROUTE)) { |