Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIMSBIOHUB-614: Fix file upload error handling. #1366

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 33 additions & 65 deletions app/src/components/attachments/FileUploadWithMeta.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,52 @@
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import ReportMetaForm, { IReportMetaForm } from 'components/attachments/ReportMetaForm';
import FileUpload, { IReplaceHandler } from 'components/file-upload/FileUpload';
import {
IFileHandler,
IOnUploadSuccess,
IUploadHandler,
UploadFileStatus
} from 'components/file-upload/FileUploadItem';
import { AttachmentType, AttachmentTypeFileExtensions } from 'constants/attachments';
import { UploadFileStatus } from 'components/file-upload/FileUploadItem';
import { FileUploadSingleItem } from 'components/file-upload/FileUploadSingleItem';
import { AttachmentTypeFileExtensions } from 'constants/attachments';
import { useFormikContext } from 'formik';
import React from 'react';

export interface IFileUploadWithMetaProps {
attachmentType: AttachmentType.REPORT | AttachmentType.KEYX | AttachmentType.CFG | AttachmentType.OTHER;
uploadHandler: IUploadHandler;
fileHandler?: IFileHandler;
onSuccess?: IOnUploadSuccess;
}
export const FileUploadWithMeta = () => {
const { handleSubmit, setFieldValue, setFieldError, values, errors } = useFormikContext<IReportMetaForm>();

Check warning on line 10 in app/src/components/attachments/FileUploadWithMeta.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/attachments/FileUploadWithMeta.tsx#L10

Added line #L10 was not covered by tests

export const FileUploadWithMeta: React.FC<IFileUploadWithMetaProps> = (props) => {
const { handleSubmit, setFieldValue, errors } = useFormikContext<IReportMetaForm>();
const onStatus = (status: UploadFileStatus) => {
console.log(status);

Check warning on line 13 in app/src/components/attachments/FileUploadWithMeta.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/attachments/FileUploadWithMeta.tsx#L12-L13

Added lines #L12 - L13 were not covered by tests
NickPhura marked this conversation as resolved.
Show resolved Hide resolved
};

const fileHandler: IFileHandler = (file) => {
const onFile = (file: File | null) => {

Check warning on line 16 in app/src/components/attachments/FileUploadWithMeta.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/attachments/FileUploadWithMeta.tsx#L16

Added line #L16 was not covered by tests
setFieldValue('attachmentFile', file);

props.fileHandler?.(file);
};

const replaceHandler: IReplaceHandler = () => {
setFieldValue('attachmentFile', null);
const onError = (error: string) => {
setFieldError('attachmentFile', error);

Check warning on line 21 in app/src/components/attachments/FileUploadWithMeta.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/attachments/FileUploadWithMeta.tsx#L20-L21

Added lines #L20 - L21 were not covered by tests
};

return (
<form onSubmit={handleSubmit}>
{props.attachmentType === AttachmentType.REPORT && (
<Box mb={3}>
<ReportMetaForm />
</Box>
)}
{props.attachmentType === AttachmentType.REPORT && (
<Box component="fieldset">
<Typography component="legend" variant="body1" id="report_upload">
Attach File
</Typography>
<FileUpload
uploadHandler={props.uploadHandler}
fileHandler={fileHandler}
onReplace={replaceHandler}
onSuccess={props.onSuccess}
dropZoneProps={{
maxNumFiles: 1,
multiple: false,
acceptedFileExtensions: AttachmentTypeFileExtensions.REPORT
}}
status={UploadFileStatus.STAGED}
replace={true}
/>
{errors?.attachmentFile && (
<Box>
{/* TODO is errors.attachmentFile correct here? (added `as string` to appease compile warning) */}
<Typography style={{ fontSize: '12px', color: '#f44336' }}>{errors.attachmentFile as string}</Typography>
</Box>
)}
</Box>
)}
{props.attachmentType === AttachmentType.KEYX && (
<FileUpload
uploadHandler={props.uploadHandler}
fileHandler={fileHandler}
onSuccess={props.onSuccess}
dropZoneProps={{
acceptedFileExtensions: AttachmentTypeFileExtensions.KEYX
<Box mb={3}>
<ReportMetaForm />
</Box>
<Box component="fieldset">
<Typography component="legend" variant="body1" id="report_upload">
Attach File
</Typography>
<FileUploadSingleItem
file={values.attachmentFile}
onStatus={onStatus}
onFile={onFile}
onError={onError}
DropZoneProps={{
acceptedFileExtensions: AttachmentTypeFileExtensions.REPORT
}}
enableErrorDetails={true}
status={UploadFileStatus.STAGED}
/>
)}
{props.attachmentType === AttachmentType.OTHER && (
<FileUpload uploadHandler={props.uploadHandler} onSuccess={props.onSuccess} />
)}
{errors?.attachmentFile && (
<Box>
{/* TODO is errors.attachmentFile correct here? (added `as string` to appease compile warning) */}
<Typography style={{ fontSize: '12px', color: '#f44336' }}>{errors.attachmentFile as string}</Typography>
</Box>
)}
</Box>
</form>
);
};
Expand Down
84 changes: 0 additions & 84 deletions app/src/components/dialog/FileUploadDialog.tsx

This file was deleted.

55 changes: 55 additions & 0 deletions app/src/components/dialog/attachments/FileUploadDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import useTheme from '@mui/material/styles/useTheme';
import useMediaQuery from '@mui/material/useMediaQuery';
import { IDropZoneConfigProps } from 'components/file-upload/DropZone';
import FileUpload from 'components/file-upload/FileUpload';
import { IUploadHandler } from 'components/file-upload/FileUploadItem';
import { IComponentDialogProps } from '../ComponentDialog';

interface IFileUploadDialogProps extends IComponentDialogProps {
open: boolean;
dialogTitle: string;
uploadHandler: IUploadHandler;
onClose: () => void;
dropZoneProps?: IDropZoneConfigProps;
}

/**
*
*
* @param {IFileUploadDialogProps} props
* @return {*}
*/
export const FileUploadDialog = (props: IFileUploadDialogProps) => {
const { open, dialogTitle, uploadHandler, onClose, dropZoneProps } = props;

const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));

if (!open) {
return null;
}

return (
<Dialog
fullScreen={fullScreen}
maxWidth="xl"
open={open}
aria-labelledby="file-upload-dialog-title"
aria-describedby="file-upload-dialog-description">
<DialogTitle id="file-upload-dialog-title">{dialogTitle}</DialogTitle>
<DialogContent>
<FileUpload uploadHandler={uploadHandler} dropZoneProps={dropZoneProps} />
</DialogContent>
<DialogActions>
<Button onClick={onClose} color="primary" variant="outlined">
Close
</Button>
</DialogActions>
</Dialog>
);
};
101 changes: 101 additions & 0 deletions app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { LoadingButton } from '@mui/lab';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import useTheme from '@mui/material/styles/useTheme';
import Typography from '@mui/material/Typography';
import useMediaQuery from '@mui/material/useMediaQuery';
import { IDropZoneConfigProps } from 'components/file-upload/DropZone';
import { UploadFileStatus } from 'components/file-upload/FileUploadItem';
import { FileUploadSingleItem } from 'components/file-upload/FileUploadSingleItem';
import { useEffect, useState } from 'react';

interface IFileUploadSingleItemDialog {
open: boolean;
dialogTitle: string;
uploadButtonLabel: string;
onUpload: (file: File) => Promise<void>;
onClose?: () => void;
dropZoneProps: Pick<IDropZoneConfigProps, 'acceptedFileExtensions' | 'maxFileSize'>;
}

/**
*
*
* @param {IFileUploadSingleItemDialog} props
* @return {*}
*/
export const FileUploadSingleItemDialog = (props: IFileUploadSingleItemDialog) => {
const { open, dialogTitle, uploadButtonLabel, onUpload, onClose, dropZoneProps } = props;

Check warning on line 31 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L30-L31

Added lines #L30 - L31 were not covered by tests

const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));

Check warning on line 34 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L33-L34

Added lines #L33 - L34 were not covered by tests

const [currentFile, setCurrentFile] = useState<File | null>(null);
const [status, setStatus] = useState<UploadFileStatus>(UploadFileStatus.STAGED);
const [error, setError] = useState<string>('');
const [isUploading, setIsUploading] = useState<boolean>(false);

Check warning on line 39 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L36-L39

Added lines #L36 - L39 were not covered by tests

const isDisabled = !currentFile;

Check warning on line 41 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L41

Added line #L41 was not covered by tests

const handleUpload = () => {

Check warning on line 43 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L43

Added line #L43 was not covered by tests
if (!currentFile) {
return;

Check warning on line 45 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L45

Added line #L45 was not covered by tests
}

setIsUploading(true);
onUpload(currentFile).finally(() => setIsUploading(false));

Check warning on line 49 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L48-L49

Added lines #L48 - L49 were not covered by tests
};

useEffect(() => {
setCurrentFile(null);

Check warning on line 53 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L52-L53

Added lines #L52 - L53 were not covered by tests
}, [open]);

if (!open) {
return null;

Check warning on line 57 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L57

Added line #L57 was not covered by tests
}

return (

Check warning on line 60 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L60

Added line #L60 was not covered by tests
<Dialog
fullScreen={fullScreen}
maxWidth="xl"
open={open}
aria-labelledby="file-upload-dialog-title"
aria-describedby="file-upload-dialog-description">
<DialogTitle id="file-upload-dialog-title">{dialogTitle}</DialogTitle>
<DialogContent>
<FileUploadSingleItem
file={currentFile}
status={status}
onStatus={(status) => setStatus(status)}

Check warning on line 72 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L72

Added line #L72 was not covered by tests
onFile={(file) => {
setCurrentFile(file);
setError('');

Check warning on line 75 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L74-L75

Added lines #L74 - L75 were not covered by tests
}}
onError={(error) => setError(error)}

Check warning on line 77 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L77

Added line #L77 was not covered by tests
onCancel={() => {}}
DropZoneProps={dropZoneProps}
/>
<Typography variant="body2" color="error">
{error}
</Typography>
</DialogContent>
<DialogActions>
<LoadingButton
loading={isUploading}
disabled={isDisabled}
onClick={() => handleUpload()}

Check warning on line 89 in app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/dialog/attachments/FileUploadSingleItemDialog.tsx#L89

Added line #L89 was not covered by tests
color="primary"
variant="contained"
autoFocus>
{uploadButtonLabel}
</LoadingButton>
<Button onClick={onClose} color="primary" variant="outlined" disabled={isUploading}>
Close
</Button>
</DialogActions>
</Dialog>
);
};
Loading
Loading