Skip to content

Commit

Permalink
[Meeting Extensibility]: Content Bubble JavaScript/NodeJS (OfficeDev#39)
Browse files Browse the repository at this point in the history
* Content Bubble Node JS Code
* Review comments Resolved

Co-authored-by: Wajeed-msft <[email protected]>
  • Loading branch information
Trinetra-MSFT and Wajeed-msft authored Apr 6, 2021
1 parent 090e032 commit f6f04ae
Show file tree
Hide file tree
Showing 15 changed files with 5,361 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@
|2|Authentication | Sample illustrating seamless inline authentication for Microsoft Teams apps. | | [View][app-auth#ts]
|3|Complete Samples | A template for building complex bots (SDK V3) for Microsoft Teams. |[View][app-complete#cs] |[View][app-complete#ts]
|4|Meetings Extensibility | Microsoft Teams meeting extensibility sample: token passing |[View][meetings-token-app#cs] |
|5|Meeting Content Bubble Bot | Microsoft Teams meeting extensibility sample for iteracting with Content Bubble Bot in-meeting |[View][meetings-content-bubble#cs] |
|5|Meeting Content Bubble Bot | Microsoft Teams meeting extensibility sample for iteracting with Content Bubble Bot in-meeting |[View][meetings-content-bubble#cs] |[View][meetings-content-bubble#js]
|6|Region Selection App | This app contains a bot and Tab which is helpful to set the region |[View][region-selection-app#cs] |


[app-hello-world#cs]:samples/app-hello-world/csharp
[app-hello-world#ts]:samples/app-hello-world/nodejs
[personal-tab-quickstart#ts]:samples/tab-personal-quickstart/ts
Expand Down Expand Up @@ -151,6 +150,7 @@
[meetings-token-app#cs]:samples/meetings-token-app/csharp
[region-selection-app#cs]: samples/app-region-selection/csharp
[meetings-content-bubble#cs]:samples/meetings-content-bubble/csharp
[meetings-content-bubble#js]:samples/meetings-content-bubble/nodejs
[graph#rsc#cs]:samples/graph-rsc/csharp
[graph#lifecycle#cs]:samples/graph-channel-lifecycle/csharp
[botframework]:https://github.com/microsoft/BotBuilder-Samples#teams-samples
Expand Down
3 changes: 3 additions & 0 deletions samples/meetings-content-bubble/nodejs/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MicrosoftAppId=
MicrosoftAppPassword=
BaseUrl=
15 changes: 15 additions & 0 deletions samples/meetings-content-bubble/nodejs/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-disable */
module.exports = {
"extends": "standard",
"rules": {
"semi": [2, "always"],
"indent": [2, 4],
"no-return-await": 0,
"space-before-function-paren": [2, {
"named": "never",
"anonymous": "never",
"asyncArrow": "always"
}],
"template-curly-spacing": [2, "always"]
}
};
56 changes: 56 additions & 0 deletions samples/meetings-content-bubble/nodejs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# ContentBubble JavaScript/NodeJS
This sample illustrates how to implement [Content Bubble](https://docs.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/create-apps-for-teams-meetings?view=msteams-client-js-latest&tabs=dotnet#notificationsignal-api) In-Meeting Experience.

## Prerequisites

- [Node.js](https://nodejs.org) version 10.14 or higher

```bash
# determine node version
node --version
```

## To try this sample

- Clone the repository

```bash
git clone https://github.com/OfficeDev/Microsoft-Teams-Samples.git
```

- In a terminal, navigate to `samples\meetings-content-bubble\nodejs`

```bash
cd samples/meetings-content-bubble/nodejs
```

- Install modules

```bash
npm install
```

- Start the bot

```bash
npm start
```

1) Create a new Bot by following steps mentioned in [Build a bot](https://docs.microsoft.com/en-us/microsoftteams/platform/bots/what-are-bots?view=msteams-client-js-latest#build--a-bot-for-teams-with-the-microsoft-bot-framework) documentation.
2) Go to appsettings.json and add `MicrosoftAppId`, `MicrosoftAppPassword` and `BaseUrl` information.
3) Update the manifest.json file with MICROSOFT-APP-ID value.
4) You need to set the `externalResourceUrl` in notification payload to load the content bubble page in-meeting pop up
```
notification: {
alertInMeeting: true,
externalResourceUrl: 'https://teams.microsoft.com/l/bubble/<<APP_ID>>?url=<<ENDPOINT_URL>>&height=270&width=300&title=ContentBubbleinTeams&completionBotId=<<APP_ID>>'
}
```
6) [Install the App in Teams Meeting](https://docs.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/teams-apps-in-meetings?view=msteams-client-js-latest#meeting-lifecycle-scenarios)
## Interacting with the app in Teams Meeting
Message the Bot by @ mentioning to interact with the content bubble.
1. You will see agenda items listed in an Adaptive Card.
2. Select any option and click on Push Agenda button
3. You can submit your feedback on either Content Bubble/Adaptive card sent in chat.
68 changes: 68 additions & 0 deletions samples/meetings-content-bubble/nodejs/bots/contentBubbleBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

const {TeamsActivityHandler, MessageFactory, CardFactory } = require('botbuilder');
const{contentBubbleTitles}=require('../models/contentbubbleTitle');
const AdaptiveCard = require('../resources/adaptiveCard.json');
const templateJson = require('../resources/QuestionTemplate.json');
var ACData = require("adaptivecards-templating");

class ContentBubbleBot extends TeamsActivityHandler {
constructor() {
super();
this.baseUrl = process.env.BaseUrl;
this.AppId = process.env.MicrosoftAppId;

this.onMessage(async (context, next) => {
if(context.activity.value==null){
await context.sendActivity({ attachments: [this.createAdaptiveCard()] });
}
else{
var json = JSON.stringify(context.activity.value);
var out=JSON.parse(json);
if(out.action=='inputselector'){
contentBubbleTitles.contentQuestion=out.myReview;
await this.contentBubble(context);
await context.sendActivity({ attachments: [this.createQuestionAdaptiveCard(out.myReview)] });
}else {
await context.sendActivity(context.activity.from.name + " : " +"**"+out.myReview+"**"+" for " + "'" + out.action + "'");
}
}
await next();
});
};

async handleTeamsTaskModuleSubmit(context,taskModuleRequest) {
var review = JSON.stringify(taskModuleRequest.data);
var reply=JSON.parse(review);
await context.sendActivity(context.activity.from.name + " : " +"**"+reply.myValue+"**"+" for " + "'" + reply.title + "'")
}

async contentBubble(context)
{
const replyActivity = MessageFactory.text("**Please provide your valuable feedback**");
replyActivity.channelData = {
notification: {
alertInMeeting: true,
externalResourceUrl: 'https://teams.microsoft.com/l/bubble/'+this.baseUrl+'?url='+this.AppId+'&height=270&width=300&title=ContentBubbleinTeams&completionBotId='+this.AppId
}
};
await context.sendActivity(replyActivity);
}

createAdaptiveCard(){
return CardFactory.adaptiveCard(AdaptiveCard);
}

createQuestionAdaptiveCard(myText){
var templatePayload = templateJson;
var template = new ACData.Template(templatePayload);
var cardPayload = template.expand({
$root: {
name: myText
}
});
return CardFactory.adaptiveCard(cardPayload);
}
}
module.exports.ContentBubbleBot = ContentBubbleBot;
75 changes: 75 additions & 0 deletions samples/meetings-content-bubble/nodejs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// index.js is used to setup and configure your bot

// Import required pckages
const path = require('path');
// const {TaskmoduleIds} =require('./models/taskmoduleids');

// console.log(TaskmoduleIds);
// Read botFilePath and botFileSecret from .env file.
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });

const restify = require('restify');

// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter } = require('botbuilder');
const { ContentBubbleBot } = require('./bots/contentBubbleBot');

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about adapters.
const adapter = new BotFrameworkAdapter({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword
});

adapter.onTurnError = async (context, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights. See https://aka.ms/bottelemetry for telemetry
// configuration instructions.
console.error(`\n [onTurnError] unhandled error: ${ error }`);

// Send a trace activity, which will be displayed in Bot Framework Emulator
await context.sendTraceActivity(
'OnTurnError Trace',
`${ error }`,
'https://www.botframework.com/schemas/error',
'TurnError'
);

// Send a message to the user
await context.sendActivity('The bot encountered an error or bug.');
await context.sendActivity('To continue to run this bot, please fix the bot source code.');
};

// Create the bot that will handle incoming messages.
const bot = new ContentBubbleBot();

// Create HTTP server.
var server = restify.createServer();
server= require("express")();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log(`\n${ server.name } listening to ${ server.url }`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

// Listen for incoming requests.
server.post('/api/messages', (req, res) =>{
adapter.processActivity(req, res, async (context) =>{
await bot.run(context);
});
});

const{contentBubbleTitles}=require('./models/contentbubbleTitle')
var bodyParser = require("body-parser");
server.set("view engine", "ejs");
server.set("views", __dirname + "/views");
server.engine('html',require('ejs').renderFile);
server.use(bodyParser.urlencoded({ extended:false}));
server.get('/', (req,res)=>{res.render('index.html',{question: contentBubbleTitles.contentQuestion})});

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

var contentBubbleTitles ={
contentQuestion:""
}
module.exports.contentBubbleTitles = contentBubbleTitles;
Loading

0 comments on commit f6f04ae

Please sign in to comment.