When I try to create a carousel dynamically in dialogflow it appears vertically and with two items per row.
This is for a Google assistant application, the actions on Google documentation say that the carousel scrolls horizontally, but I can't make it happen.
for (let i = 0; i < data_JSON.length; i++) {
let name;
let imageurl;
let venue;
name = datosJSON[i].nombre_evento
imageurl = datosJSON[i].nombre_imagen;
venue = name;
items[i] = {
optionInfo: {
key: (i + 1).toString(),
synonyms: name,
},
description: "Imagen "+i,
title: name,
url: imageurl,
image: new Image({
url: imageurl,
alt: venue
}),
}
}
var carrusel = new Carousel({
title: 'Search Items ',
items: items
});
conv.ask(carrusel);
});
I expect in Google assistant only one row which I can scroll horizontally, but I have multiple rows with 2 items per row.
Carousel displays horizontally on smart displays, but uses the 2xN grid on phones.
Related
I am having issues posting an image of a Pokémon when command is used
const { Message, Client, MessageEmbed, MessageAttachment } = require("discord.js");
const {Ecolor} = require("../../embeds.js")
pokemon = require('../../db/pokemon.js')
module.exports = {
name: "pokeinfo",
description: "Shares Information about specified Pokemon of the game",
run: async (client, message, args) => {
let pkmn = message.content.toLowerCase().split("!pokeinfo ")[1]
for(var i=0;i<pokemon.length;i++){
if(pkmn == pokemon[i]._engName.toLowerCase()){
let Embed = new MessageEmbed()
.setColor(`${Ecolor.pink}`)
.setTitle(`Details about ${pokemon[i]._engName} :`)
.setDescription(`Dex number - ${pokemon[i]._nb}`)
.setThumbnail('https://imgur.com/Q6WZOoU.png')//https://imgur.com/Q6WZOoU.png
.addFields(
{name: 'Rarity:', value:`${pokemon[i]._rare}`, inline: true },
{name: 'Evolution Chart:', value:`${pokemon[i]._evo}`, inline: true },
{name: 'Location:', value:`${pokemon[i]._loc}`, inline: false },
{name: 'Ev Yield:', value:`${pokemon[i]._ev}`, inline: true },
{name: 'Ability:', value:`${pokemon[i]._ability}`, inline: true },
{name: '__Base Stats__:', value:
`
**HP** : ${pokemon[i]._baseStats._hp}
**Atk** : ${pokemon[i]._baseStats._atk}
**Def** : ${pokemon[i]._baseStats._def}
**S. Atk** : ${pokemon[i]._baseStats._sAtk}
**S. Def** : ${pokemon[i]._baseStats._sDef}
**Speed** : ${pokemon[i]._baseStats._spd}
**Total** : ${pokemon[i]._baseStats._total}
**Growth Rate** : ${pokemon[i]._gr}
**Type** : ${pokemon[i]._ty}
`, inline: false },
);
message.channel.send({ embeds: [Embed] });
}
}
},
};
if simplisty were just gonna use 1 pokemon below is the info being called
{
_nb:1,_engName:"Bulbasaur",_rare:"N/A",
_evo:"Bulbasaur lvl 16 | Ivysaur lvl 36 | Venusaur | Mega",
_loc:"Starter ",
_ev:"1 SpA",
_ability:"Overgrow, *Chlorophyll(HA)",
_baseStats: {_total:318,_hp:45, _atk:49, _def:49, _sAtk:65, _sDef:65, _spd:45},
_gr:"Medium Slow",_ty:"Grass/Poison"
_pho: "bulbasaur.png"
i have changed .setThumbnail('https://www.pokemon.com/us/pokedex/' + ${pokemon[i]._pho}) and in the second file added _pho: bulbasaur.png
as when that is all together is will take you to https://www.pokemon.com/us/pokedex/bulbasaur.png.
I'm just trying to set a thumbnail to display the Pokémon that is being searched for. and I'm not able to figure it out.
when I use the pokemon.com..... and hover over the image after I call the command it displays the link but not the image, if click on the thumbnail image (which is a pile of poo) it will take me to the correct page, but again the image on the bot command is not showing.
If you are looking to display the Pokémon in the Thumbnail, the URL you should give is the URL that takes you to the image and not the URL where you see the Pokémon information.
The direct URL of the image can be obtained by right clicking -> Copy address/image link.
In the case of Bulbasaur, the URL of its image is: https://assets.pokemon.com/assets/cms2/img/pokedex/full/001.png and not https://www.pokemon.com/us/pokedex/bulbasaur.png
A quick and probably functional solution would be to dynamically obtain the URL of the Pokémon images according to their number in the pokedex, as it seems that in the assets they are stored/differentiated by number and not by names.
.setThumbnail(`https://assets.pokemon.com/assets/cms2/img/pokedex/full/${pokemon[i]._nb}.png`)
I feel like I'm missing something obvious here, but I've been stuck on this for a couple of days and just can't seem to find the answer.
1.) I'm using a separate swift file with an Identifiable Struct that has an object with 2 of the Struct properties, name & categoryName. (side note, I'm using var instead of let in the object because the rows can't be rearranged with the .onMove modifier as a constant)
//STRUCT
struct Item: Identifiable {
var id = UUID()
var name: String
var categoryName: String
}
//OBJECT
var items : [Item] = [
//CLOTHING
Item(name: "Hats", categoryName: "Clothing"),
Item(name: "Shirts", categoryName: "Clothing"),
Item(name: "Pants", categoryName: "Clothing"),
//Electronics
Item(name: "Macbook", categoryName: "Electronics"),
Item(name: "Macbook Adapter", categoryName: "Electronics"),
Item(name: "iPhone", categoryName: "Electronics"),
]
2.) In a swiftui file I have this code to build the list, using a nested ForEach loop to pull the categoryName, add it to the Section header, then another to loop out the items.
//List code
NavigationView {
List {
ForEach(items) { currentItem in
Section(header: Text(currentItem.categoryName)){
ForEach(items) { currentItem in
NavigationLink(destination: ItemDetail(itemData: currentItem)){ ItemRow(item: currentItem)
}
}
Unfortunately what I get is a laughable result.
I get my categoryName in the section header and I get my items listed below it. Actually, I get ALL of the items listed below it, regardless of category. Then in a very confusing fashion the sections will print out exactly as many times as the rows in my object array.
In this instance I have 6, so I get 6 rows. Yet, of the 2 categoryName strings "Clothing" and "Electronics", they'll print out 3 times each.
It feels like there's a simple way to do "for each categoryName in items.categoryName add a title to the section and list the corresponding name" - but I'm not cracking this one.
Hoping someone here can point out what I'm doing wrong.
You have flat array and just iterate though it several times, so result is also flat multiplied several times.
Ok, for model you selected, ie items, the result you tried to accomplish can be reached with the following...
List {
ForEach(Array(Set(items.compactMap{ $0[keyPath: \.categoryName] })), id: \.self) { category in
Section(header: Text(category)) {
ForEach(items.filter { $0.categoryName == category }) { currentItem in
NavigationLink(destination: Text("ItemDetail(itemData: currentItem)")){ Text("\(currentItem.name)") }
}
}
}
}
.listStyle(GroupedListStyle())
However I would select different model for items, ie. dictionary as [categoryName: Item]
You can group your array by category:
let sections = Dictionary(grouping: items) { $0.categoryName }
Then you can use it like:
var keys: [String] = { sections.map {$0.key} }
var body: some View {
List {
ForEach(keys, id: \.self) { section in
Section(header: Text(section)){
ForEach(self.sections[section] ?? []) { currentItem in
Text(currentItem.name)
}
}
}
}
}
Note that I have simplified your code to run on my machine but changes are not effecting the answer
I create a chat bot using dialogflow and actions on google library. In the back-end code I have created function including if else. I added new suggestions in the "else if". That are not display in the actions on google simulator.Another suggestions are working. Only that time it is not displayed. Please give me some instructions for fixed that.
this is my code:
'use strict';
const functions = require('firebase-functions');
const {
dialogflow,
Suggestions,
Carousel,
Image,
Table,
List,
} = require('actions-on-google');
const app = dialogflow({debug: true});
// Constants for list and carousel selection
const Order_Food = 'order food';
const Extra_Product = 'extra product';
const Spa_Reservation = 'spa reservation';
const Restaurant_Booking = 'restaurant booking';
app.intent('user.provide_room_number', (conv) => {
conv.ask('Great! I can help you with the following. Please select
from the options below.');
//conv.ask(new Suggestions('Order Food', 'Extra Product',
'Restaurant', 'Spa'));
// Create a carousel
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
[Order_Food]: {
synonyms: [
'order food',
'food',
],
title: 'Food',
description: 'Can order some food',
image: new Image({
url: 'http://www.restauranteelpalacete.com/wp-content/uploads/2018/01/Online-Food-Ordering.jpg',
alt: 'Food',
}),
},
// Add third item to the carousel
[Spa_Reservation]: {
synonyms: [
'spa',
'spa reservation',
],
title: 'Spa Reservation',
description: 'Can put the reservation on the spa.',
image: new Image({
url: 'https://res.klook.com/images/fl_lossy.progressive,q_65/c_fill,w_1295,h_720,f_auto/w_80,x_15,y_15,g_south_west,l_klook_water/activities/kykzulvt1t71kwhnmkik/OasisSpa.jpg',
alt: 'Spa',
}),
},
// Add fourth item to the carousel
[Restaurant_Booking]: {
synonyms: [
'restaurant',
'restaurant booking',
],
title: 'Restaurant',
description: 'Can put the reservation on the Restaurant.',
image: new Image({
url: 'https://cdn-image.foodandwine.com/sites/default/files/1501607996/opentable-scenic-restaurants-marine-room-FT-BLOG0818.jpg',
alt: 'Restaurant',
}),
},
},
}));
});
app.intent('actions_intent_OPTION-handler', (conv, params, option) => {
// Get the user's selection
// Compare the user's selections to each of the item's keys
if (!option) {
conv.ask('You did not select any item from the list or carousel');
} else if (option === 'order food') {
conv.ask(new SimpleResponse({speech:"Absolutely, have you decided what you like or you could go through the in room dinning menu. \n Do you need order Food.?",text:"Absolutely, have you decided what you like or you could go through the in room dinning menu. Do you need order Food.?"}));
conv.ask(new Suggestions(["Ok", "Done", "Thanks"]));
} else if (option === 'spa reservation') {
conv.ask(new Suggestions('Yes I need Spa.'));
conv.ask(`We have an excellent Spa that offer exquisite treatment packages. You can select one of the options. We have quite a few free slots today. Do you need information about that.`);
} else if (option === 'restaurant booking') {
conv.ask(`We have some dining options for you today. Do you want more information. `);
conv.ask(new Suggestions('I need restaurant.'));
} else {
conv.ask('You selected an unknown item from the list, or carousel');
}
});
You should design your conversation bot more efficiently.In second elseif condition, after a suggestion no further conversation should happen in an intent.Suggestion are for triggering intent. For your case best scenario would be to create a follow up intent.
Suggestion is not appearing in conversation because, in every rich response at least one simple response should be present. Try below code. Hope this helps you.
conv.ask(new SimpleResponse({speech:"Absolutely, have you decided what you like or you could go through the in room dinning menu. \n Do you need order Food.?",text:"Absolutely, have you decided what you like or you could go through the in room dinning menu. Do you need order Food.?"}));
conv.ask(new Suggestions(["Ok", "Done", "Thanks"]));
I am building using Node Google Actions client library version 2 to create a dynamic list using forEach or any other iterator in Node. Before I plough on does addList work with version 2 and if so does anyone have an example.
Hope someone can help but if not will do it myself and post up.
ditto for Carousel BTW but that should be very similar
Here is an example:
let items = {};
let array = ['first', 'second', 'third'];
array.forEach(element => {
items[element] = {
title: element,
image: new Image({
url: "url",
alt: "alt image title"
})
)}
})
conv.ask("List")
conv.ask(new List({
title: 'List',
items: items
)};
Hi guys
I am try to research Yahoo lib- grid. I created a button to display grid. But when i click button N times -> it is displayed N grids. I only want display one grid and after click button it will get data from server again. My code like below:
Please help me., Thank you.
YUI({ filter: 'raw' }).use("jsonp", "node",function (Y) {
function handleJSONP(response) {
// Y.one("#out").setContent(Y.Lang.sub(template, response.user));
YUI().use("datatable-base", function(Y) {
var cols = [
{ key: "id", label: "Transaction No", abbr: "id"},
{ key: "userName", label: "User Name", abbr: "userName"},
{ key: "storeName", label: "StoreName", abbr: "storeName"}
],
data = response.Root,
dt = new Y.DataTable.Base({
columnset: cols,
recordset: data,
summary: "Price sheet for inventory parts",
caption: "These columns have labels and abbrs"
}).render("#example");
});
}
Y.one("#demo_btn").on("click", function (e) {
var url = "server.jsp"+ "?callback={callback}";
Y.jsonp(url, handleJSONP);
});
});
You should be using the DataSource utility to retrieve the data via JSONP. This will allow you to then reload the data via something like
dt.datasource.load();
See the docs for details: DataTable + DataSource.Get + JSON Data
Your handler needs to check if you've already created the table.
var dt;
if (dt === null) {
dt = new Y.DataTable.Base // etc.
}