aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/settings/account
diff options
context:
space:
mode:
authorLibravatar Amine Mouafik <amine@mouafik.fr>2019-12-18 15:49:26 +0100
committerLibravatar Amine Mouafik <amine@mouafik.fr>2019-12-18 15:49:26 +0100
commitfffa3875f888aef2109dc7d91dc681069786fc0b (patch)
treec96b67b275d8ebae6f793a0455a75ae8edc87d3c /src/components/settings/account
parentUpdate Electron and Sentry for latest fixes (diff)
downloadferdium-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/account')
-rw-r--r--src/components/settings/account/AccountDashboard.js316
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';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import { 6import { ProBadge, H1, H2 } from '@meetfranz/ui';
7 ProBadge, H1, H2,
8} from '@meetfranz/ui';
9import moment from 'moment'; 7import moment from 'moment';
10 8
11import Loader from '../../ui/Loader'; 9import Loader from '../../ui/Loader';
@@ -13,6 +11,7 @@ import Button from '../../ui/Button';
13import Infobox from '../../ui/Infobox'; 11import Infobox from '../../ui/Infobox';
14import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen'; 12import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen';
15import { i18nPlanName } from '../../../helpers/plan-helpers'; 13import { i18nPlanName } from '../../../helpers/plan-helpers';
14import { LOCAL_SERVER } from '../../../config';
16 15
17const messages = defineMessages({ 16const 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>