aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorLibravatar kytwb <kytwb@pm.me>2021-12-16 12:02:18 +0100
committerLibravatar kytwb <kytwb@pm.me>2021-12-16 12:02:18 +0100
commit36c23f67c3783b3986b21ea85d56fc0e37941a0c (patch)
tree3c9138790d672ff84071bba8e441149c245a80e7 /src/components
parentBumped up ferdi to '5.6.3' (diff)
parentIterate on README [skip ci] (diff)
downloadferdium-app-36c23f67c3783b3986b21ea85d56fc0e37941a0c.tar.gz
ferdium-app-36c23f67c3783b3986b21ea85d56fc0e37941a0c.tar.zst
ferdium-app-36c23f67c3783b3986b21ea85d56fc0e37941a0c.zip
Merge branch 'develop' into release
# Conflicts: # package-lock.json # package.json
Diffstat (limited to 'src/components')
-rw-r--r--src/components/auth/AuthLayout.js3
-rw-r--r--src/components/auth/ChangeServer.js5
-rw-r--r--src/components/auth/Import.js3
-rw-r--r--src/components/auth/Invite.js7
-rw-r--r--src/components/auth/Locked.js10
-rw-r--r--src/components/auth/Login.js47
-rw-r--r--src/components/auth/Password.js5
-rw-r--r--src/components/auth/SetupAssistant.js8
-rw-r--r--src/components/auth/Signup.js37
-rw-r--r--src/components/auth/Welcome.js36
-rw-r--r--src/components/layout/AppLayout.js6
-rw-r--r--src/components/layout/Sidebar.js4
-rw-r--r--src/components/services/content/ConnectionLostBanner.js8
-rw-r--r--src/components/services/content/ErrorHandlers/WebviewErrorHandler.js6
-rw-r--r--src/components/services/content/ServiceDisabled.js7
-rw-r--r--src/components/services/content/ServiceView.js27
-rw-r--r--src/components/services/content/ServiceWebview.js17
-rw-r--r--src/components/services/content/Services.js16
-rw-r--r--src/components/services/content/WebviewCrashHandler.js3
-rw-r--r--src/components/services/tabs/TabBarSortableList.js3
-rw-r--r--src/components/services/tabs/TabItem.js19
-rw-r--r--src/components/services/tabs/Tabbar.js3
-rw-r--r--src/components/settings/SettingsLayout.js3
-rw-r--r--src/components/settings/account/AccountDashboard.js3
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js4
-rw-r--r--src/components/settings/recipes/RecipeItem.js3
-rw-r--r--src/components/settings/recipes/RecipesDashboard.js50
-rw-r--r--src/components/settings/services/EditServiceForm.js4
-rw-r--r--src/components/settings/services/ServiceError.js3
-rw-r--r--src/components/settings/services/ServiceItem.js3
-rw-r--r--src/components/settings/services/ServicesDashboard.js5
-rw-r--r--src/components/settings/settings/EditSettingsForm.js69
-rw-r--r--src/components/settings/supportFerdi/SupportFerdiDashboard.tsx33
-rw-r--r--src/components/settings/team/TeamDashboard.js66
-rw-r--r--src/components/settings/user/EditUserForm.js3
-rw-r--r--src/components/ui/AppLoader/index.tsx7
-rw-r--r--src/components/ui/Button.js6
-rw-r--r--src/components/ui/FAB.tsx5
-rw-r--r--src/components/ui/FullscreenLoader/index.js9
-rw-r--r--src/components/ui/ImageUpload.tsx10
-rw-r--r--src/components/ui/InfoBar.js3
-rw-r--r--src/components/ui/Infobox.js3
-rw-r--r--src/components/ui/Input.js12
-rw-r--r--src/components/ui/Link.js8
-rw-r--r--src/components/ui/Loader.tsx4
-rw-r--r--src/components/ui/Modal/index.tsx3
-rw-r--r--src/components/ui/Radio.tsx3
-rw-r--r--src/components/ui/SearchInput.tsx3
-rw-r--r--src/components/ui/Select.js3
-rw-r--r--src/components/ui/ServiceIcon.js6
-rw-r--r--src/components/ui/Slider.js3
-rw-r--r--src/components/ui/StatusBarTargetUrl.js3
-rw-r--r--src/components/ui/Tabs/Tabs.js3
-rw-r--r--src/components/ui/Toggle.js3
-rw-r--r--src/components/ui/ToggleRaw.js3
-rw-r--r--src/components/ui/WebviewLoader/index.js6
-rw-r--r--src/components/ui/badge/ProBadge.tsx9
-rw-r--r--src/components/ui/badge/index.tsx7
-rw-r--r--src/components/ui/button/index.tsx14
-rw-r--r--src/components/ui/error/index.tsx2
-rw-r--r--src/components/ui/headline/index.tsx10
-rw-r--r--src/components/ui/icon/index.tsx7
-rw-r--r--src/components/ui/infobox/index.tsx11
-rw-r--r--src/components/ui/input/index.tsx8
-rw-r--r--src/components/ui/label/index.tsx13
-rw-r--r--src/components/ui/loader/index.tsx18
-rw-r--r--src/components/ui/select/index.tsx11
-rw-r--r--src/components/ui/textarea/index.tsx10
-rw-r--r--src/components/ui/toggle/index.tsx10
-rw-r--r--src/components/ui/typings/generic.ts9
-rw-r--r--src/components/ui/wrapper/index.tsx9
-rw-r--r--src/components/util/ErrorBoundary/index.js5
72 files changed, 308 insertions, 480 deletions
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js
index f26282cfc..94ff5d54d 100644
--- a/src/components/auth/AuthLayout.js
+++ b/src/components/auth/AuthLayout.js
@@ -19,7 +19,6 @@ import AppUpdateInfoBar from '../AppUpdateInfoBar';
19import { GITHUB_FERDI_URL } from '../../config'; 19import { GITHUB_FERDI_URL } from '../../config';
20import { Icon } from '../ui/icon'; 20import { Icon } from '../ui/icon';
21 21
22@observer
23class AuthLayout extends Component { 22class AuthLayout extends Component {
24 static propTypes = { 23 static propTypes = {
25 children: oneOrManyChildElements.isRequired, 24 children: oneOrManyChildElements.isRequired,
@@ -107,4 +106,4 @@ class AuthLayout extends Component {
107 } 106 }
108} 107}
109 108
110export default injectIntl(AuthLayout); 109export default injectIntl(observer(AuthLayout));
diff --git a/src/components/auth/ChangeServer.js b/src/components/auth/ChangeServer.js
index 9aeebc5c8..4c69b2821 100644
--- a/src/components/auth/ChangeServer.js
+++ b/src/components/auth/ChangeServer.js
@@ -6,6 +6,7 @@ import Form from '../../lib/Form';
6import Input from '../ui/Input'; 6import Input from '../ui/Input';
7import Select from '../ui/Select'; 7import Select from '../ui/Select';
8import Button from '../ui/Button'; 8import Button from '../ui/Button';
9import Link from '../ui/Link';
9import Infobox from '../ui/Infobox'; 10import Infobox from '../ui/Infobox';
10import { url, required } from '../../helpers/validation-helpers'; 11import { url, required } from '../../helpers/validation-helpers';
11import { LIVE_FERDI_API, LIVE_FRANZ_API } from '../../config'; 12import { LIVE_FERDI_API, LIVE_FRANZ_API } from '../../config';
@@ -34,7 +35,6 @@ const messages = defineMessages({
34 }, 35 },
35}); 36});
36 37
37@observer
38class ChangeServer extends Component { 38class ChangeServer extends Component {
39 static propTypes = { 39 static propTypes = {
40 onSubmit: PropTypes.func.isRequired, 40 onSubmit: PropTypes.func.isRequired,
@@ -106,6 +106,7 @@ class ChangeServer extends Component {
106 return ( 106 return (
107 <div className="auth__container"> 107 <div className="auth__container">
108 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 108 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
109 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link>
109 <h1>{intl.formatMessage(messages.headline)}</h1> 110 <h1>{intl.formatMessage(messages.headline)}</h1>
110 {form.$('server').value === this.franzServer && ( 111 {form.$('server').value === this.franzServer && (
111 <Infobox type="warning"> 112 <Infobox type="warning">
@@ -131,4 +132,4 @@ class ChangeServer extends Component {
131 } 132 }
132} 133}
133 134
134export default injectIntl(ChangeServer); 135export default injectIntl(observer(ChangeServer));
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js
index fe2fe9872..8f70318ed 100644
--- a/src/components/auth/Import.js
+++ b/src/components/auth/Import.js
@@ -28,7 +28,6 @@ const messages = defineMessages({
28 }, 28 },
29}); 29});
30 30
31@observer
32class Import extends Component { 31class Import extends Component {
33 static propTypes = { 32 static propTypes = {
34 services: MobxPropTypes.arrayOrObservableArray.isRequired, 33 services: MobxPropTypes.arrayOrObservableArray.isRequired,
@@ -166,4 +165,4 @@ class Import extends Component {
166 } 165 }
167} 166}
168 167
169export default injectIntl(Import); 168export default injectIntl(observer(Import));
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index f23417870..a23af7c6b 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -43,7 +43,6 @@ const messages = defineMessages({
43 }, 43 },
44}); 44});
45 45
46@observer
47class Invite extends Component { 46class Invite extends Component {
48 static propTypes = { 47 static propTypes = {
49 onSubmit: PropTypes.func.isRequired, 48 onSubmit: PropTypes.func.isRequired,
@@ -125,8 +124,8 @@ class Invite extends Component {
125 .some(emailValue => emailValue.trim() !== ''); 124 .some(emailValue => emailValue.trim() !== '');
126 125
127 const sendButtonClassName = classnames({ 126 const sendButtonClassName = classnames({
128 'auth__button': true, 127 auth__button: true,
129 'invite__embed--button': embed 128 'invite__embed--button': embed,
130 }); 129 });
131 130
132 const renderForm = ( 131 const renderForm = (
@@ -198,4 +197,4 @@ class Invite extends Component {
198 } 197 }
199} 198}
200 199
201export default injectIntl(Invite); 200export default injectIntl(observer(Invite));
diff --git a/src/components/auth/Locked.js b/src/components/auth/Locked.js
index 5b36b9fc2..ac1bc4e8c 100644
--- a/src/components/auth/Locked.js
+++ b/src/components/auth/Locked.js
@@ -7,7 +7,6 @@ import { defineMessages, injectIntl } from 'react-intl';
7import Form from '../../lib/Form'; 7import Form from '../../lib/Form';
8import Input from '../ui/Input'; 8import Input from '../ui/Input';
9import Button from '../ui/Button'; 9import Button from '../ui/Button';
10import Infobox from '../ui/Infobox';
11import { isMac } from '../../environment'; 10import { isMac } from '../../environment';
12 11
13import { globalError as globalErrorPropType } from '../../prop-types'; 12import { globalError as globalErrorPropType } from '../../prop-types';
@@ -17,11 +16,6 @@ const messages = defineMessages({
17 id: 'locked.headline', 16 id: 'locked.headline',
18 defaultMessage: 'Locked', 17 defaultMessage: 'Locked',
19 }, 18 },
20 info: {
21 id: 'locked.info',
22 defaultMessage:
23 'Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.',
24 },
25 touchId: { 19 touchId: {
26 id: 'locked.touchId', 20 id: 'locked.touchId',
27 defaultMessage: 'Unlock with Touch ID', 21 defaultMessage: 'Unlock with Touch ID',
@@ -48,7 +42,6 @@ const messages = defineMessages({
48 }, 42 },
49}); 43});
50 44
51@observer
52class Locked extends Component { 45class Locked extends Component {
53 static propTypes = { 46 static propTypes = {
54 onSubmit: PropTypes.func.isRequired, 47 onSubmit: PropTypes.func.isRequired,
@@ -108,7 +101,6 @@ class Locked extends Component {
108 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 101 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
109 <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> 102 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
110 <h1>{intl.formatMessage(messages.headline)}</h1> 103 <h1>{intl.formatMessage(messages.headline)}</h1>
111 <Infobox type="warning">{intl.formatMessage(messages.info)}</Infobox>
112 104
113 {touchIdEnabled && ( 105 {touchIdEnabled && (
114 <> 106 <>
@@ -149,4 +141,4 @@ class Locked extends Component {
149 } 141 }
150} 142}
151 143
152export default injectIntl(Locked); 144export default injectIntl(observer(Locked));
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 956205258..bd01f25cd 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -5,14 +5,12 @@ import { observer, inject } from 'mobx-react';
5import { defineMessages, injectIntl } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import { LIVE_FRANZ_API } from '../../config'; 7import { LIVE_FRANZ_API } from '../../config';
8import { API_VERSION, isDevMode, useLiveAPI } from '../../environment-remote'; 8import { API_VERSION } from '../../environment-remote';
9import Form from '../../lib/Form'; 9import Form from '../../lib/Form';
10import { required, email } from '../../helpers/validation-helpers'; 10import { required, email } from '../../helpers/validation-helpers';
11import serverlessLogin from '../../helpers/serverless-helpers';
12import Input from '../ui/Input'; 11import Input from '../ui/Input';
13import Button from '../ui/Button'; 12import Button from '../ui/Button';
14import Link from '../ui/Link'; 13import Link from '../ui/Link';
15import Infobox from '../ui/Infobox';
16 14
17import { globalError as globalErrorPropType } from '../../prop-types'; 15import { globalError as globalErrorPropType } from '../../prop-types';
18 16
@@ -57,22 +55,12 @@ const messages = defineMessages({
57 id: 'login.link.signup', 55 id: 'login.link.signup',
58 defaultMessage: 'Create a free account', 56 defaultMessage: 'Create a free account',
59 }, 57 },
60 changeServer: {
61 id: 'login.changeServer',
62 defaultMessage: 'Change server',
63 },
64 serverless: {
65 id: 'services.serverless',
66 defaultMessage: 'Use Ferdi without an Account',
67 },
68 passwordLink: { 58 passwordLink: {
69 id: 'login.link.password', 59 id: 'login.link.password',
70 defaultMessage: 'Reset password', 60 defaultMessage: 'Reset password',
71 }, 61 },
72}); 62});
73 63
74@inject('actions')
75@observer
76class Login extends Component { 64class Login extends Component {
77 static propTypes = { 65 static propTypes = {
78 onSubmit: PropTypes.func.isRequired, 66 onSubmit: PropTypes.func.isRequired,
@@ -81,9 +69,7 @@ class Login extends Component {
81 isServerLogout: PropTypes.bool.isRequired, 69 isServerLogout: PropTypes.bool.isRequired,
82 signupRoute: PropTypes.string.isRequired, 70 signupRoute: PropTypes.string.isRequired,
83 passwordRoute: PropTypes.string.isRequired, 71 passwordRoute: PropTypes.string.isRequired,
84 changeServerRoute: PropTypes.string.isRequired,
85 error: globalErrorPropType.isRequired, 72 error: globalErrorPropType.isRequired,
86 actions: PropTypes.object.isRequired,
87 }; 73 };
88 74
89 form = new Form( 75 form = new Form(
@@ -105,8 +91,6 @@ class Login extends Component {
105 this.props.intl, 91 this.props.intl,
106 ); 92 );
107 93
108 emailField = null;
109
110 submit(e) { 94 submit(e) {
111 e.preventDefault(); 95 e.preventDefault();
112 this.form.submit({ 96 this.form.submit({
@@ -117,10 +101,6 @@ class Login extends Component {
117 }); 101 });
118 } 102 }
119 103
120 useLocalServer() {
121 serverlessLogin(this.props.actions);
122 }
123
124 render() { 104 render() {
125 const { form } = this; 105 const { form } = this;
126 const { intl } = this.props; 106 const { intl } = this.props;
@@ -130,21 +110,14 @@ class Login extends Component {
130 isServerLogout, 110 isServerLogout,
131 signupRoute, 111 signupRoute,
132 passwordRoute, 112 passwordRoute,
133 changeServerRoute,
134 error, 113 error,
135 } = this.props; 114 } = this.props;
136 115
137 return ( 116 return (
138 <div className="auth__container"> 117 <div className="auth__container">
139 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 118 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
140 <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> 119 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link>
141 <h1>{intl.formatMessage(messages.headline)}</h1> 120 <h1>{intl.formatMessage(messages.headline)}</h1>
142 {isDevMode && !useLiveAPI && (
143 <Infobox type="warning">
144 In Dev Mode your data is not persistent. Please use the live app
145 for accessing the production API.
146 </Infobox>
147 )}
148 {isTokenExpired && ( 121 {isTokenExpired && (
149 <p className="error-message center"> 122 <p className="error-message center">
150 {intl.formatMessage(messages.tokenExpired)} 123 {intl.formatMessage(messages.tokenExpired)}
@@ -155,13 +128,7 @@ class Login extends Component {
155 {intl.formatMessage(messages.serverLogout)} 128 {intl.formatMessage(messages.serverLogout)}
156 </p> 129 </p>
157 )} 130 )}
158 <Input 131 <Input field={form.$('email')} focus />
159 field={form.$('email')}
160 ref={element => {
161 this.emailField = element;
162 }}
163 focus
164 />
165 <Input field={form.$('password')} showPasswordToggle /> 132 <Input field={form.$('password')} showPasswordToggle />
166 {error.code === 'invalid-credentials' && ( 133 {error.code === 'invalid-credentials' && (
167 <> 134 <>
@@ -205,12 +172,6 @@ class Login extends Component {
205 )} 172 )}
206 </form> 173 </form>
207 <div className="auth__links"> 174 <div className="auth__links">
208 <Link to={changeServerRoute}>
209 {intl.formatMessage(messages.changeServer)}
210 </Link>
211 <a onClick={this.useLocalServer.bind(this)}>
212 {intl.formatMessage(messages.serverless)}
213 </a>
214 <Link to={signupRoute}> 175 <Link to={signupRoute}>
215 {intl.formatMessage(messages.signupLink)} 176 {intl.formatMessage(messages.signupLink)}
216 </Link> 177 </Link>
@@ -223,4 +184,4 @@ class Login extends Component {
223 } 184 }
224} 185}
225 186
226export default injectIntl(Login); 187export default injectIntl(inject('actions')(observer(Login)));
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js
index d5bc7fa80..49930f6bd 100644
--- a/src/components/auth/Password.js
+++ b/src/components/auth/Password.js
@@ -38,7 +38,6 @@ const messages = defineMessages({
38 }, 38 },
39}); 39});
40 40
41@observer
42class Password extends Component { 41class Password extends Component {
43 static propTypes = { 42 static propTypes = {
44 onSubmit: PropTypes.func.isRequired, 43 onSubmit: PropTypes.func.isRequired,
@@ -79,7 +78,7 @@ class Password extends Component {
79 return ( 78 return (
80 <div className="auth__container"> 79 <div className="auth__container">
81 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 80 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
82 <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> 81 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link>
83 <h1>{intl.formatMessage(messages.headline)}</h1> 82 <h1>{intl.formatMessage(messages.headline)}</h1>
84 {status.length > 0 && status.includes('sent') && ( 83 {status.length > 0 && status.includes('sent') && (
85 <Infobox type="success" icon="checkbox-marked-circle-outline"> 84 <Infobox type="success" icon="checkbox-marked-circle-outline">
@@ -119,4 +118,4 @@ class Password extends Component {
119 } 118 }
120} 119}
121 120
122export default injectIntl(Password); 121export default injectIntl(observer(Password));
diff --git a/src/components/auth/SetupAssistant.js b/src/components/auth/SetupAssistant.js
index 1665bf837..a24f4e4d5 100644
--- a/src/components/auth/SetupAssistant.js
+++ b/src/components/auth/SetupAssistant.js
@@ -9,7 +9,7 @@ import { Input } from '../ui/input/index';
9import { Button } from '../ui/button/index'; 9import { Button } from '../ui/button/index';
10import { Badge } from '../ui/badge'; 10import { Badge } from '../ui/badge';
11import Modal from '../ui/Modal'; 11import Modal from '../ui/Modal';
12import Infobox from '../ui/Infobox'; 12import * as Infobox from '../ui/Infobox';
13import Appear from '../ui/effects/Appear'; 13import Appear from '../ui/effects/Appear';
14import globalMessages from '../../i18n/globalMessages'; 14import globalMessages from '../../i18n/globalMessages';
15 15
@@ -131,8 +131,6 @@ const styles = theme => ({
131 }, 131 },
132}); 132});
133 133
134@injectSheet(styles)
135@observer
136class SetupAssistant extends Component { 134class SetupAssistant extends Component {
137 static propTypes = { 135 static propTypes = {
138 classes: PropTypes.object.isRequired, 136 classes: PropTypes.object.isRequired,
@@ -327,4 +325,6 @@ class SetupAssistant extends Component {
327 } 325 }
328} 326}
329 327
330export default injectIntl(SetupAssistant); 328export default injectIntl(
329 injectSheet(styles, { injectTheme: true })(observer(SetupAssistant)),
330);
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js
index 00625a3ac..00b387b25 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.js
@@ -4,14 +4,11 @@ import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import { defineMessages, injectIntl } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import { isDevMode, useLiveAPI } from '../../environment-remote';
8import Form from '../../lib/Form'; 7import Form from '../../lib/Form';
9import { required, email, minLength } from '../../helpers/validation-helpers'; 8import { required, email, minLength } from '../../helpers/validation-helpers';
10import serverlessLogin from '../../helpers/serverless-helpers';
11import Input from '../ui/Input'; 9import Input from '../ui/Input';
12import Button from '../ui/Button'; 10import Button from '../ui/Button';
13import Link from '../ui/Link'; 11import Link from '../ui/Link';
14import Infobox from '../ui/Infobox';
15 12
16import { globalError as globalErrorPropType } from '../../prop-types'; 13import { globalError as globalErrorPropType } from '../../prop-types';
17import { termsBase } from '../../api/apiBase'; 14import { termsBase } from '../../api/apiBase';
@@ -61,30 +58,18 @@ const messages = defineMessages({
61 id: 'signup.link.login', 58 id: 'signup.link.login',
62 defaultMessage: 'Already have an account, sign in?', 59 defaultMessage: 'Already have an account, sign in?',
63 }, 60 },
64 changeServer: {
65 id: 'login.changeServer',
66 defaultMessage: 'Change server',
67 },
68 serverless: {
69 id: 'services.serverless',
70 defaultMessage: 'Use Ferdi without an Account',
71 },
72 emailDuplicate: { 61 emailDuplicate: {
73 id: 'signup.emailDuplicate', 62 id: 'signup.emailDuplicate',
74 defaultMessage: 'A user with that email address already exists', 63 defaultMessage: 'A user with that email address already exists',
75 }, 64 },
76}); 65});
77 66
78@inject('actions')
79@observer
80class Signup extends Component { 67class Signup extends Component {
81 static propTypes = { 68 static propTypes = {
82 onSubmit: PropTypes.func.isRequired, 69 onSubmit: PropTypes.func.isRequired,
83 isSubmitting: PropTypes.bool.isRequired, 70 isSubmitting: PropTypes.bool.isRequired,
84 loginRoute: PropTypes.string.isRequired, 71 loginRoute: PropTypes.string.isRequired,
85 changeServerRoute: PropTypes.string.isRequired,
86 error: globalErrorPropType.isRequired, 72 error: globalErrorPropType.isRequired,
87 actions: PropTypes.object.isRequired,
88 }; 73 };
89 74
90 form = new Form( 75 form = new Form(
@@ -126,14 +111,10 @@ class Signup extends Component {
126 }); 111 });
127 } 112 }
128 113
129 useLocalServer() {
130 serverlessLogin(this.props.actions);
131 }
132
133 render() { 114 render() {
134 const { form } = this; 115 const { form } = this;
135 const { intl } = this.props; 116 const { intl } = this.props;
136 const { isSubmitting, loginRoute, error, changeServerRoute } = this.props; 117 const { isSubmitting, loginRoute, error } = this.props;
137 118
138 return ( 119 return (
139 <div className="auth__scroll-container"> 120 <div className="auth__scroll-container">
@@ -142,14 +123,8 @@ class Signup extends Component {
142 className="franz-form auth__form" 123 className="franz-form auth__form"
143 onSubmit={e => this.submit(e)} 124 onSubmit={e => this.submit(e)}
144 > 125 >
145 <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> 126 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link>
146 <h1>{intl.formatMessage(messages.headline)}</h1> 127 <h1>{intl.formatMessage(messages.headline)}</h1>
147 {isDevMode && !useLiveAPI && (
148 <Infobox type="warning">
149 In Dev Mode your data is not persistent. Please use the live app
150 for accesing the production API.
151 </Infobox>
152 )}
153 <div className="grid__row"> 128 <div className="grid__row">
154 <Input field={form.$('firstname')} focus /> 129 <Input field={form.$('firstname')} focus />
155 <Input field={form.$('lastname')} /> 130 <Input field={form.$('lastname')} />
@@ -201,12 +176,6 @@ class Signup extends Component {
201 </p> 176 </p>
202 </form> 177 </form>
203 <div className="auth__links"> 178 <div className="auth__links">
204 <Link to={changeServerRoute}>
205 {intl.formatMessage(messages.changeServer)}
206 </Link>
207 <a onClick={this.useLocalServer.bind(this)}>
208 {intl.formatMessage(messages.serverless)}
209 </a>
210 <Link to={loginRoute}> 179 <Link to={loginRoute}>
211 {intl.formatMessage(messages.loginLink)} 180 {intl.formatMessage(messages.loginLink)}
212 </Link> 181 </Link>
@@ -217,4 +186,4 @@ class Signup extends Component {
217 } 186 }
218} 187}
219 188
220export default injectIntl(Signup); 189export default injectIntl(inject('actions')(observer(Signup)));
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js
index 809ec67a7..4f7a5ce30 100644
--- a/src/components/auth/Welcome.js
+++ b/src/components/auth/Welcome.js
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
4import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; 4import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react';
5import { defineMessages, injectIntl } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import serverlessLogin from '../../helpers/serverless-helpers'; 6import serverlessLogin from '../../helpers/serverless-helpers';
7import { shuffleArray } from '../../helpers/array-helpers';
7 8
8import Link from '../ui/Link'; 9import Link from '../ui/Link';
9 10
@@ -16,14 +17,16 @@ const messages = defineMessages({
16 id: 'welcome.loginButton', 17 id: 'welcome.loginButton',
17 defaultMessage: 'Login to your account', 18 defaultMessage: 'Login to your account',
18 }, 19 },
20 changeServer: {
21 id: 'login.changeServer',
22 defaultMessage: 'Change server'
23 },
19 serverless: { 24 serverless: {
20 id: 'services.serverless', 25 id: 'services.serverless',
21 defaultMessage: 'Use Ferdi without an Account', 26 defaultMessage: 'Use Ferdi without an Account',
22 }, 27 },
23}); 28});
24 29
25@inject('actions')
26@observer
27class Login extends Component { 30class Login extends Component {
28 static propTypes = { 31 static propTypes = {
29 loginRoute: PropTypes.string.isRequired, 32 loginRoute: PropTypes.string.isRequired,
@@ -39,8 +42,10 @@ class Login extends Component {
39 42
40 render() { 43 render() {
41 const { intl } = this.props; 44 const { intl } = this.props;
42 const { loginRoute, signupRoute, changeServerRoute, recipes } = this.props; 45 const { loginRoute, signupRoute, changeServerRoute } = this.props;
43 46 let { recipes } = this.props;
47 recipes = shuffleArray(recipes);
48 recipes.length = 8 * 2;
44 return ( 49 return (
45 <div className="welcome"> 50 <div className="welcome">
46 <div className="welcome__content"> 51 <div className="welcome__content">
@@ -61,25 +66,22 @@ class Login extends Component {
61 <Link to={loginRoute} className="button"> 66 <Link to={loginRoute} className="button">
62 {intl.formatMessage(messages.loginButton)} 67 {intl.formatMessage(messages.loginButton)}
63 </Link> 68 </Link>
64 <br />
65 <br />
66 <a className="button" onClick={this.useLocalServer.bind(this)}>
67 {intl.formatMessage(messages.serverless)}
68 </a>
69 <br />
70 <br />
71
72 <Link to={changeServerRoute}> 69 <Link to={changeServerRoute}>
73 <span 70 <span
74 style={{ 71 style={{
75 textAlign: 'center', 72 color: '#fff'
76 width: '100%',
77 cursor: 'pointer',
78 }} 73 }}
79 > 74 >
80 Change server 75 {intl.formatMessage(messages.changeServer)}
81 </span> 76 </span>
82 </Link> 77 </Link>
78 <br />
79 <br />
80 <hr />
81 <br />
82 <a className="button" onClick={this.useLocalServer.bind(this)}>
83 {intl.formatMessage(messages.serverless)}
84 </a>
83 </div> 85 </div>
84 <div className="welcome__featured-services"> 86 <div className="welcome__featured-services">
85 {recipes.map(recipe => ( 87 {recipes.map(recipe => (
@@ -93,4 +95,4 @@ class Login extends Component {
93 } 95 }
94} 96}
95 97
96export default injectIntl(Login); 98export default injectIntl(inject('actions')(observer(Login)));
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index a31419a5e..084d93ecd 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -74,8 +74,6 @@ const toggleFullScreen = () => {
74 ipcRenderer.send('window.toolbar-double-clicked'); 74 ipcRenderer.send('window.toolbar-double-clicked');
75}; 75};
76 76
77@injectSheet(styles)
78@observer
79class AppLayout extends Component { 77class AppLayout extends Component {
80 static propTypes = { 78 static propTypes = {
81 classes: PropTypes.object.isRequired, 79 classes: PropTypes.object.isRequired,
@@ -208,4 +206,6 @@ class AppLayout extends Component {
208 } 206 }
209} 207}
210 208
211export default injectIntl(AppLayout); 209export default injectIntl(
210 injectSheet(styles, { injectTheme: true })(observer(AppLayout)),
211);
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 728613f42..4f67a8719 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -66,8 +66,6 @@ const messages = defineMessages({
66 }, 66 },
67}); 67});
68 68
69@inject('stores', 'actions')
70@observer
71class Sidebar extends Component { 69class Sidebar extends Component {
72 static propTypes = { 70 static propTypes = {
73 openSettings: PropTypes.func.isRequired, 71 openSettings: PropTypes.func.isRequired,
@@ -262,4 +260,4 @@ class Sidebar extends Component {
262 } 260 }
263} 261}
264 262
265export default injectIntl(Sidebar); 263export default injectIntl(inject('stores', 'actions')(observer(Sidebar)));
diff --git a/src/components/services/content/ConnectionLostBanner.js b/src/components/services/content/ConnectionLostBanner.js
index 5111a081a..5adb22c84 100644
--- a/src/components/services/content/ConnectionLostBanner.js
+++ b/src/components/services/content/ConnectionLostBanner.js
@@ -1,4 +1,4 @@
1import { createRef, Component } from 'react'; 1import { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
@@ -68,8 +68,6 @@ const styles = theme => ({
68 }, 68 },
69}); 69});
70 70
71@injectSheet(styles)
72@observer
73class ConnectionLostBanner extends Component { 71class ConnectionLostBanner extends Component {
74 static propTypes = { 72 static propTypes = {
75 classes: PropTypes.object.isRequired, 73 classes: PropTypes.object.isRequired,
@@ -77,8 +75,6 @@ class ConnectionLostBanner extends Component {
77 reload: PropTypes.func.isRequired, 75 reload: PropTypes.func.isRequired,
78 }; 76 };
79 77
80 inputRef = createRef();
81
82 render() { 78 render() {
83 const { classes, name, reload } = this.props; 79 const { classes, name, reload } = this.props;
84 80
@@ -105,4 +101,4 @@ class ConnectionLostBanner extends Component {
105 } 101 }
106} 102}
107 103
108export default injectIntl(ConnectionLostBanner); 104export default injectIntl(injectSheet(styles)(observer(ConnectionLostBanner)));
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
index 5c93de80f..d605b3a52 100644
--- a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
+++ b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
@@ -31,8 +31,6 @@ const messages = defineMessages({
31 }, 31 },
32}); 32});
33 33
34@injectSheet(styles)
35@observer
36class WebviewErrorHandler extends Component { 34class WebviewErrorHandler extends Component {
37 static propTypes = { 35 static propTypes = {
38 name: PropTypes.string.isRequired, 36 name: PropTypes.string.isRequired,
@@ -71,4 +69,6 @@ class WebviewErrorHandler extends Component {
71 } 69 }
72} 70}
73 71
74export default injectIntl(WebviewErrorHandler); 72export default injectIntl(
73 injectSheet(styles, { injectTheme: true })(observer(WebviewErrorHandler)),
74);
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
index 476b23235..b4658618e 100644
--- a/src/components/services/content/ServiceDisabled.js
+++ b/src/components/services/content/ServiceDisabled.js
@@ -16,17 +16,12 @@ const messages = defineMessages({
16 }, 16 },
17}); 17});
18 18
19@observer
20class ServiceDisabled extends Component { 19class ServiceDisabled extends Component {
21 static propTypes = { 20 static propTypes = {
22 name: PropTypes.string.isRequired, 21 name: PropTypes.string.isRequired,
23 enable: PropTypes.func.isRequired, 22 enable: PropTypes.func.isRequired,
24 }; 23 };
25 24
26 countdownInterval = null;
27
28 countdownIntervalTimeout = 1000;
29
30 render() { 25 render() {
31 const { name, enable } = this.props; 26 const { name, enable } = this.props;
32 const { intl } = this.props; 27 const { intl } = this.props;
@@ -44,4 +39,4 @@ class ServiceDisabled extends Component {
44 } 39 }
45} 40}
46 41
47export default injectIntl(ServiceDisabled); 42export default injectIntl(observer(ServiceDisabled));
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index 1bc1fbf5f..3ea36ae97 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -1,3 +1,4 @@
1/* eslint-disable react/jsx-no-useless-fragment */
1import { Component, Fragment } from 'react'; 2import { Component, Fragment } from 'react';
2import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
3import { autorun } from 'mobx'; 4import { autorun } from 'mobx';
@@ -15,8 +16,6 @@ import SettingsStore from '../../../stores/SettingsStore';
15import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; 16import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen';
16import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config'; 17import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config';
17 18
18@inject('stores', 'actions')
19@observer
20class ServiceView extends Component { 19class ServiceView extends Component {
21 static propTypes = { 20 static propTypes = {
22 service: PropTypes.instanceOf(ServiceModel).isRequired, 21 service: PropTypes.instanceOf(ServiceModel).isRequired,
@@ -65,17 +64,6 @@ class ServiceView extends Component {
65 clearTimeout(this.hibernationTimer); 64 clearTimeout(this.hibernationTimer);
66 } 65 }
67 66
68 updateTargetUrl = event => {
69 let visible = true;
70 if (event.url === '' || event.url === '#') {
71 visible = false;
72 }
73 this.setState({
74 targetUrl: event.url,
75 statusBarVisible: visible,
76 });
77 };
78
79 render() { 67 render() {
80 const { 68 const {
81 detachService, 69 detachService,
@@ -121,6 +109,7 @@ class ServiceView extends Component {
121 {service.isEnabled && 109 {service.isEnabled &&
122 service.isLoading && 110 service.isLoading &&
123 service.isFirstLoad && 111 service.isFirstLoad &&
112 !service.isHibernating &&
124 !service.isServiceAccessRestricted && ( 113 !service.isServiceAccessRestricted && (
125 <WebviewLoader loaded={false} name={service.name} /> 114 <WebviewLoader loaded={false} name={service.name} />
126 )} 115 )}
@@ -157,12 +146,12 @@ class ServiceView extends Component {
157 /> 146 />
158 </> 147 </>
159 ) : ( 148 ) : (
160 <div> 149 <div style={{display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>
161 <span role="img" aria-label="Sleeping Emoji"> 150 <span role="img" aria-label="Sleeping Emoji" style={{fontSize: 42}}>
162 😴 151 😴
163 </span>{' '} 152 </span><br/><br/>
164 This service is currently hibernating. If this page doesn&#x27;t 153 This service is currently hibernating.<br/>
165 close soon, please try reloading Ferdi. 154 Try switching services or reloading Ferdi.
166 </div> 155 </div>
167 )} 156 )}
168 </> 157 </>
@@ -173,4 +162,4 @@ class ServiceView extends Component {
173 } 162 }
174} 163}
175 164
176export default ServiceView; 165export default inject('stores', 'actions')(observer(ServiceView));
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 187785f82..12aaf70b7 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -9,7 +9,6 @@ import ServiceModel from '../../../models/Service';
9 9
10const debug = require('debug')('Ferdi:Services'); 10const debug = require('debug')('Ferdi:Services');
11 11
12@observer
13class ServiceWebview extends Component { 12class ServiceWebview extends Component {
14 static propTypes = { 13 static propTypes = {
15 service: PropTypes.instanceOf(ServiceModel).isRequired, 14 service: PropTypes.instanceOf(ServiceModel).isRequired,
@@ -31,11 +30,13 @@ class ServiceWebview extends Component {
31 debug('Service logged a message:', e.message); 30 debug('Service logged a message:', e.message);
32 }); 31 });
33 this.webview.view.addEventListener('did-navigate', () => { 32 this.webview.view.addEventListener('did-navigate', () => {
34 document.title = `Ferdi - ${this.props.service.name} ${ 33 if (this.props.service._webview) {
35 this.props.service.dialogTitle 34 document.title = `Ferdi - ${this.props.service.name} ${
36 ? ` - ${this.props.service.dialogTitle}` 35 this.props.service.dialogTitle
37 : '' 36 ? ` - ${this.props.service.dialogTitle}`
38 } ${`- ${this.props.service._webview.getTitle()}`}`; 37 : ''
38 } ${`- ${this.props.service._webview.getTitle()}`}`;
39 }
39 }); 40 });
40 } 41 }
41 }, 42 },
@@ -108,10 +109,10 @@ class ServiceWebview extends Component {
108 nodeintegration 109 nodeintegration
109 webpreferences={`spellcheck=${ 110 webpreferences={`spellcheck=${
110 isSpellcheckerEnabled ? 1 : 0 111 isSpellcheckerEnabled ? 1 : 0
111 }, contextIsolation=1, enableRemoteModule=1`} 112 }, contextIsolation=1, nativeWindowOpen=1, enableRemoteModule=1`}
112 /> 113 />
113 ); 114 );
114 } 115 }
115} 116}
116 117
117export default ServiceWebview; 118export default observer(ServiceWebview);
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 1edf31bd3..cbc70563d 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -12,10 +12,6 @@ import Appear from '../../ui/effects/Appear';
12import serverlessLogin from '../../../helpers/serverless-helpers'; 12import serverlessLogin from '../../../helpers/serverless-helpers';
13 13
14const messages = defineMessages({ 14const messages = defineMessages({
15 welcome: {
16 id: 'services.welcome',
17 defaultMessage: 'Welcome to Ferdi',
18 },
19 getStarted: { 15 getStarted: {
20 id: 'services.getStarted', 16 id: 'services.getStarted',
21 defaultMessage: 'Get started', 17 defaultMessage: 'Get started',
@@ -44,9 +40,6 @@ const styles = {
44 }, 40 },
45}; 41};
46 42
47@injectSheet(styles)
48@inject('actions')
49@observer
50class Services extends Component { 43class Services extends Component {
51 static propTypes = { 44 static propTypes = {
52 services: MobxPropTypes.arrayOrObservableArray, 45 services: MobxPropTypes.arrayOrObservableArray,
@@ -132,11 +125,10 @@ class Services extends Component {
132 <Appear timeout={1500} transitionName="slideUp"> 125 <Appear timeout={1500} transitionName="slideUp">
133 <div className="services__no-service"> 126 <div className="services__no-service">
134 <img 127 <img
135 src="./assets/images/logo.svg" 128 src="./assets/images/logo-beard-only.svg"
136 alt="Logo" 129 alt="Logo"
137 style={{ maxHeight: '50vh' }} 130 style={{ maxHeight: '50vh' }}
138 /> 131 />
139 <h1>{intl.formatMessage(messages.welcome)}</h1>
140 {!isLoggedIn && ( 132 {!isLoggedIn && (
141 <> 133 <>
142 <p>{intl.formatMessage(messages.login)}</p> 134 <p>{intl.formatMessage(messages.login)}</p>
@@ -197,4 +189,8 @@ class Services extends Component {
197 } 189 }
198} 190}
199 191
200export default injectIntl(Services); 192export default injectIntl(
193 injectSheet(styles, { injectTheme: true })(
194 inject('actions')(observer(Services)),
195 ),
196);
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index 3607435b3..1ca5ba415 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -26,7 +26,6 @@ const messages = defineMessages({
26 }, 26 },
27}); 27});
28 28
29@observer
30class WebviewCrashHandler extends Component { 29class WebviewCrashHandler extends Component {
31 static propTypes = { 30 static propTypes = {
32 name: PropTypes.string.isRequired, 31 name: PropTypes.string.isRequired,
@@ -81,4 +80,4 @@ class WebviewCrashHandler extends Component {
81 } 80 }
82} 81}
83 82
84export default injectIntl(WebviewCrashHandler); 83export default injectIntl(observer(WebviewCrashHandler));
diff --git a/src/components/services/tabs/TabBarSortableList.js b/src/components/services/tabs/TabBarSortableList.js
index 3049b6efa..e01461e5c 100644
--- a/src/components/services/tabs/TabBarSortableList.js
+++ b/src/components/services/tabs/TabBarSortableList.js
@@ -5,7 +5,6 @@ import { SortableContainer } from 'react-sortable-hoc';
5 5
6import TabItem from './TabItem'; 6import TabItem from './TabItem';
7 7
8@observer
9class TabBarSortableList extends Component { 8class TabBarSortableList extends Component {
10 static propTypes = { 9 static propTypes = {
11 services: MobxPropTypes.arrayOrObservableArray.isRequired, 10 services: MobxPropTypes.arrayOrObservableArray.isRequired,
@@ -75,4 +74,4 @@ class TabBarSortableList extends Component {
75 } 74 }
76} 75}
77 76
78export default SortableContainer(TabBarSortableList); 77export default SortableContainer(observer(TabBarSortableList));
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js
index 5381d7c2b..f5ced7a31 100644
--- a/src/components/services/tabs/TabItem.js
+++ b/src/components/services/tabs/TabItem.js
@@ -114,9 +114,6 @@ const styles = {
114 }, 114 },
115}; 115};
116 116
117@injectSheet(styles)
118@inject('stores')
119@observer
120class TabItem extends Component { 117class TabItem extends Component {
121 static propTypes = { 118 static propTypes = {
122 classes: PropTypes.object.isRequired, 119 classes: PropTypes.object.isRequired,
@@ -239,6 +236,7 @@ class TabItem extends Component {
239 label: intl.formatMessage(messages.reload), 236 label: intl.formatMessage(messages.reload),
240 click: reload, 237 click: reload,
241 accelerator: `${cmdOrCtrlShortcutKey()}+R`, 238 accelerator: `${cmdOrCtrlShortcutKey()}+R`,
239 enabled: service.isEnabled,
242 }, 240 },
243 { 241 {
244 label: intl.formatMessage(globalMessages.edit), 242 label: intl.formatMessage(globalMessages.edit),
@@ -256,6 +254,7 @@ class TabItem extends Component {
256 : intl.formatMessage(messages.enableNotifications), 254 : intl.formatMessage(messages.enableNotifications),
257 click: () => toggleNotifications(), 255 click: () => toggleNotifications(),
258 accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+N`, 256 accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+N`,
257 enabled: service.isEnabled,
259 }, 258 },
260 { 259 {
261 label: service.isMuted 260 label: service.isMuted
@@ -263,6 +262,7 @@ class TabItem extends Component {
263 : intl.formatMessage(messages.disableAudio), 262 : intl.formatMessage(messages.disableAudio),
264 click: () => toggleAudio(), 263 click: () => toggleAudio(),
265 accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+A`, 264 accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+A`,
265 enabled: service.isEnabled,
266 }, 266 },
267 { 267 {
268 label: service.isDarkModeEnabled 268 label: service.isDarkModeEnabled
@@ -270,13 +270,14 @@ class TabItem extends Component {
270 : intl.formatMessage(messages.enableDarkMode), 270 : intl.formatMessage(messages.enableDarkMode),
271 click: () => toggleDarkMode(), 271 click: () => toggleDarkMode(),
272 accelerator: `${shiftKey()}+${altKey()}+D`, 272 accelerator: `${shiftKey()}+${altKey()}+D`,
273 enabled: service.isEnabled,
273 }, 274 },
274 { 275 {
275 label: intl.formatMessage( 276 label: intl.formatMessage(
276 service.isEnabled ? messages.disableService : messages.enableService, 277 service.isEnabled ? messages.disableService : messages.enableService,
277 ), 278 ),
278 click: () => (service.isEnabled ? disableService() : enableService()), 279 click: () => (service.isEnabled ? disableService() : enableService()),
279 accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+S`, 280 accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+S`,
280 }, 281 },
281 { 282 {
282 label: intl.formatMessage( 283 label: intl.formatMessage(
@@ -287,7 +288,7 @@ class TabItem extends Component {
287 // eslint-disable-next-line no-confusing-arrow 288 // eslint-disable-next-line no-confusing-arrow
288 click: () => 289 click: () =>
289 service.isHibernating ? wakeUpService() : hibernateService(), 290 service.isHibernating ? wakeUpService() : hibernateService(),
290 enabled: service.canHibernate, 291 enabled: service.isEnabled && service.canHibernate,
291 }, 292 },
292 { 293 {
293 type: 'separator', 294 type: 'separator',
@@ -402,4 +403,10 @@ class TabItem extends Component {
402 } 403 }
403} 404}
404 405
405export default injectIntl(SortableElement(TabItem)); 406export default injectIntl(
407 SortableElement(
408 injectSheet(styles, { injectTheme: true })(
409 inject('stores')(observer(TabItem)),
410 ),
411 ),
412);
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index 94d6f33c1..d9e11df41 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -4,7 +4,6 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4 4
5import TabBarSortableList from './TabBarSortableList'; 5import TabBarSortableList from './TabBarSortableList';
6 6
7@observer
8class TabBar extends Component { 7class TabBar extends Component {
9 static propTypes = { 8 static propTypes = {
10 services: MobxPropTypes.arrayOrObservableArray.isRequired, 9 services: MobxPropTypes.arrayOrObservableArray.isRequired,
@@ -120,4 +119,4 @@ class TabBar extends Component {
120 } 119 }
121} 120}
122 121
123export default TabBar; 122export default observer(TabBar);
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js
index e9119a944..de13e95ab 100644
--- a/src/components/settings/SettingsLayout.js
+++ b/src/components/settings/SettingsLayout.js
@@ -16,7 +16,6 @@ const messages = defineMessages({
16 }, 16 },
17}); 17});
18 18
19@observer
20class SettingsLayout extends Component { 19class SettingsLayout extends Component {
21 static propTypes = { 20 static propTypes = {
22 navigation: PropTypes.element.isRequired, 21 navigation: PropTypes.element.isRequired,
@@ -78,4 +77,4 @@ class SettingsLayout extends Component {
78 } 77 }
79} 78}
80 79
81export default injectIntl(SettingsLayout); 80export default injectIntl(observer(SettingsLayout));
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 6c489e64b..d0c56af05 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -64,7 +64,6 @@ const messages = defineMessages({
64 }, 64 },
65}); 65});
66 66
67@observer
68class AccountDashboard extends Component { 67class AccountDashboard extends Component {
69 static propTypes = { 68 static propTypes = {
70 user: MobxPropTypes.observableObject.isRequired, 69 user: MobxPropTypes.observableObject.isRequired,
@@ -229,4 +228,4 @@ class AccountDashboard extends Component {
229 } 228 }
230} 229}
231 230
232export default injectIntl(AccountDashboard); 231export default injectIntl(observer(AccountDashboard));
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index dbb1365b0..2fdb6e574 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -42,8 +42,6 @@ const messages = defineMessages({
42 }, 42 },
43}); 43});
44 44
45@inject('stores', 'actions')
46@observer
47class SettingsNavigation extends Component { 45class SettingsNavigation extends Component {
48 static propTypes = { 46 static propTypes = {
49 stores: PropTypes.shape({ 47 stores: PropTypes.shape({
@@ -175,4 +173,4 @@ class SettingsNavigation extends Component {
175 } 173 }
176} 174}
177 175
178export default injectIntl(SettingsNavigation); 176export default injectIntl(inject('stores', 'actions')(observer(SettingsNavigation)));
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js
index 1e910e6dc..df5b42222 100644
--- a/src/components/settings/recipes/RecipeItem.js
+++ b/src/components/settings/recipes/RecipeItem.js
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
4 4
5import RecipePreviewModel from '../../../models/RecipePreview'; 5import RecipePreviewModel from '../../../models/RecipePreview';
6 6
7@observer
8class RecipeItem extends Component { 7class RecipeItem extends Component {
9 static propTypes = { 8 static propTypes = {
10 recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, 9 recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired,
@@ -31,4 +30,4 @@ class RecipeItem extends Component {
31 } 30 }
32} 31}
33 32
34export default RecipeItem; 33export default observer(RecipeItem);
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js
index dcf7a4784..0ba295369 100644
--- a/src/components/settings/recipes/RecipesDashboard.js
+++ b/src/components/settings/recipes/RecipesDashboard.js
@@ -51,7 +51,8 @@ const messages = defineMessages({
51 }, 51 },
52 customRecipeIntro: { 52 customRecipeIntro: {
53 id: 'settings.recipes.customService.intro', 53 id: 'settings.recipes.customService.intro',
54 defaultMessage: 'To add a custom service, copy the service recipe to:', 54 defaultMessage:
55 'To add a custom service, copy the service recipe folder inside:',
55 }, 56 },
56 openFolder: { 57 openFolder: {
57 id: 'settings.recipes.customService.openFolder', 58 id: 'settings.recipes.customService.openFolder',
@@ -104,8 +105,6 @@ const styles = {
104 }, 105 },
105}; 106};
106 107
107@injectSheet(styles)
108@observer
109class RecipesDashboard extends Component { 108class RecipesDashboard extends Component {
110 static propTypes = { 109 static propTypes = {
111 recipes: MobxPropTypes.arrayOrObservableArray.isRequired, 110 recipes: MobxPropTypes.arrayOrObservableArray.isRequired,
@@ -236,28 +235,6 @@ class RecipesDashboard extends Component {
236 <H3>{intl.formatMessage(messages.headlineCommunityRecipes)}</H3> 235 <H3>{intl.formatMessage(messages.headlineCommunityRecipes)}</H3>
237 )} 236 )}
238 <div className="recipes__list"> 237 <div className="recipes__list">
239 {recipes.length === 0 && recipeFilter !== 'dev' && (
240 <div className="align-middle settings__empty-state">
241 <span className="emoji">
242 <img src="./assets/images/emoji/dontknow.png" alt="" />
243 </span>
244
245 <p className="settings__empty-state-text">
246 {intl.formatMessage(messages.nothingFound)}
247 </p>
248
249 <RecipeItem
250 key={customWebsiteRecipe.id}
251 recipe={customWebsiteRecipe}
252 onClick={() =>
253 isLoggedIn &&
254 showAddServiceInterface({
255 recipeId: customWebsiteRecipe.id,
256 })
257 }
258 />
259 </div>
260 )}
261 {communityRecipes.map(recipe => ( 238 {communityRecipes.map(recipe => (
262 <RecipeItem 239 <RecipeItem
263 key={recipe.id} 240 key={recipe.id}
@@ -269,6 +246,25 @@ class RecipesDashboard extends Component {
269 /> 246 />
270 ))} 247 ))}
271 </div> 248 </div>
249 {recipes.length === 0 && recipeFilter !== 'dev' && (
250 <div className="align-middle settings__empty-state">
251 {customWebsiteRecipe && customWebsiteRecipe.id && (
252 <RecipeItem
253 key={customWebsiteRecipe.id}
254 recipe={customWebsiteRecipe}
255 onClick={() =>
256 isLoggedIn &&
257 showAddServiceInterface({
258 recipeId: customWebsiteRecipe.id,
259 })
260 }
261 />
262 )}
263 <p className="settings__empty-state-text">
264 {intl.formatMessage(messages.nothingFound)}
265 </p>
266 </div>
267 )}
272 {recipeFilter === 'dev' && devRecipes.length > 0 && ( 268 {recipeFilter === 'dev' && devRecipes.length > 0 && (
273 <div className={classes.devRecipeList}> 269 <div className={classes.devRecipeList}>
274 <H3>{intl.formatMessage(messages.headlineDevRecipes)}</H3> 270 <H3>{intl.formatMessage(messages.headlineDevRecipes)}</H3>
@@ -294,4 +290,6 @@ class RecipesDashboard extends Component {
294 } 290 }
295} 291}
296 292
297export default injectIntl(RecipesDashboard); 293export default injectIntl(
294 injectSheet(styles, { injectTheme: true })(observer(RecipesDashboard)),
295);
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index 2c451d7bf..f0e791b87 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -134,7 +134,6 @@ const messages = defineMessages({
134 }, 134 },
135}); 135});
136 136
137@observer
138class EditServiceForm extends Component { 137class EditServiceForm extends Component {
139 static propTypes = { 138 static propTypes = {
140 recipe: PropTypes.instanceOf(Recipe).isRequired, 139 recipe: PropTypes.instanceOf(Recipe).isRequired,
@@ -182,6 +181,7 @@ class EditServiceForm extends Component {
182 this.setState({ isValidatingCustomUrl: true }); 181 this.setState({ isValidatingCustomUrl: true });
183 try { 182 try {
184 values.customUrl = normalizeUrl(values.customUrl, { 183 values.customUrl = normalizeUrl(values.customUrl, {
184 stripAuthentication: false,
185 stripWWW: false, 185 stripWWW: false,
186 removeTrailingSlash: false, 186 removeTrailingSlash: false,
187 }); 187 });
@@ -499,4 +499,4 @@ class EditServiceForm extends Component {
499 } 499 }
500} 500}
501 501
502export default injectIntl(EditServiceForm); 502export default injectIntl(observer(EditServiceForm));
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js
index 6dd53a102..bcbbca3de 100644
--- a/src/components/settings/services/ServiceError.js
+++ b/src/components/settings/services/ServiceError.js
@@ -25,7 +25,6 @@ const messages = defineMessages({
25 }, 25 },
26}); 26});
27 27
28@observer
29class ServiceError extends Component { 28class ServiceError extends Component {
30 render() { 29 render() {
31 const { intl } = this.props; 30 const { intl } = this.props;
@@ -60,4 +59,4 @@ class ServiceError extends Component {
60 } 59 }
61} 60}
62 61
63export default injectIntl(ServiceError); 62export default injectIntl(observer(ServiceError));
diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js
index d83e5fd56..23250ad09 100644
--- a/src/components/settings/services/ServiceItem.js
+++ b/src/components/settings/services/ServiceItem.js
@@ -24,7 +24,6 @@ const messages = defineMessages({
24 }, 24 },
25}); 25});
26 26
27@observer
28class ServiceItem extends Component { 27class ServiceItem extends Component {
29 static propTypes = { 28 static propTypes = {
30 service: PropTypes.instanceOf(ServiceModel).isRequired, 29 service: PropTypes.instanceOf(ServiceModel).isRequired,
@@ -91,4 +90,4 @@ class ServiceItem extends Component {
91 } 90 }
92} 91}
93 92
94export default injectIntl(ServiceItem); 93export default injectIntl(observer(ServiceItem));
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index aae6eb855..b405593fd 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -27,7 +27,7 @@ const messages = defineMessages({
27 noServiceFound: { 27 noServiceFound: {
28 id: 'settings.services.nothingFound', 28 id: 'settings.services.nothingFound',
29 defaultMessage: 29 defaultMessage:
30 'Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', 30 'Sorry, but no service matched your search term.',
31 }, 31 },
32 discoverServices: { 32 discoverServices: {
33 id: 'settings.services.discoverServices', 33 id: 'settings.services.discoverServices',
@@ -51,7 +51,6 @@ const messages = defineMessages({
51 }, 51 },
52}); 52});
53 53
54@observer
55class ServicesDashboard extends Component { 54class ServicesDashboard extends Component {
56 static propTypes = { 55 static propTypes = {
57 services: MobxPropTypes.arrayOrObservableArray.isRequired, 56 services: MobxPropTypes.arrayOrObservableArray.isRequired,
@@ -188,4 +187,4 @@ class ServicesDashboard extends Component {
188 } 187 }
189} 188}
190 189
191export default injectIntl(ServicesDashboard); 190export default injectIntl(observer(ServicesDashboard));
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 7e86ea79a..1757ac297 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -5,7 +5,7 @@ import { observer } from 'mobx-react';
5import prettyBytes from 'pretty-bytes'; 5import prettyBytes from 'pretty-bytes';
6import { defineMessages, injectIntl } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8import { mdiGithub, mdiInformation, mdiOpenInNew } from '@mdi/js'; 8import { mdiGithub, mdiOpenInNew } from '@mdi/js';
9import Form from '../../../lib/Form'; 9import Form from '../../../lib/Form';
10import Button from '../../ui/Button'; 10import Button from '../../ui/Button';
11import Toggle from '../../ui/Toggle'; 11import Toggle from '../../ui/Toggle';
@@ -17,6 +17,8 @@ import {
17 DEFAULT_APP_SETTINGS, 17 DEFAULT_APP_SETTINGS,
18 FRANZ_TRANSLATION, 18 FRANZ_TRANSLATION,
19 GITHUB_FRANZ_URL, 19 GITHUB_FRANZ_URL,
20 SPLIT_COLUMNS_MAX,
21 SPLIT_COLUMNS_MIN,
20} from '../../../config'; 22} from '../../../config';
21import { isMac, isWindows, lockFerdiShortcutKey } from '../../../environment'; 23import { isMac, isWindows, lockFerdiShortcutKey } from '../../../environment';
22import { 24import {
@@ -173,16 +175,14 @@ const messages = defineMessages({
173 id: 'settings.app.restartRequired', 175 id: 'settings.app.restartRequired',
174 defaultMessage: 'Changes require restart', 176 defaultMessage: 'Changes require restart',
175 }, 177 },
176 languageDisclaimer: { 178 numberOfColumns: {
177 id: 'settings.app.languageDisclaimer', 179 id: 'settings.app.form.splitColumns',
178 defaultMessage: 180 defaultMessage: 'Number of columns',
179 'Official translations are English & German. All other languages are community based translations.',
180 }, 181 },
181}); 182});
182 183
183const Hr = () => <hr style={{ marginBottom: 20 }} />; 184const Hr = () => <hr style={{ marginBottom: 20 }} />;
184 185
185@observer
186class EditSettingsForm extends Component { 186class EditSettingsForm extends Component {
187 static propTypes = { 187 static propTypes = {
188 checkForUpdates: PropTypes.func.isRequired, 188 checkForUpdates: PropTypes.func.isRequired,
@@ -200,6 +200,7 @@ class EditSettingsForm extends Component {
200 automaticUpdates: PropTypes.bool.isRequired, 200 automaticUpdates: PropTypes.bool.isRequired,
201 isDarkmodeEnabled: PropTypes.bool.isRequired, 201 isDarkmodeEnabled: PropTypes.bool.isRequired,
202 isAdaptableDarkModeEnabled: PropTypes.bool.isRequired, 202 isAdaptableDarkModeEnabled: PropTypes.bool.isRequired,
203 isSplitModeEnabled: PropTypes.bool.isRequired,
203 isNightlyEnabled: PropTypes.bool.isRequired, 204 isNightlyEnabled: PropTypes.bool.isRequired,
204 hasAddedTodosAsService: PropTypes.bool.isRequired, 205 hasAddedTodosAsService: PropTypes.bool.isRequired,
205 isOnline: PropTypes.bool.isRequired, 206 isOnline: PropTypes.bool.isRequired,
@@ -246,6 +247,7 @@ class EditSettingsForm extends Component {
246 getCacheSize, 247 getCacheSize,
247 automaticUpdates, 248 automaticUpdates,
248 isDarkmodeEnabled, 249 isDarkmodeEnabled,
250 isSplitModeEnabled,
249 isTodosActivated, 251 isTodosActivated,
250 isNightlyEnabled, 252 isNightlyEnabled,
251 hasAddedTodosAsService, 253 hasAddedTodosAsService,
@@ -412,10 +414,8 @@ class EditSettingsForm extends Component {
412 414
413 <Hr /> 415 <Hr />
414 416
415 <> 417 <Toggle field={form.$('keepAllWorkspacesLoaded')} />
416 <Toggle field={form.$('keepAllWorkspacesLoaded')} /> 418 <Hr />
417 <Hr />
418 </>
419 419
420 {!hasAddedTodosAsService && ( 420 {!hasAddedTodosAsService && (
421 <> 421 <>
@@ -540,6 +540,16 @@ class EditSettingsForm extends Component {
540 <Hr /> 540 <Hr />
541 541
542 <Toggle field={form.$('splitMode')} /> 542 <Toggle field={form.$('splitMode')} />
543 {isSplitModeEnabled && (
544 <Input
545 type="number"
546 min={SPLIT_COLUMNS_MIN}
547 max={SPLIT_COLUMNS_MAX}
548 placeholder={`${SPLIT_COLUMNS_MIN}-${SPLIT_COLUMNS_MAX}`}
549 onChange={e => this.submit(e)}
550 field={form.$('splitColumns')}
551 />
552 )}
543 553
544 <Hr /> 554 <Hr />
545 555
@@ -800,27 +810,22 @@ class EditSettingsForm extends Component {
800 )} 810 )}
801 <p className="settings__message"> 811 <p className="settings__message">
802 <Icon icon={mdiGithub} /> 812 <Icon icon={mdiGithub} />
803 <span> 813 Ferdi is based on{' '}
804 Ferdi is based on{' '} 814 <a
805 <a 815 href={`${GITHUB_FRANZ_URL}/franz`}
806 href={`${GITHUB_FRANZ_URL}/franz`} 816 target="_blank"
807 target="_blank" 817 rel="noreferrer"
808 rel="noreferrer" 818 >
809 > 819 Franz
810 Franz 820 </a>
811 </a> 821 , a project published under the{' '}
812 , a project published under the{' '} 822 <a
813 <a 823 href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`}
814 href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} 824 target="_blank"
815 target="_blank" 825 rel="noreferrer"
816 rel="noreferrer" 826 >
817 > 827 Apache-2.0 License
818 Apache-2.0 License 828 </a>
819 </a>
820 </span>
821 <br />
822 <Icon icon={mdiInformation} />
823 {intl.formatMessage(messages.languageDisclaimer)}
824 </p> 829 </p>
825 </div> 830 </div>
826 )} 831 )}
@@ -831,4 +836,4 @@ class EditSettingsForm extends Component {
831 } 836 }
832} 837}
833 838
834export default injectIntl(EditSettingsForm); 839export default injectIntl(observer(EditSettingsForm));
diff --git a/src/components/settings/supportFerdi/SupportFerdiDashboard.tsx b/src/components/settings/supportFerdi/SupportFerdiDashboard.tsx
index 88e936b71..acebc979f 100644
--- a/src/components/settings/supportFerdi/SupportFerdiDashboard.tsx
+++ b/src/components/settings/supportFerdi/SupportFerdiDashboard.tsx
@@ -1,7 +1,5 @@
1import { defineMessages, useIntl } from 'react-intl'; 1import { defineMessages, useIntl } from 'react-intl';
2import { BrowserWindow } from '@electron/remote';
3import { mdiOpenInNew } from '@mdi/js'; 2import { mdiOpenInNew } from '@mdi/js';
4import InfoBar from '../../ui/InfoBar';
5import { Icon } from '../../ui/icon'; 3import { Icon } from '../../ui/icon';
6 4
7const messages = defineMessages({ 5const messages = defineMessages({
@@ -9,10 +7,6 @@ const messages = defineMessages({
9 id: 'settings.supportFerdi.headline', 7 id: 'settings.supportFerdi.headline',
10 defaultMessage: 'About Ferdi', 8 defaultMessage: 'About Ferdi',
11 }, 9 },
12 title: {
13 id: 'settings.supportFerdi.title',
14 defaultMessage: 'Do you like Ferdi?',
15 },
16 aboutIntro: { 10 aboutIntro: {
17 id: 'settings.supportFerdi.aboutIntro', 11 id: 'settings.supportFerdi.aboutIntro',
18 defaultMessage: 12 defaultMessage:
@@ -62,26 +56,8 @@ const messages = defineMessages({
62 id: 'settings.supportFerdi.textGitHubSponsors', 56 id: 'settings.supportFerdi.textGitHubSponsors',
63 defaultMessage: 'GitHub Sponsors', 57 defaultMessage: 'GitHub Sponsors',
64 }, 58 },
65 openSurvey: {
66 id: 'settings.supportFerdi.openSurvey',
67 defaultMessage: 'Open survey',
68 },
69 bannerText: {
70 id: 'settings.supportFerdi.bannerText',
71 defaultMessage: 'Do you want to help us improve Ferdi?',
72 },
73}); 59});
74 60
75const openSurveyWindow = () => {
76 let win = new BrowserWindow({ width: 670, height: 400 });
77 win.on('closed', () => {
78 // @ts-expect-error Type 'null' is not assignable to type 'BrowserWindow'.
79 win = null;
80 });
81
82 win.loadURL('https://rp28.typeform.com/to/E3phJT');
83};
84
85const SupportFerdiDashboard = () => { 61const SupportFerdiDashboard = () => {
86 const intl = useIntl(); 62 const intl = useIntl();
87 63
@@ -95,7 +71,6 @@ const SupportFerdiDashboard = () => {
95 </span> 71 </span>
96 </div> 72 </div>
97 <div className="settings__body"> 73 <div className="settings__body">
98 <h1>{intl.formatMessage(messages.title)}</h1>
99 <div> 74 <div>
100 <p className="settings__support-badges"> 75 <p className="settings__support-badges">
101 <a 76 <a
@@ -219,14 +194,6 @@ const SupportFerdiDashboard = () => {
219 </p> 194 </p>
220 </div> 195 </div>
221 </div> 196 </div>
222 <InfoBar
223 sticky
224 type="primary"
225 ctaLabel={intl.formatMessage(messages.openSurvey)}
226 onClick={openSurveyWindow}
227 >
228 {intl.formatMessage(messages.bannerText)}
229 </InfoBar>
230 </div> 197 </div>
231 ); 198 );
232}; 199};
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js
index 4a1a02571..802284051 100644
--- a/src/components/settings/team/TeamDashboard.js
+++ b/src/components/settings/team/TeamDashboard.js
@@ -90,8 +90,6 @@ const styles = {
90 }, 90 },
91}; 91};
92 92
93@injectSheet(styles)
94@observer
95class TeamDashboard extends Component { 93class TeamDashboard extends Component {
96 static propTypes = { 94 static propTypes = {
97 isLoading: PropTypes.bool.isRequired, 95 isLoading: PropTypes.bool.isRequired,
@@ -136,40 +134,34 @@ class TeamDashboard extends Component {
136 </Infobox> 134 </Infobox>
137 )} 135 )}
138 136
139 {!userInfoRequestFailed && ( 137 {!userInfoRequestFailed && !isLoading && (
140 <> 138 <>
141 {!isLoading && ( 139 <h1
142 <> 140 className={classnames({
143 <> 141 [classes.headline]: true,
144 <h1 142 [classes.headlineWithSpacing]: true,
145 className={classnames({ 143 })}
146 [classes.headline]: true, 144 >
147 [classes.headlineWithSpacing]: true, 145 {intl.formatMessage(messages.contentHeadline)}
148 })} 146 </h1>
149 > 147 <div className={classes.container}>
150 {intl.formatMessage(messages.contentHeadline)} 148 <div className={classes.content}>
151 </h1> 149 <p>{intl.formatMessage(messages.intro)}</p>
152 <div className={classes.container}> 150 <p>{intl.formatMessage(messages.copy)}</p>
153 <div className={classes.content}> 151 </div>
154 <p>{intl.formatMessage(messages.intro)}</p> 152 <img
155 <p>{intl.formatMessage(messages.copy)}</p> 153 className={classes.image}
156 </div> 154 src="https://cdn.franzinfra.com/announcements/assets/teams.png"
157 <img 155 alt="Ferdi for Teams"
158 className={classes.image} 156 />
159 src="https://cdn.franzinfra.com/announcements/assets/teams.png" 157 </div>
160 alt="Ferdi for Teams" 158 <div className={classes.buttonContainer}>
161 /> 159 <Button
162 </div> 160 label={intl.formatMessage(messages.manageButton)}
163 <div className={classes.buttonContainer}> 161 onClick={openTeamManagement}
164 <Button 162 className={classes.cta}
165 label={intl.formatMessage(messages.manageButton)} 163 />
166 onClick={openTeamManagement} 164 </div>
167 className={classes.cta}
168 />
169 </div>
170 </>
171 </>
172 )}
173 </> 165 </>
174 )} 166 )}
175 </div> 167 </div>
@@ -203,4 +195,6 @@ class TeamDashboard extends Component {
203 } 195 }
204} 196}
205 197
206export default injectIntl(TeamDashboard); 198export default injectIntl(
199 injectSheet(styles, { injectTheme: true })(observer(TeamDashboard)),
200);
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index 1b8a4f25a..95498d9bb 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -37,7 +37,6 @@ const messages = defineMessages({
37 }, 37 },
38}); 38});
39 39
40@observer
41class EditUserForm extends Component { 40class EditUserForm extends Component {
42 static propTypes = { 41 static propTypes = {
43 status: MobxPropTypes.observableArray.isRequired, 42 status: MobxPropTypes.observableArray.isRequired,
@@ -128,4 +127,4 @@ class EditUserForm extends Component {
128 } 127 }
129} 128}
130 129
131export default injectIntl(EditUserForm); 130export default injectIntl(observer(EditUserForm));
diff --git a/src/components/ui/AppLoader/index.tsx b/src/components/ui/AppLoader/index.tsx
index c7c290a57..e80371e47 100644
--- a/src/components/ui/AppLoader/index.tsx
+++ b/src/components/ui/AppLoader/index.tsx
@@ -1,7 +1,7 @@
1import { Component } from 'react'; 1import { Component } from 'react';
2import injectSheet, { withTheme } from 'react-jss';
3import classnames from 'classnames'; 2import classnames from 'classnames';
4 3
4import injectStyle from 'react-jss';
5import FullscreenLoader from '../FullscreenLoader'; 5import FullscreenLoader from '../FullscreenLoader';
6import { shuffleArray } from '../../../helpers/array-helpers'; 6import { shuffleArray } from '../../../helpers/array-helpers';
7 7
@@ -24,8 +24,6 @@ type Props = {
24 texts: string[]; 24 texts: string[];
25}; 25};
26 26
27@injectSheet(styles)
28@withTheme
29class AppLoader extends Component<Props> { 27class AppLoader extends Component<Props> {
30 static defaultProps = { 28 static defaultProps = {
31 texts: textList, 29 texts: textList,
@@ -57,7 +55,6 @@ class AppLoader extends Component<Props> {
57 55
58 return ( 56 return (
59 <FullscreenLoader 57 <FullscreenLoader
60 title="Ferdi"
61 className={classes.component} 58 className={classes.component}
62 spinnerColor={theme.colorAppLoaderSpinner} 59 spinnerColor={theme.colorAppLoaderSpinner}
63 > 60 >
@@ -77,4 +74,4 @@ class AppLoader extends Component<Props> {
77 } 74 }
78} 75}
79 76
80export default AppLoader; 77export default injectStyle(styles, { injectTheme: true })(AppLoader);
diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js
index 67c801d98..a52f1cadb 100644
--- a/src/components/ui/Button.js
+++ b/src/components/ui/Button.js
@@ -4,8 +4,6 @@ import { observer, inject } from 'mobx-react';
4import Loader from 'react-loader'; 4import Loader from 'react-loader';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7@inject('stores')
8@observer
9class Button extends Component { 7class Button extends Component {
10 static propTypes = { 8 static propTypes = {
11 className: PropTypes.string, 9 className: PropTypes.string,
@@ -35,8 +33,6 @@ class Button extends Component {
35 htmlForm: '', 33 htmlForm: '',
36 }; 34 };
37 35
38 element = null;
39
40 render() { 36 render() {
41 const { 37 const {
42 label, 38 label,
@@ -92,4 +88,4 @@ class Button extends Component {
92 } 88 }
93} 89}
94 90
95export default Button; 91export default inject('stores')(observer(Button));
diff --git a/src/components/ui/FAB.tsx b/src/components/ui/FAB.tsx
index 583c9d556..cb9c5f126 100644
--- a/src/components/ui/FAB.tsx
+++ b/src/components/ui/FAB.tsx
@@ -14,7 +14,6 @@ type Props = {
14 htmlForm: string; 14 htmlForm: string;
15}; 15};
16 16
17@observer
18class Button extends Component<Props> { 17class Button extends Component<Props> {
19 static defaultProps = { 18 static defaultProps = {
20 disabled: false, 19 disabled: false,
@@ -23,8 +22,6 @@ class Button extends Component<Props> {
23 htmlForm: '', 22 htmlForm: '',
24 }; 23 };
25 24
26 element = null;
27
28 render() { 25 render() {
29 const { className, disabled, onClick, type, children, htmlForm } = 26 const { className, disabled, onClick, type, children, htmlForm } =
30 this.props; 27 this.props;
@@ -48,4 +45,4 @@ class Button extends Component<Props> {
48 } 45 }
49} 46}
50 47
51export default Button; 48export default observer(Button);
diff --git a/src/components/ui/FullscreenLoader/index.js b/src/components/ui/FullscreenLoader/index.js
index f5943f3f3..39b6c5a4c 100644
--- a/src/components/ui/FullscreenLoader/index.js
+++ b/src/components/ui/FullscreenLoader/index.js
@@ -1,16 +1,13 @@
1import { Component } from 'react'; 1import { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet, { withTheme } from 'react-jss'; 4import injectStyle from 'react-jss';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7import Loader from '../Loader'; 7import Loader from '../Loader';
8 8
9import styles from './styles'; 9import styles from './styles';
10 10
11@withTheme
12@injectSheet(styles)
13@observer
14class FullscreenLoader extends Component { 11class FullscreenLoader extends Component {
15 static propTypes = { 12 static propTypes = {
16 className: PropTypes.string, 13 className: PropTypes.string,
@@ -48,4 +45,6 @@ class FullscreenLoader extends Component {
48 } 45 }
49} 46}
50 47
51export default FullscreenLoader; 48export default injectStyle(styles, { injectTheme: true })(
49 observer(FullscreenLoader),
50);
diff --git a/src/components/ui/ImageUpload.tsx b/src/components/ui/ImageUpload.tsx
index 118e6b206..b07e211c2 100644
--- a/src/components/ui/ImageUpload.tsx
+++ b/src/components/ui/ImageUpload.tsx
@@ -2,7 +2,7 @@ import { Component } from 'react';
2import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
3import { Field } from 'mobx-react-form'; 3import { Field } from 'mobx-react-form';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import Dropzone, { DropzoneRef } from 'react-dropzone'; 5import Dropzone from 'react-dropzone';
6import { mdiDelete, mdiFileImage } from '@mdi/js'; 6import { mdiDelete, mdiFileImage } from '@mdi/js';
7import { isWindows } from '../../environment'; 7import { isWindows } from '../../environment';
8import { Icon } from './icon'; 8import { Icon } from './icon';
@@ -15,7 +15,6 @@ type Props = {
15 textUpload: string; 15 textUpload: string;
16}; 16};
17 17
18@observer
19class ImageUpload extends Component<Props> { 18class ImageUpload extends Component<Props> {
20 static defaultProps = { 19 static defaultProps = {
21 multiple: false, 20 multiple: false,
@@ -25,8 +24,6 @@ class ImageUpload extends Component<Props> {
25 path: null, 24 path: null,
26 }; 25 };
27 26
28 dropzoneRef: DropzoneRef | null = null;
29
30 onDrop(acceptedFiles) { 27 onDrop(acceptedFiles) {
31 const { field } = this.props; 28 const { field } = this.props;
32 29
@@ -85,9 +82,6 @@ class ImageUpload extends Component<Props> {
85 </> 82 </>
86 ) : ( 83 ) : (
87 <Dropzone 84 <Dropzone
88 ref={node => {
89 this.dropzoneRef = node;
90 }}
91 onDrop={this.onDrop.bind(this)} 85 onDrop={this.onDrop.bind(this)}
92 multiple={multiple} 86 multiple={multiple}
93 accept="image/jpeg, image/png, image/svg+xml" 87 accept="image/jpeg, image/png, image/svg+xml"
@@ -107,4 +101,4 @@ class ImageUpload extends Component<Props> {
107 } 101 }
108} 102}
109 103
110export default ImageUpload; 104export default observer(ImageUpload);
diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js
index 89b085907..c1a6013c2 100644
--- a/src/components/ui/InfoBar.js
+++ b/src/components/ui/InfoBar.js
@@ -16,7 +16,6 @@ const messages = defineMessages({
16 }, 16 },
17}); 17});
18 18
19@observer
20class InfoBar extends Component { 19class InfoBar extends Component {
21 static propTypes = { 20 static propTypes = {
22 // eslint-disable-next-line react/forbid-prop-types 21 // eslint-disable-next-line react/forbid-prop-types
@@ -102,4 +101,4 @@ class InfoBar extends Component {
102 } 101 }
103} 102}
104 103
105export default injectIntl(InfoBar); 104export default injectIntl(observer(InfoBar));
diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js
index c0ba8f13c..6634a6808 100644
--- a/src/components/ui/Infobox.js
+++ b/src/components/ui/Infobox.js
@@ -19,7 +19,6 @@ const messages = defineMessages({
19 }, 19 },
20}); 20});
21 21
22@observer
23class Infobox extends Component { 22class Infobox extends Component {
24 static propTypes = { 23 static propTypes = {
25 // eslint-disable-next-line react/forbid-prop-types 24 // eslint-disable-next-line react/forbid-prop-types
@@ -112,4 +111,4 @@ class Infobox extends Component {
112 } 111 }
113} 112}
114 113
115export default injectIntl(Infobox); 114export default injectIntl(observer(Infobox));
diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js
index 8d37d7a05..fa1b44699 100644
--- a/src/components/ui/Input.js
+++ b/src/components/ui/Input.js
@@ -5,7 +5,9 @@ import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6import { defineMessages, injectIntl } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8import { mdiEye, mdiEyeOff } from '@mdi/js';
8import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers'; 9import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers';
10import { Icon } from './icon';
9 11
10const messages = defineMessages({ 12const messages = defineMessages({
11 passwordToggle: { 13 passwordToggle: {
@@ -14,7 +16,6 @@ const messages = defineMessages({
14 }, 16 },
15}); 17});
16 18
17@observer
18class Input extends Component { 19class Input extends Component {
19 static propTypes = { 20 static propTypes = {
20 field: PropTypes.instanceOf(Field).isRequired, 21 field: PropTypes.instanceOf(Field).isRequired,
@@ -115,9 +116,6 @@ class Input extends Component {
115 type="button" 116 type="button"
116 className={classnames({ 117 className={classnames({
117 'franz-form__input-modifier': true, 118 'franz-form__input-modifier': true,
118 mdi: true,
119 'mdi-eye': !this.state.showPassword,
120 'mdi-eye-off': this.state.showPassword,
121 })} 119 })}
122 onClick={() => 120 onClick={() =>
123 this.setState(prevState => ({ 121 this.setState(prevState => ({
@@ -126,7 +124,9 @@ class Input extends Component {
126 } 124 }
127 tabIndex={-1} 125 tabIndex={-1}
128 aria-label={intl.formatMessage(messages.passwordToggle)} 126 aria-label={intl.formatMessage(messages.passwordToggle)}
129 /> 127 >
128 <Icon icon={this.state.showPassword ? mdiEye : mdiEyeOff} />
129 </button>
130 )} 130 )}
131 {scorePassword && ( 131 {scorePassword && (
132 <div className="franz-form__password-score"> 132 <div className="franz-form__password-score">
@@ -152,4 +152,4 @@ class Input extends Component {
152 } 152 }
153} 153}
154 154
155export default injectIntl(Input); 155export default injectIntl(observer(Input));
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js
index 40766c984..565547736 100644
--- a/src/components/ui/Link.js
+++ b/src/components/ui/Link.js
@@ -9,8 +9,6 @@ import { matchRoute } from '../../helpers/routing-helpers';
9import { openExternalUrl } from '../../helpers/url-helpers'; 9import { openExternalUrl } from '../../helpers/url-helpers';
10 10
11// TODO: create container component for this component 11// TODO: create container component for this component
12@inject('stores')
13@observer
14class Link extends Component { 12class Link extends Component {
15 onClick(e) { 13 onClick(e) {
16 if (this.props.disabled) { 14 if (this.props.disabled) {
@@ -60,7 +58,7 @@ class Link extends Component {
60 } 58 }
61} 59}
62 60
63Link.wrappedComponent.propTypes = { 61Link.propTypes = {
64 stores: PropTypes.shape({ 62 stores: PropTypes.shape({
65 router: PropTypes.instanceOf(RouterStore).isRequired, 63 router: PropTypes.instanceOf(RouterStore).isRequired,
66 }).isRequired, 64 }).isRequired,
@@ -75,7 +73,7 @@ Link.wrappedComponent.propTypes = {
75 disabled: PropTypes.bool, 73 disabled: PropTypes.bool,
76}; 74};
77 75
78Link.wrappedComponent.defaultProps = { 76Link.defaultProps = {
79 className: '', 77 className: '',
80 activeClassName: '', 78 activeClassName: '',
81 strictFilter: false, 79 strictFilter: false,
@@ -84,4 +82,4 @@ Link.wrappedComponent.defaultProps = {
84 style: {}, 82 style: {},
85}; 83};
86 84
87export default Link; 85export default inject('stores')(observer(Link));
diff --git a/src/components/ui/Loader.tsx b/src/components/ui/Loader.tsx
index 1173c11e7..171d0e290 100644
--- a/src/components/ui/Loader.tsx
+++ b/src/components/ui/Loader.tsx
@@ -12,8 +12,6 @@ type Props = {
12 stores: FerdiStores; 12 stores: FerdiStores;
13}; 13};
14 14
15@inject('stores')
16@observer
17class LoaderComponent extends Component<Props> { 15class LoaderComponent extends Component<Props> {
18 static defaultProps = { 16 static defaultProps = {
19 loaded: false, 17 loaded: false,
@@ -43,4 +41,4 @@ class LoaderComponent extends Component<Props> {
43 } 41 }
44} 42}
45 43
46export default LoaderComponent; 44export default inject('stores')(observer(LoaderComponent));
diff --git a/src/components/ui/Modal/index.tsx b/src/components/ui/Modal/index.tsx
index f2f4461b8..c3c78b419 100644
--- a/src/components/ui/Modal/index.tsx
+++ b/src/components/ui/Modal/index.tsx
@@ -18,7 +18,6 @@ type Props = {
18 showClose: boolean; 18 showClose: boolean;
19}; 19};
20 20
21@injectCSS(styles)
22class Modal extends Component<Props> { 21class Modal extends Component<Props> {
23 static defaultProps = { 22 static defaultProps = {
24 className: null, 23 className: null,
@@ -64,4 +63,4 @@ class Modal extends Component<Props> {
64 } 63 }
65} 64}
66 65
67export default Modal; 66export default injectCSS(styles)(Modal);
diff --git a/src/components/ui/Radio.tsx b/src/components/ui/Radio.tsx
index 594ea70e4..a033a5fe0 100644
--- a/src/components/ui/Radio.tsx
+++ b/src/components/ui/Radio.tsx
@@ -10,7 +10,6 @@ type Props = {
10 showLabel: boolean; 10 showLabel: boolean;
11}; 11};
12 12
13@observer
14class Radio extends Component<Props> { 13class Radio extends Component<Props> {
15 static defaultProps = { 14 static defaultProps = {
16 focus: false, 15 focus: false,
@@ -74,4 +73,4 @@ class Radio extends Component<Props> {
74 } 73 }
75} 74}
76 75
77export default Radio; 76export default observer(Radio);
diff --git a/src/components/ui/SearchInput.tsx b/src/components/ui/SearchInput.tsx
index 49a50a4a0..6a6a1692e 100644
--- a/src/components/ui/SearchInput.tsx
+++ b/src/components/ui/SearchInput.tsx
@@ -17,7 +17,6 @@ type Props = {
17 autoFocus: boolean; 17 autoFocus: boolean;
18}; 18};
19 19
20@observer
21class SearchInput extends Component<Props> { 20class SearchInput extends Component<Props> {
22 static defaultProps = { 21 static defaultProps = {
23 value: '', 22 value: '',
@@ -115,4 +114,4 @@ class SearchInput extends Component<Props> {
115 } 114 }
116} 115}
117 116
118export default SearchInput; 117export default observer(SearchInput);
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js
index a560da332..0fc32e573 100644
--- a/src/components/ui/Select.js
+++ b/src/components/ui/Select.js
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7@observer
8class Select extends Component { 7class Select extends Component {
9 static propTypes = { 8 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired, 9 field: PropTypes.instanceOf(Field).isRequired,
@@ -98,4 +97,4 @@ class Select extends Component {
98 } 97 }
99} 98}
100 99
101export default Select; 100export default observer(Select);
diff --git a/src/components/ui/ServiceIcon.js b/src/components/ui/ServiceIcon.js
index f067f8955..d403d107d 100644
--- a/src/components/ui/ServiceIcon.js
+++ b/src/components/ui/ServiceIcon.js
@@ -24,8 +24,6 @@ const styles = theme => ({
24 }, 24 },
25}); 25});
26 26
27@injectSheet(styles)
28@observer
29class ServiceIcon extends Component { 27class ServiceIcon extends Component {
30 static propTypes = { 28 static propTypes = {
31 classes: PropTypes.object.isRequired, 29 classes: PropTypes.object.isRequired,
@@ -56,4 +54,6 @@ class ServiceIcon extends Component {
56 } 54 }
57} 55}
58 56
59export default ServiceIcon; 57export default injectSheet(styles, { injectTheme: true })(
58 observer(ServiceIcon),
59);
diff --git a/src/components/ui/Slider.js b/src/components/ui/Slider.js
index dea6e0563..a581e7a65 100644
--- a/src/components/ui/Slider.js
+++ b/src/components/ui/Slider.js
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { Field } from 'mobx-react-form'; 5import { Field } from 'mobx-react-form';
6 6
7@observer
8class Slider extends Component { 7class Slider extends Component {
9 static propTypes = { 8 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired, 9 field: PropTypes.instanceOf(Field).isRequired,
@@ -64,4 +63,4 @@ class Slider extends Component {
64 } 63 }
65} 64}
66 65
67export default Slider; 66export default observer(Slider);
diff --git a/src/components/ui/StatusBarTargetUrl.js b/src/components/ui/StatusBarTargetUrl.js
index 38b436742..d8d329d52 100644
--- a/src/components/ui/StatusBarTargetUrl.js
+++ b/src/components/ui/StatusBarTargetUrl.js
@@ -5,7 +5,6 @@ import classnames from 'classnames';
5 5
6import Appear from './effects/Appear'; 6import Appear from './effects/Appear';
7 7
8@observer
9class StatusBarTargetUrl extends Component { 8class StatusBarTargetUrl extends Component {
10 static propTypes = { 9 static propTypes = {
11 className: PropTypes.string, 10 className: PropTypes.string,
@@ -33,4 +32,4 @@ class StatusBarTargetUrl extends Component {
33 } 32 }
34} 33}
35 34
36export default StatusBarTargetUrl; 35export default observer(StatusBarTargetUrl);
diff --git a/src/components/ui/Tabs/Tabs.js b/src/components/ui/Tabs/Tabs.js
index 77803974b..5d2da6293 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
6import { oneOrManyChildElements } from '../../../prop-types'; 6import { oneOrManyChildElements } from '../../../prop-types';
7 7
8@observer
9class Tab extends Component { 8class Tab extends Component {
10 constructor(props) { 9 constructor(props) {
11 super(props); 10 super(props);
@@ -69,4 +68,4 @@ class Tab extends Component {
69 } 68 }
70} 69}
71 70
72export default Tab; 71export default observer(Tab);
diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js
index dfc319735..a82be690e 100644
--- a/src/components/ui/Toggle.js
+++ b/src/components/ui/Toggle.js
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { Field } from 'mobx-react-form'; 5import { Field } from 'mobx-react-form';
6 6
7@observer
8class Toggle extends Component { 7class Toggle extends Component {
9 static propTypes = { 8 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired, 9 field: PropTypes.instanceOf(Field).isRequired,
@@ -69,4 +68,4 @@ class Toggle extends Component {
69 } 68 }
70} 69}
71 70
72export default Toggle; 71export default observer(Toggle);
diff --git a/src/components/ui/ToggleRaw.js b/src/components/ui/ToggleRaw.js
index 74292a870..e482b97b4 100644
--- a/src/components/ui/ToggleRaw.js
+++ b/src/components/ui/ToggleRaw.js
@@ -6,7 +6,6 @@ import PropTypes from 'prop-types';
6import { observer } from 'mobx-react'; 6import { observer } from 'mobx-react';
7import classnames from 'classnames'; 7import classnames from 'classnames';
8 8
9@observer
10class ToggleRaw extends Component { 9class ToggleRaw extends Component {
11 static propTypes = { 10 static propTypes = {
12 onChange: PropTypes.func.isRequired, 11 onChange: PropTypes.func.isRequired,
@@ -74,4 +73,4 @@ class ToggleRaw extends Component {
74 } 73 }
75} 74}
76 75
77export default ToggleRaw; 76export default observer(ToggleRaw);
diff --git a/src/components/ui/WebviewLoader/index.js b/src/components/ui/WebviewLoader/index.js
index 8d4513172..20945d191 100644
--- a/src/components/ui/WebviewLoader/index.js
+++ b/src/components/ui/WebviewLoader/index.js
@@ -14,8 +14,6 @@ const messages = defineMessages({
14 }, 14 },
15}); 15});
16 16
17@injectSheet(styles)
18@observer
19class WebviewLoader extends Component { 17class WebviewLoader extends Component {
20 static propTypes = { 18 static propTypes = {
21 name: PropTypes.string.isRequired, 19 name: PropTypes.string.isRequired,
@@ -34,4 +32,6 @@ class WebviewLoader extends Component {
34 } 32 }
35} 33}
36 34
37export default injectIntl(WebviewLoader); 35export default injectIntl(
36 injectSheet(styles, { injectTheme: true })(observer(WebviewLoader)),
37);
diff --git a/src/components/ui/badge/ProBadge.tsx b/src/components/ui/badge/ProBadge.tsx
index dc1e76f7f..410748a64 100644
--- a/src/components/ui/badge/ProBadge.tsx
+++ b/src/components/ui/badge/ProBadge.tsx
@@ -1,14 +1,13 @@
1import { mdiStar } from '@mdi/js'; 1import { mdiStar } from '@mdi/js';
2import classnames from 'classnames'; 2import classnames from 'classnames';
3import { Component } from 'react'; 3import { Component } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle, { WithStylesProps } from 'react-jss';
5 5
6import { Theme } from '../../../themes'; 6import { Theme } from '../../../themes';
7import { Icon } from '../icon'; 7import { Icon } from '../icon';
8import { Badge } from './index'; 8import { Badge } from './index';
9import { IWithStyle } from '../typings/generic';
10 9
11interface IProps extends IWithStyle { 10interface IProps extends WithStylesProps<typeof styles> {
12 badgeClasses?: string; 11 badgeClasses?: string;
13 iconClasses?: string; 12 iconClasses?: string;
14 inverted?: boolean; 13 inverted?: boolean;
@@ -61,4 +60,6 @@ class ProBadgeComponent extends Component<IProps> {
61 } 60 }
62} 61}
63 62
64export const ProBadge = injectStyle(styles)(ProBadgeComponent); 63export const ProBadge = injectStyle(styles, { injectTheme: true })(
64 ProBadgeComponent,
65);
diff --git a/src/components/ui/badge/index.tsx b/src/components/ui/badge/index.tsx
index 61bede937..a7ed866a5 100644
--- a/src/components/ui/badge/index.tsx
+++ b/src/components/ui/badge/index.tsx
@@ -1,11 +1,10 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Component, ReactNode } from 'react'; 2import { Component, ReactNode } from 'react';
3import injectStyle from 'react-jss'; 3import injectStyle, { WithStylesProps } from 'react-jss';
4 4
5import { Theme } from '../../../themes'; 5import { Theme } from '../../../themes';
6import { IWithStyle } from '../typings/generic';
7 6
8interface IProps extends IWithStyle { 7interface IProps extends WithStylesProps<typeof styles> {
9 type: string; 8 type: string;
10 className?: string; 9 className?: string;
11 children: ReactNode; 10 children: ReactNode;
@@ -68,4 +67,4 @@ class BadgeComponent extends Component<IProps> {
68 } 67 }
69} 68}
70 69
71export const Badge = injectStyle(styles)(BadgeComponent); 70export const Badge = injectStyle(styles, { injectTheme: true })(BadgeComponent);
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx
index 12e5e4449..d91b1ee19 100644
--- a/src/components/ui/button/index.tsx
+++ b/src/components/ui/button/index.tsx
@@ -2,11 +2,11 @@ import Icon from '@mdi/react';
2import classnames from 'classnames'; 2import classnames from 'classnames';
3import { Property } from 'csstype'; 3import { Property } from 'csstype';
4import { Component, MouseEvent } from 'react'; 4import { Component, MouseEvent } from 'react';
5import injectStyle, { withTheme } from 'react-jss'; 5import injectStyle, { WithStylesProps } from 'react-jss';
6import Loader from 'react-loader'; 6import Loader from 'react-loader';
7 7
8import { Theme } from '../../../themes'; 8import { Theme } from '../../../themes';
9import { IFormField, IWithStyle } from '../typings/generic'; 9import { IFormField } from '../typings/generic';
10 10
11type ButtonType = 11type ButtonType =
12 | 'primary' 12 | 'primary'
@@ -16,7 +16,7 @@ type ButtonType =
16 | 'warning' 16 | 'warning'
17 | 'inverted'; 17 | 'inverted';
18 18
19interface IProps extends IFormField, IWithStyle { 19interface IProps extends IFormField, WithStylesProps<typeof styles> {
20 className?: string; 20 className?: string;
21 disabled?: boolean; 21 disabled?: boolean;
22 id?: string; 22 id?: string;
@@ -179,7 +179,7 @@ class ButtonComponent extends Component<IProps> {
179 const { 179 const {
180 classes, 180 classes,
181 className, 181 className,
182 theme, 182 // theme,
183 disabled, 183 disabled,
184 id, 184 id,
185 label, 185 label,
@@ -213,7 +213,7 @@ class ButtonComponent extends Component<IProps> {
213 loaded={false} 213 loaded={false}
214 width={4} 214 width={4}
215 scale={0.45} 215 scale={0.45}
216 color={theme.buttonLoaderColor[buttonType!]} 216 // color={theme.buttonLoaderColor[buttonType!]}
217 parentClassName={classes.loader} 217 parentClassName={classes.loader}
218 /> 218 />
219 )} 219 )}
@@ -262,4 +262,6 @@ class ButtonComponent extends Component<IProps> {
262 } 262 }
263} 263}
264 264
265export const Button = injectStyle(styles)(withTheme(ButtonComponent)); 265export const Button = injectStyle(styles, { injectTheme: true })(
266 ButtonComponent,
267);
diff --git a/src/components/ui/error/index.tsx b/src/components/ui/error/index.tsx
index 8439bfc8b..ff3bc31c6 100644
--- a/src/components/ui/error/index.tsx
+++ b/src/components/ui/error/index.tsx
@@ -17,4 +17,4 @@ class ErrorComponent extends Component<IProps> {
17 } 17 }
18} 18}
19 19
20export const Error = injectSheet(styles)(ErrorComponent); 20export const Error = injectSheet(styles, { injectTheme: true })(ErrorComponent);
diff --git a/src/components/ui/headline/index.tsx b/src/components/ui/headline/index.tsx
index ea2949102..d9954c38f 100644
--- a/src/components/ui/headline/index.tsx
+++ b/src/components/ui/headline/index.tsx
@@ -1,11 +1,11 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Component, createElement, ReactNode } from 'react'; 2import { Component, createElement, ReactNode } from 'react';
3import injectStyle from 'react-jss'; 3import injectStyle, { WithStylesProps } from 'react-jss';
4 4
5import { Theme } from '../../../themes'; 5import { Theme } from '../../../themes';
6import { IWithStyle, Omit } from '../typings/generic'; 6import { Omit } from '../typings/generic';
7 7
8interface IProps extends IWithStyle { 8interface IProps extends WithStylesProps<typeof styles> {
9 level?: number; 9 level?: number;
10 className?: string; 10 className?: string;
11 children: string | ReactNode; 11 children: string | ReactNode;
@@ -55,9 +55,9 @@ class HeadlineComponent extends Component<IProps> {
55 } 55 }
56} 56}
57 57
58const Headline = injectStyle(styles)(HeadlineComponent); 58const Headline = injectStyle(styles, { injectTheme: true })(HeadlineComponent);
59 59
60const createH = (level: number) => (props: Omit<IProps, 'classes' | 'theme'>) => 60const createH = (level: number) => (props: Omit<IProps, 'classes'>) =>
61 ( 61 (
62 <Headline level={level} {...props}> 62 <Headline level={level} {...props}>
63 {props.children} 63 {props.children}
diff --git a/src/components/ui/icon/index.tsx b/src/components/ui/icon/index.tsx
index 85bb61d13..52f61d2d7 100644
--- a/src/components/ui/icon/index.tsx
+++ b/src/components/ui/icon/index.tsx
@@ -1,12 +1,11 @@
1import MdiIcon from '@mdi/react'; 1import MdiIcon from '@mdi/react';
2import classnames from 'classnames'; 2import classnames from 'classnames';
3import { Component } from 'react'; 3import { Component } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle, { WithStylesProps } from 'react-jss';
5 5
6import { Theme } from '../../../themes'; 6import { Theme } from '../../../themes';
7import { IWithStyle } from '../typings/generic';
8 7
9interface IProps extends IWithStyle { 8interface IProps extends WithStylesProps<typeof styles> {
10 icon: string; 9 icon: string;
11 size?: number; 10 size?: number;
12 className?: string; 11 className?: string;
@@ -43,4 +42,4 @@ class IconComponent extends Component<IProps> {
43 } 42 }
44} 43}
45 44
46export const Icon = injectStyle(styles)(IconComponent); 45export const Icon = injectStyle(styles, { injectTheme: true })(IconComponent);
diff --git a/src/components/ui/infobox/index.tsx b/src/components/ui/infobox/index.tsx
index 87940c4d4..c0767a342 100644
--- a/src/components/ui/infobox/index.tsx
+++ b/src/components/ui/infobox/index.tsx
@@ -1,13 +1,12 @@
1import { mdiClose } from '@mdi/js'; 1import { mdiClose } from '@mdi/js';
2import classnames from 'classnames'; 2import classnames from 'classnames';
3import { Component, ReactNode } from 'react'; 3import { Component, ReactNode } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle, { WithStylesProps } from 'react-jss';
5 5
6import { Theme } from '../../../themes'; 6import { Theme } from '../../../themes';
7import { Icon } from '../icon'; 7import { Icon } from '../icon';
8import { IWithStyle } from '../typings/generic';
9 8
10interface IProps extends IWithStyle { 9interface IProps extends WithStylesProps<typeof styles> {
11 icon?: string; 10 icon?: string;
12 type?: string; 11 type?: string;
13 dismissable?: boolean; 12 dismissable?: boolean;
@@ -58,7 +57,6 @@ const styles = (theme: Theme) => ({
58 position: 'relative', 57 position: 'relative',
59 overflow: 'hidden', 58 overflow: 'hidden',
60 height: 'auto', 59 height: 'auto',
61 marginBottom: 30,
62 }, 60 },
63 infobox: { 61 infobox: {
64 alignItems: 'center', 62 alignItems: 'center',
@@ -69,6 +67,7 @@ const styles = (theme: Theme) => ({
69 top: 0, 67 top: 0,
70 transition: infoBoxTransition, 68 transition: infoBoxTransition,
71 opacity: 1, 69 opacity: 1,
70 marginBottom: 30,
72 }, 71 },
73 dismissing: { 72 dismissing: {
74 // position: 'absolute', 73 // position: 'absolute',
@@ -202,4 +201,6 @@ class InfoboxComponent extends Component<IProps, IState> {
202 } 201 }
203} 202}
204 203
205export const Infobox = injectStyle(styles)(InfoboxComponent); 204export const Infobox = injectStyle(styles, { injectTheme: true })(
205 InfoboxComponent,
206);
diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx
index c46cafc5c..bfbee33b9 100644
--- a/src/components/ui/input/index.tsx
+++ b/src/components/ui/input/index.tsx
@@ -2,9 +2,9 @@ import { mdiEye, mdiEyeOff } from '@mdi/js';
2import Icon from '@mdi/react'; 2import Icon from '@mdi/react';
3import classnames from 'classnames'; 3import classnames from 'classnames';
4import { Component, createRef, InputHTMLAttributes } from 'react'; 4import { Component, createRef, InputHTMLAttributes } from 'react';
5import injectSheet from 'react-jss'; 5import injectSheet, { WithStylesProps } from 'react-jss';
6 6
7import { IFormField, IWithStyle } from '../typings/generic'; 7import { IFormField } from '../typings/generic';
8 8
9import { Error } from '../error'; 9import { Error } from '../error';
10import { Label } from '../label'; 10import { Label } from '../label';
@@ -20,7 +20,7 @@ interface IData {
20interface IProps 20interface IProps
21 extends InputHTMLAttributes<HTMLInputElement>, 21 extends InputHTMLAttributes<HTMLInputElement>,
22 IFormField, 22 IFormField,
23 IWithStyle { 23 WithStylesProps<typeof styles> {
24 focus?: boolean; 24 focus?: boolean;
25 prefix?: string; 25 prefix?: string;
26 suffix?: string; 26 suffix?: string;
@@ -205,4 +205,4 @@ class InputComponent extends Component<IProps, IState> {
205 } 205 }
206} 206}
207 207
208export const Input = injectSheet(styles)(InputComponent); 208export const Input = injectSheet(styles, { injectTheme: true })(InputComponent);
diff --git a/src/components/ui/label/index.tsx b/src/components/ui/label/index.tsx
index 4d86f23f7..dcc14bff4 100644
--- a/src/components/ui/label/index.tsx
+++ b/src/components/ui/label/index.tsx
@@ -1,15 +1,16 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Classes } from 'jss';
3import { Component, LabelHTMLAttributes } from 'react'; 2import { Component, LabelHTMLAttributes } from 'react';
4import injectSheet from 'react-jss'; 3import injectSheet, { WithStylesProps } from 'react-jss';
5 4
6import { IFormField } from '../typings/generic'; 5import { IFormField } from '../typings/generic';
7 6
8import styles from './styles'; 7import styles from './styles';
9 8
10interface ILabel extends IFormField, LabelHTMLAttributes<HTMLLabelElement> { 9interface ILabel
11 classes: Classes; 10 extends IFormField,
12 isRequired: boolean; 11 LabelHTMLAttributes<HTMLLabelElement>,
12 WithStylesProps<typeof styles> {
13 isRequired?: boolean;
13} 14}
14 15
15class LabelComponent extends Component<ILabel> { 16class LabelComponent extends Component<ILabel> {
@@ -49,4 +50,4 @@ class LabelComponent extends Component<ILabel> {
49 } 50 }
50} 51}
51 52
52export const Label = injectSheet(styles)(LabelComponent); 53export const Label = injectSheet(styles, { injectTheme: true })(LabelComponent);
diff --git a/src/components/ui/loader/index.tsx b/src/components/ui/loader/index.tsx
index 0607bd48b..d56995ccc 100644
--- a/src/components/ui/loader/index.tsx
+++ b/src/components/ui/loader/index.tsx
@@ -1,25 +1,25 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Component } from 'react'; 2import { Component } from 'react';
3import injectStyle, { withTheme } from 'react-jss'; 3import injectStyle, { WithStylesProps } from 'react-jss';
4import ReactLoader from 'react-loader'; 4import ReactLoader from 'react-loader';
5 5
6import { IWithStyle } from '../typings/generic'; 6interface IProps extends WithStylesProps<typeof styles> {
7
8interface IProps extends IWithStyle {
9 className?: string; 7 className?: string;
10 color?: string; 8 color?: string;
11} 9}
12 10
13const styles = () => ({ 11const styles = theme => ({
14 container: { 12 container: {
15 position: 'relative', 13 position: 'relative',
16 height: 60, 14 height: 60,
17 }, 15 },
16 loader: {},
17 color: theme.colorText,
18}); 18});
19 19
20class LoaderComponent extends Component<IProps> { 20class LoaderComponent extends Component<IProps> {
21 render() { 21 render() {
22 const { classes, className, color, theme } = this.props; 22 const { classes, className, color } = this.props;
23 23
24 return ( 24 return (
25 <div 25 <div
@@ -33,7 +33,7 @@ class LoaderComponent extends Component<IProps> {
33 loaded={false} 33 loaded={false}
34 width={4} 34 width={4}
35 scale={0.75} 35 scale={0.75}
36 color={color || theme.colorText} 36 color={color || classes.color}
37 parentClassName={classes.loader} 37 parentClassName={classes.loader}
38 /> 38 />
39 </div> 39 </div>
@@ -41,4 +41,6 @@ class LoaderComponent extends Component<IProps> {
41 } 41 }
42} 42}
43 43
44export const Loader = injectStyle(styles)(withTheme(LoaderComponent)); 44export const Loader = injectStyle(styles, { injectTheme: true })(
45 LoaderComponent,
46);
diff --git a/src/components/ui/select/index.tsx b/src/components/ui/select/index.tsx
index 2605503a3..ac509aa7c 100644
--- a/src/components/ui/select/index.tsx
+++ b/src/components/ui/select/index.tsx
@@ -6,10 +6,10 @@ import {
6import Icon from '@mdi/react'; 6import Icon from '@mdi/react';
7import classnames from 'classnames'; 7import classnames from 'classnames';
8import { ChangeEvent, Component, createRef } from 'react'; 8import { ChangeEvent, Component, createRef } from 'react';
9import injectStyle from 'react-jss'; 9import injectStyle, { WithStylesProps } from 'react-jss';
10 10
11import { Theme } from '../../../themes'; 11import { Theme } from '../../../themes';
12import { IFormField, IWithStyle } from '../typings/generic'; 12import { IFormField } from '../typings/generic';
13 13
14import { Error } from '../error'; 14import { Error } from '../error';
15import { Label } from '../label'; 15import { Label } from '../label';
@@ -23,7 +23,7 @@ interface IData {
23 [index: string]: string; 23 [index: string]: string;
24} 24}
25 25
26interface IProps extends IFormField, IWithStyle { 26interface IProps extends IFormField, WithStylesProps<typeof styles> {
27 actionText: string; 27 actionText: string;
28 className?: string; 28 className?: string;
29 inputClassName?: string; 29 inputClassName?: string;
@@ -146,6 +146,7 @@ const styles = (theme: Theme) => ({
146 disabled: { 146 disabled: {
147 opacity: theme.selectDisabledOpacity, 147 opacity: theme.selectDisabledOpacity,
148 }, 148 },
149 input: {},
149}); 150});
150 151
151class SelectComponent extends Component<IProps> { 152class SelectComponent extends Component<IProps> {
@@ -457,4 +458,6 @@ class SelectComponent extends Component<IProps> {
457 } 458 }
458} 459}
459 460
460export const Select = injectStyle(styles)(SelectComponent); 461export const Select = injectStyle(styles, { injectTheme: true })(
462 SelectComponent,
463);
diff --git a/src/components/ui/textarea/index.tsx b/src/components/ui/textarea/index.tsx
index 1b16698eb..a47465806 100644
--- a/src/components/ui/textarea/index.tsx
+++ b/src/components/ui/textarea/index.tsx
@@ -1,8 +1,8 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Component, createRef, TextareaHTMLAttributes } from 'react'; 2import { Component, createRef, TextareaHTMLAttributes } from 'react';
3import injectSheet from 'react-jss'; 3import injectSheet, { WithStylesProps } from 'react-jss';
4 4
5import { IFormField, IWithStyle } from '../typings/generic'; 5import { IFormField } from '../typings/generic';
6 6
7import { Error } from '../error'; 7import { Error } from '../error';
8import { Label } from '../label'; 8import { Label } from '../label';
@@ -17,7 +17,7 @@ interface IData {
17interface IProps 17interface IProps
18 extends TextareaHTMLAttributes<HTMLTextAreaElement>, 18 extends TextareaHTMLAttributes<HTMLTextAreaElement>,
19 IFormField, 19 IFormField,
20 IWithStyle { 20 WithStylesProps<typeof styles> {
21 focus?: boolean; 21 focus?: boolean;
22 data: IData; 22 data: IData;
23 textareaClassName?: string; 23 textareaClassName?: string;
@@ -123,4 +123,6 @@ class TextareaComponent extends Component<IProps> {
123 } 123 }
124} 124}
125 125
126export const Textarea = injectSheet(styles)(TextareaComponent); 126export const Textarea = injectSheet(styles, { injectTheme: true })(
127 TextareaComponent,
128);
diff --git a/src/components/ui/toggle/index.tsx b/src/components/ui/toggle/index.tsx
index 7b6ba147f..856581a21 100644
--- a/src/components/ui/toggle/index.tsx
+++ b/src/components/ui/toggle/index.tsx
@@ -1,10 +1,10 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Property } from 'csstype'; 2import { Property } from 'csstype';
3import { Component, InputHTMLAttributes } from 'react'; 3import { Component, InputHTMLAttributes } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle, { WithStylesProps } from 'react-jss';
5 5
6import { Theme } from '../../../themes'; 6import { Theme } from '../../../themes';
7import { IFormField, IWithStyle } from '../typings/generic'; 7import { IFormField } from '../typings/generic';
8 8
9import { Error } from '../error'; 9import { Error } from '../error';
10import { Label } from '../label'; 10import { Label } from '../label';
@@ -13,7 +13,7 @@ import { Wrapper } from '../wrapper';
13interface IProps 13interface IProps
14 extends InputHTMLAttributes<HTMLInputElement>, 14 extends InputHTMLAttributes<HTMLInputElement>,
15 IFormField, 15 IFormField,
16 IWithStyle { 16 WithStylesProps<typeof styles> {
17 className?: string; 17 className?: string;
18} 18}
19 19
@@ -122,4 +122,6 @@ class ToggleComponent extends Component<IProps> {
122 } 122 }
123} 123}
124 124
125export const Toggle = injectStyle(styles)(ToggleComponent); 125export const Toggle = injectStyle(styles, { injectTheme: true })(
126 ToggleComponent,
127);
diff --git a/src/components/ui/typings/generic.ts b/src/components/ui/typings/generic.ts
index 65b996d59..3aec0bc40 100644
--- a/src/components/ui/typings/generic.ts
+++ b/src/components/ui/typings/generic.ts
@@ -1,7 +1,3 @@
1import { Classes } from 'jss';
2
3import { Theme } from '../../../themes';
4
5export interface IFormField { 1export interface IFormField {
6 showLabel?: boolean; 2 showLabel?: boolean;
7 label?: string; 3 label?: string;
@@ -10,10 +6,5 @@ export interface IFormField {
10 noMargin?: boolean; 6 noMargin?: boolean;
11} 7}
12 8
13export interface IWithStyle {
14 classes: Classes;
15 theme: Theme;
16}
17
18export type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N; 9export type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;
19export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; 10export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
diff --git a/src/components/ui/wrapper/index.tsx b/src/components/ui/wrapper/index.tsx
index ffcd6fe0b..bc385d319 100644
--- a/src/components/ui/wrapper/index.tsx
+++ b/src/components/ui/wrapper/index.tsx
@@ -1,9 +1,8 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Component, ReactNode } from 'react'; 2import { Component, ReactNode } from 'react';
3import injectStyle from 'react-jss'; 3import injectStyle, { WithStylesProps } from 'react-jss';
4import { IWithStyle } from '../typings/generic';
5 4
6interface IProps extends IWithStyle { 5interface IProps extends WithStylesProps<typeof styles> {
7 children: ReactNode; 6 children: ReactNode;
8 className?: string; 7 className?: string;
9 identifier: string; 8 identifier: string;
@@ -34,4 +33,6 @@ class WrapperComponent extends Component<IProps> {
34 } 33 }
35} 34}
36 35
37export const Wrapper = injectStyle(styles)(WrapperComponent); 36export const Wrapper = injectStyle(styles, { injectTheme: true })(
37 WrapperComponent,
38);
diff --git a/src/components/util/ErrorBoundary/index.js b/src/components/util/ErrorBoundary/index.js
index cddcd91c2..6a8b126f1 100644
--- a/src/components/util/ErrorBoundary/index.js
+++ b/src/components/util/ErrorBoundary/index.js
@@ -18,7 +18,6 @@ const messages = defineMessages({
18 }, 18 },
19}); 19});
20 20
21@injectSheet(styles)
22class ErrorBoundary extends Component { 21class ErrorBoundary extends Component {
23 state = { 22 state = {
24 hasError: false, 23 hasError: false,
@@ -56,4 +55,6 @@ class ErrorBoundary extends Component {
56 } 55 }
57} 56}
58 57
59export default injectIntl(ErrorBoundary); 58export default injectIntl(
59 injectSheet(styles, { injectTheme: true })(ErrorBoundary),
60);