Adaptive Cards Templating in MS Teams - microsoft-teams

I can't seem to get this to work. If I send the following adaptive card payload to MS Teams:
{
"$schema" : "http://adaptivecards.io/schemas/adaptive-card.json",
"version" : "1.3",
"type" : "AdaptiveCard",
"body" : [ {
"type" : "Container",
"style" : "emphasis",
"items" : [ {
"type" : "Input.Text",
"value" : "${form.name}",
"id" : "name",
"label" : "Name"
} ]
} ],
"$data" : {
"form" : {
"name" : "geoff hurst"
},
}
}
I get a response in Teams like this:
I would have thought that the template should be expanded on the client-side, but this doesn't seem to happen. Have I misunderstood?

So in simple terms, Teams doesn't have an ability to render templates (basically that would mean taking the card template and the data payload and combining them together) - it can only accept the final version of the card.
As a result, if you're wanting to use templates, then you need to implement the data + template capability your side, to send the final card payload down to Teams. See here for examples on how to do this in js or dotnet. Truth be told, if you're in js (e.g. Node), Templating is not much more than string replacement, and if you're in dotnet (e.g. C#) there's a strongly-typed Adaptive Card library you might want to rather use anyway, in which case you're combining the "template" and the "data" already inside your code.
I think probably the best use of templating would be if you're receiving a template from some kind of "template repository", but I don't think there's really practically any such thing yet for Teams.

The method you are trying to use will not allow you to use dynamic data, I prefer you use data as a separate object and use Templating SDKs.
Please have a look at this sample on how to use template :
var templateJSON = File.ReadAllText(Path.Combine(".", "CardPath"));
AdaptiveCardTemplate template = new AdaptiveCardTemplate(templateJSON);
var memberData = new
{
userName = member.Name,
userUPN = member.UserPrincipalName,
userAAD = member.AadObjectId
};
string cardJSON = template.Expand(memberData);
var adaptiveCardAttachment = new Attachment
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(cardJSON),
};
await turnContext.SendActivityAsync(MessageFactory.Attachment(adaptiveCardAttachment), cancellationToken);
In the above snippet as you can see, we need to create a model having the fields that we are using in the card.
In your case you need to create a object having the property as form -> name
var formData = new
{
form = new
{
name = "Testing"
}
};
after that use the expand method and the rest code would be same.

Related

Springdocs: Specifying an explicit type for Paged responses

I'm working on a "global search" for my application.
Currently, I'm using hibernate-search to search for instances of multiple different objects and return them to the user.
The relevant code looks as follows:
Search.session(entityManager)
.search(ModelA.classs, ModelB.class)
.where(...)
.sort(...)
.fetch(skip, count);
Skip and count are calculated based on a Pageable and the result is used to create an instance of Page, which will be returned to the controller.
This works as I'd expect, however, the types generated by swagger-docs obviously doesn't know, what the type within the Page is, and therefore uses Object.
I'd like to expose the correct types, as I use them to generate the types for the frontend application.
I was able to set the type to an array, when overwriting the schema like this:
#ArraySchema(schema = #Schema(anyOf = {ModelA.class, ModelB.class}))
public Page<?> search(Pageable pageable) {
However, this just disregards the Page and also isn't correct.
The next thing I tried is extending the PageImpl, overwriting the getContent method, and specifying the same schema on this method, but this wasn't included in the output at all.
Next was implementing Page<T> myself (and later removing the implements reference to Page<T>) and specifying the same schema on getContent, iterator, and the field itself, but also to no effect.
How do I tell spring-docs, what the content of the resulting Page might be?
I stumbled upon this when trying to solve a similar problem
Inspired from this thread Springdoc with a generic return type i came up with the following solution, and it seems to apply to your case also. Code examples are in Kotlin.
I introduced a stub class that will just act as the Schema for the response:
private class PageModel(
#Schema(oneOf = [ModelA::class, ModelB::class]))
content: List<Object>
): PageImpl<Object>(content)
Then i annotated my Controller like this:
#Operation(
responses = [
ApiResponse(
responseCode = "200",
content = [Content(schema = Schema(implementation = PageModel::class))]
)
]
)
fun getPage(pageable: Pageable): Page<Object>
This generated this api response:
"PageModel": {
"properties": {
"content": {
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/ModelA"
},
{
"$ref": "#/components/schemas/ModelB"
}
],
"type": "object"
},
"type": "array"
},
... -> more page stuff from spring's PageImpl<>
And in the "responses" section for the api call:
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PageModel"
}
}
},
"description": "OK"
}
All generated openapi doc is similar to the autogenerated json when returning a Page, it just rewrites the "content" array property to have a specific type.

