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

UI update error reporting #34

Merged
merged 9 commits into from
Apr 29, 2024
2 changes: 2 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

package-lock.json
21,739 changes: 0 additions & 21,739 deletions frontend/package-lock.json

This file was deleted.

65 changes: 44 additions & 21 deletions frontend/src/components/Analysis/Analysis.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
Box, Grid, Button, Tab, Tabs, Typography, CircularProgress,
} from '@mui/material';
import { Container } from '@mui/system';
import CancelIcon from '@mui/icons-material/Cancel';
import ReactModal from 'react-modal';
import Cookies from 'universal-cookie';
import { FileUploader } from 'react-drag-drop-files';
Expand All @@ -27,6 +26,7 @@ export default function Analysis() {
const user = cookies.get('user');

const [value, setValue] = useState(0);
const [uploadSuccess, setUploadSuccess] = useState(null);

const [isOpen, setIsOpen] = useState(false);

Expand All @@ -41,6 +41,8 @@ export default function Analysis() {
const [rulesetDescription, setRulesetDescription] = useState('');
const [coverImageDir, setCoverImageDir] = useState('');

const [file, setFile] = useState(null);

useEffect(() => {
console.log('analysis', analysisId, typeof analysisId);
if (analysisId !== undefined && analysisId !== null
Expand Down Expand Up @@ -72,27 +74,40 @@ export default function Analysis() {

const closeModal = () => {
setIsOpen(false);
setUploadSuccess('emptyDisplay');
};

const openModal = () => {
setIsOpen(true);
};

const fileTypes = ['ZIP', 'tar.gz'];

const [file, setFile] = useState(null);
// lmao, you can't use "tar.gz", only "gz", anything after the last "." works
const fileTypes = ['ZIP', 'GZ'];

const uploadFile = (fileObject) => {
setFile(fileObject);
};

const handleUpload = () => {
// Used for side effect of uploading file
// eslint-disable-next-line no-unused-vars
const response = AnalysisService.uploadAlgorithm(analysisId, user.token, file);
closeModal();
const handleUpload = async () => {
try {
const response = await AnalysisService.uploadAlgorithm(analysisId, user.token, file);
console.log('response:', response);
if (response.status === 200) {
setUploadSuccess(true);
setFile(null);
} else {
setUploadSuccess(false);
}
} catch (errorCode) {
console.error('Upload failed:', errorCode);
setUploadSuccess(false);
}
};

const handleActive = () => file !== null;

const handleClear = () => setFile(null);

const handleChange = (event, newValue) => {
setValue(newValue);
};
Expand Down Expand Up @@ -200,6 +215,7 @@ export default function Analysis() {
}
</TabPanel>
{/*
Disabled until discussions properly implemented
<TabPanel value={value} index={5}>
{user === undefined || user == null
? <BlurryPage />
Expand Down Expand Up @@ -233,16 +249,7 @@ export default function Analysis() {
</Typography>
</Grid>
<Grid item xs={1}>
<CancelIcon
sx={{
'&:hover': {
color: '#ADD8E6',
cursor: 'pointer',
},
color: '#18A0FB',
}}
onClick={() => closeModal()}
/>
<Button onClick={closeModal}>Exit</Button>
</Grid>
</Grid>
<Box sx={{ marginTop: 2, marginBottom: 2 }}>
Expand All @@ -254,9 +261,25 @@ export default function Analysis() {
/>
</Box>
<Typography sx={{ marginLeft: 20 }} color="gray" variant="body1">
{file ? `File name: ${file.name}` : 'No files uploaded yet.'}
{file ? `File name: ${file.name}` : 'No files staged for upload yet.'}
</Typography>
{uploadSuccess === true && (
<Typography color="green" variant="body1">
Upload Successful! Please check your developer page for the status of
your upload, or upload another file.
</Typography>
)}
{uploadSuccess === false && (
<Typography color="red" variant="body1">
Upload failed. Please reload the page and try again. If you continue
to receive issues with the upload, please file an issue at our github page,
{' '}
<a href="https://github.com/slacgismo/pv-validation-hub">https://github.com/slacgismo/pv-validation-hub</a>
.
</Typography>
<Button variant="contained" onClick={handleUpload}>Upload</Button>
)}
<Button disabled={!handleActive()} variant="contained" onClick={handleUpload}>Upload</Button>
<Button disabled={!handleActive()} variant="contained" onClick={handleClear}>Clear</Button>
</Box>
</ReactModal>
</Container>
Expand Down
26 changes: 22 additions & 4 deletions frontend/src/components/Developer/Mainpage/mainpage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import ErrorIcon from '@mui/icons-material/Error';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import QueryBuilderIcon from '@mui/icons-material/QueryBuilder';
import DoneIcon from '@mui/icons-material/Done';
import Checkbox from '@mui/material/Checkbox';
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import Toolbar from '@mui/material/Toolbar';
import Grid from '@mui/material/Grid';
import SummarizeIcon from '@mui/icons-material/Summarize';
import QueryBuilderIcon from '@mui/icons-material/QueryBuilder';
import DoneIcon from '@mui/icons-material/Done';
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';

Expand Down Expand Up @@ -54,7 +56,7 @@ export default function DeveloperHome() {
handler: () => { handleNavClick('home'); },
},
{
title: 'Available Analyses',
title: 'Request Logs',
icon: <AssessmentIcon />,
handler: () => {},
},
Expand Down Expand Up @@ -115,6 +117,22 @@ function Home({ onClick }) {
fetchSubmissions();
}, []);

const getIcon = (status) => {
console.log(status);
switch (status) {
case 'submitted':
return <CheckCircleOutlineIcon />;
case 'running':
return <QueryBuilderIcon />;
case 'failed':
return <ErrorIcon />;
case 'finished':
return <DoneIcon />;
default:
return null;
}
};

return (
<List sx={{ width: '100%', bgcolor: 'background.paper' }}>
{submissions.sort(
Expand All @@ -134,7 +152,7 @@ function Home({ onClick }) {
/>
</ListItemIcon>
<ListItemIcon>
{submission.status === 'finished' ? <DoneIcon /> : <QueryBuilderIcon />}
{getIcon(submission.status)}
</ListItemIcon>
<ListItemText id={labelId} primary={`Submission ${submission.submission_id}`} />
<ListItemIcon onClick={() => onClick(submission.submission_id)}>
Expand Down
61 changes: 43 additions & 18 deletions frontend/src/components/Developer/Report/report.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,42 @@ import SubmissionService from '../../../services/submission_service.js';
export default function SubmissionReport({ submissionId }) {
const [imageUrls, setImageUrls] = useState([]);
const [errorData, setErrorData] = useState([]);
const [displayErrorDetails, setDisplayErrorDetails] = useState(false);

useEffect(() => {
const fetchSubmissionResults = async () => {
const fetchSubmissionErrors = async () => {
try {
const result = await SubmissionService.getSubmissionResults(submissionId);
const errors = await SubmissionService.getSubmissionErrors(submissionId);
setErrorData(errors);
console.log('Error data:', errors);
if (errors.length === 0) {
setErrorData({ error_rate: '0%' });
setDisplayErrorDetails(false);
} else if (errors.length > 0) {
let tempErrorData = errors[0];
if (tempErrorData.error_type.toLowerCase().includes('operation'.toLowerCase())
|| tempErrorData.error_type.toLowerCase().includes('wrapper'.toLowerCase())
|| tempErrorData.error_type.toLowerCase().includes('worker'.toLowerCase())) {
tempErrorData = { ...tempErrorData, error_rate: 'N/A' };
}
setErrorData(tempErrorData);
setDisplayErrorDetails(true);
}
} catch (error) {
console.error('Error fetching submission results:', error);
}
};

const fetchSubmissionResults = async () => {
try {
const result = await SubmissionService.getSubmissionResults(submissionId);
setImageUrls(result.file_urls);
} catch (error) {
console.error('Error fetching submission results:', error);
}
};

fetchSubmissionResults();
fetchSubmissionErrors();
}, [submissionId]);

return (
Expand All @@ -39,22 +60,26 @@ export default function SubmissionReport({ submissionId }) {
{' '}
{errorData.error_rate}
</Typography>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Error Code:
{' '}
{errorData.error_rate}
</Typography>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Error Type:
{' '}
{errorData.error_rate}
</Typography>
{displayErrorDetails && (
<>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Error Code:
{' '}
{errorData.error_code}
</Typography>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Error Type:
{' '}
{errorData.error_type}
</Typography>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Error Message:
{' '}
{errorData.error_message}
</Typography>
</>
)}
</AppBar>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Error Message: WHYY
{' '}
{errorData.error_rate}
</Typography>
</Box>

<List>
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/services/analysis_service.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const AnalysisService = {
},
uploadAlgorithm(analysisId, token, file) {
if (analysisId !== null && analysisId !== undefined
&& file !== null && file !== undefined) {
&& file !== null && file !== undefined) {
const url = `/submissions/analysis/${analysisId}/submission`;
const formData = new FormData();

Expand All @@ -44,13 +44,15 @@ const AnalysisService = {
formData.append('algorithm', file);
formData.append('analysis_id', analysisId);

client.post(url, formData, {
// Return the Promise from client.post
return client.post(url, formData, {
Accept: '*/*',
'content-type': 'multipart/form-data',
}).then((response) => {
console.log(response);
});
}

// If analysisId or file is null or undefined, return a rejected Promise
return Promise.reject(new Error('analysisId and file cannot be null or undefined'));
},
};

Expand Down
Loading
Loading