How-to Build Card Layout Responses from Custom Components

Similar documents
Oracle Digital Assistant: Strategies for Escaping the Validation Loop

Oracle Bots Nodes.js SDK: Controlling Smart Homes Using IFTTT Applets with Oracle Digital Assistant

Running and Debugging Custom Components Locally

Article. Building Single Base-Language Bots. Oracle Intelligent Bots TechExchange. Frank Nimphius, Marcelo Jabali - April 2018

Merging Data From Spreadsheets to or Documents

ADF Code Corner Implementing auto suggest functionality in ADF Faces. Abstract:

Lab 3 - Pizza. Purpose. Assignment

ADF Mobile Code Corner

ADF Code Corner How-to bind custom declarative components to ADF. Abstract: twitter.com/adfcodecorner

ADF Mobile Code Corner

ADF Mobile Code Corner

Using Apache FreeMarker Template Language in BotML

Oracle APEX 18.1 New Features

ADF Code Corner How-to launch a popup upon rendering of a page fragment in a region using JSF 2. Abstract: twitter.

Instructions for Using the DAILY COOK'S SUBSTITUTE MENU

Laboratorio di Tecnologie dell'informazione. Ing. Marco Bertini

1 Copyright 2011, Oracle and/or its affiliates. All rights reserved.

ADF Mobile Code Corner

News in RSA-RTE CP1

ADF Code Corner. 048-How-to build XML Menu Model based site menus and how to protect them with ADF Security and JAAS. Abstract:

ADF Code Corner. 97. How-to defer train-stop navigation for custom form validation or other developer interaction. Abstract: twitter.

MASTER-DETAIL FORMS. In this Chapter, you will learn about: Master-Detail Forms Page 108

Using SQL Developer. Oracle University and Egabi Solutions use only

Language Basics. /* The NUMBER GAME - User tries to guess a number between 1 and 10 */ /* Generate a random number between 1 and 10 */

Task #1 The if Statement, Comparing Strings, and Flags

SCRIPT REFERENCE. UBot Studio Version 4. The UI Commands

QuickStart Guide 4 - Merge

MyEclipse ER-Designer Quickstart

TRAINING GUIDE. ArcGIS Online and Lucity

GeneXus for Smart Devices course - Architecture of Smart Device Applications

CANVASES AND WINDOWS

Creating a REST API which exposes an existing SOAP Service with IBM API Management

Rich Web UI made simple Building Data Dashboards without Code

Chapter 3 Lab Decision Structures

Chatbot Framework. Overview. Installation. Getting Started

SEO According to Google

(Refer Slide Time: 01:40)

Navigating and Managing Files and Folders in Windows XP

OALCF Tasks for the Apprenticeship Goal Path: Prepared for the Project,

Manipulating Database Objects

Chapter 9. Web Applications The McGraw-Hill Companies, Inc. All rights reserved. McGraw-Hill

NetAdvantage for ASP.NET Release Notes

PHP Syntax. PHP is a great example of a commonly-used modern programming language.

Oracle BPM 10g R3 Programming 1 Essentials

Reference Guide Novell Vibe Cloud Wave Gadgets API Reference Guide

UWP Working with Navigation

The NoPlsql and Thick Database Paradigms

User's Guide c-treeace SQL Explorer

Report Designer Report Types Table Report Multi-Column Report Label Report Parameterized Report Cross-Tab Report Drill-Down Report Chart with Static

Oracle WebCenter Suite Integrating Secure Enterprise Search

<Insert Picture Here> Advanced ADF Faces. Frank Nimphius Principal Product Manager

USER GUIDE MADCAP FLARE WebHelp

ADF OAF Who Cares? You Do! Oracle Applications Framework / Application Development Framework - Which way do I go?

EMARSYS FOR MAGENTO 2

