1

We have a webchat window on our website that can be minimized/reopened (this keeps the same token, if still valid) or closed/reopened (this ensures we retrieve a new token). Our bot should greet us when we dispatch a specific event to the bot, like this example: Welcome Event Example. However, when following a specific pattern, the webchat becomes stuck on the "WEB_CHAT/SET_REFERENCE_GRAMMAR_ID" action and our bot does not greet us with our welcome message.

Could someone please help me to understand why the webchat freezes on this action?

Does this below sample approach look feasible to recomposing the UI using javascript?

Steps to reproduce:

  1. Using the below code, create an html file. - be sure to update the secret
  2. Open the file in Chrome
  3. Click on "Open Chat"
  4. Click on "Minimize Chat"
  5. Click on "Open Chat"
  6. Click on "Close Chat"
  7. Open developer console
  8. Click on "Open Chat"

<!DOCTYPE html>
<html lang="en-US">
<head>
    <title>Web Chat</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    <style>
        html,
        body {
            height: 100%;
        }

        body {
            margin: 0;
        }

        #webchat {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
    <div style="width: 100%;">
        <div style="width: 200px; float: left;">
            <input type="button" onclick="openChat()" id="btnOpen" value="Open Chat" />
        </div>
        <div style="width: 200px; float: left;">
            <input type="button" onclick="closeChat()" id="btnClose" value="Close Chat" />
        </div>
        <div style="width: 200px; float: left;">
            <input type="button" onclick="minimizeChat()" id="btnMin" value="Minimize Chat" />
        </div>
        <div style="clear: both" id="webchat" role="main"></div>
    </div>
    <script>

        const styleOptions = {
            bubbleBackground: 'rgba(0, 0, 255, .1)',
            bubbleFromUserBackground: 'rgba(0, 255, 0, .1)',
            hideSendBox: false,
            hideUploadButton: true, // default false
            microphoneButtonColorOnDictate: '#F33',
            sendBoxBackground: 'White',
            sendBoxButtonColor: undefined, // defaults to subtle
            sendBoxButtonColorOnDisabled: '#CCC',
            sendBoxButtonColorOnFocus: '#333',
            sendBoxButtonColorOnHover: '#999', // default '#333'
            sendBoxDisabledTextColor: undefined, // defaults to subtle
            sendBoxHeight: 40,
            sendBoxMaxHeight: 200,
            sendBoxTextColor: 'Black',
            sendBoxBorderBottom: '',
            sendBoxBorderLeft: '',
            sendBoxBorderRight: '',
            sendBoxBorderTop: 'solid 1px #E6E6E6',
            sendBoxPlaceholderColor: undefined, // defaults to subtle
            sendBoxTextWrap: true,
        };

        var secret = 'YOUR SECRET HERE';
        var res = "";

        var token = "";

        const storeMiddleware = () => next => action => {
                console.log(">>> HTML DISPATCH action: " + action.type);
                if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
                    sendEvent();
                }
  if (action.type === 'DIRECT_LINE/DISCONNECT_FULFILLED'){
      setDirectLine(null);
      setStore();
  }
                return next(action);
            };

        var newT = false;

 var store = window.WebChat.createStore({}, storeMiddleware);

        var wc = document.getElementById('webchat');

        async function getRes() {
            res = await fetch(
                'https://directline.botframework.com/v3/directline/tokens/generate',
                {
                    headers: {
                        Authorization: `Bearer ${secret}`,
                        'Content-type': 'application/json'
                    },
                    method: 'POST'
                }
            );
        }

        async function openChat() {
            wc.style.display = "";

            if (token == "") {
                newT = true;
                await getRes();
                token = await res.json();
            }
            else {
                newT = false;
            }

            window.WebChat.renderWebChat(
                {
                    directLine: window.WebChat.createDirectLine({ "token": token.token }), store,
                    styleOptions
                },
                wc);

            document.querySelector('#webchat > *').focus();
        }

        function sendEvent() {
            if (newT) {
                store.dispatch({
                    type: 'WEB_CHAT/SEND_EVENT',
                    payload: { name: 'webchat/join' }
                });
            }
        }

        function minimizeChat() {
            wc.style.display = "none";
        }

        function closeChat() {
            minimizeChat();
            store.dispatch({type: 'DIRECT_LINE/DISCONNECT'});
     token ="";
        }

 function setDirectLine(dl){
     window.WebChat.directLine = dl;
 }
 
 function setStore(){
     store = window.WebChat.createStore({}, storeMiddleware);
 }

    </script>
