2022-11-06 15:30:36 +01:00
"use strict" ;
2022-11-07 03:55:07 +01:00
if ( 'serviceWorker' in navigator ) {
console . log ( "Registering service worker" ) ;
navigator . serviceWorker . register ( '/sw.js' ) ;
}
2022-11-06 15:30:36 +01:00
class CsvxmlValidator {
fieldList ; // {}{}
toValidate ; // []{}
errors ; // {}array
constructor ( fieldList , csvRaw ) {
this . errors = {
parsing : [ ] ,
mandatoryTags : [ ] ,
duplicateInvNos : [ ] ,
dependentColumns : [ ] ,
controlledLists : [ ] ,
mainImageResource : [ ] ,
} ;
2022-11-07 00:21:38 +01:00
this . fieldList = Object . freeze ( fieldList ) ;
2022-11-06 15:30:36 +01:00
2022-11-13 02:20:02 +01:00
const data = Papa . parse ( csvRaw . trim ( ) , { header : true } ) ;
2022-11-06 15:30:36 +01:00
2022-11-13 02:20:02 +01:00
if ( data . errors . length !== 0 ) {
window . alert ( data . errors ) ;
2022-11-06 23:23:02 +01:00
}
2022-11-06 15:30:36 +01:00
2022-11-13 02:20:02 +01:00
let toValidate = data . data ;
2022-11-06 15:30:36 +01:00
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 ( ) ;
// this.checkMainImageResource();
}
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 ) {
2022-11-06 23:23:02 +01:00
if ( this . fieldList [ header ] === undefined || this . fieldList [ header ] . dependsOn === undefined || this . fieldList [ header ] . dependsOn === null ) continue ;
2022-11-06 15:30:36 +01:00
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" ) ;
}
}
}
2022-11-28 14:25:11 +01:00
let lineCounter = 1 ;
for ( let line of this . toValidate ) {
for ( let fieldName in line ) {
if ( line [ fieldName ] === '' ) 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 ++ ;
}
2022-11-06 15:30:36 +01:00
}
checkControlledLists ( ) {
let lineCounter = 1 ;
for ( let line of this . toValidate ) {
for ( let fieldName in line ) {
2022-11-06 23:23:02 +01:00
if ( this . fieldList [ fieldName ] === undefined ) {
console . log ( "Undefined but requested field " + fieldName ) ;
continue ;
}
2022-11-28 14:25:11 +01:00
const allowedValues = this . fieldList [ fieldName ] . allowedValues ;
2022-11-06 15:30:36 +01:00
// No error if the field doesn't have a controlled list
if ( allowedValues === undefined || allowedValues === null ) continue ;
// No error if the line's content is in the list
2022-11-06 23:23:02 +01:00
if ( Object . values ( allowedValues ) . length === 0 || Object . values ( allowedValues ) . includes ( line [ fieldName ] ) ) {
2022-11-06 15:30:36 +01:00
continue ;
}
2022-11-28 14:25:11 +01:00
if ( line [ fieldName ] === '' ) continue ;
2022-11-10 07:52:52 +01:00
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 ] + ")" ) ;
2022-11-06 15:30:36 +01:00
}
lineCounter ++ ;
}
}
checkMainImageResource ( ) {
}
isValid ( ) {
for ( let errorClass in this . errors ) {
2022-11-06 23:23:02 +01:00
if ( this . errors [ errorClass ] . length !== 0 ) return false ;
2022-11-06 15:30:36 +01:00
}
return true ;
}
/ * *
* Generates XML for the parsed lines
* /
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 {
/ * *
* Function for setting the alignment of an element .
*
* @ param { Event } e Event triggering the execution of this function .
* @ param { DOMElement } elem Dom element to position .
*
* @ return { void }
* /
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" ;
// Insert contents loaded.
newMain . setAttribute ( "data-title" , tooltipTitle ) ;
2022-11-06 23:23:02 +01:00
newMain . appendChild ( tooltipContent ) ;
2022-11-06 15:30:36 +01:00
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 } ) ;
}
}
2022-11-06 23:23:02 +01:00
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 ) { // 27 = Esc
CsvxmlDialogue . closeDialogue ( e ) ;
}
}
/ * *
* Function for drawing a dialogue and attaching it to the body elem .
*
* @ param { DOMElement } contents Contents .
* /
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 ;
}
}
2022-11-06 15:30:36 +01:00
class CsvxmlPage {
fieldList ;
2022-11-07 00:21:38 +01:00
fieldListFlat ;
2022-11-06 23:23:02 +01:00
tls ;
2022-11-17 17:56:23 +01:00
domHelpWrapper ;
2022-11-06 15:30:36 +01:00
domUploaderWrapper ;
domMainWrapper ;
selectedFields ;
2022-11-06 23:23:02 +01:00
csvBySelectionButton ;
unsetSelectionButton ;
2022-11-07 02:55:54 +01:00
constructor ( fieldList , tls ) {
2022-11-06 15:30:36 +01:00
this . fieldList = Object . freeze ( fieldList ) ;
2022-11-07 00:21:38 +01:00
let list = { } ;
for ( let sectionName in fieldList ) {
list = Object . assign ( list , fieldList [ sectionName ] ) ;
}
this . fieldListFlat = Object . freeze ( list ) ;
2022-11-07 02:55:54 +01:00
this . tls = Object . freeze ( tls ) ;
2022-11-06 15:30:36 +01:00
2022-11-17 17:56:23 +01:00
let domHelpWrapper = document . createElement ( "div" ) ;
domHelpWrapper . id = "helpSection" ;
this . domHelpWrapper = domHelpWrapper ;
2022-11-06 15:30:36 +01:00
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 = [ ] ;
2022-11-07 00:21:38 +01:00
for ( let fieldName in this . fieldListFlat ) {
console . log ( fieldName ) ;
console . log ( selectedFields ) ;
2022-11-06 15:30:36 +01:00
2022-11-07 00:21:38 +01:00
if ( selectedFields . length !== 0 && selectedFields . includes ( fieldName ) === false ) continue ;
const field = this . fieldListFlat [ fieldName ] ;
2022-11-06 15:30:36 +01:00
2022-11-07 00:21:38 +01:00
line1 . push ( fieldName ) ;
line2 . push ( field . name _human _readable ) ;
2022-11-06 15:30:36 +01:00
2022-11-07 00:21:38 +01:00
if ( field . allowedValues !== undefined ) {
// Join for object
let values = [ ] ;
2022-11-28 14:25:11 +01:00
for ( let key in field . allowedValues ) {
values . push ( field . allowedValues [ key ] ) ;
}
2022-11-07 00:21:38 +01:00
line3 . push ( values . join ( "," ) ) ;
2022-11-06 15:30:36 +01:00
}
2022-11-07 00:21:38 +01:00
else line3 . push ( "" ) ;
2022-11-06 15:30:36 +01:00
}
const csvLine1 = '"' + line1 . join ( '";"' ) + '"' ;
const csvLine2 = '"' + line2 . join ( '";"' ) + '"' ;
const csvLine3 = '"' + line3 . join ( '";"' ) + '"' ;
const toStore = csvLine1 + "\n" + csvLine2 + "\n" + csvLine3 ;
// Download
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 ) {
2022-11-07 01:09:41 +01:00
// Wrap zipping in function to postload it
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 ) ;
} ) ;
2022-11-06 15:30:36 +01:00
}
2022-11-07 01:09:41 +01:00
if ( typeof JSZip === "undefined" ) {
2022-11-06 15:30:36 +01:00
2022-11-07 01:09:41 +01:00
const loadScript = document . createElement ( "script" ) ;
loadScript . setAttribute ( "src" , "assets/js/jszip/dist/jszip.min.js" ) ;
loadScript . addEventListener ( 'load' , function ( ) {
// console.log("Post-loaded OpenLayers");
runZipping ( ) ;
} , { passive : true , once : true } ) ;
2022-11-06 15:30:36 +01:00
2022-11-07 01:09:41 +01:00
document . body . appendChild ( loadScript ) ;
}
else {
runZipping ( ) ;
}
2022-11-06 15:30:36 +01:00
}
2022-11-17 17:56:23 +01:00
generateDialogueCloseButton ( ) {
2022-11-06 23:23:02 +01:00
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 ) ;
2022-11-17 17:56:23 +01:00
return cancelB ;
}
2022-11-06 23:23:02 +01:00
2022-11-17 17:56:23 +01:00
listValidationErrors ( validator ) {
console . log ( "Listing validation errors" ) ;
const dialogueContent = document . createElement ( "div" ) ;
const headline = document . createElement ( "h3" ) ;
headline . textContent = this . tls . validation _errors ;
headline . appendChild ( this . generateDialogueCloseButton ( ) ) ;
2022-11-06 23:23:02 +01:00
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 ) ;
}
2022-11-06 15:30:36 +01:00
uploadFileForValidation ( file ) {
const reader = new FileReader ( ) ;
reader . readAsText ( file ) ;
let app = this ;
2022-11-07 21:11:34 +01:00
document . body . classList . add ( "loading" ) ;
2022-11-06 15:30:36 +01:00
reader . onload = function ( ) {
2022-11-13 02:20:02 +01:00
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 ) ;
2022-11-06 15:30:36 +01:00
}
else {
2022-11-13 02:20:02 +01:00
handleValidation ( ) ;
2022-11-06 15:30:36 +01:00
}
} ;
reader . onerror = function ( ) {
alert ( reader . error ) ;
} ;
}
2022-11-07 21:11:34 +01:00
renderGenHeader ( ) {
2022-11-07 02:55:54 +01:00
const header = document . createElement ( "header" ) ;
2022-11-07 21:11:34 +01:00
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" ) ;
2022-11-07 02:55:54 +01:00
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 ) ;
2022-11-07 21:11:34 +01:00
appHeader . appendChild ( h1 ) ;
2022-11-07 02:55:54 +01:00
2022-11-07 21:11:34 +01:00
document . body . appendChild ( appHeader ) ;
2022-11-07 02:55:54 +01:00
}
2022-11-17 17:56:23 +01:00
renderHelpTexts ( ) {
let app = this ;
( async function ( ) {
function appendQA ( question , answer ) {
const div = document . createElement ( "div" ) ;
div . classList . add ( "qaDiv" ) ;
const qElem = document . createElement ( "h3" ) ;
qElem . textContent = question ;
qElem . style . cursor = "pointer" ;
div . appendChild ( qElem ) ;
qElem . addEventListener ( 'click' , function ( ) {
console . log ( "Listing validation errors" ) ;
const dialogueContent = document . createElement ( "div" ) ;
const headline = document . createElement ( "h3" ) ;
headline . textContent = question ;
headline . appendChild ( app . generateDialogueCloseButton ( ) ) ;
dialogueContent . appendChild ( headline ) ;
const answerDiv = document . createElement ( "div" ) ;
answerDiv . textContent = answer ;
dialogueContent . appendChild ( answerDiv ) ;
CsvxmlDialogue . drawDialogue ( dialogueContent ) ;
} ) ;
return div ;
}
const div = document . createElement ( "div" ) ;
div . appendChild ( appendQA ( app . tls . help _where _am _i , app . tls . help _where _am _i _content ) ) ;
2022-11-18 02:04:24 +01:00
div . appendChild ( appendQA ( app . tls . help _what _is _csv , app . tls . help _what _is _csv _content ) ) ;
div . appendChild ( appendQA ( app . tls . help _how _to _format _csv , app . tls . help _how _to _format _csv _content ) ) ;
2022-11-17 17:56:23 +01:00
app . domHelpWrapper . appendChild ( div ) ;
} ) ( ) ;
document . body . appendChild ( this . domHelpWrapper ) ;
}
2022-11-06 15:30:36 +01:00
renderUploader ( ) {
let app = this ;
( async function ( ) {
2022-11-17 17:56:23 +01:00
const h2 = document . createElement ( "h2" ) ;
h2 . textContent = app . tls . upload ;
app . domUploaderWrapper . appendChild ( h2 ) ;
2022-11-06 15:30:36 +01:00
const form = document . createElement ( "form" ) ;
const label = document . createElement ( "label" ) ;
2022-11-06 23:23:02 +01:00
label . textContent = app . tls . select _csv _file _for _upload ;
2022-11-06 15:30:36 +01:00
label . setAttribute ( "for" , "fileToUpload" ) ;
form . appendChild ( label ) ;
const input = document . createElement ( "input" ) ;
input . type = "file" ;
input . id = "fileToUpload" ;
2022-11-07 03:55:07 +01:00
input . setAttribute ( "tabindex" , "1" ) ;
2022-11-06 15:30:36 +01:00
input . accept = ".csv" ;
input . required = "required" ;
input . addEventListener ( 'change' , async function ( ) {
app . uploadFileForValidation ( input . files [ 0 ] ) ;
} ) ;
form . appendChild ( input ) ;
2022-11-06 23:23:02 +01:00
/ *
2022-11-06 15:30:36 +01:00
const button = document . createElement ( "button" ) ;
button . textContent = "Upload" ; // TODO
button . type = "submit" ;
form . appendChild ( button ) ;
2022-11-06 23:23:02 +01:00
* /
2022-11-06 15:30:36 +01:00
app . domUploaderWrapper . appendChild ( form ) ;
} ) ( ) ;
document . body . appendChild ( this . domUploaderWrapper ) ;
}
2022-11-06 23:23:02 +01:00
// Takes a callback function
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 ;
2022-11-07 00:21:38 +01:00
let dependencies = this . fieldListFlat [ field . id ] . dependsOn ;
2022-11-06 23:23:02 +01:00
if ( dependencies !== undefined && dependencies !== null ) {
2022-11-07 00:21:38 +01:00
let linkedFields = this . fieldListFlat [ field . id ] . dependsOn ;
2022-11-06 23:23:02 +01:00
for ( let i = 0 , max = linkedFields . length ; i < max ; i ++ ) {
let linkedField = document . getElementById ( linkedFields [ i ] ) ;
if ( linkedField . classList . contains ( "humanTLToggled" ) === true ) continue ;
2022-11-07 00:21:38 +01:00
this . toggleListFieldSelectionState ( linkedField ) ;
2022-11-06 23:23:02 +01:00
}
}
}
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" ) ;
}
}
2022-11-06 15:30:36 +01:00
getOptionsSection ( ) {
function genButton ( id , text , link = "" ) {
2022-11-07 03:55:07 +01:00
const output = document . createElement ( "span" ) ;
2022-11-06 15:30:36 +01:00
output . id = id ;
2022-11-07 03:55:07 +01:00
output . setAttribute ( "tabindex" , "1" ) ;
2022-11-06 15:30:36 +01:00
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 ;
2022-11-06 23:23:02 +01:00
const dlAllButton = genButton ( "dlAll" , this . tls . download _csv _all ) ;
2022-11-06 15:30:36 +01:00
dlAllButton . cursor = "pointer" ;
2022-11-07 03:55:07 +01:00
dlAllButton . addEventListener ( 'click' , function ( e ) {
e . preventDefault ( ) ;
2022-11-06 15:30:36 +01:00
app . generateCsv ( ) ;
} ) ;
2022-11-06 23:23:02 +01:00
options . appendChild ( dlAllButton ) ;
2022-11-06 15:30:36 +01:00
2022-11-06 23:23:02 +01:00
this . csvBySelectionButton = genButton ( "csvBySelection" , this . tls . download _csv _by _selection ) ;
this . csvBySelectionButton . classList . add ( "invisible" ) ;
options . appendChild ( this . csvBySelectionButton ) ;
2022-11-06 15:30:36 +01:00
2022-11-06 23:23:02 +01:00
const optionSelectRequired = genButton ( "selectRequired" , this . tls . select _required _fields ) ;
2022-11-06 15:30:36 +01:00
options . appendChild ( optionSelectRequired ) ;
2022-11-06 23:23:02 +01:00
const optionSelectAll = genButton ( "selectAll" , this . tls . select _all _fields ) ;
2022-11-06 15:30:36 +01:00
options . appendChild ( optionSelectAll ) ;
2022-11-06 23:23:02 +01:00
this . unsetSelectionButton = genButton ( "unsetSelection" , this . tls . unset _selection ) ;
this . unsetSelectionButton . classList . add ( "invisible" ) ;
options . appendChild ( this . unsetSelectionButton ) ;
2022-11-06 15:30:36 +01:00
2022-11-06 23:23:02 +01:00
this . csvBySelectionButton . addEventListener ( 'click' , function ( e ) {
2022-11-07 03:55:07 +01:00
e . preventDefault ( ) ;
2022-11-06 15:30:36 +01:00
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 ) {
2022-11-07 03:55:07 +01:00
e . preventDefault ( ) ;
2022-11-06 15:30:36 +01:00
2022-11-06 23:23:02 +01:00
app . doForFieldList ( function ( field ) {
2022-11-06 15:30:36 +01:00
if ( field . classList . contains ( "requiredField" ) === false ) return ;
if ( field . classList . contains ( "humanTLToggled" ) === true ) return ;
2022-11-06 23:23:02 +01:00
app . toggleListFieldSelectionState ( field ) ;
app . checkCSVBySelectionAccessibility ( ) ;
2022-11-06 15:30:36 +01:00
} ) ;
} ) ;
optionSelectAll . addEventListener ( 'click' , function ( e ) {
2022-11-07 03:55:07 +01:00
e . preventDefault ( ) ;
2022-11-06 15:30:36 +01:00
2022-11-06 23:23:02 +01:00
app . doForFieldList ( function ( field ) {
2022-11-06 15:30:36 +01:00
if ( field . classList . contains ( "humanTLToggled" ) === true ) return ;
2022-11-06 23:23:02 +01:00
app . toggleListFieldSelectionState ( field ) ;
app . checkCSVBySelectionAccessibility ( ) ;
2022-11-06 15:30:36 +01:00
} ) ;
} ) ;
2022-11-06 23:23:02 +01:00
this . unsetSelectionButton . addEventListener ( 'click' , function ( e ) {
2022-11-07 03:55:07 +01:00
e . preventDefault ( ) ;
2022-11-06 15:30:36 +01:00
2022-11-06 23:23:02 +01:00
app . doForFieldList ( function ( field ) {
2022-11-06 15:30:36 +01:00
if ( field . classList . contains ( "humanTLToggled" ) === false ) return ;
2022-11-06 23:23:02 +01:00
app . toggleListFieldSelectionState ( field ) ;
app . checkCSVBySelectionAccessibility ( ) ;
2022-11-06 15:30:36 +01:00
} ) ;
} ) ;
return options ;
}
renderMain ( ) {
const domH2 = document . createElement ( "h2" ) ;
2022-11-06 23:23:02 +01:00
domH2 . textContent = this . tls . currently _approved _tags ;
2022-11-06 15:30:36 +01:00
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 === true ) domLi . classList . add ( "requiredField" ) ;
domUl . appendChild ( domLi ) ;
2022-11-06 23:23:02 +01:00
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 ) ;
2022-11-06 15:30:36 +01:00
}
domDiv . appendChild ( domUl ) ;
this . domMainWrapper . appendChild ( domDiv ) ;
}
document . body . appendChild ( this . domMainWrapper ) ;
2022-11-06 23:23:02 +01:00
let app = this ;
this . doForFieldList ( function ( field ) {
// Each field should switch its visible content and human-readable
// translation on a click.
field . addEventListener ( 'click' , function ( e ) {
app . toggleListFieldSelectionState ( field ) ;
app . checkCSVBySelectionAccessibility ( ) ;
} ) ;
} ) ;
2022-11-06 15:30:36 +01:00
}
}
2022-11-07 02:55:54 +01:00
( async function ( ) {
function getLang ( ) {
const allowedLangs = document . documentElement . getAttribute ( "data-allowed-langs" ) . split ( ',' ) ;
2022-11-06 15:30:36 +01:00
2022-11-07 02:55:54 +01:00
if ( navigator . language === undefined ) return 'en' ;
2022-11-06 15:30:36 +01:00
2022-11-07 02:55:54 +01:00
const browserLang = navigator . language . toLowerCase ( ) . substr ( 0 , 2 ) ;
console . log ( browserLang ) ;
2022-11-06 15:30:36 +01:00
2022-11-07 02:55:54 +01:00
if ( allowedLangs . includes ( browserLang ) ) return browserLang ;
else return 'en' ;
}
const lang = getLang ( ) ;
2022-11-07 03:55:07 +01:00
document . documentElement . setAttribute ( "lang" , lang ) ;
2022-11-07 02:55:54 +01:00
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 ) ;
2022-11-07 21:11:34 +01:00
page . renderGenHeader ( ) ;
2022-11-07 02:55:54 +01:00
page . renderHeader ( ) ;
2022-11-17 17:56:23 +01:00
page . renderHelpTexts ( ) ;
2022-11-07 02:55:54 +01:00
page . renderUploader ( ) ;
page . renderMain ( ) ;
}
2022-11-06 15:30:36 +01:00
2022-11-07 02:55:54 +01:00
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 ( ) ;
} ) ;
} ) ( ) ;