added error recognition in spreadsheet
This commit is contained in:
43
frontend/src/components/SpreadsheetTable.tsx
Normal file
43
frontend/src/components/SpreadsheetTable.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Tooltip } from '@mui/material';
|
||||
|
||||
const SpreadsheetTable = ({ raw_data, errors }) => {
|
||||
const getErrorForCell = (rowIdx, colIdx) => {
|
||||
return errors.find(e => e.row === rowIdx && e.cell === colIdx);
|
||||
};
|
||||
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{raw_data.length > 0 && Object.keys(raw_data[0].data).map((col, colIdx) => (
|
||||
<TableCell key={colIdx}>{`Column ${colIdx + 1}`}</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{raw_data.map((rowItem, rowIndex) => (
|
||||
<TableRow key={rowIndex}>
|
||||
{Object.values(rowItem.data).map((cellValue, cellIndex) => {
|
||||
const cellError = getErrorForCell(rowItem.row_num, cellIndex);
|
||||
return (
|
||||
<TableCell
|
||||
key={cellIndex}
|
||||
style={{ backgroundColor: cellError ? 'red' : 'white' }}
|
||||
>
|
||||
<Tooltip title={cellError ? cellError.message : ''} arrow>
|
||||
<span>{cellValue}</span>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
)
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default SpreadsheetTable;
|
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
@ -8,6 +8,7 @@ import {
|
||||
Typography,
|
||||
IconButton,
|
||||
Box,
|
||||
Tooltip
|
||||
} from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
@ -15,6 +16,7 @@ import UploadFileIcon from '@mui/icons-material/UploadFile';
|
||||
import logo from '../assets/Heidi-logo.png';
|
||||
import { OpenAPI, SpreadsheetService } from '../../openapi';
|
||||
import type { Body_upload_file_upload_post } from '../../openapi/models/Body_upload_file_upload_post';
|
||||
import SpreadsheetTable from './SpreadsheetTable'; // Ensure the path is correct
|
||||
|
||||
interface UploadDialogProps {
|
||||
open: boolean;
|
||||
@ -24,11 +26,15 @@ interface UploadDialogProps {
|
||||
const UploadDialog: React.FC<UploadDialogProps> = ({ open, onClose }) => {
|
||||
const [uploadError, setUploadError] = useState<string | null>(null);
|
||||
const [fileSummary, setFileSummary] = useState<{
|
||||
data: any[];
|
||||
errors: { row: number, cell: number, value: any, message: string }[];
|
||||
raw_data: { row_num: number, data: any[] }[];
|
||||
dewars_count: number;
|
||||
dewars: string[];
|
||||
pucks_count: number;
|
||||
pucks: string[];
|
||||
samples_count: string[];
|
||||
samples_count: number;
|
||||
samples: string[];
|
||||
} | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@ -41,30 +47,21 @@ const UploadDialog: React.FC<UploadDialogProps> = ({ open, onClose }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the previous state
|
||||
setUploadError(null);
|
||||
setFileSummary(null);
|
||||
|
||||
// Example file type check: only allow .xlsx files
|
||||
if (!file.name.endsWith('.xlsx')) {
|
||||
setUploadError('Invalid file format. Please upload an .xlsx file.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the formData object compliant with the type definition
|
||||
const formData: Body_upload_file_upload_post = {
|
||||
file: file, // TypeScript understands that file is a Blob
|
||||
file: file,
|
||||
} as Body_upload_file_upload_post;
|
||||
|
||||
try {
|
||||
// Use the generated OpenAPI client UploadService method
|
||||
const response = await SpreadsheetService.uploadFileUploadPost(formData);
|
||||
|
||||
console.log('File summary response from backend:', response);
|
||||
console.log('Dewars:', response.dewars);
|
||||
console.log('Pucks:', response.pucks);
|
||||
console.log('Samples:', response.samples);
|
||||
|
||||
setFileSummary(response);
|
||||
} catch (error) {
|
||||
console.error('File upload error:', error);
|
||||
@ -72,6 +69,13 @@ const UploadDialog: React.FC<UploadDialogProps> = ({ open, onClose }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleRawDataChange = (updatedRawData) => {
|
||||
setFileSummary((prevSummary) => ({
|
||||
...prevSummary,
|
||||
raw_data: updatedRawData
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose} fullWidth maxWidth="sm">
|
||||
<DialogTitle>
|
||||
@ -85,8 +89,8 @@ const UploadDialog: React.FC<UploadDialogProps> = ({ open, onClose }) => {
|
||||
<DialogContent dividers>
|
||||
<Box display="flex" flexDirection="column" alignItems="center" mb={2}>
|
||||
<img src={logo} alt="Logo" style={{ width: 200, marginBottom: 16 }} />
|
||||
<Typography variant="subtitle1">Latest Spreadsheet Template Version 7</Typography>
|
||||
<Typography variant="body2" color="textSecondary">Last update: November 6, 2024</Typography>
|
||||
<Typography variant="subtitle1">Latest Spreadsheet Template Version 6</Typography>
|
||||
<Typography variant="body2" color="textSecondary">Last update: October 18, 2024</Typography>
|
||||
<Button variant="outlined" startIcon={<DownloadIcon />} href="http://127.0.0.1:8000/download-template" download sx={{ mt: 1 }}>
|
||||
Download XLSX
|
||||
</Button>
|
||||
@ -112,18 +116,14 @@ const UploadDialog: React.FC<UploadDialogProps> = ({ open, onClose }) => {
|
||||
<Typography variant="body1">
|
||||
<strong>File Summary:</strong>
|
||||
</Typography>
|
||||
<SpreadsheetTable
|
||||
raw_data={fileSummary.raw_data}
|
||||
errors={fileSummary.errors}
|
||||
setRawData={handleRawDataChange}
|
||||
/>
|
||||
<Typography>Dewars: {fileSummary.dewars_count}</Typography>
|
||||
<Typography>Pucks: {fileSummary.pucks_count}</Typography>
|
||||
<Typography>Samples: {fileSummary.samples_count}</Typography>
|
||||
<Typography variant="body2">
|
||||
<strong>Dewar Names:</strong> {Array.isArray(fileSummary.dewars) ? fileSummary.dewars.join(', ') : 'N/A'}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
<strong>Puck Names:</strong> {Array.isArray(fileSummary.pucks) ? fileSummary.pucks.join(', ') : 'N/A'}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
<strong>Sample Names:</strong> {Array.isArray(fileSummary.samples) ? fileSummary.samples.join(', ') : 'N/A'}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
Reference in New Issue
Block a user