I may be missing something really obvious, but I haven't figured out how I can build a List programatically in v2 of tne actions-on-google Nodejs client library.
In other words, I want to do something like the conv.ask code below, but don't know the items beforehand, so need to create a list, add the items to the list, and then ask the list in dynamic way. I could do this in v1 with:
var rList = app.buildList("Please select one option:");
for (var r =0; r < resp_text.length; r++) {
rList.addItems(app.buildOptionItem(resp_value[r], resp_matches[r]).setTitle(resp_text[r]));
}
app.askWithList(question_str, rList);
... so am basically looking for the v2 equivalent of the above.
Any help appreciated, thanks!
conv.ask(new List({
title: 'Things to learn about',
items: {
// Add the first item to the list
'MATH_AND_PRIME': {
synonyms: [
'math',
'math and prime',
'prime numbers',
'prime',
],
title: 'Title of the First List Item',
description: '42 is an abundant number',
image: new Image({
url: 'https://example.com/math_and_prime.jpg',
alt: 'Math & prime numbers',
}),
},
// Add the second item to the list
'EGYPT': {
synonyms: [
'religion',
'egypt',
'ancient egyptian',
],
title: 'Ancient Egyptian religion',
description: '42 gods ruled on the fate of the dead in the afterworld',
image: new Image({
url: 'http://example.com/egypt',
alt: 'Egypt',
}),
},
// Add the last item to the list
'RECIPES': {
synonyms: [
'recipes',
'recipe',
'42 recipes',
],
title: '42 recipes in 42 ingredients',
description: 'A beautifully simple recipe',
image: new Image({
url: 'http://example.com/recipe',
alt: 'Recipe',
}),
},
},
}));
Ok, answering my own question just in case it will help someone else...
The way (or at least one way) to do this is to dynamicaly create an item array and using that in the list constructor:
var ritems = {}
for (var r=0; r < resp_text.length; r++) {
ritems[resp_value[r]] = {
synonyms: [resp_matches[r]],
title: resp_text[r]
}
}
conv.ask(question_str);
conv.ask(new List({
title: "Please select one option:",
items: ritems
}))
Related
Good Morning everyone, I want ask a question if I have a list of map like this
[{
id: 1,
title: Medicine 500,
price: 100,
image: http://secret-taiga-11502.herokuapp.com/images/medicines,
quantity: 1,
pharmacyid: 15,
medicineID: 500
}]
and I want to search for an item medicineID to make a compression
how can I do this
this my code
var extractMap = cubit.myItems.map(
(element) => Map.fromEntries(
[MapEntry('medicine_id', element['medicineID']),])).toList();
if(
extractMap.contains(
cubit.onePharmacyModel!.data!.activeMedicines![index].id!.toInt())
){
cubit.updateQuery(
++cubit.myItems[index]["quantity"],
cubit.myItems[index]['id'],
cubit.onePharmacyModel!.data!.id!.toInt()
);
Fluttertoast.showToast(msg: "cart updated");
}else{
cubit.insertToDatabase(
title: cubit.onePharmacyModel!.data!.activeMedicines[index].name.toString(),
price: cubit.onePharmacyModel!.data!.activeMedicines[index].pivot!.price!.toString(),
image: cubit.onePharmacyModel!.data!.activeMedicines[index].photo.toString(),
quantity: 1,
pharmacyID: cubit.onePharmacyModel!.data!.id!.toInt(),
medicineID: cubit.onePharmacyModel!.data!.activeMedicines[index].id!.toInt());
Fluttertoast.showToast(msg: "product added to cart");
}
the general idea of code that the user when add a product to the cart I'm checking if it's already exist or not if yes => I'll update the amount of this product, if no => T'll insert it into my Database
Try something like:
if (myItems.any((e) => e['medicineID'] == 58)) {
// ...
}
How do I write a message to Mattermost using Fastlane ?
Below is my trial. I got most from this link.
What is still wrong ?
(of course, I replaced the MATTERMOST_WEBHOOK_URL by the actual value that I established in Mattermost).
In the link above, I saw an actions folder with a mattermost.rb file
How do I get this action to work ? What do I need to do inside my Fastfile or anywhere in order to get this to work ?
In fact, running the fastlane send_message lane, I get a success. But unfortunately, nothing is visible in my Mattermost channel.
Inside my Fastfile, I do:
def send_message_to_mattermost(options)
unless ENV['MATTERMOST_WEBHOOK_URL'].nil? || ENV['MATTERMOST_WEBHOOK_URL'].empty?
mattermost(
pretext: options[:pretext],
message: options[:msg],
default_payloads: options[:default_payloads],
username: 'Fastlane',
icon_url: 'https://s3-eu-west-1.amazonaws.com/fastlane.tools/fastlane.png',
payload: {},
attachment_properties: {
title: options[:title],
thumb_url: options[:thumb_url],
fields: [{
title: 'Version',
value: options[:version_number],
short: true
},
{
title: 'Build Number',
value: options[:build_number],
short: true
},
{
title: 'Built by',
value: 'Jenkins',
short: true
}]
},
success: options[:success]
)
end
end
And my Fastlane lane looks like this:
lane :send_message do
send_message_to_mattermost({
:version_number => ENV['VERSION_NUMBER'],
:build_number => ENV["BUILD_NUMBER"],
:pretext => ENV['MAIN_APP_IDENTIFIER'],
:title => 'Unsuccessful Build',
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
:msg => "My message...",
:default_payloads => [:lane],
:success => true
})
end
Is mattermost(...) a standard command in Fastlane ? If not what do I need to do in order to send information to a Mattermost channel from Fastlane ?
I finally found a solution.
What was missing is to set the ENV["MATTERMOST_WEBHOOK_URL"] upfront
before_all do
ENV["MATTERMOST_WEBHOOK_URL"] = 'https://my_new_webooh_from_mattermost'
end
...and leave the following code intact (i.e. do not replace 'MATTERMOST_WEBHOOK_URL' by anything else - the before_all does the trick...)
def send_message_to_mattermost(options)
unless ENV['MATTERMOST_WEBHOOK_URL'].nil? || ENV['MATTERMOST_WEBHOOK_URL'].empty?
mattermost(
pretext: options[:pretext],
message: options[:msg],
default_payloads: options[:default_payloads],
username: 'Fastlane',
icon_url: 'https://s3-eu-west-1.amazonaws.com/fastlane.tools/fastlane.png',
payload: {},
attachment_properties: {
title: options[:title],
thumb_url: options[:thumb_url],
fields: [{
title: 'Version',
value: options[:version_number],
short: true
},
{
title: 'Build Number',
value: options[:build_number],
short: true
},
{
title: 'Built by',
value: 'Jenkins',
short: true
}]
},
success: options[:success]
)
end
end
I am using cards to show output to the user. I can only be able to show maximum of two chat bubbles and one card. But i want to add more than one card to the intent response in the webhook. I am using nodejs webhook using actions-on-google npm module, is there a way i can add more than one card in the response in single turn?
My use case is, i want to show multiple images in the response.
No, it is not. Basic Card can be only rich response element on response. If you want to show more than one element you may consider to use Table Card element.
Here is the all fields you can use with Table Card. You can remove some of fields.
conv.ask(new Table({
title: 'Table Title',
subtitle: 'Table Subtitle',
image: new Image({
url: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
alt: 'Alt Text'
}),
columns: [
{
header: 'header 1',
align: 'CENTER',
},
{
header: 'header 2',
align: 'LEADING',
},
{
header: 'header 3',
align: 'TRAILING',
},
],
rows: [
{
cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'],
dividerAfter: false,
},
{
cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
dividerAfter: true,
},
{
cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
},
],
buttons: new Button({
title: 'Button Text',
url: 'https://assistant.google.com'
}),
}))
Also, you can use Carousel or Browsing Carousel for multiple cards with touch selection option. But, don't forget, you need use these element with option response or web urls.
For more information:
Google Assistant Responses
I have seen most of the examples related to how to return rich content via webhooks involving just basic response and Card.
https://github.com/dialogflow/fulfillment-webhook-nodejs/blob/master/functions/index.js
What's the structure needed in dialogflow webhook V2 response to return either List or Carousel?
If you want to incorporate carousels and lists with Dialogflow, you'll need to import the actions-on-google module, as not all rich responses are supported by Dialogflow alone. You can see on the Actions on Google Rich Responses reference docs. Also there's a Fulfillment-Actions on Google sample
const { WebhookClient } = require('dialogflow-fulfillment');
const { Carousel } = require('actions-on-google');
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
[SELECTION_KEY_ONE]: {
synonyms: [
'synonym of title 1',
'synonym of title 2',
'synonym of title 3',
],
title: 'Title of First Carousel Item',
description: 'This is a description of a carousel item.',
image: new Image({
url: IMG_URL_AOG,
alt: 'Image alternate text',
}),
},
// Add the second item to the carousel
[SELECTION_KEY_GOOGLE_HOME]: {
synonyms: [
'Google Home Assistant',
'Assistant on the Google Home',
],
title: 'Google Home',
description: 'Google Home is a voice-activated speaker powered by ' +
'the Google Assistant.',
image: new Image({
url: IMG_URL_GOOGLE_HOME,
alt: 'Google Home',
}),
},
// Add third item to the carousel
[SELECTION_KEY_GOOGLE_PIXEL]: {
synonyms: [
'Google Pixel XL',
'Pixel',
'Pixel XL',
],
title: 'Google Pixel',
description: 'Pixel. Phone by Google.',
image: new Image({
url: IMG_URL_GOOGLE_PIXEL,
alt: 'Google Pixel',
}),
},
},
}));
OK, I have a great confusion about data binding in SAPUI5.
After reading this and this info I still don't know why my code doesn't work.
I define the data and the model in onInit function of the controller:
var oControlsData = {
controls: [
{control: [
{title: "Input Filed"},
{visible: true},
{iconUrl: "sap-icon://edit"}
]},
{control :[
{title: "Combo Box"},
{visible: true},
{iconUrl: "sap-icon://edit"}
]},
{control :[
{title: "Radio Button"},
{visible: true},
{iconUrl: "sap-icon://bo-strategy-management"}
]}
]
};
var oControlsModel = new sap.ui.model.json.JSONModel(oControlsData);
sap.ui.getCore().setModel(oControlsModel, "controls");
Then, in onAfterRendering function I try to bind data from the model to the sap.m.List control:
var oList = sap.ui.getCore().byId("controlsList");
var oListTemplate = new sap.m.StandardListItem({
title: "{title}",
visible: "{visible}",
icon: "{iconUrl}"
});
oList.bindItems({
path: "controls>/controls/control",
template: oListTemplate
});
It seems to me the path is correct, but I still get "No Data" in the control.
What went wrong here?
If I miss something big in understanding data binding process, please give a brief explanation, because every time I have to play with data binding I wonder if it work or not.
The path in bindItems should be the path to the list of Items.
So in your case controls>/controls.
The paths of the properties of the ListItem should then be relative to each object in the list.
sap.ui.getCore().byId("controlsList").bindItems({
path: "controls>/controls",
template: new sap.m.StandardListItem({
title: "{controls>control/0/title}",
visible: "{controls>control/0/visible}",
icon: "{controls>control/0/iconUrl}"
})
});
You need the control/0/ because of your inner array. If you have control over the structure of your data, I would recommend to remove that.
var oControlsData = {
controls: [
{
title: "Input Filed",
visible: true,
iconUrl: "sap-icon://edit"
},
...
]
};
On a sidenote, why are you doing databinding in onAfterRendering?
This should be done in the View. For example in XML:
<List items="{controls>/controls}">
<StandardListItem title="{controls>control/0/title}" visible="{controls>control/0/visible}" icon="{controls>control/0/iconUrl}" />
</List>