Skip to content

Commit

Permalink
Reactnative/develop (#2990)
Browse files Browse the repository at this point in the history
* Reactnative/experimental (#2918)

* Support for HeroCard and ThumbnailCard as an experiment

* Added react-native navigation support for Visualizer

* Updated visualizer with experimental items

* Revert "Added react-native navigation support for Visualizer"

This reverts commit 80688e5.

* Updated Visualiser with  tab to show the experimental items

* windows more option icon

* Show payloads tab by default

* Reactnative/fallback - Model layer and fallback feature (#2988)

* Support for HeroCard and ThumbnailCard as an experiment

* Added react-native navigation support for Visualizer

* Updated visualizer with experimental items

* Revert "Added react-native navigation support for Visualizer"

This reverts commit 80688e5.

* Updated Visualiser with  tab to show the experimental items

* windows more option icon

* Show payloads tab by default

* Model layer added and changes for fallback feature

* Media element updated in model

* Review comment fixes

* Fixed column visible issue and number input issue

* Added isNumber check for w2hRatio for Image
  • Loading branch information
Vivek Kozhisseri authored May 29, 2019
1 parent 2dc7190 commit c29df5e
Show file tree
Hide file tree
Showing 33 changed files with 1,503 additions and 189 deletions.
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

0 comments on commit c29df5e

Please sign in to comment.