fix(striker-ui): draft file list and upload/edit form

main
Tsu-ba-me 3 years ago
parent 3ca3df01af
commit 6b69213bc3
  1. 96
      striker-ui/components/Files/FileInfo.tsx
  2. 67
      striker-ui/components/Files/FileList.tsx
  3. 32
      striker-ui/components/Files/Files.tsx

@ -0,0 +1,96 @@
import { useEffect, useRef } from 'react';
import {
Box,
Button,
Checkbox,
FormControlLabel,
Input,
InputLabel,
MenuItem,
Select,
TextField,
} from '@mui/material';
import { BodyText } from '../Text';
type FileInfoProps = {
anvilList: {
anvilName: string;
anvilDescription: string;
anvilUUID: string;
}[];
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,
}: 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 }) => {
return (
<FormControlLabel
control={<Checkbox />}
key={anvilUUID}
label={`${anvilName}: ${anvilDescription}`}
value={`${anvilUUID}-sync`}
/>
);
})}
</Box>
</form>
);
};
FileInfo.defaultProps = FILE_INFO_DEFAULT_PROPS;
export default FileInfo;

@ -0,0 +1,67 @@
import { Box, Divider, List, ListItem } from '@mui/material';
import * as prettyBytes from 'pretty-bytes';
import { DIVIDER } from '../../lib/consts/DEFAULT_THEME';
import { BodyText } from '../Text';
const FileList = ({ list = [] }: { list: string[][] }): JSX.Element => {
return (
<List>
{list.map((file) => {
const fileUUID: string = file[0];
const fileName: string = file[1];
const fileSize: string = prettyBytes.default(parseInt(file[2], 10), {
binary: true,
});
const fileType: string = file[3];
const fileChecksum: string = file[4];
return (
<ListItem button key={fileUUID}>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
width: '100%',
}}
>
<Box sx={{ p: 1, flexGrow: 1 }}>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
}}
>
<BodyText text={fileName} />
<Divider
flexItem
orientation="vertical"
sx={{
backgroundColor: DIVIDER,
marginLeft: '.5em',
marginRight: '.5em',
}}
/>
<BodyText text={fileType} />
</Box>
<BodyText text={fileSize} />
</Box>
<Box
sx={{
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
}}
>
<BodyText text={fileChecksum} />
</Box>
</Box>
</ListItem>
);
})}
</List>
);
};
export default FileList;

@ -1,5 +1,5 @@
import { useRef } from 'react'; import { useState } from 'react';
import { Box, IconButton, Input, InputLabel } from '@mui/material'; import { Box, IconButton } from '@mui/material';
import AddIcon from '@mui/icons-material/Add'; import AddIcon from '@mui/icons-material/Add';
import { styled } from '@mui/material/styles'; import { styled } from '@mui/material/styles';
@ -9,6 +9,8 @@ import { Panel } from '../Panels';
import PeriodicFetch from '../../lib/fetchers/periodicFetch'; import PeriodicFetch from '../../lib/fetchers/periodicFetch';
import Spinner from '../Spinner'; import Spinner from '../Spinner';
import { HeaderText } from '../Text'; import { HeaderText } from '../Text';
import FileInfo from './FileInfo';
import FileList from './FileList';
const PREFIX = 'Files'; const PREFIX = 'Files';
@ -26,15 +28,14 @@ const StyledDiv = styled('div')(() => ({
})); }));
const Files = (): JSX.Element => { const Files = (): JSX.Element => {
const addFileInputRef = useRef<HTMLInputElement>(); const [isShowUploadForm, setIsShowUploadForm] = useState<boolean>(false);
const { data, isLoading } = PeriodicFetch( const { data: fileList, isLoading } = PeriodicFetch(
`${process.env.NEXT_PUBLIC_API_URL?.replace('/cgi-bin', '/api')}/files`, `${process.env.NEXT_PUBLIC_API_URL?.replace('/cgi-bin', '/api')}/files`,
); );
// Let the icon button trigger the invisible input element.
const onAddFileButtonClick = () => { const onAddFileButtonClick = () => {
addFileInputRef.current?.click(); setIsShowUploadForm(!isShowUploadForm);
}; };
return ( return (
@ -45,31 +46,18 @@ const Files = (): JSX.Element => {
<HeaderText text="Files" /> <HeaderText text="Files" />
</Box> </Box>
<Box> <Box>
<form encType="multipart/form-data">
<InputLabel htmlFor="add-file-input">
<Input
className={classes.addFileInput}
id="add-file-input"
ref={addFileInputRef}
type="file"
/>
<IconButton <IconButton
className={classes.addFileButton} className={classes.addFileButton}
onClick={onAddFileButtonClick} onClick={onAddFileButtonClick}
> >
<AddIcon /> <AddIcon />
</IconButton> </IconButton>
</InputLabel>
</form>
</Box> </Box>
</Box> </Box>
{isLoading ? ( {isShowUploadForm && (
<Spinner /> <FileInfo anvilList={[]} isShowSelectFileOnStart />
) : (
<Box>
<span>{data}</span>
</Box>
)} )}
{isLoading ? <Spinner /> : <FileList list={fileList} />}
</StyledDiv> </StyledDiv>
</Panel> </Panel>
); );

Loading…
Cancel
Save