</body>
</html>

Expected behavior

You will not be greeted and, in the developer console, the last action written is ">>> HTML DISPATCH action: WEB_CHAT/SET_REFERENCE_GRAMMAR_ID"

Additional context

If you move the below line of code from the "closeChat" function to the "minimizeChat" function, the bot will properly greet us.

store.dispatch({type: 'DIRECT_LINE/DISCONNECT'});
Cwalt888
  • 11
  • 3
  • You're code works when I try it out. There are only two differences. First, I pass in `res = await fetch('http://localhost:3500/directline/token', { method: 'POST' });` in place of your `await fetch()`. I generate a token separately in a "token server" I run for development purposes. I use request and post the options, but the options are basically the same, which brings me to...Two, I pass in `json: { user: { ID: 'dl_123' } }` which Direct Line needs to be passed thru. The value is static as I don't need it to be dynamic for testing. If I use your `fetch()` call, it fails. Try it out. – Steven Kanberg Feb 11 '20 at 16:59
  • Out of idle curiosity, why didn't you use the already developed [minimizable web chat](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/06.recomposing-ui/a.minimizable-web-chat) sample? – Steven Kanberg Feb 11 '20 at 17:29
  • Hmm, from what documentation I have read, the user is optional. We haven't explored passing that yet, as it would either always be the same, or require us to come up with some way to make it unique. That also would lead us down the path of loading previous conversation history if this is a repeat user, which we are not ready to tackle yet :). – Cwalt888 Feb 12 '20 at 13:28
  • I did not use that sample as we were looking for a way to implement the functionality in javascript, and the sample was for React. The code I put together was my attempt at rewriting the React sample. – Cwalt888 Feb 12 '20 at 13:30
  • @StevenKanberg Thanks for your comments! I added in the ' json: {user: { ID: 'dl_123' } } ' and the bot still becomes stuck when I follow the steps to reproduce. – Cwalt888 Feb 12 '20 at 13:41
  • Look over [this](https://stackoverflow.com/questions/60085336/how-should-a-botframework-webchat-conversation-be-maintained-for-over-an-hour/60120299#60120299) solution I posted. In it, I show how to setup a local token server to test against. Try building and running that (ignore the webchat code) and pass in the `res = await fetch...` code I posted above in place of yours. As I mentioned, those two changes resulted in your code successfully working for me. – Steven Kanberg Feb 12 '20 at 23:08

1 Answers1

0

You're code works when I try it out. There are only two differences.

First, I pass in

res = await fetch('http://localhost:3500/directline/token', { method: 'POST' });

in place of your await fetch(). I generate a token separately in a "token server" I run for development purposes. I use request and post the options, but the options are basically the same, which brings me to...

Two, I pass in

json: { user: { ID: 'dl_123' } }

which Direct Line needs to be passed thru. The value is static as I don't need it to be dynamic for testing. If I use your fetch() call, it fails. Try it out.

Steven Kanberg
  • 6,078
  • 2
  • 16
  • 35
  • Hi Steven, I posed the question to ultimately answer this question: "Could someone please help me to understand why the webchat freezes on this action?" as I am not understanding why the webchat freezes on that action when I follow the specific steps outlined. I am not sure why dispatching a "DIRECT_LINE/DISCONNECT" in my minimizeChat function fixes the freezing issue. – Cwalt888 Feb 21 '20 at 13:57
  • So, just to be clear, it does work but only if you disconnect as part of the minimizing? From what I remember, that wasn't my experience, but I will look it over, again and see what else I might find. – Steven Kanberg Feb 21 '20 at 16:53
  • Yes, if I do the disconnect as part of the minimizing, the code I pasted works fine when going through the same steps. – Cwalt888 Feb 21 '20 at 17:35