GraphQL: Explore API without a wildcard (*)?

I am new to GraphQL and I wonder how I can explore an API without a possible wildcard (*) (https://github.com/graphql/graphql-spec/issues/127).
I am currently setting up a headless Craft CMS with GraphQL and I don't really know how my data is nested.
Event with the REST API I have no chance of just getting all the data, because I have to setup all the endpoints and therefore I have to know all field names as well.
So how could I easily explore my CraftCMS data structure?
Thanks for any hints on this.
Cheers
merc
------ Edit -------
If I use #simonpedro s suggestion:
{
__schema {
types {
name
kind
fields {
name
}
}
}
}
I can see a lot of types (?)/fields (?)...
For example I see:
{
"name": "FlexibleContentTeaser",
"kind": "OBJECT",
"fields": [
{
"name": "id"
},
{
"name": "enabled"
},
{
"name": "teaserTitle"
},
{
"name": "text"
},
{
"name": "teaserLink"
},
{
"name": "teaserLinkConnection"
}
]
But now I would like to know how a teaserLink ist structured.
I somehow found out that the teaserLink (it is a field with the type Entries, where I can link to another page) has the properties url & title.
But how would I set up query to explore the properties available within teaserLink?
I tried all sorts of queries, but I am always confrontend with messages like this:
I would be really glad if somebody could give me another pointer how I can find out which properties I can actually query...
Thank you
As far as I'm concerned currently there is no graphql implementation with that capability. However, if what you want to do is to explore the "data structure", i.e, the schema, you should use schema instrospection, which was thought for that (explore the graphql schema). For example, a simple graphql instrospection query would be like this:
{
__schema {
types {
name
kind
fields {
name
}
}
}
}
References:
- https://graphql.org/learn/introspection/
UPDATE for edit:
What you want to do I think is the following:
Make a query like this
{
__schema {
types {
name
kind
fields {
name
type {
fields {
name
}
}
}
}
}
}
And then find the wished type field to grab more information (the fields) from it. Something like this (I don't know if this works, just an idea):
const typeFlexibleContentTeaser = data.__schema.types.find(t => t === "FlexibleContentTeaser")
const teaserLinkField = typeFlexibleContentTeaser.fields.find(f => f.name === "teaserLink")
const teaserLinkField = teaserLinkField.type.fields;
i.e, you have to transverse recursively through the type field.

Get object by key in angularfire2 version 5

"items": {
"a" : {
"size" : "small",
"text" : "small thing"
},
"b" : {
"size" : "medium",
"text" : "medium sample"
},
"c" : {
"size" : "large",
"text" : "large widget"
}
}
Suppose, I have data as above. I want to get data of key a from items list in component file without iterating over whole list. I tried from the docs. But could not find this kind of requirement. Solutions on this platform are related to previous versions before 5.0. Does anyone know how can we achieve it?
I suppose you are referring to Real Time DB because you mentioned "items list", where in FireStore it is collection.
To get an object, use the AngularFireDatabase.object() function.
Examples:
// Get an object, just the data (valuesChanges function), only once (take(1) function)
import 'rxjs/add/operator/take';
let subscribe = AngularFireDatabase.object('items/a').valueChanges().take(1).subscribe(
data =>{
console.log(data);
}
);
Another way is to call the subscrible.unsubscribe() function inside the subscrible return instead of using the take() function:
let subscribe = AngularFireDatabase.object('items/a').valueChanges().subscribe(
data =>{
console.log(data);
subscribe.unsubscribe();
}
);
The above example get the data at the time of execution, not getting changes that occur with the object after that.
// Get an object, just the data (valuesChanges function), and all subsequent changes
let subscribe = AngularFireDatabase.object('items/a').valueChanges().subscribe(
data =>{
console.log(data);
}
);
The above example get the data every time there are changes in the object.
I have tested both examples.
You can read about AnglarFire2 version 5, here and here.
You can read about retrieve data from objects here.

How to change the SAPUI5 language?

I am searching for a way to change the language used in SAPUI5 "completely".
To change the language using a property file seems not to be a problem, a working example:
new sap.m.Switch({
state : false,
customTextOn : "EN",
customTextOff : "DE",
visible : true,
change : [ function(oEvent) {
var control = oEvent.getSource();
var state = control.getState();
if (state) {
i18nModel = new sap.ui.model.resource.ResourceModel({bundleUrl:"i18n/i18n.properties", bundleLocale:"en"});
sap.ui.getCore().setModel(i18nModel, "i18n");
} else {
i18nModel = new sap.ui.model.resource.ResourceModel({bundleUrl:"i18n/i18n.properties", bundleLocale:"de"});
sap.ui.getCore().setModel(i18nModel, "i18n");
}
}, this ]
}),
Pressing the switch button will immediately change the text bound to "i18n>" model.
The problem is, that I also have text from metadata (especially lables) from the oData service.
A binding path could look like this:
{modelName>/#Entity/Attribute/#sap:label}
The language for this is defined during first logon. Now I am searching for a way to reload metadata (and also data) after a language change.
Is there any way to do so? Or is the only way to logout and login again?
You may need to reinit the ODataModel
var oModel = new sap.ui.model.odata.ODataModel("/your_odata_service",
{metadataUrlParams:{"sap-language":"de"}}
);
This way it will retrieve the OData metadata for German via $metadata?sap-language=de again.
It just comes off the top of my mind. You can have a try.
Thanks! I've had an issue to change the language that smartforms/smartfields are using for labels, as i couldn't control the language in which the labels were stated in the metadata.xml file. Allen solution worked for me! I am using the SAP Web IDE and i changed the manifest.json file adding this line were the principle or main (nameless, "") model is defined:
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "mpo.i18n.i18n"
}
},
"": {
"dataSource": "mainService",
"settings": {
"defaultBindingMode": "TwoWay",
"metadataUrlParams": {
"sap-documentation": "heading",
"sap-language": "en"
}
},
Thanks Allen!
Allen is almost right.
In order to reload the metadata file with the additional sap-language parameter, you need to destroy the model first and then reinit the new one. It is important, that you don't have any other ODataModel instance of the same service.
this.getModel().destroy();
var oModel = new sap.ui.model.odata.v2.ODataModel("/youService", {
metadataUrlParams: {"sap-language":"de"}
});

Intel XDK : Parse.com integration "Unauthorized"

I am very new to Intel XDK and i try to make a very simple app like this in that video tutorial: Using Services Datafeed in App Designer.
But instead of the specific service from Rotten Tomatoes i want to integrate a database i have in Parse.com. For that i followed this video tutorial: "Integrating a New Service"
"[https]://software.intel.com/en-us/html5/videos/integrating-a-new-service",
and at the end the response was: "Unauthorized".
Then i found only this answer which comes from Intel's HTML5 Development Forums. I did not get anything either with this. The response was again: "Unauthorized".
And now i am confused and disappointed because:
I can't find other resources to help my self
I don't want to do it someone else instead of me, but
Without a full example, how is supposed to make it to learn?
My code now is similar with this in video: "Integrating a New Service"
In apiconfig.json
{
"MyService": {
"name": "The external service",
"description": "A great API with an external service",
"dashboardUrl": "https://parse.com",
"auth": "key",
"signature": "apiSecret"
}
}
In MyService.js
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
params['apiKey'] = credentials.apiKey;
url = url + '?' + $.param(params);
return $.ajax({url: url, type: 'GET'});
};
return exports;
})
And in MyService.json
{
"endpoints": [
{
"name": "classes",
"dashboardUrl": "https://parse.com/docs/rest",
"methods": [
{
"MethodName": "ServiceObject",
"Synopsis": "Show the entries",
"parameters": [
{
"Name": "objectId",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The object ID"
},
{
"Name": "text",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The text"
}
]
}
]
}
]
}
Can someone help me more? In whatever way he thinks best.
Thank you all
Edit:
After the following answer, my problem solved.
"MyService.js" file after the correction is:
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
};
return exports;
})
# user1736947: Your answer was concise and precise, exactly what i needed.
Certainly in the future I will need a lot of help, but for now I can go on my self-education thanks to you.
Thank you very much.
The way the authentication keys are accepted is different for different services. The example in the video.. rottentomatoes.. it accepted keys as a url parameter, so we append the key to the url and send it. However, seems like parse wants the keys in the headers (according to this)
So the equivalent ajax call will be something like :
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
This might not fix everything but it will move you a step beyond the authorization issue. Let me know if you are able to retreive the class this way.
To get a particular row entry, append the url with params.objectID.
Also, the XDK services tab has a parse-similar service ... kinvey. It also allows you to create a database online and retreive it.

Resources