Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reactnative/develop #2990

Merged
merged 6 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@

import * as Constants from './constants';

/**
* @description - This builder creates adaptive card from `HeroCard` / `ThumbnailCard` .
* @param cardContent - Content of the card to be converted
* @param type - Type of the card.
*/
export const buildAdaptiveCard = (cardContent, type) => {

const AdaptiveCard = {
"type": Constants.TypeAdaptiveCard,
"version": Constants.AdaptiveCardVersion,
"body": [],
"actions": []
}

const ColumnSet = {
"type": Constants.TypeColumnSet,
"columns": [
{
"type": Constants.TypeColumn,
"width": Constants.ThumbNailWidth,
"items": []
},
{
"type": Constants.TypeColumn,
"width": Constants.WidthStretch,
"items": []
}
]
}

if (cardContent && type) {
switch (type) {
case Constants.TypeHeroCard:
pushTextBlocks(cardContent, AdaptiveCard.body);
pushImages(cardContent, AdaptiveCard.body);
pushActions(cardContent, AdaptiveCard.actions);
break;
case Constants.TypeThumbnailCard:
pushImages(cardContent, ColumnSet.columns[0].items);
pushTextBlocks(cardContent, ColumnSet.columns[1].items);
pushActions(cardContent, ColumnSet.columns[1].items, true);
AdaptiveCard.body.push(ColumnSet);
delete AdaptiveCard.actions;
break;
default:
elementsContainer = [];
break;
}

/**
* `tap` to container `selectAction`
*/
if (cardContent.tap && cardContent.tap.type && cardContent.tap.value) {
const body = AdaptiveCard.body;
AdaptiveCard.body = [];
const containerBody = {};
containerBody.type = Constants.TypeContainer;
containerBody.items = body;
containerBody.selectAction = cardAction(cardContent.tap);
AdaptiveCard.body[0] = containerBody;
}

}
return AdaptiveCard;
}

/**
* @description - This method pushes text blocks to the adaptive card container.
* @param cardContent - Content of the card to be converted.
* @param textBlockContainer - Container where the tex blocks to be inserted
*/
pushTextBlocks = (cardContent, textBlockContainer) => {
if (isNotEmpty(cardContent.title))
textBlockContainer.push(textBlock(cardContent.title, Constants.TypeTitle));
if (isNotEmpty(cardContent.subtitle))
textBlockContainer.push(textBlock(cardContent.subtitle, Constants.TypeSubTitle));
if (isNotEmpty(cardContent.text))
textBlockContainer.push(textBlock(cardContent.text));
return textBlockContainer;
}

/**
* @description - This method pushes images to the adaptive card container.
* @param cardContent - Content of the card to be converted.
* @param imageContainer - Container where the images to be inserted
*/
pushImages = (cardContent, imageContainer) => {
if (cardContent.images && cardContent.images.length > 0) {
cardContent.images.forEach(image => {
imageContainer.push(cardImage(image));
})
}
}

/**
* @description - This method pushes actions to the adaptive card container.
* @param cardContent - Content of the card to be converted.
* @param actionContainer - Container where the actions to be inserted
* @param isNested - A boolean decides where the actions need to be added in the container
*/
pushActions = (cardContent, actionContainer, isNested) => {
if (cardContent.buttons && cardContent.buttons.length > 0) {
if (!isNested) {
cardContent.buttons.forEach(button => {
actionContainer.push(cardAction(button));
})
} else {
const nestedContainer = {
"type": Constants.TypeColumnSet
}
const columns = [];
cardContent.buttons.forEach(button => {
const column = {
"type": Constants.TypeColumn,
"items": []
};
column.items.push(cardAction(button));
columns.push(column);
})
nestedContainer.columns = columns;
actionContainer.push(nestedContainer);;
}
}
}

/**
* @description - Convert card types `title, subtitle and text` to Adaptive card type format.
* @param content - The content to be displayed
* @param type - Element type to be converted.
*/
textBlock = (content, type) => {
const textBlock = {};
textBlock.type = Constants.TypeTextBlock;
textBlock.text = content;
switch (type) {
case Constants.TypeTitle:
textBlock.size = Constants.SizeMedium;
textBlock.weight = Constants.WeightBold;
break;
case Constants.TypeSubTitle:
textBlock.isSubtle = true;
textBlock.wrap = true;
break;
default:
textBlock.wrap = true;
break;
}
return textBlock;

}

/**
* @description - Convert `button` to `actions`
* @param button - button content.
*/
cardAction = (button) => {
const action = Object.assign({}, button);
if (button.type === Constants.TypeOpenUrl) {
action.type = Constants.ActionOpenUrl;
action.url = button.value;
} else {
action.data = {
"type": button.type,
"data": button.value
};
action.type = Constants.ActionSubmit;
}
delete action.value;
return action;
}

/**
* @description - Format `image` properties to adaptive card format
* @param image - image content.
*/
cardImage = (image) => {
const cardImage = Object.assign({}, image);
cardImage.type = Constants.ImageType;
cardImage.size = Constants.ImageSize;
if (image.tap) {
cardImage.selectAction = cardAction(image.tap);
delete cardImage.tap;
}
return cardImage;
}

