diff options
author | Vijay A <vraravam@users.noreply.github.com> | 2021-10-06 22:59:03 +0530 |
---|---|---|
committer | Vijay A <vraravam@users.noreply.github.com> | 2021-10-06 22:59:03 +0530 |
commit | 5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216 (patch) | |
tree | 10cea6c608baea3481595ed9eb7be63ef03ca6c4 /src/features | |
parent | Bumped up version to: 5.6.2 (hotfix) (diff) | |
parent | 5.6.3-nightly.25 [skip ci] (diff) | |
download | ferdium-app-5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216.tar.gz ferdium-app-5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216.tar.zst ferdium-app-5fd7cd12cc62ceb6c4d654b3cb3b536412ed1216.zip |
Merge branch 'nightly' into release
Diffstat (limited to 'src/features')
43 files changed, 540 insertions, 441 deletions
diff --git a/src/features/appearance/index.js b/src/features/appearance/index.ts index 3aab2fcad..bb93507dc 100644 --- a/src/features/appearance/index.js +++ b/src/features/appearance/index.ts | |||
@@ -1,8 +1,6 @@ | |||
1 | import color from 'color'; | 1 | import color from 'color'; |
2 | import { reaction } from 'mobx'; | 2 | import { reaction } from 'mobx'; |
3 | import themeInfo from '../../assets/themeInfo.json'; | 3 | import { DEFAULT_APP_SETTINGS, iconSizeBias } from '../../config'; |
4 | import { iconSizeBias } from '../../config'; | ||
5 | import { DEFAULT_APP_SETTINGS } from '../../environment'; | ||
6 | 4 | ||
7 | const STYLE_ELEMENT_ID = 'custom-appearance-style'; | 5 | const STYLE_ELEMENT_ID = 'custom-appearance-style'; |
8 | 6 | ||
@@ -10,13 +8,15 @@ function createStyleElement() { | |||
10 | const styles = document.createElement('style'); | 8 | const styles = document.createElement('style'); |
11 | styles.id = STYLE_ELEMENT_ID; | 9 | styles.id = STYLE_ELEMENT_ID; |
12 | 10 | ||
13 | document.querySelector('head').appendChild(styles); | 11 | document.querySelector('head')?.appendChild(styles); |
14 | } | 12 | } |
15 | 13 | ||
16 | function setAppearance(style) { | 14 | function setAppearance(style) { |
17 | const styleElement = document.getElementById(STYLE_ELEMENT_ID); | 15 | const styleElement = document.querySelector(`#${STYLE_ELEMENT_ID}`); |
18 | 16 | ||
19 | styleElement.innerHTML = style; | 17 | if (styleElement) { |
18 | styleElement.innerHTML = style; | ||
19 | } | ||
20 | } | 20 | } |
21 | 21 | ||
22 | // See https://github.com/Qix-/color/issues/53#issuecomment-656590710 | 22 | // See https://github.com/Qix-/color/issues/53#issuecomment-656590710 |
@@ -26,24 +26,64 @@ function darkenAbsolute(originalColor, absoluteChange) { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | function generateAccentStyle(accentColorStr) { | 28 | function generateAccentStyle(accentColorStr) { |
29 | let style = ''; | ||
30 | |||
31 | Object.keys(themeInfo).forEach((property) => { | ||
32 | style += ` | ||
33 | ${themeInfo[property]} { | ||
34 | ${property}: ${accentColorStr}; | ||
35 | } | ||
36 | `; | ||
37 | }); | ||
38 | |||
39 | let accentColor = color(DEFAULT_APP_SETTINGS.accentColor); | 29 | let accentColor = color(DEFAULT_APP_SETTINGS.accentColor); |
40 | try { | 30 | try { |
41 | accentColor = color(accentColorStr); | 31 | accentColor = color(accentColorStr); |
42 | } catch (e) { | 32 | } catch { |
43 | // Ignore invalid accent color. | 33 | // Ignore invalid accent color. |
44 | } | 34 | } |
45 | const darkerColorStr = darkenAbsolute(accentColor, 5).hex(); | 35 | const darkerColorStr = darkenAbsolute(accentColor, 5).hex(); |
46 | style += ` | 36 | return ` |
37 | .theme__dark .app .sidebar .sidebar__button.is-muted, | ||
38 | .theme__dark .app .sidebar .sidebar__button.is-active, | ||
39 | .sidebar .sidebar__button.is-muted, | ||
40 | .sidebar .sidebar__button.is-active, | ||
41 | .tab-item.is-active, | ||
42 | .settings .account .invoices .invoices__action button, | ||
43 | .settings-navigation .settings-navigation__link.is-active .badge, | ||
44 | a.link, | ||
45 | button.link, | ||
46 | .auth .welcome .button:hover, | ||
47 | .auth .welcome .button__inverted, | ||
48 | .franz-form .franz-form__radio.is-selected, | ||
49 | .theme__dark .franz-form__button.franz-form__button--inverted, | ||
50 | .franz-form__button.franz-form__button--inverted { | ||
51 | color: ${accentColorStr}; | ||
52 | } | ||
53 | |||
54 | .settings .settings__header, | ||
55 | .settings .settings__close, | ||
56 | .settings-navigation .settings-navigation__link.is-active, | ||
57 | a.button, | ||
58 | button.button, | ||
59 | .auth, | ||
60 | .info-bar, | ||
61 | .info-bar.info-bar--primary, | ||
62 | .infobox.infobox--primary, | ||
63 | .theme__dark .badge.badge--primary, | ||
64 | .theme__dark, | ||
65 | .badge.badge--primary, | ||
66 | .content-tabs .content-tabs__tabs .content-tabs__item.is-active, | ||
67 | #electron-app-title-bar .toolbar-dropdown:not(.open) > .toolbar-button > button:hover, | ||
68 | #electron-app-title-bar .list-item.selected .menu-item, | ||
69 | #electron-app-title-bar .list-item.selected:focus .menu-item, | ||
70 | .theme__dark .quick-switch .active, | ||
71 | .franz-form .franz-form__toggle-wrapper .franz-form__toggle.is-active .franz-form__toggle-button, | ||
72 | .theme__dark .franz-form__button, | ||
73 | .franz-form__button, | ||
74 | .ferdi__fab, | ||
75 | .franz-form .franz-form__slider-wrapper .slider::-webkit-slider-thumb { | ||
76 | background: ${accentColorStr}; | ||
77 | } | ||
78 | |||
79 | .settings .settings__header .separator { | ||
80 | border-right-color: ${accentColorStr}; | ||
81 | } | ||
82 | |||
83 | .franz-form .franz-form__radio.is-selected { | ||
84 | border-color: ${accentColorStr}; | ||
85 | } | ||
86 | |||
47 | a.button:hover, button.button:hover { | 87 | a.button:hover, button.button:hover { |
48 | background: ${darkenAbsolute(accentColor, 10).hex()}; | 88 | background: ${darkenAbsolute(accentColor, 10).hex()}; |
49 | } | 89 | } |
@@ -72,27 +112,27 @@ function generateAccentStyle(accentColorStr) { | |||
72 | background: ${accentColor.lighten(0.35).hex()}; | 112 | background: ${accentColor.lighten(0.35).hex()}; |
73 | } | 113 | } |
74 | `; | 114 | `; |
75 | |||
76 | return style; | ||
77 | } | 115 | } |
78 | 116 | ||
79 | function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { | 117 | function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { |
80 | const width = Number(widthStr); | 118 | const width = Number(widthStr); |
81 | const iconSize = Number(iconSizeStr) - iconSizeBias; | 119 | const iconSize = Number(iconSizeStr) - iconSizeBias; |
82 | 120 | ||
83 | return vertical ? ` | 121 | return vertical |
122 | ? ` | ||
84 | .tab-item { | 123 | .tab-item { |
85 | width: ${width - 2}px !important; | 124 | width: ${width - 2}px !important; |
86 | height: ${width - 5 + iconSize}px !important; | 125 | height: ${width - 5 + iconSize}px !important; |
87 | min-height: unset; | 126 | min-height: unset; |
88 | } | 127 | } |
89 | .tab-item .tab-item__icon { | 128 | .tab-item .tab-item__icon { |
90 | width: ${(width / 2) + iconSize}px !important; | 129 | width: ${width / 2 + iconSize}px !important; |
91 | } | 130 | } |
92 | .sidebar__button { | 131 | .sidebar__button { |
93 | font-size: ${width / 3}px !important; | 132 | font-size: ${width / 3}px !important; |
94 | } | 133 | } |
95 | ` : ` | 134 | ` |
135 | : ` | ||
96 | .sidebar { | 136 | .sidebar { |
97 | width: ${width}px !important; | 137 | width: ${width}px !important; |
98 | } | 138 | } |
@@ -101,7 +141,7 @@ function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { | |||
101 | height: ${width - 5 + iconSize}px !important; | 141 | height: ${width - 5 + iconSize}px !important; |
102 | } | 142 | } |
103 | .tab-item .tab-item__icon { | 143 | .tab-item .tab-item__icon { |
104 | width: ${(width / 2) + iconSize}px !important; | 144 | width: ${width / 2 + iconSize}px !important; |
105 | } | 145 | } |
106 | .sidebar__button { | 146 | .sidebar__button { |
107 | font-size: ${width / 3}px !important; | 147 | font-size: ${width / 3}px !important; |
@@ -129,14 +169,14 @@ function generateShowDragAreaStyle(accentColor) { | |||
129 | } | 169 | } |
130 | 170 | ||
131 | function generateVerticalStyle(widthStr, alwaysShowWorkspaces) { | 171 | function generateVerticalStyle(widthStr, alwaysShowWorkspaces) { |
132 | if (!document.getElementById('vertical-style')) { | 172 | if (!document.querySelector('#vertical-style')) { |
133 | const link = document.createElement('link'); | 173 | const link = document.createElement('link'); |
134 | link.id = 'vertical-style'; | 174 | link.id = 'vertical-style'; |
135 | link.rel = 'stylesheet'; | 175 | link.rel = 'stylesheet'; |
136 | link.type = 'text/css'; | 176 | link.type = 'text/css'; |
137 | link.href = './styles/vertical.css'; | 177 | link.href = './styles/vertical.css'; |
138 | 178 | ||
139 | document.head.appendChild(link); | 179 | document.head.append(link); |
140 | } | 180 | } |
141 | const width = Number(widthStr); | 181 | const width = Number(widthStr); |
142 | const sidebarWidth = width - 4; | 182 | const sidebarWidth = width - 4; |
@@ -144,20 +184,19 @@ function generateVerticalStyle(widthStr, alwaysShowWorkspaces) { | |||
144 | 184 | ||
145 | return ` | 185 | return ` |
146 | .sidebar { | 186 | .sidebar { |
147 | height: ${sidebarWidth + verticalStyleOffset + 1}px !important; | 187 | ${ |
148 | ${alwaysShowWorkspaces ? ` | 188 | alwaysShowWorkspaces |
189 | ? ` | ||
149 | width: calc(100% - 300px) !important; | 190 | width: calc(100% - 300px) !important; |
150 | ` : ''} | 191 | ` |
192 | : '' | ||
193 | } | ||
151 | } | 194 | } |
152 | 195 | ||
153 | .sidebar .sidebar__button { | 196 | .sidebar .sidebar__button { |
154 | width: ${width}px; | 197 | width: ${width}px; |
155 | } | 198 | } |
156 | 199 | ||
157 | .app .app__content { | ||
158 | padding-top: ${sidebarWidth + verticalStyleOffset + 1}px !important; | ||
159 | } | ||
160 | |||
161 | .workspaces-drawer { | 200 | .workspaces-drawer { |
162 | margin-top: -${sidebarWidth - verticalStyleOffset - 1}px !important; | 201 | margin-top: -${sidebarWidth - verticalStyleOffset - 1}px !important; |
163 | } | 202 | } |
@@ -192,21 +231,31 @@ function generateStyle(settings) { | |||
192 | alwaysShowWorkspaces, | 231 | alwaysShowWorkspaces, |
193 | } = settings; | 232 | } = settings; |
194 | 233 | ||
195 | if (accentColor.toLowerCase() !== DEFAULT_APP_SETTINGS.accentColor.toLowerCase()) { | 234 | if ( |
235 | accentColor.toLowerCase() !== DEFAULT_APP_SETTINGS.accentColor.toLowerCase() | ||
236 | ) { | ||
196 | style += generateAccentStyle(accentColor); | 237 | style += generateAccentStyle(accentColor); |
197 | } | 238 | } |
198 | if (serviceRibbonWidth !== DEFAULT_APP_SETTINGS.serviceRibbonWidth | 239 | if ( |
199 | || iconSize !== DEFAULT_APP_SETTINGS.iconSize) { | 240 | serviceRibbonWidth !== DEFAULT_APP_SETTINGS.serviceRibbonWidth || |
200 | style += generateServiceRibbonWidthStyle(serviceRibbonWidth, iconSize, useVerticalStyle); | 241 | iconSize !== DEFAULT_APP_SETTINGS.iconSize |
242 | ) { | ||
243 | style += generateServiceRibbonWidthStyle( | ||
244 | serviceRibbonWidth, | ||
245 | iconSize, | ||
246 | useVerticalStyle, | ||
247 | ); | ||
201 | } | 248 | } |
202 | if (showDragArea) { | 249 | if (showDragArea) { |
203 | style += generateShowDragAreaStyle(accentColor); | 250 | style += generateShowDragAreaStyle(accentColor); |
204 | } | 251 | } |
205 | if (useVerticalStyle) { | 252 | if (useVerticalStyle) { |
206 | style += generateVerticalStyle(serviceRibbonWidth, alwaysShowWorkspaces); | 253 | style += generateVerticalStyle(serviceRibbonWidth, alwaysShowWorkspaces); |
207 | } else if (document.getElementById('vertical-style')) { | 254 | } else if (document.querySelector('#vertical-style')) { |
208 | const link = document.getElementById('vertical-style'); | 255 | const link = document.querySelector('#vertical-style'); |
209 | document.head.removeChild(link); | 256 | if (link) { |
257 | link.remove(); | ||
258 | } | ||
210 | } | 259 | } |
211 | if (alwaysShowWorkspaces) { | 260 | if (alwaysShowWorkspaces) { |
212 | style += generateOpenWorkspaceStyle(); | 261 | style += generateOpenWorkspaceStyle(); |
@@ -225,14 +274,14 @@ export default function initAppearance(stores) { | |||
225 | 274 | ||
226 | // Update style when settings change | 275 | // Update style when settings change |
227 | reaction( | 276 | reaction( |
228 | () => ([ | 277 | () => [ |
229 | settings.all.app.accentColor, | 278 | settings.all.app.accentColor, |
230 | settings.all.app.serviceRibbonWidth, | 279 | settings.all.app.serviceRibbonWidth, |
231 | settings.all.app.iconSize, | 280 | settings.all.app.iconSize, |
232 | settings.all.app.showDragArea, | 281 | settings.all.app.showDragArea, |
233 | settings.all.app.useVerticalStyle, | 282 | settings.all.app.useVerticalStyle, |
234 | settings.all.app.alwaysShowWorkspaces, | 283 | settings.all.app.alwaysShowWorkspaces, |
235 | ]), | 284 | ], |
236 | () => { | 285 | () => { |
237 | updateStyle(settings.all.app); | 286 | updateStyle(settings.all.app); |
238 | }, | 287 | }, |
diff --git a/src/features/basicAuth/Component.js b/src/features/basicAuth/Component.js index a9601836b..3cf937f98 100644 --- a/src/features/basicAuth/Component.js +++ b/src/features/basicAuth/Component.js | |||
@@ -2,19 +2,14 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import injectSheet from 'react-jss'; | 3 | import injectSheet from 'react-jss'; |
4 | import { observer } from 'mobx-react'; | 4 | import { observer } from 'mobx-react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | 7 | ||
8 | import Modal from '../../components/ui/Modal'; | 8 | import Modal from '../../components/ui/Modal'; |
9 | import Input from '../../components/ui/Input'; | 9 | import Input from '../../components/ui/Input'; |
10 | import Button from '../../components/ui/Button'; | 10 | import Button from '../../components/ui/Button'; |
11 | 11 | ||
12 | import { | 12 | import { state, resetState, sendCredentials, cancelLogin } from './store'; |
13 | state, | ||
14 | resetState, | ||
15 | sendCredentials, | ||
16 | cancelLogin, | ||
17 | } from './store'; | ||
18 | import Form from './Form'; | 13 | import Form from './Form'; |
19 | 14 | ||
20 | import styles from './styles'; | 15 | import styles from './styles'; |
@@ -23,17 +18,15 @@ import globalMessages from '../../i18n/globalMessages'; | |||
23 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
24 | signIn: { | 19 | signIn: { |
25 | id: 'feature.basicAuth.signIn', | 20 | id: 'feature.basicAuth.signIn', |
26 | defaultMessage: '!!!Sign In', | 21 | defaultMessage: 'Sign In', |
27 | }, | 22 | }, |
28 | }); | 23 | }); |
29 | 24 | ||
30 | export default @injectSheet(styles) @observer class BasicAuthModal extends Component { | 25 | @injectSheet(styles) |
26 | @observer | ||
27 | class BasicAuthModal extends Component { | ||
31 | static propTypes = { | 28 | static propTypes = { |
32 | classes: PropTypes.object.isRequired, | 29 | classes: PropTypes.object.isRequired, |
33 | } | ||
34 | |||
35 | static contextTypes = { | ||
36 | intl: intlShape, | ||
37 | }; | 30 | }; |
38 | 31 | ||
39 | submit(e) { | 32 | submit(e) { |
@@ -56,20 +49,15 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo | |||
56 | } | 49 | } |
57 | 50 | ||
58 | render() { | 51 | render() { |
59 | const { | 52 | const { classes } = this.props; |
60 | classes, | ||
61 | } = this.props; | ||
62 | 53 | ||
63 | const { | 54 | const { isModalVisible, authInfo } = state; |
64 | isModalVisible, | ||
65 | authInfo, | ||
66 | } = state; | ||
67 | 55 | ||
68 | if (!authInfo) { | 56 | if (!authInfo) { |
69 | return null; | 57 | return null; |
70 | } | 58 | } |
71 | 59 | ||
72 | const { intl } = this.context; | 60 | const { intl } = this.props; |
73 | 61 | ||
74 | return ( | 62 | return ( |
75 | <Modal | 63 | <Modal |
@@ -89,10 +77,7 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo | |||
89 | onSubmit={this.submit.bind(this)} | 77 | onSubmit={this.submit.bind(this)} |
90 | className={classnames('franz-form', classes.form)} | 78 | className={classnames('franz-form', classes.form)} |
91 | > | 79 | > |
92 | <Input | 80 | <Input field={Form.$('user')} showLabel={false} /> |
93 | field={Form.$('user')} | ||
94 | showLabel={false} | ||
95 | /> | ||
96 | <Input | 81 | <Input |
97 | field={Form.$('password')} | 82 | field={Form.$('password')} |
98 | showLabel={false} | 83 | showLabel={false} |
@@ -105,13 +90,11 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo | |||
105 | buttonType="secondary" | 90 | buttonType="secondary" |
106 | onClick={this.cancel.bind(this)} | 91 | onClick={this.cancel.bind(this)} |
107 | /> | 92 | /> |
108 | <Button | 93 | <Button type="submit" label={intl.formatMessage(messages.signIn)} /> |
109 | type="submit" | ||
110 | label={intl.formatMessage(messages.signIn)} | ||
111 | /> | ||
112 | </div> | 94 | </div> |
113 | </form> | 95 | </form> |
114 | </Modal> | 96 | </Modal> |
115 | ); | 97 | ); |
116 | } | 98 | } |
117 | } | 99 | } |
100 | export default injectIntl(BasicAuthModal); | ||
diff --git a/src/features/basicAuth/Form.js b/src/features/basicAuth/Form.ts index 95721d0e9..e84156d96 100644 --- a/src/features/basicAuth/Form.js +++ b/src/features/basicAuth/Form.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import Form from '../../lib/Form'; | 1 | import Form from '../../lib/Form'; |
2 | 2 | ||
3 | // @ts-expect-error Expected 0 arguments, but got 1 | ||
3 | export default new Form({ | 4 | export default new Form({ |
4 | fields: { | 5 | fields: { |
5 | user: { | 6 | user: { |
diff --git a/src/features/basicAuth/mainIpcHandler.js b/src/features/basicAuth/mainIpcHandler.ts index ae4e7cf93..4ec3848e8 100644 --- a/src/features/basicAuth/mainIpcHandler.js +++ b/src/features/basicAuth/mainIpcHandler.ts | |||
@@ -1,6 +1,8 @@ | |||
1 | import { BrowserWindow } from 'electron'; | ||
2 | |||
1 | const debug = require('debug')('Ferdi:feature:basicAuth:main'); | 3 | const debug = require('debug')('Ferdi:feature:basicAuth:main'); |
2 | 4 | ||
3 | export default function mainIpcHandler(mainWindow, authInfo) { | 5 | export default function mainIpcHandler(mainWindow: BrowserWindow, authInfo) { |
4 | debug('Sending basic auth call', authInfo); | 6 | debug('Sending basic auth call', authInfo); |
5 | 7 | ||
6 | mainWindow.webContents.send('feature:basic-auth', { | 8 | mainWindow.webContents.send('feature:basic-auth', { |
diff --git a/src/features/basicAuth/store.js b/src/features/basicAuth/store.ts index 0713ff572..0713ff572 100644 --- a/src/features/basicAuth/store.js +++ b/src/features/basicAuth/store.ts | |||
diff --git a/src/features/basicAuth/styles.js b/src/features/basicAuth/styles.ts index 6bdaf9a6e..6bdaf9a6e 100644 --- a/src/features/basicAuth/styles.js +++ b/src/features/basicAuth/styles.ts | |||
diff --git a/src/features/communityRecipes/index.js b/src/features/communityRecipes/index.ts index 828c6d867..828c6d867 100644 --- a/src/features/communityRecipes/index.js +++ b/src/features/communityRecipes/index.ts | |||
diff --git a/src/features/communityRecipes/store.js b/src/features/communityRecipes/store.ts index a3614dd11..a8d358ba0 100644 --- a/src/features/communityRecipes/store.js +++ b/src/features/communityRecipes/store.ts | |||
@@ -4,7 +4,11 @@ import { FeatureStore } from '../utils/FeatureStore'; | |||
4 | const debug = require('debug')('Ferdi:feature:communityRecipes:store'); | 4 | const debug = require('debug')('Ferdi:feature:communityRecipes:store'); |
5 | 5 | ||
6 | export class CommunityRecipesStore extends FeatureStore { | 6 | export class CommunityRecipesStore extends FeatureStore { |
7 | start(stores, actions) { | 7 | stores: any; |
8 | |||
9 | actions: any; | ||
10 | |||
11 | start(stores: any, actions: any) { | ||
8 | debug('start'); | 12 | debug('start'); |
9 | this.stores = stores; | 13 | this.stores = stores; |
10 | this.actions = actions; | 14 | this.actions = actions; |
@@ -18,12 +22,17 @@ export class CommunityRecipesStore extends FeatureStore { | |||
18 | @computed get communityRecipes() { | 22 | @computed get communityRecipes() { |
19 | if (!this.stores) return []; | 23 | if (!this.stores) return []; |
20 | 24 | ||
21 | return this.stores.recipePreviews.dev.map((r) => { | 25 | return this.stores.recipePreviews.dev.map( |
22 | // TODO: Need to figure out if this is even necessary/used | 26 | (recipePreview: { isDevRecipe: boolean; author: any[] }) => { |
23 | r.isDevRecipe = !!r.author.find((a) => a.email === this.stores.user.data.email); | 27 | // TODO: Need to figure out if this is even necessary/used |
28 | recipePreview.isDevRecipe = !!recipePreview.author.some( | ||
29 | (author: { email: any }) => | ||
30 | author.email === this.stores.user.data.email, | ||
31 | ); | ||
24 | 32 | ||
25 | return r; | 33 | return recipePreview; |
26 | }); | 34 | }, |
35 | ); | ||
27 | } | 36 | } |
28 | } | 37 | } |
29 | 38 | ||
diff --git a/src/features/nightlyBuilds/Component.js b/src/features/nightlyBuilds/Component.js index e43287db5..814d529d9 100644 --- a/src/features/nightlyBuilds/Component.js +++ b/src/features/nightlyBuilds/Component.js | |||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, inject } from 'mobx-react'; | 3 | import { observer, inject } from 'mobx-react'; |
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import { H1 } from '@meetfranz/ui'; | 6 | import { H1 } from '@meetfranz/ui'; |
7 | 7 | ||
8 | import Modal from '../../components/ui/Modal'; | 8 | import Modal from '../../components/ui/Modal'; |
@@ -16,15 +16,16 @@ import globalMessages from '../../i18n/globalMessages'; | |||
16 | const messages = defineMessages({ | 16 | const messages = defineMessages({ |
17 | title: { | 17 | title: { |
18 | id: 'feature.nightlyBuilds.title', | 18 | id: 'feature.nightlyBuilds.title', |
19 | defaultMessage: '!!!Nightly Builds', | 19 | defaultMessage: 'Nightly Builds', |
20 | }, | 20 | }, |
21 | info: { | 21 | info: { |
22 | id: 'feature.nightlyBuilds.info', | 22 | id: 'feature.nightlyBuilds.info', |
23 | defaultMessage: '!!!Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don\'t know what you are doing, we suggest not activating nightly builds.', | 23 | defaultMessage: |
24 | "Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don't know what you are doing, we suggest not activating nightly builds.", | ||
24 | }, | 25 | }, |
25 | activate: { | 26 | activate: { |
26 | id: 'feature.nightlyBuilds.activate', | 27 | id: 'feature.nightlyBuilds.activate', |
27 | defaultMessage: '!!!Activate', | 28 | defaultMessage: 'Activate', |
28 | }, | 29 | }, |
29 | }); | 30 | }); |
30 | 31 | ||
@@ -52,11 +53,10 @@ const styles = () => ({ | |||
52 | }, | 53 | }, |
53 | }); | 54 | }); |
54 | 55 | ||
55 | export default @injectSheet(styles) @inject('stores', 'actions') @observer class NightlyBuildsModal extends Component { | 56 | @injectSheet(styles) |
56 | static contextTypes = { | 57 | @inject('stores', 'actions') |
57 | intl: intlShape, | 58 | @observer |
58 | }; | 59 | class NightlyBuildsModal extends Component { |
59 | |||
60 | close() { | 60 | close() { |
61 | ModalState.isModalVisible = false; | 61 | ModalState.isModalVisible = false; |
62 | 62 | ||
@@ -84,11 +84,9 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
84 | render() { | 84 | render() { |
85 | const { isModalVisible } = ModalState; | 85 | const { isModalVisible } = ModalState; |
86 | 86 | ||
87 | const { | 87 | const { classes } = this.props; |
88 | classes, | ||
89 | } = this.props; | ||
90 | 88 | ||
91 | const { intl } = this.context; | 89 | const { intl } = this.props; |
92 | 90 | ||
93 | return ( | 91 | return ( |
94 | <Modal | 92 | <Modal |
@@ -132,3 +130,5 @@ NightlyBuildsModal.wrappedComponent.propTypes = { | |||
132 | }).isRequired, | 130 | }).isRequired, |
133 | classes: PropTypes.object.isRequired, | 131 | classes: PropTypes.object.isRequired, |
134 | }; | 132 | }; |
133 | |||
134 | export default injectIntl(NightlyBuildsModal); | ||
diff --git a/src/features/nightlyBuilds/store.js b/src/features/nightlyBuilds/store.ts index ed06e5a7d..ed06e5a7d 100644 --- a/src/features/nightlyBuilds/store.js +++ b/src/features/nightlyBuilds/store.ts | |||
diff --git a/src/features/publishDebugInfo/Component.js b/src/features/publishDebugInfo/Component.js index 5387bd358..5b5036752 100644 --- a/src/features/publishDebugInfo/Component.js +++ b/src/features/publishDebugInfo/Component.js | |||
@@ -2,7 +2,7 @@ import { H1 } from '@meetfranz/ui'; | |||
2 | import { inject, observer } from 'mobx-react'; | 2 | import { inject, observer } from 'mobx-react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import React, { Component } from 'react'; | 4 | import React, { Component } from 'react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | import { state as ModalState } from './store'; | 7 | import { state as ModalState } from './store'; |
8 | import { sendAuthRequest } from '../../api/utils/auth'; | 8 | import { sendAuthRequest } from '../../api/utils/auth'; |
@@ -18,35 +18,37 @@ const debug = require('debug')('Ferdi:feature:publishDebugInfo'); | |||
18 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
19 | title: { | 19 | title: { |
20 | id: 'feature.publishDebugInfo.title', | 20 | id: 'feature.publishDebugInfo.title', |
21 | defaultMessage: '!!!Publish debug information', | 21 | defaultMessage: 'Publish debug information', |
22 | }, | 22 | }, |
23 | info: { | 23 | info: { |
24 | id: 'feature.publishDebugInfo.info', | 24 | id: 'feature.publishDebugInfo.info', |
25 | defaultMessage: '!!!Publishing your debug information helps us find issues and errors in Ferdi. By publishing your debug information you accept Ferdi Debugger\'s privacy policy and terms of service', | 25 | defaultMessage: |
26 | "Publishing your debug information helps us find issues and errors in Ferdi. By publishing your debug information you accept Ferdi Debugger's privacy policy and terms of service", | ||
26 | }, | 27 | }, |
27 | error: { | 28 | error: { |
28 | id: 'feature.publishDebugInfo.error', | 29 | id: 'feature.publishDebugInfo.error', |
29 | defaultMessage: '!!!There was an error while trying to publish the debug information. Please try again later or view the console for more information.', | 30 | defaultMessage: |
31 | 'There was an error while trying to publish the debug information. Please try again later or view the console for more information.', | ||
30 | }, | 32 | }, |
31 | privacy: { | 33 | privacy: { |
32 | id: 'feature.publishDebugInfo.privacy', | 34 | id: 'feature.publishDebugInfo.privacy', |
33 | defaultMessage: '!!!Privacy policy', | 35 | defaultMessage: 'Privacy policy', |
34 | }, | 36 | }, |
35 | terms: { | 37 | terms: { |
36 | id: 'feature.publishDebugInfo.terms', | 38 | id: 'feature.publishDebugInfo.terms', |
37 | defaultMessage: '!!!Terms of service', | 39 | defaultMessage: 'Terms of service', |
38 | }, | 40 | }, |
39 | publish: { | 41 | publish: { |
40 | id: 'feature.publishDebugInfo.publish', | 42 | id: 'feature.publishDebugInfo.publish', |
41 | defaultMessage: '!!!Accept and publish', | 43 | defaultMessage: 'Accept and publish', |
42 | }, | 44 | }, |
43 | published: { | 45 | published: { |
44 | id: 'feature.publishDebugInfo.published', | 46 | id: 'feature.publishDebugInfo.published', |
45 | defaultMessage: '!!!Your debug log was published and is now availible at', | 47 | defaultMessage: 'Your debug log was published and is now availible at', |
46 | }, | 48 | }, |
47 | }); | 49 | }); |
48 | 50 | ||
49 | const styles = (theme) => ({ | 51 | const styles = theme => ({ |
50 | container: { | 52 | container: { |
51 | minWidth: '70vw', | 53 | minWidth: '70vw', |
52 | }, | 54 | }, |
@@ -69,7 +71,8 @@ const styles = (theme) => ({ | |||
69 | width: '100%', | 71 | width: '100%', |
70 | 72 | ||
71 | '& div': { | 73 | '& div': { |
72 | fontFamily: 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | 74 | fontFamily: |
75 | 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | ||
73 | }, | 76 | }, |
74 | 77 | ||
75 | '& input': { | 78 | '& input': { |
@@ -81,20 +84,19 @@ const styles = (theme) => ({ | |||
81 | }, | 84 | }, |
82 | }); | 85 | }); |
83 | 86 | ||
84 | export default @injectSheet(styles) @inject('stores', 'actions') @observer class PublishDebugLogModal extends Component { | 87 | @injectSheet(styles) |
88 | @inject('stores', 'actions') | ||
89 | @observer | ||
90 | class PublishDebugLogModal extends Component { | ||
85 | static propTypes = { | 91 | static propTypes = { |
86 | classes: PropTypes.object.isRequired, | 92 | classes: PropTypes.object.isRequired, |
87 | }; | 93 | }; |
88 | 94 | ||
89 | static contextTypes = { | ||
90 | intl: intlShape, | ||
91 | }; | ||
92 | |||
93 | state = { | 95 | state = { |
94 | log: null, | 96 | log: null, |
95 | error: false, | 97 | error: false, |
96 | isSendingLog: false, | 98 | isSendingLog: false, |
97 | } | 99 | }; |
98 | 100 | ||
99 | // Close this modal | 101 | // Close this modal |
100 | close() { | 102 | close() { |
@@ -109,12 +111,16 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
109 | 111 | ||
110 | const debugInfo = JSON.stringify(this.props.stores.app.debugInfo); | 112 | const debugInfo = JSON.stringify(this.props.stores.app.debugInfo); |
111 | 113 | ||
112 | const request = await sendAuthRequest(`${DEBUG_API}/create`, { | 114 | const request = await sendAuthRequest( |
113 | method: 'POST', | 115 | `${DEBUG_API}/create`, |
114 | body: JSON.stringify({ | 116 | { |
115 | log: debugInfo, | 117 | method: 'POST', |
116 | }), | 118 | body: JSON.stringify({ |
117 | }, false); | 119 | log: debugInfo, |
120 | }), | ||
121 | }, | ||
122 | false, | ||
123 | ); | ||
118 | 124 | ||
119 | debug(`debugInfo: publishing status: ${request.status}`); | 125 | debug(`debugInfo: publishing status: ${request.status}`); |
120 | if (request.status === 200) { | 126 | if (request.status === 200) { |
@@ -140,17 +146,11 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
140 | render() { | 146 | render() { |
141 | const { isModalVisible } = ModalState; | 147 | const { isModalVisible } = ModalState; |
142 | 148 | ||
143 | const { | 149 | const { classes } = this.props; |
144 | classes, | ||
145 | } = this.props; | ||
146 | 150 | ||
147 | const { | 151 | const { log, error, isSendingLog } = this.state; |
148 | log, | ||
149 | error, | ||
150 | isSendingLog, | ||
151 | } = this.state; | ||
152 | 152 | ||
153 | const { intl } = this.context; | 153 | const { intl } = this.props; |
154 | 154 | ||
155 | return ( | 155 | return ( |
156 | <Modal | 156 | <Modal |
@@ -159,12 +159,12 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
159 | close={() => this.close()} | 159 | close={() => this.close()} |
160 | > | 160 | > |
161 | <div className={classes.container}> | 161 | <div className={classes.container}> |
162 | <H1> | 162 | <H1>{intl.formatMessage(messages.title)}</H1> |
163 | {intl.formatMessage(messages.title)} | 163 | {log && ( |
164 | </H1> | ||
165 | { log && ( | ||
166 | <> | 164 | <> |
167 | <p className={classes.info}>{intl.formatMessage(messages.published)}</p> | 165 | <p className={classes.info}> |
166 | {intl.formatMessage(messages.published)} | ||
167 | </p> | ||
168 | <Input | 168 | <Input |
169 | className={classes.url} | 169 | className={classes.url} |
170 | showLabel={false} | 170 | showLabel={false} |
@@ -184,12 +184,24 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
184 | 184 | ||
185 | {!log && !error && ( | 185 | {!log && !error && ( |
186 | <> | 186 | <> |
187 | <p className={classes.info}>{intl.formatMessage(messages.info)}</p> | 187 | <p className={classes.info}> |
188 | 188 | {intl.formatMessage(messages.info)} | |
189 | <a href={`${DEBUG_API}/privacy.html`} target="_blank" className={classes.link} rel="noreferrer"> | 189 | </p> |
190 | |||
191 | <a | ||
192 | href={`${DEBUG_API}/privacy.html`} | ||
193 | target="_blank" | ||
194 | className={classes.link} | ||
195 | rel="noreferrer" | ||
196 | > | ||
190 | {intl.formatMessage(messages.privacy)} | 197 | {intl.formatMessage(messages.privacy)} |
191 | </a> | 198 | </a> |
192 | <a href={`${DEBUG_API}/terms.html`} target="_blank" className={classes.link} rel="noreferrer"> | 199 | <a |
200 | href={`${DEBUG_API}/terms.html`} | ||
201 | target="_blank" | ||
202 | className={classes.link} | ||
203 | rel="noreferrer" | ||
204 | > | ||
193 | {intl.formatMessage(messages.terms)} | 205 | {intl.formatMessage(messages.terms)} |
194 | </a> | 206 | </a> |
195 | 207 | ||
@@ -216,3 +228,5 @@ PublishDebugLogModal.wrappedComponent.propTypes = { | |||
216 | service: PropTypes.instanceOf(ServicesStore).isRequired, | 228 | service: PropTypes.instanceOf(ServicesStore).isRequired, |
217 | }).isRequired, | 229 | }).isRequired, |
218 | }; | 230 | }; |
231 | |||
232 | export default injectIntl(PublishDebugLogModal); | ||
diff --git a/src/features/publishDebugInfo/store.js b/src/features/publishDebugInfo/store.ts index ed06e5a7d..ed06e5a7d 100644 --- a/src/features/publishDebugInfo/store.js +++ b/src/features/publishDebugInfo/store.ts | |||
diff --git a/src/features/quickSwitch/Component.js b/src/features/quickSwitch/Component.js index 78d5d94a0..f21db0ebd 100644 --- a/src/features/quickSwitch/Component.js +++ b/src/features/quickSwitch/Component.js | |||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; | |||
4 | import { observer, inject } from 'mobx-react'; | 4 | import { observer, inject } from 'mobx-react'; |
5 | import { reaction } from 'mobx'; | 5 | import { reaction } from 'mobx'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | import { defineMessages, intlShape } from 'react-intl'; | 7 | import { defineMessages, injectIntl } from 'react-intl'; |
8 | import { Input } from '@meetfranz/forms'; | 8 | import { Input } from '@meetfranz/forms'; |
9 | import { H1 } from '@meetfranz/ui'; | 9 | import { H1 } from '@meetfranz/ui'; |
10 | 10 | ||
@@ -16,19 +16,20 @@ import ServicesStore from '../../stores/ServicesStore'; | |||
16 | const messages = defineMessages({ | 16 | const messages = defineMessages({ |
17 | title: { | 17 | title: { |
18 | id: 'feature.quickSwitch.title', | 18 | id: 'feature.quickSwitch.title', |
19 | defaultMessage: '!!!QuickSwitch', | 19 | defaultMessage: 'QuickSwitch', |
20 | }, | 20 | }, |
21 | search: { | 21 | search: { |
22 | id: 'feature.quickSwitch.search', | 22 | id: 'feature.quickSwitch.search', |
23 | defaultMessage: '!!!Search...', | 23 | defaultMessage: 'Search...', |
24 | }, | 24 | }, |
25 | info: { | 25 | info: { |
26 | id: 'feature.quickSwitch.info', | 26 | id: 'feature.quickSwitch.info', |
27 | defaultMessage: '!!!Select a service with TAB, ↑ and ↓. Open a service with ENTER.', | 27 | defaultMessage: |
28 | 'Select a service with TAB, ↑ and ↓. Open a service with ENTER.', | ||
28 | }, | 29 | }, |
29 | }); | 30 | }); |
30 | 31 | ||
31 | const styles = (theme) => ({ | 32 | const styles = theme => ({ |
32 | modal: { | 33 | modal: { |
33 | width: '80%', | 34 | width: '80%', |
34 | maxWidth: 600, | 35 | maxWidth: 600, |
@@ -80,20 +81,19 @@ const styles = (theme) => ({ | |||
80 | }, | 81 | }, |
81 | }); | 82 | }); |
82 | 83 | ||
83 | export default @injectSheet(styles) @inject('stores', 'actions') @observer class QuickSwitchModal extends Component { | 84 | @injectSheet(styles) |
85 | @inject('stores', 'actions') | ||
86 | @observer | ||
87 | class QuickSwitchModal extends Component { | ||
84 | static propTypes = { | 88 | static propTypes = { |
85 | classes: PropTypes.object.isRequired, | 89 | classes: PropTypes.object.isRequired, |
86 | }; | 90 | }; |
87 | 91 | ||
88 | static contextTypes = { | ||
89 | intl: intlShape, | ||
90 | }; | ||
91 | |||
92 | state = { | 92 | state = { |
93 | selected: 0, | 93 | selected: 0, |
94 | search: '', | 94 | search: '', |
95 | wasPrevVisible: false, | 95 | wasPrevVisible: false, |
96 | } | 96 | }; |
97 | 97 | ||
98 | ARROW_DOWN = 40; | 98 | ARROW_DOWN = 40; |
99 | 99 | ||
@@ -118,9 +118,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
118 | this.openService = this.openService.bind(this); | 118 | this.openService = this.openService.bind(this); |
119 | 119 | ||
120 | reaction( | 120 | reaction( |
121 | () => ( | 121 | () => ModalState.isModalVisible, |
122 | ModalState.isModalVisible | ||
123 | ), | ||
124 | () => { | 122 | () => { |
125 | this._handleVisibilityChange(); | 123 | this._handleVisibilityChange(); |
126 | }, | 124 | }, |
@@ -140,10 +138,17 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
140 | // Get currently shown services | 138 | // Get currently shown services |
141 | services() { | 139 | services() { |
142 | let services = []; | 140 | let services = []; |
143 | if (this.state.search && compact(invoke(this.state.search, 'match', /^[a-z0-9]/i)).length > 0) { | 141 | if ( |
142 | this.state.search && | ||
143 | compact(invoke(this.state.search, 'match', /^[\da-z]/i)).length > 0 | ||
144 | ) { | ||
144 | // Apply simple search algorythm to list of all services | 145 | // Apply simple search algorythm to list of all services |
145 | services = this.props.stores.services.allDisplayed; | 146 | services = this.props.stores.services.allDisplayed; |
146 | services = services.filter((service) => service.name.toLowerCase().search(this.state.search.toLowerCase()) !== -1); | 147 | services = services.filter( |
148 | service => | ||
149 | service.name.toLowerCase().search(this.state.search.toLowerCase()) !== | ||
150 | -1, | ||
151 | ); | ||
147 | } else { | 152 | } else { |
148 | // Add the currently active service first | 153 | // Add the currently active service first |
149 | const currentService = this.props.stores.services.active; | 154 | const currentService = this.props.stores.services.active; |
@@ -186,14 +191,14 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
186 | // Change the selected service | 191 | // Change the selected service |
187 | // factor should be -1 or 1 | 192 | // factor should be -1 or 1 |
188 | changeSelected(factor) { | 193 | changeSelected(factor) { |
189 | this.setState((state) => { | 194 | this.setState(state => { |
190 | let newSelected = state.selected + factor; | 195 | let newSelected = state.selected + factor; |
191 | const services = this.services().length; | 196 | const services = this.services().length; |
192 | 197 | ||
193 | // Roll around when on edge of list | 198 | // Roll around when on edge of list |
194 | if (state.selected < 1 && factor === -1) { | 199 | if (state.selected < 1 && factor === -1) { |
195 | newSelected = services - 1; | 200 | newSelected = services - 1; |
196 | } else if ((state.selected >= (services - 1)) && factor === 1) { | 201 | } else if (state.selected >= services - 1 && factor === 1) { |
197 | newSelected = 0; | 202 | newSelected = 0; |
198 | } | 203 | } |
199 | 204 | ||
@@ -256,7 +261,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
256 | // Wrapped inside timeout to let the modal render first | 261 | // Wrapped inside timeout to let the modal render first |
257 | setTimeout(() => { | 262 | setTimeout(() => { |
258 | if (this.inputRef.current) { | 263 | if (this.inputRef.current) { |
259 | this.inputRef.current.getElementsByTagName('input')[0].focus(); | 264 | this.inputRef.current.querySelectorAll('input')[0].focus(); |
260 | } | 265 | } |
261 | }, 10); | 266 | }, 10); |
262 | 267 | ||
@@ -268,7 +273,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
268 | // search query change when modal not visible | 273 | // search query change when modal not visible |
269 | setTimeout(() => { | 274 | setTimeout(() => { |
270 | if (this.inputRef.current) { | 275 | if (this.inputRef.current) { |
271 | this.inputRef.current.getElementsByTagName('input')[0].blur(); | 276 | this.inputRef.current.querySelectorAll('input')[0].blur(); |
272 | } | 277 | } |
273 | }, 100); | 278 | }, 100); |
274 | 279 | ||
@@ -286,17 +291,13 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
286 | render() { | 291 | render() { |
287 | const { isModalVisible } = ModalState; | 292 | const { isModalVisible } = ModalState; |
288 | 293 | ||
289 | const { | 294 | const { openService } = this; |
290 | openService, | ||
291 | } = this; | ||
292 | 295 | ||
293 | const { | 296 | const { classes } = this.props; |
294 | classes, | ||
295 | } = this.props; | ||
296 | 297 | ||
297 | const services = this.services(); | 298 | const services = this.services(); |
298 | 299 | ||
299 | const { intl } = this.context; | 300 | const { intl } = this.props; |
300 | 301 | ||
301 | return ( | 302 | return ( |
302 | <Modal | 303 | <Modal |
@@ -318,12 +319,16 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
318 | </div> | 319 | </div> |
319 | 320 | ||
320 | <div className={classes.services}> | 321 | <div className={classes.services}> |
321 | { services.map((service, index) => ( | 322 | {services.map((service, index) => ( |
322 | <div | 323 | <div |
323 | className={`${classes.service} ${this.state.selected === index ? `${classes.activeService} active` : ''} service`} | 324 | className={`${classes.service} ${ |
325 | this.state.selected === index | ||
326 | ? `${classes.activeService} active` | ||
327 | : '' | ||
328 | } service`} | ||
324 | onClick={() => openService(index)} | 329 | onClick={() => openService(index)} |
325 | key={service.id} | 330 | key={service.id} |
326 | ref={(el) => { | 331 | ref={el => { |
327 | this.serviceElements[index] = el; | 332 | this.serviceElements[index] = el; |
328 | }} | 333 | }} |
329 | > | 334 | > |
@@ -332,9 +337,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class | |||
332 | className={classes.serviceIcon} | 337 | className={classes.serviceIcon} |
333 | alt={service.recipe.name} | 338 | alt={service.recipe.name} |
334 | /> | 339 | /> |
335 | <div> | 340 | <div>{service.name}</div> |
336 | { service.name } | ||
337 | </div> | ||
338 | </div> | 341 | </div> |
339 | ))} | 342 | ))} |
340 | </div> | 343 | </div> |
@@ -356,3 +359,5 @@ QuickSwitchModal.wrappedComponent.propTypes = { | |||
356 | service: PropTypes.instanceOf(ServicesStore).isRequired, | 359 | service: PropTypes.instanceOf(ServicesStore).isRequired, |
357 | }).isRequired, | 360 | }).isRequired, |
358 | }; | 361 | }; |
362 | |||
363 | export default injectIntl(QuickSwitchModal); | ||
diff --git a/src/features/quickSwitch/store.js b/src/features/quickSwitch/store.ts index ed06e5a7d..ed06e5a7d 100644 --- a/src/features/quickSwitch/store.js +++ b/src/features/quickSwitch/store.ts | |||
diff --git a/src/features/serviceProxy/index.js b/src/features/serviceProxy/index.js deleted file mode 100644 index eb7116651..000000000 --- a/src/features/serviceProxy/index.js +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | import { autorun, observable } from 'mobx'; | ||
2 | import { session } from '@electron/remote'; | ||
3 | |||
4 | const debug = require('debug')('Ferdi:feature:serviceProxy'); | ||
5 | |||
6 | export const config = observable({ | ||
7 | isEnabled: true, | ||
8 | }); | ||
9 | |||
10 | export default function init(stores) { | ||
11 | debug('Initializing `serviceProxy` feature'); | ||
12 | |||
13 | autorun(() => { | ||
14 | config.isEnabled = true; | ||
15 | |||
16 | const services = stores.services.enabled; | ||
17 | const proxySettings = stores.settings.proxy; | ||
18 | |||
19 | debug('Service Proxy autorun'); | ||
20 | |||
21 | services.forEach((service) => { | ||
22 | const s = session.fromPartition(`persist:service-${service.id}`); | ||
23 | |||
24 | if (config.isEnabled) { | ||
25 | const serviceProxyConfig = proxySettings[service.id]; | ||
26 | |||
27 | if (serviceProxyConfig && serviceProxyConfig.isEnabled && serviceProxyConfig.host) { | ||
28 | const proxyHost = `${serviceProxyConfig.host}${serviceProxyConfig.port ? `:${serviceProxyConfig.port}` : ''}`; | ||
29 | debug(`Setting proxy config from service settings for "${service.name}" (${service.id}) to`, proxyHost); | ||
30 | |||
31 | s.setProxy({ proxyRules: proxyHost }, () => { | ||
32 | debug(`Using proxy "${proxyHost}" for "${service.name}" (${service.id})`); | ||
33 | }); | ||
34 | } | ||
35 | } | ||
36 | }); | ||
37 | }); | ||
38 | } | ||
diff --git a/src/features/serviceProxy/index.ts b/src/features/serviceProxy/index.ts new file mode 100644 index 000000000..f095b286a --- /dev/null +++ b/src/features/serviceProxy/index.ts | |||
@@ -0,0 +1,54 @@ | |||
1 | import { autorun, observable } from 'mobx'; | ||
2 | import { session } from '@electron/remote'; | ||
3 | |||
4 | const debug = require('debug')('Ferdi:feature:serviceProxy'); | ||
5 | |||
6 | export const config = observable({ | ||
7 | isEnabled: true, | ||
8 | }); | ||
9 | |||
10 | export default function init(stores: { | ||
11 | services: { enabled: any }; | ||
12 | settings: { proxy: any }; | ||
13 | }) { | ||
14 | debug('Initializing `serviceProxy` feature'); | ||
15 | |||
16 | autorun(() => { | ||
17 | config.isEnabled = true; | ||
18 | |||
19 | const services = stores.services.enabled; | ||
20 | const proxySettings = stores.settings.proxy; | ||
21 | |||
22 | debug('Service Proxy autorun'); | ||
23 | |||
24 | for (const service of services) { | ||
25 | const s = session.fromPartition(`persist:service-${service.id}`); | ||
26 | |||
27 | if (config.isEnabled) { | ||
28 | const serviceProxyConfig = proxySettings[service.id]; | ||
29 | |||
30 | if ( | ||
31 | serviceProxyConfig && | ||
32 | serviceProxyConfig.isEnabled && | ||
33 | serviceProxyConfig.host | ||
34 | ) { | ||
35 | const proxyHost = `${serviceProxyConfig.host}${ | ||
36 | serviceProxyConfig.port ? `:${serviceProxyConfig.port}` : '' | ||
37 | }`; | ||
38 | debug( | ||
39 | `Setting proxy config from service settings for "${service.name}" (${service.id}) to`, | ||
40 | proxyHost, | ||
41 | ); | ||
42 | |||
43 | s.setProxy({ proxyRules: proxyHost }) | ||
44 | .then(() => { | ||
45 | debug( | ||
46 | `Using proxy "${proxyHost}" for "${service.name}" (${service.id})`, | ||
47 | ); | ||
48 | }) | ||
49 | .catch(error => console.error(error)); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | }); | ||
54 | } | ||
diff --git a/src/features/settingsWS/actions.js b/src/features/settingsWS/actions.ts index 631670c8a..631670c8a 100755 --- a/src/features/settingsWS/actions.js +++ b/src/features/settingsWS/actions.ts | |||
diff --git a/src/features/settingsWS/index.js b/src/features/settingsWS/index.ts index 7771421d6..9bb206d82 100755 --- a/src/features/settingsWS/index.js +++ b/src/features/settingsWS/index.ts | |||
@@ -5,15 +5,16 @@ const debug = require('debug')('Ferdi:feature:settingsWS'); | |||
5 | 5 | ||
6 | export const settingsStore = new SettingsWSStore(); | 6 | export const settingsStore = new SettingsWSStore(); |
7 | 7 | ||
8 | export default function initSettingsWebSocket(stores, actions) { | 8 | export default function initSettingsWebSocket( |
9 | stores: { features: any }, | ||
10 | actions: any, | ||
11 | ) { | ||
9 | const { features } = stores; | 12 | const { features } = stores; |
10 | 13 | ||
11 | // Toggle SettingsWebSocket feature | 14 | // Toggle SettingsWebSocket feature |
12 | reaction( | 15 | reaction( |
13 | () => ( | 16 | () => features.features.isSettingsWSEnabled, |
14 | features.features.isSettingsWSEnabled | 17 | isEnabled => { |
15 | ), | ||
16 | (isEnabled) => { | ||
17 | if (isEnabled) { | 18 | if (isEnabled) { |
18 | debug('Initializing `settingsWS` feature'); | 19 | debug('Initializing `settingsWS` feature'); |
19 | settingsStore.start(stores, actions); | 20 | settingsStore.start(stores, actions); |
diff --git a/src/features/settingsWS/state.js b/src/features/settingsWS/state.ts index 7b16b2b6e..7b16b2b6e 100755 --- a/src/features/settingsWS/state.js +++ b/src/features/settingsWS/state.ts | |||
diff --git a/src/features/settingsWS/store.js b/src/features/settingsWS/store.js index 9100f33d1..3b9e10825 100755 --- a/src/features/settingsWS/store.js +++ b/src/features/settingsWS/store.js | |||
@@ -4,7 +4,7 @@ import ms from 'ms'; | |||
4 | 4 | ||
5 | import { FeatureStore } from '../utils/FeatureStore'; | 5 | import { FeatureStore } from '../utils/FeatureStore'; |
6 | import { createReactions } from '../../stores/lib/Reaction'; | 6 | import { createReactions } from '../../stores/lib/Reaction'; |
7 | import { WS_API } from '../../environment'; | 7 | import { WS_API } from '../../environment-remote'; |
8 | 8 | ||
9 | const debug = require('debug')('Ferdi:feature:settingsWS:store'); | 9 | const debug = require('debug')('Ferdi:feature:settingsWS:store'); |
10 | 10 | ||
@@ -25,11 +25,13 @@ export class SettingsWSStore extends FeatureStore { | |||
25 | this.stores = stores; | 25 | this.stores = stores; |
26 | this.actions = actions; | 26 | this.actions = actions; |
27 | 27 | ||
28 | this._registerReactions(createReactions([ | 28 | this._registerReactions( |
29 | this._initialize.bind(this), | 29 | createReactions([ |
30 | this._reconnect.bind(this), | 30 | this._initialize.bind(this), |
31 | this._close.bind(this), | 31 | this._reconnect.bind(this), |
32 | ])); | 32 | this._close.bind(this), |
33 | ]), | ||
34 | ); | ||
33 | } | 35 | } |
34 | 36 | ||
35 | connect() { | 37 | connect() { |
@@ -51,12 +53,12 @@ export class SettingsWSStore extends FeatureStore { | |||
51 | this.heartbeat(); | 53 | this.heartbeat(); |
52 | }); | 54 | }); |
53 | 55 | ||
54 | this.ws.on('message', (data) => { | 56 | this.ws.on('message', data => { |
55 | const resp = JSON.parse(data); | 57 | const resp = JSON.parse(data); |
56 | debug('Received message', resp); | 58 | debug('Received message', resp); |
57 | 59 | ||
58 | if (resp.id) { | 60 | if (resp.id) { |
59 | this.stores.user.getUserInfoRequest.patch((result) => { | 61 | this.stores.user.getUserInfoRequest.patch(result => { |
60 | if (!result) return; | 62 | if (!result) return; |
61 | 63 | ||
62 | debug('Patching user object with new values'); | 64 | debug('Patching user object with new values'); |
@@ -66,8 +68,8 @@ export class SettingsWSStore extends FeatureStore { | |||
66 | }); | 68 | }); |
67 | 69 | ||
68 | this.ws.on('ping', this.heartbeat.bind(this)); | 70 | this.ws.on('ping', this.heartbeat.bind(this)); |
69 | } catch (err) { | 71 | } catch (error) { |
70 | console.err(err); | 72 | console.error(error); |
71 | } | 73 | } |
72 | } | 74 | } |
73 | 75 | ||
diff --git a/src/features/todos/actions.js b/src/features/todos/actions.js deleted file mode 100644 index cc17e919b..000000000 --- a/src/features/todos/actions.js +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | import PropTypes from 'prop-types'; | ||
2 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | ||
3 | |||
4 | export const todoActions = createActionsFromDefinitions({ | ||
5 | resize: { | ||
6 | width: PropTypes.number.isRequired, | ||
7 | }, | ||
8 | toggleTodosPanel: {}, | ||
9 | toggleTodosFeatureVisibility: {}, | ||
10 | setTodosWebview: { | ||
11 | webview: PropTypes.instanceOf(Element).isRequired, | ||
12 | }, | ||
13 | handleHostMessage: { | ||
14 | action: PropTypes.string.isRequired, | ||
15 | data: PropTypes.object, | ||
16 | }, | ||
17 | handleClientMessage: { | ||
18 | channel: PropTypes.string.isRequired, | ||
19 | message: PropTypes.shape({ | ||
20 | action: PropTypes.string.isRequired, | ||
21 | data: PropTypes.object, | ||
22 | }), | ||
23 | }, | ||
24 | openDevTools: {}, | ||
25 | reload: {}, | ||
26 | }, PropTypes.checkPropTypes); | ||
27 | |||
28 | export default todoActions; | ||
diff --git a/src/features/todos/actions.ts b/src/features/todos/actions.ts new file mode 100644 index 000000000..04e299e71 --- /dev/null +++ b/src/features/todos/actions.ts | |||
@@ -0,0 +1,31 @@ | |||
1 | import PropTypes from 'prop-types'; | ||
2 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | ||
3 | |||
4 | export const todoActions = createActionsFromDefinitions( | ||
5 | { | ||
6 | resize: { | ||
7 | width: PropTypes.number.isRequired, | ||
8 | }, | ||
9 | toggleTodosPanel: {}, | ||
10 | toggleTodosFeatureVisibility: {}, | ||
11 | setTodosWebview: { | ||
12 | webview: PropTypes.instanceOf(Element).isRequired, | ||
13 | }, | ||
14 | handleHostMessage: { | ||
15 | action: PropTypes.string.isRequired, | ||
16 | data: PropTypes.object, | ||
17 | }, | ||
18 | handleClientMessage: { | ||
19 | channel: PropTypes.string.isRequired, | ||
20 | message: PropTypes.shape({ | ||
21 | action: PropTypes.string.isRequired, | ||
22 | data: PropTypes.object, | ||
23 | }), | ||
24 | }, | ||
25 | openDevTools: {}, | ||
26 | reload: {}, | ||
27 | }, | ||
28 | PropTypes.checkPropTypes, | ||
29 | ); | ||
30 | |||
31 | export default todoActions; | ||
diff --git a/src/features/todos/constants.js b/src/features/todos/constants.ts index 303a7a16e..303a7a16e 100644 --- a/src/features/todos/constants.js +++ b/src/features/todos/constants.ts | |||
diff --git a/src/features/todos/index.js b/src/features/todos/index.ts index 573190881..3665812e6 100644 --- a/src/features/todos/index.js +++ b/src/features/todos/index.ts | |||
@@ -5,16 +5,17 @@ const debug = require('debug')('Ferdi:feature:todos'); | |||
5 | 5 | ||
6 | export const todosStore = new TodoStore(); | 6 | export const todosStore = new TodoStore(); |
7 | 7 | ||
8 | export default function initTodos(stores, actions) { | 8 | export default function initTodos( |
9 | stores: { todos?: any; features?: any }, | ||
10 | actions: any, | ||
11 | ) { | ||
9 | stores.todos = todosStore; | 12 | stores.todos = todosStore; |
10 | const { features } = stores; | 13 | const { features } = stores; |
11 | 14 | ||
12 | // Toggle todos feature | 15 | // Toggle todos feature |
13 | reaction( | 16 | reaction( |
14 | () => ( | 17 | () => features.features.isTodosEnabled, |
15 | features.features.isTodosEnabled | 18 | isEnabled => { |
16 | ), | ||
17 | (isEnabled) => { | ||
18 | if (isEnabled) { | 19 | if (isEnabled) { |
19 | debug('Initializing `todos` feature'); | 20 | debug('Initializing `todos` feature'); |
20 | todosStore.start(stores, actions); | 21 | todosStore.start(stores, actions); |
diff --git a/src/features/todos/preload.js b/src/features/todos/preload.js index 9bd76a704..3b86ddbc5 100644 --- a/src/features/todos/preload.js +++ b/src/features/todos/preload.js | |||
@@ -7,7 +7,9 @@ debug('Preloading Todos Webview'); | |||
7 | 7 | ||
8 | let hostMessageListener = ({ action }) => { | 8 | let hostMessageListener = ({ action }) => { |
9 | switch (action) { | 9 | switch (action) { |
10 | case 'todos:initialize-as-service': ipcRenderer.sendToHost('hello'); break; | 10 | case 'todos:initialize-as-service': |
11 | ipcRenderer.sendToHost('hello'); | ||
12 | break; | ||
11 | default: | 13 | default: |
12 | } | 14 | } |
13 | }; | 15 | }; |
@@ -15,7 +17,9 @@ let hostMessageListener = ({ action }) => { | |||
15 | window.ferdi = { | 17 | window.ferdi = { |
16 | onInitialize(ipcHostMessageListener) { | 18 | onInitialize(ipcHostMessageListener) { |
17 | hostMessageListener = ipcHostMessageListener; | 19 | hostMessageListener = ipcHostMessageListener; |
18 | ipcRenderer.sendToHost(IPC.TODOS_CLIENT_CHANNEL, { action: 'todos:initialized' }); | 20 | ipcRenderer.sendToHost(IPC.TODOS_CLIENT_CHANNEL, { |
21 | action: 'todos:initialized', | ||
22 | }); | ||
19 | }, | 23 | }, |
20 | sendToHost(message) { | 24 | sendToHost(message) { |
21 | ipcRenderer.sendToHost(IPC.TODOS_CLIENT_CHANNEL, message); | 25 | ipcRenderer.sendToHost(IPC.TODOS_CLIENT_CHANNEL, message); |
@@ -30,7 +34,7 @@ ipcRenderer.on(IPC.TODOS_HOST_CHANNEL, (event, message) => { | |||
30 | if (window.location.href === 'https://app.franztodos.com/login/') { | 34 | if (window.location.href === 'https://app.franztodos.com/login/') { |
31 | // Insert info element informing about Franz accounts | 35 | // Insert info element informing about Franz accounts |
32 | const infoElement = document.createElement('p'); | 36 | const infoElement = document.createElement('p'); |
33 | infoElement.innerText = `You are using Franz's official Todo Service. | 37 | infoElement.textContent = `You are using Franz's official Todo Service. |
34 | This service will only work with accounts registered with Franz - no Ferdi accounts will work here! | 38 | This service will only work with accounts registered with Franz - no Ferdi accounts will work here! |
35 | If you do not have a Franz account you can change the Todo service by going into Ferdi's settings and changing the "Todo server". | 39 | If you do not have a Franz account you can change the Todo service by going into Ferdi's settings and changing the "Todo server". |
36 | You can choose any service as this Todo server, e.g. Todoist or Apple Notes.`; | 40 | You can choose any service as this Todo server, e.g. Todoist or Apple Notes.`; |
@@ -42,7 +46,7 @@ You can choose any service as this Todo server, e.g. Todoist or Apple Notes.`; | |||
42 | const textElement = document.querySelector('p'); | 46 | const textElement = document.querySelector('p'); |
43 | if (textElement) { | 47 | if (textElement) { |
44 | clearInterval(waitForReact); | 48 | clearInterval(waitForReact); |
45 | textElement.parentElement.insertBefore(infoElement, textElement); | 49 | textElement.parentElement?.insertBefore(infoElement, textElement); |
46 | } else { | 50 | } else { |
47 | numChecks += 1; | 51 | numChecks += 1; |
48 | 52 | ||
diff --git a/src/features/utils/ActionBinding.js b/src/features/utils/ActionBinding.ts index 787166d44..787166d44 100644 --- a/src/features/utils/ActionBinding.js +++ b/src/features/utils/ActionBinding.ts | |||
diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js index 4d4e217a9..afe726294 100644 --- a/src/features/utils/FeatureStore.js +++ b/src/features/utils/FeatureStore.js | |||
@@ -16,11 +16,11 @@ export class FeatureStore { | |||
16 | } | 16 | } |
17 | 17 | ||
18 | _startActions(actions = this._actions) { | 18 | _startActions(actions = this._actions) { |
19 | actions.forEach((a) => a.start()); | 19 | for (const a of actions) a.start(); |
20 | } | 20 | } |
21 | 21 | ||
22 | _stopActions(actions = this._actions) { | 22 | _stopActions(actions = this._actions) { |
23 | actions.forEach((a) => a.stop()); | 23 | for (const a of actions) a.stop(); |
24 | } | 24 | } |
25 | 25 | ||
26 | // REACTIONS | 26 | // REACTIONS |
@@ -31,10 +31,10 @@ export class FeatureStore { | |||
31 | } | 31 | } |
32 | 32 | ||
33 | _startReactions(reactions = this._reactions) { | 33 | _startReactions(reactions = this._reactions) { |
34 | reactions.forEach((r) => r.start()); | 34 | for (const r of reactions) r.start(); |
35 | } | 35 | } |
36 | 36 | ||
37 | _stopReactions(reactions = this._reactions) { | 37 | _stopReactions(reactions = this._reactions) { |
38 | reactions.forEach((r) => r.stop()); | 38 | for (const r of reactions) r.stop(); |
39 | } | 39 | } |
40 | } | 40 | } |
diff --git a/src/features/webControls/components/WebControls.js b/src/features/webControls/components/WebControls.js index bebf52c08..97fa20dcc 100644 --- a/src/features/webControls/components/WebControls.js +++ b/src/features/webControls/components/WebControls.js | |||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import { Icon } from '@meetfranz/ui'; | 5 | import { Icon } from '@meetfranz/ui'; |
6 | import { defineMessages, intlShape } from 'react-intl'; | 6 | import { defineMessages, injectIntl } from 'react-intl'; |
7 | 7 | ||
8 | import { | 8 | import { |
9 | mdiReload, | 9 | mdiReload, |
@@ -16,23 +16,23 @@ import { | |||
16 | const messages = defineMessages({ | 16 | const messages = defineMessages({ |
17 | goHome: { | 17 | goHome: { |
18 | id: 'webControls.goHome', | 18 | id: 'webControls.goHome', |
19 | defaultMessage: '!!!Home', | 19 | defaultMessage: 'Home', |
20 | }, | 20 | }, |
21 | openInBrowser: { | 21 | openInBrowser: { |
22 | id: 'webControls.openInBrowser', | 22 | id: 'webControls.openInBrowser', |
23 | defaultMessage: '!!!Open in Browser', | 23 | defaultMessage: 'Open in Browser', |
24 | }, | 24 | }, |
25 | back: { | 25 | back: { |
26 | id: 'webControls.back', | 26 | id: 'webControls.back', |
27 | defaultMessage: '!!!Back', | 27 | defaultMessage: 'Back', |
28 | }, | 28 | }, |
29 | forward: { | 29 | forward: { |
30 | id: 'webControls.forward', | 30 | id: 'webControls.forward', |
31 | defaultMessage: '!!!Forward', | 31 | defaultMessage: 'Forward', |
32 | }, | 32 | }, |
33 | reload: { | 33 | reload: { |
34 | id: 'webControls.reload', | 34 | id: 'webControls.reload', |
35 | defaultMessage: '!!!Reload', | 35 | defaultMessage: 'Reload', |
36 | }, | 36 | }, |
37 | }); | 37 | }); |
38 | 38 | ||
@@ -109,10 +109,6 @@ class WebControls extends Component { | |||
109 | navigate: PropTypes.func.isRequired, | 109 | navigate: PropTypes.func.isRequired, |
110 | }; | 110 | }; |
111 | 111 | ||
112 | static contextTypes = { | ||
113 | intl: intlShape, | ||
114 | }; | ||
115 | |||
116 | static getDerivedStateFromProps(props, state) { | 112 | static getDerivedStateFromProps(props, state) { |
117 | const { url } = props; | 113 | const { url } = props; |
118 | const { editUrl } = state; | 114 | const { editUrl } = state; |
@@ -148,7 +144,7 @@ class WebControls extends Component { | |||
148 | 144 | ||
149 | const { inputUrl, editUrl } = this.state; | 145 | const { inputUrl, editUrl } = this.state; |
150 | 146 | ||
151 | const { intl } = this.context; | 147 | const { intl } = this.props; |
152 | 148 | ||
153 | return ( | 149 | return ( |
154 | <div className={classes.root}> | 150 | <div className={classes.root}> |
@@ -241,4 +237,4 @@ class WebControls extends Component { | |||
241 | } | 237 | } |
242 | } | 238 | } |
243 | 239 | ||
244 | export default WebControls; | 240 | export default injectIntl(WebControls); |
diff --git a/src/features/webControls/containers/WebControlsScreen.js b/src/features/webControls/containers/WebControlsScreen.js index e1e1b9991..0273bb13e 100644 --- a/src/features/webControls/containers/WebControlsScreen.js +++ b/src/features/webControls/containers/WebControlsScreen.js | |||
@@ -16,7 +16,8 @@ const URL_EVENTS = [ | |||
16 | 'did-navigate-in-page', | 16 | 'did-navigate-in-page', |
17 | ]; | 17 | ]; |
18 | 18 | ||
19 | @inject('stores', 'actions') @observer | 19 | @inject('stores', 'actions') |
20 | @observer | ||
20 | class WebControlsScreen extends Component { | 21 | class WebControlsScreen extends Component { |
21 | @observable url = ''; | 22 | @observable url = ''; |
22 | 23 | ||
@@ -36,15 +37,15 @@ class WebControlsScreen extends Component { | |||
36 | this.webview = service.webview; | 37 | this.webview = service.webview; |
37 | this.url = this.webview.getURL(); | 38 | this.url = this.webview.getURL(); |
38 | 39 | ||
39 | URL_EVENTS.forEach((event) => { | 40 | for (const event of URL_EVENTS) { |
40 | this.webview.addEventListener(event, (e) => { | 41 | this.webview.addEventListener(event, e => { |
41 | if (!e.isMainFrame) return; | 42 | if (!e.isMainFrame) return; |
42 | 43 | ||
43 | this.url = e.url; | 44 | this.url = e.url; |
44 | this.canGoBack = this.webview.canGoBack(); | 45 | this.canGoBack = this.webview.canGoBack(); |
45 | this.canGoForward = this.webview.canGoForward(); | 46 | this.canGoForward = this.webview.canGoForward(); |
46 | }); | 47 | }); |
47 | }); | 48 | } |
48 | } | 49 | } |
49 | }); | 50 | }); |
50 | } | 51 | } |
@@ -83,13 +84,16 @@ class WebControlsScreen extends Component { | |||
83 | 84 | ||
84 | try { | 85 | try { |
85 | url = new URL(url).toString(); | 86 | url = new URL(url).toString(); |
86 | } catch (err) { | 87 | } catch { |
87 | // eslint-disable-next-line no-useless-escape | 88 | url = |
88 | if (url.match(/^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9\-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$/)) { | 89 | // eslint-disable-next-line no-useless-escape |
89 | url = `http://${url}`; | 90 | /^((?!-))(xn--)?[\da-z][\d_a-z-]{0,61}[\da-z]{0,1}\.(xn--)?([\da-z\-]{1,61}|[\da-z-]{1,30}\.[a-z]{2,})$/.test( |
90 | } else { | 91 | url, |
91 | url = SEARCH_ENGINE_URLS[this.settings.app.searchEngine]({ searchTerm: url }); | 92 | ) |
92 | } | 93 | ? `http://${url}` |
94 | : SEARCH_ENGINE_URLS[this.settings.app.searchEngine]({ | ||
95 | searchTerm: url, | ||
96 | }); | ||
93 | } | 97 | } |
94 | 98 | ||
95 | this.webview.loadURL(url); | 99 | this.webview.loadURL(url); |
@@ -114,7 +118,7 @@ class WebControlsScreen extends Component { | |||
114 | goBack={() => this.goBack()} | 118 | goBack={() => this.goBack()} |
115 | canGoForward={this.canGoForward} | 119 | canGoForward={this.canGoForward} |
116 | goForward={() => this.goForward()} | 120 | goForward={() => this.goForward()} |
117 | navigate={(url) => this.navigate(url)} | 121 | navigate={url => this.navigate(url)} |
118 | url={this.url} | 122 | url={this.url} |
119 | /> | 123 | /> |
120 | ); | 124 | ); |
diff --git a/src/features/workspaces/actions.js b/src/features/workspaces/actions.js deleted file mode 100644 index 5b5db422e..000000000 --- a/src/features/workspaces/actions.js +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | import PropTypes from 'prop-types'; | ||
2 | import Workspace from './models/Workspace'; | ||
3 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | ||
4 | |||
5 | export const workspaceActions = createActionsFromDefinitions({ | ||
6 | edit: { | ||
7 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
8 | }, | ||
9 | create: { | ||
10 | name: PropTypes.string.isRequired, | ||
11 | }, | ||
12 | delete: { | ||
13 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
14 | }, | ||
15 | update: { | ||
16 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
17 | }, | ||
18 | activate: { | ||
19 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
20 | }, | ||
21 | deactivate: {}, | ||
22 | toggleWorkspaceDrawer: {}, | ||
23 | openWorkspaceSettings: {}, | ||
24 | toggleKeepAllWorkspacesLoadedSetting: {}, | ||
25 | }, PropTypes.checkPropTypes); | ||
26 | |||
27 | export default workspaceActions; | ||
diff --git a/src/features/workspaces/actions.ts b/src/features/workspaces/actions.ts new file mode 100644 index 000000000..5e7e6e721 --- /dev/null +++ b/src/features/workspaces/actions.ts | |||
@@ -0,0 +1,30 @@ | |||
1 | import PropTypes from 'prop-types'; | ||
2 | import Workspace from './models/Workspace'; | ||
3 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | ||
4 | |||
5 | export const workspaceActions = createActionsFromDefinitions( | ||
6 | { | ||
7 | edit: { | ||
8 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
9 | }, | ||
10 | create: { | ||
11 | name: PropTypes.string.isRequired, | ||
12 | }, | ||
13 | delete: { | ||
14 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
15 | }, | ||
16 | update: { | ||
17 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
18 | }, | ||
19 | activate: { | ||
20 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
21 | }, | ||
22 | deactivate: {}, | ||
23 | toggleWorkspaceDrawer: {}, | ||
24 | openWorkspaceSettings: {}, | ||
25 | toggleKeepAllWorkspacesLoadedSetting: {}, | ||
26 | }, | ||
27 | PropTypes.checkPropTypes, | ||
28 | ); | ||
29 | |||
30 | export default workspaceActions; | ||
diff --git a/src/features/workspaces/api.js b/src/features/workspaces/api.ts index 322695ed2..8447fc247 100644 --- a/src/features/workspaces/api.js +++ b/src/features/workspaces/api.ts | |||
@@ -12,12 +12,14 @@ export const workspaceApi = { | |||
12 | debug('getUserWorkspaces GET', url); | 12 | debug('getUserWorkspaces GET', url); |
13 | const result = await sendAuthRequest(url, { method: 'GET' }); | 13 | const result = await sendAuthRequest(url, { method: 'GET' }); |
14 | debug('getUserWorkspaces RESULT', result); | 14 | debug('getUserWorkspaces RESULT', result); |
15 | if (!result.ok) throw result; | 15 | if (!result.ok) { |
16 | throw new Error("Couldn't getUserWorkspaces"); | ||
17 | } | ||
16 | const workspaces = await result.json(); | 18 | const workspaces = await result.json(); |
17 | return workspaces.map((data) => new Workspace(data)); | 19 | return workspaces.map(data => new Workspace(data)); |
18 | }, | 20 | }, |
19 | 21 | ||
20 | createWorkspace: async (name) => { | 22 | createWorkspace: async name => { |
21 | const url = `${apiBase()}/workspace`; | 23 | const url = `${apiBase()}/workspace`; |
22 | const options = { | 24 | const options = { |
23 | method: 'POST', | 25 | method: 'POST', |
@@ -26,20 +28,24 @@ export const workspaceApi = { | |||
26 | debug('createWorkspace POST', url, options); | 28 | debug('createWorkspace POST', url, options); |
27 | const result = await sendAuthRequest(url, options); | 29 | const result = await sendAuthRequest(url, options); |
28 | debug('createWorkspace RESULT', result); | 30 | debug('createWorkspace RESULT', result); |
29 | if (!result.ok) throw result; | 31 | if (!result.ok) { |
32 | throw new Error("Couldn't createWorkspace"); | ||
33 | } | ||
30 | return new Workspace(await result.json()); | 34 | return new Workspace(await result.json()); |
31 | }, | 35 | }, |
32 | 36 | ||
33 | deleteWorkspace: async (workspace) => { | 37 | deleteWorkspace: async workspace => { |
34 | const url = `${apiBase()}/workspace/${workspace.id}`; | 38 | const url = `${apiBase()}/workspace/${workspace.id}`; |
35 | debug('deleteWorkspace DELETE', url); | 39 | debug('deleteWorkspace DELETE', url); |
36 | const result = await sendAuthRequest(url, { method: 'DELETE' }); | 40 | const result = await sendAuthRequest(url, { method: 'DELETE' }); |
37 | debug('deleteWorkspace RESULT', result); | 41 | debug('deleteWorkspace RESULT', result); |
38 | if (!result.ok) throw result; | 42 | if (!result.ok) { |
43 | throw new Error("Couldn't deleteWorkspace"); | ||
44 | } | ||
39 | return true; | 45 | return true; |
40 | }, | 46 | }, |
41 | 47 | ||
42 | updateWorkspace: async (workspace) => { | 48 | updateWorkspace: async workspace => { |
43 | const url = `${apiBase()}/workspace/${workspace.id}`; | 49 | const url = `${apiBase()}/workspace/${workspace.id}`; |
44 | const options = { | 50 | const options = { |
45 | method: 'PUT', | 51 | method: 'PUT', |
@@ -48,15 +54,29 @@ export const workspaceApi = { | |||
48 | debug('updateWorkspace UPDATE', url, options); | 54 | debug('updateWorkspace UPDATE', url, options); |
49 | const result = await sendAuthRequest(url, options); | 55 | const result = await sendAuthRequest(url, options); |
50 | debug('updateWorkspace RESULT', result); | 56 | debug('updateWorkspace RESULT', result); |
51 | if (!result.ok) throw result; | 57 | if (!result.ok) { |
58 | throw new Error("Couldn't updateWorkspace"); | ||
59 | } | ||
52 | return new Workspace(await result.json()); | 60 | return new Workspace(await result.json()); |
53 | }, | 61 | }, |
54 | }; | 62 | }; |
55 | 63 | ||
56 | export const getUserWorkspacesRequest = new Request(workspaceApi, 'getUserWorkspaces'); | 64 | export const getUserWorkspacesRequest = new Request( |
57 | export const createWorkspaceRequest = new Request(workspaceApi, 'createWorkspace'); | 65 | workspaceApi, |
58 | export const deleteWorkspaceRequest = new Request(workspaceApi, 'deleteWorkspace'); | 66 | 'getUserWorkspaces', |
59 | export const updateWorkspaceRequest = new Request(workspaceApi, 'updateWorkspace'); | 67 | ); |
68 | export const createWorkspaceRequest = new Request( | ||
69 | workspaceApi, | ||
70 | 'createWorkspace', | ||
71 | ); | ||
72 | export const deleteWorkspaceRequest = new Request( | ||
73 | workspaceApi, | ||
74 | 'deleteWorkspace', | ||
75 | ); | ||
76 | export const updateWorkspaceRequest = new Request( | ||
77 | workspaceApi, | ||
78 | 'updateWorkspace', | ||
79 | ); | ||
60 | 80 | ||
61 | export const resetApiRequests = () => { | 81 | export const resetApiRequests = () => { |
62 | getUserWorkspacesRequest.reset(); | 82 | getUserWorkspacesRequest.reset(); |
diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js index 15b97121d..c9b05b87f 100644 --- a/src/features/workspaces/components/CreateWorkspaceForm.js +++ b/src/features/workspaces/components/CreateWorkspaceForm.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Input, Button } from '@meetfranz/forms'; | 5 | import { Input, Button } from '@meetfranz/forms'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | import Form from '../../../lib/Form'; | 7 | import Form from '../../../lib/Form'; |
@@ -11,11 +11,11 @@ import { workspaceStore } from '../index'; | |||
11 | const messages = defineMessages({ | 11 | const messages = defineMessages({ |
12 | submitButton: { | 12 | submitButton: { |
13 | id: 'settings.workspace.add.form.submitButton', | 13 | id: 'settings.workspace.add.form.submitButton', |
14 | defaultMessage: '!!!Create workspace', | 14 | defaultMessage: 'Create workspace', |
15 | }, | 15 | }, |
16 | name: { | 16 | name: { |
17 | id: 'settings.workspace.add.form.name', | 17 | id: 'settings.workspace.add.form.name', |
18 | defaultMessage: '!!!Name', | 18 | defaultMessage: 'Name', |
19 | }, | 19 | }, |
20 | }); | 20 | }); |
21 | 21 | ||
@@ -32,12 +32,9 @@ const styles = () => ({ | |||
32 | }, | 32 | }, |
33 | }); | 33 | }); |
34 | 34 | ||
35 | @injectSheet(styles) @observer | 35 | @injectSheet(styles) |
36 | @observer | ||
36 | class CreateWorkspaceForm extends Component { | 37 | class CreateWorkspaceForm extends Component { |
37 | static contextTypes = { | ||
38 | intl: intlShape, | ||
39 | }; | ||
40 | |||
41 | static propTypes = { | 38 | static propTypes = { |
42 | classes: PropTypes.object.isRequired, | 39 | classes: PropTypes.object.isRequired, |
43 | isSubmitting: PropTypes.bool.isRequired, | 40 | isSubmitting: PropTypes.bool.isRequired, |
@@ -45,7 +42,7 @@ class CreateWorkspaceForm extends Component { | |||
45 | }; | 42 | }; |
46 | 43 | ||
47 | form = (() => { | 44 | form = (() => { |
48 | const { intl } = this.context; | 45 | const { intl } = this.props; |
49 | return new Form({ | 46 | return new Form({ |
50 | fields: { | 47 | fields: { |
51 | name: { | 48 | name: { |
@@ -61,7 +58,7 @@ class CreateWorkspaceForm extends Component { | |||
61 | submitForm() { | 58 | submitForm() { |
62 | const { form } = this; | 59 | const { form } = this; |
63 | form.submit({ | 60 | form.submit({ |
64 | onSuccess: async (f) => { | 61 | onSuccess: async f => { |
65 | const { onSubmit } = this.props; | 62 | const { onSubmit } = this.props; |
66 | const values = f.values(); | 63 | const values = f.values(); |
67 | onSubmit(values); | 64 | onSubmit(values); |
@@ -70,7 +67,7 @@ class CreateWorkspaceForm extends Component { | |||
70 | } | 67 | } |
71 | 68 | ||
72 | render() { | 69 | render() { |
73 | const { intl } = this.context; | 70 | const { intl } = this.props; |
74 | const { classes, isSubmitting } = this.props; | 71 | const { classes, isSubmitting } = this.props; |
75 | const { form } = this; | 72 | const { form } = this; |
76 | return ( | 73 | return ( |
@@ -95,4 +92,4 @@ class CreateWorkspaceForm extends Component { | |||
95 | } | 92 | } |
96 | } | 93 | } |
97 | 94 | ||
98 | export default CreateWorkspaceForm; | 95 | export default injectIntl(CreateWorkspaceForm); |
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js index c97d4bd9c..f562733dd 100644 --- a/src/features/workspaces/components/EditWorkspaceForm.js +++ b/src/features/workspaces/components/EditWorkspaceForm.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component, Fragment } from 'react'; | 1 | import React, { Component, Fragment } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import { Input, Button } from '@meetfranz/forms'; | 6 | import { Input, Button } from '@meetfranz/forms'; |
7 | import injectSheet from 'react-jss'; | 7 | import injectSheet from 'react-jss'; |
@@ -20,40 +20,40 @@ import Toggle from '../../../components/ui/Toggle'; | |||
20 | const messages = defineMessages({ | 20 | const messages = defineMessages({ |
21 | buttonDelete: { | 21 | buttonDelete: { |
22 | id: 'settings.workspace.form.buttonDelete', | 22 | id: 'settings.workspace.form.buttonDelete', |
23 | defaultMessage: '!!!Delete workspace', | 23 | defaultMessage: 'Delete workspace', |
24 | }, | 24 | }, |
25 | buttonSave: { | 25 | buttonSave: { |
26 | id: 'settings.workspace.form.buttonSave', | 26 | id: 'settings.workspace.form.buttonSave', |
27 | defaultMessage: '!!!Save workspace', | 27 | defaultMessage: 'Save workspace', |
28 | }, | 28 | }, |
29 | name: { | 29 | name: { |
30 | id: 'settings.workspace.form.name', | 30 | id: 'settings.workspace.form.name', |
31 | defaultMessage: '!!!Name', | 31 | defaultMessage: 'Name', |
32 | }, | 32 | }, |
33 | yourWorkspaces: { | 33 | yourWorkspaces: { |
34 | id: 'settings.workspace.form.yourWorkspaces', | 34 | id: 'settings.workspace.form.yourWorkspaces', |
35 | defaultMessage: '!!!Your workspaces', | 35 | defaultMessage: 'Your workspaces', |
36 | }, | 36 | }, |
37 | keepLoaded: { | 37 | keepLoaded: { |
38 | id: 'settings.workspace.form.keepLoaded', | 38 | id: 'settings.workspace.form.keepLoaded', |
39 | defaultMessage: '!!!Keep this workspace loaded*', | 39 | defaultMessage: 'Keep this workspace loaded*', |
40 | }, | 40 | }, |
41 | keepLoadedInfo: { | 41 | keepLoadedInfo: { |
42 | id: 'settings.workspace.form.keepLoadedInfo', | 42 | id: 'settings.workspace.form.keepLoadedInfo', |
43 | defaultMessage: | 43 | defaultMessage: |
44 | '!!!*This option will be overwritten by the global "Keep all workspaces loaded" option.', | 44 | '*This option will be overwritten by the global "Keep all workspaces loaded" option.', |
45 | }, | 45 | }, |
46 | servicesInWorkspaceHeadline: { | 46 | servicesInWorkspaceHeadline: { |
47 | id: 'settings.workspace.form.servicesInWorkspaceHeadline', | 47 | id: 'settings.workspace.form.servicesInWorkspaceHeadline', |
48 | defaultMessage: '!!!Services in this Workspace', | 48 | defaultMessage: 'Services in this Workspace', |
49 | }, | 49 | }, |
50 | noServicesAdded: { | 50 | noServicesAdded: { |
51 | id: 'settings.services.noServicesAdded', | 51 | id: 'settings.services.noServicesAdded', |
52 | defaultMessage: '!!!Start by adding a service.', | 52 | defaultMessage: 'Start by adding a service.', |
53 | }, | 53 | }, |
54 | discoverServices: { | 54 | discoverServices: { |
55 | id: 'settings.services.discoverServices', | 55 | id: 'settings.services.discoverServices', |
56 | defaultMessage: '!!!Discover services', | 56 | defaultMessage: 'Discover services', |
57 | }, | 57 | }, |
58 | }); | 58 | }); |
59 | 59 | ||
@@ -72,10 +72,6 @@ const styles = () => ({ | |||
72 | @injectSheet(styles) | 72 | @injectSheet(styles) |
73 | @observer | 73 | @observer |
74 | class EditWorkspaceForm extends Component { | 74 | class EditWorkspaceForm extends Component { |
75 | static contextTypes = { | ||
76 | intl: intlShape, | ||
77 | }; | ||
78 | |||
79 | static propTypes = { | 75 | static propTypes = { |
80 | classes: PropTypes.object.isRequired, | 76 | classes: PropTypes.object.isRequired, |
81 | onDelete: PropTypes.func.isRequired, | 77 | onDelete: PropTypes.func.isRequired, |
@@ -97,7 +93,7 @@ class EditWorkspaceForm extends Component { | |||
97 | } | 93 | } |
98 | 94 | ||
99 | prepareWorkspaceForm(workspace) { | 95 | prepareWorkspaceForm(workspace) { |
100 | const { intl } = this.context; | 96 | const { intl } = this.props; |
101 | return new Form({ | 97 | return new Form({ |
102 | fields: { | 98 | fields: { |
103 | name: { | 99 | name: { |
@@ -112,7 +108,7 @@ class EditWorkspaceForm extends Component { | |||
112 | default: false, | 108 | default: false, |
113 | }, | 109 | }, |
114 | services: { | 110 | services: { |
115 | value: workspace.services.slice(), | 111 | value: [...workspace.services], |
116 | }, | 112 | }, |
117 | }, | 113 | }, |
118 | }); | 114 | }); |
@@ -120,7 +116,7 @@ class EditWorkspaceForm extends Component { | |||
120 | 116 | ||
121 | save(form) { | 117 | save(form) { |
122 | form.submit({ | 118 | form.submit({ |
123 | onSuccess: async (f) => { | 119 | onSuccess: async f => { |
124 | const { onSave } = this.props; | 120 | const { onSave } = this.props; |
125 | const values = f.values(); | 121 | const values = f.values(); |
126 | onSave(values); | 122 | onSave(values); |
@@ -146,7 +142,7 @@ class EditWorkspaceForm extends Component { | |||
146 | } | 142 | } |
147 | 143 | ||
148 | render() { | 144 | render() { |
149 | const { intl } = this.context; | 145 | const { intl } = this.props; |
150 | const { | 146 | const { |
151 | classes, | 147 | classes, |
152 | workspace, | 148 | workspace, |
@@ -194,7 +190,7 @@ class EditWorkspaceForm extends Component { | |||
194 | </div> | 190 | </div> |
195 | ) : ( | 191 | ) : ( |
196 | <> | 192 | <> |
197 | {services.map((s) => ( | 193 | {services.map(s => ( |
198 | <WorkspaceServiceListItem | 194 | <WorkspaceServiceListItem |
199 | key={s.id} | 195 | key={s.id} |
200 | service={s} | 196 | service={s} |
@@ -233,4 +229,4 @@ class EditWorkspaceForm extends Component { | |||
233 | } | 229 | } |
234 | } | 230 | } |
235 | 231 | ||
236 | export default EditWorkspaceForm; | 232 | export default injectIntl(EditWorkspaceForm); |
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js index 1138f23d7..3dac77bc2 100644 --- a/src/features/workspaces/components/WorkspaceDrawer.js +++ b/src/features/workspaces/components/WorkspaceDrawer.js | |||
@@ -2,11 +2,11 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, injectIntl } from 'react-intl'; |
6 | import { H1, Icon } from '@meetfranz/ui'; | 6 | import { H1, Icon } from '@meetfranz/ui'; |
7 | import ReactTooltip from 'react-tooltip'; | 7 | import ReactTooltip from 'react-tooltip'; |
8 | 8 | ||
9 | import { mdiPlusBox, mdiSettings } from '@mdi/js'; | 9 | import { mdiPlusBox, mdiCog } from '@mdi/js'; |
10 | import WorkspaceDrawerItem from './WorkspaceDrawerItem'; | 10 | import WorkspaceDrawerItem from './WorkspaceDrawerItem'; |
11 | import { workspaceActions } from '../actions'; | 11 | import { workspaceActions } from '../actions'; |
12 | import { workspaceStore } from '../index'; | 12 | import { workspaceStore } from '../index'; |
@@ -14,27 +14,28 @@ import { workspaceStore } from '../index'; | |||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
15 | headline: { | 15 | headline: { |
16 | id: 'workspaceDrawer.headline', | 16 | id: 'workspaceDrawer.headline', |
17 | defaultMessage: '!!!Workspaces', | 17 | defaultMessage: 'Workspaces', |
18 | }, | 18 | }, |
19 | allServices: { | 19 | allServices: { |
20 | id: 'workspaceDrawer.allServices', | 20 | id: 'workspaceDrawer.allServices', |
21 | defaultMessage: '!!!All services', | 21 | defaultMessage: 'All services', |
22 | }, | 22 | }, |
23 | workspacesSettingsTooltip: { | 23 | workspacesSettingsTooltip: { |
24 | id: 'workspaceDrawer.workspacesSettingsTooltip', | 24 | id: 'workspaceDrawer.workspacesSettingsTooltip', |
25 | defaultMessage: '!!!Workspaces settings', | 25 | defaultMessage: 'Edit workspaces settings', |
26 | }, | 26 | }, |
27 | workspaceFeatureInfo: { | 27 | workspaceFeatureInfo: { |
28 | id: 'workspaceDrawer.workspaceFeatureInfo', | 28 | id: 'workspaceDrawer.workspaceFeatureInfo', |
29 | defaultMessage: '!!!Info about workspace feature', | 29 | defaultMessage: |
30 | '<p>Ferdi Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>', | ||
30 | }, | 31 | }, |
31 | addNewWorkspaceLabel: { | 32 | addNewWorkspaceLabel: { |
32 | id: 'workspaceDrawer.addNewWorkspaceLabel', | 33 | id: 'workspaceDrawer.addNewWorkspaceLabel', |
33 | defaultMessage: '!!!add new workspace', | 34 | defaultMessage: 'Add new workspace', |
34 | }, | 35 | }, |
35 | }); | 36 | }); |
36 | 37 | ||
37 | const styles = (theme) => ({ | 38 | const styles = theme => ({ |
38 | drawer: { | 39 | drawer: { |
39 | background: theme.workspaces.drawer.background, | 40 | background: theme.workspaces.drawer.background, |
40 | width: `${theme.workspaces.drawer.width}px`, | 41 | width: `${theme.workspaces.drawer.width}px`, |
@@ -85,34 +86,26 @@ const styles = (theme) => ({ | |||
85 | }, | 86 | }, |
86 | }); | 87 | }); |
87 | 88 | ||
88 | @injectSheet(styles) @observer | 89 | @injectSheet(styles) |
90 | @observer | ||
89 | class WorkspaceDrawer extends Component { | 91 | class WorkspaceDrawer extends Component { |
90 | static propTypes = { | 92 | static propTypes = { |
91 | classes: PropTypes.object.isRequired, | 93 | classes: PropTypes.object.isRequired, |
92 | getServicesForWorkspace: PropTypes.func.isRequired, | 94 | getServicesForWorkspace: PropTypes.func.isRequired, |
93 | }; | 95 | }; |
94 | 96 | ||
95 | static contextTypes = { | ||
96 | intl: intlShape, | ||
97 | }; | ||
98 | |||
99 | componentDidMount() { | 97 | componentDidMount() { |
100 | ReactTooltip.rebuild(); | 98 | ReactTooltip.rebuild(); |
101 | } | 99 | } |
102 | 100 | ||
103 | render() { | 101 | render() { |
104 | const { | 102 | const { classes, getServicesForWorkspace } = this.props; |
105 | classes, | 103 | const { intl } = this.props; |
106 | getServicesForWorkspace, | 104 | const { activeWorkspace, isSwitchingWorkspace, nextWorkspace, workspaces } = |
107 | } = this.props; | 105 | workspaceStore; |
108 | const { intl } = this.context; | 106 | const actualWorkspace = isSwitchingWorkspace |
109 | const { | 107 | ? nextWorkspace |
110 | activeWorkspace, | 108 | : activeWorkspace; |
111 | isSwitchingWorkspace, | ||
112 | nextWorkspace, | ||
113 | workspaces, | ||
114 | } = workspaceStore; | ||
115 | const actualWorkspace = isSwitchingWorkspace ? nextWorkspace : activeWorkspace; | ||
116 | return ( | 109 | return ( |
117 | <div className={`${classes.drawer} workspaces-drawer`}> | 110 | <div className={`${classes.drawer} workspaces-drawer`}> |
118 | <H1 className={classes.headline}> | 111 | <H1 className={classes.headline}> |
@@ -122,10 +115,12 @@ class WorkspaceDrawer extends Component { | |||
122 | onClick={() => { | 115 | onClick={() => { |
123 | workspaceActions.openWorkspaceSettings(); | 116 | workspaceActions.openWorkspaceSettings(); |
124 | }} | 117 | }} |
125 | data-tip={`${intl.formatMessage(messages.workspacesSettingsTooltip)}`} | 118 | data-tip={`${intl.formatMessage( |
119 | messages.workspacesSettingsTooltip, | ||
120 | )}`} | ||
126 | > | 121 | > |
127 | <Icon | 122 | <Icon |
128 | icon={mdiSettings} | 123 | icon={mdiCog} |
129 | size={1.5} | 124 | size={1.5} |
130 | className={classes.workspacesSettingsButtonIcon} | 125 | className={classes.workspacesSettingsButtonIcon} |
131 | /> | 126 | /> |
@@ -152,7 +147,9 @@ class WorkspaceDrawer extends Component { | |||
152 | workspaceActions.activate({ workspace }); | 147 | workspaceActions.activate({ workspace }); |
153 | workspaceActions.toggleWorkspaceDrawer(); | 148 | workspaceActions.toggleWorkspaceDrawer(); |
154 | }} | 149 | }} |
155 | onContextMenuEditClick={() => workspaceActions.edit({ workspace })} | 150 | onContextMenuEditClick={() => |
151 | workspaceActions.edit({ workspace }) | ||
152 | } | ||
156 | services={getServicesForWorkspace(workspace)} | 153 | services={getServicesForWorkspace(workspace)} |
157 | shortcutIndex={index + 1} | 154 | shortcutIndex={index + 1} |
158 | /> | 155 | /> |
@@ -168,9 +165,7 @@ class WorkspaceDrawer extends Component { | |||
168 | size={1} | 165 | size={1} |
169 | className={classes.workspacesSettingsButtonIcon} | 166 | className={classes.workspacesSettingsButtonIcon} |
170 | /> | 167 | /> |
171 | <span> | 168 | <span>{intl.formatMessage(messages.addNewWorkspaceLabel)}</span> |
172 | {intl.formatMessage(messages.addNewWorkspaceLabel)} | ||
173 | </span> | ||
174 | </div> | 169 | </div> |
175 | </div> | 170 | </div> |
176 | <ReactTooltip place="right" type="dark" effect="solid" /> | 171 | <ReactTooltip place="right" type="dark" effect="solid" /> |
@@ -179,4 +174,4 @@ class WorkspaceDrawer extends Component { | |||
179 | } | 174 | } |
180 | } | 175 | } |
181 | 176 | ||
182 | export default WorkspaceDrawer; | 177 | export default injectIntl(WorkspaceDrawer); |
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js index 252158364..4afb9c108 100644 --- a/src/features/workspaces/components/WorkspaceDrawerItem.js +++ b/src/features/workspaces/components/WorkspaceDrawerItem.js | |||
@@ -1,20 +1,20 @@ | |||
1 | import { Menu, getCurrentWindow } from '@electron/remote'; | 1 | import { Menu } from '@electron/remote'; |
2 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { observer } from 'mobx-react'; | 4 | import { observer } from 'mobx-react'; |
5 | import injectSheet from 'react-jss'; | 5 | import injectSheet from 'react-jss'; |
6 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
7 | import { defineMessages, intlShape } from 'react-intl'; | 7 | import { defineMessages, injectIntl } from 'react-intl'; |
8 | import { altKey, cmdOrCtrlShortcutKey } from '../../../environment'; | 8 | import { altKey, cmdOrCtrlShortcutKey } from '../../../environment'; |
9 | 9 | ||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | noServicesAddedYet: { | 11 | noServicesAddedYet: { |
12 | id: 'workspaceDrawer.item.noServicesAddedYet', | 12 | id: 'workspaceDrawer.item.noServicesAddedYet', |
13 | defaultMessage: '!!!No services added yet', | 13 | defaultMessage: 'No services added yet', |
14 | }, | 14 | }, |
15 | contextMenuEdit: { | 15 | contextMenuEdit: { |
16 | id: 'workspaceDrawer.item.contextMenuEdit', | 16 | id: 'workspaceDrawer.item.contextMenuEdit', |
17 | defaultMessage: '!!!edit', | 17 | defaultMessage: 'edit', |
18 | }, | 18 | }, |
19 | }); | 19 | }); |
20 | 20 | ||
@@ -82,10 +82,6 @@ class WorkspaceDrawerItem extends Component { | |||
82 | onContextMenuEditClick: null, | 82 | onContextMenuEditClick: null, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static contextTypes = { | ||
86 | intl: intlShape, | ||
87 | }; | ||
88 | |||
89 | render() { | 85 | render() { |
90 | const { | 86 | const { |
91 | classes, | 87 | classes, |
@@ -96,7 +92,8 @@ class WorkspaceDrawerItem extends Component { | |||
96 | services, | 92 | services, |
97 | shortcutIndex, | 93 | shortcutIndex, |
98 | } = this.props; | 94 | } = this.props; |
99 | const { intl } = this.context; | 95 | |
96 | const { intl } = this.props; | ||
100 | 97 | ||
101 | const contextMenuTemplate = [ | 98 | const contextMenuTemplate = [ |
102 | { | 99 | { |
@@ -122,10 +119,14 @@ class WorkspaceDrawerItem extends Component { | |||
122 | ])} | 119 | ])} |
123 | onClick={onClick} | 120 | onClick={onClick} |
124 | onContextMenu={() => | 121 | onContextMenu={() => |
125 | onContextMenuEditClick && contextMenu.popup(getCurrentWindow()) | 122 | onContextMenuEditClick && contextMenu.popup() |
126 | } | 123 | } |
127 | data-tip={`${ | 124 | data-tip={`${ |
128 | shortcutIndex <= 9 ? `(${cmdOrCtrlShortcutKey(false)}+${altKey(false)}+${shortcutIndex})` : '' | 125 | shortcutIndex <= 9 |
126 | ? `(${cmdOrCtrlShortcutKey(false)}+${altKey( | ||
127 | false, | ||
128 | )}+${shortcutIndex})` | ||
129 | : '' | ||
129 | }`} | 130 | }`} |
130 | > | 131 | > |
131 | <span | 132 | <span |
@@ -142,7 +143,7 @@ class WorkspaceDrawerItem extends Component { | |||
142 | isActive ? classes.activeServices : null, | 143 | isActive ? classes.activeServices : null, |
143 | ])} | 144 | ])} |
144 | > | 145 | > |
145 | {services.length | 146 | {services.length > 0 |
146 | ? services.join(', ') | 147 | ? services.join(', ') |
147 | : intl.formatMessage(messages.noServicesAddedYet)} | 148 | : intl.formatMessage(messages.noServicesAddedYet)} |
148 | </span> | 149 | </span> |
@@ -151,4 +152,4 @@ class WorkspaceDrawerItem extends Component { | |||
151 | } | 152 | } |
152 | } | 153 | } |
153 | 154 | ||
154 | export default WorkspaceDrawerItem; | 155 | export default injectIntl(WorkspaceDrawerItem); |
diff --git a/src/features/workspaces/components/WorkspaceItem.js b/src/features/workspaces/components/WorkspaceItem.js index 85fc02d51..ec7b19add 100644 --- a/src/features/workspaces/components/WorkspaceItem.js +++ b/src/features/workspaces/components/WorkspaceItem.js | |||
@@ -1,12 +1,11 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { intlShape } from 'react-intl'; | ||
4 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
5 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
6 | 5 | ||
7 | import Workspace from '../models/Workspace'; | 6 | import Workspace from '../models/Workspace'; |
8 | 7 | ||
9 | const styles = (theme) => ({ | 8 | const styles = theme => ({ |
10 | row: { | 9 | row: { |
11 | height: theme.workspaces.settings.listItems.height, | 10 | height: theme.workspaces.settings.listItems.height, |
12 | borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`, | 11 | borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`, |
@@ -17,7 +16,8 @@ const styles = (theme) => ({ | |||
17 | columnName: {}, | 16 | columnName: {}, |
18 | }); | 17 | }); |
19 | 18 | ||
20 | @injectSheet(styles) @observer | 19 | @injectSheet(styles) |
20 | @observer | ||
21 | class WorkspaceItem extends Component { | 21 | class WorkspaceItem extends Component { |
22 | static propTypes = { | 22 | static propTypes = { |
23 | classes: PropTypes.object.isRequired, | 23 | classes: PropTypes.object.isRequired, |
@@ -25,18 +25,12 @@ class WorkspaceItem extends Component { | |||
25 | onItemClick: PropTypes.func.isRequired, | 25 | onItemClick: PropTypes.func.isRequired, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static contextTypes = { | ||
29 | intl: intlShape, | ||
30 | }; | ||
31 | |||
32 | render() { | 28 | render() { |
33 | const { classes, workspace, onItemClick } = this.props; | 29 | const { classes, workspace, onItemClick } = this.props; |
34 | 30 | ||
35 | return ( | 31 | return ( |
36 | <tr className={classes.row}> | 32 | <tr className={classes.row}> |
37 | <td onClick={() => onItemClick(workspace)}> | 33 | <td onClick={() => onItemClick(workspace)}>{workspace.name}</td> |
38 | {workspace.name} | ||
39 | </td> | ||
40 | </tr> | 34 | </tr> |
41 | ); | 35 | ); |
42 | } | 36 | } |
diff --git a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js index c8ec0bc4c..33a82cf4b 100644 --- a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js +++ b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js | |||
@@ -4,14 +4,14 @@ import { observer } from 'mobx-react'; | |||
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import classnames from 'classnames'; | 5 | import classnames from 'classnames'; |
6 | import { Loader } from '@meetfranz/ui'; | 6 | import { Loader } from '@meetfranz/ui'; |
7 | import { defineMessages, intlShape } from 'react-intl'; | 7 | import { defineMessages, injectIntl } from 'react-intl'; |
8 | 8 | ||
9 | import { workspaceStore } from '../index'; | 9 | import { workspaceStore } from '../index'; |
10 | 10 | ||
11 | const messages = defineMessages({ | 11 | const messages = defineMessages({ |
12 | switchingTo: { | 12 | switchingTo: { |
13 | id: 'workspaces.switchingIndicator.switchingTo', | 13 | id: 'workspaces.switchingIndicator.switchingTo', |
14 | defaultMessage: '!!!Switching to', | 14 | defaultMessage: 'Switching to', |
15 | }, | 15 | }, |
16 | }); | 16 | }); |
17 | 17 | ||
@@ -61,13 +61,9 @@ class WorkspaceSwitchingIndicator extends Component { | |||
61 | theme: PropTypes.object.isRequired, | 61 | theme: PropTypes.object.isRequired, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static contextTypes = { | ||
65 | intl: intlShape, | ||
66 | }; | ||
67 | |||
68 | render() { | 64 | render() { |
69 | const { classes, theme } = this.props; | 65 | const { classes, theme } = this.props; |
70 | const { intl } = this.context; | 66 | const { intl } = this.props; |
71 | const { isSwitchingWorkspace, nextWorkspace } = workspaceStore; | 67 | const { isSwitchingWorkspace, nextWorkspace } = workspaceStore; |
72 | if (!isSwitchingWorkspace) return null; | 68 | if (!isSwitchingWorkspace) return null; |
73 | const nextWorkspaceName = nextWorkspace | 69 | const nextWorkspaceName = nextWorkspace |
@@ -89,4 +85,4 @@ class WorkspaceSwitchingIndicator extends Component { | |||
89 | } | 85 | } |
90 | } | 86 | } |
91 | 87 | ||
92 | export default WorkspaceSwitchingIndicator; | 88 | export default injectIntl(WorkspaceSwitchingIndicator); |
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index 5f34204f1..49552df6b 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, injectIntl } from 'react-intl'; |
5 | import injectSheet from 'react-jss'; | 5 | import injectSheet from 'react-jss'; |
6 | import { Infobox } from '@meetfranz/ui'; | 6 | import { Infobox } from '@meetfranz/ui'; |
7 | 7 | ||
@@ -16,35 +16,35 @@ import UIStore from '../../../stores/UIStore'; | |||
16 | const messages = defineMessages({ | 16 | const messages = defineMessages({ |
17 | headline: { | 17 | headline: { |
18 | id: 'settings.workspaces.headline', | 18 | id: 'settings.workspaces.headline', |
19 | defaultMessage: '!!!Your workspaces', | 19 | defaultMessage: 'Your workspaces', |
20 | }, | 20 | }, |
21 | noServicesAdded: { | 21 | noServicesAdded: { |
22 | id: 'settings.workspaces.noWorkspacesAdded', | 22 | id: 'settings.workspaces.noWorkspacesAdded', |
23 | defaultMessage: "!!!You haven't created any workspaces yet.", | 23 | defaultMessage: "You haven't created any workspaces yet.", |
24 | }, | 24 | }, |
25 | workspacesRequestFailed: { | 25 | workspacesRequestFailed: { |
26 | id: 'settings.workspaces.workspacesRequestFailed', | 26 | id: 'settings.workspaces.workspacesRequestFailed', |
27 | defaultMessage: '!!!Could not load your workspaces', | 27 | defaultMessage: 'Could not load your workspaces', |
28 | }, | 28 | }, |
29 | tryReloadWorkspaces: { | 29 | tryReloadWorkspaces: { |
30 | id: 'settings.workspaces.tryReloadWorkspaces', | 30 | id: 'settings.workspaces.tryReloadWorkspaces', |
31 | defaultMessage: '!!!Try again', | 31 | defaultMessage: 'Try again', |
32 | }, | 32 | }, |
33 | updatedInfo: { | 33 | updatedInfo: { |
34 | id: 'settings.workspaces.updatedInfo', | 34 | id: 'settings.workspaces.updatedInfo', |
35 | defaultMessage: '!!!Your changes have been saved', | 35 | defaultMessage: 'Your changes have been saved', |
36 | }, | 36 | }, |
37 | deletedInfo: { | 37 | deletedInfo: { |
38 | id: 'settings.workspaces.deletedInfo', | 38 | id: 'settings.workspaces.deletedInfo', |
39 | defaultMessage: '!!!Workspace has been deleted', | 39 | defaultMessage: 'Workspace has been deleted', |
40 | }, | 40 | }, |
41 | workspaceFeatureInfo: { | 41 | workspaceFeatureInfo: { |
42 | id: 'settings.workspaces.workspaceFeatureInfo', | 42 | id: 'settings.workspaces.workspaceFeatureInfo', |
43 | defaultMessage: '!!!Info about workspace feature', | 43 | defaultMessage: 'Ferdi Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.', |
44 | }, | 44 | }, |
45 | workspaceFeatureHeadline: { | 45 | workspaceFeatureHeadline: { |
46 | id: 'settings.workspaces.workspaceFeatureHeadline', | 46 | id: 'settings.workspaces.workspaceFeatureHeadline', |
47 | defaultMessage: '!!!Less is More: Introducing Ferdi Workspaces', | 47 | defaultMessage: 'Less is More: Introducing Ferdi Workspaces', |
48 | }, | 48 | }, |
49 | }); | 49 | }); |
50 | 50 | ||
@@ -83,10 +83,6 @@ class WorkspacesDashboard extends Component { | |||
83 | workspaces: MobxPropTypes.arrayOrObservableArray.isRequired, | 83 | workspaces: MobxPropTypes.arrayOrObservableArray.isRequired, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | static contextTypes = { | ||
87 | intl: intlShape, | ||
88 | }; | ||
89 | |||
90 | render() { | 86 | render() { |
91 | const { | 87 | const { |
92 | classes, | 88 | classes, |
@@ -99,7 +95,7 @@ class WorkspacesDashboard extends Component { | |||
99 | workspaces, | 95 | workspaces, |
100 | } = this.props; | 96 | } = this.props; |
101 | 97 | ||
102 | const { intl } = this.context; | 98 | const { intl } = this.props; |
103 | 99 | ||
104 | return ( | 100 | return ( |
105 | <div className="settings__main"> | 101 | <div className="settings__main"> |
@@ -193,7 +189,7 @@ class WorkspacesDashboard extends Component { | |||
193 | } | 189 | } |
194 | } | 190 | } |
195 | 191 | ||
196 | export default WorkspacesDashboard; | 192 | export default injectIntl(WorkspacesDashboard); |
197 | 193 | ||
198 | WorkspacesDashboard.wrappedComponent.propTypes = { | 194 | WorkspacesDashboard.wrappedComponent.propTypes = { |
199 | stores: PropTypes.shape({ | 195 | stores: PropTypes.shape({ |
diff --git a/src/features/workspaces/constants.js b/src/features/workspaces/constants.ts index 2d1416ee0..2d1416ee0 100644 --- a/src/features/workspaces/constants.js +++ b/src/features/workspaces/constants.ts | |||
diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.ts index 83e4d9049..ecca64b41 100644 --- a/src/features/workspaces/index.js +++ b/src/features/workspaces/index.ts | |||
@@ -12,10 +12,8 @@ export default function initWorkspaces(stores, actions) { | |||
12 | 12 | ||
13 | // Toggle workspace feature | 13 | // Toggle workspace feature |
14 | reaction( | 14 | reaction( |
15 | () => ( | 15 | () => features.features.isWorkspaceEnabled, |
16 | features.features.isWorkspaceEnabled | 16 | isEnabled => { |
17 | ), | ||
18 | (isEnabled) => { | ||
19 | if (isEnabled && !workspaceStore.isFeatureActive) { | 17 | if (isEnabled && !workspaceStore.isFeatureActive) { |
20 | debug('Initializing `workspaces` feature'); | 18 | debug('Initializing `workspaces` feature'); |
21 | workspaceStore.start(stores, actions); | 19 | workspaceStore.start(stores, actions); |
diff --git a/src/features/workspaces/models/Workspace.js b/src/features/workspaces/models/Workspace.ts index d9488e991..cd3918fba 100644 --- a/src/features/workspaces/models/Workspace.js +++ b/src/features/workspaces/models/Workspace.ts | |||
@@ -15,7 +15,7 @@ export default class Workspace { | |||
15 | 15 | ||
16 | constructor(data) { | 16 | constructor(data) { |
17 | if (!data.id) { | 17 | if (!data.id) { |
18 | throw Error('Workspace requires Id'); | 18 | throw new Error('Workspace requires Id'); |
19 | } | 19 | } |
20 | 20 | ||
21 | this.id = data.id; | 21 | this.id = data.id; |
@@ -28,8 +28,10 @@ export default class Workspace { | |||
28 | services.push(KEEP_WS_LOADED_USID); | 28 | services.push(KEEP_WS_LOADED_USID); |
29 | } else if (data.saving && data.services.includes(KEEP_WS_LOADED_USID)) { | 29 | } else if (data.saving && data.services.includes(KEEP_WS_LOADED_USID)) { |
30 | // Don't keep loaded | 30 | // Don't keep loaded |
31 | services = services.filter((e) => e !== KEEP_WS_LOADED_USID); | 31 | services = services.filter(e => e !== KEEP_WS_LOADED_USID); |
32 | } | 32 | } |
33 | |||
34 | // @ts-expect-error Property 'replace' does not exist on type 'never[]'. | ||
33 | this.services.replace(services); | 35 | this.services.replace(services); |
34 | 36 | ||
35 | this.userId = data.userId; | 37 | this.userId = data.userId; |
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index ec9d7ee7f..db2b69f99 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -190,6 +190,12 @@ export default class WorkspacesStore extends FeatureStore { | |||
190 | setTimeout(() => { | 190 | setTimeout(() => { |
191 | this.isSwitchingWorkspace = false; | 191 | this.isSwitchingWorkspace = false; |
192 | this.nextWorkspace = null; | 192 | this.nextWorkspace = null; |
193 | if (this.stores.settings.app.splitMode) { | ||
194 | const serviceNames = new Set(this.getWorkspaceServices(workspace).map(service => service.name)); | ||
195 | for (const wrapper of document.querySelectorAll('.services__webview-wrapper')) { | ||
196 | wrapper.style.display = serviceNames.has(wrapper.dataset.name) ? '' : 'none'; | ||
197 | } | ||
198 | } | ||
193 | }, 1000); | 199 | }, 1000); |
194 | }; | 200 | }; |
195 | 201 | ||
@@ -205,6 +211,11 @@ export default class WorkspacesStore extends FeatureStore { | |||
205 | // Indicate that we are done switching to the default workspace | 211 | // Indicate that we are done switching to the default workspace |
206 | setTimeout(() => { | 212 | setTimeout(() => { |
207 | this.isSwitchingWorkspace = false; | 213 | this.isSwitchingWorkspace = false; |
214 | if (this.stores.settings.app.splitMode) { | ||
215 | for (const wrapper of document.querySelectorAll('.services__webview-wrapper')) { | ||
216 | wrapper.style.display = ''; | ||
217 | } | ||
218 | } | ||
208 | }, 1000); | 219 | }, 1000); |
209 | }; | 220 | }; |
210 | 221 | ||
@@ -302,8 +313,8 @@ export default class WorkspacesStore extends FeatureStore { | |||
302 | const { allServicesRequest } = services; | 313 | const { allServicesRequest } = services; |
303 | const servicesHaveBeenLoaded = allServicesRequest.wasExecuted && !allServicesRequest.isError; | 314 | const servicesHaveBeenLoaded = allServicesRequest.wasExecuted && !allServicesRequest.isError; |
304 | // Loop through all workspaces and remove invalid service ids (locally) | 315 | // Loop through all workspaces and remove invalid service ids (locally) |
305 | this.workspaces.forEach((workspace) => { | 316 | for (const workspace of this.workspaces) { |
306 | workspace.services.forEach((serviceId) => { | 317 | for (const serviceId of workspace.services) { |
307 | if ( | 318 | if ( |
308 | servicesHaveBeenLoaded | 319 | servicesHaveBeenLoaded |
309 | && !services.one(serviceId) | 320 | && !services.one(serviceId) |
@@ -311,7 +322,7 @@ export default class WorkspacesStore extends FeatureStore { | |||
311 | ) { | 322 | ) { |
312 | workspace.services.remove(serviceId); | 323 | workspace.services.remove(serviceId); |
313 | } | 324 | } |
314 | }); | 325 | } |
315 | }); | 326 | } |
316 | }; | 327 | }; |
317 | } | 328 | } |