parent
77aeebd90a
commit
a141b23608
|
@ -1,4 +1,17 @@
|
||||||
@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-borders: #D6D6D6;
|
||||||
|
--color-borders-dark: #646464;
|
||||||
|
|
||||||
|
--color-accent-normal: #FFCCBC;
|
||||||
|
--color-accent-hover: #CB9B8C;
|
||||||
|
}
|
||||||
|
|
||||||
/* ==============
|
/* ==============
|
||||||
| Load fonts
|
| Load fonts
|
||||||
|
@ -18,16 +31,17 @@
|
||||||
|
|
||||||
* { box-sizing: border-box; z-index: 1; }
|
* { 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; }
|
font-family: sourceSansPro, Arial, Helvetica, Times; font-size: 1.2em; line-height: 1.5em; }
|
||||||
|
|
||||||
a { text-decoration: none; color: inherit; }
|
a { text-decoration: none; color: inherit; }
|
||||||
|
|
||||||
h1 { display: block; max-width: 600px; margin: 0 auto 1.5em auto; }
|
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 { height: 2em; margin-right: .2em; border-radius: .1em; opacity: .7; transition: opacity .4s; }
|
||||||
h1 img:hover { opacity: 1; }
|
h1 img:hover { opacity: 1; }
|
||||||
|
|
||||||
|
main,
|
||||||
body > div,
|
body > div,
|
||||||
body > form { display: block; max-width: 90vw; margin: 0 auto 3em auto; padding-bottom: 3em; }
|
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,
|
select,
|
||||||
button,
|
button,
|
||||||
textarea,
|
textarea,
|
||||||
input { display: block; width: 100%; padding: .5em .5em; border: 2.5px solid #EEE;
|
input { display: block; width: 100%; padding: .5em .5em; border: 2.5px solid var(--color-bg-raised);
|
||||||
background: inherit; color: #424242; font-family: roboto; font-size: 1em;
|
background: inherit; color: var(--color-fg-less); font-family: roboto; font-size: 1em;
|
||||||
border-radius: .2em; transition: border .2s; }
|
border-radius: .2em; transition: border .2s; }
|
||||||
|
|
||||||
.buttonLike { display: inline-block; text-align: center; }
|
.buttonLike { display: inline-block; text-align: center; }
|
||||||
|
@ -49,7 +63,7 @@ input[type="submit"],
|
||||||
button { padding: .5em .8em; }
|
button { padding: .5em .8em; }
|
||||||
.buttonLike,
|
.buttonLike,
|
||||||
input[type="submit"],
|
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; }
|
textarea { line-height: 1.2em; }
|
||||||
|
|
||||||
select:hover,
|
select:hover,
|
||||||
|
@ -61,7 +75,7 @@ input[type="submit"]:focus,
|
||||||
button:focus,
|
button:focus,
|
||||||
.buttonLike:hover,
|
.buttonLike:hover,
|
||||||
input[type="submit"]:hover,
|
input[type="submit"]:hover,
|
||||||
button:hover { background: #CB9B8C; color: #000; }
|
button:hover { background: var(--color-accent-hover); color: #000; }
|
||||||
|
|
||||||
aside .buttonLike + .buttonLike,
|
aside .buttonLike + .buttonLike,
|
||||||
aside button + button { margin-top: .5em; }
|
aside button + button { margin-top: .5em; }
|
||||||
|
@ -69,7 +83,7 @@ aside > h4:first-child { margin-top: 0; }
|
||||||
|
|
||||||
select:focus,
|
select:focus,
|
||||||
textarea:focus,
|
textarea:focus,
|
||||||
input:focus { border-color: #CB9B8C; box-shadow: none; }
|
input:focus { border-color: var(--color-accent-hover); box-shadow: none; }
|
||||||
|
|
||||||
textarea:invalid,
|
textarea:invalid,
|
||||||
input:invalid { box-shadow: none; }
|
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; }
|
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; }
|
th { padding: .3em .5em; text-align: left; border-bottom: 2px solid var(--color-fg-less); }
|
||||||
tbody > tr:nth-child(2n + 1) { background: #F2F2F2; }
|
tbody > tr:nth-child(2n + 1) { background: var(--color-bg-raised2); }
|
||||||
td { padding: .3em .5em; border-bottom: 1px solid #D6D6D6; }
|
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 { 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 { 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: #FFF; border-color: #212121; }
|
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.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;
|
.options > a.buttonLike { display: inline-block; width: auto;
|
||||||
margin: .15em 0; padding: .4em .5em;
|
margin: .15em 0; padding: .4em .5em;
|
||||||
text-transform: inherit; cursor: pointer;
|
text-transform: inherit; cursor: pointer;
|
||||||
background: initial; border: 2px solid #D6D6D6;
|
background: initial; border: 2px solid var(--color-borders);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: background .4s, opacity .4s; }
|
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 { 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 { 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
|
| Dark mode
|
||||||
|
|
40
public/assets/css/dialogue.css
Normal file
40
public/assets/css/dialogue.css
Normal file
|
@ -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; }
|
|
@ -3,11 +3,11 @@
|
||||||
|= ======== */
|
|= ======== */
|
||||||
|
|
||||||
.newToolTip { position: fixed; display: none !important; min-width: 300px !important; max-width: 600px;
|
.newToolTip { position: fixed; display: none !important; min-width: 300px !important; max-width: 600px;
|
||||||
background: #212121 !important; color: #FFF; text-align: left; font-size: .95rem;
|
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 #646464; z-index: 3000; white-space: initial !important; }
|
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;
|
#newToolTipMain:before { content: attr(data-title); display: block; padding: .5em 1em; max-width: 598px;
|
||||||
background: #212121; color: #BDBDBD; font-weight: bold;
|
background: var(--color-fg-less); color: var(--color-bg-raised2); font-weight: bold;
|
||||||
box-shadow: 0px 4px 2px -2px #646464; }
|
box-shadow: 0px 4px 2px -2px var(--color-borders-dark); }
|
||||||
#newToolTipMain > * { padding: .5rem 1rem !important; }
|
#newToolTipMain > * { padding: .5rem 1rem !important; }
|
||||||
#newToolTipMain > table td { padding: .5rem 1em; vertical-align: top; }
|
#newToolTipMain > table td { padding: .5rem 1em; vertical-align: top; }
|
||||||
@media screen and (min-width:75em) {
|
@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 p + .toolTipHierarchy { padding-bottom: 0 !important; }
|
||||||
#newToolTipMain > h5 { padding: 0 1rem !important; margin: -.5rem 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; }
|
.copyToDialogue { cursor: pointer; }
|
||||||
|
|
||||||
|
|
|
@ -26,22 +26,38 @@ class CsvxmlValidator {
|
||||||
|
|
||||||
const lines = csvRaw.trim().replace("\r\n", "\n").split("\n");
|
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
|
// 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 expectedFieldCount = headers.length;
|
||||||
|
|
||||||
let toValidate = [];
|
let toValidate = [];
|
||||||
let lineCounter = 1;
|
let lineCounter = 1;
|
||||||
for (let line of lines) {
|
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,
|
// Remove fully empty lines (both without content and those with fields set up,
|
||||||
// but without content there.
|
// but without content there.
|
||||||
if (line.length <= headers.length) continue;
|
if (line.length <= headers.length) continue;
|
||||||
|
|
||||||
let lineContents = {};
|
let lineContents = {};
|
||||||
let fields = line.split(SEPARATOR);
|
let fields = line.split(separator);
|
||||||
|
|
||||||
if (fields.length !== headers.length) {
|
if (fields.length !== headers.length) {
|
||||||
this.errors.parsing.push("Number of columns in line " + lineCounter + " does not match number of headers");
|
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];
|
lineContents[headers[i]] = fields[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip totally empty lines
|
||||||
|
if (Object.values(lineContents).join("").length === 0) continue;
|
||||||
|
|
||||||
toValidate.push(lineContents);
|
toValidate.push(lineContents);
|
||||||
lineCounter++;
|
lineCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(toValidate);
|
|
||||||
this.toValidate = toValidate;
|
this.toValidate = toValidate;
|
||||||
|
|
||||||
if (toValidate.length === 0) {
|
if (toValidate.length === 0) {
|
||||||
|
@ -120,7 +138,7 @@ class CsvxmlValidator {
|
||||||
const headers = Object.keys(this.toValidate[0]);
|
const headers = Object.keys(this.toValidate[0]);
|
||||||
|
|
||||||
for (let header of headers) {
|
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;
|
let dependencies = this.fieldList[header].dependsOn;
|
||||||
for (let dep of dependencies) {
|
for (let dep of dependencies) {
|
||||||
|
@ -138,12 +156,17 @@ class CsvxmlValidator {
|
||||||
for (let line of this.toValidate) {
|
for (let line of this.toValidate) {
|
||||||
for (let fieldName in line) {
|
for (let fieldName in line) {
|
||||||
|
|
||||||
|
if (this.fieldList[fieldName] === undefined) {
|
||||||
|
console.log("Undefined but requested field " + fieldName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let allowedValues = this.fieldList[fieldName].allowedValues;
|
let allowedValues = this.fieldList[fieldName].allowedValues;
|
||||||
|
|
||||||
// No error if the field doesn't have a controlled list
|
// No error if the field doesn't have a controlled list
|
||||||
if (allowedValues === undefined || allowedValues === null) continue;
|
if (allowedValues === undefined || allowedValues === null) continue;
|
||||||
// No error if the line's content is in the list
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +184,7 @@ class CsvxmlValidator {
|
||||||
isValid() {
|
isValid() {
|
||||||
|
|
||||||
for (let errorClass in this.errors) {
|
for (let errorClass in this.errors) {
|
||||||
if (errorClass.length !== 0) return false;
|
if (this.errors[errorClass].length !== 0) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -270,9 +293,7 @@ class CsvxmlTooltip {
|
||||||
|
|
||||||
newMain.setAttribute("data-title", tooltipTitle);
|
newMain.setAttribute("data-title", tooltipTitle);
|
||||||
|
|
||||||
const tooltipDesc = document.createElement("p");
|
newMain.appendChild(tooltipContent);
|
||||||
tooltipDesc.textContent = tooltipContent;
|
|
||||||
newMain.appendChild(tooltipDesc);
|
|
||||||
|
|
||||||
document.body.appendChild(newMain);
|
document.body.appendChild(newMain);
|
||||||
newMain.classList.add("visible");
|
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 {
|
class CsvxmlPage {
|
||||||
|
|
||||||
fieldList;
|
fieldList;
|
||||||
|
tls;
|
||||||
domUploaderWrapper;
|
domUploaderWrapper;
|
||||||
domMainWrapper;
|
domMainWrapper;
|
||||||
selectedFields;
|
selectedFields;
|
||||||
|
|
||||||
|
csvBySelectionButton;
|
||||||
|
unsetSelectionButton;
|
||||||
|
|
||||||
constructor(fieldList) {
|
constructor(fieldList) {
|
||||||
this.fieldList = Object.freeze(fieldList);
|
this.fieldList = Object.freeze(fieldList);
|
||||||
|
this.tls = Object.freeze(JSON.parse(document.body.getAttribute("data-tls")));
|
||||||
|
|
||||||
let domUploaderWrapper = document.createElement("div");
|
let domUploaderWrapper = document.createElement("div");
|
||||||
domUploaderWrapper.id = "uploader";
|
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) {
|
uploadFileForValidation(file) {
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
@ -408,15 +553,13 @@ class CsvxmlPage {
|
||||||
// Validate the file
|
// Validate the file
|
||||||
let validator = new CsvxmlValidator(app.fieldList, reader.result);
|
let validator = new CsvxmlValidator(app.fieldList, reader.result);
|
||||||
if (validator.isValid() === true) {
|
if (validator.isValid() === true) {
|
||||||
alert("Document is valid");
|
alert("Document is valid. Press ok to download.");
|
||||||
|
app.zipUploadToXml(validator);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(validator.errors);
|
app.listValidationErrors(validator);
|
||||||
alert("Document is not valid. Errors are " + validator.errors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.zipUploadToXml(validator);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
reader.onerror = function() {
|
reader.onerror = function() {
|
||||||
alert(reader.error);
|
alert(reader.error);
|
||||||
|
@ -432,7 +575,7 @@ class CsvxmlPage {
|
||||||
const form = document.createElement("form");
|
const form = document.createElement("form");
|
||||||
|
|
||||||
const label = document.createElement("label");
|
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");
|
label.setAttribute("for", "fileToUpload");
|
||||||
form.appendChild(label);
|
form.appendChild(label);
|
||||||
|
|
||||||
|
@ -446,10 +589,12 @@ class CsvxmlPage {
|
||||||
});
|
});
|
||||||
form.appendChild(input);
|
form.appendChild(input);
|
||||||
|
|
||||||
|
/*
|
||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.textContent = "Upload"; // TODO
|
button.textContent = "Upload"; // TODO
|
||||||
button.type = "submit";
|
button.type = "submit";
|
||||||
form.appendChild(button);
|
form.appendChild(button);
|
||||||
|
*/
|
||||||
|
|
||||||
app.domUploaderWrapper.appendChild(form);
|
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() {
|
getOptionsSection() {
|
||||||
|
|
||||||
function genButton(id, text, link = "") {
|
function genButton(id, text, link = "") {
|
||||||
|
@ -477,93 +674,28 @@ class CsvxmlPage {
|
||||||
|
|
||||||
const app = this;
|
const app = this;
|
||||||
|
|
||||||
const dlAllButton = genButton("dlAll", "Download all");
|
const dlAllButton = genButton("dlAll", this.tls.download_csv_all);
|
||||||
dlAllButton.cursor = "pointer";
|
dlAllButton.cursor = "pointer";
|
||||||
dlAllButton.addEventListener('click', function() {
|
dlAllButton.addEventListener('click', function() {
|
||||||
app.generateCsv();
|
app.generateCsv();
|
||||||
});
|
});
|
||||||
options.appendChild(dlAllButton); // TODO
|
options.appendChild(dlAllButton);
|
||||||
|
|
||||||
const csvBySelectionButton = genButton("csvBySelection", "Csv by selection");
|
this.csvBySelectionButton = genButton("csvBySelection", this.tls.download_csv_by_selection);
|
||||||
csvBySelectionButton.classList.add("invisible");
|
this.csvBySelectionButton.classList.add("invisible");
|
||||||
// TODO: Add toggle via event listener
|
options.appendChild(this.csvBySelectionButton);
|
||||||
options.appendChild(csvBySelectionButton);
|
|
||||||
|
|
||||||
const optionSelectRequired = genButton("selectRequired", "Select required");
|
const optionSelectRequired = genButton("selectRequired", this.tls.select_required_fields);
|
||||||
options.appendChild(optionSelectRequired);
|
options.appendChild(optionSelectRequired);
|
||||||
|
|
||||||
const optionSelectAll = genButton("selectAll", "Select all");
|
const optionSelectAll = genButton("selectAll", this.tls.select_all_fields);
|
||||||
options.appendChild(optionSelectAll);
|
options.appendChild(optionSelectAll);
|
||||||
|
|
||||||
const unsetSelectionButton = genButton("unsetSelection", "Unset selection");
|
this.unsetSelectionButton = genButton("unsetSelection", this.tls.unset_selection);
|
||||||
unsetSelectionButton.classList.add("invisible");
|
this.unsetSelectionButton.classList.add("invisible");
|
||||||
// TODO: Add toggle via event listener
|
options.appendChild(this.unsetSelectionButton);
|
||||||
options.appendChild(unsetSelectionButton);
|
|
||||||
|
|
||||||
function checkCSVBySelectionAccessibility() {
|
this.csvBySelectionButton.addEventListener('click', function(e) {
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
let selected = document.getElementsByClassName("humanTLToggled");
|
let selected = document.getElementsByClassName("humanTLToggled");
|
||||||
let selectedFields = [];
|
let selectedFields = [];
|
||||||
|
@ -576,12 +708,12 @@ class CsvxmlPage {
|
||||||
|
|
||||||
optionSelectRequired.addEventListener('click', function(e) {
|
optionSelectRequired.addEventListener('click', function(e) {
|
||||||
|
|
||||||
doForFieldList(function(field) {
|
app.doForFieldList(function(field) {
|
||||||
if (field.classList.contains("requiredField") === false) return;
|
if (field.classList.contains("requiredField") === false) return;
|
||||||
if (field.classList.contains("humanTLToggled") === true) return;
|
if (field.classList.contains("humanTLToggled") === true) return;
|
||||||
|
|
||||||
toggleListFieldSelectionState(field);
|
app.toggleListFieldSelectionState(field);
|
||||||
checkCSVBySelectionAccessibility();
|
app.checkCSVBySelectionAccessibility();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -589,23 +721,23 @@ class CsvxmlPage {
|
||||||
|
|
||||||
optionSelectAll.addEventListener('click', function(e) {
|
optionSelectAll.addEventListener('click', function(e) {
|
||||||
|
|
||||||
doForFieldList(function(field) {
|
app.doForFieldList(function(field) {
|
||||||
if (field.classList.contains("humanTLToggled") === true) return;
|
if (field.classList.contains("humanTLToggled") === true) return;
|
||||||
|
|
||||||
toggleListFieldSelectionState(field);
|
app.toggleListFieldSelectionState(field);
|
||||||
checkCSVBySelectionAccessibility();
|
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;
|
if (field.classList.contains("humanTLToggled") === false) return;
|
||||||
|
|
||||||
toggleListFieldSelectionState(field);
|
app.toggleListFieldSelectionState(field);
|
||||||
checkCSVBySelectionAccessibility();
|
app.checkCSVBySelectionAccessibility();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -618,7 +750,7 @@ class CsvxmlPage {
|
||||||
renderMain() {
|
renderMain() {
|
||||||
|
|
||||||
const domH2 = document.createElement("h2");
|
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(domH2);
|
||||||
|
|
||||||
this.domMainWrapper.appendChild(this.getOptionsSection());
|
this.domMainWrapper.appendChild(this.getOptionsSection());
|
||||||
|
@ -634,8 +766,6 @@ class CsvxmlPage {
|
||||||
const domUl = document.createElement("ul");
|
const domUl = document.createElement("ul");
|
||||||
domUl.classList.add("fieldList");
|
domUl.classList.add("fieldList");
|
||||||
|
|
||||||
console.log(sectionName);
|
|
||||||
|
|
||||||
const sectionFields = this.fieldList[sectionName];
|
const sectionFields = this.fieldList[sectionName];
|
||||||
for (let fieldName in sectionFields) {
|
for (let fieldName in sectionFields) {
|
||||||
const field = sectionFields[fieldName];
|
const field = sectionFields[fieldName];
|
||||||
|
@ -648,7 +778,32 @@ class CsvxmlPage {
|
||||||
if (field.required === true) domLi.classList.add("requiredField");
|
if (field.required === true) domLi.classList.add("requiredField");
|
||||||
domUl.appendChild(domLi);
|
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);
|
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();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,30 @@
|
||||||
* @author Joshua Ramon Enslin <joshua@museum-digital.de>
|
* @author Joshua Ramon Enslin <joshua@museum-digital.de>
|
||||||
*/
|
*/
|
||||||
declare(strict_types = 1);
|
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 '
|
echo '
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
|
@ -18,7 +42,7 @@ echo '
|
||||||
<meta name="description" content="Validate import CSV files for museum-digital" />
|
<meta name="description" content="Validate import CSV files for museum-digital" />
|
||||||
<script src="assets/js/jszip/dist/jszip.min.js" type="text/javascript" async defer></script>
|
<script src="assets/js/jszip/dist/jszip.min.js" type="text/javascript" async defer></script>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css" />
|
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.css" />
|
||||||
<meta name="theme-color" content="#aa4400" />
|
<meta name="theme-color" content="#aa4400" />
|
||||||
<link rel="shortcut icon" sizes="128x128" href="assets/img/mdlogo-csvxml.svg" />
|
<link rel="shortcut icon" sizes="128x128" href="assets/img/mdlogo-csvxml.svg" />
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
|
@ -29,14 +53,34 @@ echo '
|
||||||
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="loading">
|
<body class="loading" data-tls="' . htmlspecialchars(MD_STD::json_encode([
|
||||||
|
'remarks' => $tlLoader->tl('basis', 'basis', 'remarks'),
|
||||||
|
'download' => $tlLoader->tl('export', 'export', 'download'),
|
||||||
|
'upload' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'upload'),
|
||||||
|
'select_csv_file_for_upload' => $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'),
|
||||||
|
])) . '">
|
||||||
|
|
||||||
<h1>
|
<h1>
|
||||||
<img src="assets/img/mdlogo-csvxml.svg" alt="" />
|
<img src="assets/img/mdlogo-csvxml.svg" alt="" />
|
||||||
<span>museum-digital:csvxml</span>
|
<span>museum-digital:csvxml</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<script src="assets/js/csvxmlV2.js" type="text/javascript" defer></script>
|
<script src="assets/js/csvxmlV2.js" type="text/javascript" async></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>';
|
</html>';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user