diff options
author | Amine Mouafik <amine@mouafik.fr> | 2019-12-18 15:49:26 +0100 |
---|---|---|
committer | Amine Mouafik <amine@mouafik.fr> | 2019-12-18 15:49:26 +0100 |
commit | fffa3875f888aef2109dc7d91dc681069786fc0b (patch) | |
tree | c96b67b275d8ebae6f793a0455a75ae8edc87d3c /src/components/settings | |
parent | Update Electron and Sentry for latest fixes (diff) | |
download | ferdium-app-fffa3875f888aef2109dc7d91dc681069786fc0b.tar.gz ferdium-app-fffa3875f888aef2109dc7d91dc681069786fc0b.tar.zst ferdium-app-fffa3875f888aef2109dc7d91dc681069786fc0b.zip |
Better handling of account settings (if using without account)
Diffstat (limited to 'src/components/settings')
-rw-r--r-- | src/components/settings/account/AccountDashboard.js | 316 |
1 files changed, 181 insertions, 135 deletions
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index 83dc34a52..7d6bad883 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js | |||
@@ -3,9 +3,7 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import { | 6 | import { ProBadge, H1, H2 } from '@meetfranz/ui'; |
7 | ProBadge, H1, H2, | ||
8 | } from '@meetfranz/ui'; | ||
9 | import moment from 'moment'; | 7 | import moment from 'moment'; |
10 | 8 | ||
11 | import Loader from '../../ui/Loader'; | 9 | import Loader from '../../ui/Loader'; |
@@ -13,6 +11,7 @@ import Button from '../../ui/Button'; | |||
13 | import Infobox from '../../ui/Infobox'; | 11 | import Infobox from '../../ui/Infobox'; |
14 | import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen'; | 12 | import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen'; |
15 | import { i18nPlanName } from '../../../helpers/plan-helpers'; | 13 | import { i18nPlanName } from '../../../helpers/plan-helpers'; |
14 | import { LOCAL_SERVER } from '../../../config'; | ||
16 | 15 | ||
17 | const messages = defineMessages({ | 16 | const messages = defineMessages({ |
18 | headline: { | 17 | headline: { |
@@ -69,11 +68,13 @@ const messages = defineMessages({ | |||
69 | }, | 68 | }, |
70 | deleteInfo: { | 69 | deleteInfo: { |
71 | id: 'settings.account.deleteInfo', | 70 | id: 'settings.account.deleteInfo', |
72 | defaultMessage: '!!!If you don\'t need your Ferdi account any longer, you can delete your account and all related data here.', | 71 | defaultMessage: |
72 | "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.", | ||
73 | }, | 73 | }, |
74 | deleteEmailSent: { | 74 | deleteEmailSent: { |
75 | id: 'settings.account.deleteEmailSent', | 75 | id: 'settings.account.deleteEmailSent', |
76 | defaultMessage: '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', | 76 | defaultMessage: |
77 | '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', | ||
77 | }, | 78 | }, |
78 | trial: { | 79 | trial: { |
79 | id: 'settings.account.trial', | 80 | id: 'settings.account.trial', |
@@ -89,7 +90,16 @@ const messages = defineMessages({ | |||
89 | }, | 90 | }, |
90 | trialUpdateBillingInformation: { | 91 | trialUpdateBillingInformation: { |
91 | id: 'settings.account.trialUpdateBillingInfo', | 92 | id: 'settings.account.trialUpdateBillingInfo', |
92 | defaultMessage: '!!!Please update your billing info to continue using {license} after your trial period.', | 93 | defaultMessage: |
94 | '!!!Please update your billing info to continue using {license} after your trial period.', | ||
95 | }, | ||
96 | accountUnavailable: { | ||
97 | id: 'settings.account.accountUnavailable', | ||
98 | defaultMessage: 'Account is unavailable', | ||
99 | }, | ||
100 | accountUnavailableInfo: { | ||
101 | id: 'settings.account.accountUnavailableInfo', | ||
102 | defaultMessage: 'You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.', | ||
93 | }, | 103 | }, |
94 | }); | 104 | }); |
95 | 105 | ||
@@ -110,6 +120,7 @@ class AccountDashboard extends Component { | |||
110 | upgradeToPro: PropTypes.func.isRequired, | 120 | upgradeToPro: PropTypes.func.isRequired, |
111 | openInvoices: PropTypes.func.isRequired, | 121 | openInvoices: PropTypes.func.isRequired, |
112 | onCloseSubscriptionWindow: PropTypes.func.isRequired, | 122 | onCloseSubscriptionWindow: PropTypes.func.isRequired, |
123 | server: PropTypes.string.isRequired, | ||
113 | }; | 124 | }; |
114 | 125 | ||
115 | static contextTypes = { | 126 | static contextTypes = { |
@@ -132,6 +143,7 @@ class AccountDashboard extends Component { | |||
132 | upgradeToPro, | 143 | upgradeToPro, |
133 | openInvoices, | 144 | openInvoices, |
134 | onCloseSubscriptionWindow, | 145 | onCloseSubscriptionWindow, |
146 | server, | ||
135 | } = this.props; | 147 | } = this.props; |
136 | const { intl } = this.context; | 148 | const { intl } = this.context; |
137 | 149 | ||
@@ -141,6 +153,8 @@ class AccountDashboard extends Component { | |||
141 | planName = i18nPlanName(user.team.plan, intl); | 153 | planName = i18nPlanName(user.team.plan, intl); |
142 | } | 154 | } |
143 | 155 | ||
156 | const isUsingWithoutAccount = server === LOCAL_SERVER; | ||
157 | |||
144 | return ( | 158 | return ( |
145 | <div className="settings__main"> | 159 | <div className="settings__main"> |
146 | <div className="settings__header"> | 160 | <div className="settings__header"> |
@@ -149,154 +163,186 @@ class AccountDashboard extends Component { | |||
149 | </span> | 163 | </span> |
150 | </div> | 164 | </div> |
151 | <div className="settings__body"> | 165 | <div className="settings__body"> |
152 | {isLoading && ( | 166 | {isUsingWithoutAccount && ( |
153 | <Loader /> | 167 | <> |
168 | <h1 style={{ marginBottom: 0 }}> | ||
169 | {intl.formatMessage(messages.accountUnavailable)} | ||
170 | </h1> | ||
171 | <p | ||
172 | className="settings__message" | ||
173 | style={{ | ||
174 | borderTop: 0, | ||
175 | marginTop: 0, | ||
176 | }} | ||
177 | > | ||
178 | {intl.formatMessage(messages.accountUnavailableInfo)} | ||
179 | </p> | ||
180 | </> | ||
154 | )} | 181 | )} |
182 | {!isUsingWithoutAccount && ( | ||
183 | <> | ||
184 | {isLoading && <Loader />} | ||
155 | 185 | ||
156 | {!isLoading && userInfoRequestFailed && ( | 186 | {!isLoading && userInfoRequestFailed && ( |
157 | <Infobox | 187 | <Infobox |
158 | icon="alert" | 188 | icon="alert" |
159 | type="danger" | 189 | type="danger" |
160 | ctaLabel={intl.formatMessage(messages.tryReloadUserInfoRequest)} | 190 | ctaLabel={intl.formatMessage( |
161 | ctaLoading={isLoading} | 191 | messages.tryReloadUserInfoRequest, |
162 | ctaOnClick={retryUserInfoRequest} | 192 | )} |
163 | > | 193 | ctaLoading={isLoading} |
164 | {intl.formatMessage(messages.userInfoRequestFailed)} | 194 | ctaOnClick={retryUserInfoRequest} |
165 | </Infobox> | 195 | > |
166 | )} | 196 | {intl.formatMessage(messages.userInfoRequestFailed)} |
197 | </Infobox> | ||
198 | )} | ||
167 | 199 | ||
168 | {!userInfoRequestFailed && ( | 200 | {!userInfoRequestFailed && ( |
169 | <> | ||
170 | {!isLoading && ( | ||
171 | <> | 201 | <> |
172 | <div className="account"> | 202 | {!isLoading && ( |
173 | <div className="account__box account__box--flex"> | 203 | <> |
174 | <div className="account__avatar"> | 204 | <div className="account"> |
175 | <img | 205 | <div className="account__box account__box--flex"> |
176 | src="./assets/images/logo.svg" | 206 | <div className="account__avatar"> |
177 | alt="" | 207 | <img src="./assets/images/logo.svg" alt="" /> |
178 | /> | 208 | </div> |
179 | </div> | 209 | <div className="account__info"> |
180 | <div className="account__info"> | 210 | <H1> |
181 | <H1> | 211 | <span className="username">{`${user.firstname} ${user.lastname}`}</span> |
182 | <span className="username">{`${user.firstname} ${user.lastname}`}</span> | 212 | {user.isPremium && ( |
183 | {user.isPremium && ( | 213 | <> |
184 | <> | 214 | {' '} |
185 | {' '} | 215 | <ProBadge /> |
186 | <ProBadge /> | 216 | </> |
187 | </> | 217 | )} |
188 | )} | 218 | </H1> |
189 | </H1> | 219 | <p> |
190 | <p> | 220 | {user.organization && `${user.organization}, `} |
191 | {user.organization && `${user.organization}, `} | 221 | {user.email} |
192 | {user.email} | 222 | </p> |
193 | </p> | 223 | {user.isPremium && ( |
194 | {user.isPremium && ( | 224 | <div className="manage-user-links"> |
195 | <div className="manage-user-links"> | 225 | <Button |
226 | label={intl.formatMessage( | ||
227 | messages.accountEditButton, | ||
228 | )} | ||
229 | className="franz-form__button--inverted" | ||
230 | onClick={openEditAccount} | ||
231 | /> | ||
232 | </div> | ||
233 | )} | ||
234 | </div> | ||
235 | {!user.isPremium && ( | ||
196 | <Button | 236 | <Button |
197 | label={intl.formatMessage(messages.accountEditButton)} | 237 | label={intl.formatMessage( |
238 | messages.accountEditButton, | ||
239 | )} | ||
198 | className="franz-form__button--inverted" | 240 | className="franz-form__button--inverted" |
199 | onClick={openEditAccount} | 241 | onClick={openEditAccount} |
200 | /> | 242 | /> |
201 | </div> | ||
202 | )} | ||
203 | </div> | ||
204 | {!user.isPremium && ( | ||
205 | <Button | ||
206 | label={intl.formatMessage(messages.accountEditButton)} | ||
207 | className="franz-form__button--inverted" | ||
208 | onClick={openEditAccount} | ||
209 | /> | ||
210 | )} | ||
211 | </div> | ||
212 | </div> | ||
213 | {user.isPremium && user.isSubscriptionOwner && ( | ||
214 | <div className="account"> | ||
215 | <div className="account__box"> | ||
216 | <H2> | ||
217 | {intl.formatMessage(messages.yourLicense)} | ||
218 | </H2> | ||
219 | <p> | ||
220 | Franz | ||
221 | {' '} | ||
222 | {isPremiumOverrideUser ? 'Premium' : planName} | ||
223 | {user.team.isTrial && ( | ||
224 | <> | ||
225 | {' – '} | ||
226 | {intl.formatMessage(messages.trial)} | ||
227 | </> | ||
228 | )} | 243 | )} |
229 | </p> | 244 | </div> |
230 | {user.team.isTrial && ( | 245 | </div> |
231 | <> | 246 | {user.isPremium && user.isSubscriptionOwner && ( |
232 | <br /> | 247 | <div className="account"> |
233 | <p> | 248 | <div className="account__box"> |
234 | {intl.formatMessage(messages.trialEndsIn, { | 249 | <H2>{intl.formatMessage(messages.yourLicense)}</H2> |
235 | duration: moment.duration(moment().diff(user.team.trialEnd)).humanize(), | ||
236 | })} | ||
237 | </p> | ||
238 | <p> | 250 | <p> |
239 | {intl.formatMessage(messages.trialUpdateBillingInformation, { | 251 | Franz |
240 | license: planName, | 252 | {' '} |
241 | })} | 253 | {isPremiumOverrideUser ? 'Premium' : planName} |
254 | {user.team.isTrial && ( | ||
255 | <> | ||
256 | {' – '} | ||
257 | {intl.formatMessage(messages.trial)} | ||
258 | </> | ||
259 | )} | ||
242 | </p> | 260 | </p> |
243 | </> | 261 | {user.team.isTrial && ( |
244 | )} | 262 | <> |
245 | {!isProUser && ( | 263 | <br /> |
246 | <div className="manage-user-links"> | 264 | <p> |
247 | <Button | 265 | {intl.formatMessage(messages.trialEndsIn, { |
248 | label={intl.formatMessage(messages.upgradeAccountToPro)} | 266 | duration: moment |
249 | className="franz-form__button--primary" | 267 | .duration( |
250 | onClick={upgradeToPro} | 268 | moment().diff(user.team.trialEnd), |
269 | ) | ||
270 | .humanize(), | ||
271 | })} | ||
272 | </p> | ||
273 | <p> | ||
274 | {intl.formatMessage( | ||
275 | messages.trialUpdateBillingInformation, | ||
276 | { | ||
277 | license: planName, | ||
278 | }, | ||
279 | )} | ||
280 | </p> | ||
281 | </> | ||
282 | )} | ||
283 | {!isProUser && ( | ||
284 | <div className="manage-user-links"> | ||
285 | <Button | ||
286 | label={intl.formatMessage( | ||
287 | messages.upgradeAccountToPro, | ||
288 | )} | ||
289 | className="franz-form__button--primary" | ||
290 | onClick={upgradeToPro} | ||
291 | /> | ||
292 | </div> | ||
293 | )} | ||
294 | <div className="manage-user-links"> | ||
295 | <Button | ||
296 | label={intl.formatMessage( | ||
297 | messages.manageSubscriptionButtonLabel, | ||
298 | )} | ||
299 | className="franz-form__button--inverted" | ||
300 | onClick={openBilling} | ||
301 | /> | ||
302 | <Button | ||
303 | label={intl.formatMessage( | ||
304 | messages.invoicesButton, | ||
305 | )} | ||
306 | className="franz-form__button--inverted" | ||
307 | onClick={openInvoices} | ||
308 | /> | ||
309 | </div> | ||
310 | </div> | ||
311 | </div> | ||
312 | )} | ||
313 | {!user.isPremium && ( | ||
314 | <div className="account franz-form"> | ||
315 | <div className="account__box"> | ||
316 | <SubscriptionForm | ||
317 | onCloseWindow={onCloseSubscriptionWindow} | ||
251 | /> | 318 | /> |
252 | </div> | 319 | </div> |
253 | )} | 320 | </div> |
254 | <div className="manage-user-links"> | 321 | )} |
255 | <Button | 322 | </> |
256 | label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} | 323 | )} |
257 | className="franz-form__button--inverted" | 324 | |
258 | onClick={openBilling} | 325 | <div className="account franz-form"> |
259 | /> | 326 | <div className="account__box"> |
327 | <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2> | ||
328 | {!isDeleteAccountSuccessful && ( | ||
329 | <div className="account__subscription"> | ||
330 | <p>{intl.formatMessage(messages.deleteInfo)}</p> | ||
260 | <Button | 331 | <Button |
261 | label={intl.formatMessage(messages.invoicesButton)} | 332 | label={intl.formatMessage(messages.deleteAccount)} |
262 | className="franz-form__button--inverted" | 333 | buttonType="danger" |
263 | onClick={openInvoices} | 334 | onClick={() => deleteAccount()} |
335 | loaded={!isLoadingDeleteAccount} | ||
264 | /> | 336 | /> |
265 | </div> | 337 | </div> |
266 | </div> | 338 | )} |
267 | </div> | 339 | {isDeleteAccountSuccessful && ( |
268 | )} | 340 | <p>{intl.formatMessage(messages.deleteEmailSent)}</p> |
269 | {!user.isPremium && ( | 341 | )} |
270 | <div className="account franz-form"> | ||
271 | <div className="account__box"> | ||
272 | <SubscriptionForm | ||
273 | onCloseWindow={onCloseSubscriptionWindow} | ||
274 | /> | ||
275 | </div> | ||
276 | </div> | 342 | </div> |
277 | )} | 343 | </div> |
278 | </> | 344 | </> |
279 | )} | 345 | )} |
280 | |||
281 | <div className="account franz-form"> | ||
282 | <div className="account__box"> | ||
283 | <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2> | ||
284 | {!isDeleteAccountSuccessful && ( | ||
285 | <div className="account__subscription"> | ||
286 | <p>{intl.formatMessage(messages.deleteInfo)}</p> | ||
287 | <Button | ||
288 | label={intl.formatMessage(messages.deleteAccount)} | ||
289 | buttonType="danger" | ||
290 | onClick={() => deleteAccount()} | ||
291 | loaded={!isLoadingDeleteAccount} | ||
292 | /> | ||
293 | </div> | ||
294 | )} | ||
295 | {isDeleteAccountSuccessful && ( | ||
296 | <p>{intl.formatMessage(messages.deleteEmailSent)}</p> | ||
297 | )} | ||
298 | </div> | ||
299 | </div> | ||
300 | </> | 346 | </> |
301 | )} | 347 | )} |
302 | </div> | 348 | </div> |