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 = { file: File; metadata: FileInfoMetadata; }; type InUploadFile = Pick & { progressValue: number; }; const FILE_UPLOAD_INFO_DEFAULT_PROPS = { openFilePickerEventEmitter: undefined, }; const FileUploadInfo = ({ openFilePickerEventEmitter, }: FileUploadInfoProps = FILE_UPLOAD_INFO_DEFAULT_PROPS): JSX.Element => { const selectFileRef = useRef(); const [selectedFiles, setSelectedFiles] = useState([]); const [inUploadFiles, setInUploadFiles] = useState([]); const convertMIMETypeToFileTypeKey = ( fileMIMEType: string, ): UploadFileType => { const fileTypesIterator = UPLOAD_FILE_TYPES.entries(); let fileType: UploadFileType | 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, metadata: { fileName: file.name, fileType: convertMIMETypeToFileTypeKey(file.type), fileSyncAnvils: [], }, }), ), ); } }; const generateFileInfoOnChangeHandler = ( fileIndex: number, ): ((inputValues: Partial) => void) => (inputValues) => { selectedFiles[fileIndex].metadata = { ...selectedFiles[fileIndex].metadata, ...inputValues, }; }; const uploadFiles: FormEventHandler = (event) => { event.preventDefault(); while (selectedFiles.length > 0) { const selectedFile = selectedFiles.shift(); if (selectedFile) { const { file, metadata: { 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 }, metadata: { fileName, fileType, fileSyncAnvils }, }, fileIndex, ) => ( ), )} {selectedFiles.length > 0 && ( )}
); }; FileUploadInfo.defaultProps = FILE_UPLOAD_INFO_DEFAULT_PROPS; export default FileUploadInfo;