aboutsummaryrefslogtreecommitdiffstats
path: root/src/containers/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/containers/settings')
-rw-r--r--src/containers/settings/AccountScreen.js11
-rw-r--r--src/containers/settings/EditServiceScreen.js121
-rw-r--r--src/containers/settings/EditSettingsScreen.js166
-rw-r--r--src/containers/settings/EditUserScreen.js60
-rw-r--r--src/containers/settings/InviteScreen.js8
-rw-r--r--src/containers/settings/RecipesScreen.js92
-rw-r--r--src/containers/settings/ServicesScreen.js17
-rw-r--r--src/containers/settings/SettingsWindow.js21
-rw-r--r--src/containers/settings/SupportScreen.js9
-rw-r--r--src/containers/settings/TeamScreen.js11
10 files changed, 289 insertions, 227 deletions
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js
index 8d92b01be..cc3929656 100644
--- a/src/containers/settings/AccountScreen.js
+++ b/src/containers/settings/AccountScreen.js
@@ -12,7 +12,6 @@ import ErrorBoundary from '../../components/util/ErrorBoundary';
12import { LIVE_FRANZ_API } from '../../config'; 12import { LIVE_FRANZ_API } from '../../config';
13import { WEBSITE } from '../../environment'; 13import { WEBSITE } from '../../environment';
14 14
15export default
16@inject('stores', 'actions') 15@inject('stores', 'actions')
17@observer 16@observer
18class AccountScreen extends Component { 17class AccountScreen extends Component {
@@ -58,16 +57,16 @@ class AccountScreen extends Component {
58 user={user.data} 57 user={user.data}
59 isLoading={isLoadingUserInfo} 58 isLoading={isLoadingUserInfo}
60 userInfoRequestFailed={ 59 userInfoRequestFailed={
61 user.getUserInfoRequest.wasExecuted 60 user.getUserInfoRequest.wasExecuted &&
62 && user.getUserInfoRequest.isError 61 user.getUserInfoRequest.isError
63 } 62 }
64 retryUserInfoRequest={() => this.reloadData()} 63 retryUserInfoRequest={() => this.reloadData()}
65 onCloseSubscriptionWindow={() => this.onCloseWindow()} 64 onCloseSubscriptionWindow={() => this.onCloseWindow()}
66 deleteAccount={userActions.delete} 65 deleteAccount={userActions.delete}
67 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting} 66 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting}
68 isDeleteAccountSuccessful={ 67 isDeleteAccountSuccessful={
69 user.deleteAccountRequest.wasExecuted 68 user.deleteAccountRequest.wasExecuted &&
70 && !user.deleteAccountRequest.isError 69 !user.deleteAccountRequest.isError
71 } 70 }
72 openEditAccount={() => this.handleWebsiteLink('/user/profile')} 71 openEditAccount={() => this.handleWebsiteLink('/user/profile')}
73 openInvoices={() => this.handleWebsiteLink('/user/invoices')} 72 openInvoices={() => this.handleWebsiteLink('/user/invoices')}
@@ -89,3 +88,5 @@ AccountScreen.wrappedComponent.propTypes = {
89 user: PropTypes.instanceOf(UserStore).isRequired, 88 user: PropTypes.instanceOf(UserStore).isRequired,
90 }).isRequired, 89 }).isRequired,
91}; 90};
91
92export default AccountScreen;
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index c880e97ae..12e7b9e95 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import { RouterStore } from 'mobx-react-router'; 6import { RouterStore } from 'mobx-react-router';
7import UserStore from '../../stores/UserStore'; 7import UserStore from '../../stores/UserStore';
@@ -27,87 +27,85 @@ import globalMessages from '../../i18n/globalMessages';
27const messages = defineMessages({ 27const messages = defineMessages({
28 name: { 28 name: {
29 id: 'settings.service.form.name', 29 id: 'settings.service.form.name',
30 defaultMessage: '!!!Name', 30 defaultMessage: 'Name',
31 }, 31 },
32 enableService: { 32 enableService: {
33 id: 'settings.service.form.enableService', 33 id: 'settings.service.form.enableService',
34 defaultMessage: '!!!Enable service', 34 defaultMessage: 'Enable service',
35 }, 35 },
36 enableHibernation: { 36 enableHibernation: {
37 id: 'settings.service.form.enableHibernation', 37 id: 'settings.service.form.enableHibernation',
38 defaultMessage: '!!!Enable hibernation', 38 defaultMessage: 'Enable hibernation',
39 }, 39 },
40 enableNotification: { 40 enableNotification: {
41 id: 'settings.service.form.enableNotification', 41 id: 'settings.service.form.enableNotification',
42 defaultMessage: '!!!Enable Notifications', 42 defaultMessage: 'Enable Notifications',
43 }, 43 },
44 enableBadge: { 44 enableBadge: {
45 id: 'settings.service.form.enableBadge', 45 id: 'settings.service.form.enableBadge',
46 defaultMessage: '!!!Show unread message badges', 46 defaultMessage: 'Show unread message badges',
47 }, 47 },
48 enableAudio: { 48 enableAudio: {
49 id: 'settings.service.form.enableAudio', 49 id: 'settings.service.form.enableAudio',
50 defaultMessage: '!!!Enable audio', 50 defaultMessage: 'Enable audio',
51 }, 51 },
52 team: { 52 team: {
53 id: 'settings.service.form.team', 53 id: 'settings.service.form.team',
54 defaultMessage: '!!!Team', 54 defaultMessage: 'Team',
55 }, 55 },
56 customUrl: { 56 customUrl: {
57 id: 'settings.service.form.customUrl', 57 id: 'settings.service.form.customUrl',
58 defaultMessage: '!!!Service URL', 58 defaultMessage: 'Service URL',
59 }, 59 },
60 indirectMessages: { 60 indirectMessages: {
61 id: 'settings.service.form.indirectMessages', 61 id: 'settings.service.form.indirectMessages',
62 defaultMessage: '!!!Show message badge for all new messages', 62 defaultMessage: 'Show message badge for all new messages',
63 }, 63 },
64 icon: { 64 icon: {
65 id: 'settings.service.form.icon', 65 id: 'settings.service.form.icon',
66 defaultMessage: '!!!Custom icon', 66 defaultMessage: 'Custom icon',
67 }, 67 },
68 enableDarkMode: { 68 enableDarkMode: {
69 id: 'settings.service.form.enableDarkMode', 69 id: 'settings.service.form.enableDarkMode',
70 defaultMessage: '!!!Enable Dark Mode', 70 defaultMessage: 'Enable Dark Mode',
71 }, 71 },
72 darkReaderBrightness: { 72 darkReaderBrightness: {
73 id: 'settings.service.form.darkReaderBrightness', 73 id: 'settings.service.form.darkReaderBrightness',
74 defaultMessage: '!!!Dark Reader Brightness', 74 defaultMessage: 'Dark Reader Brightness',
75 }, 75 },
76 darkReaderContrast: { 76 darkReaderContrast: {
77 id: 'settings.service.form.darkReaderContrast', 77 id: 'settings.service.form.darkReaderContrast',
78 defaultMessage: '!!!Dark Reader Contrast', 78 defaultMessage: 'Dark Reader Contrast',
79 }, 79 },
80 darkReaderSepia: { 80 darkReaderSepia: {
81 id: 'settings.service.form.darkReaderSepia', 81 id: 'settings.service.form.darkReaderSepia',
82 defaultMessage: '!!!Dark Reader Sepia', 82 defaultMessage: 'Dark Reader Sepia',
83 }, 83 },
84 enableProxy: { 84 enableProxy: {
85 id: 'settings.service.form.proxy.isEnabled', 85 id: 'settings.service.form.proxy.isEnabled',
86 defaultMessage: '!!!Use Proxy', 86 defaultMessage: 'Use Proxy',
87 }, 87 },
88 proxyHost: { 88 proxyHost: {
89 id: 'settings.service.form.proxy.host', 89 id: 'settings.service.form.proxy.host',
90 defaultMessage: '!!!Proxy Host/IP', 90 defaultMessage: 'Proxy Host/IP',
91 }, 91 },
92 proxyPort: { 92 proxyPort: {
93 id: 'settings.service.form.proxy.port', 93 id: 'settings.service.form.proxy.port',
94 defaultMessage: '!!!Port', 94 defaultMessage: 'Port',
95 }, 95 },
96 proxyUser: { 96 proxyUser: {
97 id: 'settings.service.form.proxy.user', 97 id: 'settings.service.form.proxy.user',
98 defaultMessage: '!!!User', 98 defaultMessage: 'User',
99 }, 99 },
100 proxyPassword: { 100 proxyPassword: {
101 id: 'settings.service.form.proxy.password', 101 id: 'settings.service.form.proxy.password',
102 defaultMessage: '!!!Password', 102 defaultMessage: 'Password',
103 }, 103 },
104}); 104});
105 105
106export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component { 106@inject('stores', 'actions')
107 static contextTypes = { 107@observer
108 intl: intlShape, 108class EditServiceScreen extends Component {
109 };
110
111 onSubmit(data) { 109 onSubmit(data) {
112 const { action } = this.props.router.params; 110 const { action } = this.props.router.params;
113 const { recipes, services } = this.props.stores; 111 const { recipes, services } = this.props.stores;
@@ -132,27 +130,31 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
132 } 130 }
133 131
134 prepareForm(recipe, service, proxy) { 132 prepareForm(recipe, service, proxy) {
135 const { 133 const { intl } = this.props;
136 intl,
137 } = this.context;
138 134
139 const { 135 const { stores, router } = this.props;
140 stores,
141 router,
142 } = this.props;
143 136
144 const { action } = router.params; 137 const { action } = router.params;
145 138
146 let defaultSpellcheckerLanguage = SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage]; 139 let defaultSpellcheckerLanguage =
140 SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage];
147 141
148 if (stores.settings.app.spellcheckerLanguage === 'automatic') { 142 if (stores.settings.app.spellcheckerLanguage === 'automatic') {
149 defaultSpellcheckerLanguage = intl.formatMessage(globalMessages.spellcheckerAutomaticDetectionShort); 143 defaultSpellcheckerLanguage = intl.formatMessage(
144 globalMessages.spellcheckerAutomaticDetectionShort,
145 );
150 } 146 }
151 147
152 const spellcheckerLanguage = getSelectOptions({ 148 const spellcheckerLanguage = getSelectOptions({
153 locales: SPELLCHECKER_LOCALES, 149 locales: SPELLCHECKER_LOCALES,
154 resetToDefaultText: intl.formatMessage(globalMessages.spellcheckerSystemDefault, { default: defaultSpellcheckerLanguage }), 150 resetToDefaultText: intl.formatMessage(
155 automaticDetectionText: stores.settings.app.spellcheckerLanguage !== 'automatic' ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection) : '', 151 globalMessages.spellcheckerSystemDefault,
152 { default: defaultSpellcheckerLanguage },
153 ),
154 automaticDetectionText:
155 stores.settings.app.spellcheckerLanguage !== 'automatic'
156 ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection)
157 : '',
156 }); 158 });
157 159
158 const config = { 160 const config = {
@@ -169,7 +171,10 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
169 }, 171 },
170 isHibernationEnabled: { 172 isHibernationEnabled: {
171 label: intl.formatMessage(messages.enableHibernation), 173 label: intl.formatMessage(messages.enableHibernation),
172 value: action !== 'edit' ? recipe.autoHibernate : service.isHibernationEnabled, 174 value:
175 action !== 'edit'
176 ? recipe.autoHibernate
177 : service.isHibernationEnabled,
173 default: true, 178 default: true,
174 }, 179 },
175 isNotificationEnabled: { 180 isNotificationEnabled: {
@@ -200,17 +205,23 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
200 }, 205 },
201 darkReaderBrightness: { 206 darkReaderBrightness: {
202 label: intl.formatMessage(messages.darkReaderBrightness), 207 label: intl.formatMessage(messages.darkReaderBrightness),
203 value: service.darkReaderSettings ? service.darkReaderSettings.brightness : undefined, 208 value: service.darkReaderSettings
209 ? service.darkReaderSettings.brightness
210 : undefined,
204 default: 100, 211 default: 100,
205 }, 212 },
206 darkReaderContrast: { 213 darkReaderContrast: {
207 label: intl.formatMessage(messages.darkReaderContrast), 214 label: intl.formatMessage(messages.darkReaderContrast),
208 value: service.darkReaderSettings ? service.darkReaderSettings.contrast : undefined, 215 value: service.darkReaderSettings
216 ? service.darkReaderSettings.contrast
217 : undefined,
209 default: 90, 218 default: 90,
210 }, 219 },
211 darkReaderSepia: { 220 darkReaderSepia: {
212 label: intl.formatMessage(messages.darkReaderSepia), 221 label: intl.formatMessage(messages.darkReaderSepia),
213 value: service.darkReaderSettings ? service.darkReaderSettings.sepia : undefined, 222 value: service.darkReaderSettings
223 ? service.darkReaderSettings.sepia
224 : undefined,
214 default: 10, 225 default: 10,
215 }, 226 },
216 spellcheckerLanguage: { 227 spellcheckerLanguage: {
@@ -252,7 +263,10 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
252 // More fine grained and use case specific validation rules 263 // More fine grained and use case specific validation rules
253 if (recipe.hasTeamId && recipe.hasCustomUrl) { 264 if (recipe.hasTeamId && recipe.hasCustomUrl) {
254 config.fields.team.validators = [oneRequired(['team', 'customUrl'])]; 265 config.fields.team.validators = [oneRequired(['team', 'customUrl'])];
255 config.fields.customUrl.validators = [url, oneRequired(['team', 'customUrl'])]; 266 config.fields.customUrl.validators = [
267 url,
268 oneRequired(['team', 'customUrl']),
269 ];
256 } 270 }
257 271
258 // If a service can be hosted and has a teamId or customUrl 272 // If a service can be hosted and has a teamId or customUrl
@@ -344,9 +358,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
344 } 358 }
345 359
346 render() { 360 render() {
347 const { 361 const { recipes, services, user } = this.props.stores;
348 recipes, services, user,
349 } = this.props.stores;
350 const { action } = this.props.router.params; 362 const { action } = this.props.router.params;
351 363
352 let recipe; 364 let recipe;
@@ -358,9 +370,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
358 370
359 // TODO: render error message when recipe is `null` 371 // TODO: render error message when recipe is `null`
360 if (!recipe) { 372 if (!recipe) {
361 return ( 373 return <ServiceError />;
362 <ServiceError />
363 );
364 } 374 }
365 } else { 375 } else {
366 service = services.activeSettings; 376 service = services.activeSettings;
@@ -372,13 +382,11 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
372 } 382 }
373 383
374 if (isLoading) { 384 if (isLoading) {
375 return (<div>Loading...</div>); 385 return <div>Loading...</div>;
376 } 386 }
377 387
378 if (!recipe) { 388 if (!recipe) {
379 return ( 389 return <div>something went wrong</div>;
380 <div>something went wrong</div>
381 );
382 } 390 }
383 391
384 const form = this.prepareForm(recipe, service, proxyFeature); 392 const form = this.prepareForm(recipe, service, proxyFeature);
@@ -392,11 +400,14 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
392 user={user.data} 400 user={user.data}
393 form={form} 401 form={form}
394 status={services.actionStatus} 402 status={services.actionStatus}
395 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting} 403 isSaving={
404 services.updateServiceRequest.isExecuting ||
405 services.createServiceRequest.isExecuting
406 }
396 isDeleting={services.deleteServiceRequest.isExecuting} 407 isDeleting={services.deleteServiceRequest.isExecuting}
397 onSubmit={(d) => this.onSubmit(d)} 408 onSubmit={d => this.onSubmit(d)}
398 onDelete={() => this.deleteService()} 409 onDelete={() => this.deleteService()}
399 openRecipeFile={(file) => this.openRecipeFile(file)} 410 openRecipeFile={file => this.openRecipeFile(file)}
400 isProxyFeatureEnabled={proxyFeature.isEnabled} 411 isProxyFeatureEnabled={proxyFeature.isEnabled}
401 /> 412 />
402 </ErrorBoundary> 413 </ErrorBoundary>
@@ -417,3 +428,5 @@ EditServiceScreen.wrappedComponent.propTypes = {
417 service: PropTypes.instanceOf(ServicesStore).isRequired, 428 service: PropTypes.instanceOf(ServicesStore).isRequired,
418 }).isRequired, 429 }).isRequired,
419}; 430};
431
432export default injectIntl(EditServiceScreen);
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index 09244bc3c..8834aa1ae 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import AppStore from '../../stores/AppStore'; 6import AppStore from '../../stores/AppStore';
7import SettingsStore from '../../stores/SettingsStore'; 7import SettingsStore from '../../stores/SettingsStore';
@@ -10,8 +10,15 @@ import TodosStore from '../../features/todos/store';
10import Form from '../../lib/Form'; 10import Form from '../../lib/Form';
11import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages'; 11import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages';
12import { 12import {
13 HIBERNATION_STRATEGIES, SIDEBAR_WIDTH, ICON_SIZES, NAVIGATION_BAR_BEHAVIOURS, SEARCH_ENGINE_NAMES, TODO_APPS, 13 HIBERNATION_STRATEGIES,
14 DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED, DEFAULT_IS_FEATURE_ENABLED_BY_USER, WAKE_UP_STRATEGIES, 14 SIDEBAR_WIDTH,
15 ICON_SIZES,
16 NAVIGATION_BAR_BEHAVIOURS,
17 SEARCH_ENGINE_NAMES,
18 TODO_APPS,
19 DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED,
20 DEFAULT_IS_FEATURE_ENABLED_BY_USER,
21 WAKE_UP_STRATEGIES,
15} from '../../config'; 22} from '../../config';
16import { DEFAULT_APP_SETTINGS, isMac } from '../../environment'; 23import { DEFAULT_APP_SETTINGS, isMac } from '../../environment';
17 24
@@ -31,195 +38,193 @@ const debug = require('debug')('Ferdi:EditSettingsScreen');
31const messages = defineMessages({ 38const messages = defineMessages({
32 autoLaunchOnStart: { 39 autoLaunchOnStart: {
33 id: 'settings.app.form.autoLaunchOnStart', 40 id: 'settings.app.form.autoLaunchOnStart',
34 defaultMessage: '!!!Launch Ferdi on start', 41 defaultMessage: 'Launch Ferdi on start',
35 }, 42 },
36 autoLaunchInBackground: { 43 autoLaunchInBackground: {
37 id: 'settings.app.form.autoLaunchInBackground', 44 id: 'settings.app.form.autoLaunchInBackground',
38 defaultMessage: '!!!Open in background', 45 defaultMessage: 'Open in background',
39 }, 46 },
40 runInBackground: { 47 runInBackground: {
41 id: 'settings.app.form.runInBackground', 48 id: 'settings.app.form.runInBackground',
42 defaultMessage: '!!!Keep Ferdi in background when closing the window', 49 defaultMessage: 'Keep Ferdi in background when closing the window',
43 }, 50 },
44 startMinimized: { 51 startMinimized: {
45 id: 'settings.app.form.startMinimized', 52 id: 'settings.app.form.startMinimized',
46 defaultMessage: '!!!Start minimized', 53 defaultMessage: 'Start minimized',
47 }, 54 },
48 confirmOnQuit: { 55 confirmOnQuit: {
49 id: 'settings.app.form.confirmOnQuit', 56 id: 'settings.app.form.confirmOnQuit',
50 defaultMessage: '!!!Confirm when quitting Ferdi', 57 defaultMessage: 'Confirm when quitting Ferdi',
51 }, 58 },
52 enableSystemTray: { 59 enableSystemTray: {
53 id: 'settings.app.form.enableSystemTray', 60 id: 'settings.app.form.enableSystemTray',
54 defaultMessage: '!!!Always show Ferdi in System Tray', 61 defaultMessage: 'Always show Ferdi in System Tray',
55 }, 62 },
56 enableMenuBar: { 63 enableMenuBar: {
57 id: 'settings.app.form.enableMenuBar', 64 id: 'settings.app.form.enableMenuBar',
58 defaultMessage: '!!!Always show Ferdi in Menu Bar', 65 defaultMessage: 'Always show Ferdi in Menu Bar',
59 }, 66 },
60 reloadAfterResume: { 67 reloadAfterResume: {
61 id: 'settings.app.form.reloadAfterResume', 68 id: 'settings.app.form.reloadAfterResume',
62 defaultMessage: '!!!Reload Ferdi after system resume', 69 defaultMessage: 'Reload Ferdi after system resume',
63 }, 70 },
64 minimizeToSystemTray: { 71 minimizeToSystemTray: {
65 id: 'settings.app.form.minimizeToSystemTray', 72 id: 'settings.app.form.minimizeToSystemTray',
66 defaultMessage: '!!!Minimize Ferdi to system tray', 73 defaultMessage: 'Minimize Ferdi to system tray',
67 }, 74 },
68 closeToSystemTray: { 75 closeToSystemTray: {
69 id: 'settings.app.form.closeToSystemTray', 76 id: 'settings.app.form.closeToSystemTray',
70 defaultMessage: '!!!Close Ferdi to system tray', 77 defaultMessage: 'Close Ferdi to system tray',
71 }, 78 },
72 privateNotifications: { 79 privateNotifications: {
73 id: 'settings.app.form.privateNotifications', 80 id: 'settings.app.form.privateNotifications',
74 defaultMessage: '!!!Don\'t show message content in notifications', 81 defaultMessage: "Don't show message content in notifications",
75 }, 82 },
76 clipboardNotifications: { 83 clipboardNotifications: {
77 id: 'settings.app.form.clipboardNotifications', 84 id: 'settings.app.form.clipboardNotifications',
78 defaultMessage: '!!!Don\'t show notifications for clipboard events', 85 defaultMessage: "Don't show notifications for clipboard events",
79 }, 86 },
80 notifyTaskBarOnMessage: { 87 notifyTaskBarOnMessage: {
81 id: 'settings.app.form.notifyTaskBarOnMessage', 88 id: 'settings.app.form.notifyTaskBarOnMessage',
82 defaultMessage: '!!!Notify TaskBar/Dock on new message', 89 defaultMessage: 'Notify TaskBar/Dock on new message',
83 }, 90 },
84 navigationBarBehaviour: { 91 navigationBarBehaviour: {
85 id: 'settings.app.form.navigationBarBehaviour', 92 id: 'settings.app.form.navigationBarBehaviour',
86 defaultMessage: '!!!Navigation bar behaviour', 93 defaultMessage: 'Navigation bar behaviour',
87 }, 94 },
88 searchEngine: { 95 searchEngine: {
89 id: 'settings.app.form.searchEngine', 96 id: 'settings.app.form.searchEngine',
90 defaultMessage: '!!!Search engine', 97 defaultMessage: 'Search engine',
91 }, 98 },
92 sentry: { 99 sentry: {
93 id: 'settings.app.form.sentry', 100 id: 'settings.app.form.sentry',
94 defaultMessage: '!!!Send telemetry data', 101 defaultMessage: 'Send telemetry data',
95 }, 102 },
96 hibernateOnStartup: { 103 hibernateOnStartup: {
97 id: 'settings.app.form.hibernateOnStartup', 104 id: 'settings.app.form.hibernateOnStartup',
98 defaultMessage: '!!!Keep services in hibernation on startup', 105 defaultMessage: 'Keep services in hibernation on startup',
99 }, 106 },
100 hibernationStrategy: { 107 hibernationStrategy: {
101 id: 'settings.app.form.hibernationStrategy', 108 id: 'settings.app.form.hibernationStrategy',
102 defaultMessage: '!!!Hibernation strategy', 109 defaultMessage: 'Hibernation strategy',
103 }, 110 },
104 wakeUpStrategy: { 111 wakeUpStrategy: {
105 id: 'settings.app.form.wakeUpStrategy', 112 id: 'settings.app.form.wakeUpStrategy',
106 defaultMessage: '!!!Wake up strategy', 113 defaultMessage: 'Wake up strategy',
107 }, 114 },
108 predefinedTodoServer: { 115 predefinedTodoServer: {
109 id: 'settings.app.form.predefinedTodoServer', 116 id: 'settings.app.form.predefinedTodoServer',
110 defaultMessage: '!!!Todo Server', 117 defaultMessage: 'Todo Server',
111 }, 118 },
112 customTodoServer: { 119 customTodoServer: {
113 id: 'settings.app.form.customTodoServer', 120 id: 'settings.app.form.customTodoServer',
114 defaultMessage: '!!!Custom TodoServer', 121 defaultMessage: 'Custom TodoServer',
115 }, 122 },
116 enableLock: { 123 enableLock: {
117 id: 'settings.app.form.enableLock', 124 id: 'settings.app.form.enableLock',
118 defaultMessage: '!!!Enable Password Lock', 125 defaultMessage: 'Enable Password Lock',
119 }, 126 },
120 lockPassword: { 127 lockPassword: {
121 id: 'settings.app.form.lockPassword', 128 id: 'settings.app.form.lockPassword',
122 defaultMessage: '!!!Password', 129 defaultMessage: 'Password',
123 }, 130 },
124 useTouchIdToUnlock: { 131 useTouchIdToUnlock: {
125 id: 'settings.app.form.useTouchIdToUnlock', 132 id: 'settings.app.form.useTouchIdToUnlock',
126 defaultMessage: '!!!Allow using Touch ID to unlock', 133 defaultMessage: 'Allow using Touch ID to unlock',
127 }, 134 },
128 inactivityLock: { 135 inactivityLock: {
129 id: 'settings.app.form.inactivityLock', 136 id: 'settings.app.form.inactivityLock',
130 defaultMessage: '!!!Lock after inactivity', 137 defaultMessage: 'Lock after inactivity',
131 }, 138 },
132 scheduledDNDEnabled: { 139 scheduledDNDEnabled: {
133 id: 'settings.app.form.scheduledDNDEnabled', 140 id: 'settings.app.form.scheduledDNDEnabled',
134 defaultMessage: '!!!Enable scheduled Do-not-Disturb', 141 defaultMessage: 'Enable scheduled Do-not-Disturb',
135 }, 142 },
136 scheduledDNDStart: { 143 scheduledDNDStart: {
137 id: 'settings.app.form.scheduledDNDStart', 144 id: 'settings.app.form.scheduledDNDStart',
138 defaultMessage: '!!!From', 145 defaultMessage: 'From',
139 }, 146 },
140 scheduledDNDEnd: { 147 scheduledDNDEnd: {
141 id: 'settings.app.form.scheduledDNDEnd', 148 id: 'settings.app.form.scheduledDNDEnd',
142 defaultMessage: '!!!To', 149 defaultMessage: 'To',
143 }, 150 },
144 language: { 151 language: {
145 id: 'settings.app.form.language', 152 id: 'settings.app.form.language',
146 defaultMessage: '!!!Language', 153 defaultMessage: 'Language',
147 }, 154 },
148 darkMode: { 155 darkMode: {
149 id: 'settings.app.form.darkMode', 156 id: 'settings.app.form.darkMode',
150 defaultMessage: '!!!Dark Mode', 157 defaultMessage: 'Dark Mode',
151 }, 158 },
152 adaptableDarkMode: { 159 adaptableDarkMode: {
153 id: 'settings.app.form.adaptableDarkMode', 160 id: 'settings.app.form.adaptableDarkMode',
154 defaultMessage: '!!!Synchronize dark mode with my OS\'s dark mode setting', 161 defaultMessage: "Synchronize dark mode with my OS's dark mode setting",
155 }, 162 },
156 universalDarkMode: { 163 universalDarkMode: {
157 id: 'settings.app.form.universalDarkMode', 164 id: 'settings.app.form.universalDarkMode',
158 defaultMessage: '!!!Enable universal Dark Mode', 165 defaultMessage: 'Enable universal Dark Mode',
159 }, 166 },
160 serviceRibbonWidth: { 167 serviceRibbonWidth: {
161 id: 'settings.app.form.serviceRibbonWidth', 168 id: 'settings.app.form.serviceRibbonWidth',
162 defaultMessage: '!!!Sidebar width', 169 defaultMessage: 'Sidebar width',
163 }, 170 },
164 iconSize: { 171 iconSize: {
165 id: 'settings.app.form.iconSize', 172 id: 'settings.app.form.iconSize',
166 defaultMessage: '!!!Service icon size', 173 defaultMessage: 'Service icon size',
167 }, 174 },
168 useVerticalStyle: { 175 useVerticalStyle: {
169 id: 'settings.app.form.useVerticalStyle', 176 id: 'settings.app.form.useVerticalStyle',
170 defaultMessage: '!!!Use horizontal style', 177 defaultMessage: 'Use horizontal style',
171 }, 178 },
172 alwaysShowWorkspaces: { 179 alwaysShowWorkspaces: {
173 id: 'settings.app.form.alwaysShowWorkspaces', 180 id: 'settings.app.form.alwaysShowWorkspaces',
174 defaultMessage: '!!!Always show workspace drawer', 181 defaultMessage: 'Always show workspace drawer',
175 }, 182 },
176 accentColor: { 183 accentColor: {
177 id: 'settings.app.form.accentColor', 184 id: 'settings.app.form.accentColor',
178 defaultMessage: '!!!Accent color', 185 defaultMessage: 'Accent color',
179 }, 186 },
180 showDisabledServices: { 187 showDisabledServices: {
181 id: 'settings.app.form.showDisabledServices', 188 id: 'settings.app.form.showDisabledServices',
182 defaultMessage: '!!!Display disabled services tabs', 189 defaultMessage: 'Display disabled services tabs',
183 }, 190 },
184 showMessageBadgeWhenMuted: { 191 showMessageBadgeWhenMuted: {
185 id: 'settings.app.form.showMessagesBadgesWhenMuted', 192 id: 'settings.app.form.showMessagesBadgesWhenMuted',
186 defaultMessage: '!!!Show unread message badge when notifications are disabled', 193 defaultMessage: 'Show unread message badge when notifications are disabled',
187 }, 194 },
188 showDragArea: { 195 showDragArea: {
189 id: 'settings.app.form.showDragArea', 196 id: 'settings.app.form.showDragArea',
190 defaultMessage: '!!!Show draggable area on window', 197 defaultMessage: 'Show draggable area on window',
191 }, 198 },
192 enableSpellchecking: { 199 enableSpellchecking: {
193 id: 'settings.app.form.enableSpellchecking', 200 id: 'settings.app.form.enableSpellchecking',
194 defaultMessage: '!!!Enable spell checking', 201 defaultMessage: 'Enable spell checking',
195 }, 202 },
196 enableGPUAcceleration: { 203 enableGPUAcceleration: {
197 id: 'settings.app.form.enableGPUAcceleration', 204 id: 'settings.app.form.enableGPUAcceleration',
198 defaultMessage: '!!!Enable GPU Acceleration', 205 defaultMessage: 'Enable GPU Acceleration',
199 }, 206 },
200 beta: { 207 beta: {
201 id: 'settings.app.form.beta', 208 id: 'settings.app.form.beta',
202 defaultMessage: '!!!Include beta versions', 209 defaultMessage: 'Include beta versions',
203 }, 210 },
204 automaticUpdates: { 211 automaticUpdates: {
205 id: 'settings.app.form.automaticUpdates', 212 id: 'settings.app.form.automaticUpdates',
206 defaultMessage: '!!!Enable updates', 213 defaultMessage: 'Enable updates',
207 }, 214 },
208 enableTodos: { 215 enableTodos: {
209 id: 'settings.app.form.enableTodos', 216 id: 'settings.app.form.enableTodos',
210 defaultMessage: '!!!Enable Franz Todos', 217 defaultMessage: 'Enable Franz Todos',
211 }, 218 },
212 keepAllWorkspacesLoaded: { 219 keepAllWorkspacesLoaded: {
213 id: 'settings.app.form.keepAllWorkspacesLoaded', 220 id: 'settings.app.form.keepAllWorkspacesLoaded',
214 defaultMessage: '!!!Keep all workspaces loaded', 221 defaultMessage: 'Keep all workspaces loaded',
215 }, 222 },
216}); 223});
217 224
218export default @inject('stores', 'actions') @observer class EditSettingsScreen extends Component { 225@inject('stores', 'actions')
219 static contextTypes = { 226@observer
220 intl: intlShape, 227class EditSettingsScreen extends Component {
221 };
222
223 constructor(props) { 228 constructor(props) {
224 super(props); 229 super(props);
225 230
@@ -288,7 +293,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
288 useVerticalStyle: Boolean(settingsData.useVerticalStyle), 293 useVerticalStyle: Boolean(settingsData.useVerticalStyle),
289 alwaysShowWorkspaces: Boolean(settingsData.alwaysShowWorkspaces), 294 alwaysShowWorkspaces: Boolean(settingsData.alwaysShowWorkspaces),
290 accentColor: settingsData.accentColor, 295 accentColor: settingsData.accentColor,
291 showMessageBadgeWhenMuted: Boolean(settingsData.showMessageBadgeWhenMuted), 296 showMessageBadgeWhenMuted: Boolean(
297 settingsData.showMessageBadgeWhenMuted,
298 ),
292 showDragArea: Boolean(settingsData.showDragArea), 299 showDragArea: Boolean(settingsData.showDragArea),
293 enableSpellchecking: Boolean(settingsData.enableSpellchecking), 300 enableSpellchecking: Boolean(settingsData.enableSpellchecking),
294 spellcheckerLanguage: settingsData.spellcheckerLanguage, 301 spellcheckerLanguage: settingsData.spellcheckerLanguage,
@@ -309,24 +316,27 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
309 316
310 if (workspaces.isFeatureActive) { 317 if (workspaces.isFeatureActive) {
311 const { keepAllWorkspacesLoaded } = workspaces.settings; 318 const { keepAllWorkspacesLoaded } = workspaces.settings;
312 if (Boolean(keepAllWorkspacesLoaded) !== Boolean(settingsData.keepAllWorkspacesLoaded)) { 319 if (
320 Boolean(keepAllWorkspacesLoaded) !==
321 Boolean(settingsData.keepAllWorkspacesLoaded)
322 ) {
313 workspaceActions.toggleKeepAllWorkspacesLoadedSetting(); 323 workspaceActions.toggleKeepAllWorkspacesLoadedSetting();
314 } 324 }
315 } 325 }
316 326
317 if (todos.isFeatureActive) { 327 if (todos.isFeatureActive) {
318 const { isFeatureEnabledByUser } = todos.settings; 328 const { isFeatureEnabledByUser } = todos.settings;
319 if (Boolean(isFeatureEnabledByUser) !== Boolean(settingsData.enableTodos)) { 329 if (
330 Boolean(isFeatureEnabledByUser) !== Boolean(settingsData.enableTodos)
331 ) {
320 todosActions.toggleTodosFeatureVisibility(); 332 todosActions.toggleTodosFeatureVisibility();
321 } 333 }
322 } 334 }
323 } 335 }
324 336
325 prepareForm() { 337 prepareForm() {
326 const { 338 const { app, settings, user, todos, workspaces } = this.props.stores;
327 app, settings, user, todos, workspaces, 339 const { intl } = this.props;
328 } = this.props.stores;
329 const { intl } = this.context;
330 const { lockedPassword } = this.state; 340 const { lockedPassword } = this.state;
331 341
332 const locales = getSelectOptions({ 342 const locales = getSelectOptions({
@@ -370,7 +380,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
370 380
371 const spellcheckingLanguages = getSelectOptions({ 381 const spellcheckingLanguages = getSelectOptions({
372 locales: SPELLCHECKER_LOCALES, 382 locales: SPELLCHECKER_LOCALES,
373 automaticDetectionText: this.context.intl.formatMessage(globalMessages.spellcheckerAutomaticDetection), 383 automaticDetectionText: intl.formatMessage(
384 globalMessages.spellcheckerAutomaticDetection,
385 ),
374 }); 386 });
375 387
376 const config = { 388 const config = {
@@ -401,7 +413,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
401 default: DEFAULT_APP_SETTINGS.confirmOnQuit, 413 default: DEFAULT_APP_SETTINGS.confirmOnQuit,
402 }, 414 },
403 enableSystemTray: { 415 enableSystemTray: {
404 label: intl.formatMessage(isMac ? messages.enableMenuBar : messages.enableSystemTray), 416 label: intl.formatMessage(
417 isMac ? messages.enableMenuBar : messages.enableSystemTray,
418 ),
405 value: settings.all.app.enableSystemTray, 419 value: settings.all.app.enableSystemTray,
406 default: DEFAULT_APP_SETTINGS.enableSystemTray, 420 default: DEFAULT_APP_SETTINGS.enableSystemTray,
407 }, 421 },
@@ -637,23 +651,15 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
637 } 651 }
638 652
639 render() { 653 render() {
640 const { 654 const { app, todos, workspaces, services } = this.props.stores;
641 app,
642 todos,
643 workspaces,
644 services,
645 } = this.props.stores;
646 const { 655 const {
647 updateStatus, 656 updateStatus,
648 updateStatusTypes, 657 updateStatusTypes,
649 isClearingAllCache, 658 isClearingAllCache,
650 lockingFeatureEnabled, 659 lockingFeatureEnabled,
651 } = app; 660 } = app;
652 const { 661 const { checkForUpdates, installUpdate, clearAllCache } =
653 checkForUpdates, 662 this.props.actions.app;
654 installUpdate,
655 clearAllCache,
656 } = this.props.actions.app;
657 const form = this.prepareForm(); 663 const form = this.prepareForm();
658 664
659 return ( 665 return (
@@ -666,7 +672,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
666 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE} 672 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE}
667 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE} 673 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE}
668 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED} 674 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED}
669 onSubmit={(d) => this.onSubmit(d)} 675 onSubmit={d => this.onSubmit(d)}
670 getCacheSize={() => app.cacheSize} 676 getCacheSize={() => app.cacheSize}
671 isClearingAllCache={isClearingAllCache} 677 isClearingAllCache={isClearingAllCache}
672 onClearAllCache={clearAllCache} 678 onClearAllCache={clearAllCache}
@@ -675,9 +681,13 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
675 lockingFeatureEnabled={lockingFeatureEnabled} 681 lockingFeatureEnabled={lockingFeatureEnabled}
676 automaticUpdates={this.props.stores.settings.app.automaticUpdates} 682 automaticUpdates={this.props.stores.settings.app.automaticUpdates}
677 isDarkmodeEnabled={this.props.stores.settings.app.darkMode} 683 isDarkmodeEnabled={this.props.stores.settings.app.darkMode}
678 isAdaptableDarkModeEnabled={this.props.stores.settings.app.adaptableDarkMode} 684 isAdaptableDarkModeEnabled={
685 this.props.stores.settings.app.adaptableDarkMode
686 }
679 isTodosActivated={this.props.stores.todos.isFeatureEnabledByUser} 687 isTodosActivated={this.props.stores.todos.isFeatureEnabledByUser}
680 isUsingCustomTodoService={this.props.stores.todos.isUsingCustomTodoService} 688 isUsingCustomTodoService={
689 this.props.stores.todos.isUsingCustomTodoService
690 }
681 isNightlyEnabled={this.props.stores.settings.app.nightly} 691 isNightlyEnabled={this.props.stores.settings.app.nightly}
682 hasAddedTodosAsService={services.isTodosServiceAdded} 692 hasAddedTodosAsService={services.isTodosServiceAdded}
683 isOnline={app.isOnline} 693 isOnline={app.isOnline}
@@ -704,3 +714,5 @@ EditSettingsScreen.wrappedComponent.propTypes = {
704 workspaces: PropTypes.instanceOf(WorkspacesStore).isRequired, 714 workspaces: PropTypes.instanceOf(WorkspacesStore).isRequired,
705 }).isRequired, 715 }).isRequired,
706}; 716};
717
718export default injectIntl(EditSettingsScreen);
diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js
index 820b5e4d3..92ef94c29 100644
--- a/src/containers/settings/EditUserScreen.js
+++ b/src/containers/settings/EditUserScreen.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import Form from '../../lib/Form'; 7import Form from '../../lib/Form';
@@ -13,47 +13,45 @@ import { required, email, minLength } from '../../helpers/validation-helpers';
13const messages = defineMessages({ 13const messages = defineMessages({
14 firstname: { 14 firstname: {
15 id: 'settings.user.form.firstname', 15 id: 'settings.user.form.firstname',
16 defaultMessage: '!!!Firstname', 16 defaultMessage: 'Firstname',
17 }, 17 },
18 lastname: { 18 lastname: {
19 id: 'settings.user.form.lastname', 19 id: 'settings.user.form.lastname',
20 defaultMessage: '!!!Lastname', 20 defaultMessage: 'Lastname',
21 }, 21 },
22 email: { 22 email: {
23 id: 'settings.user.form.email', 23 id: 'settings.user.form.email',
24 defaultMessage: '!!!Email', 24 defaultMessage: 'Email',
25 }, 25 },
26 accountTypeLabel: { 26 accountTypeLabel: {
27 id: 'settings.user.form.accountType.label', 27 id: 'settings.user.form.accountType.label',
28 defaultMessage: '!!!Account type', 28 defaultMessage: 'Account type',
29 }, 29 },
30 accountTypeIndividual: { 30 accountTypeIndividual: {
31 id: 'settings.user.form.accountType.individual', 31 id: 'settings.user.form.accountType.individual',
32 defaultMessage: '!!!Individual', 32 defaultMessage: 'Individual',
33 }, 33 },
34 accountTypeNonProfit: { 34 accountTypeNonProfit: {
35 id: 'settings.user.form.accountType.non-profit', 35 id: 'settings.user.form.accountType.non-profit',
36 defaultMessage: '!!!Non-Profit', 36 defaultMessage: 'Non-Profit',
37 }, 37 },
38 accountTypeCompany: { 38 accountTypeCompany: {
39 id: 'settings.user.form.accountType.company', 39 id: 'settings.user.form.accountType.company',
40 defaultMessage: '!!!Company', 40 defaultMessage: 'Company',
41 }, 41 },
42 currentPassword: { 42 currentPassword: {
43 id: 'settings.user.form.currentPassword', 43 id: 'settings.user.form.currentPassword',
44 defaultMessage: '!!!Current password', 44 defaultMessage: 'Current password',
45 }, 45 },
46 newPassword: { 46 newPassword: {
47 id: 'settings.user.form.newPassword', 47 id: 'settings.user.form.newPassword',
48 defaultMessage: '!!!New password', 48 defaultMessage: 'New password',
49 }, 49 },
50}); 50});
51 51
52export default @inject('stores', 'actions') @observer class EditUserScreen extends Component { 52@inject('stores', 'actions')
53 static contextTypes = { 53@observer
54 intl: intlShape, 54class EditUserScreen extends Component {
55 };
56
57 componentWillUnmount() { 55 componentWillUnmount() {
58 this.props.actions.user.resetStatus(); 56 this.props.actions.user.resetStatus();
59 } 57 }
@@ -67,7 +65,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
67 } 65 }
68 66
69 prepareForm(user) { 67 prepareForm(user) {
70 const { intl } = this.context; 68 const { intl } = this.props;
71 69
72 const config = { 70 const config = {
73 fields: { 71 fields: {
@@ -93,16 +91,20 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
93 value: user.accountType, 91 value: user.accountType,
94 validators: [required], 92 validators: [required],
95 label: intl.formatMessage(messages.accountTypeLabel), 93 label: intl.formatMessage(messages.accountTypeLabel),
96 options: [{ 94 options: [
97 value: 'individual', 95 {
98 label: intl.formatMessage(messages.accountTypeIndividual), 96 value: 'individual',
99 }, { 97 label: intl.formatMessage(messages.accountTypeIndividual),
100 value: 'non-profit', 98 },
101 label: intl.formatMessage(messages.accountTypeNonProfit), 99 {
102 }, { 100 value: 'non-profit',
103 value: 'company', 101 label: intl.formatMessage(messages.accountTypeNonProfit),
104 label: intl.formatMessage(messages.accountTypeCompany), 102 },
105 }], 103 {
104 value: 'company',
105 label: intl.formatMessage(messages.accountTypeCompany),
106 },
107 ],
106 }, 108 },
107 organization: { 109 organization: {
108 label: intl.formatMessage(messages.accountTypeCompany), 110 label: intl.formatMessage(messages.accountTypeCompany),
@@ -129,7 +131,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
129 const { user } = this.props.stores; 131 const { user } = this.props.stores;
130 132
131 if (user.getUserInfoRequest.isExecuting) { 133 if (user.getUserInfoRequest.isExecuting) {
132 return (<div>Loading...</div>); 134 return <div>Loading...</div>;
133 } 135 }
134 136
135 const form = this.prepareForm(user.data); 137 const form = this.prepareForm(user.data);
@@ -141,7 +143,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
141 status={user.actionStatus} 143 status={user.actionStatus}
142 form={form} 144 form={form}
143 isSaving={user.updateUserInfoRequest.isExecuting} 145 isSaving={user.updateUserInfoRequest.isExecuting}
144 onSubmit={(d) => this.onSubmit(d)} 146 onSubmit={d => this.onSubmit(d)}
145 /> 147 />
146 </ErrorBoundary> 148 </ErrorBoundary>
147 ); 149 );
@@ -156,3 +158,5 @@ EditUserScreen.wrappedComponent.propTypes = {
156 user: PropTypes.instanceOf(UserStore).isRequired, 158 user: PropTypes.instanceOf(UserStore).isRequired,
157 }).isRequired, 159 }).isRequired,
158}; 160};
161
162export default injectIntl(EditUserScreen);
diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js
index 4fdaef08b..f17f6390c 100644
--- a/src/containers/settings/InviteScreen.js
+++ b/src/containers/settings/InviteScreen.js
@@ -6,7 +6,9 @@ import Invite from '../../components/auth/Invite';
6import ErrorBoundary from '../../components/util/ErrorBoundary'; 6import ErrorBoundary from '../../components/util/ErrorBoundary';
7import UserStore from '../../stores/UserStore'; 7import UserStore from '../../stores/UserStore';
8 8
9export default @inject('stores', 'actions') @observer class InviteScreen extends Component { 9@inject('stores', 'actions')
10@observer
11class InviteScreen extends Component {
10 componentWillUnmount() { 12 componentWillUnmount() {
11 this.props.stores.user.inviteRequest.reset(); 13 this.props.stores.user.inviteRequest.reset();
12 } 14 }
@@ -20,7 +22,9 @@ export default @inject('stores', 'actions') @observer class InviteScreen extends
20 <Invite 22 <Invite
21 onSubmit={actions.user.invite} 23 onSubmit={actions.user.invite}
22 isLoadingInvite={user.inviteRequest.isExecuting} 24 isLoadingInvite={user.inviteRequest.isExecuting}
23 isInviteSuccessful={user.inviteRequest.wasExecuted && !user.inviteRequest.isError} 25 isInviteSuccessful={
26 user.inviteRequest.wasExecuted && !user.inviteRequest.isError
27 }
24 embed 28 embed
25 /> 29 />
26 </ErrorBoundary> 30 </ErrorBoundary>
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js
index 784052bbe..06ddabe4c 100644
--- a/src/containers/settings/RecipesScreen.js
+++ b/src/containers/settings/RecipesScreen.js
@@ -18,7 +18,9 @@ import RecipePreview from '../../models/RecipePreview';
18import AppStore from '../../stores/AppStore'; 18import AppStore from '../../stores/AppStore';
19import { openPath } from '../../helpers/url-helpers'; 19import { openPath } from '../../helpers/url-helpers';
20 20
21export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { 21@inject('stores', 'actions')
22@observer
23class RecipesScreen extends Component {
22 static propTypes = { 24 static propTypes = {
23 params: PropTypes.shape({ 25 params: PropTypes.shape({
24 filter: PropTypes.string, 26 filter: PropTypes.string,
@@ -75,25 +77,32 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
75 } 77 }
76 78
77 _sortByName(recipe1, recipe2) { 79 _sortByName(recipe1, recipe2) {
78 if (recipe1.name.toLowerCase() < recipe2.name.toLowerCase()) { return -1; } 80 if (recipe1.name.toLowerCase() < recipe2.name.toLowerCase()) {
79 if (recipe1.name.toLowerCase() > recipe2.name.toLowerCase()) { return 1; } 81 return -1;
82 }
83 if (recipe1.name.toLowerCase() > recipe2.name.toLowerCase()) {
84 return 1;
85 }
80 return 0; 86 return 0;
81 } 87 }
82 88
83 prepareRecipes(recipes) { 89 prepareRecipes(recipes) {
84 return recipes 90 return (
85 // Filter out duplicate recipes 91 recipes
86 .filter((recipe, index, self) => { 92 // Filter out duplicate recipes
87 const ids = self.map((rec) => rec.id); 93 .filter((recipe, index, self) => {
88 return ids.indexOf(recipe.id) === index; 94 const ids = self.map(rec => rec.id);
89 95 return ids.indexOf(recipe.id) === index;
90 // Sort alphabetically 96
91 }).sort(this._sortByName); 97 // Sort alphabetically
98 })
99 .sort(this._sortByName)
100 );
92 } 101 }
93 102
94 // Create an array of RecipePreviews from an array of recipe objects 103 // Create an array of RecipePreviews from an array of recipe objects
95 createPreviews(recipes) { 104 createPreviews(recipes) {
96 return recipes.map((recipe) => new RecipePreview(recipe)); 105 return recipes.map(recipe => new RecipePreview(recipe));
97 } 106 }
98 107
99 resetSearch() { 108 resetSearch() {
@@ -101,16 +110,9 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
101 } 110 }
102 111
103 render() { 112 render() {
104 const { 113 const { recipePreviews, recipes, services } = this.props.stores;
105 recipePreviews,
106 recipes,
107 services,
108 } = this.props.stores;
109 114
110 const { 115 const { app: appActions, service: serviceActions } = this.props.actions;
111 app: appActions,
112 service: serviceActions,
113 } = this.props.actions;
114 116
115 const { filter } = { filter: 'all', ...this.props.params }; 117 const { filter } = { filter: 'all', ...this.props.params };
116 let recipeFilter; 118 let recipeFilter;
@@ -125,21 +127,33 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
125 } 127 }
126 recipeFilter = recipeFilter.sort(this._sortByName); 128 recipeFilter = recipeFilter.sort(this._sortByName);
127 129
128 const allRecipes = this.state.needle ? this.prepareRecipes([ 130 const allRecipes = this.state.needle
129 // All search recipes from server 131 ? this.prepareRecipes([
130 ...recipePreviews.searchResults, 132 // All search recipes from server
131 // All search recipes from local recipes 133 ...recipePreviews.searchResults,
132 ...this.createPreviews( 134 // All search recipes from local recipes
133 this.customRecipes 135 ...this.createPreviews(
134 .filter((service) => service.name.toLowerCase().includes(this.state.needle.toLowerCase()) || (service.aliases || []).some(alias => alias.toLowerCase().includes(this.state.needle.toLowerCase()))), 136 this.customRecipes.filter(
135 ), 137 service =>
136 ]).sort(this._sortByName) : recipeFilter; 138 service.name
137 139 .toLowerCase()
138 const customWebsiteRecipe = recipePreviews.all.find((service) => service.id === CUSTOM_WEBSITE_RECIPE_ID); 140 .includes(this.state.needle.toLowerCase()) ||
141 (service.aliases || []).some(alias =>
142 alias.toLowerCase().includes(this.state.needle.toLowerCase()),
143 ),
144 ),
145 ),
146 ]).sort(this._sortByName)
147 : recipeFilter;
148
149 const customWebsiteRecipe = recipePreviews.all.find(
150 service => service.id === CUSTOM_WEBSITE_RECIPE_ID,
151 );
139 152
140 const isLoading = recipePreviews.allRecipePreviewsRequest.isExecuting 153 const isLoading =
141 || recipes.installRecipeRequest.isExecuting 154 recipePreviews.allRecipePreviewsRequest.isExecuting ||
142 || recipePreviews.searchRecipePreviewsRequest.isExecuting; 155 recipes.installRecipeRequest.isExecuting ||
156 recipePreviews.searchRecipePreviewsRequest.isExecuting;
143 157
144 const recipeDirectory = userDataRecipesPath('dev'); 158 const recipeDirectory = userDataRecipesPath('dev');
145 159
@@ -151,14 +165,16 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
151 isLoading={isLoading} 165 isLoading={isLoading}
152 addedServiceCount={services.all.length} 166 addedServiceCount={services.all.length}
153 showAddServiceInterface={serviceActions.showAddServiceInterface} 167 showAddServiceInterface={serviceActions.showAddServiceInterface}
154 searchRecipes={(e) => this.searchRecipes(e)} 168 searchRecipes={e => this.searchRecipes(e)}
155 resetSearch={() => this.resetSearch()} 169 resetSearch={() => this.resetSearch()}
156 searchNeedle={this.state.needle} 170 searchNeedle={this.state.needle}
157 serviceStatus={services.actionStatus} 171 serviceStatus={services.actionStatus}
158 recipeFilter={filter} 172 recipeFilter={filter}
159 recipeDirectory={recipeDirectory} 173 recipeDirectory={recipeDirectory}
160 openRecipeDirectory={() => openPath(recipeDirectory)} 174 openRecipeDirectory={() => openPath(recipeDirectory)}
161 openDevDocs={() => appActions.openExternalUrl({ url: FRANZ_DEV_DOCS })} 175 openDevDocs={() =>
176 appActions.openExternalUrl({ url: FRANZ_DEV_DOCS })
177 }
162 /> 178 />
163 </ErrorBoundary> 179 </ErrorBoundary>
164 ); 180 );
@@ -180,3 +196,5 @@ RecipesScreen.wrappedComponent.propTypes = {
180 }).isRequired, 196 }).isRequired,
181 }).isRequired, 197 }).isRequired,
182}; 198};
199
200export default RecipesScreen;
diff --git a/src/containers/settings/ServicesScreen.js b/src/containers/settings/ServicesScreen.js
index eb2b1bcb5..c9dfc68d0 100644
--- a/src/containers/settings/ServicesScreen.js
+++ b/src/containers/settings/ServicesScreen.js
@@ -10,7 +10,9 @@ import ServiceStore from '../../stores/ServicesStore';
10import ServicesDashboard from '../../components/settings/services/ServicesDashboard'; 10import ServicesDashboard from '../../components/settings/services/ServicesDashboard';
11import ErrorBoundary from '../../components/util/ErrorBoundary'; 11import ErrorBoundary from '../../components/util/ErrorBoundary';
12 12
13export default @inject('stores', 'actions') @observer class ServicesScreen extends Component { 13@inject('stores', 'actions')
14@observer
15class ServicesScreen extends Component {
14 componentWillUnmount() { 16 componentWillUnmount() {
15 this.props.actions.service.resetFilter(); 17 this.props.actions.service.resetFilter();
16 this.props.actions.service.resetStatus(); 18 this.props.actions.service.resetStatus();
@@ -23,11 +25,7 @@ export default @inject('stores', 'actions') @observer class ServicesScreen exten
23 25
24 render() { 26 render() {
25 const { user, services, router } = this.props.stores; 27 const { user, services, router } = this.props.stores;
26 const { 28 const { toggleService, filter, resetFilter } = this.props.actions.service;
27 toggleService,
28 filter,
29 resetFilter,
30 } = this.props.actions.service;
31 const isLoading = services.allServicesRequest.isExecuting; 29 const isLoading = services.allServicesRequest.isExecuting;
32 30
33 let allServices = services.all; 31 let allServices = services.all;
@@ -47,7 +45,10 @@ export default @inject('stores', 'actions') @observer class ServicesScreen exten
47 filterServices={filter} 45 filterServices={filter}
48 resetFilter={resetFilter} 46 resetFilter={resetFilter}
49 goTo={router.push} 47 goTo={router.push}
50 servicesRequestFailed={services.allServicesRequest.wasExecuted && services.allServicesRequest.isError} 48 servicesRequestFailed={
49 services.allServicesRequest.wasExecuted &&
50 services.allServicesRequest.isError
51 }
51 retryServicesRequest={() => services.allServicesRequest.reload()} 52 retryServicesRequest={() => services.allServicesRequest.reload()}
52 searchNeedle={services.filterNeedle} 53 searchNeedle={services.filterNeedle}
53 /> 54 />
@@ -66,3 +67,5 @@ ServicesScreen.wrappedComponent.propTypes = {
66 service: PropTypes.instanceOf(ServiceStore).isRequired, 67 service: PropTypes.instanceOf(ServiceStore).isRequired,
67 }).isRequired, 68 }).isRequired,
68}; 69};
70
71export default ServicesScreen;
diff --git a/src/containers/settings/SettingsWindow.js b/src/containers/settings/SettingsWindow.js
index 9bb64b6fe..58e73f2f3 100644
--- a/src/containers/settings/SettingsWindow.js
+++ b/src/containers/settings/SettingsWindow.js
@@ -11,7 +11,9 @@ import ErrorBoundary from '../../components/util/ErrorBoundary';
11import { workspaceStore } from '../../features/workspaces'; 11import { workspaceStore } from '../../features/workspaces';
12import UIStore from '../../stores/UIStore'; 12import UIStore from '../../stores/UIStore';
13 13
14export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { 14@inject('stores', 'actions')
15@observer
16class SettingsContainer extends Component {
15 portalRoot = document.querySelector('#portalContainer'); 17 portalRoot = document.querySelector('#portalContainer');
16 18
17 el = document.createElement('div'); 19 el = document.createElement('div');
@@ -36,16 +38,11 @@ export default @inject('stores', 'actions') @observer class SettingsContainer ex
36 ); 38 );
37 39
38 return ReactDOM.createPortal( 40 return ReactDOM.createPortal(
39 ( 41 <ErrorBoundary>
40 <ErrorBoundary> 42 <Layout navigation={navigation} closeSettings={closeSettings}>
41 <Layout 43 {children}
42 navigation={navigation} 44 </Layout>
43 closeSettings={closeSettings} 45 </ErrorBoundary>,
44 >
45 {children}
46 </Layout>
47 </ErrorBoundary>
48 ),
49 this.el, 46 this.el,
50 ); 47 );
51 } 48 }
@@ -60,3 +57,5 @@ SettingsContainer.wrappedComponent.propTypes = {
60 ui: PropTypes.instanceOf(UIStore).isRequired, 57 ui: PropTypes.instanceOf(UIStore).isRequired,
61 }).isRequired, 58 }).isRequired,
62}; 59};
60
61export default SettingsContainer;
diff --git a/src/containers/settings/SupportScreen.js b/src/containers/settings/SupportScreen.js
index 7d3b22f19..646f672ce 100644
--- a/src/containers/settings/SupportScreen.js
+++ b/src/containers/settings/SupportScreen.js
@@ -6,7 +6,8 @@ import SupportFerdi from '../../components/settings/supportFerdi/SupportFerdiDas
6import ErrorBoundary from '../../components/util/ErrorBoundary'; 6import ErrorBoundary from '../../components/util/ErrorBoundary';
7import AppStore from '../../stores/AppStore'; 7import AppStore from '../../stores/AppStore';
8 8
9export default @inject('actions') class SupportScreen extends Component { 9@inject('actions')
10class SupportScreen extends Component {
10 constructor(props) { 11 constructor(props) {
11 super(props); 12 super(props);
12 13
@@ -20,9 +21,7 @@ export default @inject('actions') class SupportScreen extends Component {
20 render() { 21 render() {
21 return ( 22 return (
22 <ErrorBoundary> 23 <ErrorBoundary>
23 <SupportFerdi 24 <SupportFerdi openLink={this.openLink} />
24 openLink={this.openLink}
25 />
26 </ErrorBoundary> 25 </ErrorBoundary>
27 ); 26 );
28 } 27 }
@@ -33,3 +32,5 @@ SupportScreen.wrappedComponent.propTypes = {
33 app: PropTypes.instanceOf(AppStore).isRequired, 32 app: PropTypes.instanceOf(AppStore).isRequired,
34 }).isRequired, 33 }).isRequired,
35}; 34};
35
36export default SupportScreen;
diff --git a/src/containers/settings/TeamScreen.js b/src/containers/settings/TeamScreen.js
index 10c2e36ef..ea447469b 100644
--- a/src/containers/settings/TeamScreen.js
+++ b/src/containers/settings/TeamScreen.js
@@ -10,7 +10,9 @@ import TeamDashboard from '../../components/settings/team/TeamDashboard';
10import ErrorBoundary from '../../components/util/ErrorBoundary'; 10import ErrorBoundary from '../../components/util/ErrorBoundary';
11import { DEV_API_FRANZ_WEBSITE } from '../../config'; 11import { DEV_API_FRANZ_WEBSITE } from '../../config';
12 12
13export default @inject('stores', 'actions') @observer class TeamScreen extends Component { 13@inject('stores', 'actions')
14@observer
15class TeamScreen extends Component {
14 handleWebsiteLink(route) { 16 handleWebsiteLink(route) {
15 const { actions, stores } = this.props; 17 const { actions, stores } = this.props;
16 18
@@ -29,7 +31,10 @@ export default @inject('stores', 'actions') @observer class TeamScreen extends C
29 <ErrorBoundary> 31 <ErrorBoundary>
30 <TeamDashboard 32 <TeamDashboard
31 isLoading={isLoadingUserInfo} 33 isLoading={isLoadingUserInfo}
32 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} 34 userInfoRequestFailed={
35 user.getUserInfoRequest.wasExecuted &&
36 user.getUserInfoRequest.isError
37 }
33 retryUserInfoRequest={() => this.reloadData()} 38 retryUserInfoRequest={() => this.reloadData()}
34 openTeamManagement={() => this.handleWebsiteLink('/user/team')} 39 openTeamManagement={() => this.handleWebsiteLink('/user/team')}
35 server={server} 40 server={server}
@@ -50,3 +55,5 @@ TeamScreen.wrappedComponent.propTypes = {
50 user: PropTypes.instanceOf(UserStore).isRequired, 55 user: PropTypes.instanceOf(UserStore).isRequired,
51 }).isRequired, 56 }).isRequired,
52}; 57};
58
59export default TeamScreen;