parent
6b69213bc3
commit
d46ec7b02f
5 changed files with 149 additions and 74 deletions
@ -1,96 +1,63 @@ |
||||
import { useEffect, useRef } from 'react'; |
||||
import { |
||||
Box, |
||||
Button, |
||||
Checkbox, |
||||
FormControl, |
||||
FormControlLabel, |
||||
Input, |
||||
InputLabel, |
||||
MenuItem, |
||||
Select, |
||||
TextField, |
||||
} from '@mui/material'; |
||||
import { BodyText } from '../Text'; |
||||
|
||||
import { UPLOAD_FILE_TYPES_ARRAY } from '../../lib/consts/UPLOAD_FILE_TYPES'; |
||||
|
||||
type FileInfoProps = { |
||||
anvilList: { |
||||
fileName: string; |
||||
fileType: string; |
||||
fileSyncAnvilList: { |
||||
anvilName: string; |
||||
anvilDescription: string; |
||||
anvilUUID: string; |
||||
isSync: boolean; |
||||
}[]; |
||||
isShowSelectFileOnStart?: boolean; |
||||
}; |
||||
|
||||
const FILE_TYPE_LIST = { |
||||
iso: 'ISO (optical disc)', |
||||
other: 'Other file type', |
||||
script: 'Script (program)', |
||||
}; |
||||
|
||||
// Used to solve react/require-default-params AND ensure linting works within the function component.
|
||||
const FILE_INFO_DEFAULT_PROPS = { isShowSelectFileOnStart: false }; |
||||
|
||||
const FileInfo = ({ |
||||
anvilList, |
||||
isShowSelectFileOnStart = FILE_INFO_DEFAULT_PROPS.isShowSelectFileOnStart, |
||||
fileName, |
||||
fileType, |
||||
fileSyncAnvilList, |
||||
}: FileInfoProps): JSX.Element => { |
||||
const selectFileRef = useRef<HTMLInputElement>(); |
||||
|
||||
const openFilePicker = () => { |
||||
selectFileRef.current?.click(); |
||||
}; |
||||
|
||||
useEffect(() => { |
||||
if (isShowSelectFileOnStart) { |
||||
openFilePicker(); |
||||
} |
||||
}, [isShowSelectFileOnStart]); |
||||
|
||||
return ( |
||||
<form encType="multipart/form-data"> |
||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}> |
||||
<InputLabel htmlFor="select-file"> |
||||
<Input |
||||
id="select-file" |
||||
ref={selectFileRef} |
||||
sx={{ display: 'none' }} |
||||
type="file" |
||||
/> |
||||
</InputLabel> |
||||
<Box |
||||
sx={{ alignItems: 'center', display: 'flex', flexDirection: 'row' }} |
||||
> |
||||
<TextField id="file-name" label="File name" sx={{ flexGrow: 1 }} /> |
||||
<Button onClick={openFilePicker} sx={{ textTransform: 'none' }}> |
||||
<BodyText text="Browse" /> |
||||
</Button> |
||||
</Box> |
||||
<Select id="file-type" label="File type" value="other"> |
||||
{Object.entries(FILE_TYPE_LIST).map( |
||||
([fileType, fileTypeDisplayString]) => { |
||||
return ( |
||||
<MenuItem key={fileType} value={fileType}> |
||||
{fileTypeDisplayString} |
||||
</MenuItem> |
||||
); |
||||
}, |
||||
)} |
||||
</Select> |
||||
{anvilList.map(({ anvilName, anvilDescription, anvilUUID }) => { |
||||
<FormControl> |
||||
<TextField |
||||
defaultValue={fileName} |
||||
id="file-name" |
||||
label="File name" |
||||
sx={{ flexGrow: 1 }} |
||||
/> |
||||
<Select defaultValue={fileType} id="file-type" label="File type"> |
||||
{UPLOAD_FILE_TYPES_ARRAY.map( |
||||
([fileTypeKey, [, fileTypeDisplayString]]) => { |
||||
return ( |
||||
<MenuItem key={fileTypeKey} value={fileTypeKey}> |
||||
{fileTypeDisplayString} |
||||
</MenuItem> |
||||
); |
||||
}, |
||||
)} |
||||
</Select> |
||||
{fileSyncAnvilList.map( |
||||
({ anvilName, anvilDescription, anvilUUID, isSync }) => { |
||||
return ( |
||||
<FormControlLabel |
||||
control={<Checkbox />} |
||||
control={<Checkbox checked={isSync} />} |
||||
key={anvilUUID} |
||||
label={`${anvilName}: ${anvilDescription}`} |
||||
value={`${anvilUUID}-sync`} |
||||
/> |
||||
); |
||||
})} |
||||
</Box> |
||||
</form> |
||||
}, |
||||
)} |
||||
</FormControl> |
||||
); |
||||
}; |
||||
|
||||
FileInfo.defaultProps = FILE_INFO_DEFAULT_PROPS; |
||||
|
||||
export default FileInfo; |
||||
|
@ -0,0 +1,96 @@ |
||||
import { ChangeEventHandler, 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 { BodyText } from '../Text'; |
||||
|
||||
type FileUploadInfoProps = { |
||||
openFilePickerEventEmitter?: EventEmitter; |
||||
}; |
||||
|
||||
const FILE_UPLOAD_INFO_DEFAULT_PROPS = { |
||||
openFilePickerEventEmitter: undefined, |
||||
}; |
||||
|
||||
const FileUploadInfo = ({ |
||||
openFilePickerEventEmitter, |
||||
}: FileUploadInfoProps = FILE_UPLOAD_INFO_DEFAULT_PROPS): JSX.Element => { |
||||
const selectFileRef = useRef<HTMLInputElement>(); |
||||
|
||||
const [selectedFileList, setSelectedFileList] = useState<File[]>([]); |
||||
|
||||
const convertMIMETypeToFileTypeKey = ( |
||||
fileMIMEType: string, |
||||
): UploadFileTypes => { |
||||
const fileTypesIterator = UPLOAD_FILE_TYPES.entries(); |
||||
|
||||
let fileType: UploadFileTypes | 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<HTMLInputElement> = ({ |
||||
target: { files }, |
||||
}) => { |
||||
if (files) { |
||||
setSelectedFileList(Array.from(files)); |
||||
} |
||||
}; |
||||
|
||||
useEffect(() => { |
||||
openFilePickerEventEmitter?.addListener('open', () => { |
||||
selectFileRef.current?.click(); |
||||
}); |
||||
}, [openFilePickerEventEmitter]); |
||||
|
||||
return ( |
||||
<form encType="multipart/form-data"> |
||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}> |
||||
<InputLabel htmlFor="select-file"> |
||||
<Input |
||||
id="select-file" |
||||
inputProps={{ multiple: true }} |
||||
onChange={autocompleteAfterSelectFile} |
||||
ref={selectFileRef} |
||||
sx={{ display: 'none' }} |
||||
type="file" |
||||
/> |
||||
</InputLabel> |
||||
{selectedFileList.map((file: File) => ( |
||||
<FileInfo |
||||
fileName={file.name} |
||||
fileType={convertMIMETypeToFileTypeKey(file.type)} |
||||
fileSyncAnvilList={[]} |
||||
key={file.name} |
||||
/> |
||||
))} |
||||
{selectedFileList.length > 0 && ( |
||||
<Button sx={{ textTransform: 'none' }}> |
||||
<BodyText text="Upload" /> |
||||
</Button> |
||||
)} |
||||
</Box> |
||||
</form> |
||||
); |
||||
}; |
||||
|
||||
FileUploadInfo.defaultProps = FILE_UPLOAD_INFO_DEFAULT_PROPS; |
||||
|
||||
export default FileUploadInfo; |
@ -0,0 +1,11 @@ |
||||
export const UPLOAD_FILE_TYPES_ARRAY: ReadonlyArray< |
||||
[UploadFileTypes, [string, string]] |
||||
> = [ |
||||
['iso', ['application/x-cd-image', 'ISO (optical disc)']], |
||||
['other', ['text/plain', 'Other file type']], |
||||
['script', ['text/plain', 'Script (program)']], |
||||
]; |
||||
export const UPLOAD_FILE_TYPES: ReadonlyMap< |
||||
UploadFileTypes, |
||||
[string, string] |
||||
> = new Map(UPLOAD_FILE_TYPES_ARRAY); |
@ -0,0 +1 @@ |
||||
declare type UploadFileTypes = 'iso' | 'other' | 'script'; |
Loading…
Reference in new issue