/**
* @description - Checks whether a given value is empty or not.
* @param param - param need to be checked.
*/
isNotEmpty = (param) => {
return param && param !== Constants.EmptyString && param.length > 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

## Description

This module uses our [AdaptiveCards renderer package](https://www.npmjs.com/package/adaptivecards-reactnative) and a mapper to support card types other than AdaptiveCards. Here we map the payloads of MS cards such as HeroCard, ThumbnailCard, etc to Adaptive card payload format.

## Supported Cards

As of now, this mapper supports below types of cards.

* [ Hero Card ](https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/cards/cards-reference#example-hero-card)
* [ Thumbnail Card](https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/cards/cards-reference#thumbnail-card)

## Payload Mapper

The payload mapper file `AdaptiveCardBuilder.js` builds the payload for AdaptiveCard from any HeroCard/ThumbnailCard payload content.

## Test

Follow the below steps to run the sample project in local machine.

* Clone the Repo `https://github.com/microsoft/AdaptiveCards.git`
* Navigate to source/reactnative/ **>** Run **`npm install`**
* iOS **> `react-native run-ios`**
* Android **> `react-native run-android`**
* Click on **`Other Cards`** section
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export const TypeAdaptiveCard = "AdaptiveCard";
export const AdaptiveCardVersion = "1.2";

export const TypeHeroCard = "application/vnd.microsoft.card.hero";
export const TypeThumbnailCard = "application/vnd.microsoft.card.thumbnail";

export const EmptyString = "";

export const FullWidth = '100%';

export const CenterString = "center";

export const ActionOpenUrl = "Action.OpenUrl";
export const ActionSubmit = "Action.Submit";
export const TypeOpenUrl = "openUrl";

export const ImageType = "Image";
export const ImageSize = "auto";

export const TypeTextBlock = "TextBlock";
export const TypeTitle = "Title";
export const TypeSubTitle = "SubTitle";
export const TypeContainer = "Container";
export const TypeColumnSet = "ColumnSet";
export const TypeColumn = "Column";


export const SizeMedium = "medium";
export const WeightBold = "bold";

export const ThumbNailWidth = "100px";
export const WidthStretch = "stretch";
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"contentType": "application/vnd.microsoft.card.hero",
"content": {
"title": "Seattle Center Monorail",
"images": [
{
"url":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Seattle_monorail01_2008-02-25.jpg/1024px-Seattle_monorail01_2008-02-25.jpg"
}
],
"buttons": [
{
"type": "openUrl",
"title": "Official website",
"value": "https://www.seattlemonorail.com"
},
{
"type": "Imback",
"title": "Okay",
"value": "Test Okay"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"contentType": "application/vnd.microsoft.card.hero",
"content": {
"title": "Seattle Center Monorail",
"subtitle": "Seattle Center Monorail",
"text": "The Seattle Center Monorail is an elevated train line between Seattle Center (near the Space Needle) and downtown Seattle. It was built for the 1962 World's Fair. Its original two trains, completed in 1961, are still in service.",
"images": [
{
"url":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Seattle_monorail01_2008-02-25.jpg/1024px-Seattle_monorail01_2008-02-25.jpg"
}
],
"buttons": [
{
"type": "openUrl",
"title": "Official website",
"value": "https://www.seattlemonorail.com"
},
{
"type": "openUrl",
"title": "Wikipeda page",
"value": "https://en.wikipedia.org/wiki/Seattle_Center_Monorail"
}
],
"tap" :{
"type": "Submit",
"title": "Official website",
"value": "It's a Container Select Action"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"contentType": "application/vnd.microsoft.card.thumbnail",
"content": {
"title": "Bender",
"text": "Bender Bending Rodríguez is a main character in the animated television series Futurama. He was created by series creators Matt Groening and David X. Cohen, and is voiced by John DiMaggio",
"images": [
{
"url": "https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png",
"alt": "Bender Rodríguez"
}
],
"buttons": [
{
"type": "imBack",
"title": "Thumbs Up",
"image": "http://moopz.com/assets_c/2012/06/emoji-thumbs-up-150-thumb-autox125-140616.jpg",
"value": "I like it"
},
{
"type": "imBack",
"title": "Thumbs Down",
"image": "http://yourfaceisstupid.com/wp-content/uploads/2014/08/thumbs-down.png",
"value": "I don't like it"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"contentType": "application/vnd.microsoft.card.thumbnail",
"content": {
"title": "Bender",
"subtitle": "Tale of a robot who dared to love.",
"text": "Bender Bending Rodríguez is a main character in the animated television series Futurama. He was created by series creators Matt Groening and David X. Cohen, and is voiced by John DiMaggio",
"images": [
{
"url": "https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png",
"alt": "Bender Rodríguez"
}
],
"buttons": [
{
"type": "imBack",
"title": "Thumbs Up",
"image": "http://moopz.com/assets_c/2012/06/emoji-thumbs-up-150-thumb-autox125-140616.jpg",
"value": "I like it"
},
{
"type": "imBack",
"title": "Thumbs Down",
"image": "http://yourfaceisstupid.com/wp-content/uploads/2014/08/thumbs-down.png",
"value": "I don't like it"
}
],
"tap": {
"type": "imBack",
"value": "Tapped it!"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default payloads = [
{
"title": "Hero card with all props",
"json": require('./Hero.Card.json')
},
{
"title": "Hero card",
"json": require('./Hero.Card.2.json')
},
{
"title": "Thumbnail card with all props",
"json": require('./Thumbnail.card.json')
},
{
"title": "Thumbnail card",
"json": require('./Thumbnail.card.2.json')
}
]
Loading