aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-12-09 20:48:25 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2018-12-09 20:48:25 +0100
commit5d6164973e92fa8a3e3c18a0eb2e29494aea4f48 (patch)
tree382e6c672bbc0f7582b3b627b02111dcce902894
parentAdd React 16 didCatch/ErrorBoundary component (diff)
downloadferdium-app-5d6164973e92fa8a3e3c18a0eb2e29494aea4f48.tar.gz
ferdium-app-5d6164973e92fa8a3e3c18a0eb2e29494aea4f48.tar.zst
ferdium-app-5d6164973e92fa8a3e3c18a0eb2e29494aea4f48.zip
Fix linting issues
-rw-r--r--.eslintrc20
-rw-r--r--src/api/server/ServerApi.js13
-rw-r--r--src/app.js4
-rw-r--r--src/components/auth/AuthLayout.js6
-rw-r--r--src/components/auth/Invite.js26
-rw-r--r--src/components/auth/Login.js6
-rw-r--r--src/components/auth/Pricing.js23
-rw-r--r--src/components/auth/Signup.js3
-rw-r--r--src/components/layout/AppLayout.js6
-rw-r--r--src/components/layout/Sidebar.js3
-rw-r--r--src/components/services/content/ErrorHandlers/WebviewErrorHandler.js9
-rw-r--r--src/components/services/content/ServiceDisabled.js1
-rw-r--r--src/components/services/content/ServiceWebview.js9
-rw-r--r--src/components/services/content/Services.js3
-rw-r--r--src/components/services/content/WebviewCrashHandler.js24
-rw-r--r--src/components/services/tabs/Tabbar.js2
-rw-r--r--src/components/settings/SettingsLayout.js2
-rw-r--r--src/components/settings/account/AccountDashboard.js4
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js5
-rw-r--r--src/components/settings/recipes/RecipeItem.js1
-rw-r--r--src/components/settings/recipes/RecipesDashboard.js10
-rw-r--r--src/components/settings/services/EditServiceForm.js1
-rw-r--r--src/components/settings/services/ServiceItem.js1
-rw-r--r--src/components/settings/settings/EditSettingsForm.js8
-rw-r--r--src/components/settings/user/EditUserForm.js4
-rw-r--r--src/components/subscription/SubscriptionForm.js3
-rw-r--r--src/components/subscription/SubscriptionPopup.js4
-rw-r--r--src/components/ui/AppLoader/index.js11
-rw-r--r--src/components/ui/Button.js3
-rw-r--r--src/components/ui/FullscreenLoader/index.js7
-rw-r--r--src/components/ui/ImageUpload.js4
-rw-r--r--src/components/ui/InfoBar.js4
-rw-r--r--src/components/ui/Infobox.js2
-rw-r--r--src/components/ui/Input.js6
-rw-r--r--src/components/ui/Link.js1
-rw-r--r--src/components/ui/PremiumFeatureContainer/index.js1
-rw-r--r--src/components/ui/Radio.js4
-rw-r--r--src/components/ui/SearchInput.js27
-rw-r--r--src/components/ui/Select.js1
-rw-r--r--src/components/ui/StatusBarTargetUrl.js3
-rw-r--r--src/components/util/ErrorBoundary/index.js18
-rw-r--r--src/components/util/ErrorBoundary/styles.js4
-rw-r--r--src/containers/auth/AuthLayoutContainer.js4
-rw-r--r--src/containers/settings/RecipesScreen.js10
-rw-r--r--src/containers/subscription/SubscriptionFormScreen.js2
-rw-r--r--src/electron/Settings.js1
-rw-r--r--src/electron/ipc-api/download.js2
-rw-r--r--src/features/delayApp/Component.js19
-rw-r--r--src/features/delayApp/index.js1
-rw-r--r--src/features/serviceProxy/index.js1
-rw-r--r--src/helpers/i18n-helpers.js4
-rw-r--r--src/index.js8
-rw-r--r--src/lib/Tray.js10
-rw-r--r--src/models/News.js3
-rw-r--r--src/models/Order.js5
-rw-r--r--src/models/Plan.js1
-rw-r--r--src/models/Recipe.js12
-rw-r--r--src/models/RecipePreview.js6
-rw-r--r--src/models/Service.js21
-rw-r--r--src/models/User.js17
-rw-r--r--src/stores/AppStore.js16
-rw-r--r--src/stores/FeaturesStore.js1
-rw-r--r--src/stores/GlobalErrorStore.js1
-rw-r--r--src/stores/NewsStore.js1
-rw-r--r--src/stores/PaymentStore.js3
-rw-r--r--src/stores/RecipePreviewsStore.js2
-rw-r--r--src/stores/RecipesStore.js2
-rw-r--r--src/stores/RequestStore.js3
-rw-r--r--src/stores/ServicesStore.js9
-rw-r--r--src/stores/SettingsStore.js2
-rw-r--r--src/stores/UserStore.js23
-rw-r--r--src/stores/lib/CachedRequest.js1
-rw-r--r--src/stores/lib/Reaction.js2
-rw-r--r--src/stores/lib/Request.js8
-rw-r--r--src/stores/lib/Store.js4
-rw-r--r--src/styles/searchInput.scss4
-rw-r--r--src/theme/dark/index.js1
-rw-r--r--src/theme/default/index.js1
-rw-r--r--src/webview/contextMenu.js4
-rw-r--r--src/webview/recipe.js3
80 files changed, 366 insertions, 149 deletions
diff --git a/.eslintrc b/.eslintrc
index 948550306..1843e560e 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -14,6 +14,8 @@
14 "extensions": [".js", ".jsx"] 14 "extensions": [".js", ".jsx"]
15 }], 15 }],
16 "react/forbid-prop-types": 1, 16 "react/forbid-prop-types": 1,
17 "react/destructuring-assignment": 1,
18 "prefer-destructuring": 1,
17 "no-underscore-dangle": 0, 19 "no-underscore-dangle": 0,
18 "max-len": 0, 20 "max-len": 0,
19 "class-methods-use-this": 0, 21 "class-methods-use-this": 0,
@@ -21,7 +23,23 @@
21 "react/jsx-no-bind": 0, 23 "react/jsx-no-bind": 0,
22 "jsx-a11y/no-static-element-interactions": 0, 24 "jsx-a11y/no-static-element-interactions": 0,
23 "react/jsx-no-target-blank": 0, 25 "react/jsx-no-target-blank": 0,
24 "no-restricted-syntax": [0, "ForInStatement"] 26 "no-restricted-syntax": [0, "ForInStatement"],
27 "jsx-a11y/no-noninteractive-element-interactions": 1,
28 "jsx-a11y/label-has-for": [
29 2,
30 {
31 "components": [
32 "Label"
33 ],
34 "required": {
35 "every": [
36 "id"
37 ]
38 },
39 "allowChildren": false
40 }
41 ],
42 "jsx-a11y/click-events-have-key-events": 1
25 }, 43 },
26 "globals": { 44 "globals": {
27 "window": true, 45 "window": true,
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js
index 164419951..2871769a9 100644
--- a/src/api/server/ServerApi.js
+++ b/src/api/server/ServerApi.js
@@ -42,6 +42,7 @@ const API_VERSION = 'v1';
42 42
43export default class ServerApi { 43export default class ServerApi {
44 recipePreviews = []; 44 recipePreviews = [];
45
45 recipes = []; 46 recipes = [];
46 47
47 // User 48 // User
@@ -522,8 +523,7 @@ export default class ServerApi {
522 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/${s.service}`, 523 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/${s.service}`,
523 this._prepareAuthRequest({ 524 this._prepareAuthRequest({
524 method: 'GET', 525 method: 'GET',
525 }), 526 }));
526 );
527 527
528 if (request.status === 200) { 528 if (request.status === 200) {
529 const data = await request.json(); 529 const data = await request.json();
@@ -549,9 +549,9 @@ export default class ServerApi {
549 549
550 await this._bulkRecipeCheck(recipes); 550 await this._bulkRecipeCheck(recipes);
551 551
552 return Promise.all(services 552 /* eslint-disable no-return-await */
553 .map(async service => await this._prepareServiceModel(service)) // eslint-disable-line 553 return Promise.all(services.map(async service => await this._prepareServiceModel(service)));
554 ); 554 /* eslint-enable no-return-await */
555 } 555 }
556 556
557 async _prepareServiceModel(service) { 557 async _prepareServiceModel(service) {
@@ -596,8 +596,7 @@ export default class ServerApi {
596 } 596 }
597 597
598 return recipe; 598 return recipe;
599 }), 599 })).catch(err => console.error('Can\'t load recipe', err));
600 ).catch(err => console.error('Can\'t load recipe', err));
601 } 600 }
602 601
603 _mapRecipePreviewModel(recipes) { 602 _mapRecipePreviewModel(recipes) {
diff --git a/src/app.js b/src/app.js
index 43d0cf018..831dd93ce 100644
--- a/src/app.js
+++ b/src/app.js
@@ -4,7 +4,9 @@ import React from 'react';
4import { render } from 'react-dom'; 4import { render } from 'react-dom';
5import { Provider } from 'mobx-react'; 5import { Provider } from 'mobx-react';
6import { syncHistoryWithStore, RouterStore } from 'mobx-react-router'; 6import { syncHistoryWithStore, RouterStore } from 'mobx-react-router';
7import { Router, Route, hashHistory, IndexRedirect } from 'react-router'; 7import {
8 Router, Route, hashHistory, IndexRedirect,
9} from 'react-router';
8 10
9import '@babel/polyfill'; 11import '@babel/polyfill';
10import smoothScroll from 'smoothscroll-polyfill'; 12import smoothScroll from 'smoothscroll-polyfill';
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js
index 4e1b0c52e..ac8fdbe5b 100644
--- a/src/components/auth/AuthLayout.js
+++ b/src/components/auth/AuthLayout.js
@@ -15,7 +15,6 @@ import { isWindows } from '../../environment';
15export default @observer class AuthLayout extends Component { 15export default @observer class AuthLayout extends Component {
16 static propTypes = { 16 static propTypes = {
17 children: oneOrManyChildElements.isRequired, 17 children: oneOrManyChildElements.isRequired,
18 pathname: PropTypes.string.isRequired,
19 error: globalErrorPropType.isRequired, 18 error: globalErrorPropType.isRequired,
20 isOnline: PropTypes.bool.isRequired, 19 isOnline: PropTypes.bool.isRequired,
21 isAPIHealthy: PropTypes.bool.isRequired, 20 isAPIHealthy: PropTypes.bool.isRequired,
@@ -32,7 +31,6 @@ export default @observer class AuthLayout extends Component {
32 render() { 31 render() {
33 const { 32 const {
34 children, 33 children,
35 pathname,
36 error, 34 error,
37 isOnline, 35 isOnline,
38 isAPIHealthy, 36 isAPIHealthy,
@@ -45,8 +43,8 @@ export default @observer class AuthLayout extends Component {
45 43
46 return ( 44 return (
47 <div className={darkMode ? 'theme__dark' : ''}> 45 <div className={darkMode ? 'theme__dark' : ''}>
48 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />} 46 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />}
49 <div className={'auth'}> 47 <div className="auth">
50 {!isOnline && ( 48 {!isOnline && (
51 <InfoBar 49 <InfoBar
52 type="warning" 50 type="warning"
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index 5da89f2ce..fd957ee73 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -141,11 +141,13 @@ export default @observer class Invite extends Component {
141 )} 141 )}
142 142
143 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 143 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
144 {!embed && (<img 144 {!embed && (
145 src="./assets/images/logo.svg" 145 <img
146 className="auth__logo" 146 src="./assets/images/logo.svg"
147 alt="" 147 className="auth__logo"
148 />)} 148 alt=""
149 />
150 )}
149 <h1 className={embed && 'invite__embed'}> 151 <h1 className={embed && 'invite__embed'}>
150 {intl.formatMessage(messages.headline)} 152 {intl.formatMessage(messages.headline)}
151 </h1> 153 </h1>
@@ -164,12 +166,14 @@ export default @observer class Invite extends Component {
164 label={intl.formatMessage(messages.submitButtonLabel)} 166 label={intl.formatMessage(messages.submitButtonLabel)}
165 loaded={!isLoadingInvite} 167 loaded={!isLoadingInvite}
166 /> 168 />
167 {!embed && (<Link 169 {!embed && (
168 to="/" 170 <Link
169 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" 171 to="/"
170 > 172 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip"
171 {intl.formatMessage(messages.skipButtonLabel)} 173 >
172 </Link>)} 174 {intl.formatMessage(messages.skipButtonLabel)}
175 </Link>
176 )}
173 </form> 177 </form>
174 </Fragment> 178 </Fragment>
175 ); 179 );
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 2cf614041..5d21f8b60 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -83,18 +83,18 @@ export default @observer class Login extends Component {
83 }, 83 },
84 }, this.context.intl); 84 }, this.context.intl);
85 85
86 emailField = null;
87
86 submit(e) { 88 submit(e) {
87 e.preventDefault(); 89 e.preventDefault();
88 this.form.submit({ 90 this.form.submit({
89 onSuccess: (form) => { 91 onSuccess: (form) => {
90 this.props.onSubmit(form.values()); 92 this.props.onSubmit(form.values());
91 }, 93 },
92 onError: () => {}, 94 onError: () => { },
93 }); 95 });
94 } 96 }
95 97
96 emailField = null;
97
98 render() { 98 render() {
99 const { form } = this; 99 const { form } = this;
100 const { intl } = this.context; 100 const { intl } = this.context;
diff --git a/src/components/auth/Pricing.js b/src/components/auth/Pricing.js
index f08129568..7ab14f429 100644
--- a/src/components/auth/Pricing.js
+++ b/src/components/auth/Pricing.js
@@ -69,18 +69,29 @@ export default @observer class Signup extends Component {
69 donor.amount ? ( 69 donor.amount ? (
70 <span> 70 <span>
71 <p> 71 <p>
72 Thank you so much for your previous donation of <strong>$ {donor.amount}</strong>. 72 Thank you so much for your previous donation of
73 {' '}
74 <strong>
75 $
76 {donor.amount}
77 </strong>
78 .
73 <br /> 79 <br />
74 Your support allowed us to get where we are today. 80 Your support allowed us to get where we are today.
75 <br /> 81 <br />
76 </p> 82 </p>
77 <p> 83 <p>
78 As an early supporter, you get <strong>a lifetime premium supporter license</strong> without any 84 As an early supporter, you get
85 {' '}
86 <strong>a lifetime premium supporter license</strong>
87 {' '}
88 without any
79 additional charges. 89 additional charges.
80 </p> 90 </p>
81 <p> 91 <p>
82 However, If you want to keep supporting us, you are more than welcome to subscribe to a plan. 92 However, If you want to keep supporting us, you are more than welcome to subscribe to a plan.
83 <br /><br /> 93 <br />
94 <br />
84 </p> 95 </p>
85 </span> 96 </span>
86 ) : ( 97 ) : (
@@ -113,12 +124,6 @@ export default @observer class Signup extends Component {
113 hideInfo={Boolean(donor.amount)} 124 hideInfo={Boolean(donor.amount)}
114 skipButtonLabel={intl.formatMessage(messages.skipPayment)} 125 skipButtonLabel={intl.formatMessage(messages.skipPayment)}
115 /> 126 />
116 {/* <Link
117 to={inviteRoute}
118 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip"
119 >
120 {intl.formatMessage(messages.skipPayment)}
121 </Link> */}
122 </Appear> 127 </Appear>
123 </Loader> 128 </Loader>
124 </form> 129 </form>
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js
index bbcad8b67..d9b83eeb8 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.js
@@ -199,7 +199,8 @@ export default @observer class Signup extends Component {
199 className="link" 199 className="link"
200 > 200 >
201 {intl.formatMessage(messages.privacy)} 201 {intl.formatMessage(messages.privacy)}
202 </Link>. 202 </Link>
203 .
203 </p> 204 </p>
204 </form> 205 </form>
205 <div className="auth__links"> 206 <div className="auth__links">
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index e526f6b1f..dbe0bb4b6 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -99,7 +99,7 @@ export default @observer class AppLayout extends Component {
99 <ErrorBoundary> 99 <ErrorBoundary>
100 <div className={(darkMode ? 'theme__dark' : '')}> 100 <div className={(darkMode ? 'theme__dark' : '')}>
101 <div className="app"> 101 <div className="app">
102 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />} 102 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />}
103 <div className="app__content"> 103 <div className="app__content">
104 {sidebar} 104 {sidebar}
105 <div className="app__service"> 105 <div className="app__service">
@@ -153,7 +153,9 @@ export default @observer class AppLayout extends Component {
153 sticky 153 sticky
154 > 154 >
155 <span className="mdi mdi-information" /> 155 <span className="mdi mdi-information" />
156 {intl.formatMessage(messages.updateAvailable)} <a href="https://meetfranz.com/changelog" target="_blank"> 156 {intl.formatMessage(messages.updateAvailable)}
157 {' '}
158 <a href="https://meetfranz.com/changelog" target="_blank">
157 <u>{intl.formatMessage(messages.changelog)}</u> 159 <u>{intl.formatMessage(messages.changelog)}</u>
158 </a> 160 </a>
159 </InfoBar> 161 </InfoBar>
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 6ea95bf88..609a3b604 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -65,6 +65,7 @@ export default @observer class Sidebar extends Component {
65 disableToolTip={() => this.disableToolTip()} 65 disableToolTip={() => this.disableToolTip()}
66 /> 66 />
67 <button 67 <button
68 type="button"
68 onClick={toggleMuteApp} 69 onClick={toggleMuteApp}
69 className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} 70 className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`}
70 data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`} 71 data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`}
@@ -72,6 +73,7 @@ export default @observer class Sidebar extends Component {
72 <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> 73 <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} />
73 </button> 74 </button>
74 <button 75 <button
76 type="button"
75 onClick={() => openSettings({ path: 'recipes' })} 77 onClick={() => openSettings({ path: 'recipes' })}
76 className="sidebar__button sidebar__button--new-service" 78 className="sidebar__button sidebar__button--new-service"
77 data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`} 79 data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`}
@@ -79,6 +81,7 @@ export default @observer class Sidebar extends Component {
79 <i className="mdi mdi-plus-box" /> 81 <i className="mdi mdi-plus-box" />
80 </button> 82 </button>
81 <button 83 <button
84 type="button"
82 onClick={() => openSettings({ path: 'app' })} 85 onClick={() => openSettings({ path: 'app' })}
83 className="sidebar__button sidebar__button--settings" 86 className="sidebar__button sidebar__button--settings"
84 data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`} 87 data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`}
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
index df98bf835..415a8d1b5 100644
--- a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
+++ b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
@@ -58,7 +58,14 @@ export default @injectSheet(styles) @observer class WebviewCrashHandler extends
58 <div className={classes.component}> 58 <div className={classes.component}>
59 <h1>{intl.formatMessage(messages.headline)}</h1> 59 <h1>{intl.formatMessage(messages.headline)}</h1>
60 <p>{intl.formatMessage(messages.text, { name })}</p> 60 <p>{intl.formatMessage(messages.text, { name })}</p>
61 <p><strong>{intl.formatMessage(messages.errorMessage)}:</strong> {errorMessage}</p> 61 <p>
62 <strong>
63 {intl.formatMessage(messages.errorMessage)}
64:
65 </strong>
66 {' '}
67 {errorMessage}
68 </p>
62 <div className={classes.buttonContainer}> 69 <div className={classes.buttonContainer}>
63 <Button 70 <Button
64 label={intl.formatMessage(messages.editAction, { name })} 71 label={intl.formatMessage(messages.editAction, { name })}
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
index 58fb38d8c..d0f12256e 100644
--- a/src/components/services/content/ServiceDisabled.js
+++ b/src/components/services/content/ServiceDisabled.js
@@ -27,6 +27,7 @@ export default @observer class ServiceDisabled extends Component {
27 }; 27 };
28 28
29 countdownInterval = null; 29 countdownInterval = null;
30
30 countdownIntervalTimeout = 1000; 31 countdownIntervalTimeout = 1000;
31 32
32 render() { 33 render() {
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 98daf9b9f..a2ae5a562 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -20,6 +20,7 @@ export default @observer class ServiceWebview extends Component {
20 edit: PropTypes.func.isRequired, 20 edit: PropTypes.func.isRequired,
21 isAppMuted: PropTypes.bool.isRequired, 21 isAppMuted: PropTypes.bool.isRequired,
22 enable: PropTypes.func.isRequired, 22 enable: PropTypes.func.isRequired,
23 isActive: PropTypes.bool,
23 }; 24 };
24 25
25 static defaultProps = { 26 static defaultProps = {
@@ -32,6 +33,10 @@ export default @observer class ServiceWebview extends Component {
32 statusBarVisible: false, 33 statusBarVisible: false,
33 }; 34 };
34 35
36 autorunDisposer = null;
37
38 webview = null;
39
35 componentDidMount() { 40 componentDidMount() {
36 this.autorunDisposer = autorun(() => { 41 this.autorunDisposer = autorun(() => {
37 if (this.props.service.isActive) { 42 if (this.props.service.isActive) {
@@ -58,10 +63,6 @@ export default @observer class ServiceWebview extends Component {
58 }); 63 });
59 } 64 }
60 65
61 autorunDisposer = null;
62
63 webview = null;
64
65 render() { 66 render() {
66 const { 67 const {
67 service, 68 service,
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 0d4d778cd..1aeb17e03 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -20,7 +20,7 @@ const messages = defineMessages({
20 20
21export default @observer class Services extends Component { 21export default @observer class Services extends Component {
22 static propTypes = { 22 static propTypes = {
23 services: MobxPropTypes.arrayOrObservableArray.isRequired, 23 services: MobxPropTypes.arrayOrObservableArray,
24 setWebviewReference: PropTypes.func.isRequired, 24 setWebviewReference: PropTypes.func.isRequired,
25 handleIPCMessage: PropTypes.func.isRequired, 25 handleIPCMessage: PropTypes.func.isRequired,
26 openWindow: PropTypes.func.isRequired, 26 openWindow: PropTypes.func.isRequired,
@@ -32,7 +32,6 @@ export default @observer class Services extends Component {
32 32
33 static defaultProps = { 33 static defaultProps = {
34 services: [], 34 services: [],
35 activeService: '',
36 }; 35 };
37 36
38 static contextTypes = { 37 static contextTypes = {
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index 3be1fccf4..42bc3c877 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -38,13 +38,18 @@ export default @observer class WebviewCrashHandler extends Component {
38 countdown: 10000, 38 countdown: 10000,
39 } 39 }
40 40
41 countdownInterval = null;
42
43 countdownIntervalTimeout = 1000;
44
45
41 componentDidMount() { 46 componentDidMount() {
42 const { reload } = this.props; 47 const { reload } = this.props;
43 48
44 this.countdownInterval = setInterval(() => { 49 this.countdownInterval = setInterval(() => {
45 this.setState({ 50 this.setState(prevState => ({
46 countdown: this.state.countdown - this.countdownIntervalTimeout, 51 countdown: prevState.countdown - this.countdownIntervalTimeout,
47 }); 52 }));
48 53
49 if (this.state.countdown <= 0) { 54 if (this.state.countdown <= 0) {
50 reload(); 55 reload();
@@ -53,9 +58,6 @@ export default @observer class WebviewCrashHandler extends Component {
53 }, this.countdownIntervalTimeout); 58 }, this.countdownIntervalTimeout);
54 } 59 }
55 60
56 countdownInterval = null;
57 countdownIntervalTimeout = 1000;
58
59 render() { 61 render() {
60 const { name, reload } = this.props; 62 const { name, reload } = this.props;
61 const { intl } = this.context; 63 const { intl } = this.context;
@@ -70,10 +72,12 @@ export default @observer class WebviewCrashHandler extends Component {
70 buttonType="inverted" 72 buttonType="inverted"
71 onClick={() => reload()} 73 onClick={() => reload()}
72 /> 74 />
73 <p className="footnote">{intl.formatMessage(messages.autoReload, { 75 <p className="footnote">
74 name, 76 {intl.formatMessage(messages.autoReload, {
75 seconds: this.state.countdown / 1000, 77 name,
76 })}</p> 78 seconds: this.state.countdown / 1000,
79 })}
80 </p>
77 </div> 81 </div>
78 ); 82 );
79 } 83 }
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index 27f555428..dd5c2140f 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -1,4 +1,4 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4 4
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js
index d5d8f0bb0..72ba7b2e3 100644
--- a/src/components/settings/SettingsLayout.js
+++ b/src/components/settings/SettingsLayout.js
@@ -39,6 +39,7 @@ export default @observer class SettingsLayout extends Component {
39 <div className="settings-wrapper"> 39 <div className="settings-wrapper">
40 <ErrorBoundary> 40 <ErrorBoundary>
41 <button 41 <button
42 type="button"
42 className="settings-wrapper__action" 43 className="settings-wrapper__action"
43 onClick={closeSettings} 44 onClick={closeSettings}
44 /> 45 />
@@ -46,6 +47,7 @@ export default @observer class SettingsLayout extends Component {
46 {navigation} 47 {navigation}
47 {children} 48 {children}
48 <button 49 <button
50 type="button"
49 className="settings__close mdi mdi-close" 51 className="settings__close mdi mdi-close"
50 onClick={closeSettings} 52 onClick={closeSettings}
51 /> 53 />
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 43b8387c6..9c9543749 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -167,7 +167,8 @@ export default @observer class AccountDashboard extends Component {
167 {`${user.firstname} ${user.lastname}`} 167 {`${user.firstname} ${user.lastname}`}
168 </h2> 168 </h2>
169 {user.organization && `${user.organization}, `} 169 {user.organization && `${user.organization}, `}
170 {user.email}<br /> 170 {user.email}
171 <br />
171 {!user.isEnterprise && !user.isPremium && ( 172 {!user.isEnterprise && !user.isPremium && (
172 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span> 173 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span>
173 )} 174 )}
@@ -217,6 +218,7 @@ export default @observer class AccountDashboard extends Component {
217 </td> 218 </td>
218 <td className="invoices__action"> 219 <td className="invoices__action">
219 <button 220 <button
221 type="button"
220 onClick={() => openExternalUrl(order.invoiceUrl)} 222 onClick={() => openExternalUrl(order.invoiceUrl)}
221 > 223 >
222 {intl.formatMessage(messages.invoiceDownload)} 224 {intl.formatMessage(messages.invoiceDownload)}
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index b86d94ac7..953f702f8 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -59,7 +59,9 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
59 className="settings-navigation__link" 59 className="settings-navigation__link"
60 activeClassName="is-active" 60 activeClassName="is-active"
61 > 61 >
62 {intl.formatMessage(messages.yourServices)} <span className="badge">{serviceCount}</span> 62 {intl.formatMessage(messages.yourServices)}
63 {' '}
64 <span className="badge">{serviceCount}</span>
63 </Link> 65 </Link>
64 <Link 66 <Link
65 to="/settings/user" 67 to="/settings/user"
@@ -93,4 +95,3 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
93 ); 95 );
94 } 96 }
95} 97}
96
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js
index dae8891b3..3bb0852b2 100644
--- a/src/components/settings/recipes/RecipeItem.js
+++ b/src/components/settings/recipes/RecipeItem.js
@@ -15,6 +15,7 @@ export default @observer class RecipeItem extends Component {
15 15
16 return ( 16 return (
17 <button 17 <button
18 type="button"
18 className="recipe-teaser" 19 className="recipe-teaser"
19 onClick={onClick} 20 onClick={onClick}
20 > 21 >
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js
index cd783200f..00cd725cf 100644
--- a/src/components/settings/recipes/RecipesDashboard.js
+++ b/src/components/settings/recipes/RecipesDashboard.js
@@ -129,11 +129,17 @@ export default @observer class RecipesDashboard extends Component {
129 activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`} 129 activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`}
130 onClick={() => resetSearch()} 130 onClick={() => resetSearch()}
131 > 131 >
132 {intl.formatMessage(messages.devRecipes)} ({devRecipesCount}) 132 {intl.formatMessage(messages.devRecipes)}
133 {' '}
134(
135 {devRecipesCount}
136)
133 </Link> 137 </Link>
134 )} 138 )}
135 <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request"> 139 <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request">
136 {intl.formatMessage(messages.missingService)} <i className="mdi mdi-open-in-new" /> 140 {intl.formatMessage(messages.missingService)}
141 {' '}
142 <i className="mdi mdi-open-in-new" />
137 </a> 143 </a>
138 </div> 144 </div>
139 {/* )} */} 145 {/* )} */}
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index a7c656acd..fac25c160 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -130,6 +130,7 @@ export default @observer class EditServiceForm extends Component {
130 static defaultProps = { 130 static defaultProps = {
131 service: {}, 131 service: {},
132 }; 132 };
133
133 static contextTypes = { 134 static contextTypes = {
134 intl: intlShape, 135 intl: intlShape,
135 }; 136 };
diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js
index 84080519b..ebc618a00 100644
--- a/src/components/settings/services/ServiceItem.js
+++ b/src/components/settings/services/ServiceItem.js
@@ -27,6 +27,7 @@ export default @observer class ServiceItem extends Component {
27 service: PropTypes.instanceOf(ServiceModel).isRequired, 27 service: PropTypes.instanceOf(ServiceModel).isRequired,
28 goToServiceForm: PropTypes.func.isRequired, 28 goToServiceForm: PropTypes.func.isRequired,
29 }; 29 };
30
30 static contextTypes = { 31 static contextTypes = {
31 intl: intlShape, 32 intl: intlShape,
32 }; 33 };
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index df3197520..a92e559f3 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -185,7 +185,9 @@ export default @observer class EditSettingsForm extends Component {
185 target="_blank" 185 target="_blank"
186 className="link" 186 className="link"
187 > 187 >
188 {intl.formatMessage(messages.translationHelp)} <i className="mdi mdi-open-in-new" /> 188 {intl.formatMessage(messages.translationHelp)}
189 {' '}
190 <i className="mdi mdi-open-in-new" />
189 </a> 191 </a>
190 192
191 {/* Advanced */} 193 {/* Advanced */}
@@ -233,7 +235,9 @@ export default @observer class EditSettingsForm extends Component {
233 )} 235 )}
234 <br /> 236 <br />
235 <Toggle field={form.$('beta')} /> 237 <Toggle field={form.$('beta')} />
236 {intl.formatMessage(messages.currentVersion)} {remote.app.getVersion()} 238 {intl.formatMessage(messages.currentVersion)}
239 {' '}
240 {remote.app.getVersion()}
237 </form> 241 </form>
238 </div> 242 </div>
239 </div> 243 </div>
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index b825f844a..0e3ac6b10 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -48,10 +48,6 @@ export default @observer class EditServiceForm extends Component {
48 isEnterprise: PropTypes.bool.isRequired, 48 isEnterprise: PropTypes.bool.isRequired,
49 }; 49 };
50 50
51 static defaultProps = {
52 service: {},
53 };
54
55 static contextTypes = { 51 static contextTypes = {
56 intl: intlShape, 52 intl: intlShape,
57 }; 53 };
diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js
index 6b60c2af0..90da8ddc3 100644
--- a/src/components/subscription/SubscriptionForm.js
+++ b/src/components/subscription/SubscriptionForm.js
@@ -81,8 +81,7 @@ export default @observer class SubscriptionForm extends Component {
81 hideInfo: PropTypes.bool.isRequired, 81 hideInfo: PropTypes.bool.isRequired,
82 }; 82 };
83 83
84 static defaultProps ={ 84 static defaultProps = {
85 content: '',
86 showSkipOption: false, 85 showSkipOption: false,
87 skipAction: () => null, 86 skipAction: () => null,
88 skipButtonLabel: '', 87 skipButtonLabel: '',
diff --git a/src/components/subscription/SubscriptionPopup.js b/src/components/subscription/SubscriptionPopup.js
index f3c63e7ee..b5d7c4b2d 100644
--- a/src/components/subscription/SubscriptionPopup.js
+++ b/src/components/subscription/SubscriptionPopup.js
@@ -46,7 +46,9 @@ export default @observer class SubscriptionPopup extends Component {
46 } 46 }
47 47
48 render() { 48 render() {
49 const { url, closeWindow, completeCheck, isCompleted } = this.props; 49 const {
50 url, closeWindow, completeCheck, isCompleted,
51 } = this.props;
50 const { intl } = this.context; 52 const { intl } = this.context;
51 53
52 return ( 54 return (
diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js
index 31db3d52c..1b9d044f4 100644
--- a/src/components/ui/AppLoader/index.js
+++ b/src/components/ui/AppLoader/index.js
@@ -28,11 +28,13 @@ export default @injectSheet(styles) class AppLoader extends Component {
28 step: 0, 28 step: 0,
29 } 29 }
30 30
31 interval = null;
32
31 componentDidMount() { 33 componentDidMount() {
32 this.interval = setInterval(() => { 34 this.interval = setInterval(() => {
33 this.setState({ 35 this.setState(prevState => ({
34 step: this.state.step === textList.length - 1 ? 0 : this.state.step + 1, 36 step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1,
35 }); 37 }));
36 }, 2500); 38 }, 2500);
37 } 39 }
38 40
@@ -40,8 +42,6 @@ export default @injectSheet(styles) class AppLoader extends Component {
40 clearInterval(this.interval); 42 clearInterval(this.interval);
41 } 43 }
42 44
43 interval = null;
44
45 render() { 45 render() {
46 const { classes } = this.props; 46 const { classes } = this.props;
47 const { step } = this.state; 47 const { step } = this.state;
@@ -66,4 +66,3 @@ export default @injectSheet(styles) class AppLoader extends Component {
66 ); 66 );
67 } 67 }
68} 68}
69
diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js
index 309e05bb4..ffc7f7051 100644
--- a/src/components/ui/Button.js
+++ b/src/components/ui/Button.js
@@ -62,6 +62,8 @@ export default @observer class Button extends Component {
62 } 62 }
63 63
64 return ( 64 return (
65 // disabling rule as button has type defined in `buttonProps`
66 /* eslint-disable react/button-has-type */
65 <button {...buttonProps}> 67 <button {...buttonProps}>
66 <Loader 68 <Loader
67 loaded={loaded} 69 loaded={loaded}
@@ -72,6 +74,7 @@ export default @observer class Button extends Component {
72 /> 74 />
73 {label} 75 {label}
74 </button> 76 </button>
77 /* eslint-enable react/button-has-type */
75 ); 78 );
76 } 79 }
77} 80}
diff --git a/src/components/ui/FullscreenLoader/index.js b/src/components/ui/FullscreenLoader/index.js
index 36cd32d2a..e0a24a527 100644
--- a/src/components/ui/FullscreenLoader/index.js
+++ b/src/components/ui/FullscreenLoader/index.js
@@ -7,7 +7,9 @@ import Loader from '../Loader';
7 7
8import styles from './styles'; 8import styles from './styles';
9 9
10export default inject('stores')(injectSheet(styles)(({ stores, classes, className, title, children }) => ( 10export default inject('stores')(injectSheet(styles)(({
11 stores, classes, className, title, children,
12}) => (
11 <div className={classes.wrapper}> 13 <div className={classes.wrapper}>
12 <div 14 <div
13 className={classnames({ 15 className={classnames({
@@ -24,5 +26,4 @@ export default inject('stores')(injectSheet(styles)(({ stores, classes, classNam
24 )} 26 )}
25 </div> 27 </div>
26 </div> 28 </div>
27), 29)));
28));
diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js
index cbe70ac88..83a05554b 100644
--- a/src/components/ui/ImageUpload.js
+++ b/src/components/ui/ImageUpload.js
@@ -23,6 +23,8 @@ export default @observer class ImageUpload extends Component {
23 path: null, 23 path: null,
24 } 24 }
25 25
26 dropzoneRef = null;
27
26 onDrop(acceptedFiles) { 28 onDrop(acceptedFiles) {
27 const { field } = this.props; 29 const { field } = this.props;
28 30
@@ -36,8 +38,6 @@ export default @observer class ImageUpload extends Component {
36 field.set(''); 38 field.set('');
37 } 39 }
38 40
39 dropzoneRef = null;
40
41 render() { 41 render() {
42 const { 42 const {
43 field, 43 field,
diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js
index 94a1ddf76..612399e9f 100644
--- a/src/components/ui/InfoBar.js
+++ b/src/components/ui/InfoBar.js
@@ -5,7 +5,7 @@ import classnames from 'classnames';
5import Loader from 'react-loader'; 5import Loader from 'react-loader';
6 6
7// import { oneOrManyChildElements } from '../../prop-types'; 7// import { oneOrManyChildElements } from '../../prop-types';
8import Appear from '../ui/effects/Appear'; 8import Appear from './effects/Appear';
9 9
10export default @observer class InfoBar extends Component { 10export default @observer class InfoBar extends Component {
11 static propTypes = { 11 static propTypes = {
@@ -64,6 +64,7 @@ export default @observer class InfoBar extends Component {
64 {children} 64 {children}
65 {ctaLabel && ( 65 {ctaLabel && (
66 <button 66 <button
67 type="button"
67 className="info-bar__cta" 68 className="info-bar__cta"
68 onClick={onClick} 69 onClick={onClick}
69 > 70 >
@@ -80,6 +81,7 @@ export default @observer class InfoBar extends Component {
80 </div> 81 </div>
81 {!sticky && ( 82 {!sticky && (
82 <button 83 <button
84 type="button"
83 className="info-bar__close mdi mdi-close" 85 className="info-bar__close mdi mdi-close"
84 onClick={onHide} 86 onClick={onHide}
85 /> 87 />
diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js
index 77051f567..a33c6474a 100644
--- a/src/components/ui/Infobox.js
+++ b/src/components/ui/Infobox.js
@@ -61,6 +61,7 @@ export default @observer class Infobox extends Component {
61 <button 61 <button
62 className="infobox__cta" 62 className="infobox__cta"
63 onClick={ctaOnClick} 63 onClick={ctaOnClick}
64 type="button"
64 > 65 >
65 <Loader 66 <Loader
66 loaded={!ctaLoading} 67 loaded={!ctaLoading}
@@ -74,6 +75,7 @@ export default @observer class Infobox extends Component {
74 )} 75 )}
75 {dismissable && ( 76 {dismissable && (
76 <button 77 <button
78 type="button"
77 onClick={() => this.setState({ 79 onClick={() => this.setState({
78 dismissed: true, 80 dismissed: true,
79 })} 81 })}
diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js
index 7bf6e1b00..9b070c4df 100644
--- a/src/components/ui/Input.js
+++ b/src/components/ui/Input.js
@@ -33,6 +33,8 @@ export default @observer class Input extends Component {
33 passwordScore: 0, 33 passwordScore: 0,
34 } 34 }
35 35
36 inputElement = null;
37
36 componentDidMount() { 38 componentDidMount() {
37 if (this.props.focus) { 39 if (this.props.focus) {
38 this.focus(); 40 this.focus();
@@ -53,8 +55,6 @@ export default @observer class Input extends Component {
53 this.inputElement.focus(); 55 this.inputElement.focus();
54 } 56 }
55 57
56 inputElement = null;
57
58 render() { 58 render() {
59 const { 59 const {
60 field, 60 field,
@@ -110,7 +110,7 @@ export default @observer class Input extends Component {
110 'mdi-eye': !this.state.showPassword, 110 'mdi-eye': !this.state.showPassword,
111 'mdi-eye-off': this.state.showPassword, 111 'mdi-eye-off': this.state.showPassword,
112 })} 112 })}
113 onClick={() => this.setState({ showPassword: !this.state.showPassword })} 113 onClick={() => this.setState(prevState => ({ showPassword: !prevState.showPassword }))}
114 tabIndex="-1" 114 tabIndex="-1"
115 /> 115 />
116 )} 116 )}
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js
index 0602290f1..b88686d5e 100644
--- a/src/components/ui/Link.js
+++ b/src/components/ui/Link.js
@@ -72,5 +72,4 @@ Link.wrappedComponent.defaultProps = {
72 activeClassName: '', 72 activeClassName: '',
73 strictFilter: false, 73 strictFilter: false,
74 target: '', 74 target: '',
75 openInBrowser: false,
76}; 75};
diff --git a/src/components/ui/PremiumFeatureContainer/index.js b/src/components/ui/PremiumFeatureContainer/index.js
index 73984be94..67cd6af0b 100644
--- a/src/components/ui/PremiumFeatureContainer/index.js
+++ b/src/components/ui/PremiumFeatureContainer/index.js
@@ -73,4 +73,3 @@ PremiumFeatureContainer.wrappedComponent.propTypes = {
73 }).isRequired, 73 }).isRequired,
74 }).isRequired, 74 }).isRequired,
75}; 75};
76
diff --git a/src/components/ui/Radio.js b/src/components/ui/Radio.js
index 63ca6f9b8..ba13aca63 100644
--- a/src/components/ui/Radio.js
+++ b/src/components/ui/Radio.js
@@ -18,6 +18,8 @@ export default @observer class Radio extends Component {
18 showLabel: true, 18 showLabel: true,
19 }; 19 };
20 20
21 inputElement = null;
22
21 componentDidMount() { 23 componentDidMount() {
22 if (this.props.focus) { 24 if (this.props.focus) {
23 this.focus(); 25 this.focus();
@@ -28,8 +30,6 @@ export default @observer class Radio extends Component {
28 this.inputElement.focus(); 30 this.inputElement.focus();
29 } 31 }
30 32
31 inputElement = null;
32
33 render() { 33 render() {
34 const { 34 const {
35 field, 35 field,
diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js
index 5a9571d27..78d6aae8b 100644
--- a/src/components/ui/SearchInput.js
+++ b/src/components/ui/SearchInput.js
@@ -2,7 +2,6 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import uuidv1 from 'uuid/v1';
6import { debounce } from 'lodash'; 5import { debounce } from 'lodash';
7 6
8export default @observer class SearchInput extends Component { 7export default @observer class SearchInput extends Component {
@@ -22,7 +21,7 @@ export default @observer class SearchInput extends Component {
22 value: '', 21 value: '',
23 placeholder: '', 22 placeholder: '',
24 className: '', 23 className: '',
25 name: uuidv1(), 24 name: 'searchInput',
26 throttle: false, 25 throttle: false,
27 throttleDelay: 250, 26 throttleDelay: 250,
28 onChange: () => null, 27 onChange: () => null,
@@ -30,6 +29,8 @@ export default @observer class SearchInput extends Component {
30 autoFocus: false, 29 autoFocus: false,
31 } 30 }
32 31
32 input = null;
33
33 constructor(props) { 34 constructor(props) {
34 super(props); 35 super(props);
35 36
@@ -74,8 +75,6 @@ export default @observer class SearchInput extends Component {
74 onReset(); 75 onReset();
75 } 76 }
76 77
77 input = null;
78
79 render() { 78 render() {
80 const { className, name, placeholder } = this.props; 79 const { className, name, placeholder } = this.props;
81 const { value } = this.state; 80 const { value } = this.state;
@@ -90,15 +89,17 @@ export default @observer class SearchInput extends Component {
90 <label 89 <label
91 htmlFor={name} 90 htmlFor={name}
92 className="mdi mdi-magnify" 91 className="mdi mdi-magnify"
93 /> 92 >
94 <input 93 <input
95 name={name} 94 name={name}
96 type="text" 95 id={name}
97 placeholder={placeholder} 96 type="text"
98 value={value} 97 placeholder={placeholder}
99 onChange={e => this.onChange(e)} 98 value={value}
100 ref={(ref) => { this.input = ref; }} 99 onChange={e => this.onChange(e)}
101 /> 100 ref={(ref) => { this.input = ref; }}
101 />
102 </label>
102 {value.length > 0 && ( 103 {value.length > 0 && (
103 <span 104 <span
104 className="mdi mdi-close-circle-outline" 105 className="mdi mdi-close-circle-outline"
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js
index 102737bec..6e91300e3 100644
--- a/src/components/ui/Select.js
+++ b/src/components/ui/Select.js
@@ -14,7 +14,6 @@ export default @observer class Select extends Component {
14 14
15 static defaultProps = { 15 static defaultProps = {
16 className: null, 16 className: null,
17 focus: false,
18 showLabel: true, 17 showLabel: true,
19 disabled: false, 18 disabled: false,
20 }; 19 };
diff --git a/src/components/ui/StatusBarTargetUrl.js b/src/components/ui/StatusBarTargetUrl.js
index 4285a343c..6fc50fe5c 100644
--- a/src/components/ui/StatusBarTargetUrl.js
+++ b/src/components/ui/StatusBarTargetUrl.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5 5
6import Appear from '../ui/effects/Appear'; 6import Appear from './effects/Appear';
7 7
8export default @observer class StatusBarTargetUrl extends Component { 8export default @observer class StatusBarTargetUrl extends Component {
9 static propTypes = { 9 static propTypes = {
@@ -13,7 +13,6 @@ export default @observer class StatusBarTargetUrl extends Component {
13 13
14 static defaultProps = { 14 static defaultProps = {
15 className: '', 15 className: '',
16 position: 'bottom',
17 text: '', 16 text: '',
18 }; 17 };
19 18
diff --git a/src/components/util/ErrorBoundary/index.js b/src/components/util/ErrorBoundary/index.js
index def01c74f..5db0db226 100644
--- a/src/components/util/ErrorBoundary/index.js
+++ b/src/components/util/ErrorBoundary/index.js
@@ -1,8 +1,9 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
2import injectSheet from 'react-jss'; 3import injectSheet from 'react-jss';
3import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
4 5
5import Button from '../../ui/Button'; 6import Button from '../../ui/Button';
6 7
7import styles from './styles'; 8import styles from './styles';
8 9
@@ -22,16 +23,21 @@ export default @injectSheet(styles) class ErrorBoundary extends Component {
22 hasError: false, 23 hasError: false,
23 } 24 }
24 25
26 static propTypes = {
27 classes: PropTypes.object.isRequired,
28 children: PropTypes.node.isRequired,
29 }
30
25 static contextTypes = { 31 static contextTypes = {
26 intl: intlShape, 32 intl: intlShape,
27 }; 33 };
28 34
29 componentDidCatch(error, info) { 35 componentDidCatch() {
30 this.setState({ hasError: true }); 36 this.setState({ hasError: true });
31 } 37 }
32 38
33 render() { 39 render() {
34 const { classes } = this.props; 40 const { classes } = this.props;
35 const { intl } = this.context; 41 const { intl } = this.context;
36 42
37 if (this.state.hasError) { 43 if (this.state.hasError) {
@@ -40,10 +46,10 @@ export default @injectSheet(styles) class ErrorBoundary extends Component {
40 <h1 className={classes.title}> 46 <h1 className={classes.title}>
41 {intl.formatMessage(messages.headline)} 47 {intl.formatMessage(messages.headline)}
42 </h1> 48 </h1>
43 <Button 49 <Button
44 label={intl.formatMessage(messages.action)} 50 label={intl.formatMessage(messages.action)}
45 buttonType="inverted" 51 buttonType="inverted"
46 onClick={() => location.reload()} 52 onClick={() => window.location.reload()}
47 /> 53 />
48 </div> 54 </div>
49 ); 55 );
@@ -51,4 +57,4 @@ export default @injectSheet(styles) class ErrorBoundary extends Component {
51 57
52 return this.props.children; 58 return this.props.children;
53 } 59 }
54} \ No newline at end of file 60}
diff --git a/src/components/util/ErrorBoundary/styles.js b/src/components/util/ErrorBoundary/styles.js
index 8d62767f6..0960546ff 100644
--- a/src/components/util/ErrorBoundary/styles.js
+++ b/src/components/util/ErrorBoundary/styles.js
@@ -1,4 +1,4 @@
1export default (theme) => ({ 1export default theme => ({
2 component: { 2 component: {
3 display: 'flex', 3 display: 'flex',
4 width: '100%', 4 width: '100%',
@@ -9,5 +9,5 @@ export default (theme) => ({
9 title: { 9 title: {
10 fontSize: 20, 10 fontSize: 20,
11 color: theme.colorText, 11 color: theme.colorText,
12 } 12 },
13}); 13});
diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js
index b73598f3d..762929dc6 100644
--- a/src/containers/auth/AuthLayoutContainer.js
+++ b/src/containers/auth/AuthLayoutContainer.js
@@ -18,7 +18,9 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer
18 }; 18 };
19 19
20 render() { 20 render() {
21 const { stores, actions, children, location } = this.props; 21 const {
22 stores, actions, children, location,
23 } = this.props;
22 const { app, features, globalError } = stores; 24 const { app, features, globalError } = stores;
23 25
24 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting 26 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js
index 1f05b6510..b3d758c87 100644
--- a/src/containers/settings/RecipesScreen.js
+++ b/src/containers/settings/RecipesScreen.js
@@ -16,7 +16,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
16 static propTypes = { 16 static propTypes = {
17 params: PropTypes.shape({ 17 params: PropTypes.shape({
18 filter: PropTypes.string, 18 filter: PropTypes.string,
19 }).isRequired, 19 }),
20 }; 20 };
21 21
22 static defaultProps = { 22 static defaultProps = {
@@ -30,6 +30,8 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
30 currentFilter: 'featured', 30 currentFilter: 'featured',
31 }; 31 };
32 32
33 autorunDisposer = null;
34
33 componentDidMount() { 35 componentDidMount() {
34 gaPage('Settings/Recipe Dashboard/Featured'); 36 gaPage('Settings/Recipe Dashboard/Featured');
35 37
@@ -55,8 +57,6 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
55 this.autorunDisposer(); 57 this.autorunDisposer();
56 } 58 }
57 59
58 autorunDisposer = null;
59
60 searchRecipes(needle) { 60 searchRecipes(needle) {
61 if (needle === '') { 61 if (needle === '') {
62 this.resetSearch(); 62 this.resetSearch();
@@ -72,7 +72,9 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
72 } 72 }
73 73
74 render() { 74 render() {
75 const { recipePreviews, recipes, services, user } = this.props.stores; 75 const {
76 recipePreviews, recipes, services, user,
77 } = this.props.stores;
76 const { showAddServiceInterface } = this.props.actions.service; 78 const { showAddServiceInterface } = this.props.actions.service;
77 79
78 const { filter } = this.props.params; 80 const { filter } = this.props.params;
diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js
index 50ed19bef..3eb7b6255 100644
--- a/src/containers/subscription/SubscriptionFormScreen.js
+++ b/src/containers/subscription/SubscriptionFormScreen.js
@@ -12,7 +12,7 @@ const { BrowserWindow } = remote;
12export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component { 12export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component {
13 static propTypes = { 13 static propTypes = {
14 onCloseWindow: PropTypes.func, 14 onCloseWindow: PropTypes.func,
15 content: PropTypes.oneOrManyChildElements, 15 content: PropTypes.node,
16 showSkipOption: PropTypes.bool, 16 showSkipOption: PropTypes.bool,
17 skipAction: PropTypes.func, 17 skipAction: PropTypes.func,
18 skipButtonLabel: PropTypes.string, 18 skipButtonLabel: PropTypes.string,
diff --git a/src/electron/Settings.js b/src/electron/Settings.js
index ed9733bfe..63f43b6b7 100644
--- a/src/electron/Settings.js
+++ b/src/electron/Settings.js
@@ -8,6 +8,7 @@ const debug = require('debug')('Franz:Settings');
8 8
9export default class Settings { 9export default class Settings {
10 type = ''; 10 type = '';
11
11 @observable store = {}; 12 @observable store = {};
12 13
13 constructor(type, defaultState = {}) { 14 constructor(type, defaultState = {}) {
diff --git a/src/electron/ipc-api/download.js b/src/electron/ipc-api/download.js
index 9e504834d..e6703af2d 100644
--- a/src/electron/ipc-api/download.js
+++ b/src/electron/ipc-api/download.js
@@ -12,7 +12,7 @@ function decodeBase64Image(dataString) {
12 return new Error('Invalid input string'); 12 return new Error('Invalid input string');
13 } 13 }
14 14
15 return new Buffer(matches[2], 'base64'); 15 return Buffer.from(matches[2], 'base64');
16} 16}
17 17
18export default (params) => { 18export default (params) => {
diff --git a/src/features/delayApp/Component.js b/src/features/delayApp/Component.js
index 403340c7b..5c6ceaf86 100644
--- a/src/features/delayApp/Component.js
+++ b/src/features/delayApp/Component.js
@@ -6,7 +6,7 @@ import injectSheet from 'react-jss';
6 6
7import Button from '../../components/ui/Button'; 7import Button from '../../components/ui/Button';
8 8
9import { config } from './'; 9import { config } from '.';
10import styles from './styles'; 10import styles from './styles';
11 11
12const messages = defineMessages({ 12const messages = defineMessages({
@@ -38,10 +38,14 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp
38 countdown: config.delayDuration, 38 countdown: config.delayDuration,
39 } 39 }
40 40
41 countdownInterval = null;
42
43 countdownIntervalTimeout = 1000;
44
41 componentDidMount() { 45 componentDidMount() {
42 this.countdownInterval = setInterval(() => { 46 this.countdownInterval = setInterval(() => {
43 this.setState({ 47 this.setState({
44 countdown: this.state.countdown - this.countdownIntervalTimeout, 48 countdown: prevState => ({ value: prevState.countdown - this.countdownIntervalTimeout }),
45 }); 49 });
46 50
47 if (this.state.countdown <= 0) { 51 if (this.state.countdown <= 0) {
@@ -55,9 +59,6 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp
55 clearInterval(this.countdownInterval); 59 clearInterval(this.countdownInterval);
56 } 60 }
57 61
58 countdownInterval = null;
59 countdownIntervalTimeout = 1000;
60
61 render() { 62 render() {
62 const { classes, actions } = this.props; 63 const { classes, actions } = this.props;
63 const { intl } = this.context; 64 const { intl } = this.context;
@@ -71,9 +72,11 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp
71 buttonType="inverted" 72 buttonType="inverted"
72 onClick={() => actions.ui.openSettings({ path: 'user' })} 73 onClick={() => actions.ui.openSettings({ path: 'user' })}
73 /> 74 />
74 <p className="footnote">{intl.formatMessage(messages.text, { 75 <p className="footnote">
75 seconds: this.state.countdown / 1000, 76 {intl.formatMessage(messages.text, {
76 })}</p> 77 seconds: this.state.countdown / 1000,
78 })}
79 </p>
77 </div> 80 </div>
78 ); 81 );
79 } 82 }
diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js
index 9ffa1d2fd..d5c544b78 100644
--- a/src/features/delayApp/index.js
+++ b/src/features/delayApp/index.js
@@ -67,4 +67,3 @@ export default function init(stores) {
67} 67}
68 68
69export const Component = DelayAppComponent; 69export const Component = DelayAppComponent;
70
diff --git a/src/features/serviceProxy/index.js b/src/features/serviceProxy/index.js
index acd8f162f..d46f9e6f1 100644
--- a/src/features/serviceProxy/index.js
+++ b/src/features/serviceProxy/index.js
@@ -45,4 +45,3 @@ export default function init(stores) {
45 }); 45 });
46 }); 46 });
47} 47}
48
diff --git a/src/helpers/i18n-helpers.js b/src/helpers/i18n-helpers.js
index 026a220e0..091b86b06 100644
--- a/src/helpers/i18n-helpers.js
+++ b/src/helpers/i18n-helpers.js
@@ -1,4 +1,6 @@
1export function getLocale({ locale, locales, defaultLocale, fallbackLocale }) { 1export function getLocale({
2 locale, locales, defaultLocale, fallbackLocale,
3}) {
2 let localeStr = locale; 4 let localeStr = locale;
3 if (locales[locale] === undefined) { 5 if (locales[locale] === undefined) {
4 let localeFuzzy; 6 let localeFuzzy;
diff --git a/src/index.js b/src/index.js
index 7f3fe5b44..830166dcf 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,10 +1,14 @@
1import { app, BrowserWindow, shell, ipcMain } from 'electron'; 1import {
2 app, BrowserWindow, shell, ipcMain,
3} from 'electron';
2 4
3import fs from 'fs-extra'; 5import fs from 'fs-extra';
4import path from 'path'; 6import path from 'path';
5import windowStateKeeper from 'electron-window-state'; 7import windowStateKeeper from 'electron-window-state';
6 8
7import { isDevMode, isMac, isWindows, isLinux } from './environment'; 9import {
10 isDevMode, isMac, isWindows, isLinux,
11} from './environment';
8 12
9// DEV MODE: Save user data into FranzDev 13// DEV MODE: Save user data into FranzDev
10if (isDevMode) { 14if (isDevMode) {
diff --git a/src/lib/Tray.js b/src/lib/Tray.js
index 588fa75bf..669b02709 100644
--- a/src/lib/Tray.js
+++ b/src/lib/Tray.js
@@ -1,4 +1,6 @@
1import { app, Tray, Menu, systemPreferences, nativeImage } from 'electron'; 1import {
2 app, Tray, Menu, systemPreferences, nativeImage,
3} from 'electron';
2import path from 'path'; 4import path from 'path';
3 5
4const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; 6const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png';
@@ -7,7 +9,9 @@ const INDICATOR_TRAY_UNREAD = 'tray-unread';
7 9
8export default class TrayIcon { 10export default class TrayIcon {
9 trayIcon = null; 11 trayIcon = null;
12
10 indicator = 0; 13 indicator = 0;
14
11 themeChangeSubscriberId = null; 15 themeChangeSubscriberId = null;
12 16
13 show() { 17 show() {
@@ -79,7 +83,7 @@ export default class TrayIcon {
79 } 83 }
80 84
81 return nativeImage.createFromPath(path.join( 85 return nativeImage.createFromPath(path.join(
82 __dirname, '..', 'assets', 'images', type, platform, `${asset}.${FILE_EXTENSION}`), 86 __dirname, '..', 'assets', 'images', type, platform, `${asset}.${FILE_EXTENSION}`,
83 ); 87 ));
84 } 88 }
85} 89}
diff --git a/src/models/News.js b/src/models/News.js
index caf1d70e5..acacb97dd 100644
--- a/src/models/News.js
+++ b/src/models/News.js
@@ -2,8 +2,11 @@
2 2
3export default class News { 3export default class News {
4 id = ''; 4 id = '';
5
5 message = ''; 6 message = '';
7
6 type = 'primary'; 8 type = 'primary';
9
7 sticky = false; 10 sticky = false;
8 11
9 constructor(data) { 12 constructor(data) {
diff --git a/src/models/Order.js b/src/models/Order.js
index 0e10b01d6..f7624c627 100644
--- a/src/models/Order.js
+++ b/src/models/Order.js
@@ -1,9 +1,14 @@
1export default class Order { 1export default class Order {
2 id = ''; 2 id = '';
3
3 subscriptionId = ''; 4 subscriptionId = '';
5
4 name = ''; 6 name = '';
7
5 invoiceUrl = ''; 8 invoiceUrl = '';
9
6 price = ''; 10 price = '';
11
7 date = ''; 12 date = '';
8 13
9 constructor(data) { 14 constructor(data) {
diff --git a/src/models/Plan.js b/src/models/Plan.js
index c7b4a0962..3dedf0d5e 100644
--- a/src/models/Plan.js
+++ b/src/models/Plan.js
@@ -5,6 +5,7 @@ export default class Plan {
5 id: '', 5 id: '',
6 price: 0, 6 price: 0,
7 } 7 }
8
8 year = { 9 year = {
9 id: '', 10 id: '',
10 price: 0, 11 price: 0,
diff --git a/src/models/Recipe.js b/src/models/Recipe.js
index 43c44514c..b0d60e75e 100644
--- a/src/models/Recipe.js
+++ b/src/models/Recipe.js
@@ -5,21 +5,33 @@ import path from 'path';
5 5
6export default class Recipe { 6export default class Recipe {
7 id = ''; 7 id = '';
8
8 name = ''; 9 name = '';
10
9 description = ''; 11 description = '';
12
10 version = ''; 13 version = '';
14
11 path = ''; 15 path = '';
12 16
13 serviceURL = ''; 17 serviceURL = '';
14 18
15 hasDirectMessages = true; 19 hasDirectMessages = true;
20
16 hasIndirectMessages = false; 21 hasIndirectMessages = false;
22
17 hasNotificationSound = false; 23 hasNotificationSound = false;
24
18 hasTeamId = false; 25 hasTeamId = false;
26
19 hasPredefinedUrl = false; 27 hasPredefinedUrl = false;
28
20 hasCustomUrl = false; 29 hasCustomUrl = false;
30
21 hasHostedOption = false; 31 hasHostedOption = false;
32
22 urlInputPrefix = ''; 33 urlInputPrefix = '';
34
23 urlInputSuffix = ''; 35 urlInputSuffix = '';
24 36
25 message = ''; 37 message = '';
diff --git a/src/models/RecipePreview.js b/src/models/RecipePreview.js
index 7470d757a..cfb22f860 100644
--- a/src/models/RecipePreview.js
+++ b/src/models/RecipePreview.js
@@ -2,8 +2,12 @@
2 2
3export default class RecipePreview { 3export default class RecipePreview {
4 id = ''; 4 id = '';
5
5 name = ''; 6 name = '';
6 icon = ''; // TODO: check if this isn't replaced by `icons` 7
8 icon = '';
9
10 // TODO: check if this isn't replaced by `icons`
7 featured = false; 11 featured = false;
8 12
9 constructor(data) { 13 constructor(data) {
diff --git a/src/models/Service.js b/src/models/Service.js
index 5ec42af80..03aec773b 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -6,9 +6,13 @@ const debug = require('debug')('Franz:Service');
6 6
7export default class Service { 7export default class Service {
8 id = ''; 8 id = '';
9
9 recipe = ''; 10 recipe = '';
11
10 webview = null; 12 webview = null;
13
11 timer = null; 14 timer = null;
15
12 events = {}; 16 events = {};
13 17
14 isAttached = false; 18 isAttached = false;
@@ -16,26 +20,43 @@ export default class Service {
16 @observable isActive = false; // Is current webview active 20 @observable isActive = false; // Is current webview active
17 21
18 @observable name = ''; 22 @observable name = '';
23
19 @observable unreadDirectMessageCount = 0; 24 @observable unreadDirectMessageCount = 0;
25
20 @observable unreadIndirectMessageCount = 0; 26 @observable unreadIndirectMessageCount = 0;
21 27
22 @observable order = 99; 28 @observable order = 99;
29
23 @observable isEnabled = true; 30 @observable isEnabled = true;
31
24 @observable isMuted = false; 32 @observable isMuted = false;
33
25 @observable team = ''; 34 @observable team = '';
35
26 @observable customUrl = ''; 36 @observable customUrl = '';
37
27 @observable isNotificationEnabled = true; 38 @observable isNotificationEnabled = true;
39
28 @observable isBadgeEnabled = true; 40 @observable isBadgeEnabled = true;
41
29 @observable isIndirectMessageBadgeEnabled = true; 42 @observable isIndirectMessageBadgeEnabled = true;
43
30 @observable iconUrl = ''; 44 @observable iconUrl = '';
45
31 @observable hasCustomUploadedIcon = false; 46 @observable hasCustomUploadedIcon = false;
47
32 @observable hasCrashed = false; 48 @observable hasCrashed = false;
49
33 @observable isDarkModeEnabled = false; 50 @observable isDarkModeEnabled = false;
51
34 @observable spellcheckerLanguage = null; 52 @observable spellcheckerLanguage = null;
35 53
36 @observable isFirstLoad = true; 54 @observable isFirstLoad = true;
55
37 @observable isLoading = true; 56 @observable isLoading = true;
57
38 @observable isError = false; 58 @observable isError = false;
59
39 @observable errorMessage = ''; 60 @observable errorMessage = '';
40 61
41 constructor(data, recipe) { 62 constructor(data, recipe) {
diff --git a/src/models/User.js b/src/models/User.js
index 3e4aa187d..bec78fc16 100644
--- a/src/models/User.js
+++ b/src/models/User.js
@@ -2,19 +2,34 @@ import { observable } from 'mobx';
2 2
3export default class User { 3export default class User {
4 id = null; 4 id = null;
5
5 @observable email = null; 6 @observable email = null;
7
6 @observable firstname = null; 8 @observable firstname = null;
9
7 @observable lastname = null; 10 @observable lastname = null;
11
8 @observable organization = null; 12 @observable organization = null;
13
9 @observable accountType = null; 14 @observable accountType = null;
10 @observable emailIsConfirmed = true; // better assume it's confirmed to avoid noise 15
16 @observable emailIsConfirmed = true;
17
18 // better assume it's confirmed to avoid noise
11 @observable subscription = {}; 19 @observable subscription = {};
20
12 @observable isSubscriptionOwner = false; 21 @observable isSubscriptionOwner = false;
22
13 @observable isPremium = false; 23 @observable isPremium = false;
24
14 @observable beta = false; 25 @observable beta = false;
26
15 @observable donor = {}; 27 @observable donor = {};
28
16 @observable isDonor = false; 29 @observable isDonor = false;
30
17 @observable isMiner = false; 31 @observable isMiner = false;
32
18 @observable locale = false; 33 @observable locale = false;
19 34
20 constructor(data) { 35 constructor(data) {
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 6f156a96d..dd4642d70 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -38,12 +38,15 @@ export default class AppStore extends Store {
38 }; 38 };
39 39
40 @observable healthCheckRequest = new Request(this.api.app, 'health'); 40 @observable healthCheckRequest = new Request(this.api.app, 'health');
41
41 @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize'); 42 @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize');
43
42 @observable clearAppCacheRequest = new Request(this.api.local, 'clearAppCache'); 44 @observable clearAppCacheRequest = new Request(this.api.local, 'clearAppCache');
43 45
44 @observable autoLaunchOnStart = true; 46 @observable autoLaunchOnStart = true;
45 47
46 @observable isOnline = navigator.onLine; 48 @observable isOnline = navigator.onLine;
49
47 @observable timeOfflineStart; 50 @observable timeOfflineStart;
48 51
49 @observable updateStatus = null; 52 @observable updateStatus = null;
@@ -150,19 +153,22 @@ export default class AppStore extends Store {
150 key( 153 key(
151 '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => { 154 '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => {
152 this.actions.service.setActiveNext(); 155 this.actions.service.setActiveNext();
153 }); 156 },
157 );
154 158
155 // Set active the prev service 159 // Set active the prev service
156 key( 160 key(
157 '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => { 161 '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => {
158 this.actions.service.setActivePrev(); 162 this.actions.service.setActivePrev();
159 }); 163 },
164 );
160 165
161 // Global Mute 166 // Global Mute
162 key( 167 key(
163 '⌘+shift+m ctrl+shift+m', () => { 168 '⌘+shift+m ctrl+shift+m', () => {
164 this.actions.app.toggleMuteApp(); 169 this.actions.app.toggleMuteApp();
165 }); 170 },
171 );
166 172
167 this.locale = this._getDefaultLocale(); 173 this.locale = this._getDefaultLocale();
168 174
@@ -182,7 +188,9 @@ export default class AppStore extends Store {
182 } 188 }
183 189
184 // Actions 190 // Actions
185 @action _notify({ title, options, notificationId, serviceId = null }) { 191 @action _notify({
192 title, options, notificationId, serviceId = null,
193 }) {
186 if (this.stores.settings.all.app.isAppMuted) return; 194 if (this.stores.settings.all.app.isAppMuted) return;
187 195
188 const notification = new window.Notification(title, options); 196 const notification = new window.Notification(title, options);
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js
index 10c893d3f..2a0713b6f 100644
--- a/src/stores/FeaturesStore.js
+++ b/src/stores/FeaturesStore.js
@@ -11,6 +11,7 @@ import { DEFAULT_FEATURES_CONFIG } from '../config';
11 11
12export default class FeaturesStore extends Store { 12export default class FeaturesStore extends Store {
13 @observable defaultFeaturesRequest = new CachedRequest(this.api.features, 'default'); 13 @observable defaultFeaturesRequest = new CachedRequest(this.api.features, 'default');
14
14 @observable featuresRequest = new CachedRequest(this.api.features, 'features'); 15 @observable featuresRequest = new CachedRequest(this.api.features, 'features');
15 16
16 async setup() { 17 async setup() {
diff --git a/src/stores/GlobalErrorStore.js b/src/stores/GlobalErrorStore.js
index f4b9d7838..90bf751c3 100644
--- a/src/stores/GlobalErrorStore.js
+++ b/src/stores/GlobalErrorStore.js
@@ -4,6 +4,7 @@ import Request from './lib/Request';
4 4
5export default class GlobalErrorStore extends Store { 5export default class GlobalErrorStore extends Store {
6 @observable error = null; 6 @observable error = null;
7
7 @observable response = {}; 8 @observable response = {};
8 9
9 constructor(...args) { 10 constructor(...args) {
diff --git a/src/stores/NewsStore.js b/src/stores/NewsStore.js
index e5091834f..6984425df 100644
--- a/src/stores/NewsStore.js
+++ b/src/stores/NewsStore.js
@@ -8,6 +8,7 @@ import { CHECK_INTERVAL } from '../config';
8 8
9export default class NewsStore extends Store { 9export default class NewsStore extends Store {
10 @observable latestNewsRequest = new CachedRequest(this.api.news, 'latest'); 10 @observable latestNewsRequest = new CachedRequest(this.api.news, 'latest');
11
11 @observable hideNewsRequest = new Request(this.api.news, 'hide'); 12 @observable hideNewsRequest = new Request(this.api.news, 'hide');
12 13
13 constructor(...args) { 14 constructor(...args) {
diff --git a/src/stores/PaymentStore.js b/src/stores/PaymentStore.js
index 9e348d14e..4cabee194 100644
--- a/src/stores/PaymentStore.js
+++ b/src/stores/PaymentStore.js
@@ -7,8 +7,11 @@ import { gaEvent } from '../lib/analytics';
7 7
8export default class PaymentStore extends Store { 8export default class PaymentStore extends Store {
9 @observable plansRequest = new CachedRequest(this.api.payment, 'plans'); 9 @observable plansRequest = new CachedRequest(this.api.payment, 'plans');
10
10 @observable createHostedPageRequest = new Request(this.api.payment, 'getHostedPage'); 11 @observable createHostedPageRequest = new Request(this.api.payment, 'getHostedPage');
12
11 @observable createDashboardUrlRequest = new Request(this.api.payment, 'getDashboardUrl'); 13 @observable createDashboardUrlRequest = new Request(this.api.payment, 'getDashboardUrl');
14
12 @observable ordersDataRequest = new CachedRequest(this.api.payment, 'getOrders'); 15 @observable ordersDataRequest = new CachedRequest(this.api.payment, 'getOrders');
13 16
14 constructor(...args) { 17 constructor(...args) {
diff --git a/src/stores/RecipePreviewsStore.js b/src/stores/RecipePreviewsStore.js
index e25936f15..10b2928e3 100644
--- a/src/stores/RecipePreviewsStore.js
+++ b/src/stores/RecipePreviewsStore.js
@@ -8,7 +8,9 @@ import { gaEvent } from '../lib/analytics';
8 8
9export default class RecipePreviewsStore extends Store { 9export default class RecipePreviewsStore extends Store {
10 @observable allRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'all'); 10 @observable allRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'all');
11
11 @observable featuredRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'featured'); 12 @observable featuredRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'featured');
13
12 @observable searchRecipePreviewsRequest = new Request(this.api.recipePreviews, 'search'); 14 @observable searchRecipePreviewsRequest = new Request(this.api.recipePreviews, 'search');
13 15
14 constructor(...args) { 16 constructor(...args) {
diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js
index f2480bc8e..ab64bf79c 100644
--- a/src/stores/RecipesStore.js
+++ b/src/stores/RecipesStore.js
@@ -9,7 +9,9 @@ const debug = require('debug')('Franz:RecipeStore');
9 9
10export default class RecipesStore extends Store { 10export default class RecipesStore extends Store {
11 @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all'); 11 @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all');
12
12 @observable installRecipeRequest = new Request(this.api.recipes, 'install'); 13 @observable installRecipeRequest = new Request(this.api.recipes, 'install');
14
13 @observable getRecipeUpdatesRequest = new Request(this.api.recipes, 'update'); 15 @observable getRecipeUpdatesRequest = new Request(this.api.recipes, 'update');
14 16
15 constructor(...args) { 17 constructor(...args) {
diff --git a/src/stores/RequestStore.js b/src/stores/RequestStore.js
index bbfe6f6df..2629e0a38 100644
--- a/src/stores/RequestStore.js
+++ b/src/stores/RequestStore.js
@@ -6,10 +6,13 @@ const debug = require('debug')('Franz:RequestsStore');
6 6
7export default class RequestStore extends Store { 7export default class RequestStore extends Store {
8 @observable userInfoRequest; 8 @observable userInfoRequest;
9
9 @observable servicesRequest; 10 @observable servicesRequest;
11
10 @observable showRequiredRequestsError = false; 12 @observable showRequiredRequestsError = false;
11 13
12 retries = 0; 14 retries = 0;
15
13 retryDelay = 2000; 16 retryDelay = 2000;
14 17
15 constructor(...args) { 18 constructor(...args) {
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index ccb4eed04..5b70ca271 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -1,4 +1,6 @@
1import { action, reaction, computed, observable } from 'mobx'; 1import {
2 action, reaction, computed, observable,
3} from 'mobx';
2import { debounce, remove } from 'lodash'; 4import { debounce, remove } from 'lodash';
3 5
4import Store from './lib/Store'; 6import Store from './lib/Store';
@@ -11,10 +13,15 @@ const debug = require('debug')('Franz:ServiceStore');
11 13
12export default class ServicesStore extends Store { 14export default class ServicesStore extends Store {
13 @observable allServicesRequest = new CachedRequest(this.api.services, 'all'); 15 @observable allServicesRequest = new CachedRequest(this.api.services, 'all');
16
14 @observable createServiceRequest = new Request(this.api.services, 'create'); 17 @observable createServiceRequest = new Request(this.api.services, 'create');
18
15 @observable updateServiceRequest = new Request(this.api.services, 'update'); 19 @observable updateServiceRequest = new Request(this.api.services, 'update');
20
16 @observable reorderServicesRequest = new Request(this.api.services, 'reorder'); 21 @observable reorderServicesRequest = new Request(this.api.services, 'reorder');
22
17 @observable deleteServiceRequest = new Request(this.api.services, 'delete'); 23 @observable deleteServiceRequest = new Request(this.api.services, 'delete');
24
18 @observable clearCacheRequest = new Request(this.api.services, 'clearCache'); 25 @observable clearCacheRequest = new Request(this.api.services, 'clearCache');
19 26
20 @observable filterNeedle = null; 27 @observable filterNeedle = null;
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js
index e2211aec6..ee391f5d3 100644
--- a/src/stores/SettingsStore.js
+++ b/src/stores/SettingsStore.js
@@ -14,11 +14,13 @@ const debug = require('debug')('Franz:SettingsStore');
14 14
15export default class SettingsStore extends Store { 15export default class SettingsStore extends Store {
16 @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings'); 16 @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings');
17
17 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings'); 18 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings');
18 19
19 @observable fileSystemSettingsRequests = []; 20 @observable fileSystemSettingsRequests = [];
20 21
21 fileSystemSettingsTypes = FILE_SYSTEM_SETTINGS_TYPES; 22 fileSystemSettingsTypes = FILE_SYSTEM_SETTINGS_TYPES;
23
22 @observable _fileSystemSettingsCache = { 24 @observable _fileSystemSettingsCache = {
23 app: DEFAULT_APP_SETTINGS, 25 app: DEFAULT_APP_SETTINGS,
24 proxy: {}, 26 proxy: {},
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 26ac2c60e..54bbbedae 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -14,29 +14,47 @@ const debug = require('debug')('Franz:UserStore');
14// TODO: split stores into UserStore and AuthStore 14// TODO: split stores into UserStore and AuthStore
15export default class UserStore extends Store { 15export default class UserStore extends Store {
16 BASE_ROUTE = '/auth'; 16 BASE_ROUTE = '/auth';
17
17 WELCOME_ROUTE = `${this.BASE_ROUTE}/welcome`; 18 WELCOME_ROUTE = `${this.BASE_ROUTE}/welcome`;
19
18 LOGIN_ROUTE = `${this.BASE_ROUTE}/login`; 20 LOGIN_ROUTE = `${this.BASE_ROUTE}/login`;
21
19 LOGOUT_ROUTE = `${this.BASE_ROUTE}/logout`; 22 LOGOUT_ROUTE = `${this.BASE_ROUTE}/logout`;
23
20 SIGNUP_ROUTE = `${this.BASE_ROUTE}/signup`; 24 SIGNUP_ROUTE = `${this.BASE_ROUTE}/signup`;
25
21 PRICING_ROUTE = `${this.BASE_ROUTE}/signup/pricing`; 26 PRICING_ROUTE = `${this.BASE_ROUTE}/signup/pricing`;
27
22 IMPORT_ROUTE = `${this.BASE_ROUTE}/signup/import`; 28 IMPORT_ROUTE = `${this.BASE_ROUTE}/signup/import`;
29
23 INVITE_ROUTE = `${this.BASE_ROUTE}/signup/invite`; 30 INVITE_ROUTE = `${this.BASE_ROUTE}/signup/invite`;
31
24 PASSWORD_ROUTE = `${this.BASE_ROUTE}/password`; 32 PASSWORD_ROUTE = `${this.BASE_ROUTE}/password`;
25 33
26 @observable loginRequest = new Request(this.api.user, 'login'); 34 @observable loginRequest = new Request(this.api.user, 'login');
35
27 @observable signupRequest = new Request(this.api.user, 'signup'); 36 @observable signupRequest = new Request(this.api.user, 'signup');
37
28 @observable passwordRequest = new Request(this.api.user, 'password'); 38 @observable passwordRequest = new Request(this.api.user, 'password');
39
29 @observable inviteRequest = new Request(this.api.user, 'invite'); 40 @observable inviteRequest = new Request(this.api.user, 'invite');
41
30 @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo'); 42 @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo');
43
31 @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo'); 44 @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo');
45
32 @observable getLegacyServicesRequest = new CachedRequest(this.api.user, 'getLegacyServices'); 46 @observable getLegacyServicesRequest = new CachedRequest(this.api.user, 'getLegacyServices');
47
33 @observable deleteAccountRequest = new CachedRequest(this.api.user, 'delete'); 48 @observable deleteAccountRequest = new CachedRequest(this.api.user, 'delete');
34 49
35 @observable isImportLegacyServicesExecuting = false; 50 @observable isImportLegacyServicesExecuting = false;
51
36 @observable isImportLegacyServicesCompleted = false; 52 @observable isImportLegacyServicesCompleted = false;
37 53
38 @observable id; 54 @observable id;
55
39 @observable authToken = localStorage.getItem('authToken') || null; 56 @observable authToken = localStorage.getItem('authToken') || null;
57
40 @observable accountType; 58 @observable accountType;
41 59
42 @observable hasCompletedSignup = null; 60 @observable hasCompletedSignup = null;
@@ -48,6 +66,7 @@ export default class UserStore extends Store {
48 logoutReasonTypes = { 66 logoutReasonTypes = {
49 SERVER: 'SERVER', 67 SERVER: 'SERVER',
50 }; 68 };
69
51 @observable logoutReason = null; 70 @observable logoutReason = null;
52 71
53 constructor(...args) { 72 constructor(...args) {
@@ -141,7 +160,9 @@ export default class UserStore extends Store {
141 gaEvent('User', 'login'); 160 gaEvent('User', 'login');
142 } 161 }
143 162
144 @action async _signup({ firstname, lastname, email, password, accountType, company }) { 163 @action async _signup({
164 firstname, lastname, email, password, accountType, company,
165 }) {
145 const authToken = await this.signupRequest.execute({ 166 const authToken = await this.signupRequest.execute({
146 firstname, 167 firstname,
147 lastname, 168 lastname,
diff --git a/src/stores/lib/CachedRequest.js b/src/stores/lib/CachedRequest.js
index c0c3d40a1..ac8b2bd81 100644
--- a/src/stores/lib/CachedRequest.js
+++ b/src/stores/lib/CachedRequest.js
@@ -5,6 +5,7 @@ import Request from './Request';
5 5
6export default class CachedRequest extends Request { 6export default class CachedRequest extends Request {
7 _apiCalls = []; 7 _apiCalls = [];
8
8 _isInvalidated = true; 9 _isInvalidated = true;
9 10
10 execute(...callArgs) { 11 execute(...callArgs) {
diff --git a/src/stores/lib/Reaction.js b/src/stores/lib/Reaction.js
index e9bc26d81..46aa4dae6 100644
--- a/src/stores/lib/Reaction.js
+++ b/src/stores/lib/Reaction.js
@@ -3,7 +3,9 @@ import { autorun } from 'mobx';
3 3
4export default class Reaction { 4export default class Reaction {
5 reaction; 5 reaction;
6
6 hasBeenStarted; 7 hasBeenStarted;
8
7 dispose; 9 dispose;
8 10
9 constructor(reaction) { 11 constructor(reaction) {
diff --git a/src/stores/lib/Request.js b/src/stores/lib/Request.js
index 4a6925cc5..04f528156 100644
--- a/src/stores/lib/Request.js
+++ b/src/stores/lib/Request.js
@@ -9,15 +9,23 @@ export default class Request {
9 } 9 }
10 10
11 @observable result = null; 11 @observable result = null;
12
12 @observable error = null; 13 @observable error = null;
14
13 @observable isExecuting = false; 15 @observable isExecuting = false;
16
14 @observable isError = false; 17 @observable isError = false;
18
15 @observable wasExecuted = false; 19 @observable wasExecuted = false;
16 20
17 _promise = Promise; 21 _promise = Promise;
22
18 _api = {}; 23 _api = {};
24
19 _method = ''; 25 _method = '';
26
20 _isWaitingForResponse = false; 27 _isWaitingForResponse = false;
28
21 _currentApiCall = null; 29 _currentApiCall = null;
22 30
23 constructor(api, method) { 31 constructor(api, method) {
diff --git a/src/stores/lib/Store.js b/src/stores/lib/Store.js
index 873da7b37..8d2fb4066 100644
--- a/src/stores/lib/Store.js
+++ b/src/stores/lib/Store.js
@@ -3,16 +3,20 @@ import Reaction from './Reaction';
3 3
4export default class Store { 4export default class Store {
5 stores = {}; 5 stores = {};
6
6 api = {}; 7 api = {};
8
7 actions = {}; 9 actions = {};
8 10
9 _reactions = []; 11 _reactions = [];
10 12
11 // status implementation 13 // status implementation
12 @observable _status = null; 14 @observable _status = null;
15
13 @computed get actionStatus() { 16 @computed get actionStatus() {
14 return this._status || []; 17 return this._status || [];
15 } 18 }
19
16 set actionStatus(status) { 20 set actionStatus(status) {
17 this._status = status; 21 this._status = status;
18 } 22 }
diff --git a/src/styles/searchInput.scss b/src/styles/searchInput.scss
index 32b9da065..91453c600 100644
--- a/src/styles/searchInput.scss
+++ b/src/styles/searchInput.scss
@@ -22,6 +22,10 @@
22 padding: 5px 10px; 22 padding: 5px 10px;
23 width: 100%; 23 width: 100%;
24 24
25 label {
26 width: 100%;
27 }
28
25 input { 29 input {
26 background: none; 30 background: none;
27 border: 0; 31 border: 0;
diff --git a/src/theme/dark/index.js b/src/theme/dark/index.js
index 5aa64a902..76fece134 100644
--- a/src/theme/dark/index.js
+++ b/src/theme/dark/index.js
@@ -5,4 +5,3 @@ export const colorBackgroundSubscriptionContainer = legacyStyles.themeBrandInfo;
5 5
6export const colorHeadline = legacyStyles.darkThemeTextColor; 6export const colorHeadline = legacyStyles.darkThemeTextColor;
7export const colorText = legacyStyles.darkThemeTextColor; 7export const colorText = legacyStyles.darkThemeTextColor;
8
diff --git a/src/theme/default/index.js b/src/theme/default/index.js
index e67f2ba58..cdd9aa5e6 100644
--- a/src/theme/default/index.js
+++ b/src/theme/default/index.js
@@ -20,4 +20,3 @@ export const colorSubscriptionContainerBorder = [1, 'solid', brandPrimary];
20export const colorSubscriptionContainerTitle = brandPrimary; 20export const colorSubscriptionContainerTitle = brandPrimary;
21export const colorSubscriptionContainerActionButtonBackground = brandPrimary; 21export const colorSubscriptionContainerActionButtonBackground = brandPrimary;
22export const colorSubscriptionContainerActionButtonColor = '#FFF'; 22export const colorSubscriptionContainerActionButtonColor = '#FFF';
23
diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js
index 0349a5d6c..bd099987d 100644
--- a/src/webview/contextMenu.js
+++ b/src/webview/contextMenu.js
@@ -1,7 +1,9 @@
1// This is heavily based on https://github.com/sindresorhus/electron-context-menu 1// This is heavily based on https://github.com/sindresorhus/electron-context-menu
2// ❤ @sindresorhus 2// ❤ @sindresorhus
3 3
4import { clipboard, remote, ipcRenderer, shell } from 'electron'; 4import {
5 clipboard, remote, ipcRenderer, shell,
6} from 'electron';
5 7
6import { isDevMode, isMac } from '../environment'; 8import { isDevMode, isMac } from '../environment';
7import { SPELLCHECKER_LOCALES } from '../i18n/languages'; 9import { SPELLCHECKER_LOCALES } from '../i18n/languages';
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index c9117ac72..944883899 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -56,7 +56,8 @@ class RecipeController {
56 this.spellcheckingProvider, 56 this.spellcheckingProvider,
57 () => this.settings.app.enableSpellchecking, 57 () => this.settings.app.enableSpellchecking,
58 () => this.settings.app.spellcheckerLanguage, 58 () => this.settings.app.spellcheckerLanguage,
59 () => this.spellcheckerLanguage); 59 () => this.spellcheckerLanguage,
60 );
60 61
61 autorun(() => this.update()); 62 autorun(() => this.update());
62 } 63 }