diff options
author | haraldox <hnaumann+github@gmail.com> | 2018-01-30 14:35:30 +0100 |
---|---|---|
committer | haraldox <hnaumann+github@gmail.com> | 2018-01-30 14:35:30 +0100 |
commit | 1d3f61150112af84bde1f5e681e7994a3f9a7e91 (patch) | |
tree | c4b7cfa0d1fe014ea1197d4ab9897535b6b0fbc3 /src | |
parent | ADDED invite button on settings navigation (diff) | |
download | ferdium-app-1d3f61150112af84bde1f5e681e7994a3f9a7e91.tar.gz ferdium-app-1d3f61150112af84bde1f5e681e7994a3f9a7e91.tar.zst ferdium-app-1d3f61150112af84bde1f5e681e7994a3f9a7e91.zip |
ADDED embedded invite screen in settings
reuses component `Invite`
Diffstat (limited to 'src')
-rw-r--r-- | src/app.js | 2 | ||||
-rw-r--r-- | src/components/auth/Invite.js | 24 | ||||
-rw-r--r-- | src/components/settings/navigation/SettingsNavigation.js | 2 | ||||
-rw-r--r-- | src/components/ui/Link.js | 2 | ||||
-rw-r--r-- | src/containers/auth/InviteScreen.js | 11 | ||||
-rw-r--r-- | src/containers/settings/InviteScreen.js | 48 | ||||
-rw-r--r-- | src/styles/invite.scss | 15 | ||||
-rw-r--r-- | src/styles/main.scss | 1 |
8 files changed, 90 insertions, 15 deletions
diff --git a/src/app.js b/src/app.js index 8e62776d2..edcf273dc 100644 --- a/src/app.js +++ b/src/app.js | |||
@@ -27,6 +27,7 @@ import EditServiceScreen from './containers/settings/EditServiceScreen'; | |||
27 | import AccountScreen from './containers/settings/AccountScreen'; | 27 | import AccountScreen from './containers/settings/AccountScreen'; |
28 | import EditUserScreen from './containers/settings/EditUserScreen'; | 28 | import EditUserScreen from './containers/settings/EditUserScreen'; |
29 | import EditSettingsScreen from './containers/settings/EditSettingsScreen'; | 29 | import EditSettingsScreen from './containers/settings/EditSettingsScreen'; |
30 | import InviteSettingsScreen from './containers/settings/InviteScreen'; | ||
30 | import WelcomeScreen from './containers/auth/WelcomeScreen'; | 31 | import WelcomeScreen from './containers/auth/WelcomeScreen'; |
31 | import LoginScreen from './containers/auth/LoginScreen'; | 32 | import LoginScreen from './containers/auth/LoginScreen'; |
32 | import PasswordScreen from './containers/auth/PasswordScreen'; | 33 | import PasswordScreen from './containers/auth/PasswordScreen'; |
@@ -74,6 +75,7 @@ window.addEventListener('load', () => { | |||
74 | <Route path="/settings/user" component={AccountScreen} /> | 75 | <Route path="/settings/user" component={AccountScreen} /> |
75 | <Route path="/settings/user/edit" component={EditUserScreen} /> | 76 | <Route path="/settings/user/edit" component={EditUserScreen} /> |
76 | <Route path="/settings/app" component={EditSettingsScreen} /> | 77 | <Route path="/settings/app" component={EditSettingsScreen} /> |
78 | <Route path="/settings/invite" component={InviteSettingsScreen} /> | ||
77 | </Route> | 79 | </Route> |
78 | </Route> | 80 | </Route> |
79 | <Route path="/auth" component={AuthLayoutContainer}> | 81 | <Route path="/auth" component={AuthLayoutContainer}> |
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js index fa83837ac..14dd6483d 100644 --- a/src/components/auth/Invite.js +++ b/src/components/auth/Invite.js | |||
@@ -3,6 +3,7 @@ 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 | ||
7 | import Form from '../../lib/Form'; | 8 | import Form from '../../lib/Form'; |
8 | import { email } from '../../helpers/validation-helpers'; | 9 | import { email } from '../../helpers/validation-helpers'; |
@@ -37,10 +38,12 @@ export default class Invite extends Component { | |||
37 | static propTypes = { | 38 | static propTypes = { |
38 | onSubmit: PropTypes.func.isRequired, | 39 | onSubmit: PropTypes.func.isRequired, |
39 | from: PropTypes.string, | 40 | from: PropTypes.string, |
41 | embed: PropTypes.bool, | ||
40 | }; | 42 | }; |
41 | 43 | ||
42 | static defaultProps = { | 44 | static defaultProps = { |
43 | from: '/', | 45 | from: '/', |
46 | embed: false, | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | static contextTypes = { | 49 | static contextTypes = { |
@@ -78,21 +81,25 @@ export default class Invite extends Component { | |||
78 | render() { | 81 | render() { |
79 | const { form } = this; | 82 | const { form } = this; |
80 | const { intl } = this.context; | 83 | const { intl } = this.context; |
81 | const { from } = this.props; | 84 | const { from, embed } = this.props; |
82 | 85 | ||
83 | const atLeastOneEmailAddress = form.$('invite') | 86 | const atLeastOneEmailAddress = form.$('invite') |
84 | .map(invite => invite.$('email').value) | 87 | .map(invite => invite.$('email').value) |
85 | .some(emailValue => emailValue.trim() !== ''); | 88 | .some(emailValue => emailValue.trim() !== ''); |
86 | 89 | ||
90 | const sendButtonClassName = classnames({ | ||
91 | auth__button: true, | ||
92 | 'invite__embed--button': embed, | ||
93 | }); | ||
94 | |||
87 | return ( | 95 | return ( |
88 | <div className="auth__container auth__container--signup"> | ||
89 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> | 96 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
90 | <img | 97 | {!embed && (<img |
91 | src="./assets/images/logo.svg" | 98 | src="./assets/images/logo.svg" |
92 | className="auth__logo" | 99 | className="auth__logo" |
93 | alt="" | 100 | alt="" |
94 | /> | 101 | />)} |
95 | <h1> | 102 | <h1 className={embed && 'invite__embed'}> |
96 | {intl.formatMessage(messages.headline)} | 103 | {intl.formatMessage(messages.headline)} |
97 | </h1> | 104 | </h1> |
98 | {form.$('invite').map(invite => ( | 105 | {form.$('invite').map(invite => ( |
@@ -105,18 +112,17 @@ export default class Invite extends Component { | |||
105 | ))} | 112 | ))} |
106 | <Button | 113 | <Button |
107 | type="submit" | 114 | type="submit" |
108 | className="auth__button" | 115 | className={sendButtonClassName} |
109 | disabled={!atLeastOneEmailAddress} | 116 | disabled={!atLeastOneEmailAddress} |
110 | label={intl.formatMessage(messages.submitButtonLabel)} | 117 | label={intl.formatMessage(messages.submitButtonLabel)} |
111 | /> | 118 | /> |
112 | <Link | 119 | {!embed && (<Link |
113 | to={from || '/'} | 120 | to={from || '/'} |
114 | className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" | 121 | className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" |
115 | > | 122 | > |
116 | {intl.formatMessage(messages.skipButtonLabel)} | 123 | {intl.formatMessage(messages.skipButtonLabel)} |
117 | </Link> | 124 | </Link>)} |
118 | </form> | 125 | </form> |
119 | </div> | ||
120 | ); | 126 | ); |
121 | } | 127 | } |
122 | } | 128 | } |
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js index 3b4ada768..75ace53cc 100644 --- a/src/components/settings/navigation/SettingsNavigation.js +++ b/src/components/settings/navigation/SettingsNavigation.js | |||
@@ -75,7 +75,7 @@ export default class SettingsNavigation extends Component { | |||
75 | {intl.formatMessage(messages.settings)} | 75 | {intl.formatMessage(messages.settings)} |
76 | </Link> | 76 | </Link> |
77 | <Link | 77 | <Link |
78 | to="/auth/signup/invite" | 78 | to="/settings/invite?from=/settings&embed=true" |
79 | className="settings-navigation__link" | 79 | className="settings-navigation__link" |
80 | activeClassName="is-active" | 80 | activeClassName="is-active" |
81 | > | 81 | > |
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js index 693be84ea..aabb9e0a6 100644 --- a/src/components/ui/Link.js +++ b/src/components/ui/Link.js | |||
@@ -35,7 +35,7 @@ export default class Link extends Component { | |||
35 | filter = `${to}`; | 35 | filter = `${to}`; |
36 | } | 36 | } |
37 | 37 | ||
38 | const match = matchRoute(filter, router.location.pathname); | 38 | const match = matchRoute(filter, router.location.pathname + router.location.search); |
39 | 39 | ||
40 | const linkClasses = classnames({ | 40 | const linkClasses = classnames({ |
41 | [`${className}`]: true, | 41 | [`${className}`]: true, |
diff --git a/src/containers/auth/InviteScreen.js b/src/containers/auth/InviteScreen.js index 42a00f1fc..7102df0b9 100644 --- a/src/containers/auth/InviteScreen.js +++ b/src/containers/auth/InviteScreen.js | |||
@@ -17,10 +17,13 @@ export default class InviteScreen extends Component { | |||
17 | } = this.props; | 17 | } = this.props; |
18 | 18 | ||
19 | return ( | 19 | return ( |
20 | <Invite | 20 | <div className="auth__container auth__container--signup"> |
21 | onSubmit={actions.user.invite} | 21 | <Invite |
22 | from={location.query.from} | 22 | onSubmit={actions.user.invite} |
23 | /> | 23 | from={location.query.from} |
24 | embed={false} | ||
25 | /> | ||
26 | </div> | ||
24 | ); | 27 | ); |
25 | } | 28 | } |
26 | } | 29 | } |
diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js new file mode 100644 index 000000000..5a7c64f73 --- /dev/null +++ b/src/containers/settings/InviteScreen.js | |||
@@ -0,0 +1,48 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { inject, observer } from 'mobx-react'; | ||
4 | import Invite from '../../components/auth/Invite'; | ||
5 | import { gaPage } from '../../lib/analytics'; | ||
6 | |||
7 | @inject('stores', 'actions') @observer | ||
8 | export default class InviteScreen extends Component { | ||
9 | componentDidMount() { | ||
10 | gaPage('Settings/Invite'); | ||
11 | } | ||
12 | |||
13 | render() { | ||
14 | const { | ||
15 | actions, | ||
16 | location, | ||
17 | } = this.props; | ||
18 | |||
19 | return ( | ||
20 | <div className="settings__main"> | ||
21 | <div className="settings__header"> | ||
22 | {/* <h1>{intl.formatMessage(messages.headline)}</h1> */} | ||
23 | <h1>Invite Friends</h1> | ||
24 | </div> | ||
25 | <div className="settings__body invite__form"> | ||
26 | <Invite | ||
27 | onSubmit={actions.user.invite} | ||
28 | from={location.query.from} | ||
29 | embed={location.query.embed} | ||
30 | /> | ||
31 | </div> | ||
32 | </div> | ||
33 | ); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | InviteScreen.wrappedComponent.propTypes = { | ||
38 | actions: PropTypes.shape({ | ||
39 | user: PropTypes.shape({ | ||
40 | invite: PropTypes.func.isRequired, | ||
41 | }).isRequired, | ||
42 | }).isRequired, | ||
43 | location: PropTypes.shape({ | ||
44 | query: PropTypes.shape({ | ||
45 | from: PropTypes.string, | ||
46 | }), | ||
47 | }).isRequired, | ||
48 | }; | ||
diff --git a/src/styles/invite.scss b/src/styles/invite.scss new file mode 100644 index 000000000..bfb1a4b6b --- /dev/null +++ b/src/styles/invite.scss | |||
@@ -0,0 +1,15 @@ | |||
1 | .invite__form { | ||
2 | /* play with values to see different layouts */ | ||
3 | // display: flex; | ||
4 | align-items: center; | ||
5 | align-self: center; | ||
6 | justify-content: center; | ||
7 | } | ||
8 | |||
9 | .invite__embed { | ||
10 | text-align: center; | ||
11 | } | ||
12 | |||
13 | .invite__embed--button { | ||
14 | width: 100%; | ||
15 | } \ No newline at end of file | ||
diff --git a/src/styles/main.scss b/src/styles/main.scss index 261396f6f..446bdca14 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss | |||
@@ -27,6 +27,7 @@ $mdi-font-path: '../node_modules/mdi/fonts'; | |||
27 | @import './subscription.scss'; | 27 | @import './subscription.scss'; |
28 | @import './subscription-popup.scss'; | 28 | @import './subscription-popup.scss'; |
29 | @import './content-tabs.scss'; | 29 | @import './content-tabs.scss'; |
30 | @import './invite.scss'; | ||
30 | 31 | ||
31 | // form | 32 | // form |
32 | @import './input.scss'; | 33 | @import './input.scss'; |