How to display images in imageset dynamically from an array object in adaptiev cards? - botframework

I have an array object like this:
{
"Items":[
{
"ShortName":"Product short name",
"Image":"https://www.andrew.cmu.edu/user/cfperron/cats/images/cat8.jpg",
"ManufacturerName":"MMM",
"CatalogName":"cats"
},
{
"ShortName":"Product2 short name",
"Image":"https://www.andrew.cmu.edu/user/cfperron/cats/images/cat7.jpg",
"ManufacturerName":"SSS",
"CatalogName":"Dogs"
}
]
}
how to get Images in ImageSet dynamically in adaptive cards? I was able to get rest of the values in FactSet. But stuck with images.

Ok I figured it out.
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"size": "medium",
"weight": "bolder",
"text": "Search Results"
},
{
"type": "Container",
"items": [
{
"type": "ImageSet",
"imageSize": "medium",
"images": [
{
"type": "Image",
"url": "${Image}",
"size": "Medium"
}
]
},
{
"type": "FactSet",
"facts": [
{
"title": "Short Name",
"value": "${ShortName}"
},
{
"title": "Supplier Name",
"value": "${SupplierName} "
},
{
"title": "Price ",
"value": "${PriceAmount} "
}
]
}
],
"$data": "${$root['Items']}"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2"
}
But next issue I am facing is if image url is empty, it throws an error "Adaptive Card Rendered error:
{
"message": "Cannot read property 'style' of null"
}"
How can we give a null check inside adaptive card for Image property?

Related

Incoming Webhook for Microsoft Teams - Add to Planner (Task) Tab

Is there any way to create a new task within a Planner (Task) tab within a channel by using webhooks?
Either directly or having a button on the incoming message that then creates the task once the end user presses it?
I'm new to webhooks but having a look on Google, Power Automate is a way of doing it but not sure we have access to that.
I think I went down the wrong rabbit hole of task modules as I want to use what's already configured within the Planner tab and not create something bespoke. The button also doesn't work, comes up with an error message saying "This card action is disabled because it is not supported for Connectors". But this is what I have at the moment:
{
"type":"message",
"attachments":[
{
"contentType":"application/vnd.microsoft.card.adaptive",
"contentUrl":null,
"content":{
"$schema":"http://adaptivecards.io/schemas/adaptive-card.json",
"type":"AdaptiveCard",
"version":"1.2",
"body":[
{
"type": "Container",
"id": "066de76b-17da-e6f7-8ab3-81d36d8a6162",
"padding": "None",
"items": [
{
"type": "FactSet",
"id": "10eebecd-851c-2080-24f4-9b6044821d90",
"facts": [
{
"title": "**ID**",
"value": "EXAMPLE ID"
},
{
"title": "**Name**",
"value": "EXAMPLE NAME"
}
]
}
]
},
{
"type": "Container",
"id": "879303cd-81de-618a-8e99-e66be9f22ac1",
"padding": "None",
"items": [
{
"type": "TextBlock",
"id": "0833d313-657b-b587-d4d3-f4a961e6434a",
"text": "EXAMPLE ERROR MESSAGE.",
"wrap": true
},
{
"type": "Container",
"id": "de1d9a46-b8d4-443a-5afc-8843c445cf7b",
"padding": "None",
"items": [
{
"type": "ActionSet",
"id": "3b0c8763-dba8-3d88-98f5-7189ced1fe60",
"actions": [
{
"type": "Action.Submit",
"id": "btnCreateTask",
"title": "Create Task",
"card": {
"type": "AdaptiveCard",
"padding": "None",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}
}
]
}
]
}
]
}
]
}
}
]
}
Thanks in advance for any help/suggestions

Teams bot framework - composeExtensions does not display buttons on adaptive card

Two compose extension commands are defined in the manifest. These trigger a request to bot framework, which responds with an adaptive card.
When the adaptive card is displayed, it's rendered correctly except the button is missing. If I send the exact same adaptive card as a chat activity, it displays correctly.
handleTeamsMessagingExtensionFetchTask Code
// enableInboundCard = below json
const card = this.renderAdaptiveCard(enableInboundCard, { channel })
return {
task: {
type: 'continue',
value: {
card,
height: 500,
title: 'Enable Inbound',
width: 600
}
}
};
Command (in manifest).
{
"id": "enableInbound",
"context": [
"compose"
],
"description": "Enable inbound SMS to channel",
"title": "Enable Inbound",
"type": "action",
"fetchTask": true,
"parameters": [
{
"name": "test",
"title": "test",
"inputType": "text",
"value": "test"
}
]
}
Adaptive Card
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"wrap": true,
"style": "heading",
"text": "Enable Inbound SMS"
},
{
"type": "TextBlock",
"text": "A wholeeeeeeee bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch bunch of txt",
"wrap": true
},
{
"type": "FactSet",
"facts": [
{
"title": "Current Channel",
"value": "${channel}"
}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Execute",
"title": "Enable Inbound SMS",
"verb": "enable_inbound",
"fallback": "Action.Submit"
}
]
}
]
}

