Showing posts with label MSTeams. Show all posts
Showing posts with label MSTeams. Show all posts

Microsoft Teams | Generate Deep Link To Custom MSTeams Tab

 

Introduction

 
Deep Linking allows uses tor navigate within your apps. Your app can have MS Teams development instance like Bot, Messaging Extension, or Flow Bot send the message notification to user for an important activity. Deep Link navigates the user to the tab so that the user can view more details about activity.
 

Deep Linking with Tab 

 
Deep Links can be created for Teams entities. In a typical scenario, it is used to create a link that navigates to content and information within your tab. It reduces the context switch. It keeps the user within Teams context without refreshing.
 
Note
The tab can be defined at Personal Tab with personal scope, Channel or Group Tab with teams or group scope. 
 
The following format can be used for deep links in Bot, Connector, Messaging Extension Cards.
 
https://teams.microsoft.com/l/entity/<appId>/<entityId>?webUrl=<entityWebUrl>&label=<entityLabel>&context=<context>
 
The query parameters are, 
  • appId 
    The ID from your manifest; for example, "fe4a8eba-2a31-4737-8e33-e5fae6fee194"

  • entityId
    The ID for the item in the tab, which you provided when configuring the tab; for example, "id123"

  • entityWebUrl or subEntityWebUrl
    An optional field with a fallback URL to use if the client does not support rendering the tab; for example, "https://tasklist.example.com/123" or "https://tasklist.example.com/list123/task456"

  • entityLabel or subEntityLabel
    A label for the item in your tab, to use when displaying the deep link; for example, "Task List 123" or "Task 456"

  • context
    A JSON object containing the following fields:

  • subEntityId
    An ID for the item within the tab; for example, "task456"

  • channelId
    The Microsoft Teams channel ID that is available from the tab context; for example, "19:cbe3683f25094106b826c9cada3afbe0@thread.skype". This property is only available in configurable tabs with a scope of "team". It is not available in static tabs, which have a scope of "personal".




To implement this, you can "copy link" action from Tab or action item. You can call this url on button click, which designed via adaptive cards. when you call or click the button which is configured with copy link based url. It will gte back into same context and your tab will be reloaded. 
 
Note
This deep link is different from the link provided by the copy link tab menu, its just generate deep link the points to tab.



  • Navigate to Channel Tab, which you want to connect as deep link.
  • Click on the "..." top right parllel to tab name.
  • Click to "Copy link to tab"
Sample Url will be generate,
 
https://teams.microsoft.com/l/entity/b702977d-06e1-42cc-9166-25ad4d39a9f9/_djb2_msteams_prefix_1145688105?context=%7B%22subEntityId%22%3Anull%2C%22channelId%22%3A%22<<channel id>>%40thread.tacv2%22%7D&groupId=<<group id>>&tenantId=<<tenant id>>
 
Note
Sub Entitiy Id can used to pass as parameterize value, if we need to simply navigate to tab, In that scenario it can be used as null. 
 
