Move minifying and bundling JS and CSS to compile.php, add header

Close #17
This commit is contained in:
Joshua Ramon Enslin 2022-11-07 21:11:34 +01:00
parent 2e349568e7
commit 05d6865cb3
Signed by: jrenslin
GPG Key ID: 46016F84501B70AE
11 changed files with 236 additions and 114 deletions

@ -1 +1 @@
Subproject commit a5967745828dc7c1f72039821d4859ba708d38f3
Subproject commit 22603ca7b823b5191ae64c58ce9e9526b279ffe3

View File

@ -1,11 +1,13 @@
@import 'editMenu.css';
/*
* @import 'editMenu.css';
@import 'dialogue.css';
*/
:root {
--color-bg-normal: #FFF;
--color-bg-raised: #EEE;
--color-bg-raised2: #FAFAFA;
--color-fg-normal: #000;
--color-fg-less: #212121;
--color-fg-less: #212121;
--color-borders: #D6D6D6;
--color-borders-dark: #646464;
@ -48,12 +50,14 @@
* { box-sizing: border-box; z-index: 1; }
body { margin: 2em; background: var(--color-bg-normal); color: var(--color-fg-normal);
body { margin: 0; background: var(--color-bg-normal); color: var(--color-fg-normal);
font-family: sourceSansPro, Arial, Helvetica, Times; font-size: 1.2em; line-height: 1.5em; }
a { text-decoration: none; color: inherit; }
h1 { display: block; max-width: 600px; margin: 0 auto 1.5em auto; line-height: 1.2em; }
h1 { display: block; width: 100%; text-align: center; margin: 0 auto 1.5em auto;
padding: 1em 0;
font-size: 2.5em; line-height: 1.2em; }
h1 > * { display: inline-block; vertical-align: middle; color: var(--color-fg-less); }
h1 img { height: 2em; margin-right: .5em; border-radius: .1em; opacity: .7; transition: opacity .4s; }
h1 img:hover { opacity: 1; }
@ -121,7 +125,7 @@ ul.fieldList { display: block; margin: .5em 0; padding: 0 0; list-style: none; }
ul.fieldList > li { display: inline-block; margin: .1em; padding: .3em;
border: 1px solid var(--color-borders); background: var(--color-bg-raised2);
color: var(--color-fg-normal);
cursor: pointer; transition: background .4s, border .4s, box-shadow .4s;; }
cursor: pointer; transition: background .4s, border .4s, box-shadow .4s; }
ul.fieldList > li:hover { background: var(--color-bg-normal); border-color: var(--color-fg-less); }
ul.fieldList > li.requiredField:before { display: inline-block; content: " \002612 "; margin-right: .5em; }
ul.fieldList > li.humanTLToggled { border-color: var(--color-accent-hover); background: var(--color-accent-hover); box-shadow: 0 8px 6px -6px black; }
@ -155,7 +159,67 @@ ul.fieldList > li.humanTLToggled { border-color: var(--color-accent-hover); back
to { transform: rotate(360deg); }
}
header { display: block; width: 100%; padding: 0 2em; font-size: 1rem; z-index: 2; }
header#mainHeader { margin-bottom: 2em;
background: var(--color-fg-less); color: var(--color-bg-raised2); display: table; }
header#mainHeader > * { display: table-cell; }
@media screen and (max-width: 70em) {
header#mainHeader > * { min-width: 20%; }
}
header#mainHeader > *:last-child { text-align: right; }
header#mainHeader, header#mainHeader * { z-index: 5; }
header#mainHeader:hover,
header#mainHeader *:hover { z-index: 6; }
header * { z-index: 2; }
header > * { display: inline-block; vertical-align: middle; }
header h2 { font-size: 1.1em; color: inherit; }
header select { background: inherit; font-size: .85rem; border: 0; }
header select option { color: var(--color-fg-normal); }
header nav { color: var(--color-bg-raised2); }
header nav > * { position: relative; display: inline-block; flex: 1; font-size: 1rem; padding: .7em 0; }
header#mainHeader img { display: inline-block; height: 1.9em; margin-right: .5em; vertical-align: middle; filter: invert(1); transition: opacity .4s; }
header#mainHeader h2 { display: inline-block; vertical-align: middle; font-weight: normal; }
header#mainHeader > a:focus > img,
header#mainHeader > a:hover > img { opacity: .7; }
@media screen and (min-width: 75em) {
header nav > div > div { display: none; position: absolute; right: 0; top: 100%; width: 300px;
background: var(--color-fg-less); text-align: left; }
header nav > div > a { padding: .95em 1em; transition: background .4s, color .4s; }
header nav > div:focus > a,
header nav > div:hover > a { color: var(--color-gray); }
header nav > div > a:focus + div,
header nav > div:hover > div { display: block; animation: fade-in .4s; }
header nav > div > a:focus + div > a,
header nav > div:hover > div > a { display: block; padding: .5em 1em; cursor: pointer;
transition: background .4s, color .4s; }
header nav > div > a:focus + div > a:focus,
header nav > div:hover > div > a:hover { background: var(--color-fg-normal); color: var(--color-bg-normal); }
header { padding: 0 10em; }
}
@media screen and (max-width: 75em) {
body { font-size: 1.08em; }
h1 img { display: none; }
header .branding { padding: .7rem; }
header nav:before { content: " \2630 "; display: inline-block; position: absolute; right: 3rem; top: 0;
padding: .8rem 0; font-size: 1.5em; text-align: right; }
header nav > * { display: none; }
header nav:hover:before { display: none; }
header nav:hover { position: absolute; left: 0; top: 0; display: flex;
width: 100%; min-height: 90vh; padding: 2em 1em .5em 1em; background: var(--color-bg-normal); color: var(--color-fg-normal);
border-bottom: 1px solid var(--color-borders); box-shadow: 2px 2px 4px var(--color-borders);
z-index: 3; animation: fade-in .4s; }
header nav:hover > * { display: block; flex: 1; min-width: 40vw; padding: 1em; font-size: 1em; }
header nav:hover > div a { display: block; padding: .2em 0; }
header { padding: 0 1em; }
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -502,6 +502,8 @@ class CsvxmlPage {
listValidationErrors(validator) {
console.log("Listing validation errors");
const dialogueContent = document.createElement("div");
const headline = document.createElement("h3");
@ -571,17 +573,21 @@ class CsvxmlPage {
let app = this;
document.body.classList.add("loading");
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);
}
else {
console.log("Identified invalid upload document");
app.listValidationErrors(validator);
}
@ -592,9 +598,69 @@ class CsvxmlPage {
}
renderHeader() {
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);
// Right side of the header
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");
@ -609,9 +675,9 @@ class CsvxmlPage {
h1Span.textContent = "museum-digital:csvxml";
h1.appendChild(h1Span);
header.appendChild(h1);
appHeader.appendChild(h1);
document.body.appendChild(header);
document.body.appendChild(appHeader);
}
@ -919,6 +985,7 @@ class CsvxmlPage {
document.body.classList.remove("loading");
const page = new CsvxmlPage(fieldList, tls);
page.renderGenHeader();
page.renderHeader();
page.renderUploader();
page.renderMain();

View File

@ -1,67 +1,76 @@
"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")}
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===!0){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++}}
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)===!1){this.errors.dependentColumns.push("Dependency issue at column "+header+": Corresponding column "+dep+" is missing")}}}}
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}
let allowedValues=this.fieldList[fieldName].allowedValues;if(allowedValues===undefined||allowedValues===null)continue;if(Object.values(allowedValues).length===0||Object.values(allowedValues).includes(line[fieldName])){continue}
this.errors.controlledLists.push("Disallowed value used for column "+fieldName+" at line "+lineCounter+" (Allowed values are: "+Object.values(allowedValues).join(", ")+")")}
lineCounter++}}
"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");}
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);}}
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++;}}
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");}}}}
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;}
let allowedValues=this.fieldList[fieldName].allowedValues;if(allowedValues===undefined||allowedValues===null)continue;if(Object.values(allowedValues).length===0||Object.values(allowedValues).includes(line[fieldName])){continue;}
this.errors.controlledLists.push("Disallowed value used for column "+fieldName+" at line "+lineCounter+" (Allowed values are: "+Object.values(allowedValues).join(", ")+")");}
lineCounter++;}}
checkMainImageResource(){}
isValid(){for(let errorClass in this.errors){if(this.errors[errorClass].length!==0)return!1}
return!0}
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)}
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<e.clientY+elem.clientHeight){elem.style.top="";elem.style.bottom=(window.innerHeight-e.clientY)+"px"}else{elem.style.bottom="";elem.style.top=(e.clientY+4)+"px"}
if(window.innerWidth<e.clientX+elem.clientWidth){elem.style.left="";elem.style.right=(window.innerWidth-e.clientX)+"px"}else{elem.style.right="";elem.style.left=(e.clientX+3)+"px"}}
static positionMobile(newMain){if(window.matchMedia&&window.matchMedia('(max-width:75em)').matches){newMain.style.left="";newMain.style.right="";newMain.style.top="";newMain.style.bottom="";if(newMain.classList.contains("atBottom")===!1){newMain.classList.add("atBottom")}}}
static triggerMouseMove(e){const newMain=document.getElementById("newToolTipMain");if(newMain===undefined||newMain===null)return;CsvxmlTooltip.getDirection(e,newMain);CsvxmlTooltip.positionMobile(newMain)}
static triggerMouseOut(e){const newMain=document.getElementById("newToolTipMain");if(newMain!==undefined&&newMain!==null){newMain.classList.remove("visible");document.body.removeChild(newMain)}
e.target.removeEventListener('mouseout',CsvxmlTooltip.triggerMouseOut)}
static bindTooltipToElement(elem,tooltipTitle,tooltipContent){elem.addEventListener('mouseover',function(e){let newMain=document.getElementById("newToolTipMain");if(newMain!==null)return;newMain=document.createElement("div");newMain.classList.add("newToolTip");newMain.id="newToolTipMain";newMain.setAttribute("data-title",tooltipTitle);newMain.appendChild(tooltipContent);document.body.appendChild(newMain);newMain.classList.add("visible");CsvxmlTooltip.getDirection(e,newMain);CsvxmlTooltip.positionMobile(newMain);newMain.addEventListener("mouseout",function(e){const newMain=document.getElementById("newToolTipMain");if(newMain!==undefined&&newMain!==null){newMain.classList.remove("visible");document.body.removeChild(newMain)}});elem.addEventListener("mouseout",CsvxmlTooltip.triggerMouseOut)},{passive:!0});elem.addEventListener("mousemove",CsvxmlTooltip.triggerMouseMove,{passive:!0})}}
class CsvxmlDialogue{static closeDialogue(e){if(e!==undefined){e.preventDefault();e.stopPropagation()}
let dialogueArea=document.getElementById("dialogueArea");if(dialogueArea!==null&&dialogueArea!==!1){while(dialogueArea.firstChild){dialogueArea.removeChild(dialogueArea.firstChild)}
dialogueArea.parentElement.removeChild(dialogueArea);document.removeEventListener('keydown',CsvxmlDialogue.closeDialogueByEscape,!1)}}
static closeDialogueByEscape(e){if(e.keyCode===27){CsvxmlDialogue.closeDialogue(e)}}
static drawDialogue(contents){let dialogueArea=document.createElement("div");dialogueArea.id="dialogueArea";let dialogue=document.createElement("div");dialogue.id="dialogue";dialogue.appendChild(contents);dialogueArea.appendChild(dialogue);document.body.appendChild(dialogueArea);document.addEventListener('keydown',CsvxmlDialogue.closeDialogueByEscape);return dialogue}}
class CsvxmlPage{fieldList;fieldListFlat;tls;domUploaderWrapper;domMainWrapper;selectedFields;csvBySelectionButton;unsetSelectionButton;constructor(fieldList,tls){this.fieldList=Object.freeze(fieldList);let list={};for(let sectionName in fieldList){list=Object.assign(list,fieldList[sectionName])}
this.fieldListFlat=Object.freeze(list);this.tls=Object.freeze(tls);let domUploaderWrapper=document.createElement("div");domUploaderWrapper.id="uploader";domUploaderWrapper.classList.add("uploader");this.domUploaderWrapper=domUploaderWrapper;let domMainWrapper=document.createElement("main");this.domMainWrapper=domMainWrapper;this.selectedFields=[]}
generateCsv(selectedFields=[]){let line1=[];let line2=[];let line3=[];for(let fieldName in this.fieldListFlat){console.log(fieldName);console.log(selectedFields);if(selectedFields.length!==0&&selectedFields.includes(fieldName)===!1)continue;const field=this.fieldListFlat[fieldName];line1.push(fieldName);line2.push(field.name_human_readable);if(field.allowedValues!==undefined){let values=[];for(let key in field.allowedValues)values.push(field.allowedValues[key]);line3.push(values.join(","))}else line3.push("");}
const csvLine1='"'+line1.join('";"')+'"';const csvLine2='"'+line2.join('";"')+'"';const csvLine3='"'+line3.join('";"')+'"';const toStore=csvLine1+"\n"+csvLine2+"\n"+csvLine3;const triggerLink=document.createElement('a');triggerLink.setAttribute('href','data:text/plain;charset=utf-8,'+encodeURIComponent(toStore));triggerLink.setAttribute('download',"csvxml_museum-digital_template.csv");triggerLink.style.display='none';document.body.appendChild(triggerLink);triggerLink.click();document.body.removeChild(triggerLink)}
zipUploadToXml(validator){function runZipping(){let zip=new JSZip();let xmlFiles=validator.generateXml();const serializer=new XMLSerializer();let lineCounter=0;for(let xml of xmlFiles){zip.file(lineCounter+".xml",serializer.serializeToString(xml));lineCounter++}
zip.generateAsync({type:"blob"}).then(function(content){const triggerLink=document.createElement('a');triggerLink.href=window.URL.createObjectURL(content);triggerLink.setAttribute('download',"csvxml.zip");triggerLink.style.display='none';document.body.appendChild(triggerLink);triggerLink.click();document.body.removeChild(triggerLink)})}
if(typeof JSZip==="undefined"){const loadScript=document.createElement("script");loadScript.setAttribute("src","assets/js/jszip/dist/jszip.min.js");loadScript.addEventListener('load',function(){runZipping()},{passive:!0,once:!0});document.body.appendChild(loadScript)}else{runZipping()}}
listValidationErrors(validator){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;reader.onload=function(){console.log("Read file");let validator=new CsvxmlValidator(app.fieldListFlat,reader.result);if(validator.isValid()===!0){alert("Document is valid. Press ok to download.");app.zipUploadToXml(validator)}else{app.listValidationErrors(validator)}};reader.onerror=function(){alert(reader.error)}}
renderHeader(){const header=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);header.appendChild(h1);document.body.appendChild(header)}
renderUploader(){let app=this;(async function(){const form=document.createElement("form");const label=document.createElement("label");label.textContent=app.tls.select_csv_file_for_upload;label.setAttribute("for","fileToUpload");form.appendChild(label);const input=document.createElement("input");input.type="file";input.id="fileToUpload";input.setAttribute("tabindex","1");input.accept=".csv";input.required="required";input.addEventListener('change',async function(){app.uploadFileForValidation(input.files[0])});form.appendChild(input);app.domUploaderWrapper.appendChild(form)})();document.body.appendChild(this.domUploaderWrapper)}
doForFieldList(callback){let fieldLists=document.getElementsByClassName("fieldList");for(let i=0,max=fieldLists.length;i<max;i++){let fields=fieldLists[i].getElementsByTagName("li");for(let j=0,maxj=fields.length;j<maxj;j++){callback(fields[j])}}}
toggleListFieldSelectionState(field){let app=this;let newValue=field.getAttribute("data-alt");field.setAttribute("data-alt",field.textContent);field.textContent=newValue;field.classList.toggle("humanTLToggled");if(field.classList.contains("humanTLToggled")===!1)return;let dependencies=this.fieldListFlat[field.id].dependsOn;if(dependencies!==undefined&&dependencies!==null){let linkedFields=this.fieldListFlat[field.id].dependsOn;for(let i=0,max=linkedFields.length;i<max;i++){let linkedField=document.getElementById(linkedFields[i]);if(linkedField.classList.contains("humanTLToggled")===!0)continue;this.toggleListFieldSelectionState(linkedField)}}}
checkCSVBySelectionAccessibility(){let selected=document.getElementsByClassName("humanTLToggled");if(selected.length===0){this.csvBySelectionButton.classList.add("invisible");this.unsetSelectionButton.classList.add("invisible")}else{this.csvBySelectionButton.classList.remove("invisible");this.unsetSelectionButton.classList.remove("invisible")}}
getOptionsSection(){function genButton(id,text,link=""){const output=document.createElement("span");output.id=id;output.setAttribute("tabindex","1");output.textContent=text;output.classList.add("buttonLike");if(link!=="")output.href=link;return output}
const options=document.createElement("div");options.classList.add("options");const app=this;const dlAllButton=genButton("dlAll",this.tls.download_csv_all);dlAllButton.cursor="pointer";dlAllButton.addEventListener('click',function(e){e.preventDefault();app.generateCsv()});options.appendChild(dlAllButton);this.csvBySelectionButton=genButton("csvBySelection",this.tls.download_csv_by_selection);this.csvBySelectionButton.classList.add("invisible");options.appendChild(this.csvBySelectionButton);const optionSelectRequired=genButton("selectRequired",this.tls.select_required_fields);options.appendChild(optionSelectRequired);const optionSelectAll=genButton("selectAll",this.tls.select_all_fields);options.appendChild(optionSelectAll);this.unsetSelectionButton=genButton("unsetSelection",this.tls.unset_selection);this.unsetSelectionButton.classList.add("invisible");options.appendChild(this.unsetSelectionButton);this.csvBySelectionButton.addEventListener('click',function(e){e.preventDefault();let selected=document.getElementsByClassName("humanTLToggled");let selectedFields=[];for(let i=0,max=selected.length;i<max;i++){selectedFields+=selected[i].getAttribute("data-value")}
app.generateCsv(selectedFields)});optionSelectRequired.addEventListener('click',function(e){e.preventDefault();app.doForFieldList(function(field){if(field.classList.contains("requiredField")===!1)return;if(field.classList.contains("humanTLToggled")===!0)return;app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility()})});optionSelectAll.addEventListener('click',function(e){e.preventDefault();app.doForFieldList(function(field){if(field.classList.contains("humanTLToggled")===!0)return;app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility()})});this.unsetSelectionButton.addEventListener('click',function(e){e.preventDefault();app.doForFieldList(function(field){if(field.classList.contains("humanTLToggled")===!1)return;app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility()})});return options}
return output;}}
class CsvxmlTooltip{static getDirection(e,elem){if(window.innerHeight<e.clientY+elem.clientHeight){elem.style.top="";elem.style.bottom=(window.innerHeight-e.clientY)+"px";}
else{elem.style.bottom="";elem.style.top=(e.clientY+4)+"px";}
if(window.innerWidth<e.clientX+elem.clientWidth){elem.style.left="";elem.style.right=(window.innerWidth-e.clientX)+"px";}else{elem.style.right="";elem.style.left=(e.clientX+3)+"px";}}
static positionMobile(newMain){if(window.matchMedia&&window.matchMedia('(max-width:75em)').matches){newMain.style.left="";newMain.style.right="";newMain.style.top="";newMain.style.bottom="";if(newMain.classList.contains("atBottom")===false){newMain.classList.add("atBottom");}}}
static triggerMouseMove(e){const newMain=document.getElementById("newToolTipMain");if(newMain===undefined||newMain===null)return;CsvxmlTooltip.getDirection(e,newMain);CsvxmlTooltip.positionMobile(newMain);}
static triggerMouseOut(e){const newMain=document.getElementById("newToolTipMain");if(newMain!==undefined&&newMain!==null){newMain.classList.remove("visible");document.body.removeChild(newMain);}
e.target.removeEventListener('mouseout',CsvxmlTooltip.triggerMouseOut);}
static bindTooltipToElement(elem,tooltipTitle,tooltipContent){elem.addEventListener('mouseover',function(e){let newMain=document.getElementById("newToolTipMain");if(newMain!==null)return;newMain=document.createElement("div");newMain.classList.add("newToolTip");newMain.id="newToolTipMain";newMain.setAttribute("data-title",tooltipTitle);newMain.appendChild(tooltipContent);document.body.appendChild(newMain);newMain.classList.add("visible");CsvxmlTooltip.getDirection(e,newMain);CsvxmlTooltip.positionMobile(newMain);newMain.addEventListener("mouseout",function(e){const newMain=document.getElementById("newToolTipMain");if(newMain!==undefined&&newMain!==null){newMain.classList.remove("visible");document.body.removeChild(newMain);}});elem.addEventListener("mouseout",CsvxmlTooltip.triggerMouseOut);},{passive:true});elem.addEventListener("mousemove",CsvxmlTooltip.triggerMouseMove,{passive:true});}}
class CsvxmlDialogue{static closeDialogue(e){if(e!==undefined){e.preventDefault();e.stopPropagation();}
let dialogueArea=document.getElementById("dialogueArea");if(dialogueArea!==null&&dialogueArea!==false){while(dialogueArea.firstChild){dialogueArea.removeChild(dialogueArea.firstChild);}
dialogueArea.parentElement.removeChild(dialogueArea);document.removeEventListener('keydown',CsvxmlDialogue.closeDialogueByEscape,false);}}
static closeDialogueByEscape(e){if(e.keyCode===27){CsvxmlDialogue.closeDialogue(e);}}
static drawDialogue(contents){let dialogueArea=document.createElement("div");dialogueArea.id="dialogueArea";let dialogue=document.createElement("div");dialogue.id="dialogue";dialogue.appendChild(contents);dialogueArea.appendChild(dialogue);document.body.appendChild(dialogueArea);document.addEventListener('keydown',CsvxmlDialogue.closeDialogueByEscape);return dialogue;}}
class CsvxmlPage{fieldList;fieldListFlat;tls;domUploaderWrapper;domMainWrapper;selectedFields;csvBySelectionButton;unsetSelectionButton;constructor(fieldList,tls){this.fieldList=Object.freeze(fieldList);let list={};for(let sectionName in fieldList){list=Object.assign(list,fieldList[sectionName]);}
this.fieldListFlat=Object.freeze(list);this.tls=Object.freeze(tls);let domUploaderWrapper=document.createElement("div");domUploaderWrapper.id="uploader";domUploaderWrapper.classList.add("uploader");this.domUploaderWrapper=domUploaderWrapper;let domMainWrapper=document.createElement("main");this.domMainWrapper=domMainWrapper;this.selectedFields=[];}
generateCsv(selectedFields=[]){let line1=[];let line2=[];let line3=[];for(let fieldName in this.fieldListFlat){console.log(fieldName);console.log(selectedFields);if(selectedFields.length!==0&&selectedFields.includes(fieldName)===false)continue;const field=this.fieldListFlat[fieldName];line1.push(fieldName);line2.push(field.name_human_readable);if(field.allowedValues!==undefined){let values=[];for(let key in field.allowedValues)values.push(field.allowedValues[key]);line3.push(values.join(","));}
else line3.push("");}
const csvLine1='"'+line1.join('";"')+'"';const csvLine2='"'+line2.join('";"')+'"';const csvLine3='"'+line3.join('";"')+'"';const toStore=csvLine1+"\n"+csvLine2+"\n"+csvLine3;const triggerLink=document.createElement('a');triggerLink.setAttribute('href','data:text/plain;charset=utf-8,'+encodeURIComponent(toStore));triggerLink.setAttribute('download',"csvxml_museum-digital_template.csv");triggerLink.style.display='none';document.body.appendChild(triggerLink);triggerLink.click();document.body.removeChild(triggerLink);}
zipUploadToXml(validator){function runZipping(){let zip=new JSZip();let xmlFiles=validator.generateXml();const serializer=new XMLSerializer();let lineCounter=0;for(let xml of xmlFiles){zip.file(lineCounter+".xml",serializer.serializeToString(xml));lineCounter++;}
zip.generateAsync({type:"blob"}).then(function(content){const triggerLink=document.createElement('a');triggerLink.href=window.URL.createObjectURL(content);triggerLink.setAttribute('download',"csvxml.zip");triggerLink.style.display='none';document.body.appendChild(triggerLink);triggerLink.click();document.body.removeChild(triggerLink);});}
if(typeof JSZip==="undefined"){const loadScript=document.createElement("script");loadScript.setAttribute("src","assets/js/jszip/dist/jszip.min.js");loadScript.addEventListener('load',function(){runZipping();},{passive:true,once:true});document.body.appendChild(loadScript);}
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);};}
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);}
renderUploader(){let app=this;(async function(){const form=document.createElement("form");const label=document.createElement("label");label.textContent=app.tls.select_csv_file_for_upload;label.setAttribute("for","fileToUpload");form.appendChild(label);const input=document.createElement("input");input.type="file";input.id="fileToUpload";input.setAttribute("tabindex","1");input.accept=".csv";input.required="required";input.addEventListener('change',async function(){app.uploadFileForValidation(input.files[0]);});form.appendChild(input);app.domUploaderWrapper.appendChild(form);})();document.body.appendChild(this.domUploaderWrapper);}
doForFieldList(callback){let fieldLists=document.getElementsByClassName("fieldList");for(let i=0,max=fieldLists.length;i<max;i++){let fields=fieldLists[i].getElementsByTagName("li");for(let j=0,maxj=fields.length;j<maxj;j++){callback(fields[j]);}}}
toggleListFieldSelectionState(field){let app=this;let newValue=field.getAttribute("data-alt");field.setAttribute("data-alt",field.textContent);field.textContent=newValue;field.classList.toggle("humanTLToggled");if(field.classList.contains("humanTLToggled")===false)return;let dependencies=this.fieldListFlat[field.id].dependsOn;if(dependencies!==undefined&&dependencies!==null){let linkedFields=this.fieldListFlat[field.id].dependsOn;for(let i=0,max=linkedFields.length;i<max;i++){let linkedField=document.getElementById(linkedFields[i]);if(linkedField.classList.contains("humanTLToggled")===true)continue;this.toggleListFieldSelectionState(linkedField);}}}
checkCSVBySelectionAccessibility(){let selected=document.getElementsByClassName("humanTLToggled");if(selected.length===0){this.csvBySelectionButton.classList.add("invisible");this.unsetSelectionButton.classList.add("invisible");}
else{this.csvBySelectionButton.classList.remove("invisible");this.unsetSelectionButton.classList.remove("invisible");}}
getOptionsSection(){function genButton(id,text,link=""){const output=document.createElement("span");output.id=id;output.setAttribute("tabindex","1");output.textContent=text;output.classList.add("buttonLike");if(link!=="")output.href=link;return output;}
const options=document.createElement("div");options.classList.add("options");const app=this;const dlAllButton=genButton("dlAll",this.tls.download_csv_all);dlAllButton.cursor="pointer";dlAllButton.addEventListener('click',function(e){e.preventDefault();app.generateCsv();});options.appendChild(dlAllButton);this.csvBySelectionButton=genButton("csvBySelection",this.tls.download_csv_by_selection);this.csvBySelectionButton.classList.add("invisible");options.appendChild(this.csvBySelectionButton);const optionSelectRequired=genButton("selectRequired",this.tls.select_required_fields);options.appendChild(optionSelectRequired);const optionSelectAll=genButton("selectAll",this.tls.select_all_fields);options.appendChild(optionSelectAll);this.unsetSelectionButton=genButton("unsetSelection",this.tls.unset_selection);this.unsetSelectionButton.classList.add("invisible");options.appendChild(this.unsetSelectionButton);this.csvBySelectionButton.addEventListener('click',function(e){e.preventDefault();let selected=document.getElementsByClassName("humanTLToggled");let selectedFields=[];for(let i=0,max=selected.length;i<max;i++){selectedFields+=selected[i].getAttribute("data-value");}
app.generateCsv(selectedFields);});optionSelectRequired.addEventListener('click',function(e){e.preventDefault();app.doForFieldList(function(field){if(field.classList.contains("requiredField")===false)return;if(field.classList.contains("humanTLToggled")===true)return;app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility();});});optionSelectAll.addEventListener('click',function(e){e.preventDefault();app.doForFieldList(function(field){if(field.classList.contains("humanTLToggled")===true)return;app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility();});});this.unsetSelectionButton.addEventListener('click',function(e){e.preventDefault();app.doForFieldList(function(field){if(field.classList.contains("humanTLToggled")===false)return;app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility();});});return options;}
renderMain(){const domH2=document.createElement("h2");domH2.textContent=this.tls.currently_approved_tags;this.domMainWrapper.appendChild(domH2);this.domMainWrapper.appendChild(this.getOptionsSection());for(let sectionName in this.fieldList){const domDiv=document.createElement("div");const domH3=document.createElement("h3");domH3.textContent=sectionName;domDiv.appendChild(domH3);const domUl=document.createElement("ul");domUl.classList.add("fieldList");const sectionFields=this.fieldList[sectionName];for(let fieldName in sectionFields){const field=sectionFields[fieldName];const domLi=document.createElement("li");domLi.textContent=fieldName;domLi.id=fieldName;domLi.setAttribute("data-alt",field.name_human_readable)
domLi.setAttribute("data-value",fieldName)
if(field.required===!0)domLi.classList.add("requiredField");domUl.appendChild(domLi);const tooltipContent=document.createElement("div");const explicaP=document.createElement("p");explicaP.textContent=field.explica;tooltipContent.appendChild(explicaP);if(field.remarks!==undefined&&field.remarks!==''){const remarkHl=document.createElement("h4");remarkHl.textContent=this.tls.remarks;tooltipContent.appendChild(remarkHl)
const remarkCont=document.createElement("p");remarkCont=field.remarks;tooltipContent.appendChild(remarkCont)}
if(field.allowedValues!==undefined&&Object.values(field.allowedValues).length!==0){const allowedHl=document.createElement("h4");allowedHl.textContent=this.tls.allowed_values;tooltipContent.appendChild(allowedHl);const allowedList=document.createElement("p");allowedList.textContent=Object.values(field.allowedValues).join(', ');tooltipContent.appendChild(allowedList)}
CsvxmlTooltip.bindTooltipToElement(domLi,field.name_human_readable,tooltipContent)}
domDiv.appendChild(domUl);this.domMainWrapper.appendChild(domDiv)}
document.body.appendChild(this.domMainWrapper);let app=this;this.doForFieldList(function(field){field.addEventListener('click',function(e){app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility()})})}}(async function(){function getLang(){const allowedLangs=document.documentElement.getAttribute("data-allowed-langs").split(',');if(navigator.language===undefined)return'en';const browserLang=navigator.language.toLowerCase().substr(0,2);console.log(browserLang);if(allowedLangs.includes(browserLang))return browserLang;else return'en'}
const lang=getLang();document.documentElement.setAttribute("lang",lang);document.body.classList.add("loading");let loaded=0;let fieldList;let tls;function loadPage(){document.body.classList.remove("loading");const page=new CsvxmlPage(fieldList,tls);page.renderHeader();page.renderUploader();page.renderMain()}
window.fetch('/json/fields.'+lang+'.json',{method:'GET',cache:'no-cache',credentials:'same-origin',}).then(function(response){return response.json()}).then(function(elements){fieldList=elements;loaded++;if(loaded===2)loadPage();});window.fetch('/json/tls.'+lang+'.json',{method:'GET',cache:'no-cache',credentials:'same-origin',}).then(function(response){return response.json()}).then(function(elements){tls=elements;loaded++;if(loaded===2)loadPage();})})()
if(field.required===true)domLi.classList.add("requiredField");domUl.appendChild(domLi);const tooltipContent=document.createElement("div");const explicaP=document.createElement("p");explicaP.textContent=field.explica;tooltipContent.appendChild(explicaP);if(field.remarks!==undefined&&field.remarks!==''){const remarkHl=document.createElement("h4");remarkHl.textContent=this.tls.remarks;tooltipContent.appendChild(remarkHl)
const remarkCont=document.createElement("p");remarkCont=field.remarks;tooltipContent.appendChild(remarkCont);}
if(field.allowedValues!==undefined&&Object.values(field.allowedValues).length!==0){const allowedHl=document.createElement("h4");allowedHl.textContent=this.tls.allowed_values;tooltipContent.appendChild(allowedHl);const allowedList=document.createElement("p");allowedList.textContent=Object.values(field.allowedValues).join(', ');tooltipContent.appendChild(allowedList);}
CsvxmlTooltip.bindTooltipToElement(domLi,field.name_human_readable,tooltipContent);}
domDiv.appendChild(domUl);this.domMainWrapper.appendChild(domDiv);}
document.body.appendChild(this.domMainWrapper);let app=this;this.doForFieldList(function(field){field.addEventListener('click',function(e){app.toggleListFieldSelectionState(field);app.checkCSVBySelectionAccessibility();});});}}
(async function(){function getLang(){const allowedLangs=document.documentElement.getAttribute("data-allowed-langs").split(',');if(navigator.language===undefined)return 'en';const browserLang=navigator.language.toLowerCase().substr(0,2);console.log(browserLang);if(allowedLangs.includes(browserLang))return browserLang;else return 'en';}
const lang=getLang();document.documentElement.setAttribute("lang",lang);document.body.classList.add("loading");let loaded=0;let fieldList;let tls;function loadPage(){document.body.classList.remove("loading");const page=new CsvxmlPage(fieldList,tls);page.renderGenHeader();page.renderHeader();page.renderUploader();page.renderMain();}
window.fetch('/json/fields.'+lang+'.json',{method:'GET',cache:'no-cache',credentials:'same-origin',}).then(function(response){return response.json();}).then(function(elements){fieldList=elements;loaded++;if(loaded===2)loadPage();});window.fetch('/json/tls.'+lang+'.json',{method:'GET',cache:'no-cache',credentials:'same-origin',}).then(function(response){return response.json();}).then(function(elements){tls=elements;loaded++;if(loaded===2)loadPage();});})();

