import * as React from 'react' ; import styles from './RecentlyVisitedSites.module.scss' ; import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle" ; import { escape , uniqBy } from '@microsoft/sp-lodash-subset' ; import * as strings from 'RecentlyVisitedSitesWebPartStrings' ; import { Link } from 'office-ui-fabric-react/lib/components/Link' ; import { IRecentlyVisitedSitesProps , IRecentlyVisitedSitesState , IRecentWebs , IRecentWeb , IWebs } from '.' ; import { Spinner , SpinnerSize } from 'office-ui-fabric-react/lib/components/Spinner' ; export class RecentlyVisitedSites extends React . Component < IRecentlyVisitedSitesProps , IRecentlyVisitedSitesState > { param props constructor ( props ) { super ( props ) ; this . state = { usedSites : [ ] , error : null , loading : true } ; } /**
     * Fetch the recent sites via the Microsoft Graph client
     */ private _fetchRecentSites ( ) { if ( this . props . graphClient ) { this . setState ( { loading : true } ) ; this . props . graphClient . api ( "me/insights/used" ) . filter ( `ResourceVisualization/Type eq 'Web'` ) . top ( 30 ) . get ( ( err , res ) => { if ( err ) { this . setState ( { error : err . message ? err . message : strings . Error , usedSites : [ ] , loading : false } ) ; return ; } if ( res && res . value && res . value . length > 0 ) { this . _processRecentSites ( res . value ) ; } else { this . setState ( { loading : false , usedSites : [ ] } ) ; } } ) ; } } param recentWebs private _processRecentSites ( recentWebs ) { const rWebs = recentWebs . map ( w => { return { id : w . id , title : w . resourceVisualization . containerDisplayName , path : this . _updateSitePath ( w . resourceVisualization . containerWebUrl ) } ; } ) ; const uWeb = uniqBy ( rWebs , 'path' ) ; this . setState ( { usedSites : uWeb . slice ( 0 , 10 ) , loading : false } ) ; } param path private _updateSitePath ( path ) { if ( path ) { const pathSplit = path . split ( "/sites/" ) ; if ( pathSplit . length === 2 ) { const siteUrlPath = pathSplit [ 1 ] . substring ( 0 , pathSplit [ 1 ] . indexOf ( "/" ) ) ; return `${ pathSplit [ 0 ] }/sites/${ siteUrlPath }` ; } else { const matches = path . match ( /^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i ) ; if ( matches && matches . length > 0 ) { return matches [ 0 ] ; } } } return path ; } /**
     * componentDidMount lifecycle hook
     */ public componentDidMount ( ) { this . _fetchRecentSites ( ) ; } /**
     * Default React render method
     */ public render ( ) { const color = ( ! ! this . props . themeVariant && this . props . themeVariant . semanticColors . bodyText ) || null ; const backgroundColor = ( ! ! this . props . themeVariant && this . props . themeVariant . semanticColors . bodyBackground ) || null ; return ( < div className = { styles . recentlyVisitedSites } > < WebPartTitle displayMode = { this . props . displayMode } title = { this . props . title } updateProperty = { this . props . updateProperty } themeVariant = { this . props . themeVariant } / > { this . state . loading && < Spinner label = { strings . Loading } size = { SpinnerSize . large } / > } { this . state . usedSites && this . state . usedSites . length > 0 ? ( < div className = { styles . list } style = { { backgroundColor : backgroundColor } } > < ul > { this . state . usedSites . map ( site => ( < li key = { site . id } className = { styles . site } style = { { background : backgroundColor } } > < Link href = { site . path } title = { site . title } style = { { color : color } } > { site . title } < /Link> < /li>))} < /ul> < /div>) : (!this.state.loading && (this.state.error ? < span className = { styles . error } > { this . state . error } < /span> : < span className = { styles . noSites } > { strings . NoRecentSitesMsg } < /span>))} < /div>); } }