Deep Link to tab embed into below adaptive Card, which used into power automate to send notification, On click on button, it will navigate to Tab as well as pass parameterize url.
  1. {  
  2.     "type""AdaptiveCard",  
  3.     "version""2.0",  
  4.     "body": [  
  5.         {  
  6.             "type""TextBlock",  
  7.             "text""New Ticket Created",  
  8.             "weight""Bolder"  
  9.         },  
  10.         {  
  11.             "type""FactSet",  
  12.             "facts": [  
  13.                 {  
  14.                     "title""Ticket ID",  
  15.                     "value""@{triggerOutputs()?['body/ID']}"  
  16.                 },  
  17.                 {  
  18.                     "title""Ticket Detail",  
  19.                     "value""@{triggerOutputs()?['body/Title']}"  
  20.                 },  
  21.                {  
  22.                     "title""RequestedBy",  
  23.                     "value""@{triggerOutputs()?['body/RequestorName/DisplayName']}"  
  24.                 },  
  25.                {  
  26.                     "title""Severity",  
  27.                     "value""@{triggerOutputs()?['body/Severity/Value']}"  
  28.                 },  
  29.                {  
  30.                     "title""Category",  
  31.                     "value""@{triggerOutputs()?['body/Category/Value']}"  
  32.                 }             
  33.             ],  
  34.             "spacing""Medium"  
  35.         },  
  36.         {  
  37.             "type""ActionSet",  
  38.             "actions": [  
  39.                 {  
  40.                     "type""Action.OpenUrl",  
  41.                     "title""View Ticket",  
  42.                     "url""https://teams.microsoft.com/l/entity/b702977d-06e1-42cc-9166-25ad4d39a9f9/_djb2_msteams_prefix_1145688105?context=%7B%22subEntityId%22%3A@{triggerOutputs()?['body/ID']}%2C%22channelId%22%3A%2219%3A123c0abe7f0041c68066801eb8a0f8d2%40thread.tacv2%22%7D&groupId=e8312347-f8cd-4177-8661-88b335dab65b&tenantId=4cd94c60-104d-4a43-b441-e735fc34830b",  
  43.                     "style""positive"  
  44.                 }  
  45.             ]  
  46.         }  
  47.     ],  
  48.     "$schema""http://adaptivecards.io/schemas/adaptive-card.json"  
  49. }  
Finally, we need to find out, how to consume item id into SPFx webpart. It can be achived easily with the below steps.
 
Package needed to import,
  1. import * as microsoftTeams from "@microsoft/teams-js";  
Initialize into constructor,
  1. microsoftTeams.initialize();  
SubEntityId used to get the parameterized value, assigned to provided variable and same can be used further. 
  1. public componentWillMount() {  
  2.      
  3.     microsoftTeams.getContext(teamsContext => {  
  4.     this.itemId = teamsContext.subEntityId;  
  5.     });  
  6.   }  
How easy and quick it was to build a custom Custom Deep Link to Tab. 
 
I hope you have enjoyed and learned something new in this article and Happy Learning !!

Create Search-based Messaging Extension for Microsoft Teams

Introduction

 
Messaging extensions enable users to execute search queries or trigger actions within a designed external system. As a result, messages are received from custom web services or API to the Microsoft Teams Client.
 

Messaging Extension 

 
Messaging extensions take advantage of the Bot Framework's messaging schema and secure communication protocol to connect with Microsoft Teams Client App.


 
There are three type of messaging extenions that can be build for Microsoft Teams:
  1. Search based messaging extenion for Microsoft Teams
  2. Action based messaging extenion for Microsoft Teams
  3. Unfurl Url with messaging extension for Microsoft Teams 
How Messaging Extension works
  1. Command box: This is the area at the top of the Microsoft Teams client
  2. Compose message box: This is the area at the bottom of a 1:1 or group chat and at the bottom of the Conversations tab in a channel
  3. More Actions menu: It is accessible, when users hover over a message in a conversation chat
When the messaging extension is invoked, Microsoft Teams will send, via the Bot Framework, an HTTPS message with a JSON payload that includes all relevant information.
 
Your web service will respond with a JSON payload, via the Bot Framework, that informs the Microsoft Teams client what interaction to enable next.
 
Prerequisites
  • Microsoft Teams
  • Azure Bot Framework, .NetCore
  • Azure Web API .Net Standard
  • Microsoft 365 tenant
  • Microsoft Azure subscription
Let's get started,
 
To create Microsoft Team Messaging Extension requires two activities:
  1. Create Microsoft Azure Bot.
  2. Create manifest file with bot reference 
  3. Upload manifest file to MS Team Client App.
Step 1 - Create Microsoft Azure Bot
  1. Browse the https://portal.azure.com with your work or school account.
  2. Click "+Create Resource"
  3. Select "AI + Machine Learning"
  4. Select "Web App Bot"


