Updates from: 06/30/2023 03:23:28
Service Microsoft Docs article Related commit history on GitHub Change details
platform App Icon Badging For Your App https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/apps-in-teams-meetings/app-icon-badging-for-your-app.md
+
+ Title: Enable app icon badging for your Teams app
+
+description: In this article, learn how to enable app icon badging for your Microsoft Teams app in meeting.
++
+ms.localizationpriority: medium
++
+# Enable app icon badging for your Teams app
+
+App icon badging helps a meeting participant identify any app activity during a meeting. Participants get activity notification for the meeting apps.
+
+When there's new activity during the meeting, the app calls the `targetedMeetingNotification` API and displays a red badge on the app icon in the meeting unified bar (U-bar). When the participant selects the app icon, the app opens in the meeting side panel, and the badge goes away.
+
+For example, during a real time collaboration in a meeting, if a participant adds a comment in a file added to the meeting, the app calls the `targetedMeetingNotification` API from the participant's meeting side panel. The API triggers a badge on the app icon to make other participants aware of the comment activity.
+
+The following image shows you the app icon badging in the meeting U-bar:
++
+> [!NOTE]
+>
+> * App icon badging for your Teams app is available only in [public developer preview](~/resources/dev-preview/developer-preview-intro.md).
+> * App icon badging isn't available for [Government Community Cloud (GCC)-High and Department of Defense (DOD)](~/concepts/app-fundamentals-overview.md#government-community-cloud) environments.
+> * App icon badging isn't supported for mobile clients.
+> * App icon badging isn't supported for channel meetings.
+
+To enable app icon badging, follow these steps:
+
+1. [Enable app manifest settings for app icon badging](#enable-app-manifest-settings-for-app-icon-badging)
+1. [Enable app icon badging for your Teams app](#enable-app-icon-badging-for-your-teams-app)
+
+## Enable app manifest settings for app icon badging
+
+To enable app icon badging, you must:
+
+* Ensure that you've configured `meetingSidePanel` as a `context` property for your app.
+* Configure the `authorization` property and the `name` and `type` properties under the `resourceSpecific` field in the [app manifest](../resources/schem#authorization) as follows:
+
+```json
+
+"webApplicationInfo": {
+ "id": "<<MICROSOFT-APP-ID>>",
+ "resource": "https://RscBasedStoreApp" },
+ "authorization": {
+ "permissions": {
+ "resourceSpecific": [
+ {
+ "name": "OnlineMeetingNotification.Send.Chat",
+ "type": "Application" }
+ ]
+ }
+ }
+```
+
+## Enable app icon badging for your Teams app
+
+To enable app icon badging, ensure that you've [enabled targeted in-meeting notification](in-meeting-notification-for-meeting.md#enable-targeted-in-meeting-notification).
+
+The [Targeted meeting notification and app icon badging API](meeting-apps-apis.md#targeted-meeting-notification-and-app-icon-badging-api) has been extended to support the app icon badging capability on the app icon and pass the user MRI IDs of the intended recipients. The `surfaces` parameter now supports `meetingTabIcon` value, which is used by the app.
+
+App can also pass the `tabEntityId`, if there are multiple instances of the app added to the same meeting. If the `tabEntityId` isn't passed, then Teams displays the badge on the first app icon on the users meeting window.
+
+### Example
+
+The following is an example of a payload:
+
+```json
+{
+ "type": "targetedMeetingNotification",
+ "value": {
+ "recipients": [
+ "<participant1 MRI>",
+ "<participant2 MRI>"
+ ],
+ "surfaces": [
+ {
+ "surface": "meetingTabIcon",
+ "tabEntityId": "<tab id from tab sdk>" // optional
+ }
+ ]
+ }
+}
+
+```
++
+## Limitations
+
+* App icon badging displays only one notification for a user in a minute per meeting.
+
+* App icon badging is displayed to a maximum of first 50 participants for a particular meeting.
+
+## Code sample
+
+|Sample name | Description | Node.js | .NET |
+|-|--|--|
+| App icon badging for your Teams app | This sample demonstrates how to enable app icon badging for your Teams app. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/meetings-app-icon-badging/nodejs) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/meetings-app-icon-badging/csharp) |
+
+## See also
+
+* [Build tabs for meeting](build-tabs-for-meeting.md)
+* [Build in-meeting notification for Teams meeting](in-meeting-notification-for-meeting.md)
+* [Targeted meeting notification and app icon badging API](meeting-apps-apis.md#targeted-meeting-notification-and-app-icon-badging-api)
platform Build Tabs For Meeting https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/apps-in-teams-meetings/build-tabs-for-meeting.md
Before creating a meeting tab, it's important to learn about the surfaces that a
:::image type="content" source="../assets/images/side-panel-view.png" alt-text="Screenshot shows side panel view with the list of apps.":::
+To notify meeting participants whenever there's a new activity on the app loaded in the meeting side panel, you can enable app icon badging. For more information, see [enable app icon badging for your Teams app](app-icon-badging-for-your-app.md).
+ #### Deep link to meeting side panel > [!NOTE] > > * Deep link to meeting side panel in Teams desktop client is available only in [public developer preview](~/resources/dev-preview/developer-preview-intro.md).
->
> * Deep link to meeting side panel in Teams mobile client is generally available. You can create a deep link to your tab app that can open in the meeting side panel. When users in a meeting select the deep link, it opens the meeting side panel in the meeting stage. If a user selects the deep link before or after the meeting, the deep link opens in a pre or a post-meeting tab respectively.
Pre or post-meeting tab behavior isn't supported in channel meetings.
For deep link format, see [deep links](~/concepts/build-and-test/deep-link-workflow.md#deep-link-to-meeting-side-panel).
-### Meeting Stage View
+### Meeting stage view
1. After a tab is added to the meeting side panel, you can now choose to opt into global app sharing.
The following are the limitations for app caching:
* [Enable SSO for tab app](../tabs/how-to/authentication/tab-sso-overview.md) * [Add apps to meetings using Microsoft Graph](/graph/api/chat-post-installedapps?view=graph-rest-1.0&tabs=http&preserve-view=true) * [Get change notifications for Microsoft Teams meeting call updates](/graph/changenotifications-for-onlinemeeting)
+* [Enable app icon badging for your Teams app](app-icon-badging-for-your-app.md)
platform In Meeting Notification For Meeting https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/apps-in-teams-meetings/in-meeting-notification-for-meeting.md
To enable the targeted in-meeting notification:
Targeted in-meeting notification is enabled.
-For more information on `targetedMeetingNotification`, see [Targeted meeting notification API](meeting-apps-apis.md#targeted-meeting-notification-api).
+For more information on `targetedMeetingNotification`, see [Targeted meeting notification and app icon badging API](meeting-apps-apis.md#targeted-meeting-notification-and-app-icon-badging-api).
+
+After you've built in-meeting notification for your app, you can use the `targetedMeetingNotification` API to enable app icon badging for your meeting app. This helps meeting participants to get a notification whenever there's new activity in the app. For more information, see [enable app icon badging for your Teams app](app-icon-badging-for-your-app.md).
## Code sample
platform Meeting Apps Apis https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/apps-in-teams-meetings/meeting-apps-apis.md
The following table includes the response codes:
| **403** | The app is unable to send the signal. 403 response code can occur because of various reasons, such as the tenant admin disables and blocks the app during live site migration. In this case, the payload contains a detailed error message. | | **404** | The meeting chat doesn't exist. |
-## Targeted meeting notification API
+## Targeted meeting notification and app icon badging API
-The `targetedMeetingNotification` API allows apps to send targeted in-meeting notifications to specific participants in a meeting. Apps send targeted in-meeting notifications based on user action. The API is available through bot API.
+The `targetedMeetingNotification` API allows apps to send targeted in-meeting notifications and shows app icon badging to specific participants in a meeting. Apps send targeted in-meeting notifications and app icon badging based on user action. The API is available through bot API.
### Prerequisite
-You must configure your app manifest with [RSC permissions](../graph-api/rsc/resource-specific-consent.md) under the `webApplicationInfo` property to send targeted in-meeting notifications to specific participants in a meeting. Use the following examples to configure your manifest:
+You must configure your app manifest with [RSC permissions](../graph-api/rsc/resource-specific-consent.md) under the `webApplicationInfo` property to send targeted in-meeting notifications and shows app icon badging to specific participants in a meeting. Use the following examples to configure your manifest:
<br>
You must configure your app manifest with [RSC permissions](../graph-api/rsc/res
> * The API payload only permits a task module with a URL. > * The user ID formats **aadObjectid** and **UPN** aren't supported.
-Get supported user ID format for targeted in-meeting notification:
+Get supported user ID format for targeted in-meeting notification and app icon badging:
* [Get participant API](#get-participant-api) * [Get members API](../bots/how-to/get-teams-context.md#fetch-the-roster-or-user-profile) ### Example
-Following is an example of request payload for targeted in-meeting notification:
+Following is an example of request payload for targeted in-meeting notification and app icon badging:
```http POST /v1/meetings/{meetingId}/notification
POST /v1/meetings/{meetingId}/notification
| `meetingId` | The meeting ID is available through bot invoke and TeamsJS library. | | `type` |`targetedMeetingNotification` | | `recipients` | List of user IDs. Get user IDs for meeting participants through [Get participant API](#get-participant-api). Get the entire list of chat roster using [Get members API](../bots/how-to/get-teams-context.md#fetch-the-roster-or-user-profile). Empty or null recipients list will return 400.|
-| `surface` | A type of surface. The supported surface type is `meetingStage`. |
+| `surface` | A type of surface. The supported surface type are `meetingStage` and `meetingTabIcon`. |
| `surfaces` | List of surfaces where notifications can be rendered. | | `contentType` | Type of content that the targeted in-meeting notification renders. The supported value is `task`. | | `content` | [TaskModuleContinueResponse](/dotnet/api/microsoft.bot.schema.teams.taskmodulecontinueresponse?view=botbuilder-dotnet-stable&preserve-view=true) |
POST /v1/meetings/{meetingId}/notification
> [!NOTE] > If you provide an invalid input, the API returns the status code 400.
-### Response code
-
-The following table includes the response codes:
-
-| Response code | Description |
-|||
-| **202** | Notification is successfully sent. |
-| **207** | Notifications are sent only to a few participants. |
-| **400** | Meeting notification request payload validation failed. |
-| **401** | Bot token is invalid. |
-| **403** | Bot isn't allowed to send the notification. |
-| **404** | Meeting chat isn't found or none of the participants were found in the roster. |
## Get meeting details API
platform Workflow Bot In Teams https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/conversations/workflow-bot-in-teams.md
You can also add new cards, if needed for your application. To build different t
When Adaptive Cards are sent in a Teams channel or group chat, all users can see the same card content. With the new refresh model for Adaptive Cards universal action, users can have a user-specific view. The auto-refresh also facilitates scenarios such as approvals, poll creator controls, ticketing, incident management, and project management cards. The following diagram illustrates how to provide user-specific view with `refresh` model: 1. **Base card**: The bot sends a message with the base version of the card. This base card can be sent as a bot notification, command response, or any other card action response. All members of the conversation can view the same response. The base card is automatically refreshed to the user defined `userId` in the `refresh` property of the base card.
platform Deep Link Application https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/build-and-test/deep-link-application.md
The query parameters are:
| Parameter name | Description | Example | |:|:--|:|
-| `appId`&emsp; | The ID from Teams Admin Center. |fe4a8eba-2a31-4737-8e33-e5fae6fee194|
+| `appId`&emsp; | The ID from Microsoft Teams admin center. |fe4a8eba-2a31-4737-8e33-e5fae6fee194|
| `entityId`&emsp; | The ID for the item in the tab, which you provided when [configuring the tab](~/tabs/how-to/create-tab-pages/configuration-page.md). When generating a URL for deep linking, continue to use entity ID as a parameter name in the URL. When configuring the tab, the context object refers to the entityID as {page.id}. |Tasklist123| | `entityWebUrl` or `subEntityWebUrl`&emsp; | An optional field with a fallback URL to use if the client doesn't support rendering the tab. | `https://tasklist.example.com/123` or `https://tasklist.example.com/list123/task456` | | `entityLabel` or `subEntityLabel`&emsp; | A label for the item in your tab to use when displaying the deep link. | Task List 123 or Task 456 |
The following table provides information on `APP_ID` and `BOT_APP_ID`:
| Value | Type | Required | Description | | | | | |
-| `APP_ID` | string | Yes | The [ID](~/resources/schem#validdomains) in the manifest for `APP_ID` must contain the domain for `url` if `url` is in the URL. The app ID is already known when a task module is invoked from a tab or a bot, which is why it isn't included in `TaskInfo`. |
+| `APP_ID` | string | Yes | For third-party apps, use the app `id` from manifest or the `APP_ID` from Teams admin center as they are identical. For Line of business (LOB) or custom apps, use the `APP_ID` from Teams admin center or use the [Graph API](/graph/api/application-list). The [validDomains array](~/resources/schem#validdomains) in the manifest for `APP_ID` must contain the domain for `url` if `url` is present in the deep-link URL. The app ID is already known when a task module is invoked from a tab or a bot, which is why it isn't included in `TaskInfo`. |
| `BOT_APP_ID` | string | No | If a value for `completionBotId` is specified, the `result` object is sent using a `task/submit invoke` message to the specified bot. `BOT_APP_ID` must be specified as a bot in the app's manifest, that is you can't send it to any bot. | > [!NOTE] > `APP_ID` and `BOT_APP_ID` can be the same in many cases, if an app has a recommended bot to use as an app's ID and if there is one.
+## Generate a deep link to share content to stage in meetings
+
+You can also generate a deep link to [share the app to stage](~/apps-in-teams-meetings/enable-and-configure-your-app-for-teams-meetings.md#share-entire-app-to-stage) and start or join a meeting.
+
+For deep links to share content to stage, see [deep link to share content to stage in meetings](~/concepts/build-and-test/share-in-meeting.md#generate-a-deep-link-to-share-content-to-stage-in-meetings).
+
+> [!NOTE]
+>
+> * Generating a deep link to share content to stage in meetings is available only in [public developer preview](~/resources/dev-preview/developer-preview-intro.md).
+> * Deep link to share content to stage in meeting is supported in Teams desktop client only.
+
+## Deep link to meeting side panel
+
+You can generate a deep link to the [meeting side panel](~/apps-in-teams-meetings/build-tabs-for-meeting.md#deep-link-to-meeting-side-panel) in a meeting. Use the following format for a deep link to the meeting side panel:
+
+`https://teams.microsoft.com/l/entity/<appId>/<entityId>?webUrl=<entityWebUrl>&label=<entityLabel>&context=<context>`.
+
+Example:
+
+`https://teams.microsoft.com/l/entity/fe4a8eba-2a31-4737-8e33-e5fae6fee194/tasklist123?webUrl=https://tasklist.example.com/123/456&label=Task 456&context={"chatId": "17:b42de192376346a7906a7dd5cb84b673@thread.v2","contextType":"chat"}`
+
+By default, a deep link opens in a meeting side panel. To open a deep link directly in an app rather than the meeting side panel, add `openInMeeting=false` in the deep link format:
+
+`https://teams.microsoft.com/l/entity/<appId>/<entityId>?webUrl=<entityWebUrl>&label=<entityLabel>&context=<context>&openInMeeting=false`
+
+For more information, see [deep link to a tab](~/concepts/build-and-test/deep-link-application.md#generate-a-deep-link-to-your-tab).
+
+Deep link doesn't open in the meeting side panel in the following scenarios:
+
+* If there is no active meeting.
+* If the app doesn't have `sidePanel` context declared in the app manifest.
+* If `openInMeeting=false` is set in the deep link.
+* If deep link is selected outside of the meeting window or component.
+* If deep link doesn't match the current meeting for example, deep link is created from another meeting.
++ ## Code Sample | Sample name | Description | .NET |Node.js|
platform Teams Store Validation Guidelines https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md
Teams apps must respond within a reasonable time-frame or show a loading or typi
* Message extensions must respond to user commands within two seconds. [*Mandatory Fix*] * Notifications must display within two seconds of the user action. [*Mandatory Fix*]
-### Apps powered by AI
+### Apps powered by Artificial Intelligence
+
+Explore resources designed to help you with responsible Artificial Intelligence (AI) practices at every stage of innovation such as [Microsoft RAI Toolkit](https://www.microsoft.com/en-us/ai/responsible-ai-resources) and [HAX Toolkit Project](https://www.microsoft.com/en-us/research/project/hax-toolkit/).
+ #### Apps with AI-generated content
-* App must not generate, contain, or provide access to inappropriate, harmful, or offensive Artificial Intelligence (AI) generated content consistent with existing commercial marketplace policies outlined in [100.10](/legal/marketplace/certification-policies#10010-inappropriate-content). Considering using any of the following: [*Mandatory Fix*]
+* App must not generate, contain, or provide access to inappropriate, harmful, or offensive AI generated content consistent with existing commercial marketplace policies outlined in [100.10](/legal/marketplace/certification-policies#10010-inappropriate-content). [*Mandatory Fix*]
- * Leverage upcoming Teams AI library. [*Suggested Fix*]
- * Use of moderation hooks, which can be used to regulate bot responses thr moderation API. [*Suggested Fix*]
- * Add conversation sweeping capability which helps developers monitor conversations and intervene when conversations go astray. [*Suggested Fix*]
+ * Consider using any of the following:
+ * Use [Teams AI library](~/bots/how-to/Teams%20conversational%20AI/teams-conversation-ai-overview.md), Teams-centric interface to GPT-based common language models and user intent engines. [*Suggested Fix*]
+ * Use of moderation hooks, which can be used to regulate bot responses through moderation API. [*Suggested Fix*]
+ * Add conversation sweeping capability, which helps you monitor conversations and intervene when conversations go astray. [*Suggested Fix*]
-* App must provide mechanism for app users to report inappropriate, harmful, or offensive content to the developer by any of the below mechanism. [*Mandatory Fix*]
+* App must provide mechanisms for app users to report inappropriate, harmful, or offensive content to the developer by any of the following mechanisms: [*Mandatory Fix*]
* App description including mail ID or link to the portal to log the issue.
- * In app mechanism to log issue along with specific reference of the inappropriate content.
+ * In app mechanism to log issue along with specific reference to the inappropriate content.
-* Developer must take timely action on reported concerns. [*Mandatory Fix*]
+* You must take timely action on reported concerns. [*Mandatory Fix*]
* App must clearly describe AI functionality before the customer acquires the offer consistent with policy [100.1.3](/legal/marketplace/certification-policies#10013-description) and prompt user to review the info as a part of in-app functionality. [*Mandatory Fix*]. :::image type="content" source="../../../../assets/images/submission/teams-ai-library-description-guideline.png" alt-text="Screenshot shows the description for Ai functionality."::: #### Apps using facial recognition capabilities
+> [!NOTE]
+> Apps in this category may undergo additional review for adherence to MicrosoftΓÇÖs Responsible AI principles.
+ * App must not allow use of facial recognition capabilities to identify an individual to be used by or for a police department in the United States. [*Mandatory Fix*]
-* Developers of apps utilizing facial recognition or emotional inference technologies must provide a prominent tag or indication of each of these capabilities in the app description. [*Mandatory Fix*]
+* For apps utilizing facial recognition or emotional inference technologies, you must provide a prominent tag or indication of each of these capabilities in the app description. [*Mandatory Fix*]
+ * Apps that use facial expressions or facial movements to infer emotional states, such as anger, disgust, happiness, sadness, surprise, fear, or other terms commonly used to describe the emotional state of a person can be restricted based on the review.
+ * Use of facial expressions and movements to detect and classify only individual facial elements, such as smiles or raised eyebrows is permitted. The key distinction is between the detection of facial expressions or movements as visual signals versus the inference of an emotional state.
## App package and store listing
platform Meeting Response Code https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/includes/meeting-response-code.md
+### Response code
+
+The following table includes the response codes:
+
+| Response code | Description |
+|||
+| **202** | Notification is successfully sent. |
+| **207** | Notifications are sent only to a few participants. |
+| **400** | Meeting notification request payload validation failed. |
+| **401** | Bot token is invalid. |
+| **403** | Bot isn't allowed to send the notification. |
+| **404** | Meeting chat isn't found or none of the participants were found in the roster. |
platform Teamsjs Support M365 https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/m365-apps/teamsjs-support-m365.md
Title: Teams JavaScript client library support across Microsoft 365
-date: 05/18/2023
+date: 06/26/2023
description: Understand the level of support for different TeamsJS library capabilities running in different hosts for Teams apps, including Microsoft Teams, Outlook, and Microsoft 365 app.
The following table lists host application support for TeamsJS capabilities that
<th><a href="#app">app</a></th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;*</td>
+ <td>&#x2713;*</td>
</tr> <tr> <th><a href="#appinstalldialog">appInstallDialog</a></th>
The following table lists host application support for TeamsJS capabilities that
<td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td>&#x2713;*</td> <td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td>
- <td>&#x2713;</td>
+ <td>&#x2713;*</td>
<td>&#x2713;*</td> </tr> <tr>
The following table lists host application support for TeamsJS capabilities that
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
The following table lists host application support for TeamsJS capabilities that
<th><a href="#dialog">dialog</a><img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;</td>
<td></td> <td>&#x2713;</td> <td></td>
The following table lists host application support for TeamsJS capabilities that
<td></td> <td></td> <td></td>
+ <td></td>
+ <td></td>
</tr> <tr> <th><a href="#mail">mail</a></th> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
The following table lists host application support for TeamsJS capabilities that
<th><a href="#pages">pages</a></th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;</td>
<td></td> <td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td>
- <td>&#x2713;</td>
+ <td>&#x2713;*</td>
<td>&#x2713;*</td> </tr> <tr>
The following table lists host application support for TeamsJS capabilities that
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
The following table lists support for TeamsJS capabilities that run only in the
</tr> <tr> <th><a href="#menus">menus</a></th>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> <td></td>
The following table lists support for TeamsJS capabilities that run only in the
<td></td> <td></td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> <td></td>
The following table lists support for TeamsJS capabilities that run only in the
<td></td> <td></td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
+ <td></td>
<td></td> <td></td> </tr>
The following table lists support for TeamsJS capabilities that run only in the
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> </tr>
The following table lists support for TeamsJS capabilities that run only in the
## Preview capabilities awaiting host support
-Some capabilities in the source are in early preview and still awaiting initial support in one or more host applications that include [**barCode**](#barcode), [**media**](#media), [**meeting**](#meeting), and [**search**](#search).
+Some capabilities in the source are in early preview and still awaiting initial support in one or more host applications that include [**barCode**](#barcode), [**media**](#media), [**meeting**](#meeting), [**search**](#search), and [**secondaryBrowser**](#secondarybrowser).
-The remainder of this article provides further information on each capability of the Teams JavaScript client library.
+Later in this article, you can find more information on each capability of the Teams JavaScript client library.
## `app`
The `app` namespace is supported globally across all application hosts and, ther
<th>app</th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;*</td>
+ <td>&#x2713;*</td>
</tr> </tbody> </table>
The `authentication` namespace is supported globally across all application host
<th>authentication</th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;*</td>
+ <td>&#x2713;*</td>
</tr> </tbody> </table>
Namespace providing calendar-related functionality.
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
Preview. This group of capabilities enables apps to show modal dialogs. There ar
<th>dialog <img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;</td>
<td></td> <td>&#x2713;</td> <td></td>
Preview. This group of capabilities enables apps to show modal dialogs. There ar
<th><a href="#dialogupdate">dialog.update</a><img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
- <td></td>
+ <td>&#x2713;</td>
<td>&#x2713;</td> <td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
+ <td></td>
<td></td> <td></td> </tr>
Preview. This group of capabilities enables apps to show modal dialogs. There ar
<th><a href="#dialogurl">dialog.url</a><img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th> <td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;</td>
<td></td> <td>&#x2713;</td> <td></td>
Preview. This group of capabilities enables apps to show modal dialogs. There ar
<th><a href="#dialogurlbot">dialog.url.bot</a><img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th> <td>&#x2713;</td> <td></td>
- <td>&#x2713;*</td>
+ <td></td>
<td>&#x2713;</td> <td>&#x2713;*</td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td>&#x2713;</td> <td></td>
When an API doesn't support or generates an error, add logic to fail or provide
<td></td> <td></td> <td></td>
+ <td></td>
+ <td></td>
</tr> <tr> <th><a href="#geolocationmap">geoLocation.map</a> <img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th>
When an API doesn't support or generates an error, add logic to fail or provide
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td></td>
<td></td> <td></td> <td></td>
Namespace providing email-related functionality.
<th>mail</th> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
Namespace to interact with the menu-related part of the library. This module is
<tbody> <tr> <th>menus</th>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> <td></td>
Prior to TeamsJS version 2.0, all deep linking scenarios were handled using `sha
</thead> <tbody> <tr>
- <th>pages</th>
+ <th><a href="#pages">pages</a></th>
<td>&#x2713;</td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
- <td>&#x2713;*</td>
<td>&#x2713;</td> <td>&#x2713;*</td>
- <td></td>
<td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td> <td>&#x2713;</td> <td>&#x2713;</td> <td>&#x2713;*</td>
+ <td>&#x2713;</td>
+ <td>&#x2713;*</td>
+ <td>&#x2713;*</td>
</tr> <tr> <th><a href="#pagesappbutton">pages.appButton</a></th>
Prior to TeamsJS version 2.0, all deep linking scenarios were handled using `sha
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
<td></td> <td></td> </tr>
Prior to TeamsJS version 2.0, all deep linking scenarios were handled using `sha
<td></td> <td></td> <td></td>
- <td></td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td>&#x2713;</td>
Prior to TeamsJS version 2.0, all deep linking scenarios were handled using `sha
<th><a href="#pagescurrentapp">pages.currentApp</a></th> <td></td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td></td>
- <td>&#x2713;*</td>
- <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td></td> <td></td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
+ <td></td>
+ <td></td>
<td></td> <td>&#x2713;</td>
+ <td></td>
+ <td></td>
+ <td>&#x2713;*</td>
<td>&#x2713;*</td> </tr> <tr>
Prior to TeamsJS version 2.0, all deep linking scenarios were handled using `sha
<td>&#x2713;</td> <td>&#x2713;*</td> <td></td>
- <td>&#x2713;*</td>
<td></td> <td></td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td>&#x2713;</td>
Prior to TeamsJS version 2.0, all deep linking scenarios were handled using `sha
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> </tr>
Namespace providing functionality for [People Picker API](../concepts/device-cap
<td>&#x2713;</td> <td></td> <td></td>
- <td>&#x2713;*</td>
<td>&#x2713;</td>
+ <td>&#x2713;*</td>
<td></td> <td></td> <td></td>
Preview. Namespace providing for profile-related functionality.
<td></td> <td></td> <td></td>
- <td>&#x2713;*</td>
+ <td>&#x2713;</td>
<td></td> <td></td> <td></td>
Preview. Allows your application to interact with the host Microsoft 365 applica
</tbody> </table>
+## `secondaryBrowser`
+
+[Reference](/javascript/api/@microsoft/teams-js/secondaryBrowser)
+
+Preview. Namespace supporting in-app browser experiences of the host app. For example, opening a URL in the host app inside a browser.
+
+<br />
+<table border>
+ <thead>
+ <tr>
+ <th></th>
+ <th colspan=3>Web</th>
+ <th colspan=5>Desktop</th>
+ <th colspan=6>Mobile</th>
+ </tr>
+ <tr>
+ <th></th>
+ <th colspan=3></th>
+ <th colspan=5>Windows</th>
+ <th colspan=3>Android</th>
+ <th colspan=3>iOS</th>
+ </tr>
+ <tr>
+ <td></td>
+ <td><img alt="Teams" src="./images/teams-icon.png"/></td>
+ <td><img alt="Microsoft 365 app" src="./images/microsoft-365-icon.png"/></td>
+ <td><img alt="Outlook" src="./images/outlook-icon.png"/></td>
+ <td><img alt="Teams" src="./images/teams-icon.png"/></td>
+ <td><img alt="Teams (Preview)" src="./images/teams-preview-icon.png"/></td>
+ <td><img alt="Microsoft 365 app" src="./images/microsoft-365-icon.png"/></td>
+ <td><img alt="Outlook" src="./images/outlook-icon.png"/></td>
+ <td><img alt="Outlook (Preview)" src="./images/outlook-preview-icon.png"/></td>
+ <td><img alt="Teams" src="./images/teams-icon.png"/></td>
+ <td><img alt="Microsoft 365 app" src="./images/microsoft-365-icon.png"/></td>
+ <td><img alt="Outlook" src="./images/outlook-icon.png"/></td>
+ <td><img alt="Teams" src="./images/teams-icon.png"/></td>
+ <td><img alt="Microsoft 365 app" src="./images/microsoft-365-icon.png"/></td>
+ <td><img alt="Outlook" src="./images/outlook-icon.png"/></td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th>secondaryBrowser <img src="./images/preview-badge.png" alt="Badge indicating this capability is in preview" /></th>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+</table>
+ ## `settings` [Reference](/javascript/api/@microsoft/teams-js/settings)
Namespace to open a share dialog for web content. For more information, see [Sha
<td></td> <td></td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> <td></td>
Preview. Namespace to interact with the Stage View specific part of the library.
<td></td> <td></td> <td>&#x2713;</td>
- <td>&#x2713;*</td>
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
+ <td></td>
<td></td> <td></td> </tr>
Namespace containing the set of APIs that support Teams-specific functionalities
<td></td> <td></td> <td></td>
- <td>&#x2713;</td>
<td></td> <td></td>
- <td>&#x2713;</td>
+ <td></td>
+ <td></td>
<td></td> <td></td> </tr>
platform Build A Dashboard Tab App https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/Build-a-dashboard-tab-app.md
The dashboard tab template from Teams Toolkit allows you to get started with int
:::image type="content" source="../../assets/images/dashboard/dashboard-demonstration.png" alt-text="Screenshot shows the sample of a dashboard.":::
-Your team can get the latest updates from different sources in Teams using the Teams dashboard tab app. Use dashboard tab apps to connect numerous metrics, data sources, APIs, and services to help your business extract relevant information from the sources and present it to the users. For more information about creating a dashboard tab app and the source code directory structure, see [step-by-step guide](#step-by-step-guide).
+Your team can get the latest updates from different sources in Teams using the Teams dashboard tab app. Use dashboard tab apps to connect numerous metrics, data sources, APIs, and services. Dashboard tab apps help your business extract relevant information from the sources and present it to the users. For more information about creating a dashboard tab app, see [step-by-step guide](#step-by-step-guide).
## Add a new dashboard
To add a new dashboard, follow these steps:
### Create a dashboard class
-Create a file with the .tsx extension for your dashboard in the tabs/src/views/dashboards directory, for example, YourDashboard.tsx. Then, create a class that extends the [Dashboard](https://github.com/OfficeDev/TeamsFx/wiki/) class:
+Create a file with the `.tsx` extension for your dashboard in the `src/dashboards` directory, for example, `YourDashboard.tsx`. Then, create a class that extends the `BaseDashboard class from`
+[@microsoft/teamsfx-react](/javascript/api/%40microsoft/teamsfx-react).
```typescript
+//YourDashboard.tsx
+import { BaseDashboard } from "@microsoft/teamsfx-react";
-export default class YourDashboard extends Dashboard {}
-
+export default class YourDashboard extends BaseDashboard<any, any> {}
``` > [!NOTE]
export default class YourDashboard extends Dashboard {}
### Override methods to customize dashboard tab app
-The `dashboard` class provides few methods that you can override to customize the dashboard layout. The following table lists the methods that you can override:
+The `BaseDashboard` class provides few methods that you can override to customize the dashboard layout. The following table lists the methods that you can override:
| **Methods** | **Function** | |||
-| `rowHeights()` | Customize the height of each row of the dashboard. |
-| `columnWidths()` | Customize how many columns the dashboard has at most and the width of each column. |
-| `dashboardLayout()` | Define widgets layout. |
+| `styling()` | Customize the style of the dashboard. |
+| `layout()` | Define widgets layout. |
The following code is an example to customize the dashboard layout:
+```
+.your-dashboard-layout {
+ grid-template-columns: 6fr 4fr;
+}
+```
+ ```typescript
-export default class YourDashboard extends Dashboard {
- override rowHeights(): string | undefined {
- return "500px";
- }
+import { BaseDashboard } from "@microsoft/teamsfx-react";
+import ListWidget from "../widgets/ListWidget";
+import ChartWidget from "../widgets/ChartWidget";
- override columnWidths(): string | undefined {
- return "4fr 6fr";
+export default class YourDashboard extends BaseDashboard<any, any> {
+ override styling(): string {
+ return "your-dashboard-layout";
}
- override dashboardLayout(): JSX.Element | undefined {
+ override layout(): JSX.Element | undefined {
return ( <>
- <SampleWidget />
+ <ListWidget />
+ <ChartWidget />
</> ); }
export default class YourDashboard extends Dashboard {
You must link your widget to a data source file. The widget picks up the data that's presented in the dashboard from the source file.
-Open **tabs/src/App.tsx** and add a route for the new dashboard. Here's an example:
+Open the `src/App.tsx` file and add a route for the new dashboard. Here's an example:
```typescript
-import YourDashboard from "./views/dashboards/YourDashboard";
+import YourDashboard from "./dashboards/YourDashboard";
export default function App() { ...
- <Route exact path="/yourdashboard" component={YourDashboard} />
+ <Route path="/yourdashboard" element={<YourDashboard />} />
... } ``` ### Modify manifest to add a new dashboard tab app
-Open **templates/appPackage/manifest.template.json** and add a new dashboard tab under **staticTabs**. Here's an example:
+Open the `appPackage/manifest.json` file and add a new dashboard tab under `staticTabs`. Here's an example:
```json {
+ "entityId": "index1",
"name": "Your Dashboard",
- "entityId": "yourdashboard",
- "contentUrl": "{{state.fx-resource-frontend-hosting.endpoint}}{{state.fx-resource-frontend-hosting.indexPath}}/yourdashboard",
- "websiteUrl": "{{state.fx-resource-frontend-hosting.endpoint}}{{state.fx-resource-frontend-hosting.indexPath}}/yourdashboard",
+ "contentUrl": "${{TAB_ENDPOINT}}/https://docsupdatetracker.net/index.html#/yourdashboard",
+ "websiteUrl": "${{TAB_ENDPOINT}}/https://docsupdatetracker.net/index.html#/yourdashboard",
"scopes": ["personal"] } ``` ## Customize the dashboard layout
-Teamsfx provides convenient methods to define and modify the layout of the dashboard. The following are the methods:
+TeamsFx provides convenient methods to define and modify the layout of the dashboard. The following are the methods:
* Three widgets in a row with the height of 350 px occupying 20 percent, 60 percent, and 20 percent of the width, respectively. ```typescript
- export default class SampleDashboard extends Dashboard {
- override rowHeights(): string | undefined {
- return "350px";
- }
-
- override columnWidths(): string | undefined {
- return "2fr 6fr 2fr";
+ .customize-class-name {
+ grid-template-rows: 350px;
+ grid-template-columns: 2fr 6fr 2fr;
+ }
+ ```
+
+ ```typescript
+ export default class SampleDashboard extends BaseDashboard<any, any> {
+
+ override styling(): string {
+ return "customize-class-name";
}
-
- override dashboardLayout(): undefined | JSX.Element {
+
+ override layout(): JSX.Element | undefined {
return ( <>
- <ListWidget />
- <ChartWidget />
- <NewsWidget />
+ <ListWidget />
+ <ChartWidget />
+ <NewsWidget />
</> ); }
Teamsfx provides convenient methods to define and modify the layout of the dashb
* Two widgets in a row with a width of 600 px and 1100 px. The height of the first line is the maximum height of its content, and the height of the second line is 400 px. ```typescript
- export default class SampleDashboard extends Dashboard {
- override rowHeights(): string | undefined {
- return "max-content 400px";
- }
-
- override columnWidths(): string | undefined {
- return "600px 1100px";
+ .customize-class-name {
+ grid-template-rows: max-content 400px;
+ grid-template-columns: 600px 1100px;
+ }
+ ```
+
+ ```typescript
+ export default class SampleDashboard extends Dashboard {
+ override styling(): string {
+ return "customize-class-name";
}
-
- override dashboardLayout(): undefined | JSX.Element {
+
+ override layout(): JSX.Element | undefined {
return ( <>
- <ListWidget />
- <ChartWidget />
- <NewsWidget />
+ <ListWidget />
+ <ChartWidget />
+ <NewsWidget />
</> ); }
- }
+ }
``` :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/customize-dashboard-layout2.png" alt-text="Screenshot shows the customization of height and width of the dashboard layout."::: * Arrange two widgets in a column.
- ```css
- .one-column {
+ ```css
+ .one-column {
display: grid; gap: 20px; grid-template-rows: 1fr 1fr; }
- ```
-
- ```typescript
- override dashboardLayout(): JSX.Element | undefined {
- return (
- <>
- <NewsWidget />
- <div className="one-column">
- <ListWidget />
- <ChartWidget />
- </div>
- </>
- );
- }
- ```
-
- :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/widget-customize.png" alt-text="Screenshot shows the two-widget customization.":::
-
-* Customize the height of widgets in a row.
+ ```
- The following code can achieve a height of 400 px for the `ListWidget` and a height of 350 px for the `ChartWidget`:
-
- ```css
- .one-column {
- display: grid;
- gap: 20px;
- grid-template-rows: 400px 350px;
- }
- ```
-
- ```typescript
- override dashboardLayout(): JSX.Element | undefined {
- return (
- <>
- <NewsWidget />
- <div className="one-column">
- <ListWidget />
- <ChartWidget />
- </div>
- </>
- );
+ ```typescript
+ export default class SampleDashboard extends BaseDashboard<any, any> {
+ override layout(): JSX.Element | undefined {
+ return (
+ <>
+ <NewsWidget />
+ <div className="one-column">
+ <ListWidget />
+ <ChartWidget />
+ </div>
+ </>
+ );
+ }
}
- ```
+ ```
- :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/chart-widget.png" alt-text="Screenshot shows the customization of a chart widget.":::
+ :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/widget-customize.png" alt-text="Screenshot shows the two-widget customization.":::
### Dashboard tab app abstraction
-To adjust the layout of the dashboard, Teamsfx provides a `dashboard` class for the developers to implement a dashboard.
+To adjust the layout of the dashboard, TeamsFx provides a `BaseDashboard` class for the developers to implement a dashboard.
-The following code is an example of a dashboard class:
+The following code is an example of a `BaseDashboard` class:
```typescript
-import React, { Component } from "react";
-
-import { mergeStyles } from "@fluentui/react";
+function dashboardStyle(isMobile?: boolean) {
+ return mergeStyles({
+ display: "grid",
+ gap: "20px",
+ padding: "20px",
+ gridTemplateRows: "1fr",
+ gridTemplateColumns: "4fr 6fr",
+ ...(isMobile === true ? { gridTemplateColumns: "1fr", gridTemplateRows: "1fr" } : {}),
+ });
+}
-interface IDashboardState {
+interface BaseDashboardState {
isMobile?: boolean;
+ showLogin?: boolean;
observer?: ResizeObserver; }
-export class Dashboard extends Component<{}, IDashboardState> {
+export class BaseDashboard<P, S> extends Component<P, S & BaseDashboardState> {
private ref: React.RefObject<HTMLDivElement>;
- constructor(props: any) {
+ public constructor(props: Readonly<P>) {
super(props); this.state = { isMobile: undefined,
+ showLogin: undefined,
observer: undefined,
- };
+ } as S & BaseDashboardState;
this.ref = React.createRef<HTMLDivElement>(); }
- componentDidMount(): void {
- // Observe the dashboard div for resize events
+ public async componentDidMount() {
const observer = new ResizeObserver((entries) => {
- for (let entry of entries) {
+ for (const entry of entries) {
if (entry.target === this.ref.current) { const { width } = entry.contentRect;
- this.setState({ isMobile: width < 600 });
+ this.setState({ isMobile: width < 600 } as S & BaseDashboardState);
} } }); observer.observe(this.ref.current!); }
- componentWillUnmount(): void {
- // Unobserve the dashboard div for resize events
+ public componentWillUnmount(): void {
if (this.state.observer && this.ref.current) { this.state.observer.unobserve(this.ref.current); } }
- render() {
- const styling = mergeStyles({
- display: "grid",
- gap: "20px",
- padding: "1rem",
- gridTemplateColumns: "4fr 6fr",
- gridTemplateRows: "1fr",
- ...(this.state.isMobile && { gridTemplateColumns: "1fr" }),
- ...(this.columnWidths() && { gridTemplateColumns: this.columnWidths() }),
- ...(this.rowHeights() && { gridTemplateRows: this.rowHeights() }),
- });
-
+ public render() {
return (
- <>
- <div ref={this.ref} className={styling}>
- {this.dashboardLayout()}
- </div>
- </>
+ <div
+ ref={this.ref}
+ className={mergeStyles(dashboardStyle(this.state.isMobile), this.styling())}
+ >
+ {this.layout()}
+ </div>
); }
- protected rowHeights(): string | undefined {
+ protected layout(): JSX.Element | undefined {
return undefined; }
- protected columnWidths(): string | undefined {
- return undefined;
- }
-
- protected dashboardLayout(): JSX.Element | undefined {
- return undefined;
+ protected styling(): string {
+ return null;
} } ```
-In the `dashboard` class, Teamsfx provides basic layouts with customizable methods. The dashboard is still a react component, and Teamsfx provides basic implementations of functions based on the lifecycle of react components, such as:
+In the `BaseDashboard` class, TeamsFx provides basic layouts with customizable methods. The dashboard is still a react component, and TeamsFx provides basic implementations of functions based on the lifecycle of react components, such as:
* Implementing a basic render logic based on the grid layout. * Adding an observer to automatically adapt to mobile devices. The following are the customizable methods to override:
-| File | Content | Recommend to override |
+| Methods | Function | Recommend to override |
||||
-| **constructor()** | Initializes the dashboard state and variables. | No |
-| **componentDidMount()** | Invokes after a component is mounted. | No |
-| **componentWillUnmount()** | Invokes when a component is unmounted. | No |
-| **render()** | Invokes when there's an update. The dashboard default layout is defined in this method. | No |
-| **rowHeights()** | Customizes the height of each row of the dashboard. | Yes |
-| **columnWidths()** | Customizes the number of columns the dashboard has at most and the width of each column. | Yes |
-| **dashboardLayout()** | Defines the widget layout in dashboard. | Yes |
+| `constructor()` | Initializes the dashboard state and variables. | No |
+| `componentDidMount()` | Invokes after a component is mounted. | No |
+| `componentWillUnmount()` | Invokes when a component is unmounted. | No |
+| `render()` | Invokes when there's an update. The dashboard default layout is defined in this method. | No |
+| `layout` | Defines the layout of the widget in the dashboard. You can override this method. | Yes |
+| `styling()` | To customize the style of the dashboard. You can override this method. | Yes |
## Use a widget in your dashboard
Widgets display configurable information and charts on dashboards. They appear o
### Customize the widget
-You can customize the widget by overriding the following methods in the `widget` class:
+You can customize the widget by overriding the following methods in the `BaseWidget` class:
-* Override `headerContent()`, `bodyContent()`, and `footerContent()` to customize the widget.
+* Override `header()`, `body()`, and `footer()` to customize the widget.
```typescript
- export class NewsWidget extends Widget<any, any> {
-
- headerContent(): JSX.Element | undefined {
- return (
- <div>
- <News28Regular />
- <Text>Your News</Text>
- <Button icon={<MoreHorizontal32Regular />} appearance="transparent" />
- </div>
- );
- }
-
- bodyContent(): JSX.Element | undefined {
- return (
- <div className="content-layout">
- <Image src="image.svg" className="img" />
- <Text className="title">Lorem Ipsum Dolor</Text>
- <Text className="desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim, elementum sed</Text>
- </div>
- );
- }
-
- footerContent(): JSX.Element | undefined {
- return (
- <Button
- appearance="transparent"
- icon={<ArrowRight16Filled />}
- iconPosition="after"
- size="small"
- className="footer-button"
- onClick={() => { }} // navigate to detailed page
- >
- View details
- </Button>
- );
- }
+ export class NewsWidget extends BaseWidget<any, any> {
+ override header(): JSX.Element | undefined {
+ return (
+ <div>
+ <News28Regular />
+ <Text>Your News</Text>
+ <Button icon={<MoreHorizontal32Regular />} appearance="transparent" />
+ </div>
+ );
+ }
+
+ override body(): JSX.Element | undefined {
+ return (
+ <div>
+ <Image src="image.svg" />
+ <Text>Lorem Ipsum Dolor</Text>
+ <Text>
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim,
+ elementum sed
+ </Text>
+ </div>
+ );
+ }
+
+ override footer(): JSX.Element | undefined {
+ return (
+ <Button
+ appearance="transparent"
+ icon={<ArrowRight16Filled />}
+ iconPosition="after"
+ size="small"
+ >
+ View details
+ </Button>
+ );
+ }
} ``` :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/override-header-count.png" alt-text="Screenshot shows the example of header, body, and footer content in a widget.":::
-* Override `bodyContent()` and `footerContent()` to customize the widget.
+* Override `body()` and `footer()` to customize the widget.
```typescript
- export class NewsWidget extends Widget<any, any> {
-
- bodyContent(): JSX.Element | undefined {
- return (
- <div className="content-layout">
- <Image src="image.svg" className="img" />
- <Text className="title">Lorem Ipsum Dolor</Text>
- <Text className="desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim, elementum sed</Text>
- </div>
- );
- }
-
- footerContent(): JSX.Element | undefined {
- return (
- <Button
- appearance="transparent"
- icon={<ArrowRight16Filled />}
- iconPosition="after"
- size="small"
- className="footer-button"
- onClick={() => { }} // navigate to detailed page
- >
- View details
- </Button>
- );
- }
+ export class NewsWidget extends BaseWidget<any, any> {
+ override body(): JSX.Element | undefined {
+ return (
+ <div>
+ <Image src="image.svg" />
+ <Text>Lorem Ipsum Dolor</Text>
+ <Text>
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim,
+ elementum sed
+ </Text>
+ </div>
+ );
+ }
+
+ override footer(): JSX.Element | undefined {
+ return (
+ <Button
+ appearance="transparent"
+ icon={<ArrowRight16Filled />}
+ iconPosition="after"
+ size="small"
+ >
+ View details
+ </Button>
+ );
+ }
} ``` :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/override-body-content-footer-content.png" alt-text="Screenshot shows the body and footer content in a widget.":::
-* Override `bodyContent()` to customize the widget.
+* Override `body()` to customize the widget.
```typescript
- export class NewsWidget extends Widget<any, any> {
-
- bodyContent(): JSX.Element | undefined {
- return (
- <div className="content-layout">
- <Image src="image.svg" className="img" />
- <Text className="title">Lorem Ipsum Dolor</Text>
- <Text className="desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim, elementum sed</Text>
- </div>
- );
- }
-
- }
+ export class NewsWidget extends BaseWidget<any, any> {
+ override body(): JSX.Element | undefined {
+ return (
+ <div>
+ <Image src="image.svg" />
+ <Text>Lorem Ipsum Dolor</Text>
+ <Text>
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim,
+ elementum sed
+ </Text>
+ </div>
+ );
+ }
+ }
``` :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/override-body-content.png" alt-text="Screenshot shows body content in a widget."::: ### Include a data loader
-If you want to include a data loader to your widget before the widget is loaded, you can add a property to the state of the widget to indicate that the data loader is loading. You can use this property to show a loading indicator to the user.
-
-The following steps show how to add a property to the state of `ListWidget` and how to use it to show a loading spinner while the data is loading.
-
-1. Define a state type: Define a state type including a property named `loading` that indicates whether the data is loading.
-
- ```typescript
- interface ListWidgetState {
- data: ListModel[];
- loading?: boolean;
- }
- ```
-
-1. Add a data loader: Modify the `bodyContent` method to show a loading spinner if data is loading.
-
- ```typescript
- bodyContent(): JSX.Element | undefined {
- return (
- <>
- {this.state.loading !== false ? (
- <div className="loading-class-name">
- <Spinner label="Loading..." labelPosition="below" />
- </div>
- ) : (
- <div className="list-body">
- ...
- </div>
- )}
- </>
- );
- }
- ```
-
-1. Hide the footer button if the data is loading.
+If you want to include a data loader to your widget before the widget is loaded, you can add a property to the state of the widget to indicate that the data loader is `loading()`. You can use this property to show a loading indicator to the user.
- The following code is an example of footer button:
+Example:
- ```typescript
- footerContent(): JSX.Element | undefined {
- if (this.state.loading === false) {
- return (
- <Button
- ...
- </Button>
- );
- }
+```typescript
+ override loading(): JSX.Element | undefined {
+ return (
+ <div className="loading">
+ <Spinner label="Loading..." labelPosition="below" />
+ </div>
+ );
}
- ```
-
-1. Update the state reference: Update the state reference in the widget file to use the new state type and update the state in the `getData` method to set the `loading` property to `false` after the data is loaded.
+```
- Now, the loading spinner is shown while the data is loading. When the data is loaded, the loading spinner is hidden and the list data, and footer button are shown.
+Now, the loading spinner is shown while the data is loading. When the data is loaded, the loading spinner is hidden, and the list data and footer button are shown.
- :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/spinner.gif" alt-text="Graphical representation shows the loading spinner while the data is loading.":::
### Handle empty state
-You can display a specific content in your widget when the data is empty. To do so, you need to modify the `bodyContent` method in your widget file to adopt different states of the data.
+You can display a specific content in your widget when the data is empty. To do so, you need to modify the `body` method in your widget file to adopt different states of the data.
-The following example shows how to display an empty image when the data of `ListWidget` is empty.
-
-```css
-.empty-layout {
- display: grid;
- gap: 1rem
- justify-content: center;
- align-content: center;
-}
-```
+The following example shows how to display an empty image when the data of **ListWidget** is empty.
```typescript
-bodyContent(): JSX.Element | undefined {
+override body(): JSX.Element | undefined {
let hasData = this.state.data && this.state.data.length > 0; return (
- <div className="list-body">
+ <div>
{hasData ? ( <> {this.state.data?.map((t: ListModel) => {
bodyContent(): JSX.Element | undefined {
})} </> ) : (
- <div className="empty-layout">
+ <div>
<Image src="empty-default.svg" height="150px" /> <Text align="center">No data</Text> </div>
bodyContent(): JSX.Element | undefined {
You can use a similar approach to remove the footer content of your widget when the data is empty. ```typescript
-footerContent(): JSX.Element | undefined {
- let hasData = this.state.data && this.state.data.length > 0;
- if (hasData) {
- return (
- <Button
- ...
- </Button>
- );
+ override footer(): JSX.Element | undefined {
+ let hasData = this.state.data && this.state.data.length > 0;
+ if (hasData) {
+ return <Button>...</Button>;
+ }
}
-}
```
- :::image type="content" source="../../assets/images/sbs-create-a-new-dashboard/no-data.png" alt-text="Screenshot showing no data in the list.":::
+When data is empty, your list widget appears as follows:
+ ### Refresh data as scheduled The following example shows how to display real-time data in a widget. The widget displays the current time and updates. ```typescript
-import { Widget } from "../lib/Widget";
- interface IRefreshWidgetState { data: string; }
-export class RefreshWidget extends Widget<any, IRefreshWidgetState> {
- bodyContent(): JSX.Element | undefined {
+export class RefreshWidget extends BaseWidget<any, IRefreshWidgetState> {
+ override body(): JSX.Element | undefined {
return <>{this.state.data}</>; }
You can modify `setInterval` method to call your own function to refresh data li
### Widget abstraction
-To simplify the development of a widget, Teamsfx provides a `widget` class for developers to inherit to implement a widget that meets their needs without paying much attention to implement the widget layout.
+To simplify the development of a widget, TeamsFx SDK provides a `BaseWidget` class for developers to inherit to implement a widget that meets their needs without paying much attention to implement the widget layout.
-The following code is an example of widget class:
+The following code is an example of BaseWidget class:
```typescript
-import "./Widget.css";
+export interface IWidgetClassNames {
+ root?: string;
+ header?: string;
+ body?: string;
+ footer?: string;
+}
-import { Component } from "react";
+const classNames: IWidgetClassNames = mergeStyleSets({
+ root: {
+ display: "grid",
+ padding: "1.25rem 2rem 1.25rem 2rem",
+ backgroundColor: tokens.colorNeutralBackground1,
+ border: "1px solid var(--colorTransparentStroke)",
+ boxShadow: tokens.shadow4,
+ borderRadius: tokens.borderRadiusMedium,
+ gap: tokens.spacingHorizontalL,
+ gridTemplateRows: "max-content 1fr max-content",
+ },
+ header: {
+ display: "grid",
+ height: "max-content",
+ "& div": {
+ display: "grid",
+ gap: tokens.spacingHorizontalS,
+ alignItems: "center",
+ gridTemplateColumns: "min-content 1fr min-content",
+ },
+ "& svg": {
+ height: "1.5rem",
+ width: "1.5rem",
+ },
+ "& span": {
+ fontWeight: tokens.fontWeightSemibold,
+ lineHeight: tokens.lineHeightBase200,
+ fontSize: tokens.fontSizeBase200,
+ },
+ },
+ footer: {
+ "& button": {
+ width: "fit-content",
+ },
+ },
+});
+
+interface BaseWidgetState {
+ loading?: boolean;
+}
-export abstract class Widget<P, T> extends Component<P, T> {
- constructor(props: any) {
+export class BaseWidget<P, S> extends Component<P, S & BaseWidgetState> {
+ public constructor(props: Readonly<P>) {
super(props);
- this.state = {} as T;
+ this.state = { loading: undefined } as S & BaseWidgetState;
}
- async componentDidMount() {
- this.setState({ ...(await this.getData()) });
+ public async componentDidMount() {
+ this.setState({ ...(await this.getData()), loading: false });
}
- render() {
+ public render() {
+ const { root, header, body, footer } = this.styling();
+ const showLoading = this.state.loading !== false && this.loading() !== undefined;
return (
- <div className="widget-root">
- {this.headerContent() && <div className="widget-header">{this.headerContent()}</div>}
- {this.bodyContent() && <div>{this.bodyContent()}</div>}
- {this.footerContent() && <div>{this.footerContent()}</div>}
+ <div className={mergeStyles(classNames.root, root)}>
+ {this.header() && (
+ <div className={mergeStyles(classNames.header, header)}>{this.header()}</div>
+ )}
+ {showLoading ? (
+ this.loading()
+ ) : (
+ <>
+ {this.body() !== undefined && <div className={body}>{this.body()}</div>}
+ {this.footer() !== undefined && (
+ <div className={mergeStyles(classNames.footer, footer)}>{this.footer()}</div>
+ )}
+ </>
+ )}
</div> ); }
- protected async getData(): Promise<T> {
- return new Promise<T>(() => {});
+ protected async getData(): Promise<S> {
+ return undefined;
}
- protected headerContent(): JSX.Element | undefined {
+ protected header(): JSX.Element | undefined {
return undefined; }
- protected bodyContent(): JSX.Element | undefined {
+ protected body(): JSX.Element | undefined {
return undefined; }
- protected footerContent(): JSX.Element | undefined {
+ protected footer(): JSX.Element | undefined {
return undefined; }+
+ protected loading(): JSX.Element | undefined {
+ return undefined;
+ }
+
+ protected styling(): IWidgetClassNames {
+ return {};
+ }
} ```
The following are the recommended methods to override:
| Methods | Function | Recommend to override | ||||
-| **constructor()** | Invokes the initial `this.state` and calls the constructor of the super class `React` component. | No |
-| **componentDidMount()** | Invokes after a component is mounted and assigns a value to the `data` property of the state by calling the `getData()` method. | No |
-| **render()** | Invokes whenever there's an update. The dashboard default layout is defined in this method. | No |
-| **getData()** | Invokes the data needed by the widget. The value returned by this method is set to `this.state.data`. |
-| **headerContent()** | Invokes what the widget header looks like. You can choose to override this method to customize a widget or not, if not, the widget won't have a header. | Yes |
-| **bodyContent()** | Invokes what the widget body looks like. You can choose to override this method to customize a widget or not, if not, the widget won't have a body. | Yes |
-| **footerContent()** | Invokes what the widget footer looks like. You can choose to override this method to customize a widget or not, if not, the widget won't have a footer. | Yes |
+| `constructor()` | Invokes the initial `this.state` and calls the constructor of the super class `React.Component`. | No |
+| `componentDidMount()` | Invokes after a component is mounted and assigns a value to the `data` property of the state by calling the `getData()` method. | No |
+| `render()` | Invokes whenever there's an update. The dashboard default layout is defined in this method. | No |
+| `getData()` | Invokes the data needed by the widget. The value returned by this method is set to `this.state.data`. | Yes |
+| `header()` | Invokes what the widget header looks like. You can choose to override this method to customize a widget or not, if not, the widget won't have a header. | Yes |
+| `body()` | Invokes what the widget body looks like. You can choose to override this method to customize a widget or not, if not, the widget won't have a body. | Yes |
+| `footer()` | Invokes what the widget footer looks like. You can choose to override this method to customize a widget or not, if not, the widget won't have a footer. | Yes |
+| `loading()` | Invokes when the widget is in the process of fetching data. If a loading indicator is required, the method can return a `JSX.Element` that contains the necessary components to render the loading indicator. | Yes |
+| `style()` | Invokes an object that defines the class names for the different parts of the widget. | Yes |
### Microsoft Graph Toolkit as widget content
To use Microsoft Graph Toolkit as your widget content, follow these steps:
npm install @microsoft/mgt-react @microsoft/mgt-teamsfx-provider ```
-1. Add a new Graph Toolkit widget: Create a new widget file in your project tabs/src/views/widgets folder, for example, GraphyWidget.tsx. In this widget, we'll guide users to consent our app to access Microsoft Graph and then show the user's `Todo` list by using Microsoft Graph Toolkit.
+1. Add a new Graph Toolkit widget: Create a new widget file in your project `src/views/widgets` folder, for example, `GraphWidget.tsx`. In this widget, we'll guide users to consent our app to access Microsoft Graph and then show the user's Todo list by using Microsoft Graph Toolkit.
- The following code is an example of using `Todo` component from Microsoft Graph Toolkit in widget:
+ The following code is an example of using Todo component from Microsoft Graph Toolkit in widget:
```tsx
- import { Providers, ProviderState, Todo } from "@microsoft/mgt-react";
- import { TeamsFxProvider } from "@microsoft/mgt-teamsfx-provider";
-
- import { loginAction } from "../../internal/login";
- import { TeamsUserCredentialContext } from "../../internal/singletonContext";
- import { Widget } from "../lib/Widget";
-
- interface IGraphWidgetState {
- needLogin: boolean;
+ import { Providers, ProviderState, Todo } from "@microsoft/mgt-react";
+ import { TeamsFxProvider } from "@microsoft/mgt-teamsfx-provider";
+
+ import { loginAction } from "../../internal/login";
+ import { TeamsUserCredentialContext } from "../../internal/singletonContext";
+ import { BaseWidget } from "@microsoft/teamsfx-react";
+
+ interface IGraphWidgetState {
+ needLogin: boolean;
+ }
+
+ export class GraphWidget extends Widget<any, IGraphWidgetState> {
+ override body(): JSX.Element | undefined {
+ return <div>{this.state.needLogin === false && <Todo />}</div>;
}
-
- export class GraphWidget extends Widget<any, IGraphWidgetState> {
- override bodyContent(): JSX.Element | undefined {
- return <div>{this.state.needLogin === false && <Todo />}</div>;
- }
-
- async componentDidMount() {
- super.componentDidMount();
-
- // Initialize TeamsFx provider
- const provider = new TeamsFxProvider(TeamsUserCredentialContext.getInstance().getCredential(), [
- "Tasks.ReadWrite",
- ]);
- Providers.globalProvider = provider;
-
- // Check if user is signed in
- if (await this.checkIsConsentNeeded()) {
- await loginAction(["Tasks.ReadWrite"]);
- }
-
- // Update signed in state
- Providers.globalProvider.setState(ProviderState.SignedIn);
- this.setState({ needLogin: false });
- }
-
- /**
- * Check if user needs to consent
- * @returns true if user needs to consent
- */
- async checkIsConsentNeeded() {
- let needConsent = false;
- try {
- await TeamsUserCredentialContext.getInstance().getCredential().getToken(["Tasks.ReadWrite"]);
- } catch (error) {
- needConsent = true;
- }
- return needConsent;
+
+ async componentDidMount() {
+ super.componentDidMount();
+
+ // Initialize TeamsFx provider
+ const provider = new TeamsFxProvider(TeamsUserCredentialContext.getInstance().getCredential(), [
+ "Tasks.ReadWrite",
+ ]);
+ Providers.globalProvider = provider;
+
+ // Check if user is signed in
+ if (await this.checkIsConsentNeeded()) {
+ await loginAction(["Tasks.ReadWrite"]);
+ }
+
+ // Update signed in state
+ Providers.globalProvider.setState(ProviderState.SignedIn);
+ this.setState({ needLogin: false });
+
+ }
+
+ /**
+
+ * Check if user needs to consent
+ * @returns true if user needs to consent
+ */
+
+ async checkIsConsentNeeded() {
+ let needConsent = false;
+ try {
+ await TeamsUserCredentialContext.getInstance().getCredential().getToken(["Tasks.ReadWrite"]);
+ } catch (error) {
+ needConsent = true;
}
+ return needConsent;
}
-
+ }
```
- For more information, refer [Microsoft Graph Toolkit](/graph/toolkit/overview).
+ You can use alternative Microsoft Graph Toolkit components within your widget. For more information, see [Microsoft Graph Toolkit](/graph/toolkit/overview).
1. Add the widget to dashboard layout. Include the new widget in your dashboard file. ```tsx ...
- export default class YourDashboard extends Dashboard {
+ export default class YourDashboard extends BaseDashboard<any, any> {
...
- override dashboardLayout(): undefined | JSX.Element {
+ override layout(): undefined | JSX.Element {
return ( <> <GraphWiget />
Now, launch or refresh your Teams app, you'll see the new widget using Microsoft
Microsoft Graph API is a web API that you can use to communicate with Microsoft cloud and other services. Custom applications can use the Microsoft Graph API to connect to data and use it in custom applications to enhance organizational productivity.
+Before implementing your Graph API call logic, it's necessary to enable SSO for your dashboard project. For more information, see [Add single sign-on to Teams app](../../toolkit/add-single-sign-on.md).
+ To add a Graph API call: * [Call Graph API from the front-end (use delegated permissions)](#call-graph-api-from-the-front-end-use-delegated-permissions)
To add a Graph API call:
If you want to call a Graph API from the front-end tab, follow these steps:
-1. Consent delegated permissions first: You can call `addNewPermissionScope(scopes: string[])` to consent the scopes of permissions you want to add. The consented status is preserved in a global context `FxContext`.
+1. To obtain the name of the permission scope associated with the Graph API you intend to invoke, see [Graph API](/graph/api/overview).
1. Create a Graph client by adding the scope related to the Graph API you want to call. ```typescript
- let teamsfx;
- teamsfx = FxContextInstance.getTeamsFx();
- const graphClient = createMicrosoftGraphClient(teamsfx, scope);
+ let credential: TeamsUserCredential;
+ credential = TeamsUserCredentialContext.getInstance().getCredential();
+ const graphClient: Client = createMicrosoftGraphClientWithCredential(credential, scope);
``` 1. Call the Graph API and parse the response into a certain model.
To consent application permissions, follow these steps:
#### Add an Azure function
-In the left pane of the Visual Studio Code, select **Teams Toolkit** > **Adding features** > **Azure Functions** > and Enter the function name.
+In the left pane of the Visual Studio Code, go to **Teams Toolkit** > **Adding features** > **Azure Functions** and enter the function name.
:::image type="content" source="~/assets/images/sbs-create-a-new-dashboard/azure-functions.png" alt-text="Screenshot shows the selection of Azure Functions.":::
+For more information on how to add an Azure Function to your project, see [integrate Azure Functions with your Teams app](https://github.com/OfficeDev/TeamsFx/wiki/How-to-integrate-Azure-Functions-with-your-Teams-app).
+ #### Add your logic in Azure function In the `index.ts`/`index.ts` under the folder named Azure Function, you can add your logic that contains back-end Graph API calling with application permissions. Refer to the following code snippet:
Call the Azure function by function name. Refer to the following code snippet to
```typescript const functionName = process.env.REACT_APP_FUNC_NAME || "myFunc";
-async function callFunction(teamsfx) {
- if (!teamsfx) {
+export let taskName: string;
+
+export async function callFunction(params?: string) {
+ taskName = params || "";
+ const credential = TeamsUserCredentialContext.getInstance().getCredential();
+ if (!credential) {
throw new Error("TeamsFx SDK is not initialized."); } try {
- const credential = teamsfx.getCredential();
- const apiBaseUrl = teamsfx.getConfig("apiEndpoint") + "/api/";
- // createApiClient(...) creates an Axios instance which uses BearerTokenAuthProvider to inject token to request header
+ const apiBaseUrl = process.env.REACT_APP_FUNC_ENDPOINT + "/api/";
const apiClient = createApiClient( apiBaseUrl,
- new BearerTokenAuthProvider(
- async () => (await credential.getToken(""))!.token
- )
+ new BearerTokenAuthProvider(async () => (await credential.getToken(""))!.token)
); const response = await apiClient.get(functionName); return response.data;
- } catch (e) {}
+ } catch (err: unknown) {
+ ...
+ }
} ```
platform Create Personal Tab https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/create-personal-tab.md
zone_pivot_groups: teams-app-environment
# Create a personal tab
+> [!IMPORTANT]
+>
+> * To learn how to create a tab with Teams Toolkit, see [build your first tab app using JavaScript](../../sbs-gs-javascript.yml).
+> * We've introduced the [Teams Toolkit Overview](../../toolkit/teams-toolkit-fundamentals.md) extension within Visual Studio Code. This version comes to you with many new app development features. We recommend that you use Teams Toolkit v5 for building your Teams app.
+ Personal tabs, along with personally-scoped bots, are part of personal apps and are scoped to a single user. They can be pinned to the left pane for easy access. You can also [reorder](#reorder-static-personal-tabs) your personal tabs. Ensure that you've all the [prerequisites](~/tabs/how-to/tab-requirements.md) to build your personal tab.
platform Debug Mobile https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/toolkit/debug-mobile.md
+
+ Title: Debug for mobile
+
+description: In this module, learn how to debug your Teams app in mobile clients.
+
+ms.localizationpriority: high
+ Last updated : 06/14/2023++
+# Debug for mobile
+
+When you're building a Microsoft Teams app that includes a tab, bot, or message extension, you must debug your app to know how the app functions on both Android and iOS Microsoft Teams mobile clients. For more information, see [debug your Teams app locally](debug-local.md).
+
+## Debug your tab app
+
+To debug your tab app follow these steps:
+
+# [Visual Studio Code](#tab/vscode)
+
+You can view the project folders and files under **Explorer** in the Visual Studio Code.
+
+1. Add `Start local tunnel` after `Validate prerequisites` in the `task.json` file to make the tab app accessible on the mobile client.
+1. Add the following code after the property `dependsOrder` in the `task.json` file.
+
+ ```json
+ {
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Start Teams App Locally",
+ "dependsOn": [
+ "Validate prerequisites",
+ "Start local tunnel", // Add this line
+ "Provision",
+ "Deploy",
+ "Start application"
+ ],
+ "dependsOrder": "sequence"
+ },
+ {
+ // Add this task
+ "label": "Start local tunnel",
+ "type": "teamsfx",
+ "command": "debug-start-local-tunnel",
+ "args": {
+ "type": "dev-tunnel",
+ "ports": [
+ {
+ "portNumber": 53000,
+ "protocol": "https",
+ "access": "private",
+ "writeToEnvironmentFile": {
+ "endpoint": "TAB_ENDPOINT",
+ "domain": "TAB_DOMAIN"
+ }
+ }
+ ],
+ "env": "local"
+ },
+ "isBackground": true,
+ "problemMatcher": "$teamsfx-local-tunnel-watch"
+ }
+ ]
+ }
+ ```
+
+ > [!NOTE]
+ >
+ > * To preview the tab app only in mobile client, set the value for `access` property to `private`.
+ > * When the dev tunnel access value is set to `private`, the tab app cannot be displayed within an iframe on the web client. The login page is hosted on **login.microsoftonline.com**, which has the `X-FRAME-Options` header set to DENY.
+ > * To preview the tab app on the mobile client and debug it on web clients, set the access value to `public`. Any user with the app's URL can visit the tab.
+
+ :::image type="content" source="../assets/images/debug-mobile/login.PNG" alt-text="The screenshot shows the login page.":::
+
+1. Remove `TAB_DOMAIN` and `TAB_ENDPOINT` from the `teamsapp.local.yml` file.
+
+ ```javascript
+ - uses: script
+ with:
+ run:
+ echo "::set-teamsfx-env TAB_DOMAIN=localhost:53000";
+ echo "::set-teamsfx-env TAB_ENDPOINT=https://localhost:53000";
+ ```
+
+1. If you're using React, add the configuration `WDS_SOCKET_PORT=0` in `teamsapp.local.yml` file to activate hot reloading while debugging in React after utilizing the tunnel service.
+
+ ```javascript
+ - uses: file/createOrUpdateEnvironmentFile
+ with:
+ target: ./.localConfigs
+ envs:
+ BROWSER: none
+ HTTPS: true
+ PORT: 53000
+ SSL_CRT_FILE: ${{SSL_CRT_FILE}}
+ SSL_KEY_FILE: ${{SSL_KEY_FILE}}
+ REACT_APP_CLIENT_ID: ${{AAD_APP_CLIENT_ID}}
+ ΓÇ» ΓÇ» ΓÇ» REACT_APP_START_LOGIN_PAGE_URL: ${{TAB_ENDPOINT}}/auth-start.html
+ ΓÇ» ΓÇ» ΓÇ» WDS_SOCKET_PORT: 0
+ ```
+
+## Run the deployed app
+
+1. Open the debug panel (**Ctrl+Shift+D** / **⌘⇧-D** or **View > Run**) from Visual Studio Code.
+1. Select **Launch Remote (Edge)** from the launch configuration dropdown.
+1. Select the Start debugging (F5) button.
+
+ :::image type="content" source="~/assets/images/teams-toolkit-v2/deploy-azure/launch-remote.png" alt-text="The screenshot showing how to launch the app remotely.":::
+
+# [Command Line](#tab/cline)
+
+1. Go to [ngrok](https://ngrok.com) and sign up for a free account or log into your existing account.
+1. After you've signed in, from the left pane select [**Your Authtoken**](https://dashboard.ngrok.com).
+1. Copy the value of your Authtoken.
+1. Run the ngrok.exe file.
+1. Run the command `ngrok http https://localhost:53000 --authtoken=<your-personal-ngrok-authtoken>` to start the local tunnel service.
+1. In the `env/.env.local` file, update the values for `TAB_DOMAIN` and `TAB_ENDPOINT`.
+
+ ```json
+ TAB_DOMAIN=sample-ngrok-id.ngrok.io
+ TAB_ENDPOINT=https://sample-ngrok-id.ngrok.io
+ ```
+
+1. Execute the command `teamsfx provision --env local` in your project directory.
+1. Execute the command `teamsfx deploy --env local` in your project directory.
+1. Execute the command `teamsfx preview --env local` in your project directory.
+++
+You'll be prompted to sideload the app into Teams. Select **Add**.
++
+## Test your tab app on mobile client
+
+1. To find the previewing app, open Teams on your mobile device and select **More**.
+
+ :::image type="content" source="../assets/images/debug-mobile/mobile-more-option.PNG" alt-text="Screenshot shows more option in Teams mobile client." lightbox="../assets/images/debug-mobile/debug-mobile.PNG":::
+
+ > [!NOTE]
+ > If a you have debugged the app previously, it's recommended to clear the cache on the mobile device to ensure immediate app synchronization. After clearing the cache, the app takes some time to sync.
+
+ # [iOS](#tab/ios1)
+
+ To clear the Teams app data, go to **Settings** > **Teams** > **Clear App Data**.
+
+ :::image type="content" source="../assets/images/debug-mobile/clear-app-data-ios-option.PNG" alt-text="The screenshot showing to clean the app data in iOS mobile client for tab." lightbox="../assets/images/debug-mobile/clear-app-data-ios.PNG":::
+
+
+ # [Android](#tab/android1)
+
+ To clear the Teams app data, go to **Teams** > **Settings** > **Data and storage** > **Clear app data** > **Clear data**.
+
+ :::image type="content" source="../assets/images/debug-mobile/clear-app-data-android-option.PNG" alt-text="The screenshot showing to clean the app data in android mobile client for tab." lightbox="../assets/images/debug-mobile/clear-app-data-android.PNG":::
+
+
+1. If you're accessing the dev tunnel for the first time, sign in to Microsoft 365 account and select **continue**.
+
+ :::image type="content" source="../assets/images/debug-mobile/m365-sign-in.PNG" alt-text="The screenshot showing the Microsoft 365 sign in page.":::
+
+ > [!NOTE]
+ > You need to login only once per device, and every time you install the app you need to confirm the anti-phishing page.
+
+1. Your first mobile tab app is created.
+
+ :::image type="content" source="../assets/images/debug-mobile/mobile-tab-app.PNG" alt-text="The screenshot shows the mobile tab app.":::
+
+1. For Android devices, use [DevTools](../tabs/how-to/developer-tools.md#access-devtools-from-an-android-device) to debug your tab while it's running.
+
+## Test your bot app on mobile client
+
+1. To test your bot in mobile client, follow the steps listed in [Test your tab app on mobile client](#test-your-tab-app-on-mobile-client) for your bot.
+
+ > [!NOTE]
+ > If a you have debugged the bot app previously and the Teams app manifest file is changed, it's recommended to clear the cache on the mobile device to ensure immediate app synchronization. After clearing the cache, the app takes some time to sync.
+
+ # [iOS](#tab/ios2)
+
+ To clear the Teams app data, go to **Settings** > **Teams** > **Clear App Data**.
+
+ :::image type="content" source="../assets/images/debug-mobile/clear-app-data-ios-option.PNG" alt-text="The screenshot showing to clean the app data in iOS mobile client for bot." lightbox="../assets/images/debug-mobile/clear-app-data-ios.PNG":::
+
+
+ # [Android](#tab/android2)
+
+ To clear the Teams app data, go to **Teams** > **Settings** > **Data and storage** > **Clear app data** > **Clear data**.
+
+ :::image type="content" source="../assets/images/debug-mobile/clear-app-data-android-option.PNG" alt-text="The screenshot showing to clean the app data in android mobile client for bot." lightbox="../assets/images/debug-mobile/clear-app-data-android.PNG":::
+
+
+
+1. Your first mobile bot app is created.
+
+ :::image type="content" source="../assets/images/debug-mobile/debug-bot-mobile.PNG" alt-text="The screenshot showing to debug the bot app in mobile client.":::
platform Publish https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/toolkit/publish.md
You can build an app for internal use and share it with your team without submit
You need to run **Provision in the cloud** before you build the app package. The following step helps you to build the app package:
-* Select **Zip Teams App Package** > **UTILITY**.<br>
+Select **Zip Teams App Package** > **UTILITY**.<br>
The generated app package is located in `{your project folder}\appPackage\build\appPackage.{env}.zip`. ### Upload app package
Perform the following steps to upload app package:
When the app is ready for use in production, you can submit the app using the Teams app submission API, called from Microsoft Graph API. Teams app submission API is an integrated development environment (IDE) such as Microsoft Visual Studio Code installed with Teams toolkit. The following steps help you to publish the app to your organization: * [Publish from Teams Toolkit](#publish-from-teams-toolkit)
-* [Approve on Admin Center](#approve-on-admin-center)
+* [Approve on admin center](#approve-on-admin-center)
### Publish from Teams Toolkit
+> [!NOTE]
+> You can use CICD pipelines to publish your Teams app. For more information, see [set up CI/CD pipelines](use-CICD-template.md).
+ The following steps help you to publish the app from Teams Toolkit: 1. You can publish your Teams app in one of the following ways: * Select **Publish** under **LIFECYCLE**. * Select **View** > **Command Palette...** > **Teams: Publish**.
- :::image type="content" source="../assets/images/teams-toolkit-v2/teams toolkit fundamentals/select-publish_1.png" alt-text="Screenshot shows the Publish option highlighted.":::
+ :::image type="content" source="../assets/images/teams-toolkit-v2/teams toolkit fundamentals/select-publish_1.png" alt-text="Screenshot shows the Publish option highlighted.":::
1. Select your environment, Teams Toolkit runs the `publish` lifecycle defined in `teamsapp.yml`.
Now the app is available on the Manage apps of Microsoft Teams admin center, whe
> [!NOTE] > The app doesn't publish to your organization's app store yet. The step submits the app to the Teams admin center where you can approve it for publishing to your organization's app store.
-### Approve on Admin Center
+### Approve on admin center
Teams toolkit for Visual Studio Code built on top of the Teams App Submission API and it allows you to automate the submission-to-approval process for custom apps on Teams.
Teams toolkit for Visual Studio Code built on top of the Teams App Submission AP
> * View permissions requested by apps. > * Grant admin consent to apps in [manage org wide app settings.](https://admin.teams.microsoft.com/policies/manage-apps).
-The following steps help you to approve from Admin Center:
+The following steps help you to approve from admin center:
1. Select **Go to admin portal**.
platform Connectors Using https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/webhooks-and-connectors/how-to/connectors-using.md
To post a message to the webhook with PowerShell, follow these steps:
> [!NOTE] > If the POST succeeds, you must see a simple **1** output by `Invoke-RestMethod`.
-1. Check the Teams channels associated with the webhook URL. You can see the new card posted to the channel. Before you use the connector to test or publish your app, you must do the following:
-
- * [Include two icons](../../concepts/build-and-test/apps-package.md#app-icons).
- * Modify the `icons` portion of the manifest to the file names of the icons instead of URLs.
+1. Check the Teams channels associated with the webhook URL. You can see the new card posted to the channel.
platform Whats New https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/whats-new.md
Discover Microsoft Teams platform features that are generally available (GA). Yo
| **Date** | **Update** | **Find here** | | -- | | -|
-| 25/05/2023 | Deep link to meeting side panel in Teams moble client. | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Build tabs for meeting](apps-in-teams-meetings/build-tabs-for-meeting.md#deep-link-to-meeting-side-panel) |
-|23/05/2023 | Live Share SDK is now generally available. | Build apps for Teams meetings and calls > Enhanced collaboration with Live Share > [Live Share SDK](apps-in-teams-meetings/teams-live-share-overview.md)|
-|23/05/2023 | Design your app for new Teams. | Design your app > [Overview](concepts/design/design-teams-app-overview.md)|
-|17/05/2023 | Distribute your app to specific countries. | Distribute your app > Publish to the Teams store > Prepare your Teams store submission > [Distribute your app to specific countries](concepts/deploy-and-publish/appsource/prepare/submission-checklist.md#distribute-your-app-to-specific-countries)|
-| 17/05/2023 | Introduced the Teams Toolkit v5 extension within Visual Studio Code. | Tools and SDKs > Teams Toolkit > [Teams Toolkit Overview](toolkit/teams-toolkit-fundamentals.md)|
+| 25/05/2023 | Use a deep link to open a tab app in meeting side panel in Teams mobile client. | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Build tabs for meeting](apps-in-teams-meetings/build-tabs-for-meeting.md#deep-link-to-meeting-side-panel) |
+|23/05/2023 | Live Share SDK is now generally available. Use Live Share to transform Teams apps into collaborative multi-user experiences without writing any dedicated back-end code. | Build apps for Teams meetings and calls > Enhanced collaboration with Live Share > [Live Share SDK](apps-in-teams-meetings/teams-live-share-overview.md)|
+|23/05/2023 | Use Teams app design guidelines to help you make quick and right decisions to design your app. | Design your app > [Overview](concepts/design/design-teams-app-overview.md)|
+|17/05/2023 | Cater your app to a specific audience from the available list of countries. | Distribute your app > Publish to the Teams store > Prepare your Teams store submission > [Distribute your app to specific countries](concepts/deploy-and-publish/appsource/prepare/submission-checklist.md#distribute-your-app-to-specific-countries)|
+| 17/05/2023 | Use the Teams Toolkit v5 extension with many new app development features to get started with app development for Teams using Visual Studio Code. | Tools and SDKs > Teams Toolkit > [Teams Toolkit Overview](toolkit/teams-toolkit-fundamentals.md)|
| 17/05/2023 | Updated Get started module with GitHub Codespaces and step-by-step guides aligned with Teams Toolkit v5. It also includes details for extending Teams app over Microsoft 365 and Outlook. | [Get started](get-started/get-started-overview.md)| ## Generally available
Teams platform features that are available to all app developers.
**2023 June**
-* ***June 14, 2023***: [Collaborative Stage View](tabs/tabs-link-unfurling.md#collaborative-stage-view).
+* ***June 14, 2023***: [Added validation guidelines for Teams app powered by Artificial Intelligence (AI)](concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md#apps-powered-by-artificial-intelligence).
-* ***June 14, 2023***: [Added validation guidelines for Teams app powered by Artificial Intelligence (AI)](concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md#apps-powered-by-ai).
-
-* ***June 02, 2023***: [Real-time meeting events are supported in channel meetings](apps-in-teams-meetings/meeting-apps-apis.md#get-real-time-teams-meeting-events-api).
+* ***June 02, 2023***: [Get real-time meeting events for channel meetings](apps-in-teams-meetings/meeting-apps-apis.md#get-real-time-teams-meeting-events-api).
:::column-end::: :::row-end:::
Teams platform features that are available to all app developers.
| **Date** | **Update** | **Find here** | | -- | | -|
-| 24/04/2023 | Develop your apps with Teams Toolkit | Tools and SDKs > Developer Portal for Teams > [Develop your apps with Teams Toolkit](concepts/build-and-test/develop-your-apps-with-teams-toolkit.md) |
-| 14/04/2023 | Contextless app update | Distribute your app > [Upload your app in Teams](concepts/deploy-and-publish/apps-upload.md#update-your-app) |
-| 06/04/2023 | Set up Microsoft license management | Monetize your app > [Set up Microsoft license management](~/concepts/deploy-and-publish/appsource/prepare/manage-third-party-apps-license.md) |
-| 04/04/2023 | Tab apps in shared channels are available in DOD | Build tabs > [Build apps for shared channels](~/concepts/build-and-test/shared-channels.md) |
-| 23/03/2023 | Apps are available for scheduled public channel meetings | Build apps for Teams meetings and calls > [Overview](apps-in-teams-meetings/teams-apps-in-meetings.md) |
-| 20/03/2023 | Bots are available in DOD | Build bots > [Overview](bots/what-are-bots.md)|
-| 20/03/2023 | Message extensions are available in DOD | Build message extensions > [Overview](messaging-extensions/what-are-messaging-extensions.md)|
-| 28/02/2023 | Facilitate adoption of your app and create awareness | Distribute your app > adoption > [Drive customer adoption of your app](promote-app-adoption.md) |
-| 27/02/2023 | Changelog for Developer Portal | Tools and SDKs > Developer Portal for Teams > [Overview](concepts/build-and-test/teams-developer-portal.md#changelog-for-developer-portal) |
-| 23/02/2023 | SSO authentication for your Adaptive Cards Universal Actions | Add authentication > Enable SSO for your Teams app > Enable SSO for Adaptive Cards Universal Actions in your bot > [Overview](task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/enable-sso-for-your-adaptive-cards-universal-action.md) |
-|23/02/2023| Third party authentication for Adaptive Cards Universal Actions | Add authentication > Use third party IdP authentication > [Third party authentication for Adaptive Cards Universal Actions](task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/authentication-flow-in-universal-action-for-adaptive-cards.md) |
-|21/02/2023| Targeted in-meeting notification for apps in Teams | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Targeted in-meeting notification for apps in Teams](apps-in-teams-meetings/in-meeting-notification-for-meeting.md#targeted-in-meeting-notification) |
-|20/02/2023| Plan your app growth in Teams | Grow your app > [Strategize and execute growth for your app](concepts/deploy-and-publish/appsource/post-publish/app-growth/overview-app-growth.md)|
-|17/02/2023| Build a dashboard tab app | Build Tabs > [Build a dashboard tab app](tabs/how-to/build-a-dashboard-tab-app.md#build-a-dashboard-tab-app)|
-|09/02/2023| Apps for Teams meetings support anonymous users | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Build apps for anonymous users](apps-in-teams-meetings/build-apps-for-anonymous-user.md) |
-|31/01/2023| Introducing update and soft delete event notifications in bot | Build bots > Bot conversations > [Messages in bot conversations](bots/how-to/conversations/conversation-messages.md#get-edit-message-event)|
+| 24/04/2023 | Develop your apps with a seamless transition between Teams Developer Portal and Teams Toolkit. | Tools and SDKs > Developer Portal for Teams > [Develop your apps with Teams Toolkit](concepts/build-and-test/develop-your-apps-with-teams-toolkit.md) |
+| 14/04/2023 | App update in any one context where the app is installed automatically updates the app in all the related contexts (chats, channels, and meetings). | Distribute your app > [Upload your app in Teams](concepts/deploy-and-publish/apps-upload.md#update-your-app) |
+| 06/04/2023 | Set up Microsoft license management for third-party SaaS apps in Partner Centre as part of the offer publishing that allows easy management and tracking of licenses for third-party app subscriptions within Teams. | Monetize your app > [Set up Microsoft license management](~/concepts/deploy-and-publish/appsource/prepare/manage-third-party-apps-license.md) |
+| 04/04/2023 | Tab apps in shared channels are available in Department of Defense (DOD) environment. | Build tabs > [Build apps for shared channels](~/concepts/build-and-test/shared-channels.md) |
+| 23/03/2023 | Use apps in Teams meetings scheduled through public channels. | Build apps for Teams meetings and calls > [Overview](apps-in-teams-meetings/teams-apps-in-meetings.md) |
+| 20/03/2023 | Bots are available in Department of Defense (DOD) environment. | Build bots > [Overview](bots/what-are-bots.md)|
+| 20/03/2023 | Message extensions are available in Department of Defense (DOD) environment. | Build message extensions > [Overview](messaging-extensions/what-are-messaging-extensions.md)|
+| 28/02/2023 | Use the resources and best practices to support the rollout of your Teams app in your customersΓÇÖ organizations and facilitate adoption of your app. | Distribute your app > adoption > [Drive customer adoption of your app](promote-app-adoption.md) |
+| 27/02/2023 | Use Changelog to view the latest updates on Developer Portal about features, recent changes in APIs, and important bug fixes. | Tools and SDKs > Developer Portal for Teams > [Overview](concepts/build-and-test/teams-developer-portal.md#changelog-for-developer-portal) |
+| 23/02/2023 | Enable single sign-on (SSO) authentication to access Adaptive Cards Universal Actions in a bot. | Add authentication > Enable SSO for your Teams app > Enable SSO for Adaptive Cards Universal Actions in your bot > [Overview](task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/enable-sso-for-your-adaptive-cards-universal-action.md) |
+|23/02/2023| Enable third party authentication to add user-specific views in instances where an Adaptive Card with Universal Action is shared. | Add authentication > Use third party IdP authentication > [Third party authentication for Adaptive Cards Universal Actions](task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/authentication-flow-in-universal-action-for-adaptive-cards.md) |
+|21/02/2023| Send notifications to specific participants on a meeting stage with targeted in-meeting notification. | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Targeted in-meeting notification for apps in Teams](apps-in-teams-meetings/in-meeting-notification-for-meeting.md#targeted-in-meeting-notification) |
+|20/02/2023| Plan, strategize, and execute your app growth in Teams to make it a successful app on the marketplace. | Grow your app > [Strategize and execute growth for your app](concepts/deploy-and-publish/appsource/post-publish/app-growth/overview-app-growth.md)|
+|17/02/2023| Build a dashboard tab app that acts as a tool to track, analyze, monitor, display, and extract data. | Build Tabs > [Build a dashboard tab app](tabs/how-to/build-a-dashboard-tab-app.md#build-a-dashboard-tab-app)|
+|09/02/2023| Build apps for anonymous users that support anonymous users to attend Teams meetings with an alternative authentication experience. | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Build apps for anonymous users](apps-in-teams-meetings/build-apps-for-anonymous-user.md) |
+|31/01/2023| Get update and soft delete event notification in a bot when you edit, undelete or soft delete a message in a chat. | Build bots > Bot conversations > [Messages in bot conversations](bots/how-to/conversations/conversation-messages.md#get-edit-message-event)
</details> </br>
Discover Microsoft Teams platform features that are in developer preview. You ca
| **Date** | **Update** | **Find here** | | -- | | -|
-| 25/05/2023 | Deep link to meeting side panel in Teams desktop client. | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Build tabs for meeting](apps-in-teams-meetings/build-tabs-for-meeting.md#deep-link-to-meeting-side-panel) |
-|23/05/2023 | Introduced Teams AI library to help build AI-powered Teams apps. | Build Bots > [Teams AI library](bots/how-to/Teams%20conversational%20AI/teams-conversation-ai-overview.md)|
-|23/05/2023| Extend Microsoft 365 Copilot| [Extend Microsoft 365 Copilot](copilot/how-to-extend-copilot.md)|
+| 25/05/2023 | Use a deep link to open a tab app in meeting side panel in Teams mobile client. | Build apps for Teams meetings and calls > Enable and configure apps for Teams meeting > [Build tabs for meeting](apps-in-teams-meetings/build-tabs-for-meeting.md#deep-link-to-meeting-side-panel) |
+|23/05/2023 | Teams AI library helps you build AI-powered Teams apps. | Build Bots > [Teams AI library](bots/how-to/Teams%20conversational%20AI/teams-conversation-ai-overview.md)|
+|23/05/2023| Extend Microsoft 365 Copilot to integrate with Microsoft Teams apps to turn your app into most powerful productivity tool. | [Extend Microsoft 365 Copilot](copilot/how-to-extend-copilot.md)|
## Developer preview
Developer preview is a public program that provides early access to unreleased T
**2023 June**
-***June 19, 2023***: [Introduced Collaborative Stage View](tabs/tabs-link-unfurling.md#collaborative-stage-view).
+* ***June 29, 2023***: [Use app icon badging to identify any app activity during a meeting.](apps-in-teams-meetings/app-icon-badging-for-your-app.md)
+* ***June 19, 2023***: [Use Collaborative Stage View to engage with your app content in a new Teams window](tabs/tabs-link-unfurling.md#collaborative-stage-view).
:::column-end::: :::row-end:::
+<br>
+<details>
+<summary><b>2023</b></summary>
+
+| **Date** | **Update** | **Find here** |
+| -- | | -|
+|31/01/2023| Send notifications to specific participants on a meeting stage with targeted in-meeting notification. |Build apps for Teams meetings and calls > Enable and configure apps for meetings > Build in-meeting notification for Teams meeting > Build tabs for meeting > [Targeted in-meeting notification](apps-in-teams-meetings/in-meeting-notification-for-meeting.md#targeted-in-meeting-notification)|
+|30/01/2023| Enable app caching to improve subsequent launch time of the apps to the meeting side panel.|Build apps for Teams meetings and calls > Enable and configure apps for meetings > [App caching](apps-in-teams-meetings/build-tabs-for-meeting.md#app-caching) |
+
+</details>
+</br>
+
+<details>
+<summary><b>2022</b></summary>
+ | **Date** | **Update** | **Find here** | | -- | | |
-|01/31/2023| Introduced Targeted in-meeting notification for apps in Teams.|Build apps for Teams meetings and calls > Enable and configure apps for meetings > Build in-meeting notification for Teams meeting > Build tabs for meeting > [Targeted in-meeting notification](apps-in-teams-meetings/in-meeting-notification-for-meeting.md#targeted-in-meeting-notification)|
-|01/30/2023| Enable app caching to improve subsequent launch time of the apps to the meeting side panel.|Build apps for Teams meetings and calls > Enable and configure apps for meetings > [App caching](apps-in-teams-meetings/build-tabs-for-meeting.md#app-caching) |
-|05/12/2022| Introduced share in meeting to share any document or third-party app to the meeting stage.|Build apps for Teams meetings and calls > Enable and configure apps for meetings > [Share in meeting](concepts/build-and-test/share-in-meeting.md) |
-|10/11/2022| Enable bots to receive all chat messages without being @mentioned.|Build bots > Bot conversations > Message in bot conversations > [Receive all conversation messages with RSC](bots/how-to/conversations/channel-messages-with-rsc.md) |
+|05/12/2022| Use share in meeting to share any document or third-party app to the meeting stage.|Build apps for Teams meetings and calls > Enable and configure apps for meetings > [Share in meeting](concepts/build-and-test/share-in-meeting.md) |
+|10/11/2022| Enable bots to receive all conversation messages without being @mentioned in relevant contexts.|Build bots > Bot conversations > Message in bot conversations > [Receive all conversation messages with RSC](bots/how-to/conversations/channel-messages-with-rsc.md) |
|10/11/2022|Generate a deep link to share content to stage in meetings.|Build apps for Teams meetings and calls > Enable and configure apps for meetings > Share in meeting > [Generate a deep link to share content to stage in meetings.](concepts/build-and-test/share-in-meeting.md) |
-| 09/23/2022 | Introduced meeting app support for Scheduled Channel Meetings. | Build apps for Teams meetings and calls > [Apps for Teams meetings and calls](apps-in-teams-meetings/teams-apps-in-meetings.md) |
-| 08/23/2022 | Share apps to the Teams meeting stage in mobile | Build apps for Teams meetings and calls > [Enable and configure apps for meetings](/microsoftteams/platform/apps-in-teams-meetings/enable-and-configure-your-app-for-teams-meetings) |
-| 08/03/2022 | Mute and unmute APIs for apps in Teams meeting stage | Build apps for Teams meetings and calls > [Meeting apps API references](/microsoftteams/platform/apps-in-teams-meetings/api-references?tabs=dotnet) |
-| 08/02/2022| Collaboration controls for Teams| Integrate with Teams > [Collaboration controls](samples/collaboration-control.md) |
-|05/24/2022| Enhanced collaboration with Live Share SDK | Build apps for Teams meetings > Enhanced collaboration with Live Share > [Overview](apps-in-teams-meetings/teams-live-share-overview.md) |
-| 10/28/2021 |Bots can be enabled to receive all channel messages using resource-specific consent (RSC) | ΓÇó Build bots > Bot conversations > [bot conversation overview](~/bots/how-to/conversations/conversation-basics.md) </br> ΓÇó Build bots > Bot conversations > [channel and group conversations](~/bots/how-to/conversations/channel-and-group-conversations.md) |
-| 06/16/2021 | Resource-specific consent for chats | ΓÇó Utilize Teams data with Microsoft Graph > [Resource-specific consent](graph-api/rsc/resource-specific-consent.md) </br> ΓÇó Test your app > Microsoft Graph > [Test resource-specific consent permissions in Teams](graph-api/rsc/test-resource-specific-consent.md)|
+| 09/23/2022 | Use apps in Teams meetings scheduled through public channels. | Build apps for Teams meetings and calls > [Apps for Teams meetings and calls](apps-in-teams-meetings/teams-apps-in-meetings.md) |
+| 08/23/2022 | Share apps to the Teams meeting stage in mobile. | Build apps for Teams meetings and calls > [Enable and configure apps for meetings](/microsoftteams/platform/apps-in-teams-meetings/enable-and-configure-your-app-for-teams-meetings) |
+| 08/03/2022 | Use toggle incoming audio API to toggle the incoming audio state setting for the user in Teams meeting stage from mute to unmute or vice-versa. | Build apps for Teams meetings and calls > [Meeting apps API references](/microsoftteams/platform/apps-in-teams-meetings/api-references?tabs=dotnet) |
+| 08/02/2022| Use Collaboration controls to build custom collaborative experiences and integrate with Microsoft 365 services. | Integrate with Teams > [Collaboration controls](samples/collaboration-control.md) |
+|05/24/2022| Use Live Share to transform Teams apps into collaborative multi-user experiences without writing any dedicated back-end code. | Build apps for Teams meetings > Enhanced collaboration with Live Share > [Overview](apps-in-teams-meetings/teams-live-share-overview.md) |
+| 10/28/2021 |Enable bots to receive all channel messages using resource-specific consent (RSC). | ΓÇó Build bots > Bot conversations > [bot conversation overview](~/bots/how-to/conversations/conversation-basics.md) </br> ΓÇó Build bots > Bot conversations > [channel and group conversations](~/bots/how-to/conversations/channel-and-group-conversations.md) |
+| 06/16/2021 | Use resource-specific consent permissions to allow the app to access the data of a specific instance of a resource type. | ΓÇó Utilize Teams data with Microsoft Graph > [Resource-specific consent](graph-api/rsc/resource-specific-consent.md) </br> ΓÇó Test your app > Microsoft Graph > [Test resource-specific consent permissions in Teams](graph-api/rsc/test-resource-specific-consent.md)|
For more information, see [public developer preview for Teams](~/resources/dev-preview/developer-preview-intro.md).
+</details>
+</br>
+ ::: zone-end ::: zone pivot="dep-feature"