import * as React from 'react' ; import { IPropertyFieldGroupOrPerson , PrincipalType } from './IPropertyFieldPeoplePicker' ; import { NormalPeoplePicker , IBasePickerSuggestionsProps } from 'office-ui-fabric-react/lib/Pickers' ; import { Label } from 'office-ui-fabric-react/lib/Label' ; import { IPersonaProps , PersonaPresence , PersonaInitialsColor } from 'office-ui-fabric-react/lib/Persona' ; import { Async } from 'office-ui-fabric-react/lib/Utilities' ; import * as strings from 'PropertyControlStrings' ; import { IPropertyFieldPeoplePickerHostProps , IPeoplePickerState } from './IPropertyFieldPeoplePickerHost' ; import SPPeopleSearchService from '../../services/SPPeopleSearchService' ; import FieldErrorMessage from '../errorMessage/FieldErrorMessage' ; import * as telemetry from '../../common/telemetry' ; import { setPropertyValue } from '../../helpers/GeneralHelper' ; /**
 * Renders the controls for PropertyFieldPeoplePicker component
 */ export default class PropertyFieldPeoplePickerHost extends React . Component < IPropertyFieldPeoplePickerHostProps , IPeoplePickerState > { private searchService : SPPeopleSearchService ; private intialPersonas : Array < IPersonaProps > = new Array < IPersonaProps > ( ) ; private resultsPeople : Array < IPropertyFieldGroupOrPerson > = new Array < IPropertyFieldGroupOrPerson > ( ) ; private resultsPersonas : Array < IPersonaProps > = new Array < IPersonaProps > ( ) ; private selectedPeople : Array < IPropertyFieldGroupOrPerson > = new Array < IPropertyFieldGroupOrPerson > ( ) ; private selectedPersonas : Array < IPersonaProps > = new Array < IPersonaProps > ( ) ; private async : Async ; private delayedValidate : ( value : IPropertyFieldGroupOrPerson [ ] ) => void ; /**
     * Constructor method
     */ constructor ( props ) { super ( props ) ; telemetry . track ( 'PropertyFieldPeoplePicker' , { allowDuplicate : props . allowDuplicate , principalType : props . principalType ? props . principalType . toString ( ) : '' , disabled : props . disabled } ) ; this . searchService = new SPPeopleSearchService ( ) ; this . onSearchFieldChanged = this . onSearchFieldChanged . bind ( this ) ; this . onItemChanged = this . onItemChanged . bind ( this ) ; this . createInitialPersonas ( ) ; this . state = { resultsPeople : this . resultsPeople , resultsPersonas : this . resultsPersonas , errorMessage : '' } ; this . async = new Async ( this ) ; this . validate = this . validate . bind ( this ) ; this . notifyAfterValidate = this . notifyAfterValidate . bind ( this ) ; this . delayedValidate = this . async . debounce ( this . validate , this . props . deferredValidationTime ) ; } /**
     * A search field change occured
     */ private onSearchFieldChanged ( searchText , currentSelected ) { if ( searchText . length > 2 ) { this . setState ( { resultsPeople : this . resultsPeople , resultsPersonas : this . resultsPersonas } ) ; const result = this . searchService . searchPeople ( this . props . context , searchText , this . props . principalType , this . props . targetSiteUrl ) . then ( ( response ) => { this . resultsPeople = [ ] ; this . resultsPersonas = [ ] ; if ( this . props . allowDuplicate === false ) { response = this . removeDuplicates ( response ) ; } response . forEach ( ( element , index ) => { this . resultsPeople . push ( element ) ; this . resultsPersonas . push ( this . getPersonaFromPeople ( element , index ) ) ; } ) ; this . setState ( { resultsPeople : this . resultsPeople , resultsPersonas : this . resultsPersonas } ) ; return this . resultsPersonas ; } ) ; return result ; } else { return [ ] ; } } /**
     * Remove the duplicates if property allowDuplicate equals false
     */ private removeDuplicates ( responsePeople ) { if ( this . selectedPeople === null || this . selectedPeople . length === 0 ) { return responsePeople ; } const res = [ ] ; for ( const element of responsePeople ) { let found = false ; for ( let i = 0 ; i < this . selectedPeople . length ; i ++ ) { const responseItem = this . selectedPeople [ i ] ; if ( responseItem . login === element . login && responseItem . id === element . id ) { found = true ; break ; } } if ( found === false ) { res . push ( element ) ; } } return res ; } /**
     * Creates the collection of initial personas from initial IPropertyFieldGroupOrPerson collection
     */ private createInitialPersonas ( ) { if ( this . props . initialData === null || typeof ( this . props . initialData ) !== typeof Array < IPropertyFieldGroupOrPerson > ( ) ) { return ; } this . props . initialData . forEach ( ( element , index ) => { const persona = this . getPersonaFromPeople ( element , index ) ; this . intialPersonas . push ( persona ) ; this . selectedPersonas . push ( persona ) ; this . selectedPeople . push ( element ) ; } ) ; } /**
     * Generates a IPersonaProps object from a IPropertyFieldGroupOrPerson object
     */ private getPersonaFromPeople ( element , index ) { return { primaryText : element . fullName , secondaryText : element . jobTitle , imageUrl : element . imageUrl , imageInitials : element . initials , presence : PersonaPresence . none , initialsColor : this . getRandomInitialsColor ( index ) } ; } /**
     * Refreshes the web part properties
     */ private refreshWebPartProperties ( ) { this . delayedValidate ( this . selectedPeople ) ; } /**
    * Validates the new custom field value
    */ private validate ( value ) { if ( this . props . onGetErrorMessage === null || this . props . onGetErrorMessage === undefined ) { this . notifyAfterValidate ( this . props . initialData , value ) ; return ; } const errResult = this . props . onGetErrorMessage ( value || [ ] ) ; if ( errResult ) { if ( typeof errResult === 'string' ) { if ( errResult === '' ) { this . notifyAfterValidate ( this . props . initialData , value ) ; } this . setState ( { errorMessage : errResult } ) ; } else { errResult . then ( ( errorMessage ) => { if ( ! errorMessage ) { this . notifyAfterValidate ( this . props . initialData , value ) ; } this . setState ( { errorMessage : errorMessage } ) ; } ) ; } } else { this . notifyAfterValidate ( this . props . initialData , value ) ; this . setState ( { errorMessage : null } ) ; } } /**
     * Notifies the parent Web Part of a property value change
     */ private notifyAfterValidate ( oldValue , newValue ) { if ( this . props . onPropertyChange && newValue ) { setPropertyValue ( this . props . properties , this . props . targetProperty , newValue ) ; this . props . onPropertyChange ( this . props . targetProperty , oldValue , newValue ) ; if ( typeof this . props . onChange !== 'undefined' && this . props . onChange !== null ) { this . props . onChange ( this . props . targetProperty , newValue ) ; } } } /**
     * Called when the component will unmount
     */ public componentWillUnmount ( ) { this . async . dispose ( ) ; } param selectedItem private _findIndex ( selectedItem ) { for ( let i = 0 ; i < this . resultsPersonas . length ; i ++ ) { const crntPersona = this . resultsPersonas [ i ] ; if ( crntPersona . imageUrl === selectedItem . imageUrl && crntPersona . primaryText === selectedItem . primaryText && crntPersona . secondaryText === selectedItem . secondaryText ) { return i ; } } return - 1 ; } /**
     * Event raises when the user changed people from the PeoplePicker component
     */ private onItemChanged ( selectedItems ) { if ( selectedItems . length > 0 ) { if ( selectedItems . length > this . selectedPersonas . length ) { const index = this . _findIndex ( selectedItems [ selectedItems . length - 1 ] ) ; if ( index > - 1 ) { const people = this . resultsPeople [ index ] ; this . selectedPeople . push ( people ) ; this . selectedPersonas . push ( this . resultsPersonas [ index ] ) ; } } else { this . selectedPersonas . forEach ( ( person , index2 ) => { const selectedItemIndex = selectedItems . indexOf ( person ) ; if ( selectedItemIndex === - 1 ) { this . selectedPersonas . splice ( index2 , 1 ) ; this . selectedPeople . splice ( index2 , 1 ) ; } } ) ; } } else { this . selectedPersonas . splice ( 0 , this . selectedPersonas . length ) ; this . selectedPeople . splice ( 0 , this . selectedPeople . length ) ; } this . refreshWebPartProperties ( ) ; } /**
     * Generate a PersonaInitialsColor from the item position in the collection
     */ private getRandomInitialsColor ( index ) { const num = index % 13 ; switch ( num ) { case 0 : return PersonaInitialsColor . blue ; case 1 : return PersonaInitialsColor . darkBlue ; case 2 : return PersonaInitialsColor . teal ; case 3 : return PersonaInitialsColor . lightGreen ; case 4 : return PersonaInitialsColor . green ; case 5 : return PersonaInitialsColor . darkGreen ; case 6 : return PersonaInitialsColor . lightPink ; case 7 : return PersonaInitialsColor . pink ; case 8 : return PersonaInitialsColor . magenta ; case 9 : return PersonaInitialsColor . purple ; case 10 : return PersonaInitialsColor . black ; case 11 : return PersonaInitialsColor . orange ; case 12 : return PersonaInitialsColor . red ; case 13 : return PersonaInitialsColor . darkRed ; default : return PersonaInitialsColor . blue ; } } /**
     * Renders the PeoplePicker controls with Office UI  Fabric
     */ public render ( ) { const suggestionProps = { suggestionsHeaderText : strings . PeoplePickerSuggestedContacts , noResultsFoundText : strings . PeoplePickerNoResults , loadingText : strings . PeoplePickerLoading , } ; if ( this . props . principalType && this . props . principalType . length > 0 ) { let userType = this . props . principalType . indexOf ( PrincipalType . Users ) !== - 1 ; let groupType = this . props . principalType . indexOf ( PrincipalType . SharePoint ) !== - 1 || this . props . principalType . indexOf ( PrincipalType . Security ) !== - 1 ; if ( userType && groupType ) { suggestionProps . suggestionsHeaderText = strings . PeoplePickerSuggestedCombined ; } if ( ! userType && groupType ) { suggestionProps . suggestionsHeaderText = strings . PeoplePickerSuggestedGroups ; } } return ( < div > { this . props . label && < Label > { this . props . label } < /Label>} < NormalPeoplePicker disabled = { this . props . disabled } pickerSuggestionsProps = { suggestionProps } onResolveSuggestions = { this . onSearchFieldChanged } onChange = { this . onItemChanged } defaultSelectedItems = { this . intialPersonas } itemLimit = { this . props . multiSelect ? undefined : 1 } / > < FieldErrorMessage errorMessage = { this . state . errorMessage } /> < /div>); } }