From 977e7511ec8e9836dcda4bb53bb8562343654cbb Mon Sep 17 00:00:00 2001 From: Joshua Ramon Enslin Date: Wed, 18 Jan 2023 01:31:36 +0100 Subject: [PATCH] Set hard-coded delimiter (;) and escape char (") and better display parsing errors --- public/assets/js/csvxmlV2.js | 16 +++++- public/assets/js/csvxmlV2.min.js | 83 +------------------------------- public/index.htm | 4 +- scripts/compile.php | 2 +- 4 files changed, 18 insertions(+), 87 deletions(-) diff --git a/public/assets/js/csvxmlV2.js b/public/assets/js/csvxmlV2.js index 43943c3..1372b67 100644 --- a/public/assets/js/csvxmlV2.js +++ b/public/assets/js/csvxmlV2.js @@ -24,10 +24,22 @@ class CsvxmlValidator { this.fieldList = Object.freeze(fieldList); - const data = Papa.parse(csvRaw.trim(), {header: true}); + const data = Papa.parse(csvRaw.trim(), { + delimiter: ";", // auto-detect + escapeChar: '"', + skipEmptyLines: true, + header: true, + }); if (data.errors.length !== 0) { - window.alert(data.errors); + console.log("Errors encountered: "); + console.error(data.errors); + + let msg = ''; + for (let err of data.errors) { + msg += err.type + ': ' + err.message + "\n"; + } + window.alert(msg); } let toValidate = data.data; diff --git a/public/assets/js/csvxmlV2.min.js b/public/assets/js/csvxmlV2.min.js index c5b9160..cf48a89 100644 --- a/public/assets/js/csvxmlV2.min.js +++ b/public/assets/js/csvxmlV2.min.js @@ -1,82 +1 @@ -"use strict";if('serviceWorker'in navigator){console.log("Registering service worker");navigator.serviceWorker.register('/sw.js');} -class CsvxmlValidator{fieldList;toValidate;errors;constructor(fieldList,csvRaw){this.errors={parsing:[],mandatoryTags:[],duplicateInvNos:[],dependentColumns:[],controlledLists:[],mainImageResource:[],};this.fieldList=Object.freeze(fieldList);const data=Papa.parse(csvRaw.trim(),{header:true});if(data.errors.length!==0){window.alert(data.errors);} -let toValidate=data.data;this.toValidate=toValidate;if(toValidate.length===0){alert("Error: No lines of content identified");} -this.validate();} -validate(){this.validateMandatoryTagsPresent();this.validateInvalidTagsPresent();this.checkDuplicateInvNos();this.checkDependentColumns();this.checkControlledLists();} -validateMandatoryTagsPresent(){let mandatoryFields=[];for(let fieldName in this.fieldList){if(this.fieldList[fieldName].required===true){mandatoryFields.push(fieldName);}} -console.log(this.toValidate);let lineCounter=1;for(let line of this.toValidate){for(let mandatoryField of mandatoryFields){if(line[mandatoryField]===undefined||line[mandatoryField]===null||line[mandatoryField]===''){this.errors.mandatoryTags.push("Missing or empty mandatory tag "+mandatoryField+" on line "+lineCounter);}} -lineCounter++;}} -validateInvalidTagsPresent(){const headers=Object.keys(this.toValidate[0]);for(let header of headers){if(this.fieldList[header]===undefined){this.errors.parsing.push("Invalid column "+header+" detected! Please remove this column or use the appropriate name!");}}} -checkDuplicateInvNos(){let invNoEncountered=[];let lineCounter=1;for(let line of this.toValidate){if(invNoEncountered.includes(line.inventory_number)){this.errors.duplicateInvNos.push("Duplicate inventory number "+line.inventory_number+" on line "+lineCounter);} -invNoEncountered.push(line.inventory_number);lineCounter++;}} -checkDependentColumns(){const headers=Object.keys(this.toValidate[0]);for(let header of headers){if(this.fieldList[header]===undefined||this.fieldList[header].dependsOn===undefined||this.fieldList[header].dependsOn===null)continue;let dependencies=this.fieldList[header].dependsOn;for(let dep of dependencies){if(headers.includes(dep)===false){this.errors.dependentColumns.push("Dependency issue at column "+header+": Corresponding column "+dep+" is missing");}}} -let lineCounter=1;for(let line of this.toValidate){for(let fieldName in line){if(line[fieldName]==='')continue;if(this.fieldList[fieldName]===undefined)continue;const dependencies=this.fieldList[fieldName].dependsOn;if(dependencies===undefined)continue;for(let dependency of dependencies){if(line[dependency]===''){this.errors.dependentColumns.push("Dependency issue at column "+fieldName+": Corresponding column "+dependency+" is empty");}}} -lineCounter++;}} -checkControlledLists(){let lineCounter=1;for(let line of this.toValidate){for(let fieldName in line){if(this.fieldList[fieldName]===undefined){console.log("Undefined but requested field "+fieldName);continue;} -const allowedValues=this.fieldList[fieldName].allowedValues;if(allowedValues===undefined||allowedValues===null)continue;if(Object.values(allowedValues).length===0||Object.values(allowedValues).includes(line[fieldName])){continue;} -if(line[fieldName]==='')continue;this.errors.controlledLists.push("Disallowed value used for column "+fieldName+" at line "+lineCounter+" (Allowed values are: "+Object.values(allowedValues).join(", ")+"; current value is "+line[fieldName]+")");} -lineCounter++;}} -checkMainImageResource(){} -isValid(){for(let errorClass in this.errors){if(this.errors[errorClass].length!==0)return false;} -return true;} -generateXml(){let output=[];let xmlDoc=document.implementation.createDocument(null,"record");for(let line of this.toValidate){let root=xmlDoc.createElement("record");for(let fieldName in line){const elem=xmlDoc.createElement(fieldName);elem.textContent=line[fieldName];root.appendChild(elem);} -output.push(root)} -return output;}} -class CsvxmlTooltip{static getDirection(e,elem){if(window.innerHeight - + @@ -27,7 +27,7 @@ - + \ No newline at end of file diff --git a/scripts/compile.php b/scripts/compile.php index 9ad61e9..f9e3d32 100644 --- a/scripts/compile.php +++ b/scripts/compile.php @@ -7,7 +7,7 @@ declare(strict_types = 1); require_once __DIR__ . "/../functions/functions.php"; -const GET_PARAM_JS_CSS = "v000008"; +const GET_PARAM_JS_CSS = "v000009"; /** * Generates the json for a translation file.