Skip to content

Commit

Permalink
Adaptive Cards sample
Browse files Browse the repository at this point in the history
  • Loading branch information
pcostantini committed Jun 9, 2017
1 parent f5179c3 commit 47557d8
Show file tree
Hide file tree
Showing 8 changed files with 576 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Node/cards-AdaptiveCards/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Bot Framework Credentials

MICROSOFT_APP_ID=
MICROSOFT_APP_PASSWORD=
18 changes: 18 additions & 0 deletions Node/cards-AdaptiveCards/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Multi-Dialog Bot Sample

A sample bot showing different kind of dialogs.

[![Deploy to Azure][Deploy Button]][Deploy Node/AdaptiveCards]

[Deploy Button]: https://azuredeploy.net/deploybutton.png
[Deploy Node/AdaptiveCards]: https://azuredeploy.net

### Prerequisites

The minimum prerequisites to run this sample are:
* Latest Node.js with NPM. Download it from [here](https://nodejs.org/en/download/).
* The Bot Framework Emulator. To install the Bot Framework Emulator, download it from [here](https://emulator.botframework.com/). Please refer to [this documentation article](https://github.com/microsoft/botframework-emulator/wiki/Getting-Started) to know more about the Bot Framework Emulator.
* **[Recommended]** Visual Studio Code for IntelliSense and debugging, download it from [here](https://code.visualstudio.com/) for free.

### Code Highlights

266 changes: 266 additions & 0 deletions Node/cards-AdaptiveCards/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
// This loads the environment variables from the .env file
require('dotenv-extended').load();

var util = require('util');
var builder = require('botbuilder');
var restify = require('restify');

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});

// Create chat bot and listen to messages
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
server.post('/api/messages', connector.listen());

var bot = new builder.UniversalBot(connector, function (session) {

if (session.message && session.message.value) {
// receiving a card submit action
var value = session.message.value;

// Search, vlaidate parameters
if (value.type === 'hotelSearch') {
if (validateHotelSearch(session.message.value)) {
// proceed to search
return session.beginDialog('hotels-search', session.message.value);
}
}

// Hotel selection
if (value.type === 'hotelSelection') {
return sendHotelSelection(session, session.message.value);
}

// A form data was recieved, invalid or incomplete since the previous validation did not pass
return session.send('Please complete all the search parameters');
}

// Display Welcome card with Hotels and Flights search options
var card = {
'contentType': 'application/vnd.microsoft.card.adaptive',
'content': {
'$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
'type': 'AdaptiveCard',
'version': '1.0',
'body': [
{
'type': 'Container',
'speak': '<s>Hello!</s><s>Are you looking for a flight or a hotel?</s>',
'items': [
{
'type': 'ColumnSet',
'columns': [
{
'type': 'Column',
'size': 'auto',
'items': [
{
'type': 'Image',
'url': 'https://placeholdit.imgix.net/~text?txtsize=65&txt=Adaptive+Cards&w=300&h=300',
'size': 'medium',
'style': 'person'
}
]
},
{
'type': 'Column',
'size': 'stretch',
'items': [
{
'type': 'TextBlock',
'text': 'Hello!',
'weight': 'bolder',
'isSubtle': true
},
{
'type': 'TextBlock',
'text': 'Are you looking for a flight or a hotel?',
'wrap': true
}
]
}
]
}
]
}
],
'actions': [
// Hotels Search form
{
'type': 'Action.ShowCard',
'title': 'Hotels',
'speak': '<s>Hotels</s>',
'card': {
'type': 'AdaptiveCard',
'body': [
{
'type': 'TextBlock',
'text': 'Welcome to the Hotels finder!',
'speak': '<s>Welcome to the Hotels finder!</s>',
'weight': 'bolder',
'size': 'large'
},
{
'type': 'TextBlock',
'text': 'Please enter your destination:'
},
{
'type': 'Input.Text',
'id': 'destination',
'speak': '<s>Please enter your destination</s>',
'placeholder': 'Miami, Florida',
'style': 'text'
},
{
'type': 'TextBlock',
'text': 'When do you want to check in?'
},
{
'type': 'Input.Date',
'id': 'checkin',
'speak': '<s>When do you want to check in?</s>'
},
{
'type': 'TextBlock',
'text': 'How many nights do you want to stay?'
},
{
'type': 'Input.Number',
'id': 'nights',
'min': 1,
'max': 60,
'speak': '<s>How many nights do you want to stay?</s>'
}
],
'actions': [
{
'type': 'Action.Submit',
'title': 'Search',
'speak': '<s>Search</s>',
'data': {
'type': 'hotelSearch'
}
}
]
}
},
{
'type': 'Action.ShowCard',
'title': 'Flights',
'speak': '<s>Flights</s>',
'card': {
'type': 'AdaptiveCard',
'body': [
{
'type': 'TextBlock',
'text': 'Flights is not implemented =(',
'speak': '<s>Flights is not implemented</s>',
'weight': 'bolder'
}
]
}
}
]
}
};

var msg = new builder.Message(session)
.addAttachment(card);
session.send(msg);
});

// Search Hotels
bot.dialog('hotels-search', require('./hotels-search'));

// Help
bot.dialog('support', require('./support'))
.triggerAction({
matches: [/help/i, /support/i, /problem/i]
});

// log any bot errors into the console
bot.on('error', function (e) {
console.log('And error ocurred', e);
});

function validateHotelSearch(hotelSearch) {
if (!hotelSearch) {
return false;
}

// Destination
var hasDestination = typeof hotelSearch.destination === 'string' && hotelSearch.destination.length > 3;

// Checkin
var checkin = Date.parse(hotelSearch.checkin);
var hasCheckin = !isNaN(checkin);
if (hasCheckin) {
hotelSearch.checkin = new Date(checkin);
}

// Nights
var nights = parseInt(hotelSearch.nights, 10);
var hasNights = !isNaN(nights);
if (hasNights) {
hotelSearch.nights = nights;
}

return hasDestination && hasCheckin && hasNights;
}

function sendHotelSelection(session, hotel) {
var description = util.format('%d stars with %d reviews. From $%d per night.', hotel.rating, hotel.numberOfReviews, hotel.priceStarting);
var card = {
'contentType': 'application/vnd.microsoft.card.adaptive',
'content': {
'type': 'AdaptiveCard',
'body': [
{
'type': 'Container',
'items': [
{
'type': 'TextBlock',
'text': hotel.name + ' in ' + hotel.location,
'weight': 'bolder',
'speak': '<s>' + hotel.name + '</s>'
},
{
'type': 'TextBlock',
'text': description,
'speak': '<s>' + description + '</s>'
},
{
'type': 'Image',
'size': 'auto',
'url': hotel.image
},
{
'type': 'ImageSet',
'imageSize': 'medium',
'separation': 'strong',
'images': hotel.moreImages.map((img) => ({
'type': 'Image',
'url': img
}))
}
],
'selectAction': {
'type': 'Action.OpenUrl',
'url': 'https://dev.botframework.com/'
}
}
]
}
};

var msg = new builder.Message(session)
.addAttachment(card);

session.send(msg);
}
Loading

0 comments on commit 47557d8

Please sign in to comment.