import * as React from 'react' ; import { Dialog , DialogType , DialogFooter } from 'office-ui-fabric-react/lib/Dialog' ; import { PrimaryButton , DefaultButton } from 'office-ui-fabric-react/lib/Button' ; import { Label } from "office-ui-fabric-react/lib/Label" ; import * as strings from 'ControlStrings' ; import styles from './ListItemAttachments.module.scss' ; import { UploadAttachment } from './UploadAttachment' ; import { IListItemAttachmentFile } from './IListItemAttachmentFile' ; import { DocumentCard , DocumentCardActions , DocumentCardPreview , IDocumentCardPreviewImage } from 'office-ui-fabric-react/lib/DocumentCard' ; import { ImageFit } from 'office-ui-fabric-react/lib/Image' ; import { IListItemAttachmentsProps } from '.' ; import { IListItemAttachmentsState } from '.' ; import SPservice from "../../services/SPService" ; import { TooltipHost , DirectionalHint } from 'office-ui-fabric-react/lib/Tooltip' ; import { Spinner , SpinnerSize } from 'office-ui-fabric-react/lib/Spinner' ; import utilities from './utilities' ; import { Placeholder } from "../placeholder" ; import * as telemetry from '../../common/telemetry' ; interface IPreviewImageCollection { [ fileName ] : IDocumentCardPreviewImage ; } export class ListItemAttachments extends React . Component < IListItemAttachmentsProps , IListItemAttachmentsState > { private _spservice : SPservice ; private previewImages : IPreviewImageCollection = { } ; private _utilities : utilities ; constructor ( props ) { super ( props ) ; telemetry . track ( 'ReactListItemAttachments' , { } ) ; this . state = { file : null , hideDialog : true , dialogMessage : '' , attachments : [ ] , deleteAttachment : false , disableButton : false , showPlaceHolder : false , fireUpload : false , filesToUpload : [ ] , itemId : props . itemId } ; this . _spservice = new SPservice ( this . props . context ) ; this . _utilities = new utilities ( ) ; } /**
     * componentDidMount lifecycle hook
     */ public async componentDidMount ( ) { await this . loadAttachments ( ) ; } private async loadAttachmentPreview ( file ) { return this . _utilities . GetFileImageUrl ( file ) . then ( previewImageUrl => { return { name : file . FileName , previewImageSrc : previewImageUrl , iconSrc : '' , imageFit : ImageFit . center , width : 187 , height : 130 , } ; } ) ; } public async uploadAttachments ( itemId ) { if ( this . state . filesToUpload ) { await Promise . all ( this . state . filesToUpload . map ( file => this . _spservice . addAttachment ( this . props . listId , itemId , file . name , file , this . props . webUrl ) ) ) ; } return new Promise < void > ( ( resolve , error ) => { this . setState ( { filesToUpload : [ ] , itemId : itemId } , ( ) => this . loadAttachments ( ) . then ( resolve ) ) ; } ) ; } protected loadAttachmentsPreview ( files ) { const filePreviewImages = files . map ( file => this . loadAttachmentPreview ( file ) ) ; return Promise . all ( filePreviewImages ) . then ( filePreviews => { filePreviews . forEach ( preview => { this . previewImages [ preview . name ] = preview ; } ) ; this . setState ( { fireUpload : false , hideDialog : true , dialogMessage : '' , attachments : files , showPlaceHolder : files . length === 0 ? true : false } ) ; } ) ; } /**
     * Load Item Attachments
     */ private async loadAttachments ( ) { if ( this . state . itemId ) { await this . _spservice . getListItemAttachments ( this . props . listId , this . state . itemId ) . then ( async ( files ) => { await this . loadAttachmentsPreview ( files ) ; } ) . catch ( ( error ) => { this . setState ( { fireUpload : false , hideDialog : false , dialogMessage : strings . ListItemAttachmentserrorLoadAttachments . replace ( '{0}' , error . message ) } ) ; } ) ; } else if ( this . state . filesToUpload && this . state . filesToUpload . length > 0 ) { let files = this . state . filesToUpload . map ( file => ( { FileName : file . name , ServerRelativeUrl : undefined } ) ) ; await this . loadAttachmentsPreview ( files ) ; } else { this . setState ( { fireUpload : false , hideDialog : true , dialogMessage : '' , showPlaceHolder : true } ) ; } } /**
     * Close the dialog
     */ private _closeDialog = ( ) => { this . setState ( { fireUpload : false , hideDialog : true , dialogMessage : '' , file : null , deleteAttachment : false , } ) ; this . loadAttachments ( ) ; } ; /**
     * Attachment uploaded event handler
     */ private _onAttachmentUpload = async ( file ) => { if ( ! this . state . itemId ) { let files = this . state . filesToUpload || [ ] ; files . push ( file ) ; this . setState ( { filesToUpload : [ ... files ] } ) ; } await this . loadAttachments ( ) ; } ; param file private onDeleteAttachment = ( file ) => { this . setState ( { fireUpload : false , hideDialog : false , deleteAttachment : true , file : file , dialogMessage : strings . ListItemAttachmentsconfirmDelete . replace ( '{0}' , file . FileName ) , } ) ; } ; /**
     * Delete the attachment once it was confirmed
     */ private onConfirmedDeleteAttachment = async ( ) => { const { file } = this . state ; this . setState ( { fireUpload : false , disableButton : true , } ) ; try { if ( this . state . itemId ) { await this . _spservice . deleteAttachment ( file . FileName , this . props . listId , this . state . itemId , this . props . webUrl ) ; } else { let filesToUpload = this . state . filesToUpload ; let fileToRemove = filesToUpload . find ( f => f . name === file . FileName ) ; if ( fileToRemove ) { filesToUpload . splice ( filesToUpload . indexOf ( fileToRemove ) , 1 ) ; } let attachments = this . state . attachments ; let attachmentToRemove = attachments . find ( attachment => attachment . FileName === file . FileName ) ; if ( attachmentToRemove ) { attachments . splice ( attachments . indexOf ( attachmentToRemove ) , 1 ) ; } this . setState ( { filesToUpload : [ ... filesToUpload ] , attachments : [ ... attachments ] } ) ; } this . setState ( { fireUpload : false , hideDialog : false , deleteAttachment : false , disableButton : false , file : null , dialogMessage : strings . ListItemAttachmentsfileDeletedMsg . replace ( '{0}' , file . FileName ) , } ) ; } catch ( error ) { this . setState ( { fireUpload : false , hideDialog : false , file : null , deleteAttachment : false , dialogMessage : strings . ListItemAttachmentsfileDeleteError . replace ( '{0}' , file . FileName ) . replace ( '{1}' , error . message ) } ) ; } } ; /**
     * Default React render method
     */ public render ( ) { const { openAttachmentsInNewWindow } = this . props ; return ( < div className = { styles . ListItemAttachments } > < UploadAttachment listId = { this . props . listId } itemId = { this . state . itemId } disabled = { this . props . disabled } context = { this . props . context } onAttachmentUpload = { this . _onAttachmentUpload } fireUpload = { this . state . fireUpload } / > { this . state . showPlaceHolder ? < Placeholder iconName = 'Upload' iconText = { this . props . label || strings . ListItemAttachmentslPlaceHolderIconText } description = { this . props . description || strings . ListItemAttachmentslPlaceHolderDescription } buttonLabel = { strings . ListItemAttachmentslPlaceHolderButtonLabel } hideButton = { this . props . disabled } onConfigure = { ( ) => this . setState ( { fireUpload : true } ) } / > : this . state . attachments . map ( file => { const fileName = file . FileName ; const previewImage = this . previewImages [ fileName ] ; return ( < div key = { fileName } className = { styles . documentCardWrapper } > < TooltipHost content = { fileName } calloutProps = { { gapSpace : 0 , isBeakVisible : true } } closeDelay = { 200 } directionalHint = { DirectionalHint . rightCenter } > < DocumentCard onClickHref = { ! openAttachmentsInNewWindow && `${ file . ServerRelativeUrl }?web=1` } onClick = { openAttachmentsInNewWindow && ( ( ) => window . open ( `${ file . ServerRelativeUrl }?web=1` , "_blank" ) ) } className = { styles . documentCard } > < DocumentCardPreview previewImages = { [ previewImage ] } /> < Label className = { styles . fileLabel } > { fileName } < /Label> < DocumentCardActions actions = { [ { iconProps : { iconName : 'Delete' , title : strings . ListItemAttachmentsActionDeleteIconTitle , } , title : strings . ListItemAttachmentsactionDeleteTitle , text : strings . ListItemAttachmentsactionDeleteTitle , disabled : this . props . disabled , onClick : ( ev ) => { ev . preventDefault ( ) ; ev . stopPropagation ( ) ; this . onDeleteAttachment ( file ) ; } } , ] } / > < /DocumentCard> < /TooltipHost> < /div>); } ) } { ! this . state . hideDialog && < Dialog hidden = { this . state . hideDialog } type = { DialogType . normal } onDismiss = { this . _closeDialog } dialogContentProps = { { type : DialogType . normal , title : strings . ListItemAttachmentsdialogTitle , subText : this . state . dialogMessage } } modalProps = { { isBlocking : true , containerClassName : 'ms-dialogMainOverride' } } > < DialogFooter > < div style = { { marginBottom : 7 } } > { this . state . disableButton ? < Spinner size = { SpinnerSize . medium } /> : null} < /div> { this . state . deleteAttachment ? ( < PrimaryButton disabled = { this . state . disableButton } onClick = { this . onConfirmedDeleteAttachment } > { strings . ListItemAttachmentsdialogOKbuttonLabelOnDelete } < /PrimaryButton>) : null} { this . state . deleteAttachment ? ( < DefaultButton disabled = { this . state . disableButton } onClick = { this . _closeDialog } > { strings . ListItemAttachmentsdialogCancelButtonLabel } < /DefaultButton>) : < PrimaryButton onClick = { this . _closeDialog } > { strings . ListItemAttachmentsdialogOKbuttonLabel } < /PrimaryButton>} < /DialogFooter> < /Dialog>} < /div>); } }