diff options
author | 2019-08-05 13:24:35 +0200 | |
---|---|---|
committer | 2019-08-05 13:24:35 +0200 | |
commit | 76559f2895012803aed3256ce521b9cfff2f63b8 (patch) | |
tree | f511ed44ab8cb16af257e58ff960da1fd60c5876 /src/components | |
parent | Add trial onboarding during signup (diff) | |
download | ferdium-app-76559f2895012803aed3256ce521b9cfff2f63b8.tar.gz ferdium-app-76559f2895012803aed3256ce521b9cfff2f63b8.tar.zst ferdium-app-76559f2895012803aed3256ce521b9cfff2f63b8.zip |
WIP: add option to activate trial
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/TrialActivationInfoBar.js | 94 | ||||
-rw-r--r-- | src/components/layout/AppLayout.js | 37 | ||||
-rw-r--r-- | src/components/services/content/Services.js | 61 | ||||
-rw-r--r-- | src/components/settings/account/AccountDashboard.js | 134 | ||||
-rw-r--r-- | src/components/settings/settings/EditSettingsForm.js | 2 |
5 files changed, 226 insertions, 102 deletions
diff --git a/src/components/TrialActivationInfoBar.js b/src/components/TrialActivationInfoBar.js new file mode 100644 index 000000000..acdf51d08 --- /dev/null +++ b/src/components/TrialActivationInfoBar.js | |||
@@ -0,0 +1,94 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { defineMessages, intlShape } from 'react-intl'; | ||
4 | import ms from 'ms'; | ||
5 | import injectSheet from 'react-jss'; | ||
6 | import classnames from 'classnames'; | ||
7 | |||
8 | import InfoBar from './ui/InfoBar'; | ||
9 | |||
10 | const messages = defineMessages({ | ||
11 | message: { | ||
12 | id: 'infobar.trialActivated', | ||
13 | defaultMessage: '!!!Your trial was successfully activated. Happy messaging!', | ||
14 | }, | ||
15 | }); | ||
16 | |||
17 | const styles = { | ||
18 | notification: { | ||
19 | height: 'auto', | ||
20 | position: 'absolute', | ||
21 | top: -50, | ||
22 | transition: 'top 0.3s', | ||
23 | zIndex: 300, | ||
24 | width: 'calc(100% - 300px)', | ||
25 | }, | ||
26 | show: { | ||
27 | top: 0, | ||
28 | }, | ||
29 | }; | ||
30 | |||
31 | @injectSheet(styles) | ||
32 | class TrialActivationInfoBar extends Component { | ||
33 | static propTypes = { | ||
34 | // eslint-disable-next-line | ||
35 | classes: PropTypes.object.isRequired, | ||
36 | }; | ||
37 | |||
38 | static contextTypes = { | ||
39 | intl: intlShape, | ||
40 | }; | ||
41 | |||
42 | state = { | ||
43 | showing: false, | ||
44 | removed: false, | ||
45 | } | ||
46 | |||
47 | componentDidMount() { | ||
48 | setTimeout(() => { | ||
49 | this.setState({ | ||
50 | showing: true, | ||
51 | }); | ||
52 | }, 0); | ||
53 | |||
54 | setTimeout(() => { | ||
55 | this.setState({ | ||
56 | showing: false, | ||
57 | }); | ||
58 | }, ms('6s')); | ||
59 | |||
60 | setTimeout(() => { | ||
61 | this.setState({ | ||
62 | removed: true, | ||
63 | }); | ||
64 | }, ms('7s')); | ||
65 | } | ||
66 | |||
67 | render() { | ||
68 | const { classes } = this.props; | ||
69 | const { showing, removed } = this.state; | ||
70 | const { intl } = this.context; | ||
71 | |||
72 | if (removed) return null; | ||
73 | |||
74 | return ( | ||
75 | <div | ||
76 | className={classnames({ | ||
77 | [classes.notification]: true, | ||
78 | [classes.show]: showing, | ||
79 | })} | ||
80 | > | ||
81 | <InfoBar | ||
82 | type="primary" | ||
83 | position="top" | ||
84 | sticky | ||
85 | > | ||
86 | <span className="mdi mdi-information" /> | ||
87 | {intl.formatMessage(messages.message)} | ||
88 | </InfoBar> | ||
89 | </div> | ||
90 | ); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | export default TrialActivationInfoBar; | ||
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index ebb9849ea..1976f5a50 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -17,6 +17,7 @@ import { isWindows } from '../../environment'; | |||
17 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; | 17 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; |
18 | import { workspaceStore } from '../../features/workspaces'; | 18 | import { workspaceStore } from '../../features/workspaces'; |
19 | import AppUpdateInfoBar from '../AppUpdateInfoBar'; | 19 | import AppUpdateInfoBar from '../AppUpdateInfoBar'; |
20 | import TrialActivationInfoBar from '../TrialActivationInfoBar'; | ||
20 | 21 | ||
21 | function createMarkup(HTMLString) { | 22 | function createMarkup(HTMLString) { |
22 | return { __html: HTMLString }; | 23 | return { __html: HTMLString }; |
@@ -57,7 +58,6 @@ class AppLayout extends Component { | |||
57 | services: PropTypes.element.isRequired, | 58 | services: PropTypes.element.isRequired, |
58 | children: PropTypes.element, | 59 | children: PropTypes.element, |
59 | news: MobxPropTypes.arrayOrObservableArray.isRequired, | 60 | news: MobxPropTypes.arrayOrObservableArray.isRequired, |
60 | // isOnline: PropTypes.bool.isRequired, | ||
61 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, | 61 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, |
62 | appUpdateIsDownloaded: PropTypes.bool.isRequired, | 62 | appUpdateIsDownloaded: PropTypes.bool.isRequired, |
63 | nextAppReleaseVersion: PropTypes.string, | 63 | nextAppReleaseVersion: PropTypes.string, |
@@ -69,6 +69,7 @@ class AppLayout extends Component { | |||
69 | retryRequiredRequests: PropTypes.func.isRequired, | 69 | retryRequiredRequests: PropTypes.func.isRequired, |
70 | areRequiredRequestsLoading: PropTypes.bool.isRequired, | 70 | areRequiredRequestsLoading: PropTypes.bool.isRequired, |
71 | isDelayAppScreenVisible: PropTypes.bool.isRequired, | 71 | isDelayAppScreenVisible: PropTypes.bool.isRequired, |
72 | hasActivatedTrial: PropTypes.bool.isRequired, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static defaultProps = { | 75 | static defaultProps = { |
@@ -88,7 +89,6 @@ class AppLayout extends Component { | |||
88 | sidebar, | 89 | sidebar, |
89 | services, | 90 | services, |
90 | children, | 91 | children, |
91 | // isOnline, | ||
92 | news, | 92 | news, |
93 | showServicesUpdatedInfoBar, | 93 | showServicesUpdatedInfoBar, |
94 | appUpdateIsDownloaded, | 94 | appUpdateIsDownloaded, |
@@ -101,6 +101,7 @@ class AppLayout extends Component { | |||
101 | retryRequiredRequests, | 101 | retryRequiredRequests, |
102 | areRequiredRequestsLoading, | 102 | areRequiredRequestsLoading, |
103 | isDelayAppScreenVisible, | 103 | isDelayAppScreenVisible, |
104 | hasActivatedTrial, | ||
104 | } = this.props; | 105 | } = this.props; |
105 | 106 | ||
106 | const { intl } = this.context; | 107 | const { intl } = this.context; |
@@ -125,26 +126,20 @@ class AppLayout extends Component { | |||
125 | <span dangerouslySetInnerHTML={createMarkup(item.message)} /> | 126 | <span dangerouslySetInnerHTML={createMarkup(item.message)} /> |
126 | </InfoBar> | 127 | </InfoBar> |
127 | ))} | 128 | ))} |
128 | {/* {!isOnline && ( | 129 | {hasActivatedTrial && ( |
129 | <InfoBar | 130 | <TrialActivationInfoBar /> |
130 | type="danger" | 131 | )} |
131 | sticky | ||
132 | > | ||
133 | <span className="mdi mdi-flash" /> | ||
134 | {intl.formatMessage(globalMessages.notConnectedToTheInternet)} | ||
135 | </InfoBar> | ||
136 | )} */} | ||
137 | {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( | 132 | {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( |
138 | <InfoBar | 133 | <InfoBar |
139 | type="danger" | 134 | type="danger" |
140 | ctaLabel="Try again" | 135 | ctaLabel="Try again" |
141 | ctaLoading={areRequiredRequestsLoading} | 136 | ctaLoading={areRequiredRequestsLoading} |
142 | sticky | 137 | sticky |
143 | onClick={retryRequiredRequests} | 138 | onClick={retryRequiredRequests} |
144 | > | 139 | > |
145 | <span className="mdi mdi-flash" /> | 140 | <span className="mdi mdi-flash" /> |
146 | {intl.formatMessage(messages.requiredRequestsFailed)} | 141 | {intl.formatMessage(messages.requiredRequestsFailed)} |
147 | </InfoBar> | 142 | </InfoBar> |
148 | )} | 143 | )} |
149 | {showServicesUpdatedInfoBar && ( | 144 | {showServicesUpdatedInfoBar && ( |
150 | <InfoBar | 145 | <InfoBar |
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index 7f1624003..b71ddd8e6 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js | |||
@@ -26,7 +26,8 @@ const styles = { | |||
26 | confettiContainer: { | 26 | confettiContainer: { |
27 | position: 'absolute', | 27 | position: 'absolute', |
28 | width: '100%', | 28 | width: '100%', |
29 | zIndex: 0, | 29 | zIndex: 9999, |
30 | pointerEvents: 'none', | ||
30 | }, | 31 | }, |
31 | }; | 32 | }; |
32 | 33 | ||
@@ -41,6 +42,7 @@ export default @observer @injectSheet(styles) class Services extends Component { | |||
41 | openSettings: PropTypes.func.isRequired, | 42 | openSettings: PropTypes.func.isRequired, |
42 | update: PropTypes.func.isRequired, | 43 | update: PropTypes.func.isRequired, |
43 | userHasCompletedSignup: PropTypes.bool.isRequired, | 44 | userHasCompletedSignup: PropTypes.bool.isRequired, |
45 | hasActivatedTrial: PropTypes.bool.isRequired, | ||
44 | classes: PropTypes.object.isRequired, | 46 | classes: PropTypes.object.isRequired, |
45 | }; | 47 | }; |
46 | 48 | ||
@@ -75,6 +77,7 @@ export default @observer @injectSheet(styles) class Services extends Component { | |||
75 | openSettings, | 77 | openSettings, |
76 | update, | 78 | update, |
77 | userHasCompletedSignup, | 79 | userHasCompletedSignup, |
80 | hasActivatedTrial, | ||
78 | classes, | 81 | classes, |
79 | } = this.props; | 82 | } = this.props; |
80 | 83 | ||
@@ -84,37 +87,37 @@ export default @observer @injectSheet(styles) class Services extends Component { | |||
84 | 87 | ||
85 | const { intl } = this.context; | 88 | const { intl } = this.context; |
86 | 89 | ||
90 | console.log('hasActivatedTrial', hasActivatedTrial, (userHasCompletedSignup || hasActivatedTrial)); | ||
91 | |||
87 | return ( | 92 | return ( |
88 | <div className="services"> | 93 | <div className="services"> |
94 | {(userHasCompletedSignup || hasActivatedTrial) && ( | ||
95 | <div className={classes.confettiContainer}> | ||
96 | <Confetti | ||
97 | width={window.width} | ||
98 | height={window.height} | ||
99 | numberOfPieces={showConfetti ? 200 : 0} | ||
100 | /> | ||
101 | </div> | ||
102 | )} | ||
89 | {services.length === 0 && ( | 103 | {services.length === 0 && ( |
90 | <> | 104 | <Appear |
91 | {userHasCompletedSignup && ( | 105 | timeout={1500} |
92 | <div className={classes.confettiContainer}> | 106 | transitionName="slideUp" |
93 | <Confetti | 107 | > |
94 | width={window.width} | 108 | <div className="services__no-service"> |
95 | height={window.height} | 109 | <img src="./assets/images/logo.svg" alt="" /> |
96 | numberOfPieces={showConfetti ? 200 : 0} | 110 | <h1>{intl.formatMessage(messages.welcome)}</h1> |
97 | /> | 111 | <Appear |
98 | </div> | 112 | timeout={300} |
99 | )} | 113 | transitionName="slideUp" |
100 | <Appear | 114 | > |
101 | timeout={1500} | 115 | <Link to="/settings/recipes" className="button"> |
102 | transitionName="slideUp" | 116 | {intl.formatMessage(messages.getStarted)} |
103 | > | 117 | </Link> |
104 | <div className="services__no-service"> | 118 | </Appear> |
105 | <img src="./assets/images/logo.svg" alt="" /> | 119 | </div> |
106 | <h1>{intl.formatMessage(messages.welcome)}</h1> | 120 | </Appear> |
107 | <Appear | ||
108 | timeout={300} | ||
109 | transitionName="slideUp" | ||
110 | > | ||
111 | <Link to="/settings/recipes" className="button"> | ||
112 | {intl.formatMessage(messages.getStarted)} | ||
113 | </Link> | ||
114 | </Appear> | ||
115 | </div> | ||
116 | </Appear> | ||
117 | </> | ||
118 | )} | 121 | )} |
119 | {services.map(service => ( | 122 | {services.map(service => ( |
120 | <ServiceView | 123 | <ServiceView |
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index 3f6964b6b..0366dc1ee 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js | |||
@@ -135,62 +135,96 @@ export default @observer class AccountDashboard extends Component { | |||
135 | )} | 135 | )} |
136 | 136 | ||
137 | {!userInfoRequestFailed && ( | 137 | {!userInfoRequestFailed && ( |
138 | <Fragment> | 138 | <> |
139 | {!isLoading && ( | 139 | {!isLoading && ( |
140 | <div className="account"> | 140 | <> |
141 | <div className="account__box account__box--flex"> | 141 | <div className="account"> |
142 | <div className="account__avatar"> | 142 | <div className="account__box account__box--flex"> |
143 | <img | 143 | <div className="account__avatar"> |
144 | src="./assets/images/logo.svg" | 144 | <img |
145 | alt="" | 145 | src="./assets/images/logo.svg" |
146 | /> | 146 | alt="" |
147 | </div> | 147 | /> |
148 | <div className="account__info"> | 148 | </div> |
149 | <h2> | 149 | <div className="account__info"> |
150 | <span className="username">{`${user.firstname} ${user.lastname}`}</span> | 150 | <h2> |
151 | {user.isPremium && ( | 151 | <span className="username">{`${user.firstname} ${user.lastname}`}</span> |
152 | <> | 152 | {user.isPremium && ( |
153 | {' '} | ||
154 | <ProBadge /> | ||
155 | <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span> | ||
156 | </> | ||
157 | )} | ||
158 | </h2> | ||
159 | {user.organization && `${user.organization}, `} | ||
160 | {user.email} | ||
161 | {user.isPremium && ( | ||
162 | <div className="manage-user-links"> | ||
163 | <Button | ||
164 | label={intl.formatMessage(messages.accountEditButton)} | ||
165 | className="franz-form__button--inverted" | ||
166 | onClick={openEditAccount} | ||
167 | /> | ||
168 | {user.isSubscriptionOwner && ( | ||
169 | <> | 153 | <> |
170 | <Button | 154 | {' '} |
171 | label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} | 155 | <ProBadge /> |
172 | className="franz-form__button--inverted" | 156 | {/* <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span> */} |
173 | onClick={openBilling} | ||
174 | /> | ||
175 | <Button | ||
176 | label={intl.formatMessage(messages.invoicesButton)} | ||
177 | className="franz-form__button--inverted" | ||
178 | onClick={openInvoices} | ||
179 | /> | ||
180 | </> | 157 | </> |
181 | )} | 158 | )} |
182 | </div> | 159 | </h2> |
160 | <p> | ||
161 | {user.organization && `${user.organization}, `} | ||
162 | {user.email} | ||
163 | </p> | ||
164 | {user.isPremium && ( | ||
165 | <div className="manage-user-links"> | ||
166 | <Button | ||
167 | label={intl.formatMessage(messages.accountEditButton)} | ||
168 | className="franz-form__button--inverted" | ||
169 | onClick={openEditAccount} | ||
170 | /> | ||
171 | {/* {user.isSubscriptionOwner && ( | ||
172 | <> | ||
173 | <Button | ||
174 | label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} | ||
175 | className="franz-form__button--inverted" | ||
176 | onClick={openBilling} | ||
177 | /> | ||
178 | <Button | ||
179 | label={intl.formatMessage(messages.invoicesButton)} | ||
180 | className="franz-form__button--inverted" | ||
181 | onClick={openInvoices} | ||
182 | /> | ||
183 | </> | ||
184 | )} */} | ||
185 | </div> | ||
186 | )} | ||
187 | </div> | ||
188 | {!user.isPremium && ( | ||
189 | <Button | ||
190 | label={intl.formatMessage(messages.accountEditButton)} | ||
191 | className="franz-form__button--inverted" | ||
192 | onClick={openEditAccount} | ||
193 | /> | ||
183 | )} | 194 | )} |
184 | </div> | 195 | </div> |
185 | {!user.isPremium && ( | ||
186 | <Button | ||
187 | label={intl.formatMessage(messages.accountEditButton)} | ||
188 | className="franz-form__button--inverted" | ||
189 | onClick={openEditAccount} | ||
190 | /> | ||
191 | )} | ||
192 | </div> | 196 | </div> |
193 | </div> | 197 | {user.isSubscriptionOwner && ( |
198 | <div className="account"> | ||
199 | <div className="account__box"> | ||
200 | <h2> | ||
201 | Your license: {user.team.plan} | ||
202 | </h2> | ||
203 | {user.team.isTrial && ( | ||
204 | <> | ||
205 | <p> | ||
206 | Trial ends in 14 days | ||
207 | </p> | ||
208 | </> | ||
209 | )} | ||
210 | {user.isPremium && ( | ||
211 | <div className="manage-user-links"> | ||
212 | <Button | ||
213 | label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} | ||
214 | className="franz-form__button--inverted" | ||
215 | onClick={openBilling} | ||
216 | /> | ||
217 | <Button | ||
218 | label={intl.formatMessage(messages.invoicesButton)} | ||
219 | className="franz-form__button--inverted" | ||
220 | onClick={openInvoices} | ||
221 | /> | ||
222 | </div> | ||
223 | )} | ||
224 | </div> | ||
225 | </div> | ||
226 | )} | ||
227 | </> | ||
194 | )} | 228 | )} |
195 | 229 | ||
196 | {!user.isPremium && ( | 230 | {!user.isPremium && ( |
@@ -227,7 +261,7 @@ export default @observer class AccountDashboard extends Component { | |||
227 | )} | 261 | )} |
228 | </div> | 262 | </div> |
229 | </div> | 263 | </div> |
230 | </Fragment> | 264 | </> |
231 | )} | 265 | )} |
232 | </div> | 266 | </div> |
233 | <ReactTooltip place="right" type="dark" effect="solid" /> | 267 | <ReactTooltip place="right" type="dark" effect="solid" /> |
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 6d0811b1b..3f9e0a6bc 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -143,8 +143,6 @@ export default @observer class EditSettingsForm extends Component { | |||
143 | updateButtonLabelMessage = messages.buttonSearchForUpdate; | 143 | updateButtonLabelMessage = messages.buttonSearchForUpdate; |
144 | } | 144 | } |
145 | 145 | ||
146 | console.log('isSpellcheckerIncludedInCurrentPlan', isSpellcheckerIncludedInCurrentPlan); | ||
147 | |||
148 | return ( | 146 | return ( |
149 | <div className="settings__main"> | 147 | <div className="settings__main"> |
150 | <div className="settings__header"> | 148 | <div className="settings__header"> |