Der hier beschriebene Webservice kann z. B. bei Google Cloud Run gehostet werden.
Für einen Formulardialog in Kiko Webchat mit eigenem Datumspicker werden Einstellungen an drei Stellen vorgenommen:
- Webseite
- Chatbot
- Webservice zur Formularsteuerung
Beispiel-Webseite
Der Kiko Webchat wird auf einer eigenen Seite mit einem Code-Snippet eingebunden.
Zusätzlich ist die externe Datepicker-Bibliothek im Header zu laden.
Ein weiteres Code-Snippet am Ende der Seite wird zur Überwachung der eingehenden Chatbot-Nachrichten und Ausgabe der des Datepickers benötigt.
Kiko-Chatbot
Ein Chatbot wird im Kiko CMS erstellt und als Widget auf der eigenen Webseite eingebunden. Benutzer werden dort vom Chatbot begrüßt und können auf den Intent mit dem Formulardialog weitergeleitet werden.
In diesem Intent werden alle Formularfelder sowie eine Vorlage für den finalen Antworttext definiert.
Auch hier werden die Benutzereingaben an die Webservices eines externen Subbots weitergeleitet, der die individuelle Ablaufsteuerung des Formulardialogs übernimmt.
Wenn der externe Subbot alle benötigten Daten gesammelt und zur Verarbeitung geschickt hat, gibt er die Kontrolle an den Chatbot zurück.
Webservice des externen Subbots
Aufgabe des Webservice ist es, dem Benutzer sukzessive die Fragen zu stellen, die zum Ausfüllen eines Formulars notwendig sind.
Die Formularantworten des Benutzers sollen so lange gespeichert werden, bis der Formulardialog abgeschlossen ist.
Wenn ein Formularfeld vom Typ Datum ist, soll die Anzeige des Datumspickers ausgelöst werden.
Am Ende des Formulardialogs sollen alle gesammelten Daten an einen anderen Webservice oder an einen Mitarbeiter zur späteren Beantwortung übergeben werden. Es ist aber auch möglich, dass mit diesen Daten bereits die endgültige Antwort für den Benutzer berechnet wird.
Blick auf den Code
public/index.html
Der Kiko Webchat wird auf einer eigenen Seite mit einem Code-Snippet eingebunden. Die Konstante "kikoBotIdentifier" ist individuell anzupassen (siehe "Bot Liste" / "Metabot" / "Bot bearbeiten" / "Identifier")
- <script async>
- const dateElementId = 'mydatepicker'
- const kikoCmsDomain = "cloud02-7c83ec0.prod.1000grad.de";
- const kikoBotIdentifier = "6d5abc25-6110-31fa-87a2-77cd2422c3d5";
- const script = document.createElement('script');
- script.src = '//' + kikoCmsDomain + '/chat/assets/js/main.js';
- script.id = 'tgd-chat-script';
- script.onload = async function () {
- window.$chatbot = new TGDChatBot({ identifier: kikoBotIdentifier });
- await window.$chatbot.startApp();
- };
- document.getElementsByTagName('body')[0].appendChild(script);
- </script>
Zusätzlich ist die externe Datepicker-Bibliothek im Header zu laden.
Ein weiteres Code-Snippet am Ende der Seite wird zur Überwachung aller eingehenden Chatbot-Nachrichten benötigt. Der Datepicker wird angezeigt, wenn ein Datepicker-HTML-Element in einer Formular-Dialognachricht gefunden wird. Nach der Änderung des Datums wird das Ergebnis als Nutzereingabe an den Chatbot gesendet.
- const parser = new DOMParser()
- window.$chatbot.on('messageReceived', (event) => {
- event.detail.forEach((message) => {
- if (message.data.type === 'text/html' && message.data.hasOwnProperty('content')) {
- const htmlDoc = parser.parseFromString(message.data.content, 'text/html');
- if (htmlDoc.getElementById(dateElementId)) {
- const elem = document.getElementById(dateElementId);
- const datepicker = new Datepicker(elem,{ language: 'de' });
- elem.addEventListener('changeDate', e => {
- window.$chatbot.sendAsUser({ text: Datepicker.formatDate(e.detail.date, 'dd.mm.yyyy', 'de') });
- });
- }
- }
- });
- });
Die drei Code-Schnipsel aus der Beispielseite können auf jeder Webseite integriert werden, die einen Chatbot mit individuellem Datumswähler benötigen.
Nun folgen einige Erläuterungen zur Verarbeitung der Nutzeranfrage im Webservice.
src/index.js
Zu Beginn wird der Webserver initialisiert.
Die Route "/v1/webhook-message-sent" führt zur Verarbeitung der Nutzernachrichten. Sie ist die Zieladresse für den Webhook des Subbots (Nutzer-Nachricht empfangen).
src/functions.js
Sobald der Formular-Intent im Chatbot erkannt wurde, werden alle weiteren Benutzernachrichten an den Subbot und die Funktion "postWebhookMessageSent" gesendet.
postWebhookMessageSent
Diese Funktion nimmt den Request entgegen, ermittelt die Daten des Servers und leitet die Nachrichten weiter an die Dialog-Funktion.
- const { conversationId, messages } = req.body
- const referer = req.get('referer') || req.query.referer
- if (!referer) throw createError(400, 'Missing referer.')
- const endpointBaseUrl = referer.replace(/\/\//g, 'https://')
- await runDatePickerDialog({ endpointBaseUrl, conversationId, messages })
runDatePickerDialog
In dieser Funktion werden die Formular-Felder bzw. -Parameter durchlaufen, welche in den Metadaten des Intents definiert sind.
- const lastParameterPos = formSessionData ? formSessionData.lastParameterPos : null
- const lastParameter = lastParameterPos !== null ? metadata.parameters[lastParameterPos] : null
- if (lastParameter) {
- // save form parameter input data if necessary
- const fieldInputContent = messages[0].data ? messages[0].data.content : undefined
- newFormSessionData.content = newFormSessionData.content || {}
- newFormSessionData.content[lastParameter.name] = fieldInputContent
- }
- const pos = (lastParameterPos === null ? 0 : lastParameterPos + 1)
- const parameter = metadata.parameters[pos] ? metadata.parameters[pos] : null
Je Datentyp kann eine individuelle Funktion zur Ausgabe der Formularfrage aufgerufen werden.
- const typeToFunctionMapping = {
- '@sys.any': getAnyQuestionMessages,
- '@sys.date': getDateQuestionMessages
- }
- const myFunction = typeToFunctionMapping[parameter.dataType] || getAnyQuestionMessages
- const questionMessages = await myFunction.call(this, parameter)
- await kikoBotService.sendMessage(questionMessages, false)
- .catch((err) => { throw createError(500, 'sendMessage: ' + err.message) })
Nachdem die Formulardaten in der Variable "newFormSessionData.content" gesammelt wurden, können sie an einen anderen Webdienst oder an eine E-Mail-Adresse zur Verarbeitung weitergeleitet werden. (Im Beispiel nicht enthalten.)
- const outputMessages = metadata.intent.output
- // form session ends here - remove session data
- await kikoFormSession.removeData(conversationId)
- // send the form content to somewhere
- // ... newFormSessionData.content
Als Antwort erhält der Benutzer nun den im Intent hinterlegten Ergebnistext aus "metadata.intent.output".
- await kikoBotService.sendMessage(outputMessages, true).catch((err) => { throw createError(500, 'sendMessage: ' + err.message) })
getDateQuestionMessages
Die Funktion für das Datums-Format generiert eine zusätzliche Nachricht an den Webchat mit einem HTML-DIV-Element mit der ID 'mydatepicker'. Weiterhin kann das voreingestellte Datum übergeben werden.
- const dateElementId = 'mydatepicker'
- const selectedDate = '14.2.2021'
- return [
- {
- type: 'message',
- data: {
- content: parameter.question,
- type: 'text/plain'
- }
- },
- {
- type: 'message',
- data: {
- content: `
- <div id="${dateElementId}" data-date="${selectedDate}"></div>
- `,
- type: 'text/html'
- }
- }
- ]
Livestellung
Verwenden Sie für die Livestellung die Cloud Code Cloud-Run-Erweiterung Ihres Code-Editors.
- Klicken Sie in der Fußzeile des Editors auf "Cloud Code".
- Klicken Sie auf "Deploy to Cloud Run".
Deployment zu Google Cloud Run - Wählen Sie Ihre bevorzugte Region und klicken Sie auf "Deploy".
Kiko Chatbot
Erstellen Sie im CMS über das Menü "Botlist" einen externen Subbot mit dem Namen "subbot-datepicker".
Tragen Sie im Subbot über den Untermenüpunkt "Webhooks bearbeiten" im Feld "Nachricht empfangen" die URL des veröffentlichten Webservices ein.
Legen Sie über das Menü "Inhalt" im "Metabot" einen Intent mit dem Namen "Datepicker-Formular-Dialog" an und geben Sie als Weiterleitung des Subbots "subbot-datepicker" ein.
Tragen Sie in "Inhalt" unter "Ergebnis" den Textwert "Formular gesendet." ein.
Intent mit Antworttext Legen Sie zur Erkennung den Entitätstyp "topic" mit dem Entitätswert "Formular" an.
Geben Sie in "Ablaufsteuerung" unter "Metadaten für externen Subbot" den folgenden Wert ein
- {
- "action":"date-picker-dialog",
- "parameters": [
- {
- "name": "date-field-01",
- "question": "Wie lautet das Datum",
- "dataType": "@sys.date"
- },
- {
- "name": "text-field-02",
- "question": "Wie lautet der Titel 02",
- "dataType": "@sys.any"
- }
- ]
- }
Lassen Sie das Feld "Abfrageparameter" deaktiviert.