Adaptive card on Select Item event of Search Message Extension

I am trying to return an adaptive card when search result is selected in Search Message extension. Below is my class to return the card:
import { IEntity } from '../model/IEntity';
import { Attachment, CardFactory } from "botbuilder";
export class AccountResultCard {
public static getCard(account: IEntity): Attachment {
// Get map
let logo = `https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg`;
let url = `https://pbs.twimg.com/docs/test.aspx?GoPage=AccountCard.aspx?AccountID='${account.ID}'&_Division_='${account.Division}'`;
const accountDetail = account.Code ? account.Code + ' - ' + account.Description : '';
const accountcontextinfo1 = account.ContextInfo[1] ? account.ContextInfo[1] : '';
const accountcontextinfo2 = account.ContextInfo[3] ? account.ContextInfo[3] + ' '+ account.ContextInfo[2] : '';
const card = CardFactory.adaptiveCard(
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": "Title"
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": accountDetail
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": accountcontextinfo1,
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"text": accountcontextinfo2,
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"text": "Missing state and country",
"wrap": true
}
],
"width": "stretch"
},
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": logo,
"size": "Small"
}
],
"width": "auto"
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Open in Aurora",
"url": url,
"width": "Small",
"style": "default"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2"
}
);
return card;
}
}
and below is my select item event:
public async handleTeamsMessagingExtensionSelectItem(
context: TurnContext,
obj: any
): Promise<any> {
const item = this.response.find(e => e.ID == obj.name);
return {
composeExtension: {
type: "result",
attachmentLayout: "list",
attachments: [AccountResultCard.getCard(item)],
},
};
}
But it never return anything. I deleted everything from get card and sent just a one single text block with hard coded value in body. That also didn't work.Can you guys suggest me where I am doing wrong.
I was able to send the adaptive card in SelectItem event by changing the code to :
return {
composeExtension: {
type: "result",
attachmentLayout: "list",
attachments: [{preview: CardFactory.heroCard("title", ""),
...yourAdaptiveCard}],
},
};
This has been answered here.

VSC validation with $schema and usage of additionalProperties = false

i have a dataobject.json and a corresponding example.json. I like to compare both if everything what is in the example is the same notation as in the dataobject.
I added in the exampe the dataobject file as a schema to validate against. This works, but only for the required field, not for the optional properties. - there the validation doesn't find a problem, even if there are some.
To validate these I added the "additionalProperties": false line. This works in general, so I find all the deviations, but I also get a problem that property §schema is not allowed.
How can I solve this?
the dataobject
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"title": "GroupDO",
"required": [
"id",
"name"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"format": "uuid",
"example": "5dd6c80a-3376-4bce-bc47-8t41b3565325",
"description": "Unique id ."
},
"name": {
"type": "string",
"example": "ABD",
"description": "The name."
},
"GroupSort": {
"type": "integer",
"format": "int32",
"example": 1,
"description": "Defines in which order the groups should appear."
},
"GroupTextList": {
"type": "array",
"description": "A descriptoin in multiple languages.",
"items": {
"$ref": "../../common/dataobjects/Description_1000_DO.json"
}
},
"parentGroupId": {
"type": "string",
"format": "uuid",
"example": "8e590f93-1ab6-40e4-a5f4-aa1eeb2b6a80",
"description": "Unique id for the parent group."
}
},
"description": "DO representing a group object. "}
the example
{ "$schema": "../dataobjects/GroupDO.json",
"id": "18694b46-0833-4790-b780-c7897ap08500",
"version": 1,
"lastChange": "2020-05-12T13:57:39.935305",
"sort": 3,
"name": "STR",
"parentGroupId": "b504273e-61fb-48d1-aef8-c289jk779709",
"GroupTexts": [
{
"id": "7598b668-d9b7-4d27-a489-19e45h2bdad0",
"version": 0,
"lastChange": "2020-03-09T14:14:25.491787",
"languageIsoCode": "de_DE",
"description": "Tasche"
},
{
"id": "376e82f8-837d-4bb2-a21f-a9e0ebd59e23",
"version": 0,
"lastChange": "2020-03-09T14:14:25.491787",
"languageIsoCode": "en_GB",
"description": "Bag"
}
]
}
the problem messages:
property $schema is not allowed
Thanks in advance for your help.

