aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/settings/services/EditServiceForm.js20
-rw-r--r--src/components/settings/services/ServicesDashboard.js7
-rw-r--r--src/components/settings/settings/EditSettingsForm.js11
-rw-r--r--src/components/ui/FAB.js72
-rw-r--r--src/components/ui/Select.js44
5 files changed, 142 insertions, 12 deletions
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index 3dba793b2..f1e70ce59 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -21,6 +21,8 @@ import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
21import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox'; 21import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox';
22import { serviceLimitStore } from '../../../features/serviceLimit'; 22import { serviceLimitStore } from '../../../features/serviceLimit';
23 23
24import { isMac } from '../../../environment';
25
24const messages = defineMessages({ 26const messages = defineMessages({
25 saveService: { 27 saveService: {
26 id: 'settings.service.form.saveButton', 28 id: 'settings.service.form.saveButton',
@@ -401,14 +403,16 @@ export default @observer class EditServiceForm extends Component {
401 </div> 403 </div>
402 </div> 404 </div>
403 405
404 <PremiumFeatureContainer 406 {!isMac && (
405 condition={!isSpellcheckerIncludedInCurrentPlan} 407 <PremiumFeatureContainer
406 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }} 408 condition={!isSpellcheckerIncludedInCurrentPlan}
407 > 409 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }}
408 <div className="settings__settings-group"> 410 >
409 <Select field={form.$('spellcheckerLanguage')} /> 411 <div className="settings__settings-group">
410 </div> 412 <Select field={form.$('spellcheckerLanguage')} multiple />
411 </PremiumFeatureContainer> 413 </div>
414 </PremiumFeatureContainer>
415 )}
412 416
413 {isProxyFeatureEnabled && ( 417 {isProxyFeatureEnabled && (
414 <PremiumFeatureContainer 418 <PremiumFeatureContainer
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index 78038e86a..826dbb176 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -7,6 +7,7 @@ import { defineMessages, intlShape } from 'react-intl';
7import SearchInput from '../../ui/SearchInput'; 7import SearchInput from '../../ui/SearchInput';
8import Infobox from '../../ui/Infobox'; 8import Infobox from '../../ui/Infobox';
9import Loader from '../../ui/Loader'; 9import Loader from '../../ui/Loader';
10import FAB from '../../ui/FAB';
10import ServiceItem from './ServiceItem'; 11import ServiceItem from './ServiceItem';
11import Appear from '../../ui/effects/Appear'; 12import Appear from '../../ui/effects/Appear';
12import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox'; 13import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox';
@@ -175,6 +176,12 @@ export default @observer class ServicesDashboard extends Component {
175 </tbody> 176 </tbody>
176 </table> 177 </table>
177 )} 178 )}
179
180 <FAB>
181 <Link to="/settings/recipes">
182 +
183 </Link>
184 </FAB>
178 </div> 185 </div>
179 </div> 186 </div>
180 ); 187 );
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 50358c36f..ba7cb7317 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -91,6 +91,10 @@ const messages = defineMessages({
91 id: 'settings.app.translationHelp', 91 id: 'settings.app.translationHelp',
92 defaultMessage: '!!!Help us to translate Ferdi into your language.', 92 defaultMessage: '!!!Help us to translate Ferdi into your language.',
93 }, 93 },
94 spellCheckerLanguageInfo: {
95 id: 'settings.app.spellCheckerLanguageInfo',
96 defaultMessage: '!!!Ferdi uses your Mac\'s build-in spellchecker to check for typos. If you want to change the languages the spellchecker checks for, you can do so in your Mac\'s System Preferences.',
97 },
94 subheadlineCache: { 98 subheadlineCache: {
95 id: 'settings.app.subheadlineCache', 99 id: 'settings.app.subheadlineCache',
96 defaultMessage: '!!!Cache', 100 defaultMessage: '!!!Cache',
@@ -518,8 +522,11 @@ export default @observer class EditSettingsForm extends Component {
518 <Toggle 522 <Toggle
519 field={form.$('enableSpellchecking')} 523 field={form.$('enableSpellchecking')}
520 /> 524 />
521 {form.$('enableSpellchecking').value && ( 525 {form.$('enableSpellchecking').value && !isMac && (
522 <Select field={form.$('spellcheckerLanguage')} /> 526 <Select field={form.$('spellcheckerLanguage')} multiple />
527 )}
528 {form.$('enableSpellchecking').value && isMac && (
529 <p>{intl.formatMessage(messages.spellCheckerLanguageInfo)}</p>
523 )} 530 )}
524 </Fragment> 531 </Fragment>
525 </PremiumFeatureContainer> 532 </PremiumFeatureContainer>
diff --git a/src/components/ui/FAB.js b/src/components/ui/FAB.js
new file mode 100644
index 000000000..9359a3c6c
--- /dev/null
+++ b/src/components/ui/FAB.js
@@ -0,0 +1,72 @@
1/**
2 * Floating Action Button (FAB)
3 */
4import React, { Component } from 'react';
5import PropTypes from 'prop-types';
6import { observer, inject } from 'mobx-react';
7import classnames from 'classnames';
8
9export default @inject('stores') @observer class Button extends Component {
10 static propTypes = {
11 className: PropTypes.string,
12 disabled: PropTypes.bool,
13 onClick: PropTypes.func,
14 type: PropTypes.string,
15 htmlForm: PropTypes.string,
16 stores: PropTypes.shape({
17 settings: PropTypes.shape({
18 app: PropTypes.shape({
19 accentColor: PropTypes.string.isRequired,
20 }).isRequired,
21 }).isRequired,
22 }).isRequired,
23 };
24
25 static defaultProps = {
26 className: null,
27 disabled: false,
28 onClick: () => { },
29 type: 'button',
30 htmlForm: '',
31 };
32
33 element = null;
34
35 render() {
36 const {
37 className,
38 disabled,
39 onClick,
40 type,
41 children,
42 htmlForm,
43 } = this.props;
44
45 const buttonProps = {
46 className: classnames({
47 ferdi__fab: true,
48 [`${className}`]: className,
49 }),
50 type,
51 };
52
53 if (disabled) {
54 buttonProps.disabled = true;
55 }
56
57 if (onClick) {
58 buttonProps.onClick = onClick;
59 }
60
61 if (htmlForm) {
62 buttonProps.form = htmlForm;
63 }
64
65 return (
66 // disabling rule as button has type defined in `buttonProps`
67 <button {...buttonProps} type="button">
68 {children}
69 </button>
70 );
71 }
72}
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js
index da52243ca..b4511433c 100644
--- a/src/components/ui/Select.js
+++ b/src/components/ui/Select.js
@@ -10,22 +10,60 @@ export default @observer class Select extends Component {
10 className: PropTypes.string, 10 className: PropTypes.string,
11 showLabel: PropTypes.bool, 11 showLabel: PropTypes.bool,
12 disabled: PropTypes.bool, 12 disabled: PropTypes.bool,
13 multiple: PropTypes.bool,
13 }; 14 };
14 15
15 static defaultProps = { 16 static defaultProps = {
16 className: null, 17 className: null,
17 showLabel: true, 18 showLabel: true,
18 disabled: false, 19 disabled: false,
20 multiple: false,
19 }; 21 };
20 22
23 constructor(props) {
24 super(props);
25
26 this.element = React.createRef();
27 }
28
29 multipleChange() {
30 const element = this.element.current;
31
32 const result = [];
33 const options = element && element.options;
34
35 for (const option of options) {
36 if (option.selected) {
37 result.push(option.value || option.text);
38 }
39 }
40
41 const { field } = this.props;
42 field.value = result;
43 }
44
21 render() { 45 render() {
22 const { 46 const {
23 field, 47 field,
24 className, 48 className,
25 showLabel, 49 showLabel,
26 disabled, 50 disabled,
51 multiple,
27 } = this.props; 52 } = this.props;
28 53
54 let selected = field.value;
55
56 if (multiple) {
57 if (typeof field.value === 'string' && field.value.substr(0, 1) === '[') {
58 // Value is JSON encoded
59 selected = JSON.parse(field.value);
60 } else if (typeof field.value === 'object') {
61 selected = field.value;
62 } else {
63 selected = [field.value];
64 }
65 }
66
29 return ( 67 return (
30 <div 68 <div
31 className={classnames({ 69 className={classnames({
@@ -44,11 +82,13 @@ export default @observer class Select extends Component {
44 </label> 82 </label>
45 )} 83 )}
46 <select 84 <select
47 onChange={field.onChange} 85 onChange={multiple ? e => this.multipleChange(e) : field.onChange}
48 id={field.id} 86 id={field.id}
49 defaultValue={field.value} 87 defaultValue={selected}
50 className="franz-form__select" 88 className="franz-form__select"
51 disabled={field.disabled || disabled} 89 disabled={field.disabled || disabled}
90 multiple={multiple}
91 ref={this.element}
52 > 92 >
53 {field.options.map(type => ( 93 {field.options.map(type => (
54 <option 94 <option