Step 2 - Complete all required information and click create to provision the bot
  1. Bot handle:- The unique name of your bot.
  2. Subscription:- Select a valid available subscription.
  3. Resource Group:-Select an appropriate resource group or create a new one as per requirement.
  4. Location:- Select your closed azure location or the preferred location.
  5. Pricing:- Select the required pricing tier or F0 as free for POC activity.
  6. App Name:- Leave it as-is for this demo purpose.
  7. Service Plan:- Leave it as-is for this demo purpose.
  8. Bot Template:- Leave it as-is for this demo purpose.
  9. Application insight: Select off for this demo purpose
  10. Microsoft App Id and Password:- Leave it as-is for this demo purpose.
  11. Click create to provision.

Step 3 - Enable Microsoft Teams Channel for your Bot
 
In order for the bot to interact with MS Teams, you must enable the Teams Channel.



To complete the process, MS Teams and Webchat should be available and should be listed in your channel lists.


Step 4 - Create a Bot Framework
 
In this section, we are going to create a echo bot using Visual Studio 2019
  • Open the Visual Studio, Select create project and navigate to the desired directory to create a project.
  • Select Echo Bot (Bot Framework v4) .Net Core

Step 5 - Update Default Bot Code
  1. Select EchoBot.cs 
  2. Remove all default methods defined into EchoBot Class
  3. Inherit Team Activity Handler to EchoBot Class to implement messaging extension related method.
  4. Add Query Async method to pass query parameter to external api.
  5. Select Item Async method used to post the selected message into team channel conversation area via adaptive card.

Query Async Method - Take typed query as parameter and pass it to api to get JSON Payload, render the JSON Payload into hero card with list; i.e., attachment layout.

  1. protected override async Task<MessagingExtensionResponse> OnTeamsMessagingExtensionQueryAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken)  
  2.         {  
  3.             var text = query?.Parameters?[0]?.Value as string ?? string.Empty;  
  4.   
  5.             var packages = await FindPackages(text);  
  6.   
  7.             var attachments = packages.Select(package => {  
  8.                 var previewCard = new ThumbnailCard { Title = package.Item1, Tap = new CardAction { Type = "invoke", Value = package } };  
  9.                 if (!string.IsNullOrEmpty(package.Item5))  
  10.                 {  
  11.                     previewCard.Images = new List<CardImage>() { new CardImage(package.Item5, "Icon") };  
  12.                 }  
  13.   
  14.                 var attachment = new MessagingExtensionAttachment  
  15.                 {  
  16.                     ContentType = HeroCard.ContentType,  
  17.                     Content = new HeroCard { Title = package.Item1 },  
  18.                     Preview = previewCard.ToAttachment()  
  19.                 };  
  20.   
  21.                 return attachment;  
  22.             }).ToList();  
  23.   
  24.             return new MessagingExtensionResponse  
  25.             {  
  26.                 ComposeExtension = new MessagingExtensionResult  
  27.                 {  
  28.                     Type = "result",  
  29.                     AttachmentLayout = "list",  
  30.                     Attachments = attachments  
  31.                 }  
  32.             };  
  33.         }  