Example or plugin to anonymize FHIR Json

I have a set of health care information in FHIR json format. Before storing such sensitive information i would like to anonymize the sensitive information such as name , phone number, address, physician contacts, etc.
I googled about anonimizing the fhir json and found there exist some security labels which classifies the information as Confidential , restricted , etc - https://www.hl7.org/fhir/valueset-security-labels.html
https://www.hl7.org/fhir/extension-auditevent-anonymized.html - This talks about the extension and the structure of anonymized data.
I am not sure how to replace these variables with security codes. Is there any api which does that or i have to find all the tags which are sensitive and loop the json and replace tags with security code.
Can someone give me an example of this can be achieved.
i have attached a sample json which i generated via synthea
{
"fullUrl": "urn:uuid:7a534e34-40a2-48ab-bc92-066d23251a8b",
"resource": {
"resourceType": "Patient",
"id": "7a534e34-40a2-48ab-bc92-066d23251a8b",
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Generated by Synthea.Version identifier: v2.5.0-378-gee8c6470\n . Person seed: 6477291342685874262 Population seed: 1586936726889</div>"
},
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName",
"valueString": "Hilma831 Luettgen772"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-birthPlace",
"valueAddress": {
"city": "Boston",
"state": "Massachusetts",
"country": "US"
}
},
{
"url": "http://synthetichealth.github.io/synthea/disability-adjusted-life-years",
"valueDecimal": 3.3178400761167306
},
{
"url": "http://synthetichealth.github.io/synthea/quality-adjusted-life-years",
"valueDecimal": 71.68215992388328
}
],
"identifier": [
{
"system": "https://github.com/synthetichealth/synthea",
"value": "7a534e34-40a2-48ab-bc92-066d23251a8b"
},
{
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR",
"display": "Medical Record Number"
}
],
"text": "Medical Record Number"
},
"system": "http://hospital.smarthealthit.org",
"value": "7a534e34-40a2-48ab-bc92-066d23251a8b"
},
{
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "SS",
"display": "Social Security Number"
}
],
"text": "Social Security Number"
},
"system": "http://hl7.org/fhir/sid/us-ssn",
"value": "999-80-4232"
},
{
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "DL",
"display": "Driver's License"
}
],
"text": "Driver's License"
},
"system": "urn:oid:2.16.840.1.113883.4.3.25",
"value": "S99911013"
},
{
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "PPN",
"display": "Passport Number"
}
],
"text": "Passport Number"
},
"system": "http://standardhealthrecord.org/fhir/StructureDefinition/passportNumber",
"value": "X66843459X"
}
],
"name": [
{
"use": "official",
"family": "Kreiger457",
"given": [
"Anthony633"
],
"prefix": [
"Mr."
]
}
],
"telecom": [
{
"system": "phone",
"value": "555-660-2614",
"use": "home"
}
],
"gender": "male",
"birthDate": "1939-12-25",
"deceasedDateTime": "2015-02-02T22:36:55+05:30",
"address": [
{
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/geolocation",
"extension": [
{
"url": "latitude",
"valueDecimal": 42.11942297974089
},
{
"url": "longitude",
"valueDecimal": -71.21834679934824
}
]
}
],
"line": [
"496 Tromp Mews Unit 96"
],
"city": "Walpole",
"state": "Massachusetts",
"postalCode": "02081",
"country": "US"
}
],
"maritalStatus": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
"code": "M",
"display": "M"
}
],
"text": "M"
},
"multipleBirthBoolean": false,
"communication": [
{
"language": {
"coding": [
{
"system": "urn:ietf:bcp:47",
"code": "en-US",
"display": "English"
}
],
"text": "English"
}
}
]
},
"request": {
"method": "POST",
"url": "Patient"
}
}
There is no 'standard' way to anonymize because anonymization is a risk-reduction approach that requires knowledge of both the threats you're trying to defend against and how the data needs to be used. When combined with other data, any element could potentially be 'sensitive'. It could also be essential to the intended analysis.
The extension you're looking at is specific to audit event. The way you'd actually flag a Patient resource as having been anonymized is using the ANONYED security tag in resource.meta. I don't believe there's a standard extension for marking what elements should be anonymized. If there were such an element, the element would also need to indicated how the data should be anonymized and the alorithm would typically need to take into account multiple elements - or even multiple resources. E.g. Should dates be changed to a random value, or just have the day shifted? Should all dates in the set of related resources be shifted by the same amount or should they be adjusted independently. If you're changing the practitioners pointed to by different resources, should they be left as is, each one changed randomly, the same practitioner changed to the same random practitioner?

Resources