import * as React from 'react' ; import { PrimaryButton , DefaultButton , Spinner , FocusZone , List , IRectangle , Selection , SelectionMode , SelectionZone , Image , ImageFit , Check , css } from 'office-ui-fabric-react' ; import { Placeholder } from '../../../Placeholder' ; import { IRecentFile } from '../../../services/FilesSearchService.types' ; import { IFilePickerResult } from '../FilePicker.types' ; import { GeneralHelper } from '../../../common/utilities' ; import { IRecentFilesTabProps , IRecentFilesTabState } from '.' ; import * as strings from 'M365LPStrings' ; import styles from './RecentFilesTab.module.scss' ; /**
 * Rows per page
 */ const ROWS_PER_PAGE = 3 ; /**
 * Maximum row height
 */ const MAX_ROW_HEIGHT = 250 ; export default class RecentFilesTab extends React . Component < IRecentFilesTabProps , IRecentFilesTabState > { private _columnCount : number ; private _columnWidth : number ; private _rowHeight : number ; private _selection : Selection ; private _listElem : List = undefined ; constructor ( props ) { super ( props ) ; this . _selection = new Selection ( { selectionMode : SelectionMode . single , onSelectionChanged : this . _onSelectionChanged } ) ; this . state = { isLoading : true , results : [ ] , filePickerResult : null } ; } /**
     * Gets the most recently used files
     */ public async componentDidMount ( ) { const recentFilesResult = await this . props . fileSearchService . executeRecentSearch ( this . props . accepts ) ; this . _selection . setItems ( recentFilesResult , true ) ; this . setState ( { isLoading : false , results : recentFilesResult } ) ; } /**
     * Render the tab
     */ public render ( ) { const { results , isLoading } = this . state ; return ( < span className = { styles . tabContainer } > < span className = { styles . tabHeaderContainer } > < h2 className = { styles . tabHeader } > { strings . RecentDocumentsHeader } < /h2> < /span> < span className = { styles . tab } > { isLoading ? this . _renderSpinner ( ) : results === undefined || results . length < 1 ? this . _renderPlaceholder ( ) : this . _renderGridList ( ) } < /span> < span className = { styles . actionButtonsContainer } > < span className = { styles . actionButtons } > < PrimaryButton disabled = { ! this . state . filePickerResult } onClick = { ( ) => this . _handleSave ( ) } className = { styles . actionButton } > { strings . OpenButtonLabel } < /PrimaryButton> < DefaultButton onClick = { ( ) => this . _handleClose ( ) } className = { styles . actionButton } > { strings . CancelButtonLabel } < /DefaultButton> < /span> < /span> < /span>); } private _onSelectionChanged = ( ) => { const selectedItems = this . _selection . getSelection ( ) ; if ( selectedItems && selectedItems . length > 0 ) { const selectedKey = selectedItems [ 0 ] as IRecentFile ; const filePickerResult = { fileAbsoluteUrl : selectedKey . fileUrl , fileName : GeneralHelper . getFileNameFromUrl ( selectedKey . fileUrl ) , fileNameWithoutExtension : GeneralHelper . getFileNameWithoutExtension ( selectedKey . fileUrl ) , downloadFileContent : ( ) => { return this . props . fileSearchService . downloadSPFileContent ( selectedKey . fileUrl , GeneralHelper . getFileNameFromUrl ( selectedKey . fileUrl ) ) ; } } ; this . setState ( { filePickerResult } ) ; } else { this . setState ( { filePickerResult : undefined } ) ; } if ( this . _listElem ) { this . _listElem . forceUpdate ( ) ; } } ; private _getItemCountForPage = ( itemIndex , surfaceRect ) : number => { if ( itemIndex === 0 ) { this . _columnCount = Math . ceil ( surfaceRect . width / MAX_ROW_HEIGHT ) ; this . _columnWidth = Math . floor ( surfaceRect . width / this . _columnCount ) ; this . _rowHeight = this . _columnWidth ; } return this . _columnCount * ROWS_PER_PAGE ; } ; private _getPageHeight = ( ) : number => { return this . _rowHeight * ROWS_PER_PAGE ; } ; private _renderSpinner = ( ) : JSX . Element => { return < Spinner label = { strings . Loading } />; } ; private _renderPlaceholder = ( ) : JSX . Element => { return < Placeholder iconName = 'OpenFolderHorizontal' iconText = { strings . NoRecentFiles } description = { strings . NoRecentFilesDescription } / > ; } ; private _renderGridList = ( ) : JSX . Element => { return < span className = { styles . recentGridList } role = "grid" > < FocusZone > < SelectionZone selection = { this . _selection } onItemInvoked = { ( item ) => this . _handleItemInvoked ( item ) } > < List ref = { this . _linkElement } items = { this . state . results } onRenderCell = { this . _onRenderCell } getItemCountForPage = { this . _getItemCountForPage } getPageHeight = { this . _getPageHeight } renderedWindowsAhead = { 4 } / > < /SelectionZone> < /FocusZone> < /span>; } ; private _onRenderCell = ( item , index ) : JSX . Element => { let isSelected = false ; if ( this . _selection && index !== undefined ) { isSelected = this . _selection . isIndexSelected ( index ) ; } return ( < div className = { styles . gridListCell } role = { "gridCell" } > < div className = { css ( styles . itemTile , styles . isFile , styles . hasThumbnail , isSelected ? styles . isSelected : undefined ) } role = "link" aria - selected = { isSelected } data - is - draggable = "false" data - is - focusable = "true" data - selection - index = { index } data - selection - invoke = "true" data - item - index = { index } data - automationid = "ItemTile" style = { { width : this . _columnWidth , height : this . _rowHeight } } > < div className = { styles . itemTileContent } > < div className = { styles . itemTileFile } > < div className = { styles . itemTileFileContainer } > < div className = { styles . itemTileThumbnail } > { } < Image src = { item . fileUrl } width = { this . _columnWidth } height = { this . _rowHeight } imageFit = { ImageFit . cover } / > { } < /div> < div className = { styles . itemTileCheckCircle } role = 'checkbox' aria - checked = { isSelected } data - item - index = { index } data - selection - toggle = { true } data - automationid = 'CheckCircle' > < Check checked = { isSelected } /> < /div> < div className = { styles . itemTileNamePlate } > < div className = { styles . itemTileName } > { item . name } < /div> < div className = { styles . itemTileSubText } > < span > { strings . EditedByNamePlate } { item . editedBy } < /span> < /div> < /div> < /div> < /div> < /div> < /div> < /div>); } ; private _handleItemInvoked = ( item ) => { this . _selection . setKeySelected ( item . key , true , true ) ; } ; private _handleSave = ( ) => { this . props . onSave ( this . state . filePickerResult ) ; } ; private _handleClose = ( ) => { this . props . onClose ( ) ; } ; private _linkElement = ( e ) => { this . _listElem = e ; } ; }