View File

@ -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" />
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000001" />
<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" type="text/javascript" async></script>
<script src="assets/js/csvxmlV2.min.js?v000001" type="text/javascript" async></script>
</body>
</html>

View File

@ -1 +1 @@
{"remarks":"Notizen","download":"Download","upload":"Hochladen","select_csv_file_for_upload":"Bitte w\u00e4hlen Sie eine CSV Datei als Basis zum Erstellen von XML Dateien","currently_approved_tags":"Derzeit zum Import verf\u00fcgbare Tags \/ Felder","download_csv_all":"CSV-Vorlage mit allen Feldern runterladen","download_csv_by_selection":"CSV-Vorlage auf Basis der Auswahl herunterladen","select_required_fields":"Pflichtfelder ausw\u00e4hlen","select_all_fields":"Alle Felder ausw\u00e4hlen","unset_selection":"Auswahl entfernen","file_format":"Dateiformat","validation_errors":"Validierungsfehler","errors_parsing":"Parsing-Fehler","errors_mandatoryTags":"Fehlende Pflichtfelder","errors_duplicateInvNos":"Doppelte Inventarnummern","errors_dependentColumns":"Spaltenabh\u00e4ngigkeiten nicht ber\u00fccksichtigt","errors_controlledLists":"Kontrollierte Werte","errors_mainImageResource":"Fehlende Haupt-Bilder oder Ressourcen","allowed_values":"Zugelassene Werte"}
{"remarks":"Notizen","download":"Download","upload":"Hochladen","select_csv_file_for_upload":"Bitte w\u00e4hlen Sie eine CSV Datei als Basis zum Erstellen von XML Dateien","currently_approved_tags":"Derzeit zum Import verf\u00fcgbare Tags \/ Felder","download_csv_all":"CSV-Vorlage mit allen Feldern runterladen","download_csv_by_selection":"CSV-Vorlage auf Basis der Auswahl herunterladen","select_required_fields":"Pflichtfelder ausw\u00e4hlen","select_all_fields":"Alle Felder ausw\u00e4hlen","unset_selection":"Auswahl entfernen","file_format":"Dateiformat","validation_errors":"Validierungsfehler","errors_parsing":"Parsing-Fehler","errors_mandatoryTags":"Fehlende Pflichtfelder","errors_duplicateInvNos":"Doppelte Inventarnummern","errors_dependentColumns":"Spaltenabh\u00e4ngigkeiten nicht ber\u00fccksichtigt","errors_controlledLists":"Kontrollierte Werte","errors_mainImageResource":"Fehlende Haupt-Bilder oder Ressourcen","allowed_values":"Zugelassene Werte","privacy_policy":"Datenschutzerkl\u00e4rung","contact":"Kontakt","news":"Neuigkeiten","imprint":"Impressum","about":"\u00dcber"}

