diff options
Diffstat (limited to 'src/components/auth')
-rw-r--r-- | src/components/auth/Import.js | 17 | ||||
-rw-r--r-- | src/components/auth/Invite.js | 128 | ||||
-rw-r--r-- | src/components/auth/Login.js | 4 | ||||
-rw-r--r-- | src/components/auth/Password.js | 2 | ||||
-rw-r--r-- | src/components/auth/Pricing.js | 2 | ||||
-rw-r--r-- | src/components/auth/Signup.js | 10 | ||||
-rw-r--r-- | src/components/auth/Welcome.js | 2 |
7 files changed, 121 insertions, 44 deletions
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js index 078244434..9ba14e768 100644 --- a/src/components/auth/Import.js +++ b/src/components/auth/Import.js | |||
@@ -41,21 +41,21 @@ export default class Import extends Component { | |||
41 | intl: intlShape, | 41 | intl: intlShape, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | prepareForm() { | 44 | componentWillMount() { |
45 | const { services } = this.props; | ||
46 | |||
47 | const config = { | 45 | const config = { |
48 | fields: { | 46 | fields: { |
49 | import: [...services.filter(s => s.recipe).map(s => ({ | 47 | import: [...this.props.services.filter(s => s.recipe).map(s => ({ |
50 | add: { | 48 | fields: { |
51 | default: true, | 49 | add: { |
52 | options: s, | 50 | default: true, |
51 | options: s, | ||
52 | }, | ||
53 | }, | 53 | }, |
54 | }))], | 54 | }))], |
55 | }, | 55 | }, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | return new Form(config, this.context.intl); | 58 | this.form = new Form(config, this.context.intl); |
59 | } | 59 | } |
60 | 60 | ||
61 | submit(e) { | 61 | submit(e) { |
@@ -74,7 +74,6 @@ export default class Import extends Component { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | render() { | 76 | render() { |
77 | this.form = this.prepareForm(); | ||
78 | const { intl } = this.context; | 77 | const { intl } = this.context; |
79 | const { services, isSubmitting, inviteRoute } = this.props; | 78 | const { services, isSubmitting, inviteRoute } = this.props; |
80 | 79 | ||
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js index c1d815dcd..f1c16986b 100644 --- a/src/components/auth/Invite.js +++ b/src/components/auth/Invite.js | |||
@@ -3,13 +3,20 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import classnames from 'classnames'; | ||
6 | 7 | ||
8 | import Infobox from '../ui/Infobox'; | ||
9 | import Appear from '../ui/effects/Appear'; | ||
7 | import Form from '../../lib/Form'; | 10 | import Form from '../../lib/Form'; |
8 | import { email } from '../../helpers/validation-helpers'; | 11 | import { email } from '../../helpers/validation-helpers'; |
9 | import Input from '../ui/Input'; | 12 | import Input from '../ui/Input'; |
10 | import Button from '../ui/Button'; | 13 | import Button from '../ui/Button'; |
11 | 14 | ||
12 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
16 | settingsHeadline: { | ||
17 | id: 'settings.invite.headline', | ||
18 | defaultMessage: '!!!Invite Friends', | ||
19 | }, | ||
13 | headline: { | 20 | headline: { |
14 | id: 'invite.headline.friends', | 21 | id: 'invite.headline.friends', |
15 | defaultMessage: '!!!Invite 3 of your friends or colleagues', | 22 | defaultMessage: '!!!Invite 3 of your friends or colleagues', |
@@ -30,41 +37,77 @@ const messages = defineMessages({ | |||
30 | id: 'invite.skip.label', | 37 | id: 'invite.skip.label', |
31 | defaultMessage: '!!!I want to do this later', | 38 | defaultMessage: '!!!I want to do this later', |
32 | }, | 39 | }, |
40 | inviteSuccessInfo: { | ||
41 | id: 'invite.successInfo', | ||
42 | defaultMessage: '!!!Invitations sent successfully', | ||
43 | }, | ||
33 | }); | 44 | }); |
34 | 45 | ||
35 | @observer | 46 | @observer |
36 | export default class Invite extends Component { | 47 | export default class Invite extends Component { |
37 | static propTypes = { | 48 | static propTypes = { |
38 | onSubmit: PropTypes.func.isRequired, | 49 | onSubmit: PropTypes.func.isRequired, |
50 | embed: PropTypes.bool, | ||
51 | isInviteSuccessful: PropTypes.bool, | ||
52 | isLoadingInvite: PropTypes.bool, | ||
53 | }; | ||
54 | |||
55 | static defaultProps = { | ||
56 | embed: false, | ||
57 | isInviteSuccessful: false, | ||
58 | isLoadingInvite: false, | ||
39 | }; | 59 | }; |
40 | 60 | ||
41 | static contextTypes = { | 61 | static contextTypes = { |
42 | intl: intlShape, | 62 | intl: intlShape, |
43 | }; | 63 | }; |
44 | 64 | ||
45 | form = new Form({ | 65 | state = { showSuccessInfo: false }; |
46 | fields: { | 66 | |
47 | invite: [...Array(3).fill({ | 67 | componentWillMount() { |
48 | name: { | 68 | const handlers = { |
49 | label: this.context.intl.formatMessage(messages.nameLabel), | 69 | onChange: () => { |
50 | // value: '', | 70 | this.setState({ showSuccessInfo: false }); |
51 | placeholder: this.context.intl.formatMessage(messages.nameLabel), | 71 | }, |
52 | }, | 72 | }; |
53 | email: { | 73 | |
54 | label: this.context.intl.formatMessage(messages.emailLabel), | 74 | this.form = new Form({ |
55 | // value: '', | 75 | fields: { |
56 | validate: [email], | 76 | invite: [...Array(3).fill({ |
57 | placeholder: this.context.intl.formatMessage(messages.emailLabel), | 77 | fields: { |
58 | }, | 78 | name: { |
59 | })], | 79 | label: this.context.intl.formatMessage(messages.nameLabel), |
60 | }, | 80 | placeholder: this.context.intl.formatMessage(messages.nameLabel), |
61 | }, this.context.intl); | 81 | handlers, |
82 | // related: ['invite.0.email'], // path accepted but does not work | ||
83 | }, | ||
84 | email: { | ||
85 | label: this.context.intl.formatMessage(messages.emailLabel), | ||
86 | placeholder: this.context.intl.formatMessage(messages.emailLabel), | ||
87 | handlers, | ||
88 | validators: [email], | ||
89 | }, | ||
90 | }, | ||
91 | })], | ||
92 | }, | ||
93 | }, this.context.intl); | ||
94 | } | ||
95 | |||
96 | componentDidMount() { | ||
97 | document.querySelector('input:first-child').focus(); | ||
98 | } | ||
62 | 99 | ||
63 | submit(e) { | 100 | submit(e) { |
64 | e.preventDefault(); | 101 | e.preventDefault(); |
102 | |||
65 | this.form.submit({ | 103 | this.form.submit({ |
66 | onSuccess: (form) => { | 104 | onSuccess: (form) => { |
67 | this.props.onSubmit({ invites: form.values().invite }); | 105 | this.props.onSubmit({ invites: form.values().invite }); |
106 | |||
107 | this.form.clear(); | ||
108 | // this.form.$('invite.0.name').focus(); // path accepted but does not focus ;( | ||
109 | document.querySelector('input:first-child').focus(); | ||
110 | this.setState({ showSuccessInfo: true }); | ||
68 | }, | 111 | }, |
69 | onError: () => {}, | 112 | onError: () => {}, |
70 | }); | 113 | }); |
@@ -73,16 +116,38 @@ export default class Invite extends Component { | |||
73 | render() { | 116 | render() { |
74 | const { form } = this; | 117 | const { form } = this; |
75 | const { intl } = this.context; | 118 | const { intl } = this.context; |
119 | const { embed, isInviteSuccessful, isLoadingInvite } = this.props; | ||
120 | |||
121 | const atLeastOneEmailAddress = form.$('invite') | ||
122 | .map(invite => invite.$('email').value) | ||
123 | .some(emailValue => emailValue.trim() !== ''); | ||
124 | |||
125 | const sendButtonClassName = classnames({ | ||
126 | auth__button: true, | ||
127 | 'invite__embed--button': embed, | ||
128 | }); | ||
129 | |||
130 | const renderForm = ( | ||
131 | <div> | ||
132 | {this.state.showSuccessInfo && isInviteSuccessful && ( | ||
133 | <Appear> | ||
134 | <Infobox | ||
135 | type="success" | ||
136 | icon="checkbox-marked-circle-outline" | ||
137 | dismissable | ||
138 | > | ||
139 | {intl.formatMessage(messages.inviteSuccessInfo)} | ||
140 | </Infobox> | ||
141 | </Appear> | ||
142 | )} | ||
76 | 143 | ||
77 | return ( | ||
78 | <div className="auth__container auth__container--signup"> | ||
79 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> | 144 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
80 | <img | 145 | {!embed && (<img |
81 | src="./assets/images/logo.svg" | 146 | src="./assets/images/logo.svg" |
82 | className="auth__logo" | 147 | className="auth__logo" |
83 | alt="" | 148 | alt="" |
84 | /> | 149 | />)} |
85 | <h1> | 150 | <h1 className={embed && 'invite__embed'}> |
86 | {intl.formatMessage(messages.headline)} | 151 | {intl.formatMessage(messages.headline)} |
87 | </h1> | 152 | </h1> |
88 | {form.$('invite').map(invite => ( | 153 | {form.$('invite').map(invite => ( |
@@ -95,17 +160,30 @@ export default class Invite extends Component { | |||
95 | ))} | 160 | ))} |
96 | <Button | 161 | <Button |
97 | type="submit" | 162 | type="submit" |
98 | className="auth__button" | 163 | className={sendButtonClassName} |
164 | disabled={!atLeastOneEmailAddress} | ||
99 | label={intl.formatMessage(messages.submitButtonLabel)} | 165 | label={intl.formatMessage(messages.submitButtonLabel)} |
166 | loaded={!isLoadingInvite} | ||
100 | /> | 167 | /> |
101 | <Link | 168 | {!embed && (<Link |
102 | to="/" | 169 | to="/" |
103 | className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" | 170 | className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" |
104 | > | 171 | > |
105 | {intl.formatMessage(messages.skipButtonLabel)} | 172 | {intl.formatMessage(messages.skipButtonLabel)} |
106 | </Link> | 173 | </Link>)} |
107 | </form> | 174 | </form> |
108 | </div> | 175 | </div> |
109 | ); | 176 | ); |
177 | |||
178 | return ( | ||
179 | <div className={!embed ? 'auth__container auth__container--signup' : 'settings__main'}> | ||
180 | {embed && ( | ||
181 | <div className="settings__header"> | ||
182 | <h1>{this.context.intl.formatMessage(messages.settingsHeadline)}</h1> | ||
183 | </div> | ||
184 | )} | ||
185 | {!embed ? <div>{renderForm}</div> : <div className="settings__body invite__form">{renderForm}</div>} | ||
186 | </div> | ||
187 | ); | ||
110 | } | 188 | } |
111 | } | 189 | } |
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js index 67e92849d..4a3cd6776 100644 --- a/src/components/auth/Login.js +++ b/src/components/auth/Login.js | |||
@@ -76,12 +76,12 @@ export default class Login extends Component { | |||
76 | email: { | 76 | email: { |
77 | label: this.context.intl.formatMessage(messages.emailLabel), | 77 | label: this.context.intl.formatMessage(messages.emailLabel), |
78 | value: '', | 78 | value: '', |
79 | validate: [required, email], | 79 | validators: [required, email], |
80 | }, | 80 | }, |
81 | password: { | 81 | password: { |
82 | label: this.context.intl.formatMessage(messages.passwordLabel), | 82 | label: this.context.intl.formatMessage(messages.passwordLabel), |
83 | value: '', | 83 | value: '', |
84 | validate: [required], | 84 | validators: [required], |
85 | type: 'password', | 85 | type: 'password', |
86 | }, | 86 | }, |
87 | }, | 87 | }, |
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js index d2b196853..5bcc80b6e 100644 --- a/src/components/auth/Password.js +++ b/src/components/auth/Password.js | |||
@@ -60,7 +60,7 @@ export default class Password extends Component { | |||
60 | email: { | 60 | email: { |
61 | label: this.context.intl.formatMessage(messages.emailLabel), | 61 | label: this.context.intl.formatMessage(messages.emailLabel), |
62 | value: '', | 62 | value: '', |
63 | validate: [required, email], | 63 | validators: [required, email], |
64 | }, | 64 | }, |
65 | }, | 65 | }, |
66 | }, this.context.intl); | 66 | }, this.context.intl); |
diff --git a/src/components/auth/Pricing.js b/src/components/auth/Pricing.js index 761561a89..3cc8d5f6b 100644 --- a/src/components/auth/Pricing.js +++ b/src/components/auth/Pricing.js | |||
@@ -7,7 +7,7 @@ import { defineMessages, intlShape } from 'react-intl'; | |||
7 | // import Button from '../ui/Button'; | 7 | // import Button from '../ui/Button'; |
8 | import Loader from '../ui/Loader'; | 8 | import Loader from '../ui/Loader'; |
9 | import Appear from '../ui/effects/Appear'; | 9 | import Appear from '../ui/effects/Appear'; |
10 | import SubscriptionForm from '../../containers/ui/SubscriptionFormScreen'; | 10 | import SubscriptionForm from '../../containers/subscription/SubscriptionFormScreen'; |
11 | 11 | ||
12 | const messages = defineMessages({ | 12 | const messages = defineMessages({ |
13 | headline: { | 13 | headline: { |
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js index a990a112e..219948274 100644 --- a/src/components/auth/Signup.js +++ b/src/components/auth/Signup.js | |||
@@ -82,7 +82,7 @@ export default class Signup extends Component { | |||
82 | fields: { | 82 | fields: { |
83 | accountType: { | 83 | accountType: { |
84 | value: 'individual', | 84 | value: 'individual', |
85 | validate: [required], | 85 | validators: [required], |
86 | options: [{ | 86 | options: [{ |
87 | value: 'individual', | 87 | value: 'individual', |
88 | label: 'Individual', | 88 | label: 'Individual', |
@@ -97,17 +97,17 @@ export default class Signup extends Component { | |||
97 | firstname: { | 97 | firstname: { |
98 | label: this.context.intl.formatMessage(messages.firstnameLabel), | 98 | label: this.context.intl.formatMessage(messages.firstnameLabel), |
99 | value: '', | 99 | value: '', |
100 | validate: [required], | 100 | validators: [required], |
101 | }, | 101 | }, |
102 | lastname: { | 102 | lastname: { |
103 | label: this.context.intl.formatMessage(messages.lastnameLabel), | 103 | label: this.context.intl.formatMessage(messages.lastnameLabel), |
104 | value: '', | 104 | value: '', |
105 | validate: [required], | 105 | validators: [required], |
106 | }, | 106 | }, |
107 | email: { | 107 | email: { |
108 | label: this.context.intl.formatMessage(messages.emailLabel), | 108 | label: this.context.intl.formatMessage(messages.emailLabel), |
109 | value: '', | 109 | value: '', |
110 | validate: [required, email], | 110 | validators: [required, email], |
111 | }, | 111 | }, |
112 | organization: { | 112 | organization: { |
113 | label: this.context.intl.formatMessage(messages.companyLabel), | 113 | label: this.context.intl.formatMessage(messages.companyLabel), |
@@ -116,7 +116,7 @@ export default class Signup extends Component { | |||
116 | password: { | 116 | password: { |
117 | label: this.context.intl.formatMessage(messages.passwordLabel), | 117 | label: this.context.intl.formatMessage(messages.passwordLabel), |
118 | value: '', | 118 | value: '', |
119 | validate: [required, minLength(6)], | 119 | validators: [required, minLength(6)], |
120 | type: 'password', | 120 | type: 'password', |
121 | }, | 121 | }, |
122 | }, | 122 | }, |
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js index eb9fbb847..9e1c762a5 100644 --- a/src/components/auth/Welcome.js +++ b/src/components/auth/Welcome.js | |||
@@ -46,7 +46,7 @@ export default class Login extends Component { | |||
46 | </div> | 46 | </div> |
47 | </div> | 47 | </div> |
48 | <div className="welcome__buttons"> | 48 | <div className="welcome__buttons"> |
49 | <Link to={signupRoute} className="button"> | 49 | <Link to={signupRoute} className="button button__inverted"> |
50 | {intl.formatMessage(messages.signupButton)} | 50 | {intl.formatMessage(messages.signupButton)} |
51 | </Link> | 51 | </Link> |
52 | <Link to={loginRoute} className="button"> | 52 | <Link to={loginRoute} className="button"> |