77
88import * as MicrosoftGraph from '@microsoft/microsoft-graph-types' ;
99import { customElement , html , property , TemplateResult } from 'lit-element' ;
10- import { getEmailFromGraphEntity } from '../../graph/graph.people' ;
10+ import { findPerson , findUserByEmail , getEmailFromGraphEntity } from '../../graph/graph.people' ;
11+ import { getContactPhoto , getUserPhoto , myPhoto } from '../../graph/graph.photos' ;
12+ import { getUser , getUserWithPhoto } from '../../graph/graph.user' ;
1113import { Providers } from '../../Providers' ;
1214import { ProviderState } from '../../providers/IProvider' ;
1315import { getSvg , SvgIcon } from '../../utils/SvgHelper' ;
@@ -38,6 +40,23 @@ export class MgtPersonCard extends MgtTemplatedComponent {
3840 static get styles ( ) {
3941 return styles ;
4042 }
43+ /**
44+ * allows developer to define name of person for component
45+ * @type {string }
46+ */
47+ @property ( {
48+ attribute : 'person-query'
49+ } )
50+ public personQuery : string ;
51+
52+ /**
53+ * user-id property allows developer to use id value for component
54+ * @type {string }
55+ */
56+ @property ( {
57+ attribute : 'user-id'
58+ } )
59+ public userId : string ;
4160
4261 /**
4362 * Set the person details to render
@@ -110,9 +129,21 @@ export class MgtPersonCard extends MgtTemplatedComponent {
110129 public attributeChangedCallback ( name : string , oldValue : string , newValue : string ) {
111130 super . attributeChangedCallback ( name , oldValue , newValue ) ;
112131
113- if ( name === 'is-expanded' && oldValue !== newValue ) {
132+ if ( oldValue === newValue ) {
133+ return ;
134+ }
135+
136+ if ( name === 'is-expanded' ) {
114137 this . isExpanded = false ;
115138 }
139+
140+ switch ( name ) {
141+ case 'person-query' :
142+ case 'user-id' :
143+ this . personDetails = null ;
144+ this . requestStateUpdate ( ) ;
145+ break ;
146+ }
116147 }
117148
118149 /**
@@ -218,7 +249,7 @@ export class MgtPersonCard extends MgtTemplatedComponent {
218249 }
219250
220251 /**
221- * foo
252+ * Render person title.
222253 *
223254 * @protected
224255 * @param {IDynamicPerson } person
@@ -236,7 +267,7 @@ export class MgtPersonCard extends MgtTemplatedComponent {
236267 }
237268
238269 /**
239- * foo
270+ * Render person subtitle.
240271 *
241272 * @protected
242273 * @param {IDynamicPerson } person
@@ -267,6 +298,7 @@ export class MgtPersonCard extends MgtTemplatedComponent {
267298
268299 person = person || this . personDetails ;
269300 const userPerson = person as MicrosoftGraph . User ;
301+ const personPerson = person as MicrosoftGraph . Person ;
270302
271303 // Chat
272304 let chat : TemplateResult ;
@@ -290,7 +322,10 @@ export class MgtPersonCard extends MgtTemplatedComponent {
290322
291323 // Phone
292324 let phone : TemplateResult ;
293- if ( userPerson . businessPhones && userPerson . businessPhones . length > 0 ) {
325+ if (
326+ ( userPerson . businessPhones && userPerson . businessPhones . length > 0 ) ||
327+ ( personPerson . phones && personPerson . phones . length > 0 )
328+ ) {
294329 phone = html `
295330 < div class ="icon " @click =${ ( ) => this . callUser ( ) } >
296331 ${ getSvg ( SvgIcon . Phone , '#666666' ) }
@@ -328,7 +363,7 @@ export class MgtPersonCard extends MgtTemplatedComponent {
328363 }
329364
330365 /**
331- * foo
366+ * Render expanded details.
332367 *
333368 * @protected
334369 * @param {IDynamicPerson } [person]
@@ -384,6 +419,7 @@ export class MgtPersonCard extends MgtTemplatedComponent {
384419 protected renderContactDetails ( person ?: IDynamicPerson ) : TemplateResult {
385420 person = person || this . personDetails ;
386421 const userPerson = person as MicrosoftGraph . User ;
422+ const personPerson = person as MicrosoftGraph . Person ;
387423
388424 if ( this . hasTemplate ( 'contact-details' ) ) {
389425 return this . renderTemplate ( 'contact-details' , { userPerson } ) ;
@@ -420,6 +456,14 @@ export class MgtPersonCard extends MgtTemplatedComponent {
420456 < span class ="link-subtitle data "> ${ userPerson . businessPhones [ 0 ] } </ span >
421457 </ div >
422458 ` ;
459+ } else if ( personPerson . phones && personPerson . phones . length > 0 ) {
460+ const businessPhones = this . getPersonBusinessPhones ( personPerson ) ;
461+ phone = html `
462+ < div class ="details-icon " @click =${ ( ) => this . callUser ( ) } >
463+ ${ getSvg ( SvgIcon . SmallPhone , '#666666' ) }
464+ < span class ="link-subtitle data "> ${ businessPhones [ 0 ] } </ span >
465+ </ div >
466+ ` ;
423467 }
424468
425469 // Location
@@ -450,7 +494,31 @@ export class MgtPersonCard extends MgtTemplatedComponent {
450494 * @memberof MgtPersonCard
451495 */
452496 protected async loadState ( ) {
453- if ( this . inheritDetails ) {
497+ const provider = Providers . globalProvider ;
498+
499+ // check if user is signed in
500+ if ( ! provider || provider . state !== ProviderState . SignedIn ) {
501+ return ;
502+ }
503+
504+ const graph = provider . graph . forComponent ( this ) ;
505+
506+ // check if personDetail already populated
507+ if ( this . personDetails ) {
508+ const user = this . personDetails as MicrosoftGraph . User ;
509+ const id = user . userPrincipalName || user . id ;
510+ // if we have an id but no email, we should get data from the graph
511+ if ( id && ! getEmailFromGraphEntity ( user ) ) {
512+ const person = await getUserWithPhoto ( graph , id ) ;
513+ this . personDetails = person ;
514+ this . personImage = this . getImage ( ) ;
515+ } else if ( this . personImage === '@' && ! this . personDetails . personImage ) {
516+ // in some cases we might only have name or email, but need to find the image
517+ // use @ for the image value to search for an image
518+ this . loadImage ( ) ;
519+ }
520+ } else if ( this . inheritDetails ) {
521+ // User person details inherited from parent tree
454522 let parent = this . parentElement ;
455523 while ( parent && parent . tagName !== 'MGT-PERSON' ) {
456524 parent = parent . parentElement ;
@@ -460,15 +528,20 @@ export class MgtPersonCard extends MgtTemplatedComponent {
460528 this . personDetails = ( parent as MgtPerson ) . personDetails ;
461529 this . personImage = ( parent as MgtPerson ) . personImage ;
462530 }
463- }
464-
465- if ( this . personDetails ) {
466- return ;
467- }
468-
469- const provider = Providers . globalProvider ;
470- if ( ! provider || provider . state !== ProviderState . SignedIn ) {
471- return ;
531+ } else if ( this . userId || this . personQuery === 'me' ) {
532+ // Use userId or 'me' query to get the person and image
533+ const person = await getUserWithPhoto ( graph , this . userId ) ;
534+
535+ this . personDetails = person ;
536+ this . personImage = this . getImage ( ) ;
537+ } else if ( this . personQuery ) {
538+ // Use the personQuery to find our person.
539+ const people = await findPerson ( graph , this . personQuery ) ;
540+
541+ if ( people && people . length ) {
542+ this . personDetails = people [ 0 ] ;
543+ this . loadImage ( ) ;
544+ }
472545 }
473546 }
474547
@@ -496,11 +569,19 @@ export class MgtPersonCard extends MgtTemplatedComponent {
496569 */
497570 protected callUser ( ) {
498571 const user = this . personDetails as MicrosoftGraph . User ;
572+ const person = this . personDetails as microsoftgraph . Person ;
573+
499574 if ( user && user . businessPhones && user . businessPhones . length ) {
500575 const phone = user . businessPhones [ 0 ] ;
501576 if ( phone ) {
502577 window . open ( 'tel:' + phone , '_blank' ) ;
503578 }
579+ } else if ( person && person . phones && person . phones . length ) {
580+ const businessPhones = this . getPersonBusinessPhones ( person ) ;
581+ const phone = businessPhones [ 0 ] ;
582+ if ( phone ) {
583+ window . open ( 'tel:' + phone , '_blank' ) ;
584+ }
504585 }
505586 }
506587
@@ -560,6 +641,45 @@ export class MgtPersonCard extends MgtTemplatedComponent {
560641 this . isExpanded = true ;
561642 }
562643
644+ private async loadImage ( ) {
645+ const provider = Providers . globalProvider ;
646+ const graph = provider . graph . forComponent ( this ) ;
647+ const person = this . personDetails ;
648+ let image : string ;
649+
650+ if ( ( person as MicrosoftGraph . Person ) . userPrincipalName ) {
651+ // try to find a user by userPrincipalName
652+ const userPrincipalName = ( person as MicrosoftGraph . Person ) . userPrincipalName ;
653+ image = await getUserPhoto ( graph , userPrincipalName ) ;
654+ } else {
655+ // try to find a user by e-mail
656+ const email = getEmailFromGraphEntity ( person ) ;
657+ if ( email ) {
658+ const users = await findUserByEmail ( graph , email ) ;
659+ if ( users && users . length ) {
660+ // Check for an OrganizationUser
661+ const orgUser = users . find ( p => {
662+ return ( p as any ) . personType && ( p as any ) . personType . subclass === 'OrganizationUser' ;
663+ } ) ;
664+ if ( orgUser ) {
665+ // Lookup by userId
666+ const userId = ( users [ 0 ] as MicrosoftGraph . Person ) . scoredEmailAddresses [ 0 ] . address ;
667+ image = await getUserPhoto ( graph , userId ) ;
668+ } else {
669+ // Lookup by contactId
670+ const contactId = users [ 0 ] . id ;
671+ image = await getContactPhoto ( graph , contactId ) ;
672+ }
673+ }
674+ }
675+ }
676+
677+ if ( image ) {
678+ this . personDetails . personImage = image ;
679+ this . personImage = image ;
680+ }
681+ }
682+
563683 private getImage ( ) : string {
564684 if ( this . personImage && this . personImage !== '@' ) {
565685 return this . personImage ;
@@ -568,4 +688,15 @@ export class MgtPersonCard extends MgtTemplatedComponent {
568688 const person = this . personDetails ;
569689 return person && person . personImage ? person . personImage : null ;
570690 }
691+
692+ private getPersonBusinessPhones ( person : MicrosoftGraph . Person ) : string [ ] {
693+ const phones = person . phones ;
694+ const businessPhones : string [ ] = [ ] ;
695+ for ( const p of phones ) {
696+ if ( p . type === 'business' ) {
697+ businessPhones . push ( p . number ) ;
698+ }
699+ }
700+ return businessPhones ;
701+ }
571702}
0 commit comments