"use strict"; const MAX_INPUT_SIZE = 1048576; if ('serviceWorker' in navigator) { console.log("Registering service worker"); navigator.serviceWorker.register('/sw.js'); } class ConcPage { lang; tls; domWrapper; domUploaderWrapper; domResultsWrapper; domMainWrapper; constructor(lang, tls) { this.lang = lang; this.tls = Object.freeze(tls); let wrapper = document.createElement("div"); wrapper.id = "contentWrapper"; this.domWrapper = wrapper; let domUploaderWrapper = document.createElement("div"); domUploaderWrapper.id = "uploader"; domUploaderWrapper.classList.add("uploader"); this.domUploaderWrapper = domUploaderWrapper; let domResultsWrapper = document.createElement("div"); domResultsWrapper.id = "results"; domResultsWrapper.classList.add("results"); this.domResultsWrapper = domResultsWrapper; let domMainWrapper = document.createElement("main"); this.domMainWrapper = domMainWrapper; } downloadFromString(filename, text) { const blob = new Blob([text], { type: "text/plain" }); const link = document.createElement("a"); link.download = filename; link.href = window.URL.createObjectURL(blob); link.dataset.downloadurl = ["text/plain", link.download, link.href].join(":"); const evt = new MouseEvent("click", { view: window, bubbles: true, cancelable: true, }); link.dispatchEvent(evt); link.remove() } renderGenHeader() { const header = document.createElement("header"); header.id = "mainHeader"; const logoArea = document.createElement("a"); logoArea.id = "logoArea"; logoArea.href = "https://www.museum-digital.org/"; const logoImg = document.createElement("img"); logoImg.src = "/static/img/mdlogo-code.svg"; 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"); appHeader.id = "appHeader"; const h1 = document.createElement("h1"); const img = document.createElement("img"); img.width = "70"; img.height = "70"; img.src = "/static/img/mdlogo-code.svg"; img.alt = ""; h1.appendChild(img); h1.appendChild(this.createPlainTextElem("span", "museum-digital:" + this.tls.concordance_checker)); appHeader.appendChild(h1); document.body.appendChild(appHeader); } createP(text) { const output = document.createElement("p"); output.textContent = text; return output; } createPlainTextElem(type, text) { const output = document.createElement(type); output.textContent = text; return output; } renderText() { const domH2 = document.createElement("h2"); domH2.textContent = this.tls.quality_assessment_tools; this.domMainWrapper.appendChild(domH2); this.domMainWrapper.appendChild(this.createP(this.tls.intro)); this.domWrapper.appendChild(this.domMainWrapper); } generateBoilerplateForTableSection(hl) { const passedSec = document.createElement("div"); const passedHl = document.createElement("h3"); passedHl.textContent = hl; passedSec.appendChild(passedHl); const passedTable = document.createElement("table"); const passedThead = document.createElement("thead"); passedTable.appendChild(passedThead); const passedTBody = document.createElement("tbody"); passedTable.appendChild(passedTBody); passedSec.appendChild(passedTable); return { section: passedSec, thead: passedThead, tbody: passedTBody, }; } generateListResponse(context, listOptionsEn, listOptions, elements) { // Empty while (this.domResultsWrapper.firstChild) { this.domResultsWrapper.removeChild(this.domResultsWrapper.firstChild); } // Fill passed entries if (elements.passed.length === undefined) { const passedSec = this.generateBoilerplateForTableSection(this.tls.passed); // TL TODO const theadTr = document.createElement("tr"); for (const theadname of ['Input', 'Match']) { const theadTd = document.createElement("th"); theadTd.textContent = theadname; theadTr.appendChild(theadTd); } passedSec.thead.appendChild(theadTr); for (const passedKey in elements.passed) { const passedValue = elements.passed[passedKey]; const tr = document.createElement("tr"); tr.appendChild(this.createPlainTextElem("td", passedKey)); if (listOptions[passedValue]) { tr.appendChild(this.createPlainTextElem("td", listOptions[passedValue])); } else { valueTd.textContent = passedValue; tr.appendChild(this.createPlainTextElem("td", passedValue)); } passedSec.tbody.appendChild(tr); } this.domResultsWrapper.appendChild(passedSec.section); } // Fill unpassed entries const app = this; if (elements.not_passed.length !== 0) { const nonpassedSec = this.generateBoilerplateForTableSection(this.tls.not_yet_matched); const ntheadTr = document.createElement("tr"); for (const theadname of ['Input', 'Select Your Match']) { const theadTd = document.createElement("th"); theadTd.textContent = theadname; ntheadTr.appendChild(theadTd); } nonpassedSec.thead.appendChild(ntheadTr); let matchSelects = []; for (let nonpassedName of elements.not_passed) { const tr = document.createElement("tr"); tr.appendChild(this.createPlainTextElem("td", nonpassedName)); const valueTd = document.createElement("td"); const valueSelect = document.createElement("select"); valueSelect.setAttribute('data-input', nonpassedName); for (const key in listOptions) { const opt = document.createElement("option"); opt.value = key; opt.textContent = listOptions[key]; valueSelect.appendChild(opt); } matchSelects.push(valueSelect); valueTd.appendChild(valueSelect); tr.appendChild(valueTd); nonpassedSec.tbody.appendChild(tr); } this.domResultsWrapper.appendChild(nonpassedSec.section); const convertB = document.createElement("button"); convertB.textContent = this.tls.generate_code_snippet; nonpassedSec.section.appendChild(convertB); const resultsWrap = document.createElement("div"); convertB.addEventListener('click', function() { let lines = []; let keysAreNumeric = false; if (listOptions[1] !== undefined && listOptions[1] !== null) { keysAreNumeric = true; } for (let m of matchSelects) { let line = ("'" + m.getAttribute("data-input") + "'").padEnd(40, " ") + " => "; if (keysAreNumeric === true) { line += m.value + ","; } else { line += "'" + m.value + "',"; } line += ' // ' + listOptionsEn[m.value]; lines.push(line); m.setAttribute("readonly", "readonly"); } const output = " ".repeat(8) + lines.join("\n" + " ".repeat(8)); console.log(output); // Present output online const resultsP = app.createP(output); resultsP.id = "resultsP"; resultsP.style.fontFamily = "Monospace, Courier"; resultsP.style.whiteSpace = "pre-wrap"; resultsWrap.appendChild(resultsP); resultsP.scrollIntoView({block: "start", behavior: "smooth"}); // Download app.downloadFromString("new-concordance-" + context + '.htm', output); }); this.domResultsWrapper.appendChild(resultsWrap); } this.domResultsWrapper.scrollIntoView({block: "start", behavior: "smooth"}); // } // Setup renderUploader() { const listSelect = document.createElement("select"); const listOptions = document.documentElement.getAttribute("data-lists").split(','); for (const lOpt of listOptions) { const opt = document.createElement("option"); opt.textContent = this.tls[lOpt]; opt.value = lOpt; listSelect.appendChild(opt); } this.domUploaderWrapper.appendChild(listSelect); const textarea = document.createElement("textarea"); textarea.placeholder = this.tls.one_line_per_entry; this.domUploaderWrapper.appendChild(textarea); const submitB = document.createElement("button"); submitB.textContent = this.tls.submit; this.domUploaderWrapper.appendChild(submitB); const app = this; submitB.addEventListener('click', async function(e) { e.stopPropagation(); e.preventDefault(); // Load translations in English const listResponseEn = await window.fetch('/static/json/tls.' + listSelect.value + '.en.json', { method: 'GET', cache: 'no-cache', }); if (listResponseEn.status !== 200) { const text = await response.text(); window.alert(text); } const tListOptionsEn = await listResponseEn.json(); // Load translations const listResponse = await window.fetch('/static/json/tls.' + listSelect.value + '.' + app.lang + '.json', { method: 'GET', cache: 'no-cache', }); if (listResponse.status !== 200) { const text = await response.text(); window.alert(text); } const tListOptions = await listResponse.json(); // Get API output let requestBody = []; requestBody.push('terms=' + encodeURIComponent(textarea.value)); const response = await window.fetch('/api/evaluate/' + listSelect.value, { method: 'POST', cache: 'no-cache', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: requestBody.join("&"), }); if (response.status !== 200) { const text = await response.text(); window.alert(text); } const elements = await response.json(); app.generateListResponse(listSelect.value, tListOptionsEn, tListOptions, elements); }); this.domWrapper.appendChild(this.domUploaderWrapper); this.domWrapper.appendChild(this.domResultsWrapper); } renderFooter() { const footer = document.createElement("footer"); /* const licenseStatement = document.createElement("p"); licenseStatement.textContent = "This work is licensed under the GNU Affero Public License Version 3."; footer.appendChild(licenseStatement); */ const footerOptions = document.createElement("div"); /* const codeLink = document.createElement("a"); codeLink.textContent = "Source code"; codeLink.href = "https://gitea.armuli.eu/museum-digital/csvxml"; footerOptions.appendChild(codeLink); */ /* const codeLink = document.createElement("a"); codeLink.textContent = "API"; // TODO codeLink.href = "/swagger"; footerOptions.appendChild(codeLink); */ if ('serviceWorker' in navigator) { const refreshB = document.createElement("span"); refreshB.textContent = this.tls.reload_application; refreshB.setAttribute("tabindex", 1); refreshB.addEventListener('click', function(e) { Promise.all(['conc-cache-v1'].map(function(cache) { caches.has(cache).then(function(hasCache) { if (hasCache === true) { caches.delete(cache).then(function(deletionStatus) {}); } }) })) location.reload() }, {passive: true, once: true}); footerOptions.appendChild(refreshB); } const allowedLangs = document.documentElement.getAttribute("data-allowed-langs").split(','); const langSel = document.createElement("div"); for (let lang of allowedLangs) { const l = document.createElement("a"); l.href = "#" + lang; l.textContent = lang; l.style.textTranform = "uppercase"; l.addEventListener('click', function(e) { e.preventDefault(); sessionStorage.setItem("lang", lang); location.reload(); }); langSel.appendChild(l); } footerOptions.appendChild(langSel); footer.appendChild(footerOptions); const licenseLine = document.createElement("p"); const license = document.createElement("a"); license.textContent = "MIT-Licensed"; license.href = "https://opensource.org/license/mit"; licenseLine.appendChild(license); licenseLine.appendChild(this.createPlainTextElem("span", " @ ")); const author = document.createElement("a"); author.textContent = "Joshua Ramon Enslin"; author.href = "https://www.jrenslin.de"; author.setAttribute("rel", "author"); licenseLine.appendChild(author); licenseLine.appendChild(this.createPlainTextElem("span", ", ")); const attributionYear = document.createElement("span"); attributionYear.textContent = "2023"; licenseLine.appendChild(attributionYear); footer.appendChild(licenseLine); document.body.appendChild(footer); } } (async function() { function getLang() { const allowedLangs = document.documentElement.getAttribute("data-allowed-langs").split(','); const langFromSession = sessionStorage.getItem("lang"); if (langFromSession !== undefined && allowedLangs.includes(langFromSession)) { return langFromSession; } if (navigator.language === undefined) return 'en'; const browserLang = navigator.language.toLowerCase().substr(0, 2); console.log(browserLang); if (allowedLangs.includes(browserLang)) return browserLang; else return 'en'; } const lang = getLang(); document.documentElement.setAttribute("lang", lang); document.body.classList.add("loading"); let loaded = 0; let tls; function loadPage() { document.body.classList.remove("loading"); const page = new ConcPage(lang, tls); page.renderGenHeader(); page.renderHeader(); page.renderText(); page.renderUploader(); document.body.appendChild(page.domWrapper); page.renderFooter(); } window.fetch('/static/json/tls.' + lang + '.json', { method: 'GET', cache: 'no-cache', credentials: 'same-origin', }).then(function(response) { return response.json(); }).then(function(elements) { tls = elements; loadPage(); }); })();