aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/settings/services
diff options
context:
space:
mode:
authorLibravatar Vijay A <vraravam@users.noreply.github.com>2021-10-06 22:59:03 +0530
committerLibravatar Vijay A <vraravam@users.noreply.github.com>2021-10-06 22:59:03 +0530
commit5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216 (patch)
tree10cea6c608baea3481595ed9eb7be63ef03ca6c4 /src/components/settings/services
parentBumped up version to: 5.6.2 (hotfix) (diff)
parent5.6.3-nightly.25 [skip ci] (diff)
downloadferdium-app-5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216.tar.gz
ferdium-app-5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216.tar.zst
ferdium-app-5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216.zip
Merge branch 'nightly' into release
Diffstat (limited to 'src/components/settings/services')
-rw-r--r--src/components/settings/services/EditServiceForm.js173
-rw-r--r--src/components/settings/services/ServiceError.js26
-rw-r--r--src/components/settings/services/ServiceItem.js48
-rw-r--r--src/components/settings/services/ServicesDashboard.js56
4 files changed, 157 insertions, 146 deletions
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index c41cdd56a..22089ec45 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -2,13 +2,14 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { Link } from 'react-router'; 4import { Link } from 'react-router';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import normalizeUrl from 'normalize-url'; 6import normalizeUrl from 'normalize-url';
7 7
8import Form from '../../../lib/Form'; 8import Form from '../../../lib/Form';
9import Recipe from '../../../models/Recipe'; 9import Recipe from '../../../models/Recipe';
10import Service from '../../../models/Service'; 10import Service from '../../../models/Service';
11import Tabs, { TabItem } from '../../ui/Tabs'; 11import Tabs from '../../ui/Tabs/Tabs';
12import { TabItem } from '../../ui/Tabs/TabItem';
12import Input from '../../ui/Input'; 13import Input from '../../ui/Input';
13import Toggle from '../../ui/Toggle'; 14import Toggle from '../../ui/Toggle';
14import Slider from '../../ui/Slider'; 15import Slider from '../../ui/Slider';
@@ -22,111 +23,117 @@ import globalMessages from '../../../i18n/globalMessages';
22const messages = defineMessages({ 23const messages = defineMessages({
23 saveService: { 24 saveService: {
24 id: 'settings.service.form.saveButton', 25 id: 'settings.service.form.saveButton',
25 defaultMessage: '!!!Save service', 26 defaultMessage: 'Save service',
26 }, 27 },
27 deleteService: { 28 deleteService: {
28 id: 'settings.service.form.deleteButton', 29 id: 'settings.service.form.deleteButton',
29 defaultMessage: '!!!Delete Service', 30 defaultMessage: 'Delete service',
30 }, 31 },
31 openDarkmodeCss: { 32 openDarkmodeCss: {
32 id: 'settings.service.form.openDarkmodeCss', 33 id: 'settings.service.form.openDarkmodeCss',
33 defaultMessage: '!!!Open darkmode.css', 34 defaultMessage: 'Open darkmode.css',
34 }, 35 },
35 openUserCss: { 36 openUserCss: {
36 id: 'settings.service.form.openUserCss', 37 id: 'settings.service.form.openUserCss',
37 defaultMessage: '!!!Open user.css', 38 defaultMessage: 'Open user.css',
38 }, 39 },
39 openUserJs: { 40 openUserJs: {
40 id: 'settings.service.form.openUserJs', 41 id: 'settings.service.form.openUserJs',
41 defaultMessage: '!!!Open user.js', 42 defaultMessage: 'Open user.js',
42 }, 43 },
43 recipeFileInfo: { 44 recipeFileInfo: {
44 id: 'settings.service.form.recipeFileInfo', 45 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.', 46 defaultMessage:
47 '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 }, 48 },
47 availableServices: { 49 availableServices: {
48 id: 'settings.service.form.availableServices', 50 id: 'settings.service.form.availableServices',
49 defaultMessage: '!!!Available services', 51 defaultMessage: 'Available services',
50 }, 52 },
51 yourServices: { 53 yourServices: {
52 id: 'settings.service.form.yourServices', 54 id: 'settings.service.form.yourServices',
53 defaultMessage: '!!!Your services', 55 defaultMessage: 'Your services',
54 }, 56 },
55 addServiceHeadline: { 57 addServiceHeadline: {
56 id: 'settings.service.form.addServiceHeadline', 58 id: 'settings.service.form.addServiceHeadline',
57 defaultMessage: '!!!Add {name}', 59 defaultMessage: 'Add {name}',
58 }, 60 },
59 editServiceHeadline: { 61 editServiceHeadline: {
60 id: 'settings.service.form.editServiceHeadline', 62 id: 'settings.service.form.editServiceHeadline',
61 defaultMessage: '!!!Edit {name}', 63 defaultMessage: 'Edit {name}',
62 }, 64 },
63 tabHosted: { 65 tabHosted: {
64 id: 'settings.service.form.tabHosted', 66 id: 'settings.service.form.tabHosted',
65 defaultMessage: '!!!Hosted', 67 defaultMessage: 'Hosted',
66 }, 68 },
67 tabOnPremise: { 69 tabOnPremise: {
68 id: 'settings.service.form.tabOnPremise', 70 id: 'settings.service.form.tabOnPremise',
69 defaultMessage: '!!!Self hosted ⭐️', 71 defaultMessage: 'Self hosted ⭐️',
70 }, 72 },
71 useHostedService: { 73 useHostedService: {
72 id: 'settings.service.form.useHostedService', 74 id: 'settings.service.form.useHostedService',
73 defaultMessage: '!!!Use the hosted {name} service.', 75 defaultMessage: 'Use the hosted {name} service.',
74 }, 76 },
75 customUrlValidationError: { 77 customUrlValidationError: {
76 id: 'settings.service.form.customUrlValidationError', 78 id: 'settings.service.form.customUrlValidationError',
77 defaultMessage: '!!!Could not validate custom {name} server.', 79 defaultMessage: 'Could not validate custom {name} server.',
78 }, 80 },
79 indirectMessageInfo: { 81 indirectMessageInfo: {
80 id: 'settings.service.form.indirectMessageInfo', 82 id: 'settings.service.form.indirectMessageInfo',
81 defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', 83 defaultMessage:
84 'You will be notified about all new messages in a channel, not just @username, @channel, @here, ...',
82 }, 85 },
83 isMutedInfo: { 86 isMutedInfo: {
84 id: 'settings.service.form.isMutedInfo', 87 id: 'settings.service.form.isMutedInfo',
85 defaultMessage: '!!!When disabled, all notification sounds and audio playback are muted', 88 defaultMessage:
89 'When disabled, all notification sounds and audio playback are muted',
86 }, 90 },
87 isHibernationEnabledInfo: { 91 isHibernationEnabledInfo: {
88 id: 'settings.service.form.isHibernatedEnabledInfo', 92 id: 'settings.service.form.isHibernatedEnabledInfo',
89 defaultMessage: '!!!When enabled, a service will be shut down after a period of time to save system resources.', 93 defaultMessage:
94 'When enabled, a service will be shut down after a period of time to save system resources.',
90 }, 95 },
91 headlineNotifications: { 96 headlineNotifications: {
92 id: 'settings.service.form.headlineNotifications', 97 id: 'settings.service.form.headlineNotifications',
93 defaultMessage: '!!!Notifications', 98 defaultMessage: 'Notifications',
94 }, 99 },
95 headlineBadges: { 100 headlineBadges: {
96 id: 'settings.service.form.headlineBadges', 101 id: 'settings.service.form.headlineBadges',
97 defaultMessage: '!!!Unread message badges', 102 defaultMessage: 'Unread message badges',
98 }, 103 },
99 headlineGeneral: { 104 headlineGeneral: {
100 id: 'settings.service.form.headlineGeneral', 105 id: 'settings.service.form.headlineGeneral',
101 defaultMessage: '!!!General', 106 defaultMessage: 'General',
102 }, 107 },
103 headlineDarkReaderSettings: { 108 headlineDarkReaderSettings: {
104 id: 'settings.service.form.headlineDarkReaderSettings', 109 id: 'settings.service.form.headlineDarkReaderSettings',
105 defaultMessage: '!!!Dark Reader Settings', 110 defaultMessage: 'Dark Reader Settings',
106 }, 111 },
107 iconDelete: { 112 iconDelete: {
108 id: 'settings.service.form.iconDelete', 113 id: 'settings.service.form.iconDelete',
109 defaultMessage: '!!!Delete', 114 defaultMessage: 'Delete',
110 }, 115 },
111 iconUpload: { 116 iconUpload: {
112 id: 'settings.service.form.iconUpload', 117 id: 'settings.service.form.iconUpload',
113 defaultMessage: '!!!Drop your image, or click here', 118 defaultMessage: 'Drop your image, or click here',
114 }, 119 },
115 headlineProxy: { 120 headlineProxy: {
116 id: 'settings.service.form.proxy.headline', 121 id: 'settings.service.form.proxy.headline',
117 defaultMessage: '!!!HTTP/HTTPS Proxy Settings', 122 defaultMessage: 'HTTP/HTTPS Proxy Settings',
118 }, 123 },
119 proxyRestartInfo: { 124 proxyRestartInfo: {
120 id: 'settings.service.form.proxy.restartInfo', 125 id: 'settings.service.form.proxy.restartInfo',
121 defaultMessage: '!!!Please restart Ferdi after changing proxy Settings.', 126 defaultMessage: 'Please restart Ferdi after changing proxy Settings.',
122 }, 127 },
123 proxyInfo: { 128 proxyInfo: {
124 id: 'settings.service.form.proxy.info', 129 id: 'settings.service.form.proxy.info',
125 defaultMessage: '!!!Proxy settings will not be synchronized with the Ferdi servers.', 130 defaultMessage:
131 'Proxy settings will not be synchronized with the Ferdi servers.',
126 }, 132 },
127}); 133});
128 134
129export default @observer class EditServiceForm extends Component { 135@observer
136class EditServiceForm extends Component {
130 static propTypes = { 137 static propTypes = {
131 recipe: PropTypes.instanceOf(Recipe).isRequired, 138 recipe: PropTypes.instanceOf(Recipe).isRequired,
132 service(props, propName) { 139 service(props, propName) {
@@ -151,20 +158,16 @@ export default @observer class EditServiceForm extends Component {
151 service: {}, 158 service: {},
152 }; 159 };
153 160
154 static contextTypes = {
155 intl: intlShape,
156 };
157
158 state = { 161 state = {
159 isValidatingCustomUrl: false, 162 isValidatingCustomUrl: false,
160 } 163 };
161 164
162 submit(e) { 165 submit(e) {
163 const { recipe } = this.props; 166 const { recipe } = this.props;
164 167
165 e.preventDefault(); 168 e.preventDefault();
166 this.props.form.submit({ 169 this.props.form.submit({
167 onSuccess: async (form) => { 170 onSuccess: async form => {
168 const values = form.values(); 171 const values = form.values();
169 let isValid = true; 172 let isValid = true;
170 173
@@ -176,10 +179,13 @@ export default @observer class EditServiceForm extends Component {
176 if (recipe.validateUrl && values.customUrl) { 179 if (recipe.validateUrl && values.customUrl) {
177 this.setState({ isValidatingCustomUrl: true }); 180 this.setState({ isValidatingCustomUrl: true });
178 try { 181 try {
179 values.customUrl = normalizeUrl(values.customUrl, { stripWWW: false, removeTrailingSlash: false }); 182 values.customUrl = normalizeUrl(values.customUrl, {
183 stripWWW: false,
184 removeTrailingSlash: false,
185 });
180 isValid = await recipe.validateUrl(values.customUrl); 186 isValid = await recipe.validateUrl(values.customUrl);
181 } catch (err) { 187 } catch (error) {
182 console.warn('ValidateURL', err); 188 console.warn('ValidateURL', error);
183 isValid = false; 189 isValid = false;
184 } 190 }
185 } 191 }
@@ -208,7 +214,7 @@ export default @observer class EditServiceForm extends Component {
208 openRecipeFile, 214 openRecipeFile,
209 isProxyFeatureEnabled, 215 isProxyFeatureEnabled,
210 } = this.props; 216 } = this.props;
211 const { intl } = this.context; 217 const { intl } = this.props;
212 218
213 const { isValidatingCustomUrl } = this.state; 219 const { isValidatingCustomUrl } = this.state;
214 220
@@ -236,7 +242,8 @@ export default @observer class EditServiceForm extends Component {
236 activeTabIndex = 2; 242 activeTabIndex = 2;
237 } 243 }
238 244
239 const requiresUserInput = !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); 245 const requiresUserInput =
246 !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl);
240 247
241 return ( 248 return (
242 <div className="settings__main"> 249 <div className="settings__main">
@@ -254,29 +261,27 @@ export default @observer class EditServiceForm extends Component {
254 </span> 261 </span>
255 <span className="separator" /> 262 <span className="separator" />
256 <span className="settings__header-item"> 263 <span className="settings__header-item">
257 {action === 'add' ? ( 264 {action === 'add'
258 intl.formatMessage(messages.addServiceHeadline, { 265 ? intl.formatMessage(messages.addServiceHeadline, {
259 name: recipe.name, 266 name: recipe.name,
260 }) 267 })
261 ) : ( 268 : intl.formatMessage(messages.editServiceHeadline, {
262 intl.formatMessage(messages.editServiceHeadline, { 269 name: service.name !== '' ? service.name : recipe.name,
263 name: service.name !== '' ? service.name : recipe.name, 270 })}
264 })
265 )}
266 </span> 271 </span>
267 </div> 272 </div>
268 <div className="settings__body"> 273 <div className="settings__body">
269 <form onSubmit={(e) => this.submit(e)} id="form"> 274 <form onSubmit={e => this.submit(e)} id="form">
270 <div className="service-name"> 275 <div className="service-name">
271 <Input field={form.$('name')} focus /> 276 <Input field={form.$('name')} focus />
272 </div> 277 </div>
273 {(recipe.hasTeamId || recipe.hasCustomUrl) && ( 278 {(recipe.hasTeamId || recipe.hasCustomUrl) && (
274 <Tabs 279 <Tabs active={activeTabIndex}>
275 active={activeTabIndex}
276 >
277 {recipe.hasHostedOption && ( 280 {recipe.hasHostedOption && (
278 <TabItem title={recipe.name}> 281 <TabItem title={recipe.name}>
279 {intl.formatMessage(messages.useHostedService, { name: recipe.name })} 282 {intl.formatMessage(messages.useHostedService, {
283 name: recipe.name,
284 })}
280 </TabItem> 285 </TabItem>
281 )} 286 )}
282 {recipe.hasTeamId && ( 287 {recipe.hasTeamId && (
@@ -293,7 +298,9 @@ export default @observer class EditServiceForm extends Component {
293 <Input field={form.$('customUrl')} /> 298 <Input field={form.$('customUrl')} />
294 {form.error === 'url-validation-error' && ( 299 {form.error === 'url-validation-error' && (
295 <p className="franz-form__error"> 300 <p className="franz-form__error">
296 {intl.formatMessage(messages.customUrlValidationError, { name: recipe.name })} 301 {intl.formatMessage(messages.customUrlValidationError, {
302 name: recipe.name,
303 })}
297 </p> 304 </p>
298 )} 305 )}
299 </TabItem> 306 </TabItem>
@@ -326,13 +333,19 @@ export default @observer class EditServiceForm extends Component {
326 <div className="settings__settings-group"> 333 <div className="settings__settings-group">
327 <h3>{intl.formatMessage(messages.headlineBadges)}</h3> 334 <h3>{intl.formatMessage(messages.headlineBadges)}</h3>
328 <Toggle field={form.$('isBadgeEnabled')} /> 335 <Toggle field={form.$('isBadgeEnabled')} />
329 {recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && ( 336 {recipe.hasIndirectMessages &&
330 <> 337 form.$('isBadgeEnabled').value && (
331 <Toggle field={form.$('isIndirectMessageBadgeEnabled')} /> 338 <>
332 <p className="settings__help indented__help"> 339 <Toggle
333 {intl.formatMessage(messages.indirectMessageInfo)} 340 field={form.$('isIndirectMessageBadgeEnabled')}
334 </p> 341 />
335 </> 342 <p className="settings__help indented__help">
343 {intl.formatMessage(messages.indirectMessageInfo)}
344 </p>
345 </>
346 )}
347 {recipe.allowFavoritesDelineationInUnreadCount && (
348 <Toggle field={form.$('onlyShowFavoritesInUnreadCount')} />
336 )} 349 )}
337 </div> 350 </div>
338 351
@@ -344,15 +357,18 @@ export default @observer class EditServiceForm extends Component {
344 {intl.formatMessage(messages.isHibernationEnabledInfo)} 357 {intl.formatMessage(messages.isHibernationEnabledInfo)}
345 </p> 358 </p>
346 <Toggle field={form.$('isDarkModeEnabled')} /> 359 <Toggle field={form.$('isDarkModeEnabled')} />
347 {form.$('isDarkModeEnabled').value 360 {form.$('isDarkModeEnabled').value && (
348 && ( 361 <>
349 <> 362 <h3>
350 <h3>{intl.formatMessage(messages.headlineDarkReaderSettings)}</h3> 363 {intl.formatMessage(
351 <Slider field={form.$('darkReaderBrightness')} /> 364 messages.headlineDarkReaderSettings,
352 <Slider field={form.$('darkReaderContrast')} /> 365 )}
353 <Slider field={form.$('darkReaderSepia')} /> 366 </h3>
354 </> 367 <Slider field={form.$('darkReaderBrightness')} />
355 )} 368 <Slider field={form.$('darkReaderContrast')} />
369 <Slider field={form.$('darkReaderSepia')} />
370 </>
371 )}
356 </div> 372 </div>
357 </div> 373 </div>
358 <div className="service-icon"> 374 <div className="service-icon">
@@ -381,7 +397,10 @@ export default @observer class EditServiceForm extends Component {
381 <> 397 <>
382 <div className="grid"> 398 <div className="grid">
383 <div className="grid__row"> 399 <div className="grid__row">
384 <Input field={form.$('proxy.host')} className="proxyHost" /> 400 <Input
401 field={form.$('proxy.host')}
402 className="proxyHost"
403 />
385 <Input field={form.$('proxy.port')} /> 404 <Input field={form.$('proxy.port')} />
386 </div> 405 </div>
387 </div> 406 </div>
@@ -409,7 +428,9 @@ export default @observer class EditServiceForm extends Component {
409 428
410 <div className="user-agent"> 429 <div className="user-agent">
411 <Input field={form.$('userAgentPref')} /> 430 <Input field={form.$('userAgentPref')} />
412 <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> 431 <p className="settings__help">
432 {intl.formatMessage(globalMessages.userAgentHelp)}
433 </p>
413 </div> 434 </div>
414 </form> 435 </form>
415 436
@@ -464,7 +485,9 @@ export default @observer class EditServiceForm extends Component {
464 type="submit" 485 type="submit"
465 label={intl.formatMessage(messages.saveService)} 486 label={intl.formatMessage(messages.saveService)}
466 htmlForm="form" 487 htmlForm="form"
467 disabled={action !== 'edit' && (form.isPristine && requiresUserInput)} 488 disabled={
489 action !== 'edit' && form.isPristine && requiresUserInput
490 }
468 /> 491 />
469 )} 492 )}
470 </div> 493 </div>
@@ -472,3 +495,5 @@ export default @observer class EditServiceForm extends Component {
472 ); 495 );
473 } 496 }
474} 497}
498
499export 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 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
3import { Link } from 'react-router'; 3import { Link } from 'react-router';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import Infobox from '../../ui/Infobox'; 6import Infobox from '../../ui/Infobox';
7import Button from '../../ui/Button'; 7import Button from '../../ui/Button';
@@ -9,29 +9,26 @@ import Button from '../../ui/Button';
9const messages = defineMessages({ 9const 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
28export default @observer class ServiceError extends Component { 28@observer
29 static contextTypes = { 29class 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
63export 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 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, injectIntl } from 'react-intl';
4import ReactTooltip from 'react-tooltip'; 4import ReactTooltip from 'react-tooltip';
5import { observer } from 'mobx-react'; 5import { observer } from 'mobx-react';
6import classnames from 'classnames'; 6import classnames from 'classnames';
@@ -10,35 +10,32 @@ import ServiceModel from '../../../models/Service';
10const messages = defineMessages({ 10const 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
25export default @observer class ServiceItem extends Component { 25@observer
26class 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
92export default injectIntl(ServiceItem);
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index 11d3eaa79..bb52db97f 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { Link } from 'react-router'; 4import { Link } from 'react-router';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import SearchInput from '../../ui/SearchInput'; 7import SearchInput from '../../ui/SearchInput';
8import Infobox from '../../ui/Infobox'; 8import Infobox from '../../ui/Infobox';
@@ -14,43 +14,45 @@ import Appear from '../../ui/effects/Appear';
14const messages = defineMessages({ 14const 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.services.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 - 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.',
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
53export default @observer class ServicesDashboard extends Component { 54@observer
55class 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">
@@ -93,10 +91,10 @@ export default @observer class ServicesDashboard extends Component {
93 <h1>{intl.formatMessage(messages.headline)}</h1> 91 <h1>{intl.formatMessage(messages.headline)}</h1>
94 </div> 92 </div>
95 <div className="settings__body"> 93 <div className="settings__body">
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
191export default injectIntl(ServicesDashboard);