From a141b236083054d0e63e9cb4160f3f550d6cacc1 Mon Sep 17 00:00:00 2001 From: Joshua Ramon Enslin Date: Sun, 6 Nov 2022 23:23:02 +0100 Subject: [PATCH] Finish full JS rewrite (in index_new.php fr now) See #14 --- public/assets/css/csvxml.css | 48 +++-- public/assets/css/dialogue.css | 40 ++++ public/assets/css/editMenu.css | 12 +- public/assets/js/csvxmlV2.js | 381 ++++++++++++++++++++++++--------- public/index_new.php | 50 ++++- 5 files changed, 397 insertions(+), 134 deletions(-) create mode 100644 public/assets/css/dialogue.css diff --git a/public/assets/css/csvxml.css b/public/assets/css/csvxml.css index d4cd750..ad63ce1 100644 --- a/public/assets/css/csvxml.css +++ b/public/assets/css/csvxml.css @@ -1,4 +1,17 @@ @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-borders: #D6D6D6; + --color-borders-dark: #646464; + + --color-accent-normal: #FFCCBC; + --color-accent-hover: #CB9B8C; +} /* ============== | Load fonts @@ -18,16 +31,17 @@ * { box-sizing: border-box; z-index: 1; } -body { margin: 2em; background: #FFF; +body { margin: 2em; background: var(--color-bg-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; } -h1 > * { display: inline-block; vertical-align: middle; color: #212121; } +h1 > * { display: inline-block; vertical-align: middle; color: var(--color-fg-less); } h1 img { height: 2em; margin-right: .2em; border-radius: .1em; opacity: .7; transition: opacity .4s; } h1 img:hover { opacity: 1; } +main, body > div, body > form { display: block; max-width: 90vw; margin: 0 auto 3em auto; padding-bottom: 3em; } @@ -40,8 +54,8 @@ label { display: block; font-weight: bold; margin-bottom: .5em; } select, button, textarea, -input { display: block; width: 100%; padding: .5em .5em; border: 2.5px solid #EEE; - background: inherit; color: #424242; font-family: roboto; font-size: 1em; +input { display: block; width: 100%; padding: .5em .5em; border: 2.5px solid var(--color-bg-raised); + background: inherit; color: var(--color-fg-less); font-family: roboto; font-size: 1em; border-radius: .2em; transition: border .2s; } .buttonLike { display: inline-block; text-align: center; } @@ -49,7 +63,7 @@ input[type="submit"], button { padding: .5em .8em; } .buttonLike, input[type="submit"], -button { background: #FFCCBC; color: #424242; border: none; font-weight: bold; text-transform: uppercase; transition: background .2s, color .2s; } +button { background: var(--color-accent-normal); color: var(--color-fg-less); border: none; font-weight: bold; text-transform: uppercase; transition: background .2s, color .2s; } textarea { line-height: 1.2em; } select:hover, @@ -61,7 +75,7 @@ input[type="submit"]:focus, button:focus, .buttonLike:hover, input[type="submit"]:hover, -button:hover { background: #CB9B8C; color: #000; } +button:hover { background: var(--color-accent-hover); color: #000; } aside .buttonLike + .buttonLike, aside button + button { margin-top: .5em; } @@ -69,7 +83,7 @@ aside > h4:first-child { margin-top: 0; } select:focus, textarea:focus, -input:focus { border-color: #CB9B8C; box-shadow: none; } +input:focus { border-color: var(--color-accent-hover); box-shadow: none; } textarea:invalid, input:invalid { box-shadow: none; } @@ -80,29 +94,29 @@ textarea { min-height: 30vh; } table { width: 100%; max-height: 60vh; margin: 2em 0; border-collapse: collapse; overflow: auto; } -th { padding: .3em .5em; text-align: left; border-bottom: 2px solid #424242; } -tbody > tr:nth-child(2n + 1) { background: #F2F2F2; } -td { padding: .3em .5em; border-bottom: 1px solid #D6D6D6; } +th { padding: .3em .5em; text-align: left; border-bottom: 2px solid var(--color-fg-less); } +tbody > tr:nth-child(2n + 1) { background: var(--color-bg-raised2); } +td { padding: .3em .5em; border-bottom: 1px solid var(--color-borders); } -body > div.uploader { background: #F2F2F2; border: 2px solid #EEE; padding: 1em 1em; } +body > div.uploader { background: var(--color-bg-raised2); border: 2px solid var(--color-bg-raised); padding: 1em 1em; } ul.fieldList { display: block; margin: .5em 0; padding: 0 0; list-style: none; } -ul.fieldList > li { display: inline-block; padding: .3em; margin: .1em; border: 1px solid #D6D6D6; background: #FAFAFA; cursor: pointer; transition: background .4s, border .4s, box-shadow .4s;; } -ul.fieldList > li:hover { background: #FFF; border-color: #212121; } +ul.fieldList > li { display: inline-block; padding: .3em; margin: .1em; border: 1px solid var(--color-borders); background: var(--color-bg-raised2); 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: #CB9B8C; background: #CB9B8C; box-shadow: 0 8px 6px -6px black; } +ul.fieldList > li.humanTLToggled { border-color: var(--color-accent-hover); background: var(--color-accent-hover); box-shadow: 0 8px 6px -6px black; } .options > a.buttonLike { display: inline-block; width: auto; margin: .15em 0; padding: .4em .5em; text-transform: inherit; cursor: pointer; - background: initial; border: 2px solid #D6D6D6; + background: initial; border: 2px solid var(--color-borders); opacity: 1; transition: background .4s, opacity .4s; } -.options > a.buttonLike:hover { background: #D6D6D6; } +.options > a.buttonLike:hover { background: var(--color-borders); } .actionList { margin: 1em 0 1em 1em; padding: .5em 0; } .actionList > li a { display: inline-block; padding: .3em; border-radius: .3em; transition: background .4s; } -.actionList > li a:hover { background: #CB9B8C; } +.actionList > li a:hover { background: var(--color-accent-hover); } /* ============= | Dark mode diff --git a/public/assets/css/dialogue.css b/public/assets/css/dialogue.css new file mode 100644 index 0000000..91d06a5 --- /dev/null +++ b/public/assets/css/dialogue.css @@ -0,0 +1,40 @@ +/* ======== +| Reference overlay +|= ======== */ + +#dialogueArea { display: block; position: fixed; left: 0; top: 0; + width: 100%; height: 100%; + max-width: initial; max-height: initial; + background: rgba(0,0,0,.7); backdrop-filter: blur(3px); + z-index: 10000; } +#dialogue { display: block; position: absolute; left: 50%; top: 50%; + transform: translate(-50%, -50%); min-width: 60vw; min-height: 2em; + max-width: 90vw; max-height: 90vh; overflow-y: auto; + padding: 1.5em 1em; + background: var(--color-bg-normal); border-radius: .3em; + box-shadow: 2px 2px 4px var(--color-fg-less), -2px -2px 4px var(--color-fg-less); } +#dialogue h3 { margin-top: 0; padding-top: 0; text-transform: initial; color: var(--color-fg-less); } + +#confirmButtons { text-align: right; } +#dialogue .buttonLike { margin: .5em 0 .2em .5em; background: transparent; transition: background .4s, color .4s; } +#dialogue .buttonLike:hover { background: var(--color-borders-dark); color: var(--color-bg-normal); } + +#dialogue input[type="text"], +#dialogue textarea { padding: .5em; border-radius: .1em; border: 2px solid var(--color-borders); transition: border .4s; } +#dialogue input[type="text"]:hover, +#dialogue textarea:hover { border-color: var(--color-fg-normal); } +#dialogue button { padding: .6em .8em; font-size: .8em; background: var(--color-bg-normal); border: 1px solid var(--color-borders); + transition: .4s; } +#dialogue button:focus, +#dialogue button:hover { background: var(--color-fg-less); color: var(--color-bg-normal); border-color: var(--color-fg-less); } +#dialogue form > * { display: block; width: 100%; } +#dialogue form label { font-weight: bold; color: var(--color-fg-less); } +#dialogueClose { float: right; display: inline-block; padding: 0 .6em .2em .6em; background: var(--color-bg-raised); + border-radius: 100%; cursor: pointer; transition: .4s; } +#dialogueClose:hover { background: var(--color-fg-less); color: var(--color-bg-normal); } + +#dialogue ul { margin-left: 1em; padding-left: 0; transition: .4s; } +#dialogue ul.minimized { height: 20px; background-color: var(--color-accent-normal); + background-size: 20px 20px; + background-image: repeating-linear-gradient(to right, var(--color-fg-normal), var(--color-fg-normal) 1px, var(--color-accent-normal) 1px, var(--color-accent-normal)); } +#dialogue ul.minimized > * { display: none; } diff --git a/public/assets/css/editMenu.css b/public/assets/css/editMenu.css index 2a5db17..23e1dad 100644 --- a/public/assets/css/editMenu.css +++ b/public/assets/css/editMenu.css @@ -3,11 +3,11 @@ |= ======== */ .newToolTip { position: fixed; display: none !important; min-width: 300px !important; max-width: 600px; - background: #212121 !important; color: #FFF; text-align: left; font-size: .95rem; - border-radius: .2em; box-shadow: 1px 1px 4px #646464; z-index: 3000; white-space: initial !important; } + background: var(--color-fg-less) !important; color: var(--color-bg-normal); text-align: left; font-size: .95rem; + border-radius: .2em; box-shadow: 1px 1px 4px var(--color-borders-dark); z-index: 3000; white-space: initial !important; } #newToolTipMain:before { content: attr(data-title); display: block; padding: .5em 1em; max-width: 598px; - background: #212121; color: #BDBDBD; font-weight: bold; - box-shadow: 0px 4px 2px -2px #646464; } + background: var(--color-fg-less); color: var(--color-bg-raised2); font-weight: bold; + box-shadow: 0px 4px 2px -2px var(--color-borders-dark); } #newToolTipMain > * { padding: .5rem 1rem !important; } #newToolTipMain > table td { padding: .5rem 1em; vertical-align: top; } @media screen and (min-width:75em) { @@ -21,10 +21,6 @@ dl#newToolTipMain dd { margin: -1em 0 0 0; padding: 0 0 0 0; } .newToolTipMain p + .toolTipHierarchy { padding-bottom: 0 !important; } #newToolTipMain > h5 { padding: 0 1rem !important; margin: -.5rem 0 !important; } -.toolTipHierarchy { margin: 0; padding: 0; border-top: 1px solid #424242; list-style: none; } -.toolTipHierarchy ul { margin: 0; padding: .2em 0 .2em 0; list-style: none; } -.toolTipHierarchy ul ul { padding: .1em 0 .1em 1.2em; } -.toolTipHierarchy ul > li:before { content: " \002514 "; display: inline-block; padding-right: .4em; } .copyToDialogue { cursor: pointer; } diff --git a/public/assets/js/csvxmlV2.js b/public/assets/js/csvxmlV2.js index e02cc36..9a2aec4 100644 --- a/public/assets/js/csvxmlV2.js +++ b/public/assets/js/csvxmlV2.js @@ -26,22 +26,38 @@ class CsvxmlValidator { const lines = csvRaw.trim().replace("\r\n", "\n").split("\n"); - const SEPARATOR = ';'; + let separator; + let delimiter; + if (csvRaw.substr(0, 1) === '"') { + separator = '";"'; + delimiter = '"' + } + else { + separator = ';'; + delimiter = ''; + } // Gets first line - let headers = lines.shift().split(SEPARATOR); + 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); + 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"); @@ -55,11 +71,13 @@ class CsvxmlValidator { lineContents[headers[i]] = fields[i]; } + // Skip totally empty lines + if (Object.values(lineContents).join("").length === 0) continue; + toValidate.push(lineContents); lineCounter++; } - console.log(toValidate); this.toValidate = toValidate; if (toValidate.length === 0) { @@ -120,7 +138,7 @@ class CsvxmlValidator { const headers = Object.keys(this.toValidate[0]); for (let header of headers) { - if (this.fieldList[header].dependsOn === undefined || this.fieldList[header].dependsOn === null) continue; + 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) { @@ -138,12 +156,17 @@ class CsvxmlValidator { 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; // 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 - if (Object.values(allowedValues).length === 0 || Object.values(allowedValues).includes(line.fieldName)) { + if (Object.values(allowedValues).length === 0 || Object.values(allowedValues).includes(line[fieldName])) { continue; } @@ -161,7 +184,7 @@ class CsvxmlValidator { isValid() { for (let errorClass in this.errors) { - if (errorClass.length !== 0) return false; + if (this.errors[errorClass].length !== 0) return false; } return true; @@ -270,9 +293,7 @@ class CsvxmlTooltip { newMain.setAttribute("data-title", tooltipTitle); - const tooltipDesc = document.createElement("p"); - tooltipDesc.textContent = tooltipContent; - newMain.appendChild(tooltipDesc); + newMain.appendChild(tooltipContent); document.body.appendChild(newMain); newMain.classList.add("visible"); @@ -297,15 +318,75 @@ class CsvxmlTooltip { } +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; + } + +} + class CsvxmlPage { fieldList; + tls; domUploaderWrapper; domMainWrapper; selectedFields; + csvBySelectionButton; + unsetSelectionButton; + constructor(fieldList) { this.fieldList = Object.freeze(fieldList); + this.tls = Object.freeze(JSON.parse(document.body.getAttribute("data-tls"))); let domUploaderWrapper = document.createElement("div"); domUploaderWrapper.id = "uploader"; @@ -394,6 +475,70 @@ class CsvxmlPage { } + 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(); @@ -408,15 +553,13 @@ class CsvxmlPage { // Validate the file let validator = new CsvxmlValidator(app.fieldList, reader.result); if (validator.isValid() === true) { - alert("Document is valid"); + alert("Document is valid. Press ok to download."); + app.zipUploadToXml(validator); } else { - console.log(validator.errors); - alert("Document is not valid. Errors are " + validator.errors); + app.listValidationErrors(validator); } - app.zipUploadToXml(validator); - }; reader.onerror = function() { alert(reader.error); @@ -432,7 +575,7 @@ class CsvxmlPage { const form = document.createElement("form"); const label = document.createElement("label"); - label.textContent = "Please select a CSV file to create XML files"; // TODO + label.textContent = app.tls.select_csv_file_for_upload; label.setAttribute("for", "fileToUpload"); form.appendChild(label); @@ -446,10 +589,12 @@ class CsvxmlPage { }); form.appendChild(input); + /* const button = document.createElement("button"); button.textContent = "Upload"; // TODO button.type = "submit"; form.appendChild(button); + */ app.domUploaderWrapper.appendChild(form); @@ -459,6 +604,58 @@ class CsvxmlPage { } + // 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; + + let dependencies = field.getAttribute("data-dependencies"); + if (dependencies !== undefined && dependencies !== null) { + let linkedFields = dependencies.split(";"); + for (let i = 0, max = linkedFields.length; i < max; i++) { + let linkedField = document.getElementById(linkedFields[i]); + if (linkedField.classList.contains("humanTLToggled") === true) continue; + app.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 = "") { @@ -477,93 +674,28 @@ class CsvxmlPage { const app = this; - const dlAllButton = genButton("dlAll", "Download all"); + const dlAllButton = genButton("dlAll", this.tls.download_csv_all); dlAllButton.cursor = "pointer"; dlAllButton.addEventListener('click', function() { app.generateCsv(); }); - options.appendChild(dlAllButton); // TODO + options.appendChild(dlAllButton); - const csvBySelectionButton = genButton("csvBySelection", "Csv by selection"); - csvBySelectionButton.classList.add("invisible"); - // TODO: Add toggle via event listener - options.appendChild(csvBySelectionButton); + this.csvBySelectionButton = genButton("csvBySelection", this.tls.download_csv_by_selection); + this.csvBySelectionButton.classList.add("invisible"); + options.appendChild(this.csvBySelectionButton); - const optionSelectRequired = genButton("selectRequired", "Select required"); + const optionSelectRequired = genButton("selectRequired", this.tls.select_required_fields); options.appendChild(optionSelectRequired); - const optionSelectAll = genButton("selectAll", "Select all"); + const optionSelectAll = genButton("selectAll", this.tls.select_all_fields); options.appendChild(optionSelectAll); - const unsetSelectionButton = genButton("unsetSelection", "Unset selection"); - unsetSelectionButton.classList.add("invisible"); - // TODO: Add toggle via event listener - options.appendChild(unsetSelectionButton); + this.unsetSelectionButton = genButton("unsetSelection", this.tls.unset_selection); + this.unsetSelectionButton.classList.add("invisible"); + options.appendChild(this.unsetSelectionButton); - function checkCSVBySelectionAccessibility() { - - let selected = document.getElementsByClassName("humanTLToggled"); - if (selected.length === 0) { - csvBySelectionButton.classList.add("invisible"); - unsetSelectionButton.classList.add("invisible"); - } - else { - csvBySelectionButton.classList.remove("invisible"); - unsetSelectionButton.classList.remove("invisible"); - } - - } - - // Takes a callback function - 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]); - - } - - } - } - - function toggleListFieldSelectionState(field) { - - 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 = field.getAttribute("data-dependencies"); - if (dependencies !== undefined && dependencies !== null) { - let linkedFields = dependencies.split(";"); - for (let i = 0, max = linkedFields.length; i < max; i++) { - let linkedField = document.getElementById(linkedFields[i]); - if (linkedField.classList.contains("humanTLToggled") === true) continue; - toggleListFieldSelectionState(linkedField); - } - } - - } - - doForFieldList(function(field) { - - // Each field should switch its visible content and human-readable - // translation on a click. - field.addEventListener('click', function(e) { - - toggleListFieldSelectionState(field); - checkCSVBySelectionAccessibility(); - - }); - - }); - - csvBySelectionButton.addEventListener('click', function(e) { + this.csvBySelectionButton.addEventListener('click', function(e) { let selected = document.getElementsByClassName("humanTLToggled"); let selectedFields = []; @@ -576,12 +708,12 @@ class CsvxmlPage { optionSelectRequired.addEventListener('click', function(e) { - doForFieldList(function(field) { + app.doForFieldList(function(field) { if (field.classList.contains("requiredField") === false) return; if (field.classList.contains("humanTLToggled") === true) return; - toggleListFieldSelectionState(field); - checkCSVBySelectionAccessibility(); + app.toggleListFieldSelectionState(field); + app.checkCSVBySelectionAccessibility(); }); @@ -589,23 +721,23 @@ class CsvxmlPage { optionSelectAll.addEventListener('click', function(e) { - doForFieldList(function(field) { + app.doForFieldList(function(field) { if (field.classList.contains("humanTLToggled") === true) return; - toggleListFieldSelectionState(field); - checkCSVBySelectionAccessibility(); + app.toggleListFieldSelectionState(field); + app.checkCSVBySelectionAccessibility(); }); }); - unsetSelectionButton.addEventListener('click', function(e) { + this.unsetSelectionButton.addEventListener('click', function(e) { - doForFieldList(function(field) { + app.doForFieldList(function(field) { if (field.classList.contains("humanTLToggled") === false) return; - toggleListFieldSelectionState(field); - checkCSVBySelectionAccessibility(); + app.toggleListFieldSelectionState(field); + app.checkCSVBySelectionAccessibility(); }); @@ -618,7 +750,7 @@ class CsvxmlPage { renderMain() { const domH2 = document.createElement("h2"); - domH2.textContent = "Currently approved tags (column names) for md:import"; + domH2.textContent = this.tls.currently_approved_tags; this.domMainWrapper.appendChild(domH2); this.domMainWrapper.appendChild(this.getOptionsSection()); @@ -634,8 +766,6 @@ class CsvxmlPage { const domUl = document.createElement("ul"); domUl.classList.add("fieldList"); - console.log(sectionName); - const sectionFields = this.fieldList[sectionName]; for (let fieldName in sectionFields) { const field = sectionFields[fieldName]; @@ -648,7 +778,32 @@ class CsvxmlPage { if (field.required === true) domLi.classList.add("requiredField"); domUl.appendChild(domLi); - CsvxmlTooltip.bindTooltipToElement(domLi, field.name_human_readable, field.explica); + 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); } @@ -660,6 +815,20 @@ class CsvxmlPage { document.body.appendChild(this.domMainWrapper); + 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(); + + }); + + }); + } } diff --git a/public/index_new.php b/public/index_new.php index 283b42c..db2edde 100644 --- a/public/index_new.php +++ b/public/index_new.php @@ -7,6 +7,30 @@ * @author Joshua Ramon Enslin */ declare(strict_types = 1); +require_once __DIR__ . "/../functions/functions.php"; + +$allowed_langs = ['ar', 'de', 'en', 'hu', 'id', 'it', 'pl', 'pt']; +$lang = MD_STD::get_user_lang($allowed_langs, "en"); +$tlLoader = new MDTlLoader("csxml_start_v2", $lang); + +$outFormat = MD_STD_IN::get_http_input_text("output", "html", ['html', 'json']); + +if ($outFormat === 'json') { + + $fieldsGetter = new CsvxmlAvailableFields($lang); + $availableFields = $fieldsGetter->getFields(); + + header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0'); // HTTP/1.1 + header('Pragma: no-cache'); // HTTP/1.0 + header("Access-Control-Allow-Origin: *"); + header("Access-Control-Allow-Methods: GET"); + header("Access-Control-Allow-Headers: X-PINGOTHER, Content-Type, Accept-Encoding, cache-control"); + header("Access-Control-Max-Age: 86400"); + header('content-type: application/json'); + echo json_encode($availableFields); + return; +} + echo ' @@ -18,7 +42,7 @@ echo ' - + @@ -29,14 +53,34 @@ echo ' - + $tlLoader->tl("csvxml-overview", "csvxml_overview", 'select_csv_file_for_upload'), + 'currently_approved_tags' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'currently_approved_tags'), + 'download_csv_all' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'download_csv_all'), + 'download_csv_by_selection' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'download_csv_by_selection'), + 'select_required_fields' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'select_required_fields'), + 'select_all_fields' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'select_all_fields'), + 'unset_selection' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'unset_selection'), + 'file_format' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'file_format'), + 'validation_errors' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'validation_errors'), + 'errors_parsing' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'errors_parsing'), + 'errors_mandatoryTags' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'errors_mandatoryTags'), + 'errors_duplicateInvNos' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'errors_duplicateInvNos'), + 'errors_dependentColumns' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'errors_dependentColumns'), + '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'), +])) . '">

museum-digital:csvxml

- + ';