aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package-lock.json2
-rw-r--r--packages/theme/src/themes/default/index.ts7
-rw-r--r--src/actions/index.js2
-rw-r--r--src/components/layout/AppLayout.js15
-rw-r--r--src/config.js4
-rw-r--r--src/environment.js8
-rw-r--r--src/features/todos/actions.js10
-rw-r--r--src/features/todos/components/TodosWebview.js149
-rw-r--r--src/features/todos/containers/TodosScreen.js45
-rw-r--r--src/features/todos/index.js33
-rw-r--r--src/features/todos/store.js86
-rw-r--r--src/i18n/locales/defaultMessages.json12
-rw-r--r--src/i18n/messages/src/components/layout/AppLayout.json12
-rw-r--r--src/stores/FeaturesStore.js2
-rw-r--r--src/styles/layout.scss14
15 files changed, 373 insertions, 28 deletions
diff --git a/package-lock.json b/package-lock.json
index b4d86c5e1..17513869a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "franz", 2 "name": "franz",
3 "version": "5.2.0-beta.3", 3 "version": "5.2.0",
4 "lockfileVersion": 1, 4 "lockfileVersion": 1,
5 "requires": true, 5 "requires": true,
6 "dependencies": { 6 "dependencies": {
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
212export 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';
13import requests from './requests'; 13import requests from './requests';
14import announcements from '../features/announcements/actions'; 14import announcements from '../features/announcements/actions';
15import workspaces from '../features/workspaces/actions'; 15import workspaces from '../features/workspaces/actions';
16import todos from '../features/todos/actions';
16 17
17const actions = Object.assign({}, { 18const 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 ebb9849ea..dbf7d3c21 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -17,6 +17,7 @@ import { isWindows } from '../../environment';
17import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; 17import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator';
18import { workspaceStore } from '../../features/workspaces'; 18import { workspaceStore } from '../../features/workspaces';
19import AppUpdateInfoBar from '../AppUpdateInfoBar'; 19import AppUpdateInfoBar from '../AppUpdateInfoBar';
20import Todos from '../../features/todos/containers/TodosScreen';
20 21
21function createMarkup(HTMLString) { 22function createMarkup(HTMLString) {
22 return { __html: HTMLString }; 23 return { __html: HTMLString };
@@ -39,7 +40,8 @@ const messages = defineMessages({
39 40
40const styles = theme => ({ 41const styles = theme => ({
41 appContent: { 42 appContent: {
42 width: `calc(100% + ${theme.workspaces.drawer.width}px)`, 43 // width: `calc(100% + ${theme.workspaces.drawer.width}px)`,
44 width: '100%',
43 transition: 'transform 0.5s ease', 45 transition: 'transform 0.5s ease',
44 transform() { 46 transform() {
45 return workspaceStore.isWorkspaceDrawerOpen ? 'translateX(0)' : `translateX(-${theme.workspaces.drawer.width}px)`; 47 return workspaceStore.isWorkspaceDrawerOpen ? 'translateX(0)' : `translateX(-${theme.workspaces.drawer.width}px)`;
@@ -57,7 +59,6 @@ class AppLayout extends Component {
57 services: PropTypes.element.isRequired, 59 services: PropTypes.element.isRequired,
58 children: PropTypes.element, 60 children: PropTypes.element,
59 news: MobxPropTypes.arrayOrObservableArray.isRequired, 61 news: MobxPropTypes.arrayOrObservableArray.isRequired,
60 // isOnline: PropTypes.bool.isRequired,
61 showServicesUpdatedInfoBar: PropTypes.bool.isRequired, 62 showServicesUpdatedInfoBar: PropTypes.bool.isRequired,
62 appUpdateIsDownloaded: PropTypes.bool.isRequired, 63 appUpdateIsDownloaded: PropTypes.bool.isRequired,
63 nextAppReleaseVersion: PropTypes.string, 64 nextAppReleaseVersion: PropTypes.string,
@@ -125,15 +126,6 @@ class AppLayout extends Component {
125 <span dangerouslySetInnerHTML={createMarkup(item.message)} /> 126 <span dangerouslySetInnerHTML={createMarkup(item.message)} />
126 </InfoBar> 127 </InfoBar>
127 ))} 128 ))}
128 {/* {!isOnline && (
129 <InfoBar
130 type="danger"
131 sticky
132 >
133 <span className="mdi mdi-flash" />
134 {intl.formatMessage(globalMessages.notConnectedToTheInternet)}
135 </InfoBar>
136 )} */}
137 {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( 129 {!areRequiredRequestsSuccessful && showRequiredRequestsError && (
138 <InfoBar 130 <InfoBar
139 type="danger" 131 type="danger"
@@ -169,6 +161,7 @@ class AppLayout extends Component {
169 {services} 161 {services}
170 {children} 162 {children}
171 </div> 163 </div>
164 <Todos />
172 </div> 165 </div>
173 </div> 166 </div>
174 </ErrorBoundary> 167 </ErrorBoundary>
diff --git a/src/config.js b/src/config.js
index 5bc318545..6968f8500 100644
--- a/src/config.js
+++ b/src/config.js
@@ -24,6 +24,10 @@ export const LIVE_API_WEBSITE = 'https://meetfranz.com';
24 24
25export const STATS_API = 'https://stats.franzinfra.com'; 25export const STATS_API = 'https://stats.franzinfra.com';
26 26
27export const LOCAL_TODOS_FRONTEND_URL = 'http://localhost:4000';
28export const PRODUCTION_TODOS_FRONTEND_URL = 'https://franz-todos.netlify.com';
29export const DEVELOPMENT_TODOS_FRONTEND_URL = 'https://development--franz-todos.netlify.com';
30
27export const GA_ID = !isDevMode ? 'UA-74126766-10' : 'UA-74126766-12'; 31export const GA_ID = !isDevMode ? 'UA-74126766-10' : 'UA-74126766-12';
28 32
29export const DEFAULT_APP_SETTINGS = { 33export const DEFAULT_APP_SETTINGS = {
diff --git a/src/environment.js b/src/environment.js
index ae7a67e4d..707449e09 100644
--- a/src/environment.js
+++ b/src/environment.js
@@ -10,6 +10,9 @@ import {
10 LIVE_WS_API, 10 LIVE_WS_API,
11 LOCAL_WS_API, 11 LOCAL_WS_API,
12 DEV_WS_API, 12 DEV_WS_API,
13 LOCAL_TODOS_FRONTEND_URL,
14 PRODUCTION_TODOS_FRONTEND_URL,
15 DEVELOPMENT_TODOS_FRONTEND_URL,
13} from './config'; 16} from './config';
14 17
15export const isDevMode = isDev; 18export const isDevMode = isDev;
@@ -31,21 +34,26 @@ export const cmdKey = isMac ? 'Cmd' : 'Ctrl';
31let api; 34let api;
32let wsApi; 35let wsApi;
33let web; 36let web;
37let todos;
34if (!isDevMode || (isDevMode && useLiveAPI)) { 38if (!isDevMode || (isDevMode && useLiveAPI)) {
35 api = LIVE_API; 39 api = LIVE_API;
36 wsApi = LIVE_WS_API; 40 wsApi = LIVE_WS_API;
37 web = LIVE_API_WEBSITE; 41 web = LIVE_API_WEBSITE;
42 todos = PRODUCTION_TODOS_FRONTEND_URL;
38} else if (isDevMode && useLocalAPI) { 43} else if (isDevMode && useLocalAPI) {
39 api = LOCAL_API; 44 api = LOCAL_API;
40 wsApi = LOCAL_WS_API; 45 wsApi = LOCAL_WS_API;
41 web = LOCAL_API_WEBSITE; 46 web = LOCAL_API_WEBSITE;
47 todos = LOCAL_TODOS_FRONTEND_URL;
42} else { 48} else {
43 api = DEV_API; 49 api = DEV_API;
44 wsApi = DEV_WS_API; 50 wsApi = DEV_WS_API;
45 web = DEV_API_WEBSITE; 51 web = DEV_API_WEBSITE;
52 todos = DEVELOPMENT_TODOS_FRONTEND_URL;
46} 53}
47 54
48export const API = api; 55export const API = api;
49export const API_VERSION = 'v1'; 56export const API_VERSION = 'v1';
50export const WS_API = wsApi; 57export const WS_API = wsApi;
51export const WEBSITE = web; 58export const WEBSITE = web;
59export const TODOS_FRONTEND = todos;
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 @@
1import PropTypes from 'prop-types';
2import { createActionsFromDefinitions } from '../../actions/lib/actions';
3
4export const todoActions = createActionsFromDefinitions({
5 resize: {
6 width: PropTypes.number.isRequired,
7 },
8}, PropTypes.checkPropTypes);
9
10export default todoActions;
diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js
new file mode 100644
index 000000000..1d99b9388
--- /dev/null
+++ b/src/features/todos/components/TodosWebview.js
@@ -0,0 +1,149 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss';
5import Webview from 'react-electron-web-view';
6import * as environment from '../../../environment';
7
8const styles = theme => ({
9 root: {
10 background: theme.colorBackground,
11 position: 'relative',
12 },
13 webview: {
14 height: '100%',
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 },
31});
32
33@injectSheet(styles) @observer
34class TodosWebview extends Component {
35 static propTypes = {
36 classes: PropTypes.object.isRequired,
37 authToken: PropTypes.string.isRequired,
38 resize: PropTypes.func.isRequired,
39 width: PropTypes.number.isRequired,
40 minWidth: PropTypes.number.isRequired,
41 };
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
116 render() {
117 const { authToken, classes } = this.props;
118 const { width, delta, isDragging } = this.state;
119
120 return (
121 <>
122 <div
123 className={classes.root}
124 style={{ width }}
125 onMouseUp={() => this.stopResize()}
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 </>
145 );
146 }
147}
148
149export default TodosWebview;
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 @@
1import React, { Component } from 'react';
2import { inject, observer } from 'mobx-react';
3import PropTypes from 'prop-types';
4
5import TodosWebview from '../components/TodosWebview';
6import ErrorBoundary from '../../../components/util/ErrorBoundary';
7import UserStore from '../../../stores/UserStore';
8import TodoStore from '../store';
9import { TODOS_MIN_WIDTH } from '..';
10
11@inject('stores', 'actions') @observer
12class 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
45export 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 @@
1import { reaction } from 'mobx';
2import TodoStore from './store';
3
4const debug = require('debug')('Franz:feature:todos');
5
6export const GA_CATEGORY_TODOS = 'Todos';
7
8export const DEFAULT_TODOS_WIDTH = 300;
9export const TODOS_MIN_WIDTH = 200;
10
11export const todoStore = new TodoStore();
12
13export 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 @@
1import {
2 computed,
3 action,
4 observable,
5} from 'mobx';
6import localStorage from 'mobx-localstorage';
7
8import { todoActions } from './actions';
9import { FeatureStore } from '../utils/FeatureStore';
10import { createReactions } from '../../stores/lib/Reaction';
11import { createActionBindings } from '../utils/ActionBinding';
12import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH } from '.';
13
14const debug = require('debug')('Franz:feature:todos:store');
15
16export 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/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json
index eca3062c2..015987b8a 100644
--- a/src/i18n/locales/defaultMessages.json
+++ b/src/i18n/locales/defaultMessages.json
@@ -669,39 +669,39 @@
669 "defaultMessage": "!!!Your services have been updated.", 669 "defaultMessage": "!!!Your services have been updated.",
670 "end": { 670 "end": {
671 "column": 3, 671 "column": 3,
672 "line": 29 672 "line": 30
673 }, 673 },
674 "file": "src/components/layout/AppLayout.js", 674 "file": "src/components/layout/AppLayout.js",
675 "id": "infobar.servicesUpdated", 675 "id": "infobar.servicesUpdated",
676 "start": { 676 "start": {
677 "column": 19, 677 "column": 19,
678 "line": 26 678 "line": 27
679 } 679 }
680 }, 680 },
681 { 681 {
682 "defaultMessage": "!!!Reload services", 682 "defaultMessage": "!!!Reload services",
683 "end": { 683 "end": {
684 "column": 3, 684 "column": 3,
685 "line": 33 685 "line": 34
686 }, 686 },
687 "file": "src/components/layout/AppLayout.js", 687 "file": "src/components/layout/AppLayout.js",
688 "id": "infobar.buttonReloadServices", 688 "id": "infobar.buttonReloadServices",
689 "start": { 689 "start": {
690 "column": 24, 690 "column": 24,
691 "line": 30 691 "line": 31
692 } 692 }
693 }, 693 },
694 { 694 {
695 "defaultMessage": "!!!Could not load services and user information", 695 "defaultMessage": "!!!Could not load services and user information",
696 "end": { 696 "end": {
697 "column": 3, 697 "column": 3,
698 "line": 37 698 "line": 38
699 }, 699 },
700 "file": "src/components/layout/AppLayout.js", 700 "file": "src/components/layout/AppLayout.js",
701 "id": "infobar.requiredRequestsFailed", 701 "id": "infobar.requiredRequestsFailed",
702 "start": { 702 "start": {
703 "column": 26, 703 "column": 26,
704 "line": 34 704 "line": 35
705 } 705 }
706 } 706 }
707 ], 707 ],
diff --git a/src/i18n/messages/src/components/layout/AppLayout.json b/src/i18n/messages/src/components/layout/AppLayout.json
index 190c5dff7..b71889155 100644
--- a/src/i18n/messages/src/components/layout/AppLayout.json
+++ b/src/i18n/messages/src/components/layout/AppLayout.json
@@ -4,11 +4,11 @@
4 "defaultMessage": "!!!Your services have been updated.", 4 "defaultMessage": "!!!Your services have been updated.",
5 "file": "src/components/layout/AppLayout.js", 5 "file": "src/components/layout/AppLayout.js",
6 "start": { 6 "start": {
7 "line": 26, 7 "line": 27,
8 "column": 19 8 "column": 19
9 }, 9 },
10 "end": { 10 "end": {
11 "line": 29, 11 "line": 30,
12 "column": 3 12 "column": 3
13 } 13 }
14 }, 14 },
@@ -17,11 +17,11 @@
17 "defaultMessage": "!!!Reload services", 17 "defaultMessage": "!!!Reload services",
18 "file": "src/components/layout/AppLayout.js", 18 "file": "src/components/layout/AppLayout.js",
19 "start": { 19 "start": {
20 "line": 30, 20 "line": 31,
21 "column": 24 21 "column": 24
22 }, 22 },
23 "end": { 23 "end": {
24 "line": 33, 24 "line": 34,
25 "column": 3 25 "column": 3
26 } 26 }
27 }, 27 },
@@ -30,11 +30,11 @@
30 "defaultMessage": "!!!Could not load services and user information", 30 "defaultMessage": "!!!Could not load services and user information",
31 "file": "src/components/layout/AppLayout.js", 31 "file": "src/components/layout/AppLayout.js",
32 "start": { 32 "start": {
33 "line": 34, 33 "line": 35,
34 "column": 26 34 "column": 26
35 }, 35 },
36 "end": { 36 "end": {
37 "line": 37, 37 "line": 38,
38 "column": 3 38 "column": 3
39 } 39 }
40 } 40 }
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';
16import shareFranz from '../features/shareFranz'; 16import shareFranz from '../features/shareFranz';
17import announcements from '../features/announcements'; 17import announcements from '../features/announcements';
18import settingsWS from '../features/settingsWS'; 18import settingsWS from '../features/settingsWS';
19import todos from '../features/todos';
19 20
20import { DEFAULT_FEATURES_CONFIG } from '../config'; 21import { 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 9f226b61c..10027da60 100644
--- a/src/styles/layout.scss
+++ b/src/styles/layout.scss
@@ -33,13 +33,19 @@ html { overflow: hidden; }
33} 33}
34 34
35.app { 35.app {
36 display: flex; 36 //display: flex;
37 flex-direction: column;
38 37
39 .app__content { display: flex; } 38 .app__content {
39 display: flex;
40 width: calc(100% + 300px);
41 }
42
43 .app__main-content {
44 display: flex;
45 width: 100%;
46 }
40 47
41 .app__service { 48 .app__service {
42 // position: relative;
43 display: flex; 49 display: flex;
44 flex: 1; 50 flex: 1;
45 flex-direction: column; 51 flex-direction: column;