aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar haraldox <hnaumann+github@gmail.com>2018-02-02 19:46:20 +0100
committerLibravatar haraldox <hnaumann+github@gmail.com>2018-02-02 19:46:20 +0100
commitcb45601e87c6af08fc8336da13ac6a0bb38b8484 (patch)
tree9d0d1b2a148a9b245b2aa2e95bf667e7370b12cf
parentgot server callback and infobox working (diff)
downloadferdium-app-cb45601e87c6af08fc8336da13ac6a0bb38b8484.tar.gz
ferdium-app-cb45601e87c6af08fc8336da13ac6a0bb38b8484.tar.zst
ferdium-app-cb45601e87c6af08fc8336da13ac6a0bb38b8484.zip
finished embedded invite functionality
ADDED internationalization ADDED loading indicator in send button REMOVED query param `from`
-rw-r--r--src/components/auth/Invite.js28
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js2
-rw-r--r--src/components/ui/Link.js2
-rw-r--r--src/containers/settings/InviteScreen.js11
-rw-r--r--src/i18n/locales/en-US.json1
-rw-r--r--src/stores/UserStore.js3
6 files changed, 17 insertions, 30 deletions
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index dbbe58900..9f85c3152 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -33,6 +33,10 @@ const messages = defineMessages({
33 id: 'invite.skip.label', 33 id: 'invite.skip.label',
34 defaultMessage: '!!!I want to do this later', 34 defaultMessage: '!!!I want to do this later',
35 }, 35 },
36 inviteSuccessInfo: {
37 id: 'invite.successInfo',
38 defaultMessage: '!!!Invitations sent successfully',
39 }
36}); 40});
37 41
38@observer 42@observer
@@ -52,11 +56,11 @@ export default class Invite extends Component {
52 intl: intlShape, 56 intl: intlShape,
53 }; 57 };
54 58
55 state = { showSuccessMessage: false }; 59 state = { showSuccessInfo: false };
56 60
57 handlers = { 61 handlers = {
58 onChange: (field) => { 62 onChange: (field) => {
59 this.setState({ showSuccessMessage: false }) 63 this.setState({ showSuccessInfo: false })
60 } 64 }
61 }; 65 };
62 66
@@ -83,20 +87,15 @@ export default class Invite extends Component {
83 87
84 submit(e) { 88 submit(e) {
85 e.preventDefault(); 89 e.preventDefault();
86 90
87 const from = this.props.from;
88
89 this.form.submit({ 91 this.form.submit({
90 onSuccess: (form) => { 92 onSuccess: (form) => {
91 this.props.onSubmit({ 93 this.props.onSubmit({ invites: form.values().invite });
92 invites: form.values().invite,
93 from
94 });
95 94
96 this.form.clear() 95 this.form.clear()
97 // 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 ;(
98 document.querySelector('input:first-child').focus() 97 document.querySelector('input:first-child').focus()
99 this.setState({ showSuccessMessage: true }) 98 this.setState({ showSuccessInfo: true })
100 }, 99 },
101 onError: () => {}, 100 onError: () => {},
102 }); 101 });
@@ -105,7 +104,7 @@ export default class Invite extends Component {
105 render() { 104 render() {
106 const { form } = this; 105 const { form } = this;
107 const { intl } = this.context; 106 const { intl } = this.context;
108 const { from, embed, success, isInviteSuccessful } = this.props; 107 const { embed, isInviteSuccessful, isLoadingInvite } = this.props;
109 108
110 const atLeastOneEmailAddress = form.$('invite') 109 const atLeastOneEmailAddress = form.$('invite')
111 .map(invite => invite.$('email').value) 110 .map(invite => invite.$('email').value)
@@ -118,13 +117,13 @@ export default class Invite extends Component {
118 117
119 return ( 118 return (
120 <div> 119 <div>
121 {this.state.showSuccessMessage && isInviteSuccessful && (<Appear> 120 {this.state.showSuccessInfo && isInviteSuccessful && (<Appear>
122 <Infobox 121 <Infobox
123 type="success" 122 type="success"
124 icon="checkbox-marked-circle-outline" 123 icon="checkbox-marked-circle-outline"
125 dismissable 124 dismissable
126 > 125 >
127 Great Success! 126 {intl.formatMessage(messages.inviteSuccessInfo)}
128 </Infobox> 127 </Infobox>
129 </Appear>)} 128 </Appear>)}
130 129
@@ -150,9 +149,10 @@ export default class Invite extends Component {
150 className={sendButtonClassName} 149 className={sendButtonClassName}
151 disabled={!atLeastOneEmailAddress} 150 disabled={!atLeastOneEmailAddress}
152 label={intl.formatMessage(messages.submitButtonLabel)} 151 label={intl.formatMessage(messages.submitButtonLabel)}
152 loaded={!isLoadingInvite}
153 /> 153 />
154 {!embed && (<Link 154 {!embed && (<Link
155 to={from || '/'} 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)}
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 3f42cd10e..66539f324 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="/settings/invite?from=/settings/invite" 78 to="/settings/invite"
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 b09ef026e..693be84ea 100644
--- a/src/components/ui/Link.js
+++ b/src/components/ui/Link.js
@@ -37,8 +37,6 @@ export default class Link extends Component {
37 37
38 const match = matchRoute(filter, router.location.pathname); 38 const match = matchRoute(filter, router.location.pathname);
39 39
40 console.log(filter, strictFilter, router.location.pathname, router.location.search, match)
41
42 const linkClasses = classnames({ 40 const linkClasses = classnames({
43 [`${className}`]: true, 41 [`${className}`]: true,
44 [`${activeClassName}`]: match, 42 [`${activeClassName}`]: match,
diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js
index a1170bfec..63e88765e 100644
--- a/src/containers/settings/InviteScreen.js
+++ b/src/containers/settings/InviteScreen.js
@@ -31,9 +31,6 @@ export default class InviteScreen extends Component {
31 const { actions, location } = this.props; 31 const { actions, location } = this.props;
32 const { user } = this.props.stores; 32 const { user } = this.props.stores;
33 33
34 const isLoadingInvite = user.inviteRequest.isExecuting;
35 const isInviteSuccessful = user.inviteRequest.wasExecuted && !user.inviteRequest.isError;
36
37 return ( 34 return (
38 <div className="settings__main"> 35 <div className="settings__main">
39 <div className="settings__header"> 36 <div className="settings__header">
@@ -42,12 +39,9 @@ export default class InviteScreen extends Component {
42 <div className="settings__body invite__form"> 39 <div className="settings__body invite__form">
43 <Invite 40 <Invite
44 onSubmit={actions.user.invite} 41 onSubmit={actions.user.invite}
45 // status={user.actionStatus} // not needed
46 isLoadingInvite={user.inviteRequest.isExecuting} 42 isLoadingInvite={user.inviteRequest.isExecuting}
47 isInviteSuccessful={user.inviteRequest.wasExecuted && !user.inviteRequest.isError} 43 isInviteSuccessful={user.inviteRequest.wasExecuted && !user.inviteRequest.isError}
48 from={location.query.from}
49 embed={true} 44 embed={true}
50 success={location.query.success}
51 /> 45 />
52 </div> 46 </div>
53 </div> 47 </div>
@@ -61,9 +55,4 @@ InviteScreen.wrappedComponent.propTypes = {
61 invite: PropTypes.func.isRequired, 55 invite: PropTypes.func.isRequired,
62 }).isRequired, 56 }).isRequired,
63 }).isRequired, 57 }).isRequired,
64 location: PropTypes.shape({
65 query: PropTypes.shape({
66 from: PropTypes.string,
67 }),
68 }).isRequired,
69}; 58};
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index bd0863f64..29b979838 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -45,6 +45,7 @@
45 "invite.name.label": "Name", 45 "invite.name.label": "Name",
46 "invite.email.label": "Email address", 46 "invite.email.label": "Email address",
47 "invite.skip.label": "I want to do this later", 47 "invite.skip.label": "I want to do this later",
48 "invite.successInfo": "Invitations sent successfully",
48 "subscription.submit.label": "I want to support the development of Franz", 49 "subscription.submit.label": "I want to support the development of Franz",
49 "subscription.paymentSessionError": "Could not initialize payment form", 50 "subscription.paymentSessionError": "Could not initialize payment form",
50 "subscription.includedFeatures": "Paid Franz Premium Supporter Account includes", 51 "subscription.includedFeatures": "Paid Franz Premium Supporter Account includes",
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 82eab9f44..54627440a 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -163,8 +163,7 @@ export default class UserStore extends Store {
163 gaEvent('User', 'retrievePassword'); 163 gaEvent('User', 'retrievePassword');
164 } 164 }
165 165
166 // TODO: REFACTOR from -> fromRoute 166 @action async _invite({ invites }) {
167 @action async _invite({ invites, from }) {
168 const data = invites.filter(invite => invite.email !== ''); 167 const data = invites.filter(invite => invite.email !== '');
169 168
170 const response = await this.inviteRequest.execute(data)._promise; 169 const response = await this.inviteRequest.execute(data)._promise;