diff options
author | Stefan Malzner <stefan@adlk.io> | 2019-07-30 11:41:54 +0200 |
---|---|---|
committer | Stefan Malzner <stefan@adlk.io> | 2019-07-30 11:41:54 +0200 |
commit | d7ed456a7b6f73e046ba3a2ef38eb21f82f06ca4 (patch) | |
tree | f24f4f39ae38bdfdd581f451fc3e2e79f5670df5 | |
parent | Fix position of todos app (diff) | |
download | ferdium-app-d7ed456a7b6f73e046ba3a2ef38eb21f82f06ca4.tar.gz ferdium-app-d7ed456a7b6f73e046ba3a2ef38eb21f82f06ca4.tar.zst ferdium-app-d7ed456a7b6f73e046ba3a2ef38eb21f82f06ca4.zip |
Make todo layer resizable
-rw-r--r-- | packages/theme/src/themes/default/index.ts | 7 | ||||
-rw-r--r-- | src/actions/index.js | 2 | ||||
-rw-r--r-- | src/components/layout/AppLayout.js | 16 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 4 | ||||
-rw-r--r-- | src/features/todos/actions.js | 10 | ||||
-rw-r--r-- | src/features/todos/components/TodosWebview.js | 129 | ||||
-rw-r--r-- | src/features/todos/containers/TodosScreen.js | 45 | ||||
-rw-r--r-- | src/features/todos/index.js | 33 | ||||
-rw-r--r-- | src/features/todos/store.js | 86 | ||||
-rw-r--r-- | src/stores/FeaturesStore.js | 2 | ||||
-rw-r--r-- | src/styles/layout.scss | 7 |
11 files changed, 311 insertions, 30 deletions
diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts index 0f02fa3c8..4a49a4de0 100644 --- a/packages/theme/src/themes/default/index.ts +++ b/packages/theme/src/themes/default/index.ts | |||
@@ -207,3 +207,10 @@ export const announcements = { | |||
207 | background: legacyStyles.themeGrayLightest, | 207 | background: legacyStyles.themeGrayLightest, |
208 | }, | 208 | }, |
209 | }; | 209 | }; |
210 | |||
211 | // Todos | ||
212 | export const todos = { | ||
213 | dragIndicator: { | ||
214 | background: legacyStyles.themeGrayLight, | ||
215 | }, | ||
216 | }; | ||
diff --git a/src/actions/index.js b/src/actions/index.js index fc525afeb..336344d76 100644 --- a/src/actions/index.js +++ b/src/actions/index.js | |||
@@ -13,6 +13,7 @@ import settings from './settings'; | |||
13 | import requests from './requests'; | 13 | import requests from './requests'; |
14 | import announcements from '../features/announcements/actions'; | 14 | import announcements from '../features/announcements/actions'; |
15 | import workspaces from '../features/workspaces/actions'; | 15 | import workspaces from '../features/workspaces/actions'; |
16 | import todos from '../features/todos/actions'; | ||
16 | 17 | ||
17 | const actions = Object.assign({}, { | 18 | const actions = Object.assign({}, { |
18 | service, | 19 | service, |
@@ -31,4 +32,5 @@ export default Object.assign( | |||
31 | defineActions(actions, PropTypes.checkPropTypes), | 32 | defineActions(actions, PropTypes.checkPropTypes), |
32 | { announcements }, | 33 | { announcements }, |
33 | { workspaces }, | 34 | { workspaces }, |
35 | { todos }, | ||
34 | ); | 36 | ); |
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 7f2f707fb..dbf7d3c21 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -17,7 +17,7 @@ import { isWindows } from '../../environment'; | |||
17 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; | 17 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; |
18 | import { workspaceStore } from '../../features/workspaces'; | 18 | import { workspaceStore } from '../../features/workspaces'; |
19 | import AppUpdateInfoBar from '../AppUpdateInfoBar'; | 19 | import AppUpdateInfoBar from '../AppUpdateInfoBar'; |
20 | import TodosWebview from '../../features/todos/components/TodosWebview'; | 20 | import Todos from '../../features/todos/containers/TodosScreen'; |
21 | 21 | ||
22 | function createMarkup(HTMLString) { | 22 | function createMarkup(HTMLString) { |
23 | return { __html: HTMLString }; | 23 | return { __html: HTMLString }; |
@@ -52,7 +52,6 @@ const styles = theme => ({ | |||
52 | @injectSheet(styles) @observer | 52 | @injectSheet(styles) @observer |
53 | class AppLayout extends Component { | 53 | class AppLayout extends Component { |
54 | static propTypes = { | 54 | static propTypes = { |
55 | authToken: PropTypes.string.isRequired, | ||
56 | classes: PropTypes.object.isRequired, | 55 | classes: PropTypes.object.isRequired, |
57 | isFullScreen: PropTypes.bool.isRequired, | 56 | isFullScreen: PropTypes.bool.isRequired, |
58 | sidebar: PropTypes.element.isRequired, | 57 | sidebar: PropTypes.element.isRequired, |
@@ -60,7 +59,6 @@ class AppLayout extends Component { | |||
60 | services: PropTypes.element.isRequired, | 59 | services: PropTypes.element.isRequired, |
61 | children: PropTypes.element, | 60 | children: PropTypes.element, |
62 | news: MobxPropTypes.arrayOrObservableArray.isRequired, | 61 | news: MobxPropTypes.arrayOrObservableArray.isRequired, |
63 | // isOnline: PropTypes.bool.isRequired, | ||
64 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, | 62 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, |
65 | appUpdateIsDownloaded: PropTypes.bool.isRequired, | 63 | appUpdateIsDownloaded: PropTypes.bool.isRequired, |
66 | nextAppReleaseVersion: PropTypes.string, | 64 | nextAppReleaseVersion: PropTypes.string, |
@@ -85,7 +83,6 @@ class AppLayout extends Component { | |||
85 | 83 | ||
86 | render() { | 84 | render() { |
87 | const { | 85 | const { |
88 | authToken, | ||
89 | classes, | 86 | classes, |
90 | isFullScreen, | 87 | isFullScreen, |
91 | workspacesDrawer, | 88 | workspacesDrawer, |
@@ -129,15 +126,6 @@ class AppLayout extends Component { | |||
129 | <span dangerouslySetInnerHTML={createMarkup(item.message)} /> | 126 | <span dangerouslySetInnerHTML={createMarkup(item.message)} /> |
130 | </InfoBar> | 127 | </InfoBar> |
131 | ))} | 128 | ))} |
132 | {/* {!isOnline && ( | ||
133 | <InfoBar | ||
134 | type="danger" | ||
135 | sticky | ||
136 | > | ||
137 | <span className="mdi mdi-flash" /> | ||
138 | {intl.formatMessage(globalMessages.notConnectedToTheInternet)} | ||
139 | </InfoBar> | ||
140 | )} */} | ||
141 | {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( | 129 | {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( |
142 | <InfoBar | 130 | <InfoBar |
143 | type="danger" | 131 | type="danger" |
@@ -173,7 +161,7 @@ class AppLayout extends Component { | |||
173 | {services} | 161 | {services} |
174 | {children} | 162 | {children} |
175 | </div> | 163 | </div> |
176 | <TodosWebview authToken={authToken} /> | 164 | <Todos /> |
177 | </div> | 165 | </div> |
178 | </div> | 166 | </div> |
179 | </ErrorBoundary> | 167 | </ErrorBoundary> |
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 8a48f4924..cf3da71e8 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -12,7 +12,6 @@ import NewsStore from '../../stores/NewsStore'; | |||
12 | import SettingsStore from '../../stores/SettingsStore'; | 12 | import SettingsStore from '../../stores/SettingsStore'; |
13 | import RequestStore from '../../stores/RequestStore'; | 13 | import RequestStore from '../../stores/RequestStore'; |
14 | import GlobalErrorStore from '../../stores/GlobalErrorStore'; | 14 | import GlobalErrorStore from '../../stores/GlobalErrorStore'; |
15 | import UserStore from '../../stores/UserStore'; | ||
16 | 15 | ||
17 | import { oneOrManyChildElements } from '../../prop-types'; | 16 | import { oneOrManyChildElements } from '../../prop-types'; |
18 | import AppLayout from '../../components/layout/AppLayout'; | 17 | import AppLayout from '../../components/layout/AppLayout'; |
@@ -40,7 +39,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
40 | settings, | 39 | settings, |
41 | globalError, | 40 | globalError, |
42 | requests, | 41 | requests, |
43 | user, | ||
44 | } = this.props.stores; | 42 | } = this.props.stores; |
45 | 43 | ||
46 | const { | 44 | const { |
@@ -133,7 +131,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
133 | return ( | 131 | return ( |
134 | <ThemeProvider theme={ui.theme}> | 132 | <ThemeProvider theme={ui.theme}> |
135 | <AppLayout | 133 | <AppLayout |
136 | authToken={user.authToken} | ||
137 | isFullScreen={app.isFullScreen} | 134 | isFullScreen={app.isFullScreen} |
138 | isOnline={app.isOnline} | 135 | isOnline={app.isOnline} |
139 | showServicesUpdatedInfoBar={ui.showServicesUpdatedInfoBar} | 136 | showServicesUpdatedInfoBar={ui.showServicesUpdatedInfoBar} |
@@ -171,7 +168,6 @@ AppLayoutContainer.wrappedComponent.propTypes = { | |||
171 | settings: PropTypes.instanceOf(SettingsStore).isRequired, | 168 | settings: PropTypes.instanceOf(SettingsStore).isRequired, |
172 | requests: PropTypes.instanceOf(RequestStore).isRequired, | 169 | requests: PropTypes.instanceOf(RequestStore).isRequired, |
173 | globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, | 170 | globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, |
174 | user: PropTypes.instanceOf(UserStore).isRequired, | ||
175 | }).isRequired, | 171 | }).isRequired, |
176 | actions: PropTypes.shape({ | 172 | actions: PropTypes.shape({ |
177 | service: PropTypes.shape({ | 173 | service: PropTypes.shape({ |
diff --git a/src/features/todos/actions.js b/src/features/todos/actions.js new file mode 100644 index 000000000..673ce8531 --- /dev/null +++ b/src/features/todos/actions.js | |||
@@ -0,0 +1,10 @@ | |||
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 | }, PropTypes.checkPropTypes); | ||
9 | |||
10 | export default todoActions; | ||
diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index ca0b94ea1..1d99b9388 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js | |||
@@ -8,15 +8,26 @@ import * as environment from '../../../environment'; | |||
8 | const styles = theme => ({ | 8 | const styles = theme => ({ |
9 | root: { | 9 | root: { |
10 | background: theme.colorBackground, | 10 | background: theme.colorBackground, |
11 | height: '100%', | 11 | position: 'relative', |
12 | width: 300, | ||
13 | position: 'absolute', | ||
14 | top: 0, | ||
15 | right: -300, | ||
16 | }, | 12 | }, |
17 | webview: { | 13 | webview: { |
18 | height: '100%', | 14 | height: '100%', |
19 | }, | 15 | }, |
16 | resizeHandler: { | ||
17 | position: 'absolute', | ||
18 | left: 0, | ||
19 | marginLeft: -5, | ||
20 | width: 10, | ||
21 | zIndex: 400, | ||
22 | cursor: 'col-resize', | ||
23 | }, | ||
24 | dragIndicator: { | ||
25 | position: 'absolute', | ||
26 | left: 0, | ||
27 | width: 5, | ||
28 | zIndex: 400, | ||
29 | background: theme.todos.dragIndicator.background, | ||
30 | }, | ||
20 | }); | 31 | }); |
21 | 32 | ||
22 | @injectSheet(styles) @observer | 33 | @injectSheet(styles) @observer |
@@ -24,17 +35,113 @@ class TodosWebview extends Component { | |||
24 | static propTypes = { | 35 | static propTypes = { |
25 | classes: PropTypes.object.isRequired, | 36 | classes: PropTypes.object.isRequired, |
26 | authToken: PropTypes.string.isRequired, | 37 | authToken: PropTypes.string.isRequired, |
38 | resize: PropTypes.func.isRequired, | ||
39 | width: PropTypes.number.isRequired, | ||
40 | minWidth: PropTypes.number.isRequired, | ||
27 | }; | 41 | }; |
28 | 42 | ||
43 | state = { | ||
44 | isDragging: false, | ||
45 | width: 300, | ||
46 | } | ||
47 | |||
48 | componentWillMount() { | ||
49 | const { width } = this.props; | ||
50 | |||
51 | this.setState({ | ||
52 | width, | ||
53 | }); | ||
54 | } | ||
55 | |||
56 | componentDidMount() { | ||
57 | this.node.addEventListener('mousemove', this.resizePanel.bind(this)); | ||
58 | this.node.addEventListener('mouseup', this.stopResize.bind(this)); | ||
59 | this.node.addEventListener('mouseleave', this.stopResize.bind(this)); | ||
60 | } | ||
61 | |||
62 | startResize = (event) => { | ||
63 | this.setState({ | ||
64 | isDragging: true, | ||
65 | initialPos: event.clientX, | ||
66 | delta: 0, | ||
67 | }); | ||
68 | } | ||
69 | |||
70 | resizePanel(e) { | ||
71 | const { minWidth } = this.props; | ||
72 | |||
73 | const { | ||
74 | isDragging, | ||
75 | initialPos, | ||
76 | } = this.state; | ||
77 | |||
78 | if (isDragging && Math.abs(e.clientX - window.innerWidth) > minWidth) { | ||
79 | const delta = e.clientX - initialPos; | ||
80 | |||
81 | this.setState({ | ||
82 | delta, | ||
83 | }); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | stopResize() { | ||
88 | const { | ||
89 | resize, | ||
90 | minWidth, | ||
91 | } = this.props; | ||
92 | |||
93 | const { | ||
94 | isDragging, | ||
95 | delta, | ||
96 | width, | ||
97 | } = this.state; | ||
98 | |||
99 | if (isDragging) { | ||
100 | let newWidth = width + (delta < 0 ? Math.abs(delta) : -Math.abs(delta)); | ||
101 | |||
102 | if (newWidth < minWidth) { | ||
103 | newWidth = minWidth; | ||
104 | } | ||
105 | |||
106 | this.setState({ | ||
107 | isDragging: false, | ||
108 | delta: 0, | ||
109 | width: newWidth, | ||
110 | }); | ||
111 | |||
112 | resize(newWidth); | ||
113 | } | ||
114 | } | ||
115 | |||
29 | render() { | 116 | render() { |
30 | const { authToken, classes } = this.props; | 117 | const { authToken, classes } = this.props; |
118 | const { width, delta, isDragging } = this.state; | ||
119 | |||
31 | return ( | 120 | return ( |
32 | <div className={classes.root}> | 121 | <> |
33 | <Webview | 122 | <div |
34 | className={classes.webview} | 123 | className={classes.root} |
35 | src={`${environment.TODOS_FRONTEND}?authToken=${authToken}`} | 124 | style={{ width }} |
36 | /> | 125 | onMouseUp={() => this.stopResize()} |
37 | </div> | 126 | ref={(node) => { this.node = node; }} |
127 | > | ||
128 | <div | ||
129 | className={classes.resizeHandler} | ||
130 | style={Object.assign({ left: delta }, isDragging ? { width: 600, marginLeft: -200 } : {})} // This hack is required as resizing with webviews beneath behaves quite bad | ||
131 | onMouseDown={e => this.startResize(e)} | ||
132 | /> | ||
133 | {isDragging && ( | ||
134 | <div | ||
135 | className={classes.dragIndicator} | ||
136 | style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad | ||
137 | /> | ||
138 | )} | ||
139 | <Webview | ||
140 | className={classes.webview} | ||
141 | src={`${environment.TODOS_FRONTEND}?authToken=${authToken}`} | ||
142 | /> | ||
143 | </div> | ||
144 | </> | ||
38 | ); | 145 | ); |
39 | } | 146 | } |
40 | } | 147 | } |
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js new file mode 100644 index 000000000..0759c22db --- /dev/null +++ b/src/features/todos/containers/TodosScreen.js | |||
@@ -0,0 +1,45 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import { inject, observer } from 'mobx-react'; | ||
3 | import PropTypes from 'prop-types'; | ||
4 | |||
5 | import TodosWebview from '../components/TodosWebview'; | ||
6 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; | ||
7 | import UserStore from '../../../stores/UserStore'; | ||
8 | import TodoStore from '../store'; | ||
9 | import { TODOS_MIN_WIDTH } from '..'; | ||
10 | |||
11 | @inject('stores', 'actions') @observer | ||
12 | class TodosScreen extends Component { | ||
13 | static propTypes = { | ||
14 | stores: PropTypes.shape({ | ||
15 | user: PropTypes.instanceOf(UserStore).isRequired, | ||
16 | todos: PropTypes.instanceOf(TodoStore).isRequired, | ||
17 | }).isRequired, | ||
18 | actions: PropTypes.shape({ | ||
19 | todos: PropTypes.shape({ | ||
20 | resize: PropTypes.func.isRequired, | ||
21 | }), | ||
22 | }).isRequired, | ||
23 | }; | ||
24 | |||
25 | render() { | ||
26 | const { stores, actions } = this.props; | ||
27 | |||
28 | if (!stores.todos || !stores.todos.isFeatureActive) { | ||
29 | return null; | ||
30 | } | ||
31 | |||
32 | return ( | ||
33 | <ErrorBoundary> | ||
34 | <TodosWebview | ||
35 | authToken={stores.user.authToken} | ||
36 | width={stores.todos.width} | ||
37 | minWidth={TODOS_MIN_WIDTH} | ||
38 | resize={width => actions.todos.resize({ width })} | ||
39 | /> | ||
40 | </ErrorBoundary> | ||
41 | ); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | export default TodosScreen; | ||
diff --git a/src/features/todos/index.js b/src/features/todos/index.js new file mode 100644 index 000000000..0dfd35c78 --- /dev/null +++ b/src/features/todos/index.js | |||
@@ -0,0 +1,33 @@ | |||
1 | import { reaction } from 'mobx'; | ||
2 | import TodoStore from './store'; | ||
3 | |||
4 | const debug = require('debug')('Franz:feature:todos'); | ||
5 | |||
6 | export const GA_CATEGORY_TODOS = 'Todos'; | ||
7 | |||
8 | export const DEFAULT_TODOS_WIDTH = 300; | ||
9 | export const TODOS_MIN_WIDTH = 200; | ||
10 | |||
11 | export const todoStore = new TodoStore(); | ||
12 | |||
13 | export default function initTodos(stores, actions) { | ||
14 | stores.todos = todoStore; | ||
15 | const { features } = stores; | ||
16 | |||
17 | // Toggle todos feature | ||
18 | reaction( | ||
19 | () => features.features.isTodosEnabled, | ||
20 | (isEnabled) => { | ||
21 | if (isEnabled) { | ||
22 | debug('Initializing `todos` feature'); | ||
23 | todoStore.start(stores, actions); | ||
24 | } else if (todoStore.isFeatureActive) { | ||
25 | debug('Disabling `todos` feature'); | ||
26 | todoStore.stop(); | ||
27 | } | ||
28 | }, | ||
29 | { | ||
30 | fireImmediately: true, | ||
31 | }, | ||
32 | ); | ||
33 | } | ||
diff --git a/src/features/todos/store.js b/src/features/todos/store.js new file mode 100644 index 000000000..e7e13b37f --- /dev/null +++ b/src/features/todos/store.js | |||
@@ -0,0 +1,86 @@ | |||
1 | import { | ||
2 | computed, | ||
3 | action, | ||
4 | observable, | ||
5 | } from 'mobx'; | ||
6 | import localStorage from 'mobx-localstorage'; | ||
7 | |||
8 | import { todoActions } from './actions'; | ||
9 | import { FeatureStore } from '../utils/FeatureStore'; | ||
10 | import { createReactions } from '../../stores/lib/Reaction'; | ||
11 | import { createActionBindings } from '../utils/ActionBinding'; | ||
12 | import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH } from '.'; | ||
13 | |||
14 | const debug = require('debug')('Franz:feature:todos:store'); | ||
15 | |||
16 | export default class TodoStore extends FeatureStore { | ||
17 | @observable isFeatureEnabled = false; | ||
18 | |||
19 | @observable isFeatureActive = false; | ||
20 | |||
21 | @computed get width() { | ||
22 | const width = this.settings.width || DEFAULT_TODOS_WIDTH; | ||
23 | |||
24 | return width < TODOS_MIN_WIDTH ? TODOS_MIN_WIDTH : width; | ||
25 | } | ||
26 | |||
27 | @computed get settings() { | ||
28 | return localStorage.getItem('todos') || {}; | ||
29 | } | ||
30 | |||
31 | // ========== PUBLIC API ========= // | ||
32 | |||
33 | @action start(stores, actions) { | ||
34 | debug('TodoStore::start'); | ||
35 | this.stores = stores; | ||
36 | this.actions = actions; | ||
37 | |||
38 | // ACTIONS | ||
39 | |||
40 | this._registerActions(createActionBindings([ | ||
41 | [todoActions.resize, this._resize], | ||
42 | ])); | ||
43 | |||
44 | // REACTIONS | ||
45 | |||
46 | this._allReactions = createReactions([ | ||
47 | this._setFeatureEnabledReaction, | ||
48 | ]); | ||
49 | |||
50 | this._registerReactions(this._allReactions); | ||
51 | |||
52 | this.isFeatureActive = true; | ||
53 | } | ||
54 | |||
55 | @action stop() { | ||
56 | super.stop(); | ||
57 | debug('TodoStore::stop'); | ||
58 | this.reset(); | ||
59 | this.isFeatureActive = false; | ||
60 | } | ||
61 | |||
62 | // ========== PRIVATE METHODS ========= // | ||
63 | |||
64 | _updateSettings = (changes) => { | ||
65 | localStorage.setItem('todos', { | ||
66 | ...this.settings, | ||
67 | ...changes, | ||
68 | }); | ||
69 | }; | ||
70 | |||
71 | // Actions | ||
72 | |||
73 | @action _resize = ({ width }) => { | ||
74 | this._updateSettings({ | ||
75 | width, | ||
76 | }); | ||
77 | }; | ||
78 | |||
79 | // Reactions | ||
80 | |||
81 | _setFeatureEnabledReaction = () => { | ||
82 | const { isTodosEnabled } = this.stores.features.features; | ||
83 | |||
84 | this.isFeatureEnabled = isTodosEnabled; | ||
85 | }; | ||
86 | } | ||
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js index e7832088b..35a050c67 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js | |||
@@ -16,6 +16,7 @@ import workspaces from '../features/workspaces'; | |||
16 | import shareFranz from '../features/shareFranz'; | 16 | import shareFranz from '../features/shareFranz'; |
17 | import announcements from '../features/announcements'; | 17 | import announcements from '../features/announcements'; |
18 | import settingsWS from '../features/settingsWS'; | 18 | import settingsWS from '../features/settingsWS'; |
19 | import todos from '../features/todos'; | ||
19 | 20 | ||
20 | import { DEFAULT_FEATURES_CONFIG } from '../config'; | 21 | import { DEFAULT_FEATURES_CONFIG } from '../config'; |
21 | 22 | ||
@@ -75,5 +76,6 @@ export default class FeaturesStore extends Store { | |||
75 | shareFranz(this.stores, this.actions); | 76 | shareFranz(this.stores, this.actions); |
76 | announcements(this.stores, this.actions); | 77 | announcements(this.stores, this.actions); |
77 | settingsWS(this.stores, this.actions); | 78 | settingsWS(this.stores, this.actions); |
79 | todos(this.stores, this.actions); | ||
78 | } | 80 | } |
79 | } | 81 | } |
diff --git a/src/styles/layout.scss b/src/styles/layout.scss index 739082445..10027da60 100644 --- a/src/styles/layout.scss +++ b/src/styles/layout.scss | |||
@@ -37,10 +37,15 @@ html { overflow: hidden; } | |||
37 | 37 | ||
38 | .app__content { | 38 | .app__content { |
39 | display: flex; | 39 | display: flex; |
40 | width: calc(100% + 300px); | ||
41 | } | ||
42 | |||
43 | .app__main-content { | ||
44 | display: flex; | ||
45 | width: 100%; | ||
40 | } | 46 | } |
41 | 47 | ||
42 | .app__service { | 48 | .app__service { |
43 | // position: relative; | ||
44 | display: flex; | 49 | display: flex; |
45 | flex: 1; | 50 | flex: 1; |
46 | flex-direction: column; | 51 | flex-direction: column; |