Call External API based on provided query parameter.
  1. private async Task<IEnumerable<(string, string, string, string, string)>> FindPackages(string text)  
  2.         {  
  3.             var obj = JObject.Parse(await (new HttpClient()).GetStringAsync($"https://azuresearch-usnc.nuget.org/query?q=id:{text}"));  
  4.             return obj["data"].Select(item => (item["id"].ToString(), item["version"].ToString(), item["description"].ToString(), item["projectUrl"]?.ToString(), item["iconUrl"]?.ToString()));  
  5.         }  
 Select Item Async used to post bot framework thumbnail card based on selected item information into teams channel conversation.
  1. protected override Task<MessagingExtensionResponse> OnTeamsMessagingExtensionSelectItemAsync(ITurnContext<IInvokeActivity> turnContext, JObject query, CancellationToken cancellationToken)  
  2.        {  
  3.            var (packageId, version, description, projectUrl, iconUrl) = query.ToObject<(string, string, string, string, string)>();  
  4.            var card = new ThumbnailCard  
  5.            {  
  6.                Title = $"{packageId}, {version}",  
  7.                Subtitle = description,  
  8.                Buttons = new List<CardAction>  
  9.                    {  
  10.                        new CardAction { Type = ActionTypes.OpenUrl, Title = "Nuget Package", Value = $"https://www.nuget.org/packages/{packageId}" },  
  11.                        new CardAction { Type = ActionTypes.OpenUrl, Title = "Project", Value = projectUrl },  
  12.                    },  
  13.            };  
  14.   
  15.            if (!string.IsNullOrEmpty(iconUrl))  
  16.            {  
  17.                card.Images = new List<CardImage>() { new CardImage(iconUrl, "Icon") };  
  18.            }  
  19.   
  20.            var attachment = new MessagingExtensionAttachment  
  21.            {  
  22.                ContentType = ThumbnailCard.ContentType,  
  23.                Content = card,  
  24.            };  
  25.   
  26.            return Task.FromResult(new MessagingExtensionResponse  
  27.            {  
  28.                ComposeExtension = new MessagingExtensionResult  
  29.                {  
  30.                    Type = "result",  
  31.                    AttachmentLayout = "list",  
  32.                    Attachments = new List<MessagingExtensionAttachment> { attachment }  
  33.                }  
  34.            });  
  35.        }  
 Build and Publish the Bot Code to Publishing Profile.
 
 Step 5 - Create Manifest 
  1. Create folder within solution with the name "TeamAppManifest" 
  2. Create and add icon-color.png file
  3. Create and add icon-outline.png file 
  4. Create manifest.json file and Update compose Extension with Command Context "Compose" and "CommandBox" 
  1. "composeExtensions": [  
  2.   {  
  3.     "botId""4c961f60-bb20-44a9-913d-2177652ddb3b",  
  4.     "canUpdateConfiguration"true,  
  5.     "commands": [  
  6.       {  
  7.         "id""searchQuery",  
  8.         "context": [ "compose""commandBox" ],  
  9.         "description""Test command to run query",  
  10.         "title""Search",  
  11.         "type""query",  
  12.         "parameters": [  
  13.           {  
  14.             "name""searchQuery",  
  15.             "title""Search Query",  
  16.             "description""Your search query",  
  17.             "inputType""text"  
  18.           }  
  19.         ]  
  20.       }  
  21.     ]  
  22.   }  
  23. ]  

 Select all three files and make it as .zip file and name it manifest.

Step 6 - Upload Manifest into Microsoft Teams App  
 
Navigate to manifest folder /src/manifest. Select both .png files and manifest.jon file and zip all three files. Give the name of zip file "manifest"
 
Login to https://teams.microsoft.com
  1. Navigate to App Studio
  2. Select Import an existing app
  3. Select the manifest.zip file
  4. Bot name with the icon will appear at the screen

Step 7 - Install Custom App to Teams Solution
  1. Select the install App using Manifets file and It will navigate to create an app page will all pre-filled information.
  2. Select test and distribute
  3. Click Add to add app to teams. 

Once bot deployment and Manifest configuration is done, now it's time to test the messaging extension.
 
Output 
  1. Navigate to teams and select channel
  2. Click on below compose message box "..." and select deployed app i.e. "searc-extension-settigns"
  3. Type keyword which will get searched from external api
Here we used nuget.org as external api. 



Select any item from messaging extension and the same will be posted as adaptive card to Teams Channel Conversation area. 


 
I hope you have enjoyed and learned something new in this article. Thanks for reading and stay tuned for the next article.