diff options
Diffstat (limited to 'src')
64 files changed, 461 insertions, 292 deletions
diff --git a/src/@types/ferdium-components.types.ts b/src/@types/ferdium-components.types.ts index 03cfdc3b7..516ef9dd7 100644 --- a/src/@types/ferdium-components.types.ts +++ b/src/@types/ferdium-components.types.ts | |||
@@ -7,7 +7,7 @@ export interface StoresProps { | |||
7 | } | 7 | } |
8 | 8 | ||
9 | export interface GlobalError { | 9 | export interface GlobalError { |
10 | status: number; | 10 | status?: number; |
11 | message: string; | 11 | message?: string; |
12 | code: string; | 12 | code?: string; |
13 | } | 13 | } |
diff --git a/src/@types/ferdium.types.ts b/src/@types/ferdium.types.ts index 0747f8e14..db8711cd3 100644 --- a/src/@types/ferdium.types.ts +++ b/src/@types/ferdium.types.ts | |||
@@ -19,4 +19,4 @@ declare global { | |||
19 | * Workaround to make TS recognize this file as a module. | 19 | * Workaround to make TS recognize this file as a module. |
20 | * https://fettblog.eu/typescript-augmenting-global-lib-dom/ | 20 | * https://fettblog.eu/typescript-augmenting-global-lib-dom/ |
21 | */ | 21 | */ |
22 | export { }; | 22 | export {}; |
diff --git a/src/I18n.tsx b/src/I18n.tsx index 5f725eebc..1a69ed1a2 100644 --- a/src/I18n.tsx +++ b/src/I18n.tsx | |||
@@ -24,6 +24,7 @@ class I18N extends Component<Props> { | |||
24 | render(): ReactNode { | 24 | render(): ReactNode { |
25 | const { stores, children } = this.props; | 25 | const { stores, children } = this.props; |
26 | const { locale } = stores.app; | 26 | const { locale } = stores.app; |
27 | |||
27 | return ( | 28 | return ( |
28 | <IntlProvider | 29 | <IntlProvider |
29 | {...{ locale, key: locale, messages: translations[locale] }} | 30 | {...{ locale, key: locale, messages: translations[locale] }} |
diff --git a/src/api/apiBase.ts b/src/api/apiBase.ts index 918213542..701919785 100644 --- a/src/api/apiBase.ts +++ b/src/api/apiBase.ts | |||
@@ -23,6 +23,7 @@ export default function apiBase(withVersion = true) { | |||
23 | // Stores have not yet been loaded - return SERVER_NOT_LOADED to force a retry when stores are loaded | 23 | // Stores have not yet been loaded - return SERVER_NOT_LOADED to force a retry when stores are loaded |
24 | return SERVER_NOT_LOADED; | 24 | return SERVER_NOT_LOADED; |
25 | } | 25 | } |
26 | |||
26 | const url = | 27 | const url = |
27 | (window as any).ferdium.stores.settings.all.app.server === LOCAL_SERVER | 28 | (window as any).ferdium.stores.settings.all.app.server === LOCAL_SERVER |
28 | ? `http://${LOCAL_HOSTNAME}:${ | 29 | ? `http://${LOCAL_HOSTNAME}:${ |
@@ -34,7 +35,6 @@ export default function apiBase(withVersion = true) { | |||
34 | }; | 35 | }; |
35 | 36 | ||
36 | export function serverBase() { | 37 | export function serverBase() { |
37 | |||
38 | const serverType = (window as any).ferdium.stores.settings.all.app.server; | 38 | const serverType = (window as any).ferdium.stores.settings.all.app.server; |
39 | const noServer = 'You are using Ferdium without a server'; | 39 | const noServer = 'You are using Ferdium without a server'; |
40 | 40 | ||
@@ -54,7 +54,6 @@ export function serverBase() { | |||
54 | } | 54 | } |
55 | 55 | ||
56 | export function serverName(): string { | 56 | export function serverName(): string { |
57 | |||
58 | const serverType = (window as any).ferdium.stores.settings.all.app.server; | 57 | const serverType = (window as any).ferdium.stores.settings.all.app.server; |
59 | const noServer = 'You are using Ferdium without a server'; | 58 | const noServer = 'You are using Ferdium without a server'; |
60 | 59 | ||
diff --git a/src/api/server/ServerApi.ts b/src/api/server/ServerApi.ts index a636f3e0d..77a759b3e 100644 --- a/src/api/server/ServerApi.ts +++ b/src/api/server/ServerApi.ts | |||
@@ -291,6 +291,10 @@ export default class ServerApi { | |||
291 | 291 | ||
292 | // Features | 292 | // Features |
293 | async getDefaultFeatures() { | 293 | async getDefaultFeatures() { |
294 | if (apiBase() === SERVER_NOT_LOADED) { | ||
295 | throw new Error('Server not loaded'); | ||
296 | } | ||
297 | |||
294 | const request = await sendAuthRequest(`${apiBase()}/features/default`); | 298 | const request = await sendAuthRequest(`${apiBase()}/features/default`); |
295 | if (!request.ok) { | 299 | if (!request.ok) { |
296 | throw new Error(request.statusText); | 300 | throw new Error(request.statusText); |
diff --git a/src/app.jsx b/src/app.jsx index db0dee392..87297c664 100644 --- a/src/app.jsx +++ b/src/app.jsx | |||
@@ -2,8 +2,8 @@ import { webFrame } from 'electron'; | |||
2 | 2 | ||
3 | import { render } from 'react-dom'; | 3 | import { render } from 'react-dom'; |
4 | import { Provider } from 'mobx-react'; | 4 | import { Provider } from 'mobx-react'; |
5 | import { syncHistoryWithStore, RouterStore } from 'mobx-react-router'; | 5 | import { RouterStore } from '@superwf/mobx-react-router'; |
6 | import { hashHistory } from 'react-router'; | 6 | import { createHashHistory } from 'history'; |
7 | 7 | ||
8 | import ServerApi from './api/server/ServerApi'; | 8 | import ServerApi from './api/server/ServerApi'; |
9 | import LocalApi from './api/server/LocalApi'; | 9 | import LocalApi from './api/server/LocalApi'; |
@@ -14,7 +14,7 @@ import MenuFactory from './lib/Menu'; | |||
14 | import TouchBarFactory from './lib/TouchBar'; | 14 | import TouchBarFactory from './lib/TouchBar'; |
15 | 15 | ||
16 | import I18N from './I18n'; | 16 | import I18N from './I18n'; |
17 | import Routes from './routes'; | 17 | import FerdiumRoutes from './routes'; |
18 | 18 | ||
19 | // Basic electron Setup | 19 | // Basic electron Setup |
20 | webFrame.setVisualZoomLevelLimits(1, 1); | 20 | webFrame.setVisualZoomLevelLimits(1, 1); |
@@ -22,9 +22,9 @@ webFrame.setVisualZoomLevelLimits(1, 1); | |||
22 | window.addEventListener('load', () => { | 22 | window.addEventListener('load', () => { |
23 | const serverApi = new ServerApi(); | 23 | const serverApi = new ServerApi(); |
24 | const api = apiFactory(serverApi, new LocalApi()); | 24 | const api = apiFactory(serverApi, new LocalApi()); |
25 | const router = new RouterStore(); | 25 | const history = createHashHistory(); |
26 | const router = new RouterStore(history); | ||
26 | const stores = storeFactory(api, actions, router); | 27 | const stores = storeFactory(api, actions, router); |
27 | const history = syncHistoryWithStore(hashHistory, router); | ||
28 | const menu = new MenuFactory(stores, actions); | 28 | const menu = new MenuFactory(stores, actions); |
29 | const touchBar = new TouchBarFactory(stores, actions); | 29 | const touchBar = new TouchBarFactory(stores, actions); |
30 | 30 | ||
@@ -39,7 +39,7 @@ window.addEventListener('load', () => { | |||
39 | const preparedApp = ( | 39 | const preparedApp = ( |
40 | <Provider stores={stores} actions={actions}> | 40 | <Provider stores={stores} actions={actions}> |
41 | <I18N stores={{ app: stores.app, user: stores.user }}> | 41 | <I18N stores={{ app: stores.app, user: stores.user }}> |
42 | <Routes history={history} /> | 42 | <FerdiumRoutes history={history} /> |
43 | </I18N> | 43 | </I18N> |
44 | </Provider> | 44 | </Provider> |
45 | ); | 45 | ); |
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js index e43be07a8..41b887974 100644 --- a/src/components/auth/Import.js +++ b/src/components/auth/Import.js | |||
@@ -2,7 +2,7 @@ import { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router-dom'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | 7 | ||
8 | import Form from '../../lib/Form'; | 8 | import Form from '../../lib/Form'; |
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js index 8e1ab514e..9eca924cd 100644 --- a/src/components/auth/Invite.js +++ b/src/components/auth/Invite.js | |||
@@ -2,7 +2,7 @@ import { Component, Fragment } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router-dom'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | 7 | ||
8 | import Infobox from '../ui/Infobox'; | 8 | import Infobox from '../ui/Infobox'; |
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js index 3de576ca6..eb184f1ee 100644 --- a/src/components/auth/Login.js +++ b/src/components/auth/Login.js | |||
@@ -178,7 +178,7 @@ class Login extends Component { | |||
178 | <Link to={signupRoute}> | 178 | <Link to={signupRoute}> |
179 | {intl.formatMessage(messages.signupLink)} | 179 | {intl.formatMessage(messages.signupLink)} |
180 | </Link> | 180 | </Link> |
181 | <Link | 181 | <Link |
182 | // to={passwordRoute} // TODO: Uncomment this line after fixing password recovery in-app | 182 | // to={passwordRoute} // TODO: Uncomment this line after fixing password recovery in-app |
183 | to={`${serverBase()}/user/forgot`} // TODO: Remove this line after fixing password recovery in-app | 183 | to={`${serverBase()}/user/forgot`} // TODO: Remove this line after fixing password recovery in-app |
184 | target='_blank' // TODO: Remove this line after fixing password recovery in-app | 184 | target='_blank' // TODO: Remove this line after fixing password recovery in-app |
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.jsx index c9d592a88..c784b75c3 100644 --- a/src/components/auth/Welcome.js +++ b/src/components/auth/Welcome.jsx | |||
@@ -25,7 +25,7 @@ const messages = defineMessages({ | |||
25 | }, | 25 | }, |
26 | changeServer: { | 26 | changeServer: { |
27 | id: 'login.changeServer', | 27 | id: 'login.changeServer', |
28 | defaultMessage: 'Change here!' | 28 | defaultMessage: 'Change here!', |
29 | }, | 29 | }, |
30 | serverless: { | 30 | serverless: { |
31 | id: 'services.serverless', | 31 | id: 'services.serverless', |
@@ -65,7 +65,6 @@ class Welcome extends Component { | |||
65 | className="welcome__logo" | 65 | className="welcome__logo" |
66 | alt="" | 66 | alt="" |
67 | /> | 67 | /> |
68 | {/* <img src="./assets/images/welcome.png" className="welcome__services" alt="" /> */} | ||
69 | </div> | 68 | </div> |
70 | <div className="welcome__text"> | 69 | <div className="welcome__text"> |
71 | <H1>Ferdium</H1> | 70 | <H1>Ferdium</H1> |
@@ -82,9 +81,7 @@ class Welcome extends Component { | |||
82 | {intl.formatMessage(messages.changeServerMessage, { serverNameParse })} | 81 | {intl.formatMessage(messages.changeServerMessage, { serverNameParse })} |
83 | </span> | 82 | </span> |
84 | <Link to={changeServerRoute} className="button__change-server"> | 83 | <Link to={changeServerRoute} className="button__change-server"> |
85 | <span> | 84 | <span>{intl.formatMessage(messages.changeServer)}</span> |
86 | {intl.formatMessage(messages.changeServer)} | ||
87 | </span> | ||
88 | </Link> | 85 | </Link> |
89 | </div> | 86 | </div> |
90 | <br /> | 87 | <br /> |
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index e22d4eb50..f7860afc6 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -7,6 +7,7 @@ import injectSheet from 'react-jss'; | |||
7 | import { ipcRenderer } from 'electron'; | 7 | import { ipcRenderer } from 'electron'; |
8 | 8 | ||
9 | import { mdiFlash, mdiPowerPlug } from '@mdi/js'; | 9 | import { mdiFlash, mdiPowerPlug } from '@mdi/js'; |
10 | import { Outlet } from 'react-router-dom'; | ||
10 | import InfoBar from '../ui/InfoBar'; | 11 | import InfoBar from '../ui/InfoBar'; |
11 | import { Component as BasicAuth } from '../../features/basicAuth'; | 12 | import { Component as BasicAuth } from '../../features/basicAuth'; |
12 | import { Component as QuickSwitch } from '../../features/quickSwitch'; | 13 | import { Component as QuickSwitch } from '../../features/quickSwitch'; |
@@ -83,7 +84,6 @@ class AppLayout extends Component { | |||
83 | sidebar: PropTypes.element.isRequired, | 84 | sidebar: PropTypes.element.isRequired, |
84 | workspacesDrawer: PropTypes.element.isRequired, | 85 | workspacesDrawer: PropTypes.element.isRequired, |
85 | services: PropTypes.element.isRequired, | 86 | services: PropTypes.element.isRequired, |
86 | children: PropTypes.element, | ||
87 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, | 87 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, |
88 | appUpdateIsDownloaded: PropTypes.bool.isRequired, | 88 | appUpdateIsDownloaded: PropTypes.bool.isRequired, |
89 | authRequestFailed: PropTypes.bool.isRequired, | 89 | authRequestFailed: PropTypes.bool.isRequired, |
@@ -99,10 +99,6 @@ class AppLayout extends Component { | |||
99 | shouldShowServicesUpdatedInfoBar: true, | 99 | shouldShowServicesUpdatedInfoBar: true, |
100 | }; | 100 | }; |
101 | 101 | ||
102 | static defaultProps = { | ||
103 | children: [], | ||
104 | }; | ||
105 | |||
106 | render() { | 102 | render() { |
107 | const { | 103 | const { |
108 | classes, | 104 | classes, |
@@ -110,7 +106,6 @@ class AppLayout extends Component { | |||
110 | workspacesDrawer, | 106 | workspacesDrawer, |
111 | sidebar, | 107 | sidebar, |
112 | services, | 108 | services, |
113 | children, | ||
114 | showServicesUpdatedInfoBar, | 109 | showServicesUpdatedInfoBar, |
115 | appUpdateIsDownloaded, | 110 | appUpdateIsDownloaded, |
116 | authRequestFailed, | 111 | authRequestFailed, |
@@ -205,7 +200,7 @@ class AppLayout extends Component { | |||
205 | <QuickSwitch /> | 200 | <QuickSwitch /> |
206 | <PublishDebugInfo /> | 201 | <PublishDebugInfo /> |
207 | {services} | 202 | {services} |
208 | {children} | 203 | <Outlet /> |
209 | </div> | 204 | </div> |
210 | <Todos /> | 205 | <Todos /> |
211 | </div> | 206 | </div> |
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index 66dc8af41..502f87225 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { observable, reaction } from 'mobx'; | 4 | import { makeObservable, observable, reaction } from 'mobx'; |
5 | import ElectronWebView from 'react-electron-web-view'; | 5 | import ElectronWebView from 'react-electron-web-view'; |
6 | import { join } from 'path'; | 6 | import { join } from 'path'; |
7 | 7 | ||
@@ -22,6 +22,8 @@ class ServiceWebview extends Component { | |||
22 | constructor(props) { | 22 | constructor(props) { |
23 | super(props); | 23 | super(props); |
24 | 24 | ||
25 | makeObservable(this); | ||
26 | |||
25 | reaction( | 27 | reaction( |
26 | () => this.webview, | 28 | () => this.webview, |
27 | () => { | 29 | () => { |
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.jsx index b38b0e3c3..da700b5b1 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.jsx | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router-dom'; |
5 | import { defineMessages, injectIntl } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import Confetti from 'react-confetti'; | 6 | import Confetti from 'react-confetti'; |
7 | import ms from 'ms'; | 7 | import ms from 'ms'; |
@@ -50,6 +50,7 @@ class Services extends Component { | |||
50 | openSettings: PropTypes.func.isRequired, | 50 | openSettings: PropTypes.func.isRequired, |
51 | update: PropTypes.func.isRequired, | 51 | update: PropTypes.func.isRequired, |
52 | userHasCompletedSignup: PropTypes.bool.isRequired, | 52 | userHasCompletedSignup: PropTypes.bool.isRequired, |
53 | // eslint-disable-next-line react/forbid-prop-types | ||
53 | classes: PropTypes.object.isRequired, | 54 | classes: PropTypes.object.isRequired, |
54 | isSpellcheckerEnabled: PropTypes.bool.isRequired, | 55 | isSpellcheckerEnabled: PropTypes.bool.isRequired, |
55 | }; | 56 | }; |
@@ -58,12 +59,16 @@ class Services extends Component { | |||
58 | services: [], | 59 | services: [], |
59 | }; | 60 | }; |
60 | 61 | ||
61 | state = { | ||
62 | showConfetti: true, | ||
63 | }; | ||
64 | |||
65 | _confettiTimeout = null; | 62 | _confettiTimeout = null; |
66 | 63 | ||
64 | constructor() { | ||
65 | super(); | ||
66 | |||
67 | this.state = { | ||
68 | showConfetti: true, | ||
69 | }; | ||
70 | } | ||
71 | |||
67 | componentDidMount() { | 72 | componentDidMount() { |
68 | this._confettiTimeout = window.setTimeout(() => { | 73 | this._confettiTimeout = window.setTimeout(() => { |
69 | this.setState({ | 74 | this.setState({ |
@@ -117,10 +122,7 @@ class Services extends Component { | |||
117 | style={{ maxHeight: '50vh' }} | 122 | style={{ maxHeight: '50vh' }} |
118 | /> | 123 | /> |
119 | <Appear timeout={300} transitionName="slideUp"> | 124 | <Appear timeout={300} transitionName="slideUp"> |
120 | <Link | 125 | <Link to="/settings/recipes" className="button"> |
121 | to='/settings/recipes' | ||
122 | className="button" | ||
123 | > | ||
124 | {intl.formatMessage(messages.getStarted)} | 126 | {intl.formatMessage(messages.getStarted)} |
125 | </Link> | 127 | </Link> |
126 | </Appear> | 128 | </Appear> |
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index 9d2b6b333..a996990b5 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js | |||
@@ -8,7 +8,7 @@ import { SortableElement } from 'react-sortable-hoc'; | |||
8 | import injectSheet from 'react-jss'; | 8 | import injectSheet from 'react-jss'; |
9 | import ms from 'ms'; | 9 | import ms from 'ms'; |
10 | 10 | ||
11 | import { observable, autorun, reaction } from 'mobx'; | 11 | import { observable, autorun, reaction, makeObservable } from 'mobx'; |
12 | import { mdiExclamation } from '@mdi/js'; | 12 | import { mdiExclamation } from '@mdi/js'; |
13 | import ServiceModel from '../../../models/Service'; | 13 | import ServiceModel from '../../../models/Service'; |
14 | import { cmdOrCtrlShortcutKey, shiftKey, altKey } from '../../../environment'; | 14 | import { cmdOrCtrlShortcutKey, shiftKey, altKey } from '../../../environment'; |
@@ -144,6 +144,9 @@ class TabItem extends Component { | |||
144 | 144 | ||
145 | constructor(props) { | 145 | constructor(props) { |
146 | super(props); | 146 | super(props); |
147 | |||
148 | makeObservable(this); | ||
149 | |||
147 | this.state = { | 150 | this.state = { |
148 | showShortcutIndex: false, | 151 | showShortcutIndex: false, |
149 | }; | 152 | }; |
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.jsx index d70f471d5..dea4bb387 100644 --- a/src/components/settings/SettingsLayout.js +++ b/src/components/settings/SettingsLayout.jsx | |||
@@ -4,8 +4,8 @@ import { observer } from 'mobx-react'; | |||
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import { mdiClose } from '@mdi/js'; | 6 | import { mdiClose } from '@mdi/js'; |
7 | import { Outlet } from 'react-router-dom'; | ||
7 | import ErrorBoundary from '../util/ErrorBoundary'; | 8 | import ErrorBoundary from '../util/ErrorBoundary'; |
8 | import { oneOrManyChildElements } from '../../prop-types'; | ||
9 | import Appear from '../ui/effects/Appear'; | 9 | import Appear from '../ui/effects/Appear'; |
10 | import Icon from '../ui/icon'; | 10 | import Icon from '../ui/icon'; |
11 | 11 | ||
@@ -19,7 +19,6 @@ const messages = defineMessages({ | |||
19 | class SettingsLayout extends Component { | 19 | class SettingsLayout extends Component { |
20 | static propTypes = { | 20 | static propTypes = { |
21 | navigation: PropTypes.element.isRequired, | 21 | navigation: PropTypes.element.isRequired, |
22 | children: oneOrManyChildElements.isRequired, | ||
23 | closeSettings: PropTypes.func.isRequired, | 22 | closeSettings: PropTypes.func.isRequired, |
24 | }; | 23 | }; |
25 | 24 | ||
@@ -44,7 +43,7 @@ class SettingsLayout extends Component { | |||
44 | } | 43 | } |
45 | 44 | ||
46 | render() { | 45 | render() { |
47 | const { navigation, children, closeSettings } = this.props; | 46 | const { navigation, closeSettings } = this.props; |
48 | 47 | ||
49 | const { intl } = this.props; | 48 | const { intl } = this.props; |
50 | 49 | ||
@@ -60,7 +59,8 @@ class SettingsLayout extends Component { | |||
60 | /> | 59 | /> |
61 | <div className="settings franz-form"> | 60 | <div className="settings franz-form"> |
62 | {navigation} | 61 | {navigation} |
63 | {children} | 62 | |
63 | <Outlet /> | ||
64 | <button | 64 | <button |
65 | type="button" | 65 | type="button" |
66 | className="settings__close" | 66 | className="settings__close" |
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.jsx index ad1cef1e4..bbbe8d888 100644 --- a/src/components/settings/navigation/SettingsNavigation.js +++ b/src/components/settings/navigation/SettingsNavigation.jsx | |||
@@ -2,10 +2,10 @@ import { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { defineMessages, injectIntl } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | import { inject, observer } from 'mobx-react'; | 4 | import { inject, observer } from 'mobx-react'; |
5 | import { RouterStore } from 'mobx-react-router'; | 5 | import { RouterStore } from '@superwf/mobx-react-router'; |
6 | 6 | ||
7 | import { NavLink } from 'react-router-dom'; | ||
7 | import { LOCAL_SERVER, LIVE_FERDIUM_API, LIVE_FRANZ_API } from '../../../config'; | 8 | import { LOCAL_SERVER, LIVE_FERDIUM_API, LIVE_FRANZ_API } from '../../../config'; |
8 | import Link from '../../ui/Link'; | ||
9 | import UIStore from '../../../stores/UIStore'; | 9 | import UIStore from '../../../stores/UIStore'; |
10 | import SettingsStore from '../../../stores/SettingsStore'; | 10 | import SettingsStore from '../../../stores/SettingsStore'; |
11 | import UserStore from '../../../stores/UserStore'; | 11 | import UserStore from '../../../stores/UserStore'; |
@@ -90,70 +90,94 @@ class SettingsNavigation extends Component { | |||
90 | 90 | ||
91 | return ( | 91 | return ( |
92 | <div className="settings-navigation"> | 92 | <div className="settings-navigation"> |
93 | <Link | 93 | <NavLink |
94 | to="/settings/recipes" | 94 | to="/settings/recipes" |
95 | className="settings-navigation__link" | 95 | className={({ isActive }) => |
96 | activeClassName="is-active" | 96 | isActive |
97 | ? 'settings-navigation__link is-active' | ||
98 | : 'settings-navigation__link' | ||
99 | } | ||
97 | > | 100 | > |
98 | {intl.formatMessage(messages.availableServices)} | 101 | {intl.formatMessage(messages.availableServices)} |
99 | </Link> | 102 | </NavLink> |
100 | <Link | 103 | <NavLink |
101 | to="/settings/services" | 104 | to="/settings/services" |
102 | className="settings-navigation__link" | 105 | className={({ isActive }) => |
103 | activeClassName="is-active" | 106 | isActive |
107 | ? 'settings-navigation__link is-active' | ||
108 | : 'settings-navigation__link' | ||
109 | } | ||
104 | > | 110 | > |
105 | {intl.formatMessage(messages.yourServices)}{' '} | 111 | {intl.formatMessage(messages.yourServices)}{' '} |
106 | <span className="badge">{serviceCount}</span> | 112 | <span className="badge">{serviceCount}</span> |
107 | </Link> | 113 | </NavLink> |
108 | <Link | 114 | <NavLink |
109 | to="/settings/workspaces" | 115 | to="/settings/workspaces" |
110 | className="settings-navigation__link" | 116 | className={({ isActive }) => |
111 | activeClassName="is-active" | 117 | isActive |
118 | ? 'settings-navigation__link is-active' | ||
119 | : 'settings-navigation__link' | ||
120 | } | ||
112 | > | 121 | > |
113 | {intl.formatMessage(messages.yourWorkspaces)}{' '} | 122 | {intl.formatMessage(messages.yourWorkspaces)}{' '} |
114 | <span className="badge">{workspaceCount}</span> | 123 | <span className="badge">{workspaceCount}</span> |
115 | </Link> | 124 | </NavLink> |
116 | {!isUsingWithoutAccount && ( | 125 | {!isUsingWithoutAccount && ( |
117 | <Link | 126 | <NavLink |
118 | to="/settings/user" | 127 | to="/settings/user" |
119 | className="settings-navigation__link" | 128 | className={({ isActive }) => |
120 | activeClassName="is-active" | 129 | isActive |
130 | ? 'settings-navigation__link is-active' | ||
131 | : 'settings-navigation__link' | ||
132 | } | ||
121 | > | 133 | > |
122 | {intl.formatMessage(messages.account)} | 134 | {intl.formatMessage(messages.account)} |
123 | </Link> | 135 | </NavLink> |
124 | )} | 136 | )} |
125 | {isUsingFranzServer && ( | 137 | {isUsingFranzServer && ( |
126 | <Link | 138 | <NavLink |
127 | to="/settings/team" | 139 | to="/settings/team" |
128 | className="settings-navigation__link" | 140 | className={({ isActive }) => |
129 | activeClassName="is-active" | 141 | isActive |
142 | ? 'settings-navigation__link is-active' | ||
143 | : 'settings-navigation__link' | ||
144 | } | ||
130 | > | 145 | > |
131 | {intl.formatMessage(messages.team)} | 146 | {intl.formatMessage(messages.team)} |
132 | </Link> | 147 | </NavLink> |
133 | )} | 148 | )} |
134 | <Link | 149 | <NavLink |
135 | to="/settings/app" | 150 | to="/settings/app" |
136 | className="settings-navigation__link" | 151 | className={({ isActive }) => |
137 | activeClassName="is-active" | 152 | isActive |
153 | ? 'settings-navigation__link is-active' | ||
154 | : 'settings-navigation__link' | ||
155 | } | ||
138 | > | 156 | > |
139 | {intl.formatMessage(globalMessages.settings)} | 157 | {intl.formatMessage(globalMessages.settings)} |
140 | {stores.settings.app.automaticUpdates && (stores.ui.showServicesUpdatedInfoBar || | 158 | {stores.settings.app.automaticUpdates && |
141 | (stores.app.updateStatus === stores.app.updateStatusTypes.AVAILABLE || | 159 | (stores.ui.showServicesUpdatedInfoBar || |
142 | stores.app.updateStatus === stores.app.updateStatusTypes.DOWNLOADED)) && ( | 160 | stores.app.updateStatus === |
143 | <span className="update-available">•</span> | 161 | stores.app.updateStatusTypes.AVAILABLE || |
144 | )} | 162 | stores.app.updateStatus === |
145 | </Link> | 163 | stores.app.updateStatusTypes.DOWNLOADED) && ( |
146 | <Link | 164 | <span className="update-available">•</span> |
165 | )} | ||
166 | </NavLink> | ||
167 | <NavLink | ||
147 | to="/settings/support" | 168 | to="/settings/support" |
148 | className="settings-navigation__link" | 169 | className={({ isActive }) => |
149 | activeClassName="is-active" | 170 | isActive |
171 | ? 'settings-navigation__link is-active' | ||
172 | : 'settings-navigation__link' | ||
173 | } | ||
150 | > | 174 | > |
151 | {intl.formatMessage(messages.supportFerdium)} | 175 | {intl.formatMessage(messages.supportFerdium)} |
152 | </Link> | 176 | </NavLink> |
153 | <span className="settings-navigation__expander" /> | 177 | <span className="settings-navigation__expander" /> |
154 | <button | 178 | <button |
155 | type="button" | 179 | type="button" |
156 | to='/auth/logout' | 180 | to="/auth/logout" |
157 | className="settings-navigation__link" | 181 | className="settings-navigation__link" |
158 | onClick={this.handleLogout.bind(this)} | 182 | onClick={this.handleLogout.bind(this)} |
159 | > | 183 | > |
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.jsx index c05144117..589b97ecd 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.jsx | |||
@@ -2,7 +2,7 @@ import { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { NavLink } from 'react-router-dom'; |
6 | 6 | ||
7 | import injectSheet from 'react-jss'; | 7 | import injectSheet from 'react-jss'; |
8 | 8 | ||
@@ -179,30 +179,33 @@ class RecipesDashboard extends Component { | |||
179 | throttle | 179 | throttle |
180 | /> | 180 | /> |
181 | <div className="recipes__navigation"> | 181 | <div className="recipes__navigation"> |
182 | <Link | 182 | <NavLink |
183 | to="/settings/recipes" | 183 | to="/settings/recipes" |
184 | className="badge" | 184 | className={() => |
185 | activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`} | 185 | recipeFilter === 'featured' ? 'badge badge--primary' : 'badge' |
186 | } | ||
186 | onClick={() => resetSearch()} | 187 | onClick={() => resetSearch()} |
187 | > | 188 | > |
188 | {intl.formatMessage(messages.ferdiumPicksRecipes)} | 189 | {intl.formatMessage(messages.ferdiumPicksRecipes)} |
189 | </Link> | 190 | </NavLink> |
190 | <Link | 191 | <NavLink |
191 | to="/settings/recipes/all" | 192 | to="/settings/recipes/all" |
192 | className="badge" | 193 | className={({ isActive }) => |
193 | activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`} | 194 | isActive && recipeFilter === 'all' ? 'badge badge--primary' : 'badge' |
195 | } | ||
194 | onClick={() => resetSearch()} | 196 | onClick={() => resetSearch()} |
195 | > | 197 | > |
196 | {intl.formatMessage(messages.allRecipes)} | 198 | {intl.formatMessage(messages.allRecipes)} |
197 | </Link> | 199 | </NavLink> |
198 | <Link | 200 | <NavLink |
199 | to="/settings/recipes/dev" | 201 | to="/settings/recipes/dev" |
200 | className="badge" | 202 | className={({ isActive }) => |
201 | activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`} | 203 | isActive && !searchNeedle ? 'badge badge--primary' : 'badge' |
204 | } | ||
202 | onClick={() => resetSearch()} | 205 | onClick={() => resetSearch()} |
203 | > | 206 | > |
204 | {intl.formatMessage(messages.customRecipes)} | 207 | {intl.formatMessage(messages.customRecipes)} |
205 | </Link> | 208 | </NavLink> |
206 | <a | 209 | <a |
207 | href={FERDIUM_SERVICE_REQUEST} | 210 | href={FERDIUM_SERVICE_REQUEST} |
208 | target="_blank" | 211 | target="_blank" |
@@ -257,24 +260,26 @@ class RecipesDashboard extends Component { | |||
257 | /> | 260 | /> |
258 | ))} | 261 | ))} |
259 | </div> | 262 | </div> |
260 | {hasLoadedRecipes && recipes.length === 0 && recipeFilter !== 'dev' && ( | 263 | {hasLoadedRecipes && |
261 | <div className="align-middle settings__empty-state"> | 264 | recipes.length === 0 && |
262 | {customWebsiteRecipe && customWebsiteRecipe.id && ( | 265 | recipeFilter !== 'dev' && ( |
263 | <RecipeItem | 266 | <div className="align-middle settings__empty-state"> |
264 | key={customWebsiteRecipe.id} | 267 | {customWebsiteRecipe && customWebsiteRecipe.id && ( |
265 | recipe={customWebsiteRecipe} | 268 | <RecipeItem |
266 | onClick={() => | 269 | key={customWebsiteRecipe.id} |
267 | showAddServiceInterface({ | 270 | recipe={customWebsiteRecipe} |
268 | recipeId: customWebsiteRecipe.id, | 271 | onClick={() => |
269 | }) | 272 | showAddServiceInterface({ |
270 | } | 273 | recipeId: customWebsiteRecipe.id, |
271 | /> | 274 | }) |
272 | )} | 275 | } |
273 | <p className="settings__empty-state-text"> | 276 | /> |
274 | {intl.formatMessage(messages.nothingFound)} | 277 | )} |
275 | </p> | 278 | <p className="settings__empty-state-text"> |
276 | </div> | 279 | {intl.formatMessage(messages.nothingFound)} |
277 | )} | 280 | </p> |
281 | </div> | ||
282 | )} | ||
278 | {recipeFilter === 'dev' && devRecipes.length > 0 && ( | 283 | {recipeFilter === 'dev' && devRecipes.length > 0 && ( |
279 | <div className={classes.devRecipeList}> | 284 | <div className={classes.devRecipeList}> |
280 | <H3>{intl.formatMessage(messages.headlineDevRecipes)}</H3> | 285 | <H3>{intl.formatMessage(messages.headlineDevRecipes)}</H3> |
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index f69d86726..73136529a 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router-dom'; |
5 | import { defineMessages, injectIntl } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import normalizeUrl from 'normalize-url'; | 6 | import normalizeUrl from 'normalize-url'; |
7 | 7 | ||
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js index 991817175..fdcdb54c9 100644 --- a/src/components/settings/services/ServiceError.js +++ b/src/components/settings/services/ServiceError.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import { observer } from 'mobx-react'; | 2 | import { observer } from 'mobx-react'; |
3 | import { Link } from 'react-router'; | 3 | import { Link } from 'react-router-dom'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | 5 | ||
6 | import Infobox from '../../ui/Infobox'; | 6 | import Infobox from '../../ui/Infobox'; |
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js index c5bb1433c..ac1c30ecb 100644 --- a/src/components/settings/services/ServicesDashboard.js +++ b/src/components/settings/services/ServicesDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { Link } from 'react-router'; | 4 | import { Link } from 'react-router-dom'; |
5 | import { defineMessages, injectIntl } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | 6 | ||
7 | import SearchInput from '../../ui/SearchInput'; | 7 | import SearchInput from '../../ui/SearchInput'; |
@@ -27,8 +27,7 @@ const messages = defineMessages({ | |||
27 | }, | 27 | }, |
28 | noServiceFound: { | 28 | noServiceFound: { |
29 | id: 'settings.services.nothingFound', | 29 | id: 'settings.services.nothingFound', |
30 | defaultMessage: | 30 | defaultMessage: 'Sorry, but no service matched your search term.', |
31 | 'Sorry, but no service matched your search term.', | ||
32 | }, | 31 | }, |
33 | discoverServices: { | 32 | discoverServices: { |
34 | id: 'settings.services.discoverServices', | 33 | id: 'settings.services.discoverServices', |
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js index 436a6b76b..c2773a47d 100644 --- a/src/components/settings/user/EditUserForm.js +++ b/src/components/settings/user/EditUserForm.js | |||
@@ -2,7 +2,7 @@ import { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router-dom'; |
6 | 6 | ||
7 | import Input from '../../ui/input/index'; | 7 | import Input from '../../ui/input/index'; |
8 | import Form from '../../../lib/Form'; | 8 | import Form from '../../../lib/Form'; |
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js index 5ab19bf74..714fc5a68 100644 --- a/src/components/ui/Link.js +++ b/src/components/ui/Link.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { inject, observer } from 'mobx-react'; | 3 | import { inject, observer } from 'mobx-react'; |
4 | import { RouterStore } from 'mobx-react-router'; | 4 | import { RouterStore } from '@superwf/mobx-react-router'; |
5 | import classnames from 'classnames'; | 5 | import classnames from 'classnames'; |
6 | 6 | ||
7 | import { oneOrManyChildElements } from '../../prop-types'; | 7 | import { oneOrManyChildElements } from '../../prop-types'; |
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx index 26fd6bcfe..a8bbfe730 100644 --- a/src/components/ui/button/index.tsx +++ b/src/components/ui/button/index.tsx | |||
@@ -169,20 +169,18 @@ class ButtonComponent extends Component<IProps> { | |||
169 | busy: false, | 169 | busy: false, |
170 | }; | 170 | }; |
171 | 171 | ||
172 | componentWillMount() { | 172 | constructor(props: IProps) { |
173 | this.setState({ busy: this.props.busy }); | 173 | super(props); |
174 | |||
175 | this.state = { | ||
176 | busy: props.busy || false, | ||
177 | }; | ||
174 | } | 178 | } |
175 | 179 | ||
176 | componentWillReceiveProps(nextProps: IProps) { | 180 | static getDerivedStateFromProps(nextProps: IProps) { |
177 | if (nextProps.busy !== this.props.busy) { | 181 | return { |
178 | if (this.props.busy) { | 182 | busy: nextProps.busy, |
179 | setTimeout(() => { | 183 | }; |
180 | this.setState({ busy: nextProps.busy }); | ||
181 | }, 300); | ||
182 | } else { | ||
183 | this.setState({ busy: nextProps.busy }); | ||
184 | } | ||
185 | } | ||
186 | } | 184 | } |
187 | 185 | ||
188 | render() { | 186 | render() { |
diff --git a/src/components/ui/infobox/index.tsx b/src/components/ui/infobox/index.tsx index 976ed5bc4..d1d7ef6cd 100644 --- a/src/components/ui/infobox/index.tsx +++ b/src/components/ui/infobox/index.tsx | |||
@@ -199,6 +199,4 @@ class InfoboxComponent extends Component<IProps, IState> { | |||
199 | } | 199 | } |
200 | } | 200 | } |
201 | 201 | ||
202 | export default injectStyle(styles, { injectTheme: true })( | 202 | export default injectStyle(styles, { injectTheme: true })(InfoboxComponent); |
203 | InfoboxComponent, | ||
204 | ); | ||
diff --git a/src/components/ui/select/index.tsx b/src/components/ui/select/index.tsx index c3b5314e3..1ce6c674b 100644 --- a/src/components/ui/select/index.tsx +++ b/src/components/ui/select/index.tsx | |||
@@ -177,12 +177,16 @@ class SelectComponent extends Component<IProps> { | |||
177 | 177 | ||
178 | private keyListener: any; | 178 | private keyListener: any; |
179 | 179 | ||
180 | componentWillReceiveProps(nextProps: IProps) { | 180 | static getDerivedStateFromProps(nextProps: IProps, prevState: IProps) { |
181 | if (nextProps.value && nextProps.value !== this.props.value) { | 181 | if (nextProps.value && nextProps.value !== prevState.value) { |
182 | this.setState({ | 182 | return { |
183 | value: nextProps.value, | 183 | value: nextProps.value, |
184 | }); | 184 | }; |
185 | } | 185 | } |
186 | |||
187 | return { | ||
188 | value: prevState.value, | ||
189 | }; | ||
186 | } | 190 | } |
187 | 191 | ||
188 | componentDidUpdate() { | 192 | componentDidUpdate() { |
@@ -199,6 +203,7 @@ class SelectComponent extends Component<IProps> { | |||
199 | 203 | ||
200 | if (data) { | 204 | if (data) { |
201 | Object.keys(data).map( | 205 | Object.keys(data).map( |
206 | // eslint-disable-next-line no-return-assign | ||
202 | key => (this.inputRef.current!.dataset[key] = data[key]), | 207 | key => (this.inputRef.current!.dataset[key] = data[key]), |
203 | ); | 208 | ); |
204 | } | 209 | } |
@@ -458,6 +463,6 @@ class SelectComponent extends Component<IProps> { | |||
458 | } | 463 | } |
459 | } | 464 | } |
460 | 465 | ||
461 | export const Select = injectStyle(styles, { injectTheme: true })( | 466 | export default injectStyle(styles, { injectTheme: true })( |
462 | SelectComponent, | 467 | SelectComponent, |
463 | ); | 468 | ); |
diff --git a/src/components/ui/textarea/index.tsx b/src/components/ui/textarea/index.tsx index e005767f8..6796ab83d 100644 --- a/src/components/ui/textarea/index.tsx +++ b/src/components/ui/textarea/index.tsx | |||
@@ -121,6 +121,6 @@ class TextareaComponent extends Component<IProps> { | |||
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
124 | export const Textarea = injectSheet(styles, { injectTheme: true })( | 124 | export default injectSheet(styles, { injectTheme: true })( |
125 | TextareaComponent, | 125 | TextareaComponent, |
126 | ); | 126 | ); |
diff --git a/src/components/ui/toggle/index.tsx b/src/components/ui/toggle/index.tsx index 0629d1a2c..d478cbba5 100644 --- a/src/components/ui/toggle/index.tsx +++ b/src/components/ui/toggle/index.tsx | |||
@@ -122,6 +122,4 @@ class ToggleComponent extends Component<IProps> { | |||
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | export default injectStyle(styles, { injectTheme: true })( | 125 | export default injectStyle(styles, { injectTheme: true })(ToggleComponent); |
126 | ToggleComponent, | ||
127 | ); | ||
diff --git a/src/components/util/ErrorBoundary/index.tsx b/src/components/util/ErrorBoundary/index.tsx index 846d6dc3f..b042e62c8 100644 --- a/src/components/util/ErrorBoundary/index.tsx +++ b/src/components/util/ErrorBoundary/index.tsx | |||
@@ -32,8 +32,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps> { | |||
32 | } | 32 | } |
33 | 33 | ||
34 | render(): ReactNode { | 34 | render(): ReactNode { |
35 | const { classes } = this.props; | 35 | const { classes, intl } = this.props; |
36 | const { intl } = this.props; | ||
37 | 36 | ||
38 | if (this.state.hasError) { | 37 | if (this.state.hasError) { |
39 | return ( | 38 | return ( |
diff --git a/src/components/util/WithParams.tsx b/src/components/util/WithParams.tsx new file mode 100644 index 000000000..6fc0957ff --- /dev/null +++ b/src/components/util/WithParams.tsx | |||
@@ -0,0 +1,8 @@ | |||
1 | import { useParams } from 'react-router-dom'; | ||
2 | |||
3 | export default function withParams(Component: any) { | ||
4 | return (props: any) => { | ||
5 | const params = useParams(); | ||
6 | return <Component {...props} params={params} />; | ||
7 | }; | ||
8 | } | ||
diff --git a/src/containers/auth/AuthLayoutContainer.tsx b/src/containers/auth/AuthLayoutContainer.tsx index 1f2753a66..8d31cfb48 100644 --- a/src/containers/auth/AuthLayoutContainer.tsx +++ b/src/containers/auth/AuthLayoutContainer.tsx | |||
@@ -1,20 +1,17 @@ | |||
1 | import { Component, ReactElement, ReactNode } from 'react'; | 1 | import { Component, ReactElement } from 'react'; |
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | import { ThemeProvider } from 'react-jss'; | 3 | import { ThemeProvider } from 'react-jss'; |
4 | import { Outlet } from 'react-router-dom'; | ||
4 | 5 | ||
5 | import { Location } from 'mobx-react-router'; | ||
6 | import { StoresProps } from '../../@types/ferdium-components.types'; | 6 | import { StoresProps } from '../../@types/ferdium-components.types'; |
7 | import AuthLayout from '../../components/auth/AuthLayout'; | 7 | import AuthLayout from '../../components/auth/AuthLayout'; |
8 | import AppLoader from '../../components/ui/AppLoader'; | 8 | import AppLoader from '../../components/ui/AppLoader'; |
9 | 9 | ||
10 | interface AuthLayoutContainerProps extends StoresProps { | 10 | interface AuthLayoutContainerProps extends StoresProps {} |
11 | location: Location; | ||
12 | children: ReactNode; | ||
13 | } | ||
14 | 11 | ||
15 | class AuthLayoutContainer extends Component<AuthLayoutContainerProps> { | 12 | class AuthLayoutContainer extends Component<AuthLayoutContainerProps> { |
16 | render(): ReactElement { | 13 | render(): ReactElement { |
17 | const { stores, actions, children, location } = this.props; | 14 | const { stores, actions } = this.props; |
18 | const { app, features, globalError, user } = stores; | 15 | const { app, features, globalError, user } = stores; |
19 | 16 | ||
20 | const isLoadingBaseFeatures = | 17 | const isLoadingBaseFeatures = |
@@ -42,7 +39,7 @@ class AuthLayoutContainer extends Component<AuthLayoutContainerProps> { | |||
42 | <ThemeProvider theme={stores.ui.theme}> | 39 | <ThemeProvider theme={stores.ui.theme}> |
43 | <AuthLayout | 40 | <AuthLayout |
44 | error={globalError.response} | 41 | error={globalError.response} |
45 | pathname={location.pathname} | 42 | pathname={stores.router.location.pathname} |
46 | isOnline={app.isOnline} | 43 | isOnline={app.isOnline} |
47 | isAPIHealthy={!app.healthCheckRequest.isError} | 44 | isAPIHealthy={!app.healthCheckRequest.isError} |
48 | retryHealthCheck={actions.app.healthCheck} | 45 | retryHealthCheck={actions.app.healthCheck} |
@@ -53,7 +50,7 @@ class AuthLayoutContainer extends Component<AuthLayoutContainerProps> { | |||
53 | app.updateStatus === app.updateStatusTypes.DOWNLOADED | 50 | app.updateStatus === app.updateStatusTypes.DOWNLOADED |
54 | } | 51 | } |
55 | > | 52 | > |
56 | {children} | 53 | <Outlet /> |
57 | </AuthLayout> | 54 | </AuthLayout> |
58 | </ThemeProvider> | 55 | </ThemeProvider> |
59 | ); | 56 | ); |
diff --git a/src/containers/layout/AppLayoutContainer.tsx b/src/containers/layout/AppLayoutContainer.tsx index 984ea8b68..a4857a426 100644 --- a/src/containers/layout/AppLayoutContainer.tsx +++ b/src/containers/layout/AppLayoutContainer.tsx | |||
@@ -1,19 +1,17 @@ | |||
1 | import { Children, Component, ReactElement, ReactNode } from 'react'; | 1 | import { Component, ReactElement } from 'react'; |
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | import { ThemeProvider } from 'react-jss'; | 3 | import { ThemeProvider } from 'react-jss'; |
4 | import { Outlet } from 'react-router-dom'; | ||
4 | 5 | ||
5 | import { StoresProps } from '../../@types/ferdium-components.types'; | 6 | import { StoresProps } from '../../@types/ferdium-components.types'; |
6 | import AppLayout from '../../components/layout/AppLayout'; | 7 | import AppLayout from '../../components/layout/AppLayout'; |
7 | import Sidebar from '../../components/layout/Sidebar'; | 8 | import Sidebar from '../../components/layout/Sidebar'; |
8 | import Services from '../../components/services/content/Services'; | 9 | import Services from '../../components/services/content/Services'; |
9 | import AppLoader from '../../components/ui/AppLoader'; | 10 | import AppLoader from '../../components/ui/AppLoader'; |
10 | |||
11 | import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; | 11 | import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; |
12 | import { workspaceStore } from '../../features/workspaces'; | 12 | import { workspaceStore } from '../../features/workspaces'; |
13 | 13 | ||
14 | interface AppLayoutContainerProps extends StoresProps { | 14 | interface AppLayoutContainerProps extends StoresProps {} |
15 | children: ReactNode; | ||
16 | } | ||
17 | 15 | ||
18 | class AppLayoutContainer extends Component<AppLayoutContainerProps> { | 16 | class AppLayoutContainer extends Component<AppLayoutContainerProps> { |
19 | render(): ReactElement { | 17 | render(): ReactElement { |
@@ -62,8 +60,6 @@ class AppLayoutContainer extends Component<AppLayoutContainerProps> { | |||
62 | 60 | ||
63 | const { openSettings, closeSettings } = this.props.actions.ui; | 61 | const { openSettings, closeSettings } = this.props.actions.ui; |
64 | 62 | ||
65 | const { children } = this.props; | ||
66 | |||
67 | const isLoadingFeatures = | 63 | const isLoadingFeatures = |
68 | features.featuresRequest.isExecuting && | 64 | features.featuresRequest.isExecuting && |
69 | !features.featuresRequest.wasExecuted; | 65 | !features.featuresRequest.wasExecuted; |
@@ -162,7 +158,7 @@ class AppLayoutContainer extends Component<AppLayoutContainerProps> { | |||
162 | retryRequiredRequests={retryRequiredRequests} | 158 | retryRequiredRequests={retryRequiredRequests} |
163 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} | 159 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} |
164 | > | 160 | > |
165 | {Children.count(children) > 0 ? children : null} | 161 | <Outlet /> |
166 | </AppLayout> | 162 | </AppLayout> |
167 | </ThemeProvider> | 163 | </ThemeProvider> |
168 | ); | 164 | ); |
diff --git a/src/containers/settings/EditServiceScreen.tsx b/src/containers/settings/EditServiceScreen.tsx index f8532a7b4..ba8f374c3 100644 --- a/src/containers/settings/EditServiceScreen.tsx +++ b/src/containers/settings/EditServiceScreen.tsx | |||
@@ -2,7 +2,7 @@ import { Component, ReactElement } from 'react'; | |||
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | import { defineMessages, injectIntl } from 'react-intl'; | 3 | import { defineMessages, injectIntl } from 'react-intl'; |
4 | 4 | ||
5 | import { RouterStore } from 'mobx-react-router'; | 5 | import { Params } from 'react-router-dom'; |
6 | import { StoresProps } from '../../@types/ferdium-components.types'; | 6 | import { StoresProps } from '../../@types/ferdium-components.types'; |
7 | import { IRecipe } from '../../models/Recipe'; | 7 | import { IRecipe } from '../../models/Recipe'; |
8 | import Service from '../../models/Service'; | 8 | import Service from '../../models/Service'; |
@@ -22,6 +22,7 @@ import { SPELLCHECKER_LOCALES } from '../../i18n/languages'; | |||
22 | 22 | ||
23 | import globalMessages from '../../i18n/globalMessages'; | 23 | import globalMessages from '../../i18n/globalMessages'; |
24 | import { DEFAULT_APP_SETTINGS, DEFAULT_SERVICE_SETTINGS } from '../../config'; | 24 | import { DEFAULT_APP_SETTINGS, DEFAULT_SERVICE_SETTINGS } from '../../config'; |
25 | import withParams from '../../components/util/WithParams'; | ||
25 | 26 | ||
26 | const messages = defineMessages({ | 27 | const messages = defineMessages({ |
27 | name: { | 28 | name: { |
@@ -119,14 +120,13 @@ const messages = defineMessages({ | |||
119 | }); | 120 | }); |
120 | 121 | ||
121 | interface EditServicesScreenProps extends StoresProps { | 122 | interface EditServicesScreenProps extends StoresProps { |
122 | router: RouterStore; | ||
123 | intl: any; | 123 | intl: any; |
124 | params: Params; | ||
124 | } | 125 | } |
125 | 126 | ||
126 | class EditServiceScreen extends Component<EditServicesScreenProps> { | 127 | class EditServiceScreen extends Component<EditServicesScreenProps> { |
127 | onSubmit(data: any) { | 128 | onSubmit(data: any) { |
128 | // @ts-ignore TODO: This is actually there and we don't have a correct type right now. | 129 | const { action } = this.props.params; |
129 | const { action } = this.props.router.params; | ||
130 | const { recipes, services } = this.props.stores; | 130 | const { recipes, services } = this.props.stores; |
131 | const { createService, updateService } = this.props.actions.service; | 131 | const { createService, updateService } = this.props.actions.service; |
132 | data.darkReaderSettings = { | 132 | data.darkReaderSettings = { |
@@ -151,10 +151,9 @@ class EditServiceScreen extends Component<EditServicesScreenProps> { | |||
151 | prepareForm(recipe: IRecipe, service: Service | null, proxy: any): Form { | 151 | prepareForm(recipe: IRecipe, service: Service | null, proxy: any): Form { |
152 | const { intl } = this.props; | 152 | const { intl } = this.props; |
153 | 153 | ||
154 | const { stores, router } = this.props; | 154 | const { stores } = this.props; |
155 | 155 | ||
156 | // @ts-ignore TODO: This is actually there and we don't have a correct type right now. | 156 | const { action } = stores.router.pathValue; |
157 | const { action } = router.params; | ||
158 | 157 | ||
159 | let defaultSpellcheckerLanguage = | 158 | let defaultSpellcheckerLanguage = |
160 | SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage]; | 159 | SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage]; |
@@ -389,8 +388,7 @@ class EditServiceScreen extends Component<EditServicesScreenProps> { | |||
389 | 388 | ||
390 | deleteService(): void { | 389 | deleteService(): void { |
391 | const { deleteService } = this.props.actions.service; | 390 | const { deleteService } = this.props.actions.service; |
392 | // @ts-ignore TODO: This is actually there and we don't have a correct type right now. | 391 | const { action } = this.props.params; |
393 | const { action } = this.props.router.params; | ||
394 | 392 | ||
395 | if (action === 'edit') { | 393 | if (action === 'edit') { |
396 | const { activeSettings: service } = this.props.stores.services; | 394 | const { activeSettings: service } = this.props.stores.services; |
@@ -403,8 +401,7 @@ class EditServiceScreen extends Component<EditServicesScreenProps> { | |||
403 | 401 | ||
404 | openRecipeFile(file: any): void { | 402 | openRecipeFile(file: any): void { |
405 | const { openRecipeFile } = this.props.actions.service; | 403 | const { openRecipeFile } = this.props.actions.service; |
406 | // @ts-ignore TODO: This is actually there and we don't have a correct type right now. | 404 | const { action } = this.props.params; |
407 | const { action } = this.props.router.params; | ||
408 | 405 | ||
409 | if (action === 'edit') { | 406 | if (action === 'edit') { |
410 | const { activeSettings: service } = this.props.stores.services; | 407 | const { activeSettings: service } = this.props.stores.services; |
@@ -417,9 +414,7 @@ class EditServiceScreen extends Component<EditServicesScreenProps> { | |||
417 | 414 | ||
418 | render(): ReactElement { | 415 | render(): ReactElement { |
419 | const { recipes, services, user } = this.props.stores; | 416 | const { recipes, services, user } = this.props.stores; |
420 | 417 | const { action } = this.props.params; | |
421 | // @ts-ignore TODO: This is actually there and we don't have a correct type right now. | ||
422 | const { action } = this.props.router.params; | ||
423 | 418 | ||
424 | let recipe: null | IRecipe = null; | 419 | let recipe: null | IRecipe = null; |
425 | let service: null | Service = null; | 420 | let service: null | Service = null; |
@@ -427,7 +422,6 @@ class EditServiceScreen extends Component<EditServicesScreenProps> { | |||
427 | 422 | ||
428 | if (action === 'add') { | 423 | if (action === 'add') { |
429 | recipe = recipes.active; | 424 | recipe = recipes.active; |
430 | |||
431 | // TODO: render error message when recipe is `null` | 425 | // TODO: render error message when recipe is `null` |
432 | if (!recipe) { | 426 | if (!recipe) { |
433 | return <ServiceError />; | 427 | return <ServiceError />; |
@@ -475,6 +469,8 @@ class EditServiceScreen extends Component<EditServicesScreenProps> { | |||
475 | } | 469 | } |
476 | } | 470 | } |
477 | 471 | ||
478 | export default injectIntl<'intl', EditServicesScreenProps>( | 472 | export default withParams( |
479 | inject('stores', 'actions')(observer(EditServiceScreen)), | 473 | injectIntl<'intl', EditServicesScreenProps>( |
474 | inject('stores', 'actions')(observer(EditServiceScreen)), | ||
475 | ), | ||
480 | ); | 476 | ); |
diff --git a/src/containers/settings/RecipesScreen.tsx b/src/containers/settings/RecipesScreen.tsx index bc7fa9ba0..fffdd39fa 100644 --- a/src/containers/settings/RecipesScreen.tsx +++ b/src/containers/settings/RecipesScreen.tsx | |||
@@ -3,6 +3,7 @@ import { Component, ReactElement } from 'react'; | |||
3 | import { autorun, IReactionDisposer } from 'mobx'; | 3 | import { autorun, IReactionDisposer } from 'mobx'; |
4 | import { inject, observer } from 'mobx-react'; | 4 | import { inject, observer } from 'mobx-react'; |
5 | 5 | ||
6 | import { Params } from 'react-router-dom'; | ||
6 | import Recipe from '../../models/Recipe'; | 7 | import Recipe from '../../models/Recipe'; |
7 | import { StoresProps } from '../../@types/ferdium-components.types'; | 8 | import { StoresProps } from '../../@types/ferdium-components.types'; |
8 | import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; | 9 | import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; |
@@ -13,11 +14,10 @@ import { asarRecipesPath } from '../../helpers/asar-helpers'; | |||
13 | import { communityRecipesStore } from '../../features/communityRecipes'; | 14 | import { communityRecipesStore } from '../../features/communityRecipes'; |
14 | import RecipePreview from '../../models/RecipePreview'; | 15 | import RecipePreview from '../../models/RecipePreview'; |
15 | import { openPath } from '../../helpers/url-helpers'; | 16 | import { openPath } from '../../helpers/url-helpers'; |
17 | import withParams from '../../components/util/WithParams'; | ||
16 | 18 | ||
17 | interface RecipesScreenProps extends StoresProps { | 19 | interface RecipesScreenProps extends StoresProps { |
18 | params: { | 20 | params: Params; |
19 | filter?: string | null; | ||
20 | }; | ||
21 | } | 21 | } |
22 | 22 | ||
23 | class RecipesScreen extends Component<RecipesScreenProps> { | 23 | class RecipesScreen extends Component<RecipesScreenProps> { |
@@ -36,8 +36,6 @@ class RecipesScreen extends Component<RecipesScreenProps> { | |||
36 | constructor(props: RecipesScreenProps) { | 36 | constructor(props: RecipesScreenProps) { |
37 | super(props); | 37 | super(props); |
38 | 38 | ||
39 | this.props.params.filter = this.props.params.filter || null; | ||
40 | |||
41 | this.customRecipes = readJsonSync(asarRecipesPath('all.json')); | 39 | this.customRecipes = readJsonSync(asarRecipesPath('all.json')); |
42 | } | 40 | } |
43 | 41 | ||
@@ -104,7 +102,7 @@ class RecipesScreen extends Component<RecipesScreenProps> { | |||
104 | } | 102 | } |
105 | 103 | ||
106 | resetSearch(): void { | 104 | resetSearch(): void { |
107 | this.setState({ needle: null }); | 105 | this.setState({ needle: null, currentFilter: 'featured' }); |
108 | } | 106 | } |
109 | 107 | ||
110 | render(): ReactElement { | 108 | render(): ReactElement { |
@@ -112,7 +110,8 @@ class RecipesScreen extends Component<RecipesScreenProps> { | |||
112 | 110 | ||
113 | const { app: appActions, service: serviceActions } = this.props.actions; | 111 | const { app: appActions, service: serviceActions } = this.props.actions; |
114 | 112 | ||
115 | const { filter } = this.props.params; | 113 | const filter = this.state.currentFilter; |
114 | |||
116 | let recipeFilter; | 115 | let recipeFilter; |
117 | 116 | ||
118 | if (filter === 'all') { | 117 | if (filter === 'all') { |
@@ -125,7 +124,7 @@ class RecipesScreen extends Component<RecipesScreenProps> { | |||
125 | } else { | 124 | } else { |
126 | recipeFilter = recipePreviews.featured; | 125 | recipeFilter = recipePreviews.featured; |
127 | } | 126 | } |
128 | recipeFilter = recipeFilter.sort(this._sortByName); | 127 | recipeFilter = [...recipeFilter].sort(this._sortByName); |
129 | 128 | ||
130 | const { needle } = this.state; | 129 | const { needle } = this.state; |
131 | const allRecipes = | 130 | const allRecipes = |
@@ -185,4 +184,4 @@ class RecipesScreen extends Component<RecipesScreenProps> { | |||
185 | } | 184 | } |
186 | } | 185 | } |
187 | 186 | ||
188 | export default inject('stores', 'actions')(observer(RecipesScreen)); | 187 | export default withParams(inject('stores', 'actions')(observer(RecipesScreen))); |
diff --git a/src/containers/settings/SettingsWindow.tsx b/src/containers/settings/SettingsWindow.tsx index 2192a6f69..93bb08c7c 100644 --- a/src/containers/settings/SettingsWindow.tsx +++ b/src/containers/settings/SettingsWindow.tsx | |||
@@ -1,23 +1,20 @@ | |||
1 | import { Component, ReactNode, ReactPortal } from 'react'; | 1 | import { inject, observer } from 'mobx-react'; |
2 | import { Component, ReactPortal } from 'react'; | ||
2 | import ReactDOM from 'react-dom'; | 3 | import ReactDOM from 'react-dom'; |
3 | import { observer, inject } from 'mobx-react'; | 4 | import { Outlet } from 'react-router-dom'; |
4 | 5 | ||
5 | import { StoresProps } from '../../@types/ferdium-components.types'; | 6 | import { StoresProps } from '../../@types/ferdium-components.types'; |
6 | import Layout from '../../components/settings/SettingsLayout'; | ||
7 | import Navigation from '../../components/settings/navigation/SettingsNavigation'; | 7 | import Navigation from '../../components/settings/navigation/SettingsNavigation'; |
8 | import Layout from '../../components/settings/SettingsLayout'; | ||
8 | import ErrorBoundary from '../../components/util/ErrorBoundary'; | 9 | import ErrorBoundary from '../../components/util/ErrorBoundary'; |
9 | import { workspaceStore } from '../../features/workspaces'; | 10 | import { workspaceStore } from '../../features/workspaces'; |
10 | 11 | ||
11 | interface SettingsContainerProps extends StoresProps { | 12 | class SettingsContainer extends Component<StoresProps> { |
12 | children: ReactNode; | ||
13 | } | ||
14 | |||
15 | class SettingsContainer extends Component<SettingsContainerProps> { | ||
16 | portalRoot: any; | 13 | portalRoot: any; |
17 | 14 | ||
18 | el: HTMLDivElement; | 15 | el: HTMLDivElement; |
19 | 16 | ||
20 | constructor(props: SettingsContainerProps) { | 17 | constructor(props: StoresProps) { |
21 | super(props); | 18 | super(props); |
22 | 19 | ||
23 | this.portalRoot = document.querySelector('#portalContainer'); | 20 | this.portalRoot = document.querySelector('#portalContainer'); |
@@ -33,7 +30,7 @@ class SettingsContainer extends Component<SettingsContainerProps> { | |||
33 | } | 30 | } |
34 | 31 | ||
35 | render(): ReactPortal { | 32 | render(): ReactPortal { |
36 | const { children, stores } = this.props; | 33 | const { stores } = this.props; |
37 | const { closeSettings } = this.props.actions.ui; | 34 | const { closeSettings } = this.props.actions.ui; |
38 | 35 | ||
39 | const navigation = ( | 36 | const navigation = ( |
@@ -46,7 +43,7 @@ class SettingsContainer extends Component<SettingsContainerProps> { | |||
46 | return ReactDOM.createPortal( | 43 | return ReactDOM.createPortal( |
47 | <ErrorBoundary> | 44 | <ErrorBoundary> |
48 | <Layout navigation={navigation} closeSettings={closeSettings}> | 45 | <Layout navigation={navigation} closeSettings={closeSettings}> |
49 | {children} | 46 | <Outlet /> |
50 | </Layout> | 47 | </Layout> |
51 | </ErrorBoundary>, | 48 | </ErrorBoundary>, |
52 | this.el, | 49 | this.el, |
diff --git a/src/electron/Settings.ts b/src/electron/Settings.ts index d09ac7fb6..3e9c6ed99 100644 --- a/src/electron/Settings.ts +++ b/src/electron/Settings.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable, toJS } from 'mobx'; | 1 | import { makeObservable, observable, toJS } from 'mobx'; |
2 | import { pathExistsSync, outputJsonSync, readJsonSync } from 'fs-extra'; | 2 | import { pathExistsSync, outputJsonSync, readJsonSync } from 'fs-extra'; |
3 | import { userDataPath } from '../environment-remote'; | 3 | import { userDataPath } from '../environment-remote'; |
4 | 4 | ||
@@ -12,6 +12,8 @@ export default class Settings { | |||
12 | @observable store: object = {}; | 12 | @observable store: object = {}; |
13 | 13 | ||
14 | constructor(type: string, defaultState = {}) { | 14 | constructor(type: string, defaultState = {}) { |
15 | makeObservable(this); | ||
16 | |||
15 | this.type = type; | 17 | this.type = type; |
16 | this.store = defaultState; | 18 | this.store = defaultState; |
17 | this.defaultState = defaultState; | 19 | this.defaultState = defaultState; |
diff --git a/src/features/communityRecipes/store.ts b/src/features/communityRecipes/store.ts index 34e6cd92c..d3b3318fa 100644 --- a/src/features/communityRecipes/store.ts +++ b/src/features/communityRecipes/store.ts | |||
@@ -1,7 +1,9 @@ | |||
1 | import { computed } from 'mobx'; | 1 | import { computed } from 'mobx'; |
2 | import FeatureStore from '../utils/FeatureStore'; | 2 | import FeatureStore from '../utils/FeatureStore'; |
3 | 3 | ||
4 | const debug = require('../../preload-safe-debug')('Ferdium:feature:communityRecipes:store'); | 4 | const debug = require('../../preload-safe-debug')( |
5 | 'Ferdium:feature:communityRecipes:store', | ||
6 | ); | ||
5 | 7 | ||
6 | export class CommunityRecipesStore extends FeatureStore { | 8 | export class CommunityRecipesStore extends FeatureStore { |
7 | stores: any; | 9 | stores: any; |
diff --git a/src/features/todos/store.js b/src/features/todos/store.js index 1a3d6c1e7..0f195f10d 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import { computed, action, observable } from 'mobx'; | 1 | import { computed, action, observable, makeObservable } from 'mobx'; |
2 | import localStorage from 'mobx-localstorage'; | 2 | import localStorage from 'mobx-localstorage'; |
3 | 3 | ||
4 | import { ThemeType } from '../../themes'; | 4 | import { ThemeType } from '../../themes'; |
@@ -33,6 +33,12 @@ export default class TodoStore extends FeatureStore { | |||
33 | 33 | ||
34 | isInitialized = false; | 34 | isInitialized = false; |
35 | 35 | ||
36 | constructor() { | ||
37 | super(); | ||
38 | |||
39 | makeObservable(this); | ||
40 | } | ||
41 | |||
36 | @computed get width() { | 42 | @computed get width() { |
37 | const width = this.settings.width || DEFAULT_TODOS_WIDTH; | 43 | const width = this.settings.width || DEFAULT_TODOS_WIDTH; |
38 | 44 | ||
diff --git a/src/features/webControls/containers/WebControlsScreen.js b/src/features/webControls/containers/WebControlsScreen.js index 3dac6997c..e5567eec5 100644 --- a/src/features/webControls/containers/WebControlsScreen.js +++ b/src/features/webControls/containers/WebControlsScreen.js | |||
@@ -2,7 +2,7 @@ import { Component } from 'react'; | |||
2 | import { observer, inject } from 'mobx-react'; | 2 | import { observer, inject } from 'mobx-react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | 4 | ||
5 | import { autorun, observable } from 'mobx'; | 5 | import { autorun, makeObservable, observable } from 'mobx'; |
6 | import WebControls from '../components/WebControls'; | 6 | import WebControls from '../components/WebControls'; |
7 | import ServicesStore from '../../../stores/ServicesStore'; | 7 | import ServicesStore from '../../../stores/ServicesStore'; |
8 | import Service from '../../../models/Service'; | 8 | import Service from '../../../models/Service'; |
@@ -27,6 +27,12 @@ class WebControlsScreen extends Component { | |||
27 | 27 | ||
28 | autorunDisposer = null; | 28 | autorunDisposer = null; |
29 | 29 | ||
30 | constructor(props) { | ||
31 | super(props); | ||
32 | |||
33 | makeObservable(this); | ||
34 | } | ||
35 | |||
30 | componentDidMount() { | 36 | componentDidMount() { |
31 | const { service } = this.props; | 37 | const { service } = this.props; |
32 | 38 | ||
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js index 3c7c36a3d..7e8541c44 100644 --- a/src/features/workspaces/components/EditWorkspaceForm.js +++ b/src/features/workspaces/components/EditWorkspaceForm.js | |||
@@ -2,7 +2,7 @@ import { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router-dom'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | 7 | ||
8 | import Infobox from '../../../components/ui/infobox/index'; | 8 | import Infobox from '../../../components/ui/infobox/index'; |
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.jsx index 3454fdbe9..b0b0e639a 100644 --- a/src/features/workspaces/components/WorkspaceDrawer.js +++ b/src/features/workspaces/components/WorkspaceDrawer.jsx | |||
@@ -12,9 +12,7 @@ import Icon from '../../../components/ui/icon'; | |||
12 | import WorkspaceDrawerItem from './WorkspaceDrawerItem'; | 12 | import WorkspaceDrawerItem from './WorkspaceDrawerItem'; |
13 | import workspaceActions from '../actions'; | 13 | import workspaceActions from '../actions'; |
14 | import { workspaceStore } from '../index'; | 14 | import { workspaceStore } from '../index'; |
15 | import { | 15 | import { getUserWorkspacesRequest } from '../api'; |
16 | getUserWorkspacesRequest, | ||
17 | } from '../api'; | ||
18 | 16 | ||
19 | const messages = defineMessages({ | 17 | const messages = defineMessages({ |
20 | headline: { | 18 | headline: { |
diff --git a/src/features/workspaces/containers/EditWorkspaceScreen.tsx b/src/features/workspaces/containers/EditWorkspaceScreen.tsx index f0c7e4574..0b66db0d0 100644 --- a/src/features/workspaces/containers/EditWorkspaceScreen.tsx +++ b/src/features/workspaces/containers/EditWorkspaceScreen.tsx | |||
@@ -1,23 +1,14 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | 3 | ||
4 | import { StoresProps } from '../../../@types/ferdium-components.types'; | ||
4 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; | 5 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; |
5 | import EditWorkspaceForm from '../components/EditWorkspaceForm'; | 6 | import EditWorkspaceForm from '../components/EditWorkspaceForm'; |
6 | import Workspace from '../models/Workspace'; | 7 | import Workspace from '../models/Workspace'; |
7 | import { workspaceStore } from '../index'; | 8 | import { workspaceStore } from '../index'; |
8 | import { deleteWorkspaceRequest, updateWorkspaceRequest } from '../api'; | 9 | import { deleteWorkspaceRequest, updateWorkspaceRequest } from '../api'; |
9 | import { ServicesStore, WorkspacesStore } from '../../../@types/stores.types'; | ||
10 | 10 | ||
11 | type Props = { | 11 | class EditWorkspaceScreen extends Component<StoresProps> { |
12 | actions: { | ||
13 | workspaces: WorkspacesStore; | ||
14 | }; | ||
15 | stores: { | ||
16 | services: ServicesStore; | ||
17 | }; | ||
18 | }; | ||
19 | |||
20 | class EditWorkspaceScreen extends Component<Props> { | ||
21 | // @ts-expect-error Not all code paths return a value. | 12 | // @ts-expect-error Not all code paths return a value. |
22 | onDelete = () => { | 13 | onDelete = () => { |
23 | const { workspaceBeingEdited } = workspaceStore; | 14 | const { workspaceBeingEdited } = workspaceStore; |
diff --git a/src/features/workspaces/containers/WorkspacesScreen.tsx b/src/features/workspaces/containers/WorkspacesScreen.tsx index 5b153fb50..d43dc5efa 100644 --- a/src/features/workspaces/containers/WorkspacesScreen.tsx +++ b/src/features/workspaces/containers/WorkspacesScreen.tsx | |||
@@ -1,5 +1,6 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | import { StoresProps } from '../../../@types/ferdium-components.types'; | ||
3 | import WorkspacesDashboard from '../components/WorkspacesDashboard'; | 4 | import WorkspacesDashboard from '../components/WorkspacesDashboard'; |
4 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; | 5 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; |
5 | import { workspaceStore } from '../index'; | 6 | import { workspaceStore } from '../index'; |
@@ -9,15 +10,8 @@ import { | |||
9 | getUserWorkspacesRequest, | 10 | getUserWorkspacesRequest, |
10 | updateWorkspaceRequest, | 11 | updateWorkspaceRequest, |
11 | } from '../api'; | 12 | } from '../api'; |
12 | import { WorkspacesStore } from '../../../@types/stores.types'; | ||
13 | 13 | ||
14 | type Props = { | 14 | class WorkspacesScreen extends Component<StoresProps> { |
15 | actions: { | ||
16 | workspaces: WorkspacesStore; | ||
17 | }; | ||
18 | }; | ||
19 | |||
20 | class WorkspacesScreen extends Component<Props> { | ||
21 | render() { | 15 | render() { |
22 | const { actions } = this.props; | 16 | const { actions } = this.props; |
23 | return ( | 17 | return ( |
diff --git a/src/features/workspaces/models/Workspace.ts b/src/features/workspaces/models/Workspace.ts index bc636011d..98086289f 100644 --- a/src/features/workspaces/models/Workspace.ts +++ b/src/features/workspaces/models/Workspace.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable } from 'mobx'; | 1 | import { makeObservable, observable } from 'mobx'; |
2 | 2 | ||
3 | import { KEEP_WS_LOADED_USID } from '../../../config'; | 3 | import { KEEP_WS_LOADED_USID } from '../../../config'; |
4 | 4 | ||
@@ -18,6 +18,8 @@ export default class Workspace { | |||
18 | throw new Error('Workspace requires Id'); | 18 | throw new Error('Workspace requires Id'); |
19 | } | 19 | } |
20 | 20 | ||
21 | makeObservable(this); | ||
22 | |||
21 | this.id = data.id; | 23 | this.id = data.id; |
22 | this.name = data.name; | 24 | this.name = data.name; |
23 | this.order = data.order; | 25 | this.order = data.order; |
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index 9b4c4e928..e8c5d0590 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import { computed, observable, action } from 'mobx'; | 1 | import { computed, observable, action, makeObservable } from 'mobx'; |
2 | import localStorage from 'mobx-localstorage'; | 2 | import localStorage from 'mobx-localstorage'; |
3 | import matchRoute from '../../helpers/routing-helpers'; | 3 | import matchRoute from '../../helpers/routing-helpers'; |
4 | import workspaceActions from './actions'; | 4 | import workspaceActions from './actions'; |
@@ -32,6 +32,12 @@ export default class WorkspacesStore extends FeatureStore { | |||
32 | 32 | ||
33 | @observable isSettingsRouteActive = null; | 33 | @observable isSettingsRouteActive = null; |
34 | 34 | ||
35 | constructor() { | ||
36 | super(); | ||
37 | |||
38 | makeObservable(this); | ||
39 | } | ||
40 | |||
35 | @computed get workspaces() { | 41 | @computed get workspaces() { |
36 | if (!this.isFeatureActive) return []; | 42 | if (!this.isFeatureActive) return []; |
37 | return getUserWorkspacesRequest.result || []; | 43 | return getUserWorkspacesRequest.result || []; |
diff --git a/src/index.ts b/src/index.ts index 7ca364a2e..739f653d4 100644 --- a/src/index.ts +++ b/src/index.ts | |||
@@ -626,7 +626,6 @@ ipcMain.on('set-spellchecker-locales', (_e, { locale, serviceId }) => { | |||
626 | serviceSession.setSpellCheckerLanguages(locales); | 626 | serviceSession.setSpellCheckerLanguages(locales); |
627 | }); | 627 | }); |
628 | 628 | ||
629 | |||
630 | ipcMain.handle('get-desktop-capturer-sources', () => desktopCapturer.getSources({ | 629 | ipcMain.handle('get-desktop-capturer-sources', () => desktopCapturer.getSources({ |
631 | types: ['screen', 'window'], | 630 | types: ['screen', 'window'], |
632 | })); | 631 | })); |
diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 0272f39c3..c2b43bd5c 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js | |||
@@ -7,7 +7,7 @@ import { | |||
7 | systemPreferences, | 7 | systemPreferences, |
8 | getCurrentWindow, | 8 | getCurrentWindow, |
9 | } from '@electron/remote'; | 9 | } from '@electron/remote'; |
10 | import { autorun, observable } from 'mobx'; | 10 | import { autorun, makeObservable, observable } from 'mobx'; |
11 | import { defineMessages } from 'react-intl'; | 11 | import { defineMessages } from 'react-intl'; |
12 | import osName from 'os-name'; | 12 | import osName from 'os-name'; |
13 | import { | 13 | import { |
@@ -626,6 +626,8 @@ class FranzMenu { | |||
626 | this.stores = stores; | 626 | this.stores = stores; |
627 | this.actions = actions; | 627 | this.actions = actions; |
628 | 628 | ||
629 | makeObservable(this); | ||
630 | |||
629 | setTimeout(() => { | 631 | setTimeout(() => { |
630 | autorun(this._build.bind(this)); | 632 | autorun(this._build.bind(this)); |
631 | }, 10); | 633 | }, 10); |
diff --git a/src/models/Service.ts b/src/models/Service.ts index 35d573cab..92b8ee64c 100644 --- a/src/models/Service.ts +++ b/src/models/Service.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { autorun, computed, observable } from 'mobx'; | 1 | import { autorun, computed, makeObservable, observable } from 'mobx'; |
2 | import { ipcRenderer } from 'electron'; | 2 | import { ipcRenderer } from 'electron'; |
3 | import { webContents } from '@electron/remote'; | 3 | import { webContents } from '@electron/remote'; |
4 | import normalizeUrl from 'normalize-url'; | 4 | import normalizeUrl from 'normalize-url'; |
@@ -132,6 +132,8 @@ export default class Service { | |||
132 | throw new Error('Service recipe not valid'); | 132 | throw new Error('Service recipe not valid'); |
133 | } | 133 | } |
134 | 134 | ||
135 | makeObservable(this); | ||
136 | |||
135 | this.recipe = recipe; | 137 | this.recipe = recipe; |
136 | 138 | ||
137 | this.userAgentModel = new UserAgent(recipe.overrideUserAgent); | 139 | this.userAgentModel = new UserAgent(recipe.overrideUserAgent); |
diff --git a/src/models/User.ts b/src/models/User.ts index 14481fbb6..6540a14e9 100644 --- a/src/models/User.ts +++ b/src/models/User.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable } from 'mobx'; | 1 | import { makeObservable, observable } from 'mobx'; |
2 | 2 | ||
3 | interface IUser { | 3 | interface IUser { |
4 | id: string | null; | 4 | id: string | null; |
@@ -42,6 +42,8 @@ export default class User { | |||
42 | @observable team = {}; | 42 | @observable team = {}; |
43 | 43 | ||
44 | constructor(data: IUser) { | 44 | constructor(data: IUser) { |
45 | makeObservable(this); | ||
46 | |||
45 | if (!data) { | 47 | if (!data) { |
46 | throw new Error('User config not valid'); | 48 | throw new Error('User config not valid'); |
47 | } | 49 | } |
diff --git a/src/models/UserAgent.ts b/src/models/UserAgent.ts index 1d06d72b0..d54286ee8 100644 --- a/src/models/UserAgent.ts +++ b/src/models/UserAgent.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { action, computed, observe, observable } from 'mobx'; | 1 | import { action, computed, makeObservable, observable, observe } from 'mobx'; |
2 | 2 | ||
3 | import ElectronWebView from 'react-electron-web-view'; | 3 | import ElectronWebView from 'react-electron-web-view'; |
4 | import defaultUserAgent from '../helpers/userAgent-helpers'; | 4 | import defaultUserAgent from '../helpers/userAgent-helpers'; |
@@ -21,6 +21,8 @@ export default class UserAgent { | |||
21 | @observable overrideUserAgent = (): string => ''; | 21 | @observable overrideUserAgent = (): string => ''; |
22 | 22 | ||
23 | constructor(overrideUserAgent: any = null) { | 23 | constructor(overrideUserAgent: any = null) { |
24 | makeObservable(this); | ||
25 | |||
24 | if (typeof overrideUserAgent === 'function') { | 26 | if (typeof overrideUserAgent === 'function') { |
25 | this.overrideUserAgent = overrideUserAgent; | 27 | this.overrideUserAgent = overrideUserAgent; |
26 | } | 28 | } |
diff --git a/src/routes.tsx b/src/routes.tsx index 490d13ee8..1f929531e 100644 --- a/src/routes.tsx +++ b/src/routes.tsx | |||
@@ -1,6 +1,11 @@ | |||
1 | import { Component, ReactElement } from 'react'; | 1 | import { Component, ReactElement } from 'react'; |
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | import { Router, Route, IndexRedirect } from 'react-router'; | 3 | import { Route } from 'react-router'; |
4 | import { | ||
5 | Navigate, | ||
6 | Routes, | ||
7 | unstable_HistoryRouter as HistoryRouter, | ||
8 | } from 'react-router-dom'; | ||
4 | 9 | ||
5 | import AppLayoutContainer from './containers/layout/AppLayoutContainer'; | 10 | import AppLayoutContainer from './containers/layout/AppLayoutContainer'; |
6 | import SettingsWindow from './containers/settings/SettingsWindow'; | 11 | import SettingsWindow from './containers/settings/SettingsWindow'; |
@@ -25,59 +30,137 @@ import AuthLayoutContainer from './containers/auth/AuthLayoutContainer'; | |||
25 | import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen'; | 30 | import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen'; |
26 | import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen'; | 31 | import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen'; |
27 | import { WORKSPACES_ROUTES } from './features/workspaces/constants'; | 32 | import { WORKSPACES_ROUTES } from './features/workspaces/constants'; |
33 | import { Actions } from './actions/lib/actions'; | ||
34 | import { RealStores } from './stores'; | ||
28 | 35 | ||
29 | type Props = { | 36 | type Props = { |
37 | stores: RealStores; | ||
38 | actions: Actions; | ||
30 | history: any; | 39 | history: any; |
31 | }; | 40 | }; |
32 | 41 | ||
33 | class Routes extends Component<Props> { | 42 | class FerdiumRoutes extends Component<Props> { |
34 | render(): ReactElement { | 43 | render(): ReactElement { |
35 | const { history } = this.props; | 44 | const { history } = this.props; |
45 | const routeProps = { | ||
46 | stores: this.props.stores, | ||
47 | actions: this.props.actions, | ||
48 | }; | ||
49 | const errorProps = { | ||
50 | error: this.props.stores.globalError.error || {}, | ||
51 | }; | ||
36 | 52 | ||
37 | return ( | 53 | return ( |
38 | <Router history={history}> | 54 | <HistoryRouter history={history}> |
39 | <Route path="/" component={AppLayoutContainer}> | 55 | <Routes> |
40 | <Route path="/settings" component={SettingsWindow}> | 56 | <Route path="/auth" element={<AuthLayoutContainer {...routeProps} />}> |
41 | <IndexRedirect to="/settings/recipes" /> | ||
42 | <Route path="/settings/recipes" component={RecipesScreen} /> | ||
43 | <Route path="/settings/recipes/:filter" component={RecipesScreen} /> | ||
44 | <Route path="/settings/services" component={ServicesScreen} /> | ||
45 | <Route | 57 | <Route |
46 | path="/settings/services/:action/:id" | 58 | path="/auth" |
47 | component={EditServiceScreen} | 59 | element={<Navigate to="/auth/welcome" replace />} |
48 | /> | 60 | /> |
49 | <Route path={WORKSPACES_ROUTES.ROOT} component={WorkspacesScreen} /> | ||
50 | <Route | 61 | <Route |
51 | path={WORKSPACES_ROUTES.EDIT} | 62 | path="/auth/welcome" |
52 | component={EditWorkspaceScreen} | 63 | element={<WelcomeScreen {...routeProps} />} |
64 | /> | ||
65 | <Route | ||
66 | path="/auth/login" | ||
67 | element={<LoginScreen {...routeProps} {...errorProps} />} | ||
68 | /> | ||
69 | <Route | ||
70 | path="/auth/server" | ||
71 | element={<ChangeServerScreen {...routeProps} />} | ||
72 | /> | ||
73 | <Route path="/auth/signup"> | ||
74 | <Route | ||
75 | path="/auth/signup" | ||
76 | element={<Navigate to="/auth/signup/form" replace />} | ||
77 | /> | ||
78 | <Route | ||
79 | path="/auth/signup/form" | ||
80 | element={<SignupScreen {...routeProps} {...errorProps} />} | ||
81 | /> | ||
82 | <Route | ||
83 | path="/auth/signup/import" | ||
84 | element={<ImportScreen {...routeProps} />} | ||
85 | /> | ||
86 | <Route | ||
87 | path="/auth/signup/setup" | ||
88 | element={<SetupAssistentScreen {...routeProps} />} | ||
89 | /> | ||
90 | <Route | ||
91 | path="/auth/signup/invite" | ||
92 | element={<InviteScreen {...routeProps} />} | ||
93 | /> | ||
94 | </Route> | ||
95 | <Route | ||
96 | path="/auth/password" | ||
97 | element={<PasswordScreen {...routeProps} />} | ||
98 | /> | ||
99 | <Route | ||
100 | path="/auth/logout" | ||
101 | element={<LoginScreen {...routeProps} {...errorProps} />} | ||
53 | /> | 102 | /> |
54 | <Route path="/settings/user" component={AccountScreen} /> | ||
55 | <Route path="/settings/user/edit" component={EditUserScreen} /> | ||
56 | <Route path="/settings/team" component={TeamScreen} /> | ||
57 | <Route path="/settings/app" component={EditSettingsScreen} /> | ||
58 | <Route path="/settings/invite" component={InviteSettingsScreen} /> | ||
59 | <Route path="/settings/support" component={SupportFerdiumScreen} /> | ||
60 | </Route> | 103 | </Route> |
61 | </Route> | 104 | |
62 | <Route path="/auth" component={AuthLayoutContainer}> | 105 | <Route path="/" element={<AppLayoutContainer {...routeProps} />}> |
63 | <IndexRedirect to="/auth/welcome" /> | 106 | <Route |
64 | <Route path="/auth/welcome" component={WelcomeScreen} /> | 107 | path="/settings" |
65 | <Route path="/auth/login" component={LoginScreen} /> | 108 | element={<SettingsWindow {...this.props} />} |
66 | <Route path="/auth/server" component={ChangeServerScreen} /> | 109 | > |
67 | <Route path="/auth/signup"> | 110 | <Route |
68 | <IndexRedirect to="/auth/signup/form" /> | 111 | path="/settings/recipes" |
69 | <Route path="/auth/signup/form" component={SignupScreen} /> | 112 | element={<RecipesScreen {...this.props} />} |
70 | <Route path="/auth/signup/import" component={ImportScreen} /> | 113 | /> |
71 | <Route path="/auth/signup/setup" component={SetupAssistentScreen} /> | 114 | <Route |
72 | <Route path="/auth/signup/invite" component={InviteScreen} /> | 115 | path="/settings/recipes/:filter" |
116 | element={<RecipesScreen {...this.props} />} | ||
117 | /> | ||
118 | <Route | ||
119 | path="/settings/services" | ||
120 | element={<ServicesScreen {...this.props} />} | ||
121 | /> | ||
122 | <Route | ||
123 | path="/settings/services/:action/:id" | ||
124 | element={<EditServiceScreen {...this.props} />} | ||
125 | /> | ||
126 | <Route | ||
127 | path={WORKSPACES_ROUTES.ROOT} | ||
128 | element={<WorkspacesScreen {...this.props} />} | ||
129 | /> | ||
130 | <Route | ||
131 | path={WORKSPACES_ROUTES.EDIT} | ||
132 | element={<EditWorkspaceScreen {...this.props} />} | ||
133 | /> | ||
134 | <Route | ||
135 | path="/settings/user" | ||
136 | element={<AccountScreen {...this.props} />} | ||
137 | /> | ||
138 | <Route | ||
139 | path="/settings/user/edit" | ||
140 | element={<EditUserScreen {...this.props} />} | ||
141 | /> | ||
142 | <Route | ||
143 | path="/settings/team" | ||
144 | element={<TeamScreen {...this.props} />} | ||
145 | /> | ||
146 | <Route | ||
147 | path="/settings/app" | ||
148 | element={<EditSettingsScreen {...this.props} />} | ||
149 | /> | ||
150 | <Route | ||
151 | path="/settings/invite" | ||
152 | element={<InviteSettingsScreen {...this.props} />} | ||
153 | /> | ||
154 | <Route | ||
155 | path="/settings/support" | ||
156 | element={<SupportFerdiumScreen {...this.props} />} | ||
157 | /> | ||
158 | </Route> | ||
73 | </Route> | 159 | </Route> |
74 | <Route path="/auth/password" component={PasswordScreen} /> | 160 | </Routes> |
75 | <Route path="/auth/logout" component={LoginScreen} /> | 161 | </HistoryRouter> |
76 | </Route> | ||
77 | <Route path="*" component={AppLayoutContainer} /> | ||
78 | </Router> | ||
79 | ); | 162 | ); |
80 | } | 163 | } |
81 | } | 164 | } |
82 | 165 | ||
83 | export default inject('stores', 'actions')(observer(Routes)); | 166 | export default inject('stores', 'actions')(observer(FerdiumRoutes)); |
diff --git a/src/stores/AppStore.ts b/src/stores/AppStore.ts index 0ecfdb7c0..ed6d0e263 100644 --- a/src/stores/AppStore.ts +++ b/src/stores/AppStore.ts | |||
@@ -7,7 +7,7 @@ import { | |||
7 | getCurrentWindow, | 7 | getCurrentWindow, |
8 | process as remoteProcess, | 8 | process as remoteProcess, |
9 | } from '@electron/remote'; | 9 | } from '@electron/remote'; |
10 | import { action, computed, observable } from 'mobx'; | 10 | import { action, computed, makeObservable, observable } from 'mobx'; |
11 | import moment from 'moment'; | 11 | import moment from 'moment'; |
12 | import AutoLaunch from 'auto-launch'; | 12 | import AutoLaunch from 'auto-launch'; |
13 | import ms from 'ms'; | 13 | import ms from 'ms'; |
@@ -105,6 +105,8 @@ export default class AppStore extends TypedStore { | |||
105 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 105 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
106 | super(stores, api, actions); | 106 | super(stores, api, actions); |
107 | 107 | ||
108 | makeObservable(this); | ||
109 | |||
108 | // Register action handlers | 110 | // Register action handlers |
109 | this.actions.app.notify.listen(this._notify.bind(this)); | 111 | this.actions.app.notify.listen(this._notify.bind(this)); |
110 | this.actions.app.setBadge.listen(this._setBadge.bind(this)); | 112 | this.actions.app.setBadge.listen(this._setBadge.bind(this)); |
@@ -510,7 +512,7 @@ export default class AppStore extends TypedStore { | |||
510 | } | 512 | } |
511 | 513 | ||
512 | _setLocale() { | 514 | _setLocale() { |
513 | if (this.stores.user.isLoggedIn && this.stores.user.data.locale) { | 515 | if (this.stores.user?.isLoggedIn && this.stores.user?.data.locale) { |
514 | this.locale = this.stores.user.data.locale; | 516 | this.locale = this.stores.user.data.locale; |
515 | } else if (!this.locale) { | 517 | } else if (!this.locale) { |
516 | this.locale = this._getDefaultLocale(); | 518 | this.locale = this._getDefaultLocale(); |
diff --git a/src/stores/FeaturesStore.ts b/src/stores/FeaturesStore.ts index b63c252df..ed0c6c17b 100644 --- a/src/stores/FeaturesStore.ts +++ b/src/stores/FeaturesStore.ts | |||
@@ -1,5 +1,14 @@ | |||
1 | import { computed, observable, runInAction } from 'mobx'; | 1 | import { |
2 | action, | ||
3 | computed, | ||
4 | makeObservable, | ||
5 | observable, | ||
6 | runInAction, | ||
7 | } from 'mobx'; | ||
2 | 8 | ||
9 | import { Stores } from '../@types/stores.types'; | ||
10 | import { ApiInterface } from '../api'; | ||
11 | import { Actions } from '../actions/lib/actions'; | ||
3 | import CachedRequest from './lib/CachedRequest'; | 12 | import CachedRequest from './lib/CachedRequest'; |
4 | import serviceProxy from '../features/serviceProxy'; | 13 | import serviceProxy from '../features/serviceProxy'; |
5 | import basicAuth from '../features/basicAuth'; | 14 | import basicAuth from '../features/basicAuth'; |
@@ -24,6 +33,12 @@ export default class FeaturesStore extends TypedStore { | |||
24 | 33 | ||
25 | @observable features = {}; | 34 | @observable features = {}; |
26 | 35 | ||
36 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | ||
37 | super(stores, api, actions); | ||
38 | |||
39 | makeObservable(this); | ||
40 | } | ||
41 | |||
27 | async setup(): Promise<void> { | 42 | async setup(): Promise<void> { |
28 | this.registerReactions([ | 43 | this.registerReactions([ |
29 | this._updateFeatures, | 44 | this._updateFeatures, |
@@ -49,9 +64,11 @@ export default class FeaturesStore extends TypedStore { | |||
49 | } | 64 | } |
50 | Object.assign(features, requestResult); | 65 | Object.assign(features, requestResult); |
51 | } | 66 | } |
52 | runInAction('FeaturesStore::_updateFeatures', () => { | 67 | runInAction( |
53 | this.features = features; | 68 | action('FeaturesStore::_updateFeatures', () => { |
54 | }); | 69 | this.features = features; |
70 | }), | ||
71 | ); | ||
55 | }; | 72 | }; |
56 | 73 | ||
57 | _monitorLoginStatus(): void { | 74 | _monitorLoginStatus(): void { |
diff --git a/src/stores/GlobalErrorStore.ts b/src/stores/GlobalErrorStore.ts index 8c6317c91..c42e9a4af 100644 --- a/src/stores/GlobalErrorStore.ts +++ b/src/stores/GlobalErrorStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable, action } from 'mobx'; | 1 | import { observable, action, makeObservable } from 'mobx'; |
2 | import { Actions } from '../actions/lib/actions'; | 2 | import { Actions } from '../actions/lib/actions'; |
3 | import { ApiInterface } from '../api'; | 3 | import { ApiInterface } from '../api'; |
4 | import { Stores } from '../@types/stores.types'; | 4 | import { Stores } from '../@types/stores.types'; |
@@ -34,6 +34,8 @@ export default class GlobalErrorStore extends TypedStore { | |||
34 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 34 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
35 | super(stores, api, actions); | 35 | super(stores, api, actions); |
36 | 36 | ||
37 | makeObservable(this); | ||
38 | |||
37 | window.addEventListener('error', (...errorArgs: any[]): void => { | 39 | window.addEventListener('error', (...errorArgs: any[]): void => { |
38 | // @ts-ignore ts-message: Expected 5 arguments, but got 2. | 40 | // @ts-ignore ts-message: Expected 5 arguments, but got 2. |
39 | this._handleConsoleError.call(this, ['error', ...errorArgs]); | 41 | this._handleConsoleError.call(this, ['error', ...errorArgs]); |
diff --git a/src/stores/RecipePreviewsStore.ts b/src/stores/RecipePreviewsStore.ts index b1d50c8b8..1c95e6b54 100644 --- a/src/stores/RecipePreviewsStore.ts +++ b/src/stores/RecipePreviewsStore.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { action, computed, observable } from 'mobx'; | 1 | import { action, computed, makeObservable, observable } from 'mobx'; |
2 | |||
2 | import { Actions } from '../actions/lib/actions'; | 3 | import { Actions } from '../actions/lib/actions'; |
3 | import { ApiInterface } from '../api'; | 4 | import { ApiInterface } from '../api'; |
4 | import Recipe from '../models/Recipe'; | 5 | import Recipe from '../models/Recipe'; |
@@ -28,6 +29,8 @@ export default class RecipePreviewsStore extends TypedStore { | |||
28 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 29 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
29 | super(stores, api, actions); | 30 | super(stores, api, actions); |
30 | 31 | ||
32 | makeObservable(this); | ||
33 | |||
31 | // Register action handlers | 34 | // Register action handlers |
32 | this.actions.recipePreview.search.listen(this._search.bind(this)); | 35 | this.actions.recipePreview.search.listen(this._search.bind(this)); |
33 | } | 36 | } |
diff --git a/src/stores/RecipesStore.ts b/src/stores/RecipesStore.ts index 364d56dd2..25304e97c 100644 --- a/src/stores/RecipesStore.ts +++ b/src/stores/RecipesStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { action, computed, observable } from 'mobx'; | 1 | import { action, computed, makeObservable, observable } from 'mobx'; |
2 | import { readJSONSync } from 'fs-extra'; | 2 | import { readJSONSync } from 'fs-extra'; |
3 | import semver from 'semver'; | 3 | import semver from 'semver'; |
4 | 4 | ||
@@ -24,6 +24,8 @@ export default class RecipesStore extends TypedStore { | |||
24 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 24 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
25 | super(stores, api, actions); | 25 | super(stores, api, actions); |
26 | 26 | ||
27 | makeObservable(this); | ||
28 | |||
27 | // Register action handlers | 29 | // Register action handlers |
28 | this.actions.recipe.install.listen(this._install.bind(this)); | 30 | this.actions.recipe.install.listen(this._install.bind(this)); |
29 | this.actions.recipe.update.listen(this._update.bind(this)); | 31 | this.actions.recipe.update.listen(this._update.bind(this)); |
diff --git a/src/stores/RequestStore.ts b/src/stores/RequestStore.ts index e5df1292d..a964c5d12 100644 --- a/src/stores/RequestStore.ts +++ b/src/stores/RequestStore.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { ipcRenderer } from 'electron'; | 1 | import { ipcRenderer } from 'electron'; |
2 | import { action, computed, observable } from 'mobx'; | 2 | import { action, computed, makeObservable, observable } from 'mobx'; |
3 | import ms from 'ms'; | 3 | import ms from 'ms'; |
4 | 4 | ||
5 | import { Actions } from '../actions/lib/actions'; | 5 | import { Actions } from '../actions/lib/actions'; |
@@ -28,6 +28,8 @@ export default class RequestStore extends TypedStore { | |||
28 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 28 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
29 | super(stores, api, actions); | 29 | super(stores, api, actions); |
30 | 30 | ||
31 | makeObservable(this); | ||
32 | |||
31 | this.actions.requests.retryRequiredRequests.listen( | 33 | this.actions.requests.retryRequiredRequests.listen( |
32 | this._retryRequiredRequests.bind(this), | 34 | this._retryRequiredRequests.bind(this), |
33 | ); | 35 | ); |
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index 4c1b4116c..7812d5aee 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { shell } from 'electron'; | 1 | import { shell } from 'electron'; |
2 | import { action, reaction, computed, observable } from 'mobx'; | 2 | import { action, reaction, computed, observable, makeObservable } from 'mobx'; |
3 | import { debounce, remove } from 'lodash'; | 3 | import { debounce, remove } from 'lodash'; |
4 | import ms from 'ms'; | 4 | import ms from 'ms'; |
5 | import { ensureFileSync, pathExistsSync, writeFileSync } from 'fs-extra'; | 5 | import { ensureFileSync, pathExistsSync, writeFileSync } from 'fs-extra'; |
@@ -67,6 +67,8 @@ export default class ServicesStore extends TypedStore { | |||
67 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 67 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
68 | super(stores, api, actions); | 68 | super(stores, api, actions); |
69 | 69 | ||
70 | makeObservable(this); | ||
71 | |||
70 | // Register action handlers | 72 | // Register action handlers |
71 | this.actions.service.setActive.listen(this._setActive.bind(this)); | 73 | this.actions.service.setActive.listen(this._setActive.bind(this)); |
72 | this.actions.service.blurActive.listen(this._blurActive.bind(this)); | 74 | this.actions.service.blurActive.listen(this._blurActive.bind(this)); |
diff --git a/src/stores/SettingsStore.ts b/src/stores/SettingsStore.ts index 0296ba0e7..a03d3c188 100644 --- a/src/stores/SettingsStore.ts +++ b/src/stores/SettingsStore.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | |||
1 | import { ipcRenderer } from 'electron'; | 2 | import { ipcRenderer } from 'electron'; |
2 | import { getCurrentWindow } from '@electron/remote'; | 3 | import { getCurrentWindow } from '@electron/remote'; |
3 | import { action, computed, observable, reaction } from 'mobx'; | 4 | import { action, computed, makeObservable, observable, reaction } from 'mobx'; |
4 | import localStorage from 'mobx-localstorage'; | 5 | import localStorage from 'mobx-localstorage'; |
5 | import { Stores } from '../@types/stores.types'; | 6 | import { Stores } from '../@types/stores.types'; |
6 | import { ApiInterface } from '../api'; | 7 | import { ApiInterface } from '../api'; |
@@ -22,7 +23,7 @@ export default class SettingsStore extends TypedStore { | |||
22 | 'updateAppSettings', | 23 | 'updateAppSettings', |
23 | ); | 24 | ); |
24 | 25 | ||
25 | loaded = false; | 26 | @observable loaded: boolean = false; |
26 | 27 | ||
27 | fileSystemSettingsTypes = FILE_SYSTEM_SETTINGS_TYPES; | 28 | fileSystemSettingsTypes = FILE_SYSTEM_SETTINGS_TYPES; |
28 | 29 | ||
@@ -34,6 +35,8 @@ export default class SettingsStore extends TypedStore { | |||
34 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 35 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
35 | super(stores, api, actions); | 36 | super(stores, api, actions); |
36 | 37 | ||
38 | makeObservable(this); | ||
39 | |||
37 | // Register action handlers | 40 | // Register action handlers |
38 | this.actions.settings.update.listen(this._update.bind(this)); | 41 | this.actions.settings.update.listen(this._update.bind(this)); |
39 | this.actions.settings.remove.listen(this._remove.bind(this)); | 42 | this.actions.settings.remove.listen(this._remove.bind(this)); |
diff --git a/src/stores/UIStore.ts b/src/stores/UIStore.ts index c43c6d8c7..e0589729f 100644 --- a/src/stores/UIStore.ts +++ b/src/stores/UIStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { action, observable, computed, reaction } from 'mobx'; | 1 | import { action, observable, computed, reaction, makeObservable } from 'mobx'; |
2 | import { nativeTheme } from '@electron/remote'; | 2 | import { nativeTheme } from '@electron/remote'; |
3 | 3 | ||
4 | import { Stores } from '../@types/stores.types'; | 4 | import { Stores } from '../@types/stores.types'; |
@@ -14,6 +14,9 @@ export default class UIStore extends TypedStore { | |||
14 | 14 | ||
15 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 15 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
16 | super(stores, api, actions); | 16 | super(stores, api, actions); |
17 | |||
18 | makeObservable(this); | ||
19 | |||
17 | // Register action handlers | 20 | // Register action handlers |
18 | this.actions.ui.openSettings.listen(this._openSettings.bind(this)); | 21 | this.actions.ui.openSettings.listen(this._openSettings.bind(this)); |
19 | this.actions.ui.closeSettings.listen(this._closeSettings.bind(this)); | 22 | this.actions.ui.closeSettings.listen(this._closeSettings.bind(this)); |
diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts index b9c3c7576..c5e67c966 100644 --- a/src/stores/UserStore.ts +++ b/src/stores/UserStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable, computed, action } from 'mobx'; | 1 | import { observable, computed, action, makeObservable } from 'mobx'; |
2 | import moment from 'moment'; | 2 | import moment from 'moment'; |
3 | import jwt from 'jsonwebtoken'; | 3 | import jwt from 'jsonwebtoken'; |
4 | import localStorage from 'mobx-localstorage'; | 4 | import localStorage from 'mobx-localstorage'; |
@@ -93,6 +93,8 @@ export default class UserStore extends TypedStore { | |||
93 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 93 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
94 | super(stores, api, actions); | 94 | super(stores, api, actions); |
95 | 95 | ||
96 | makeObservable(this); | ||
97 | |||
96 | // Register action handlers | 98 | // Register action handlers |
97 | this.actions.user.login.listen(this._login.bind(this)); | 99 | this.actions.user.login.listen(this._login.bind(this)); |
98 | this.actions.user.retrievePassword.listen( | 100 | this.actions.user.retrievePassword.listen( |
diff --git a/src/stores/index.ts b/src/stores/index.ts index d31f2c933..8836f2892 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { RouterStore } from 'mobx-react-router'; | 1 | import { RouterStore } from '@superwf/mobx-react-router'; |
2 | import { ApiInterface } from '../api'; | 2 | import { ApiInterface } from '../api'; |
3 | import { Actions } from '../actions/lib/actions'; | 3 | import { Actions } from '../actions/lib/actions'; |
4 | import AppStore from './AppStore'; | 4 | import AppStore from './AppStore'; |
diff --git a/src/stores/lib/Request.js b/src/stores/lib/Request.js index 0ac36a218..e58341790 100644 --- a/src/stores/lib/Request.js +++ b/src/stores/lib/Request.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable, action, computed } from 'mobx'; | 1 | import { observable, action, computed, makeObservable } from 'mobx'; |
2 | import { isEqual } from 'lodash/fp'; | 2 | import { isEqual } from 'lodash/fp'; |
3 | 3 | ||
4 | export default class Request { | 4 | export default class Request { |
@@ -29,6 +29,8 @@ export default class Request { | |||
29 | _currentApiCall = null; | 29 | _currentApiCall = null; |
30 | 30 | ||
31 | constructor(api, method) { | 31 | constructor(api, method) { |
32 | makeObservable(this); | ||
33 | |||
32 | this._api = api; | 34 | this._api = api; |
33 | this._method = method; | 35 | this._method = method; |
34 | } | 36 | } |
diff --git a/src/stores/lib/TypedStore.ts b/src/stores/lib/TypedStore.ts index c97ae1aa5..e44eadd32 100644 --- a/src/stores/lib/TypedStore.ts +++ b/src/stores/lib/TypedStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { computed, IReactionPublic, observable } from 'mobx'; | 1 | import { computed, IReactionPublic, makeObservable, observable } from 'mobx'; |
2 | import { Actions } from '../../actions/lib/actions'; | 2 | import { Actions } from '../../actions/lib/actions'; |
3 | import { ApiInterface } from '../../api'; | 3 | import { ApiInterface } from '../../api'; |
4 | import { Stores } from '../../@types/stores.types'; | 4 | import { Stores } from '../../@types/stores.types'; |
@@ -9,6 +9,12 @@ export default abstract class TypedStore { | |||
9 | 9 | ||
10 | @observable _status: any = null; | 10 | @observable _status: any = null; |
11 | 11 | ||
12 | stores: Stores; | ||
13 | |||
14 | api: ApiInterface; | ||
15 | |||
16 | actions: Actions; | ||
17 | |||
12 | @computed get actionStatus() { | 18 | @computed get actionStatus() { |
13 | return this._status || []; | 19 | return this._status || []; |
14 | } | 20 | } |
@@ -17,11 +23,13 @@ export default abstract class TypedStore { | |||
17 | this._status = status; | 23 | this._status = status; |
18 | } | 24 | } |
19 | 25 | ||
20 | constructor( | 26 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
21 | public readonly stores: Stores, | 27 | makeObservable(this); |
22 | public readonly api: ApiInterface, | 28 | |
23 | public readonly actions: Actions, | 29 | this.stores = stores; |
24 | ) {} | 30 | this.api = api; |
31 | this.actions = actions; | ||
32 | } | ||
25 | 33 | ||
26 | registerReactions(reactions: { (r: IReactionPublic): void }[]): void { | 34 | registerReactions(reactions: { (r: IReactionPublic): void }[]): void { |
27 | for (const reaction of reactions) { | 35 | for (const reaction of reactions) { |
diff --git a/src/webview/recipe.js b/src/webview/recipe.js index 3c8a5326f..102d93642 100644 --- a/src/webview/recipe.js +++ b/src/webview/recipe.js | |||
@@ -2,7 +2,7 @@ | |||
2 | /* eslint-disable import/first */ | 2 | /* eslint-disable import/first */ |
3 | import { contextBridge, ipcRenderer } from 'electron'; | 3 | import { contextBridge, ipcRenderer } from 'electron'; |
4 | import { join } from 'path'; | 4 | import { join } from 'path'; |
5 | import { autorun, computed, observable } from 'mobx'; | 5 | import { autorun, computed, makeObservable, observable } from 'mobx'; |
6 | import { pathExistsSync, readFileSync } from 'fs-extra'; | 6 | import { pathExistsSync, readFileSync } from 'fs-extra'; |
7 | import { debounce } from 'lodash'; | 7 | import { debounce } from 'lodash'; |
8 | 8 | ||
@@ -154,6 +154,8 @@ class RecipeController { | |||
154 | hasUpdatedBeforeRecipeLoaded = false; | 154 | hasUpdatedBeforeRecipeLoaded = false; |
155 | 155 | ||
156 | constructor() { | 156 | constructor() { |
157 | makeObservable(this); | ||
158 | |||
157 | this.initialize(); | 159 | this.initialize(); |
158 | } | 160 | } |
159 | 161 | ||