import { ChangeEventHandler, FormEventHandler, useEffect, useRef, useState, } from 'react'; import { Box, Button, Input, InputLabel } from '@mui/material'; import EventEmitter from 'events'; import { UPLOAD_FILE_TYPES } from '../../lib/consts/UPLOAD_FILE_TYPES'; import FileInfo from './FileInfo'; import { ProgressBar } from '../Bars'; import { BodyText } from '../Text'; import mainAxiosInstance from '../../lib/singletons/mainAxiosInstance'; type FileUploadInfoProps = { openFilePickerEventEmitter?: EventEmitter; }; type SelectedFile = Pick< FileDetailMetadata, 'fileName' | 'fileLocations' | 'fileType' > & { file: File; }; type InUploadFile = Pick & { progressValue: number; }; const FILE_UPLOAD_INFO_DEFAULT_PROPS: Partial = { openFilePickerEventEmitter: undefined, }; const FileUploadInfo = ( { openFilePickerEventEmitter, }: FileUploadInfoProps = FILE_UPLOAD_INFO_DEFAULT_PROPS as FileUploadInfoProps, ): JSX.Element => { const selectFileRef = useRef(); const [selectedFiles, setSelectedFiles] = useState([]); const [inUploadFiles, setInUploadFiles] = useState([]); const convertMIMETypeToFileTypeKey = (fileMIMEType: string): FileType => { const fileTypesIterator = UPLOAD_FILE_TYPES.entries(); let fileType: FileType | undefined; do { const fileTypesResult = fileTypesIterator.next(); if (fileTypesResult.value) { const [fileTypeKey, [mimeTypeToUse]] = fileTypesResult.value; if (fileMIMEType === mimeTypeToUse) { fileType = fileTypeKey; } } else { fileType = 'other'; } } while (!fileType); return fileType; }; const autocompleteAfterSelectFile: ChangeEventHandler = ({ target: { files }, }) => { if (files) { setSelectedFiles( Array.from(files).map( (file): SelectedFile => ({ file, fileName: file.name, fileLocations: [], fileType: convertMIMETypeToFileTypeKey(file.type), }), ), ); } }; const generateFileInfoOnChangeHandler = ( fileIndex: number, ): FileInfoChangeHandler => (inputValues) => { selectedFiles[fileIndex] = { ...selectedFiles[fileIndex], ...inputValues, }; }; const uploadFiles: FormEventHandler = (event) => { event.preventDefault(); while (selectedFiles.length > 0) { const selectedFile = selectedFiles.shift(); if (selectedFile) { const { file, fileName, fileType } = selectedFile; const fileFormData = new FormData(); fileFormData.append('file', new File([file], fileName, { ...file })); fileFormData.append('file-type', fileType); const inUploadFile: InUploadFile = { fileName, progressValue: 0 }; inUploadFiles.push(inUploadFile); mainAxiosInstance.post('/files', fileFormData, { headers: { 'Content-Type': 'multipart/form-data', }, onUploadProgress: ({ loaded, total }) => { inUploadFile.progressValue = Math.round((loaded / total) * 100); setInUploadFiles([...inUploadFiles]); // Should probably write a onUploadFileComplete to update the file list in the parent every time a file finishes upload. }, }); } } setSelectedFiles([]); setInUploadFiles([...inUploadFiles]); }; useEffect(() => { openFilePickerEventEmitter?.addListener('open', () => { selectFileRef.current?.click(); }); }, [openFilePickerEventEmitter]); return (
{inUploadFiles.map(({ fileName, progressValue }) => ( ))} {selectedFiles.map( ( { file: { name: originalFileName }, fileName, fileType, fileLocations, }, fileIndex, ) => ( ), )} {selectedFiles.length > 0 && ( )}
); }; FileUploadInfo.defaultProps = FILE_UPLOAD_INFO_DEFAULT_PROPS; export default FileUploadInfo;