import * as React from 'react'; import { isArray, includes, isEmpty } from 'lodash'; import {handleFileSelect} from '../function' import Icon from '../Icon'; import PropsTypes from './types'; import * as numeral from 'numeral'; import FormComponent from '../FormComponent'; import Input from "../Input"; import ScrollArea from 'react-scrollbar' interface State extends PropsTypes { files: any[], loading: boolean, fileDetail: any[], errorMessage: any[], tempFilesError: any[], inputOption: any, show: boolean } export default class FileUpload extends FormComponent { public state: State; // private input = React.createRef(); constructor(props: PropsTypes, {}) { super(props); let iOption = {}; if (props.inputOption && !isEmpty(props.inputOption)) { iOption = { editable: props.inputOption.editable || true, icon: props.inputOption.icon || null, label: props.inputOption.label || null, caption: props.inputOption.caption || '', size: props.inputOption.size || 'medium', customStyle: props.inputOption.customStyle || '', closeAfterSelect: props.inputOption.closeAfterSelect || true, infoText: props.inputOption.infoText || '', autoFocus: props.inputOption.autoFocus || false, } } this.state = { files: [], loading: false, fileDetail: [], errorMessage: [], tempFilesError: [], inputOption: iOption, show:false // ...props }; } componentDidMount() { const {fileDetail} = this.state; this.validate(fileDetail.filter(t => t.status === 2).length ? 'true' : '') } errorRules(val: any) { const {maxSize, minSize, multiple, maxFile, minFile, mimeTypes} = this.props; if (val && val.length) { val.forEach((t:any) => { if (mimeTypes && isArray(mimeTypes) && !mimeTypes.filter(x => includes(t.type, x)).length) { t.error = `Bu formatta dosya ekleyemezsiniz` } if (maxSize && t.size > maxSize) { t.error = `Dosya boyutu en fazla ${numeral(maxSize).format('0.0 b')} olmalıdır` } if (minSize && t.size < minSize) { t.error = `Dosya boyutu en az ${numeral(minSize).format('0.0 b')} olmalıdır` } if (t.size > 1000000000) { t.error = 'Dosya boyutu çok büyük. İzin verilen boyut max 1 GB' } }); } let fileSize: number = val.filter((t:any) => !t.error).length; // let fileUnreadSize:number = val.filter(t => t.error).length; let errMsg: any[] = []; if (!multiple && fileSize > 1) { errMsg.push('Yalnızca 1 dosya yüklenebilir') } /* if (fileUnreadSize) { errMsg.push('Yüklemeye çalıştığınız dosyalar okunamadı') }*/ if (multiple && minFile && fileSize < minFile) { errMsg.push(`En az ${minFile} dosya yüklenmelidir`) } if (maxFile && multiple && fileSize > maxFile) { errMsg.push(`Yalnızca ${maxFile} dosya yüklenebilir`) } this.setState({ files: val, errorMessage: errMsg }); } async handleChange(val: any) { const {files} = this.state; const inputFiles = val.target.files; const stateFiles: any[] = [ ...files, ...Array.from(inputFiles) ]; await this.errorRules(stateFiles); this.setState({ files: stateFiles, errorMessage: [] }, () => { this.fileStart(); }) } fileOverWrite(callbackFile:any) { const {fileDetail} = this.state; let tempFileDetail: any[] = fileDetail; let isFile = tempFileDetail.filter(t => t.name === callbackFile.name); if (!isFile.length) { tempFileDetail.push(callbackFile) } else { tempFileDetail.filter((f) => { if (f.name === callbackFile.name) { f = callbackFile } }); } this.setState({ fileDetail: tempFileDetail }) } fileRead(callback:any) { const {fileDetail} = this.state; let tempFileDetail: any[] = fileDetail; tempFileDetail.filter((f) => { if (f.id === callback.id && !f.read) { f.status = callback.status; } }); this.setState({ fileDetail: tempFileDetail }) } fileDone = (callback:any) => { const {fileDetail, errorMessage, files} = this.state; const {onChange, /*imageMaxHeight, imageMaxWidth, *//*imageMinHeight, imageMinWidth*/} = this.props; let tempFileDetail: any[] = fileDetail; let tempFiles: any[] = files; tempFileDetail.filter((f) => { if (f.id === callback.id && !f.read) { f.status = callback.status; f.read = callback.read; f.output = callback.output; } }); this.setState({ fileDetail: tempFileDetail, files: tempFiles }, () => { this.validate(errorMessage.length ? '' : 'true', errorMessage[0]) onChange && onChange(tempFileDetail.filter(t => t.status === 2)) }) } fileProgress(callbackProgress:any) { const {fileDetail} = this.state; let tempFileDetail: any[] = fileDetail; tempFileDetail.filter((f) => { if (f.id === callbackProgress.id && !f.read) { f.progress = callbackProgress.progress; } }); this.setState({ fileDetail: tempFileDetail }) } async fileStart() { const {files} = this.state; if (files.length) { for (let i in files) { if (Number(i) < files.length) { handleFileSelect( files[Number(i)], files[i].error, (callbackStart: any) => callbackStart && this.fileOverWrite(callbackStart), (callbackRead: any) => callbackRead && this.fileRead(callbackRead), (callbackDone: any) => callbackDone && this.fileDone(callbackDone), (callbackProgress: any) => this.fileProgress(callbackProgress) ) } } } } /*fileOpen(): void { this.input.current && this.input.current.click() }*/ fileRemove(id: any) { const {onChange} = this.props; const {files, fileDetail} = this.state; let fileDetailList: any[] = []; let fileList: any[] = []; fileDetailList = fileDetail.filter(t => t.id !== id); fileList = files.filter(t => t.lastModified !== id); this.setState({ files: fileList, fileDetail: fileDetailList }, () => { onChange && onChange(fileDetailList.filter(t => t.status === 2)) }) } renderFileItems() { const {fileDetail} = this.state; if (isArray(fileDetail) && fileDetail.length) { let progress: any = null; let icon: string = 'file'; return fileDetail.map((item: any, i: number) => { progress = `${item.progress}%`; // console.log('File', item) if (includes(item.type, 'zip') || includes(item.type, 'rar') || includes(item.type, '7z')) { icon = 'fa-file-archive' } else if (includes(item.type, 'document')) { icon = 'fa-file-alt' } else if (includes(item.type, 'image')) { icon = 'fa-file-image' } else if (includes(item.type, 'pdf')) { icon = 'fa-file-pdf' } else { icon = 'fa-file' } if (item.error) { icon = 'fa-exclamation-circle'; } return
{item.status !== 2 ? : null}
{item.status === 2 && } {item.status === 0 || item.status === 1 && } {item.status === -1 && }
{item.name}
{item.status === 2 && !item.error ? item.size.textValue : item.error ? item.error : `Dosya okunuyor (%${item.progress} bitti)`}
this.fileRemove(item.id)}/>
}) } return null } renderInput() { const {inputOption, fileDetail, show} = this.state; const {validate, disabled} = this.props; return
{}} validate={validate} disabled={disabled} readOnly={this.readOnly()} readOnlyInput={this.readOnly()} errorMessage={this.error()} autoFocus={inputOption.autoFocus} onClick={() => { this.setState({show: !this.state.show}) }} icon={inputOption.icon} value={fileDetail ? `${fileDetail.filter(t => t.status === 2).length} dosya seçili` : ''} size={inputOption.size} customStyle={inputOption.customStyle} infoText={inputOption.infoText} /> {show ?
{this.renderFileArea()}
: null}
} /*renderModal() { return
{this.renderFileArea()}
}*/ renderFileArea() { const {fileDetail, errorMessage} = this.state; const {caption, multiple, infoText} = this.props; return
{errorMessage.length ?
{errorMessage.map((t, i) => { return

{t}

})}
: null} {isEmpty(this.error()) ?
{infoText}
: null} {this.error() ?
{this.error()}
: null}
{caption}
{fileDetail ? `${fileDetail.filter(t => t.status === 2).length} dosya seçili` : null}

this.handleChange(val)} />
{this.renderFileItems()}
} public render() { const {uiType} = this.props; return uiType === 'input' ? this.renderInput() : this.renderFileArea() } }