added script to generate open api scheme automatically - execute with npm run watch:openapi
This commit is contained in:
parent
501d09e6aa
commit
1fa61f0e78
@ -79,17 +79,20 @@ async def validate_cell(data: dict):
|
||||
|
||||
importer = SampleSpreadsheetImporter()
|
||||
|
||||
# Determine the expected type based on column name
|
||||
# Ensure we've cleaned the value before validation
|
||||
expected_type = importer.get_expected_type(col_name)
|
||||
|
||||
# Clean and validate the cell value
|
||||
cleaned_value = importer._clean_value(value, expected_type)
|
||||
|
||||
logger.info(f"Validating cell: row {row_num}, column {col_name}, value {cleaned_value}")
|
||||
|
||||
try:
|
||||
# Validate the cleaned value using the SpreadsheetModel (Pydantic validation)
|
||||
SpreadsheetModel(**{col_name: cleaned_value})
|
||||
# Construct a dictionary with the expected format for validation
|
||||
validation_data = {col_name: cleaned_value}
|
||||
SpreadsheetModel(**validation_data)
|
||||
logger.info(f"Validation succeeded for row {row_num}, column {col_name}")
|
||||
return {"is_valid": True, "message": ""}
|
||||
except ValidationError as e:
|
||||
# If validation fails, return the first error message
|
||||
# Extract the first error message
|
||||
message = e.errors()[0]['msg']
|
||||
logger.error(f"Validation failed for row {row_num}, column {col_name}: {message}")
|
||||
return {"is_valid": False, "message": message}
|
@ -1,41 +1,103 @@
|
||||
// fetch-openapi.js
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
const { exec } = require('child_process');
|
||||
// fetch-and-generate-openapi.js
|
||||
import fs from 'fs';
|
||||
import http from 'http';
|
||||
import { exec } from 'child_process';
|
||||
import chokidar from 'chokidar';
|
||||
import path from 'path';
|
||||
import util from 'util';
|
||||
|
||||
// FastAPI server URL (make sure your server is running locally at this address)
|
||||
const OPENAPI_URL = 'http://127.0.0.1:8000/openapi.json';
|
||||
const SCHEMA_PATH = path.resolve('./src/openapi.json');
|
||||
const OUTPUT_DIRECTORY = path.resolve('./openapi');
|
||||
|
||||
// Path to save the OpenAPI schema file and TypeScript types
|
||||
const SCHEMA_PATH = './src/schema/openapi.json';
|
||||
const TYPES_PATH = './src/types/api-types.ts';
|
||||
console.log(`Using SCHEMA_PATH: ${SCHEMA_PATH}`);
|
||||
console.log(`Using OUTPUT_DIRECTORY: ${OUTPUT_DIRECTORY}`);
|
||||
|
||||
const execPromisified = util.promisify(exec);
|
||||
|
||||
let isGenerating = false;
|
||||
const debounceDelay = 500; // 500ms debounce
|
||||
|
||||
function debounce(func, delay) {
|
||||
let timer;
|
||||
return (...args) => {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
func.apply(this, args);
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchAndGenerate() {
|
||||
if (isGenerating) {
|
||||
console.log("⚠️ Generation is already running.");
|
||||
return;
|
||||
}
|
||||
isGenerating = true;
|
||||
|
||||
console.log("🚀 Fetching OpenAPI schema...");
|
||||
|
||||
try {
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
http.get(OPENAPI_URL, resolve).on('error', reject);
|
||||
});
|
||||
|
||||
// Fetch OpenAPI JSON
|
||||
https.get(OPENAPI_URL, (res) => {
|
||||
let data = '';
|
||||
|
||||
res.on('data', chunk => {
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
// Save the fetched OpenAPI JSON to a file
|
||||
res.on('end', async () => {
|
||||
try {
|
||||
fs.writeFileSync(SCHEMA_PATH, data, 'utf8');
|
||||
console.log(`✅ OpenAPI schema saved to ${SCHEMA_PATH}`);
|
||||
} catch (writeError) {
|
||||
console.error(`❌ Error saving OpenAPI schema: ${writeError}`);
|
||||
isGenerating = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Run openapi-typescript to generate TypeScript types
|
||||
exec(`npx openapi-typescript ${SCHEMA_PATH} --output ${TYPES_PATH}`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(`❌ Error generating types: ${error}`);
|
||||
return;
|
||||
console.log("🧼 Cleaning output directory...");
|
||||
try {
|
||||
await fs.promises.rm(OUTPUT_DIRECTORY, { recursive: true, force: true });
|
||||
console.log(`✅ Output directory cleaned at ${OUTPUT_DIRECTORY}`);
|
||||
|
||||
// Verify directory removal
|
||||
if (fs.existsSync(OUTPUT_DIRECTORY)) {
|
||||
console.error(`❌ Output directory still exists: ${OUTPUT_DIRECTORY}`);
|
||||
} else {
|
||||
console.log(`✅ Confirmed removal of ${OUTPUT_DIRECTORY}`);
|
||||
}
|
||||
|
||||
const command = `npx openapi -i ${SCHEMA_PATH} -o ${OUTPUT_DIRECTORY}`;
|
||||
console.log(`Executing debug command: ${command}`);
|
||||
|
||||
const { stdout, stderr } = await execPromisified(command);
|
||||
console.log("🔍 Inside exec callback");
|
||||
if (stderr) {
|
||||
console.error(`⚠️ stderr: ${stderr}`);
|
||||
return;
|
||||
console.error(`⚠️ stderr while generating services: ${stderr}`);
|
||||
} else {
|
||||
console.log(`✅ Command executed successfully, output:\n${stdout}`);
|
||||
}
|
||||
console.log(`✅ TypeScript types generated at ${TYPES_PATH}`);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error cleaning or executing command: ${error}`);
|
||||
}
|
||||
|
||||
isGenerating = false;
|
||||
});
|
||||
});
|
||||
}).on("error", (err) => {
|
||||
console.error("Error fetching OpenAPI schema: " + err.message);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Error fetching OpenAPI schema: ' + error.message);
|
||||
isGenerating = false;
|
||||
}
|
||||
}
|
||||
|
||||
const backendDirectory = '/Users/gotthardg/PycharmProjects/heidi-v2/backend/';
|
||||
console.log(`👀 Watching for changes in ${backendDirectory}`);
|
||||
const watcher = chokidar.watch(backendDirectory, { persistent: true, ignored: [SCHEMA_PATH, OUTPUT_DIRECTORY] });
|
||||
|
||||
watcher
|
||||
.on('add', debounce(fetchAndGenerate, debounceDelay))
|
||||
.on('change', debounce(fetchAndGenerate, debounceDelay))
|
||||
.on('unlink', debounce(fetchAndGenerate, debounceDelay));
|
||||
|
||||
console.log(`👀 Watching for changes in ${backendDirectory}`);
|
459
frontend/package-lock.json
generated
459
frontend/package-lock.json
generated
@ -21,6 +21,7 @@
|
||||
"@mui/icons-material": "^6.1.5",
|
||||
"@mui/material": "^6.1.5",
|
||||
"axios": "^1.7.7",
|
||||
"chokidar": "^4.0.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"openapi-typescript-codegen": "^0.29.0",
|
||||
"react": "^18.3.1",
|
||||
@ -28,7 +29,8 @@
|
||||
"react-dom": "^18.3.1",
|
||||
"react-qr-code": "^2.0.15",
|
||||
"react-router-dom": "^6.27.0",
|
||||
"react-scheduler": "^0.1.0"
|
||||
"react-scheduler": "^0.1.0",
|
||||
"rimraf": "^5.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.11.1",
|
||||
@ -1200,6 +1202,23 @@
|
||||
"url": "https://github.com/sponsors/nzakas"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^5.1.2",
|
||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||
"strip-ansi": "^7.0.1",
|
||||
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
|
||||
"wrap-ansi": "^8.1.0",
|
||||
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
@ -1592,6 +1611,16 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
@ -2596,6 +2625,18 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
@ -2661,8 +2702,7 @@
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
@ -2791,6 +2831,21 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
|
||||
"integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
@ -2869,7 +2924,6 @@
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
@ -2981,11 +3035,23 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.43",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.43.tgz",
|
||||
"integrity": "sha512-NxnmFBHDl5Sachd2P46O7UJiMaMHMLSofoIWVJq3mj8NJgG0umiSeljAVP9lGzjI0UDLJJ5jjoGjcrB8RSbjLQ=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
@ -3448,6 +3514,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
||||
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
||||
@ -3505,6 +3587,26 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
@ -3517,6 +3619,30 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/globalize": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz",
|
||||
@ -3706,6 +3832,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
@ -3730,8 +3865,22 @@
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-levenshtein": {
|
||||
"version": "1.1.6",
|
||||
@ -3990,6 +4139,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
@ -4202,6 +4360,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@ -4252,7 +4416,6 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -4262,6 +4425,28 @@
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
@ -4569,6 +4754,19 @@
|
||||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
|
||||
"integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||
@ -4618,6 +4816,21 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "5.0.10",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
|
||||
"integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^10.3.7"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "dist/esm/bin.mjs"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
|
||||
@ -4701,7 +4914,6 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
@ -4713,11 +4925,22 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/snake-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
||||
@ -4746,6 +4969,102 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width-cjs": {
|
||||
"name": "string-width",
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width-cjs/node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width-cjs/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string-width-cjs/node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi-cjs": {
|
||||
"name": "strip-ansi",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
@ -5128,7 +5447,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
@ -5153,6 +5471,127 @@
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs": {
|
||||
"name": "wrap-ansi",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
@ -8,7 +8,7 @@
|
||||
"build": "node_modules/.bin/tsc -b && vite build",
|
||||
"lint": "node_modules/.bin/eslint .",
|
||||
"preview": "node_modules/.bin/vite preview",
|
||||
"fetch:types": "node fetch-openapi.js"
|
||||
"watch:openapi": "node fetch-openapi.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aldabil/react-scheduler": "^2.9.5",
|
||||
@ -24,6 +24,7 @@
|
||||
"@mui/icons-material": "^6.1.5",
|
||||
"@mui/material": "^6.1.5",
|
||||
"axios": "^1.7.7",
|
||||
"chokidar": "^4.0.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"openapi-typescript-codegen": "^0.29.0",
|
||||
"react": "^18.3.1",
|
||||
@ -31,7 +32,8 @@
|
||||
"react-dom": "^18.3.1",
|
||||
"react-qr-code": "^2.0.15",
|
||||
"react-router-dom": "^6.27.0",
|
||||
"react-scheduler": "^0.1.0"
|
||||
"react-scheduler": "^0.1.0",
|
||||
"rimraf": "^5.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.11.1",
|
||||
|
@ -9,14 +9,15 @@ import {
|
||||
Paper,
|
||||
Tooltip,
|
||||
TextField,
|
||||
Typography
|
||||
Typography,
|
||||
Button
|
||||
} from '@mui/material';
|
||||
import { SpreadsheetService } from '../../openapi'; // Ensure correct path
|
||||
import { SpreadsheetService } from '../../openapi';
|
||||
|
||||
const SpreadsheetTable = ({ raw_data, errors, headers, setRawData }) => {
|
||||
const [localErrors, setLocalErrors] = useState(errors || []);
|
||||
const [editingCell, setEditingCell] = useState({});
|
||||
|
||||
// Create an error map to easily lookup errors by row and column
|
||||
const generateErrorMap = (errorsList) => {
|
||||
const errorMap = new Map();
|
||||
if (Array.isArray(errorsList)) {
|
||||
@ -30,57 +31,105 @@ const SpreadsheetTable = ({ raw_data, errors, headers, setRawData }) => {
|
||||
|
||||
const errorMap = generateErrorMap(localErrors);
|
||||
|
||||
// Handle cell edit
|
||||
const handleCellEdit = async (rowIndex, colIndex, newValue) => {
|
||||
const handleCellEdit = async (rowIndex, colIndex) => {
|
||||
const updatedRawData = [...raw_data];
|
||||
const columnName = headers[colIndex];
|
||||
const currentRow = updatedRawData[rowIndex];
|
||||
const newValue = editingCell[`${rowIndex}-${colIndex}`];
|
||||
|
||||
// Assuming data is an array and we need to set by index
|
||||
if (newValue === undefined) return;
|
||||
|
||||
console.log(`Editing cell at row ${rowIndex}, column ${colIndex}: new value: ${newValue}`);
|
||||
|
||||
// Ensure currentRow.data exists before accessing it
|
||||
if (!currentRow.data) {
|
||||
currentRow.data = [];
|
||||
}
|
||||
|
||||
// Update the relevant cell value
|
||||
currentRow.data[colIndex] = newValue;
|
||||
|
||||
setEditingCell(prev => {
|
||||
const updated = { ...prev };
|
||||
delete updated[`${rowIndex}-${colIndex}`];
|
||||
return updated;
|
||||
});
|
||||
|
||||
try {
|
||||
// Send a request to validate the cell
|
||||
const response = await SpreadsheetService.validateCellValidateCellPost({
|
||||
row: currentRow.row_num, // Use row_num directly from the current row
|
||||
row: currentRow.row_num,
|
||||
column: columnName,
|
||||
value: newValue
|
||||
});
|
||||
|
||||
// Log the response to debug the structure
|
||||
console.log('Validation response:', response);
|
||||
|
||||
// Check if response is valid and structured as expected
|
||||
if (response.data && response.data.is_valid !== undefined) {
|
||||
if (response.data.is_valid) {
|
||||
// Remove error if validation passes
|
||||
const updatedErrors = localErrors.filter(error => !(error.row === currentRow.row_num && error.cell === colIndex));
|
||||
if (response.is_valid !== undefined) {
|
||||
if (response.is_valid) {
|
||||
// Remove error if it passes validation
|
||||
const updatedErrors = localErrors.filter(
|
||||
error => !(error.row === currentRow.row_num && error.cell === colIndex)
|
||||
);
|
||||
setLocalErrors(updatedErrors);
|
||||
} else {
|
||||
// Add error if validation fails
|
||||
const updatedErrors = [...localErrors, { row: currentRow.row_num, cell: colIndex, message: response.data.message || 'Invalid value.' }];
|
||||
const updatedErrors = [
|
||||
...localErrors,
|
||||
{ row: currentRow.row_num, cell: colIndex, message: response.message || 'Invalid value.' }
|
||||
];
|
||||
setLocalErrors(updatedErrors);
|
||||
}
|
||||
} else {
|
||||
// Handle unexpected response format
|
||||
console.error('Unexpected response structure:', response);
|
||||
}
|
||||
|
||||
// Update the raw data
|
||||
setRawData(updatedRawData);
|
||||
} catch (error) {
|
||||
console.error('Validation failed:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Hook to log and monitor changes in raw data, errors, and headers
|
||||
const handleCellBlur = (rowIndex, colIndex) => {
|
||||
handleCellEdit(rowIndex, colIndex);
|
||||
};
|
||||
|
||||
const validateBeforeSubmit = () => {
|
||||
let isValid = true;
|
||||
raw_data.forEach((row, rowIndex) => {
|
||||
headers.forEach((header, colIndex) => {
|
||||
const key = `${row.row_num}-${header}`;
|
||||
const newValue = editingCell[`${rowIndex}-${colIndex}`];
|
||||
|
||||
if (newValue !== undefined) {
|
||||
// Perform cell validation on each edit
|
||||
handleCellEdit(rowIndex, colIndex);
|
||||
}
|
||||
|
||||
const errorMessage = errorMap.get(key);
|
||||
if (errorMessage) {
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const isValid = validateBeforeSubmit();
|
||||
|
||||
if (isValid) {
|
||||
console.log('All data is valid. Proceeding with submission...');
|
||||
// Use validated data to populate the database
|
||||
// You can call a dedicated API endpoint to process the entire dataset as needed
|
||||
} else {
|
||||
console.log('There are validation errors in the dataset. Please correct them before submission.');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log('Raw data:', raw_data);
|
||||
console.log('Errors:', errors);
|
||||
console.log('Errors:', localErrors);
|
||||
console.log('Headers:', headers);
|
||||
}, [raw_data, errors, headers]);
|
||||
}, [raw_data, localErrors, headers]);
|
||||
|
||||
// Ensure data is loaded before rendering
|
||||
if (!raw_data || !headers) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
@ -101,35 +150,30 @@ const SpreadsheetTable = ({ raw_data, errors, headers, setRawData }) => {
|
||||
{raw_data.map((row, rowIndex) => (
|
||||
<TableRow key={rowIndex}>
|
||||
{headers.map((header, colIndex) => {
|
||||
const key = `${row.row_num}-${header}`; // Key for error lookup should match row's row_num
|
||||
const key = `${row.row_num}-${header}`;
|
||||
const errorMessage = errorMap.get(key);
|
||||
const isInvalid = !!errorMessage; // Check if the cell has an error
|
||||
const cellValue = row.data[colIndex]; // Extract cell value via index
|
||||
const isInvalid = !!errorMessage;
|
||||
const cellValue = (row.data && row.data[colIndex]) || "";
|
||||
const editingValue = editingCell[`${rowIndex}-${colIndex}`];
|
||||
|
||||
return (
|
||||
<TableCell key={colIndex} align="center">
|
||||
{isInvalid ? (
|
||||
<Tooltip title={errorMessage} arrow>
|
||||
<Tooltip title={errorMessage || ""} arrow disableHoverListener={!isInvalid}>
|
||||
<TextField
|
||||
value={cellValue || ""} // Prevent null, fallback to empty string
|
||||
onChange={(e) => handleCellEdit(rowIndex, colIndex, e.target.value)}
|
||||
error={true} // Show red border if there's an error
|
||||
fullWidth
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root.Mui-error': {
|
||||
borderColor: 'red', // Apply red border for invalid cells
|
||||
},
|
||||
value={editingValue !== undefined ? editingValue : cellValue}
|
||||
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"
|
||||
/>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<TextField
|
||||
value={cellValue || ""}
|
||||
onChange={(e) => handleCellEdit(rowIndex, colIndex, e.target.value)}
|
||||
fullWidth
|
||||
disabled={true} // Disable valid cells so they cannot be edited
|
||||
/>
|
||||
)}
|
||||
</TableCell>
|
||||
);
|
||||
})}
|
||||
@ -137,6 +181,9 @@ const SpreadsheetTable = ({ raw_data, errors, headers, setRawData }) => {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Button variant="contained" color="primary" onClick={handleSubmit}>
|
||||
Submit
|
||||
</Button>
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user