Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deep link bug #26

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
# msteams-sample-contoso-hr-talent-app
This is a sample of the HR solution, please do not use it in a Production environment.

A Microsoft Teams app that will be used by the Human Resources department within their Microsoft Teams clients. The app will facilitate the department's hiring of new talent into the organization, provide immediate interview feedback, schedule interview loops, and improve the overall hiring process of new employees. Contoso HR Talent App will help you understand how to transform hiring and candidate management flow of new talent and make it more interactive and responsive for HR teams and interviewees.

The lab file is attached, but it would require extra steps on your part to setup your own O365 Tenant and pre-create Teams, Channels, Personas. Please use it for your reference.

# Microsoft Teams Talent Management Sample App in .NET/C#

This app simulates connection to a recruiting and talent management system and allows users and teams to create, manage and search positions and candidates. The content is randomly generated to simulate what you can do with Teams. The full source code is provided, along with the app package and manifest that you can use to side load and test in your Teams environment.
This app simulates connection to a recruiting and talent management system and allows users and teams to create, manage and search positions and candidates. The content is randomly generated to simulate what you can do with Teams. The full source code is provided, along with a lab guide that will walk you through the setup of this app, and how to surface it in Teams.

## Prerequisites
Please see the Teams Apps Talent Management Lab.pdf document for a detailed list of Pre-requisites.
This is a sample of the HR solution, please do not use it in a Production environment. It is designed to demonstrate how third-party apps can be surfaced in teams using the various interfaces that exist within Teams as a Platform.

## How to use this lab
Open the Teams Apps Talent Management Lab.pdf document, and start working through the guidance in this document. This guide will walk you through, step-by-step, with screenshots, the setup of the app (in Visual Studio, using NGROK as the tunnel) and the setup of the Teams app, which will introduce you to how the various interfaces in Teams work when surfacing a third-party app within Teams (Tabs, Bots, Messaging Extensions, Azure AD SSO, Proactive Messaging & Graph API).
Open the [Teams Apps Talent Management Lab.pdf](/Teams%20Apps%20Talent%20Mangagement%20Lab.pdf) document, and start working through the guidance in this document. This guide will walk you through, step-by-step with screenshots, the setup of the app (in Visual Studio, using NGROK as the tunnel) and the setup of the Teams app, which will introduce you to how the various interfaces in Teams work when surfacing a third-party app within Teams (Tabs, Bots, Messaging Extensions, Azure AD SSO, Proactive Messaging & Graph API).

