diff options
author | 2018-02-02 19:46:20 +0100 | |
---|---|---|
committer | 2018-02-02 19:46:20 +0100 | |
commit | cb45601e87c6af08fc8336da13ac6a0bb38b8484 (patch) | |
tree | 9d0d1b2a148a9b245b2aa2e95bf667e7370b12cf | |
parent | got server callback and infobox working (diff) | |
download | ferdium-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.js | 28 | ||||
-rw-r--r-- | src/components/settings/navigation/SettingsNavigation.js | 2 | ||||
-rw-r--r-- | src/components/ui/Link.js | 2 | ||||
-rw-r--r-- | src/containers/settings/InviteScreen.js | 11 | ||||
-rw-r--r-- | src/i18n/locales/en-US.json | 1 | ||||
-rw-r--r-- | src/stores/UserStore.js | 3 |
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; |