Image not displaying in table response in actions on Google - dialogflow-es

conv.ask(new Table({
title: 'Emissions due to different gases',
// subtitle: 'Table Subtitle',
image: new Image({
uri: 'https://www.scienceabc.com/wp-content/uploads/2015/05/Walking-in-Rain.jpg',
alt: 'Emissions Image'
}),
columns: [
{
header: 'CO2',
align: 'CENTER',
},
{
header: 'CH4',
align: 'CENTER',
},
{
header: 'N20',
align: 'CENTER',
},
],
rows: [
// {
// cells: [carbonEmission, methaneEmission, nitrousEmission],
// dividerAfter: true,
// },
{
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: 'Read More',
url: 'https://assistant.google.com'
}),
I have added this code, I am able to see the table with the given fields but the image is not coming up in the table instead I am getting this error even when the image is https URL.
MalformedResponse
expected_inputs[0].input_prompt.rich_initial_prompt.items[1].table_card.image: the protocol must be http or https.

I believe the issue is that the property inside the Image class should probably be called url and not uri.

Related

Why are my row/cell changes in Tabulator applied to both old and new rows/cells?

I am attempting to react to a cellEdited event in Tabulator by: (a) copying the modified row to a new row; and (b) restoring the cell value in the modified row.
My Tabulator instance is coded as follows:
function TabulatorInvitees(divId, companyName) {
try {
var table = new Tabulator(divId, {
columns: [
{
title: "<div style='width:20%; float:left; text-align:left; color:blue; font-size:14px;'>Vendor Invitees</div>",
columns: [
{ title: "DbId", field: "DbId", visible: true },
{ title: "Added", field: "Added", visible: true },
{ title: "Changed", field: "Changed", visible: true },
{ title: "Marked For Exclusion", field: "MarkedForExclusion", visible: true },
{
title: "Email Address",
field: "Email",
widthGrow: 1,
responsive: 0,
hozAlign: "center",
editor: "input",
visible: true,
cellEdited: function (cell) {
// When an email address has been changed the former record needs to be marked for exclusion and a new record needs to be added.
// Step #1: Copy the edited row to a new row and modify the [DbId] and [Added] columns.
let refTable = cell.getTable();
let row = cell.getRow();
refTable.addRow({}, true).then((newRow) => {
newRow.update(row.getData()); // Paste a copy of the data from the edited row.
newRow.update({ DbId: 0, Added: true });
})
// Step #2: Restore the original value to the edited row.
cell.restoreOldValue();
}
},
{
title: "First Name",
field: "FirstName",
widthGrow: 0.5,
responsive: 1,
hozAlign: "center",
editor: "input",
visible: true,
cellEdited: function (cell) {
cell.getRow().update({ Changed: true });
}
},
{
title: "Last Name",
field: "LastName",
widthGrow: 0.5,
responsive: 1,
hozAlign: "center",
editor: "input",
visible: true,
cellEdited: function (cell) {
cell.getRow().update({ Changed: true });
}
}
]
},
{
title: tabulatorAddUserIcon(companyName),
field: "ManageRows",
widthGrow: 0.25,
responsive: 2,
hozAlign: "center",
formatter: "tickCross",
headerClick: function (e, row) {
row.getTable().addRow({ DbId: 0, Added: true }, false);
},
cellClick: function (e, cell) {
tabulatorFreezeUnfreezeDelete(cell.getRow());
}
},
],
data: [],
height: "100%",
layout: "fitColumns", // required when using 'widthGrow'
placeholder: tabulatorPlaceholder(companyName), //display message to user on empty table
reactiveData: true, //enable reactive data
responsiveLayout: "collapse",
rowContextMenu: tabulatorContextMenu(),
});
table.on("rowTapHold", function (e, row) {
// from Tabulator documentation: "The rowTapHold event is triggered when a user taps on a row on a touch display and holds their finger down for over 1 second."
//e - the tap event object
tabulatorContextMenu();
});
table.on("tableBuilt", function () {
if (companyName.length > 0) {
table.setData(getDataSync({ caseSelector: "VendorMgmt_EmployeeList", companyCode: companyName, userEmail: graphMail }));
}
else {
table.setData([]);
}
});
}
catch (error) {
console.log(error);
}
}
Specifically, any time an [Email Address] is edited the original version must be preserved and marked as excluded. My remedy is to copy the edited version of the row into a new Tabulator row then reverse the edits to the original row (thus preserving its contents).
The following screenshot shows the initial state of the Tabulator instance after data has been retrieved from a local database using the setData() method.
The following screenshot shows the original [Email Address] (jane.doe#gmail.com) having been modified (jane.doe#yahoo.com):
The anticipated behavior is that a new record will be inserted into the table (jane.doe#yahoo.com) and the edited row will be restored using the restoreOldValue() method.
By removing the restoreOldValue() method, I can readily see the contents of the modified row have been copied to a new row. So far, so good....
The new row is added with the new [Email Address], as anticipated.
My problem arises when the restoreOldValue() method is invoked on the [Email] cell of the edited row. The restored/original value is applied to both the new row and the edited row, as follows:
Instead of having a new row for "jane.doe#yahoo.com" and an original row for "jane.doe#gmail.com" I now have two rows for "jane.doe#gmail.com".
I feel as though there should be a simple fix but I have yet to find it. Any assistance is greatly appreciated.

Why is the Tabulator getRows() function not working?

This seems like the simplest of requests but I can't seem to retrieve a set of rows from a Tabulator object.
Here's the code which instantiates the Tabulator object.........
function TabulatorInvitees(divId, companyName, userEmail) {
try {
var table = new Tabulator(divId, {
columns: [
{
title: "<div style='width:20%; float:left; text-align:left; color:blue; font-size:14px;'>Vendor Invitees</div>",
columns: [
{ title: "Id", field: "Id", visible: false },
{ title: "Added", field: "Added", visible: false },
{ title: "Changed", field: "Changed", visible: false },
{ title: "MarkedForExclusion", field: "MarkedForExclusion", visible: false },
{ title: "Email Address", field: "Email", widthGrow: 1, responsive: 0, hozAlign: "center", editor: "input", visible: true },
{ title: "First Name", field: "FirstName", widthGrow: 0.5, responsive: 1, hozAlign: "center", editor: "input", visible: true },
{ title: "Last Name", field: "LastName", widthGrow: 0.5, responsive: 1, hozAlign: "center", editor: "input", visible: true }
]
},
{
title: tabulatorAddUser(companyName),
field: "ManageRows",
widthGrow: 0.25,
responsive: 2,
hozAlign: "center",
formatter: "tickCross",
headerClick: function (e, row) {
row.getTable().addRow({ Id: 0, Added: true }, false);
},
cellClick: function (e, cell) {
tabulatorFreezeUnfreezeDelete(cell.getRow());
}
},
],
data: [],
height: "100%",
layout: "fitColumns", // required when using 'widthGrow'
placeholder: tabulatorPlaceholder(companyName), //display message to user on empty table
reactiveData: true, //enable reactive data
responsiveLayout: "collapse",
rowContextMenu: tabulatorContextMenu(),
});
table.on("rowTapHold", function (e, row) {
// from Tabulator documentation: "The rowTapHold event is triggered when a user taps on a row on a touch display and holds their finger down for over 1 second."
//e - the tap event object
//row - row component
tabulatorContextMenu();
});
table.on("tableBuilt", function () {
if (companyName.length > 0) {
table.setData(getDataSync({ caseSelector: "VendorMgmt_EmployeeList", companyCode: companyName, userEmail: userEmail }));
}
else {
table.setData([]);
}
});
}
catch (error) {
console.log(error);
}
}
The setData() function makes a call to a database function which returns three rows, similar to the following:
The following JQuery function is called when a radio button is clicked....
$(".vendorStatus").click(function (e) {
const status = e.target.value;
const tbls = Tabulator.findTable("#divVendorEmployees");
const tbl = tbls[0];
const tblRows = tbl.getRows();
console.log("tbls.length", tbls.length);
console.log("tblRows", tblRows);
});
The browser console indicates a table has been found (tbls.length = 1) but the tblRows array is empty:
I see the three rows in my Tabulator but I am not able to recall them programmatically. It seems like a simple problem which should have a simple answer.
I am using the most recent version of Tabulator (v5.4).
Any assistance is greatly appreciated.
After much searching, I finally came to the realization the DOM element associated with the Tabulator instance must be managed when attempting to refresh or replace data. I've implemented a method which allows me to delete and rebuild the DOM element each time I need to save data to my database and subsequently refresh my Tabulator instance.
Here's the code...
function refreshTabulatorObject(obj) {
let parentId = obj.parentId;
let childId = obj.childId;
//Empty and remove the current version of the [Tabulator] object.
const tables = Tabulator.findTable(childId);
if (tables.length > 0) {
var table = Tabulator.findTable(childId)[0];
table.setData([]);
}
//Remove the existing <div> from the DOM.
$(childId).remove();
//Re-create the <div> element for the [Tabulator] object and append it to the DOM.
var parentDiv = document.getElementById(parentId);
parentDiv.innerHTML = "";
var childDiv = document.createElement("div");
childDiv.setAttribute("id", childId);
parentDiv.appendChild(childDiv);
//Re-create the [Tabulator] object.
TabulatorInvitees("#" + childId, obj.companyName);
}
I'm sure those of you with a more intimate knowledge of Tabulator would likely suggest a more elegant method, however, this one appears to work and I've already spent far more time on this issue that I had anticipated. Unfortunately, elegance is not a luxury I can afford at this point.
I hope this solution might be of help to some other struggling soul.

Querying a sub document of a sub document in mongoose

Inside my parent I have many childs and in one of them childs they also have many sub childs, I need to return the sub childs from a specific child.
exports.test = (req, res) => {
Forum.find({title: req.params.id}).then(record => {
console.log(record);
})
};
The code here returns the following when I insert the News & Announcement url param which is correct:
_id: 5e7bf52ebb5b2b09fb46e29f,
title: 'News & Announcements',
property: 'ACP',
position: 1,
visible: true,
topics: [ [Object], [Object], [Object] ],
__v: 5 } ]
I then want to access the topics and return a specific topic - finding it by a name/title as I did above, how would I do this?
If this topics field is an array of objects and each object contains the name and title, then you can search for the topic you want, just add that to the object you passed to the find query
for example, If you need to query for some topic with name 'My Topic', then the query should be
Forum.find({ title: req.params.id, 'topics.name': 'My Topic' })
this will narrow down the results of the query but if there are some other topics with different names in the same forum, they will be come with you in the query
for example, if some forum has the following info:
{
_id: ObjectId("5e7bf52ebb5b2b09fb46e29f"),
title: 'News & Announcements',
property: 'ACP',
position: 1,
visible: true,
topics: [
{
name: 'Topic 1',
title: 'Title 1'
}, {
name: 'Topic 2',
title: 'Title 2'
}, {
name: 'My Topic',
title: 'My Title'
}
],
}
and you search for the topic 'My Topic' only in this forum, all the topics array will be returned from the query, as the search is done per documents
so you have to do some javaScript trick after finishing the query to get only the topic that has the name you wanted
var myTopic = record.ropics.filter(topic => topic.name === 'My Topic'}
this will return the topic you wanted only

Multiselect search whole string

I have a multiselect with search bound to a store (with attribute string_value). Search only searches strings that start with "string to search" instead of contains "string to search" (similar to searching for '%string%' instead of 'string%'). Is there a way to do this by extending 'multiselector-search'?
Below is my multiselector control bound to a form:
var ms = Ext.widget('form', {
xtype: 'multi-selector',
width: 400,
height: 300,
requires: [
'Ext.view.MultiSelector'
],
layout: 'fit',
renderTo: Ext.getBody(),
items: [{
bbar: [{
xtype: 'button',
itemId: 'button',
html: 'Toolbar here',
text: 'Submit request to API',
// get submitted array
handler: function() {
if (cardioCatalogQT.config.mode === 'test') {
console.log('In submitted values handler: ');
}
var submitted = Ext.getCmp('test');
var dx = [];
Ext.Array.each(submitted.store.data.items, function (item) {
dx.push(item.data.string_value);
}); // each()
Ext.Msg.alert('Submitted Values',
'The following diagnoses will be sent to the server: <br
/>' + dx);
if (cardioCatalogQT.config.mode === 'test') {
console.log(dx);
}
}
}],
xtype: 'multiselector',
title: 'Selected Dx',
id: 'test',
name:'test',
fieldName: 'string_value',
viewConfig: {
deferEmptyText: false,
emptyText: 'No Dx selected'
},
// TODO: fix ability to remove selected items when box is unchecked
search: {
field: 'string_value',
store: 'Diagnoses'
}
}]
}).center();
The closest I could find to this problem was http://www.sencha.com/forum/showthread.php?240887. I tried making it work with the multiselect search with no success.
The MultiSelector uses the Ext.util.Filter to narrow the results based on the typed text. You need to enable the anyMatch property for it to match anywhere.
To do that, you'll have to include a new "search" function in your multiselector's search object that will have anyMatch=true.
Please see my fiddle, https://fiddle.sencha.com/#fiddle/jf5, for an example of how to do this.

Using image and carousel on the same panel in sencha touch

I am new in sencha touch and need to achieve this layout on a single simple page:
I need an image and below the image, there should be a carousel containing two another images which the user can swipe.
Here is my code:
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
// Create a Carousel of Items
var carousel1 = new Ext.Carousel({
defaults: {
cls: 'card'
},
items: [{
html: "<img src='teil1.jpg' width='320' height='60' alt='' border='0'>"
},
{
html: "<img src='teil2.jpg' width='320' height='60' alt='' border='0'>"
}
]
});
var panel = new Ext.Panel({
fullscreen: true,
html: "<img src='sport1_top.jpg' width='320' height='302'>"
});
new Ext.Panel({
fullscreen: true,
layout: {
type: 'vbox',
align: 'stretch'
},
defaults: {
flex: 1
},
items: [panel, carousel1]
});
}
});
The carousel and the panel containing the first image are displayed on the same portion of the page.
Am I missing something?
Thanks for your interest.
leon.
Removing the
fullscreen: true
from the sport1_top panel worked for me
Mark
This problem was nagging me too. After trying everything I could think of, what appears to help was to get rid of all of those fullscreen properties except on the main Ext.Panel, and use "layout:'fit'" on all of the cards, which I added to my defaults in the Ext.Carousel object.
var toolbar = new Ext.Toolbar({ title: 'testing', dock: 'top'});
var around = new Ext.Carousel({
ui: 'dark',
direction: 'horizontal',
defaults: { cls: 'card', layout:'fit' },
items: [
{ html: 'card 1'},
{ html: 'card 2'},
{ html: 'card 3'},
{ html: 'card 4'},
]
})
var panel = new Ext.Panel({
fullscreen: true,
layout: {
type : 'fit',
align: 'top'
},
defaults: {
flex: 1
},
items: [ around ],
dockedItems: [ toolbar ]
});
panel.show();
I believe you have to use layout: 'fit' for your Carousel (In your Panel, instead of vbox). Or you could make another panel SubPanel that has your vbox and that SUbPanel({layout: 'fit'});
I came across the same problem, I believe this works.
GL

Resources