diff options
Diffstat (limited to 'src/components/settings')
-rw-r--r-- | src/components/settings/SettingsLayout.js | 13 | ||||
-rw-r--r-- | src/components/settings/account/AccountDashboard.js | 37 | ||||
-rw-r--r-- | src/components/settings/navigation/SettingsNavigation.js | 49 | ||||
-rw-r--r-- | src/components/settings/recipes/RecipeItem.js | 17 | ||||
-rw-r--r-- | src/components/settings/recipes/RecipesDashboard.js | 83 | ||||
-rw-r--r-- | src/components/settings/services/EditServiceForm.js | 157 | ||||
-rw-r--r-- | src/components/settings/services/ServiceError.js | 26 | ||||
-rw-r--r-- | src/components/settings/services/ServiceItem.js | 48 | ||||
-rw-r--r-- | src/components/settings/services/ServicesDashboard.js | 52 | ||||
-rw-r--r-- | src/components/settings/settings/EditSettingsForm.js | 527 | ||||
-rw-r--r-- | src/components/settings/supportFerdi/SupportFerdiDashboard.js | 141 | ||||
-rw-r--r-- | src/components/settings/team/TeamDashboard.js | 54 | ||||
-rw-r--r-- | src/components/settings/user/EditUserForm.js | 39 |
13 files changed, 704 insertions, 539 deletions
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js index 5b3b754fa..0574b3765 100644 --- a/src/components/settings/SettingsLayout.js +++ b/src/components/settings/SettingsLayout.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import ErrorBoundary from '../util/ErrorBoundary'; | 6 | import ErrorBoundary from '../util/ErrorBoundary'; |
7 | import { oneOrManyChildElements } from '../../prop-types'; | 7 | import { oneOrManyChildElements } from '../../prop-types'; |
@@ -10,11 +10,10 @@ import Appear from '../ui/effects/Appear'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | closeSettings: { | 11 | closeSettings: { |
12 | id: 'settings.app.closeSettings', | 12 | id: 'settings.app.closeSettings', |
13 | defaultMessage: '!!!Close settings', | 13 | defaultMessage: 'Close settings', |
14 | }, | 14 | }, |
15 | }); | 15 | }); |
16 | 16 | ||
17 | export default | ||
18 | @observer | 17 | @observer |
19 | class SettingsLayout extends Component { | 18 | class SettingsLayout extends Component { |
20 | static propTypes = { | 19 | static propTypes = { |
@@ -23,10 +22,6 @@ class SettingsLayout extends Component { | |||
23 | closeSettings: PropTypes.func.isRequired, | 22 | closeSettings: PropTypes.func.isRequired, |
24 | }; | 23 | }; |
25 | 24 | ||
26 | static contextTypes = { | ||
27 | intl: intlShape, | ||
28 | }; | ||
29 | |||
30 | componentDidMount() { | 25 | componentDidMount() { |
31 | document.addEventListener('keydown', this.handleKeyDown.bind(this), false); | 26 | document.addEventListener('keydown', this.handleKeyDown.bind(this), false); |
32 | } | 27 | } |
@@ -49,7 +44,7 @@ class SettingsLayout extends Component { | |||
49 | render() { | 44 | render() { |
50 | const { navigation, children, closeSettings } = this.props; | 45 | const { navigation, children, closeSettings } = this.props; |
51 | 46 | ||
52 | const { intl } = this.context; | 47 | const { intl } = this.props; |
53 | 48 | ||
54 | return ( | 49 | return ( |
55 | <Appear transitionName="fadeIn-fast"> | 50 | <Appear transitionName="fadeIn-fast"> |
@@ -77,3 +72,5 @@ class SettingsLayout extends Component { | |||
77 | ); | 72 | ); |
78 | } | 73 | } |
79 | } | 74 | } |
75 | |||
76 | export default injectIntl(SettingsLayout); | ||
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index ef7748343..933d47d12 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | 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, injectIntl } from 'react-intl'; |
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import { H1, H2 } from '@meetfranz/ui'; | 6 | import { H1, H2 } from '@meetfranz/ui'; |
7 | 7 | ||
@@ -13,7 +13,7 @@ import { LOCAL_SERVER, LIVE_FRANZ_API } from '../../../config'; | |||
13 | const messages = defineMessages({ | 13 | const messages = defineMessages({ |
14 | headline: { | 14 | headline: { |
15 | id: 'settings.account.headline', | 15 | id: 'settings.account.headline', |
16 | defaultMessage: '!!!Account', | 16 | defaultMessage: 'Account', |
17 | }, | 17 | }, |
18 | headlineDangerZone: { | 18 | headlineDangerZone: { |
19 | id: 'settings.account.headlineDangerZone', | 19 | id: 'settings.account.headlineDangerZone', |
@@ -21,7 +21,7 @@ const messages = defineMessages({ | |||
21 | }, | 21 | }, |
22 | accountEditButton: { | 22 | accountEditButton: { |
23 | id: 'settings.account.account.editButton', | 23 | id: 'settings.account.account.editButton', |
24 | defaultMessage: '!!!Edit Account', | 24 | defaultMessage: 'Edit Account', |
25 | }, | 25 | }, |
26 | invoicesButton: { | 26 | invoicesButton: { |
27 | id: 'settings.account.headlineInvoices', | 27 | id: 'settings.account.headlineInvoices', |
@@ -29,29 +29,29 @@ const messages = defineMessages({ | |||
29 | }, | 29 | }, |
30 | userInfoRequestFailed: { | 30 | userInfoRequestFailed: { |
31 | id: 'settings.account.userInfoRequestFailed', | 31 | id: 'settings.account.userInfoRequestFailed', |
32 | defaultMessage: '!!!Could not load user information', | 32 | defaultMessage: 'Could not load user information', |
33 | }, | 33 | }, |
34 | tryReloadUserInfoRequest: { | 34 | tryReloadUserInfoRequest: { |
35 | id: 'settings.account.tryReloadUserInfoRequest', | 35 | id: 'settings.account.tryReloadUserInfoRequest', |
36 | defaultMessage: '!!!Try again', | 36 | defaultMessage: 'Try again', |
37 | }, | 37 | }, |
38 | deleteAccount: { | 38 | deleteAccount: { |
39 | id: 'settings.account.deleteAccount', | 39 | id: 'settings.account.deleteAccount', |
40 | defaultMessage: '!!!Delete account', | 40 | defaultMessage: 'Delete account', |
41 | }, | 41 | }, |
42 | deleteInfo: { | 42 | deleteInfo: { |
43 | id: 'settings.account.deleteInfo', | 43 | id: 'settings.account.deleteInfo', |
44 | defaultMessage: | 44 | defaultMessage: |
45 | "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.", | 45 | "If you don't need your Ferdi account any longer, you can delete your account and all related data here.", |
46 | }, | 46 | }, |
47 | deleteEmailSent: { | 47 | deleteEmailSent: { |
48 | id: 'settings.account.deleteEmailSent', | 48 | id: 'settings.account.deleteEmailSent', |
49 | defaultMessage: | 49 | defaultMessage: |
50 | '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', | 50 | 'You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', |
51 | }, | 51 | }, |
52 | yourLicense: { | 52 | yourLicense: { |
53 | id: 'settings.account.yourLicense', | 53 | id: 'settings.account.yourLicense', |
54 | defaultMessage: '!!!Your Franz License:', | 54 | defaultMessage: 'Your Franz License:', |
55 | }, | 55 | }, |
56 | accountUnavailable: { | 56 | accountUnavailable: { |
57 | id: 'settings.account.accountUnavailable', | 57 | id: 'settings.account.accountUnavailable', |
@@ -59,7 +59,8 @@ const messages = defineMessages({ | |||
59 | }, | 59 | }, |
60 | accountUnavailableInfo: { | 60 | accountUnavailableInfo: { |
61 | id: 'settings.account.accountUnavailableInfo', | 61 | id: 'settings.account.accountUnavailableInfo', |
62 | 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.', | 62 | defaultMessage: |
63 | '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.', | ||
63 | }, | 64 | }, |
64 | }); | 65 | }); |
65 | 66 | ||
@@ -78,10 +79,6 @@ class AccountDashboard extends Component { | |||
78 | server: PropTypes.string.isRequired, | 79 | server: PropTypes.string.isRequired, |
79 | }; | 80 | }; |
80 | 81 | ||
81 | static contextTypes = { | ||
82 | intl: intlShape, | ||
83 | }; | ||
84 | |||
85 | render() { | 82 | render() { |
86 | const { | 83 | const { |
87 | user, | 84 | user, |
@@ -95,7 +92,7 @@ class AccountDashboard extends Component { | |||
95 | openInvoices, | 92 | openInvoices, |
96 | server, | 93 | server, |
97 | } = this.props; | 94 | } = this.props; |
98 | const { intl } = this.context; | 95 | const { intl } = this.props; |
99 | 96 | ||
100 | const isUsingWithoutAccount = server === LOCAL_SERVER; | 97 | const isUsingWithoutAccount = server === LOCAL_SERVER; |
101 | const isUsingFranzServer = server === LIVE_FRANZ_API; | 98 | const isUsingFranzServer = server === LIVE_FRANZ_API; |
@@ -182,9 +179,7 @@ class AccountDashboard extends Component { | |||
182 | <div className="account"> | 179 | <div className="account"> |
183 | <div className="account__box"> | 180 | <div className="account__box"> |
184 | <H2>{intl.formatMessage(messages.yourLicense)}</H2> | 181 | <H2>{intl.formatMessage(messages.yourLicense)}</H2> |
185 | <p> | 182 | <p>Franz</p> |
186 | Franz | ||
187 | </p> | ||
188 | <div className="manage-user-links"> | 183 | <div className="manage-user-links"> |
189 | <Button | 184 | <Button |
190 | label={intl.formatMessage( | 185 | label={intl.formatMessage( |
@@ -203,7 +198,9 @@ class AccountDashboard extends Component { | |||
203 | {isUsingFranzServer && ( | 198 | {isUsingFranzServer && ( |
204 | <div className="account franz-form"> | 199 | <div className="account franz-form"> |
205 | <div className="account__box"> | 200 | <div className="account__box"> |
206 | <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2> | 201 | <H2> |
202 | {intl.formatMessage(messages.headlineDangerZone)} | ||
203 | </H2> | ||
207 | {!isDeleteAccountSuccessful && ( | 204 | {!isDeleteAccountSuccessful && ( |
208 | <div className="account__subscription"> | 205 | <div className="account__subscription"> |
209 | <p>{intl.formatMessage(messages.deleteInfo)}</p> | 206 | <p>{intl.formatMessage(messages.deleteInfo)}</p> |
@@ -232,4 +229,4 @@ class AccountDashboard extends Component { | |||
232 | } | 229 | } |
233 | } | 230 | } |
234 | 231 | ||
235 | export default AccountDashboard; | 232 | export default injectIntl(AccountDashboard); |
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js index 0a5ace586..72c7faa66 100644 --- a/src/components/settings/navigation/SettingsNavigation.js +++ b/src/components/settings/navigation/SettingsNavigation.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | import { inject, observer } from 'mobx-react'; | 4 | import { inject, observer } from 'mobx-react'; |
5 | import { RouterStore } from 'mobx-react-router'; | 5 | import { RouterStore } from 'mobx-react-router'; |
6 | 6 | ||
@@ -15,35 +15,37 @@ import globalMessages from '../../../i18n/globalMessages'; | |||
15 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
16 | availableServices: { | 16 | availableServices: { |
17 | id: 'settings.navigation.availableServices', | 17 | id: 'settings.navigation.availableServices', |
18 | defaultMessage: '!!!Available services', | 18 | defaultMessage: 'Available services', |
19 | }, | 19 | }, |
20 | yourServices: { | 20 | yourServices: { |
21 | id: 'settings.navigation.yourServices', | 21 | id: 'settings.navigation.yourServices', |
22 | defaultMessage: '!!!Your services', | 22 | defaultMessage: 'Your services', |
23 | }, | 23 | }, |
24 | yourWorkspaces: { | 24 | yourWorkspaces: { |
25 | id: 'settings.navigation.yourWorkspaces', | 25 | id: 'settings.navigation.yourWorkspaces', |
26 | defaultMessage: '!!!Your workspaces', | 26 | defaultMessage: 'Your workspaces', |
27 | }, | 27 | }, |
28 | account: { | 28 | account: { |
29 | id: 'settings.navigation.account', | 29 | id: 'settings.navigation.account', |
30 | defaultMessage: '!!!Account', | 30 | defaultMessage: 'Account', |
31 | }, | 31 | }, |
32 | team: { | 32 | team: { |
33 | id: 'settings.navigation.team', | 33 | id: 'settings.navigation.team', |
34 | defaultMessage: '!!!Manage Team', | 34 | defaultMessage: 'Manage Team', |
35 | }, | 35 | }, |
36 | supportFerdi: { | 36 | supportFerdi: { |
37 | id: 'settings.navigation.supportFerdi', | 37 | id: 'settings.navigation.supportFerdi', |
38 | defaultMessage: '!!!About Ferdi', | 38 | defaultMessage: 'About Ferdi', |
39 | }, | 39 | }, |
40 | logout: { | 40 | logout: { |
41 | id: 'settings.navigation.logout', | 41 | id: 'settings.navigation.logout', |
42 | defaultMessage: '!!!Logout', | 42 | defaultMessage: 'Logout', |
43 | }, | 43 | }, |
44 | }); | 44 | }); |
45 | 45 | ||
46 | export default @inject('stores', 'actions') @observer class SettingsNavigation extends Component { | 46 | @inject('stores', 'actions') |
47 | @observer | ||
48 | class SettingsNavigation extends Component { | ||
47 | static propTypes = { | 49 | static propTypes = { |
48 | stores: PropTypes.shape({ | 50 | stores: PropTypes.shape({ |
49 | ui: PropTypes.instanceOf(UIStore).isRequired, | 51 | ui: PropTypes.instanceOf(UIStore).isRequired, |
@@ -58,13 +60,10 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
58 | workspaceCount: PropTypes.number.isRequired, | 60 | workspaceCount: PropTypes.number.isRequired, |
59 | }; | 61 | }; |
60 | 62 | ||
61 | static contextTypes = { | ||
62 | intl: intlShape, | ||
63 | }; | ||
64 | |||
65 | handleLoginLogout() { | 63 | handleLoginLogout() { |
66 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | 64 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); |
67 | const isUsingWithoutAccount = this.props.stores.settings.app.server === LOCAL_SERVER; | 65 | const isUsingWithoutAccount = |
66 | this.props.stores.settings.app.server === LOCAL_SERVER; | ||
68 | 67 | ||
69 | if (isLoggedIn) { | 68 | if (isLoggedIn) { |
70 | // Remove current auth token | 69 | // Remove current auth token |
@@ -82,7 +81,9 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
82 | this.props.stores.user.isLoggingOut = true; | 81 | this.props.stores.user.isLoggingOut = true; |
83 | } | 82 | } |
84 | 83 | ||
85 | this.props.stores.router.push(isLoggedIn ? '/auth/logout' : '/auth/welcome'); | 84 | this.props.stores.router.push( |
85 | isLoggedIn ? '/auth/logout' : '/auth/welcome', | ||
86 | ); | ||
86 | 87 | ||
87 | if (isLoggedIn) { | 88 | if (isLoggedIn) { |
88 | // Reload Ferdi, otherwise many settings won't sync correctly with the server | 89 | // Reload Ferdi, otherwise many settings won't sync correctly with the server |
@@ -93,7 +94,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
93 | 94 | ||
94 | render() { | 95 | render() { |
95 | const { serviceCount, workspaceCount, stores } = this.props; | 96 | const { serviceCount, workspaceCount, stores } = this.props; |
96 | const { intl } = this.context; | 97 | const { intl } = this.props; |
97 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | 98 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); |
98 | const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER; | 99 | const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER; |
99 | const isUsingFranzServer = stores.settings.app.server === LIVE_FRANZ_API; | 100 | const isUsingFranzServer = stores.settings.app.server === LIVE_FRANZ_API; |
@@ -113,11 +114,8 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
113 | activeClassName="is-active" | 114 | activeClassName="is-active" |
114 | disabled={!isLoggedIn} | 115 | disabled={!isLoggedIn} |
115 | > | 116 | > |
116 | {intl.formatMessage(messages.yourServices)} | 117 | {intl.formatMessage(messages.yourServices)}{' '} |
117 | {' '} | 118 | <span className="badge">{serviceCount}</span> |
118 | <span className="badge"> | ||
119 | {serviceCount} | ||
120 | </span> | ||
121 | </Link> | 119 | </Link> |
122 | {workspaceStore.isFeatureEnabled ? ( | 120 | {workspaceStore.isFeatureEnabled ? ( |
123 | <Link | 121 | <Link |
@@ -126,8 +124,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
126 | activeClassName="is-active" | 124 | activeClassName="is-active" |
127 | disabled={!isLoggedIn} | 125 | disabled={!isLoggedIn} |
128 | > | 126 | > |
129 | {intl.formatMessage(messages.yourWorkspaces)} | 127 | {intl.formatMessage(messages.yourWorkspaces)}{' '} |
130 | {' '} | ||
131 | <span className="badge">{workspaceCount}</span> | 128 | <span className="badge">{workspaceCount}</span> |
132 | </Link> | 129 | </Link> |
133 | ) : null} | 130 | ) : null} |
@@ -172,9 +169,13 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
172 | className="settings-navigation__link" | 169 | className="settings-navigation__link" |
173 | onClick={this.handleLoginLogout.bind(this)} | 170 | onClick={this.handleLoginLogout.bind(this)} |
174 | > | 171 | > |
175 | { isLoggedIn && !isUsingWithoutAccount ? intl.formatMessage(messages.logout) : 'Login'} | 172 | {isLoggedIn && !isUsingWithoutAccount |
173 | ? intl.formatMessage(messages.logout) | ||
174 | : 'Login'} | ||
176 | </button> | 175 | </button> |
177 | </div> | 176 | </div> |
178 | ); | 177 | ); |
179 | } | 178 | } |
180 | } | 179 | } |
180 | |||
181 | export default injectIntl(SettingsNavigation); | ||
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js index 55f415bd5..ca188aa99 100644 --- a/src/components/settings/recipes/RecipeItem.js +++ b/src/components/settings/recipes/RecipeItem.js | |||
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | 4 | ||
5 | import RecipePreviewModel from '../../../models/RecipePreview'; | 5 | import RecipePreviewModel from '../../../models/RecipePreview'; |
6 | 6 | ||
7 | export default @observer class RecipeItem extends Component { | 7 | @observer |
8 | class RecipeItem extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, | 10 | recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, |
10 | onClick: PropTypes.func.isRequired, | 11 | onClick: PropTypes.func.isRequired, |
@@ -14,19 +15,11 @@ export default @observer class RecipeItem extends Component { | |||
14 | const { recipe, onClick } = this.props; | 15 | const { recipe, onClick } = this.props; |
15 | 16 | ||
16 | return ( | 17 | return ( |
17 | <button | 18 | <button type="button" className="recipe-teaser" onClick={onClick}> |
18 | type="button" | ||
19 | className="recipe-teaser" | ||
20 | onClick={onClick} | ||
21 | > | ||
22 | {recipe.isDevRecipe && ( | 19 | {recipe.isDevRecipe && ( |
23 | <span className="recipe-teaser__dev-badge">dev</span> | 20 | <span className="recipe-teaser__dev-badge">dev</span> |
24 | )} | 21 | )} |
25 | <img | 22 | <img src={recipe.icons.svg} className="recipe-teaser__icon" alt="" /> |
26 | src={recipe.icons.svg} | ||
27 | className="recipe-teaser__icon" | ||
28 | alt="" | ||
29 | /> | ||
30 | <span className="recipe-teaser__label">{recipe.name}</span> | 23 | <span className="recipe-teaser__label">{recipe.name}</span> |
31 | {recipe.aliases && recipe.aliases.length > 0 && ( | 24 | {recipe.aliases && recipe.aliases.length > 0 && ( |
32 | <span className="recipe-teaser__alias_label"> | 25 | <span className="recipe-teaser__alias_label"> |
@@ -37,3 +30,5 @@ export default @observer class RecipeItem extends Component { | |||
37 | ); | 30 | ); |
38 | } | 31 | } |
39 | } | 32 | } |
33 | |||
34 | export default RecipeItem; | ||
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js index 44ff2d0d7..e620abf93 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | 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, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | 6 | ||
7 | import { Button, Input } from '@meetfranz/forms'; | 7 | import { Button, Input } from '@meetfranz/forms'; |
@@ -18,55 +18,56 @@ import RecipePreview from '../../../models/RecipePreview'; | |||
18 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
19 | headline: { | 19 | headline: { |
20 | id: 'settings.recipes.headline', | 20 | id: 'settings.recipes.headline', |
21 | defaultMessage: '!!!Available Services', | 21 | defaultMessage: 'Available Services', |
22 | }, | 22 | }, |
23 | searchService: { | 23 | searchService: { |
24 | id: 'settings.searchService', | 24 | id: 'settings.searchService', |
25 | defaultMessage: '!!!Search service', | 25 | defaultMessage: 'Search service', |
26 | }, | 26 | }, |
27 | allRecipes: { | 27 | allRecipes: { |
28 | id: 'settings.recipes.all', | 28 | id: 'settings.recipes.all', |
29 | defaultMessage: '!!!All services', | 29 | defaultMessage: 'All services', |
30 | }, | 30 | }, |
31 | customRecipes: { | 31 | customRecipes: { |
32 | id: 'settings.recipes.custom', | 32 | id: 'settings.recipes.custom', |
33 | defaultMessage: '!!!Custom Services', | 33 | defaultMessage: 'Custom Services', |
34 | }, | 34 | }, |
35 | nothingFound: { | 35 | nothingFound: { |
36 | id: 'settings.recipes.nothingFound', | 36 | id: 'settings.recipes.nothingFound', |
37 | defaultMessage: '!!!Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | 37 | defaultMessage: |
38 | 'Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | ||
38 | }, | 39 | }, |
39 | servicesSuccessfulAddedInfo: { | 40 | servicesSuccessfulAddedInfo: { |
40 | id: 'settings.recipes.servicesSuccessfulAddedInfo', | 41 | id: 'settings.recipes.servicesSuccessfulAddedInfo', |
41 | defaultMessage: '!!!Service successfully added', | 42 | defaultMessage: 'Service successfully added', |
42 | }, | 43 | }, |
43 | missingService: { | 44 | missingService: { |
44 | id: 'settings.recipes.missingService', | 45 | id: 'settings.recipes.missingService', |
45 | defaultMessage: '!!!Missing a service?', | 46 | defaultMessage: 'Missing a service?', |
46 | }, | 47 | }, |
47 | customRecipeIntro: { | 48 | customRecipeIntro: { |
48 | id: 'settings.recipes.customService.intro', | 49 | id: 'settings.recipes.customService.intro', |
49 | defaultMessage: '!!!To add a custom service, copy the recipe folder into:', | 50 | defaultMessage: 'To add a custom service, copy the recipe folder into:', |
50 | }, | 51 | }, |
51 | openFolder: { | 52 | openFolder: { |
52 | id: 'settings.recipes.customService.openFolder', | 53 | id: 'settings.recipes.customService.openFolder', |
53 | defaultMessage: '!!!Open directory', | 54 | defaultMessage: 'Open directory', |
54 | }, | 55 | }, |
55 | openDevDocs: { | 56 | openDevDocs: { |
56 | id: 'settings.recipes.customService.openDevDocs', | 57 | id: 'settings.recipes.customService.openDevDocs', |
57 | defaultMessage: '!!!Developer Documentation', | 58 | defaultMessage: 'Developer Documentation', |
58 | }, | 59 | }, |
59 | headlineCustomRecipes: { | 60 | headlineCustomRecipes: { |
60 | id: 'settings.recipes.customService.headline.customRecipes', | 61 | id: 'settings.recipes.customService.headline.customRecipes', |
61 | defaultMessage: '!!!Custom 3rd Party Recipes', | 62 | defaultMessage: 'Custom 3rd Party Recipes', |
62 | }, | 63 | }, |
63 | headlineCommunityRecipes: { | 64 | headlineCommunityRecipes: { |
64 | id: 'settings.recipes.customService.headline.communityRecipes', | 65 | id: 'settings.recipes.customService.headline.communityRecipes', |
65 | defaultMessage: '!!!Community 3rd Party Recipes', | 66 | defaultMessage: 'Community 3rd Party Recipes', |
66 | }, | 67 | }, |
67 | headlineDevRecipes: { | 68 | headlineDevRecipes: { |
68 | id: 'settings.recipes.customService.headline.devRecipes', | 69 | id: 'settings.recipes.customService.headline.devRecipes', |
69 | defaultMessage: '!!!Your Development Service Recipes', | 70 | defaultMessage: 'Your Development Service Recipes', |
70 | }, | 71 | }, |
71 | }); | 72 | }); |
72 | 73 | ||
@@ -81,7 +82,8 @@ const styles = { | |||
81 | marginTop: 20, | 82 | marginTop: 20, |
82 | 83 | ||
83 | '& > div': { | 84 | '& > div': { |
84 | fontFamily: 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | 85 | fontFamily: |
86 | 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | ||
85 | }, | 87 | }, |
86 | }, | 88 | }, |
87 | actionContainer: { | 89 | actionContainer: { |
@@ -98,7 +100,9 @@ const styles = { | |||
98 | }, | 100 | }, |
99 | }; | 101 | }; |
100 | 102 | ||
101 | export default @injectSheet(styles) @observer class RecipesDashboard extends Component { | 103 | @injectSheet(styles) |
104 | @observer | ||
105 | class RecipesDashboard extends Component { | ||
102 | static propTypes = { | 106 | static propTypes = { |
103 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, | 107 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, |
104 | customWebsiteRecipe: PropTypes.instanceOf(RecipePreview).isRequired, | 108 | customWebsiteRecipe: PropTypes.instanceOf(RecipePreview).isRequired, |
@@ -118,10 +122,6 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
118 | static defaultProps = { | 122 | static defaultProps = { |
119 | searchNeedle: '', | 123 | searchNeedle: '', |
120 | recipeFilter: 'all', | 124 | recipeFilter: 'all', |
121 | } | ||
122 | |||
123 | static contextTypes = { | ||
124 | intl: intlShape, | ||
125 | }; | 125 | }; |
126 | 126 | ||
127 | render() { | 127 | render() { |
@@ -140,7 +140,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
140 | openDevDocs, | 140 | openDevDocs, |
141 | classes, | 141 | classes, |
142 | } = this.props; | 142 | } = this.props; |
143 | const { intl } = this.context; | 143 | const { intl } = this.props; |
144 | 144 | ||
145 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); | 145 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); |
146 | const devRecipes = recipes.filter(r => r.isDevRecipe); | 146 | const devRecipes = recipes.filter(r => r.isDevRecipe); |
@@ -188,9 +188,13 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
188 | > | 188 | > |
189 | {intl.formatMessage(messages.customRecipes)} | 189 | {intl.formatMessage(messages.customRecipes)} |
190 | </Link> | 190 | </Link> |
191 | <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request" rel="noreferrer"> | 191 | <a |
192 | {intl.formatMessage(messages.missingService)} | 192 | href={FRANZ_SERVICE_REQUEST} |
193 | {' '} | 193 | target="_blank" |
194 | className="link recipes__service-request" | ||
195 | rel="noreferrer" | ||
196 | > | ||
197 | {intl.formatMessage(messages.missingService)}{' '} | ||
194 | <i className="mdi mdi-open-in-new" /> | 198 | <i className="mdi mdi-open-in-new" /> |
195 | </a> | 199 | </a> |
196 | </div> | 200 | </div> |
@@ -201,13 +205,9 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
201 | <> | 205 | <> |
202 | {recipeFilter === 'dev' && ( | 206 | {recipeFilter === 'dev' && ( |
203 | <> | 207 | <> |
204 | <H2> | 208 | <H2>{intl.formatMessage(messages.headlineCustomRecipes)}</H2> |
205 | {intl.formatMessage(messages.headlineCustomRecipes)} | ||
206 | </H2> | ||
207 | <div className={classes.devRecipeIntroContainer}> | 209 | <div className={classes.devRecipeIntroContainer}> |
208 | <p> | 210 | <p>{intl.formatMessage(messages.customRecipeIntro)}</p> |
209 | {intl.formatMessage(messages.customRecipeIntro)} | ||
210 | </p> | ||
211 | <Input | 211 | <Input |
212 | value={recipeDirectory} | 212 | value={recipeDirectory} |
213 | className={classes.path} | 213 | className={classes.path} |
@@ -238,12 +238,19 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
238 | <img src="./assets/images/emoji/dontknow.png" alt="" /> | 238 | <img src="./assets/images/emoji/dontknow.png" alt="" /> |
239 | </span> | 239 | </span> |
240 | 240 | ||
241 | <p className="settings__empty-state-text">{intl.formatMessage(messages.nothingFound)}</p> | 241 | <p className="settings__empty-state-text"> |
242 | {intl.formatMessage(messages.nothingFound)} | ||
243 | </p> | ||
242 | 244 | ||
243 | <RecipeItem | 245 | <RecipeItem |
244 | key={customWebsiteRecipe.id} | 246 | key={customWebsiteRecipe.id} |
245 | recipe={customWebsiteRecipe} | 247 | recipe={customWebsiteRecipe} |
246 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: customWebsiteRecipe.id })} | 248 | onClick={() => |
249 | isLoggedIn && | ||
250 | showAddServiceInterface({ | ||
251 | recipeId: customWebsiteRecipe.id, | ||
252 | }) | ||
253 | } | ||
247 | /> | 254 | /> |
248 | </div> | 255 | </div> |
249 | )} | 256 | )} |
@@ -251,7 +258,10 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
251 | <RecipeItem | 258 | <RecipeItem |
252 | key={recipe.id} | 259 | key={recipe.id} |
253 | recipe={recipe} | 260 | recipe={recipe} |
254 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} | 261 | onClick={() => |
262 | isLoggedIn && | ||
263 | showAddServiceInterface({ recipeId: recipe.id }) | ||
264 | } | ||
255 | /> | 265 | /> |
256 | ))} | 266 | ))} |
257 | </div> | 267 | </div> |
@@ -263,7 +273,10 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
263 | <RecipeItem | 273 | <RecipeItem |
264 | key={recipe.id} | 274 | key={recipe.id} |
265 | recipe={recipe} | 275 | recipe={recipe} |
266 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} | 276 | onClick={() => |
277 | isLoggedIn && | ||
278 | showAddServiceInterface({ recipeId: recipe.id }) | ||
279 | } | ||
267 | /> | 280 | /> |
268 | ))} | 281 | ))} |
269 | </div> | 282 | </div> |
@@ -276,3 +289,5 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
276 | ); | 289 | ); |
277 | } | 290 | } |
278 | } | 291 | } |
292 | |||
293 | export default injectIntl(RecipesDashboard); | ||
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index c41cdd56a..3fbb57cbb 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import normalizeUrl from 'normalize-url'; | 6 | import normalizeUrl from 'normalize-url'; |
7 | 7 | ||
8 | import Form from '../../../lib/Form'; | 8 | import Form from '../../../lib/Form'; |
@@ -22,111 +22,117 @@ import globalMessages from '../../../i18n/globalMessages'; | |||
22 | const messages = defineMessages({ | 22 | const messages = defineMessages({ |
23 | saveService: { | 23 | saveService: { |
24 | id: 'settings.service.form.saveButton', | 24 | id: 'settings.service.form.saveButton', |
25 | defaultMessage: '!!!Save service', | 25 | defaultMessage: 'Save service', |
26 | }, | 26 | }, |
27 | deleteService: { | 27 | deleteService: { |
28 | id: 'settings.service.form.deleteButton', | 28 | id: 'settings.service.form.deleteButton', |
29 | defaultMessage: '!!!Delete Service', | 29 | defaultMessage: 'Delete Service', |
30 | }, | 30 | }, |
31 | openDarkmodeCss: { | 31 | openDarkmodeCss: { |
32 | id: 'settings.service.form.openDarkmodeCss', | 32 | id: 'settings.service.form.openDarkmodeCss', |
33 | defaultMessage: '!!!Open darkmode.css', | 33 | defaultMessage: 'Open darkmode.css', |
34 | }, | 34 | }, |
35 | openUserCss: { | 35 | openUserCss: { |
36 | id: 'settings.service.form.openUserCss', | 36 | id: 'settings.service.form.openUserCss', |
37 | defaultMessage: '!!!Open user.css', | 37 | defaultMessage: 'Open user.css', |
38 | }, | 38 | }, |
39 | openUserJs: { | 39 | openUserJs: { |
40 | id: 'settings.service.form.openUserJs', | 40 | id: 'settings.service.form.openUserJs', |
41 | defaultMessage: '!!!Open user.js', | 41 | defaultMessage: 'Open user.js', |
42 | }, | 42 | }, |
43 | recipeFileInfo: { | 43 | recipeFileInfo: { |
44 | id: 'settings.service.form.recipeFileInfo', | 44 | id: 'settings.service.form.recipeFileInfo', |
45 | defaultMessage: '!!!Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.', | 45 | defaultMessage: |
46 | 'Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.', | ||
46 | }, | 47 | }, |
47 | availableServices: { | 48 | availableServices: { |
48 | id: 'settings.service.form.availableServices', | 49 | id: 'settings.service.form.availableServices', |
49 | defaultMessage: '!!!Available services', | 50 | defaultMessage: 'Available services', |
50 | }, | 51 | }, |
51 | yourServices: { | 52 | yourServices: { |
52 | id: 'settings.service.form.yourServices', | 53 | id: 'settings.service.form.yourServices', |
53 | defaultMessage: '!!!Your services', | 54 | defaultMessage: 'Your services', |
54 | }, | 55 | }, |
55 | addServiceHeadline: { | 56 | addServiceHeadline: { |
56 | id: 'settings.service.form.addServiceHeadline', | 57 | id: 'settings.service.form.addServiceHeadline', |
57 | defaultMessage: '!!!Add {name}', | 58 | defaultMessage: 'Add {name}', |
58 | }, | 59 | }, |
59 | editServiceHeadline: { | 60 | editServiceHeadline: { |
60 | id: 'settings.service.form.editServiceHeadline', | 61 | id: 'settings.service.form.editServiceHeadline', |
61 | defaultMessage: '!!!Edit {name}', | 62 | defaultMessage: 'Edit {name}', |
62 | }, | 63 | }, |
63 | tabHosted: { | 64 | tabHosted: { |
64 | id: 'settings.service.form.tabHosted', | 65 | id: 'settings.service.form.tabHosted', |
65 | defaultMessage: '!!!Hosted', | 66 | defaultMessage: 'Hosted', |
66 | }, | 67 | }, |
67 | tabOnPremise: { | 68 | tabOnPremise: { |
68 | id: 'settings.service.form.tabOnPremise', | 69 | id: 'settings.service.form.tabOnPremise', |
69 | defaultMessage: '!!!Self hosted ⭐️', | 70 | defaultMessage: 'Self hosted ⭐️', |
70 | }, | 71 | }, |
71 | useHostedService: { | 72 | useHostedService: { |
72 | id: 'settings.service.form.useHostedService', | 73 | id: 'settings.service.form.useHostedService', |
73 | defaultMessage: '!!!Use the hosted {name} service.', | 74 | defaultMessage: 'Use the hosted {name} service.', |
74 | }, | 75 | }, |
75 | customUrlValidationError: { | 76 | customUrlValidationError: { |
76 | id: 'settings.service.form.customUrlValidationError', | 77 | id: 'settings.service.form.customUrlValidationError', |
77 | defaultMessage: '!!!Could not validate custom {name} server.', | 78 | defaultMessage: 'Could not validate custom {name} server.', |
78 | }, | 79 | }, |
79 | indirectMessageInfo: { | 80 | indirectMessageInfo: { |
80 | id: 'settings.service.form.indirectMessageInfo', | 81 | id: 'settings.service.form.indirectMessageInfo', |
81 | defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', | 82 | defaultMessage: |
83 | 'You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', | ||
82 | }, | 84 | }, |
83 | isMutedInfo: { | 85 | isMutedInfo: { |
84 | id: 'settings.service.form.isMutedInfo', | 86 | id: 'settings.service.form.isMutedInfo', |
85 | defaultMessage: '!!!When disabled, all notification sounds and audio playback are muted', | 87 | defaultMessage: |
88 | 'When disabled, all notification sounds and audio playback are muted', | ||
86 | }, | 89 | }, |
87 | isHibernationEnabledInfo: { | 90 | isHibernationEnabledInfo: { |
88 | id: 'settings.service.form.isHibernatedEnabledInfo', | 91 | id: 'settings.service.form.isHibernatedEnabledInfo', |
89 | defaultMessage: '!!!When enabled, a service will be shut down after a period of time to save system resources.', | 92 | defaultMessage: |
93 | 'When enabled, a service will be shut down after a period of time to save system resources.', | ||
90 | }, | 94 | }, |
91 | headlineNotifications: { | 95 | headlineNotifications: { |
92 | id: 'settings.service.form.headlineNotifications', | 96 | id: 'settings.service.form.headlineNotifications', |
93 | defaultMessage: '!!!Notifications', | 97 | defaultMessage: 'Notifications', |
94 | }, | 98 | }, |
95 | headlineBadges: { | 99 | headlineBadges: { |
96 | id: 'settings.service.form.headlineBadges', | 100 | id: 'settings.service.form.headlineBadges', |
97 | defaultMessage: '!!!Unread message badges', | 101 | defaultMessage: 'Unread message badges', |
98 | }, | 102 | }, |
99 | headlineGeneral: { | 103 | headlineGeneral: { |
100 | id: 'settings.service.form.headlineGeneral', | 104 | id: 'settings.service.form.headlineGeneral', |
101 | defaultMessage: '!!!General', | 105 | defaultMessage: 'General', |
102 | }, | 106 | }, |
103 | headlineDarkReaderSettings: { | 107 | headlineDarkReaderSettings: { |
104 | id: 'settings.service.form.headlineDarkReaderSettings', | 108 | id: 'settings.service.form.headlineDarkReaderSettings', |
105 | defaultMessage: '!!!Dark Reader Settings', | 109 | defaultMessage: 'Dark Reader Settings', |
106 | }, | 110 | }, |
107 | iconDelete: { | 111 | iconDelete: { |
108 | id: 'settings.service.form.iconDelete', | 112 | id: 'settings.service.form.iconDelete', |
109 | defaultMessage: '!!!Delete', | 113 | defaultMessage: 'Delete', |
110 | }, | 114 | }, |
111 | iconUpload: { | 115 | iconUpload: { |
112 | id: 'settings.service.form.iconUpload', | 116 | id: 'settings.service.form.iconUpload', |
113 | defaultMessage: '!!!Drop your image, or click here', | 117 | defaultMessage: 'Drop your image, or click here', |
114 | }, | 118 | }, |
115 | headlineProxy: { | 119 | headlineProxy: { |
116 | id: 'settings.service.form.proxy.headline', | 120 | id: 'settings.service.form.proxy.headline', |
117 | defaultMessage: '!!!HTTP/HTTPS Proxy Settings', | 121 | defaultMessage: 'HTTP/HTTPS Proxy Settings', |
118 | }, | 122 | }, |
119 | proxyRestartInfo: { | 123 | proxyRestartInfo: { |
120 | id: 'settings.service.form.proxy.restartInfo', | 124 | id: 'settings.service.form.proxy.restartInfo', |
121 | defaultMessage: '!!!Please restart Ferdi after changing proxy Settings.', | 125 | defaultMessage: 'Please restart Ferdi after changing proxy Settings.', |
122 | }, | 126 | }, |
123 | proxyInfo: { | 127 | proxyInfo: { |
124 | id: 'settings.service.form.proxy.info', | 128 | id: 'settings.service.form.proxy.info', |
125 | defaultMessage: '!!!Proxy settings will not be synchronized with the Ferdi servers.', | 129 | defaultMessage: |
130 | 'Proxy settings will not be synchronized with the Ferdi servers.', | ||
126 | }, | 131 | }, |
127 | }); | 132 | }); |
128 | 133 | ||
129 | export default @observer class EditServiceForm extends Component { | 134 | @observer |
135 | class EditServiceForm extends Component { | ||
130 | static propTypes = { | 136 | static propTypes = { |
131 | recipe: PropTypes.instanceOf(Recipe).isRequired, | 137 | recipe: PropTypes.instanceOf(Recipe).isRequired, |
132 | service(props, propName) { | 138 | service(props, propName) { |
@@ -151,20 +157,16 @@ export default @observer class EditServiceForm extends Component { | |||
151 | service: {}, | 157 | service: {}, |
152 | }; | 158 | }; |
153 | 159 | ||
154 | static contextTypes = { | ||
155 | intl: intlShape, | ||
156 | }; | ||
157 | |||
158 | state = { | 160 | state = { |
159 | isValidatingCustomUrl: false, | 161 | isValidatingCustomUrl: false, |
160 | } | 162 | }; |
161 | 163 | ||
162 | submit(e) { | 164 | submit(e) { |
163 | const { recipe } = this.props; | 165 | const { recipe } = this.props; |
164 | 166 | ||
165 | e.preventDefault(); | 167 | e.preventDefault(); |
166 | this.props.form.submit({ | 168 | this.props.form.submit({ |
167 | onSuccess: async (form) => { | 169 | onSuccess: async form => { |
168 | const values = form.values(); | 170 | const values = form.values(); |
169 | let isValid = true; | 171 | let isValid = true; |
170 | 172 | ||
@@ -176,7 +178,10 @@ export default @observer class EditServiceForm extends Component { | |||
176 | if (recipe.validateUrl && values.customUrl) { | 178 | if (recipe.validateUrl && values.customUrl) { |
177 | this.setState({ isValidatingCustomUrl: true }); | 179 | this.setState({ isValidatingCustomUrl: true }); |
178 | try { | 180 | try { |
179 | values.customUrl = normalizeUrl(values.customUrl, { stripWWW: false, removeTrailingSlash: false }); | 181 | values.customUrl = normalizeUrl(values.customUrl, { |
182 | stripWWW: false, | ||
183 | removeTrailingSlash: false, | ||
184 | }); | ||
180 | isValid = await recipe.validateUrl(values.customUrl); | 185 | isValid = await recipe.validateUrl(values.customUrl); |
181 | } catch (err) { | 186 | } catch (err) { |
182 | console.warn('ValidateURL', err); | 187 | console.warn('ValidateURL', err); |
@@ -208,7 +213,7 @@ export default @observer class EditServiceForm extends Component { | |||
208 | openRecipeFile, | 213 | openRecipeFile, |
209 | isProxyFeatureEnabled, | 214 | isProxyFeatureEnabled, |
210 | } = this.props; | 215 | } = this.props; |
211 | const { intl } = this.context; | 216 | const { intl } = this.props; |
212 | 217 | ||
213 | const { isValidatingCustomUrl } = this.state; | 218 | const { isValidatingCustomUrl } = this.state; |
214 | 219 | ||
@@ -236,7 +241,8 @@ export default @observer class EditServiceForm extends Component { | |||
236 | activeTabIndex = 2; | 241 | activeTabIndex = 2; |
237 | } | 242 | } |
238 | 243 | ||
239 | const requiresUserInput = !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); | 244 | const requiresUserInput = |
245 | !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); | ||
240 | 246 | ||
241 | return ( | 247 | return ( |
242 | <div className="settings__main"> | 248 | <div className="settings__main"> |
@@ -254,29 +260,27 @@ export default @observer class EditServiceForm extends Component { | |||
254 | </span> | 260 | </span> |
255 | <span className="separator" /> | 261 | <span className="separator" /> |
256 | <span className="settings__header-item"> | 262 | <span className="settings__header-item"> |
257 | {action === 'add' ? ( | 263 | {action === 'add' |
258 | intl.formatMessage(messages.addServiceHeadline, { | 264 | ? intl.formatMessage(messages.addServiceHeadline, { |
259 | name: recipe.name, | 265 | name: recipe.name, |
260 | }) | 266 | }) |
261 | ) : ( | 267 | : intl.formatMessage(messages.editServiceHeadline, { |
262 | intl.formatMessage(messages.editServiceHeadline, { | ||
263 | name: service.name !== '' ? service.name : recipe.name, | 268 | name: service.name !== '' ? service.name : recipe.name, |
264 | }) | 269 | })} |
265 | )} | ||
266 | </span> | 270 | </span> |
267 | </div> | 271 | </div> |
268 | <div className="settings__body"> | 272 | <div className="settings__body"> |
269 | <form onSubmit={(e) => this.submit(e)} id="form"> | 273 | <form onSubmit={e => this.submit(e)} id="form"> |
270 | <div className="service-name"> | 274 | <div className="service-name"> |
271 | <Input field={form.$('name')} focus /> | 275 | <Input field={form.$('name')} focus /> |
272 | </div> | 276 | </div> |
273 | {(recipe.hasTeamId || recipe.hasCustomUrl) && ( | 277 | {(recipe.hasTeamId || recipe.hasCustomUrl) && ( |
274 | <Tabs | 278 | <Tabs active={activeTabIndex}> |
275 | active={activeTabIndex} | ||
276 | > | ||
277 | {recipe.hasHostedOption && ( | 279 | {recipe.hasHostedOption && ( |
278 | <TabItem title={recipe.name}> | 280 | <TabItem title={recipe.name}> |
279 | {intl.formatMessage(messages.useHostedService, { name: recipe.name })} | 281 | {intl.formatMessage(messages.useHostedService, { |
282 | name: recipe.name, | ||
283 | })} | ||
280 | </TabItem> | 284 | </TabItem> |
281 | )} | 285 | )} |
282 | {recipe.hasTeamId && ( | 286 | {recipe.hasTeamId && ( |
@@ -293,7 +297,9 @@ export default @observer class EditServiceForm extends Component { | |||
293 | <Input field={form.$('customUrl')} /> | 297 | <Input field={form.$('customUrl')} /> |
294 | {form.error === 'url-validation-error' && ( | 298 | {form.error === 'url-validation-error' && ( |
295 | <p className="franz-form__error"> | 299 | <p className="franz-form__error"> |
296 | {intl.formatMessage(messages.customUrlValidationError, { name: recipe.name })} | 300 | {intl.formatMessage(messages.customUrlValidationError, { |
301 | name: recipe.name, | ||
302 | })} | ||
297 | </p> | 303 | </p> |
298 | )} | 304 | )} |
299 | </TabItem> | 305 | </TabItem> |
@@ -326,13 +332,16 @@ export default @observer class EditServiceForm extends Component { | |||
326 | <div className="settings__settings-group"> | 332 | <div className="settings__settings-group"> |
327 | <h3>{intl.formatMessage(messages.headlineBadges)}</h3> | 333 | <h3>{intl.formatMessage(messages.headlineBadges)}</h3> |
328 | <Toggle field={form.$('isBadgeEnabled')} /> | 334 | <Toggle field={form.$('isBadgeEnabled')} /> |
329 | {recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && ( | 335 | {recipe.hasIndirectMessages && |
330 | <> | 336 | form.$('isBadgeEnabled').value && ( |
331 | <Toggle field={form.$('isIndirectMessageBadgeEnabled')} /> | 337 | <> |
332 | <p className="settings__help indented__help"> | 338 | <Toggle |
333 | {intl.formatMessage(messages.indirectMessageInfo)} | 339 | field={form.$('isIndirectMessageBadgeEnabled')} |
334 | </p> | 340 | /> |
335 | </> | 341 | <p className="settings__help indented__help"> |
342 | {intl.formatMessage(messages.indirectMessageInfo)} | ||
343 | </p> | ||
344 | </> | ||
336 | )} | 345 | )} |
337 | </div> | 346 | </div> |
338 | 347 | ||
@@ -344,15 +353,18 @@ export default @observer class EditServiceForm extends Component { | |||
344 | {intl.formatMessage(messages.isHibernationEnabledInfo)} | 353 | {intl.formatMessage(messages.isHibernationEnabledInfo)} |
345 | </p> | 354 | </p> |
346 | <Toggle field={form.$('isDarkModeEnabled')} /> | 355 | <Toggle field={form.$('isDarkModeEnabled')} /> |
347 | {form.$('isDarkModeEnabled').value | 356 | {form.$('isDarkModeEnabled').value && ( |
348 | && ( | 357 | <> |
349 | <> | 358 | <h3> |
350 | <h3>{intl.formatMessage(messages.headlineDarkReaderSettings)}</h3> | 359 | {intl.formatMessage( |
351 | <Slider field={form.$('darkReaderBrightness')} /> | 360 | messages.headlineDarkReaderSettings, |
352 | <Slider field={form.$('darkReaderContrast')} /> | 361 | )} |
353 | <Slider field={form.$('darkReaderSepia')} /> | 362 | </h3> |
354 | </> | 363 | <Slider field={form.$('darkReaderBrightness')} /> |
355 | )} | 364 | <Slider field={form.$('darkReaderContrast')} /> |
365 | <Slider field={form.$('darkReaderSepia')} /> | ||
366 | </> | ||
367 | )} | ||
356 | </div> | 368 | </div> |
357 | </div> | 369 | </div> |
358 | <div className="service-icon"> | 370 | <div className="service-icon"> |
@@ -381,7 +393,10 @@ export default @observer class EditServiceForm extends Component { | |||
381 | <> | 393 | <> |
382 | <div className="grid"> | 394 | <div className="grid"> |
383 | <div className="grid__row"> | 395 | <div className="grid__row"> |
384 | <Input field={form.$('proxy.host')} className="proxyHost" /> | 396 | <Input |
397 | field={form.$('proxy.host')} | ||
398 | className="proxyHost" | ||
399 | /> | ||
385 | <Input field={form.$('proxy.port')} /> | 400 | <Input field={form.$('proxy.port')} /> |
386 | </div> | 401 | </div> |
387 | </div> | 402 | </div> |
@@ -409,7 +424,9 @@ export default @observer class EditServiceForm extends Component { | |||
409 | 424 | ||
410 | <div className="user-agent"> | 425 | <div className="user-agent"> |
411 | <Input field={form.$('userAgentPref')} /> | 426 | <Input field={form.$('userAgentPref')} /> |
412 | <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> | 427 | <p className="settings__help"> |
428 | {intl.formatMessage(globalMessages.userAgentHelp)} | ||
429 | </p> | ||
413 | </div> | 430 | </div> |
414 | </form> | 431 | </form> |
415 | 432 | ||
@@ -464,7 +481,9 @@ export default @observer class EditServiceForm extends Component { | |||
464 | type="submit" | 481 | type="submit" |
465 | label={intl.formatMessage(messages.saveService)} | 482 | label={intl.formatMessage(messages.saveService)} |
466 | htmlForm="form" | 483 | htmlForm="form" |
467 | disabled={action !== 'edit' && (form.isPristine && requiresUserInput)} | 484 | disabled={ |
485 | action !== 'edit' && form.isPristine && requiresUserInput | ||
486 | } | ||
468 | /> | 487 | /> |
469 | )} | 488 | )} |
470 | </div> | 489 | </div> |
@@ -472,3 +491,5 @@ export default @observer class EditServiceForm extends Component { | |||
472 | ); | 491 | ); |
473 | } | 492 | } |
474 | } | 493 | } |
494 | |||
495 | export default injectIntl(EditServiceForm); | ||
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js index 3cfc080d6..d16d76db2 100644 --- a/src/components/settings/services/ServiceError.js +++ b/src/components/settings/services/ServiceError.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import { observer } from 'mobx-react'; | 2 | import { observer } from 'mobx-react'; |
3 | import { Link } from 'react-router'; | 3 | import { Link } from 'react-router'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import Infobox from '../../ui/Infobox'; | 6 | import Infobox from '../../ui/Infobox'; |
7 | import Button from '../../ui/Button'; | 7 | import Button from '../../ui/Button'; |
@@ -9,29 +9,26 @@ import Button from '../../ui/Button'; | |||
9 | const messages = defineMessages({ | 9 | const messages = defineMessages({ |
10 | headline: { | 10 | headline: { |
11 | id: 'settings.service.error.headline', | 11 | id: 'settings.service.error.headline', |
12 | defaultMessage: '!!!Error', | 12 | defaultMessage: 'Error', |
13 | }, | 13 | }, |
14 | goBack: { | 14 | goBack: { |
15 | id: 'settings.service.error.goBack', | 15 | id: 'settings.service.error.goBack', |
16 | defaultMessage: '!!!Back to services', | 16 | defaultMessage: 'Back to services', |
17 | }, | 17 | }, |
18 | availableServices: { | 18 | availableServices: { |
19 | id: 'settings.service.form.availableServices', | 19 | id: 'settings.service.form.availableServices', |
20 | defaultMessage: '!!!Available services', | 20 | defaultMessage: 'Available services', |
21 | }, | 21 | }, |
22 | errorMessage: { | 22 | errorMessage: { |
23 | id: 'settings.service.error.message', | 23 | id: 'settings.service.error.message', |
24 | defaultMessage: '!!!Could not load service recipe.', | 24 | defaultMessage: 'Could not load service recipe.', |
25 | }, | 25 | }, |
26 | }); | 26 | }); |
27 | 27 | ||
28 | export default @observer class ServiceError extends Component { | 28 | @observer |
29 | static contextTypes = { | 29 | class ServiceError extends Component { |
30 | intl: intlShape, | ||
31 | }; | ||
32 | |||
33 | render() { | 30 | render() { |
34 | const { intl } = this.context; | 31 | const { intl } = this.props; |
35 | 32 | ||
36 | return ( | 33 | return ( |
37 | <div className="settings__main"> | 34 | <div className="settings__main"> |
@@ -47,10 +44,7 @@ export default @observer class ServiceError extends Component { | |||
47 | </span> | 44 | </span> |
48 | </div> | 45 | </div> |
49 | <div className="settings__body"> | 46 | <div className="settings__body"> |
50 | <Infobox | 47 | <Infobox type="danger" icon="alert"> |
51 | type="danger" | ||
52 | icon="alert" | ||
53 | > | ||
54 | {intl.formatMessage(messages.errorMessage)} | 48 | {intl.formatMessage(messages.errorMessage)} |
55 | </Infobox> | 49 | </Infobox> |
56 | </div> | 50 | </div> |
@@ -65,3 +59,5 @@ export default @observer class ServiceError extends Component { | |||
65 | ); | 59 | ); |
66 | } | 60 | } |
67 | } | 61 | } |
62 | |||
63 | export default injectIntl(ServiceError); | ||
diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js index ebc618a00..4916e4ecc 100644 --- a/src/components/settings/services/ServiceItem.js +++ b/src/components/settings/services/ServiceItem.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | import ReactTooltip from 'react-tooltip'; | 4 | import ReactTooltip from 'react-tooltip'; |
5 | import { observer } from 'mobx-react'; | 5 | import { observer } from 'mobx-react'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
@@ -10,35 +10,32 @@ import ServiceModel from '../../../models/Service'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | tooltipIsDisabled: { | 11 | tooltipIsDisabled: { |
12 | id: 'settings.services.tooltip.isDisabled', | 12 | id: 'settings.services.tooltip.isDisabled', |
13 | defaultMessage: '!!!Service is disabled', | 13 | defaultMessage: 'Service is disabled', |
14 | }, | 14 | }, |
15 | tooltipNotificationsDisabled: { | 15 | tooltipNotificationsDisabled: { |
16 | id: 'settings.services.tooltip.notificationsDisabled', | 16 | id: 'settings.services.tooltip.notificationsDisabled', |
17 | defaultMessage: '!!!Notifications are disabled', | 17 | defaultMessage: 'Notifications are disabled', |
18 | }, | 18 | }, |
19 | tooltipIsMuted: { | 19 | tooltipIsMuted: { |
20 | id: 'settings.services.tooltip.isMuted', | 20 | id: 'settings.services.tooltip.isMuted', |
21 | defaultMessage: '!!!All sounds are muted', | 21 | defaultMessage: 'All sounds are muted', |
22 | }, | 22 | }, |
23 | }); | 23 | }); |
24 | 24 | ||
25 | export default @observer class ServiceItem extends Component { | 25 | @observer |
26 | class ServiceItem extends Component { | ||
26 | static propTypes = { | 27 | static propTypes = { |
27 | service: PropTypes.instanceOf(ServiceModel).isRequired, | 28 | service: PropTypes.instanceOf(ServiceModel).isRequired, |
28 | goToServiceForm: PropTypes.func.isRequired, | 29 | goToServiceForm: PropTypes.func.isRequired, |
29 | }; | 30 | }; |
30 | 31 | ||
31 | static contextTypes = { | ||
32 | intl: intlShape, | ||
33 | }; | ||
34 | |||
35 | render() { | 32 | render() { |
36 | const { | 33 | const { |
37 | service, | 34 | service, |
38 | // toggleAction, | 35 | // toggleAction, |
39 | goToServiceForm, | 36 | goToServiceForm, |
40 | } = this.props; | 37 | } = this.props; |
41 | const { intl } = this.context; | 38 | const { intl } = this.props; |
42 | 39 | ||
43 | return ( | 40 | return ( |
44 | <tr | 41 | <tr |
@@ -47,10 +44,7 @@ export default @observer class ServiceItem extends Component { | |||
47 | 'service-table__row--disabled': !service.isEnabled, | 44 | 'service-table__row--disabled': !service.isEnabled, |
48 | })} | 45 | })} |
49 | > | 46 | > |
50 | <td | 47 | <td className="service-table__column-icon" onClick={goToServiceForm}> |
51 | className="service-table__column-icon" | ||
52 | onClick={goToServiceForm} | ||
53 | > | ||
54 | <img | 48 | <img |
55 | src={service.icon} | 49 | src={service.icon} |
56 | className={classnames({ | 50 | className={classnames({ |
@@ -60,16 +54,10 @@ export default @observer class ServiceItem extends Component { | |||
60 | alt="" | 54 | alt="" |
61 | /> | 55 | /> |
62 | </td> | 56 | </td> |
63 | <td | 57 | <td className="service-table__column-name" onClick={goToServiceForm}> |
64 | className="service-table__column-name" | ||
65 | onClick={goToServiceForm} | ||
66 | > | ||
67 | {service.name !== '' ? service.name : service.recipe.name} | 58 | {service.name !== '' ? service.name : service.recipe.name} |
68 | </td> | 59 | </td> |
69 | <td | 60 | <td className="service-table__column-info" onClick={goToServiceForm}> |
70 | className="service-table__column-info" | ||
71 | onClick={goToServiceForm} | ||
72 | > | ||
73 | {service.isMuted && ( | 61 | {service.isMuted && ( |
74 | <span | 62 | <span |
75 | className="mdi mdi-bell-off" | 63 | className="mdi mdi-bell-off" |
@@ -77,10 +65,7 @@ export default @observer class ServiceItem extends Component { | |||
77 | /> | 65 | /> |
78 | )} | 66 | )} |
79 | </td> | 67 | </td> |
80 | <td | 68 | <td className="service-table__column-info" onClick={goToServiceForm}> |
81 | className="service-table__column-info" | ||
82 | onClick={goToServiceForm} | ||
83 | > | ||
84 | {!service.isEnabled && ( | 69 | {!service.isEnabled && ( |
85 | <span | 70 | <span |
86 | className="mdi mdi-power" | 71 | className="mdi mdi-power" |
@@ -88,14 +73,13 @@ export default @observer class ServiceItem extends Component { | |||
88 | /> | 73 | /> |
89 | )} | 74 | )} |
90 | </td> | 75 | </td> |
91 | <td | 76 | <td className="service-table__column-info" onClick={goToServiceForm}> |
92 | className="service-table__column-info" | ||
93 | onClick={goToServiceForm} | ||
94 | > | ||
95 | {!service.isNotificationEnabled && ( | 77 | {!service.isNotificationEnabled && ( |
96 | <span | 78 | <span |
97 | className="mdi mdi-message-bulleted-off" | 79 | className="mdi mdi-message-bulleted-off" |
98 | data-tip={intl.formatMessage(messages.tooltipNotificationsDisabled)} | 80 | data-tip={intl.formatMessage( |
81 | messages.tooltipNotificationsDisabled, | ||
82 | )} | ||
99 | /> | 83 | /> |
100 | )} | 84 | )} |
101 | <ReactTooltip place="top" type="dark" effect="solid" /> | 85 | <ReactTooltip place="top" type="dark" effect="solid" /> |
@@ -104,3 +88,5 @@ export default @observer class ServiceItem extends Component { | |||
104 | ); | 88 | ); |
105 | } | 89 | } |
106 | } | 90 | } |
91 | |||
92 | export default injectIntl(ServiceItem); | ||
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js index 11d3eaa79..847f2ea06 100644 --- a/src/components/settings/services/ServicesDashboard.js +++ b/src/components/settings/services/ServicesDashboard.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | 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 { Link } from 'react-router'; | 4 | import { Link } from 'react-router'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import SearchInput from '../../ui/SearchInput'; | 7 | import SearchInput from '../../ui/SearchInput'; |
8 | import Infobox from '../../ui/Infobox'; | 8 | import Infobox from '../../ui/Infobox'; |
@@ -14,43 +14,45 @@ import Appear from '../../ui/effects/Appear'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'settings.services.headline', | 16 | id: 'settings.services.headline', |
17 | defaultMessage: '!!!Your services', | 17 | defaultMessage: 'Your services', |
18 | }, | 18 | }, |
19 | searchService: { | 19 | searchService: { |
20 | id: 'settings.searchService', | 20 | id: 'settings.searchService', |
21 | defaultMessage: '!!!Search service', | 21 | defaultMessage: 'Search service', |
22 | }, | 22 | }, |
23 | noServicesAdded: { | 23 | noServicesAdded: { |
24 | id: 'settings.services.noServicesAdded', | 24 | id: 'settings.services.noServicesAdded', |
25 | defaultMessage: '!!!Start by adding a service.', | 25 | defaultMessage: 'Start by adding a service.', |
26 | }, | 26 | }, |
27 | noServiceFound: { | 27 | noServiceFound: { |
28 | id: 'settings.recipes.nothingFound', | 28 | id: 'settings.recipes.nothingFound', |
29 | defaultMessage: '!!!Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | 29 | defaultMessage: |
30 | 'Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | ||
30 | }, | 31 | }, |
31 | discoverServices: { | 32 | discoverServices: { |
32 | id: 'settings.services.discoverServices', | 33 | id: 'settings.services.discoverServices', |
33 | defaultMessage: '!!!Discover services', | 34 | defaultMessage: 'Discover services', |
34 | }, | 35 | }, |
35 | servicesRequestFailed: { | 36 | servicesRequestFailed: { |
36 | id: 'settings.services.servicesRequestFailed', | 37 | id: 'settings.services.servicesRequestFailed', |
37 | defaultMessage: '!!!Could not load your services', | 38 | defaultMessage: 'Could not load your services', |
38 | }, | 39 | }, |
39 | tryReloadServices: { | 40 | tryReloadServices: { |
40 | id: 'settings.account.tryReloadServices', | 41 | id: 'settings.account.tryReloadServices', |
41 | defaultMessage: '!!!Try again', | 42 | defaultMessage: 'Try again', |
42 | }, | 43 | }, |
43 | updatedInfo: { | 44 | updatedInfo: { |
44 | id: 'settings.services.updatedInfo', | 45 | id: 'settings.services.updatedInfo', |
45 | defaultMessage: '!!!Your changes have been saved', | 46 | defaultMessage: 'Your changes have been saved', |
46 | }, | 47 | }, |
47 | deletedInfo: { | 48 | deletedInfo: { |
48 | id: 'settings.services.deletedInfo', | 49 | id: 'settings.services.deletedInfo', |
49 | defaultMessage: '!!!Service has been deleted', | 50 | defaultMessage: 'Service has been deleted', |
50 | }, | 51 | }, |
51 | }); | 52 | }); |
52 | 53 | ||
53 | export default @observer class ServicesDashboard extends Component { | 54 | @observer |
55 | class ServicesDashboard extends Component { | ||
54 | static propTypes = { | 56 | static propTypes = { |
55 | services: MobxPropTypes.arrayOrObservableArray.isRequired, | 57 | services: MobxPropTypes.arrayOrObservableArray.isRequired, |
56 | isLoading: PropTypes.bool.isRequired, | 58 | isLoading: PropTypes.bool.isRequired, |
@@ -68,10 +70,6 @@ export default @observer class ServicesDashboard extends Component { | |||
68 | searchNeedle: '', | 70 | searchNeedle: '', |
69 | }; | 71 | }; |
70 | 72 | ||
71 | static contextTypes = { | ||
72 | intl: intlShape, | ||
73 | }; | ||
74 | |||
75 | render() { | 73 | render() { |
76 | const { | 74 | const { |
77 | services, | 75 | services, |
@@ -85,7 +83,7 @@ export default @observer class ServicesDashboard extends Component { | |||
85 | status, | 83 | status, |
86 | searchNeedle, | 84 | searchNeedle, |
87 | } = this.props; | 85 | } = this.props; |
88 | const { intl } = this.context; | 86 | const { intl } = this.props; |
89 | 87 | ||
90 | return ( | 88 | return ( |
91 | <div className="settings__main"> | 89 | <div className="settings__main"> |
@@ -96,7 +94,7 @@ export default @observer class ServicesDashboard extends Component { | |||
96 | {(services.length !== 0 || searchNeedle) && !isLoading && ( | 94 | {(services.length !== 0 || searchNeedle) && !isLoading && ( |
97 | <SearchInput | 95 | <SearchInput |
98 | placeholder={intl.formatMessage(messages.searchService)} | 96 | placeholder={intl.formatMessage(messages.searchService)} |
99 | onChange={(needle) => filterServices({ needle })} | 97 | onChange={needle => filterServices({ needle })} |
100 | onReset={() => resetFilter()} | 98 | onReset={() => resetFilter()} |
101 | autoFocus | 99 | autoFocus |
102 | /> | 100 | /> |
@@ -145,7 +143,9 @@ export default @observer class ServicesDashboard extends Component { | |||
145 | </span> | 143 | </span> |
146 | {intl.formatMessage(messages.noServicesAdded)} | 144 | {intl.formatMessage(messages.noServicesAdded)} |
147 | </p> | 145 | </p> |
148 | <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link> | 146 | <Link to="/settings/recipes" className="button"> |
147 | {intl.formatMessage(messages.discoverServices)} | ||
148 | </Link> | ||
149 | </div> | 149 | </div> |
150 | )} | 150 | )} |
151 | {!isLoading && services.length === 0 && searchNeedle && ( | 151 | {!isLoading && services.length === 0 && searchNeedle && ( |
@@ -163,12 +163,16 @@ export default @observer class ServicesDashboard extends Component { | |||
163 | ) : ( | 163 | ) : ( |
164 | <table className="service-table"> | 164 | <table className="service-table"> |
165 | <tbody> | 165 | <tbody> |
166 | {services.map((service) => ( | 166 | {services.map(service => ( |
167 | <ServiceItem | 167 | <ServiceItem |
168 | key={service.id} | 168 | key={service.id} |
169 | service={service} | 169 | service={service} |
170 | toggleAction={() => toggleService({ serviceId: service.id })} | 170 | toggleAction={() => |
171 | goToServiceForm={() => goTo(`/settings/services/edit/${service.id}`)} | 171 | toggleService({ serviceId: service.id }) |
172 | } | ||
173 | goToServiceForm={() => | ||
174 | goTo(`/settings/services/edit/${service.id}`) | ||
175 | } | ||
172 | /> | 176 | /> |
173 | ))} | 177 | ))} |
174 | </tbody> | 178 | </tbody> |
@@ -176,12 +180,12 @@ export default @observer class ServicesDashboard extends Component { | |||
176 | )} | 180 | )} |
177 | 181 | ||
178 | <FAB> | 182 | <FAB> |
179 | <Link to="/settings/recipes"> | 183 | <Link to="/settings/recipes">+</Link> |
180 | + | ||
181 | </Link> | ||
182 | </FAB> | 184 | </FAB> |
183 | </div> | 185 | </div> |
184 | </div> | 186 | </div> |
185 | ); | 187 | ); |
186 | } | 188 | } |
187 | } | 189 | } |
190 | |||
191 | export default injectIntl(ServicesDashboard); | ||
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 6a919b902..0a468e342 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -3,7 +3,7 @@ import React, { Component } from 'react'; | |||
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer } from 'mobx-react'; | 4 | import { observer } from 'mobx-react'; |
5 | import prettyBytes from 'pretty-bytes'; | 5 | import prettyBytes from 'pretty-bytes'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | import Form from '../../../lib/Form'; | 8 | import Form from '../../../lib/Form'; |
9 | import Button from '../../ui/Button'; | 9 | import Button from '../../ui/Button'; |
@@ -13,154 +13,173 @@ import Select from '../../ui/Select'; | |||
13 | import Input from '../../ui/Input'; | 13 | import Input from '../../ui/Input'; |
14 | 14 | ||
15 | import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config'; | 15 | import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config'; |
16 | import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, userDataPath, userDataRecipesPath } from '../../../environment'; | 16 | import { |
17 | DEFAULT_APP_SETTINGS, | ||
18 | ferdiVersion, | ||
19 | isMac, | ||
20 | isWindows, | ||
21 | lockFerdiShortcutKey, | ||
22 | userDataPath, | ||
23 | userDataRecipesPath, | ||
24 | } from '../../../environment'; | ||
17 | import { openPath } from '../../../helpers/url-helpers'; | 25 | import { openPath } from '../../../helpers/url-helpers'; |
18 | import globalMessages from '../../../i18n/globalMessages'; | 26 | import globalMessages from '../../../i18n/globalMessages'; |
19 | 27 | ||
20 | const messages = defineMessages({ | 28 | const messages = defineMessages({ |
21 | headlineGeneral: { | 29 | headlineGeneral: { |
22 | id: 'settings.app.headlineGeneral', | 30 | id: 'settings.app.headlineGeneral', |
23 | defaultMessage: '!!!General', | 31 | defaultMessage: 'General', |
24 | }, | 32 | }, |
25 | sentryInfo: { | 33 | sentryInfo: { |
26 | id: 'settings.app.sentryInfo', | 34 | id: 'settings.app.sentryInfo', |
27 | defaultMessage: '!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!', | 35 | defaultMessage: |
36 | 'Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!', | ||
28 | }, | 37 | }, |
29 | hibernateInfo: { | 38 | hibernateInfo: { |
30 | id: 'settings.app.hibernateInfo', | 39 | id: 'settings.app.hibernateInfo', |
31 | 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.', | 40 | defaultMessage: |
41 | '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.', | ||
32 | }, | 42 | }, |
33 | inactivityLockInfo: { | 43 | inactivityLockInfo: { |
34 | id: 'settings.app.inactivityLockInfo', | 44 | id: 'settings.app.inactivityLockInfo', |
35 | defaultMessage: '!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable', | 45 | defaultMessage: |
46 | 'Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable', | ||
36 | }, | 47 | }, |
37 | todoServerInfo: { | 48 | todoServerInfo: { |
38 | id: 'settings.app.todoServerInfo', | 49 | id: 'settings.app.todoServerInfo', |
39 | defaultMessage: '!!!This server will be used for the "Franz Todo" feature. (default: https://app.franztodos.com)', | 50 | defaultMessage: |
51 | 'This server will be used for the "Franz Todo" feature. (default: https://app.franztodos.com)', | ||
40 | }, | 52 | }, |
41 | lockedPassword: { | 53 | lockedPassword: { |
42 | id: 'settings.app.lockedPassword', | 54 | id: 'settings.app.lockedPassword', |
43 | defaultMessage: '!!!Password', | 55 | defaultMessage: 'Password', |
44 | }, | 56 | }, |
45 | lockedPasswordInfo: { | 57 | lockedPasswordInfo: { |
46 | id: 'settings.app.lockedPasswordInfo', | 58 | id: 'settings.app.lockedPasswordInfo', |
47 | defaultMessage: '!!!Please make sure to set a password you\'ll remember.\nIf you loose this password, you will have to reinstall Ferdi.', | 59 | defaultMessage: |
60 | "Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", | ||
48 | }, | 61 | }, |
49 | lockInfo: { | 62 | lockInfo: { |
50 | id: 'settings.app.lockInfo', | 63 | id: 'settings.app.lockInfo', |
51 | 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 {lockShortcut}.', | 64 | defaultMessage: |
65 | '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 {lockShortcut}.', | ||
52 | }, | 66 | }, |
53 | scheduledDNDTimeInfo: { | 67 | scheduledDNDTimeInfo: { |
54 | id: 'settings.app.scheduledDNDTimeInfo', | 68 | id: 'settings.app.scheduledDNDTimeInfo', |
55 | defaultMessage: '!!!Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.', | 69 | defaultMessage: |
70 | 'Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.', | ||
56 | }, | 71 | }, |
57 | scheduledDNDInfo: { | 72 | scheduledDNDInfo: { |
58 | id: 'settings.app.scheduledDNDInfo', | 73 | id: 'settings.app.scheduledDNDInfo', |
59 | defaultMessage: '!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.', | 74 | defaultMessage: |
75 | 'Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.', | ||
60 | }, | 76 | }, |
61 | headlineLanguage: { | 77 | headlineLanguage: { |
62 | id: 'settings.app.headlineLanguage', | 78 | id: 'settings.app.headlineLanguage', |
63 | defaultMessage: '!!!Language', | 79 | defaultMessage: 'Language', |
64 | }, | 80 | }, |
65 | headlineUpdates: { | 81 | headlineUpdates: { |
66 | id: 'settings.app.headlineUpdates', | 82 | id: 'settings.app.headlineUpdates', |
67 | defaultMessage: '!!!Updates', | 83 | defaultMessage: 'Updates', |
68 | }, | 84 | }, |
69 | headlineAppearance: { | 85 | headlineAppearance: { |
70 | id: 'settings.app.headlineAppearance', | 86 | id: 'settings.app.headlineAppearance', |
71 | defaultMessage: '!!!Appearance', | 87 | defaultMessage: 'Appearance', |
72 | }, | 88 | }, |
73 | universalDarkModeInfo: { | 89 | universalDarkModeInfo: { |
74 | id: 'settings.app.universalDarkModeInfo', | 90 | id: 'settings.app.universalDarkModeInfo', |
75 | defaultMessage: '!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', | 91 | defaultMessage: |
92 | 'Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', | ||
76 | }, | 93 | }, |
77 | accentColorInfo: { | 94 | accentColorInfo: { |
78 | id: 'settings.app.accentColorInfo', | 95 | id: 'settings.app.accentColorInfo', |
79 | defaultMessage: '!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})', | 96 | defaultMessage: |
97 | 'Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})', | ||
80 | }, | 98 | }, |
81 | headlinePrivacy: { | 99 | headlinePrivacy: { |
82 | id: 'settings.app.headlinePrivacy', | 100 | id: 'settings.app.headlinePrivacy', |
83 | defaultMessage: '!!!Privacy', | 101 | defaultMessage: 'Privacy', |
84 | }, | 102 | }, |
85 | headlineAdvanced: { | 103 | headlineAdvanced: { |
86 | id: 'settings.app.headlineAdvanced', | 104 | id: 'settings.app.headlineAdvanced', |
87 | defaultMessage: '!!!Advanced', | 105 | defaultMessage: 'Advanced', |
88 | }, | 106 | }, |
89 | translationHelp: { | 107 | translationHelp: { |
90 | id: 'settings.app.translationHelp', | 108 | id: 'settings.app.translationHelp', |
91 | defaultMessage: '!!!Help us to translate Ferdi into your language.', | 109 | defaultMessage: 'Help us to translate Ferdi into your language.', |
92 | }, | 110 | }, |
93 | spellCheckerLanguageInfo: { | 111 | spellCheckerLanguageInfo: { |
94 | id: 'settings.app.spellCheckerLanguageInfo', | 112 | id: 'settings.app.spellCheckerLanguageInfo', |
95 | defaultMessage: '!!!Ferdi uses your Mac\'s build-in spellchecker to check for typos. If you want to change the languages the spellchecker checks for, you can do so in your Mac\'s System Preferences.', | 113 | defaultMessage: |
114 | "Ferdi uses your Mac's build-in spellchecker to check for typos. If you want to change the languages the spellchecker checks for, you can do so in your Mac's System Preferences.", | ||
96 | }, | 115 | }, |
97 | subheadlineCache: { | 116 | subheadlineCache: { |
98 | id: 'settings.app.subheadlineCache', | 117 | id: 'settings.app.subheadlineCache', |
99 | defaultMessage: '!!!Cache', | 118 | defaultMessage: 'Cache', |
100 | }, | 119 | }, |
101 | cacheInfo: { | 120 | cacheInfo: { |
102 | id: 'settings.app.cacheInfo', | 121 | id: 'settings.app.cacheInfo', |
103 | defaultMessage: '!!!Ferdi cache is currently using {size} of disk space.', | 122 | defaultMessage: 'Ferdi cache is currently using {size} of disk space.', |
104 | }, | 123 | }, |
105 | cacheNotCleared: { | 124 | cacheNotCleared: { |
106 | id: 'settings.app.cacheNotCleared', | 125 | id: 'settings.app.cacheNotCleared', |
107 | defaultMessage: '!!!Couldn\'t clear all cache', | 126 | defaultMessage: "Couldn't clear all cache", |
108 | }, | 127 | }, |
109 | buttonClearAllCache: { | 128 | buttonClearAllCache: { |
110 | id: 'settings.app.buttonClearAllCache', | 129 | id: 'settings.app.buttonClearAllCache', |
111 | defaultMessage: '!!!Clear cache', | 130 | defaultMessage: 'Clear cache', |
112 | }, | 131 | }, |
113 | subheadlineFerdiProfile: { | 132 | subheadlineFerdiProfile: { |
114 | id: 'settings.app.subheadlineFerdiProfile', | 133 | id: 'settings.app.subheadlineFerdiProfile', |
115 | defaultMessage: '!!!Ferdi Profile', | 134 | defaultMessage: 'Ferdi Profile', |
116 | }, | 135 | }, |
117 | buttonOpenFerdiProfileFolder: { | 136 | buttonOpenFerdiProfileFolder: { |
118 | id: 'settings.app.buttonOpenFerdiProfileFolder', | 137 | id: 'settings.app.buttonOpenFerdiProfileFolder', |
119 | defaultMessage: '!!!Open Profile folder', | 138 | defaultMessage: 'Open Profile folder', |
120 | }, | 139 | }, |
121 | buttonOpenFerdiServiceRecipesFolder: { | 140 | buttonOpenFerdiServiceRecipesFolder: { |
122 | id: 'settings.app.buttonOpenFerdiServiceRecipesFolder', | 141 | id: 'settings.app.buttonOpenFerdiServiceRecipesFolder', |
123 | defaultMessage: '!!!Open Service Recipes folder', | 142 | defaultMessage: 'Open Service Recipes folder', |
124 | }, | 143 | }, |
125 | buttonSearchForUpdate: { | 144 | buttonSearchForUpdate: { |
126 | id: 'settings.app.buttonSearchForUpdate', | 145 | id: 'settings.app.buttonSearchForUpdate', |
127 | defaultMessage: '!!!Check for updates', | 146 | defaultMessage: 'Check for updates', |
128 | }, | 147 | }, |
129 | buttonInstallUpdate: { | 148 | buttonInstallUpdate: { |
130 | id: 'settings.app.buttonInstallUpdate', | 149 | id: 'settings.app.buttonInstallUpdate', |
131 | defaultMessage: '!!!Restart & install update', | 150 | defaultMessage: 'Restart & install update', |
132 | }, | 151 | }, |
133 | updateStatusSearching: { | 152 | updateStatusSearching: { |
134 | id: 'settings.app.updateStatusSearching', | 153 | id: 'settings.app.updateStatusSearching', |
135 | defaultMessage: '!!!Is searching for update', | 154 | defaultMessage: 'Is searching for update', |
136 | }, | 155 | }, |
137 | updateStatusAvailable: { | 156 | updateStatusAvailable: { |
138 | id: 'settings.app.updateStatusAvailable', | 157 | id: 'settings.app.updateStatusAvailable', |
139 | defaultMessage: '!!!Update available, downloading...', | 158 | defaultMessage: 'Update available, downloading...', |
140 | }, | 159 | }, |
141 | updateStatusUpToDate: { | 160 | updateStatusUpToDate: { |
142 | id: 'settings.app.updateStatusUpToDate', | 161 | id: 'settings.app.updateStatusUpToDate', |
143 | defaultMessage: '!!!You are using the latest version of Ferdi', | 162 | defaultMessage: 'You are using the latest version of Ferdi', |
144 | }, | 163 | }, |
145 | currentVersion: { | 164 | currentVersion: { |
146 | id: 'settings.app.currentVersion', | 165 | id: 'settings.app.currentVersion', |
147 | defaultMessage: '!!!Current version:', | 166 | defaultMessage: 'Current version:', |
148 | }, | 167 | }, |
149 | appRestartRequired: { | 168 | appRestartRequired: { |
150 | id: 'settings.app.restartRequired', | 169 | id: 'settings.app.restartRequired', |
151 | defaultMessage: '!!!Changes require restart', | 170 | defaultMessage: 'Changes require restart', |
152 | }, | 171 | }, |
153 | languageDisclaimer: { | 172 | languageDisclaimer: { |
154 | id: 'settings.app.languageDisclaimer', | 173 | id: 'settings.app.languageDisclaimer', |
155 | defaultMessage: '!!!Official translations are English & German. All other languages are community based translations.', | 174 | defaultMessage: |
175 | 'Official translations are English & German. All other languages are community based translations.', | ||
156 | }, | 176 | }, |
157 | }); | 177 | }); |
158 | 178 | ||
159 | const Hr = () => ( | 179 | const Hr = () => <hr style={{ marginBottom: 20 }} />; |
160 | <hr style={{ marginBottom: 20 }} /> | ||
161 | ); | ||
162 | 180 | ||
163 | export default @observer class EditSettingsForm extends Component { | 181 | @observer |
182 | class EditSettingsForm extends Component { | ||
164 | static propTypes = { | 183 | static propTypes = { |
165 | checkForUpdates: PropTypes.func.isRequired, | 184 | checkForUpdates: PropTypes.func.isRequired, |
166 | installUpdate: PropTypes.func.isRequired, | 185 | installUpdate: PropTypes.func.isRequired, |
@@ -184,14 +203,10 @@ export default @observer class EditSettingsForm extends Component { | |||
184 | isOnline: PropTypes.bool.isRequired, | 203 | isOnline: PropTypes.bool.isRequired, |
185 | }; | 204 | }; |
186 | 205 | ||
187 | static contextTypes = { | ||
188 | intl: intlShape, | ||
189 | }; | ||
190 | |||
191 | state = { | 206 | state = { |
192 | activeSetttingsTab: 'general', | 207 | activeSetttingsTab: 'general', |
193 | clearCacheButtonClicked: false, | 208 | clearCacheButtonClicked: false, |
194 | } | 209 | }; |
195 | 210 | ||
196 | setActiveSettingsTab(tab) { | 211 | setActiveSettingsTab(tab) { |
197 | this.setState({ | 212 | this.setState({ |
@@ -199,14 +214,14 @@ export default @observer class EditSettingsForm extends Component { | |||
199 | }); | 214 | }); |
200 | } | 215 | } |
201 | 216 | ||
202 | onClearCacheClicked=() => { | 217 | onClearCacheClicked = () => { |
203 | this.setState({ clearCacheButtonClicked: true }); | 218 | this.setState({ clearCacheButtonClicked: true }); |
204 | } | 219 | }; |
205 | 220 | ||
206 | submit(e) { | 221 | submit(e) { |
207 | e.preventDefault(); | 222 | e.preventDefault(); |
208 | this.props.form.submit({ | 223 | this.props.form.submit({ |
209 | onSuccess: (form) => { | 224 | onSuccess: form => { |
210 | const values = form.values(); | 225 | const values = form.values(); |
211 | this.props.onSubmit(values); | 226 | this.props.onSubmit(values); |
212 | }, | 227 | }, |
@@ -236,7 +251,7 @@ export default @observer class EditSettingsForm extends Component { | |||
236 | hasAddedTodosAsService, | 251 | hasAddedTodosAsService, |
237 | isOnline, | 252 | isOnline, |
238 | } = this.props; | 253 | } = this.props; |
239 | const { intl } = this.context; | 254 | const { intl } = this.props; |
240 | 255 | ||
241 | let updateButtonLabelMessage = messages.buttonSearchForUpdate; | 256 | let updateButtonLabelMessage = messages.buttonSearchForUpdate; |
242 | if (isCheckingForUpdates) { | 257 | if (isCheckingForUpdates) { |
@@ -247,10 +262,8 @@ export default @observer class EditSettingsForm extends Component { | |||
247 | updateButtonLabelMessage = messages.buttonSearchForUpdate; | 262 | updateButtonLabelMessage = messages.buttonSearchForUpdate; |
248 | } | 263 | } |
249 | 264 | ||
250 | const { | 265 | const { lockingFeatureEnabled, scheduledDNDEnabled } = |
251 | lockingFeatureEnabled, | 266 | window.ferdi.stores.settings.all.app; |
252 | scheduledDNDEnabled, | ||
253 | } = window.ferdi.stores.settings.all.app; | ||
254 | 267 | ||
255 | let cacheSize; | 268 | let cacheSize; |
256 | let notCleared; | 269 | let notCleared; |
@@ -258,7 +271,10 @@ export default @observer class EditSettingsForm extends Component { | |||
258 | const cacheSizeBytes = getCacheSize(); | 271 | const cacheSizeBytes = getCacheSize(); |
259 | if (typeof cacheSizeBytes === 'number') { | 272 | if (typeof cacheSizeBytes === 'number') { |
260 | cacheSize = prettyBytes(cacheSizeBytes); | 273 | cacheSize = prettyBytes(cacheSizeBytes); |
261 | notCleared = this.state.clearCacheButtonClicked && isClearingAllCache === false && cacheSizeBytes !== 0; | 274 | notCleared = |
275 | this.state.clearCacheButtonClicked && | ||
276 | isClearingAllCache === false && | ||
277 | cacheSizeBytes !== 0; | ||
262 | } else { | 278 | } else { |
263 | cacheSize = '…'; | 279 | cacheSize = '…'; |
264 | notCleared = false; | 280 | notCleared = false; |
@@ -275,58 +291,94 @@ export default @observer class EditSettingsForm extends Component { | |||
275 | </div> | 291 | </div> |
276 | <div className="settings__body"> | 292 | <div className="settings__body"> |
277 | <form | 293 | <form |
278 | onSubmit={(e) => this.submit(e)} | 294 | onSubmit={e => this.submit(e)} |
279 | onChange={(e) => this.submit(e)} | 295 | onChange={e => this.submit(e)} |
280 | id="form" | 296 | id="form" |
281 | > | 297 | > |
282 | {/* Titles */} | 298 | {/* Titles */} |
283 | <div className="recipes__navigation"> | 299 | <div className="recipes__navigation"> |
284 | <h2 | 300 | <h2 |
285 | id="general" | 301 | id="general" |
286 | className={this.state.activeSetttingsTab === 'general' ? 'badge badge--primary' : 'badge'} | 302 | className={ |
287 | onClick={() => { this.setActiveSettingsTab('general'); }} | 303 | this.state.activeSetttingsTab === 'general' |
304 | ? 'badge badge--primary' | ||
305 | : 'badge' | ||
306 | } | ||
307 | onClick={() => { | ||
308 | this.setActiveSettingsTab('general'); | ||
309 | }} | ||
288 | > | 310 | > |
289 | {intl.formatMessage(messages.headlineGeneral)} | 311 | {intl.formatMessage(messages.headlineGeneral)} |
290 | </h2> | 312 | </h2> |
291 | <h2 | 313 | <h2 |
292 | id="appearance" | 314 | id="appearance" |
293 | className={this.state.activeSetttingsTab === 'appearance' ? 'badge badge--primary' : 'badge'} | 315 | className={ |
294 | onClick={() => { this.setActiveSettingsTab('appearance'); }} | 316 | this.state.activeSetttingsTab === 'appearance' |
317 | ? 'badge badge--primary' | ||
318 | : 'badge' | ||
319 | } | ||
320 | onClick={() => { | ||
321 | this.setActiveSettingsTab('appearance'); | ||
322 | }} | ||
295 | > | 323 | > |
296 | {intl.formatMessage(messages.headlineAppearance)} | 324 | {intl.formatMessage(messages.headlineAppearance)} |
297 | </h2> | 325 | </h2> |
298 | <h2 | 326 | <h2 |
299 | id="privacy" | 327 | id="privacy" |
300 | className={this.state.activeSetttingsTab === 'privacy' ? 'badge badge--primary' : 'badge'} | 328 | className={ |
301 | onClick={() => { this.setActiveSettingsTab('privacy'); }} | 329 | this.state.activeSetttingsTab === 'privacy' |
330 | ? 'badge badge--primary' | ||
331 | : 'badge' | ||
332 | } | ||
333 | onClick={() => { | ||
334 | this.setActiveSettingsTab('privacy'); | ||
335 | }} | ||
302 | > | 336 | > |
303 | {intl.formatMessage(messages.headlinePrivacy)} | 337 | {intl.formatMessage(messages.headlinePrivacy)} |
304 | </h2> | 338 | </h2> |
305 | <h2 | 339 | <h2 |
306 | id="language" | 340 | id="language" |
307 | className={this.state.activeSetttingsTab === 'language' ? 'badge badge--primary' : 'badge'} | 341 | className={ |
308 | onClick={() => { this.setActiveSettingsTab('language'); }} | 342 | this.state.activeSetttingsTab === 'language' |
343 | ? 'badge badge--primary' | ||
344 | : 'badge' | ||
345 | } | ||
346 | onClick={() => { | ||
347 | this.setActiveSettingsTab('language'); | ||
348 | }} | ||
309 | > | 349 | > |
310 | {intl.formatMessage(messages.headlineLanguage)} | 350 | {intl.formatMessage(messages.headlineLanguage)} |
311 | </h2> | 351 | </h2> |
312 | <h2 | 352 | <h2 |
313 | id="advanced" | 353 | id="advanced" |
314 | className={this.state.activeSetttingsTab === 'advanced' ? 'badge badge--primary' : 'badge'} | 354 | className={ |
315 | onClick={() => { this.setActiveSettingsTab('advanced'); }} | 355 | this.state.activeSetttingsTab === 'advanced' |
356 | ? 'badge badge--primary' | ||
357 | : 'badge' | ||
358 | } | ||
359 | onClick={() => { | ||
360 | this.setActiveSettingsTab('advanced'); | ||
361 | }} | ||
316 | > | 362 | > |
317 | {intl.formatMessage(messages.headlineAdvanced)} | 363 | {intl.formatMessage(messages.headlineAdvanced)} |
318 | </h2> | 364 | </h2> |
319 | <h2 | 365 | <h2 |
320 | id="updates" | 366 | id="updates" |
321 | className={this.state.activeSetttingsTab === 'updates' ? 'badge badge--primary' : 'badge'} | 367 | className={ |
322 | onClick={() => { this.setActiveSettingsTab('updates'); }} | 368 | this.state.activeSetttingsTab === 'updates' |
369 | ? 'badge badge--primary' | ||
370 | : 'badge' | ||
371 | } | ||
372 | onClick={() => { | ||
373 | this.setActiveSettingsTab('updates'); | ||
374 | }} | ||
323 | > | 375 | > |
324 | {intl.formatMessage(messages.headlineUpdates)} | 376 | {intl.formatMessage(messages.headlineUpdates)} |
325 | </h2> | 377 | </h2> |
326 | </div> | 378 | </div> |
327 | 379 | ||
328 | {/* General */} | 380 | {/* General */} |
329 | { this.state.activeSetttingsTab === 'general' && ( | 381 | {this.state.activeSetttingsTab === 'general' && ( |
330 | <div> | 382 | <div> |
331 | <Toggle field={form.$('autoLaunchOnStart')} /> | 383 | <Toggle field={form.$('autoLaunchOnStart')} /> |
332 | <Toggle field={form.$('runInBackground')} /> | 384 | <Toggle field={form.$('runInBackground')} /> |
@@ -334,12 +386,8 @@ export default @observer class EditSettingsForm extends Component { | |||
334 | <Toggle field={form.$('enableSystemTray')} /> | 386 | <Toggle field={form.$('enableSystemTray')} /> |
335 | <Toggle field={form.$('reloadAfterResume')} /> | 387 | <Toggle field={form.$('reloadAfterResume')} /> |
336 | <Toggle field={form.$('startMinimized')} /> | 388 | <Toggle field={form.$('startMinimized')} /> |
337 | {isWindows && ( | 389 | {isWindows && <Toggle field={form.$('minimizeToSystemTray')} />} |
338 | <Toggle field={form.$('minimizeToSystemTray')} /> | 390 | {isWindows && <Toggle field={form.$('closeToSystemTray')} />} |
339 | )} | ||
340 | {isWindows && ( | ||
341 | <Toggle field={form.$('closeToSystemTray')} /> | ||
342 | )} | ||
343 | <Select field={form.$('navigationBarBehaviour')} /> | 391 | <Select field={form.$('navigationBarBehaviour')} /> |
344 | 392 | ||
345 | <Hr /> | 393 | <Hr /> |
@@ -349,12 +397,13 @@ export default @observer class EditSettingsForm extends Component { | |||
349 | <p | 397 | <p |
350 | className="settings__message" | 398 | className="settings__message" |
351 | style={{ | 399 | style={{ |
352 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 400 | borderTop: 0, |
401 | marginTop: 0, | ||
402 | paddingTop: 0, | ||
403 | marginBottom: '2rem', | ||
353 | }} | 404 | }} |
354 | > | 405 | > |
355 | <span> | 406 | <span>{intl.formatMessage(messages.hibernateInfo)}</span> |
356 | { intl.formatMessage(messages.hibernateInfo) } | ||
357 | </span> | ||
358 | </p> | 407 | </p> |
359 | 408 | ||
360 | <Select field={form.$('wakeUpStrategy')} /> | 409 | <Select field={form.$('wakeUpStrategy')} /> |
@@ -374,20 +423,24 @@ export default @observer class EditSettingsForm extends Component { | |||
374 | {isTodosActivated && ( | 423 | {isTodosActivated && ( |
375 | <div> | 424 | <div> |
376 | <Select field={form.$('predefinedTodoServer')} /> | 425 | <Select field={form.$('predefinedTodoServer')} /> |
377 | {form.$('predefinedTodoServer').value === 'isUsingCustomTodoService' && ( | 426 | {form.$('predefinedTodoServer').value === |
427 | 'isUsingCustomTodoService' && ( | ||
378 | <div> | 428 | <div> |
379 | <Input | 429 | <Input |
380 | placeholder="Todo Server" | 430 | placeholder="Todo Server" |
381 | onChange={(e) => this.submit(e)} | 431 | onChange={e => this.submit(e)} |
382 | field={form.$('customTodoServer')} | 432 | field={form.$('customTodoServer')} |
383 | /> | 433 | /> |
384 | <p | 434 | <p |
385 | className="settings__message" | 435 | className="settings__message" |
386 | style={{ | 436 | style={{ |
387 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 437 | borderTop: 0, |
438 | marginTop: 0, | ||
439 | paddingTop: 0, | ||
440 | marginBottom: '2rem', | ||
388 | }} | 441 | }} |
389 | > | 442 | > |
390 | { intl.formatMessage(messages.todoServerInfo) } | 443 | {intl.formatMessage(messages.todoServerInfo)} |
391 | </p> | 444 | </p> |
392 | </div> | 445 | </div> |
393 | )} | 446 | )} |
@@ -400,56 +453,58 @@ export default @observer class EditSettingsForm extends Component { | |||
400 | <Toggle field={form.$('scheduledDNDEnabled')} /> | 453 | <Toggle field={form.$('scheduledDNDEnabled')} /> |
401 | {scheduledDNDEnabled && ( | 454 | {scheduledDNDEnabled && ( |
402 | <> | 455 | <> |
403 | <div style={{ | 456 | <div |
404 | display: 'flex', | 457 | style={{ |
405 | justifyContent: 'center', | 458 | display: 'flex', |
406 | }} | 459 | justifyContent: 'center', |
407 | > | ||
408 | <div style={{ | ||
409 | padding: '0 1rem', | ||
410 | width: '100%', | ||
411 | }} | 460 | }} |
461 | > | ||
462 | <div | ||
463 | style={{ | ||
464 | padding: '0 1rem', | ||
465 | width: '100%', | ||
466 | }} | ||
412 | > | 467 | > |
413 | <Input | 468 | <Input |
414 | placeholder="17:00" | 469 | placeholder="17:00" |
415 | onChange={(e) => this.submit(e)} | 470 | onChange={e => this.submit(e)} |
416 | field={form.$('scheduledDNDStart')} | 471 | field={form.$('scheduledDNDStart')} |
417 | type="time" | 472 | type="time" |
418 | /> | 473 | /> |
419 | </div> | 474 | </div> |
420 | <div style={{ | 475 | <div |
421 | padding: '0 1rem', | 476 | style={{ |
422 | width: '100%', | 477 | padding: '0 1rem', |
423 | }} | 478 | width: '100%', |
479 | }} | ||
424 | > | 480 | > |
425 | <Input | 481 | <Input |
426 | placeholder="09:00" | 482 | placeholder="09:00" |
427 | onChange={(e) => this.submit(e)} | 483 | onChange={e => this.submit(e)} |
428 | field={form.$('scheduledDNDEnd')} | 484 | field={form.$('scheduledDNDEnd')} |
429 | type="time" | 485 | type="time" |
430 | /> | 486 | /> |
431 | </div> | 487 | </div> |
432 | </div> | 488 | </div> |
433 | <p> | 489 | <p>{intl.formatMessage(messages.scheduledDNDTimeInfo)}</p> |
434 | { intl.formatMessage(messages.scheduledDNDTimeInfo) } | ||
435 | </p> | ||
436 | </> | 490 | </> |
437 | )} | 491 | )} |
438 | <p | 492 | <p |
439 | className="settings__message" | 493 | className="settings__message" |
440 | style={{ | 494 | style={{ |
441 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 495 | borderTop: 0, |
496 | marginTop: 0, | ||
497 | paddingTop: 0, | ||
498 | marginBottom: '2rem', | ||
442 | }} | 499 | }} |
443 | > | 500 | > |
444 | <span> | 501 | <span>{intl.formatMessage(messages.scheduledDNDInfo)}</span> |
445 | { intl.formatMessage(messages.scheduledDNDInfo) } | ||
446 | </span> | ||
447 | </p> | 502 | </p> |
448 | </div> | 503 | </div> |
449 | )} | 504 | )} |
450 | 505 | ||
451 | {/* Appearance */} | 506 | {/* Appearance */} |
452 | { this.state.activeSetttingsTab === 'appearance' && ( | 507 | {this.state.activeSetttingsTab === 'appearance' && ( |
453 | <div> | 508 | <div> |
454 | <Toggle field={form.$('showDisabledServices')} /> | 509 | <Toggle field={form.$('showDisabledServices')} /> |
455 | <Toggle field={form.$('showMessageBadgeWhenMuted')} /> | 510 | <Toggle field={form.$('showMessageBadgeWhenMuted')} /> |
@@ -459,21 +514,26 @@ export default @observer class EditSettingsForm extends Component { | |||
459 | <Hr /> | 514 | <Hr /> |
460 | 515 | ||
461 | <Toggle field={form.$('adaptableDarkMode')} /> | 516 | <Toggle field={form.$('adaptableDarkMode')} /> |
462 | {!isAdaptableDarkModeEnabled && <Toggle field={form.$('darkMode')} />} | 517 | {!isAdaptableDarkModeEnabled && ( |
518 | <Toggle field={form.$('darkMode')} /> | ||
519 | )} | ||
463 | {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( | 520 | {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( |
464 | <> | 521 | <> |
465 | <Toggle field={form.$('universalDarkMode')} /> | 522 | <Toggle field={form.$('universalDarkMode')} /> |
466 | <p | 523 | <p |
467 | className="settings__message" | 524 | className="settings__message" |
468 | style={{ | 525 | style={{ |
469 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 526 | borderTop: 0, |
470 | }} | 527 | marginTop: 0, |
471 | > | 528 | paddingTop: 0, |
472 | <span> | 529 | marginBottom: '2rem', |
473 | { intl.formatMessage(messages.universalDarkModeInfo) } | 530 | }} |
474 | </span> | 531 | > |
475 | </p> | 532 | <span> |
476 | </> | 533 | {intl.formatMessage(messages.universalDarkModeInfo)} |
534 | </span> | ||
535 | </p> | ||
536 | </> | ||
477 | )} | 537 | )} |
478 | 538 | ||
479 | <Hr /> | 539 | <Hr /> |
@@ -491,23 +551,25 @@ export default @observer class EditSettingsForm extends Component { | |||
491 | 551 | ||
492 | <Input | 552 | <Input |
493 | placeholder="Accent Color" | 553 | placeholder="Accent Color" |
494 | onChange={(e) => this.submit(e)} | 554 | onChange={e => this.submit(e)} |
495 | field={form.$('accentColor')} | 555 | field={form.$('accentColor')} |
496 | /> | 556 | /> |
497 | <p> | 557 | <p> |
498 | {intl.formatMessage(messages.accentColorInfo, | 558 | {intl.formatMessage(messages.accentColorInfo, { |
499 | { defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor })} | 559 | defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor, |
560 | })} | ||
500 | </p> | 561 | </p> |
501 | </div> | 562 | </div> |
502 | )} | 563 | )} |
503 | 564 | ||
504 | {/* Privacy */} | 565 | {/* Privacy */} |
505 | { this.state.activeSetttingsTab === 'privacy' && ( | 566 | {this.state.activeSetttingsTab === 'privacy' && ( |
506 | <div> | 567 | <div> |
507 | <Toggle field={form.$('privateNotifications')} /> | 568 | <Toggle field={form.$('privateNotifications')} /> |
508 | <Toggle field={form.$('clipboardNotifications')} /> | 569 | <Toggle field={form.$('clipboardNotifications')} /> |
509 | {(isWindows || isMac) && ( | 570 | {(isWindows || isMac) && ( |
510 | <Toggle field={form.$('notifyTaskBarOnMessage')} />)} | 571 | <Toggle field={form.$('notifyTaskBarOnMessage')} /> |
572 | )} | ||
511 | 573 | ||
512 | <Hr /> | 574 | <Hr /> |
513 | 575 | ||
@@ -516,8 +578,12 @@ export default @observer class EditSettingsForm extends Component { | |||
516 | <Hr /> | 578 | <Hr /> |
517 | 579 | ||
518 | <Toggle field={form.$('sentry')} /> | 580 | <Toggle field={form.$('sentry')} /> |
519 | <p className="settings__help">{intl.formatMessage(messages.sentryInfo)}</p> | 581 | <p className="settings__help"> |
520 | <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 582 | {intl.formatMessage(messages.sentryInfo)} |
583 | </p> | ||
584 | <p className="settings__help"> | ||
585 | {intl.formatMessage(messages.appRestartRequired)} | ||
586 | </p> | ||
521 | 587 | ||
522 | <Hr /> | 588 | <Hr /> |
523 | 589 | ||
@@ -530,57 +596,60 @@ export default @observer class EditSettingsForm extends Component { | |||
530 | 596 | ||
531 | <Input | 597 | <Input |
532 | placeholder={intl.formatMessage(messages.lockedPassword)} | 598 | placeholder={intl.formatMessage(messages.lockedPassword)} |
533 | onChange={(e) => this.submit(e)} | 599 | onChange={e => this.submit(e)} |
534 | field={form.$('lockedPassword')} | 600 | field={form.$('lockedPassword')} |
535 | type="password" | 601 | type="password" |
536 | scorePassword | 602 | scorePassword |
537 | showPasswordToggle | 603 | showPasswordToggle |
538 | /> | 604 | /> |
539 | <p> | 605 | <p>{intl.formatMessage(messages.lockedPasswordInfo)}</p> |
540 | { intl.formatMessage(messages.lockedPasswordInfo) } | ||
541 | </p> | ||
542 | 606 | ||
543 | <Input | 607 | <Input |
544 | placeholder="Lock after inactivity" | 608 | placeholder="Lock after inactivity" |
545 | onChange={(e) => this.submit(e)} | 609 | onChange={e => this.submit(e)} |
546 | field={form.$('inactivityLock')} | 610 | field={form.$('inactivityLock')} |
547 | autoFocus | 611 | autoFocus |
548 | /> | 612 | /> |
549 | <p> | 613 | <p>{intl.formatMessage(messages.inactivityLockInfo)}</p> |
550 | { intl.formatMessage(messages.inactivityLockInfo) } | ||
551 | </p> | ||
552 | </> | 614 | </> |
553 | )} | 615 | )} |
554 | <p | 616 | <p |
555 | className="settings__message" | 617 | className="settings__message" |
556 | style={{ | 618 | style={{ |
557 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 619 | borderTop: 0, |
620 | marginTop: 0, | ||
621 | paddingTop: 0, | ||
622 | marginBottom: '2rem', | ||
558 | }} | 623 | }} |
559 | > | 624 | > |
560 | <span> | 625 | <span> |
561 | { intl.formatMessage(messages.lockInfo, { lockShortcut: `${lockFerdiShortcutKey(false)}` }) } | 626 | {intl.formatMessage(messages.lockInfo, { |
627 | lockShortcut: `${lockFerdiShortcutKey(false)}`, | ||
628 | })} | ||
562 | </span> | 629 | </span> |
563 | </p> | 630 | </p> |
564 | </div> | 631 | </div> |
565 | )} | 632 | )} |
566 | 633 | ||
567 | {/* Language */} | 634 | {/* Language */} |
568 | { this.state.activeSetttingsTab === 'language' && ( | 635 | {this.state.activeSetttingsTab === 'language' && ( |
569 | <div> | 636 | <div> |
570 | <Select field={form.$('locale')} showLabel={false} /> | 637 | <Select field={form.$('locale')} showLabel={false} /> |
571 | 638 | ||
572 | <Hr /> | 639 | <Hr /> |
573 | 640 | ||
574 | <Toggle | 641 | <Toggle field={form.$('enableSpellchecking')} /> |
575 | field={form.$('enableSpellchecking')} | ||
576 | /> | ||
577 | {!isMac && form.$('enableSpellchecking').value && ( | 642 | {!isMac && form.$('enableSpellchecking').value && ( |
578 | <Select field={form.$('spellcheckerLanguage')} /> | 643 | <Select field={form.$('spellcheckerLanguage')} /> |
579 | )} | 644 | )} |
580 | {isMac && form.$('enableSpellchecking').value && ( | 645 | {isMac && form.$('enableSpellchecking').value && ( |
581 | <p className="settings__help">{intl.formatMessage(messages.spellCheckerLanguageInfo)}</p> | 646 | <p className="settings__help"> |
647 | {intl.formatMessage(messages.spellCheckerLanguageInfo)} | ||
648 | </p> | ||
582 | )} | 649 | )} |
583 | <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 650 | <p className="settings__help"> |
651 | {intl.formatMessage(messages.appRestartRequired)} | ||
652 | </p> | ||
584 | 653 | ||
585 | <Hr /> | 654 | <Hr /> |
586 | 655 | ||
@@ -590,52 +659,54 @@ export default @observer class EditSettingsForm extends Component { | |||
590 | className="link" | 659 | className="link" |
591 | rel="noreferrer" | 660 | rel="noreferrer" |
592 | > | 661 | > |
593 | {intl.formatMessage(messages.translationHelp)} | 662 | {intl.formatMessage(messages.translationHelp)}{' '} |
594 | {' '} | ||
595 | <i className="mdi mdi-open-in-new" /> | 663 | <i className="mdi mdi-open-in-new" /> |
596 | </a> | 664 | </a> |
597 | </div> | 665 | </div> |
598 | )} | 666 | )} |
599 | 667 | ||
600 | {/* Advanced */} | 668 | {/* Advanced */} |
601 | { this.state.activeSetttingsTab === 'advanced' && ( | 669 | {this.state.activeSetttingsTab === 'advanced' && ( |
602 | <div> | 670 | <div> |
603 | <Toggle field={form.$('enableGPUAcceleration')} /> | 671 | <Toggle field={form.$('enableGPUAcceleration')} /> |
604 | <p className="settings__help indented__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 672 | <p className="settings__help indented__help"> |
673 | {intl.formatMessage(messages.appRestartRequired)} | ||
674 | </p> | ||
605 | 675 | ||
606 | <Hr /> | 676 | <Hr /> |
607 | 677 | ||
608 | <Input | 678 | <Input |
609 | placeholder="User Agent" | 679 | placeholder="User Agent" |
610 | onChange={(e) => this.submit(e)} | 680 | onChange={e => this.submit(e)} |
611 | field={form.$('userAgentPref')} | 681 | field={form.$('userAgentPref')} |
612 | /> | 682 | /> |
613 | <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> | 683 | <p className="settings__help"> |
614 | <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 684 | {intl.formatMessage(globalMessages.userAgentHelp)} |
685 | </p> | ||
686 | <p className="settings__help"> | ||
687 | {intl.formatMessage(messages.appRestartRequired)} | ||
688 | </p> | ||
615 | 689 | ||
616 | <Hr /> | 690 | <Hr /> |
617 | 691 | ||
618 | <div className="settings__settings-group"> | 692 | <div className="settings__settings-group"> |
619 | <h3> | 693 | <h3>{intl.formatMessage(messages.subheadlineCache)}</h3> |
620 | {intl.formatMessage(messages.subheadlineCache)} | ||
621 | </h3> | ||
622 | <p> | 694 | <p> |
623 | {intl.formatMessage(messages.cacheInfo, { | 695 | {intl.formatMessage(messages.cacheInfo, { |
624 | size: cacheSize, | 696 | size: cacheSize, |
625 | })} | 697 | })} |
626 | </p> | 698 | </p> |
627 | { | 699 | {notCleared && ( |
628 | notCleared && ( | 700 | <p>{intl.formatMessage(messages.cacheNotCleared)}</p> |
629 | <p> | 701 | )} |
630 | {intl.formatMessage(messages.cacheNotCleared)} | ||
631 | </p> | ||
632 | ) | ||
633 | } | ||
634 | <p> | 702 | <p> |
635 | <Button | 703 | <Button |
636 | buttonType="secondary" | 704 | buttonType="secondary" |
637 | label={intl.formatMessage(messages.buttonClearAllCache)} | 705 | label={intl.formatMessage(messages.buttonClearAllCache)} |
638 | onClick={() => { onClearAllCache(); this.onClearCacheClicked(); }} | 706 | onClick={() => { |
707 | onClearAllCache(); | ||
708 | this.onClearCacheClicked(); | ||
709 | }} | ||
639 | disabled={isClearingAllCache} | 710 | disabled={isClearingAllCache} |
640 | loaded={!isClearingAllCache} | 711 | loaded={!isClearingAllCache} |
641 | /> | 712 | /> |
@@ -652,13 +723,17 @@ export default @observer class EditSettingsForm extends Component { | |||
652 | <div className="settings__open-settings-file-container"> | 723 | <div className="settings__open-settings-file-container"> |
653 | <Button | 724 | <Button |
654 | buttonType="secondary" | 725 | buttonType="secondary" |
655 | label={intl.formatMessage(messages.buttonOpenFerdiProfileFolder)} | 726 | label={intl.formatMessage( |
727 | messages.buttonOpenFerdiProfileFolder, | ||
728 | )} | ||
656 | className="settings__open-settings-file-button" | 729 | className="settings__open-settings-file-button" |
657 | onClick={() => openPath(profileFolder)} | 730 | onClick={() => openPath(profileFolder)} |
658 | /> | 731 | /> |
659 | <Button | 732 | <Button |
660 | buttonType="secondary" | 733 | buttonType="secondary" |
661 | label={intl.formatMessage(messages.buttonOpenFerdiServiceRecipesFolder)} | 734 | label={intl.formatMessage( |
735 | messages.buttonOpenFerdiServiceRecipesFolder, | ||
736 | )} | ||
662 | className="settings__open-settings-file-button" | 737 | className="settings__open-settings-file-button" |
663 | onClick={() => openPath(recipeFolder)} | 738 | onClick={() => openPath(recipeFolder)} |
664 | /> | 739 | /> |
@@ -669,66 +744,78 @@ export default @observer class EditSettingsForm extends Component { | |||
669 | )} | 744 | )} |
670 | 745 | ||
671 | {/* Updates */} | 746 | {/* Updates */} |
672 | { this.state.activeSetttingsTab === 'updates' && ( | 747 | {this.state.activeSetttingsTab === 'updates' && ( |
673 | <div> | ||
674 | <Toggle field={form.$('automaticUpdates')} /> | ||
675 | {automaticUpdates && ( | ||
676 | <div> | 748 | <div> |
677 | <Toggle field={form.$('beta')} /> | 749 | <Toggle field={form.$('automaticUpdates')} /> |
678 | <ToggleRaw | 750 | {automaticUpdates && ( |
679 | field={{ | 751 | <div> |
680 | value: isNightlyEnabled, | 752 | <Toggle field={form.$('beta')} /> |
681 | id: 'nightly', | 753 | <ToggleRaw |
682 | label: 'Include nightly versions', | 754 | field={{ |
683 | name: 'Nightly builds', | 755 | value: isNightlyEnabled, |
684 | }} | 756 | id: 'nightly', |
685 | onChange={window.ferdi.features.nightlyBuilds.toggleFeature} | 757 | label: 'Include nightly versions', |
686 | /> | 758 | name: 'Nightly builds', |
687 | {updateIsReadyToInstall ? ( | 759 | }} |
688 | <Button | 760 | onChange={ |
689 | label={intl.formatMessage(messages.buttonInstallUpdate)} | 761 | window.ferdi.features.nightlyBuilds.toggleFeature |
690 | onClick={installUpdate} | 762 | } |
691 | /> | 763 | /> |
692 | ) : ( | 764 | {updateIsReadyToInstall ? ( |
693 | <Button | 765 | <Button |
694 | buttonType="secondary" | 766 | label={intl.formatMessage(messages.buttonInstallUpdate)} |
695 | label={intl.formatMessage(updateButtonLabelMessage)} | 767 | onClick={installUpdate} |
696 | onClick={checkForUpdates} | 768 | /> |
697 | disabled={!automaticUpdates || isCheckingForUpdates || isUpdateAvailable || !isOnline} | 769 | ) : ( |
698 | loaded={!isCheckingForUpdates || !isUpdateAvailable} | 770 | <Button |
699 | /> | 771 | buttonType="secondary" |
772 | label={intl.formatMessage(updateButtonLabelMessage)} | ||
773 | onClick={checkForUpdates} | ||
774 | disabled={ | ||
775 | !automaticUpdates || | ||
776 | isCheckingForUpdates || | ||
777 | isUpdateAvailable || | ||
778 | !isOnline | ||
779 | } | ||
780 | loaded={!isCheckingForUpdates || !isUpdateAvailable} | ||
781 | /> | ||
782 | )} | ||
783 | <br /> | ||
784 | </div> | ||
785 | )} | ||
786 | {intl.formatMessage(messages.currentVersion)} {ferdiVersion} | ||
787 | {noUpdateAvailable && ( | ||
788 | <> | ||
789 | <br /> | ||
790 | <br /> | ||
791 | {intl.formatMessage(messages.updateStatusUpToDate)} | ||
792 | </> | ||
700 | )} | 793 | )} |
701 | <br /> | 794 | <p className="settings__message"> |
795 | <span className="mdi mdi-github-face" /> | ||
796 | <span> | ||
797 | Ferdi is based on{' '} | ||
798 | <a | ||
799 | href={`${GITHUB_FRANZ_URL}/franz`} | ||
800 | target="_blank" | ||
801 | rel="noreferrer" | ||
802 | > | ||
803 | Franz | ||
804 | </a> | ||
805 | , a project published under the{' '} | ||
806 | <a | ||
807 | href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} | ||
808 | target="_blank" | ||
809 | rel="noreferrer" | ||
810 | > | ||
811 | Apache-2.0 License | ||
812 | </a> | ||
813 | </span> | ||
814 | <br /> | ||
815 | <span className="mdi mdi-information" /> | ||
816 | {intl.formatMessage(messages.languageDisclaimer)} | ||
817 | </p> | ||
702 | </div> | 818 | </div> |
703 | )} | ||
704 | {intl.formatMessage(messages.currentVersion)} | ||
705 | {' '} | ||
706 | {ferdiVersion} | ||
707 | {noUpdateAvailable && ( | ||
708 | <> | ||
709 | <br /> | ||
710 | <br /> | ||
711 | {intl.formatMessage(messages.updateStatusUpToDate)} | ||
712 | </> | ||
713 | )} | ||
714 | <p className="settings__message"> | ||
715 | <span className="mdi mdi-github-face" /> | ||
716 | <span> | ||
717 | |||
718 | Ferdi is based on | ||
719 | {' '} | ||
720 | <a href={`${GITHUB_FRANZ_URL}/franz`} target="_blank" rel="noreferrer">Franz</a> | ||
721 | |||
722 | , a project published | ||
723 | under the | ||
724 | {' '} | ||
725 | <a href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} target="_blank" rel="noreferrer">Apache-2.0 License</a> | ||
726 | </span> | ||
727 | <br /> | ||
728 | <span className="mdi mdi-information" /> | ||
729 | {intl.formatMessage(messages.languageDisclaimer)} | ||
730 | </p> | ||
731 | </div> | ||
732 | )} | 819 | )} |
733 | </form> | 820 | </form> |
734 | </div> | 821 | </div> |
@@ -736,3 +823,5 @@ export default @observer class EditSettingsForm extends Component { | |||
736 | ); | 823 | ); |
737 | } | 824 | } |
738 | } | 825 | } |
826 | |||
827 | export default injectIntl(EditSettingsForm); | ||
diff --git a/src/components/settings/supportFerdi/SupportFerdiDashboard.js b/src/components/settings/supportFerdi/SupportFerdiDashboard.js index b84e06739..c4d4bd72f 100644 --- a/src/components/settings/supportFerdi/SupportFerdiDashboard.js +++ b/src/components/settings/supportFerdi/SupportFerdiDashboard.js | |||
@@ -1,76 +1,77 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import { defineMessages, FormattedHTMLMessage, intlShape } from 'react-intl'; | 2 | import { defineMessages, injectIntl } from 'react-intl'; |
3 | import { BrowserWindow } from '@electron/remote'; | 3 | import { BrowserWindow } from '@electron/remote'; |
4 | import InfoBar from '../../ui/InfoBar'; | 4 | import InfoBar from '../../ui/InfoBar'; |
5 | 5 | ||
6 | const messages = defineMessages({ | 6 | const messages = defineMessages({ |
7 | headline: { | 7 | headline: { |
8 | id: 'settings.supportFerdi.headline', | 8 | id: 'settings.supportFerdi.headline', |
9 | defaultMessage: '!!!About Ferdi', | 9 | defaultMessage: 'About Ferdi', |
10 | }, | 10 | }, |
11 | title: { | 11 | title: { |
12 | id: 'settings.supportFerdi.title', | 12 | id: 'settings.supportFerdi.title', |
13 | defaultMessage: '!!!Do you like Ferdi?', | 13 | defaultMessage: 'Do you like Ferdi?', |
14 | }, | 14 | }, |
15 | aboutIntro: { | 15 | aboutIntro: { |
16 | id: 'settings.supportFerdi.aboutIntro', | 16 | id: 'settings.supportFerdi.aboutIntro', |
17 | defaultMessage: '!!!<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>', | 17 | defaultMessage: |
18 | '<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>', | ||
18 | }, | 19 | }, |
19 | textListContributors: { | 20 | textListContributors: { |
20 | id: 'settings.supportFerdi.textListContributors', | 21 | id: 'settings.supportFerdi.textListContributors', |
21 | defaultMessage: '!!!Full list of contributor', | 22 | defaultMessage: 'Full list of contributor', |
22 | }, | 23 | }, |
23 | textListContributorsHere: { | 24 | textListContributorsHere: { |
24 | id: 'settings.supportFerdi.textListContributorsHere', | 25 | id: 'settings.supportFerdi.textListContributorsHere', |
25 | defaultMessage: '!!!here', | 26 | defaultMessage: 'here', |
26 | }, | 27 | }, |
27 | textVolunteers: { | 28 | textVolunteers: { |
28 | id: 'settings.supportFerdi.textVolunteers', | 29 | id: 'settings.supportFerdi.textVolunteers', |
29 | defaultMessage: '!!!The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.', | 30 | defaultMessage: |
31 | 'The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.', | ||
30 | }, | 32 | }, |
31 | textSupportWelcome: { | 33 | textSupportWelcome: { |
32 | id: 'settings.supportFerdi.textSupportWelcome', | 34 | id: 'settings.supportFerdi.textSupportWelcome', |
33 | defaultMessage: '!!!Support is always welcome. You can find a list of the help we need', | 35 | defaultMessage: |
36 | 'Support is always welcome. You can find a list of the help we need', | ||
34 | }, | 37 | }, |
35 | textSupportWelcomeHere: { | 38 | textSupportWelcomeHere: { |
36 | id: 'settings.supportFerdi.textSupportWelcomeHere', | 39 | id: 'settings.supportFerdi.textSupportWelcomeHere', |
37 | defaultMessage: '!!!here', | 40 | defaultMessage: 'here', |
38 | }, | 41 | }, |
39 | textExpenses: { | 42 | textExpenses: { |
40 | id: 'settings.supportFerdi.textExpenses', | 43 | id: 'settings.supportFerdi.textExpenses', |
41 | defaultMessage: '!!!While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our', | 44 | defaultMessage: |
45 | 'While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our', | ||
42 | }, | 46 | }, |
43 | textOpenCollective: { | 47 | textOpenCollective: { |
44 | id: 'settings.supportFerdi.textOpenCollective', | 48 | id: 'settings.supportFerdi.textOpenCollective', |
45 | defaultMessage: '!!!Open Collective', | 49 | defaultMessage: 'Open Collective', |
46 | }, | 50 | }, |
47 | textDonation: { | 51 | textDonation: { |
48 | id: 'settings.supportFerdi.textDonation', | 52 | id: 'settings.supportFerdi.textDonation', |
49 | defaultMessage: '!!!If you feel like supporting Ferdi development with a donation, you can do so on both,', | 53 | defaultMessage: |
54 | 'If you feel like supporting Ferdi development with a donation, you can do so on both,', | ||
50 | }, | 55 | }, |
51 | textDonationAnd: { | 56 | textDonationAnd: { |
52 | id: 'settings.supportFerdi.textDonationAnd', | 57 | id: 'settings.supportFerdi.textDonationAnd', |
53 | defaultMessage: '!!!and', | 58 | defaultMessage: 'and', |
54 | }, | 59 | }, |
55 | textGitHubSponsors: { | 60 | textGitHubSponsors: { |
56 | id: 'settings.supportFerdi.textGitHubSponsors', | 61 | id: 'settings.supportFerdi.textGitHubSponsors', |
57 | defaultMessage: '!!!GitHub Sponsors', | 62 | defaultMessage: 'GitHub Sponsors', |
58 | }, | 63 | }, |
59 | openSurvey: { | 64 | openSurvey: { |
60 | id: 'settings.supportFerdi.openSurvey', | 65 | id: 'settings.supportFerdi.openSurvey', |
61 | defaultMessage: '!!!Open Survey', | 66 | defaultMessage: 'Open Survey', |
62 | }, | 67 | }, |
63 | bannerText: { | 68 | bannerText: { |
64 | id: 'settings.supportFerdi.bannerText', | 69 | id: 'settings.supportFerdi.bannerText', |
65 | defaultMessage: '!!!Do you want to help us improve Ferdi?', | 70 | defaultMessage: 'Do you want to help us improve Ferdi?', |
66 | }, | 71 | }, |
67 | }); | 72 | }); |
68 | 73 | ||
69 | class SupportFerdiDashboard extends Component { | 74 | class SupportFerdiDashboard extends Component { |
70 | static contextTypes = { | ||
71 | intl: intlShape, | ||
72 | }; | ||
73 | |||
74 | openSurveyWindow() { | 75 | openSurveyWindow() { |
75 | let win = new BrowserWindow({ width: 670, height: 400 }); | 76 | let win = new BrowserWindow({ width: 670, height: 400 }); |
76 | win.on('closed', () => { | 77 | win.on('closed', () => { |
@@ -81,7 +82,9 @@ class SupportFerdiDashboard extends Component { | |||
81 | } | 82 | } |
82 | 83 | ||
83 | render() { | 84 | render() { |
84 | const { intl } = this.context; | 85 | const { intl } = this.props; |
86 | |||
87 | const aboutIntro = intl.formatMessage(messages.aboutIntro); | ||
85 | 88 | ||
86 | return ( | 89 | return ( |
87 | <div className="settings__main"> | 90 | <div className="settings__main"> |
@@ -94,22 +97,67 @@ class SupportFerdiDashboard extends Component { | |||
94 | <h1>{intl.formatMessage(messages.title)}</h1> | 97 | <h1>{intl.formatMessage(messages.title)}</h1> |
95 | <div> | 98 | <div> |
96 | <p className="settings__support-badges"> | 99 | <p className="settings__support-badges"> |
97 | <a href="https://github.com/getferdi/ferdi" target="_blank" rel="noreferrer"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" /></a> | 100 | <a |
98 | <a href="https://twitter.com/getferdi/" target="_blank" rel="noreferrer"><img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" /></a> | 101 | href="https://github.com/getferdi/ferdi" |
99 | <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective backers" src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" /></a> | 102 | target="_blank" |
100 | <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective sponsors" src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" /></a> | 103 | rel="noreferrer" |
104 | > | ||
105 | <img | ||
106 | alt="GitHub Stars" | ||
107 | src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" | ||
108 | /> | ||
109 | </a> | ||
110 | <a | ||
111 | href="https://twitter.com/getferdi/" | ||
112 | target="_blank" | ||
113 | rel="noreferrer" | ||
114 | > | ||
115 | <img | ||
116 | alt="Twitter Follow" | ||
117 | src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" | ||
118 | /> | ||
119 | </a> | ||
120 | <a | ||
121 | href="https://opencollective.com/getferdi#section-contributors" | ||
122 | target="_blank" | ||
123 | rel="noreferrer" | ||
124 | > | ||
125 | <img | ||
126 | alt="Open Collective backers" | ||
127 | src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" | ||
128 | /> | ||
129 | </a> | ||
130 | <a | ||
131 | href="https://opencollective.com/getferdi#section-contributors" | ||
132 | target="_blank" | ||
133 | rel="noreferrer" | ||
134 | > | ||
135 | <img | ||
136 | alt="Open Collective sponsors" | ||
137 | src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" | ||
138 | /> | ||
139 | </a> | ||
101 | </p> | 140 | </p> |
102 | <FormattedHTMLMessage {...messages.aboutIntro} /> | 141 | <span dangerouslySetInnerHTML={{ __html: aboutIntro }} /> |
103 | <br /> | 142 | <br /> |
104 | <br /> | 143 | <br /> |
105 | <p> | 144 | <p> |
106 | <a href="#contributors-via-opencollective"> | 145 | <a href="#contributors-via-opencollective"> |
107 | <img alt="GitHub contributors (non-exhaustive)" width="100%" src="https://opencollective.com/getferdi/contributors.svg?width=642&button=false" /> | 146 | <img |
147 | alt="GitHub contributors (non-exhaustive)" | ||
148 | width="100%" | ||
149 | src="https://opencollective.com/getferdi/contributors.svg?width=642&button=false" | ||
150 | /> | ||
108 | </a> | 151 | </a> |
109 | </p> | 152 | </p> |
110 | <p> | 153 | <p> |
111 | {intl.formatMessage(messages.textListContributors)} | 154 | {intl.formatMessage(messages.textListContributors)} |
112 | <a href="https://github.com/getferdi/ferdi#contributors-" target="_blank" className="link" rel="noreferrer"> | 155 | <a |
156 | href="https://github.com/getferdi/ferdi#contributors-" | ||
157 | target="_blank" | ||
158 | className="link" | ||
159 | rel="noreferrer" | ||
160 | > | ||
113 | {' '} | 161 | {' '} |
114 | {intl.formatMessage(messages.textListContributorsHere)} | 162 | {intl.formatMessage(messages.textListContributorsHere)} |
115 | <i className="mdi mdi-open-in-new" /> | 163 | <i className="mdi mdi-open-in-new" /> |
@@ -117,12 +165,15 @@ class SupportFerdiDashboard extends Component { | |||
117 | <br /> | 165 | <br /> |
118 | <br /> | 166 | <br /> |
119 | </p> | 167 | </p> |
120 | <p> | 168 | <p>{intl.formatMessage(messages.textVolunteers)}</p> |
121 | {intl.formatMessage(messages.textVolunteers)} | ||
122 | </p> | ||
123 | <p> | 169 | <p> |
124 | {intl.formatMessage(messages.textSupportWelcome)} | 170 | {intl.formatMessage(messages.textSupportWelcome)} |
125 | <a href="https://help.getferdi.com/general/support" target="_blank" className="link" rel="noreferrer"> | 171 | <a |
172 | href="https://help.getferdi.com/general/support" | ||
173 | target="_blank" | ||
174 | className="link" | ||
175 | rel="noreferrer" | ||
176 | > | ||
126 | {' '} | 177 | {' '} |
127 | {intl.formatMessage(messages.textSupportWelcomeHere)} | 178 | {intl.formatMessage(messages.textSupportWelcomeHere)} |
128 | <i className="mdi mdi-open-in-new" /> | 179 | <i className="mdi mdi-open-in-new" /> |
@@ -130,7 +181,12 @@ class SupportFerdiDashboard extends Component { | |||
130 | </p> | 181 | </p> |
131 | <p> | 182 | <p> |
132 | {intl.formatMessage(messages.textExpenses)} | 183 | {intl.formatMessage(messages.textExpenses)} |
133 | <a href="https://opencollective.com/getferdi#section-budget" target="_blank" className="link" rel="noreferrer"> | 184 | <a |
185 | href="https://opencollective.com/getferdi#section-budget" | ||
186 | target="_blank" | ||
187 | className="link" | ||
188 | rel="noreferrer" | ||
189 | > | ||
134 | {' '} | 190 | {' '} |
135 | {intl.formatMessage(messages.textOpenCollective)} | 191 | {intl.formatMessage(messages.textOpenCollective)} |
136 | <i className="mdi mdi-open-in-new" /> | 192 | <i className="mdi mdi-open-in-new" /> |
@@ -138,14 +194,23 @@ class SupportFerdiDashboard extends Component { | |||
138 | </p> | 194 | </p> |
139 | <p> | 195 | <p> |
140 | {intl.formatMessage(messages.textDonation)} | 196 | {intl.formatMessage(messages.textDonation)} |
141 | <a href="https://opencollective.com/getferdi#section-contribute" target="_blank" className="link" rel="noreferrer"> | 197 | <a |
198 | href="https://opencollective.com/getferdi#section-contribute" | ||
199 | target="_blank" | ||
200 | className="link" | ||
201 | rel="noreferrer" | ||
202 | > | ||
142 | {' '} | 203 | {' '} |
143 | {intl.formatMessage(messages.textOpenCollective)} | 204 | {intl.formatMessage(messages.textOpenCollective)} |
144 | <i className="mdi mdi-open-in-new" /> | 205 | <i className="mdi mdi-open-in-new" /> |
145 | </a> | 206 | </a>{' '} |
146 | {' '} | ||
147 | {intl.formatMessage(messages.textDonationAnd)} | 207 | {intl.formatMessage(messages.textDonationAnd)} |
148 | <a href="https://github.com/sponsors/getferdi" target="_blank" className="link" rel="noreferrer"> | 208 | <a |
209 | href="https://github.com/sponsors/getferdi" | ||
210 | target="_blank" | ||
211 | className="link" | ||
212 | rel="noreferrer" | ||
213 | > | ||
149 | {' '} | 214 | {' '} |
150 | {intl.formatMessage(messages.textGitHubSponsors)} | 215 | {intl.formatMessage(messages.textGitHubSponsors)} |
151 | <i className="mdi mdi-open-in-new" /> | 216 | <i className="mdi mdi-open-in-new" /> |
@@ -166,4 +231,4 @@ class SupportFerdiDashboard extends Component { | |||
166 | } | 231 | } |
167 | } | 232 | } |
168 | 233 | ||
169 | export default SupportFerdiDashboard; | 234 | export default injectIntl(SupportFerdiDashboard); |
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js index 437225058..176365fa8 100644 --- a/src/components/settings/team/TeamDashboard.js +++ b/src/components/settings/team/TeamDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | import classnames from 'classnames'; | 7 | import classnames from 'classnames'; |
@@ -14,31 +14,34 @@ import { LIVE_FRANZ_API } from '../../../config'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'settings.team.headline', | 16 | id: 'settings.team.headline', |
17 | defaultMessage: '!!!Team', | 17 | defaultMessage: 'Team', |
18 | }, | 18 | }, |
19 | contentHeadline: { | 19 | contentHeadline: { |
20 | id: 'settings.team.contentHeadline', | 20 | id: 'settings.team.contentHeadline', |
21 | defaultMessage: '!!!Franz Team Management', | 21 | defaultMessage: 'Franz Team Management', |
22 | }, | 22 | }, |
23 | intro: { | 23 | intro: { |
24 | id: 'settings.team.intro', | 24 | id: 'settings.team.intro', |
25 | defaultMessage: '!!!Your are currently using Franz Servers, which is why you have access to Team Management.', | 25 | defaultMessage: |
26 | 'Your are currently using Franz Servers, which is why you have access to Team Management.', | ||
26 | }, | 27 | }, |
27 | copy: { | 28 | copy: { |
28 | id: 'settings.team.copy', | 29 | id: 'settings.team.copy', |
29 | defaultMessage: '!!!Franz\'s Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don\'t loose any functionality in managing your account.', | 30 | defaultMessage: |
31 | "Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.", | ||
30 | }, | 32 | }, |
31 | manageButton: { | 33 | manageButton: { |
32 | id: 'settings.team.manageAction', | 34 | id: 'settings.team.manageAction', |
33 | defaultMessage: '!!!Manage your Team on meetfranz.com', | 35 | defaultMessage: 'Manage your Team on meetfranz.com', |
34 | }, | 36 | }, |
35 | teamsUnavailable: { | 37 | teamsUnavailable: { |
36 | id: 'settings.team.teamsUnavailable', | 38 | id: 'settings.team.teamsUnavailable', |
37 | defaultMessage: '!!!Teams are unavailable', | 39 | defaultMessage: 'Teams are unavailable', |
38 | }, | 40 | }, |
39 | teamsUnavailableInfo: { | 41 | teamsUnavailableInfo: { |
40 | id: 'settings.team.teamsUnavailableInfo', | 42 | id: 'settings.team.teamsUnavailableInfo', |
41 | defaultMessage: '!!!Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.', | 43 | defaultMessage: |
44 | 'Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.', | ||
42 | }, | 45 | }, |
43 | }); | 46 | }); |
44 | 47 | ||
@@ -87,7 +90,9 @@ const styles = { | |||
87 | }, | 90 | }, |
88 | }; | 91 | }; |
89 | 92 | ||
90 | export default @injectSheet(styles) @observer class TeamDashboard extends Component { | 93 | @injectSheet(styles) |
94 | @observer | ||
95 | class TeamDashboard extends Component { | ||
91 | static propTypes = { | 96 | static propTypes = { |
92 | isLoading: PropTypes.bool.isRequired, | 97 | isLoading: PropTypes.bool.isRequired, |
93 | userInfoRequestFailed: PropTypes.bool.isRequired, | 98 | userInfoRequestFailed: PropTypes.bool.isRequired, |
@@ -97,10 +102,6 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
97 | server: PropTypes.string.isRequired, | 102 | server: PropTypes.string.isRequired, |
98 | }; | 103 | }; |
99 | 104 | ||
100 | static contextTypes = { | ||
101 | intl: intlShape, | ||
102 | }; | ||
103 | |||
104 | render() { | 105 | render() { |
105 | const { | 106 | const { |
106 | isLoading, | 107 | isLoading, |
@@ -110,7 +111,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
110 | classes, | 111 | classes, |
111 | server, | 112 | server, |
112 | } = this.props; | 113 | } = this.props; |
113 | const { intl } = this.context; | 114 | const { intl } = this.props; |
114 | 115 | ||
115 | if (server === LIVE_FRANZ_API) { | 116 | if (server === LIVE_FRANZ_API) { |
116 | return ( | 117 | return ( |
@@ -121,9 +122,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
121 | </span> | 122 | </span> |
122 | </div> | 123 | </div> |
123 | <div className="settings__body"> | 124 | <div className="settings__body"> |
124 | {isLoading && ( | 125 | {isLoading && <Loader />} |
125 | <Loader /> | ||
126 | )} | ||
127 | 126 | ||
128 | {!isLoading && userInfoRequestFailed && ( | 127 | {!isLoading && userInfoRequestFailed && ( |
129 | <Infobox | 128 | <Infobox |
@@ -142,20 +141,24 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
142 | {!isLoading && ( | 141 | {!isLoading && ( |
143 | <> | 142 | <> |
144 | <> | 143 | <> |
145 | <h1 className={classnames({ | 144 | <h1 |
146 | [classes.headline]: true, | 145 | className={classnames({ |
147 | [classes.headlineWithSpacing]: true, | 146 | [classes.headline]: true, |
148 | })} | 147 | [classes.headlineWithSpacing]: true, |
148 | })} | ||
149 | > | 149 | > |
150 | {intl.formatMessage(messages.contentHeadline)} | 150 | {intl.formatMessage(messages.contentHeadline)} |
151 | |||
152 | </h1> | 151 | </h1> |
153 | <div className={classes.container}> | 152 | <div className={classes.container}> |
154 | <div className={classes.content}> | 153 | <div className={classes.content}> |
155 | <p>{intl.formatMessage(messages.intro)}</p> | 154 | <p>{intl.formatMessage(messages.intro)}</p> |
156 | <p>{intl.formatMessage(messages.copy)}</p> | 155 | <p>{intl.formatMessage(messages.copy)}</p> |
157 | </div> | 156 | </div> |
158 | <img className={classes.image} src="https://cdn.franzinfra.com/announcements/assets/teams.png" alt="Ferdi for Teams" /> | 157 | <img |
158 | className={classes.image} | ||
159 | src="https://cdn.franzinfra.com/announcements/assets/teams.png" | ||
160 | alt="Ferdi for Teams" | ||
161 | /> | ||
159 | </div> | 162 | </div> |
160 | <div className={classes.buttonContainer}> | 163 | <div className={classes.buttonContainer}> |
161 | <Button | 164 | <Button |
@@ -188,7 +191,8 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
188 | <p | 191 | <p |
189 | className="settings__message" | 192 | className="settings__message" |
190 | style={{ | 193 | style={{ |
191 | borderTop: 0, marginTop: 0, | 194 | borderTop: 0, |
195 | marginTop: 0, | ||
192 | }} | 196 | }} |
193 | > | 197 | > |
194 | {intl.formatMessage(messages.teamsUnavailableInfo)} | 198 | {intl.formatMessage(messages.teamsUnavailableInfo)} |
@@ -198,3 +202,5 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
198 | ); | 202 | ); |
199 | } | 203 | } |
200 | } | 204 | } |
205 | |||
206 | export default injectIntl(TeamDashboard); | ||
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js index db78acb69..4067881b8 100644 --- a/src/components/settings/user/EditUserForm.js +++ b/src/components/settings/user/EditUserForm.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | 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, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import { Input } from '@meetfranz/forms'; | 6 | import { Input } from '@meetfranz/forms'; |
7 | 7 | ||
@@ -14,31 +14,32 @@ import Infobox from '../../ui/Infobox'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'settings.account.headline', | 16 | id: 'settings.account.headline', |
17 | defaultMessage: '!!!Account', | 17 | defaultMessage: 'Account', |
18 | }, | 18 | }, |
19 | headlineProfile: { | 19 | headlineProfile: { |
20 | id: 'settings.account.headlineProfile', | 20 | id: 'settings.account.headlineProfile', |
21 | defaultMessage: '!!!Update Profile', | 21 | defaultMessage: 'Update Profile', |
22 | }, | 22 | }, |
23 | headlineAccount: { | 23 | headlineAccount: { |
24 | id: 'settings.account.headlineAccount', | 24 | id: 'settings.account.headlineAccount', |
25 | defaultMessage: '!!!Account Information', | 25 | defaultMessage: 'Account Information', |
26 | }, | 26 | }, |
27 | headlinePassword: { | 27 | headlinePassword: { |
28 | id: 'settings.account.headlinePassword', | 28 | id: 'settings.account.headlinePassword', |
29 | defaultMessage: '!!!Change Password', | 29 | defaultMessage: 'Change Password', |
30 | }, | 30 | }, |
31 | successInfo: { | 31 | successInfo: { |
32 | id: 'settings.account.successInfo', | 32 | id: 'settings.account.successInfo', |
33 | defaultMessage: '!!!Your changes have been saved', | 33 | defaultMessage: 'Your changes have been saved', |
34 | }, | 34 | }, |
35 | buttonSave: { | 35 | buttonSave: { |
36 | id: 'settings.account.buttonSave', | 36 | id: 'settings.account.buttonSave', |
37 | defaultMessage: '!!!Update profile', | 37 | defaultMessage: 'Update profile', |
38 | }, | 38 | }, |
39 | }); | 39 | }); |
40 | 40 | ||
41 | export default @observer class EditUserForm extends Component { | 41 | @observer |
42 | class EditUserForm extends Component { | ||
42 | static propTypes = { | 43 | static propTypes = { |
43 | status: MobxPropTypes.observableArray.isRequired, | 44 | status: MobxPropTypes.observableArray.isRequired, |
44 | form: PropTypes.instanceOf(Form).isRequired, | 45 | form: PropTypes.instanceOf(Form).isRequired, |
@@ -46,14 +47,10 @@ export default @observer class EditUserForm extends Component { | |||
46 | isSaving: PropTypes.bool.isRequired, | 47 | isSaving: PropTypes.bool.isRequired, |
47 | }; | 48 | }; |
48 | 49 | ||
49 | static contextTypes = { | ||
50 | intl: intlShape, | ||
51 | }; | ||
52 | |||
53 | submit(e) { | 50 | submit(e) { |
54 | e.preventDefault(); | 51 | e.preventDefault(); |
55 | this.props.form.submit({ | 52 | this.props.form.submit({ |
56 | onSuccess: (form) => { | 53 | onSuccess: form => { |
57 | const values = form.values(); | 54 | const values = form.values(); |
58 | this.props.onSubmit(values); | 55 | this.props.onSubmit(values); |
59 | }, | 56 | }, |
@@ -68,7 +65,7 @@ export default @observer class EditUserForm extends Component { | |||
68 | form, | 65 | form, |
69 | isSaving, | 66 | isSaving, |
70 | } = this.props; | 67 | } = this.props; |
71 | const { intl } = this.context; | 68 | const { intl } = this.props; |
72 | 69 | ||
73 | return ( | 70 | return ( |
74 | <div className="settings__main"> | 71 | <div className="settings__main"> |
@@ -84,12 +81,9 @@ export default @observer class EditUserForm extends Component { | |||
84 | </span> | 81 | </span> |
85 | </div> | 82 | </div> |
86 | <div className="settings__body"> | 83 | <div className="settings__body"> |
87 | <form onSubmit={(e) => this.submit(e)} id="form"> | 84 | <form onSubmit={e => this.submit(e)} id="form"> |
88 | {status.length > 0 && status.includes('data-updated') && ( | 85 | {status.length > 0 && status.includes('data-updated') && ( |
89 | <Infobox | 86 | <Infobox type="success" icon="checkbox-marked-circle-outline"> |
90 | type="success" | ||
91 | icon="checkbox-marked-circle-outline" | ||
92 | > | ||
93 | {intl.formatMessage(messages.successInfo)} | 87 | {intl.formatMessage(messages.successInfo)} |
94 | </Infobox> | 88 | </Infobox> |
95 | )} | 89 | )} |
@@ -104,10 +98,7 @@ export default @observer class EditUserForm extends Component { | |||
104 | <Input field={form.$('organization')} /> | 98 | <Input field={form.$('organization')} /> |
105 | )} | 99 | )} |
106 | <h2>{intl.formatMessage(messages.headlinePassword)}</h2> | 100 | <h2>{intl.formatMessage(messages.headlinePassword)}</h2> |
107 | <Input | 101 | <Input {...form.$('oldPassword').bind()} showPasswordToggle /> |
108 | {...form.$('oldPassword').bind()} | ||
109 | showPasswordToggle | ||
110 | /> | ||
111 | <Input | 102 | <Input |
112 | {...form.$('newPassword').bind()} | 103 | {...form.$('newPassword').bind()} |
113 | showPasswordToggle | 104 | showPasswordToggle |
@@ -137,3 +128,5 @@ export default @observer class EditUserForm extends Component { | |||
137 | ); | 128 | ); |
138 | } | 129 | } |
139 | } | 130 | } |
131 | |||
132 | export default injectIntl(EditUserForm); | ||