# Contributing

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
}
],
"url": {
"raw": "https://graph.microsoft.com/v1.0/teams/f3e9518c-c11f-451a-b890-495d2476848b/channels",
"raw": "https://graph.microsoft.com/v1.0/teams/TEAMID/channels",
"protocol": "https",
"host": [
"graph",
Expand All @@ -85,7 +85,7 @@
"path": [
"v1.0",
"teams",
"f3e9518c-c11f-451a-b890-495d2476848b",
"TEAMID",
"channels"
]
}
Expand Down Expand Up @@ -113,7 +113,7 @@
"raw": "{\r\n \"body\": {\r\n \"content\": \"Hello World\"\r\n }\r\n}"
},
"url": {
"raw": "https://graph.microsoft.com/v1.0/teams/12288a3d-8742-4ce1-93e4-03e35e5773fb/channels/19:[email protected]/messages",
"raw": "https://graph.microsoft.com/v1.0/teams/TEAMID/channels/CHANNELID/messages",
"protocol": "https",
"host": [
"graph",
Expand All @@ -123,9 +123,9 @@
"path": [
"v1.0",
"teams",
"12288a3d-8742-4ce1-93e4-03e35e5773fb",
"TEAMID",
"channels",
"19:[email protected]",
"CHANNELID",
"messages"
]
}
Expand Down Expand Up @@ -191,7 +191,7 @@
}
},
"url": {
"raw": "https://graph.microsoft.com/v1.0/teams/12288a3d-8742-4ce1-93e4-03e35e5773fb/channels/19:[email protected]/messages/1622105461963/replies",
"raw": "https://graph.microsoft.com/v1.0/teams/TEAMID/channels/CHANNELID/messages/THEADID/replies",
"protocol": "https",
"host": [
"graph",
Expand All @@ -201,11 +201,11 @@
"path": [
"v1.0",
"teams",
"12288a3d-8742-4ce1-93e4-03e35e5773fb",
"TEAMID",
"channels",
"19:[email protected]",
"CHANNELID",
"messages",
"1622105461963",
"THEADID",
"replies"
]
}
Expand Down Expand Up @@ -233,7 +233,7 @@
}
},
"url": {
"raw": "https://graph.microsoft.com/v1.0/teams/12288a3d-8742-4ce1-93e4-03e35e5773fb/channels/19:[email protected]/messages/1622105461963/replies",
"raw": "https://graph.microsoft.com/v1.0/teams/TEAMID/channels/CHANNELID/messages/THEADID/replies",
"protocol": "https",
"host": [
"graph",
Expand All @@ -243,11 +243,11 @@
"path": [
"v1.0",
"teams",
"12288a3d-8742-4ce1-93e4-03e35e5773fb",
"TEAMID",
"channels",
"19:[email protected]",
"CHANNELID",
"messages",
"1622105461963",
"THEADID",
"replies"
]
}
Expand All @@ -272,7 +272,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"chatType\": \"oneOnOne\",\r\n \"members\": [\r\n {\r\n \"@odata.type\": \"#microsoft.graph.aadUserConversationMember\",\r\n \"roles\": [\"owner\"],\r\n \"[email protected]\": \"https://graph.microsoft.com/v1.0/users('5e9e185e-1a9a-4d1e-920b-2e8d51513ac9')\"\r\n },\r\n {\r\n \"@odata.type\": \"#microsoft.graph.aadUserConversationMember\",\r\n \"roles\": [\"owner\"],\r\n \"[email protected]\": \"https://graph.microsoft.com/v1.0/users('c7a18f5a-1deb-4c82-9c76-a5322f0ceeff')\"\r\n }\r\n ]\r\n}"
"raw": "{\r\n \"chatType\": \"oneOnOne\",\r\n \"members\": [\r\n {\r\n \"@odata.type\": \"#microsoft.graph.aadUserConversationMember\",\r\n \"roles\": [\"owner\"],\r\n \"[email protected]\": \"https://graph.microsoft.com/v1.0/users('USEROID')\"\r\n },\r\n {\r\n \"@odata.type\": \"#microsoft.graph.aadUserConversationMember\",\r\n \"roles\": [\"owner\"],\r\n \"[email protected]\": \"https://graph.microsoft.com/v1.0/users('USEROID')\"\r\n }\r\n ]\r\n}"
},
"url": {
"raw": "https://graph.microsoft.com/v1.0/chats",
Expand Down Expand Up @@ -311,7 +311,7 @@
"raw": "{\r\n \"body\": {\r\n \"content\": \"Hello World\"\r\n }\r\n}"
},
"url": {
"raw": "https://graph.microsoft.com/v1.0/chats/19:5e9e185e-1a9a-4d1e-920b-2e8d51513ac9_c7a18f5a-1deb-4c82-9c76-a5322f0ceeff@unq.gbl.spaces/messages",
"raw": "https://graph.microsoft.com/v1.0/chats/CHATID/messages",
"protocol": "https",
"host": [
"graph",
Expand All @@ -321,7 +321,7 @@
"path": [
"v1.0",
"chats",
"19:5e9e185e-1a9a-4d1e-920b-2e8d51513ac9_c7a18f5a-1deb-4c82-9c76-a5322f0ceeff@unq.gbl.spaces",
"CHATID",
"messages"
]
}
Expand Down
12 changes: 12 additions & 0 deletions src/Bot/TeamsTalentMgmtBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ public TeamsTalentMgmtBot(
protected override Task OnTeamsSigninVerifyStateAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
=> _invokeActivityHandler.HandleSigninVerifyStateAsync(turnContext, cancellationToken);

protected override async Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
{
return new TaskModuleResponse
{
Task = new TaskModuleContinueResponse
{
Type = "continue",
Value = await _invokeActivityHandler.HandleTaskModuleFetchAsync(taskModuleRequest, cancellationToken)
}
};
}

protected override Task<MessagingExtensionResponse> OnTeamsMessagingExtensionQueryAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken)
=> _invokeActivityHandler.HandleMessagingExtensionQueryAsync(turnContext, query, cancellationToken);

Expand Down
2 changes: 2 additions & 0 deletions src/Services/Interfaces/IInvokeActivityHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public interface IInvokeActivityHandler
{
Task<InvokeResponse> HandleSigninVerifyStateAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken);

Task<TaskModuleTaskInfo> HandleTaskModuleFetchAsync(TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken);

Task<MessagingExtensionResponse> HandleMessagingExtensionQueryAsync(
ITurnContext turnContext,
MessagingExtensionQuery query,
Expand Down
13 changes: 13 additions & 0 deletions src/Services/InvokeActivityHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ public async Task<InvokeResponse> HandleSigninVerifyStateAsync(ITurnContext<IInv
return new InvokeResponse { Status = (int)HttpStatusCode.OK };
}

public async Task<TaskModuleTaskInfo> HandleTaskModuleFetchAsync(TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
{
var candidate = await _candidateService.GetById((int)((dynamic)taskModuleRequest.Data).CandidateId, cancellationToken);

return new TaskModuleTaskInfo
{
Url = _appSettings.BaseUrl.TrimEnd('/') + $"/StaticViews/CandidateFeedback.html?candidateId={candidate.CandidateId}",
Title = "Feedback for " + candidate.Name,
Height = "large",
Width = "large"
};
}

public async Task<MessagingExtensionResponse> HandleMessagingExtensionQueryAsync(
ITurnContext turnContext,
MessagingExtensionQuery query,
Expand Down
19 changes: 9 additions & 10 deletions src/Services/Templates/CandidatesTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,17 @@ private static Attachment BuildSingleCandidateCardAsAdaptive(CandidateTemplateMo

if (candidate.Comments.Any() || candidate.Interviews.Any())
{
var contentUrl = data.AppSettings.BaseUrl + $"StaticViews/CandidateFeedback.html?candidateId={candidate.CandidateId}";
card.Actions.Add(new AdaptiveOpenUrlAction
card.Actions.Add(new AdaptiveSubmitAction
{
Title = "Open candidate feedback",
Url = new Uri(string.Format(
CommonConstants.TaskModuleUrlFormat,
data.AppSettings.TeamsAppId,
Uri.EscapeDataString(contentUrl),
Uri.EscapeDataString("Feedback for " + candidate.Name),
data.AppSettings.MicrosoftAppId,
"large",
"large"))
Data = new
{
CandidateId = candidate.CandidateId,
msteams = new
{
type = "task/fetch"
}
}
});
}

Expand Down
18 changes: 13 additions & 5 deletions src/StaticViews/proactivemessaging.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="/config.js"></script>
<script src="https://unpkg.com/@microsoft/mgt/dist/bundle/mgt-loader.js"></script>
<meta charset="utf-8" />
<title>Proactive Messaging Form</title>
<script type="text/javascript">
Expand Down Expand Up @@ -37,14 +38,14 @@
if (data.ok) {
console.log("HTTP Status: " + data.status);
console.log(data);
if (data.status >= 200 && data.status <300 ) {
if (data.status >= 200 && data.status < 300) {
$("#successfulRequest > span").html(data.status);
$("#successfulRequest").show();
}

} else {
console.error("HTTP-Error: " + data.status);

if (data.status == '403') {
$("#consentRequired").show();
}
Expand Down Expand Up @@ -76,7 +77,7 @@
//logic to capture succesful or unsuccesful consent after redirect back from Azure AD
$(() => {


var urlParams = new URLSearchParams(window.location.search);
var adminConsent = urlParams.get('admin_consent');
if (adminConsent == 'True') {
Expand All @@ -94,7 +95,14 @@ <h1>
Please submit the UPN and TenantID of the user into the form, to either Install the App, using Graph API or Send the User a proactive message, via the Bot.
</h1>
</div>
<form id="form1" >
<!--
Graph Toolkit stuff (TODO: Login and click the user)
<mgt-msal2-provider client-id="6a56bee2-c36e-4838-a0c2-7cf53be8bcd0"></mgt-msal2-provider>
<mgt-login></mgt-login>
<mgt-people-picker selection-mode='single'></mgt-people-picker>
-->

<form id="form1">
<label>UPN</label> <br>
<input id="upn" type="text" size="40" placeholder="[email protected]"> <br> <br>
<label>TenantId</label> <br>
Expand Down