diff options
author | Markus Hatvan <markus_hatvan@aon.at> | 2021-09-13 14:45:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-13 14:45:46 +0200 |
commit | 537697a6e9757f118d09d9e76362ba1ff617e2c6 (patch) | |
tree | bc55447115e385137684e84697a8c15d2199b8d5 /src/components | |
parent | Bumped up version to: 5.6.3-nightly.0 [skip ci] (diff) | |
download | ferdium-app-537697a6e9757f118d09d9e76362ba1ff617e2c6.tar.gz ferdium-app-537697a6e9757f118d09d9e76362ba1ff617e2c6.tar.zst ferdium-app-537697a6e9757f118d09d9e76362ba1ff617e2c6.zip |
chore: upgrade intl dependencies (#1920)
Diffstat (limited to 'src/components')
56 files changed, 1525 insertions, 1369 deletions
diff --git a/src/components/AppUpdateInfoBar.js b/src/components/AppUpdateInfoBar.js index 30804262a..9dc86bd1d 100644 --- a/src/components/AppUpdateInfoBar.js +++ b/src/components/AppUpdateInfoBar.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | 4 | ||
5 | import InfoBar from './ui/InfoBar'; | 5 | import InfoBar from './ui/InfoBar'; |
6 | import { GITHUB_FERDI_URL } from '../config'; | 6 | import { GITHUB_FERDI_URL } from '../config'; |
@@ -9,15 +9,15 @@ import { openExternalUrl } from '../helpers/url-helpers'; | |||
9 | const messages = defineMessages({ | 9 | const messages = defineMessages({ |
10 | updateAvailable: { | 10 | updateAvailable: { |
11 | id: 'infobar.updateAvailable', | 11 | id: 'infobar.updateAvailable', |
12 | defaultMessage: '!!!A new update for Ferdi is available.', | 12 | defaultMessage: 'A new update for Ferdi is available.', |
13 | }, | 13 | }, |
14 | changelog: { | 14 | changelog: { |
15 | id: 'infobar.buttonChangelog', | 15 | id: 'infobar.buttonChangelog', |
16 | defaultMessage: '!!!Changelog', | 16 | defaultMessage: 'Changelog', |
17 | }, | 17 | }, |
18 | buttonInstallUpdate: { | 18 | buttonInstallUpdate: { |
19 | id: 'infobar.buttonInstallUpdate', | 19 | id: 'infobar.buttonInstallUpdate', |
20 | defaultMessage: '!!!Restart & install update', | 20 | defaultMessage: 'Restart & install update', |
21 | }, | 21 | }, |
22 | }); | 22 | }); |
23 | 23 | ||
@@ -27,12 +27,8 @@ class AppUpdateInfoBar extends Component { | |||
27 | onHide: PropTypes.func.isRequired, | 27 | onHide: PropTypes.func.isRequired, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static contextTypes = { | ||
31 | intl: intlShape, | ||
32 | }; | ||
33 | |||
34 | render() { | 30 | render() { |
35 | const { intl } = this.context; | 31 | const { intl } = this.props; |
36 | const { onInstallUpdate, onHide } = this.props; | 32 | const { onInstallUpdate, onHide } = this.props; |
37 | 33 | ||
38 | return ( | 34 | return ( |
@@ -61,4 +57,4 @@ class AppUpdateInfoBar extends Component { | |||
61 | } | 57 | } |
62 | } | 58 | } |
63 | 59 | ||
64 | export default AppUpdateInfoBar; | 60 | export default injectIntl(AppUpdateInfoBar); |
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js index 8235932c2..3e2b75731 100644 --- a/src/components/auth/AuthLayout.js +++ b/src/components/auth/AuthLayout.js | |||
@@ -1,9 +1,9 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { intlShape } from 'react-intl'; | ||
5 | import { TitleBar } from 'electron-react-titlebar'; | 4 | import { TitleBar } from 'electron-react-titlebar'; |
6 | 5 | ||
6 | import { injectIntl } from 'react-intl'; | ||
7 | import Link from '../ui/Link'; | 7 | import Link from '../ui/Link'; |
8 | import InfoBar from '../ui/InfoBar'; | 8 | import InfoBar from '../ui/InfoBar'; |
9 | 9 | ||
@@ -17,7 +17,6 @@ import { isWindows } from '../../environment'; | |||
17 | import AppUpdateInfoBar from '../AppUpdateInfoBar'; | 17 | import AppUpdateInfoBar from '../AppUpdateInfoBar'; |
18 | import { GITHUB_FERDI_URL } from '../../config'; | 18 | import { GITHUB_FERDI_URL } from '../../config'; |
19 | 19 | ||
20 | export default | ||
21 | @observer | 20 | @observer |
22 | class AuthLayout extends Component { | 21 | class AuthLayout extends Component { |
23 | static propTypes = { | 22 | static propTypes = { |
@@ -36,10 +35,6 @@ class AuthLayout extends Component { | |||
36 | shouldShowAppUpdateInfoBar: true, | 35 | shouldShowAppUpdateInfoBar: true, |
37 | }; | 36 | }; |
38 | 37 | ||
39 | static contextTypes = { | ||
40 | intl: intlShape, | ||
41 | }; | ||
42 | |||
43 | render() { | 38 | render() { |
44 | const { | 39 | const { |
45 | children, | 40 | children, |
@@ -52,7 +47,8 @@ class AuthLayout extends Component { | |||
52 | installAppUpdate, | 47 | installAppUpdate, |
53 | appUpdateIsDownloaded, | 48 | appUpdateIsDownloaded, |
54 | } = this.props; | 49 | } = this.props; |
55 | const { intl } = this.context; | 50 | |
51 | const { intl } = this.props; | ||
56 | 52 | ||
57 | return ( | 53 | return ( |
58 | <> | 54 | <> |
@@ -108,3 +104,5 @@ class AuthLayout extends Component { | |||
108 | ); | 104 | ); |
109 | } | 105 | } |
110 | } | 106 | } |
107 | |||
108 | export default injectIntl(AuthLayout); | ||
diff --git a/src/components/auth/ChangeServer.js b/src/components/auth/ChangeServer.js index 8e8a7af32..b98fb50f7 100644 --- a/src/components/auth/ChangeServer.js +++ b/src/components/auth/ChangeServer.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import Form from '../../lib/Form'; | 5 | import Form from '../../lib/Form'; |
6 | import Input from '../ui/Input'; | 6 | import Input from '../ui/Input'; |
7 | import Select from '../ui/Select'; | 7 | import Select from '../ui/Select'; |
@@ -14,56 +14,65 @@ import globalMessages from '../../i18n/globalMessages'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'changeserver.headline', | 16 | id: 'changeserver.headline', |
17 | defaultMessage: '!!!Change server', | 17 | defaultMessage: 'Change server', |
18 | }, | 18 | }, |
19 | label: { | 19 | label: { |
20 | id: 'changeserver.label', | 20 | id: 'changeserver.label', |
21 | defaultMessage: '!!!Server', | 21 | defaultMessage: 'Server', |
22 | }, | 22 | }, |
23 | warning: { | 23 | warning: { |
24 | id: 'changeserver.warning', | 24 | id: 'changeserver.warning', |
25 | defaultMessage: '!!!Extra settings offered by Ferdi will not be saved', | 25 | defaultMessage: 'Extra settings offered by Ferdi will not be saved', |
26 | }, | 26 | }, |
27 | customServerLabel: { | 27 | customServerLabel: { |
28 | id: 'changeserver.customServerLabel', | 28 | id: 'changeserver.customServerLabel', |
29 | defaultMessage: '!!!Custom server', | 29 | defaultMessage: 'Custom server', |
30 | }, | 30 | }, |
31 | urlError: { | 31 | urlError: { |
32 | id: 'changeserver.urlError', | 32 | id: 'changeserver.urlError', |
33 | defaultMessage: '!!!Enter a valid URL', | 33 | defaultMessage: 'Enter a valid URL', |
34 | }, | 34 | }, |
35 | }); | 35 | }); |
36 | 36 | ||
37 | export default @observer class ChangeServer extends Component { | 37 | @observer |
38 | class ChangeServer extends Component { | ||
38 | static propTypes = { | 39 | static propTypes = { |
39 | onSubmit: PropTypes.func.isRequired, | 40 | onSubmit: PropTypes.func.isRequired, |
40 | server: PropTypes.string.isRequired, | 41 | server: PropTypes.string.isRequired, |
41 | }; | 42 | }; |
42 | 43 | ||
43 | static contextTypes = { | 44 | ferdiServer = LIVE_FERDI_API; |
44 | intl: intlShape, | ||
45 | }; | ||
46 | |||
47 | ferdiServer=LIVE_FERDI_API; | ||
48 | 45 | ||
49 | franzServer=LIVE_FRANZ_API; | 46 | franzServer = LIVE_FRANZ_API; |
50 | 47 | ||
51 | defaultServers=[this.franzServer, this.ferdiServer]; | 48 | defaultServers = [this.franzServer, this.ferdiServer]; |
52 | 49 | ||
53 | form = new Form({ | 50 | form = new Form( |
54 | fields: { | 51 | { |
55 | server: { | 52 | fields: { |
56 | label: this.context.intl.formatMessage(messages.label), | 53 | server: { |
57 | value: this.props.server, | 54 | label: this.props.intl.formatMessage(messages.label), |
58 | options: [{ value: this.ferdiServer, label: 'Ferdi' }, { value: this.franzServer, label: 'Franz' }, { value: this.defaultServers.includes(this.props.server) ? '' : this.props.server, label: 'Custom' }], | 55 | value: this.props.server, |
59 | }, | 56 | options: [ |
60 | customServer: { | 57 | { value: this.ferdiServer, label: 'Ferdi' }, |
61 | label: this.context.intl.formatMessage(messages.customServerLabel), | 58 | { value: this.franzServer, label: 'Franz' }, |
62 | value: '', | 59 | { |
63 | validators: [url, required], | 60 | value: this.defaultServers.includes(this.props.server) |
61 | ? '' | ||
62 | : this.props.server, | ||
63 | label: 'Custom', | ||
64 | }, | ||
65 | ], | ||
66 | }, | ||
67 | customServer: { | ||
68 | label: this.props.intl.formatMessage(messages.customServerLabel), | ||
69 | value: '', | ||
70 | validators: [url, required], | ||
71 | }, | ||
64 | }, | 72 | }, |
65 | }, | 73 | }, |
66 | }, this.context.intl); | 74 | this.props.intl, |
75 | ); | ||
67 | 76 | ||
68 | componentDidMount() { | 77 | componentDidMount() { |
69 | if (this.defaultServers.includes(this.props.server)) { | 78 | if (this.defaultServers.includes(this.props.server)) { |
@@ -77,13 +86,13 @@ export default @observer class ChangeServer extends Component { | |||
77 | submit(e) { | 86 | submit(e) { |
78 | e.preventDefault(); | 87 | e.preventDefault(); |
79 | this.form.submit({ | 88 | this.form.submit({ |
80 | onSuccess: (form) => { | 89 | onSuccess: form => { |
81 | if (!this.defaultServers.includes(form.values().server)) { | 90 | if (!this.defaultServers.includes(form.values().server)) { |
82 | form.$('server').onChange(form.values().customServer); | 91 | form.$('server').onChange(form.values().customServer); |
83 | } | 92 | } |
84 | this.props.onSubmit(form.values()); | 93 | this.props.onSubmit(form.values()); |
85 | }, | 94 | }, |
86 | onError: (form) => { | 95 | onError: form => { |
87 | if (this.defaultServers.includes(form.values().server)) { | 96 | if (this.defaultServers.includes(form.values().server)) { |
88 | this.props.onSubmit(form.values()); | 97 | this.props.onSubmit(form.values()); |
89 | } | 98 | } |
@@ -93,23 +102,21 @@ export default @observer class ChangeServer extends Component { | |||
93 | 102 | ||
94 | render() { | 103 | render() { |
95 | const { form } = this; | 104 | const { form } = this; |
96 | const { intl } = this.context; | 105 | const { intl } = this.props; |
97 | return ( | 106 | return ( |
98 | <div className="auth__container"> | 107 | <div className="auth__container"> |
99 | <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> | 108 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
100 | <h1>{intl.formatMessage(messages.headline)}</h1> | 109 | <h1>{intl.formatMessage(messages.headline)}</h1> |
101 | {form.$('server').value === this.franzServer | 110 | {form.$('server').value === this.franzServer && ( |
102 | && ( | ||
103 | <Infobox type="warning"> | 111 | <Infobox type="warning"> |
104 | {intl.formatMessage(messages.warning)} | 112 | {intl.formatMessage(messages.warning)} |
105 | </Infobox> | 113 | </Infobox> |
106 | )} | 114 | )} |
107 | <Select field={form.$('server')} /> | 115 | <Select field={form.$('server')} /> |
108 | {!this.defaultServers.includes(form.$('server').value) | 116 | {!this.defaultServers.includes(form.$('server').value) && ( |
109 | && ( | ||
110 | <Input | 117 | <Input |
111 | placeholder="Custom Server" | 118 | placeholder="Custom Server" |
112 | onChange={(e) => this.submit(e)} | 119 | onChange={e => this.submit(e)} |
113 | field={form.$('customServer')} | 120 | field={form.$('customServer')} |
114 | /> | 121 | /> |
115 | )} | 122 | )} |
@@ -123,3 +130,5 @@ export default @observer class ChangeServer extends Component { | |||
123 | ); | 130 | ); |
124 | } | 131 | } |
125 | } | 132 | } |
133 | |||
134 | export default injectIntl(ChangeServer); | ||
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js index 3073cad73..44cb7e791 100644 --- a/src/components/auth/Import.js +++ b/src/components/auth/Import.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | 7 | ||
@@ -12,23 +12,22 @@ import Button from '../ui/Button'; | |||
12 | const messages = defineMessages({ | 12 | const messages = defineMessages({ |
13 | headline: { | 13 | headline: { |
14 | id: 'import.headline', | 14 | id: 'import.headline', |
15 | defaultMessage: '!!!Import your Ferdi 4 services', | 15 | defaultMessage: 'Import your Ferdi 4 services', |
16 | }, | 16 | }, |
17 | notSupportedHeadline: { | 17 | notSupportedHeadline: { |
18 | id: 'import.notSupportedHeadline', | 18 | id: 'import.notSupportedHeadline', |
19 | defaultMessage: '!!!Services not yet supported in Ferdi 5', | 19 | defaultMessage: 'Services not yet supported in Ferdi 5', |
20 | }, | 20 | }, |
21 | submitButtonLabel: { | 21 | submitButtonLabel: { |
22 | id: 'import.submit.label', | 22 | id: 'import.submit.label', |
23 | defaultMessage: '!!!Import {count} services', | 23 | defaultMessage: 'Import {count} services', |
24 | }, | 24 | }, |
25 | skipButtonLabel: { | 25 | skipButtonLabel: { |
26 | id: 'import.skip.label', | 26 | id: 'import.skip.label', |
27 | defaultMessage: '!!!I want to add services manually', | 27 | defaultMessage: 'I want to add services manually', |
28 | }, | 28 | }, |
29 | }); | 29 | }); |
30 | 30 | ||
31 | export default | ||
32 | @observer | 31 | @observer |
33 | class Import extends Component { | 32 | class Import extends Component { |
34 | static propTypes = { | 33 | static propTypes = { |
@@ -38,17 +37,13 @@ class Import extends Component { | |||
38 | inviteRoute: PropTypes.string.isRequired, | 37 | inviteRoute: PropTypes.string.isRequired, |
39 | }; | 38 | }; |
40 | 39 | ||
41 | static contextTypes = { | ||
42 | intl: intlShape, | ||
43 | }; | ||
44 | |||
45 | componentDidMount() { | 40 | componentDidMount() { |
46 | const config = { | 41 | const config = { |
47 | fields: { | 42 | fields: { |
48 | import: [ | 43 | import: [ |
49 | ...this.props.services | 44 | ...this.props.services |
50 | .filter((s) => s.recipe) | 45 | .filter(s => s.recipe) |
51 | .map((s) => ({ | 46 | .map(s => ({ |
52 | fields: { | 47 | fields: { |
53 | add: { | 48 | add: { |
54 | default: true, | 49 | default: true, |
@@ -60,20 +55,20 @@ class Import extends Component { | |||
60 | }, | 55 | }, |
61 | }; | 56 | }; |
62 | 57 | ||
63 | this.form = new Form(config, this.context.intl); | 58 | this.form = new Form(config, this.props.intl); |
64 | } | 59 | } |
65 | 60 | ||
66 | submit(e) { | 61 | submit(e) { |
67 | const { services } = this.props; | 62 | const { services } = this.props; |
68 | e.preventDefault(); | 63 | e.preventDefault(); |
69 | this.form.submit({ | 64 | this.form.submit({ |
70 | onSuccess: (form) => { | 65 | onSuccess: form => { |
71 | const servicesImport = form | 66 | const servicesImport = form |
72 | .values() | 67 | .values() |
73 | .import.map( | 68 | .import.map( |
74 | (value, i) => !value.add || services.filter((s) => s.recipe)[i], | 69 | (value, i) => !value.add || services.filter(s => s.recipe)[i], |
75 | ) | 70 | ) |
76 | .filter((s) => typeof s !== 'boolean'); | 71 | .filter(s => typeof s !== 'boolean'); |
77 | 72 | ||
78 | this.props.onSubmit({ services: servicesImport }); | 73 | this.props.onSubmit({ services: servicesImport }); |
79 | }, | 74 | }, |
@@ -82,18 +77,18 @@ class Import extends Component { | |||
82 | } | 77 | } |
83 | 78 | ||
84 | render() { | 79 | render() { |
85 | const { intl } = this.context; | 80 | const { intl } = this.props; |
86 | const { services, isSubmitting, inviteRoute } = this.props; | 81 | const { services, isSubmitting, inviteRoute } = this.props; |
87 | 82 | ||
88 | const availableServices = services.filter((s) => s.recipe); | 83 | const availableServices = services.filter(s => s.recipe); |
89 | const unavailableServices = services.filter((s) => !s.recipe); | 84 | const unavailableServices = services.filter(s => !s.recipe); |
90 | 85 | ||
91 | return ( | 86 | return ( |
92 | <div className="auth__scroll-container"> | 87 | <div className="auth__scroll-container"> |
93 | <div className="auth__container auth__container--signup"> | 88 | <div className="auth__container auth__container--signup"> |
94 | <form | 89 | <form |
95 | className="franz-form auth__form" | 90 | className="franz-form auth__form" |
96 | onSubmit={(e) => this.submit(e)} | 91 | onSubmit={e => this.submit(e)} |
97 | > | 92 | > |
98 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> | 93 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> |
99 | <h1>{intl.formatMessage(messages.headline)}</h1> | 94 | <h1>{intl.formatMessage(messages.headline)}</h1> |
@@ -107,8 +102,8 @@ class Import extends Component { | |||
107 | <td className="service-table__column-icon"> | 102 | <td className="service-table__column-icon"> |
108 | <img | 103 | <img |
109 | src={ | 104 | src={ |
110 | availableServices[i].custom_icon | 105 | availableServices[i].custom_icon || |
111 | || availableServices[i].recipe.icons.svg | 106 | availableServices[i].recipe.icons.svg |
112 | } | 107 | } |
113 | className={classnames({ | 108 | className={classnames({ |
114 | 'service-table__icon': true, | 109 | 'service-table__icon': true, |
@@ -133,7 +128,7 @@ class Import extends Component { | |||
133 | </strong> | 128 | </strong> |
134 | <p> | 129 | <p> |
135 | {services | 130 | {services |
136 | .filter((s) => !s.recipe) | 131 | .filter(s => !s.recipe) |
137 | .map((service, i) => ( | 132 | .map((service, i) => ( |
138 | <span key={service.id}> | 133 | <span key={service.id}> |
139 | {service.name !== '' ? service.name : service.service} | 134 | {service.name !== '' ? service.name : service.service} |
@@ -170,3 +165,5 @@ class Import extends Component { | |||
170 | ); | 165 | ); |
171 | } | 166 | } |
172 | } | 167 | } |
168 | |||
169 | export default injectIntl(Import); | ||
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js index 4b4d63a6b..519691ede 100644 --- a/src/components/auth/Invite.js +++ b/src/components/auth/Invite.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component, Fragment } from 'react'; | 1 | import React, { Component, Fragment } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | 7 | ||
@@ -15,35 +15,34 @@ import Button from '../ui/Button'; | |||
15 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
16 | settingsHeadline: { | 16 | settingsHeadline: { |
17 | id: 'settings.invite.headline', | 17 | id: 'settings.invite.headline', |
18 | defaultMessage: '!!!Invite Friends', | 18 | defaultMessage: 'Invite Friends', |
19 | }, | 19 | }, |
20 | headline: { | 20 | headline: { |
21 | id: 'invite.headline.friends', | 21 | id: 'invite.headline.friends', |
22 | defaultMessage: '!!!Invite 3 of your friends or colleagues', | 22 | defaultMessage: 'Invite 3 of your friends or colleagues', |
23 | }, | 23 | }, |
24 | nameLabel: { | 24 | nameLabel: { |
25 | id: 'invite.name.label', | 25 | id: 'invite.name.label', |
26 | defaultMessage: '!!!Name', | 26 | defaultMessage: 'Name', |
27 | }, | 27 | }, |
28 | emailLabel: { | 28 | emailLabel: { |
29 | id: 'invite.email.label', | 29 | id: 'invite.email.label', |
30 | defaultMessage: '!!!Email address', | 30 | defaultMessage: 'Email address', |
31 | }, | 31 | }, |
32 | submitButtonLabel: { | 32 | submitButtonLabel: { |
33 | id: 'invite.submit.label', | 33 | id: 'invite.submit.label', |
34 | defaultMessage: '!!!Send invites', | 34 | defaultMessage: 'Send invites', |
35 | }, | 35 | }, |
36 | skipButtonLabel: { | 36 | skipButtonLabel: { |
37 | id: 'invite.skip.label', | 37 | id: 'invite.skip.label', |
38 | defaultMessage: '!!!I want to do this later', | 38 | defaultMessage: 'I want to do this later', |
39 | }, | 39 | }, |
40 | inviteSuccessInfo: { | 40 | inviteSuccessInfo: { |
41 | id: 'invite.successInfo', | 41 | id: 'invite.successInfo', |
42 | defaultMessage: '!!!Invitations sent successfully', | 42 | defaultMessage: 'Invitations sent successfully', |
43 | }, | 43 | }, |
44 | }); | 44 | }); |
45 | 45 | ||
46 | export default | ||
47 | @observer | 46 | @observer |
48 | class Invite extends Component { | 47 | class Invite extends Component { |
49 | static propTypes = { | 48 | static propTypes = { |
@@ -59,10 +58,6 @@ class Invite extends Component { | |||
59 | isLoadingInvite: false, | 58 | isLoadingInvite: false, |
60 | }; | 59 | }; |
61 | 60 | ||
62 | static contextTypes = { | ||
63 | intl: intlShape, | ||
64 | }; | ||
65 | |||
66 | state = { showSuccessInfo: false }; | 61 | state = { showSuccessInfo: false }; |
67 | 62 | ||
68 | componentDidMount() { | 63 | componentDidMount() { |
@@ -73,8 +68,8 @@ class Invite extends Component { | |||
73 | ...Array(3).fill({ | 68 | ...Array(3).fill({ |
74 | fields: { | 69 | fields: { |
75 | name: { | 70 | name: { |
76 | label: this.context.intl.formatMessage(messages.nameLabel), | 71 | label: this.props.intl.formatMessage(messages.nameLabel), |
77 | placeholder: this.context.intl.formatMessage( | 72 | placeholder: this.props.intl.formatMessage( |
78 | messages.nameLabel, | 73 | messages.nameLabel, |
79 | ), | 74 | ), |
80 | onChange: () => { | 75 | onChange: () => { |
@@ -83,8 +78,8 @@ class Invite extends Component { | |||
83 | // related: ['invite.0.email'], // path accepted but does not work | 78 | // related: ['invite.0.email'], // path accepted but does not work |
84 | }, | 79 | }, |
85 | email: { | 80 | email: { |
86 | label: this.context.intl.formatMessage(messages.emailLabel), | 81 | label: this.props.intl.formatMessage(messages.emailLabel), |
87 | placeholder: this.context.intl.formatMessage( | 82 | placeholder: this.props.intl.formatMessage( |
88 | messages.emailLabel, | 83 | messages.emailLabel, |
89 | ), | 84 | ), |
90 | onChange: () => { | 85 | onChange: () => { |
@@ -97,7 +92,7 @@ class Invite extends Component { | |||
97 | ], | 92 | ], |
98 | }, | 93 | }, |
99 | }, | 94 | }, |
100 | this.context.intl, | 95 | this.props.intl, |
101 | ); | 96 | ); |
102 | 97 | ||
103 | document.querySelector('input:first-child').focus(); | 98 | document.querySelector('input:first-child').focus(); |
@@ -107,7 +102,7 @@ class Invite extends Component { | |||
107 | e.preventDefault(); | 102 | e.preventDefault(); |
108 | 103 | ||
109 | this.form.submit({ | 104 | this.form.submit({ |
110 | onSuccess: (form) => { | 105 | onSuccess: form => { |
111 | this.props.onSubmit({ invites: form.values().invite }); | 106 | this.props.onSubmit({ invites: form.values().invite }); |
112 | 107 | ||
113 | this.form.clear(); | 108 | this.form.clear(); |
@@ -121,13 +116,13 @@ class Invite extends Component { | |||
121 | 116 | ||
122 | render() { | 117 | render() { |
123 | const { form } = this; | 118 | const { form } = this; |
124 | const { intl } = this.context; | 119 | const { intl } = this.props; |
125 | const { embed, isInviteSuccessful, isLoadingInvite } = this.props; | 120 | const { embed, isInviteSuccessful, isLoadingInvite } = this.props; |
126 | 121 | ||
127 | const atLeastOneEmailAddress = form | 122 | const atLeastOneEmailAddress = form |
128 | .$('invite') | 123 | .$('invite') |
129 | .map((invite) => invite.$('email').value) | 124 | .map(invite => invite.$('email').value) |
130 | .some((emailValue) => emailValue.trim() !== ''); | 125 | .some(emailValue => emailValue.trim() !== ''); |
131 | 126 | ||
132 | const sendButtonClassName = classnames({ | 127 | const sendButtonClassName = classnames({ |
133 | auth__button: true, | 128 | auth__button: true, |
@@ -148,17 +143,14 @@ class Invite extends Component { | |||
148 | </Appear> | 143 | </Appear> |
149 | )} | 144 | )} |
150 | 145 | ||
151 | <form | 146 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
152 | className="franz-form auth__form" | ||
153 | onSubmit={(e) => this.submit(e)} | ||
154 | > | ||
155 | {!embed && ( | 147 | {!embed && ( |
156 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> | 148 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> |
157 | )} | 149 | )} |
158 | <h1 className={embed && 'invite__embed'}> | 150 | <h1 className={embed && 'invite__embed'}> |
159 | {intl.formatMessage(messages.headline)} | 151 | {intl.formatMessage(messages.headline)} |
160 | </h1> | 152 | </h1> |
161 | {form.$('invite').map((invite) => ( | 153 | {form.$('invite').map(invite => ( |
162 | <div className="grid" key={invite.key}> | 154 | <div className="grid" key={invite.key}> |
163 | <div className="grid__row"> | 155 | <div className="grid__row"> |
164 | <Input field={invite.$('name')} showLabel={false} /> | 156 | <Input field={invite.$('name')} showLabel={false} /> |
@@ -193,9 +185,7 @@ class Invite extends Component { | |||
193 | > | 185 | > |
194 | {embed && ( | 186 | {embed && ( |
195 | <div className="settings__header"> | 187 | <div className="settings__header"> |
196 | <h1> | 188 | <h1>{this.props.intl.formatMessage(messages.settingsHeadline)}</h1> |
197 | {this.context.intl.formatMessage(messages.settingsHeadline)} | ||
198 | </h1> | ||
199 | </div> | 189 | </div> |
200 | )} | 190 | )} |
201 | {!embed ? ( | 191 | {!embed ? ( |
@@ -207,3 +197,5 @@ class Invite extends Component { | |||
207 | ); | 197 | ); |
208 | } | 198 | } |
209 | } | 199 | } |
200 | |||
201 | export default injectIntl(Invite); | ||
diff --git a/src/components/auth/Locked.js b/src/components/auth/Locked.js index 2ad8a2409..a507ba140 100644 --- a/src/components/auth/Locked.js +++ b/src/components/auth/Locked.js | |||
@@ -2,7 +2,7 @@ import { systemPreferences } from '@electron/remote'; | |||
2 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer } from 'mobx-react'; | 4 | import { observer } from 'mobx-react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import Form from '../../lib/Form'; | 7 | import Form from '../../lib/Form'; |
8 | import Input from '../ui/Input'; | 8 | import Input from '../ui/Input'; |
@@ -15,39 +15,41 @@ import { globalError as globalErrorPropType } from '../../prop-types'; | |||
15 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
16 | headline: { | 16 | headline: { |
17 | id: 'locked.headline', | 17 | id: 'locked.headline', |
18 | defaultMessage: '!!!Locked', | 18 | defaultMessage: 'Locked', |
19 | }, | 19 | }, |
20 | info: { | 20 | info: { |
21 | id: 'locked.info', | 21 | id: 'locked.info', |
22 | defaultMessage: '!!!Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.', | 22 | defaultMessage: |
23 | 'Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.', | ||
23 | }, | 24 | }, |
24 | touchId: { | 25 | touchId: { |
25 | id: 'locked.touchId', | 26 | id: 'locked.touchId', |
26 | defaultMessage: '!!!Unlock with Touch ID', | 27 | defaultMessage: 'Unlock with Touch ID', |
27 | }, | 28 | }, |
28 | touchIdPrompt: { | 29 | touchIdPrompt: { |
29 | id: 'locked.touchIdPrompt', | 30 | id: 'locked.touchIdPrompt', |
30 | defaultMessage: '!!!unlock via Touch ID', | 31 | defaultMessage: 'unlock via Touch ID', |
31 | }, | 32 | }, |
32 | passwordLabel: { | 33 | passwordLabel: { |
33 | id: 'locked.password.label', | 34 | id: 'locked.password.label', |
34 | defaultMessage: '!!!Password', | 35 | defaultMessage: 'Password', |
35 | }, | 36 | }, |
36 | submitButtonLabel: { | 37 | submitButtonLabel: { |
37 | id: 'locked.submit.label', | 38 | id: 'locked.submit.label', |
38 | defaultMessage: '!!!Unlock', | 39 | defaultMessage: 'Unlock', |
39 | }, | 40 | }, |
40 | unlockWithPassword: { | 41 | unlockWithPassword: { |
41 | id: 'locked.unlockWithPassword', | 42 | id: 'locked.unlockWithPassword', |
42 | defaultMessage: '!!!Unlock with Password', | 43 | defaultMessage: 'Unlock with Password', |
43 | }, | 44 | }, |
44 | invalidCredentials: { | 45 | invalidCredentials: { |
45 | id: 'locked.invalidCredentials', | 46 | id: 'locked.invalidCredentials', |
46 | defaultMessage: '!!!Password invalid', | 47 | defaultMessage: 'Password invalid', |
47 | }, | 48 | }, |
48 | }); | 49 | }); |
49 | 50 | ||
50 | export default @observer class Locked extends Component { | 51 | @observer |
52 | class Locked extends Component { | ||
51 | static propTypes = { | 53 | static propTypes = { |
52 | onSubmit: PropTypes.func.isRequired, | 54 | onSubmit: PropTypes.func.isRequired, |
53 | unlock: PropTypes.func.isRequired, | 55 | unlock: PropTypes.func.isRequired, |
@@ -56,62 +58,57 @@ export default @observer class Locked extends Component { | |||
56 | error: globalErrorPropType.isRequired, | 58 | error: globalErrorPropType.isRequired, |
57 | }; | 59 | }; |
58 | 60 | ||
59 | static contextTypes = { | 61 | form = new Form( |
60 | intl: intlShape, | 62 | { |
61 | }; | 63 | fields: { |
62 | 64 | password: { | |
63 | form = new Form({ | 65 | label: this.props.intl.formatMessage(messages.passwordLabel), |
64 | fields: { | 66 | value: '', |
65 | password: { | 67 | type: 'password', |
66 | label: this.context.intl.formatMessage(messages.passwordLabel), | 68 | }, |
67 | value: '', | ||
68 | type: 'password', | ||
69 | }, | 69 | }, |
70 | }, | 70 | }, |
71 | }, this.context.intl); | 71 | this.props.intl, |
72 | ); | ||
72 | 73 | ||
73 | submit(e) { | 74 | submit(e) { |
74 | e.preventDefault(); | 75 | e.preventDefault(); |
75 | this.form.submit({ | 76 | this.form.submit({ |
76 | onSuccess: (form) => { | 77 | onSuccess: form => { |
77 | this.props.onSubmit(form.values()); | 78 | this.props.onSubmit(form.values()); |
78 | }, | 79 | }, |
79 | onError: () => { }, | 80 | onError: () => {}, |
80 | }); | 81 | }); |
81 | } | 82 | } |
82 | 83 | ||
83 | touchIdUnlock() { | 84 | touchIdUnlock() { |
84 | const { intl } = this.context; | 85 | const { intl } = this.props; |
85 | 86 | ||
86 | systemPreferences.promptTouchID(intl.formatMessage(messages.touchIdPrompt)).then(() => { | 87 | systemPreferences |
87 | this.props.unlock(); | 88 | .promptTouchID(intl.formatMessage(messages.touchIdPrompt)) |
88 | }); | 89 | .then(() => { |
90 | this.props.unlock(); | ||
91 | }); | ||
89 | } | 92 | } |
90 | 93 | ||
91 | render() { | 94 | render() { |
92 | const { form } = this; | 95 | const { form } = this; |
93 | const { intl } = this.context; | 96 | const { intl } = this.props; |
94 | const { | 97 | const { isSubmitting, error, useTouchIdToUnlock } = this.props; |
95 | isSubmitting, | ||
96 | error, | ||
97 | useTouchIdToUnlock, | ||
98 | } = this.props; | ||
99 | 98 | ||
100 | const touchIdEnabled = isMac ? (useTouchIdToUnlock && systemPreferences.canPromptTouchID()) : false; | 99 | const touchIdEnabled = isMac |
101 | const submitButtonLabel = touchIdEnabled ? intl.formatMessage(messages.unlockWithPassword) : intl.formatMessage(messages.submitButtonLabel); | 100 | ? useTouchIdToUnlock && systemPreferences.canPromptTouchID() |
101 | : false; | ||
102 | const submitButtonLabel = touchIdEnabled | ||
103 | ? intl.formatMessage(messages.unlockWithPassword) | ||
104 | : intl.formatMessage(messages.submitButtonLabel); | ||
102 | 105 | ||
103 | return ( | 106 | return ( |
104 | <div className="auth__container"> | 107 | <div className="auth__container"> |
105 | <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> | 108 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
106 | <img | 109 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> |
107 | src="./assets/images/logo.svg" | ||
108 | className="auth__logo" | ||
109 | alt="" | ||
110 | /> | ||
111 | <h1>{intl.formatMessage(messages.headline)}</h1> | 110 | <h1>{intl.formatMessage(messages.headline)}</h1> |
112 | <Infobox type="warning"> | 111 | <Infobox type="warning">{intl.formatMessage(messages.info)}</Infobox> |
113 | {intl.formatMessage(messages.info)} | ||
114 | </Infobox> | ||
115 | 112 | ||
116 | {touchIdEnabled && ( | 113 | {touchIdEnabled && ( |
117 | <> | 114 | <> |
@@ -125,13 +122,11 @@ export default @observer class Locked extends Component { | |||
125 | </> | 122 | </> |
126 | )} | 123 | )} |
127 | 124 | ||
128 | <Input | 125 | <Input field={form.$('password')} showPasswordToggle focus /> |
129 | field={form.$('password')} | ||
130 | showPasswordToggle | ||
131 | focus | ||
132 | /> | ||
133 | {error.code === 'invalid-credentials' && ( | 126 | {error.code === 'invalid-credentials' && ( |
134 | <p className="error-message center">{intl.formatMessage(messages.invalidCredentials)}</p> | 127 | <p className="error-message center"> |
128 | {intl.formatMessage(messages.invalidCredentials)} | ||
129 | </p> | ||
135 | )} | 130 | )} |
136 | {isSubmitting ? ( | 131 | {isSubmitting ? ( |
137 | <Button | 132 | <Button |
@@ -153,3 +148,5 @@ export default @observer class Locked extends Component { | |||
153 | ); | 148 | ); |
154 | } | 149 | } |
155 | } | 150 | } |
151 | |||
152 | export default injectIntl(Locked); | ||
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js index 9e6a8d046..a47834e19 100644 --- a/src/components/auth/Login.js +++ b/src/components/auth/Login.js | |||
@@ -2,7 +2,7 @@ | |||
2 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer, inject } from 'mobx-react'; | 4 | import { observer, inject } from 'mobx-react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import { LIVE_FRANZ_API } from '../../config'; | 7 | import { LIVE_FRANZ_API } from '../../config'; |
8 | import { API_VERSION, isDevMode, useLiveAPI } from '../../environment'; | 8 | import { API_VERSION, isDevMode, useLiveAPI } from '../../environment'; |
@@ -19,59 +19,61 @@ import { globalError as globalErrorPropType } from '../../prop-types'; | |||
19 | const messages = defineMessages({ | 19 | const messages = defineMessages({ |
20 | headline: { | 20 | headline: { |
21 | id: 'login.headline', | 21 | id: 'login.headline', |
22 | defaultMessage: '!!!Sign in', | 22 | defaultMessage: 'Sign in', |
23 | }, | 23 | }, |
24 | emailLabel: { | 24 | emailLabel: { |
25 | id: 'login.email.label', | 25 | id: 'login.email.label', |
26 | defaultMessage: '!!!Email address', | 26 | defaultMessage: 'Email address', |
27 | }, | 27 | }, |
28 | passwordLabel: { | 28 | passwordLabel: { |
29 | id: 'login.password.label', | 29 | id: 'login.password.label', |
30 | defaultMessage: '!!!Password', | 30 | defaultMessage: 'Password', |
31 | }, | 31 | }, |
32 | submitButtonLabel: { | 32 | submitButtonLabel: { |
33 | id: 'login.submit.label', | 33 | id: 'login.submit.label', |
34 | defaultMessage: '!!!Sign in', | 34 | defaultMessage: 'Sign in', |
35 | }, | 35 | }, |
36 | invalidCredentials: { | 36 | invalidCredentials: { |
37 | id: 'login.invalidCredentials', | 37 | id: 'login.invalidCredentials', |
38 | defaultMessage: '!!!Email or password not valid', | 38 | defaultMessage: 'Email or password not valid', |
39 | }, | 39 | }, |
40 | customServerQuestion: { | 40 | customServerQuestion: { |
41 | id: 'login.customServerQuestion', | 41 | id: 'login.customServerQuestion', |
42 | defaultMessage: '!!!Using a Franz account to log in?', | 42 | defaultMessage: 'Using a Franz account to log in?', |
43 | }, | 43 | }, |
44 | customServerSuggestion: { | 44 | customServerSuggestion: { |
45 | id: 'login.customServerSuggestion', | 45 | id: 'login.customServerSuggestion', |
46 | defaultMessage: '!!!Try importing your Franz account into Ferdi', | 46 | defaultMessage: 'Try importing your Franz account into Ferdi', |
47 | }, | 47 | }, |
48 | tokenExpired: { | 48 | tokenExpired: { |
49 | id: 'login.tokenExpired', | 49 | id: 'login.tokenExpired', |
50 | defaultMessage: '!!!Your session expired, please login again.', | 50 | defaultMessage: 'Your session expired, please login again.', |
51 | }, | 51 | }, |
52 | serverLogout: { | 52 | serverLogout: { |
53 | id: 'login.serverLogout', | 53 | id: 'login.serverLogout', |
54 | defaultMessage: '!!!Your session expired, please login again.', | 54 | defaultMessage: 'Your session expired, please login again.', |
55 | }, | 55 | }, |
56 | signupLink: { | 56 | signupLink: { |
57 | id: 'login.link.signup', | 57 | id: 'login.link.signup', |
58 | defaultMessage: '!!!Create a free account', | 58 | defaultMessage: 'Create a free account', |
59 | }, | 59 | }, |
60 | changeServer: { | 60 | changeServer: { |
61 | id: 'login.changeServer', | 61 | id: 'login.changeServer', |
62 | defaultMessage: '!!!Change server', | 62 | defaultMessage: 'Change server', |
63 | }, | 63 | }, |
64 | serverless: { | 64 | serverless: { |
65 | id: 'services.serverless', | 65 | id: 'services.serverless', |
66 | defaultMessage: '!!!Use Ferdi without an Account', | 66 | defaultMessage: 'Use Ferdi without an Account', |
67 | }, | 67 | }, |
68 | passwordLink: { | 68 | passwordLink: { |
69 | id: 'login.link.password', | 69 | id: 'login.link.password', |
70 | defaultMessage: '!!!Forgot password', | 70 | defaultMessage: 'Forgot password', |
71 | }, | 71 | }, |
72 | }); | 72 | }); |
73 | 73 | ||
74 | export default @inject('actions') @observer class Login extends Component { | 74 | @inject('actions') |
75 | @observer | ||
76 | class Login extends Component { | ||
75 | static propTypes = { | 77 | static propTypes = { |
76 | onSubmit: PropTypes.func.isRequired, | 78 | onSubmit: PropTypes.func.isRequired, |
77 | isSubmitting: PropTypes.bool.isRequired, | 79 | isSubmitting: PropTypes.bool.isRequired, |
@@ -84,35 +86,34 @@ export default @inject('actions') @observer class Login extends Component { | |||
84 | actions: PropTypes.object.isRequired, | 86 | actions: PropTypes.object.isRequired, |
85 | }; | 87 | }; |
86 | 88 | ||
87 | static contextTypes = { | 89 | form = new Form( |
88 | intl: intlShape, | 90 | { |
89 | }; | 91 | fields: { |
90 | 92 | email: { | |
91 | form = new Form({ | 93 | label: this.props.intl.formatMessage(messages.emailLabel), |
92 | fields: { | 94 | value: '', |
93 | email: { | 95 | validators: [required, email], |
94 | label: this.context.intl.formatMessage(messages.emailLabel), | 96 | }, |
95 | value: '', | 97 | password: { |
96 | validators: [required, email], | 98 | label: this.props.intl.formatMessage(messages.passwordLabel), |
97 | }, | 99 | value: '', |
98 | password: { | 100 | validators: [required], |
99 | label: this.context.intl.formatMessage(messages.passwordLabel), | 101 | type: 'password', |
100 | value: '', | 102 | }, |
101 | validators: [required], | ||
102 | type: 'password', | ||
103 | }, | 103 | }, |
104 | }, | 104 | }, |
105 | }, this.context.intl); | 105 | this.props.intl, |
106 | ); | ||
106 | 107 | ||
107 | emailField = null; | 108 | emailField = null; |
108 | 109 | ||
109 | submit(e) { | 110 | submit(e) { |
110 | e.preventDefault(); | 111 | e.preventDefault(); |
111 | this.form.submit({ | 112 | this.form.submit({ |
112 | onSuccess: (form) => { | 113 | onSuccess: form => { |
113 | this.props.onSubmit(form.values()); | 114 | this.props.onSubmit(form.values()); |
114 | }, | 115 | }, |
115 | onError: () => { }, | 116 | onError: () => {}, |
116 | }); | 117 | }); |
117 | } | 118 | } |
118 | 119 | ||
@@ -122,7 +123,7 @@ export default @inject('actions') @observer class Login extends Component { | |||
122 | 123 | ||
123 | render() { | 124 | render() { |
124 | const { form } = this; | 125 | const { form } = this; |
125 | const { intl } = this.context; | 126 | const { intl } = this.props; |
126 | const { | 127 | const { |
127 | isSubmitting, | 128 | isSubmitting, |
128 | isTokenExpired, | 129 | isTokenExpired, |
@@ -135,42 +136,47 @@ export default @inject('actions') @observer class Login extends Component { | |||
135 | 136 | ||
136 | return ( | 137 | return ( |
137 | <div className="auth__container"> | 138 | <div className="auth__container"> |
138 | <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> | 139 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
139 | <img | 140 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> |
140 | src="./assets/images/logo.svg" | ||
141 | className="auth__logo" | ||
142 | alt="" | ||
143 | /> | ||
144 | <h1>{intl.formatMessage(messages.headline)}</h1> | 141 | <h1>{intl.formatMessage(messages.headline)}</h1> |
145 | {isDevMode && !useLiveAPI && ( | 142 | {isDevMode && !useLiveAPI && ( |
146 | <Infobox type="warning"> | 143 | <Infobox type="warning"> |
147 | In Dev Mode your data is not persistent. Please use the live app for accessing the production API. | 144 | In Dev Mode your data is not persistent. Please use the live app |
145 | for accessing the production API. | ||
148 | </Infobox> | 146 | </Infobox> |
149 | )} | 147 | )} |
150 | {isTokenExpired && ( | 148 | {isTokenExpired && ( |
151 | <p className="error-message center">{intl.formatMessage(messages.tokenExpired)}</p> | 149 | <p className="error-message center"> |
150 | {intl.formatMessage(messages.tokenExpired)} | ||
151 | </p> | ||
152 | )} | 152 | )} |
153 | {isServerLogout && ( | 153 | {isServerLogout && ( |
154 | <p className="error-message center">{intl.formatMessage(messages.serverLogout)}</p> | 154 | <p className="error-message center"> |
155 | {intl.formatMessage(messages.serverLogout)} | ||
156 | </p> | ||
155 | )} | 157 | )} |
156 | <Input | 158 | <Input |
157 | field={form.$('email')} | 159 | field={form.$('email')} |
158 | ref={(element) => { this.emailField = element; }} | 160 | ref={element => { |
161 | this.emailField = element; | ||
162 | }} | ||
159 | focus | 163 | focus |
160 | /> | 164 | /> |
161 | <Input | 165 | <Input field={form.$('password')} showPasswordToggle /> |
162 | field={form.$('password')} | ||
163 | showPasswordToggle | ||
164 | /> | ||
165 | {error.code === 'invalid-credentials' && ( | 166 | {error.code === 'invalid-credentials' && ( |
166 | <> | 167 | <> |
167 | <p className="error-message center">{intl.formatMessage(messages.invalidCredentials)}</p> | 168 | <p className="error-message center"> |
168 | { window.ferdi.stores.settings.all.app.server !== LIVE_FRANZ_API && ( | 169 | {intl.formatMessage(messages.invalidCredentials)} |
170 | </p> | ||
171 | {window.ferdi.stores.settings.all.app.server !== | ||
172 | LIVE_FRANZ_API && ( | ||
169 | <p className="error-message center"> | 173 | <p className="error-message center"> |
170 | {intl.formatMessage(messages.customServerQuestion)} | 174 | {intl.formatMessage(messages.customServerQuestion)}{' '} |
171 | {' '} | ||
172 | <Link | 175 | <Link |
173 | to={`${window.ferdi.stores.settings.all.app.server.replace(API_VERSION, '')}/import`} | 176 | to={`${window.ferdi.stores.settings.all.app.server.replace( |
177 | API_VERSION, | ||
178 | '', | ||
179 | )}/import`} | ||
174 | target="_blank" | 180 | target="_blank" |
175 | style={{ cursor: 'pointer', textDecoration: 'underline' }} | 181 | style={{ cursor: 'pointer', textDecoration: 'underline' }} |
176 | > | 182 | > |
@@ -197,12 +203,22 @@ export default @inject('actions') @observer class Login extends Component { | |||
197 | )} | 203 | )} |
198 | </form> | 204 | </form> |
199 | <div className="auth__links"> | 205 | <div className="auth__links"> |
200 | <Link to={changeServerRoute}>{intl.formatMessage(messages.changeServer)}</Link> | 206 | <Link to={changeServerRoute}> |
201 | <a onClick={this.useLocalServer.bind(this)}>{intl.formatMessage(messages.serverless)}</a> | 207 | {intl.formatMessage(messages.changeServer)} |
202 | <Link to={signupRoute}>{intl.formatMessage(messages.signupLink)}</Link> | 208 | </Link> |
203 | <Link to={passwordRoute}>{intl.formatMessage(messages.passwordLink)}</Link> | 209 | <a onClick={this.useLocalServer.bind(this)}> |
210 | {intl.formatMessage(messages.serverless)} | ||
211 | </a> | ||
212 | <Link to={signupRoute}> | ||
213 | {intl.formatMessage(messages.signupLink)} | ||
214 | </Link> | ||
215 | <Link to={passwordRoute}> | ||
216 | {intl.formatMessage(messages.passwordLink)} | ||
217 | </Link> | ||
204 | </div> | 218 | </div> |
205 | </div> | 219 | </div> |
206 | ); | 220 | ); |
207 | } | 221 | } |
208 | } | 222 | } |
223 | |||
224 | export default injectIntl(Login); | ||
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js index 1be2097bd..74346b382 100644 --- a/src/components/auth/Password.js +++ b/src/components/auth/Password.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import Form from '../../lib/Form'; | 6 | import Form from '../../lib/Form'; |
7 | import { required, email } from '../../helpers/validation-helpers'; | 7 | import { required, email } from '../../helpers/validation-helpers'; |
@@ -14,31 +14,32 @@ import globalMessages from '../../i18n/globalMessages'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'password.headline', | 16 | id: 'password.headline', |
17 | defaultMessage: '!!!Forgot password', | 17 | defaultMessage: 'Forgot password', |
18 | }, | 18 | }, |
19 | emailLabel: { | 19 | emailLabel: { |
20 | id: 'password.email.label', | 20 | id: 'password.email.label', |
21 | defaultMessage: '!!!Email address', | 21 | defaultMessage: 'Email address', |
22 | }, | 22 | }, |
23 | successInfo: { | 23 | successInfo: { |
24 | id: 'password.successInfo', | 24 | id: 'password.successInfo', |
25 | defaultMessage: '!!!Your new password was sent to your email address', | 25 | defaultMessage: 'Your new password was sent to your email address', |
26 | }, | 26 | }, |
27 | noUser: { | 27 | noUser: { |
28 | id: 'password.noUser', | 28 | id: 'password.noUser', |
29 | defaultMessage: '!!!No user affiliated with that email address', | 29 | defaultMessage: 'No user affiliated with that email address', |
30 | }, | 30 | }, |
31 | signupLink: { | 31 | signupLink: { |
32 | id: 'password.link.signup', | 32 | id: 'password.link.signup', |
33 | defaultMessage: '!!!Create a free account', | 33 | defaultMessage: 'Create a free account', |
34 | }, | 34 | }, |
35 | loginLink: { | 35 | loginLink: { |
36 | id: 'password.link.login', | 36 | id: 'password.link.login', |
37 | defaultMessage: '!!!Sign in to your account', | 37 | defaultMessage: 'Sign in to your account', |
38 | }, | 38 | }, |
39 | }); | 39 | }); |
40 | 40 | ||
41 | export default @observer class Password extends Component { | 41 | @observer |
42 | class Password extends Component { | ||
42 | static propTypes = { | 43 | static propTypes = { |
43 | onSubmit: PropTypes.func.isRequired, | 44 | onSubmit: PropTypes.func.isRequired, |
44 | isSubmitting: PropTypes.bool.isRequired, | 45 | isSubmitting: PropTypes.bool.isRequired, |
@@ -47,24 +48,23 @@ export default @observer class Password extends Component { | |||
47 | status: MobxPropTypes.arrayOrObservableArray.isRequired, | 48 | status: MobxPropTypes.arrayOrObservableArray.isRequired, |
48 | }; | 49 | }; |
49 | 50 | ||
50 | static contextTypes = { | 51 | form = new Form( |
51 | intl: intlShape, | 52 | { |
52 | }; | 53 | fields: { |
53 | 54 | email: { | |
54 | form = new Form({ | 55 | label: this.props.intl.formatMessage(messages.emailLabel), |
55 | fields: { | 56 | value: '', |
56 | email: { | 57 | validators: [required, email], |
57 | label: this.context.intl.formatMessage(messages.emailLabel), | 58 | }, |
58 | value: '', | ||
59 | validators: [required, email], | ||
60 | }, | 59 | }, |
61 | }, | 60 | }, |
62 | }, this.context.intl); | 61 | this.props.intl, |
62 | ); | ||
63 | 63 | ||
64 | submit(e) { | 64 | submit(e) { |
65 | e.preventDefault(); | 65 | e.preventDefault(); |
66 | this.form.submit({ | 66 | this.form.submit({ |
67 | onSuccess: (form) => { | 67 | onSuccess: form => { |
68 | this.props.onSubmit(form.values()); | 68 | this.props.onSubmit(form.values()); |
69 | }, | 69 | }, |
70 | onError: () => {}, | 70 | onError: () => {}, |
@@ -73,37 +73,24 @@ export default @observer class Password extends Component { | |||
73 | 73 | ||
74 | render() { | 74 | render() { |
75 | const { form } = this; | 75 | const { form } = this; |
76 | const { intl } = this.context; | 76 | const { intl } = this.props; |
77 | const { | 77 | const { isSubmitting, signupRoute, loginRoute, status } = this.props; |
78 | isSubmitting, | ||
79 | signupRoute, | ||
80 | loginRoute, | ||
81 | status, | ||
82 | } = this.props; | ||
83 | 78 | ||
84 | return ( | 79 | return ( |
85 | <div className="auth__container"> | 80 | <div className="auth__container"> |
86 | <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> | 81 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> |
87 | <img | 82 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> |
88 | src="./assets/images/logo.svg" | ||
89 | className="auth__logo" | ||
90 | alt="" | ||
91 | /> | ||
92 | <h1>{intl.formatMessage(messages.headline)}</h1> | 83 | <h1>{intl.formatMessage(messages.headline)}</h1> |
93 | {status.length > 0 && status.includes('sent') && ( | 84 | {status.length > 0 && status.includes('sent') && ( |
94 | <Infobox | 85 | <Infobox type="success" icon="checkbox-marked-circle-outline"> |
95 | type="success" | ||
96 | icon="checkbox-marked-circle-outline" | ||
97 | > | ||
98 | {intl.formatMessage(messages.successInfo)} | 86 | {intl.formatMessage(messages.successInfo)} |
99 | </Infobox> | 87 | </Infobox> |
100 | )} | 88 | )} |
101 | <Input | 89 | <Input field={form.$('email')} focus /> |
102 | field={form.$('email')} | ||
103 | focus | ||
104 | /> | ||
105 | {status.length > 0 && status.includes('no-user') && ( | 90 | {status.length > 0 && status.includes('no-user') && ( |
106 | <p className="error-message center">{intl.formatMessage(messages.noUser)}</p> | 91 | <p className="error-message center"> |
92 | {intl.formatMessage(messages.noUser)} | ||
93 | </p> | ||
107 | )} | 94 | )} |
108 | {isSubmitting ? ( | 95 | {isSubmitting ? ( |
109 | <Button | 96 | <Button |
@@ -123,9 +110,13 @@ export default @observer class Password extends Component { | |||
123 | </form> | 110 | </form> |
124 | <div className="auth__links"> | 111 | <div className="auth__links"> |
125 | <Link to={loginRoute}>{intl.formatMessage(messages.loginLink)}</Link> | 112 | <Link to={loginRoute}>{intl.formatMessage(messages.loginLink)}</Link> |
126 | <Link to={signupRoute}>{intl.formatMessage(messages.signupLink)}</Link> | 113 | <Link to={signupRoute}> |
114 | {intl.formatMessage(messages.signupLink)} | ||
115 | </Link> | ||
127 | </div> | 116 | </div> |
128 | </div> | 117 | </div> |
129 | ); | 118 | ); |
130 | } | 119 | } |
131 | } | 120 | } |
121 | |||
122 | export default injectIntl(Password); | ||
diff --git a/src/components/auth/SetupAssistant.js b/src/components/auth/SetupAssistant.js index ded36bbe7..299c40c63 100644 --- a/src/components/auth/SetupAssistant.js +++ b/src/components/auth/SetupAssistant.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import injectSheet from 'react-jss'; | 5 | import injectSheet from 'react-jss'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | 7 | ||
@@ -19,20 +19,20 @@ const SLACK_ID = 'slack'; | |||
19 | const messages = defineMessages({ | 19 | const messages = defineMessages({ |
20 | headline: { | 20 | headline: { |
21 | id: 'setupAssistant.headline', | 21 | id: 'setupAssistant.headline', |
22 | defaultMessage: "!!!Let's get started", | 22 | defaultMessage: "Let's get started", |
23 | }, | 23 | }, |
24 | subHeadline: { | 24 | subHeadline: { |
25 | id: 'setupAssistant.subheadline', | 25 | id: 'setupAssistant.subheadline', |
26 | defaultMessage: | 26 | defaultMessage: |
27 | '!!!Choose from our most used services and get back on top of your messaging now.', | 27 | 'Choose from our most used services and get back on top of your messaging now.', |
28 | }, | 28 | }, |
29 | submitButtonLabel: { | 29 | submitButtonLabel: { |
30 | id: 'setupAssistant.submit.label', | 30 | id: 'setupAssistant.submit.label', |
31 | defaultMessage: "!!!Let's go", | 31 | defaultMessage: "Let's go", |
32 | }, | 32 | }, |
33 | inviteSuccessInfo: { | 33 | inviteSuccessInfo: { |
34 | id: 'invite.successInfo', | 34 | id: 'invite.successInfo', |
35 | defaultMessage: '!!!Invitations sent successfully', | 35 | defaultMessage: 'Invitations sent successfully', |
36 | }, | 36 | }, |
37 | }); | 37 | }); |
38 | 38 | ||
@@ -145,10 +145,6 @@ class SetupAssistant extends Component { | |||
145 | isInviteSuccessful: false, | 145 | isInviteSuccessful: false, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static contextTypes = { | ||
149 | intl: intlShape, | ||
150 | }; | ||
151 | |||
152 | state = { | 148 | state = { |
153 | services: [ | 149 | services: [ |
154 | { | 150 | { |
@@ -189,7 +185,7 @@ class SetupAssistant extends Component { | |||
189 | } | 185 | } |
190 | 186 | ||
191 | render() { | 187 | render() { |
192 | const { intl } = this.context; | 188 | const { intl } = this.props; |
193 | const { | 189 | const { |
194 | classes, | 190 | classes, |
195 | isInviteSuccessful, | 191 | isInviteSuccessful, |
@@ -330,4 +326,4 @@ class SetupAssistant extends Component { | |||
330 | } | 326 | } |
331 | } | 327 | } |
332 | 328 | ||
333 | export default SetupAssistant; | 329 | export default injectIntl(SetupAssistant); |
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js index 6fb41a164..4d39835a2 100644 --- a/src/components/auth/Signup.js +++ b/src/components/auth/Signup.js | |||
@@ -2,7 +2,7 @@ | |||
2 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer, inject } from 'mobx-react'; | 4 | import { observer, inject } from 'mobx-react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import { isDevMode, useLiveAPI } from '../../environment'; | 7 | import { isDevMode, useLiveAPI } from '../../environment'; |
8 | import Form from '../../lib/Form'; | 8 | import Form from '../../lib/Form'; |
@@ -19,63 +19,65 @@ import { termsBase } from '../../api/apiBase'; | |||
19 | const messages = defineMessages({ | 19 | const messages = defineMessages({ |
20 | headline: { | 20 | headline: { |
21 | id: 'signup.headline', | 21 | id: 'signup.headline', |
22 | defaultMessage: '!!!Sign up', | 22 | defaultMessage: 'Sign up', |
23 | }, | 23 | }, |
24 | firstnameLabel: { | 24 | firstnameLabel: { |
25 | id: 'signup.firstname.label', | 25 | id: 'signup.firstname.label', |
26 | defaultMessage: '!!!Firstname', | 26 | defaultMessage: 'Firstname', |
27 | }, | 27 | }, |
28 | lastnameLabel: { | 28 | lastnameLabel: { |
29 | id: 'signup.lastname.label', | 29 | id: 'signup.lastname.label', |
30 | defaultMessage: '!!!Lastname', | 30 | defaultMessage: 'Lastname', |
31 | }, | 31 | }, |
32 | emailLabel: { | 32 | emailLabel: { |
33 | id: 'signup.email.label', | 33 | id: 'signup.email.label', |
34 | defaultMessage: '!!!Email address', | 34 | defaultMessage: 'Email address', |
35 | }, | 35 | }, |
36 | // companyLabel: { | 36 | // companyLabel: { |
37 | // id: 'signup.company.label', | 37 | // id: 'signup.company.label', |
38 | // defaultMessage: '!!!Company', | 38 | // defaultMessage: 'Company', |
39 | // }, | 39 | // }, |
40 | passwordLabel: { | 40 | passwordLabel: { |
41 | id: 'signup.password.label', | 41 | id: 'signup.password.label', |
42 | defaultMessage: '!!!Password', | 42 | defaultMessage: 'Password', |
43 | }, | 43 | }, |
44 | legalInfo: { | 44 | legalInfo: { |
45 | id: 'signup.legal.info', | 45 | id: 'signup.legal.info', |
46 | defaultMessage: '!!!By creating a Ferdi account you accept the', | 46 | defaultMessage: 'By creating a Ferdi account you accept the', |
47 | }, | 47 | }, |
48 | terms: { | 48 | terms: { |
49 | id: 'signup.legal.terms', | 49 | id: 'signup.legal.terms', |
50 | defaultMessage: '!!!Terms of service', | 50 | defaultMessage: 'Terms of service', |
51 | }, | 51 | }, |
52 | privacy: { | 52 | privacy: { |
53 | id: 'signup.legal.privacy', | 53 | id: 'signup.legal.privacy', |
54 | defaultMessage: '!!!Privacy Statement', | 54 | defaultMessage: 'Privacy Statement', |
55 | }, | 55 | }, |
56 | submitButtonLabel: { | 56 | submitButtonLabel: { |
57 | id: 'signup.submit.label', | 57 | id: 'signup.submit.label', |
58 | defaultMessage: '!!!Create account', | 58 | defaultMessage: 'Create account', |
59 | }, | 59 | }, |
60 | loginLink: { | 60 | loginLink: { |
61 | id: 'signup.link.login', | 61 | id: 'signup.link.login', |
62 | defaultMessage: '!!!Already have an account, sign in?', | 62 | defaultMessage: 'Already have an account, sign in?', |
63 | }, | 63 | }, |
64 | changeServer: { | 64 | changeServer: { |
65 | id: 'login.changeServer', | 65 | id: 'login.changeServer', |
66 | defaultMessage: '!!!Change server', | 66 | defaultMessage: 'Change server', |
67 | }, | 67 | }, |
68 | serverless: { | 68 | serverless: { |
69 | id: 'services.serverless', | 69 | id: 'services.serverless', |
70 | defaultMessage: '!!!Use Ferdi without an Account', | 70 | defaultMessage: 'Use Ferdi without an Account', |
71 | }, | 71 | }, |
72 | emailDuplicate: { | 72 | emailDuplicate: { |
73 | id: 'signup.emailDuplicate', | 73 | id: 'signup.emailDuplicate', |
74 | defaultMessage: '!!!A user with that email address already exists', | 74 | defaultMessage: 'A user with that email address already exists', |
75 | }, | 75 | }, |
76 | }); | 76 | }); |
77 | 77 | ||
78 | export default @inject('actions') @observer class Signup extends Component { | 78 | @inject('actions') |
79 | @observer | ||
80 | class Signup extends Component { | ||
79 | static propTypes = { | 81 | static propTypes = { |
80 | onSubmit: PropTypes.func.isRequired, | 82 | onSubmit: PropTypes.func.isRequired, |
81 | isSubmitting: PropTypes.bool.isRequired, | 83 | isSubmitting: PropTypes.bool.isRequired, |
@@ -85,40 +87,39 @@ export default @inject('actions') @observer class Signup extends Component { | |||
85 | actions: PropTypes.object.isRequired, | 87 | actions: PropTypes.object.isRequired, |
86 | }; | 88 | }; |
87 | 89 | ||
88 | static contextTypes = { | 90 | form = new Form( |
89 | intl: intlShape, | 91 | { |
90 | }; | 92 | fields: { |
91 | 93 | firstname: { | |
92 | form = new Form({ | 94 | label: this.props.intl.formatMessage(messages.firstnameLabel), |
93 | fields: { | 95 | value: '', |
94 | firstname: { | 96 | validators: [required], |
95 | label: this.context.intl.formatMessage(messages.firstnameLabel), | 97 | }, |
96 | value: '', | 98 | lastname: { |
97 | validators: [required], | 99 | label: this.props.intl.formatMessage(messages.lastnameLabel), |
98 | }, | 100 | value: '', |
99 | lastname: { | 101 | validators: [required], |
100 | label: this.context.intl.formatMessage(messages.lastnameLabel), | 102 | }, |
101 | value: '', | 103 | email: { |
102 | validators: [required], | 104 | label: this.props.intl.formatMessage(messages.emailLabel), |
103 | }, | 105 | value: '', |
104 | email: { | 106 | validators: [required, email], |
105 | label: this.context.intl.formatMessage(messages.emailLabel), | 107 | }, |
106 | value: '', | 108 | password: { |
107 | validators: [required, email], | 109 | label: this.props.intl.formatMessage(messages.passwordLabel), |
108 | }, | 110 | value: '', |
109 | password: { | 111 | validators: [required, minLength(6)], |
110 | label: this.context.intl.formatMessage(messages.passwordLabel), | 112 | type: 'password', |
111 | value: '', | 113 | }, |
112 | validators: [required, minLength(6)], | ||
113 | type: 'password', | ||
114 | }, | 114 | }, |
115 | }, | 115 | }, |
116 | }, this.context.intl); | 116 | this.props.intl, |
117 | ); | ||
117 | 118 | ||
118 | submit(e) { | 119 | submit(e) { |
119 | e.preventDefault(); | 120 | e.preventDefault(); |
120 | this.form.submit({ | 121 | this.form.submit({ |
121 | onSuccess: (form) => { | 122 | onSuccess: form => { |
122 | this.props.onSubmit(form.values()); | 123 | this.props.onSubmit(form.values()); |
123 | }, | 124 | }, |
124 | onError: () => {}, | 125 | onError: () => {}, |
@@ -131,24 +132,22 @@ export default @inject('actions') @observer class Signup extends Component { | |||
131 | 132 | ||
132 | render() { | 133 | render() { |
133 | const { form } = this; | 134 | const { form } = this; |
134 | const { intl } = this.context; | 135 | const { intl } = this.props; |
135 | const { | 136 | const { isSubmitting, loginRoute, error, changeServerRoute } = this.props; |
136 | isSubmitting, loginRoute, error, changeServerRoute, | ||
137 | } = this.props; | ||
138 | 137 | ||
139 | return ( | 138 | return ( |
140 | <div className="auth__scroll-container"> | 139 | <div className="auth__scroll-container"> |
141 | <div className="auth__container auth__container--signup"> | 140 | <div className="auth__container auth__container--signup"> |
142 | <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> | 141 | <form |
143 | <img | 142 | className="franz-form auth__form" |
144 | src="./assets/images/logo.svg" | 143 | onSubmit={e => this.submit(e)} |
145 | className="auth__logo" | 144 | > |
146 | alt="" | 145 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> |
147 | /> | ||
148 | <h1>{intl.formatMessage(messages.headline)}</h1> | 146 | <h1>{intl.formatMessage(messages.headline)}</h1> |
149 | {isDevMode && !useLiveAPI && ( | 147 | {isDevMode && !useLiveAPI && ( |
150 | <Infobox type="warning"> | 148 | <Infobox type="warning"> |
151 | In Dev Mode your data is not persistent. Please use the live app for accesing the production API. | 149 | In Dev Mode your data is not persistent. Please use the live app |
150 | for accesing the production API. | ||
152 | </Infobox> | 151 | </Infobox> |
153 | )} | 152 | )} |
154 | <div className="grid__row"> | 153 | <div className="grid__row"> |
@@ -162,7 +161,9 @@ export default @inject('actions') @observer class Signup extends Component { | |||
162 | scorePassword | 161 | scorePassword |
163 | /> | 162 | /> |
164 | {error.code === 'email-duplicate' && ( | 163 | {error.code === 'email-duplicate' && ( |
165 | <p className="error-message center">{intl.formatMessage(messages.emailDuplicate)}</p> | 164 | <p className="error-message center"> |
165 | {intl.formatMessage(messages.emailDuplicate)} | ||
166 | </p> | ||
166 | )} | 167 | )} |
167 | {isSubmitting ? ( | 168 | {isSubmitting ? ( |
168 | <Button | 169 | <Button |
@@ -200,12 +201,20 @@ export default @inject('actions') @observer class Signup extends Component { | |||
200 | </p> | 201 | </p> |
201 | </form> | 202 | </form> |
202 | <div className="auth__links"> | 203 | <div className="auth__links"> |
203 | <Link to={changeServerRoute}>{intl.formatMessage(messages.changeServer)}</Link> | 204 | <Link to={changeServerRoute}> |
204 | <a onClick={this.useLocalServer.bind(this)}>{intl.formatMessage(messages.serverless)}</a> | 205 | {intl.formatMessage(messages.changeServer)} |
205 | <Link to={loginRoute}>{intl.formatMessage(messages.loginLink)}</Link> | 206 | </Link> |
207 | <a onClick={this.useLocalServer.bind(this)}> | ||
208 | {intl.formatMessage(messages.serverless)} | ||
209 | </a> | ||
210 | <Link to={loginRoute}> | ||
211 | {intl.formatMessage(messages.loginLink)} | ||
212 | </Link> | ||
206 | </div> | 213 | </div> |
207 | </div> | 214 | </div> |
208 | </div> | 215 | </div> |
209 | ); | 216 | ); |
210 | } | 217 | } |
211 | } | 218 | } |
219 | |||
220 | export default injectIntl(Signup); | ||
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js index cb522e26e..2d2e2ab28 100644 --- a/src/components/auth/Welcome.js +++ b/src/components/auth/Welcome.js | |||
@@ -2,7 +2,7 @@ | |||
2 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; | 4 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import serverlessLogin from '../../helpers/serverless-helpers'; | 6 | import serverlessLogin from '../../helpers/serverless-helpers'; |
7 | 7 | ||
8 | import Link from '../ui/Link'; | 8 | import Link from '../ui/Link'; |
@@ -10,19 +10,21 @@ import Link from '../ui/Link'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | signupButton: { | 11 | signupButton: { |
12 | id: 'welcome.signupButton', | 12 | id: 'welcome.signupButton', |
13 | defaultMessage: '!!!Create a free account', | 13 | defaultMessage: 'Create a free account', |
14 | }, | 14 | }, |
15 | loginButton: { | 15 | loginButton: { |
16 | id: 'welcome.loginButton', | 16 | id: 'welcome.loginButton', |
17 | defaultMessage: '!!!Login to your account', | 17 | defaultMessage: 'Login to your account', |
18 | }, | 18 | }, |
19 | serverless: { | 19 | serverless: { |
20 | id: 'services.serverless', | 20 | id: 'services.serverless', |
21 | defaultMessage: '!!!Use Ferdi without an Account', | 21 | defaultMessage: 'Use Ferdi without an Account', |
22 | }, | 22 | }, |
23 | }); | 23 | }); |
24 | 24 | ||
25 | export default @inject('actions') @observer class Login extends Component { | 25 | @inject('actions') |
26 | @observer | ||
27 | class Login extends Component { | ||
26 | static propTypes = { | 28 | static propTypes = { |
27 | loginRoute: PropTypes.string.isRequired, | 29 | loginRoute: PropTypes.string.isRequired, |
28 | signupRoute: PropTypes.string.isRequired, | 30 | signupRoute: PropTypes.string.isRequired, |
@@ -31,27 +33,22 @@ export default @inject('actions') @observer class Login extends Component { | |||
31 | actions: PropTypes.object.isRequired, | 33 | actions: PropTypes.object.isRequired, |
32 | }; | 34 | }; |
33 | 35 | ||
34 | static contextTypes = { | ||
35 | intl: intlShape, | ||
36 | }; | ||
37 | |||
38 | useLocalServer() { | 36 | useLocalServer() { |
39 | serverlessLogin(this.props.actions); | 37 | serverlessLogin(this.props.actions); |
40 | } | 38 | } |
41 | 39 | ||
42 | render() { | 40 | render() { |
43 | const { intl } = this.context; | 41 | const { intl } = this.props; |
44 | const { | 42 | const { loginRoute, signupRoute, changeServerRoute, recipes } = this.props; |
45 | loginRoute, | ||
46 | signupRoute, | ||
47 | changeServerRoute, | ||
48 | recipes, | ||
49 | } = this.props; | ||
50 | 43 | ||
51 | return ( | 44 | return ( |
52 | <div className="welcome"> | 45 | <div className="welcome"> |
53 | <div className="welcome__content"> | 46 | <div className="welcome__content"> |
54 | <img src="./assets/images/logo.svg" className="welcome__logo" alt="" /> | 47 | <img |
48 | src="./assets/images/logo.svg" | ||
49 | className="welcome__logo" | ||
50 | alt="" | ||
51 | /> | ||
55 | {/* <img src="./assets/images/welcome.png" className="welcome__services" alt="" /> */} | 52 | {/* <img src="./assets/images/welcome.png" className="welcome__services" alt="" /> */} |
56 | <div className="welcome__text"> | 53 | <div className="welcome__text"> |
57 | <h1>Ferdi</h1> | 54 | <h1>Ferdi</h1> |
@@ -73,27 +70,21 @@ export default @inject('actions') @observer class Login extends Component { | |||
73 | <br /> | 70 | <br /> |
74 | 71 | ||
75 | <Link to={changeServerRoute}> | 72 | <Link to={changeServerRoute}> |
76 | <span style={{ | 73 | <span |
77 | textAlign: 'center', | 74 | style={{ |
78 | width: '100%', | 75 | textAlign: 'center', |
79 | cursor: 'pointer', | 76 | width: '100%', |
80 | }} | 77 | cursor: 'pointer', |
78 | }} | ||
81 | > | 79 | > |
82 | Change server | 80 | Change server |
83 | </span> | 81 | </span> |
84 | </Link> | 82 | </Link> |
85 | </div> | 83 | </div> |
86 | <div className="welcome__featured-services"> | 84 | <div className="welcome__featured-services"> |
87 | {recipes.map((recipe) => ( | 85 | {recipes.map(recipe => ( |
88 | <div | 86 | <div key={recipe.id} className="welcome__featured-service"> |
89 | key={recipe.id} | 87 | <img key={recipe.id} src={recipe.icons.svg} alt="" /> |
90 | className="welcome__featured-service" | ||
91 | > | ||
92 | <img | ||
93 | key={recipe.id} | ||
94 | src={recipe.icons.svg} | ||
95 | alt="" | ||
96 | /> | ||
97 | </div> | 88 | </div> |
98 | ))} | 89 | ))} |
99 | </div> | 90 | </div> |
@@ -101,3 +92,5 @@ export default @inject('actions') @observer class Login extends Component { | |||
101 | ); | 92 | ); |
102 | } | 93 | } |
103 | } | 94 | } |
95 | |||
96 | export default injectIntl(Login); | ||
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index e6e5d40fe..83e037083 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { TitleBar } from 'electron-react-titlebar'; | 5 | import { TitleBar } from 'electron-react-titlebar'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | 7 | ||
@@ -27,20 +27,20 @@ function createMarkup(HTMLString) { | |||
27 | const messages = defineMessages({ | 27 | const messages = defineMessages({ |
28 | servicesUpdated: { | 28 | servicesUpdated: { |
29 | id: 'infobar.servicesUpdated', | 29 | id: 'infobar.servicesUpdated', |
30 | defaultMessage: '!!!Your services have been updated.', | 30 | defaultMessage: 'Your services have been updated.', |
31 | }, | 31 | }, |
32 | buttonReloadServices: { | 32 | buttonReloadServices: { |
33 | id: 'infobar.buttonReloadServices', | 33 | id: 'infobar.buttonReloadServices', |
34 | defaultMessage: '!!!Reload services', | 34 | defaultMessage: 'Reload services', |
35 | }, | 35 | }, |
36 | requiredRequestsFailed: { | 36 | requiredRequestsFailed: { |
37 | id: 'infobar.requiredRequestsFailed', | 37 | id: 'infobar.requiredRequestsFailed', |
38 | defaultMessage: '!!!Could not load services and user information', | 38 | defaultMessage: 'Could not load services and user information', |
39 | }, | 39 | }, |
40 | authRequestFailed: { | 40 | authRequestFailed: { |
41 | id: 'infobar.authRequestFailed', | 41 | id: 'infobar.authRequestFailed', |
42 | defaultMessage: | 42 | defaultMessage: |
43 | '!!!There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.', | 43 | 'There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.', |
44 | }, | 44 | }, |
45 | }); | 45 | }); |
46 | 46 | ||
@@ -94,10 +94,6 @@ class AppLayout extends Component { | |||
94 | children: [], | 94 | children: [], |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static contextTypes = { | ||
98 | intl: intlShape, | ||
99 | }; | ||
100 | |||
101 | render() { | 97 | render() { |
102 | const { | 98 | const { |
103 | classes, | 99 | classes, |
@@ -119,7 +115,7 @@ class AppLayout extends Component { | |||
119 | areRequiredRequestsLoading, | 115 | areRequiredRequestsLoading, |
120 | } = this.props; | 116 | } = this.props; |
121 | 117 | ||
122 | const { intl } = this.context; | 118 | const { intl } = this.props; |
123 | 119 | ||
124 | return ( | 120 | return ( |
125 | <ErrorBoundary> | 121 | <ErrorBoundary> |
@@ -213,4 +209,4 @@ class AppLayout extends Component { | |||
213 | } | 209 | } |
214 | } | 210 | } |
215 | 211 | ||
216 | export default AppLayout; | 212 | export default injectIntl(AppLayout); |
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index 1ee7733b9..87233f7ca 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js | |||
@@ -1,12 +1,19 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import ReactTooltip from 'react-tooltip'; | 3 | import ReactTooltip from 'react-tooltip'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { inject, observer } from 'mobx-react'; | 5 | import { inject, observer } from 'mobx-react'; |
6 | import { Link } from 'react-router'; | 6 | import { Link } from 'react-router'; |
7 | 7 | ||
8 | import Tabbar from '../services/tabs/Tabbar'; | 8 | import Tabbar from '../services/tabs/Tabbar'; |
9 | import { settingsShortcutKey, lockFerdiShortcutKey, todosToggleShortcutKey, workspaceToggleShortcutKey, addNewServiceShortcutKey, muteFerdiShortcutKey } from '../../environment'; | 9 | import { |
10 | settingsShortcutKey, | ||
11 | lockFerdiShortcutKey, | ||
12 | todosToggleShortcutKey, | ||
13 | workspaceToggleShortcutKey, | ||
14 | addNewServiceShortcutKey, | ||
15 | muteFerdiShortcutKey, | ||
16 | } from '../../environment'; | ||
10 | import { workspaceStore } from '../../features/workspaces'; | 17 | import { workspaceStore } from '../../features/workspaces'; |
11 | import { todosStore } from '../../features/todos'; | 18 | import { todosStore } from '../../features/todos'; |
12 | import { todoActions } from '../../features/todos/actions'; | 19 | import { todoActions } from '../../features/todos/actions'; |
@@ -17,39 +24,41 @@ import globalMessages from '../../i18n/globalMessages'; | |||
17 | const messages = defineMessages({ | 24 | const messages = defineMessages({ |
18 | addNewService: { | 25 | addNewService: { |
19 | id: 'sidebar.addNewService', | 26 | id: 'sidebar.addNewService', |
20 | defaultMessage: '!!!Add new service', | 27 | defaultMessage: 'Add new service', |
21 | }, | 28 | }, |
22 | mute: { | 29 | mute: { |
23 | id: 'sidebar.muteApp', | 30 | id: 'sidebar.muteApp', |
24 | defaultMessage: '!!!Disable notifications & audio', | 31 | defaultMessage: 'Disable notifications & audio', |
25 | }, | 32 | }, |
26 | unmute: { | 33 | unmute: { |
27 | id: 'sidebar.unmuteApp', | 34 | id: 'sidebar.unmuteApp', |
28 | defaultMessage: '!!!Enable notifications & audio', | 35 | defaultMessage: 'Enable notifications & audio', |
29 | }, | 36 | }, |
30 | openWorkspaceDrawer: { | 37 | openWorkspaceDrawer: { |
31 | id: 'sidebar.openWorkspaceDrawer', | 38 | id: 'sidebar.openWorkspaceDrawer', |
32 | defaultMessage: '!!!Open workspace drawer', | 39 | defaultMessage: 'Open workspace drawer', |
33 | }, | 40 | }, |
34 | closeWorkspaceDrawer: { | 41 | closeWorkspaceDrawer: { |
35 | id: 'sidebar.closeWorkspaceDrawer', | 42 | id: 'sidebar.closeWorkspaceDrawer', |
36 | defaultMessage: '!!!Close workspace drawer', | 43 | defaultMessage: 'Close workspace drawer', |
37 | }, | 44 | }, |
38 | openTodosDrawer: { | 45 | openTodosDrawer: { |
39 | id: 'sidebar.openTodosDrawer', | 46 | id: 'sidebar.openTodosDrawer', |
40 | defaultMessage: '!!!Open Ferdi Todos', | 47 | defaultMessage: 'Open Ferdi Todos', |
41 | }, | 48 | }, |
42 | closeTodosDrawer: { | 49 | closeTodosDrawer: { |
43 | id: 'sidebar.closeTodosDrawer', | 50 | id: 'sidebar.closeTodosDrawer', |
44 | defaultMessage: '!!!Close Ferdi Todos', | 51 | defaultMessage: 'Close Ferdi Todos', |
45 | }, | 52 | }, |
46 | lockFerdi: { | 53 | lockFerdi: { |
47 | id: 'sidebar.lockFerdi', | 54 | id: 'sidebar.lockFerdi', |
48 | defaultMessage: '!!!Lock Ferdi', | 55 | defaultMessage: 'Lock Ferdi', |
49 | }, | 56 | }, |
50 | }); | 57 | }); |
51 | 58 | ||
52 | export default @inject('stores', 'actions') @observer class Sidebar extends Component { | 59 | @inject('stores', 'actions') |
60 | @observer | ||
61 | class Sidebar extends Component { | ||
53 | static propTypes = { | 62 | static propTypes = { |
54 | openSettings: PropTypes.func.isRequired, | 63 | openSettings: PropTypes.func.isRequired, |
55 | closeSettings: PropTypes.func.isRequired, | 64 | closeSettings: PropTypes.func.isRequired, |
@@ -79,10 +88,6 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
79 | }).isRequired, | 88 | }).isRequired, |
80 | }; | 89 | }; |
81 | 90 | ||
82 | static contextTypes = { | ||
83 | intl: intlShape, | ||
84 | }; | ||
85 | |||
86 | state = { | 91 | state = { |
87 | tooltipEnabled: true, | 92 | tooltipEnabled: true, |
88 | }; | 93 | }; |
@@ -115,14 +120,14 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
115 | actions, | 120 | actions, |
116 | isTodosServiceActive, | 121 | isTodosServiceActive, |
117 | } = this.props; | 122 | } = this.props; |
118 | const { intl } = this.context; | 123 | const { intl } = this.props; |
119 | const todosToggleMessage = ( | 124 | const todosToggleMessage = todosStore.isTodosPanelVisible |
120 | todosStore.isTodosPanelVisible ? messages.closeTodosDrawer : messages.openTodosDrawer | 125 | ? messages.closeTodosDrawer |
121 | ); | 126 | : messages.openTodosDrawer; |
122 | 127 | ||
123 | const workspaceToggleMessage = ( | 128 | const workspaceToggleMessage = isWorkspaceDrawerOpen |
124 | isWorkspaceDrawerOpen ? messages.closeWorkspaceDrawer : messages.openWorkspaceDrawer | 129 | ? messages.closeWorkspaceDrawer |
125 | ); | 130 | : messages.openWorkspaceDrawer; |
126 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | 131 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); |
127 | 132 | ||
128 | return ( | 133 | return ( |
@@ -133,9 +138,9 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
133 | disableToolTip={() => this.disableToolTip()} | 138 | disableToolTip={() => this.disableToolTip()} |
134 | useVerticalStyle={stores.settings.all.app.useVerticalStyle} | 139 | useVerticalStyle={stores.settings.all.app.useVerticalStyle} |
135 | /> | 140 | /> |
136 | { isLoggedIn ? ( | 141 | {isLoggedIn ? ( |
137 | <> | 142 | <> |
138 | { stores.settings.all.app.lockingFeatureEnabled ? ( | 143 | {stores.settings.all.app.lockingFeatureEnabled ? ( |
139 | <button | 144 | <button |
140 | type="button" | 145 | type="button" |
141 | className="sidebar__button" | 146 | className="sidebar__button" |
@@ -147,12 +152,15 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
147 | }, | 152 | }, |
148 | }); | 153 | }); |
149 | }} | 154 | }} |
150 | data-tip={`${intl.formatMessage(messages.lockFerdi)} (${lockFerdiShortcutKey(false)})`} | 155 | data-tip={`${intl.formatMessage( |
156 | messages.lockFerdi, | ||
157 | )} (${lockFerdiShortcutKey(false)})`} | ||
151 | > | 158 | > |
152 | <i className="mdi mdi-lock" /> | 159 | <i className="mdi mdi-lock" /> |
153 | </button> | 160 | </button> |
154 | ) : null} | 161 | ) : null} |
155 | {todosStore.isFeatureEnabled && todosStore.isFeatureEnabledByUser ? ( | 162 | {todosStore.isFeatureEnabled && |
163 | todosStore.isFeatureEnabledByUser ? ( | ||
156 | <button | 164 | <button |
157 | type="button" | 165 | type="button" |
158 | onClick={() => { | 166 | onClick={() => { |
@@ -160,12 +168,16 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
160 | this.updateToolTip(); | 168 | this.updateToolTip(); |
161 | }} | 169 | }} |
162 | disabled={isTodosServiceActive} | 170 | disabled={isTodosServiceActive} |
163 | className={`sidebar__button sidebar__button--todos ${todosStore.isTodosPanelVisible ? 'is-active' : ''}`} | 171 | className={`sidebar__button sidebar__button--todos ${ |
164 | data-tip={`${intl.formatMessage(todosToggleMessage)} (${todosToggleShortcutKey(false)})`} | 172 | todosStore.isTodosPanelVisible ? 'is-active' : '' |
173 | }`} | ||
174 | data-tip={`${intl.formatMessage( | ||
175 | todosToggleMessage, | ||
176 | )} (${todosToggleShortcutKey(false)})`} | ||
165 | > | 177 | > |
166 | <i className="mdi mdi-check-all" /> | 178 | <i className="mdi mdi-check-all" /> |
167 | </button> | 179 | </button> |
168 | ) : null} | 180 | ) : null} |
169 | {workspaceStore.isFeatureEnabled ? ( | 181 | {workspaceStore.isFeatureEnabled ? ( |
170 | <button | 182 | <button |
171 | type="button" | 183 | type="button" |
@@ -173,8 +185,12 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
173 | toggleWorkspaceDrawer(); | 185 | toggleWorkspaceDrawer(); |
174 | this.updateToolTip(); | 186 | this.updateToolTip(); |
175 | }} | 187 | }} |
176 | className={`sidebar__button sidebar__button--workspaces ${isWorkspaceDrawerOpen ? 'is-active' : ''}`} | 188 | className={`sidebar__button sidebar__button--workspaces ${ |
177 | data-tip={`${intl.formatMessage(workspaceToggleMessage)} (${workspaceToggleShortcutKey(false)})`} | 189 | isWorkspaceDrawerOpen ? 'is-active' : '' |
190 | }`} | ||
191 | data-tip={`${intl.formatMessage( | ||
192 | workspaceToggleMessage, | ||
193 | )} (${workspaceToggleShortcutKey(false)})`} | ||
178 | > | 194 | > |
179 | <i className="mdi mdi-view-grid" /> | 195 | <i className="mdi mdi-view-grid" /> |
180 | </button> | 196 | </button> |
@@ -185,8 +201,12 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
185 | toggleMuteApp(); | 201 | toggleMuteApp(); |
186 | this.updateToolTip(); | 202 | this.updateToolTip(); |
187 | }} | 203 | }} |
188 | className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} | 204 | className={`sidebar__button sidebar__button--audio ${ |
189 | data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${muteFerdiShortcutKey(false)})`} | 205 | isAppMuted ? 'is-muted' : '' |
206 | }`} | ||
207 | data-tip={`${intl.formatMessage( | ||
208 | isAppMuted ? messages.unmute : messages.mute, | ||
209 | )} (${muteFerdiShortcutKey(false)})`} | ||
190 | > | 210 | > |
191 | <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> | 211 | <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> |
192 | </button> | 212 | </button> |
@@ -194,7 +214,9 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
194 | type="button" | 214 | type="button" |
195 | onClick={() => openSettings({ path: 'recipes' })} | 215 | onClick={() => openSettings({ path: 'recipes' })} |
196 | className="sidebar__button sidebar__button--new-service" | 216 | className="sidebar__button sidebar__button--new-service" |
197 | data-tip={`${intl.formatMessage(messages.addNewService)} (${addNewServiceShortcutKey(false)})`} | 217 | data-tip={`${intl.formatMessage( |
218 | messages.addNewService, | ||
219 | )} (${addNewServiceShortcutKey(false)})`} | ||
198 | > | 220 | > |
199 | <i className="mdi mdi-plus-box" /> | 221 | <i className="mdi mdi-plus-box" /> |
200 | </button> | 222 | </button> |
@@ -212,15 +234,17 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
212 | type="button" | 234 | type="button" |
213 | onClick={() => openSettings({ path: 'app' })} | 235 | onClick={() => openSettings({ path: 'app' })} |
214 | className="sidebar__button sidebar__button--settings" | 236 | className="sidebar__button sidebar__button--settings" |
215 | data-tip={`${intl.formatMessage(globalMessages.settings)} (${settingsShortcutKey(false)})`} | 237 | data-tip={`${intl.formatMessage( |
238 | globalMessages.settings, | ||
239 | )} (${settingsShortcutKey(false)})`} | ||
216 | > | 240 | > |
217 | <i className="mdi mdi-cog" /> | 241 | <i className="mdi mdi-cog" /> |
218 | { (this.props.stores.app.updateStatus === this.props.stores.app.updateStatusTypes.AVAILABLE | 242 | {(this.props.stores.app.updateStatus === |
219 | || this.props.stores.app.updateStatus === this.props.stores.app.updateStatusTypes.DOWNLOADED) && ( | 243 | this.props.stores.app.updateStatusTypes.AVAILABLE || |
220 | <span className="update-available"> | 244 | this.props.stores.app.updateStatus === |
221 | • | 245 | this.props.stores.app.updateStatusTypes.DOWNLOADED) && ( |
222 | </span> | 246 | <span className="update-available">•</span> |
223 | ) } | 247 | )} |
224 | </button> | 248 | </button> |
225 | {this.state.tooltipEnabled && ( | 249 | {this.state.tooltipEnabled && ( |
226 | <ReactTooltip place="right" type="dark" effect="solid" /> | 250 | <ReactTooltip place="right" type="dark" effect="solid" /> |
@@ -229,3 +253,5 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp | |||
229 | ); | 253 | ); |
230 | } | 254 | } |
231 | } | 255 | } |
256 | |||
257 | export default injectIntl(Sidebar); | ||
diff --git a/src/components/services/content/ConnectionLostBanner.js b/src/components/services/content/ConnectionLostBanner.js index ebe863333..423edb3c7 100644 --- a/src/components/services/content/ConnectionLostBanner.js +++ b/src/components/services/content/ConnectionLostBanner.js | |||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import { Icon } from '@meetfranz/ui'; | 5 | import { Icon } from '@meetfranz/ui'; |
6 | import { intlShape, defineMessages } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | import { mdiAlert } from '@mdi/js'; | 8 | import { mdiAlert } from '@mdi/js'; |
9 | import { LIVE_API_FERDI_WEBSITE } from '../../../config'; | 9 | import { LIVE_API_FERDI_WEBSITE } from '../../../config'; |
@@ -12,15 +12,15 @@ import { LIVE_API_FERDI_WEBSITE } from '../../../config'; | |||
12 | const messages = defineMessages({ | 12 | const messages = defineMessages({ |
13 | text: { | 13 | text: { |
14 | id: 'connectionLostBanner.message', | 14 | id: 'connectionLostBanner.message', |
15 | defaultMessage: '!!!Oh no! Ferdi lost the connection to {name}.', | 15 | defaultMessage: 'Oh no! Ferdi lost the connection to {name}.', |
16 | }, | 16 | }, |
17 | moreInformation: { | 17 | moreInformation: { |
18 | id: 'connectionLostBanner.informationLink', | 18 | id: 'connectionLostBanner.informationLink', |
19 | defaultMessage: '!!!What happened?', | 19 | defaultMessage: 'What happened?', |
20 | }, | 20 | }, |
21 | cta: { | 21 | cta: { |
22 | id: 'connectionLostBanner.cta', | 22 | id: 'connectionLostBanner.cta', |
23 | defaultMessage: '!!!Reload Service', | 23 | defaultMessage: 'Reload Service', |
24 | }, | 24 | }, |
25 | }); | 25 | }); |
26 | 26 | ||
@@ -78,16 +78,12 @@ class ConnectionLostBanner extends Component { | |||
78 | reload: PropTypes.func.isRequired, | 78 | reload: PropTypes.func.isRequired, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static contextTypes = { | ||
82 | intl: intlShape, | ||
83 | }; | ||
84 | |||
85 | inputRef = React.createRef(); | 81 | inputRef = React.createRef(); |
86 | 82 | ||
87 | render() { | 83 | render() { |
88 | const { classes, name, reload } = this.props; | 84 | const { classes, name, reload } = this.props; |
89 | 85 | ||
90 | const { intl } = this.context; | 86 | const { intl } = this.props; |
91 | 87 | ||
92 | return ( | 88 | return ( |
93 | <div className={classes.root}> | 89 | <div className={classes.root}> |
@@ -110,4 +106,4 @@ class ConnectionLostBanner extends Component { | |||
110 | } | 106 | } |
111 | } | 107 | } |
112 | 108 | ||
113 | export default ConnectionLostBanner; | 109 | export default injectIntl(ConnectionLostBanner); |
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js index 36e0ac418..41d84c0b0 100644 --- a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js +++ b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import injectSheet from 'react-jss'; | 5 | import injectSheet from 'react-jss'; |
6 | 6 | ||
7 | import Button from '../../../ui/Button'; | 7 | import Button from '../../../ui/Button'; |
@@ -11,27 +11,29 @@ import styles from './styles'; | |||
11 | const messages = defineMessages({ | 11 | const messages = defineMessages({ |
12 | headline: { | 12 | headline: { |
13 | id: 'service.errorHandler.headline', | 13 | id: 'service.errorHandler.headline', |
14 | defaultMessage: '!!!Oh no!', | 14 | defaultMessage: 'Oh no!', |
15 | }, | 15 | }, |
16 | text: { | 16 | text: { |
17 | id: 'service.errorHandler.text', | 17 | id: 'service.errorHandler.text', |
18 | defaultMessage: '!!!{name} has failed to load.', | 18 | defaultMessage: '{name} has failed to load.', |
19 | }, | 19 | }, |
20 | action: { | 20 | action: { |
21 | id: 'service.errorHandler.action', | 21 | id: 'service.errorHandler.action', |
22 | defaultMessage: '!!!Reload {name}', | 22 | defaultMessage: 'Reload {name}', |
23 | }, | 23 | }, |
24 | editAction: { | 24 | editAction: { |
25 | id: 'service.errorHandler.editAction', | 25 | id: 'service.errorHandler.editAction', |
26 | defaultMessage: '!!!Edit {name}', | 26 | defaultMessage: 'Edit {name}', |
27 | }, | 27 | }, |
28 | errorMessage: { | 28 | errorMessage: { |
29 | id: 'service.errorHandler.message', | 29 | id: 'service.errorHandler.message', |
30 | defaultMessage: '!!!Error:', | 30 | defaultMessage: 'Error:', |
31 | }, | 31 | }, |
32 | }); | 32 | }); |
33 | 33 | ||
34 | export default @injectSheet(styles) @observer class WebviewErrorHandler extends Component { | 34 | @injectSheet(styles) |
35 | @observer | ||
36 | class WebviewErrorHandler extends Component { | ||
35 | static propTypes = { | 37 | static propTypes = { |
36 | name: PropTypes.string.isRequired, | 38 | name: PropTypes.string.isRequired, |
37 | reload: PropTypes.func.isRequired, | 39 | reload: PropTypes.func.isRequired, |
@@ -40,30 +42,16 @@ export default @injectSheet(styles) @observer class WebviewErrorHandler extends | |||
40 | classes: PropTypes.object.isRequired, | 42 | classes: PropTypes.object.isRequired, |
41 | }; | 43 | }; |
42 | 44 | ||
43 | static contextTypes = { | ||
44 | intl: intlShape, | ||
45 | }; | ||
46 | |||
47 | render() { | 45 | render() { |
48 | const { | 46 | const { name, reload, edit, errorMessage, classes } = this.props; |
49 | name, | 47 | const { intl } = this.props; |
50 | reload, | ||
51 | edit, | ||
52 | errorMessage, | ||
53 | classes, | ||
54 | } = this.props; | ||
55 | const { intl } = this.context; | ||
56 | 48 | ||
57 | return ( | 49 | return ( |
58 | <div className={classes.component}> | 50 | <div className={classes.component}> |
59 | <h1>{intl.formatMessage(messages.headline)}</h1> | 51 | <h1>{intl.formatMessage(messages.headline)}</h1> |
60 | <p>{intl.formatMessage(messages.text, { name })}</p> | 52 | <p>{intl.formatMessage(messages.text, { name })}</p> |
61 | <p> | 53 | <p> |
62 | <strong> | 54 | <strong>{intl.formatMessage(messages.errorMessage)}:</strong>{' '} |
63 | {intl.formatMessage(messages.errorMessage)} | ||
64 | : | ||
65 | </strong> | ||
66 | {' '} | ||
67 | {errorMessage} | 55 | {errorMessage} |
68 | </p> | 56 | </p> |
69 | <div className={classes.buttonContainer}> | 57 | <div className={classes.buttonContainer}> |
@@ -82,3 +70,5 @@ export default @injectSheet(styles) @observer class WebviewErrorHandler extends | |||
82 | ); | 70 | ); |
83 | } | 71 | } |
84 | } | 72 | } |
73 | |||
74 | export default injectIntl(WebviewErrorHandler); | ||
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js index d0f12256e..e59ed58bd 100644 --- a/src/components/services/content/ServiceDisabled.js +++ b/src/components/services/content/ServiceDisabled.js | |||
@@ -1,38 +1,35 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import Button from '../../ui/Button'; | 6 | import Button from '../../ui/Button'; |
7 | 7 | ||
8 | const messages = defineMessages({ | 8 | const messages = defineMessages({ |
9 | headline: { | 9 | headline: { |
10 | id: 'service.disabledHandler.headline', | 10 | id: 'service.disabledHandler.headline', |
11 | defaultMessage: '!!!{name} is disabled', | 11 | defaultMessage: '{name} is disabled', |
12 | }, | 12 | }, |
13 | action: { | 13 | action: { |
14 | id: 'service.disabledHandler.action', | 14 | id: 'service.disabledHandler.action', |
15 | defaultMessage: '!!!Enable {name}', | 15 | defaultMessage: 'Enable {name}', |
16 | }, | 16 | }, |
17 | }); | 17 | }); |
18 | 18 | ||
19 | export default @observer class ServiceDisabled extends Component { | 19 | @observer |
20 | class ServiceDisabled extends Component { | ||
20 | static propTypes = { | 21 | static propTypes = { |
21 | name: PropTypes.string.isRequired, | 22 | name: PropTypes.string.isRequired, |
22 | enable: PropTypes.func.isRequired, | 23 | enable: PropTypes.func.isRequired, |
23 | }; | 24 | }; |
24 | 25 | ||
25 | static contextTypes = { | ||
26 | intl: intlShape, | ||
27 | }; | ||
28 | |||
29 | countdownInterval = null; | 26 | countdownInterval = null; |
30 | 27 | ||
31 | countdownIntervalTimeout = 1000; | 28 | countdownIntervalTimeout = 1000; |
32 | 29 | ||
33 | render() { | 30 | render() { |
34 | const { name, enable } = this.props; | 31 | const { name, enable } = this.props; |
35 | const { intl } = this.context; | 32 | const { intl } = this.props; |
36 | 33 | ||
37 | return ( | 34 | return ( |
38 | <div className="services__info-layer"> | 35 | <div className="services__info-layer"> |
@@ -46,3 +43,5 @@ export default @observer class ServiceDisabled extends Component { | |||
46 | ); | 43 | ); |
47 | } | 44 | } |
48 | } | 45 | } |
46 | |||
47 | export default injectIntl(ServiceDisabled); | ||
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js index 3fc084ff0..fa866e153 100644 --- a/src/components/services/content/ServiceView.js +++ b/src/components/services/content/ServiceView.js | |||
@@ -15,7 +15,9 @@ import SettingsStore from '../../../stores/SettingsStore'; | |||
15 | import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; | 15 | import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; |
16 | import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config'; | 16 | import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config'; |
17 | 17 | ||
18 | export default @inject('stores', 'actions') @observer class ServiceView extends Component { | 18 | @inject('stores', 'actions') |
19 | @observer | ||
20 | class ServiceView extends Component { | ||
19 | static propTypes = { | 21 | static propTypes = { |
20 | service: PropTypes.instanceOf(ServiceModel).isRequired, | 22 | service: PropTypes.instanceOf(ServiceModel).isRequired, |
21 | setWebviewReference: PropTypes.func.isRequired, | 23 | setWebviewReference: PropTypes.func.isRequired, |
@@ -63,7 +65,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
63 | clearTimeout(this.hibernationTimer); | 65 | clearTimeout(this.hibernationTimer); |
64 | } | 66 | } |
65 | 67 | ||
66 | updateTargetUrl = (event) => { | 68 | updateTargetUrl = event => { |
67 | let visible = true; | 69 | let visible = true; |
68 | if (event.url === '' || event.url === '#') { | 70 | if (event.url === '' || event.url === '#') { |
69 | visible = false; | 71 | visible = false; |
@@ -86,11 +88,12 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
86 | isSpellcheckerEnabled, | 88 | isSpellcheckerEnabled, |
87 | } = this.props; | 89 | } = this.props; |
88 | 90 | ||
89 | const { | 91 | const { navigationBarBehaviour } = stores.settings.app; |
90 | navigationBarBehaviour, | ||
91 | } = stores.settings.app; | ||
92 | 92 | ||
93 | const showNavBar = navigationBarBehaviour === 'always' || (navigationBarBehaviour === 'custom' && service.recipe.id === CUSTOM_WEBSITE_RECIPE_ID); | 93 | const showNavBar = |
94 | navigationBarBehaviour === 'always' || | ||
95 | (navigationBarBehaviour === 'custom' && | ||
96 | service.recipe.id === CUSTOM_WEBSITE_RECIPE_ID); | ||
94 | 97 | ||
95 | const webviewClasses = classnames({ | 98 | const webviewClasses = classnames({ |
96 | services__webview: true, | 99 | services__webview: true, |
@@ -101,9 +104,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
101 | 104 | ||
102 | let statusBar = null; | 105 | let statusBar = null; |
103 | if (this.state.statusBarVisible) { | 106 | if (this.state.statusBarVisible) { |
104 | statusBar = ( | 107 | statusBar = <StatusBarTargetUrl text={this.state.targetUrl} />; |
105 | <StatusBarTargetUrl text={this.state.targetUrl} /> | ||
106 | ); | ||
107 | } | 108 | } |
108 | 109 | ||
109 | return ( | 110 | return ( |
@@ -117,11 +118,11 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
117 | reload={reload} | 118 | reload={reload} |
118 | /> | 119 | /> |
119 | )} | 120 | )} |
120 | {service.isEnabled && service.isLoading && service.isFirstLoad && !service.isServiceAccessRestricted && ( | 121 | {service.isEnabled && |
121 | <WebviewLoader | 122 | service.isLoading && |
122 | loaded={false} | 123 | service.isFirstLoad && |
123 | name={service.name} | 124 | !service.isServiceAccessRestricted && ( |
124 | /> | 125 | <WebviewLoader loaded={false} name={service.name} /> |
125 | )} | 126 | )} |
126 | {service.isError && ( | 127 | {service.isError && ( |
127 | <WebviewErrorHandler | 128 | <WebviewErrorHandler |
@@ -147,9 +148,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
147 | <> | 148 | <> |
148 | {!service.isHibernating ? ( | 149 | {!service.isHibernating ? ( |
149 | <> | 150 | <> |
150 | {showNavBar && ( | 151 | {showNavBar && <WebControlsScreen service={service} />} |
151 | <WebControlsScreen service={service} /> | ||
152 | )} | ||
153 | <ServiceWebview | 152 | <ServiceWebview |
154 | service={service} | 153 | service={service} |
155 | setWebviewReference={setWebviewReference} | 154 | setWebviewReference={setWebviewReference} |
@@ -159,9 +158,11 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
159 | </> | 158 | </> |
160 | ) : ( | 159 | ) : ( |
161 | <div> | 160 | <div> |
162 | <span role="img" aria-label="Sleeping Emoji">😴</span> | 161 | <span role="img" aria-label="Sleeping Emoji"> |
163 | {' '} | 162 | 😴 |
164 | This service is currently hibernating. If this page doesn't close soon, please try reloading Ferdi. | 163 | </span>{' '} |
164 | This service is currently hibernating. If this page doesn't | ||
165 | close soon, please try reloading Ferdi. | ||
165 | </div> | 166 | </div> |
166 | )} | 167 | )} |
167 | </> | 168 | </> |
@@ -171,3 +172,5 @@ export default @inject('stores', 'actions') @observer class ServiceView extends | |||
171 | ); | 172 | ); |
172 | } | 173 | } |
173 | } | 174 | } |
175 | |||
176 | export default ServiceView; | ||
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index bb93ff7d4..fb43fb816 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import Confetti from 'react-confetti'; | 6 | import Confetti from 'react-confetti'; |
7 | import ms from 'ms'; | 7 | import ms from 'ms'; |
8 | import injectSheet from 'react-jss'; | 8 | import injectSheet from 'react-jss'; |
@@ -14,23 +14,24 @@ import serverlessLogin from '../../../helpers/serverless-helpers'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | welcome: { | 15 | welcome: { |
16 | id: 'services.welcome', | 16 | id: 'services.welcome', |
17 | defaultMessage: '!!!Welcome to Ferdi', | 17 | defaultMessage: 'Welcome to Ferdi', |
18 | }, | 18 | }, |
19 | getStarted: { | 19 | getStarted: { |
20 | id: 'services.getStarted', | 20 | id: 'services.getStarted', |
21 | defaultMessage: '!!!Get started', | 21 | defaultMessage: 'Get started', |
22 | }, | 22 | }, |
23 | login: { | 23 | login: { |
24 | id: 'services.login', | 24 | id: 'services.login', |
25 | defaultMessage: '!!!Please login to use Ferdi.', | 25 | defaultMessage: 'Please login to use Ferdi.', |
26 | }, | 26 | }, |
27 | serverless: { | 27 | serverless: { |
28 | id: 'services.serverless', | 28 | id: 'services.serverless', |
29 | defaultMessage: '!!!Use Ferdi without an Account', | 29 | defaultMessage: 'Use Ferdi without an Account', |
30 | }, | 30 | }, |
31 | serverInfo: { | 31 | serverInfo: { |
32 | id: 'services.serverInfo', | 32 | id: 'services.serverInfo', |
33 | defaultMessage: '!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!', | 33 | defaultMessage: |
34 | 'Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!', | ||
34 | }, | 35 | }, |
35 | }); | 36 | }); |
36 | 37 | ||
@@ -43,7 +44,10 @@ const styles = { | |||
43 | }, | 44 | }, |
44 | }; | 45 | }; |
45 | 46 | ||
46 | export default @injectSheet(styles) @inject('actions') @observer class Services extends Component { | 47 | @injectSheet(styles) |
48 | @inject('actions') | ||
49 | @observer | ||
50 | class Services extends Component { | ||
47 | static propTypes = { | 51 | static propTypes = { |
48 | services: MobxPropTypes.arrayOrObservableArray, | 52 | services: MobxPropTypes.arrayOrObservableArray, |
49 | setWebviewReference: PropTypes.func.isRequired, | 53 | setWebviewReference: PropTypes.func.isRequired, |
@@ -63,10 +67,6 @@ export default @injectSheet(styles) @inject('actions') @observer class Services | |||
63 | services: [], | 67 | services: [], |
64 | }; | 68 | }; |
65 | 69 | ||
66 | static contextTypes = { | ||
67 | intl: intlShape, | ||
68 | }; | ||
69 | |||
70 | state = { | 70 | state = { |
71 | showConfetti: true, | 71 | showConfetti: true, |
72 | }; | 72 | }; |
@@ -112,11 +112,9 @@ export default @injectSheet(styles) @inject('actions') @observer class Services | |||
112 | isSpellcheckerEnabled, | 112 | isSpellcheckerEnabled, |
113 | } = this.props; | 113 | } = this.props; |
114 | 114 | ||
115 | const { | 115 | const { showConfetti } = this.state; |
116 | showConfetti, | ||
117 | } = this.state; | ||
118 | 116 | ||
119 | const { intl } = this.context; | 117 | const { intl } = this.props; |
120 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | 118 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); |
121 | 119 | ||
122 | return ( | 120 | return ( |
@@ -131,25 +129,28 @@ export default @injectSheet(styles) @inject('actions') @observer class Services | |||
131 | </div> | 129 | </div> |
132 | )} | 130 | )} |
133 | {services.length === 0 && ( | 131 | {services.length === 0 && ( |
134 | <Appear | 132 | <Appear timeout={1500} transitionName="slideUp"> |
135 | timeout={1500} | ||
136 | transitionName="slideUp" | ||
137 | > | ||
138 | <div className="services__no-service"> | 133 | <div className="services__no-service"> |
139 | <img src="./assets/images/logo.svg" alt="Logo" style={{ maxHeight: '50vh' }} /> | 134 | <img |
135 | src="./assets/images/logo.svg" | ||
136 | alt="Logo" | ||
137 | style={{ maxHeight: '50vh' }} | ||
138 | /> | ||
140 | <h1>{intl.formatMessage(messages.welcome)}</h1> | 139 | <h1>{intl.formatMessage(messages.welcome)}</h1> |
141 | { !isLoggedIn && ( | 140 | {!isLoggedIn && ( |
142 | <> | 141 | <> |
143 | <p>{intl.formatMessage(messages.login)}</p> | 142 | <p>{intl.formatMessage(messages.login)}</p> |
144 | <p>{intl.formatMessage(messages.serverInfo)}</p> | 143 | <p>{intl.formatMessage(messages.serverInfo)}</p> |
145 | </> | 144 | </> |
146 | ) } | 145 | )} |
147 | <Appear | 146 | <Appear timeout={300} transitionName="slideUp"> |
148 | timeout={300} | 147 | <Link |
149 | transitionName="slideUp" | 148 | to={isLoggedIn ? '/settings/recipes' : '/auth/welcome'} |
150 | > | 149 | className="button" |
151 | <Link to={isLoggedIn ? '/settings/recipes' : '/auth/welcome'} className="button"> | 150 | > |
152 | { isLoggedIn ? intl.formatMessage(messages.getStarted) : 'Login' } | 151 | {isLoggedIn |
152 | ? intl.formatMessage(messages.getStarted) | ||
153 | : 'Login'} | ||
153 | </Link> | 154 | </Link> |
154 | {!isLoggedIn && ( | 155 | {!isLoggedIn && ( |
155 | <button | 156 | <button |
@@ -167,27 +168,33 @@ export default @injectSheet(styles) @inject('actions') @observer class Services | |||
167 | </div> | 168 | </div> |
168 | </Appear> | 169 | </Appear> |
169 | )} | 170 | )} |
170 | {services.filter((service) => !service.isTodosService).map((service) => ( | 171 | {services |
171 | <ServiceView | 172 | .filter(service => !service.isTodosService) |
172 | key={service.id} | 173 | .map(service => ( |
173 | service={service} | 174 | <ServiceView |
174 | handleIPCMessage={handleIPCMessage} | 175 | key={service.id} |
175 | setWebviewReference={setWebviewReference} | 176 | service={service} |
176 | detachService={detachService} | 177 | handleIPCMessage={handleIPCMessage} |
177 | openWindow={openWindow} | 178 | setWebviewReference={setWebviewReference} |
178 | reload={() => reload({ serviceId: service.id })} | 179 | detachService={detachService} |
179 | edit={() => openSettings({ path: `services/edit/${service.id}` })} | 180 | openWindow={openWindow} |
180 | enable={() => update({ | 181 | reload={() => reload({ serviceId: service.id })} |
181 | serviceId: service.id, | 182 | edit={() => openSettings({ path: `services/edit/${service.id}` })} |
182 | serviceData: { | 183 | enable={() => |
183 | isEnabled: true, | 184 | update({ |
184 | }, | 185 | serviceId: service.id, |
185 | redirect: false, | 186 | serviceData: { |
186 | })} | 187 | isEnabled: true, |
187 | isSpellcheckerEnabled={isSpellcheckerEnabled} | 188 | }, |
188 | /> | 189 | redirect: false, |
189 | ))} | 190 | }) |
191 | } | ||
192 | isSpellcheckerEnabled={isSpellcheckerEnabled} | ||
193 | /> | ||
194 | ))} | ||
190 | </div> | 195 | </div> |
191 | ); | 196 | ); |
192 | } | 197 | } |
193 | } | 198 | } |
199 | |||
200 | export default injectIntl(Services); | ||
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js index 10ff0bbbb..a332602be 100644 --- a/src/components/services/content/WebviewCrashHandler.js +++ b/src/components/services/content/WebviewCrashHandler.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import ms from 'ms'; | 5 | import ms from 'ms'; |
6 | 6 | ||
7 | import Button from '../../ui/Button'; | 7 | import Button from '../../ui/Button'; |
@@ -9,35 +9,33 @@ import Button from '../../ui/Button'; | |||
9 | const messages = defineMessages({ | 9 | const messages = defineMessages({ |
10 | headline: { | 10 | headline: { |
11 | id: 'service.crashHandler.headline', | 11 | id: 'service.crashHandler.headline', |
12 | defaultMessage: '!!!Oh no!', | 12 | defaultMessage: 'Oh no!', |
13 | }, | 13 | }, |
14 | text: { | 14 | text: { |
15 | id: 'service.crashHandler.text', | 15 | id: 'service.crashHandler.text', |
16 | defaultMessage: '!!!{name} has caused an error.', | 16 | defaultMessage: '{name} has caused an error.', |
17 | }, | 17 | }, |
18 | action: { | 18 | action: { |
19 | id: 'service.crashHandler.action', | 19 | id: 'service.crashHandler.action', |
20 | defaultMessage: '!!!Reload {name}', | 20 | defaultMessage: 'Reload {name}', |
21 | }, | 21 | }, |
22 | autoReload: { | 22 | autoReload: { |
23 | id: 'service.crashHandler.autoReload', | 23 | id: 'service.crashHandler.autoReload', |
24 | defaultMessage: '!!!Trying to automatically restore {name} in {seconds} seconds', | 24 | defaultMessage: |
25 | 'Trying to automatically restore {name} in {seconds} seconds', | ||
25 | }, | 26 | }, |
26 | }); | 27 | }); |
27 | 28 | ||
28 | export default @observer class WebviewCrashHandler extends Component { | 29 | @observer |
30 | class WebviewCrashHandler extends Component { | ||
29 | static propTypes = { | 31 | static propTypes = { |
30 | name: PropTypes.string.isRequired, | 32 | name: PropTypes.string.isRequired, |
31 | reload: PropTypes.func.isRequired, | 33 | reload: PropTypes.func.isRequired, |
32 | }; | 34 | }; |
33 | 35 | ||
34 | static contextTypes = { | ||
35 | intl: intlShape, | ||
36 | }; | ||
37 | |||
38 | state = { | 36 | state = { |
39 | countdown: ms('10s'), | 37 | countdown: ms('10s'), |
40 | } | 38 | }; |
41 | 39 | ||
42 | countdownInterval = null; | 40 | countdownInterval = null; |
43 | 41 | ||
@@ -47,7 +45,7 @@ export default @observer class WebviewCrashHandler extends Component { | |||
47 | const { reload } = this.props; | 45 | const { reload } = this.props; |
48 | 46 | ||
49 | this.countdownInterval = setInterval(() => { | 47 | this.countdownInterval = setInterval(() => { |
50 | this.setState((prevState) => ({ | 48 | this.setState(prevState => ({ |
51 | countdown: prevState.countdown - this.countdownIntervalTimeout, | 49 | countdown: prevState.countdown - this.countdownIntervalTimeout, |
52 | })); | 50 | })); |
53 | 51 | ||
@@ -60,7 +58,7 @@ export default @observer class WebviewCrashHandler extends Component { | |||
60 | 58 | ||
61 | render() { | 59 | render() { |
62 | const { name, reload } = this.props; | 60 | const { name, reload } = this.props; |
63 | const { intl } = this.context; | 61 | const { intl } = this.props; |
64 | 62 | ||
65 | return ( | 63 | return ( |
66 | <div className="services__info-layer"> | 64 | <div className="services__info-layer"> |
@@ -82,3 +80,5 @@ export default @observer class WebviewCrashHandler extends Component { | |||
82 | ); | 80 | ); |
83 | } | 81 | } |
84 | } | 82 | } |
83 | |||
84 | export default injectIntl(WebviewCrashHandler); | ||
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index e5892be5d..b1a3ffbbb 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Menu, dialog, app, getCurrentWindow } from '@electron/remote'; | 1 | import { Menu, dialog, app, getCurrentWindow } from '@electron/remote'; |
2 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | import PropTypes from 'prop-types'; | 4 | import PropTypes from 'prop-types'; |
5 | import { observer } from 'mobx-react'; | 5 | import { observer } from 'mobx-react'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
@@ -20,56 +20,55 @@ const IS_SERVICE_DEBUGGING_ENABLED = ( | |||
20 | const messages = defineMessages({ | 20 | const messages = defineMessages({ |
21 | reload: { | 21 | reload: { |
22 | id: 'tabs.item.reload', | 22 | id: 'tabs.item.reload', |
23 | defaultMessage: '!!!Reload', | 23 | defaultMessage: 'Reload', |
24 | }, | 24 | }, |
25 | disableNotifications: { | 25 | disableNotifications: { |
26 | id: 'tabs.item.disableNotifications', | 26 | id: 'tabs.item.disableNotifications', |
27 | defaultMessage: '!!!Disable notifications', | 27 | defaultMessage: 'Disable notifications', |
28 | }, | 28 | }, |
29 | enableNotifications: { | 29 | enableNotifications: { |
30 | id: 'tabs.item.enableNotification', | 30 | id: 'tabs.item.enableNotification', |
31 | defaultMessage: '!!!Enable notifications', | 31 | defaultMessage: 'Enable notifications', |
32 | }, | 32 | }, |
33 | disableAudio: { | 33 | disableAudio: { |
34 | id: 'tabs.item.disableAudio', | 34 | id: 'tabs.item.disableAudio', |
35 | defaultMessage: '!!!Disable audio', | 35 | defaultMessage: 'Disable audio', |
36 | }, | 36 | }, |
37 | enableAudio: { | 37 | enableAudio: { |
38 | id: 'tabs.item.enableAudio', | 38 | id: 'tabs.item.enableAudio', |
39 | defaultMessage: '!!!Enable audio', | 39 | defaultMessage: 'Enable audio', |
40 | }, | 40 | }, |
41 | enableDarkMode: { | 41 | enableDarkMode: { |
42 | id: 'tabs.item.enableDarkMode', | 42 | id: 'tabs.item.enableDarkMode', |
43 | defaultMessage: '!!!Enable Dark mode', | 43 | defaultMessage: 'Enable Dark mode', |
44 | }, | 44 | }, |
45 | disableDarkMode: { | 45 | disableDarkMode: { |
46 | id: 'tabs.item.disableDarkMode', | 46 | id: 'tabs.item.disableDarkMode', |
47 | defaultMessage: '!!!Disable Dark mode', | 47 | defaultMessage: 'Disable Dark mode', |
48 | }, | 48 | }, |
49 | disableService: { | 49 | disableService: { |
50 | id: 'tabs.item.disableService', | 50 | id: 'tabs.item.disableService', |
51 | defaultMessage: '!!!Disable Service', | 51 | defaultMessage: 'Disable Service', |
52 | }, | 52 | }, |
53 | enableService: { | 53 | enableService: { |
54 | id: 'tabs.item.enableService', | 54 | id: 'tabs.item.enableService', |
55 | defaultMessage: '!!!Enable Service', | 55 | defaultMessage: 'Enable Service', |
56 | }, | 56 | }, |
57 | hibernateService: { | 57 | hibernateService: { |
58 | id: 'tabs.item.hibernateService', | 58 | id: 'tabs.item.hibernateService', |
59 | defaultMessage: '!!!Hibernate Service', | 59 | defaultMessage: 'Hibernate Service', |
60 | }, | 60 | }, |
61 | wakeUpService: { | 61 | wakeUpService: { |
62 | id: 'tabs.item.wakeUpService', | 62 | id: 'tabs.item.wakeUpService', |
63 | defaultMessage: '!!!Wake Up Service', | 63 | defaultMessage: 'Wake Up Service', |
64 | }, | 64 | }, |
65 | deleteService: { | 65 | deleteService: { |
66 | id: 'tabs.item.deleteService', | 66 | id: 'tabs.item.deleteService', |
67 | defaultMessage: '!!!Delete Service', | 67 | defaultMessage: 'Delete Service', |
68 | }, | 68 | }, |
69 | confirmDeleteService: { | 69 | confirmDeleteService: { |
70 | id: 'tabs.item.confirmDeleteService', | 70 | id: 'tabs.item.confirmDeleteService', |
71 | defaultMessage: | 71 | defaultMessage: 'Do you really want to delete the {serviceName} service?', |
72 | '!!!Do you really want to delete the {serviceName} service?', | ||
73 | }, | 72 | }, |
74 | }); | 73 | }); |
75 | 74 | ||
@@ -134,10 +133,6 @@ class TabItem extends Component { | |||
134 | showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired, | 133 | showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired, |
135 | }; | 134 | }; |
136 | 135 | ||
137 | static contextTypes = { | ||
138 | intl: intlShape, | ||
139 | }; | ||
140 | |||
141 | @observable isPolled = false; | 136 | @observable isPolled = false; |
142 | 137 | ||
143 | @observable isPollAnswered = false; | 138 | @observable isPollAnswered = false; |
@@ -185,7 +180,7 @@ class TabItem extends Component { | |||
185 | showMessageBadgeWhenMutedSetting, | 180 | showMessageBadgeWhenMutedSetting, |
186 | showMessageBadgesEvenWhenMuted, | 181 | showMessageBadgesEvenWhenMuted, |
187 | } = this.props; | 182 | } = this.props; |
188 | const { intl } = this.context; | 183 | const { intl } = this.props; |
189 | 184 | ||
190 | const menuTemplate = [ | 185 | const menuTemplate = [ |
191 | { | 186 | { |
@@ -256,7 +251,10 @@ class TabItem extends Component { | |||
256 | detail: intl.formatMessage(messages.confirmDeleteService, { | 251 | detail: intl.formatMessage(messages.confirmDeleteService, { |
257 | serviceName: service.name || service.recipe.name, | 252 | serviceName: service.name || service.recipe.name, |
258 | }), | 253 | }), |
259 | buttons: [intl.formatMessage(globalMessages.yes), intl.formatMessage(globalMessages.no)], | 254 | buttons: [ |
255 | intl.formatMessage(globalMessages.yes), | ||
256 | intl.formatMessage(globalMessages.no), | ||
257 | ], | ||
260 | }); | 258 | }); |
261 | if (selection === 0) { | 259 | if (selection === 0) { |
262 | deleteService(); | 260 | deleteService(); |
@@ -304,7 +302,9 @@ class TabItem extends Component { | |||
304 | onClick={clickHandler} | 302 | onClick={clickHandler} |
305 | onContextMenu={() => menu.popup(getCurrentWindow())} | 303 | onContextMenu={() => menu.popup(getCurrentWindow())} |
306 | data-tip={`${service.name} ${ | 304 | data-tip={`${service.name} ${ |
307 | shortcutIndex <= 9 ? `(${cmdOrCtrlShortcutKey(false)}+${shortcutIndex})` : '' | 305 | shortcutIndex <= 9 |
306 | ? `(${cmdOrCtrlShortcutKey(false)}+${shortcutIndex})` | ||
307 | : '' | ||
308 | }`} | 308 | }`} |
309 | > | 309 | > |
310 | <img src={service.icon} className="tab-item__icon" alt="" /> | 310 | <img src={service.icon} className="tab-item__icon" alt="" /> |
@@ -332,4 +332,4 @@ class TabItem extends Component { | |||
332 | } | 332 | } |
333 | } | 333 | } |
334 | 334 | ||
335 | export default SortableElement(TabItem); | 335 | export default injectIntl(SortableElement(TabItem)); |
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js index c1421a2b1..a77799819 100644 --- a/src/components/services/tabs/Tabbar.js +++ b/src/components/services/tabs/Tabbar.js | |||
@@ -4,7 +4,8 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | |||
4 | 4 | ||
5 | import TabBarSortableList from './TabBarSortableList'; | 5 | import TabBarSortableList from './TabBarSortableList'; |
6 | 6 | ||
7 | export default @observer class TabBar extends Component { | 7 | @observer |
8 | class TabBar extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | services: MobxPropTypes.arrayOrObservableArray.isRequired, | 10 | services: MobxPropTypes.arrayOrObservableArray.isRequired, |
10 | setActive: PropTypes.func.isRequired, | 11 | setActive: PropTypes.func.isRequired, |
@@ -26,16 +27,13 @@ export default @observer class TabBar extends Component { | |||
26 | }; | 27 | }; |
27 | 28 | ||
28 | onSortEnd = ({ oldIndex, newIndex }) => { | 29 | onSortEnd = ({ oldIndex, newIndex }) => { |
29 | const { | 30 | const { enableToolTip, reorder } = this.props; |
30 | enableToolTip, | ||
31 | reorder, | ||
32 | } = this.props; | ||
33 | 31 | ||
34 | enableToolTip(); | 32 | enableToolTip(); |
35 | reorder({ oldIndex, newIndex }); | 33 | reorder({ oldIndex, newIndex }); |
36 | }; | 34 | }; |
37 | 35 | ||
38 | shouldPreventSorting = (event) => event.target.tagName !== 'LI'; | 36 | shouldPreventSorting = event => event.target.tagName !== 'LI'; |
39 | 37 | ||
40 | toggleService = ({ serviceId, isEnabled }) => { | 38 | toggleService = ({ serviceId, isEnabled }) => { |
41 | const { updateService } = this.props; | 39 | const { updateService } = this.props; |
@@ -102,10 +100,10 @@ export default @observer class TabBar extends Component { | |||
102 | toggleAudio={toggleAudio} | 100 | toggleAudio={toggleAudio} |
103 | toggleDarkMode={toggleDarkMode} | 101 | toggleDarkMode={toggleDarkMode} |
104 | deleteService={deleteService} | 102 | deleteService={deleteService} |
105 | disableService={(args) => this.disableService(args)} | 103 | disableService={args => this.disableService(args)} |
106 | enableService={(args) => this.enableService(args)} | 104 | enableService={args => this.enableService(args)} |
107 | hibernateService={(args) => this.hibernateService(args)} | 105 | hibernateService={args => this.hibernateService(args)} |
108 | wakeUpService={(args) => this.wakeUpService(args)} | 106 | wakeUpService={args => this.wakeUpService(args)} |
109 | openSettings={openSettings} | 107 | openSettings={openSettings} |
110 | distance={20} | 108 | distance={20} |
111 | axis={axis} | 109 | axis={axis} |
@@ -118,3 +116,5 @@ export default @observer class TabBar extends Component { | |||
118 | ); | 116 | ); |
119 | } | 117 | } |
120 | } | 118 | } |
119 | |||
120 | export default TabBar; | ||
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js index 5b3b754fa..0574b3765 100644 --- a/src/components/settings/SettingsLayout.js +++ b/src/components/settings/SettingsLayout.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import ErrorBoundary from '../util/ErrorBoundary'; | 6 | import ErrorBoundary from '../util/ErrorBoundary'; |
7 | import { oneOrManyChildElements } from '../../prop-types'; | 7 | import { oneOrManyChildElements } from '../../prop-types'; |
@@ -10,11 +10,10 @@ import Appear from '../ui/effects/Appear'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | closeSettings: { | 11 | closeSettings: { |
12 | id: 'settings.app.closeSettings', | 12 | id: 'settings.app.closeSettings', |
13 | defaultMessage: '!!!Close settings', | 13 | defaultMessage: 'Close settings', |
14 | }, | 14 | }, |
15 | }); | 15 | }); |
16 | 16 | ||
17 | export default | ||
18 | @observer | 17 | @observer |
19 | class SettingsLayout extends Component { | 18 | class SettingsLayout extends Component { |
20 | static propTypes = { | 19 | static propTypes = { |
@@ -23,10 +22,6 @@ class SettingsLayout extends Component { | |||
23 | closeSettings: PropTypes.func.isRequired, | 22 | closeSettings: PropTypes.func.isRequired, |
24 | }; | 23 | }; |
25 | 24 | ||
26 | static contextTypes = { | ||
27 | intl: intlShape, | ||
28 | }; | ||
29 | |||
30 | componentDidMount() { | 25 | componentDidMount() { |
31 | document.addEventListener('keydown', this.handleKeyDown.bind(this), false); | 26 | document.addEventListener('keydown', this.handleKeyDown.bind(this), false); |
32 | } | 27 | } |
@@ -49,7 +44,7 @@ class SettingsLayout extends Component { | |||
49 | render() { | 44 | render() { |
50 | const { navigation, children, closeSettings } = this.props; | 45 | const { navigation, children, closeSettings } = this.props; |
51 | 46 | ||
52 | const { intl } = this.context; | 47 | const { intl } = this.props; |
53 | 48 | ||
54 | return ( | 49 | return ( |
55 | <Appear transitionName="fadeIn-fast"> | 50 | <Appear transitionName="fadeIn-fast"> |
@@ -77,3 +72,5 @@ class SettingsLayout extends Component { | |||
77 | ); | 72 | ); |
78 | } | 73 | } |
79 | } | 74 | } |
75 | |||
76 | export default injectIntl(SettingsLayout); | ||
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index ef7748343..933d47d12 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import { H1, H2 } from '@meetfranz/ui'; | 6 | import { H1, H2 } from '@meetfranz/ui'; |
7 | 7 | ||
@@ -13,7 +13,7 @@ import { LOCAL_SERVER, LIVE_FRANZ_API } from '../../../config'; | |||
13 | const messages = defineMessages({ | 13 | const messages = defineMessages({ |
14 | headline: { | 14 | headline: { |
15 | id: 'settings.account.headline', | 15 | id: 'settings.account.headline', |
16 | defaultMessage: '!!!Account', | 16 | defaultMessage: 'Account', |
17 | }, | 17 | }, |
18 | headlineDangerZone: { | 18 | headlineDangerZone: { |
19 | id: 'settings.account.headlineDangerZone', | 19 | id: 'settings.account.headlineDangerZone', |
@@ -21,7 +21,7 @@ const messages = defineMessages({ | |||
21 | }, | 21 | }, |
22 | accountEditButton: { | 22 | accountEditButton: { |
23 | id: 'settings.account.account.editButton', | 23 | id: 'settings.account.account.editButton', |
24 | defaultMessage: '!!!Edit Account', | 24 | defaultMessage: 'Edit Account', |
25 | }, | 25 | }, |
26 | invoicesButton: { | 26 | invoicesButton: { |
27 | id: 'settings.account.headlineInvoices', | 27 | id: 'settings.account.headlineInvoices', |
@@ -29,29 +29,29 @@ const messages = defineMessages({ | |||
29 | }, | 29 | }, |
30 | userInfoRequestFailed: { | 30 | userInfoRequestFailed: { |
31 | id: 'settings.account.userInfoRequestFailed', | 31 | id: 'settings.account.userInfoRequestFailed', |
32 | defaultMessage: '!!!Could not load user information', | 32 | defaultMessage: 'Could not load user information', |
33 | }, | 33 | }, |
34 | tryReloadUserInfoRequest: { | 34 | tryReloadUserInfoRequest: { |
35 | id: 'settings.account.tryReloadUserInfoRequest', | 35 | id: 'settings.account.tryReloadUserInfoRequest', |
36 | defaultMessage: '!!!Try again', | 36 | defaultMessage: 'Try again', |
37 | }, | 37 | }, |
38 | deleteAccount: { | 38 | deleteAccount: { |
39 | id: 'settings.account.deleteAccount', | 39 | id: 'settings.account.deleteAccount', |
40 | defaultMessage: '!!!Delete account', | 40 | defaultMessage: 'Delete account', |
41 | }, | 41 | }, |
42 | deleteInfo: { | 42 | deleteInfo: { |
43 | id: 'settings.account.deleteInfo', | 43 | id: 'settings.account.deleteInfo', |
44 | defaultMessage: | 44 | defaultMessage: |
45 | "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.", | 45 | "If you don't need your Ferdi account any longer, you can delete your account and all related data here.", |
46 | }, | 46 | }, |
47 | deleteEmailSent: { | 47 | deleteEmailSent: { |
48 | id: 'settings.account.deleteEmailSent', | 48 | id: 'settings.account.deleteEmailSent', |
49 | defaultMessage: | 49 | defaultMessage: |
50 | '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', | 50 | 'You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', |
51 | }, | 51 | }, |
52 | yourLicense: { | 52 | yourLicense: { |
53 | id: 'settings.account.yourLicense', | 53 | id: 'settings.account.yourLicense', |
54 | defaultMessage: '!!!Your Franz License:', | 54 | defaultMessage: 'Your Franz License:', |
55 | }, | 55 | }, |
56 | accountUnavailable: { | 56 | accountUnavailable: { |
57 | id: 'settings.account.accountUnavailable', | 57 | id: 'settings.account.accountUnavailable', |
@@ -59,7 +59,8 @@ const messages = defineMessages({ | |||
59 | }, | 59 | }, |
60 | accountUnavailableInfo: { | 60 | accountUnavailableInfo: { |
61 | id: 'settings.account.accountUnavailableInfo', | 61 | id: 'settings.account.accountUnavailableInfo', |
62 | defaultMessage: 'You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.', | 62 | defaultMessage: |
63 | 'You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.', | ||
63 | }, | 64 | }, |
64 | }); | 65 | }); |
65 | 66 | ||
@@ -78,10 +79,6 @@ class AccountDashboard extends Component { | |||
78 | server: PropTypes.string.isRequired, | 79 | server: PropTypes.string.isRequired, |
79 | }; | 80 | }; |
80 | 81 | ||
81 | static contextTypes = { | ||
82 | intl: intlShape, | ||
83 | }; | ||
84 | |||
85 | render() { | 82 | render() { |
86 | const { | 83 | const { |
87 | user, | 84 | user, |
@@ -95,7 +92,7 @@ class AccountDashboard extends Component { | |||
95 | openInvoices, | 92 | openInvoices, |
96 | server, | 93 | server, |
97 | } = this.props; | 94 | } = this.props; |
98 | const { intl } = this.context; | 95 | const { intl } = this.props; |
99 | 96 | ||
100 | const isUsingWithoutAccount = server === LOCAL_SERVER; | 97 | const isUsingWithoutAccount = server === LOCAL_SERVER; |
101 | const isUsingFranzServer = server === LIVE_FRANZ_API; | 98 | const isUsingFranzServer = server === LIVE_FRANZ_API; |
@@ -182,9 +179,7 @@ class AccountDashboard extends Component { | |||
182 | <div className="account"> | 179 | <div className="account"> |
183 | <div className="account__box"> | 180 | <div className="account__box"> |
184 | <H2>{intl.formatMessage(messages.yourLicense)}</H2> | 181 | <H2>{intl.formatMessage(messages.yourLicense)}</H2> |
185 | <p> | 182 | <p>Franz</p> |
186 | Franz | ||
187 | </p> | ||
188 | <div className="manage-user-links"> | 183 | <div className="manage-user-links"> |
189 | <Button | 184 | <Button |
190 | label={intl.formatMessage( | 185 | label={intl.formatMessage( |
@@ -203,7 +198,9 @@ class AccountDashboard extends Component { | |||
203 | {isUsingFranzServer && ( | 198 | {isUsingFranzServer && ( |
204 | <div className="account franz-form"> | 199 | <div className="account franz-form"> |
205 | <div className="account__box"> | 200 | <div className="account__box"> |
206 | <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2> | 201 | <H2> |
202 | {intl.formatMessage(messages.headlineDangerZone)} | ||
203 | </H2> | ||
207 | {!isDeleteAccountSuccessful && ( | 204 | {!isDeleteAccountSuccessful && ( |
208 | <div className="account__subscription"> | 205 | <div className="account__subscription"> |
209 | <p>{intl.formatMessage(messages.deleteInfo)}</p> | 206 | <p>{intl.formatMessage(messages.deleteInfo)}</p> |
@@ -232,4 +229,4 @@ class AccountDashboard extends Component { | |||
232 | } | 229 | } |
233 | } | 230 | } |
234 | 231 | ||
235 | export default AccountDashboard; | 232 | export default injectIntl(AccountDashboard); |
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js index 0a5ace586..72c7faa66 100644 --- a/src/components/settings/navigation/SettingsNavigation.js +++ b/src/components/settings/navigation/SettingsNavigation.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | import { inject, observer } from 'mobx-react'; | 4 | import { inject, observer } from 'mobx-react'; |
5 | import { RouterStore } from 'mobx-react-router'; | 5 | import { RouterStore } from 'mobx-react-router'; |
6 | 6 | ||
@@ -15,35 +15,37 @@ import globalMessages from '../../../i18n/globalMessages'; | |||
15 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
16 | availableServices: { | 16 | availableServices: { |
17 | id: 'settings.navigation.availableServices', | 17 | id: 'settings.navigation.availableServices', |
18 | defaultMessage: '!!!Available services', | 18 | defaultMessage: 'Available services', |
19 | }, | 19 | }, |
20 | yourServices: { | 20 | yourServices: { |
21 | id: 'settings.navigation.yourServices', | 21 | id: 'settings.navigation.yourServices', |
22 | defaultMessage: '!!!Your services', | 22 | defaultMessage: 'Your services', |
23 | }, | 23 | }, |
24 | yourWorkspaces: { | 24 | yourWorkspaces: { |
25 | id: 'settings.navigation.yourWorkspaces', | 25 | id: 'settings.navigation.yourWorkspaces', |
26 | defaultMessage: '!!!Your workspaces', | 26 | defaultMessage: 'Your workspaces', |
27 | }, | 27 | }, |
28 | account: { | 28 | account: { |
29 | id: 'settings.navigation.account', | 29 | id: 'settings.navigation.account', |
30 | defaultMessage: '!!!Account', | 30 | defaultMessage: 'Account', |
31 | }, | 31 | }, |
32 | team: { | 32 | team: { |
33 | id: 'settings.navigation.team', | 33 | id: 'settings.navigation.team', |
34 | defaultMessage: '!!!Manage Team', | 34 | defaultMessage: 'Manage Team', |
35 | }, | 35 | }, |
36 | supportFerdi: { | 36 | supportFerdi: { |
37 | id: 'settings.navigation.supportFerdi', | 37 | id: 'settings.navigation.supportFerdi', |
38 | defaultMessage: '!!!About Ferdi', | 38 | defaultMessage: 'About Ferdi', |
39 | }, | 39 | }, |
40 | logout: { | 40 | logout: { |
41 | id: 'settings.navigation.logout', | 41 | id: 'settings.navigation.logout', |
42 | defaultMessage: '!!!Logout', | 42 | defaultMessage: 'Logout', |
43 | }, | 43 | }, |
44 | }); | 44 | }); |
45 | 45 | ||
46 | export default @inject('stores', 'actions') @observer class SettingsNavigation extends Component { | 46 | @inject('stores', 'actions') |
47 | @observer | ||
48 | class SettingsNavigation extends Component { | ||
47 | static propTypes = { | 49 | static propTypes = { |
48 | stores: PropTypes.shape({ | 50 | stores: PropTypes.shape({ |
49 | ui: PropTypes.instanceOf(UIStore).isRequired, | 51 | ui: PropTypes.instanceOf(UIStore).isRequired, |
@@ -58,13 +60,10 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
58 | workspaceCount: PropTypes.number.isRequired, | 60 | workspaceCount: PropTypes.number.isRequired, |
59 | }; | 61 | }; |
60 | 62 | ||
61 | static contextTypes = { | ||
62 | intl: intlShape, | ||
63 | }; | ||
64 | |||
65 | handleLoginLogout() { | 63 | handleLoginLogout() { |
66 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | 64 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); |
67 | const isUsingWithoutAccount = this.props.stores.settings.app.server === LOCAL_SERVER; | 65 | const isUsingWithoutAccount = |
66 | this.props.stores.settings.app.server === LOCAL_SERVER; | ||
68 | 67 | ||
69 | if (isLoggedIn) { | 68 | if (isLoggedIn) { |
70 | // Remove current auth token | 69 | // Remove current auth token |
@@ -82,7 +81,9 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
82 | this.props.stores.user.isLoggingOut = true; | 81 | this.props.stores.user.isLoggingOut = true; |
83 | } | 82 | } |
84 | 83 | ||
85 | this.props.stores.router.push(isLoggedIn ? '/auth/logout' : '/auth/welcome'); | 84 | this.props.stores.router.push( |
85 | isLoggedIn ? '/auth/logout' : '/auth/welcome', | ||
86 | ); | ||
86 | 87 | ||
87 | if (isLoggedIn) { | 88 | if (isLoggedIn) { |
88 | // Reload Ferdi, otherwise many settings won't sync correctly with the server | 89 | // Reload Ferdi, otherwise many settings won't sync correctly with the server |
@@ -93,7 +94,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
93 | 94 | ||
94 | render() { | 95 | render() { |
95 | const { serviceCount, workspaceCount, stores } = this.props; | 96 | const { serviceCount, workspaceCount, stores } = this.props; |
96 | const { intl } = this.context; | 97 | const { intl } = this.props; |
97 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | 98 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); |
98 | const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER; | 99 | const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER; |
99 | const isUsingFranzServer = stores.settings.app.server === LIVE_FRANZ_API; | 100 | const isUsingFranzServer = stores.settings.app.server === LIVE_FRANZ_API; |
@@ -113,11 +114,8 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
113 | activeClassName="is-active" | 114 | activeClassName="is-active" |
114 | disabled={!isLoggedIn} | 115 | disabled={!isLoggedIn} |
115 | > | 116 | > |
116 | {intl.formatMessage(messages.yourServices)} | 117 | {intl.formatMessage(messages.yourServices)}{' '} |
117 | {' '} | 118 | <span className="badge">{serviceCount}</span> |
118 | <span className="badge"> | ||
119 | {serviceCount} | ||
120 | </span> | ||
121 | </Link> | 119 | </Link> |
122 | {workspaceStore.isFeatureEnabled ? ( | 120 | {workspaceStore.isFeatureEnabled ? ( |
123 | <Link | 121 | <Link |
@@ -126,8 +124,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
126 | activeClassName="is-active" | 124 | activeClassName="is-active" |
127 | disabled={!isLoggedIn} | 125 | disabled={!isLoggedIn} |
128 | > | 126 | > |
129 | {intl.formatMessage(messages.yourWorkspaces)} | 127 | {intl.formatMessage(messages.yourWorkspaces)}{' '} |
130 | {' '} | ||
131 | <span className="badge">{workspaceCount}</span> | 128 | <span className="badge">{workspaceCount}</span> |
132 | </Link> | 129 | </Link> |
133 | ) : null} | 130 | ) : null} |
@@ -172,9 +169,13 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e | |||
172 | className="settings-navigation__link" | 169 | className="settings-navigation__link" |
173 | onClick={this.handleLoginLogout.bind(this)} | 170 | onClick={this.handleLoginLogout.bind(this)} |
174 | > | 171 | > |
175 | { isLoggedIn && !isUsingWithoutAccount ? intl.formatMessage(messages.logout) : 'Login'} | 172 | {isLoggedIn && !isUsingWithoutAccount |
173 | ? intl.formatMessage(messages.logout) | ||
174 | : 'Login'} | ||
176 | </button> | 175 | </button> |
177 | </div> | 176 | </div> |
178 | ); | 177 | ); |
179 | } | 178 | } |
180 | } | 179 | } |
180 | |||
181 | export default injectIntl(SettingsNavigation); | ||
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js index 55f415bd5..ca188aa99 100644 --- a/src/components/settings/recipes/RecipeItem.js +++ b/src/components/settings/recipes/RecipeItem.js | |||
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | 4 | ||
5 | import RecipePreviewModel from '../../../models/RecipePreview'; | 5 | import RecipePreviewModel from '../../../models/RecipePreview'; |
6 | 6 | ||
7 | export default @observer class RecipeItem extends Component { | 7 | @observer |
8 | class RecipeItem extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, | 10 | recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, |
10 | onClick: PropTypes.func.isRequired, | 11 | onClick: PropTypes.func.isRequired, |
@@ -14,19 +15,11 @@ export default @observer class RecipeItem extends Component { | |||
14 | const { recipe, onClick } = this.props; | 15 | const { recipe, onClick } = this.props; |
15 | 16 | ||
16 | return ( | 17 | return ( |
17 | <button | 18 | <button type="button" className="recipe-teaser" onClick={onClick}> |
18 | type="button" | ||
19 | className="recipe-teaser" | ||
20 | onClick={onClick} | ||
21 | > | ||
22 | {recipe.isDevRecipe && ( | 19 | {recipe.isDevRecipe && ( |
23 | <span className="recipe-teaser__dev-badge">dev</span> | 20 | <span className="recipe-teaser__dev-badge">dev</span> |
24 | )} | 21 | )} |
25 | <img | 22 | <img src={recipe.icons.svg} className="recipe-teaser__icon" alt="" /> |
26 | src={recipe.icons.svg} | ||
27 | className="recipe-teaser__icon" | ||
28 | alt="" | ||
29 | /> | ||
30 | <span className="recipe-teaser__label">{recipe.name}</span> | 23 | <span className="recipe-teaser__label">{recipe.name}</span> |
31 | {recipe.aliases && recipe.aliases.length > 0 && ( | 24 | {recipe.aliases && recipe.aliases.length > 0 && ( |
32 | <span className="recipe-teaser__alias_label"> | 25 | <span className="recipe-teaser__alias_label"> |
@@ -37,3 +30,5 @@ export default @observer class RecipeItem extends Component { | |||
37 | ); | 30 | ); |
38 | } | 31 | } |
39 | } | 32 | } |
33 | |||
34 | export default RecipeItem; | ||
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js index 44ff2d0d7..e620abf93 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | 6 | ||
7 | import { Button, Input } from '@meetfranz/forms'; | 7 | import { Button, Input } from '@meetfranz/forms'; |
@@ -18,55 +18,56 @@ import RecipePreview from '../../../models/RecipePreview'; | |||
18 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
19 | headline: { | 19 | headline: { |
20 | id: 'settings.recipes.headline', | 20 | id: 'settings.recipes.headline', |
21 | defaultMessage: '!!!Available Services', | 21 | defaultMessage: 'Available Services', |
22 | }, | 22 | }, |
23 | searchService: { | 23 | searchService: { |
24 | id: 'settings.searchService', | 24 | id: 'settings.searchService', |
25 | defaultMessage: '!!!Search service', | 25 | defaultMessage: 'Search service', |
26 | }, | 26 | }, |
27 | allRecipes: { | 27 | allRecipes: { |
28 | id: 'settings.recipes.all', | 28 | id: 'settings.recipes.all', |
29 | defaultMessage: '!!!All services', | 29 | defaultMessage: 'All services', |
30 | }, | 30 | }, |
31 | customRecipes: { | 31 | customRecipes: { |
32 | id: 'settings.recipes.custom', | 32 | id: 'settings.recipes.custom', |
33 | defaultMessage: '!!!Custom Services', | 33 | defaultMessage: 'Custom Services', |
34 | }, | 34 | }, |
35 | nothingFound: { | 35 | nothingFound: { |
36 | id: 'settings.recipes.nothingFound', | 36 | id: 'settings.recipes.nothingFound', |
37 | defaultMessage: '!!!Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | 37 | defaultMessage: |
38 | 'Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | ||
38 | }, | 39 | }, |
39 | servicesSuccessfulAddedInfo: { | 40 | servicesSuccessfulAddedInfo: { |
40 | id: 'settings.recipes.servicesSuccessfulAddedInfo', | 41 | id: 'settings.recipes.servicesSuccessfulAddedInfo', |
41 | defaultMessage: '!!!Service successfully added', | 42 | defaultMessage: 'Service successfully added', |
42 | }, | 43 | }, |
43 | missingService: { | 44 | missingService: { |
44 | id: 'settings.recipes.missingService', | 45 | id: 'settings.recipes.missingService', |
45 | defaultMessage: '!!!Missing a service?', | 46 | defaultMessage: 'Missing a service?', |
46 | }, | 47 | }, |
47 | customRecipeIntro: { | 48 | customRecipeIntro: { |
48 | id: 'settings.recipes.customService.intro', | 49 | id: 'settings.recipes.customService.intro', |
49 | defaultMessage: '!!!To add a custom service, copy the recipe folder into:', | 50 | defaultMessage: 'To add a custom service, copy the recipe folder into:', |
50 | }, | 51 | }, |
51 | openFolder: { | 52 | openFolder: { |
52 | id: 'settings.recipes.customService.openFolder', | 53 | id: 'settings.recipes.customService.openFolder', |
53 | defaultMessage: '!!!Open directory', | 54 | defaultMessage: 'Open directory', |
54 | }, | 55 | }, |
55 | openDevDocs: { | 56 | openDevDocs: { |
56 | id: 'settings.recipes.customService.openDevDocs', | 57 | id: 'settings.recipes.customService.openDevDocs', |
57 | defaultMessage: '!!!Developer Documentation', | 58 | defaultMessage: 'Developer Documentation', |
58 | }, | 59 | }, |
59 | headlineCustomRecipes: { | 60 | headlineCustomRecipes: { |
60 | id: 'settings.recipes.customService.headline.customRecipes', | 61 | id: 'settings.recipes.customService.headline.customRecipes', |
61 | defaultMessage: '!!!Custom 3rd Party Recipes', | 62 | defaultMessage: 'Custom 3rd Party Recipes', |
62 | }, | 63 | }, |
63 | headlineCommunityRecipes: { | 64 | headlineCommunityRecipes: { |
64 | id: 'settings.recipes.customService.headline.communityRecipes', | 65 | id: 'settings.recipes.customService.headline.communityRecipes', |
65 | defaultMessage: '!!!Community 3rd Party Recipes', | 66 | defaultMessage: 'Community 3rd Party Recipes', |
66 | }, | 67 | }, |
67 | headlineDevRecipes: { | 68 | headlineDevRecipes: { |
68 | id: 'settings.recipes.customService.headline.devRecipes', | 69 | id: 'settings.recipes.customService.headline.devRecipes', |
69 | defaultMessage: '!!!Your Development Service Recipes', | 70 | defaultMessage: 'Your Development Service Recipes', |
70 | }, | 71 | }, |
71 | }); | 72 | }); |
72 | 73 | ||
@@ -81,7 +82,8 @@ const styles = { | |||
81 | marginTop: 20, | 82 | marginTop: 20, |
82 | 83 | ||
83 | '& > div': { | 84 | '& > div': { |
84 | fontFamily: 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | 85 | fontFamily: |
86 | 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | ||
85 | }, | 87 | }, |
86 | }, | 88 | }, |
87 | actionContainer: { | 89 | actionContainer: { |
@@ -98,7 +100,9 @@ const styles = { | |||
98 | }, | 100 | }, |
99 | }; | 101 | }; |
100 | 102 | ||
101 | export default @injectSheet(styles) @observer class RecipesDashboard extends Component { | 103 | @injectSheet(styles) |
104 | @observer | ||
105 | class RecipesDashboard extends Component { | ||
102 | static propTypes = { | 106 | static propTypes = { |
103 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, | 107 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, |
104 | customWebsiteRecipe: PropTypes.instanceOf(RecipePreview).isRequired, | 108 | customWebsiteRecipe: PropTypes.instanceOf(RecipePreview).isRequired, |
@@ -118,10 +122,6 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
118 | static defaultProps = { | 122 | static defaultProps = { |
119 | searchNeedle: '', | 123 | searchNeedle: '', |
120 | recipeFilter: 'all', | 124 | recipeFilter: 'all', |
121 | } | ||
122 | |||
123 | static contextTypes = { | ||
124 | intl: intlShape, | ||
125 | }; | 125 | }; |
126 | 126 | ||
127 | render() { | 127 | render() { |
@@ -140,7 +140,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
140 | openDevDocs, | 140 | openDevDocs, |
141 | classes, | 141 | classes, |
142 | } = this.props; | 142 | } = this.props; |
143 | const { intl } = this.context; | 143 | const { intl } = this.props; |
144 | 144 | ||
145 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); | 145 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); |
146 | const devRecipes = recipes.filter(r => r.isDevRecipe); | 146 | const devRecipes = recipes.filter(r => r.isDevRecipe); |
@@ -188,9 +188,13 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
188 | > | 188 | > |
189 | {intl.formatMessage(messages.customRecipes)} | 189 | {intl.formatMessage(messages.customRecipes)} |
190 | </Link> | 190 | </Link> |
191 | <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request" rel="noreferrer"> | 191 | <a |
192 | {intl.formatMessage(messages.missingService)} | 192 | href={FRANZ_SERVICE_REQUEST} |
193 | {' '} | 193 | target="_blank" |
194 | className="link recipes__service-request" | ||
195 | rel="noreferrer" | ||
196 | > | ||
197 | {intl.formatMessage(messages.missingService)}{' '} | ||
194 | <i className="mdi mdi-open-in-new" /> | 198 | <i className="mdi mdi-open-in-new" /> |
195 | </a> | 199 | </a> |
196 | </div> | 200 | </div> |
@@ -201,13 +205,9 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
201 | <> | 205 | <> |
202 | {recipeFilter === 'dev' && ( | 206 | {recipeFilter === 'dev' && ( |
203 | <> | 207 | <> |
204 | <H2> | 208 | <H2>{intl.formatMessage(messages.headlineCustomRecipes)}</H2> |
205 | {intl.formatMessage(messages.headlineCustomRecipes)} | ||
206 | </H2> | ||
207 | <div className={classes.devRecipeIntroContainer}> | 209 | <div className={classes.devRecipeIntroContainer}> |
208 | <p> | 210 | <p>{intl.formatMessage(messages.customRecipeIntro)}</p> |
209 | {intl.formatMessage(messages.customRecipeIntro)} | ||
210 | </p> | ||
211 | <Input | 211 | <Input |
212 | value={recipeDirectory} | 212 | value={recipeDirectory} |
213 | className={classes.path} | 213 | className={classes.path} |
@@ -238,12 +238,19 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
238 | <img src="./assets/images/emoji/dontknow.png" alt="" /> | 238 | <img src="./assets/images/emoji/dontknow.png" alt="" /> |
239 | </span> | 239 | </span> |
240 | 240 | ||
241 | <p className="settings__empty-state-text">{intl.formatMessage(messages.nothingFound)}</p> | 241 | <p className="settings__empty-state-text"> |
242 | {intl.formatMessage(messages.nothingFound)} | ||
243 | </p> | ||
242 | 244 | ||
243 | <RecipeItem | 245 | <RecipeItem |
244 | key={customWebsiteRecipe.id} | 246 | key={customWebsiteRecipe.id} |
245 | recipe={customWebsiteRecipe} | 247 | recipe={customWebsiteRecipe} |
246 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: customWebsiteRecipe.id })} | 248 | onClick={() => |
249 | isLoggedIn && | ||
250 | showAddServiceInterface({ | ||
251 | recipeId: customWebsiteRecipe.id, | ||
252 | }) | ||
253 | } | ||
247 | /> | 254 | /> |
248 | </div> | 255 | </div> |
249 | )} | 256 | )} |
@@ -251,7 +258,10 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
251 | <RecipeItem | 258 | <RecipeItem |
252 | key={recipe.id} | 259 | key={recipe.id} |
253 | recipe={recipe} | 260 | recipe={recipe} |
254 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} | 261 | onClick={() => |
262 | isLoggedIn && | ||
263 | showAddServiceInterface({ recipeId: recipe.id }) | ||
264 | } | ||
255 | /> | 265 | /> |
256 | ))} | 266 | ))} |
257 | </div> | 267 | </div> |
@@ -263,7 +273,10 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
263 | <RecipeItem | 273 | <RecipeItem |
264 | key={recipe.id} | 274 | key={recipe.id} |
265 | recipe={recipe} | 275 | recipe={recipe} |
266 | onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} | 276 | onClick={() => |
277 | isLoggedIn && | ||
278 | showAddServiceInterface({ recipeId: recipe.id }) | ||
279 | } | ||
267 | /> | 280 | /> |
268 | ))} | 281 | ))} |
269 | </div> | 282 | </div> |
@@ -276,3 +289,5 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
276 | ); | 289 | ); |
277 | } | 290 | } |
278 | } | 291 | } |
292 | |||
293 | export default injectIntl(RecipesDashboard); | ||
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index c41cdd56a..3fbb57cbb 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import normalizeUrl from 'normalize-url'; | 6 | import normalizeUrl from 'normalize-url'; |
7 | 7 | ||
8 | import Form from '../../../lib/Form'; | 8 | import Form from '../../../lib/Form'; |
@@ -22,111 +22,117 @@ import globalMessages from '../../../i18n/globalMessages'; | |||
22 | const messages = defineMessages({ | 22 | const messages = defineMessages({ |
23 | saveService: { | 23 | saveService: { |
24 | id: 'settings.service.form.saveButton', | 24 | id: 'settings.service.form.saveButton', |
25 | defaultMessage: '!!!Save service', | 25 | defaultMessage: 'Save service', |
26 | }, | 26 | }, |
27 | deleteService: { | 27 | deleteService: { |
28 | id: 'settings.service.form.deleteButton', | 28 | id: 'settings.service.form.deleteButton', |
29 | defaultMessage: '!!!Delete Service', | 29 | defaultMessage: 'Delete Service', |
30 | }, | 30 | }, |
31 | openDarkmodeCss: { | 31 | openDarkmodeCss: { |
32 | id: 'settings.service.form.openDarkmodeCss', | 32 | id: 'settings.service.form.openDarkmodeCss', |
33 | defaultMessage: '!!!Open darkmode.css', | 33 | defaultMessage: 'Open darkmode.css', |
34 | }, | 34 | }, |
35 | openUserCss: { | 35 | openUserCss: { |
36 | id: 'settings.service.form.openUserCss', | 36 | id: 'settings.service.form.openUserCss', |
37 | defaultMessage: '!!!Open user.css', | 37 | defaultMessage: 'Open user.css', |
38 | }, | 38 | }, |
39 | openUserJs: { | 39 | openUserJs: { |
40 | id: 'settings.service.form.openUserJs', | 40 | id: 'settings.service.form.openUserJs', |
41 | defaultMessage: '!!!Open user.js', | 41 | defaultMessage: 'Open user.js', |
42 | }, | 42 | }, |
43 | recipeFileInfo: { | 43 | recipeFileInfo: { |
44 | id: 'settings.service.form.recipeFileInfo', | 44 | id: 'settings.service.form.recipeFileInfo', |
45 | defaultMessage: '!!!Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.', | 45 | defaultMessage: |
46 | 'Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.', | ||
46 | }, | 47 | }, |
47 | availableServices: { | 48 | availableServices: { |
48 | id: 'settings.service.form.availableServices', | 49 | id: 'settings.service.form.availableServices', |
49 | defaultMessage: '!!!Available services', | 50 | defaultMessage: 'Available services', |
50 | }, | 51 | }, |
51 | yourServices: { | 52 | yourServices: { |
52 | id: 'settings.service.form.yourServices', | 53 | id: 'settings.service.form.yourServices', |
53 | defaultMessage: '!!!Your services', | 54 | defaultMessage: 'Your services', |
54 | }, | 55 | }, |
55 | addServiceHeadline: { | 56 | addServiceHeadline: { |
56 | id: 'settings.service.form.addServiceHeadline', | 57 | id: 'settings.service.form.addServiceHeadline', |
57 | defaultMessage: '!!!Add {name}', | 58 | defaultMessage: 'Add {name}', |
58 | }, | 59 | }, |
59 | editServiceHeadline: { | 60 | editServiceHeadline: { |
60 | id: 'settings.service.form.editServiceHeadline', | 61 | id: 'settings.service.form.editServiceHeadline', |
61 | defaultMessage: '!!!Edit {name}', | 62 | defaultMessage: 'Edit {name}', |
62 | }, | 63 | }, |
63 | tabHosted: { | 64 | tabHosted: { |
64 | id: 'settings.service.form.tabHosted', | 65 | id: 'settings.service.form.tabHosted', |
65 | defaultMessage: '!!!Hosted', | 66 | defaultMessage: 'Hosted', |
66 | }, | 67 | }, |
67 | tabOnPremise: { | 68 | tabOnPremise: { |
68 | id: 'settings.service.form.tabOnPremise', | 69 | id: 'settings.service.form.tabOnPremise', |
69 | defaultMessage: '!!!Self hosted ⭐️', | 70 | defaultMessage: 'Self hosted ⭐️', |
70 | }, | 71 | }, |
71 | useHostedService: { | 72 | useHostedService: { |
72 | id: 'settings.service.form.useHostedService', | 73 | id: 'settings.service.form.useHostedService', |
73 | defaultMessage: '!!!Use the hosted {name} service.', | 74 | defaultMessage: 'Use the hosted {name} service.', |
74 | }, | 75 | }, |
75 | customUrlValidationError: { | 76 | customUrlValidationError: { |
76 | id: 'settings.service.form.customUrlValidationError', | 77 | id: 'settings.service.form.customUrlValidationError', |
77 | defaultMessage: '!!!Could not validate custom {name} server.', | 78 | defaultMessage: 'Could not validate custom {name} server.', |
78 | }, | 79 | }, |
79 | indirectMessageInfo: { | 80 | indirectMessageInfo: { |
80 | id: 'settings.service.form.indirectMessageInfo', | 81 | id: 'settings.service.form.indirectMessageInfo', |
81 | defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', | 82 | defaultMessage: |
83 | 'You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', | ||
82 | }, | 84 | }, |
83 | isMutedInfo: { | 85 | isMutedInfo: { |
84 | id: 'settings.service.form.isMutedInfo', | 86 | id: 'settings.service.form.isMutedInfo', |
85 | defaultMessage: '!!!When disabled, all notification sounds and audio playback are muted', | 87 | defaultMessage: |
88 | 'When disabled, all notification sounds and audio playback are muted', | ||
86 | }, | 89 | }, |
87 | isHibernationEnabledInfo: { | 90 | isHibernationEnabledInfo: { |
88 | id: 'settings.service.form.isHibernatedEnabledInfo', | 91 | id: 'settings.service.form.isHibernatedEnabledInfo', |
89 | defaultMessage: '!!!When enabled, a service will be shut down after a period of time to save system resources.', | 92 | defaultMessage: |
93 | 'When enabled, a service will be shut down after a period of time to save system resources.', | ||
90 | }, | 94 | }, |
91 | headlineNotifications: { | 95 | headlineNotifications: { |
92 | id: 'settings.service.form.headlineNotifications', | 96 | id: 'settings.service.form.headlineNotifications', |
93 | defaultMessage: '!!!Notifications', | 97 | defaultMessage: 'Notifications', |
94 | }, | 98 | }, |
95 | headlineBadges: { | 99 | headlineBadges: { |
96 | id: 'settings.service.form.headlineBadges', | 100 | id: 'settings.service.form.headlineBadges', |
97 | defaultMessage: '!!!Unread message badges', | 101 | defaultMessage: 'Unread message badges', |
98 | }, | 102 | }, |
99 | headlineGeneral: { | 103 | headlineGeneral: { |
100 | id: 'settings.service.form.headlineGeneral', | 104 | id: 'settings.service.form.headlineGeneral', |
101 | defaultMessage: '!!!General', | 105 | defaultMessage: 'General', |
102 | }, | 106 | }, |
103 | headlineDarkReaderSettings: { | 107 | headlineDarkReaderSettings: { |
104 | id: 'settings.service.form.headlineDarkReaderSettings', | 108 | id: 'settings.service.form.headlineDarkReaderSettings', |
105 | defaultMessage: '!!!Dark Reader Settings', | 109 | defaultMessage: 'Dark Reader Settings', |
106 | }, | 110 | }, |
107 | iconDelete: { | 111 | iconDelete: { |
108 | id: 'settings.service.form.iconDelete', | 112 | id: 'settings.service.form.iconDelete', |
109 | defaultMessage: '!!!Delete', | 113 | defaultMessage: 'Delete', |
110 | }, | 114 | }, |
111 | iconUpload: { | 115 | iconUpload: { |
112 | id: 'settings.service.form.iconUpload', | 116 | id: 'settings.service.form.iconUpload', |
113 | defaultMessage: '!!!Drop your image, or click here', | 117 | defaultMessage: 'Drop your image, or click here', |
114 | }, | 118 | }, |
115 | headlineProxy: { | 119 | headlineProxy: { |
116 | id: 'settings.service.form.proxy.headline', | 120 | id: 'settings.service.form.proxy.headline', |
117 | defaultMessage: '!!!HTTP/HTTPS Proxy Settings', | 121 | defaultMessage: 'HTTP/HTTPS Proxy Settings', |
118 | }, | 122 | }, |
119 | proxyRestartInfo: { | 123 | proxyRestartInfo: { |
120 | id: 'settings.service.form.proxy.restartInfo', | 124 | id: 'settings.service.form.proxy.restartInfo', |
121 | defaultMessage: '!!!Please restart Ferdi after changing proxy Settings.', | 125 | defaultMessage: 'Please restart Ferdi after changing proxy Settings.', |
122 | }, | 126 | }, |
123 | proxyInfo: { | 127 | proxyInfo: { |
124 | id: 'settings.service.form.proxy.info', | 128 | id: 'settings.service.form.proxy.info', |
125 | defaultMessage: '!!!Proxy settings will not be synchronized with the Ferdi servers.', | 129 | defaultMessage: |
130 | 'Proxy settings will not be synchronized with the Ferdi servers.', | ||
126 | }, | 131 | }, |
127 | }); | 132 | }); |
128 | 133 | ||
129 | export default @observer class EditServiceForm extends Component { | 134 | @observer |
135 | class EditServiceForm extends Component { | ||
130 | static propTypes = { | 136 | static propTypes = { |
131 | recipe: PropTypes.instanceOf(Recipe).isRequired, | 137 | recipe: PropTypes.instanceOf(Recipe).isRequired, |
132 | service(props, propName) { | 138 | service(props, propName) { |
@@ -151,20 +157,16 @@ export default @observer class EditServiceForm extends Component { | |||
151 | service: {}, | 157 | service: {}, |
152 | }; | 158 | }; |
153 | 159 | ||
154 | static contextTypes = { | ||
155 | intl: intlShape, | ||
156 | }; | ||
157 | |||
158 | state = { | 160 | state = { |
159 | isValidatingCustomUrl: false, | 161 | isValidatingCustomUrl: false, |
160 | } | 162 | }; |
161 | 163 | ||
162 | submit(e) { | 164 | submit(e) { |
163 | const { recipe } = this.props; | 165 | const { recipe } = this.props; |
164 | 166 | ||
165 | e.preventDefault(); | 167 | e.preventDefault(); |
166 | this.props.form.submit({ | 168 | this.props.form.submit({ |
167 | onSuccess: async (form) => { | 169 | onSuccess: async form => { |
168 | const values = form.values(); | 170 | const values = form.values(); |
169 | let isValid = true; | 171 | let isValid = true; |
170 | 172 | ||
@@ -176,7 +178,10 @@ export default @observer class EditServiceForm extends Component { | |||
176 | if (recipe.validateUrl && values.customUrl) { | 178 | if (recipe.validateUrl && values.customUrl) { |
177 | this.setState({ isValidatingCustomUrl: true }); | 179 | this.setState({ isValidatingCustomUrl: true }); |
178 | try { | 180 | try { |
179 | values.customUrl = normalizeUrl(values.customUrl, { stripWWW: false, removeTrailingSlash: false }); | 181 | values.customUrl = normalizeUrl(values.customUrl, { |
182 | stripWWW: false, | ||
183 | removeTrailingSlash: false, | ||
184 | }); | ||
180 | isValid = await recipe.validateUrl(values.customUrl); | 185 | isValid = await recipe.validateUrl(values.customUrl); |
181 | } catch (err) { | 186 | } catch (err) { |
182 | console.warn('ValidateURL', err); | 187 | console.warn('ValidateURL', err); |
@@ -208,7 +213,7 @@ export default @observer class EditServiceForm extends Component { | |||
208 | openRecipeFile, | 213 | openRecipeFile, |
209 | isProxyFeatureEnabled, | 214 | isProxyFeatureEnabled, |
210 | } = this.props; | 215 | } = this.props; |
211 | const { intl } = this.context; | 216 | const { intl } = this.props; |
212 | 217 | ||
213 | const { isValidatingCustomUrl } = this.state; | 218 | const { isValidatingCustomUrl } = this.state; |
214 | 219 | ||
@@ -236,7 +241,8 @@ export default @observer class EditServiceForm extends Component { | |||
236 | activeTabIndex = 2; | 241 | activeTabIndex = 2; |
237 | } | 242 | } |
238 | 243 | ||
239 | const requiresUserInput = !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); | 244 | const requiresUserInput = |
245 | !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); | ||
240 | 246 | ||
241 | return ( | 247 | return ( |
242 | <div className="settings__main"> | 248 | <div className="settings__main"> |
@@ -254,29 +260,27 @@ export default @observer class EditServiceForm extends Component { | |||
254 | </span> | 260 | </span> |
255 | <span className="separator" /> | 261 | <span className="separator" /> |
256 | <span className="settings__header-item"> | 262 | <span className="settings__header-item"> |
257 | {action === 'add' ? ( | 263 | {action === 'add' |
258 | intl.formatMessage(messages.addServiceHeadline, { | 264 | ? intl.formatMessage(messages.addServiceHeadline, { |
259 | name: recipe.name, | 265 | name: recipe.name, |
260 | }) | 266 | }) |
261 | ) : ( | 267 | : intl.formatMessage(messages.editServiceHeadline, { |
262 | intl.formatMessage(messages.editServiceHeadline, { | ||
263 | name: service.name !== '' ? service.name : recipe.name, | 268 | name: service.name !== '' ? service.name : recipe.name, |
264 | }) | 269 | })} |
265 | )} | ||
266 | </span> | 270 | </span> |
267 | </div> | 271 | </div> |
268 | <div className="settings__body"> | 272 | <div className="settings__body"> |
269 | <form onSubmit={(e) => this.submit(e)} id="form"> | 273 | <form onSubmit={e => this.submit(e)} id="form"> |
270 | <div className="service-name"> | 274 | <div className="service-name"> |
271 | <Input field={form.$('name')} focus /> | 275 | <Input field={form.$('name')} focus /> |
272 | </div> | 276 | </div> |
273 | {(recipe.hasTeamId || recipe.hasCustomUrl) && ( | 277 | {(recipe.hasTeamId || recipe.hasCustomUrl) && ( |
274 | <Tabs | 278 | <Tabs active={activeTabIndex}> |
275 | active={activeTabIndex} | ||
276 | > | ||
277 | {recipe.hasHostedOption && ( | 279 | {recipe.hasHostedOption && ( |
278 | <TabItem title={recipe.name}> | 280 | <TabItem title={recipe.name}> |
279 | {intl.formatMessage(messages.useHostedService, { name: recipe.name })} | 281 | {intl.formatMessage(messages.useHostedService, { |
282 | name: recipe.name, | ||
283 | })} | ||
280 | </TabItem> | 284 | </TabItem> |
281 | )} | 285 | )} |
282 | {recipe.hasTeamId && ( | 286 | {recipe.hasTeamId && ( |
@@ -293,7 +297,9 @@ export default @observer class EditServiceForm extends Component { | |||
293 | <Input field={form.$('customUrl')} /> | 297 | <Input field={form.$('customUrl')} /> |
294 | {form.error === 'url-validation-error' && ( | 298 | {form.error === 'url-validation-error' && ( |
295 | <p className="franz-form__error"> | 299 | <p className="franz-form__error"> |
296 | {intl.formatMessage(messages.customUrlValidationError, { name: recipe.name })} | 300 | {intl.formatMessage(messages.customUrlValidationError, { |
301 | name: recipe.name, | ||
302 | })} | ||
297 | </p> | 303 | </p> |
298 | )} | 304 | )} |
299 | </TabItem> | 305 | </TabItem> |
@@ -326,13 +332,16 @@ export default @observer class EditServiceForm extends Component { | |||
326 | <div className="settings__settings-group"> | 332 | <div className="settings__settings-group"> |
327 | <h3>{intl.formatMessage(messages.headlineBadges)}</h3> | 333 | <h3>{intl.formatMessage(messages.headlineBadges)}</h3> |
328 | <Toggle field={form.$('isBadgeEnabled')} /> | 334 | <Toggle field={form.$('isBadgeEnabled')} /> |
329 | {recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && ( | 335 | {recipe.hasIndirectMessages && |
330 | <> | 336 | form.$('isBadgeEnabled').value && ( |
331 | <Toggle field={form.$('isIndirectMessageBadgeEnabled')} /> | 337 | <> |
332 | <p className="settings__help indented__help"> | 338 | <Toggle |
333 | {intl.formatMessage(messages.indirectMessageInfo)} | 339 | field={form.$('isIndirectMessageBadgeEnabled')} |
334 | </p> | 340 | /> |
335 | </> | 341 | <p className="settings__help indented__help"> |
342 | {intl.formatMessage(messages.indirectMessageInfo)} | ||
343 | </p> | ||
344 | </> | ||
336 | )} | 345 | )} |
337 | </div> | 346 | </div> |
338 | 347 | ||
@@ -344,15 +353,18 @@ export default @observer class EditServiceForm extends Component { | |||
344 | {intl.formatMessage(messages.isHibernationEnabledInfo)} | 353 | {intl.formatMessage(messages.isHibernationEnabledInfo)} |
345 | </p> | 354 | </p> |
346 | <Toggle field={form.$('isDarkModeEnabled')} /> | 355 | <Toggle field={form.$('isDarkModeEnabled')} /> |
347 | {form.$('isDarkModeEnabled').value | 356 | {form.$('isDarkModeEnabled').value && ( |
348 | && ( | 357 | <> |
349 | <> | 358 | <h3> |
350 | <h3>{intl.formatMessage(messages.headlineDarkReaderSettings)}</h3> | 359 | {intl.formatMessage( |
351 | <Slider field={form.$('darkReaderBrightness')} /> | 360 | messages.headlineDarkReaderSettings, |
352 | <Slider field={form.$('darkReaderContrast')} /> | 361 | )} |
353 | <Slider field={form.$('darkReaderSepia')} /> | 362 | </h3> |
354 | </> | 363 | <Slider field={form.$('darkReaderBrightness')} /> |
355 | )} | 364 | <Slider field={form.$('darkReaderContrast')} /> |
365 | <Slider field={form.$('darkReaderSepia')} /> | ||
366 | </> | ||
367 | )} | ||
356 | </div> | 368 | </div> |
357 | </div> | 369 | </div> |
358 | <div className="service-icon"> | 370 | <div className="service-icon"> |
@@ -381,7 +393,10 @@ export default @observer class EditServiceForm extends Component { | |||
381 | <> | 393 | <> |
382 | <div className="grid"> | 394 | <div className="grid"> |
383 | <div className="grid__row"> | 395 | <div className="grid__row"> |
384 | <Input field={form.$('proxy.host')} className="proxyHost" /> | 396 | <Input |
397 | field={form.$('proxy.host')} | ||
398 | className="proxyHost" | ||
399 | /> | ||
385 | <Input field={form.$('proxy.port')} /> | 400 | <Input field={form.$('proxy.port')} /> |
386 | </div> | 401 | </div> |
387 | </div> | 402 | </div> |
@@ -409,7 +424,9 @@ export default @observer class EditServiceForm extends Component { | |||
409 | 424 | ||
410 | <div className="user-agent"> | 425 | <div className="user-agent"> |
411 | <Input field={form.$('userAgentPref')} /> | 426 | <Input field={form.$('userAgentPref')} /> |
412 | <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> | 427 | <p className="settings__help"> |
428 | {intl.formatMessage(globalMessages.userAgentHelp)} | ||
429 | </p> | ||
413 | </div> | 430 | </div> |
414 | </form> | 431 | </form> |
415 | 432 | ||
@@ -464,7 +481,9 @@ export default @observer class EditServiceForm extends Component { | |||
464 | type="submit" | 481 | type="submit" |
465 | label={intl.formatMessage(messages.saveService)} | 482 | label={intl.formatMessage(messages.saveService)} |
466 | htmlForm="form" | 483 | htmlForm="form" |
467 | disabled={action !== 'edit' && (form.isPristine && requiresUserInput)} | 484 | disabled={ |
485 | action !== 'edit' && form.isPristine && requiresUserInput | ||
486 | } | ||
468 | /> | 487 | /> |
469 | )} | 488 | )} |
470 | </div> | 489 | </div> |
@@ -472,3 +491,5 @@ export default @observer class EditServiceForm extends Component { | |||
472 | ); | 491 | ); |
473 | } | 492 | } |
474 | } | 493 | } |
494 | |||
495 | export default injectIntl(EditServiceForm); | ||
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js index 3cfc080d6..d16d76db2 100644 --- a/src/components/settings/services/ServiceError.js +++ b/src/components/settings/services/ServiceError.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import { observer } from 'mobx-react'; | 2 | import { observer } from 'mobx-react'; |
3 | import { Link } from 'react-router'; | 3 | import { Link } from 'react-router'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import Infobox from '../../ui/Infobox'; | 6 | import Infobox from '../../ui/Infobox'; |
7 | import Button from '../../ui/Button'; | 7 | import Button from '../../ui/Button'; |
@@ -9,29 +9,26 @@ import Button from '../../ui/Button'; | |||
9 | const messages = defineMessages({ | 9 | const messages = defineMessages({ |
10 | headline: { | 10 | headline: { |
11 | id: 'settings.service.error.headline', | 11 | id: 'settings.service.error.headline', |
12 | defaultMessage: '!!!Error', | 12 | defaultMessage: 'Error', |
13 | }, | 13 | }, |
14 | goBack: { | 14 | goBack: { |
15 | id: 'settings.service.error.goBack', | 15 | id: 'settings.service.error.goBack', |
16 | defaultMessage: '!!!Back to services', | 16 | defaultMessage: 'Back to services', |
17 | }, | 17 | }, |
18 | availableServices: { | 18 | availableServices: { |
19 | id: 'settings.service.form.availableServices', | 19 | id: 'settings.service.form.availableServices', |
20 | defaultMessage: '!!!Available services', | 20 | defaultMessage: 'Available services', |
21 | }, | 21 | }, |
22 | errorMessage: { | 22 | errorMessage: { |
23 | id: 'settings.service.error.message', | 23 | id: 'settings.service.error.message', |
24 | defaultMessage: '!!!Could not load service recipe.', | 24 | defaultMessage: 'Could not load service recipe.', |
25 | }, | 25 | }, |
26 | }); | 26 | }); |
27 | 27 | ||
28 | export default @observer class ServiceError extends Component { | 28 | @observer |
29 | static contextTypes = { | 29 | class ServiceError extends Component { |
30 | intl: intlShape, | ||
31 | }; | ||
32 | |||
33 | render() { | 30 | render() { |
34 | const { intl } = this.context; | 31 | const { intl } = this.props; |
35 | 32 | ||
36 | return ( | 33 | return ( |
37 | <div className="settings__main"> | 34 | <div className="settings__main"> |
@@ -47,10 +44,7 @@ export default @observer class ServiceError extends Component { | |||
47 | </span> | 44 | </span> |
48 | </div> | 45 | </div> |
49 | <div className="settings__body"> | 46 | <div className="settings__body"> |
50 | <Infobox | 47 | <Infobox type="danger" icon="alert"> |
51 | type="danger" | ||
52 | icon="alert" | ||
53 | > | ||
54 | {intl.formatMessage(messages.errorMessage)} | 48 | {intl.formatMessage(messages.errorMessage)} |
55 | </Infobox> | 49 | </Infobox> |
56 | </div> | 50 | </div> |
@@ -65,3 +59,5 @@ export default @observer class ServiceError extends Component { | |||
65 | ); | 59 | ); |
66 | } | 60 | } |
67 | } | 61 | } |
62 | |||
63 | export default injectIntl(ServiceError); | ||
diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js index ebc618a00..4916e4ecc 100644 --- a/src/components/settings/services/ServiceItem.js +++ b/src/components/settings/services/ServiceItem.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | import ReactTooltip from 'react-tooltip'; | 4 | import ReactTooltip from 'react-tooltip'; |
5 | import { observer } from 'mobx-react'; | 5 | import { observer } from 'mobx-react'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
@@ -10,35 +10,32 @@ import ServiceModel from '../../../models/Service'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | tooltipIsDisabled: { | 11 | tooltipIsDisabled: { |
12 | id: 'settings.services.tooltip.isDisabled', | 12 | id: 'settings.services.tooltip.isDisabled', |
13 | defaultMessage: '!!!Service is disabled', | 13 | defaultMessage: 'Service is disabled', |
14 | }, | 14 | }, |
15 | tooltipNotificationsDisabled: { | 15 | tooltipNotificationsDisabled: { |
16 | id: 'settings.services.tooltip.notificationsDisabled', | 16 | id: 'settings.services.tooltip.notificationsDisabled', |
17 | defaultMessage: '!!!Notifications are disabled', | 17 | defaultMessage: 'Notifications are disabled', |
18 | }, | 18 | }, |
19 | tooltipIsMuted: { | 19 | tooltipIsMuted: { |
20 | id: 'settings.services.tooltip.isMuted', | 20 | id: 'settings.services.tooltip.isMuted', |
21 | defaultMessage: '!!!All sounds are muted', | 21 | defaultMessage: 'All sounds are muted', |
22 | }, | 22 | }, |
23 | }); | 23 | }); |
24 | 24 | ||
25 | export default @observer class ServiceItem extends Component { | 25 | @observer |
26 | class ServiceItem extends Component { | ||
26 | static propTypes = { | 27 | static propTypes = { |
27 | service: PropTypes.instanceOf(ServiceModel).isRequired, | 28 | service: PropTypes.instanceOf(ServiceModel).isRequired, |
28 | goToServiceForm: PropTypes.func.isRequired, | 29 | goToServiceForm: PropTypes.func.isRequired, |
29 | }; | 30 | }; |
30 | 31 | ||
31 | static contextTypes = { | ||
32 | intl: intlShape, | ||
33 | }; | ||
34 | |||
35 | render() { | 32 | render() { |
36 | const { | 33 | const { |
37 | service, | 34 | service, |
38 | // toggleAction, | 35 | // toggleAction, |
39 | goToServiceForm, | 36 | goToServiceForm, |
40 | } = this.props; | 37 | } = this.props; |
41 | const { intl } = this.context; | 38 | const { intl } = this.props; |
42 | 39 | ||
43 | return ( | 40 | return ( |
44 | <tr | 41 | <tr |
@@ -47,10 +44,7 @@ export default @observer class ServiceItem extends Component { | |||
47 | 'service-table__row--disabled': !service.isEnabled, | 44 | 'service-table__row--disabled': !service.isEnabled, |
48 | })} | 45 | })} |
49 | > | 46 | > |
50 | <td | 47 | <td className="service-table__column-icon" onClick={goToServiceForm}> |
51 | className="service-table__column-icon" | ||
52 | onClick={goToServiceForm} | ||
53 | > | ||
54 | <img | 48 | <img |
55 | src={service.icon} | 49 | src={service.icon} |
56 | className={classnames({ | 50 | className={classnames({ |
@@ -60,16 +54,10 @@ export default @observer class ServiceItem extends Component { | |||
60 | alt="" | 54 | alt="" |
61 | /> | 55 | /> |
62 | </td> | 56 | </td> |
63 | <td | 57 | <td className="service-table__column-name" onClick={goToServiceForm}> |
64 | className="service-table__column-name" | ||
65 | onClick={goToServiceForm} | ||
66 | > | ||
67 | {service.name !== '' ? service.name : service.recipe.name} | 58 | {service.name !== '' ? service.name : service.recipe.name} |
68 | </td> | 59 | </td> |
69 | <td | 60 | <td className="service-table__column-info" onClick={goToServiceForm}> |
70 | className="service-table__column-info" | ||
71 | onClick={goToServiceForm} | ||
72 | > | ||
73 | {service.isMuted && ( | 61 | {service.isMuted && ( |
74 | <span | 62 | <span |
75 | className="mdi mdi-bell-off" | 63 | className="mdi mdi-bell-off" |
@@ -77,10 +65,7 @@ export default @observer class ServiceItem extends Component { | |||
77 | /> | 65 | /> |
78 | )} | 66 | )} |
79 | </td> | 67 | </td> |
80 | <td | 68 | <td className="service-table__column-info" onClick={goToServiceForm}> |
81 | className="service-table__column-info" | ||
82 | onClick={goToServiceForm} | ||
83 | > | ||
84 | {!service.isEnabled && ( | 69 | {!service.isEnabled && ( |
85 | <span | 70 | <span |
86 | className="mdi mdi-power" | 71 | className="mdi mdi-power" |
@@ -88,14 +73,13 @@ export default @observer class ServiceItem extends Component { | |||
88 | /> | 73 | /> |
89 | )} | 74 | )} |
90 | </td> | 75 | </td> |
91 | <td | 76 | <td className="service-table__column-info" onClick={goToServiceForm}> |
92 | className="service-table__column-info" | ||
93 | onClick={goToServiceForm} | ||
94 | > | ||
95 | {!service.isNotificationEnabled && ( | 77 | {!service.isNotificationEnabled && ( |
96 | <span | 78 | <span |
97 | className="mdi mdi-message-bulleted-off" | 79 | className="mdi mdi-message-bulleted-off" |
98 | data-tip={intl.formatMessage(messages.tooltipNotificationsDisabled)} | 80 | data-tip={intl.formatMessage( |
81 | messages.tooltipNotificationsDisabled, | ||
82 | )} | ||
99 | /> | 83 | /> |
100 | )} | 84 | )} |
101 | <ReactTooltip place="top" type="dark" effect="solid" /> | 85 | <ReactTooltip place="top" type="dark" effect="solid" /> |
@@ -104,3 +88,5 @@ export default @observer class ServiceItem extends Component { | |||
104 | ); | 88 | ); |
105 | } | 89 | } |
106 | } | 90 | } |
91 | |||
92 | export default injectIntl(ServiceItem); | ||
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js index 11d3eaa79..847f2ea06 100644 --- a/src/components/settings/services/ServicesDashboard.js +++ b/src/components/settings/services/ServicesDashboard.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import SearchInput from '../../ui/SearchInput'; | 7 | import SearchInput from '../../ui/SearchInput'; |
8 | import Infobox from '../../ui/Infobox'; | 8 | import Infobox from '../../ui/Infobox'; |
@@ -14,43 +14,45 @@ import Appear from '../../ui/effects/Appear'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'settings.services.headline', | 16 | id: 'settings.services.headline', |
17 | defaultMessage: '!!!Your services', | 17 | defaultMessage: 'Your services', |
18 | }, | 18 | }, |
19 | searchService: { | 19 | searchService: { |
20 | id: 'settings.searchService', | 20 | id: 'settings.searchService', |
21 | defaultMessage: '!!!Search service', | 21 | defaultMessage: 'Search service', |
22 | }, | 22 | }, |
23 | noServicesAdded: { | 23 | noServicesAdded: { |
24 | id: 'settings.services.noServicesAdded', | 24 | id: 'settings.services.noServicesAdded', |
25 | defaultMessage: '!!!Start by adding a service.', | 25 | defaultMessage: 'Start by adding a service.', |
26 | }, | 26 | }, |
27 | noServiceFound: { | 27 | noServiceFound: { |
28 | id: 'settings.recipes.nothingFound', | 28 | id: 'settings.recipes.nothingFound', |
29 | defaultMessage: '!!!Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | 29 | defaultMessage: |
30 | 'Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', | ||
30 | }, | 31 | }, |
31 | discoverServices: { | 32 | discoverServices: { |
32 | id: 'settings.services.discoverServices', | 33 | id: 'settings.services.discoverServices', |
33 | defaultMessage: '!!!Discover services', | 34 | defaultMessage: 'Discover services', |
34 | }, | 35 | }, |
35 | servicesRequestFailed: { | 36 | servicesRequestFailed: { |
36 | id: 'settings.services.servicesRequestFailed', | 37 | id: 'settings.services.servicesRequestFailed', |
37 | defaultMessage: '!!!Could not load your services', | 38 | defaultMessage: 'Could not load your services', |
38 | }, | 39 | }, |
39 | tryReloadServices: { | 40 | tryReloadServices: { |
40 | id: 'settings.account.tryReloadServices', | 41 | id: 'settings.account.tryReloadServices', |
41 | defaultMessage: '!!!Try again', | 42 | defaultMessage: 'Try again', |
42 | }, | 43 | }, |
43 | updatedInfo: { | 44 | updatedInfo: { |
44 | id: 'settings.services.updatedInfo', | 45 | id: 'settings.services.updatedInfo', |
45 | defaultMessage: '!!!Your changes have been saved', | 46 | defaultMessage: 'Your changes have been saved', |
46 | }, | 47 | }, |
47 | deletedInfo: { | 48 | deletedInfo: { |
48 | id: 'settings.services.deletedInfo', | 49 | id: 'settings.services.deletedInfo', |
49 | defaultMessage: '!!!Service has been deleted', | 50 | defaultMessage: 'Service has been deleted', |
50 | }, | 51 | }, |
51 | }); | 52 | }); |
52 | 53 | ||
53 | export default @observer class ServicesDashboard extends Component { | 54 | @observer |
55 | class ServicesDashboard extends Component { | ||
54 | static propTypes = { | 56 | static propTypes = { |
55 | services: MobxPropTypes.arrayOrObservableArray.isRequired, | 57 | services: MobxPropTypes.arrayOrObservableArray.isRequired, |
56 | isLoading: PropTypes.bool.isRequired, | 58 | isLoading: PropTypes.bool.isRequired, |
@@ -68,10 +70,6 @@ export default @observer class ServicesDashboard extends Component { | |||
68 | searchNeedle: '', | 70 | searchNeedle: '', |
69 | }; | 71 | }; |
70 | 72 | ||
71 | static contextTypes = { | ||
72 | intl: intlShape, | ||
73 | }; | ||
74 | |||
75 | render() { | 73 | render() { |
76 | const { | 74 | const { |
77 | services, | 75 | services, |
@@ -85,7 +83,7 @@ export default @observer class ServicesDashboard extends Component { | |||
85 | status, | 83 | status, |
86 | searchNeedle, | 84 | searchNeedle, |
87 | } = this.props; | 85 | } = this.props; |
88 | const { intl } = this.context; | 86 | const { intl } = this.props; |
89 | 87 | ||
90 | return ( | 88 | return ( |
91 | <div className="settings__main"> | 89 | <div className="settings__main"> |
@@ -96,7 +94,7 @@ export default @observer class ServicesDashboard extends Component { | |||
96 | {(services.length !== 0 || searchNeedle) && !isLoading && ( | 94 | {(services.length !== 0 || searchNeedle) && !isLoading && ( |
97 | <SearchInput | 95 | <SearchInput |
98 | placeholder={intl.formatMessage(messages.searchService)} | 96 | placeholder={intl.formatMessage(messages.searchService)} |
99 | onChange={(needle) => filterServices({ needle })} | 97 | onChange={needle => filterServices({ needle })} |
100 | onReset={() => resetFilter()} | 98 | onReset={() => resetFilter()} |
101 | autoFocus | 99 | autoFocus |
102 | /> | 100 | /> |
@@ -145,7 +143,9 @@ export default @observer class ServicesDashboard extends Component { | |||
145 | </span> | 143 | </span> |
146 | {intl.formatMessage(messages.noServicesAdded)} | 144 | {intl.formatMessage(messages.noServicesAdded)} |
147 | </p> | 145 | </p> |
148 | <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link> | 146 | <Link to="/settings/recipes" className="button"> |
147 | {intl.formatMessage(messages.discoverServices)} | ||
148 | </Link> | ||
149 | </div> | 149 | </div> |
150 | )} | 150 | )} |
151 | {!isLoading && services.length === 0 && searchNeedle && ( | 151 | {!isLoading && services.length === 0 && searchNeedle && ( |
@@ -163,12 +163,16 @@ export default @observer class ServicesDashboard extends Component { | |||
163 | ) : ( | 163 | ) : ( |
164 | <table className="service-table"> | 164 | <table className="service-table"> |
165 | <tbody> | 165 | <tbody> |
166 | {services.map((service) => ( | 166 | {services.map(service => ( |
167 | <ServiceItem | 167 | <ServiceItem |
168 | key={service.id} | 168 | key={service.id} |
169 | service={service} | 169 | service={service} |
170 | toggleAction={() => toggleService({ serviceId: service.id })} | 170 | toggleAction={() => |
171 | goToServiceForm={() => goTo(`/settings/services/edit/${service.id}`)} | 171 | toggleService({ serviceId: service.id }) |
172 | } | ||
173 | goToServiceForm={() => | ||
174 | goTo(`/settings/services/edit/${service.id}`) | ||
175 | } | ||
172 | /> | 176 | /> |
173 | ))} | 177 | ))} |
174 | </tbody> | 178 | </tbody> |
@@ -176,12 +180,12 @@ export default @observer class ServicesDashboard extends Component { | |||
176 | )} | 180 | )} |
177 | 181 | ||
178 | <FAB> | 182 | <FAB> |
179 | <Link to="/settings/recipes"> | 183 | <Link to="/settings/recipes">+</Link> |
180 | + | ||
181 | </Link> | ||
182 | </FAB> | 184 | </FAB> |
183 | </div> | 185 | </div> |
184 | </div> | 186 | </div> |
185 | ); | 187 | ); |
186 | } | 188 | } |
187 | } | 189 | } |
190 | |||
191 | export default injectIntl(ServicesDashboard); | ||
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 6a919b902..0a468e342 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -3,7 +3,7 @@ import React, { Component } from 'react'; | |||
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer } from 'mobx-react'; | 4 | import { observer } from 'mobx-react'; |
5 | import prettyBytes from 'pretty-bytes'; | 5 | import prettyBytes from 'pretty-bytes'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | import Form from '../../../lib/Form'; | 8 | import Form from '../../../lib/Form'; |
9 | import Button from '../../ui/Button'; | 9 | import Button from '../../ui/Button'; |
@@ -13,154 +13,173 @@ import Select from '../../ui/Select'; | |||
13 | import Input from '../../ui/Input'; | 13 | import Input from '../../ui/Input'; |
14 | 14 | ||
15 | import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config'; | 15 | import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config'; |
16 | import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, userDataPath, userDataRecipesPath } from '../../../environment'; | 16 | import { |
17 | DEFAULT_APP_SETTINGS, | ||
18 | ferdiVersion, | ||
19 | isMac, | ||
20 | isWindows, | ||
21 | lockFerdiShortcutKey, | ||
22 | userDataPath, | ||
23 | userDataRecipesPath, | ||
24 | } from '../../../environment'; | ||
17 | import { openPath } from '../../../helpers/url-helpers'; | 25 | import { openPath } from '../../../helpers/url-helpers'; |
18 | import globalMessages from '../../../i18n/globalMessages'; | 26 | import globalMessages from '../../../i18n/globalMessages'; |
19 | 27 | ||
20 | const messages = defineMessages({ | 28 | const messages = defineMessages({ |
21 | headlineGeneral: { | 29 | headlineGeneral: { |
22 | id: 'settings.app.headlineGeneral', | 30 | id: 'settings.app.headlineGeneral', |
23 | defaultMessage: '!!!General', | 31 | defaultMessage: 'General', |
24 | }, | 32 | }, |
25 | sentryInfo: { | 33 | sentryInfo: { |
26 | id: 'settings.app.sentryInfo', | 34 | id: 'settings.app.sentryInfo', |
27 | defaultMessage: '!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!', | 35 | defaultMessage: |
36 | 'Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!', | ||
28 | }, | 37 | }, |
29 | hibernateInfo: { | 38 | hibernateInfo: { |
30 | id: 'settings.app.hibernateInfo', | 39 | id: 'settings.app.hibernateInfo', |
31 | defaultMessage: '!!!By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.', | 40 | defaultMessage: |
41 | 'By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.', | ||
32 | }, | 42 | }, |
33 | inactivityLockInfo: { | 43 | inactivityLockInfo: { |
34 | id: 'settings.app.inactivityLockInfo', | 44 | id: 'settings.app.inactivityLockInfo', |
35 | defaultMessage: '!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable', | 45 | defaultMessage: |
46 | 'Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable', | ||
36 | }, | 47 | }, |
37 | todoServerInfo: { | 48 | todoServerInfo: { |
38 | id: 'settings.app.todoServerInfo', | 49 | id: 'settings.app.todoServerInfo', |
39 | defaultMessage: '!!!This server will be used for the "Franz Todo" feature. (default: https://app.franztodos.com)', | 50 | defaultMessage: |
51 | 'This server will be used for the "Franz Todo" feature. (default: https://app.franztodos.com)', | ||
40 | }, | 52 | }, |
41 | lockedPassword: { | 53 | lockedPassword: { |
42 | id: 'settings.app.lockedPassword', | 54 | id: 'settings.app.lockedPassword', |
43 | defaultMessage: '!!!Password', | 55 | defaultMessage: 'Password', |
44 | }, | 56 | }, |
45 | lockedPasswordInfo: { | 57 | lockedPasswordInfo: { |
46 | id: 'settings.app.lockedPasswordInfo', | 58 | id: 'settings.app.lockedPasswordInfo', |
47 | defaultMessage: '!!!Please make sure to set a password you\'ll remember.\nIf you loose this password, you will have to reinstall Ferdi.', | 59 | defaultMessage: |
60 | "Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", | ||
48 | }, | 61 | }, |
49 | lockInfo: { | 62 | lockInfo: { |
50 | id: 'settings.app.lockInfo', | 63 | id: 'settings.app.lockInfo', |
51 | defaultMessage: '!!!Password Lock allows you to keep your messages protected.\nUsing Password Lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut {lockShortcut}.', | 64 | defaultMessage: |
65 | 'Password Lock allows you to keep your messages protected.\nUsing Password Lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut {lockShortcut}.', | ||
52 | }, | 66 | }, |
53 | scheduledDNDTimeInfo: { | 67 | scheduledDNDTimeInfo: { |
54 | id: 'settings.app.scheduledDNDTimeInfo', | 68 | id: 'settings.app.scheduledDNDTimeInfo', |
55 | defaultMessage: '!!!Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.', | 69 | defaultMessage: |
70 | 'Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.', | ||
56 | }, | 71 | }, |
57 | scheduledDNDInfo: { | 72 | scheduledDNDInfo: { |
58 | id: 'settings.app.scheduledDNDInfo', | 73 | id: 'settings.app.scheduledDNDInfo', |
59 | defaultMessage: '!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.', | 74 | defaultMessage: |
75 | 'Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.', | ||
60 | }, | 76 | }, |
61 | headlineLanguage: { | 77 | headlineLanguage: { |
62 | id: 'settings.app.headlineLanguage', | 78 | id: 'settings.app.headlineLanguage', |
63 | defaultMessage: '!!!Language', | 79 | defaultMessage: 'Language', |
64 | }, | 80 | }, |
65 | headlineUpdates: { | 81 | headlineUpdates: { |
66 | id: 'settings.app.headlineUpdates', | 82 | id: 'settings.app.headlineUpdates', |
67 | defaultMessage: '!!!Updates', | 83 | defaultMessage: 'Updates', |
68 | }, | 84 | }, |
69 | headlineAppearance: { | 85 | headlineAppearance: { |
70 | id: 'settings.app.headlineAppearance', | 86 | id: 'settings.app.headlineAppearance', |
71 | defaultMessage: '!!!Appearance', | 87 | defaultMessage: 'Appearance', |
72 | }, | 88 | }, |
73 | universalDarkModeInfo: { | 89 | universalDarkModeInfo: { |
74 | id: 'settings.app.universalDarkModeInfo', | 90 | id: 'settings.app.universalDarkModeInfo', |
75 | defaultMessage: '!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', | 91 | defaultMessage: |
92 | 'Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', | ||
76 | }, | 93 | }, |
77 | accentColorInfo: { | 94 | accentColorInfo: { |
78 | id: 'settings.app.accentColorInfo', | 95 | id: 'settings.app.accentColorInfo', |
79 | defaultMessage: '!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})', | 96 | defaultMessage: |
97 | 'Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})', | ||
80 | }, | 98 | }, |
81 | headlinePrivacy: { | 99 | headlinePrivacy: { |
82 | id: 'settings.app.headlinePrivacy', | 100 | id: 'settings.app.headlinePrivacy', |
83 | defaultMessage: '!!!Privacy', | 101 | defaultMessage: 'Privacy', |
84 | }, | 102 | }, |
85 | headlineAdvanced: { | 103 | headlineAdvanced: { |
86 | id: 'settings.app.headlineAdvanced', | 104 | id: 'settings.app.headlineAdvanced', |
87 | defaultMessage: '!!!Advanced', | 105 | defaultMessage: 'Advanced', |
88 | }, | 106 | }, |
89 | translationHelp: { | 107 | translationHelp: { |
90 | id: 'settings.app.translationHelp', | 108 | id: 'settings.app.translationHelp', |
91 | defaultMessage: '!!!Help us to translate Ferdi into your language.', | 109 | defaultMessage: 'Help us to translate Ferdi into your language.', |
92 | }, | 110 | }, |
93 | spellCheckerLanguageInfo: { | 111 | spellCheckerLanguageInfo: { |
94 | id: 'settings.app.spellCheckerLanguageInfo', | 112 | id: 'settings.app.spellCheckerLanguageInfo', |
95 | defaultMessage: '!!!Ferdi uses your Mac\'s build-in spellchecker to check for typos. If you want to change the languages the spellchecker checks for, you can do so in your Mac\'s System Preferences.', | 113 | defaultMessage: |
114 | "Ferdi uses your Mac's build-in spellchecker to check for typos. If you want to change the languages the spellchecker checks for, you can do so in your Mac's System Preferences.", | ||
96 | }, | 115 | }, |
97 | subheadlineCache: { | 116 | subheadlineCache: { |
98 | id: 'settings.app.subheadlineCache', | 117 | id: 'settings.app.subheadlineCache', |
99 | defaultMessage: '!!!Cache', | 118 | defaultMessage: 'Cache', |
100 | }, | 119 | }, |
101 | cacheInfo: { | 120 | cacheInfo: { |
102 | id: 'settings.app.cacheInfo', | 121 | id: 'settings.app.cacheInfo', |
103 | defaultMessage: '!!!Ferdi cache is currently using {size} of disk space.', | 122 | defaultMessage: 'Ferdi cache is currently using {size} of disk space.', |
104 | }, | 123 | }, |
105 | cacheNotCleared: { | 124 | cacheNotCleared: { |
106 | id: 'settings.app.cacheNotCleared', | 125 | id: 'settings.app.cacheNotCleared', |
107 | defaultMessage: '!!!Couldn\'t clear all cache', | 126 | defaultMessage: "Couldn't clear all cache", |
108 | }, | 127 | }, |
109 | buttonClearAllCache: { | 128 | buttonClearAllCache: { |
110 | id: 'settings.app.buttonClearAllCache', | 129 | id: 'settings.app.buttonClearAllCache', |
111 | defaultMessage: '!!!Clear cache', | 130 | defaultMessage: 'Clear cache', |
112 | }, | 131 | }, |
113 | subheadlineFerdiProfile: { | 132 | subheadlineFerdiProfile: { |
114 | id: 'settings.app.subheadlineFerdiProfile', | 133 | id: 'settings.app.subheadlineFerdiProfile', |
115 | defaultMessage: '!!!Ferdi Profile', | 134 | defaultMessage: 'Ferdi Profile', |
116 | }, | 135 | }, |
117 | buttonOpenFerdiProfileFolder: { | 136 | buttonOpenFerdiProfileFolder: { |
118 | id: 'settings.app.buttonOpenFerdiProfileFolder', | 137 | id: 'settings.app.buttonOpenFerdiProfileFolder', |
119 | defaultMessage: '!!!Open Profile folder', | 138 | defaultMessage: 'Open Profile folder', |
120 | }, | 139 | }, |
121 | buttonOpenFerdiServiceRecipesFolder: { | 140 | buttonOpenFerdiServiceRecipesFolder: { |
122 | id: 'settings.app.buttonOpenFerdiServiceRecipesFolder', | 141 | id: 'settings.app.buttonOpenFerdiServiceRecipesFolder', |
123 | defaultMessage: '!!!Open Service Recipes folder', | 142 | defaultMessage: 'Open Service Recipes folder', |
124 | }, | 143 | }, |
125 | buttonSearchForUpdate: { | 144 | buttonSearchForUpdate: { |
126 | id: 'settings.app.buttonSearchForUpdate', | 145 | id: 'settings.app.buttonSearchForUpdate', |
127 | defaultMessage: '!!!Check for updates', | 146 | defaultMessage: 'Check for updates', |
128 | }, | 147 | }, |
129 | buttonInstallUpdate: { | 148 | buttonInstallUpdate: { |
130 | id: 'settings.app.buttonInstallUpdate', | 149 | id: 'settings.app.buttonInstallUpdate', |
131 | defaultMessage: '!!!Restart & install update', | 150 | defaultMessage: 'Restart & install update', |
132 | }, | 151 | }, |
133 | updateStatusSearching: { | 152 | updateStatusSearching: { |
134 | id: 'settings.app.updateStatusSearching', | 153 | id: 'settings.app.updateStatusSearching', |
135 | defaultMessage: '!!!Is searching for update', | 154 | defaultMessage: 'Is searching for update', |
136 | }, | 155 | }, |
137 | updateStatusAvailable: { | 156 | updateStatusAvailable: { |
138 | id: 'settings.app.updateStatusAvailable', | 157 | id: 'settings.app.updateStatusAvailable', |
139 | defaultMessage: '!!!Update available, downloading...', | 158 | defaultMessage: 'Update available, downloading...', |
140 | }, | 159 | }, |
141 | updateStatusUpToDate: { | 160 | updateStatusUpToDate: { |
142 | id: 'settings.app.updateStatusUpToDate', | 161 | id: 'settings.app.updateStatusUpToDate', |
143 | defaultMessage: '!!!You are using the latest version of Ferdi', | 162 | defaultMessage: 'You are using the latest version of Ferdi', |
144 | }, | 163 | }, |
145 | currentVersion: { | 164 | currentVersion: { |
146 | id: 'settings.app.currentVersion', | 165 | id: 'settings.app.currentVersion', |
147 | defaultMessage: '!!!Current version:', | 166 | defaultMessage: 'Current version:', |
148 | }, | 167 | }, |
149 | appRestartRequired: { | 168 | appRestartRequired: { |
150 | id: 'settings.app.restartRequired', | 169 | id: 'settings.app.restartRequired', |
151 | defaultMessage: '!!!Changes require restart', | 170 | defaultMessage: 'Changes require restart', |
152 | }, | 171 | }, |
153 | languageDisclaimer: { | 172 | languageDisclaimer: { |
154 | id: 'settings.app.languageDisclaimer', | 173 | id: 'settings.app.languageDisclaimer', |
155 | defaultMessage: '!!!Official translations are English & German. All other languages are community based translations.', | 174 | defaultMessage: |
175 | 'Official translations are English & German. All other languages are community based translations.', | ||
156 | }, | 176 | }, |
157 | }); | 177 | }); |
158 | 178 | ||
159 | const Hr = () => ( | 179 | const Hr = () => <hr style={{ marginBottom: 20 }} />; |
160 | <hr style={{ marginBottom: 20 }} /> | ||
161 | ); | ||
162 | 180 | ||
163 | export default @observer class EditSettingsForm extends Component { | 181 | @observer |
182 | class EditSettingsForm extends Component { | ||
164 | static propTypes = { | 183 | static propTypes = { |
165 | checkForUpdates: PropTypes.func.isRequired, | 184 | checkForUpdates: PropTypes.func.isRequired, |
166 | installUpdate: PropTypes.func.isRequired, | 185 | installUpdate: PropTypes.func.isRequired, |
@@ -184,14 +203,10 @@ export default @observer class EditSettingsForm extends Component { | |||
184 | isOnline: PropTypes.bool.isRequired, | 203 | isOnline: PropTypes.bool.isRequired, |
185 | }; | 204 | }; |
186 | 205 | ||
187 | static contextTypes = { | ||
188 | intl: intlShape, | ||
189 | }; | ||
190 | |||
191 | state = { | 206 | state = { |
192 | activeSetttingsTab: 'general', | 207 | activeSetttingsTab: 'general', |
193 | clearCacheButtonClicked: false, | 208 | clearCacheButtonClicked: false, |
194 | } | 209 | }; |
195 | 210 | ||
196 | setActiveSettingsTab(tab) { | 211 | setActiveSettingsTab(tab) { |
197 | this.setState({ | 212 | this.setState({ |
@@ -199,14 +214,14 @@ export default @observer class EditSettingsForm extends Component { | |||
199 | }); | 214 | }); |
200 | } | 215 | } |
201 | 216 | ||
202 | onClearCacheClicked=() => { | 217 | onClearCacheClicked = () => { |
203 | this.setState({ clearCacheButtonClicked: true }); | 218 | this.setState({ clearCacheButtonClicked: true }); |
204 | } | 219 | }; |
205 | 220 | ||
206 | submit(e) { | 221 | submit(e) { |
207 | e.preventDefault(); | 222 | e.preventDefault(); |
208 | this.props.form.submit({ | 223 | this.props.form.submit({ |
209 | onSuccess: (form) => { | 224 | onSuccess: form => { |
210 | const values = form.values(); | 225 | const values = form.values(); |
211 | this.props.onSubmit(values); | 226 | this.props.onSubmit(values); |
212 | }, | 227 | }, |
@@ -236,7 +251,7 @@ export default @observer class EditSettingsForm extends Component { | |||
236 | hasAddedTodosAsService, | 251 | hasAddedTodosAsService, |
237 | isOnline, | 252 | isOnline, |
238 | } = this.props; | 253 | } = this.props; |
239 | const { intl } = this.context; | 254 | const { intl } = this.props; |
240 | 255 | ||
241 | let updateButtonLabelMessage = messages.buttonSearchForUpdate; | 256 | let updateButtonLabelMessage = messages.buttonSearchForUpdate; |
242 | if (isCheckingForUpdates) { | 257 | if (isCheckingForUpdates) { |
@@ -247,10 +262,8 @@ export default @observer class EditSettingsForm extends Component { | |||
247 | updateButtonLabelMessage = messages.buttonSearchForUpdate; | 262 | updateButtonLabelMessage = messages.buttonSearchForUpdate; |
248 | } | 263 | } |
249 | 264 | ||
250 | const { | 265 | const { lockingFeatureEnabled, scheduledDNDEnabled } = |
251 | lockingFeatureEnabled, | 266 | window.ferdi.stores.settings.all.app; |
252 | scheduledDNDEnabled, | ||
253 | } = window.ferdi.stores.settings.all.app; | ||
254 | 267 | ||
255 | let cacheSize; | 268 | let cacheSize; |
256 | let notCleared; | 269 | let notCleared; |
@@ -258,7 +271,10 @@ export default @observer class EditSettingsForm extends Component { | |||
258 | const cacheSizeBytes = getCacheSize(); | 271 | const cacheSizeBytes = getCacheSize(); |
259 | if (typeof cacheSizeBytes === 'number') { | 272 | if (typeof cacheSizeBytes === 'number') { |
260 | cacheSize = prettyBytes(cacheSizeBytes); | 273 | cacheSize = prettyBytes(cacheSizeBytes); |
261 | notCleared = this.state.clearCacheButtonClicked && isClearingAllCache === false && cacheSizeBytes !== 0; | 274 | notCleared = |
275 | this.state.clearCacheButtonClicked && | ||
276 | isClearingAllCache === false && | ||
277 | cacheSizeBytes !== 0; | ||
262 | } else { | 278 | } else { |
263 | cacheSize = '…'; | 279 | cacheSize = '…'; |
264 | notCleared = false; | 280 | notCleared = false; |
@@ -275,58 +291,94 @@ export default @observer class EditSettingsForm extends Component { | |||
275 | </div> | 291 | </div> |
276 | <div className="settings__body"> | 292 | <div className="settings__body"> |
277 | <form | 293 | <form |
278 | onSubmit={(e) => this.submit(e)} | 294 | onSubmit={e => this.submit(e)} |
279 | onChange={(e) => this.submit(e)} | 295 | onChange={e => this.submit(e)} |
280 | id="form" | 296 | id="form" |
281 | > | 297 | > |
282 | {/* Titles */} | 298 | {/* Titles */} |
283 | <div className="recipes__navigation"> | 299 | <div className="recipes__navigation"> |
284 | <h2 | 300 | <h2 |
285 | id="general" | 301 | id="general" |
286 | className={this.state.activeSetttingsTab === 'general' ? 'badge badge--primary' : 'badge'} | 302 | className={ |
287 | onClick={() => { this.setActiveSettingsTab('general'); }} | 303 | this.state.activeSetttingsTab === 'general' |
304 | ? 'badge badge--primary' | ||
305 | : 'badge' | ||
306 | } | ||
307 | onClick={() => { | ||
308 | this.setActiveSettingsTab('general'); | ||
309 | }} | ||
288 | > | 310 | > |
289 | {intl.formatMessage(messages.headlineGeneral)} | 311 | {intl.formatMessage(messages.headlineGeneral)} |
290 | </h2> | 312 | </h2> |
291 | <h2 | 313 | <h2 |
292 | id="appearance" | 314 | id="appearance" |
293 | className={this.state.activeSetttingsTab === 'appearance' ? 'badge badge--primary' : 'badge'} | 315 | className={ |
294 | onClick={() => { this.setActiveSettingsTab('appearance'); }} | 316 | this.state.activeSetttingsTab === 'appearance' |
317 | ? 'badge badge--primary' | ||
318 | : 'badge' | ||
319 | } | ||
320 | onClick={() => { | ||
321 | this.setActiveSettingsTab('appearance'); | ||
322 | }} | ||
295 | > | 323 | > |
296 | {intl.formatMessage(messages.headlineAppearance)} | 324 | {intl.formatMessage(messages.headlineAppearance)} |
297 | </h2> | 325 | </h2> |
298 | <h2 | 326 | <h2 |
299 | id="privacy" | 327 | id="privacy" |
300 | className={this.state.activeSetttingsTab === 'privacy' ? 'badge badge--primary' : 'badge'} | 328 | className={ |
301 | onClick={() => { this.setActiveSettingsTab('privacy'); }} | 329 | this.state.activeSetttingsTab === 'privacy' |
330 | ? 'badge badge--primary' | ||
331 | : 'badge' | ||
332 | } | ||
333 | onClick={() => { | ||
334 | this.setActiveSettingsTab('privacy'); | ||
335 | }} | ||
302 | > | 336 | > |
303 | {intl.formatMessage(messages.headlinePrivacy)} | 337 | {intl.formatMessage(messages.headlinePrivacy)} |
304 | </h2> | 338 | </h2> |
305 | <h2 | 339 | <h2 |
306 | id="language" | 340 | id="language" |
307 | className={this.state.activeSetttingsTab === 'language' ? 'badge badge--primary' : 'badge'} | 341 | className={ |
308 | onClick={() => { this.setActiveSettingsTab('language'); }} | 342 | this.state.activeSetttingsTab === 'language' |
343 | ? 'badge badge--primary' | ||
344 | : 'badge' | ||
345 | } | ||
346 | onClick={() => { | ||
347 | this.setActiveSettingsTab('language'); | ||
348 | }} | ||
309 | > | 349 | > |
310 | {intl.formatMessage(messages.headlineLanguage)} | 350 | {intl.formatMessage(messages.headlineLanguage)} |
311 | </h2> | 351 | </h2> |
312 | <h2 | 352 | <h2 |
313 | id="advanced" | 353 | id="advanced" |
314 | className={this.state.activeSetttingsTab === 'advanced' ? 'badge badge--primary' : 'badge'} | 354 | className={ |
315 | onClick={() => { this.setActiveSettingsTab('advanced'); }} | 355 | this.state.activeSetttingsTab === 'advanced' |
356 | ? 'badge badge--primary' | ||
357 | : 'badge' | ||
358 | } | ||
359 | onClick={() => { | ||
360 | this.setActiveSettingsTab('advanced'); | ||
361 | }} | ||
316 | > | 362 | > |
317 | {intl.formatMessage(messages.headlineAdvanced)} | 363 | {intl.formatMessage(messages.headlineAdvanced)} |
318 | </h2> | 364 | </h2> |
319 | <h2 | 365 | <h2 |
320 | id="updates" | 366 | id="updates" |
321 | className={this.state.activeSetttingsTab === 'updates' ? 'badge badge--primary' : 'badge'} | 367 | className={ |
322 | onClick={() => { this.setActiveSettingsTab('updates'); }} | 368 | this.state.activeSetttingsTab === 'updates' |
369 | ? 'badge badge--primary' | ||
370 | : 'badge' | ||
371 | } | ||
372 | onClick={() => { | ||
373 | this.setActiveSettingsTab('updates'); | ||
374 | }} | ||
323 | > | 375 | > |
324 | {intl.formatMessage(messages.headlineUpdates)} | 376 | {intl.formatMessage(messages.headlineUpdates)} |
325 | </h2> | 377 | </h2> |
326 | </div> | 378 | </div> |
327 | 379 | ||
328 | {/* General */} | 380 | {/* General */} |
329 | { this.state.activeSetttingsTab === 'general' && ( | 381 | {this.state.activeSetttingsTab === 'general' && ( |
330 | <div> | 382 | <div> |
331 | <Toggle field={form.$('autoLaunchOnStart')} /> | 383 | <Toggle field={form.$('autoLaunchOnStart')} /> |
332 | <Toggle field={form.$('runInBackground')} /> | 384 | <Toggle field={form.$('runInBackground')} /> |
@@ -334,12 +386,8 @@ export default @observer class EditSettingsForm extends Component { | |||
334 | <Toggle field={form.$('enableSystemTray')} /> | 386 | <Toggle field={form.$('enableSystemTray')} /> |
335 | <Toggle field={form.$('reloadAfterResume')} /> | 387 | <Toggle field={form.$('reloadAfterResume')} /> |
336 | <Toggle field={form.$('startMinimized')} /> | 388 | <Toggle field={form.$('startMinimized')} /> |
337 | {isWindows && ( | 389 | {isWindows && <Toggle field={form.$('minimizeToSystemTray')} />} |
338 | <Toggle field={form.$('minimizeToSystemTray')} /> | 390 | {isWindows && <Toggle field={form.$('closeToSystemTray')} />} |
339 | )} | ||
340 | {isWindows && ( | ||
341 | <Toggle field={form.$('closeToSystemTray')} /> | ||
342 | )} | ||
343 | <Select field={form.$('navigationBarBehaviour')} /> | 391 | <Select field={form.$('navigationBarBehaviour')} /> |
344 | 392 | ||
345 | <Hr /> | 393 | <Hr /> |
@@ -349,12 +397,13 @@ export default @observer class EditSettingsForm extends Component { | |||
349 | <p | 397 | <p |
350 | className="settings__message" | 398 | className="settings__message" |
351 | style={{ | 399 | style={{ |
352 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 400 | borderTop: 0, |
401 | marginTop: 0, | ||
402 | paddingTop: 0, | ||
403 | marginBottom: '2rem', | ||
353 | }} | 404 | }} |
354 | > | 405 | > |
355 | <span> | 406 | <span>{intl.formatMessage(messages.hibernateInfo)}</span> |
356 | { intl.formatMessage(messages.hibernateInfo) } | ||
357 | </span> | ||
358 | </p> | 407 | </p> |
359 | 408 | ||
360 | <Select field={form.$('wakeUpStrategy')} /> | 409 | <Select field={form.$('wakeUpStrategy')} /> |
@@ -374,20 +423,24 @@ export default @observer class EditSettingsForm extends Component { | |||
374 | {isTodosActivated && ( | 423 | {isTodosActivated && ( |
375 | <div> | 424 | <div> |
376 | <Select field={form.$('predefinedTodoServer')} /> | 425 | <Select field={form.$('predefinedTodoServer')} /> |
377 | {form.$('predefinedTodoServer').value === 'isUsingCustomTodoService' && ( | 426 | {form.$('predefinedTodoServer').value === |
427 | 'isUsingCustomTodoService' && ( | ||
378 | <div> | 428 | <div> |
379 | <Input | 429 | <Input |
380 | placeholder="Todo Server" | 430 | placeholder="Todo Server" |
381 | onChange={(e) => this.submit(e)} | 431 | onChange={e => this.submit(e)} |
382 | field={form.$('customTodoServer')} | 432 | field={form.$('customTodoServer')} |
383 | /> | 433 | /> |
384 | <p | 434 | <p |
385 | className="settings__message" | 435 | className="settings__message" |
386 | style={{ | 436 | style={{ |
387 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 437 | borderTop: 0, |
438 | marginTop: 0, | ||
439 | paddingTop: 0, | ||
440 | marginBottom: '2rem', | ||
388 | }} | 441 | }} |
389 | > | 442 | > |
390 | { intl.formatMessage(messages.todoServerInfo) } | 443 | {intl.formatMessage(messages.todoServerInfo)} |
391 | </p> | 444 | </p> |
392 | </div> | 445 | </div> |
393 | )} | 446 | )} |
@@ -400,56 +453,58 @@ export default @observer class EditSettingsForm extends Component { | |||
400 | <Toggle field={form.$('scheduledDNDEnabled')} /> | 453 | <Toggle field={form.$('scheduledDNDEnabled')} /> |
401 | {scheduledDNDEnabled && ( | 454 | {scheduledDNDEnabled && ( |
402 | <> | 455 | <> |
403 | <div style={{ | 456 | <div |
404 | display: 'flex', | 457 | style={{ |
405 | justifyContent: 'center', | 458 | display: 'flex', |
406 | }} | 459 | justifyContent: 'center', |
407 | > | ||
408 | <div style={{ | ||
409 | padding: '0 1rem', | ||
410 | width: '100%', | ||
411 | }} | 460 | }} |
461 | > | ||
462 | <div | ||
463 | style={{ | ||
464 | padding: '0 1rem', | ||
465 | width: '100%', | ||
466 | }} | ||
412 | > | 467 | > |
413 | <Input | 468 | <Input |
414 | placeholder="17:00" | 469 | placeholder="17:00" |
415 | onChange={(e) => this.submit(e)} | 470 | onChange={e => this.submit(e)} |
416 | field={form.$('scheduledDNDStart')} | 471 | field={form.$('scheduledDNDStart')} |
417 | type="time" | 472 | type="time" |
418 | /> | 473 | /> |
419 | </div> | 474 | </div> |
420 | <div style={{ | 475 | <div |
421 | padding: '0 1rem', | 476 | style={{ |
422 | width: '100%', | 477 | padding: '0 1rem', |
423 | }} | 478 | width: '100%', |
479 | }} | ||
424 | > | 480 | > |
425 | <Input | 481 | <Input |
426 | placeholder="09:00" | 482 | placeholder="09:00" |
427 | onChange={(e) => this.submit(e)} | 483 | onChange={e => this.submit(e)} |
428 | field={form.$('scheduledDNDEnd')} | 484 | field={form.$('scheduledDNDEnd')} |
429 | type="time" | 485 | type="time" |
430 | /> | 486 | /> |
431 | </div> | 487 | </div> |
432 | </div> | 488 | </div> |
433 | <p> | 489 | <p>{intl.formatMessage(messages.scheduledDNDTimeInfo)}</p> |
434 | { intl.formatMessage(messages.scheduledDNDTimeInfo) } | ||
435 | </p> | ||
436 | </> | 490 | </> |
437 | )} | 491 | )} |
438 | <p | 492 | <p |
439 | className="settings__message" | 493 | className="settings__message" |
440 | style={{ | 494 | style={{ |
441 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 495 | borderTop: 0, |
496 | marginTop: 0, | ||
497 | paddingTop: 0, | ||
498 | marginBottom: '2rem', | ||
442 | }} | 499 | }} |
443 | > | 500 | > |
444 | <span> | 501 | <span>{intl.formatMessage(messages.scheduledDNDInfo)}</span> |
445 | { intl.formatMessage(messages.scheduledDNDInfo) } | ||
446 | </span> | ||
447 | </p> | 502 | </p> |
448 | </div> | 503 | </div> |
449 | )} | 504 | )} |
450 | 505 | ||
451 | {/* Appearance */} | 506 | {/* Appearance */} |
452 | { this.state.activeSetttingsTab === 'appearance' && ( | 507 | {this.state.activeSetttingsTab === 'appearance' && ( |
453 | <div> | 508 | <div> |
454 | <Toggle field={form.$('showDisabledServices')} /> | 509 | <Toggle field={form.$('showDisabledServices')} /> |
455 | <Toggle field={form.$('showMessageBadgeWhenMuted')} /> | 510 | <Toggle field={form.$('showMessageBadgeWhenMuted')} /> |
@@ -459,21 +514,26 @@ export default @observer class EditSettingsForm extends Component { | |||
459 | <Hr /> | 514 | <Hr /> |
460 | 515 | ||
461 | <Toggle field={form.$('adaptableDarkMode')} /> | 516 | <Toggle field={form.$('adaptableDarkMode')} /> |
462 | {!isAdaptableDarkModeEnabled && <Toggle field={form.$('darkMode')} />} | 517 | {!isAdaptableDarkModeEnabled && ( |
518 | <Toggle field={form.$('darkMode')} /> | ||
519 | )} | ||
463 | {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( | 520 | {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( |
464 | <> | 521 | <> |
465 | <Toggle field={form.$('universalDarkMode')} /> | 522 | <Toggle field={form.$('universalDarkMode')} /> |
466 | <p | 523 | <p |
467 | className="settings__message" | 524 | className="settings__message" |
468 | style={{ | 525 | style={{ |
469 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 526 | borderTop: 0, |
470 | }} | 527 | marginTop: 0, |
471 | > | 528 | paddingTop: 0, |
472 | <span> | 529 | marginBottom: '2rem', |
473 | { intl.formatMessage(messages.universalDarkModeInfo) } | 530 | }} |
474 | </span> | 531 | > |
475 | </p> | 532 | <span> |
476 | </> | 533 | {intl.formatMessage(messages.universalDarkModeInfo)} |
534 | </span> | ||
535 | </p> | ||
536 | </> | ||
477 | )} | 537 | )} |
478 | 538 | ||
479 | <Hr /> | 539 | <Hr /> |
@@ -491,23 +551,25 @@ export default @observer class EditSettingsForm extends Component { | |||
491 | 551 | ||
492 | <Input | 552 | <Input |
493 | placeholder="Accent Color" | 553 | placeholder="Accent Color" |
494 | onChange={(e) => this.submit(e)} | 554 | onChange={e => this.submit(e)} |
495 | field={form.$('accentColor')} | 555 | field={form.$('accentColor')} |
496 | /> | 556 | /> |
497 | <p> | 557 | <p> |
498 | {intl.formatMessage(messages.accentColorInfo, | 558 | {intl.formatMessage(messages.accentColorInfo, { |
499 | { defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor })} | 559 | defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor, |
560 | })} | ||
500 | </p> | 561 | </p> |
501 | </div> | 562 | </div> |
502 | )} | 563 | )} |
503 | 564 | ||
504 | {/* Privacy */} | 565 | {/* Privacy */} |
505 | { this.state.activeSetttingsTab === 'privacy' && ( | 566 | {this.state.activeSetttingsTab === 'privacy' && ( |
506 | <div> | 567 | <div> |
507 | <Toggle field={form.$('privateNotifications')} /> | 568 | <Toggle field={form.$('privateNotifications')} /> |
508 | <Toggle field={form.$('clipboardNotifications')} /> | 569 | <Toggle field={form.$('clipboardNotifications')} /> |
509 | {(isWindows || isMac) && ( | 570 | {(isWindows || isMac) && ( |
510 | <Toggle field={form.$('notifyTaskBarOnMessage')} />)} | 571 | <Toggle field={form.$('notifyTaskBarOnMessage')} /> |
572 | )} | ||
511 | 573 | ||
512 | <Hr /> | 574 | <Hr /> |
513 | 575 | ||
@@ -516,8 +578,12 @@ export default @observer class EditSettingsForm extends Component { | |||
516 | <Hr /> | 578 | <Hr /> |
517 | 579 | ||
518 | <Toggle field={form.$('sentry')} /> | 580 | <Toggle field={form.$('sentry')} /> |
519 | <p className="settings__help">{intl.formatMessage(messages.sentryInfo)}</p> | 581 | <p className="settings__help"> |
520 | <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 582 | {intl.formatMessage(messages.sentryInfo)} |
583 | </p> | ||
584 | <p className="settings__help"> | ||
585 | {intl.formatMessage(messages.appRestartRequired)} | ||
586 | </p> | ||
521 | 587 | ||
522 | <Hr /> | 588 | <Hr /> |
523 | 589 | ||
@@ -530,57 +596,60 @@ export default @observer class EditSettingsForm extends Component { | |||
530 | 596 | ||
531 | <Input | 597 | <Input |
532 | placeholder={intl.formatMessage(messages.lockedPassword)} | 598 | placeholder={intl.formatMessage(messages.lockedPassword)} |
533 | onChange={(e) => this.submit(e)} | 599 | onChange={e => this.submit(e)} |
534 | field={form.$('lockedPassword')} | 600 | field={form.$('lockedPassword')} |
535 | type="password" | 601 | type="password" |
536 | scorePassword | 602 | scorePassword |
537 | showPasswordToggle | 603 | showPasswordToggle |
538 | /> | 604 | /> |
539 | <p> | 605 | <p>{intl.formatMessage(messages.lockedPasswordInfo)}</p> |
540 | { intl.formatMessage(messages.lockedPasswordInfo) } | ||
541 | </p> | ||
542 | 606 | ||
543 | <Input | 607 | <Input |
544 | placeholder="Lock after inactivity" | 608 | placeholder="Lock after inactivity" |
545 | onChange={(e) => this.submit(e)} | 609 | onChange={e => this.submit(e)} |
546 | field={form.$('inactivityLock')} | 610 | field={form.$('inactivityLock')} |
547 | autoFocus | 611 | autoFocus |
548 | /> | 612 | /> |
549 | <p> | 613 | <p>{intl.formatMessage(messages.inactivityLockInfo)}</p> |
550 | { intl.formatMessage(messages.inactivityLockInfo) } | ||
551 | </p> | ||
552 | </> | 614 | </> |
553 | )} | 615 | )} |
554 | <p | 616 | <p |
555 | className="settings__message" | 617 | className="settings__message" |
556 | style={{ | 618 | style={{ |
557 | borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', | 619 | borderTop: 0, |
620 | marginTop: 0, | ||
621 | paddingTop: 0, | ||
622 | marginBottom: '2rem', | ||
558 | }} | 623 | }} |
559 | > | 624 | > |
560 | <span> | 625 | <span> |
561 | { intl.formatMessage(messages.lockInfo, { lockShortcut: `${lockFerdiShortcutKey(false)}` }) } | 626 | {intl.formatMessage(messages.lockInfo, { |
627 | lockShortcut: `${lockFerdiShortcutKey(false)}`, | ||
628 | })} | ||
562 | </span> | 629 | </span> |
563 | </p> | 630 | </p> |
564 | </div> | 631 | </div> |
565 | )} | 632 | )} |
566 | 633 | ||
567 | {/* Language */} | 634 | {/* Language */} |
568 | { this.state.activeSetttingsTab === 'language' && ( | 635 | {this.state.activeSetttingsTab === 'language' && ( |
569 | <div> | 636 | <div> |
570 | <Select field={form.$('locale')} showLabel={false} /> | 637 | <Select field={form.$('locale')} showLabel={false} /> |
571 | 638 | ||
572 | <Hr /> | 639 | <Hr /> |
573 | 640 | ||
574 | <Toggle | 641 | <Toggle field={form.$('enableSpellchecking')} /> |
575 | field={form.$('enableSpellchecking')} | ||
576 | /> | ||
577 | {!isMac && form.$('enableSpellchecking').value && ( | 642 | {!isMac && form.$('enableSpellchecking').value && ( |
578 | <Select field={form.$('spellcheckerLanguage')} /> | 643 | <Select field={form.$('spellcheckerLanguage')} /> |
579 | )} | 644 | )} |
580 | {isMac && form.$('enableSpellchecking').value && ( | 645 | {isMac && form.$('enableSpellchecking').value && ( |
581 | <p className="settings__help">{intl.formatMessage(messages.spellCheckerLanguageInfo)}</p> | 646 | <p className="settings__help"> |
647 | {intl.formatMessage(messages.spellCheckerLanguageInfo)} | ||
648 | </p> | ||
582 | )} | 649 | )} |
583 | <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 650 | <p className="settings__help"> |
651 | {intl.formatMessage(messages.appRestartRequired)} | ||
652 | </p> | ||
584 | 653 | ||
585 | <Hr /> | 654 | <Hr /> |
586 | 655 | ||
@@ -590,52 +659,54 @@ export default @observer class EditSettingsForm extends Component { | |||
590 | className="link" | 659 | className="link" |
591 | rel="noreferrer" | 660 | rel="noreferrer" |
592 | > | 661 | > |
593 | {intl.formatMessage(messages.translationHelp)} | 662 | {intl.formatMessage(messages.translationHelp)}{' '} |
594 | {' '} | ||
595 | <i className="mdi mdi-open-in-new" /> | 663 | <i className="mdi mdi-open-in-new" /> |
596 | </a> | 664 | </a> |
597 | </div> | 665 | </div> |
598 | )} | 666 | )} |
599 | 667 | ||
600 | {/* Advanced */} | 668 | {/* Advanced */} |
601 | { this.state.activeSetttingsTab === 'advanced' && ( | 669 | {this.state.activeSetttingsTab === 'advanced' && ( |
602 | <div> | 670 | <div> |
603 | <Toggle field={form.$('enableGPUAcceleration')} /> | 671 | <Toggle field={form.$('enableGPUAcceleration')} /> |
604 | <p className="settings__help indented__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 672 | <p className="settings__help indented__help"> |
673 | {intl.formatMessage(messages.appRestartRequired)} | ||
674 | </p> | ||
605 | 675 | ||
606 | <Hr /> | 676 | <Hr /> |
607 | 677 | ||
608 | <Input | 678 | <Input |
609 | placeholder="User Agent" | 679 | placeholder="User Agent" |
610 | onChange={(e) => this.submit(e)} | 680 | onChange={e => this.submit(e)} |
611 | field={form.$('userAgentPref')} | 681 | field={form.$('userAgentPref')} |
612 | /> | 682 | /> |
613 | <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> | 683 | <p className="settings__help"> |
614 | <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> | 684 | {intl.formatMessage(globalMessages.userAgentHelp)} |
685 | </p> | ||
686 | <p className="settings__help"> | ||
687 | {intl.formatMessage(messages.appRestartRequired)} | ||
688 | </p> | ||
615 | 689 | ||
616 | <Hr /> | 690 | <Hr /> |
617 | 691 | ||
618 | <div className="settings__settings-group"> | 692 | <div className="settings__settings-group"> |
619 | <h3> | 693 | <h3>{intl.formatMessage(messages.subheadlineCache)}</h3> |
620 | {intl.formatMessage(messages.subheadlineCache)} | ||
621 | </h3> | ||
622 | <p> | 694 | <p> |
623 | {intl.formatMessage(messages.cacheInfo, { | 695 | {intl.formatMessage(messages.cacheInfo, { |
624 | size: cacheSize, | 696 | size: cacheSize, |
625 | })} | 697 | })} |
626 | </p> | 698 | </p> |
627 | { | 699 | {notCleared && ( |
628 | notCleared && ( | 700 | <p>{intl.formatMessage(messages.cacheNotCleared)}</p> |
629 | <p> | 701 | )} |
630 | {intl.formatMessage(messages.cacheNotCleared)} | ||
631 | </p> | ||
632 | ) | ||
633 | } | ||
634 | <p> | 702 | <p> |
635 | <Button | 703 | <Button |
636 | buttonType="secondary" | 704 | buttonType="secondary" |
637 | label={intl.formatMessage(messages.buttonClearAllCache)} | 705 | label={intl.formatMessage(messages.buttonClearAllCache)} |
638 | onClick={() => { onClearAllCache(); this.onClearCacheClicked(); }} | 706 | onClick={() => { |
707 | onClearAllCache(); | ||
708 | this.onClearCacheClicked(); | ||
709 | }} | ||
639 | disabled={isClearingAllCache} | 710 | disabled={isClearingAllCache} |
640 | loaded={!isClearingAllCache} | 711 | loaded={!isClearingAllCache} |
641 | /> | 712 | /> |
@@ -652,13 +723,17 @@ export default @observer class EditSettingsForm extends Component { | |||
652 | <div className="settings__open-settings-file-container"> | 723 | <div className="settings__open-settings-file-container"> |
653 | <Button | 724 | <Button |
654 | buttonType="secondary" | 725 | buttonType="secondary" |
655 | label={intl.formatMessage(messages.buttonOpenFerdiProfileFolder)} | 726 | label={intl.formatMessage( |
727 | messages.buttonOpenFerdiProfileFolder, | ||
728 | )} | ||
656 | className="settings__open-settings-file-button" | 729 | className="settings__open-settings-file-button" |
657 | onClick={() => openPath(profileFolder)} | 730 | onClick={() => openPath(profileFolder)} |
658 | /> | 731 | /> |
659 | <Button | 732 | <Button |
660 | buttonType="secondary" | 733 | buttonType="secondary" |
661 | label={intl.formatMessage(messages.buttonOpenFerdiServiceRecipesFolder)} | 734 | label={intl.formatMessage( |
735 | messages.buttonOpenFerdiServiceRecipesFolder, | ||
736 | )} | ||
662 | className="settings__open-settings-file-button" | 737 | className="settings__open-settings-file-button" |
663 | onClick={() => openPath(recipeFolder)} | 738 | onClick={() => openPath(recipeFolder)} |
664 | /> | 739 | /> |
@@ -669,66 +744,78 @@ export default @observer class EditSettingsForm extends Component { | |||
669 | )} | 744 | )} |
670 | 745 | ||
671 | {/* Updates */} | 746 | {/* Updates */} |
672 | { this.state.activeSetttingsTab === 'updates' && ( | 747 | {this.state.activeSetttingsTab === 'updates' && ( |
673 | <div> | ||
674 | <Toggle field={form.$('automaticUpdates')} /> | ||
675 | {automaticUpdates && ( | ||
676 | <div> | 748 | <div> |
677 | <Toggle field={form.$('beta')} /> | 749 | <Toggle field={form.$('automaticUpdates')} /> |
678 | <ToggleRaw | 750 | {automaticUpdates && ( |
679 | field={{ | 751 | <div> |
680 | value: isNightlyEnabled, | 752 | <Toggle field={form.$('beta')} /> |
681 | id: 'nightly', | 753 | <ToggleRaw |
682 | label: 'Include nightly versions', | 754 | field={{ |
683 | name: 'Nightly builds', | 755 | value: isNightlyEnabled, |
684 | }} | 756 | id: 'nightly', |
685 | onChange={window.ferdi.features.nightlyBuilds.toggleFeature} | 757 | label: 'Include nightly versions', |
686 | /> | 758 | name: 'Nightly builds', |
687 | {updateIsReadyToInstall ? ( | 759 | }} |
688 | <Button | 760 | onChange={ |
689 | label={intl.formatMessage(messages.buttonInstallUpdate)} | 761 | window.ferdi.features.nightlyBuilds.toggleFeature |
690 | onClick={installUpdate} | 762 | } |
691 | /> | 763 | /> |
692 | ) : ( | 764 | {updateIsReadyToInstall ? ( |
693 | <Button | 765 | <Button |
694 | buttonType="secondary" | 766 | label={intl.formatMessage(messages.buttonInstallUpdate)} |
695 | label={intl.formatMessage(updateButtonLabelMessage)} | 767 | onClick={installUpdate} |
696 | onClick={checkForUpdates} | 768 | /> |
697 | disabled={!automaticUpdates || isCheckingForUpdates || isUpdateAvailable || !isOnline} | 769 | ) : ( |
698 | loaded={!isCheckingForUpdates || !isUpdateAvailable} | 770 | <Button |
699 | /> | 771 | buttonType="secondary" |
772 | label={intl.formatMessage(updateButtonLabelMessage)} | ||
773 | onClick={checkForUpdates} | ||
774 | disabled={ | ||
775 | !automaticUpdates || | ||
776 | isCheckingForUpdates || | ||
777 | isUpdateAvailable || | ||
778 | !isOnline | ||
779 | } | ||
780 | loaded={!isCheckingForUpdates || !isUpdateAvailable} | ||
781 | /> | ||
782 | )} | ||
783 | <br /> | ||
784 | </div> | ||
785 | )} | ||
786 | {intl.formatMessage(messages.currentVersion)} {ferdiVersion} | ||
787 | {noUpdateAvailable && ( | ||
788 | <> | ||
789 | <br /> | ||
790 | <br /> | ||
791 | {intl.formatMessage(messages.updateStatusUpToDate)} | ||
792 | </> | ||
700 | )} | 793 | )} |
701 | <br /> | 794 | <p className="settings__message"> |
795 | <span className="mdi mdi-github-face" /> | ||
796 | <span> | ||
797 | Ferdi is based on{' '} | ||
798 | <a | ||
799 | href={`${GITHUB_FRANZ_URL}/franz`} | ||
800 | target="_blank" | ||
801 | rel="noreferrer" | ||
802 | > | ||
803 | Franz | ||
804 | </a> | ||
805 | , a project published under the{' '} | ||
806 | <a | ||
807 | href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} | ||
808 | target="_blank" | ||
809 | rel="noreferrer" | ||
810 | > | ||
811 | Apache-2.0 License | ||
812 | </a> | ||
813 | </span> | ||
814 | <br /> | ||
815 | <span className="mdi mdi-information" /> | ||
816 | {intl.formatMessage(messages.languageDisclaimer)} | ||
817 | </p> | ||
702 | </div> | 818 | </div> |
703 | )} | ||
704 | {intl.formatMessage(messages.currentVersion)} | ||
705 | {' '} | ||
706 | {ferdiVersion} | ||
707 | {noUpdateAvailable && ( | ||
708 | <> | ||
709 | <br /> | ||
710 | <br /> | ||
711 | {intl.formatMessage(messages.updateStatusUpToDate)} | ||
712 | </> | ||
713 | )} | ||
714 | <p className="settings__message"> | ||
715 | <span className="mdi mdi-github-face" /> | ||
716 | <span> | ||
717 | |||
718 | Ferdi is based on | ||
719 | {' '} | ||
720 | <a href={`${GITHUB_FRANZ_URL}/franz`} target="_blank" rel="noreferrer">Franz</a> | ||
721 | |||
722 | , a project published | ||
723 | under the | ||
724 | {' '} | ||
725 | <a href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} target="_blank" rel="noreferrer">Apache-2.0 License</a> | ||
726 | </span> | ||
727 | <br /> | ||
728 | <span className="mdi mdi-information" /> | ||
729 | {intl.formatMessage(messages.languageDisclaimer)} | ||
730 | </p> | ||
731 | </div> | ||
732 | )} | 819 | )} |
733 | </form> | 820 | </form> |
734 | </div> | 821 | </div> |
@@ -736,3 +823,5 @@ export default @observer class EditSettingsForm extends Component { | |||
736 | ); | 823 | ); |
737 | } | 824 | } |
738 | } | 825 | } |
826 | |||
827 | export default injectIntl(EditSettingsForm); | ||
diff --git a/src/components/settings/supportFerdi/SupportFerdiDashboard.js b/src/components/settings/supportFerdi/SupportFerdiDashboard.js index b84e06739..c4d4bd72f 100644 --- a/src/components/settings/supportFerdi/SupportFerdiDashboard.js +++ b/src/components/settings/supportFerdi/SupportFerdiDashboard.js | |||
@@ -1,76 +1,77 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import { defineMessages, FormattedHTMLMessage, intlShape } from 'react-intl'; | 2 | import { defineMessages, injectIntl } from 'react-intl'; |
3 | import { BrowserWindow } from '@electron/remote'; | 3 | import { BrowserWindow } from '@electron/remote'; |
4 | import InfoBar from '../../ui/InfoBar'; | 4 | import InfoBar from '../../ui/InfoBar'; |
5 | 5 | ||
6 | const messages = defineMessages({ | 6 | const messages = defineMessages({ |
7 | headline: { | 7 | headline: { |
8 | id: 'settings.supportFerdi.headline', | 8 | id: 'settings.supportFerdi.headline', |
9 | defaultMessage: '!!!About Ferdi', | 9 | defaultMessage: 'About Ferdi', |
10 | }, | 10 | }, |
11 | title: { | 11 | title: { |
12 | id: 'settings.supportFerdi.title', | 12 | id: 'settings.supportFerdi.title', |
13 | defaultMessage: '!!!Do you like Ferdi?', | 13 | defaultMessage: 'Do you like Ferdi?', |
14 | }, | 14 | }, |
15 | aboutIntro: { | 15 | aboutIntro: { |
16 | id: 'settings.supportFerdi.aboutIntro', | 16 | id: 'settings.supportFerdi.aboutIntro', |
17 | defaultMessage: '!!!<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>', | 17 | defaultMessage: |
18 | '<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>', | ||
18 | }, | 19 | }, |
19 | textListContributors: { | 20 | textListContributors: { |
20 | id: 'settings.supportFerdi.textListContributors', | 21 | id: 'settings.supportFerdi.textListContributors', |
21 | defaultMessage: '!!!Full list of contributor', | 22 | defaultMessage: 'Full list of contributor', |
22 | }, | 23 | }, |
23 | textListContributorsHere: { | 24 | textListContributorsHere: { |
24 | id: 'settings.supportFerdi.textListContributorsHere', | 25 | id: 'settings.supportFerdi.textListContributorsHere', |
25 | defaultMessage: '!!!here', | 26 | defaultMessage: 'here', |
26 | }, | 27 | }, |
27 | textVolunteers: { | 28 | textVolunteers: { |
28 | id: 'settings.supportFerdi.textVolunteers', | 29 | id: 'settings.supportFerdi.textVolunteers', |
29 | defaultMessage: '!!!The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.', | 30 | defaultMessage: |
31 | 'The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.', | ||
30 | }, | 32 | }, |
31 | textSupportWelcome: { | 33 | textSupportWelcome: { |
32 | id: 'settings.supportFerdi.textSupportWelcome', | 34 | id: 'settings.supportFerdi.textSupportWelcome', |
33 | defaultMessage: '!!!Support is always welcome. You can find a list of the help we need', | 35 | defaultMessage: |
36 | 'Support is always welcome. You can find a list of the help we need', | ||
34 | }, | 37 | }, |
35 | textSupportWelcomeHere: { | 38 | textSupportWelcomeHere: { |
36 | id: 'settings.supportFerdi.textSupportWelcomeHere', | 39 | id: 'settings.supportFerdi.textSupportWelcomeHere', |
37 | defaultMessage: '!!!here', | 40 | defaultMessage: 'here', |
38 | }, | 41 | }, |
39 | textExpenses: { | 42 | textExpenses: { |
40 | id: 'settings.supportFerdi.textExpenses', | 43 | id: 'settings.supportFerdi.textExpenses', |
41 | defaultMessage: '!!!While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our', | 44 | defaultMessage: |
45 | 'While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our', | ||
42 | }, | 46 | }, |
43 | textOpenCollective: { | 47 | textOpenCollective: { |
44 | id: 'settings.supportFerdi.textOpenCollective', | 48 | id: 'settings.supportFerdi.textOpenCollective', |
45 | defaultMessage: '!!!Open Collective', | 49 | defaultMessage: 'Open Collective', |
46 | }, | 50 | }, |
47 | textDonation: { | 51 | textDonation: { |
48 | id: 'settings.supportFerdi.textDonation', | 52 | id: 'settings.supportFerdi.textDonation', |
49 | defaultMessage: '!!!If you feel like supporting Ferdi development with a donation, you can do so on both,', | 53 | defaultMessage: |
54 | 'If you feel like supporting Ferdi development with a donation, you can do so on both,', | ||
50 | }, | 55 | }, |
51 | textDonationAnd: { | 56 | textDonationAnd: { |
52 | id: 'settings.supportFerdi.textDonationAnd', | 57 | id: 'settings.supportFerdi.textDonationAnd', |
53 | defaultMessage: '!!!and', | 58 | defaultMessage: 'and', |
54 | }, | 59 | }, |
55 | textGitHubSponsors: { | 60 | textGitHubSponsors: { |
56 | id: 'settings.supportFerdi.textGitHubSponsors', | 61 | id: 'settings.supportFerdi.textGitHubSponsors', |
57 | defaultMessage: '!!!GitHub Sponsors', | 62 | defaultMessage: 'GitHub Sponsors', |
58 | }, | 63 | }, |
59 | openSurvey: { | 64 | openSurvey: { |
60 | id: 'settings.supportFerdi.openSurvey', | 65 | id: 'settings.supportFerdi.openSurvey', |
61 | defaultMessage: '!!!Open Survey', | 66 | defaultMessage: 'Open Survey', |
62 | }, | 67 | }, |
63 | bannerText: { | 68 | bannerText: { |
64 | id: 'settings.supportFerdi.bannerText', | 69 | id: 'settings.supportFerdi.bannerText', |
65 | defaultMessage: '!!!Do you want to help us improve Ferdi?', | 70 | defaultMessage: 'Do you want to help us improve Ferdi?', |
66 | }, | 71 | }, |
67 | }); | 72 | }); |
68 | 73 | ||
69 | class SupportFerdiDashboard extends Component { | 74 | class SupportFerdiDashboard extends Component { |
70 | static contextTypes = { | ||
71 | intl: intlShape, | ||
72 | }; | ||
73 | |||
74 | openSurveyWindow() { | 75 | openSurveyWindow() { |
75 | let win = new BrowserWindow({ width: 670, height: 400 }); | 76 | let win = new BrowserWindow({ width: 670, height: 400 }); |
76 | win.on('closed', () => { | 77 | win.on('closed', () => { |
@@ -81,7 +82,9 @@ class SupportFerdiDashboard extends Component { | |||
81 | } | 82 | } |
82 | 83 | ||
83 | render() { | 84 | render() { |
84 | const { intl } = this.context; | 85 | const { intl } = this.props; |
86 | |||
87 | const aboutIntro = intl.formatMessage(messages.aboutIntro); | ||
85 | 88 | ||
86 | return ( | 89 | return ( |
87 | <div className="settings__main"> | 90 | <div className="settings__main"> |
@@ -94,22 +97,67 @@ class SupportFerdiDashboard extends Component { | |||
94 | <h1>{intl.formatMessage(messages.title)}</h1> | 97 | <h1>{intl.formatMessage(messages.title)}</h1> |
95 | <div> | 98 | <div> |
96 | <p className="settings__support-badges"> | 99 | <p className="settings__support-badges"> |
97 | <a href="https://github.com/getferdi/ferdi" target="_blank" rel="noreferrer"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" /></a> | 100 | <a |
98 | <a href="https://twitter.com/getferdi/" target="_blank" rel="noreferrer"><img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" /></a> | 101 | href="https://github.com/getferdi/ferdi" |
99 | <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective backers" src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" /></a> | 102 | target="_blank" |
100 | <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective sponsors" src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" /></a> | 103 | rel="noreferrer" |
104 | > | ||
105 | <img | ||
106 | alt="GitHub Stars" | ||
107 | src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" | ||
108 | /> | ||
109 | </a> | ||
110 | <a | ||
111 | href="https://twitter.com/getferdi/" | ||
112 | target="_blank" | ||
113 | rel="noreferrer" | ||
114 | > | ||
115 | <img | ||
116 | alt="Twitter Follow" | ||
117 | src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" | ||
118 | /> | ||
119 | </a> | ||
120 | <a | ||
121 | href="https://opencollective.com/getferdi#section-contributors" | ||
122 | target="_blank" | ||
123 | rel="noreferrer" | ||
124 | > | ||
125 | <img | ||
126 | alt="Open Collective backers" | ||
127 | src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" | ||
128 | /> | ||
129 | </a> | ||
130 | <a | ||
131 | href="https://opencollective.com/getferdi#section-contributors" | ||
132 | target="_blank" | ||
133 | rel="noreferrer" | ||
134 | > | ||
135 | <img | ||
136 | alt="Open Collective sponsors" | ||
137 | src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" | ||
138 | /> | ||
139 | </a> | ||
101 | </p> | 140 | </p> |
102 | <FormattedHTMLMessage {...messages.aboutIntro} /> | 141 | <span dangerouslySetInnerHTML={{ __html: aboutIntro }} /> |
103 | <br /> | 142 | <br /> |
104 | <br /> | 143 | <br /> |
105 | <p> | 144 | <p> |
106 | <a href="#contributors-via-opencollective"> | 145 | <a href="#contributors-via-opencollective"> |
107 | <img alt="GitHub contributors (non-exhaustive)" width="100%" src="https://opencollective.com/getferdi/contributors.svg?width=642&button=false" /> | 146 | <img |
147 | alt="GitHub contributors (non-exhaustive)" | ||
148 | width="100%" | ||
149 | src="https://opencollective.com/getferdi/contributors.svg?width=642&button=false" | ||
150 | /> | ||
108 | </a> | 151 | </a> |
109 | </p> | 152 | </p> |
110 | <p> | 153 | <p> |
111 | {intl.formatMessage(messages.textListContributors)} | 154 | {intl.formatMessage(messages.textListContributors)} |
112 | <a href="https://github.com/getferdi/ferdi#contributors-" target="_blank" className="link" rel="noreferrer"> | 155 | <a |
156 | href="https://github.com/getferdi/ferdi#contributors-" | ||
157 | target="_blank" | ||
158 | className="link" | ||
159 | rel="noreferrer" | ||
160 | > | ||
113 | {' '} | 161 | {' '} |
114 | {intl.formatMessage(messages.textListContributorsHere)} | 162 | {intl.formatMessage(messages.textListContributorsHere)} |
115 | <i className="mdi mdi-open-in-new" /> | 163 | <i className="mdi mdi-open-in-new" /> |
@@ -117,12 +165,15 @@ class SupportFerdiDashboard extends Component { | |||
117 | <br /> | 165 | <br /> |
118 | <br /> | 166 | <br /> |
119 | </p> | 167 | </p> |
120 | <p> | 168 | <p>{intl.formatMessage(messages.textVolunteers)}</p> |
121 | {intl.formatMessage(messages.textVolunteers)} | ||
122 | </p> | ||
123 | <p> | 169 | <p> |
124 | {intl.formatMessage(messages.textSupportWelcome)} | 170 | {intl.formatMessage(messages.textSupportWelcome)} |
125 | <a href="https://help.getferdi.com/general/support" target="_blank" className="link" rel="noreferrer"> | 171 | <a |
172 | href="https://help.getferdi.com/general/support" | ||
173 | target="_blank" | ||
174 | className="link" | ||
175 | rel="noreferrer" | ||
176 | > | ||
126 | {' '} | 177 | {' '} |
127 | {intl.formatMessage(messages.textSupportWelcomeHere)} | 178 | {intl.formatMessage(messages.textSupportWelcomeHere)} |
128 | <i className="mdi mdi-open-in-new" /> | 179 | <i className="mdi mdi-open-in-new" /> |
@@ -130,7 +181,12 @@ class SupportFerdiDashboard extends Component { | |||
130 | </p> | 181 | </p> |
131 | <p> | 182 | <p> |
132 | {intl.formatMessage(messages.textExpenses)} | 183 | {intl.formatMessage(messages.textExpenses)} |
133 | <a href="https://opencollective.com/getferdi#section-budget" target="_blank" className="link" rel="noreferrer"> | 184 | <a |
185 | href="https://opencollective.com/getferdi#section-budget" | ||
186 | target="_blank" | ||
187 | className="link" | ||
188 | rel="noreferrer" | ||
189 | > | ||
134 | {' '} | 190 | {' '} |
135 | {intl.formatMessage(messages.textOpenCollective)} | 191 | {intl.formatMessage(messages.textOpenCollective)} |
136 | <i className="mdi mdi-open-in-new" /> | 192 | <i className="mdi mdi-open-in-new" /> |
@@ -138,14 +194,23 @@ class SupportFerdiDashboard extends Component { | |||
138 | </p> | 194 | </p> |
139 | <p> | 195 | <p> |
140 | {intl.formatMessage(messages.textDonation)} | 196 | {intl.formatMessage(messages.textDonation)} |
141 | <a href="https://opencollective.com/getferdi#section-contribute" target="_blank" className="link" rel="noreferrer"> | 197 | <a |
198 | href="https://opencollective.com/getferdi#section-contribute" | ||
199 | target="_blank" | ||
200 | className="link" | ||
201 | rel="noreferrer" | ||
202 | > | ||
142 | {' '} | 203 | {' '} |
143 | {intl.formatMessage(messages.textOpenCollective)} | 204 | {intl.formatMessage(messages.textOpenCollective)} |
144 | <i className="mdi mdi-open-in-new" /> | 205 | <i className="mdi mdi-open-in-new" /> |
145 | </a> | 206 | </a>{' '} |
146 | {' '} | ||
147 | {intl.formatMessage(messages.textDonationAnd)} | 207 | {intl.formatMessage(messages.textDonationAnd)} |
148 | <a href="https://github.com/sponsors/getferdi" target="_blank" className="link" rel="noreferrer"> | 208 | <a |
209 | href="https://github.com/sponsors/getferdi" | ||
210 | target="_blank" | ||
211 | className="link" | ||
212 | rel="noreferrer" | ||
213 | > | ||
149 | {' '} | 214 | {' '} |
150 | {intl.formatMessage(messages.textGitHubSponsors)} | 215 | {intl.formatMessage(messages.textGitHubSponsors)} |
151 | <i className="mdi mdi-open-in-new" /> | 216 | <i className="mdi mdi-open-in-new" /> |
@@ -166,4 +231,4 @@ class SupportFerdiDashboard extends Component { | |||
166 | } | 231 | } |
167 | } | 232 | } |
168 | 233 | ||
169 | export default SupportFerdiDashboard; | 234 | export default injectIntl(SupportFerdiDashboard); |
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js index 437225058..176365fa8 100644 --- a/src/components/settings/team/TeamDashboard.js +++ b/src/components/settings/team/TeamDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | import classnames from 'classnames'; | 7 | import classnames from 'classnames'; |
@@ -14,31 +14,34 @@ import { LIVE_FRANZ_API } from '../../../config'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'settings.team.headline', | 16 | id: 'settings.team.headline', |
17 | defaultMessage: '!!!Team', | 17 | defaultMessage: 'Team', |
18 | }, | 18 | }, |
19 | contentHeadline: { | 19 | contentHeadline: { |
20 | id: 'settings.team.contentHeadline', | 20 | id: 'settings.team.contentHeadline', |
21 | defaultMessage: '!!!Franz Team Management', | 21 | defaultMessage: 'Franz Team Management', |
22 | }, | 22 | }, |
23 | intro: { | 23 | intro: { |
24 | id: 'settings.team.intro', | 24 | id: 'settings.team.intro', |
25 | defaultMessage: '!!!Your are currently using Franz Servers, which is why you have access to Team Management.', | 25 | defaultMessage: |
26 | 'Your are currently using Franz Servers, which is why you have access to Team Management.', | ||
26 | }, | 27 | }, |
27 | copy: { | 28 | copy: { |
28 | id: 'settings.team.copy', | 29 | id: 'settings.team.copy', |
29 | defaultMessage: '!!!Franz\'s Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don\'t loose any functionality in managing your account.', | 30 | defaultMessage: |
31 | "Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.", | ||
30 | }, | 32 | }, |
31 | manageButton: { | 33 | manageButton: { |
32 | id: 'settings.team.manageAction', | 34 | id: 'settings.team.manageAction', |
33 | defaultMessage: '!!!Manage your Team on meetfranz.com', | 35 | defaultMessage: 'Manage your Team on meetfranz.com', |
34 | }, | 36 | }, |
35 | teamsUnavailable: { | 37 | teamsUnavailable: { |
36 | id: 'settings.team.teamsUnavailable', | 38 | id: 'settings.team.teamsUnavailable', |
37 | defaultMessage: '!!!Teams are unavailable', | 39 | defaultMessage: 'Teams are unavailable', |
38 | }, | 40 | }, |
39 | teamsUnavailableInfo: { | 41 | teamsUnavailableInfo: { |
40 | id: 'settings.team.teamsUnavailableInfo', | 42 | id: 'settings.team.teamsUnavailableInfo', |
41 | defaultMessage: '!!!Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.', | 43 | defaultMessage: |
44 | 'Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.', | ||
42 | }, | 45 | }, |
43 | }); | 46 | }); |
44 | 47 | ||
@@ -87,7 +90,9 @@ const styles = { | |||
87 | }, | 90 | }, |
88 | }; | 91 | }; |
89 | 92 | ||
90 | export default @injectSheet(styles) @observer class TeamDashboard extends Component { | 93 | @injectSheet(styles) |
94 | @observer | ||
95 | class TeamDashboard extends Component { | ||
91 | static propTypes = { | 96 | static propTypes = { |
92 | isLoading: PropTypes.bool.isRequired, | 97 | isLoading: PropTypes.bool.isRequired, |
93 | userInfoRequestFailed: PropTypes.bool.isRequired, | 98 | userInfoRequestFailed: PropTypes.bool.isRequired, |
@@ -97,10 +102,6 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
97 | server: PropTypes.string.isRequired, | 102 | server: PropTypes.string.isRequired, |
98 | }; | 103 | }; |
99 | 104 | ||
100 | static contextTypes = { | ||
101 | intl: intlShape, | ||
102 | }; | ||
103 | |||
104 | render() { | 105 | render() { |
105 | const { | 106 | const { |
106 | isLoading, | 107 | isLoading, |
@@ -110,7 +111,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
110 | classes, | 111 | classes, |
111 | server, | 112 | server, |
112 | } = this.props; | 113 | } = this.props; |
113 | const { intl } = this.context; | 114 | const { intl } = this.props; |
114 | 115 | ||
115 | if (server === LIVE_FRANZ_API) { | 116 | if (server === LIVE_FRANZ_API) { |
116 | return ( | 117 | return ( |
@@ -121,9 +122,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
121 | </span> | 122 | </span> |
122 | </div> | 123 | </div> |
123 | <div className="settings__body"> | 124 | <div className="settings__body"> |
124 | {isLoading && ( | 125 | {isLoading && <Loader />} |
125 | <Loader /> | ||
126 | )} | ||
127 | 126 | ||
128 | {!isLoading && userInfoRequestFailed && ( | 127 | {!isLoading && userInfoRequestFailed && ( |
129 | <Infobox | 128 | <Infobox |
@@ -142,20 +141,24 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
142 | {!isLoading && ( | 141 | {!isLoading && ( |
143 | <> | 142 | <> |
144 | <> | 143 | <> |
145 | <h1 className={classnames({ | 144 | <h1 |
146 | [classes.headline]: true, | 145 | className={classnames({ |
147 | [classes.headlineWithSpacing]: true, | 146 | [classes.headline]: true, |
148 | })} | 147 | [classes.headlineWithSpacing]: true, |
148 | })} | ||
149 | > | 149 | > |
150 | {intl.formatMessage(messages.contentHeadline)} | 150 | {intl.formatMessage(messages.contentHeadline)} |
151 | |||
152 | </h1> | 151 | </h1> |
153 | <div className={classes.container}> | 152 | <div className={classes.container}> |
154 | <div className={classes.content}> | 153 | <div className={classes.content}> |
155 | <p>{intl.formatMessage(messages.intro)}</p> | 154 | <p>{intl.formatMessage(messages.intro)}</p> |
156 | <p>{intl.formatMessage(messages.copy)}</p> | 155 | <p>{intl.formatMessage(messages.copy)}</p> |
157 | </div> | 156 | </div> |
158 | <img className={classes.image} src="https://cdn.franzinfra.com/announcements/assets/teams.png" alt="Ferdi for Teams" /> | 157 | <img |
158 | className={classes.image} | ||
159 | src="https://cdn.franzinfra.com/announcements/assets/teams.png" | ||
160 | alt="Ferdi for Teams" | ||
161 | /> | ||
159 | </div> | 162 | </div> |
160 | <div className={classes.buttonContainer}> | 163 | <div className={classes.buttonContainer}> |
161 | <Button | 164 | <Button |
@@ -188,7 +191,8 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
188 | <p | 191 | <p |
189 | className="settings__message" | 192 | className="settings__message" |
190 | style={{ | 193 | style={{ |
191 | borderTop: 0, marginTop: 0, | 194 | borderTop: 0, |
195 | marginTop: 0, | ||
192 | }} | 196 | }} |
193 | > | 197 | > |
194 | {intl.formatMessage(messages.teamsUnavailableInfo)} | 198 | {intl.formatMessage(messages.teamsUnavailableInfo)} |
@@ -198,3 +202,5 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
198 | ); | 202 | ); |
199 | } | 203 | } |
200 | } | 204 | } |
205 | |||
206 | export default injectIntl(TeamDashboard); | ||
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js index db78acb69..4067881b8 100644 --- a/src/components/settings/user/EditUserForm.js +++ b/src/components/settings/user/EditUserForm.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import { Input } from '@meetfranz/forms'; | 6 | import { Input } from '@meetfranz/forms'; |
7 | 7 | ||
@@ -14,31 +14,32 @@ import Infobox from '../../ui/Infobox'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'settings.account.headline', | 16 | id: 'settings.account.headline', |
17 | defaultMessage: '!!!Account', | 17 | defaultMessage: 'Account', |
18 | }, | 18 | }, |
19 | headlineProfile: { | 19 | headlineProfile: { |
20 | id: 'settings.account.headlineProfile', | 20 | id: 'settings.account.headlineProfile', |
21 | defaultMessage: '!!!Update Profile', | 21 | defaultMessage: 'Update Profile', |
22 | }, | 22 | }, |
23 | headlineAccount: { | 23 | headlineAccount: { |
24 | id: 'settings.account.headlineAccount', | 24 | id: 'settings.account.headlineAccount', |
25 | defaultMessage: '!!!Account Information', | 25 | defaultMessage: 'Account Information', |
26 | }, | 26 | }, |
27 | headlinePassword: { | 27 | headlinePassword: { |
28 | id: 'settings.account.headlinePassword', | 28 | id: 'settings.account.headlinePassword', |
29 | defaultMessage: '!!!Change Password', | 29 | defaultMessage: 'Change Password', |
30 | }, | 30 | }, |
31 | successInfo: { | 31 | successInfo: { |
32 | id: 'settings.account.successInfo', | 32 | id: 'settings.account.successInfo', |
33 | defaultMessage: '!!!Your changes have been saved', | 33 | defaultMessage: 'Your changes have been saved', |
34 | }, | 34 | }, |
35 | buttonSave: { | 35 | buttonSave: { |
36 | id: 'settings.account.buttonSave', | 36 | id: 'settings.account.buttonSave', |
37 | defaultMessage: '!!!Update profile', | 37 | defaultMessage: 'Update profile', |
38 | }, | 38 | }, |
39 | }); | 39 | }); |
40 | 40 | ||
41 | export default @observer class EditUserForm extends Component { | 41 | @observer |
42 | class EditUserForm extends Component { | ||
42 | static propTypes = { | 43 | static propTypes = { |
43 | status: MobxPropTypes.observableArray.isRequired, | 44 | status: MobxPropTypes.observableArray.isRequired, |
44 | form: PropTypes.instanceOf(Form).isRequired, | 45 | form: PropTypes.instanceOf(Form).isRequired, |
@@ -46,14 +47,10 @@ export default @observer class EditUserForm extends Component { | |||
46 | isSaving: PropTypes.bool.isRequired, | 47 | isSaving: PropTypes.bool.isRequired, |
47 | }; | 48 | }; |
48 | 49 | ||
49 | static contextTypes = { | ||
50 | intl: intlShape, | ||
51 | }; | ||
52 | |||
53 | submit(e) { | 50 | submit(e) { |
54 | e.preventDefault(); | 51 | e.preventDefault(); |
55 | this.props.form.submit({ | 52 | this.props.form.submit({ |
56 | onSuccess: (form) => { | 53 | onSuccess: form => { |
57 | const values = form.values(); | 54 | const values = form.values(); |
58 | this.props.onSubmit(values); | 55 | this.props.onSubmit(values); |
59 | }, | 56 | }, |
@@ -68,7 +65,7 @@ export default @observer class EditUserForm extends Component { | |||
68 | form, | 65 | form, |
69 | isSaving, | 66 | isSaving, |
70 | } = this.props; | 67 | } = this.props; |
71 | const { intl } = this.context; | 68 | const { intl } = this.props; |
72 | 69 | ||
73 | return ( | 70 | return ( |
74 | <div className="settings__main"> | 71 | <div className="settings__main"> |
@@ -84,12 +81,9 @@ export default @observer class EditUserForm extends Component { | |||
84 | </span> | 81 | </span> |
85 | </div> | 82 | </div> |
86 | <div className="settings__body"> | 83 | <div className="settings__body"> |
87 | <form onSubmit={(e) => this.submit(e)} id="form"> | 84 | <form onSubmit={e => this.submit(e)} id="form"> |
88 | {status.length > 0 && status.includes('data-updated') && ( | 85 | {status.length > 0 && status.includes('data-updated') && ( |
89 | <Infobox | 86 | <Infobox type="success" icon="checkbox-marked-circle-outline"> |
90 | type="success" | ||
91 | icon="checkbox-marked-circle-outline" | ||
92 | > | ||
93 | {intl.formatMessage(messages.successInfo)} | 87 | {intl.formatMessage(messages.successInfo)} |
94 | </Infobox> | 88 | </Infobox> |
95 | )} | 89 | )} |
@@ -104,10 +98,7 @@ export default @observer class EditUserForm extends Component { | |||
104 | <Input field={form.$('organization')} /> | 98 | <Input field={form.$('organization')} /> |
105 | )} | 99 | )} |
106 | <h2>{intl.formatMessage(messages.headlinePassword)}</h2> | 100 | <h2>{intl.formatMessage(messages.headlinePassword)}</h2> |
107 | <Input | 101 | <Input {...form.$('oldPassword').bind()} showPasswordToggle /> |
108 | {...form.$('oldPassword').bind()} | ||
109 | showPasswordToggle | ||
110 | /> | ||
111 | <Input | 102 | <Input |
112 | {...form.$('newPassword').bind()} | 103 | {...form.$('newPassword').bind()} |
113 | showPasswordToggle | 104 | showPasswordToggle |
@@ -137,3 +128,5 @@ export default @observer class EditUserForm extends Component { | |||
137 | ); | 128 | ); |
138 | } | 129 | } |
139 | } | 130 | } |
131 | |||
132 | export default injectIntl(EditUserForm); | ||
diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js index bbfd5de28..fa4a719ab 100644 --- a/src/components/ui/AppLoader/index.js +++ b/src/components/ui/AppLoader/index.js | |||
@@ -19,7 +19,9 @@ const textList = shuffleArray([ | |||
19 | 'Fixing bugs', | 19 | 'Fixing bugs', |
20 | ]); | 20 | ]); |
21 | 21 | ||
22 | export default @injectSheet(styles) @withTheme class AppLoader extends Component { | 22 | @injectSheet(styles) |
23 | @withTheme | ||
24 | class AppLoader extends Component { | ||
23 | static propTypes = { | 25 | static propTypes = { |
24 | classes: PropTypes.object.isRequired, | 26 | classes: PropTypes.object.isRequired, |
25 | theme: PropTypes.object.isRequired, | 27 | theme: PropTypes.object.isRequired, |
@@ -28,7 +30,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component | |||
28 | 30 | ||
29 | static defaultProps = { | 31 | static defaultProps = { |
30 | texts: textList, | 32 | texts: textList, |
31 | } | 33 | }; |
32 | 34 | ||
33 | state = { | 35 | state = { |
34 | step: 0, | 36 | step: 0, |
@@ -38,7 +40,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component | |||
38 | 40 | ||
39 | componentDidMount() { | 41 | componentDidMount() { |
40 | this.interval = setInterval(() => { | 42 | this.interval = setInterval(() => { |
41 | this.setState((prevState) => ({ | 43 | this.setState(prevState => ({ |
42 | step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1, | 44 | step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1, |
43 | })); | 45 | })); |
44 | }, 2500); | 46 | }, 2500); |
@@ -73,3 +75,5 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component | |||
73 | ); | 75 | ); |
74 | } | 76 | } |
75 | } | 77 | } |
78 | |||
79 | export default AppLoader; | ||
diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js index 5066b9c06..f6c9fd3d3 100644 --- a/src/components/ui/Button.js +++ b/src/components/ui/Button.js | |||
@@ -4,7 +4,9 @@ import { observer, inject } from 'mobx-react'; | |||
4 | import Loader from 'react-loader'; | 4 | import Loader from 'react-loader'; |
5 | import classnames from 'classnames'; | 5 | import classnames from 'classnames'; |
6 | 6 | ||
7 | export default @inject('stores') @observer class Button extends Component { | 7 | @inject('stores') |
8 | @observer | ||
9 | class Button extends Component { | ||
8 | static propTypes = { | 10 | static propTypes = { |
9 | className: PropTypes.string, | 11 | className: PropTypes.string, |
10 | label: PropTypes.string.isRequired, | 12 | label: PropTypes.string.isRequired, |
@@ -26,7 +28,7 @@ export default @inject('stores') @observer class Button extends Component { | |||
26 | static defaultProps = { | 28 | static defaultProps = { |
27 | className: null, | 29 | className: null, |
28 | disabled: false, | 30 | disabled: false, |
29 | onClick: () => { }, | 31 | onClick: () => {}, |
30 | type: 'button', | 32 | type: 'button', |
31 | buttonType: '', | 33 | buttonType: '', |
32 | loaded: true, | 34 | loaded: true, |
@@ -76,7 +78,11 @@ export default @inject('stores') @observer class Button extends Component { | |||
76 | loaded={loaded} | 78 | loaded={loaded} |
77 | lines={10} | 79 | lines={10} |
78 | scale={0.4} | 80 | scale={0.4} |
79 | color={buttonType !== 'secondary' ? '#FFF' : this.props.stores.settings.app.accentColor} | 81 | color={ |
82 | buttonType !== 'secondary' | ||
83 | ? '#FFF' | ||
84 | : this.props.stores.settings.app.accentColor | ||
85 | } | ||
80 | component="span" | 86 | component="span" |
81 | /> | 87 | /> |
82 | {label} | 88 | {label} |
@@ -85,3 +91,5 @@ export default @inject('stores') @observer class Button extends Component { | |||
85 | ); | 91 | ); |
86 | } | 92 | } |
87 | } | 93 | } |
94 | |||
95 | export default Button; | ||
diff --git a/src/components/ui/FAB.js b/src/components/ui/FAB.js index 633edbe2c..a3aa06bc9 100644 --- a/src/components/ui/FAB.js +++ b/src/components/ui/FAB.js | |||
@@ -8,7 +8,8 @@ import classnames from 'classnames'; | |||
8 | 8 | ||
9 | import { oneOrManyChildElements } from '../../prop-types'; | 9 | import { oneOrManyChildElements } from '../../prop-types'; |
10 | 10 | ||
11 | export default @observer class Button extends Component { | 11 | @observer |
12 | class Button extends Component { | ||
12 | static propTypes = { | 13 | static propTypes = { |
13 | className: PropTypes.string, | 14 | className: PropTypes.string, |
14 | disabled: PropTypes.bool, | 15 | disabled: PropTypes.bool, |
@@ -21,7 +22,7 @@ export default @observer class Button extends Component { | |||
21 | static defaultProps = { | 22 | static defaultProps = { |
22 | className: null, | 23 | className: null, |
23 | disabled: false, | 24 | disabled: false, |
24 | onClick: () => { }, | 25 | onClick: () => {}, |
25 | type: 'button', | 26 | type: 'button', |
26 | htmlForm: '', | 27 | htmlForm: '', |
27 | }; | 28 | }; |
@@ -29,14 +30,8 @@ export default @observer class Button extends Component { | |||
29 | element = null; | 30 | element = null; |
30 | 31 | ||
31 | render() { | 32 | render() { |
32 | const { | 33 | const { className, disabled, onClick, type, children, htmlForm } = |
33 | className, | 34 | this.props; |
34 | disabled, | ||
35 | onClick, | ||
36 | type, | ||
37 | children, | ||
38 | htmlForm, | ||
39 | } = this.props; | ||
40 | 35 | ||
41 | const buttonProps = { | 36 | const buttonProps = { |
42 | className: classnames({ | 37 | className: classnames({ |
@@ -66,3 +61,5 @@ export default @observer class Button extends Component { | |||
66 | ); | 61 | ); |
67 | } | 62 | } |
68 | } | 63 | } |
64 | |||
65 | export default Button; | ||
diff --git a/src/components/ui/FeatureList.js b/src/components/ui/FeatureList.js index cf2664830..14e7ec3c4 100644 --- a/src/components/ui/FeatureList.js +++ b/src/components/ui/FeatureList.js | |||
@@ -1,53 +1,53 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | 4 | ||
5 | import { FeatureItem } from './FeatureItem'; | 5 | import { FeatureItem } from './FeatureItem'; |
6 | 6 | ||
7 | const messages = defineMessages({ | 7 | const messages = defineMessages({ |
8 | availableRecipes: { | 8 | availableRecipes: { |
9 | id: 'pricing.features.recipes', | 9 | id: 'pricing.features.recipes', |
10 | defaultMessage: '!!!Choose from more than 70 Services', // TODO: Make this dynamic | 10 | defaultMessage: 'Choose from more than 70 Services', // TODO: Make this dynamic |
11 | }, | 11 | }, |
12 | accountSync: { | 12 | accountSync: { |
13 | id: 'pricing.features.accountSync', | 13 | id: 'pricing.features.accountSync', |
14 | defaultMessage: '!!!Account Synchronisation', | 14 | defaultMessage: 'Account Synchronisation', |
15 | }, | 15 | }, |
16 | desktopNotifications: { | 16 | desktopNotifications: { |
17 | id: 'pricing.features.desktopNotifications', | 17 | id: 'pricing.features.desktopNotifications', |
18 | defaultMessage: '!!!Desktop Notifications', | 18 | defaultMessage: 'Desktop Notifications', |
19 | }, | 19 | }, |
20 | unlimitedServices: { | 20 | unlimitedServices: { |
21 | id: 'pricing.features.unlimitedServices', | 21 | id: 'pricing.features.unlimitedServices', |
22 | defaultMessage: '!!!Add unlimited services', | 22 | defaultMessage: 'Add unlimited services', |
23 | }, | 23 | }, |
24 | spellchecker: { | 24 | spellchecker: { |
25 | id: 'pricing.features.spellchecker', | 25 | id: 'pricing.features.spellchecker', |
26 | defaultMessage: '!!!Spellchecker support', | 26 | defaultMessage: 'Spellchecker support', |
27 | }, | 27 | }, |
28 | workspaces: { | 28 | workspaces: { |
29 | id: 'pricing.features.workspaces', | 29 | id: 'pricing.features.workspaces', |
30 | defaultMessage: '!!!Workspaces', | 30 | defaultMessage: 'Workspaces', |
31 | }, | 31 | }, |
32 | customWebsites: { | 32 | customWebsites: { |
33 | id: 'pricing.features.customWebsites', | 33 | id: 'pricing.features.customWebsites', |
34 | defaultMessage: '!!!Add Custom Websites', | 34 | defaultMessage: 'Add Custom Websites', |
35 | }, | 35 | }, |
36 | onPremise: { | 36 | onPremise: { |
37 | id: 'pricing.features.onPremise', | 37 | id: 'pricing.features.onPremise', |
38 | defaultMessage: '!!!On-premise & other Hosted Services', | 38 | defaultMessage: 'On-premise & other Hosted Services', |
39 | }, | 39 | }, |
40 | thirdPartyServices: { | 40 | thirdPartyServices: { |
41 | id: 'pricing.features.thirdPartyServices', | 41 | id: 'pricing.features.thirdPartyServices', |
42 | defaultMessage: '!!!Install 3rd party services', | 42 | defaultMessage: 'Install 3rd party services', |
43 | }, | 43 | }, |
44 | serviceProxies: { | 44 | serviceProxies: { |
45 | id: 'pricing.features.serviceProxies', | 45 | id: 'pricing.features.serviceProxies', |
46 | defaultMessage: '!!!Service Proxies', | 46 | defaultMessage: 'Service Proxies', |
47 | }, | 47 | }, |
48 | teamManagement: { | 48 | teamManagement: { |
49 | id: 'pricing.features.teamManagement', | 49 | id: 'pricing.features.teamManagement', |
50 | defaultMessage: '!!!Team Management', | 50 | defaultMessage: 'Team Management', |
51 | }, | 51 | }, |
52 | }); | 52 | }); |
53 | 53 | ||
@@ -60,18 +60,11 @@ export class FeatureList extends Component { | |||
60 | static defaultProps = { | 60 | static defaultProps = { |
61 | className: '', | 61 | className: '', |
62 | featureClassName: '', | 62 | featureClassName: '', |
63 | } | ||
64 | |||
65 | static contextTypes = { | ||
66 | intl: intlShape, | ||
67 | }; | 63 | }; |
68 | 64 | ||
69 | render() { | 65 | render() { |
70 | const { | 66 | const { className, featureClassName } = this.props; |
71 | className, | 67 | const { intl } = this.props; |
72 | featureClassName, | ||
73 | } = this.props; | ||
74 | const { intl } = this.context; | ||
75 | 68 | ||
76 | const features = [ | 69 | const features = [ |
77 | messages.availableRecipes, | 70 | messages.availableRecipes, |
@@ -92,10 +85,15 @@ export class FeatureList extends Component { | |||
92 | 85 | ||
93 | return ( | 86 | return ( |
94 | <ul className={className}> | 87 | <ul className={className}> |
95 | {features.map((feature) => <FeatureItem name={intl.formatMessage(feature)} className={featureClassName} />)} | 88 | {features.map(feature => ( |
89 | <FeatureItem | ||
90 | name={intl.formatMessage(feature)} | ||
91 | className={featureClassName} | ||
92 | /> | ||
93 | ))} | ||
96 | </ul> | 94 | </ul> |
97 | ); | 95 | ); |
98 | } | 96 | } |
99 | } | 97 | } |
100 | 98 | ||
101 | export default FeatureList; | 99 | export default injectIntl(FeatureList); |
diff --git a/src/components/ui/FullscreenLoader/index.js b/src/components/ui/FullscreenLoader/index.js index 2952cd96b..ab5e2f365 100644 --- a/src/components/ui/FullscreenLoader/index.js +++ b/src/components/ui/FullscreenLoader/index.js | |||
@@ -8,7 +8,10 @@ import Loader from '../Loader'; | |||
8 | 8 | ||
9 | import styles from './styles'; | 9 | import styles from './styles'; |
10 | 10 | ||
11 | export default @withTheme @injectSheet(styles) @observer class FullscreenLoader extends Component { | 11 | @withTheme |
12 | @injectSheet(styles) | ||
13 | @observer | ||
14 | class FullscreenLoader extends Component { | ||
12 | static propTypes = { | 15 | static propTypes = { |
13 | className: PropTypes.string, | 16 | className: PropTypes.string, |
14 | title: PropTypes.string.isRequired, | 17 | title: PropTypes.string.isRequired, |
@@ -25,14 +28,8 @@ export default @withTheme @injectSheet(styles) @observer class FullscreenLoader | |||
25 | }; | 28 | }; |
26 | 29 | ||
27 | render() { | 30 | render() { |
28 | const { | 31 | const { classes, title, children, spinnerColor, className, theme } = |
29 | classes, | 32 | this.props; |
30 | title, | ||
31 | children, | ||
32 | spinnerColor, | ||
33 | className, | ||
34 | theme, | ||
35 | } = this.props; | ||
36 | 33 | ||
37 | return ( | 34 | return ( |
38 | <div className={classes.wrapper}> | 35 | <div className={classes.wrapper}> |
@@ -44,13 +41,11 @@ export default @withTheme @injectSheet(styles) @observer class FullscreenLoader | |||
44 | > | 41 | > |
45 | <h1 className={classes.title}>{title}</h1> | 42 | <h1 className={classes.title}>{title}</h1> |
46 | <Loader color={spinnerColor || theme.colorFullscreenLoaderSpinner} /> | 43 | <Loader color={spinnerColor || theme.colorFullscreenLoaderSpinner} /> |
47 | {children && ( | 44 | {children && <div className={classes.content}>{children}</div>} |
48 | <div className={classes.content}> | ||
49 | {children} | ||
50 | </div> | ||
51 | )} | ||
52 | </div> | 45 | </div> |
53 | </div> | 46 | </div> |
54 | ); | 47 | ); |
55 | } | 48 | } |
56 | } | 49 | } |
50 | |||
51 | export default FullscreenLoader; | ||
diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js index bb4ea0565..8ea31ca40 100644 --- a/src/components/ui/ImageUpload.js +++ b/src/components/ui/ImageUpload.js | |||
@@ -6,7 +6,8 @@ import classnames from 'classnames'; | |||
6 | import Dropzone from 'react-dropzone'; | 6 | import Dropzone from 'react-dropzone'; |
7 | import { isWindows } from '../../environment'; | 7 | import { isWindows } from '../../environment'; |
8 | 8 | ||
9 | export default @observer class ImageUpload extends Component { | 9 | @observer |
10 | class ImageUpload extends Component { | ||
10 | static propTypes = { | 11 | static propTypes = { |
11 | field: PropTypes.instanceOf(Field).isRequired, | 12 | field: PropTypes.instanceOf(Field).isRequired, |
12 | className: PropTypes.string, | 13 | className: PropTypes.string, |
@@ -29,7 +30,7 @@ export default @observer class ImageUpload extends Component { | |||
29 | onDrop(acceptedFiles) { | 30 | onDrop(acceptedFiles) { |
30 | const { field } = this.props; | 31 | const { field } = this.props; |
31 | 32 | ||
32 | acceptedFiles.forEach((file) => { | 33 | acceptedFiles.forEach(file => { |
33 | const imgPath = isWindows ? file.path.replace(/\\/g, '/') : file.path; | 34 | const imgPath = isWindows ? file.path.replace(/\\/g, '/') : file.path; |
34 | this.setState({ | 35 | this.setState({ |
35 | path: imgPath, | 36 | path: imgPath, |
@@ -42,9 +43,7 @@ export default @observer class ImageUpload extends Component { | |||
42 | } | 43 | } |
43 | 44 | ||
44 | render() { | 45 | render() { |
45 | const { | 46 | const { field, className, multiple, textDelete, textUpload } = this.props; |
46 | field, className, multiple, textDelete, textUpload, | ||
47 | } = this.props; | ||
48 | 47 | ||
49 | const cssClasses = classnames({ | 48 | const cssClasses = classnames({ |
50 | 'image-upload__dropzone': true, | 49 | 'image-upload__dropzone': true, |
@@ -86,7 +85,7 @@ export default @observer class ImageUpload extends Component { | |||
86 | </> | 85 | </> |
87 | ) : ( | 86 | ) : ( |
88 | <Dropzone | 87 | <Dropzone |
89 | ref={(node) => { | 88 | ref={node => { |
90 | this.dropzoneRef = node; | 89 | this.dropzoneRef = node; |
91 | }} | 90 | }} |
92 | onDrop={this.onDrop.bind(this)} | 91 | onDrop={this.onDrop.bind(this)} |
@@ -107,3 +106,5 @@ export default @observer class ImageUpload extends Component { | |||
107 | ); | 106 | ); |
108 | } | 107 | } |
109 | } | 108 | } |
109 | |||
110 | export default ImageUpload; | ||
diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js index bd2af2296..f5cbad48b 100644 --- a/src/components/ui/InfoBar.js +++ b/src/components/ui/InfoBar.js | |||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import classnames from 'classnames'; | 4 | import classnames from 'classnames'; |
5 | import Loader from 'react-loader'; | 5 | import Loader from 'react-loader'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | // import { oneOrManyChildElements } from '../../prop-types'; | 8 | // import { oneOrManyChildElements } from '../../prop-types'; |
9 | import Appear from './effects/Appear'; | 9 | import Appear from './effects/Appear'; |
@@ -11,11 +11,10 @@ import Appear from './effects/Appear'; | |||
11 | const messages = defineMessages({ | 11 | const messages = defineMessages({ |
12 | hide: { | 12 | hide: { |
13 | id: 'infobar.hide', | 13 | id: 'infobar.hide', |
14 | defaultMessage: '!!!Hide', | 14 | defaultMessage: 'Hide', |
15 | }, | 15 | }, |
16 | }); | 16 | }); |
17 | 17 | ||
18 | export default | ||
19 | @observer | 18 | @observer |
20 | class InfoBar extends Component { | 19 | class InfoBar extends Component { |
21 | static propTypes = { | 20 | static propTypes = { |
@@ -42,10 +41,6 @@ class InfoBar extends Component { | |||
42 | onHide: () => null, | 41 | onHide: () => null, |
43 | }; | 42 | }; |
44 | 43 | ||
45 | static contextTypes = { | ||
46 | intl: intlShape, | ||
47 | }; | ||
48 | |||
49 | render() { | 44 | render() { |
50 | const { | 45 | const { |
51 | children, | 46 | children, |
@@ -59,7 +54,7 @@ class InfoBar extends Component { | |||
59 | onHide, | 54 | onHide, |
60 | } = this.props; | 55 | } = this.props; |
61 | 56 | ||
62 | const { intl } = this.context; | 57 | const { intl } = this.props; |
63 | 58 | ||
64 | let transitionName = 'slideUp'; | 59 | let transitionName = 'slideUp'; |
65 | if (position === 'top') { | 60 | if (position === 'top') { |
@@ -103,3 +98,5 @@ class InfoBar extends Component { | |||
103 | ); | 98 | ); |
104 | } | 99 | } |
105 | } | 100 | } |
101 | |||
102 | export default injectIntl(InfoBar); | ||
diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js index 73b48b957..13ae2303b 100644 --- a/src/components/ui/Infobox.js +++ b/src/components/ui/Infobox.js | |||
@@ -3,16 +3,15 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import classnames from 'classnames'; | 4 | import classnames from 'classnames'; |
5 | import Loader from 'react-loader'; | 5 | import Loader from 'react-loader'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | const messages = defineMessages({ | 8 | const messages = defineMessages({ |
9 | dismiss: { | 9 | dismiss: { |
10 | id: 'infobox.dismiss', | 10 | id: 'infobox.dismiss', |
11 | defaultMessage: '!!!Dismiss', | 11 | defaultMessage: 'Dismiss', |
12 | }, | 12 | }, |
13 | }); | 13 | }); |
14 | 14 | ||
15 | export default | ||
16 | @observer | 15 | @observer |
17 | class Infobox extends Component { | 16 | class Infobox extends Component { |
18 | static propTypes = { | 17 | static propTypes = { |
@@ -38,10 +37,6 @@ class Infobox extends Component { | |||
38 | onSeen: () => null, | 37 | onSeen: () => null, |
39 | }; | 38 | }; |
40 | 39 | ||
41 | static contextTypes = { | ||
42 | intl: intlShape, | ||
43 | }; | ||
44 | |||
45 | state = { | 40 | state = { |
46 | dismissed: false, | 41 | dismissed: false, |
47 | }; | 42 | }; |
@@ -63,7 +58,7 @@ class Infobox extends Component { | |||
63 | onDismiss, | 58 | onDismiss, |
64 | } = this.props; | 59 | } = this.props; |
65 | 60 | ||
66 | const { intl } = this.context; | 61 | const { intl } = this.props; |
67 | 62 | ||
68 | if (this.state.dismissed) { | 63 | if (this.state.dismissed) { |
69 | return null; | 64 | return null; |
@@ -106,3 +101,5 @@ class Infobox extends Component { | |||
106 | ); | 101 | ); |
107 | } | 102 | } |
108 | } | 103 | } |
104 | |||
105 | export default injectIntl(Infobox); | ||
diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js index 7417fef1c..335367f03 100644 --- a/src/components/ui/Input.js +++ b/src/components/ui/Input.js | |||
@@ -3,18 +3,17 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { Field } from 'mobx-react-form'; | 4 | import { Field } from 'mobx-react-form'; |
5 | import classnames from 'classnames'; | 5 | import classnames from 'classnames'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers'; | 8 | import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers'; |
9 | 9 | ||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | passwordToggle: { | 11 | passwordToggle: { |
12 | id: 'settings.app.form.passwordToggle', | 12 | id: 'settings.app.form.passwordToggle', |
13 | defaultMessage: '!!!Password toggle', | 13 | defaultMessage: 'Password toggle', |
14 | }, | 14 | }, |
15 | }); | 15 | }); |
16 | 16 | ||
17 | export default | ||
18 | @observer | 17 | @observer |
19 | class Input extends Component { | 18 | class Input extends Component { |
20 | static propTypes = { | 19 | static propTypes = { |
@@ -38,10 +37,6 @@ class Input extends Component { | |||
38 | suffix: '', | 37 | suffix: '', |
39 | }; | 38 | }; |
40 | 39 | ||
41 | static contextTypes = { | ||
42 | intl: intlShape, | ||
43 | }; | ||
44 | |||
45 | state = { | 40 | state = { |
46 | showPassword: false, | 41 | showPassword: false, |
47 | passwordScore: 0, | 42 | passwordScore: 0, |
@@ -82,7 +77,7 @@ class Input extends Component { | |||
82 | 77 | ||
83 | const { passwordScore } = this.state; | 78 | const { passwordScore } = this.state; |
84 | 79 | ||
85 | const { intl } = this.context; | 80 | const { intl } = this.props; |
86 | 81 | ||
87 | let { type } = field; | 82 | let { type } = field; |
88 | if (type === 'password' && this.state.showPassword) { | 83 | if (type === 'password' && this.state.showPassword) { |
@@ -106,10 +101,10 @@ class Input extends Component { | |||
106 | name={field.name} | 101 | name={field.name} |
107 | value={field.value} | 102 | value={field.value} |
108 | placeholder={field.placeholder} | 103 | placeholder={field.placeholder} |
109 | onChange={(e) => this.onChange(e)} | 104 | onChange={e => this.onChange(e)} |
110 | onBlur={field.onBlur} | 105 | onBlur={field.onBlur} |
111 | onFocus={field.onFocus} | 106 | onFocus={field.onFocus} |
112 | ref={(element) => { | 107 | ref={element => { |
113 | this.inputElement = element; | 108 | this.inputElement = element; |
114 | }} | 109 | }} |
115 | disabled={field.disabled} | 110 | disabled={field.disabled} |
@@ -124,9 +119,11 @@ class Input extends Component { | |||
124 | 'mdi-eye': !this.state.showPassword, | 119 | 'mdi-eye': !this.state.showPassword, |
125 | 'mdi-eye-off': this.state.showPassword, | 120 | 'mdi-eye-off': this.state.showPassword, |
126 | })} | 121 | })} |
127 | onClick={() => this.setState((prevState) => ({ | 122 | onClick={() => |
128 | showPassword: !prevState.showPassword, | 123 | this.setState(prevState => ({ |
129 | }))} | 124 | showPassword: !prevState.showPassword, |
125 | })) | ||
126 | } | ||
130 | tabIndex={-1} | 127 | tabIndex={-1} |
131 | aria-label={intl.formatMessage(messages.passwordToggle)} | 128 | aria-label={intl.formatMessage(messages.passwordToggle)} |
132 | /> | 129 | /> |
@@ -154,3 +151,5 @@ class Input extends Component { | |||
154 | ); | 151 | ); |
155 | } | 152 | } |
156 | } | 153 | } |
154 | |||
155 | export default injectIntl(Input); | ||
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js index 003211e5c..94db3f842 100644 --- a/src/components/ui/Link.js +++ b/src/components/ui/Link.js | |||
@@ -9,7 +9,9 @@ import { matchRoute } from '../../helpers/routing-helpers'; | |||
9 | import { openExternalUrl } from '../../helpers/url-helpers'; | 9 | import { openExternalUrl } from '../../helpers/url-helpers'; |
10 | 10 | ||
11 | // TODO: create container component for this component | 11 | // TODO: create container component for this component |
12 | export default @inject('stores') @observer class Link extends Component { | 12 | @inject('stores') |
13 | @observer | ||
14 | class Link extends Component { | ||
13 | onClick(e) { | 15 | onClick(e) { |
14 | if (this.props.disabled) { | 16 | if (this.props.disabled) { |
15 | e.preventDefault(); | 17 | e.preventDefault(); |
@@ -50,7 +52,7 @@ export default @inject('stores') @observer class Link extends Component { | |||
50 | href={router.history.createHref(to)} | 52 | href={router.history.createHref(to)} |
51 | className={linkClasses} | 53 | className={linkClasses} |
52 | style={style} | 54 | style={style} |
53 | onClick={(e) => this.onClick(e)} | 55 | onClick={e => this.onClick(e)} |
54 | > | 56 | > |
55 | {children} | 57 | {children} |
56 | </a> | 58 | </a> |
@@ -62,10 +64,8 @@ Link.wrappedComponent.propTypes = { | |||
62 | stores: PropTypes.shape({ | 64 | stores: PropTypes.shape({ |
63 | router: PropTypes.instanceOf(RouterStore).isRequired, | 65 | router: PropTypes.instanceOf(RouterStore).isRequired, |
64 | }).isRequired, | 66 | }).isRequired, |
65 | children: PropTypes.oneOfType([ | 67 | children: PropTypes.oneOfType([oneOrManyChildElements, PropTypes.string]) |
66 | oneOrManyChildElements, | 68 | .isRequired, |
67 | PropTypes.string, | ||
68 | ]).isRequired, | ||
69 | to: PropTypes.string.isRequired, | 69 | to: PropTypes.string.isRequired, |
70 | className: PropTypes.string, | 70 | className: PropTypes.string, |
71 | activeClassName: PropTypes.string, | 71 | activeClassName: PropTypes.string, |
@@ -83,3 +83,5 @@ Link.wrappedComponent.defaultProps = { | |||
83 | target: '', | 83 | target: '', |
84 | style: {}, | 84 | style: {}, |
85 | }; | 85 | }; |
86 | |||
87 | export default Link; | ||
diff --git a/src/components/ui/Loader.js b/src/components/ui/Loader.js index 4d7113aa1..46c1390bf 100644 --- a/src/components/ui/Loader.js +++ b/src/components/ui/Loader.js | |||
@@ -5,7 +5,9 @@ import Loader from 'react-loader'; | |||
5 | 5 | ||
6 | import { oneOrManyChildElements } from '../../prop-types'; | 6 | import { oneOrManyChildElements } from '../../prop-types'; |
7 | 7 | ||
8 | export default @inject('stores') @observer class LoaderComponent extends Component { | 8 | @inject('stores') |
9 | @observer | ||
10 | class LoaderComponent extends Component { | ||
9 | static propTypes = { | 11 | static propTypes = { |
10 | children: oneOrManyChildElements, | 12 | children: oneOrManyChildElements, |
11 | loaded: PropTypes.bool, | 13 | loaded: PropTypes.bool, |
@@ -28,13 +30,12 @@ export default @inject('stores') @observer class LoaderComponent extends Compone | |||
28 | }; | 30 | }; |
29 | 31 | ||
30 | render() { | 32 | render() { |
31 | const { | 33 | const { children, loaded, className } = this.props; |
32 | children, | ||
33 | loaded, | ||
34 | className, | ||
35 | } = this.props; | ||
36 | 34 | ||
37 | const color = this.props.color !== 'ACCENT' ? this.props.color : this.props.stores.settings.app.accentColor; | 35 | const color = |
36 | this.props.color !== 'ACCENT' | ||
37 | ? this.props.color | ||
38 | : this.props.stores.settings.app.accentColor; | ||
38 | 39 | ||
39 | return ( | 40 | return ( |
40 | <Loader | 41 | <Loader |
@@ -51,3 +52,5 @@ export default @inject('stores') @observer class LoaderComponent extends Compone | |||
51 | ); | 52 | ); |
52 | } | 53 | } |
53 | } | 54 | } |
55 | |||
56 | export default LoaderComponent; | ||
diff --git a/src/components/ui/Modal/index.js b/src/components/ui/Modal/index.js index a9fa0cd1b..9e6830b0c 100644 --- a/src/components/ui/Modal/index.js +++ b/src/components/ui/Modal/index.js | |||
@@ -10,7 +10,8 @@ import styles from './styles'; | |||
10 | 10 | ||
11 | // ReactModal.setAppElement('#root'); | 11 | // ReactModal.setAppElement('#root'); |
12 | 12 | ||
13 | export default @injectCSS(styles) class Modal extends Component { | 13 | @injectCSS(styles) |
14 | class Modal extends Component { | ||
14 | static propTypes = { | 15 | static propTypes = { |
15 | children: PropTypes.node.isRequired, | 16 | children: PropTypes.node.isRequired, |
16 | className: PropTypes.string, | 17 | className: PropTypes.string, |
@@ -20,14 +21,14 @@ export default @injectCSS(styles) class Modal extends Component { | |||
20 | close: PropTypes.func.isRequired, | 21 | close: PropTypes.func.isRequired, |
21 | shouldCloseOnOverlayClick: PropTypes.bool, | 22 | shouldCloseOnOverlayClick: PropTypes.bool, |
22 | showClose: PropTypes.bool, | 23 | showClose: PropTypes.bool, |
23 | } | 24 | }; |
24 | 25 | ||
25 | static defaultProps = { | 26 | static defaultProps = { |
26 | className: null, | 27 | className: null, |
27 | portal: 'modal-portal', | 28 | portal: 'modal-portal', |
28 | shouldCloseOnOverlayClick: false, | 29 | shouldCloseOnOverlayClick: false, |
29 | showClose: true, | 30 | showClose: true, |
30 | } | 31 | }; |
31 | 32 | ||
32 | render() { | 33 | render() { |
33 | const { | 34 | const { |
@@ -56,18 +57,14 @@ export default @injectCSS(styles) class Modal extends Component { | |||
56 | appElement={document.getElementById('root')} | 57 | appElement={document.getElementById('root')} |
57 | > | 58 | > |
58 | {showClose && close && ( | 59 | {showClose && close && ( |
59 | <button | 60 | <button type="button" className={classes.close} onClick={close}> |
60 | type="button" | ||
61 | className={classes.close} | ||
62 | onClick={close} | ||
63 | > | ||
64 | <Icon icon={mdiClose} size={1.5} /> | 61 | <Icon icon={mdiClose} size={1.5} /> |
65 | </button> | 62 | </button> |
66 | )} | 63 | )} |
67 | <div className={classes.content}> | 64 | <div className={classes.content}>{children}</div> |
68 | {children} | ||
69 | </div> | ||
70 | </ReactModal> | 65 | </ReactModal> |
71 | ); | 66 | ); |
72 | } | 67 | } |
73 | } | 68 | } |
69 | |||
70 | export default Modal; | ||
diff --git a/src/components/ui/Radio.js b/src/components/ui/Radio.js index e77714eb7..65a777ff1 100644 --- a/src/components/ui/Radio.js +++ b/src/components/ui/Radio.js | |||
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | import { Field } from 'mobx-react-form'; | 4 | import { Field } from 'mobx-react-form'; |
5 | import classnames from 'classnames'; | 5 | import classnames from 'classnames'; |
6 | 6 | ||
7 | export default @observer class Radio extends Component { | 7 | @observer |
8 | class Radio extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | field: PropTypes.instanceOf(Field).isRequired, | 10 | field: PropTypes.instanceOf(Field).isRequired, |
10 | className: PropTypes.string, | 11 | className: PropTypes.string, |
@@ -31,11 +32,7 @@ export default @observer class Radio extends Component { | |||
31 | } | 32 | } |
32 | 33 | ||
33 | render() { | 34 | render() { |
34 | const { | 35 | const { field, className, showLabel } = this.props; |
35 | field, | ||
36 | className, | ||
37 | showLabel, | ||
38 | } = this.props; | ||
39 | 36 | ||
40 | return ( | 37 | return ( |
41 | <div | 38 | <div |
@@ -46,15 +43,12 @@ export default @observer class Radio extends Component { | |||
46 | })} | 43 | })} |
47 | > | 44 | > |
48 | {field.label && showLabel && ( | 45 | {field.label && showLabel && ( |
49 | <label | 46 | <label className="franz-form__label" htmlFor={field.name}> |
50 | className="franz-form__label" | ||
51 | htmlFor={field.name} | ||
52 | > | ||
53 | {field.label} | 47 | {field.label} |
54 | </label> | 48 | </label> |
55 | )} | 49 | )} |
56 | <div className="franz-form__radio-wrapper"> | 50 | <div className="franz-form__radio-wrapper"> |
57 | {field.options.map((type) => ( | 51 | {field.options.map(type => ( |
58 | <label | 52 | <label |
59 | key={type.value} | 53 | key={type.value} |
60 | htmlFor={`${field.id}-${type.value}`} | 54 | htmlFor={`${field.id}-${type.value}`} |
@@ -75,14 +69,10 @@ export default @observer class Radio extends Component { | |||
75 | </label> | 69 | </label> |
76 | ))} | 70 | ))} |
77 | </div> | 71 | </div> |
78 | {field.error && ( | 72 | {field.error && <div className="franz-form__error">{field.error}</div>} |
79 | <div | ||
80 | className="franz-form__error" | ||
81 | > | ||
82 | {field.error} | ||
83 | </div> | ||
84 | )} | ||
85 | </div> | 73 | </div> |
86 | ); | 74 | ); |
87 | } | 75 | } |
88 | } | 76 | } |
77 | |||
78 | export default Radio; | ||
diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js index 0b25734dd..2d760beab 100644 --- a/src/components/ui/SearchInput.js +++ b/src/components/ui/SearchInput.js | |||
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | import classnames from 'classnames'; | 4 | import classnames from 'classnames'; |
5 | import { debounce } from 'lodash'; | 5 | import { debounce } from 'lodash'; |
6 | 6 | ||
7 | export default @observer class SearchInput extends Component { | 7 | @observer |
8 | class SearchInput extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | value: PropTypes.string, | 10 | value: PropTypes.string, |
10 | placeholder: PropTypes.string, | 11 | placeholder: PropTypes.string, |
@@ -27,7 +28,7 @@ export default @observer class SearchInput extends Component { | |||
27 | onChange: () => null, | 28 | onChange: () => null, |
28 | onReset: () => null, | 29 | onReset: () => null, |
29 | autoFocus: false, | 30 | autoFocus: false, |
30 | } | 31 | }; |
31 | 32 | ||
32 | input = null; | 33 | input = null; |
33 | 34 | ||
@@ -38,7 +39,10 @@ export default @observer class SearchInput extends Component { | |||
38 | value: props.value, | 39 | value: props.value, |
39 | }; | 40 | }; |
40 | 41 | ||
41 | this.throttledOnChange = debounce(this.throttledOnChange, this.props.throttleDelay); | 42 | this.throttledOnChange = debounce( |
43 | this.throttledOnChange, | ||
44 | this.props.throttleDelay, | ||
45 | ); | ||
42 | } | 46 | } |
43 | 47 | ||
44 | componentDidMount() { | 48 | componentDidMount() { |
@@ -80,24 +84,18 @@ export default @observer class SearchInput extends Component { | |||
80 | const { value } = this.state; | 84 | const { value } = this.state; |
81 | 85 | ||
82 | return ( | 86 | return ( |
83 | <div | 87 | <div className={classnames([className, 'search-input'])}> |
84 | className={classnames([ | 88 | <label htmlFor={name} className="mdi mdi-magnify"> |
85 | className, | ||
86 | 'search-input', | ||
87 | ])} | ||
88 | > | ||
89 | <label | ||
90 | htmlFor={name} | ||
91 | className="mdi mdi-magnify" | ||
92 | > | ||
93 | <input | 89 | <input |
94 | name={name} | 90 | name={name} |
95 | id={name} | 91 | id={name} |
96 | type="text" | 92 | type="text" |
97 | placeholder={placeholder} | 93 | placeholder={placeholder} |
98 | value={value} | 94 | value={value} |
99 | onChange={(e) => this.onChange(e)} | 95 | onChange={e => this.onChange(e)} |
100 | ref={(ref) => { this.input = ref; }} | 96 | ref={ref => { |
97 | this.input = ref; | ||
98 | }} | ||
101 | /> | 99 | /> |
102 | </label> | 100 | </label> |
103 | {value.length > 0 && ( | 101 | {value.length > 0 && ( |
@@ -110,3 +108,5 @@ export default @observer class SearchInput extends Component { | |||
110 | ); | 108 | ); |
111 | } | 109 | } |
112 | } | 110 | } |
111 | |||
112 | export default SearchInput; | ||
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js index e7a5eafa8..15b4c28e7 100644 --- a/src/components/ui/Select.js +++ b/src/components/ui/Select.js | |||
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | import { Field } from 'mobx-react-form'; | 4 | import { Field } from 'mobx-react-form'; |
5 | import classnames from 'classnames'; | 5 | import classnames from 'classnames'; |
6 | 6 | ||
7 | export default @observer class Select extends Component { | 7 | @observer |
8 | class Select extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | field: PropTypes.instanceOf(Field).isRequired, | 10 | field: PropTypes.instanceOf(Field).isRequired, |
10 | className: PropTypes.string, | 11 | className: PropTypes.string, |
@@ -43,13 +44,7 @@ export default @observer class Select extends Component { | |||
43 | } | 44 | } |
44 | 45 | ||
45 | render() { | 46 | render() { |
46 | const { | 47 | const { field, className, showLabel, disabled, multiple } = this.props; |
47 | field, | ||
48 | className, | ||
49 | showLabel, | ||
50 | disabled, | ||
51 | multiple, | ||
52 | } = this.props; | ||
53 | 48 | ||
54 | let selected = field.value; | 49 | let selected = field.value; |
55 | 50 | ||
@@ -74,15 +69,12 @@ export default @observer class Select extends Component { | |||
74 | })} | 69 | })} |
75 | > | 70 | > |
76 | {field.label && showLabel && ( | 71 | {field.label && showLabel && ( |
77 | <label | 72 | <label className="franz-form__label" htmlFor={field.name}> |
78 | className="franz-form__label" | ||
79 | htmlFor={field.name} | ||
80 | > | ||
81 | {field.label} | 73 | {field.label} |
82 | </label> | 74 | </label> |
83 | )} | 75 | )} |
84 | <select | 76 | <select |
85 | onChange={multiple ? (e) => this.multipleChange(e) : field.onChange} | 77 | onChange={multiple ? e => this.multipleChange(e) : field.onChange} |
86 | id={field.id} | 78 | id={field.id} |
87 | defaultValue={selected} | 79 | defaultValue={selected} |
88 | className="franz-form__select" | 80 | className="franz-form__select" |
@@ -90,7 +82,7 @@ export default @observer class Select extends Component { | |||
90 | multiple={multiple} | 82 | multiple={multiple} |
91 | ref={this.element} | 83 | ref={this.element} |
92 | > | 84 | > |
93 | {field.options.map((type) => ( | 85 | {field.options.map(type => ( |
94 | <option | 86 | <option |
95 | key={type.value} | 87 | key={type.value} |
96 | value={type.value} | 88 | value={type.value} |
@@ -100,14 +92,10 @@ export default @observer class Select extends Component { | |||
100 | </option> | 92 | </option> |
101 | ))} | 93 | ))} |
102 | </select> | 94 | </select> |
103 | {field.error && ( | 95 | {field.error && <div className="franz-form__error">{field.error}</div>} |
104 | <div | ||
105 | className="franz-form__error" | ||
106 | > | ||
107 | {field.error} | ||
108 | </div> | ||
109 | )} | ||
110 | </div> | 96 | </div> |
111 | ); | 97 | ); |
112 | } | 98 | } |
113 | } | 99 | } |
100 | |||
101 | export default Select; | ||
diff --git a/src/components/ui/Slider.js b/src/components/ui/Slider.js index f344449a0..6f17eae00 100644 --- a/src/components/ui/Slider.js +++ b/src/components/ui/Slider.js | |||
@@ -4,62 +4,64 @@ import { observer } from 'mobx-react'; | |||
4 | import classnames from 'classnames'; | 4 | import classnames from 'classnames'; |
5 | import { Field } from 'mobx-react-form'; | 5 | import { Field } from 'mobx-react-form'; |
6 | 6 | ||
7 | export default @observer class Slider extends Component { | 7 | @observer |
8 | static propTypes = { | 8 | class Slider extends Component { |
9 | field: PropTypes.instanceOf(Field).isRequired, | 9 | static propTypes = { |
10 | className: PropTypes.string, | 10 | field: PropTypes.instanceOf(Field).isRequired, |
11 | showLabel: PropTypes.bool, | 11 | className: PropTypes.string, |
12 | disabled: PropTypes.bool, | 12 | showLabel: PropTypes.bool, |
13 | }; | 13 | disabled: PropTypes.bool, |
14 | }; | ||
14 | 15 | ||
15 | static defaultProps = { | 16 | static defaultProps = { |
16 | className: '', | 17 | className: '', |
17 | showLabel: true, | 18 | showLabel: true, |
18 | disabled: false, | 19 | disabled: false, |
19 | }; | 20 | }; |
20 | 21 | ||
21 | onChange(e) { | 22 | onChange(e) { |
22 | const { field } = this.props; | 23 | const { field } = this.props; |
23 | 24 | ||
24 | field.onChange(e); | 25 | field.onChange(e); |
25 | } | 26 | } |
26 | |||
27 | render() { | ||
28 | const { | ||
29 | field, | ||
30 | className, | ||
31 | showLabel, | ||
32 | disabled, | ||
33 | } = this.props; | ||
34 | 27 | ||
35 | if (field.value === '' && field.default !== '') { | 28 | render() { |
36 | field.value = field.default; | 29 | const { field, className, showLabel, disabled } = this.props; |
37 | } | ||
38 | 30 | ||
39 | return ( | 31 | if (field.value === '' && field.default !== '') { |
40 | <div | 32 | field.value = field.default; |
41 | className={classnames([ | 33 | } |
42 | 'franz-form__field', | ||
43 | 'franz-form__slider-wrapper', | ||
44 | className, | ||
45 | ])} | ||
46 | > | ||
47 | <div className="slider-container"> | ||
48 | <input | ||
49 | className="slider" | ||
50 | type="range" | ||
51 | id={field.id} | ||
52 | name={field.name} | ||
53 | value={field.value} | ||
54 | min="1" | ||
55 | max="100" | ||
56 | onChange={(e) => (!disabled ? this.onChange(e) : null)} | ||
57 | /> | ||
58 | </div> | ||
59 | 34 | ||
60 | {field.error && <div className={field.error}>{field.error}</div>} | 35 | return ( |
61 | {field.label && showLabel && <label className="franz-form__label" htmlFor={field.id}>{field.label}</label>} | 36 | <div |
37 | className={classnames([ | ||
38 | 'franz-form__field', | ||
39 | 'franz-form__slider-wrapper', | ||
40 | className, | ||
41 | ])} | ||
42 | > | ||
43 | <div className="slider-container"> | ||
44 | <input | ||
45 | className="slider" | ||
46 | type="range" | ||
47 | id={field.id} | ||
48 | name={field.name} | ||
49 | value={field.value} | ||
50 | min="1" | ||
51 | max="100" | ||
52 | onChange={e => (!disabled ? this.onChange(e) : null)} | ||
53 | /> | ||
62 | </div> | 54 | </div> |
63 | ); | 55 | |
64 | } | 56 | {field.error && <div className={field.error}>{field.error}</div>} |
57 | {field.label && showLabel && ( | ||
58 | <label className="franz-form__label" htmlFor={field.id}> | ||
59 | {field.label} | ||
60 | </label> | ||
61 | )} | ||
62 | </div> | ||
63 | ); | ||
64 | } | ||
65 | } | 65 | } |
66 | |||
67 | export default Slider; | ||
diff --git a/src/components/ui/StatusBarTargetUrl.js b/src/components/ui/StatusBarTargetUrl.js index 6fc50fe5c..ff4e8c795 100644 --- a/src/components/ui/StatusBarTargetUrl.js +++ b/src/components/ui/StatusBarTargetUrl.js | |||
@@ -5,7 +5,8 @@ import classnames from 'classnames'; | |||
5 | 5 | ||
6 | import Appear from './effects/Appear'; | 6 | import Appear from './effects/Appear'; |
7 | 7 | ||
8 | export default @observer class StatusBarTargetUrl extends Component { | 8 | @observer |
9 | class StatusBarTargetUrl extends Component { | ||
9 | static propTypes = { | 10 | static propTypes = { |
10 | className: PropTypes.string, | 11 | className: PropTypes.string, |
11 | text: PropTypes.string, | 12 | text: PropTypes.string, |
@@ -17,10 +18,7 @@ export default @observer class StatusBarTargetUrl extends Component { | |||
17 | }; | 18 | }; |
18 | 19 | ||
19 | render() { | 20 | render() { |
20 | const { | 21 | const { className, text } = this.props; |
21 | className, | ||
22 | text, | ||
23 | } = this.props; | ||
24 | 22 | ||
25 | return ( | 23 | return ( |
26 | <Appear | 24 | <Appear |
@@ -29,10 +27,10 @@ export default @observer class StatusBarTargetUrl extends Component { | |||
29 | [`${className}`]: true, | 27 | [`${className}`]: true, |
30 | })} | 28 | })} |
31 | > | 29 | > |
32 | <div className="status-bar-target-url__content"> | 30 | <div className="status-bar-target-url__content">{text}</div> |
33 | {text} | ||
34 | </div> | ||
35 | </Appear> | 31 | </Appear> |
36 | ); | 32 | ); |
37 | } | 33 | } |
38 | } | 34 | } |
35 | |||
36 | export default StatusBarTargetUrl; | ||
diff --git a/src/components/ui/Tabs/Tabs.js b/src/components/ui/Tabs/Tabs.js index 56c76f215..195398708 100644 --- a/src/components/ui/Tabs/Tabs.js +++ b/src/components/ui/Tabs/Tabs.js | |||
@@ -5,7 +5,6 @@ import classnames from 'classnames'; | |||
5 | 5 | ||
6 | import { oneOrManyChildElements } from '../../../prop-types'; | 6 | import { oneOrManyChildElements } from '../../../prop-types'; |
7 | 7 | ||
8 | export default | ||
9 | @observer | 8 | @observer |
10 | class Tab extends Component { | 9 | class Tab extends Component { |
11 | constructor(props) { | 10 | constructor(props) { |
@@ -28,7 +27,7 @@ class Tab extends Component { | |||
28 | 27 | ||
29 | render() { | 28 | render() { |
30 | const { children: childElements } = this.props; | 29 | const { children: childElements } = this.props; |
31 | const children = childElements.filter((c) => !!c); | 30 | const children = childElements.filter(c => !!c); |
32 | 31 | ||
33 | if (children.length === 1) { | 32 | if (children.length === 1) { |
34 | return <div>{children}</div>; | 33 | return <div>{children}</div>; |
@@ -69,3 +68,5 @@ class Tab extends Component { | |||
69 | ); | 68 | ); |
70 | } | 69 | } |
71 | } | 70 | } |
71 | |||
72 | export default Tab; | ||
diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js index 14330e5c7..bd7bc242d 100644 --- a/src/components/ui/Toggle.js +++ b/src/components/ui/Toggle.js | |||
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | import classnames from 'classnames'; | 4 | import classnames from 'classnames'; |
5 | import { Field } from 'mobx-react-form'; | 5 | import { Field } from 'mobx-react-form'; |
6 | 6 | ||
7 | export default @observer class Toggle extends Component { | 7 | @observer |
8 | class Toggle extends Component { | ||
8 | static propTypes = { | 9 | static propTypes = { |
9 | field: PropTypes.instanceOf(Field).isRequired, | 10 | field: PropTypes.instanceOf(Field).isRequired, |
10 | className: PropTypes.string, | 11 | className: PropTypes.string, |
@@ -25,12 +26,7 @@ export default @observer class Toggle extends Component { | |||
25 | } | 26 | } |
26 | 27 | ||
27 | render() { | 28 | render() { |
28 | const { | 29 | const { field, className, showLabel, disabled } = this.props; |
29 | field, | ||
30 | className, | ||
31 | showLabel, | ||
32 | disabled, | ||
33 | } = this.props; | ||
34 | 30 | ||
35 | if (field.value === '' && field.default !== '') { | 31 | if (field.value === '' && field.default !== '') { |
36 | field.value = field.default; | 32 | field.value = field.default; |
@@ -59,12 +55,18 @@ export default @observer class Toggle extends Component { | |||
59 | name={field.name} | 55 | name={field.name} |
60 | value={field.name} | 56 | value={field.name} |
61 | checked={field.value} | 57 | checked={field.value} |
62 | onChange={(e) => (!disabled ? this.onChange(e) : null)} | 58 | onChange={e => (!disabled ? this.onChange(e) : null)} |
63 | /> | 59 | /> |
64 | </label> | 60 | </label> |
65 | {field.error && <div className={field.error}>{field.error}</div>} | 61 | {field.error && <div className={field.error}>{field.error}</div>} |
66 | {field.label && showLabel && <label className="franz-form__label" htmlFor={field.id}>{field.label}</label>} | 62 | {field.label && showLabel && ( |
63 | <label className="franz-form__label" htmlFor={field.id}> | ||
64 | {field.label} | ||
65 | </label> | ||
66 | )} | ||
67 | </div> | 67 | </div> |
68 | ); | 68 | ); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | |||
72 | export default Toggle; | ||
diff --git a/src/components/ui/ToggleRaw.js b/src/components/ui/ToggleRaw.js index 4700127d4..1fde879ac 100644 --- a/src/components/ui/ToggleRaw.js +++ b/src/components/ui/ToggleRaw.js | |||
@@ -6,7 +6,8 @@ import PropTypes from 'prop-types'; | |||
6 | import { observer } from 'mobx-react'; | 6 | import { observer } from 'mobx-react'; |
7 | import classnames from 'classnames'; | 7 | import classnames from 'classnames'; |
8 | 8 | ||
9 | export default @observer class ToggleRaw extends Component { | 9 | @observer |
10 | class ToggleRaw extends Component { | ||
10 | static propTypes = { | 11 | static propTypes = { |
11 | onChange: PropTypes.func.isRequired, | 12 | onChange: PropTypes.func.isRequired, |
12 | field: PropTypes.shape({ | 13 | field: PropTypes.shape({ |
@@ -34,12 +35,7 @@ export default @observer class ToggleRaw extends Component { | |||
34 | } | 35 | } |
35 | 36 | ||
36 | render() { | 37 | render() { |
37 | const { | 38 | const { field, className, showLabel, disabled } = this.props; |
38 | field, | ||
39 | className, | ||
40 | showLabel, | ||
41 | disabled, | ||
42 | } = this.props; | ||
43 | 39 | ||
44 | return ( | 40 | return ( |
45 | <div | 41 | <div |
@@ -64,12 +60,18 @@ export default @observer class ToggleRaw extends Component { | |||
64 | name={field.name} | 60 | name={field.name} |
65 | value={field.name} | 61 | value={field.name} |
66 | checked={field.value} | 62 | checked={field.value} |
67 | onChange={(e) => (!disabled ? this.onChange(e) : null)} | 63 | onChange={e => (!disabled ? this.onChange(e) : null)} |
68 | /> | 64 | /> |
69 | </label> | 65 | </label> |
70 | {field.error && <div className={field.error}>{field.error}</div>} | 66 | {field.error && <div className={field.error}>{field.error}</div>} |
71 | {field.label && showLabel && <label className="franz-form__label" htmlFor={field.id}>{field.label}</label>} | 67 | {field.label && showLabel && ( |
68 | <label className="franz-form__label" htmlFor={field.id}> | ||
69 | {field.label} | ||
70 | </label> | ||
71 | )} | ||
72 | </div> | 72 | </div> |
73 | ); | 73 | ); |
74 | } | 74 | } |
75 | } | 75 | } |
76 | |||
77 | export default ToggleRaw; | ||
diff --git a/src/components/ui/WebviewLoader/index.js b/src/components/ui/WebviewLoader/index.js index c58d69374..8f4499e7b 100644 --- a/src/components/ui/WebviewLoader/index.js +++ b/src/components/ui/WebviewLoader/index.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import FullscreenLoader from '../FullscreenLoader'; | 7 | import FullscreenLoader from '../FullscreenLoader'; |
8 | import styles from './styles'; | 8 | import styles from './styles'; |
@@ -10,23 +10,21 @@ import styles from './styles'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | loading: { | 11 | loading: { |
12 | id: 'service.webviewLoader.loading', | 12 | id: 'service.webviewLoader.loading', |
13 | defaultMessage: '!!!Loading {service}', | 13 | defaultMessage: 'Loading {service}', |
14 | }, | 14 | }, |
15 | }); | 15 | }); |
16 | 16 | ||
17 | export default @injectSheet(styles) @observer class WebviewLoader extends Component { | 17 | @injectSheet(styles) |
18 | @observer | ||
19 | class WebviewLoader extends Component { | ||
18 | static propTypes = { | 20 | static propTypes = { |
19 | name: PropTypes.string.isRequired, | 21 | name: PropTypes.string.isRequired, |
20 | classes: PropTypes.object.isRequired, | 22 | classes: PropTypes.object.isRequired, |
21 | }; | 23 | }; |
22 | 24 | ||
23 | static contextTypes = { | ||
24 | intl: intlShape, | ||
25 | }; | ||
26 | |||
27 | render() { | 25 | render() { |
28 | const { classes, name } = this.props; | 26 | const { classes, name } = this.props; |
29 | const { intl } = this.context; | 27 | const { intl } = this.props; |
30 | return ( | 28 | return ( |
31 | <FullscreenLoader | 29 | <FullscreenLoader |
32 | className={classes.component} | 30 | className={classes.component} |
@@ -35,3 +33,5 @@ export default @injectSheet(styles) @observer class WebviewLoader extends Compon | |||
35 | ); | 33 | ); |
36 | } | 34 | } |
37 | } | 35 | } |
36 | |||
37 | export default injectIntl(WebviewLoader); | ||
diff --git a/src/components/util/ErrorBoundary/index.js b/src/components/util/ErrorBoundary/index.js index 5db0db226..9c789e981 100644 --- a/src/components/util/ErrorBoundary/index.js +++ b/src/components/util/ErrorBoundary/index.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import injectSheet from 'react-jss'; | 3 | import injectSheet from 'react-jss'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import Button from '../../ui/Button'; | 6 | import Button from '../../ui/Button'; |
7 | 7 | ||
@@ -10,26 +10,23 @@ import styles from './styles'; | |||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | headline: { | 11 | headline: { |
12 | id: 'app.errorHandler.headline', | 12 | id: 'app.errorHandler.headline', |
13 | defaultMessage: '!!!Something went wrong.', | 13 | defaultMessage: 'Something went wrong.', |
14 | }, | 14 | }, |
15 | action: { | 15 | action: { |
16 | id: 'app.errorHandler.action', | 16 | id: 'app.errorHandler.action', |
17 | defaultMessage: '!!!Reload', | 17 | defaultMessage: 'Reload', |
18 | }, | 18 | }, |
19 | }); | 19 | }); |
20 | 20 | ||
21 | export default @injectSheet(styles) class ErrorBoundary extends Component { | 21 | @injectSheet(styles) |
22 | class ErrorBoundary extends Component { | ||
22 | state = { | 23 | state = { |
23 | hasError: false, | 24 | hasError: false, |
24 | } | 25 | }; |
25 | 26 | ||
26 | static propTypes = { | 27 | static propTypes = { |
27 | classes: PropTypes.object.isRequired, | 28 | classes: PropTypes.object.isRequired, |
28 | children: PropTypes.node.isRequired, | 29 | children: PropTypes.node.isRequired, |
29 | } | ||
30 | |||
31 | static contextTypes = { | ||
32 | intl: intlShape, | ||
33 | }; | 30 | }; |
34 | 31 | ||
35 | componentDidCatch() { | 32 | componentDidCatch() { |
@@ -38,7 +35,7 @@ export default @injectSheet(styles) class ErrorBoundary extends Component { | |||
38 | 35 | ||
39 | render() { | 36 | render() { |
40 | const { classes } = this.props; | 37 | const { classes } = this.props; |
41 | const { intl } = this.context; | 38 | const { intl } = this.props; |
42 | 39 | ||
43 | if (this.state.hasError) { | 40 | if (this.state.hasError) { |
44 | return ( | 41 | return ( |
@@ -58,3 +55,5 @@ export default @injectSheet(styles) class ErrorBoundary extends Component { | |||
58 | return this.props.children; | 55 | return this.props.children; |
59 | } | 56 | } |
60 | } | 57 | } |
58 | |||
59 | export default injectIntl(ErrorBoundary); | ||