oracle intelligent bots techexchange...oracle intelligent bots - techexchange 3 about the...

16
Oracle Intelligent Bots – TechExchange 1 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-and- running-immediately

Upload: others

Post on 08-Jun-2020

9 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots – TechExchange

1

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-and-running-immediately

Page 2: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 2

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

Page 3: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 3

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

Page 4: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 4

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', …

});

Page 5: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 5

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-running-immediately

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": {

Page 6: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 6

"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

Page 7: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 7

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

Page 8: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 8

//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();

}

Page 9: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 9

}

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-cloud-enterprise-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();

Page 10: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 10

//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 … }

Page 11: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 11

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.

Page 12: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 12

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.

Page 13: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 13

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.

Page 14: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 14

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",

Page 15: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 15

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"

},

{

Page 16: Oracle Intelligent Bots TechExchange...Oracle Intelligent Bots - TechExchange 3 About the Conversation Message Model (CMM) No magic happens without a reason. The magic behind the CR

Oracle Intelligent Bots - TechExchange 16

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)

};