/* * The nopaque object is used as a namespace for nopaque specific functions and * variables. */ var nopaque = {}; // nopaque ressources nopaque.socket = undefined; nopaque.corpora = undefined; nopaque.corporaSubscribers = []; nopaque.jobs = undefined; nopaque.jobsSubscribers = []; nopaque.foreignCorpora = undefined; nopaque.foreignCorporaSubscribers = []; nopaque.foreignJobs = undefined; nopaque.foreignJobsSubscribers = []; nopaque.user = {}; nopaque.user.isAuthenticated = undefined; nopaque.user.settings = {} nopaque.user.settings.darkMode = undefined; nopaque.flashedMessages = undefined; // nopaque functions nopaque.socket = {}; nopaque.socket.init = function() { nopaque.socket = io({transports: ['websocket']}); // Add event handlers nopaque.socket.on("user_data_stream_init", function(msg) { nopaque.user = JSON.parse(msg); for (let subscriber of nopaque.corporaSubscribers) {subscriber._init(nopaque.user.corpora);} for (let subscriber of nopaque.jobsSubscribers) {subscriber._init(nopaque.user.jobs);} }); nopaque.socket.on("user_data_stream_update", function(msg) { var patch; patch = JSON.parse(msg); nopaque.user = jsonpatch.apply_patch(nopaque.user, patch); corpora_patch = patch.filter(operation => operation.path.startsWith("/corpora")); jobs_patch = patch.filter(operation => operation.path.startsWith("/jobs")); for (let subscriber of nopaque.corporaSubscribers) {subscriber._update(corpora_patch);} for (let subscriber of nopaque.jobsSubscribers) {subscriber._update(jobs_patch);} if (["all", "end"].includes(nopaque.user.settings.job_status_site_notifications)) { for (operation of jobs_patch) { /* "/jobs/{jobId}/..." -> ["{jobId}", ...] */ pathArray = operation.path.split("/").slice(2); if (operation.op === "replace" && pathArray[1] === "status") { if (nopaque.user.settings.job_status_site_notifications === "end" && !["complete", "failed"].includes(operation.value)) {continue;} nopaque.flash(`[${nopaque.user.jobs[pathArray[0]].title}] New status: ${operation.value}`, "job"); } } } }); nopaque.socket.on("foreign_user_data_stream_init", function(msg) { nopaque.foreignUser = JSON.parse(msg); for (let subscriber of nopaque.foreignCorporaSubscribers) {subscriber._init(nopaque.foreignUser.corpora);} for (let subscriber of nopaque.foreignJobsSubscribers) {subscriber._init(nopaque.foreignUser.jobs);} }); nopaque.socket.on("foreign_user_data_stream_update", function(msg) { var patch; patch = JSON.parse(msg); nopaque.foreignUser = jsonpatch.apply_patch(nopaque.foreignUser, patch); corpora_patch = patch.filter(operation => operation.path.startsWith("/corpora")); jobs_patch = patch.filter(operation => operation.path.startsWith("/jobs")); for (let subscriber of nopaque.foreignCorporaSubscribers) {subscriber._update(corpora_patch);} for (let subscriber of nopaque.foreignJobsSubscribers) {subscriber._update(jobs_patch);} }); } nopaque.Forms = {}; nopaque.Forms.init = function() { var abortRequestElement, parentElement, progressElement, progressModal, progressModalElement, request, submitElement; for (let form of document.querySelectorAll(".nopaque-submit-form")) { submitElement = form.querySelector('button[type="submit"]'); submitElement.addEventListener("click", function() { for (let selectElement of form.querySelectorAll('select')) { if (selectElement.value === "") { parentElement = selectElement.closest(".input-field"); parentElement.querySelector(".select-dropdown").classList.add("invalid"); for (let helperTextElement of parentElement.querySelectorAll(".helper-text")) { helperTextElement.remove(); } parentElement.insertAdjacentHTML("beforeend", `Please select an option.`); } } }); request = new XMLHttpRequest(); if (form.dataset.hasOwnProperty("progressModal")) { progressModalElement = document.getElementById(form.dataset.progressModal); progressModal = M.Modal.getInstance(progressModalElement); progressModal.options.dismissible = false; abortRequestElement = progressModalElement.querySelector(".abort-request"); abortRequestElement.addEventListener("click", function() {request.abort();}); progressElement = progressModalElement.querySelector(".determinate"); } form.addEventListener("submit", function(event) { event.preventDefault(); var formData; formData = new FormData(form); // Initialize progress modal if (progressModalElement) { progressElement.style.width = "0%"; progressModal.open(); } request.open("POST", window.location.href); request.send(formData); }); request.addEventListener("load", function(event) { var fieldElement; if (request.status === 201) { window.location.href = JSON.parse(this.responseText).redirect_url; } if (request.status === 400) { console.log(request); for (let [field, errors] of Object.entries(JSON.parse(this.responseText))) { fieldElement = form.querySelector(`input[name$="${field}"]`).closest(".input-field"); for (let error of errors) { fieldElement.insertAdjacentHTML("beforeend", `${error}`); } } if (progressModalElement) { progressModal.close(); } } if (request.status === 500) { location.reload(); } }); if (progressModalElement) { request.upload.addEventListener("progress", function(event) { progressElement.style.width = Math.floor(100 * event.loaded / event.total).toString() + "%"; }); } } } nopaque.Navigation = {}; nopaque.Navigation.init = function() { /* ### Initialize sidenav-main ### */ for (let entry of document.querySelectorAll("#sidenav-main a")) { if (entry.href === window.location.href) { entry.parentNode.classList.add("active"); } } } nopaque.flash = function() { var classes, toast, toastActionElement; switch (arguments.length) { case 1: category = "message"; message = arguments[0]; break; case 2: message = arguments[0]; category = arguments[1]; break; default: console.error("Usage: nopaque.flash(message) or nopaque.flash(message, category)") } switch (category) { case "corpus": message = `book${message}`; break; case "error": message = `error${message}`; break; case "job": message = `work${message}`; break; default: message = `notifications${message}`; } toast = M.toast({html: `${message} `}); toastActionElement = toast.el.querySelector('.toast-action[data-action="close"]'); if (toastActionElement) { toastActionElement.addEventListener("click", function() { toast.dismiss(); }); } } document.addEventListener("DOMContentLoaded", function() { // Disable all option elements with no value for (let optionElement of document.querySelectorAll('option[value=""]')) { optionElement.disabled = true; } M.AutoInit(); M.CharacterCounter.init(document.querySelectorAll('input[data-length][type="text"]')); M.Dropdown.init(document.querySelectorAll("#nav-notifications, #nav-account"), {alignment: "right", constrainWidth: false, coverTrigger: false}); nopaque.Forms.init(); nopaque.Navigation.init(); while (nopaque.flashedMessages.length) { flashedMessage = nopaque.flashedMessages.shift(); nopaque.flash(flashedMessage[1], flashedMessage[0]); } nopaque.socket.init(); nopaque.socket.emit("user_data_stream_init"); });