From d7ed456a7b6f73e046ba3a2ef38eb21f82f06ca4 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Tue, 30 Jul 2019 11:41:54 +0200 Subject: Make todo layer resizable --- src/stores/FeaturesStore.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/stores') 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'; import shareFranz from '../features/shareFranz'; import announcements from '../features/announcements'; import settingsWS from '../features/settingsWS'; +import todos from '../features/todos'; import { DEFAULT_FEATURES_CONFIG } from '../config'; @@ -75,5 +76,6 @@ export default class FeaturesStore extends Store { shareFranz(this.stores, this.actions); announcements(this.stores, this.actions); settingsWS(this.stores, this.actions); + todos(this.stores, this.actions); } } -- cgit v1.2.3-54-g00ecf From bd49d59008d64db13e3f37277ec873a3a464ef9e Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Wed, 31 Jul 2019 17:08:29 +0200 Subject: MVP for service <-> todos integration --- src/features/todos/actions.js | 11 ++ src/features/todos/components/TodosWebview.js | 20 +++- src/features/todos/containers/TodosScreen.js | 3 + src/features/todos/preload.js | 21 ++++ src/features/todos/store.js | 29 +++++ src/i18n/messages/src/lib/Menu.json | 157 ++++++++++++++------------ src/index.html | 11 +- src/lib/Menu.js | 16 +++ src/stores/ServicesStore.js | 3 + src/webview/contextMenu.js | 17 +++ 10 files changed, 210 insertions(+), 78 deletions(-) create mode 100644 src/features/todos/preload.js (limited to 'src/stores') diff --git a/src/features/todos/actions.js b/src/features/todos/actions.js index 673ce8531..696568f7f 100644 --- a/src/features/todos/actions.js +++ b/src/features/todos/actions.js @@ -5,6 +5,17 @@ export const todoActions = createActionsFromDefinitions({ resize: { width: PropTypes.number.isRequired, }, + setTodosWebview: { + webview: PropTypes.element.isRequired, + }, + handleHostMessage: { + action: PropTypes.string.isRequired, + data: PropTypes.object, + }, + handleClientMessage: { + action: PropTypes.string.isRequired, + data: PropTypes.object, + }, }, PropTypes.checkPropTypes); export default todoActions; diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index 1d99b9388..1f4730094 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js @@ -35,6 +35,8 @@ class TodosWebview extends Component { static propTypes = { classes: PropTypes.object.isRequired, authToken: PropTypes.string.isRequired, + handleClientMessage: PropTypes.func.isRequired, + setTodosWebview: PropTypes.func.isRequired, resize: PropTypes.func.isRequired, width: PropTypes.number.isRequired, minWidth: PropTypes.number.isRequired, @@ -43,7 +45,7 @@ class TodosWebview extends Component { state = { isDragging: false, width: 300, - } + }; componentWillMount() { const { width } = this.props; @@ -65,7 +67,7 @@ class TodosWebview extends Component { initialPos: event.clientX, delta: 0, }); - } + }; resizePanel(e) { const { minWidth } = this.props; @@ -113,10 +115,15 @@ class TodosWebview extends Component { } } + startListeningToIpcMessages() { + const { handleClientMessage } = this.props; + if (!this.webview) return; + this.webview.addEventListener('ipc-message', e => handleClientMessage(e.args[0])); + } + render() { const { authToken, classes } = this.props; const { width, delta, isDragging } = this.state; - return ( <>
{ + this.props.setTodosWebview(this.webview); + this.startListeningToIpcMessages(); + }} + partition="persist:todos" + preload="./features/todos/preload.js" + ref={(webview) => { this.webview = webview ? webview.view : null; }} src={`${environment.TODOS_FRONTEND}?authToken=${authToken}`} />
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index 0759c22db..5b7c4531b 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js @@ -18,6 +18,7 @@ class TodosScreen extends Component { actions: PropTypes.shape({ todos: PropTypes.shape({ resize: PropTypes.func.isRequired, + handleIPCMessage: PropTypes.func.isRequired, }), }).isRequired, }; @@ -33,6 +34,8 @@ class TodosScreen extends Component { actions.todos.setTodosWebview({ webview })} width={stores.todos.width} minWidth={TODOS_MIN_WIDTH} resize={width => actions.todos.resize({ width })} diff --git a/src/features/todos/preload.js b/src/features/todos/preload.js new file mode 100644 index 000000000..533c9aea3 --- /dev/null +++ b/src/features/todos/preload.js @@ -0,0 +1,21 @@ +import { ipcRenderer } from 'electron'; + +const debug = require('debug')('Franz:feature:todos:preload'); + +debug('Preloading Todos Webview'); + +let hostMessageListener = () => {}; + +window.franz = { + onInitialize(ipcHostMessageListener) { + hostMessageListener = ipcHostMessageListener; + }, + sendToHost(message) { + ipcRenderer.sendToHost('clientMessage', message); + }, +}; + +ipcRenderer.on('hostMessage', (event, message) => { + debug('Received host message', event, message); + hostMessageListener(message); +}); diff --git a/src/features/todos/store.js b/src/features/todos/store.js index e7e13b37f..737902946 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -18,6 +18,8 @@ export default class TodoStore extends FeatureStore { @observable isFeatureActive = false; + webview = null; + @computed get width() { const width = this.settings.width || DEFAULT_TODOS_WIDTH; @@ -39,6 +41,9 @@ export default class TodoStore extends FeatureStore { this._registerActions(createActionBindings([ [todoActions.resize, this._resize], + [todoActions.setTodosWebview, this._setTodosWebview], + [todoActions.handleHostMessage, this._handleHostMessage], + [todoActions.handleClientMessage, this._handleClientMessage], ])); // REACTIONS @@ -76,6 +81,30 @@ export default class TodoStore extends FeatureStore { }); }; + @action _setTodosWebview = ({ webview }) => { + debug('_setTodosWebview', webview); + this.webview = webview; + }; + + @action _handleHostMessage = (message) => { + debug('_handleHostMessage', message); + if (message.action === 'create:todo') { + console.log(this.webview); + this.webview.send('hostMessage', message); + } + }; + + @action _handleClientMessage = (message) => { + debug('_handleClientMessage', message); + if (message.action === 'goToService') { + const { url, serviceId } = message.data; + if (url) { + this.stores.services.one(serviceId).webview.loadURL(url); + } + this.actions.service.setActive({ serviceId }); + } + }; + // Reactions _setFeatureEnabledReaction = () => { diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index 6f878cbd1..fa9509cbf 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -272,16 +272,29 @@ "column": 3 } }, + { + "id": "menu.view.toggleTodosDevTools", + "defaultMessage": "!!!Toggle Todos Developer Tools", + "file": "src/lib/Menu.js", + "start": { + "line": 99, + "column": 23 + }, + "end": { + "line": 102, + "column": 3 + } + }, { "id": "menu.view.toggleServiceDevTools", "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 99, + "line": 103, "column": 25 }, "end": { - "line": 102, + "line": 106, "column": 3 } }, @@ -290,11 +303,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 103, + "line": 107, "column": 17 }, "end": { - "line": 106, + "line": 110, "column": 3 } }, @@ -303,11 +316,11 @@ "defaultMessage": "!!!Reload Franz", "file": "src/lib/Menu.js", "start": { - "line": 107, + "line": 111, "column": 15 }, "end": { - "line": 110, + "line": 114, "column": 3 } }, @@ -316,11 +329,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 111, + "line": 115, "column": 12 }, "end": { - "line": 114, + "line": 118, "column": 3 } }, @@ -329,11 +342,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 115, + "line": 119, "column": 9 }, "end": { - "line": 118, + "line": 122, "column": 3 } }, @@ -342,11 +355,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 119, + "line": 123, "column": 13 }, "end": { - "line": 122, + "line": 126, "column": 3 } }, @@ -355,11 +368,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 123, + "line": 127, "column": 13 }, "end": { - "line": 126, + "line": 130, "column": 3 } }, @@ -368,11 +381,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 127, + "line": 131, "column": 11 }, "end": { - "line": 130, + "line": 134, "column": 3 } }, @@ -381,11 +394,11 @@ "defaultMessage": "!!!Copy Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 131, + "line": 135, "column": 13 }, "end": { - "line": 134, + "line": 138, "column": 3 } }, @@ -394,11 +407,11 @@ "defaultMessage": "!!!Franz Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 135, + "line": 139, "column": 27 }, "end": { - "line": 138, + "line": 142, "column": 3 } }, @@ -407,11 +420,11 @@ "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.", "file": "src/lib/Menu.js", "start": { - "line": 139, + "line": 143, "column": 23 }, "end": { - "line": 142, + "line": 146, "column": 3 } }, @@ -420,11 +433,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 143, + "line": 147, "column": 7 }, "end": { - "line": 146, + "line": 150, "column": 3 } }, @@ -433,11 +446,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 147, + "line": 151, "column": 11 }, "end": { - "line": 150, + "line": 154, "column": 3 } }, @@ -446,11 +459,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 151, + "line": 155, "column": 8 }, "end": { - "line": 154, + "line": 158, "column": 3 } }, @@ -459,11 +472,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 155, + "line": 159, "column": 8 }, "end": { - "line": 158, + "line": 162, "column": 3 } }, @@ -472,11 +485,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 159, + "line": 163, "column": 12 }, "end": { - "line": 162, + "line": 166, "column": 3 } }, @@ -485,11 +498,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 163, + "line": 167, "column": 10 }, "end": { - "line": 166, + "line": 170, "column": 3 } }, @@ -498,11 +511,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 167, + "line": 171, "column": 8 }, "end": { - "line": 170, + "line": 174, "column": 3 } }, @@ -511,11 +524,11 @@ "defaultMessage": "!!!About Franz", "file": "src/lib/Menu.js", "start": { - "line": 171, + "line": 175, "column": 9 }, "end": { - "line": 174, + "line": 178, "column": 3 } }, @@ -524,11 +537,11 @@ "defaultMessage": "!!!What's new?", "file": "src/lib/Menu.js", "start": { - "line": 175, + "line": 179, "column": 16 }, "end": { - "line": 178, + "line": 182, "column": 3 } }, @@ -537,11 +550,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 179, + "line": 183, "column": 12 }, "end": { - "line": 182, + "line": 186, "column": 3 } }, @@ -550,11 +563,11 @@ "defaultMessage": "!!!Check for updates", "file": "src/lib/Menu.js", "start": { - "line": 183, + "line": 187, "column": 19 }, "end": { - "line": 186, + "line": 190, "column": 3 } }, @@ -563,11 +576,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 187, + "line": 191, "column": 8 }, "end": { - "line": 190, + "line": 194, "column": 3 } }, @@ -576,11 +589,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 191, + "line": 195, "column": 14 }, "end": { - "line": 194, + "line": 198, "column": 3 } }, @@ -589,11 +602,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 195, + "line": 199, "column": 10 }, "end": { - "line": 198, + "line": 202, "column": 3 } }, @@ -602,11 +615,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 199, + "line": 203, "column": 8 }, "end": { - "line": 202, + "line": 206, "column": 3 } }, @@ -615,11 +628,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 203, + "line": 207, "column": 17 }, "end": { - "line": 206, + "line": 210, "column": 3 } }, @@ -628,11 +641,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 207, + "line": 211, "column": 19 }, "end": { - "line": 210, + "line": 214, "column": 3 } }, @@ -641,11 +654,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 211, + "line": 215, "column": 23 }, "end": { - "line": 214, + "line": 218, "column": 3 } }, @@ -654,11 +667,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 215, + "line": 219, "column": 24 }, "end": { - "line": 218, + "line": 222, "column": 3 } }, @@ -667,11 +680,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 219, + "line": 223, "column": 23 }, "end": { - "line": 222, + "line": 226, "column": 3 } }, @@ -680,11 +693,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 223, + "line": 227, "column": 27 }, "end": { - "line": 226, + "line": 230, "column": 3 } }, @@ -693,11 +706,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 227, + "line": 231, "column": 11 }, "end": { - "line": 230, + "line": 234, "column": 3 } }, @@ -706,11 +719,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 231, + "line": 235, "column": 13 }, "end": { - "line": 234, + "line": 238, "column": 3 } }, @@ -719,11 +732,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 235, + "line": 239, "column": 14 }, "end": { - "line": 238, + "line": 242, "column": 3 } }, @@ -732,11 +745,11 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 239, + "line": 243, "column": 20 }, "end": { - "line": 242, + "line": 246, "column": 3 } } diff --git a/src/index.html b/src/index.html index f29aa2686..198c1ab7b 100644 --- a/src/index.html +++ b/src/index.html @@ -35,11 +35,16 @@ const originalReloadBehaviour = window._onLiveReloadFileChanged; window._onLiveReloadFileChanged = (file) => { - if (!file.path.includes('/build/webview/') && !file.path.includes('/build/index.js') && !file.path.includes('/build/electron/')) { + const isTodoPreloadPath = file.path.includes('/build/features/todos/preload.js'); + if (!file.path.includes('/build/webview/') && !file.path.includes('/build/index.js') && !file.path.includes('/build/electron/') && !isTodoPreloadPath) { originalReloadBehaviour(file); } else { - if (file.path.includes('/build/webview/')) { - debug('Livereload: Reloading all webvies'); + if (isTodoPreloadPath) { + debug('Livereload: Reloading all webviews'); + const webview = document.querySelector('webview[partition="persist:todos"]'); + if (webview) webview.reload(); + } else if (file.path.includes('/build/webview/')) { + debug('Livereload: Reloading all webviews'); const webviews = document.querySelectorAll('webview').forEach(webview => webview.reload()); } else { debug('Livereload: skip reload as only main process files have changed'); diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 22d788918..9e491e151 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -96,6 +96,10 @@ const menuItems = defineMessages({ id: 'menu.view.toggleDevTools', defaultMessage: '!!!Toggle Developer Tools', }, + toggleTodosDevTools: { + id: 'menu.view.toggleTodosDevTools', + defaultMessage: '!!!Toggle Todos Developer Tools', + }, toggleServiceDevTools: { id: 'menu.view.toggleServiceDevTools', defaultMessage: '!!!Toggle Service Developer Tools', @@ -240,6 +244,7 @@ const menuItems = defineMessages({ id: 'menu.workspaces.defaultWorkspace', defaultMessage: '!!!Default', }, + }); function getActiveWebview() { @@ -620,6 +625,17 @@ export default class FranzMenu { enabled: this.stores.user.isLoggedIn && this.stores.services.enabled.length > 0, }); + if (this.stores.features.features.isTodosEnabled) { + tpl[1].submenu.push({ + label: intl.formatMessage(menuItems.toggleTodosDevTools), + accelerator: `${cmdKey}+Shift+Alt+O`, + click: () => { + const webview = document.querySelector('webview[partition="persist:todos"]'); + if (webview) webview.openDevTools(); + }, + }); + } + tpl[1].submenu.unshift({ label: intl.formatMessage(menuItems.reloadService), id: 'reloadService', // TODO: needed? diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 109ac5cd7..b13425249 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -440,6 +440,9 @@ export default class ServicesStore extends Store { redirect: false, }); } + } else if (channel === 'feature:todos') { + Object.assign(args[0].data, { serviceId }); + this.actions.todos.handleHostMessage(args[0]); } } diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js index a4a6ab899..663b1ebca 100644 --- a/src/webview/contextMenu.js +++ b/src/webview/contextMenu.js @@ -36,6 +36,23 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck // @adlk: we can't use roles here due to a bug with electron where electron.remote.webContents.getFocusedWebContents() returns the first webview in DOM instead of the focused one // Github issue creation is pending let menuTpl = [ + { + type: 'separator', + }, { + id: 'createTodo', + label: `Create todo: "${textSelection.length > 15 ? `${textSelection.slice(0, 15)}...` : textSelection}"`, + visible: hasText, + click() { + debug('Create todo from selected text', textSelection); + ipcRenderer.sendToHost('feature:todos', { + action: 'create:todo', + data: { + title: textSelection, + url: window.location.href, + }, + }); + }, + }, { type: 'separator', }, { -- cgit v1.2.3-54-g00ecf From 5818e579f4baf6326250ac8d94d225675b7d8165 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 1 Aug 2019 14:12:30 +0200 Subject: Fix eslint issues --- src/features/todos/actions.js | 2 +- src/features/todos/containers/TodosScreen.js | 23 ++++++++--------------- src/features/todos/index.js | 10 +++++----- src/stores/index.js | 2 ++ 4 files changed, 16 insertions(+), 21 deletions(-) (limited to 'src/stores') diff --git a/src/features/todos/actions.js b/src/features/todos/actions.js index 696568f7f..a6090a259 100644 --- a/src/features/todos/actions.js +++ b/src/features/todos/actions.js @@ -6,7 +6,7 @@ export const todoActions = createActionsFromDefinitions({ width: PropTypes.number.isRequired, }, setTodosWebview: { - webview: PropTypes.element.isRequired, + webview: PropTypes.instanceOf(Element).isRequired, }, handleHostMessage: { action: PropTypes.string.isRequired, diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index 5b7c4531b..2b81bd728 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js @@ -5,26 +5,19 @@ import PropTypes from 'prop-types'; import TodosWebview from '../components/TodosWebview'; import ErrorBoundary from '../../../components/util/ErrorBoundary'; import UserStore from '../../../stores/UserStore'; -import TodoStore from '../store'; -import { TODOS_MIN_WIDTH } from '..'; +import { TODOS_MIN_WIDTH, todosStore } from '..'; +import { todoActions } from '../actions'; -@inject('stores', 'actions') @observer +@inject('stores') @observer class TodosScreen extends Component { static propTypes = { stores: PropTypes.shape({ user: PropTypes.instanceOf(UserStore).isRequired, - todos: PropTypes.instanceOf(TodoStore).isRequired, - }).isRequired, - actions: PropTypes.shape({ - todos: PropTypes.shape({ - resize: PropTypes.func.isRequired, - handleIPCMessage: PropTypes.func.isRequired, - }), }).isRequired, }; render() { - const { stores, actions } = this.props; + const { stores } = this.props; if (!stores.todos || !stores.todos.isFeatureActive) { return null; @@ -34,11 +27,11 @@ class TodosScreen extends Component { actions.todos.setTodosWebview({ webview })} - width={stores.todos.width} + handleClientMessage={todoActions.handleClientMessage} + setTodosWebview={webview => todoActions.setTodosWebview({ webview })} + width={todosStore.width} minWidth={TODOS_MIN_WIDTH} - resize={width => actions.todos.resize({ width })} + resize={width => todoActions.resize({ width })} /> ); diff --git a/src/features/todos/index.js b/src/features/todos/index.js index 0dfd35c78..f741561d6 100644 --- a/src/features/todos/index.js +++ b/src/features/todos/index.js @@ -8,10 +8,10 @@ export const GA_CATEGORY_TODOS = 'Todos'; export const DEFAULT_TODOS_WIDTH = 300; export const TODOS_MIN_WIDTH = 200; -export const todoStore = new TodoStore(); +export const todosStore = new TodoStore(); export default function initTodos(stores, actions) { - stores.todos = todoStore; + stores.todos = todosStore; const { features } = stores; // Toggle todos feature @@ -20,10 +20,10 @@ export default function initTodos(stores, actions) { (isEnabled) => { if (isEnabled) { debug('Initializing `todos` feature'); - todoStore.start(stores, actions); - } else if (todoStore.isFeatureActive) { + todosStore.start(stores, actions); + } else if (todosStore.isFeatureActive) { debug('Disabling `todos` feature'); - todoStore.stop(); + todosStore.stop(); } }, { diff --git a/src/stores/index.js b/src/stores/index.js index 1912418a2..e9ef523f8 100644 --- a/src/stores/index.js +++ b/src/stores/index.js @@ -12,6 +12,7 @@ import RequestStore from './RequestStore'; import GlobalErrorStore from './GlobalErrorStore'; import { workspaceStore } from '../features/workspaces'; import { announcementsStore } from '../features/announcements'; +import { todosStore } from '../features/todos'; export default (api, actions, router) => { const stores = {}; @@ -31,6 +32,7 @@ export default (api, actions, router) => { globalError: new GlobalErrorStore(stores, api, actions), workspaces: workspaceStore, announcements: announcementsStore, + todos: todosStore, }); // Initialize all stores Object.keys(stores).forEach((name) => { -- cgit v1.2.3-54-g00ecf