From 837136432c4b1be9de6b04abcaf48624d96a4a2d Mon Sep 17 00:00:00 2001 From: Corina <14900841+corinagum@users.noreply.github.com> Date: Thu, 14 Nov 2019 10:03:47 -0800 Subject: [PATCH 1/2] Add tableflip script --- CHANGELOG.md | 7 +- package.json | 7 +- samples/17.b.clear-after-idle/README.md | 183 ++++++++++++------------ 3 files changed, 100 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3a7e3263a..a22e7fc8d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Breaking changes -- `adaptiveCardHostConfig` is being renamed to `adaptiveCardsHostConfig` - - If you are using the deprecated `adaptiveCardHostConfig`, we will rename it automatically +- `adaptiveCardHostConfig` is being renamed to `adaptiveCardsHostConfig` + - If you are using the deprecated `adaptiveCardHostConfig`, we will rename it automatically ### Fixed @@ -41,8 +41,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - PR [#2541](https://github.com/microsoft/BotFramework-WebChat/pull/2541): `useStyleOptions`, `useStyleSet` - PR [#2542](https://github.com/microsoft/BotFramework-WebChat/pull/2542): `useLanguage`, `useLocalize`, `useLocalizeDate` - PR [#2543](https://github.com/microsoft/BotFramework-WebChat/pull/2543): `useAdaptiveCardsHostConfig`, `useAdaptiveCardsPackage`, `useRenderMarkdownAsHTML` -- Bring your own Adaptive Cards package by specifying `adaptiveCardsPackage` prop, by [@compulim](https://github.com/compulim) in PR [#2543](https://github.com/microsoft/BotFramework-WebChat/pull/2543) +- Bring your own Adaptive Cards package by specifying `adaptiveCardsPackage` prop, by [@compulim](https://github.com/compulim) in PR [#2543](https://github.com/microsoft/BotFramework-WebChat/pull/2543) - PR [#2544](https://github.com/microsoft/BotFramework-WebChat/pull/2544): `useAvatarForBot`, `useAvatarForUser` +- Fixes [#2597](https://github.com/microsoft/BotFramework-WebChat/issues/2597). Modify `watch` script to `start` and add `tableflip` script for throwing `node_modules`, by [@corinagum](https://github.com/corinagum) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX) ### Fixed diff --git a/package.json b/package.json index 00d9f146bd..d416ea52c2 100644 --- a/package.json +++ b/package.json @@ -77,11 +77,14 @@ "lerna-publish": "lerna publish", "prepublishOnly": "lerna run --scope=botframework-webchat* --scope=isomorphic* --scope=playground --stream prepublishOnly", "prettier-readmes": "prettier --write **/**/*.md --tab-width 3 --single-quote true", + "start": "npm run build && lerna run --parallel --scope=botframework-webchat* --scope=isomorphic* --stream watch", "start:docker": "npm run build && docker-compose up --build", "start:playground": "cd packages/playground && npm run start", + "tableflip": "npm run tableflip:start && lerna clean --yes --concurrency 2 && npx rimraf node_modules && npm ci && npm run bootstrap -- --concurrency 2 && npm run tableflip:end", + "tableflip:end": "echo ┬──┬ ノ( ゜-゜ノ) Tableflip complete. Now run npm start", + "tableflip:start": "echo (╯ರ ~ ರ)╯︵ ┻━┻ Begin tableflip.", "test": "jest --no-cache", - "test:all": "lerna run --parallel --stream test", - "watch": "lerna run --parallel --scope=botframework-webchat* --scope=isomorphic* --stream watch" + "test:all": "lerna run --parallel --stream test" }, "devDependencies": { "@azure/storage-blob": "^12.0.0", diff --git a/samples/17.b.clear-after-idle/README.md b/samples/17.b.clear-after-idle/README.md index f9e2056591..f7b49b4ce9 100644 --- a/samples/17.b.clear-after-idle/README.md +++ b/samples/17.b.clear-after-idle/README.md @@ -27,90 +27,88 @@ This sample shows how to replace Web Chat's store to clear the conversation. ## Overview - -This sample demonstrates how to clear the conversation data and start a new conversation with the user after the conversation has sat idle for a set time. To accomplish this, we created a custom hook - `useTimer` - that takes a callback as a parameter, which is called when the timer expires, and returns an array containing the time remaining in milliseconds - `timeRemaining` - and a method to set the time remaining - `setTimeRemaining`. +This sample demonstrates how to clear the conversation data and start a new conversation with the user after the conversation has sat idle for a set time. To accomplish this, we created a custom hook - `useTimer` - that takes a callback as a parameter, which is called when the timer expires, and returns an array containing the time remaining in milliseconds - `timeRemaining` - and a method to set the time remaining - `setTimeRemaining`. ```javascript import { useEffect, useState } from 'react'; export default function useTimer(fn, step = 1000) { - const [timeRemaining, setTimeRemaining] = useState(); - - useEffect(() => { - let timeout; - if (timeRemaining > 0) { - timeout = setTimeout(() => setTimeRemaining(ms => (ms > step ? ms - step : 0)), step); - } else if (timeRemaining === 0) { - setTimeRemaining(); - fn(); - } + const [timeRemaining, setTimeRemaining] = useState(); + + useEffect(() => { + let timeout; + if (timeRemaining > 0) { + timeout = setTimeout(() => setTimeRemaining(ms => (ms > step ? ms - step : 0)), step); + } else if (timeRemaining === 0) { + setTimeRemaining(); + fn(); + } - return () => clearTimeout(timeout); - }, [fn, timeRemaining, setTimeRemaining, step]); + return () => clearTimeout(timeout); + }, [fn, timeRemaining, setTimeRemaining, step]); - return [timeRemaining, setTimeRemaining]; + return [timeRemaining, setTimeRemaining]; } - ``` We also created a custom store middleware that resets the timer by calling `setTimeRemaining` with the default time interval when the user submits the send box. ```javascript -setStore(createStore( - {}, - ({ dispatch }) => next => action => { - if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { - dispatch({ - type: 'WEB_CHAT/SEND_EVENT', - payload: { - name: 'webchat/join', - value: { language: window.navigator.language } - } - }); - } else if (action.type === 'WEB_CHAT/SUBMIT_SEND_BOX') { - // Reset the timer when the user sends an activity - setTimeRemaining(TIME_INTERVAL); - } - - return next(action); - })); -``` - - If the user stops participating in the conversation and the timer expires, we will replace the store to clear the conversation data. However, when the store is replaced, Web Chat dispatches a `'DIRECT_LINE/DISCONNECT'`, so we also need to request a new token. The `initConversation` method handles both replacing the custom store and requesting a new Direct Line token to start a new conversation with the bot. This function is passed to the `useTimer` hook so the conversation will be restarted when the timer expires. - - ```javascript - const initConversation = useCallback(() => { - setStore( - createStore({}, ({ dispatch }) => next => action => { +setStore( + createStore({}, ({ dispatch }) => next => action => { if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { - dispatch({ - type: 'WEB_CHAT/SEND_EVENT', - payload: { - name: 'webchat/join', - value: { language: window.navigator.language } - } - }); + dispatch({ + type: 'WEB_CHAT/SEND_EVENT', + payload: { + name: 'webchat/join', + value: { language: window.navigator.language } + } + }); } else if (action.type === 'WEB_CHAT/SUBMIT_SEND_BOX') { - // Reset the timer when the user sends an activity - setTimeRemaining(TIME_INTERVAL); + // Reset the timer when the user sends an activity + setTimeRemaining(TIME_INTERVAL); } return next(action); - }) - ); + }) +); +``` - (async function() { - const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' }); - const { token } = await res.json(); +If the user stops participating in the conversation and the timer expires, we will replace the store to clear the conversation data. However, when the store is replaced, Web Chat dispatches a `'DIRECT_LINE/DISCONNECT'`, so we also need to request a new token. The `initConversation` method handles both replacing the custom store and requesting a new Direct Line token to start a new conversation with the bot. This function is passed to the `useTimer` hook so the conversation will be restarted when the timer expires. - setDirectLine(createDirectLine({ token })); - })().catch(error => console.log(error)); +```javascript +const initConversation = useCallback(() => { + setStore( + createStore({}, ({ dispatch }) => next => action => { + if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { + dispatch({ + type: 'WEB_CHAT/SEND_EVENT', + payload: { + name: 'webchat/join', + value: { language: window.navigator.language } + } + }); + } else if (action.type === 'WEB_CHAT/SUBMIT_SEND_BOX') { + // Reset the timer when the user sends an activity + setTimeRemaining(TIME_INTERVAL); + } + + return next(action); + }) + ); + + (async function() { + const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' }); + const { token } = await res.json(); + + setDirectLine(createDirectLine({ token })); + })().catch(error => console.log(error)); }, [setStore, setDirectLine]); useEffect(initConversation, []); const [timeRemaining, setTimeRemaining] = useTimer(initConversation); - ``` +``` ## Completed Code @@ -127,46 +125,46 @@ import useTimer from './utils/useTimer'; const TIME_INTERVAL = 30000; function App() { - const [directLine, setDirectLine] = useState(createDirectLine({})); - const [store, setStore] = useState(); - - const initConversation = useCallback(() => { - setStore(createStore( - {}, - ({ dispatch }) => next => action => { - if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { - dispatch({ - type: 'WEB_CHAT/SEND_EVENT', - payload: { - name: 'webchat/join', - value: { language: window.navigator.language } + const [directLine, setDirectLine] = useState(createDirectLine({})); + const [store, setStore] = useState(); + + const initConversation = useCallback(() => { + setStore( + createStore({}, ({ dispatch }) => next => action => { + if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { + dispatch({ + type: 'WEB_CHAT/SEND_EVENT', + payload: { + name: 'webchat/join', + value: { language: window.navigator.language } + } + }); + } else if (action.type === 'WEB_CHAT/SUBMIT_SEND_BOX') { + setTimeRemaining(TIME_INTERVAL); } - }); - } else if (action.type === 'WEB_CHAT/SUBMIT_SEND_BOX') { - setTimeRemaining(TIME_INTERVAL); - } - return next(action); - })); + return next(action); + }) + ); - (async function() { - const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' }); - const { token } = await res.json(); + (async function() { + const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' }); + const { token } = await res.json(); - setDirectLine(createDirectLine({ token })); - })().catch(error => console.log(error)); - }, [setStore, setDirectLine]); + setDirectLine(createDirectLine({ token })); + })().catch(error => console.log(error)); + }, [setStore, setDirectLine]); - useEffect(initConversation, []); + useEffect(initConversation, []); - const [timeRemaining, setTimeRemaining] = useTimer(initConversation); + const [timeRemaining, setTimeRemaining] = useTimer(initConversation); - return ( -
- - -
- ); + return ( +
+ + +
+ ); } export default App; @@ -176,6 +174,7 @@ export default App; - [Hooks at a Glance](https://reactjs.org/docs/hooks-overview.html) - [Web Chat Back Channel Welcome Event Sample](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/15.d.backchannel-send-welcome-event) + ## Full list of Web Chat hosted samples View the list of [available Web Chat samples](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples) From 22b54561b09cc67a18b98524b190aebf7f2b5272 Mon Sep 17 00:00:00 2001 From: Corina <14900841+corinagum@users.noreply.github.com> Date: Thu, 14 Nov 2019 10:07:14 -0800 Subject: [PATCH 2/2] update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a22e7fc8d1..bbfae11eb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - PR [#2543](https://github.com/microsoft/BotFramework-WebChat/pull/2543): `useAdaptiveCardsHostConfig`, `useAdaptiveCardsPackage`, `useRenderMarkdownAsHTML` - Bring your own Adaptive Cards package by specifying `adaptiveCardsPackage` prop, by [@compulim](https://github.com/compulim) in PR [#2543](https://github.com/microsoft/BotFramework-WebChat/pull/2543) - PR [#2544](https://github.com/microsoft/BotFramework-WebChat/pull/2544): `useAvatarForBot`, `useAvatarForUser` -- Fixes [#2597](https://github.com/microsoft/BotFramework-WebChat/issues/2597). Modify `watch` script to `start` and add `tableflip` script for throwing `node_modules`, by [@corinagum](https://github.com/corinagum) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX) +- Fixes [#2597](https://github.com/microsoft/BotFramework-WebChat/issues/2597). Modify `watch` script to `start` and add `tableflip` script for throwing `node_modules`, by [@corinagum](https://github.com/corinagum) in PR [#2598](https://github.com/microsoft/BotFramework-WebChat/pull/2598) ### Fixed