View File

@ -1 +1 @@
{"remarks":"Remarks","download":"Download","upload":"Upload","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Currently approved tags (column names) for md:import","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"Select required fields","select_all_fields":"Select all fields","unset_selection":"Unset selection","file_format":"File format","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values"}
{"remarks":"Remarks","download":"Download","upload":"Upload","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Currently approved tags (column names) for md:import","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"Select required fields","select_all_fields":"Select all fields","unset_selection":"Unset selection","file_format":"File format","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values","privacy_policy":"Privacy policy","contact":"Contact","news":"News","imprint":"Imprint","about":"About"}

View File

@ -1 +1 @@
{"remarks":"Megjegyz\u00e9sek","download":"Let\u00f6lt\u00e9s","upload":"Felt\u00f6lt\u00e9s","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Jelenleg j\u00f3v\u00e1hagyott c\u00edmk\u00e9k (oszlopnevek) az md:importhoz","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"K\u00f6telez\u0151 mez\u0151k kijel\u00f6l\u00e9se","select_all_fields":"\u00d6sszes mez\u0151 kijel\u00f6l\u00e9s","unset_selection":"Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se","file_format":"Kiterjeszt\u00e9s","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values"}
{"remarks":"Megjegyz\u00e9sek","download":"Let\u00f6lt\u00e9s","upload":"Felt\u00f6lt\u00e9s","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Jelenleg j\u00f3v\u00e1hagyott c\u00edmk\u00e9k (oszlopnevek) az md:importhoz","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"K\u00f6telez\u0151 mez\u0151k kijel\u00f6l\u00e9se","select_all_fields":"\u00d6sszes mez\u0151 kijel\u00f6l\u00e9s","unset_selection":"Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se","file_format":"Kiterjeszt\u00e9s","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values","privacy_policy":"Privacy policy","contact":"Contact","news":"News","imprint":"Imprint","about":"About"}

View File

@ -53,6 +53,12 @@ function generateTranslationFile(string $lang):string {
'errors_controlledLists' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'errors_controlledLists'),
'errors_mainImageResource' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'errors_mainImageResource'),
'allowed_values' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'allowed_values'),
'privacy_policy' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'privacy_policy'),
'contact' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'contact'),
'news' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'news'),
'imprint' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'imprint'),
'about' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'about'),
]);
}
@ -70,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" />
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000001" />
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#aa4400" />
@ -93,7 +99,7 @@ function generateAppShell():string {
</head>
<body class="loading">
<script src="assets/js/csvxmlV2.min.js" type="text/javascript" async></script>
<script src="assets/js/csvxmlV2.min.js?v000001" type="text/javascript" async></script>
</body>
</html>';
@ -111,3 +117,13 @@ foreach (ALLOWED_LANGS as $lang) {
}
file_put_contents(SERVED_ROOT . 'index.htm', generateAppShell());
exec("minify \\
-o " . escapeshellarg(__DIR__ . '/../public/assets/css/csvxml.min.css') . '\\
' . escapeshellarg(__DIR__ . '/../public/assets/css/editMenu.css') . '\\
' . escapeshellarg(__DIR__ . '/../public/assets/css/dialogue.css') . '\\
' . escapeshellarg(__DIR__ . '/../public/assets/css/csvxml.css'));
exec("minify \\
-o " . escapeshellarg(__DIR__ . '/../public/assets/js/csvxmlV2.min.js') . '\
' . escapeshellarg(__DIR__ . '/../public/assets/js/csvxmlV2.js'));