Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Redux Devtools #3277

Merged
merged 3 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Resolves [#3250](https://github.com/microsoft/BotFramework-WebChat/issues/3250). Added activity grouping feature, by [@compulim](https://github.com/compulim), in PR [#3365](https://github.com/microsoft/BotFramework-WebChat/pull/3365)
- Resolves [#3354](https://github.com/microsoft/BotFramework-WebChat/issues/3354). Added access key (<kbd>ALT</kbd> + <kbd>SHIFT</kbd> + <kbd>A</kbd> for Windows and <kbd>CTRL</kbd> + <kbd>OPTION</kbd> + <kbd>A</kbd> for Mac) to suggested actions, by [@compulim](https://github.com/compulim), in PR [#3367](https://github.com/microsoft/BotFramework-WebChat/pull/3367)
- Resolves [#3247](https://github.com/microsoft/BotFramework-WebChat/issues/3247). Support activity ID on `useObserveScrollPosition` and `useScrollTo` hook, by [@compulim](https://github.com/compulim), in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX)
- Added support for [Redux DevTools](https://github.com/zalmoxisus/redux-devtools-extension), by [@tpdewolf](https://github.com/tpdewolf) and [@compulim](https://github.com/compulim), in PR [#3277](https://github.com/microsoft/BotFramework-WebChat/pull/3277)

### Fixed

Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,38 @@ export default () => {

See the working sample of [Web Chat rendered via React](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/e.host-with-react/).

### Experimental support for Redux DevTools

Web Chat internally use Redux for state management. [Redux DevTools](https://github.com/reduxjs/redux-devtools) is enabled in the NPM build as an opt-in feature.

This is for glancing into how Web Chat works. This is not an API explorer and is not an endorsement of using the Redux store to programmatically access the UI. The [hooks API](https://github.com/microsoft/BotFramework-WebChat/tree/master/docs/HOOKS.md) should be used instead.

To use Redux DevTools, use the `createStoreWithDevTools` function for creating a Redux DevTools-enabled store.

<!-- prettier-ignore-start -->
```diff
import React, { useMemo } from 'react';
- import ReactWebChat, { createDirectLine, createStore } from 'botframework-webchat';
+ import ReactWebChat, { createDirectLine, createStoreWithDevTools } from 'botframework-webchat';

export default () => {
const directLine = useMemo(() => createDirectLine({ token: 'YOUR_DIRECT_LINE_TOKEN' }), []);
- const store = useMemo(() => createStore(), []);
+ const store = useMemo(() => createStoreWithDevTools(), []);

return <ReactWebChat directLine={directLine} store={store} userID="YOUR_USER_ID" />;
};
```
<!-- prettier-ignore-end -->

There are some limitations when using the Redux DevTools:

- The Redux store uses side-effects via [`redux-saga`](https://github.com/redux-saga/redux-saga). Time-traveling may break the UI.
- Many UI states are stored in React context and state. They are not exposed in the Redux store.
- Some time-sensitive UIs are based on real-time clock and not affected by time-traveling.
- Dispatching actions are not officially supported. Please use [hooks API](https://github.com/microsoft/BotFramework-WebChat/tree/master/docs/HOOKS.md) instead.
- Actions and reducers may move in and out of Redux store across versions. [Hooks API](https://github.com/microsoft/BotFramework-WebChat/tree/master/docs/HOOKS.md) is the official API for accessing the UI.

# Customizing the Web Chat UI

Web Chat is designed to be customizable without forking the source code. The table below outlines what kind of customizations you can achieve when you are importing Web Chat in different ways. This list is not exhaustive.
Expand Down
4 changes: 3 additions & 1 deletion packages/bundle/src/index-minimal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint dot-notation: ["error", { "allowPattern": "^WebChat$" }] */
// window['WebChat'] is required for TypeScript

import { Constants, createStore, version } from 'botframework-webchat-core';
import { Constants, createStore, createStoreWithDevTools, version } from 'botframework-webchat-core';

import ReactWebChat, {
Components,
Expand Down Expand Up @@ -46,12 +46,14 @@ export {
Constants,
createBrowserWebSpeechPonyfillFactory,
createStore,
createStoreWithDevTools,
createStyleSet,
hooks,
renderWebChat,
version
};

// Until we have a development-specific bundle, we are not shipping createStoreWithDevTools in bundle.
window['WebChat'] = {
...window['WebChat'],
concatMiddleware,
Expand Down
5 changes: 5 additions & 0 deletions packages/core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"p-defer": "3.0.0",
"p-defer-es5": "1.1.0",
"redux": "4.0.4",
"redux-devtools-extension": "2.13.8",
"redux-saga": "1.1.3",
"simple-update-in": "2.2.0"
}
Expand Down
28 changes: 24 additions & 4 deletions packages/core/src/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
// This is for the racing between sagaMiddleware and store
/* eslint no-use-before-define: "off" */

import { applyMiddleware, createStore } from 'redux';
import { applyMiddleware, createStore as createReduxStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import createSagaMiddleware from 'redux-saga';

import reducer from './reducer';
import sagaError from './actions/sagaError';
import sagas from './sagas';

export default function createWebChatStore(initialState, ...middlewares) {
function createEnhancerAndSagaMiddleware(getStore, ...middlewares) {
const sagaMiddleware = createSagaMiddleware({
onError: (...args) => {
const [err] = args;

console.error(err);

store.dispatch(sagaError());
const store = getStore();

store && store.dispatch(sagaError());
}
});

const store = createStore(reducer, initialState || {}, applyMiddleware(...middlewares, sagaMiddleware));
return {
enhancer: applyMiddleware(...middlewares, sagaMiddleware),
sagaMiddleware
};
}

export default function createStore(initialState, ...middlewares) {
const { enhancer, sagaMiddleware } = createEnhancerAndSagaMiddleware(() => store, ...middlewares);
const store = createReduxStore(reducer, initialState || {}, enhancer);

sagaMiddleware.run(sagas);

return store;
}

export function withDevTools(initialState, ...middlewares) {
const { enhancer, sagaMiddleware } = createEnhancerAndSagaMiddleware(() => store, ...middlewares);
const store = createReduxStore(reducer, initialState || {}, composeWithDevTools(enhancer));

sagaMiddleware.run(sagas);

Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import clearSuggestedActions from './actions/clearSuggestedActions';
import connect from './actions/connect';
import createStore from './createStore';
import createStore, { withDevTools as createStoreWithDevTools } from './createStore';
import disconnect from './actions/disconnect';
import dismissNotification from './actions/dismissNotification';
import emitTypingIndicator from './actions/emitTypingIndicator';
Expand Down Expand Up @@ -37,6 +37,7 @@ export {
connect,
Constants,
createStore,
createStoreWithDevTools,
disconnect,
dismissNotification,
emitTypingIndicator,
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';

import { createStore } from 'botframework-webchat';
import { createStoreWithDevTools } from 'botframework-webchat';

import App from './App';

Expand All @@ -27,7 +27,7 @@ window.addEventListener('keydown', event => {
}
});

store = createStore(
store = createStoreWithDevTools(
onErrorResumeNext(() => JSON.parse(window.sessionStorage.getItem(REDUX_STORE_KEY))),
({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
Expand Down