aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/settings/services/EditServiceForm.js
diff options
context:
space:
mode:
authorLibravatar Muhamed <unknown>2022-11-08 07:40:02 +0530
committerLibravatar Vijay Aravamudhan <vraravam@users.noreply.github.com>2022-11-08 17:25:27 +0530
commit570d26baf9e4ad87a8c0752b5edfb5c441bf9d80 (patch)
treeee0a0e6bec7d10ec438b5269537905fee80c377b /src/components/settings/services/EditServiceForm.js
parentrefactor: remove toggle component's duplicate (diff)
downloadferdium-app-570d26baf9e4ad87a8c0752b5edfb5c441bf9d80.tar.gz
ferdium-app-570d26baf9e4ad87a8c0752b5edfb5c441bf9d80.tar.zst
ferdium-app-570d26baf9e4ad87a8c0752b5edfb5c441bf9d80.zip
fix: slack issue caused by input TS conversion
Diffstat (limited to 'src/components/settings/services/EditServiceForm.js')
-rw-r--r--src/components/settings/services/EditServiceForm.js536
1 files changed, 0 insertions, 536 deletions
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
deleted file mode 100644
index eb18b57eb..000000000
--- a/src/components/settings/services/EditServiceForm.js
+++ /dev/null
@@ -1,536 +0,0 @@
1import { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { Link } from 'react-router-dom';
5import { defineMessages, injectIntl } from 'react-intl';
6import normalizeUrl from 'normalize-url';
7import { mdiInformation } from '@mdi/js';
8import Form from '../../../lib/Form';
9import Recipe from '../../../models/Recipe';
10import Service from '../../../models/Service';
11import Tabs from '../../ui/Tabs/Tabs';
12import TabItem from '../../ui/Tabs/TabItem';
13import Input from '../../ui/input/index';
14import Toggle from '../../ui/toggle';
15import Slider from '../../ui/Slider';
16import Button from '../../ui/button';
17import ImageUpload from '../../ui/ImageUpload';
18import Select from '../../ui/Select';
19import { isMac } from '../../../environment';
20import globalMessages from '../../../i18n/globalMessages';
21import Icon from '../../ui/icon';
22import { H3 } from '../../ui/headline';
23
24const messages = defineMessages({
25 saveService: {
26 id: 'settings.service.form.saveButton',
27 defaultMessage: 'Save service',
28 },
29 deleteService: {
30 id: 'settings.service.form.deleteButton',
31 defaultMessage: 'Delete service',
32 },
33 openDarkmodeCss: {
34 id: 'settings.service.form.openDarkmodeCss',
35 defaultMessage: 'Open darkmode.css',
36 },
37 openUserCss: {
38 id: 'settings.service.form.openUserCss',
39 defaultMessage: 'Open user.css',
40 },
41 openUserJs: {
42 id: 'settings.service.form.openUserJs',
43 defaultMessage: 'Open user.js',
44 },
45 recipeFileInfo: {
46 id: 'settings.service.form.recipeFileInfo',
47 defaultMessage:
48 '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.',
49 },
50 availableServices: {
51 id: 'settings.service.form.availableServices',
52 defaultMessage: 'Available services',
53 },
54 yourServices: {
55 id: 'settings.service.form.yourServices',
56 defaultMessage: 'Your services',
57 },
58 addServiceHeadline: {
59 id: 'settings.service.form.addServiceHeadline',
60 defaultMessage: 'Add {name}',
61 },
62 editServiceHeadline: {
63 id: 'settings.service.form.editServiceHeadline',
64 defaultMessage: 'Edit {name}',
65 },
66 tabHosted: {
67 id: 'settings.service.form.tabHosted',
68 defaultMessage: 'Hosted',
69 },
70 tabOnPremise: {
71 id: 'settings.service.form.tabOnPremise',
72 defaultMessage: 'Self hosted ⭐️',
73 },
74 useHostedService: {
75 id: 'settings.service.form.useHostedService',
76 defaultMessage: 'Use the hosted {name} service.',
77 },
78 customUrlValidationError: {
79 id: 'settings.service.form.customUrlValidationError',
80 defaultMessage: 'Could not validate custom {name} server.',
81 },
82 indirectMessageInfo: {
83 id: 'settings.service.form.indirectMessageInfo',
84 defaultMessage:
85 'You will be notified about all new messages in a channel, not just @username, @channel, @here, ...',
86 },
87 isMutedInfo: {
88 id: 'settings.service.form.isMutedInfo',
89 defaultMessage:
90 'When disabled, all notification sounds and audio playback are muted',
91 },
92 isHibernationEnabledInfo: {
93 id: 'settings.service.form.isHibernatedEnabledInfo',
94 defaultMessage:
95 'When enabled, a service will be shut down after a period of time to save system resources.',
96 },
97 headlineNotifications: {
98 id: 'settings.service.form.headlineNotifications',
99 defaultMessage: 'Notifications',
100 },
101 headlineBadges: {
102 id: 'settings.service.form.headlineBadges',
103 defaultMessage: 'Unread message badges',
104 },
105 headlineGeneral: {
106 id: 'settings.service.form.headlineGeneral',
107 defaultMessage: 'General',
108 },
109 headlineAppearance: {
110 id: 'settings.service.form.headlineAppearance',
111 defaultMessage: 'Appearance',
112 },
113 headlineDarkReaderSettings: {
114 id: 'settings.service.form.headlineDarkReaderSettings',
115 defaultMessage: 'Dark Reader Settings',
116 },
117 iconDelete: {
118 id: 'settings.service.form.iconDelete',
119 defaultMessage: 'Delete',
120 },
121 iconUpload: {
122 id: 'settings.service.form.iconUpload',
123 defaultMessage: 'Drop your image, or click here',
124 },
125 headlineProxy: {
126 id: 'settings.service.form.proxy.headline',
127 defaultMessage: 'HTTP/HTTPS Proxy Settings',
128 },
129 proxyRestartInfo: {
130 id: 'settings.service.form.proxy.restartInfo',
131 defaultMessage: 'Please restart Ferdium after changing proxy Settings.',
132 },
133 proxyInfo: {
134 id: 'settings.service.form.proxy.info',
135 defaultMessage:
136 'Proxy settings will not be synchronized with the Ferdium servers.',
137 },
138 serviceReloadRequired: {
139 id: 'settings.service.reloadRequired',
140 defaultMessage: 'Changes require reload of the service',
141 },
142 maxFileSize: {
143 id: 'settings.service.form.maxFileSize',
144 defaultMessage: 'Maximum filesize:',
145 },
146 maxFileSizeError: {
147 id: 'settings.service.form.maxFileSizeError',
148 defaultMessage: 'The file you are trying to submit is too large.',
149 },
150});
151
152class EditServiceForm extends Component {
153 static propTypes = {
154 recipe: PropTypes.instanceOf(Recipe).isRequired,
155 service(props, propName) {
156 if (props.action === 'edit' && !(props[propName] instanceof Service)) {
157 return new Error(`'${propName}'' is expected to be of type 'Service'
158 when editing a Service`);
159 }
160
161 return null;
162 },
163 action: PropTypes.string.isRequired,
164 form: PropTypes.instanceOf(Form).isRequired,
165 onSubmit: PropTypes.func.isRequired,
166 onDelete: PropTypes.func.isRequired,
167 openRecipeFile: PropTypes.func.isRequired,
168 isSaving: PropTypes.bool.isRequired,
169 isDeleting: PropTypes.bool.isRequired,
170 isProxyFeatureEnabled: PropTypes.bool.isRequired,
171 };
172
173 static defaultProps = {
174 service: {},
175 };
176
177 state = {
178 isValidatingCustomUrl: false,
179 };
180
181 submit(e) {
182 const { recipe } = this.props;
183
184 e.preventDefault();
185 this.props.form.submit({
186 onSuccess: async form => {
187 const values = form.values();
188 let isValid = true;
189
190 const { files } = form.$('customIcon');
191 if (files) {
192 values.iconFile = files[0];
193 }
194
195 if (recipe.validateUrl && values.customUrl) {
196 this.setState({ isValidatingCustomUrl: true });
197 try {
198 values.customUrl = normalizeUrl(values.customUrl, {
199 stripAuthentication: false,
200 stripWWW: false,
201 removeTrailingSlash: false,
202 });
203 isValid = await recipe.validateUrl(values.customUrl);
204 } catch (error) {
205 console.warn('ValidateURL', error);
206 isValid = false;
207 }
208 }
209
210 if (isValid) {
211 this.props.onSubmit(values);
212 } else {
213 form.invalidate('url-validation-error');
214 }
215
216 this.setState({ isValidatingCustomUrl: false });
217 },
218 onError: () => {},
219 });
220 }
221
222 render() {
223 const {
224 recipe,
225 service,
226 action,
227 form,
228 isSaving,
229 isDeleting,
230 onDelete,
231 openRecipeFile,
232 isProxyFeatureEnabled,
233 } = this.props;
234 const { intl } = this.props;
235
236 const { isValidatingCustomUrl } = this.state;
237
238 const deleteButton = isDeleting ? (
239 <Button
240 label={intl.formatMessage(messages.deleteService)}
241 loaded={false}
242 buttonType="secondary"
243 className="settings__delete-button"
244 disabled
245 />
246 ) : (
247 <Button
248 buttonType="danger"
249 label={intl.formatMessage(messages.deleteService)}
250 className="settings__delete-button"
251 onClick={onDelete}
252 />
253 );
254
255 let activeTabIndex = 0;
256 if (recipe.hasHostedOption && service?.team) {
257 activeTabIndex = 1;
258 } else if (recipe.hasHostedOption && service?.customUrl) {
259 activeTabIndex = 2;
260 }
261
262 const requiresUserInput =
263 !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl);
264
265 return (
266 <div className="settings__main">
267 <div className="settings__header">
268 <span className="settings__header-item">
269 {action === 'add' ? (
270 <Link to="/settings/recipes">
271 {intl.formatMessage(messages.availableServices)}
272 </Link>
273 ) : (
274 <Link to="/settings/services">
275 {intl.formatMessage(messages.yourServices)}
276 </Link>
277 )}
278 </span>
279 <span className="separator" />
280 <span className="settings__header-item">
281 {action === 'add'
282 ? intl.formatMessage(messages.addServiceHeadline, {
283 name: recipe.name,
284 })
285 : intl.formatMessage(messages.editServiceHeadline, {
286 name: service.name !== '' ? service.name : recipe.name,
287 })}
288 </span>
289 </div>
290 <div className="settings__body">
291 <form onSubmit={e => this.submit(e)} id="form">
292 <div className="service-name">
293 <Input {...form.$('name').bind()} focus />
294 </div>
295 {(recipe.hasTeamId || recipe.hasCustomUrl) && (
296 <Tabs active={activeTabIndex}>
297 {recipe.hasHostedOption && (
298 <TabItem title={recipe.name}>
299 {intl.formatMessage(messages.useHostedService, {
300 name: recipe.name,
301 })}
302 </TabItem>
303 )}
304 {recipe.hasTeamId && (
305 <TabItem title={intl.formatMessage(messages.tabHosted)}>
306 <Input
307 field={form.$('team')}
308 prefix={recipe.urlInputPrefix}
309 suffix={recipe.urlInputSuffix}
310 />
311 </TabItem>
312 )}
313 {recipe.hasCustomUrl && (
314 <TabItem title={intl.formatMessage(messages.tabOnPremise)}>
315 <Input {...form.$('customUrl').bind()} />
316 {form.error === 'url-validation-error' && (
317 <p className="franz-form__error">
318 {intl.formatMessage(messages.customUrlValidationError, {
319 name: recipe.name,
320 })}
321 </p>
322 )}
323 </TabItem>
324 )}
325 </Tabs>
326 )}
327
328 {recipe.message && (
329 <p
330 className="settings__message"
331 style={{
332 marginTop: 0,
333 }}
334 >
335 <Icon icon={mdiInformation} />
336 {recipe.message}
337 </p>
338 )}
339 <div className="service-flex-grid">
340 <div className="settings__options">
341 <div className="settings__settings-group">
342 <H3>{intl.formatMessage(messages.headlineNotifications)}</H3>
343 <Toggle {...form.$('isNotificationEnabled').bind()} />
344 <Toggle {...form.$('isMuted').bind()} />
345 <p className="settings__help indented__help">
346 {intl.formatMessage(messages.isMutedInfo)}
347 </p>
348 <Toggle {...form.$('isMediaBadgeEnabled').bind()} />
349 </div>
350
351 <div className="settings__settings-group">
352 <H3>{intl.formatMessage(messages.headlineBadges)}</H3>
353 <Toggle {...form.$('isBadgeEnabled').bind()} />
354 {recipe.hasIndirectMessages &&
355 form.$('isBadgeEnabled').value && (
356 <>
357 <Toggle
358 {...form.$('isIndirectMessageBadgeEnabled').bind()}
359 />
360 <p className="settings__help indented__help">
361 {intl.formatMessage(messages.indirectMessageInfo)}
362 </p>
363 </>
364 )}
365 {recipe.allowFavoritesDelineationInUnreadCount && (
366 <Toggle
367 {...form.$('onlyShowFavoritesInUnreadCount').bind()}
368 />
369 )}
370 </div>
371
372 <div className="settings__settings-group">
373 <H3>{intl.formatMessage(messages.headlineGeneral)}</H3>
374 <Toggle {...form.$('isEnabled').bind()} />
375 <Toggle {...form.$('isHibernationEnabled').bind()} />
376 <p className="settings__help indented__help">
377 {intl.formatMessage(messages.isHibernationEnabledInfo)}
378 </p>
379 <Toggle {...form.$('isWakeUpEnabled').bind()} />
380 <Toggle {...form.$('trapLinkClicks').bind()} />
381 {/* TODO: Need to figure out how to effect this change without a reload of the recipe */}
382 <p className="settings__help indented__help">
383 {intl.formatMessage(messages.serviceReloadRequired)}
384 </p>
385 </div>
386
387 <div className="settings__settings-group">
388 <H3>{intl.formatMessage(messages.headlineAppearance)}</H3>
389 <Toggle {...form.$('isDarkModeEnabled').bind()} />
390 {form.$('isDarkModeEnabled').value && (
391 <>
392 <H3>
393 {intl.formatMessage(
394 messages.headlineDarkReaderSettings,
395 )}
396 </H3>
397 <Slider field={form.$('darkReaderBrightness')} />
398 <Slider field={form.$('darkReaderContrast')} />
399 <Slider field={form.$('darkReaderSepia')} />
400 </>
401 )}
402 <Toggle {...form.$('isProgressbarEnabled').bind()} />
403 </div>
404 </div>
405 <div className="service-icon">
406 <ImageUpload
407 field={form.$('customIcon')}
408 textDelete={intl.formatMessage(messages.iconDelete)}
409 textUpload={intl.formatMessage(messages.iconUpload)}
410 maxSize={2_097_152}
411 maxFiles={1}
412 textMaxFileSize={intl.formatMessage(messages.maxFileSize)}
413 textMaxFileSizeError={intl.formatMessage(
414 messages.maxFileSizeError,
415 )}
416 />
417 </div>
418 </div>
419
420 {!isMac && (
421 <div className="settings__settings-group">
422 <Select field={form.$('spellcheckerLanguage')} />
423 </div>
424 )}
425
426 {isProxyFeatureEnabled && (
427 <div className="settings__settings-group">
428 <H3>
429 {intl.formatMessage(messages.headlineProxy)}
430 <span className="badge badge--success">beta</span>
431 </H3>
432 <Toggle {...form.$('proxy.isEnabled').bind()} />
433 {form.$('proxy.isEnabled').value && (
434 <>
435 <div className="grid">
436 <div className="grid__row">
437 <Input
438 {...form.$('proxy.host').bind()}
439 className="proxyHost"
440 />
441 <Input {...form.$('proxy.port').bind()} />
442 </div>
443 </div>
444 <div className="grid">
445 <div className="grid__row">
446 <Input {...form.$('proxy.user').bind()} />
447 <Input
448 {...form.$('proxy.password').bind()}
449 showPasswordToggle
450 />
451 </div>
452 </div>
453 <p>
454 <Icon icon={mdiInformation} />
455 {intl.formatMessage(messages.proxyRestartInfo)}
456 </p>
457 <p>
458 <Icon icon={mdiInformation} />
459 {intl.formatMessage(messages.proxyInfo)}
460 </p>
461 </>
462 )}
463 </div>
464 )}
465
466 <div className="user-agent">
467 <Input {...form.$('userAgentPref').bind()} />
468 <p className="settings__help">
469 {intl.formatMessage(globalMessages.userAgentHelp)}
470 </p>
471 </div>
472 </form>
473
474 {action === 'edit' && (
475 <>
476 <div className="settings__open-recipe-file-container">
477 <Button
478 buttonType="secondary"
479 label={intl.formatMessage(messages.openDarkmodeCss)}
480 className="settings__open-recipe-file-button"
481 onClick={() => openRecipeFile('darkmode.css')}
482 />
483 <Button
484 buttonType="secondary"
485 label={intl.formatMessage(messages.openUserCss)}
486 className="settings__open-recipe-file-button"
487 onClick={() => openRecipeFile('user.css')}
488 />
489 <Button
490 buttonType="secondary"
491 label={intl.formatMessage(messages.openUserJs)}
492 className="settings__open-recipe-file-button"
493 onClick={() => openRecipeFile('user.js')}
494 />
495 </div>
496 <p style={{ marginTop: 10, marginBottom: 10 }}>
497 <Icon icon={mdiInformation} />
498 {intl.formatMessage(messages.recipeFileInfo)}
499 </p>
500 </>
501 )}
502 <span style={{ fontStyle: 'italic', fontSize: '80%' }}>
503 Recipe version:
504 {recipe.version}
505 </span>
506 </div>
507 <div className="settings__controls">
508 {/* Delete Button */}
509 <div>{action === 'edit' && deleteButton}</div>
510
511 {/* Save Button */}
512 {isSaving || isValidatingCustomUrl ? (
513 <Button
514 type="submit"
515 label={intl.formatMessage(messages.saveService)}
516 loaded={false}
517 buttonType="secondary"
518 disabled
519 />
520 ) : (
521 <Button
522 type="submit"
523 label={intl.formatMessage(messages.saveService)}
524 htmlForm="form"
525 disabled={
526 action !== 'edit' && form.isPristine && requiresUserInput
527 }
528 />
529 )}
530 </div>
531 </div>
532 );
533 }
534}
535
536export default injectIntl(observer(EditServiceForm));