import * as React from 'react' ; import { css } from 'office-ui-fabric-react/lib/Utilities' ; import clone from 'lodash/clone' ; import { IExpandingCardProps } from 'office-ui-fabric-react/lib/HoverCard' ; import { DirectionalHint } from 'office-ui-fabric-react/lib/common/DirectionalHint' ; import { Persona , PersonaSize } from 'office-ui-fabric-react/lib/Persona' ; import { IconButton , Button , ButtonType } from 'office-ui-fabric-react/lib/Button' ; import { Spinner , SpinnerSize } from 'office-ui-fabric-react/lib/Spinner' ; import { Link } from 'office-ui-fabric-react/lib/Link' ; import { Icon } from 'office-ui-fabric-react/lib/Icon' ; import { IPrincipal , IUserProfileProperties , IODataKeyValuePair } from '../../../common/SPEntities' ; import { IFieldRendererProps } from '../fieldCommon/IFieldRendererProps' ; import styles from './FieldUserRenderer.module.scss' ; import { IContext } from '../../../common/Interfaces' ; import { GeneralHelper } from '../../../common/utilities/GeneralHelper' ; import FieldUserHoverCard , { IFieldUserHoverCardProps } from './FieldUserHoverCard' ; import * as telemetry from '../../../common/telemetry' ; import * as strings from 'ControlStrings' ; import { SPHelper } from '../../../common/utilities' ; export interface IFieldUserRendererProps extends IFieldRendererProps { /**
     * users to be displayed
     */ users ? : IPrincipal [ ] ; /**
     * Customizer context
     */ context : IContext ; } /**
 * Internal interface to work with user profile
 */ export interface IFieldUser { /**
     * display  name
     */ displayName ? : string ; /**
     * job title
     */ jobTitle ? : string ; /**
     * department
     */ department ? : string ; /**
     * user id
     */ id ? : string ; /**
     * avatar url
     */ imageUrl ? : string ; /**
     * email
     */ email ? : string ; /**
     * skype for business username
     */ sip ? : string ; /**
     * true if the user is current user
     */ currentUser ? : boolean ; /**
     * work phone
     */ workPhone ? : string ; /**
     * cell phone
     */ cellPhone ? : string ; /**
     * url to edit user profile in Delve
     */ userUrl ? : string ; } export interface IFieldUserRendererState { users ? : IFieldUser [ ] ; } /**
 * Field User Renderer.
 * Used for:
 *   - People and Groups
 */ export class FieldUserRenderer extends React . Component < IFieldUserRendererProps , IFieldUserRendererState > { private _loadedUserProfiles : { [ id ] : IUserProfileProperties ; } = { } ; private _userUrlTemplate : string ; private _userImageUrl : string ; public constructor ( props , state ) { super ( props , state ) ; telemetry . track ( 'FieldUserRenderer' , { } ) ; this . _userImageUrl = `${ GeneralHelper . trimSlash ( props . context . pageContext . web . absoluteUrl ) }/_layouts/15/userphoto.aspx?size=L&accountname={0}` ; const users = props . users ? props . users . map ( user => { return this . _getUserFromPrincipalAndProps ( user , { } ) ; } ) : [ ] ; this . state = { users : users } ; } public componentWillReceiveProps ( nextProps ) { const currentPrincipals = this . props . users ? this . props . users . map ( u => u . id ) : [ ] ; const newPrincipals = nextProps . users ? nextProps . users . map ( u => u . id ) : [ ] ; if ( currentPrincipals . length !== newPrincipals . length || currentPrincipals . filter ( cp => newPrincipals . indexOf ( cp ) === - 1 ) . length || newPrincipals . filter ( np => currentPrincipals . indexOf ( np ) === - 1 ) . length ) { this . setState ( { users : nextProps . users . map ( user => { return this . _getUserFromPrincipalAndProps ( user , { } ) ; } ) } ) ; } } public render ( ) { const userEls = this . state . users . map ( ( user , index ) => { const expandingCardProps = { onRenderCompactCard : ( user . email ? this . _onRenderCompactCard . bind ( this , index ) : null ) , onRenderExpandedCard : ( user . email ? this . _onRenderExpandedCard . bind ( this ) : null ) , renderData : user , directionalHint : DirectionalHint . bottomLeftEdge , gapSpace : 1 , expandedCardHeight : 150 } ; const hoverCardProps = { expandingCardProps : expandingCardProps , displayName : user . displayName , cssProps : this . props . cssProps } ; return < FieldUserHoverCard { ... hoverCardProps } / > ; } ) ; return < div style = { this . props . cssProps } className = { css ( this . props . className ) } > { userEls } < /div>; } param index param user private _onRenderCompactCard ( index , user ) { this . _requestUserProfile ( user , index ) ; const sip = user . sip || user . email ; let actionsEl ; if ( user . currentUser ) { actionsEl = < div className = { styles . actions } > < Button buttonType = { ButtonType . command } iconProps = { { iconName : 'Edit' } } href = { user . userUrl } target = { '_blank' } > { strings . UpdateProfile } < /Button> < /div>; } else { actionsEl = < div className = { styles . actions } > < IconButton iconProps = { { iconName : 'Mail' } } title = { strings . SendEmailTo . replace ( '{0}' , user . email ) } href = { `mailto:${ user . email }` } /> < IconButton iconProps = { { iconName : 'Chat' } } title = { strings . StartChatWith . replace ( '{0}' , sip ) } href = { `sip:${ sip }` } className = { styles . chat } / > < /div>; } return < div className = { styles . main } > < Persona imageUrl = { user . imageUrl } primaryText = { user . displayName } secondaryText = { user . department } tertiaryText = { user . jobTitle } size = { PersonaSize . large } / > { actionsEl } < /div>; } private _onRenderExpandedCard ( user ) { if ( this . _loadedUserProfiles [ user . id ] ) { return < ul className = { styles . sections } > < li className = { styles . section } > < div className = { styles . header } > { strings . Contact } < Icon iconName = "ChevronRight" className = { styles . chevron } / > < /div> < div className = { styles . contactItem } > < Icon iconName = { 'Mail' } /> < Link className = { styles . content } title = { user . email } href = { `mailto:${ user . email }` } target = { '_self' } > { user . email } < /Link> < /div> { user . workPhone && < div className = { styles . contactItem } > < Icon iconName = { 'Phone' } /> < Link className = { styles . content } title = { user . workPhone } href = { `tel:${ user . workPhone }` } target = { '_self' } > { user . workPhone } < /Link> < /div>} { user . cellPhone && < div className = { styles . contactItem } > < Icon iconName = { 'Phone' } /> < Link className = { styles . content } title = { user . cellPhone } href = { `tel:${ user . cellPhone }` } target = { '_self' } > { user . cellPhone } < /Link> < /div>} < /li> < /ul>; } else { return < Spinner size = { SpinnerSize . large } />; } } private _getUserFromPrincipalAndProps ( principal , userProfileProperties ) { let imageUrl = userProfileProperties . pictureUrl || principal . picture ; const mthumbStr = 'MThumb.jpg' ; if ( imageUrl && imageUrl . indexOf ( mthumbStr ) === imageUrl . length - mthumbStr . length ) { imageUrl = '' ; } return { displayName : userProfileProperties . displayName || principal . title , jobTitle : userProfileProperties . jobTitle || principal . jobTitle , department : userProfileProperties . department || principal . department , id : principal . id , imageUrl : imageUrl ? this . _userImageUrl . replace ( '{0}' , principal . email ) : imageUrl , email : userProfileProperties . email || principal . email , sip : userProfileProperties . sip || principal . sip , workPhone : userProfileProperties . workPhone , cellPhone : userProfileProperties . cellPhone , userUrl : this . _getUserUrlTemplate ( ) . replace ( '{0}' , principal . email ) , currentUser : principal . id == this . props . context . pageContext . legacyPageContext . userId } ; } private _getUserUrlTemplate ( ) { if ( ! this . _userUrlTemplate ) { this . _userUrlTemplate = `${ location . protocol }//${ location . hostname . split ( '.sharepoint.com' ) [ 0 ] }-my.sharepoint.com/person.aspx?user={0}&v=editprofile` ; } return this . _userUrlTemplate ; } private async _requestUserProfile ( user , index ) { if ( this . _loadedUserProfiles [ user . id ] ) { return ; } const context = this . props . context ; const siteUser = await SPHelper . getUserById ( parseInt ( user . id ) , context ) ; const value = await SPHelper . getUserProperties ( siteUser . LoginName , context ) ; const mthumbStr = 'MThumb.jpg' ; const userProfileProps = { displayName : value . DisplayName , email : value . Email , jobTitle : value . Title , userUrl : value . UserUrl , pictureUrl : value . PictureUrl && value . PictureUrl . toString ( ) . indexOf ( mthumbStr ) === value . PictureUrl . toString ( ) . length - mthumbStr . length ? '' : value . PictureUrl } ; const props = value . UserProfileProperties as IODataKeyValuePair [ ] ; let foundPropsCount = 0 ; for ( let i = 0 , len = props . length ; i < len ; i ++ ) { const prop = props [ i ] ; switch ( prop . Key ) { case 'WorkPhone' : userProfileProps . workPhone = prop . Value ; foundPropsCount ++ ; break ; case 'Department' : userProfileProps . department = prop . Value ; foundPropsCount ++ ; break ; case 'SPS-SipAddress' : userProfileProps . sip = prop . Value ; foundPropsCount ++ ; break ; case 'CellPhone' : userProfileProps . cellPhone = prop . Value ; foundPropsCount ++ ; break ; } if ( foundPropsCount === 4 ) { break ; } } this . _loadedUserProfiles [ user . id ] = userProfileProps ; this . setState ( ( prevState , componentProps ) => { const newUsers = clone < IFieldUser [ ] > ( prevState . users ) ; newUsers [ index ] = this . _getUserFromPrincipalAndProps ( this . props . users [ index ] , userProfileProps ) ; return { users : newUsers } ; } ) ; } }