Add column type mapping and enhance validation

Introduced a backend mapping for column expected types, improving validation and error handling. Updated UI to highlight default and corrected values, with additional detailed validation for data collection parameters.
This commit is contained in:
GotthardG
2025-01-07 15:45:08 +01:00
parent 54975b5919
commit 92306fcfa6
5 changed files with 503 additions and 401 deletions

View File

@ -79,16 +79,17 @@ const SpreadsheetTable = ({
const errorMap = generateErrorMap(localErrors);
useEffect(() => {
const initialNonEditableCells = new Set();
const updatedNonEditableCells = new Set();
raw_data.forEach((row, rowIndex) => {
headers.forEach((_, colIndex) => {
const key = `${row.row_num}-${headers[colIndex]}`;
if (!errorMap.has(key)) {
initialNonEditableCells.add(`${rowIndex}-${colIndex}`);
updatedNonEditableCells.add(`${rowIndex}-${colIndex}`);
}
});
});
setNonEditableCells(initialNonEditableCells);
setNonEditableCells(updatedNonEditableCells);
console.log("Recalculated nonEditableCells:", updatedNonEditableCells);
}, [raw_data, headers, errorMap]);
const handleCellEdit = async (rowIndex, colIndex) => {
@ -97,14 +98,15 @@ const SpreadsheetTable = ({
const currentRow = updatedRawData[rowIndex];
const newValue = editingCell[`${rowIndex}-${colIndex}`];
if (newValue === undefined) return;
if (newValue === undefined) return; // Ensure value is provided
// Prepare for validation request
if (!currentRow.data) {
currentRow.data = [];
}
currentRow.data[colIndex] = newValue;
// Reset editing state
setEditingCell((prev) => {
const updated = { ...prev };
delete updated[`${rowIndex}-${colIndex}`];
@ -115,27 +117,46 @@ const SpreadsheetTable = ({
const response = await SpreadsheetService.validateCellValidateCellPost({
row: currentRow.row_num,
column: columnName,
value: newValue
value: newValue,
});
if (response.is_valid !== undefined) {
if (response && response.is_valid !== undefined) {
if (response.is_valid) {
// Handle validation success (remove error)
const correctedValue = response.corrected_value ?? newValue;
currentRow.data[colIndex] = correctedValue;
updatedRawData[rowIndex] = currentRow;
setRawData(updatedRawData); // Update table data
// Remove error associated with this cell
const updatedErrors = localErrors.filter(
(error) => !(error.row === currentRow.row_num && error.cell === colIndex)
);
setLocalErrors(updatedErrors);
// Update non-editable state
setNonEditableCells((prev) => new Set([...prev, `${rowIndex}-${colIndex}`]));
} else {
// Handle validation failure (add error)
const errorMessage = response.message || "Invalid value.";
const newError = {
row: currentRow.row_num,
cell: colIndex,
message: errorMessage,
};
const updatedErrors = [
...localErrors,
{ row: currentRow.row_num, cell: colIndex, message: response.message || 'Invalid value.' }
...localErrors.filter((error) => !(error.row === newError.row && error.cell === newError.cell)), // Avoid duplicates
newError,
];
setLocalErrors(updatedErrors);
}
} else {
console.error("Unexpected response from backend:", response);
}
setRawData(updatedRawData);
} catch (error) {
console.error('Validation failed:', error);
console.error("Validation request failed:", error);
}
};
@ -431,46 +452,56 @@ const SpreadsheetTable = ({
{headers.map((header, colIndex) => {
const key = `${row.row_num}-${header}`;
const errorMessage = errorMap.get(key);
const isInvalid = !!errorMessage;
const cellValue = (row.data && row.data[colIndex]) || "";
const isInvalid = !!errorMap.get(`${row.row_num}-${headers[colIndex]}`);
const cellValue = row.data[colIndex];
const editingValue = editingCell[`${rowIndex}-${colIndex}`];
const isReadonly = !isInvalid;
const isDefaultAssigned = colIndex === 7 && row.default_set; // Directory column (index 7) and marked as default_set
const isReadonly = !isInvalid && editingCell[`${rowIndex}-${colIndex}`] === undefined;
const isCorrected = colIndex === 7 && row.corrected; // Corrected field exists and is true
const isDefaultAssigned = colIndex === 7 && row.default_set; // Default-assigned field exists and is true
return (
<TableCell
key={colIndex}
align="center"
style={{
backgroundColor: isDefaultAssigned ? "#e6fbe6" : "transparent", // Light green for default
color: isDefaultAssigned ? "#1b5e20" : "inherit", // Dark green text for default
backgroundColor:
colIndex === 7 && isDefaultAssigned
? "#e6fbe6" // Default value for "directory"
: colIndex === 7 && isCorrected
? "#fff8e1" // Corrected directory
: "transparent", // No highlight for other columns
color: colIndex === 7 && isDefaultAssigned
? "#1b5e20" // Dark green text for default
: "inherit", // Normal text
}}
>
<Tooltip title={errorMessage || ""} arrow disableHoverListener={!isInvalid}>
<Tooltip
title={
colIndex === 7 && isCorrected
? "Value corrected automatically by the system."
: errorMessage || "" // Show validation errors for other columns
}
arrow
disableHoverListener={colIndex !== 7 && !errorMessage}
>
{isInvalid ? (
<TextField
value={editingValue !== undefined ? editingValue : cellValue}
value={editingValue !== undefined ? editingValue : cellValue} // Ensure this reflects corrected value
onChange={(e) =>
setEditingCell({
...editingCell,
[`${rowIndex}-${colIndex}`]: e.target.value,
})
}
onKeyDown={(e) => {
if (e.key === "Enter") {
handleCellEdit(rowIndex, colIndex);
}
}}
onBlur={() => handleCellBlur(rowIndex, colIndex)}
error={isInvalid}
fullWidth
variant="outlined"
size="small"
disabled={isReadonly}
disabled={!isInvalid}
/>
) : (
cellValue
cellValue // This should reflect the updated 'raw_data'
)}
</Tooltip>
</TableCell>