diff options
author | Bennett <hello@vantezzen.io> | 2020-01-31 17:24:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-31 17:24:30 +0100 |
commit | 9277d42ee8fd6d9e3eccf948f71c8688f726784e (patch) | |
tree | 6f167ea9eb2ed50a079596048993a79c7aeb9447 /src/components | |
parent | Update (diff) | |
parent | Fix lint (diff) | |
download | ferdium-app-9277d42ee8fd6d9e3eccf948f71c8688f726784e.tar.gz ferdium-app-9277d42ee8fd6d9e3eccf948f71c8688f726784e.tar.zst ferdium-app-9277d42ee8fd6d9e3eccf948f71c8688f726784e.zip |
Merge branch 'develop' into start-in-tray
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/auth/Locked.js | 3 | ||||
-rw-r--r-- | src/components/services/content/ServiceView.js | 1 | ||||
-rw-r--r-- | src/components/settings/account/AccountDashboard.js | 316 | ||||
-rw-r--r-- | src/components/settings/navigation/SettingsNavigation.js | 4 | ||||
-rw-r--r-- | src/components/settings/recipes/RecipesDashboard.js | 6 | ||||
-rw-r--r-- | src/components/settings/settings/EditSettingsForm.js | 77 | ||||
-rw-r--r-- | src/components/settings/team/TeamDashboard.js | 9 | ||||
-rw-r--r-- | src/components/ui/ImageUpload.js | 2 | ||||
-rw-r--r-- | src/components/ui/Link.js | 6 | ||||
-rw-r--r-- | src/components/ui/WebviewLoader/index.js | 4 |
10 files changed, 269 insertions, 159 deletions
diff --git a/src/components/auth/Locked.js b/src/components/auth/Locked.js index 045621d0a..e7f3dc78b 100644 --- a/src/components/auth/Locked.js +++ b/src/components/auth/Locked.js | |||
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react'; | |||
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | 5 | ||
6 | import Form from '../../lib/Form'; | 6 | import Form from '../../lib/Form'; |
7 | import { required } from '../../helpers/validation-helpers'; | ||
8 | import Input from '../ui/Input'; | 7 | import Input from '../ui/Input'; |
9 | import Button from '../ui/Button'; | 8 | import Button from '../ui/Button'; |
10 | import Infobox from '../ui/Infobox'; | 9 | import Infobox from '../ui/Infobox'; |
@@ -50,7 +49,6 @@ export default @observer class Locked extends Component { | |||
50 | password: { | 49 | password: { |
51 | label: this.context.intl.formatMessage(messages.passwordLabel), | 50 | label: this.context.intl.formatMessage(messages.passwordLabel), |
52 | value: '', | 51 | value: '', |
53 | validators: [required], | ||
54 | type: 'password', | 52 | type: 'password', |
55 | }, | 53 | }, |
56 | }, | 54 | }, |
@@ -89,6 +87,7 @@ export default @observer class Locked extends Component { | |||
89 | <Input | 87 | <Input |
90 | field={form.$('password')} | 88 | field={form.$('password')} |
91 | showPasswordToggle | 89 | showPasswordToggle |
90 | focus | ||
92 | /> | 91 | /> |
93 | {error.code === 'invalid-credentials' && ( | 92 | {error.code === 'invalid-credentials' && ( |
94 | <p className="error-message center">{intl.formatMessage(messages.invalidCredentials)}</p> | 93 | <p className="error-message center">{intl.formatMessage(messages.invalidCredentials)}</p> |
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js index 1fff5ef7a..860863d26 100644 --- a/src/components/services/content/ServiceView.js +++ b/src/components/services/content/ServiceView.js | |||
@@ -96,6 +96,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
96 | componentWillUnmount() { | 96 | componentWillUnmount() { |
97 | this.autorunDisposer(); | 97 | this.autorunDisposer(); |
98 | clearTimeout(this.forceRepaintTimeout); | 98 | clearTimeout(this.forceRepaintTimeout); |
99 | clearTimeout(this.hibernationTimer); | ||
99 | } | 100 | } |
100 | 101 | ||
101 | updateTargetUrl = (event) => { | 102 | updateTargetUrl = (event) => { |
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> |
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js index 192cfde7a..eb3249fa0 100644 --- a/src/components/settings/navigation/SettingsNavigation.js +++ b/src/components/settings/navigation/SettingsNavigation.js | |||
@@ -119,6 +119,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
119 | to="/settings/services" | 119 | to="/settings/services" |
120 | className="settings-navigation__link" | 120 | className="settings-navigation__link" |
121 | activeClassName="is-active" | 121 | activeClassName="is-active" |
122 | disabled={!isLoggedIn} | ||
122 | > | 123 | > |
123 | {intl.formatMessage(messages.yourServices)} | 124 | {intl.formatMessage(messages.yourServices)} |
124 | {' '} | 125 | {' '} |
@@ -134,6 +135,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
134 | to="/settings/workspaces" | 135 | to="/settings/workspaces" |
135 | className="settings-navigation__link" | 136 | className="settings-navigation__link" |
136 | activeClassName="is-active" | 137 | activeClassName="is-active" |
138 | disabled={!isLoggedIn} | ||
137 | > | 139 | > |
138 | {intl.formatMessage(messages.yourWorkspaces)} | 140 | {intl.formatMessage(messages.yourWorkspaces)} |
139 | {' '} | 141 | {' '} |
@@ -148,6 +150,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
148 | to="/settings/user" | 150 | to="/settings/user" |
149 | className="settings-navigation__link" | 151 | className="settings-navigation__link" |
150 | activeClassName="is-active" | 152 | activeClassName="is-active" |
153 | disabled={!isLoggedIn} | ||
151 | > | 154 | > |
152 | {intl.formatMessage(messages.account)} | 155 | {intl.formatMessage(messages.account)} |
153 | </Link> | 156 | </Link> |
@@ -155,6 +158,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
155 | to="/settings/team" | 158 | to="/settings/team" |
156 | className="settings-navigation__link" | 159 | className="settings-navigation__link" |
157 | activeClassName="is-active" | 160 | activeClassName="is-active" |
161 | disabled={!isLoggedIn} | ||
158 | > | 162 | > |
159 | {intl.formatMessage(messages.team)} | 163 | {intl.formatMessage(messages.team)} |
160 | {!user.data.isPremium && ( | 164 | {!user.data.isPremium && ( |
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js index 877cbc588..d08e6cbc2 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.js | |||
@@ -153,6 +153,8 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
153 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); | 153 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); |
154 | const devRecipes = recipes.filter(r => r.isDevRecipe); | 154 | const devRecipes = recipes.filter(r => r.isDevRecipe); |
155 | 155 | ||
156 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | ||
157 | |||
156 | return ( | 158 | return ( |
157 | <div className="settings__main"> | 159 | <div className="settings__main"> |
158 | <div className="settings__header"> | 160 | <div className="settings__header"> |
@@ -265,7 +267,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
265 | <RecipeItem | 267 | <RecipeItem |
266 | key={recipe.id} | 268 | key={recipe.id} |
267 | recipe={recipe} | 269 | recipe={recipe} |
268 | onClick={() => showAddServiceInterface({ recipeId: recipe.id })} | 270 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} |
269 | /> | 271 | /> |
270 | ))} | 272 | ))} |
271 | </div> | 273 | </div> |
@@ -278,7 +280,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
278 | <RecipeItem | 280 | <RecipeItem |
279 | key={recipe.id} | 281 | key={recipe.id} |
280 | recipe={recipe} | 282 | recipe={recipe} |
281 | onClick={() => showAddServiceInterface({ recipeId: recipe.id })} | 283 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} |
282 | /> | 284 | /> |
283 | ))} | 285 | ))} |
284 | </div> | 286 | </div> |
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 0badd3b98..efb6eaa18 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -36,6 +36,10 @@ const messages = defineMessages({ | |||
36 | id: 'settings.app.hibernateInfo', | 36 | id: 'settings.app.hibernateInfo', |
37 | defaultMessage: '!!!By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.', | 37 | defaultMessage: '!!!By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.', |
38 | }, | 38 | }, |
39 | inactivityLockInfo: { | ||
40 | id: 'settings.app.inactivityLockInfo', | ||
41 | defaultMessage: '!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable', | ||
42 | }, | ||
39 | serverInfo: { | 43 | serverInfo: { |
40 | id: 'settings.app.serverInfo', | 44 | id: 'settings.app.serverInfo', |
41 | defaultMessage: '!!!We advice you to logout after changing your server as your settings might not be saved otherwise.', | 45 | defaultMessage: '!!!We advice you to logout after changing your server as your settings might not be saved otherwise.', |
@@ -50,7 +54,7 @@ const messages = defineMessages({ | |||
50 | }, | 54 | }, |
51 | lockedPassword: { | 55 | lockedPassword: { |
52 | id: 'settings.app.lockedPassword', | 56 | id: 'settings.app.lockedPassword', |
53 | defaultMessage: '!!!Ferdi Lock Password', | 57 | defaultMessage: '!!!Password', |
54 | }, | 58 | }, |
55 | lockedPasswordInfo: { | 59 | lockedPasswordInfo: { |
56 | id: 'settings.app.lockedPasswordInfo', | 60 | id: 'settings.app.lockedPasswordInfo', |
@@ -58,7 +62,7 @@ const messages = defineMessages({ | |||
58 | }, | 62 | }, |
59 | lockInfo: { | 63 | lockInfo: { |
60 | id: 'settings.app.lockInfo', | 64 | id: 'settings.app.lockInfo', |
61 | defaultMessage: '!!!Ferdi password lock allows you to keep your messages protected.\nUsing Ferdi password lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut CMD/CTRL+Shift+L.', | 65 | defaultMessage: '!!!Password Lock allows you to keep your messages protected.\nUsing Password Lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut CMD/CTRL+Shift+L.', |
62 | }, | 66 | }, |
63 | scheduledDNDTimeInfo: { | 67 | scheduledDNDTimeInfo: { |
64 | id: 'settings.app.scheduledDNDTimeInfo', | 68 | id: 'settings.app.scheduledDNDTimeInfo', |
@@ -142,6 +146,10 @@ const messages = defineMessages({ | |||
142 | }, | 146 | }, |
143 | }); | 147 | }); |
144 | 148 | ||
149 | const Hr = () => ( | ||
150 | <hr style={{ marginBottom: 20 }} /> | ||
151 | ); | ||
152 | |||
145 | export default @observer class EditSettingsForm extends Component { | 153 | export default @observer class EditSettingsForm extends Component { |
146 | static propTypes = { | 154 | static propTypes = { |
147 | checkForUpdates: PropTypes.func.isRequired, | 155 | checkForUpdates: PropTypes.func.isRequired, |
@@ -163,6 +171,7 @@ export default @observer class EditSettingsForm extends Component { | |||
163 | hibernationEnabled: PropTypes.bool.isRequired, | 171 | hibernationEnabled: PropTypes.bool.isRequired, |
164 | isDarkmodeEnabled: PropTypes.bool.isRequired, | 172 | isDarkmodeEnabled: PropTypes.bool.isRequired, |
165 | isTrayEnabled: PropTypes.bool.isRequired, | 173 | isTrayEnabled: PropTypes.bool.isRequired, |
174 | isAdaptableDarkModeEnabled: PropTypes.bool.isRequired, | ||
166 | openProcessManager: PropTypes.func.isRequired, | 175 | openProcessManager: PropTypes.func.isRequired, |
167 | }; | 176 | }; |
168 | 177 | ||
@@ -187,6 +196,7 @@ export default @observer class EditSettingsForm extends Component { | |||
187 | installUpdate, | 196 | installUpdate, |
188 | form, | 197 | form, |
189 | isCheckingForUpdates, | 198 | isCheckingForUpdates, |
199 | isAdaptableDarkModeEnabled, | ||
190 | isUpdateAvailable, | 200 | isUpdateAvailable, |
191 | noUpdateAvailable, | 201 | noUpdateAvailable, |
192 | updateIsReadyToInstall, | 202 | updateIsReadyToInstall, |
@@ -240,6 +250,9 @@ export default @observer class EditSettingsForm extends Component { | |||
240 | {isTrayEnabled && <Toggle field={form.$('startMinimized')} />} | 250 | {isTrayEnabled && <Toggle field={form.$('startMinimized')} />} |
241 | <Toggle field={form.$('privateNotifications')} /> | 251 | <Toggle field={form.$('privateNotifications')} /> |
242 | <Toggle field={form.$('showServiceNavigationBar')} /> | 252 | <Toggle field={form.$('showServiceNavigationBar')} /> |
253 | |||
254 | <Hr /> | ||
255 | |||
243 | <Toggle field={form.$('hibernate')} /> | 256 | <Toggle field={form.$('hibernate')} /> |
244 | {hibernationEnabled && ( | 257 | {hibernationEnabled && ( |
245 | <Select field={form.$('hibernationStrategy')} /> | 258 | <Select field={form.$('hibernationStrategy')} /> |
@@ -254,9 +267,13 @@ export default @observer class EditSettingsForm extends Component { | |||
254 | { intl.formatMessage(messages.hibernateInfo) } | 267 | { intl.formatMessage(messages.hibernateInfo) } |
255 | </span> | 268 | </span> |
256 | </p> | 269 | </p> |
270 | |||
271 | <Hr /> | ||
272 | |||
257 | {process.platform === 'win32' && ( | 273 | {process.platform === 'win32' && ( |
258 | <Toggle field={form.$('minimizeToSystemTray')} /> | 274 | <Toggle field={form.$('minimizeToSystemTray')} /> |
259 | )} | 275 | )} |
276 | |||
260 | <Input | 277 | <Input |
261 | placeholder="Server" | 278 | placeholder="Server" |
262 | onChange={e => this.submit(e)} | 279 | onChange={e => this.submit(e)} |
@@ -264,7 +281,14 @@ export default @observer class EditSettingsForm extends Component { | |||
264 | autoFocus | 281 | autoFocus |
265 | /> | 282 | /> |
266 | {isLoggedIn && ( | 283 | {isLoggedIn && ( |
267 | <p>{ intl.formatMessage(messages.serverInfo) }</p> | 284 | <p |
285 | className="settings__message" | ||
286 | style={{ | ||
287 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | ||
288 | }} | ||
289 | > | ||
290 | { intl.formatMessage(messages.serverInfo) } | ||
291 | </p> | ||
268 | )} | 292 | )} |
269 | {server === 'https://api.franzinfra.com' && ( | 293 | {server === 'https://api.franzinfra.com' && ( |
270 | <p | 294 | <p |
@@ -292,6 +316,10 @@ export default @observer class EditSettingsForm extends Component { | |||
292 | {isWorkspaceEnabled && ( | 316 | {isWorkspaceEnabled && ( |
293 | <Toggle field={form.$('keepAllWorkspacesLoaded')} /> | 317 | <Toggle field={form.$('keepAllWorkspacesLoaded')} /> |
294 | )} | 318 | )} |
319 | |||
320 | |||
321 | <Hr /> | ||
322 | |||
295 | {isTodosEnabled && ( | 323 | {isTodosEnabled && ( |
296 | <> | 324 | <> |
297 | <Toggle field={form.$('enableTodos')} /> | 325 | <Toggle field={form.$('enableTodos')} /> |
@@ -300,10 +328,19 @@ export default @observer class EditSettingsForm extends Component { | |||
300 | onChange={e => this.submit(e)} | 328 | onChange={e => this.submit(e)} |
301 | field={form.$('todoServer')} | 329 | field={form.$('todoServer')} |
302 | /> | 330 | /> |
303 | <p>{ intl.formatMessage(messages.todoServerInfo) }</p> | 331 | <p |
332 | className="settings__message" | ||
333 | style={{ | ||
334 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | ||
335 | }} | ||
336 | > | ||
337 | { intl.formatMessage(messages.todoServerInfo) } | ||
338 | </p> | ||
304 | </> | 339 | </> |
305 | )} | 340 | )} |
306 | 341 | ||
342 | <Hr /> | ||
343 | |||
307 | <Toggle field={form.$('lockingFeatureEnabled')} /> | 344 | <Toggle field={form.$('lockingFeatureEnabled')} /> |
308 | {lockingFeatureEnabled && ( | 345 | {lockingFeatureEnabled && ( |
309 | <> | 346 | <> |
@@ -318,6 +355,16 @@ export default @observer class EditSettingsForm extends Component { | |||
318 | <p> | 355 | <p> |
319 | { intl.formatMessage(messages.lockedPasswordInfo) } | 356 | { intl.formatMessage(messages.lockedPasswordInfo) } |
320 | </p> | 357 | </p> |
358 | |||
359 | <Input | ||
360 | placeholder="Lock after inactivity" | ||
361 | onChange={e => this.submit(e)} | ||
362 | field={form.$('inactivityLock')} | ||
363 | autoFocus | ||
364 | /> | ||
365 | <p> | ||
366 | { intl.formatMessage(messages.inactivityLockInfo) } | ||
367 | </p> | ||
321 | </> | 368 | </> |
322 | )} | 369 | )} |
323 | <p | 370 | <p |
@@ -331,6 +378,7 @@ export default @observer class EditSettingsForm extends Component { | |||
331 | </span> | 378 | </span> |
332 | </p> | 379 | </p> |
333 | 380 | ||
381 | <Hr /> | ||
334 | 382 | ||
335 | <Toggle field={form.$('scheduledDNDEnabled')} /> | 383 | <Toggle field={form.$('scheduledDNDEnabled')} /> |
336 | {scheduledDNDEnabled && ( | 384 | {scheduledDNDEnabled && ( |
@@ -386,11 +434,10 @@ export default @observer class EditSettingsForm extends Component { | |||
386 | <h2 id="apperance">{intl.formatMessage(messages.headlineAppearance)}</h2> | 434 | <h2 id="apperance">{intl.formatMessage(messages.headlineAppearance)}</h2> |
387 | <Toggle field={form.$('showDisabledServices')} /> | 435 | <Toggle field={form.$('showDisabledServices')} /> |
388 | <Toggle field={form.$('showMessageBadgeWhenMuted')} /> | 436 | <Toggle field={form.$('showMessageBadgeWhenMuted')} /> |
389 | <Toggle field={form.$('darkMode')} /> | 437 | {isMac && <Toggle field={form.$('adaptableDarkMode')} />} |
390 | {isMac && <Toggle field={form.$('adaptableDarkMode')} disabled={isDarkmodeEnabled} />} | 438 | {!(isMac && isAdaptableDarkModeEnabled) && <Toggle field={form.$('darkMode')} disabled={isAdaptableDarkModeEnabled} />} |
391 | {isDarkmodeEnabled && ( | 439 | {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( |
392 | <> | 440 | <> |
393 | <Toggle field={form.$('adaptableDarkMode')} /> | ||
394 | <Toggle field={form.$('universalDarkMode')} /> | 441 | <Toggle field={form.$('universalDarkMode')} /> |
395 | <p | 442 | <p |
396 | className="settings__message" | 443 | className="settings__message" |
@@ -488,20 +535,17 @@ export default @observer class EditSettingsForm extends Component { | |||
488 | loaded={!isCheckingForUpdates || !isUpdateAvailable} | 535 | loaded={!isCheckingForUpdates || !isUpdateAvailable} |
489 | /> | 536 | /> |
490 | )} | 537 | )} |
491 | {noUpdateAvailable && ( | ||
492 | <p>{intl.formatMessage(messages.updateStatusUpToDate)}</p> | ||
493 | )} | ||
494 | <br /> | 538 | <br /> |
495 | <Toggle field={form.$('beta')} /> | 539 | <Toggle field={form.$('beta')} /> |
496 | <Toggle field={form.$('noUpdates')} /> | 540 | <Toggle field={form.$('noUpdates')} /> |
497 | {intl.formatMessage(messages.currentVersion)} | 541 | {intl.formatMessage(messages.currentVersion)} |
498 | {' '} | 542 | {' '} |
499 | {remote.app.getVersion()} | 543 | {remote.app.getVersion()} |
544 | <br /> | ||
545 | <br /> | ||
546 | {noUpdateAvailable && intl.formatMessage(messages.updateStatusUpToDate)} | ||
500 | <p className="settings__message"> | 547 | <p className="settings__message"> |
501 | <span className="mdi mdi-information" /> | 548 | |
502 | {intl.formatMessage(messages.languageDisclaimer)} | ||
503 | </p> | ||
504 | <p className="settings__message"> | ||
505 | <span className="mdi mdi-github-face" /> | 549 | <span className="mdi mdi-github-face" /> |
506 | <span> | 550 | <span> |
507 | Ferdi is based on | 551 | Ferdi is based on |
@@ -512,6 +556,9 @@ export default @observer class EditSettingsForm extends Component { | |||
512 | {' '} | 556 | {' '} |
513 | <a href="https://github.com/meetfranz/franz/blob/master/LICENSE" target="_blank">Apache-2.0 License</a> | 557 | <a href="https://github.com/meetfranz/franz/blob/master/LICENSE" target="_blank">Apache-2.0 License</a> |
514 | </span> | 558 | </span> |
559 | <br /> | ||
560 | <span className="mdi mdi-information" /> | ||
561 | {intl.formatMessage(messages.languageDisclaimer)} | ||
515 | </p> | 562 | </p> |
516 | </form> | 563 | </form> |
517 | </div> | 564 | </div> |
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js index 7e6d93997..3d5358d89 100644 --- a/src/components/settings/team/TeamDashboard.js +++ b/src/components/settings/team/TeamDashboard.js | |||
@@ -210,7 +210,14 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
210 | <h1 className={classes.headline}> | 210 | <h1 className={classes.headline}> |
211 | {intl.formatMessage(messages.teamsUnavailable)} | 211 | {intl.formatMessage(messages.teamsUnavailable)} |
212 | </h1> | 212 | </h1> |
213 | {intl.formatMessage(messages.teamsUnavailableInfo)} | 213 | <p |
214 | className="settings__message" | ||
215 | style={{ | ||
216 | borderTop: 0, marginTop: 0, | ||
217 | }} | ||
218 | > | ||
219 | {intl.formatMessage(messages.teamsUnavailableInfo)} | ||
220 | </p> | ||
214 | </div> | 221 | </div> |
215 | </div> | 222 | </div> |
216 | ); | 223 | ); |
diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js index 83a05554b..e0b608b96 100644 --- a/src/components/ui/ImageUpload.js +++ b/src/components/ui/ImageUpload.js | |||
@@ -91,7 +91,7 @@ export default @observer class ImageUpload extends Component { | |||
91 | onDrop={this.onDrop.bind(this)} | 91 | onDrop={this.onDrop.bind(this)} |
92 | className={cssClasses} | 92 | className={cssClasses} |
93 | multiple={multiple} | 93 | multiple={multiple} |
94 | accept="image/jpeg, image/png" | 94 | accept="image/jpeg, image/png, image/svg+xml" |
95 | > | 95 | > |
96 | <i className="mdi mdi-file-image" /> | 96 | <i className="mdi mdi-file-image" /> |
97 | <p> | 97 | <p> |
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js index 5f729844b..7930d98b4 100644 --- a/src/components/ui/Link.js +++ b/src/components/ui/Link.js | |||
@@ -11,7 +11,8 @@ import { matchRoute } from '../../helpers/routing-helpers'; | |||
11 | // TODO: create container component for this component | 11 | // TODO: create container component for this component |
12 | export default @inject('stores') @observer class Link extends Component { | 12 | export default @inject('stores') @observer class Link extends Component { |
13 | onClick(e) { | 13 | onClick(e) { |
14 | if (this.props.target === '_blank') { | 14 | if (this.props.disabled) e.preventDefault(); |
15 | else if (this.props.target === '_blank') { | ||
15 | e.preventDefault(); | 16 | e.preventDefault(); |
16 | shell.openExternal(this.props.to); | 17 | shell.openExternal(this.props.to); |
17 | } | 18 | } |
@@ -39,6 +40,7 @@ export default @inject('stores') @observer class Link extends Component { | |||
39 | const linkClasses = classnames({ | 40 | const linkClasses = classnames({ |
40 | [`${className}`]: true, | 41 | [`${className}`]: true, |
41 | [`${activeClassName}`]: match, | 42 | [`${activeClassName}`]: match, |
43 | 'is-disabled': this.props.disabled, | ||
42 | }); | 44 | }); |
43 | 45 | ||
44 | return ( | 46 | return ( |
@@ -68,12 +70,14 @@ Link.wrappedComponent.propTypes = { | |||
68 | strictFilter: PropTypes.bool, | 70 | strictFilter: PropTypes.bool, |
69 | target: PropTypes.string, | 71 | target: PropTypes.string, |
70 | style: PropTypes.object, | 72 | style: PropTypes.object, |
73 | disabled: PropTypes.bool, | ||
71 | }; | 74 | }; |
72 | 75 | ||
73 | Link.wrappedComponent.defaultProps = { | 76 | Link.wrappedComponent.defaultProps = { |
74 | className: '', | 77 | className: '', |
75 | activeClassName: '', | 78 | activeClassName: '', |
76 | strictFilter: false, | 79 | strictFilter: false, |
80 | disabled: false, | ||
77 | target: '', | 81 | target: '', |
78 | style: {}, | 82 | style: {}, |
79 | }; | 83 | }; |
diff --git a/src/components/ui/WebviewLoader/index.js b/src/components/ui/WebviewLoader/index.js index 923f10327..c58d69374 100644 --- a/src/components/ui/WebviewLoader/index.js +++ b/src/components/ui/WebviewLoader/index.js | |||
@@ -10,7 +10,7 @@ import styles from './styles'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | loading: { | 11 | loading: { |
12 | id: 'service.webviewLoader.loading', | 12 | id: 'service.webviewLoader.loading', |
13 | defaultMessage: '!!!Loading', | 13 | defaultMessage: '!!!Loading {service}', |
14 | }, | 14 | }, |
15 | }); | 15 | }); |
16 | 16 | ||
@@ -30,7 +30,7 @@ export default @injectSheet(styles) @observer class WebviewLoader extends Compon | |||
30 | return ( | 30 | return ( |
31 | <FullscreenLoader | 31 | <FullscreenLoader |
32 | className={classes.component} | 32 | className={classes.component} |
33 | title={`${intl.formatMessage(messages.loading)} ${name}`} | 33 | title={`${intl.formatMessage(messages.loading, { service: name })}`} |
34 | /> | 34 | /> |
35 | ); | 35 | ); |
36 | } | 36 | } |