I use bot to post cards with version 2 (сards_v2 property).
Cards are rendered as normal, but I want to add a Button to open Dialog. This does not work.
How can I achieve this?
I post to POST /v1/chat/channels/:channel_id/messages?
body:
{
"cards_v2": [{
"card": {
"header": {
"title": "Rolodex",
"subtitle": "Manage your contacts!",
"imageType": "CIRCLE",
"imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png"
},
"sections": [{
"widgets": [{
"buttonList": {
"buttons": [{
"text": "Add Contact",
"onClick": {
"action": {
"function": "openDialog",
"interaction": "OPEN_DIALOG"
}
}
}]
}
}]
}]
}
}]
}
Then I click on Button, and receive event:
{
"type": "CARD_CLICKED",
"eventTime": "2022-08-31T16:16:36.147391Z",
"message": {
"name": "spaces/:space_id/messages/YTyNVBNW-H4.YTyNVBNW-H4",
"sender": { ... },
"createTime": "2022-08-31T16:16:31.639439Z",
"thread": { ... },
"space": { ... },
"cardsV2": [{
"card": {
"header": {
"title": "Rolodex",
"subtitle": "Manage your contacts!",
"imageType": "CIRCLE",
"imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png"
},
"sections": [{
"widgets": [{
"buttonList": {
"buttons": [{
"text": "Add Contact",
"onClick": {
"action": {
"function": "openDialog"
}
}
}]
}
}]
}]
}
}],
"retentionSettings": {
"state": "PERMANENT"
}
},
"user": { ... },
"space": { ... },
"action": {
"actionMethodName": "openDialog"
},
"common": {
"hostApp": "CHAT",
"invokedFunction": "openDialog"
}
}
First: Event skips DialogEventType is REQUEST_DIALOG.
Second: When I respond with dialog response, but no dialog appears.
{
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"dialog": {
"body": {
"sections": [{
"header": "Add new contact",
"widgets": [{
"textInput": {
"name": "contactName",
"label": "Name",
"type": "SINGLE_LINE"
}
}, {
"buttonList": {
"buttons": [{
"text": "Next",
"onClick": {
"action": {
"function": "openSequentialDialog"
}
}
}]
}
}]
}]
}
}
}
}
}
I see only error:
I'm pretty sure the below can be done, I'm struggling to understand how to do it in MongoDB.
My data is structured like this (demo data):
db={
"recipes": [
{
"id": 1,
"name": "flatbread pizza",
"ingredients": {
"1010": 1,
"1020": 2,
"1030": 200
}
},
{
"id": 2,
"name": "cheese sandwich",
"ingredients": {
"1040": 1,
"1050": 2
}
}
],
"ingredients": [
{
"id": 1010,
"name": "flatbread",
"unit": "pieces"
},
{
"id": 1020,
"name": "garlic",
"unit": "clove"
},
{
"id": 1030,
"name": "tomato sauce",
"unit": "ml"
},
{
"id": 1040,
"name": "bread",
"unit": "slices"
},
{
"id": 1050,
"name": "cheese",
"unit": "slices"
}
]
}
The output I'm trying to achieve would look like this:
[
{
"id": 1,
"name": "flatbread pizza",
“flatbread”: “1 pieces”,
“garlic”: “2 cloves”,
“tomato sauce”: “200 ml”
},
{
"id": 2,
"name": "cheese sandwich",
“bread”: “1 slices”,
“cheese”: “2 slices”
}
]
I've tried several approaches, and I get stuck at the bit where I need to do a lookup based on the ingredient name (which actually is the id). I tried using $objectToArray to turn it into a k-v document, but then I get stuck in how to construct the lookup pipeline.
This is not a simple solution, and probably can be improved:
db.recipes.aggregate([
{
"$addFields": {
ingredientsParts: {
"$objectToArray": "$ingredients"
}
}
},
{
$unwind: "$ingredientsParts"
},
{
"$group": {
_id: "$id",
name: {
$first: "$name"
},
ingredientsParts: {
$push: {
v: "$ingredientsParts.v",
id: {
$toInt: "$ingredientsParts.k"
}
}
}
}
},
{
"$lookup": {
"from": "ingredients",
"localField": "ingredientsParts.id",
"foreignField": "id",
"as": "ingredients"
}
},
{
$unwind: "$ingredients"
},
{
"$addFields": {
"ingredientsPart": {
"$filter": {
input: "$ingredientsParts",
as: "item",
cond: {
$eq: [
"$$item.id",
"$ingredients.id"
]
}
}
}
}
},
{
$project: {
ingredients: 1,
ingredientsPart: {
"$arrayElemAt": [
"$ingredientsPart",
0
]
},
name: 1
}
},
{
"$addFields": {
units: {
k: "$ingredients.name",
v: {
"$concat": [
{
$toString: "$ingredientsPart.v"
},
" ",
"$ingredients.unit"
]
}
}
}
},
{
$group: {
_id: "$_id",
name: {
$first: "$name"
},
units: {
$push: "$units"
}
}
},
{
"$addFields": {
"data": {
"$arrayToObject": "$units"
}
}
},
{
"$addFields": {
"data.id": "$_id",
"data.name": "$name"
}
},
{
"$replaceRoot": {
"newRoot": "$data"
}
}
])
You can see it works here
As rickhg12hs said, it can be modeled better.
I'm trying to replicate this chart http://jsfiddle.net/edzk8Loe/ using vue js.
To be honest, I'm learning vuejs and so I'm trying to replicate already ready projects to get confident quickly.
The issue I'm facing at the moment I guess is a logic one. The functions have to create new series as drilldown when click on a column, seams not triggered at all. I'm not getting any error in the console and I'm
Not having yet a totally clear idea about the structure, I think I'm messing up the code. Hereunder you'll find the code I'm using in VUE.
<template>
<div class="chartElem">
<div class="row">
<highcharts class="chart" :constructor-type="'chart'" :options="chartOptions"></highcharts>
</div>
</div>
</template>
<script>
import HighchartsVue from "highcharts-vue";
import Highcharts from "highcharts";
import dataModule from "highcharts/modules/data";
import drilldown from "highcharts/modules/drilldown";
drilldown( Highcharts );
dataModule( Highcharts );
let drilldownChart, drilldownEvent, drilldownLevel = 0;
const chartOptions = {
chart: {
"type": "column",
},
credits: {
"enabled": false
},
plotOptions: {
column: {
stacking: "normal",
events: {
click: function ( event ) {
return false;
}
}
},
"series": {
"borderWidth": 0,
"dataLabels": {
"enabled": true,
"style": {
"textShadow": false,
"fontSize": "10px"
}
}
}
},
"legend": {
"enabled": false,
},
"yAxis": {
"stackLabels": {
"enabled": false,
"style": {
"fontWeight": "bold",
"color": "gray"
}
}
},
"title": {
"text": "Stacked Column Drilldown Chart",
"fontWeight": "bold"
},
"xAxis": {
"title": {},
"type": "category"
},
"yAxis": [ {
"title": {
"text": "Number of Students"
},
"min": 0,
"allowDecimals": false
} ],
"series": [ {
"name": "Outstanding",
"color": "rgb(102, 168, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 1,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Very Good",
"color": "rgb(128, 183, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Satisfactory",
"color": "rgb(179, 212, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 1,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Needs Improvement",
"color": "rgb(204, 226, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Not Performing",
"color": "rgb(230, 242, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
} ]
};
export default {
data: () => ( {
chartOptions,
drilldownChart,
drilldownEvent,
drilldownLevel
} ),
methods: {},
computed:{
drilldown: function ( e ) {
if ( !e.seriesOptions ) {
updateGraph( true, this, e );
}
},
drillup: function ( e ) {
if ( !e.seriesOptions.flag ) {
drilldownLevel = e.seriesOptions._levelNumber;
updateGraph( false );
}
}
},
mounted() {
function updateGraph( isDrilldown, chart, e ) {
if ( isDrilldown ) {
drilldownLevel++;
drilldownChart = chart;
drilldownEvent = e;
if ( drilldownLevel === 1 ) {
var drilldowns = {
'Social Science': {
name: 'Outstanding',
color: 'rgb(102, 168, 255)',
data: [ {
name: 'Geography',
y: 7,
drilldown: true
}, {
name: 'History',
y: 4
}, {
name: 'Civics',
y: 9
} ]
}
},
drilldowns2 = {
'Social Science': {
name: 'Very Good',
color: 'rgb(128, 183, 255)',
data: [ {
name: 'Geography',
y: 4,
drilldown: true
}, {
name: 'History',
y: 8
}, {
name: 'Civics',
y: 2
} ],
},
},
drilldowns3 = {
'Social Science': {
name: 'Satisfactory',
color: 'rgb(179, 212, 255)',
data: [ {
name: 'Geography',
y: 4,
drilldown: true
}, {
name: 'History',
y: 7
}, {
name: 'Civics',
y: 1
} ],
}
},
drilldowns4 = {
'Social Science': {
name: 'Needs Improvement',
color: 'rgb(204, 226, 255)',
data: [ {
name: 'Geography',
y: 2,
drilldown: true
}, {
name: 'History',
y: 7
}, {
name: 'Civics',
y: 2
} ]
}
},
drilldowns5 = {
'Social Science': {
name: 'Not Performing',
color: 'rgb(230, 242, 255)',
data: [ {
name: 'Geography',
y: 6,
drilldown: true
}, {
name: 'History',
y: 3
}, {
name: 'Civics',
y: 0
} ],
}
},
series = drilldowns[ e.point.name ],
series2 = drilldowns2[ e.point.name ],
series3 = drilldowns3[ e.point.name ],
series4 = drilldowns4[ e.point.name ],
series5 = drilldowns5[ e.point.name ];
chart.addSingleSeriesAsDrilldown( e.point, series );
chart.addSingleSeriesAsDrilldown( e.point, series2 );
chart.addSingleSeriesAsDrilldown( e.point, series3 );
chart.addSingleSeriesAsDrilldown( e.point, series4 );
chart.addSingleSeriesAsDrilldown( e.point, series5 );
chart.applyDrilldown();
} else if ( drilldownLevel === 2 ) {
var drilldown1 = {
"Geography": {
"name": "Yes",
stacking: 'percent',
color: 'red',
"data": [ {
"name": "Q1",
"y": 1
}, {
"name": "Q2",
"y": 2
}, {
"name": "Q3",
"y": 3
}, {
"name": "Q4",
"y": 4
} ]
}
};
var drilldown2 = {
"Geography": {
"name": "No",
stacking: 'percent',
color: 'green',
"data": [ {
"name": "Q1",
"y": 1
}, {
"name": "Q2",
"y": 2
}, {
"name": "Q3",
"y": 3
}, {
"name": "Q4",
"y": 4
} ]
}
};
var drilldown3 = {
"exampleDrilldown": {
type: 'line',
"name": "Example",
color: 'black',
"data": [ {
"name": "Q1",
"y": 10
}, {
"name": "Q2",
"y": 20
}, {
"name": "Q3",
"y": 30
}, {
"name": "Q4",
"y": 40
} ]
}
}
chart.addSingleSeriesAsDrilldown( e.point, drilldown1[ e.point.name ] );
chart.addSingleSeriesAsDrilldown( e.point, drilldown2[ e.point.name ] );
chart.addSingleSeriesAsDrilldown( e.point, drilldown3[ 'exampleDrilldown' ] );
console.log( e );
chart.applyDrilldown();
}
}
}
}
}
</script>
I'm not looking for someone is doing the task instead of me, I won't learn anything. Ideas and tips are super welcomed.
Cheers
You've made several simple mistakes in your code.
1) Add updateGraph function to chart methods - that way you can invoke this method in drilldown callback
2) Save chart component reference in the chart object to be able to use updateGraph method from drilldown callback function. You can make it using mounted() hook:
mounted() {
this.$children[0].chart.vueRef = this;
}
3) Data should be a function that returns an object with properties:
data() {
return {
chartOptions,
drilldownChart,
drilldownEvent,
drilldownLevel
}
}
4) Add drilldown and drillup callbacks to chart.events object. There you can invoke updateGraph method from the chart component reference saved in mounted hook:
chart: {
"type": "column",
events: {
drilldown: function(e) {
if (!e.seriesOptions) {
this.vueRef.updateGraph(true, this, e);
}
},
drillup: function(e) {
if (!e.seriesOptions.flag) {
this.vueRef.drilldownLevel = e.seriesOptions._levelNumber;
this.vueRef.updateGraph(false);
}
}
}
}
Demo:
https://codesandbox.io/s/2w513lwpw0
I am trying to filter same level object values in the payload in Dataweave. I was able to loop through but it does not produce the expected output.
Sample Payload:
{
"root": {
"createItem": {
"itemInfo": {
"lines": [{
"lineIdentifier": "4",
"Attributes": "Test1",
"partNumber": "QZRB"
}, {
"lineIdentifier": "10",
"Attributes": "Test3",
"partNumber": "QPR1"
}, {
"lineIdentifier": "12",
"Attributes": "Test4",
"partNumber": "QHT2"
}]
}
},
"ItemResponse": {
"lines": [{
"lineIdentifier": 4,
"itemName": "QZRB",
"status": "FAILED"
}, {
"lineIdentifier": 10,
"itemName": "QPR1",
"status": "COMPLETE"
}, {
"lineIdentifier": 12,
"itemName": "QHT2",
"status": "COMPLETE"
}]
}
}
}
Expected Output:
{
"root": {
"createItem": {
"itemInfo": {
"lines": [ {
"lineIdentifier": "10",
"Attributes": "Test3",
"partNumber": "QPR1"
}, {
"lineIdentifier": "12",
"Attributes": "Test4",
"partNumber": "QHT2"
}]
}
}
}
}
Here's what I am doing:
{
root: {
(payload.root.createItem.itemInfo.lines map ((respLines, indexOfRespLines) -> {
items:payload.root.ItemResponse.lines filter ($.itemName == respLines.partNumber and $.status =='COMPLETE') map
{
item: $.itemName,
attributes: respLines.Attributes
}
}
)
)
}
}
How do I achieve this?
Thanks,
ROA
try this:
%dw 1.0
%output application/json
%var completedLines = payload.root.ItemResponse.lines filter $.status == 'COMPLETE' map $.lineIdentifier as :string
---
{
root: {
createItem: {
itemInfo: {
lines: payload.root.createItem.itemInfo.lines filter (completedLines contains $.lineIdentifier)
}
}
}
}
pay attention to as :string in completedLines, because the lineIdentifier in ItemResponse is a number, while in itemInfo it is a string.
Now suppose I have a json data formation like this following:
{
"ServiceName": "cacheWebApi",
"Description": "This is a CacheWebApiService",
"IsActive": true,
"Urls": [{ "ServiceAddress": "http://192.168.111.210:8200", "Weight": 5, "IsAvailable": true },
{ "ServiceAddress": ",http://192.168.111.210:8200", "Weight": 3, "IsAvailable": true }]
}
Now what worries me is that the "Urls" is another nested json formation. So how to bind this value to the datatables? And have you got any good ideas (e.g:something like I only wanna show all the ServiceAddress)...
This should do what you need:
var data = [{
"ServiceName": "cacheWebApi",
"Description": "This is a CacheWebApiService",
"IsActive": true,
"Urls": [
{
"ServiceAddress": "http://192.168.111.210:8200",
"Weight": 5,
"IsAvailable": true
},
{
"ServiceAddress": ",http://192.168.111.210:8200",
"Weight": 3,
"IsAvailable": true
}
]
}];
$(function() {
var table = $('#example').dataTable({
"data": data,
"columns": [
{
"data": "ServiceName"
}, {
"data": "Description"
}, {
"data": "IsActive"
}, {
"data": "Urls[0].ServiceAddress"
}, {
"data": "Urls[0].Weight"
}, {
"data": "Urls[0].IsAvailable"
}, {
"data": "Urls[1].ServiceAddress"
}, {
"data": "Urls[1].Weight"
}, {
"data": "Urls[1].IsAvailable"
}
],
});
});
You should put your data in an array though. Working JSFiddle
EDIT
IF the number of Urls isn't defined then you could do something like this:
var table = $('#example').dataTable({
"data": data,
"columns": [
{
"data": "ServiceName"
}, {
"data": "Description"
}, {
"data": "IsActive"
}, {
"data": "Urls",
"render": function(d){
return JSON.stringify(d);
}
}
],
});
I guess that that isn't brilliant but you could do almost anything to that function, for instance:
var table = $('#example').dataTable({
"data": data,
"columns": [
{
"data": "ServiceName"
}, {
"data": "Description"
}, {
"data": "IsActive"
}, {
"data": "Urls",
"render": function(d){
return d.map(function(c){
return c.ServiceAddress
}).join(", ");
}
}
],
});