Highlight the s address (example: and go to the top of the page and click on Insert

INF5750. Introduction to JavaScript and Node.js

MadCap Software. WebHelp Guide. Flare 2017 r2

IN PRACTICE. Daniele Bochicchio Stefano Mostarda Marco De Sanctis. Includes 106 practical techniques MANNING

Premium POS Pizza Order Entry Module. Introduction and Tutorial

ADF Code Corner How-to enforce LOV Query Filtering. Abstract: twitter.com/adfcodecorner

08/10/2018. Istanbul Now Platform User Interface

Oracle Fusion Middleware 11g: Build Applications with ADF Accel

ECM Extensions xcp 2.2 xcelerator Abstract

ADF Code Corner. 71. How-to integrate Java Applets with Oracle ADF Faces. Abstract: twitter.com/adfcodecorner

Oracle Developer Day

ADF Hands-On. Understanding Task Flow Activities / 2011 ADF Internal Enterprise 2.0 Training. Abstract:

R12.x Oracle E-Business Suite Personalizations

Implementing a Numerical Data Access Service

Creating Buttons and Pop-up Menus

Remote Tracker Documentation

Configure App Service Authentication for Your Azure Web App

GSA QMAC. Transportation Service Provider (TSP) TransPort Integrator User Guide. TransPort Integrator Service. Version 3.0

USER GUIDE MADCAP FLARE Accessibility

Nintex Forms 2010 Help

ADF Code Corner How-to show a glasspane and splash screen for long running queries. Abstract: twitter.com/adfcodecorner

JScript Reference. Contents

QuickStart Guide 2 - Normalisation

Rio Maining Dining Hall menu

Cannot Create Index On View 'test' Because

allergen Main menu Starters & Salads HOUSE PICKLES TEAR & SHARE PRETZEL BREAD POPCORN SQUID GLAZED SPARE RIBS CORN CHIPS & SPIN DIP

Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting

BCI.com Sitecore Publishing Guide. November 2017

ADF Code Corner. 65. Active Data Service Sample Twitter Client. Abstract: twitter.com/adfcodecorner

CLIL-6-PHP-6. Arrays - part 1. So far we've looked at the basic variables types such as strings and integers, as

Figaro s Italian Pizza Presents A Quick Reference Guide on How-To in MENU DESIGNER

Introduction to JavaScript p. 1 JavaScript Myths p. 2 Versions of JavaScript p. 2 Client-Side JavaScript p. 3 JavaScript in Other Contexts p.

JavaScript: More Syntax

Creating a REST API which exposes an existing SOAP Service with IBM API Management

Preface 7. 1 Introduction to OpenUI5 9

Tableau Automation Starter Kit:

Oracle User Productivity Kit Content Player

Concept - first iteration DAM 2.0 & CMIS

Ignite UI Release Notes

Oracle. Engagement Cloud Using Service Request Management. Release 12

ORIGINAL FAMOUS RAY S HELL BURGER

Oracle Adapter for Salesforce Lightning Winter 18. What s New

CREATING A REPORT TEMPLATE TO USE IN MAGICDRAW user guide

OnCrawl Metrics. What SEO indicators do we analyze for you? Dig into our board of metrics to find the one you are looking for.

Advanced Input Help - The Object Value Selector (OVS)

12/05/2017. Geneva ServiceNow Custom Application Development

Transcription:

Oracle Intelligent Bots TechExchange Article. How-to Build Card Layout Responses from Custom Components Frank Nimphius, June 2018 Using the Common Response component (CR component) in Oracle Intelligent Bots, bot conversation designers can build arbitrary complex bot responses declaratively. A very popular bot response is the card layout that displays multiple cards in a vertical or horizontal order with each card displaying a title, a description, an imagen an optional URL and one or more action items for the user to tap on. While the recommended conversation design strategy is to use the CR component whenever possible, there exist use cases in which a custom component must render its own UI. Still displaying data in cards remains a popular layout. In this article I explain how to display a card layout from a custom component and how you handle post back actions (buttons on a card) and user text entries. Note: If you are new to custom components in Oracle Intelligent Bots, then please have a look at this previously written TechExchange article first: https://blogs.oracle.com/mobile/techexchange-custom-component-development-in-omce-%e2%80%93-getting-up-andrunning-immediately 1 Oracle Intelligent Bots TechExchange

Table of Contents About the Conversation Message Model (CMM)... 3 About MessageModel.js in the Custom Component SDK... 3 Building Card Layouts... 3 Defining a card... 3 Defining a Postback Action... 4 A Complete Example... 5 The custom component metadata function... 5 The custom component invoke function... 6 Handling Postback Actions... 9 Bot dialog flow... 11 Runtime View... 12 Appendix: Sample Data Provider... 14 2

About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR component rich layout capabilities is the underlying message model, the conversation message model (CMM). For each response type, like text and attachment, the CMM provides a conversation message object that components use to compose and return rich bot responses. One of the available conversation message objects is and you may have guessed it for building card layouts. About MessageModel.js in the Custom Component SDK The custom component MessageModel.js class in the bot custom component service SDK contains helper functions that make it easy for custom component developers to work with the conversion message model. When building custom components, you access the SDK s MessageModel instance through the SDK reference, which usually is passed to the custom component as the conversation argument. invoke: (conversation, done) => { var messagemodel = conversation.messagemodel() Building Card Layouts The MessageModel.js class contains the CardConversationMessage object definition, that you use to build a response object for card layouts. The CardConversationMessage object abstracts the metadata structure that is used internally by the CMM to define and deliver bot responses to multiple different messenger channels. To simplify the creation of the various conversation messages supported by the CMM from custom components, the MessageModel SDK class does provide static helper functions. For the CardConversationMessage, you find the following helper function defined var cardmessage = conversation.messagemodel().cardconversationmessage (layout,cards,actions); The function expects the following arguments layout: vertical or horizontal string value to determine the direction of the cards. In the horizontal setting the individual cards are rendered in a carousel for scrolling cards: An array of card objects. Each card in the array has a title, a description, a URL and an array of local actions (various types), which are rendered as buttons on an individual card. actions: (optional) global actions rendered on the cars layout level Defining a card To define a card to be rendered on the card layout, you use the static cardobject() function exposed on the MessageModel class. The cardobject() function creates a card instance that you then add to an array for 3

display through the cardconversationmessage( ) function. The cardobject( ) function takes the following arguments: title: The title of the card description: A description that can have multiple lines of text imageurl: The URL of the image to be displayed on the card. Images must be publicly accessible url: A hyperlink that is displayed on the card actions: An array of actions, e.g. postback, location or phone, to be added as a command button to the card Example: let cardobj = conversation.messagemodel().cardobject('pizza Supreme', 'Pizza with the best of season topics', 'http://acme.com/pizza/images/supreme.jpg', 'http://acme.com', [action1, action2, ]); Defining a Postback Action The conversation message model supports different action types including location, call, url and postback. For this article I will explain how to create and use postback actions. Note: Other action types may become subject of separate Oracle TechExchange articles. However, I suggest you read the source code of the MessageModel.js file for details on each of the available action types. Just search for "ActionObject" to find each of the types in the form of <type name>actionobject( parameters ) The postback action function requires at least 2 parameters to build and return an action object that you then can add to an array of actions that eventually is added to a card response message. Arguments: label: The label of the command item (button) displayed on a card image: optional, the URL reference of an image to display on a button postback: JSON object or a simple string to be send back to the bot when a user presses the action command (button) on a card. A JSON object allows you to set multiple variables in response to a user action. let action = conversation.messagemodel().postbackactionobject("place Order", null, { propertyname1: 'value1', propertyname2: 'value2', ); 4

The code snippet above creates an action that renders a command item with a label "Place Order". The image argument is set to null, so the command item renders with a label only. The last argument is a JSON object that defines attributes and values to work with when a user clicked the command item. A Complete Example If you are familiar with the Oracle Intelligent Bots samples, then you should know the CRC pizza sample that renders pizza types in cards for a user to order the pizza by tapping a command item. The code source below does the same in that it reads the pizza menu from a JavaScript object referenced as "datasource". It then iterates over all the pizza menu items (an array of JavaScript objects) to create a card for each of the pizza types. The custom component allows bot designers to define a variable name of a context variable that gets updated with the name of the pizza when selected. The custom component skeleton looks like shown below "use strict"; //reference the local JS class containing the pizza menu data var datasource = require('./../utilities/sampledataprovider'); module.exports = { metadata: () => ({ ), invoke: (conversation, done) => { ; Note: If you are new to custom components in Oracle Intelligent Bots, then please have a look at this previously written TechExchange article: https://blogs.oracle.com/mobile/techexchange-custom-component-development-in-omce-%e2%80%93-getting-up-and-runningimmediately The custom component metadata function The custom component metadata function describes the component to the Oracle Intelligent Bot chatbot instance. It tells the bot about the component name, mandatory and optional input parameters, as well as about returned action strings that allow bot designers to make a sensitive decision of where to navigate next. metadata: () => ({ "name": "cmm.card.sample", "properties": { "variable": { "type": "string", "required": true "cardlayout": { "type": "string", "required": false "keepturn": { 5

"type": "boolean", "required": false "supportedactions": ['textreceived'] ), The component definition defines a single required parameter for the context variable that should be updated with the content of a postback action payload when the user taps on an action item. Two more optional parameters are defined to define the orientation in which cards are rendered in the messenger ('vertical' or 'horizontal') and to define whether user input is required after the user taps the action item (keepturn). If, after selecting the action item the bot only prints a message then keepturn should be set to true. If the conversation is not complete, then keepturn should be set to false (default). Note: You can read up about on what keepturn does when set on a component in the following TechExchange article: https://blogs.oracle.com/mobile/techexchange-real-world-insight-into-keepturn-and-transition-in-intelligent-bots The supported action string is set to "textreceived" and is returned when a user types text into the messenger instead of selecting an action from a card. The custom component invoke function The invoke function manages a variable to track the component internal state. If the tracking variable is not set or set to 'false' then the card layout is rendered. After the card layout is rendered, the tracking variable is set to true and the custom component returns the turn to the user to select a card action. The component does not transition to a next state so that the custom component also handles the next user interaction. This is how you handle postback actions similar to how the CR component does. The code below contains highlighted comments that explain the implementation invoke: (conversation, done) => { //read input parameters or set their default values var cardlayout = conversation.properties().cardlayout? conversation.properties().cardlayout : "vertical"; var keepturn = conversation.properties().keepturn? conversation.properties().keepturn : false; var variablename = conversation.properties().variable; //read variable that tracks the component state. If the component is called the first //time, then render the card layout. Else handle the user selection (postback) or user //text message (if the user used the keyboard to type a message instead of selecting a //value 6

var statetracker = (conversation.variable(' cardcomp_state ') == 'true')? 'true' : 'false'; //check for and handle postback response if the component previously rendered the //card layout if (conversation.postback() && statetracker == 'true') { //reset state tracker so that next time the card layout renders again conversation.variable(' cardcomp_state ', 'false'); //get the postback message object let postbackpayload = conversation.postback(); //read the key/value pair in the postback message and update the variable with the value //note that in the sample, as you will see further below, the postback action payload //object has the key name set to the variable name to receive the value update conversation.variable(variablename, postbackpayload[variablename]); // when the user selected an action from a card, then this job of the custom component //is done and transition goes to a next state. If the next state does not require user //interaction, then the bot designer should have set the keepturn input parameter to //false conversation.keepturn(keepturn); conversation.transition(); done(); //handle text response by returning the textreceived action string if the //component has rendered the card layout before else if(conversation.text() && statetracker == 'true'){ //reset state tracker conversation.variable(' cardcomp_state ', 'false'); //the user entered text, so we return 'textreceived'. Note that you can use //this custom component to also access to the user text string and e.g. save it //for later. For the example in this article, I simply return the action string //for the bot designer to do the right thing conversation.transition('textreceived'); //navigate to the next state with no further user input required conversationkeepturn(true); done(); else { //set state tracker indcating that card has been rendered conversation.variable(' cardcomp_state ', 'true'); //No message sent. So, it's safe to assume that the card layout should be rendered 7

//read the data array from the local file. Note that the local file could be replaced //with a remote service call to query data from a remote system. var dataarray = datasource.data(); //define a card array var cards = []; //iterate over all pizza menu items in the data array to create the card definition and //the postback action for (let i = 0; i < dataarray.length; i++) { //define the action object. Each action has a label saying "Order <pizza name>". //the postback payload that is sent to the bot when a user clicks on an action //in the card is set such that the JSON object attribute name is the same name //as the context variable passed as a parameter to the component. The value of the //payload is the name of the pizza to order let action = conversation.messagemodel().postbackactionobject( "Order " + dataarray[i].name, null, { //define which variable to update when postback action is used [variablename]: dataarray[i].name ); //build the card using information from the data source for the pizza to render. The //action array only has a single action item in it let cardobj = conversation.messagemodel().cardobject( dataarray[i].name, dataarray[i].description, dataarray[i].image, null, [action]); //add the card to the cards array cards.push(cardobj); //build the card layout response to send back to the bot to render in the messenger. //the cardlayout variable holds a value of 'vertical' or 'horizontal' as provided //by the bot designer var cardresponsemessage = conversation.messagemodel().cardconversationmessage(cardlayout, cards); //render the card layout conversation.reply(cardresponsemessage); //pass the handle back to the user to select an option. //BUT don't transition to a next state in the conversation. The custom component stays //in focus so it can handle the next user action done(); 8

The component invoke function above renders a card layout with one action item on each card. When the user taps on a button, the context variable that is referenced in the custom component variable property is updated with the value read from the payload. Note: If you are interested in how to call remote services from a custom component to query data, please read the following Oracle TechExchange article https://blogs.oracle.com/mobile/techexchange%3a-master-oracle-intelligent-bots-backend-integration-with-oracle-mobile-cloudenterprise-like-a-pro Handling Postback Actions Building "custom components" is another way of saying "on your own". Though the code sample in the previous section already explained how to handle user messages in response to a previous card layout rendering, it is important to make it clear that you, the custom component designer, must handle the user response too. This means that whatever you want to happen when a user selects an action from a card, you need to build it. Many bot designers get confused by the functionality that exists in the CR component and assume this to magically happen for card layouts rendered by custom components as well. For a custom component to handle the postback action, you need to implement it in your component code as shown in the example code in this article. In the example code provided in this article a postback action is added to each card in the card layout to select a pizza to order and to save the selected pizza name in a context variable. To handle this in a custom component you need to do the following: - Determine whether the component input message is a postback message or not - Read values from the payload - Access the context variable for update with content from the postback message The code below is from the sample code in the previous section. It shows how, at the beginning of the invoke function, your custom component needs to check for incoming messages to determine whether or not it should render the card layout. //check for and handle postback response if (conversation.postback() && statetracker == 'true') { //reset state tracker conversation.variable(' cardcomp_state ', 'false'); //get the postback message object let postbackpayload = conversation.postback(); 9

//read the key/value pair in the postback message and update the variable with the value //note that in the sample, as you will see further below, the postback action payload //object has the key name set to the variable name to receive the value update conversation.variable(variablename, postbackpayload[variablename]); // when the user selected an action from a card, then this job of the custom component //is done and transition goes to a next state. If the next state does not require user //interaction, then the bot designer should have set the keepturn input parameter to //false conversation.keepturn(keepturn); conversation.transition(); done(); //handle text response returning textreceived action as CRC component does else if(conversation.text() && statetracker == 'true'){ //reset state tracker conversation.variable(' cardcomp_state ', 'false'); //the user entered text, so we return 'textreceived'. Note that you can use //this custom component to also access to the user text string and e.g. save it //for later. For the example in this article, I simply return the action string //for the bot designer to do the right thing conversation.transition('textreceived'); //navigate to the next state with no further user input required conversationkeepturn(true); done(); else { render the card menu 10

Bot dialog flow After registering the custom component service with the bot, you can use the custom component in the dialog flow. An example is shown below for the code sample provided in this article Line 12 defines the state that references the custom component that renders the card layout. The component variable property references the pizzaname context variable defined in line 10 for the component to update it with the pizza name selected by the user. Line 17-20 handle the component navigation when the user selects a pizza by pressing the postback button or when the user typed text (in which case this sample cancels the pizza order process). When the user types text instead of selecting a choice from the menu, then the custom component returns the "textreceived" action. The textreceived action is mapped to the "cancel" state. If the user selects a pizza by pressing the order button then navigation happens to the "printconfirmation" state as indicated by the "next" transition directive. 11

Runtime View At runtime, the user may start the bot conversation with "hi". The dialog flow invokes the custom component, which then renders the vertical card layout displaying the pizza options. Each pizza option in the menu has a button that can be used to order a pizza. The command button sends a postback message to the bot containing the JSON object with the information for updating the pizzaname variable. 12

In response to the user selecting an action button, the custom component updates the pizzaname variable and triggers navigation to the printconfirmation page. If the user does not select from the pizza menu buttons but types a text, then the custom component navigates to the state mapped to the textreceived action, which in the sample is the cancel state. 13

Appendix: Sample Data Provider For those wondering how the data source file looks that is used in the sample code for this article. Below is the complete file content of the SampleDataProvider.js file. var data; data = [{ name: "CHEESE", 14

description: "Classic marinara sauce topped with whole milk mozzarella cheese.", image: "https://cdn.pixabay.com/photo/2017/09/03/10/35/pizza-2709845 340.jpg" { name: "PEPPERONI", description: "Classic marinara sauce with authentic old-world style pepperoni.", image: "https://cdn.pixabay.com/photo/2017/08/02/12/38/pepperoni-2571392 340.jpg" { name: "MEAT LOVER", description: "Classic marinara sauce, authentic old-world pepperoni, all-natural Italian sausage, slow-roasted ham, hardwood smoked bacon, seasoned pork and beef.", image: "https://cdn.pixabay.com/photo/2017/07/22/22/51/big-2530144 340.jpg" { name: "SUPREME", description: "Classic marinara sauce, authentic old-world pepperoni, seasoned pork, beef, fresh mushrooms, fresh green bell peppers and fresh red onions.", image: "https://cdn.pixabay.com/photo/2017/07/22/22/57/pizza-2530169 340.jpg" { name: "PREMIUM GARDEN VEGGIE", description: "Premium crushed tomato sauce topped with green peppers, red onions, mushrooms, Roma tomatoes and roasted spinach with our Hut Favorite on the crust.", image: "https://cdn.pixabay.com/photo/2017/07/22/22/57/pizza-2530169 340.jpg" { name: "ULTIMATE CHEESE LOVER", description: "Garlic Parmesan sauce topped with 50% more mozzarella cheese with a toasted Parmesan crust.", image: "https://cdn.pixabay.com/photo/2017/08/02/12/38/pepperoni-2571392 340.jpg" { 15

name: "HAWAIIAN CHICKEN", description: "Grilled chicken, ham, pineapple and green bell peppers.", image: "https://cdn.pixabay.com/photo/2017/07/22/22/51/big-2530144 340.jpg" { name: "BACON SPINACH ALFREDO", description: "Garlic Parmesan sauce topped with bacon, mushrooms and roasted spinach ' with a salted pretzel crust.", image: "https://cdn.pixabay.com/photo/2017/09/03/10/35/pizza-2709845 340.jpg" ]; //expose this data a module module.exports = { ; // return data array data: () => (data) 16