Use papaparse for parsing CSV
This commit is contained in:
		| @@ -24,59 +24,13 @@ class CsvxmlValidator { | ||||
|  | ||||
|         this.fieldList = Object.freeze(fieldList); | ||||
|  | ||||
|         const lines = csvRaw.trim().replace("\r\n", "\n").split("\n"); | ||||
|         const data = Papa.parse(csvRaw.trim(), {header: true}); | ||||
|  | ||||
|         let separator; | ||||
|         let delimiter; | ||||
|         if (csvRaw.substr(0, 1) === '"') { | ||||
|             separator = '";"'; | ||||
|             delimiter = '"' | ||||
|         } | ||||
|         else { | ||||
|             separator = ';'; | ||||
|             delimiter = ''; | ||||
|         if (data.errors.length !== 0) { | ||||
|             window.alert(data.errors); | ||||
|         } | ||||
|  | ||||
|         // Gets first line | ||||
|         let headersFields = lines.shift(); | ||||
|         let headers; | ||||
|         if (delimiter === "") headers = headersFields.split(separator); | ||||
|         else headers = headersFields.substr(1, headersFields.length - 2).split(separator); | ||||
|         let expectedFieldCount = headers.length; | ||||
|  | ||||
|         let toValidate = []; | ||||
|         let lineCounter = 1; | ||||
|         for (let line of lines) { | ||||
|  | ||||
|             if (delimiter !== '') { | ||||
|                 line = line.substr(1, line.length - 2); | ||||
|             } | ||||
|  | ||||
|             // Remove fully empty lines (both without content and those with fields set up, | ||||
|             // but without content there. | ||||
|             if (line.length <= headers.length) continue; | ||||
|  | ||||
|             let lineContents = {}; | ||||
|             let fields = line.split(separator); | ||||
|  | ||||
|             if (fields.length !== headers.length) { | ||||
|                 this.errors.parsing.push("Number of columns in line " + lineCounter + " does not match number of headers"); | ||||
|             } | ||||
|  | ||||
|             for (let i = 0, max = fields.length; i < max; i++) { | ||||
|                 if (headers[i] === undefined || headers[i] === null) { | ||||
|                     this.errors.parsing.push("ERROR parsing line " + lineCounter + "; column " + i); | ||||
|                     continue; | ||||
|                 } | ||||
|                 lineContents[headers[i]] = fields[i]; | ||||
|             } | ||||
|  | ||||
|             // Skip totally empty lines | ||||
|             if (Object.values(lineContents).join("").length === 0) continue; | ||||
|  | ||||
|             toValidate.push(lineContents); | ||||
|             lineCounter++; | ||||
|         } | ||||
|         let toValidate = data.data; | ||||
|  | ||||
|         this.toValidate = toValidate; | ||||
|  | ||||
| @@ -577,18 +531,38 @@ class CsvxmlPage { | ||||
|  | ||||
|         reader.onload = function() { | ||||
|  | ||||
|             // On loading success, check if the upload is valid JSON | ||||
|             console.log("Read file"); | ||||
|             // Validate the file | ||||
|             let validator = new CsvxmlValidator(app.fieldListFlat, reader.result); | ||||
|             document.body.classList.remove("loading"); | ||||
|             if (validator.isValid() === true) { | ||||
|                 alert("Document is valid. Press ok to download."); | ||||
|                 app.zipUploadToXml(validator); | ||||
|             function handleValidation() { | ||||
|  | ||||
|                 // On loading success, check if the upload is valid JSON | ||||
|                 console.log("Read file"); | ||||
|                 // Validate the file | ||||
|                 let validator = new CsvxmlValidator(app.fieldListFlat, reader.result); | ||||
|                 document.body.classList.remove("loading"); | ||||
|                 if (validator.isValid() === true) { | ||||
|                     alert("Document is valid. Press ok to download."); | ||||
|                     app.zipUploadToXml(validator); | ||||
|                 } | ||||
|                 else { | ||||
|                     console.log("Identified invalid upload document"); | ||||
|                     app.listValidationErrors(validator); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|             console.log("Postload papaparse"); | ||||
|             if (typeof Papa === "undefined") { | ||||
|  | ||||
|                 const loadScript = document.createElement("script"); | ||||
|                 loadScript.setAttribute("src", "assets/js/papaparse/papaparse.min.js"); | ||||
|                 loadScript.addEventListener('load', function() { | ||||
|                     // console.log("Post-loaded OpenLayers"); | ||||
|                     handleValidation(); | ||||
|                 }, {passive: true, once: true}); | ||||
|                 document.body.appendChild(loadScript); | ||||
|  | ||||
|             } | ||||
|             else { | ||||
|                 console.log("Identified invalid upload document"); | ||||
|                 app.listValidationErrors(validator); | ||||
|                 handleValidation(); | ||||
|             } | ||||
|  | ||||
|         }; | ||||
|   | ||||
							
								
								
									
										16
									
								
								public/assets/js/csvxmlV2.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								public/assets/js/csvxmlV2.min.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,12 +1,6 @@ | ||||
| "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 lines=csvRaw.trim().replace("\r\n","\n").split("\n");let separator;let delimiter;if(csvRaw.substr(0,1)==='"'){separator='";"';delimiter='"'} | ||||
| else{separator=';';delimiter='';} | ||||
| let headersFields=lines.shift();let headers;if(delimiter==="")headers=headersFields.split(separator);else headers=headersFields.substr(1,headersFields.length-2).split(separator);let expectedFieldCount=headers.length;let toValidate=[];let lineCounter=1;for(let line of lines){if(delimiter!==''){line=line.substr(1,line.length-2);} | ||||
| if(line.length<=headers.length)continue;let lineContents={};let fields=line.split(separator);if(fields.length!==headers.length){this.errors.parsing.push("Number of columns in line "+lineCounter+" does not match number of headers");} | ||||
| for(let i=0,max=fields.length;i<max;i++){if(headers[i]===undefined||headers[i]===null){this.errors.parsing.push("ERROR parsing line "+lineCounter+"; column "+i);continue;} | ||||
| lineContents[headers[i]]=fields[i];} | ||||
| if(Object.values(lineContents).join("").length===0)continue;toValidate.push(lineContents);lineCounter++;} | ||||
| this.toValidate=toValidate;if(toValidate.length===0){alert("Error: No lines of content identified");} | ||||
| 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.checkDuplicateInvNos();this.checkDependentColumns();this.checkControlledLists();} | ||||
| validateMandatoryTagsPresent(){let mandatoryFields=[];for(let fieldName in this.fieldList){if(this.fieldList[fieldName].required===true){mandatoryFields.push(fieldName);}} | ||||
| @@ -50,8 +44,10 @@ else{runZipping();}} | ||||
| listValidationErrors(validator){console.log("Listing validation errors");const dialogueContent=document.createElement("div");const headline=document.createElement("h3");headline.textContent=this.tls.validation_errors;const cancelB=document.createElement("a");cancelB.classList.add("icons");cancelB.classList.add("iconsClose");cancelB.classList.add("dialogueCloseX");cancelB.id="dialogueClose";cancelB.textContent="X";cancelB.title="Close";cancelB.href="#"+location.href;cancelB.addEventListener('click',CsvxmlDialogue.closeDialogue);headline.appendChild(cancelB);dialogueContent.appendChild(headline);const domErrorsSection=document.createElement("div");for(let errorType in validator.errors){if(validator.errors[errorType].length===0)continue;const ulHl=document.createElement("h4");ulHl.textContent=this.tls['errors_'+errorType]+" ("+validator.errors[errorType].length+")";ulHl.style.cursor="pointer";domErrorsSection.appendChild(ulHl);const ul=document.createElement("ul");for(let error of validator.errors[errorType]){const li=document.createElement("li");li.textContent=error;ul.appendChild(li);} | ||||
| ulHl.addEventListener('click',function(){ul.classList.toggle("minimized");});domErrorsSection.appendChild(ul);} | ||||
| dialogueContent.appendChild(domErrorsSection);const domDlSection=document.createElement("div");const domDlA=document.createElement("span");domDlA.textContent=this.tls.download;domDlA.classList.add("buttonLike");let app=this;domDlA.addEventListener('click',function(){app.zipUploadToXml(validator);});domDlSection.appendChild(domDlA);dialogueContent.appendChild(domDlSection);dialogue=CsvxmlDialogue.drawDialogue(dialogueContent);} | ||||
| uploadFileForValidation(file){const reader=new FileReader();reader.readAsText(file);let app=this;document.body.classList.add("loading");reader.onload=function(){console.log("Read file");let validator=new CsvxmlValidator(app.fieldListFlat,reader.result);document.body.classList.remove("loading");if(validator.isValid()===true){alert("Document is valid. Press ok to download.");app.zipUploadToXml(validator);} | ||||
| else{console.log("Identified invalid upload document");app.listValidationErrors(validator);}};reader.onerror=function(){alert(reader.error);};} | ||||
| uploadFileForValidation(file){const reader=new FileReader();reader.readAsText(file);let app=this;document.body.classList.add("loading");reader.onload=function(){function handleValidation(){console.log("Read file");let validator=new CsvxmlValidator(app.fieldListFlat,reader.result);document.body.classList.remove("loading");if(validator.isValid()===true){alert("Document is valid. Press ok to download.");app.zipUploadToXml(validator);} | ||||
| else{console.log("Identified invalid upload document");app.listValidationErrors(validator);}} | ||||
| console.log("Postload papaparse");if(typeof Papa==="undefined"){const loadScript=document.createElement("script");loadScript.setAttribute("src","assets/js/papaparse/papaparse.min.js");loadScript.addEventListener('load',function(){handleValidation();},{passive:true,once:true});document.body.appendChild(loadScript);} | ||||
| else{handleValidation();}};reader.onerror=function(){alert(reader.error);};} | ||||
| renderGenHeader(){const header=document.createElement("header");header.id="mainHeader";const logoArea=document.createElement("a");logoArea.id="logoArea";logoArea.href="https://www.museum-digital.org/";const logoImg=document.createElement("img");logoImg.src="assets/img/mdlogo-code-128px.png";logoImg.alt="Logo of museum-digital";logoArea.appendChild(logoImg);const h2=document.createElement("h2");h2.textContent="museum-digital";logoArea.appendChild(h2);header.appendChild(logoArea);const nav=document.createElement("nav");const lAbout=document.createElement("a");lAbout.href="https://en.about.museum-digital.org/about";lAbout.textContent=this.tls.about;nav.appendChild(lAbout);const lContactList=document.createElement("div");const lContact=document.createElement("a");lContact.textContent=this.tls.contact;lContact.href="https://en.about.museum-digital.org/contact/";lContactList.appendChild(lContact);const lContactDiv=document.createElement("div");const lImprint=document.createElement("a");lImprint.textContent=this.tls.imprint;lImprint.href="https://en.about.museum-digital.org/impressum";lContactDiv.appendChild(lImprint);const lPrivacy=document.createElement("a");lPrivacy.textContent=this.tls.privacy_policy;lPrivacy.href="https://en.about.museum-digital.org/privacy/";lContactDiv.appendChild(lPrivacy);lContactList.appendChild(lContactDiv);nav.appendChild(lContactList);const lNews=document.createElement("a") | ||||
| lNews.textContent=this.tls.news;lNews.href="https://blog.museum-digital.org/";nav.appendChild(lNews);header.appendChild(nav);document.body.appendChild(header);} | ||||
| renderHeader(){const appHeader=document.createElement("header");const h1=document.createElement("h1");const img=document.createElement("img");img.width="70";img.height="70";img.src="assets/img/mdlogo-csvxml.svg";img.alt="";h1.appendChild(img);const h1Span=document.createElement("span");h1Span.textContent="museum-digital:csvxml";h1.appendChild(h1Span);appHeader.appendChild(h1);document.body.appendChild(appHeader);} | ||||
|   | ||||
							
								
								
									
										7
									
								
								public/assets/js/papaparse/papaparse.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								public/assets/js/papaparse/papaparse.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -4,7 +4,7 @@ | ||||
|  | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
|     <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> | ||||
|     <link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000002" /> | ||||
|     <link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000003" /> | ||||
|     <link rel="manifest" href="/manifest.json" /> | ||||
|     <meta name="theme-color" content="#aa4400" /> | ||||
|  | ||||
| @@ -27,7 +27,7 @@ | ||||
| </head> | ||||
| <body class="loading"> | ||||
|  | ||||
| <script src="assets/js/csvxmlV2.min.js?v000002" type="text/javascript" async></script> | ||||
| <script src="assets/js/csvxmlV2.min.js?v000003" type="text/javascript" async></script> | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
| @@ -4,8 +4,8 @@ const urlsToCache = [ | ||||
|  | ||||
|     '/index.htm', | ||||
|     '/assets/js/jszip/dist/jszip.min.js', | ||||
|     '/assets/js/csvxmlV2.min.js', | ||||
|     '/assets/css/csvxml.min.css', | ||||
|     '/assets/js/csvxmlV2.min.js?v000003', | ||||
|     '/assets/css/csvxml.min.css?v000003', | ||||
|  | ||||
|     '/assets/fonts/SourceSansPro-Regular.woff2', | ||||
|  | ||||
|   | ||||
| @@ -76,7 +76,7 @@ function generateAppShell():string { | ||||
| 
 | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
|     <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> | ||||
|     <link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000002" /> | ||||
|     <link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000003" /> | ||||
|     <link rel="manifest" href="/manifest.json" /> | ||||
|     <meta name="theme-color" content="#aa4400" /> | ||||
| 
 | ||||
| @@ -99,7 +99,7 @@ function generateAppShell():string { | ||||
| </head> | ||||
| <body class="loading"> | ||||
| 
 | ||||
| <script src="assets/js/csvxmlV2.min.js?v000002" type="text/javascript" async></script> | ||||
| <script src="assets/js/csvxmlV2.min.js?v000003" type="text/javascript" async></script> | ||||
| 
 | ||||
| </body> | ||||
| </html>'; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user