Microsoft Teams task module
A task module allows you to create modal popup experiences in your Teams application. Inside the popup, you can run your own custom HTML/JavaScript code, show an <iframe>
-based widget such as a YouTube or Microsoft Stream video, or display an Adaptive card.
Task modules build on the foundation of Microsoft Teams tabs: a task module is essentially a tab in a popup window. It uses the same SDK, so if you've built a tab you are already 90% of the way to being able to create a task module.
Included Features
- Bots
- Tabs
- Task Modules
- Adaptive Cards
Interaction with app
Prerequisites
- Microsoft Teams is installed and you have an account (not a guest account)
- NodeJS
- dev tunnel or ngrok latest version or equivalent tunneling solution
- M365 developer account or access to a Teams account with the appropriate permissions to install an app.
Setup
Register a new application in the Microsoft Entra ID – App Registrations portal.
Setup for Bot
- In Azure portal, create a Azure Bot resource.
- Ensure that you've enabled the Teams Channel
- While registering the bot, use
https://<your_tunnel_domain>/api/messages
as the messaging endpoint. NOTE: When you create app registration, you will create an App ID and App password - make sure you keep these for later.
- Setup NGROK
Run ngrok - point to port 3978
ngrok http 3978 --host-header="localhost:3978"
Alternatively, you can also use the
dev tunnels
. Please follow Create and host a dev tunnel and host the tunnel with anonymous user access command as shown below:devtunnel host -p 3978 --allow-anonymous
- Setup for code
Clone the repository
git clone https://github.com/OfficeDev/Microsoft-Teams-Samples.git
In a terminal, navigate to
samples/app-task-module/nodejs
Update the
.env
configuration for the bot to use theMICROSOFT_APP_ID
andMICROSOFT_APP_PASSWORD
from the Azure Bot resource. (Note that the MicrosoftAppId is the AppId created in step 1, the MicrosoftAppPassword is referred to as the "client secret" in step 1 and you can always create a new client secret anytime.). ForBASE_URI
provide the application base url, E.g. https://12345.ngrok-free.app if you are using ngrok and if you are using dev tunnels, your URL will be like: https://12345.devtunnels.ms.Install modules
npm install
Build application:
npm run build
Run your app.
npm start
- Setup Manifest for Teams
This step is specific to Teams.
- Edit the
manifest.json
contained in theappPackage
folder to replace your Microsoft App Id (that was created when you registered your app registration earlier) everywhere you see the place holder string{{Microsoft-App-Id}}
(depending on the scenario the Microsoft App Id may occur multiple times in themanifest.json
) - Edit the
manifest.json
forvalidDomains
and replace{{domain-name}}
with base Url of your domain. E.g. if you are using ngrok it would behttps://1234.ngrok-free.app
then your domain-name will be1234.ngrok-free.app
and if you are using dev tunnels then your domain will be like:12345.devtunnels.ms
. - Note: If you want to test your app across multi hub like: Outlook/Office.com, please update the
manifest.json
in theapp-task-module\nodejs\Manifest_Hub
folder with the required values. - Zip up the contents of the
appPackage
folder to create aManifest.zip
orManifest_Hub
folder into aManifest_Hub.zip
. (Make sure that zip file does not contains any subfolder otherwise you will get error while uploading your .zip package)
- Edit the
Upload the manifest.zip to Teams (in the Apps view click "Upload a custom app")
- Go to Microsoft Teams. From the lower left corner, select Apps
- From the lower left corner, choose Upload a custom App
- Go to your project directory, the
appPackage
folder, copy that file and paste someother folder then zip, and choose Open. - Select Add in the pop-up dialog box. Your app is uploaded to Teams.
Overview of this sample
This sample app was developed in conjunction with the task module feature itself to exercise as much of it as possible. Here's what's included:
- A channel tab. Add the app to a team, then add a Task Module tab and choose "Task Module Demo" from the dropdown list.
- A bot. Add the app to a team, then chat with it (@Task Module)
- A personal app. When you upload the TaskModule.zip file, choose "Add for you" and "Task Module" will appear in the "..." menu in the Teams app bar. The personal app has both a tab and a bot.
The tab shows how to invoke the task module using the Teams SDK. Source code for the tab is found in TaskModuleTab.ts; the view definition is in taskmodule.pug. This sample app uses Pug (formerly Jade) for HTML rendering.
Running the sample
- YouTube, which is comprised of a generic template for embedded
<iframe>
experiences (also used for the PowerApp task module below) plus a four-line stub containing the YouTube embed URL
- PowerApp — unfortunately it doesn't work out of the box; click the button or see the source code for details on how you can customize it for your tenant
- There are two Adaptive card examples:
- Showing the results of an
Action.Submit
button returned to the tab - Showing the results returned to the bot as a message
- Showing the results of an
The sample app also contains a bot with cards allowing you to invoke these task modules.
You can invoke them from an Adaptive card (using the tasks command) or from a Bot Framework thumbnail card (using the bfcard command).
RootDialog.ts contains the code for the tasks and bfcard commands, and TeamsBot.ts contains the code for responding to task/fetch
and task/submit
messages. The task modules when invoked from a bot are the same as for the tab, except for the Adaptive card examples:
- Adaptive Card - Single returns the results to the conversation as a message.
- Adaptive Card - Sequence shows how adaptive cards can be chained together: instead of returning the result to the chat, the result is shown in another Adaptive card.
Outlook on the web
To view your app in Outlook on the web.
Go to Outlook on the weband sign in using your dev tenant account.
On the side bar, select More Apps. Your sideloaded app title appears among your installed apps
Select your app icon to launch and preview your app running in Outlook on the web
Note: Similarly, you can test your application in the Outlook desktop app as well.
Office on the web
To preview your app running in Office on the web.
Log into office.com with test tenant credentials
Select the Apps icon on the side bar. Your sideloaded app title appears among your installed apps
Select your app icon to launch your app in Office on the web
Note: Similarly, you can test your application in the Office 365 desktop app as well.
Implementation notes
- This sample is data-driven as much as possible and shares as much code as possible between the bot and the tabs forms of task module:
- Metadata used to generate TaskInfo objects is in contants.ts.
- All cards are generated via JSON templates in the cardTemplates collection in CardTemplates.ts and rendered using the ST-JS (Select Transform) JavaScript library. The values in
cardTemplates
have data placeholders, e.g.{{title}}
; JavaScript objects are created in TaskModuleTab.ts and RootDialog.ts, and helper functions in CardUtils.ts are used to render the cards. - Deep links are generated in the
taskModuleLink()
function in DeepLinks.ts. - Except for the JavaScript in the task modules themselves, all code is in TypeScript. Three source files, contants.ts, DeepLinks.ts, and CardTemplates.ts are used on both the client (tab) and server (bot). Browserify is used in the gulpfile.js build script to bundle the JavaScript generated by TypeScript; this script file is referenced by taskmodule.pug.
- The logic for handling
task/fetch
messages is also data-driven, shared across card types (Adaptive and Bot Framework), and supports chaining of Adaptive card task modules. The data-driven approach for card generation combined with the fact that the Adaptive and Bot Framework card schemas are quite different unfortunately means that the way it works is not obvious. Here's how it works:- All the
task/fetch
andtask/submit
requests and responses are JavaScript objects defined in thefetchTemplates[]
collection in CardTemplates.ts and generated in TeamsBot.ts in theonInvoke()
function. - The custom properties
data.taskModule
(for Adaptive cardAction.Submit
buttons) andvalue.taskModule
(for Bot Framework card actions) are used as lookup values to select a specific response from thefetchTemplates[]
collection when atask/fetch
message is received. - Adaptive card chaining — showing multiple adaptive cards in a sequence — is implemented using the
data.taskResponse
property on an Adaptive cardAction.Submit
button. With Adaptive Card - Single, the card is rendered withdata.taskResponse
set to "message" (show a message to the user); for Adaptive Card - Sequence, the same Adaptive card is rendered withdata.taskResponse
set to "continue" (show another Adaptive card). This is the only difference betweenfetchTemplates.adaptivecard1
andfetchTemplates.adaptivecard2
. The second Adaptive card (cardTemplates.acSubmitResponse
in CardTemplates.ts) in the sequence just shows the JSON submitted in the first; itsdata.taskResponse
is set to "final". The logic for handling the various values ofdata.taskResponse
is in TeamsBot.ts. ThetaskResponse
values form a simple "protocol" for responding to the different ways to respond totask/submit
messages: do nothing (complete), show a message to the user, load a subsequent adaptive card in a sequence, or load the final adaptive card in a sequence.
- All the
- To avoid hardcoding an
appId
in customform.pug, theappId
is passed in at Pug template rendering time by tabs.ts, the TypeScript which implements the tab routes. - Theming and simple keyboard handling for the Esc key are supported.
Bonus features
There's also an actester bot command. It's a handy way of seeing what an Adaptive card looks like in Teams - simply copy/paste the JSON of Adaptive cards, e.g. the Samples page on the Adaptive card site, and the bot will render it as a reply.
Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.