Skip to content

Commit 613a226

Browse files
Fixed messaging logic in person card (#357)
* Fixed messaging logic in person card * Adding Teams deeplink support * Added TeamsHelper * PR updates
1 parent 1a72666 commit 613a226

File tree

4 files changed

+131
-47
lines changed

4 files changed

+131
-47
lines changed

src/components/mgt-person-card/mgt-person-card.ts

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { getEmailFromGraphEntity } from '../../graph/graph.people';
1111
import { Providers } from '../../Providers';
1212
import { ProviderState } from '../../providers/IProvider';
1313
import { getSvg, SvgIcon } from '../../utils/SvgHelper';
14+
import { TeamsHelper } from '../../utils/TeamsHelper';
1415
import { IDynamicPerson, MgtPerson } from '../mgt-person/mgt-person';
1516
import { MgtTemplatedComponent } from '../templatedComponent';
1617
import { styles } from './mgt-person-card-css';
@@ -267,27 +268,31 @@ export class MgtPersonCard extends MgtTemplatedComponent {
267268
person = person || this.personDetails;
268269
const userPerson = person as MicrosoftGraph.User;
269270

271+
// Chat
270272
let chat: TemplateResult;
271-
let email: TemplateResult;
272-
let phone: TemplateResult;
273-
274-
if (userPerson.mailNickname) {
273+
if (userPerson.userPrincipalName) {
275274
chat = html`
276-
<div class="icon" @click=${this.chatUser}>
275+
<div class="icon" @click=${() => this.chatUser()}>
277276
${getSvg(SvgIcon.Chat, '#666666')}
278277
</div>
279278
`;
280279
}
280+
281+
// Email
282+
let email: TemplateResult;
281283
if (getEmailFromGraphEntity(person)) {
282284
email = html`
283285
<div class="icon" @click=${() => this.emailUser()}>
284286
${getSvg(SvgIcon.Email, '#666666')}
285287
</div>
286288
`;
287289
}
290+
291+
// Phone
292+
let phone: TemplateResult;
288293
if (userPerson.businessPhones && userPerson.businessPhones.length > 0) {
289294
phone = html`
290-
<div class="icon" @click=${this.callUser}>
295+
<div class="icon" @click=${() => this.callUser()}>
291296
${getSvg(SvgIcon.Phone, '#666666')}
292297
</div>
293298
`;
@@ -378,27 +383,25 @@ export class MgtPersonCard extends MgtTemplatedComponent {
378383
*/
379384
protected renderContactDetails(person?: IDynamicPerson): TemplateResult {
380385
person = person || this.personDetails;
386+
const userPerson = person as MicrosoftGraph.User;
381387

382388
if (this.hasTemplate('contact-details')) {
383-
return this.renderTemplate('contact-details', { person });
389+
return this.renderTemplate('contact-details', { userPerson });
384390
}
385391

386-
const userPerson = person as MicrosoftGraph.User;
387-
388-
let phone: TemplateResult;
389-
let email: TemplateResult;
390-
let location: TemplateResult;
392+
// Chat
391393
let chat: TemplateResult;
392-
393-
if (userPerson.businessPhones && userPerson.businessPhones.length > 0) {
394-
phone = html`
395-
<div class="details-icon" @click=${this.callUser}>
396-
${getSvg(SvgIcon.SmallPhone, '#666666')}
397-
<span class="link-subtitle data">${userPerson.businessPhones[0]}</span>
394+
if (userPerson.userPrincipalName) {
395+
chat = html`
396+
<div class="details-icon" @click=${() => this.chatUser()}>
397+
${getSvg(SvgIcon.SmallChat, '#666666')}
398+
<span class="link-subtitle data">${userPerson.userPrincipalName}</span>
398399
</div>
399400
`;
400401
}
401402

403+
// Email
404+
let email: TemplateResult;
402405
if (getEmailFromGraphEntity(person)) {
403406
email = html`
404407
<div class="details-icon" @click=${() => this.emailUser()}>
@@ -408,15 +411,19 @@ export class MgtPersonCard extends MgtTemplatedComponent {
408411
`;
409412
}
410413

411-
if (userPerson.mailNickname) {
412-
chat = html`
413-
<div class="details-icon" @click=${this.chatUser}>
414-
${getSvg(SvgIcon.SmallChat, '#666666')}
415-
<span class="link-subtitle data">${userPerson.mailNickname}</span>
414+
// Phone
415+
let phone: TemplateResult;
416+
if (userPerson.businessPhones && userPerson.businessPhones.length > 0) {
417+
phone = html`
418+
<div class="details-icon" @click=${() => this.callUser()}>
419+
${getSvg(SvgIcon.SmallPhone, '#666666')}
420+
<span class="link-subtitle data">${userPerson.businessPhones[0]}</span>
416421
</div>
417422
`;
418423
}
419424

425+
// Location
426+
let location: TemplateResult;
420427
if (person.officeLocation) {
421428
location = html`
422429
<div class="details-icon">
@@ -498,16 +505,27 @@ export class MgtPersonCard extends MgtTemplatedComponent {
498505
}
499506

500507
/**
501-
* Use the sip: protocol to initiate a chat message to the user.
508+
* Initiate a chat message to the user via deeplink.
502509
*
503510
* @protected
504511
* @memberof MgtPersonCard
505512
*/
506513
protected chatUser() {
507514
const user = this.personDetails as MicrosoftGraph.User;
508-
if (user && user.mailNickname) {
509-
const chat = user.mailNickname;
510-
window.open('sip:' + chat, '_blank');
515+
if (user && user.userPrincipalName) {
516+
const users: string = user.userPrincipalName;
517+
const url = `https://teams.microsoft.com/l/chat/0/0?users=${users}`;
518+
const openWindow = () => window.open(url, '_blank');
519+
520+
if (TeamsHelper.isAvailable) {
521+
TeamsHelper.executeDeepLink(url, (status: boolean) => {
522+
if (!status) {
523+
openWindow();
524+
}
525+
});
526+
} else {
527+
openWindow();
528+
}
511529
}
512530
}
513531

src/components/providers/mgt-teams-provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* -------------------------------------------------------------------------------------------
66
*/
77

8-
import { customElement, LitElement, property } from 'lit-element';
8+
import { customElement, property } from 'lit-element';
99
import { Providers } from '../../Providers';
1010
import { TeamsConfig, TeamsProvider } from '../../providers/TeamsProvider';
1111
import { MgtBaseProvider } from './baseProvider';

src/providers/TeamsProvider.ts

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77

88
import { AuthenticationProviderOptions } from '@microsoft/microsoft-graph-client/lib/es/IAuthenticationProviderOptions';
99
import { AuthenticationParameters, Configuration, UserAgentApplication } from 'msal';
10+
import { TeamsHelper } from '../utils/TeamsHelper';
1011
import { LoginType, ProviderState } from './IProvider';
1112
import { MsalProvider } from './MsalProvider';
1213

13-
// tslint:disable-next-line: completed-docs
14-
declare var microsoftTeams: any;
15-
1614
// tslint:disable-next-line: completed-docs
1715
declare global {
1816
// tslint:disable-next-line: completed-docs
@@ -108,16 +106,8 @@ export class TeamsProvider extends MsalProvider {
108106
* @static
109107
* @memberof TeamsProvider
110108
*/
111-
public static get isAvailable() {
112-
if (window.parent === window.self && window.nativeInterface) {
113-
// In Teams mobile client
114-
return true;
115-
} else if (window.name === 'embedded-page-container' || window.name === 'extension-tab-frame') {
116-
// In Teams web/desktop client
117-
return true;
118-
} else {
119-
return false;
120-
}
109+
public static get isAvailable(): boolean {
110+
return TeamsHelper.isAvailable;
121111
}
122112

123113
/**
@@ -128,7 +118,12 @@ export class TeamsProvider extends MsalProvider {
128118
* @static
129119
* @memberof TeamsProvider
130120
*/
131-
public static microsoftTeamsLib;
121+
public static get microsoftTeamsLib(): any {
122+
return TeamsHelper.microsoftTeamsLib;
123+
}
124+
public static set microsoftTeamsLib(value: any) {
125+
TeamsHelper.microsoftTeamsLib = value;
126+
}
132127

133128
/**
134129
* Handle all authentication redirects in the authentication page and authenticates the user
@@ -139,7 +134,7 @@ export class TeamsProvider extends MsalProvider {
139134
*/
140135
public static async handleAuth() {
141136
// we are in popup world now - authenticate and handle it
142-
const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams;
137+
const teams = TeamsHelper.microsoftTeamsLib;
143138
if (!teams) {
144139
// tslint:disable-next-line: no-console
145140
console.error('Make sure you have referenced the Microsoft Teams sdk before using the TeamsProvider');
@@ -246,9 +241,9 @@ export class TeamsProvider extends MsalProvider {
246241
scopes: config.scopes
247242
});
248243

249-
const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams;
250-
251244
this._authPopupUrl = config.authPopupUrl;
245+
246+
const teams = TeamsHelper.microsoftTeamsLib;
252247
teams.initialize();
253248
}
254249

@@ -260,7 +255,7 @@ export class TeamsProvider extends MsalProvider {
260255
*/
261256
public async login(): Promise<void> {
262257
this.setState(ProviderState.Loading);
263-
const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams;
258+
const teams = TeamsHelper.microsoftTeamsLib;
264259

265260
return new Promise((resolve, reject) => {
266261
teams.getContext(context => {
@@ -301,7 +296,7 @@ export class TeamsProvider extends MsalProvider {
301296
*/
302297
public async getAccessToken(options: AuthenticationProviderOptions): Promise<string> {
303298
if (!this.teamsContext) {
304-
const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams;
299+
const teams = TeamsHelper.microsoftTeamsLib;
305300
this.teamsContext = await teams.getContext();
306301
}
307302

src/utils/TeamsHelper.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
8+
// tslint:disable-next-line: completed-docs
9+
declare var microsoftTeams: any;
10+
11+
/**
12+
* A helper class for interacting with the Teams Client SDK.
13+
*
14+
* @export
15+
* @class TeamsHelper
16+
*/
17+
export class TeamsHelper {
18+
/**
19+
* Optional entry point to the teams library
20+
* If this value is not set, the provider will attempt to use
21+
* the microsoftTeams global variable.
22+
*
23+
* @static
24+
* @type {*}
25+
* @memberof TeamsHelper
26+
*/
27+
public static get microsoftTeamsLib(): any {
28+
return this._microsoftTeamsLib || microsoftTeams;
29+
}
30+
public static set microsoftTeamsLib(value: any) {
31+
this._microsoftTeamsLib = value;
32+
}
33+
34+
/**
35+
* Gets whether the Teams provider can be used in the current context
36+
* (Whether the app is running in Microsoft Teams)
37+
*
38+
* @readonly
39+
* @static
40+
* @memberof TeamsProvider
41+
*/
42+
public static get isAvailable(): boolean {
43+
if (!this.microsoftTeamsLib) {
44+
return false;
45+
}
46+
if (window.parent === window.self && window.nativeInterface) {
47+
// In Teams mobile client
48+
return true;
49+
} else if (window.name === 'embedded-page-container' || window.name === 'extension-tab-frame') {
50+
// In Teams web/desktop client
51+
return true;
52+
}
53+
return false;
54+
}
55+
56+
/**
57+
* Execute a deeplink against the Teams lib.
58+
*
59+
* @static
60+
* @param {string} deeplink
61+
* @param {(status: boolean, reason?: string) => void} [onComplete]
62+
* @memberof TeamsProvider
63+
*/
64+
public static executeDeepLink(deeplink: string, onComplete?: (status: boolean, reason?: string) => void): void {
65+
const teams = this.microsoftTeamsLib;
66+
teams.initialize();
67+
teams.executeDeepLink(deeplink, onComplete);
68+
}
69+
70+
private static _microsoftTeamsLib: any;
71+
}

0 commit comments

Comments
 (0)