Project import generated by Copybara.
GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/src/js/calendar.js b/src/js/calendar.js
new file mode 100644
index 0000000..920bf98
--- /dev/null
+++ b/src/js/calendar.js
@@ -0,0 +1,8 @@
+document.addEventListener("DOMContentLoaded", _ => {
+ document.querySelectorAll("select").forEach(el => {
+ el.addEventListener("change", _ => {
+ el.setAttribute("data-value", el.value);
+ });
+ el.setAttribute("data-value", el.value);
+ });
+});
diff --git a/src/js/categories.js b/src/js/categories.js
new file mode 100644
index 0000000..412f585
--- /dev/null
+++ b/src/js/categories.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addcategory").addEventListener("click", function() {
+ document.querySelector("#addcategory").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/common.js b/src/js/common.js
new file mode 100644
index 0000000..445016e
--- /dev/null
+++ b/src/js/common.js
@@ -0,0 +1,242 @@
+/**
+ * Functions hasClass(), addClass() and removeClass() developed by Jake Trent (http://jaketrent.com/post/addremove-classes-raw-javascript/)
+ */
+function hasClass(el, className) {
+ if (el.classList)
+ return el.classList.contains(className)
+ else
+ return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
+}
+
+function addClass(el, className) {
+ if (el.classList)
+ el.classList.add(className)
+ else if (!hasClass(el, className)) el.className += " " + className
+}
+
+function removeClass(el, className) {
+ if (el.classList)
+ el.classList.remove(className)
+ else if (hasClass(el, className)) {
+ var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
+ el.className=el.className.replace(reg, ' ')
+ }
+}
+
+// MultiSelect implementation:
+var MultiSelect = function MultiSelect(element) {
+ this.element_ = element;
+ this.selected_ = [];
+
+ var forElId = this.element_.getAttribute("for") || this.element_.getAttribute("data-for");
+ if (forElId) {
+ this.forEl_ = (forElId ? document.getElementById(this.element_.getAttribute("for")) : null);
+ }
+
+ this.init();
+};
+
+MultiSelect.prototype.renderSummary = function() {
+ if (this.forEl_) {
+ this.forEl_.innerText = this.selected_.join(", ") || "-";
+ }
+};
+
+MultiSelect.prototype.init = function() {
+ if (this.element_) {
+ this.element_.addEventListener("click", e => {
+ e.stopImmediatePropagation();
+ }, true);
+
+ this.element_.querySelectorAll(".mdl-custom-multiselect__item").forEach(item => {
+ var checkbox = item.querySelector("input[type=\"checkbox\"]");
+ var label = item.querySelector(".mdl-checkbox__label").innerText;
+ checkbox.addEventListener("change", e => {
+ if(checkbox.checked) {
+ this.selected_.push(label);
+ } else {
+ this.selected_ = this.selected_.filter(item => item !== label);
+ }
+ this.renderSummary();
+
+ var customEvent = new Event('custom-multiselect-change');
+ this.element_.dispatchEvent(customEvent);
+ });
+ });
+ }
+};
+
+var dynDialog = {
+ didItInit: false,
+ dialog: null,
+ url: null,
+ load: function(url, reload) {
+ if (this.didItInit === false) {
+ this.init();
+ }
+
+ if (this.url == url && reload !== true) {
+ this.show();
+ return;
+ }
+
+ this.url = url;
+
+ fetch(url).then(response => response.text()).then(response => {
+ if (this.dialog.open) {
+ this.close();
+ }
+
+ this.dialog.innerHTML = response;
+ componentHandler.upgradeElements(this.dialog);
+
+ this.dialog.querySelectorAll("[data-required]").forEach(input => {
+ input.setAttribute("required", "true");
+ });
+
+ var script = this.dialog.querySelectorAll("dynscript");
+ if (script.length > 0) {
+ for (var i = 0; i < script.length; i++) {
+ eval(script[i].innerText);
+ }
+ }
+ this.dialog.querySelectorAll("[data-dyndialog-close]").forEach(btn => {
+ btn.addEventListener("click", e => {
+ e.preventDefault();
+ this.close();
+ });
+ });
+
+ this.dialog.showModal();
+ });
+ },
+ reload: function() {
+ this.load(this.url, true);
+ },
+ show: function() {
+ this.dialog.showModal();
+ },
+ close: function() {
+ this.dialog.close();
+ },
+ init: function() {
+ this.dialog = document.createElement("dialog");
+ this.dialog.setAttribute("id", "dynDialog");
+ this.dialog.setAttribute("class", "mdl-dialog");
+ dialogPolyfill.registerDialog(this.dialog);
+ document.body.appendChild(this.dialog);
+
+ this.didItInit = true;
+ }
+};
+
+// From nodep-date-input-polyfill
+function isDateInputSupported() {
+ const input = document.createElement("input");
+ input.setAttribute("type", "date");
+
+ const notADateValue = "not-a-date";
+ input.setAttribute("value", notADateValue);
+
+ return (input.value !== notADateValue);
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ var dialogs = document.querySelectorAll("dialog");
+ for (var i = 0; i < dialogs.length; i++) {
+ dialogPolyfill.registerDialog(dialogs[i]);
+ }
+
+ document.querySelectorAll("[data-dyndialog-href]").forEach(link => {
+ link.addEventListener("click", e => {
+ e.preventDefault();
+ dynDialog.load(link.getAttribute("data-dyndialog-href"));
+ });
+ });
+
+ document.querySelectorAll(".mdl-custom-multiselect-js").forEach(menu => {
+ new MultiSelect(menu);
+ });
+});
+
+function importCSS(url) {
+ var link = document.createElement("link");
+ link.setAttribute("rel", "stylesheet");
+ link.setAttribute("href", url);
+ document.head.appendChild(link);
+}
+
+var loadScriptAsync = function(uri) {
+ return new Promise((resolve, reject) => {
+ var script = document.createElement('script');
+ script.src = uri;
+ script.async = true;
+ script.onload = () => {
+ resolve();
+ };
+ document.head.appendChild(script);
+ });
+}
+
+function hasParentDialog(el) {
+ while (el != document.documentElement) {
+ if (el.tagName == "DIALOG") {
+ return el;
+ }
+
+ el = el.parentNode;
+ }
+
+ return undefined;
+}
+
+function polyfillDateSupport(container) {
+ container.querySelectorAll("input[type=\"date\"]").forEach(el => {
+ el.setAttribute("type", "text");
+
+ dialogParent = hasParentDialog(el);
+
+ var options = {
+ format: "yyyy-mm-dd",
+ todayHighlight: true,
+ weekStart: 1,
+ zIndexOffset: 100,
+ container: dialogParent || container
+ };
+
+ if (el.hasAttribute("max")) {
+ options.endDate = el.getAttribute("max");
+ }
+
+ $(el).datepicker(options);
+ });
+
+ container.querySelectorAll("input[type=\"time\"]").forEach(el => {
+ el.setAttribute("placeholder", "hh:mm");
+ });
+}
+
+function initPolyfillDateSupport() {
+ console.info("Polyfilling date support");
+
+ importCSS("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/css/bootstrap-datepicker3.standalone.min.css", "css");
+
+ loadScriptAsync("https://unpkg.com/jquery@3.4.1/dist/jquery.min.js", "js").then(_ => {
+ return loadScriptAsync("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/js/bootstrap-datepicker.min.js");
+ }).then(_ => {
+ return loadScriptAsync("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/locales/bootstrap-datepicker.es.min.js");
+ }).then(_ => {
+ console.log("[Date polyfill] Scripts loaded.");
+ polyfillDateSupport(document.documentElement);
+ });
+}
+
+window.addEventListener("load", function() {
+ document.querySelectorAll("[data-required]").forEach(input => {
+ input.setAttribute("required", "true");
+ });
+
+ if (!isDateInputSupported()) {
+ initPolyfillDateSupport();
+ }
+});
diff --git a/src/js/common_webauthn.js b/src/js/common_webauthn.js
new file mode 100644
index 0000000..fa95364
--- /dev/null
+++ b/src/js/common_webauthn.js
@@ -0,0 +1,44 @@
+/**
+ * convert RFC 1342-like base64 strings to array buffer
+ * @param {mixed} obj
+ * @returns {undefined}
+ */
+function recursiveBase64StrToArrayBuffer(obj) {
+ let prefix = '=?BINARY?B?';
+ let suffix = '?=';
+ if (typeof obj === 'object') {
+ for (let key in obj) {
+ if (typeof obj[key] === 'string') {
+ let str = obj[key];
+ if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {
+ str = str.substring(prefix.length, str.length - suffix.length);
+
+ let binary_string = window.atob(str);
+ let len = binary_string.length;
+ let bytes = new Uint8Array(len);
+ for (var i = 0; i < len; i++) {
+ bytes[i] = binary_string.charCodeAt(i);
+ }
+ obj[key] = bytes.buffer;
+ }
+ } else {
+ recursiveBase64StrToArrayBuffer(obj[key]);
+ }
+ }
+ }
+}
+
+/**
+ * Convert a ArrayBuffer to Base64
+ * @param {ArrayBuffer} buffer
+ * @returns {String}
+ */
+function arrayBufferToBase64(buffer) {
+ var binary = '';
+ var bytes = new Uint8Array(buffer);
+ var len = bytes.byteLength;
+ for (var i = 0; i < len; i++) {
+ binary += String.fromCharCode( bytes[ i ] );
+ }
+ return window.btoa(binary);
+}
diff --git a/src/js/companies.js b/src/js/companies.js
new file mode 100644
index 0000000..aa8d9dd
--- /dev/null
+++ b/src/js/companies.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addcompany").addEventListener("click", function() {
+ document.querySelector("#addcompany").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/export.js b/src/js/export.js
new file mode 100644
index 0000000..9bdbbbe
--- /dev/null
+++ b/src/js/export.js
@@ -0,0 +1,71 @@
+function toggleTr(tr, show) {
+ var checkbox = tr.querySelector("label").MaterialCheckbox;
+ if (show) {
+ tr.style.display = "table-row";
+ checkbox.enable();
+ } else {
+ tr.style.display = "none";
+ checkbox.disable();
+ }
+}
+
+window.addEventListener("load", function() {
+ document.querySelectorAll("tr[data-worker-id]").forEach(tr => {
+ var checkbox = tr.querySelector("input[type=\"checkbox\"]");
+
+ checkbox.setAttribute("name", "workers[]");
+ checkbox.setAttribute("value", tr.getAttribute("data-worker-id"));
+
+ toggleTr(tr, false);
+ });
+
+ document.querySelectorAll(".select-all").forEach(el => {
+ el.addEventListener("click", e => {
+ var allchecked = true;
+ el.getAttribute("data-workers").split(",").forEach(workerid => {
+ var tr = document.querySelector("tr[data-worker-id=\""+workerid+"\"]");
+ var checkbox = tr.querySelector("label").MaterialCheckbox;
+ if (checkbox.inputElement_.disabled) return;
+ if (!checkbox.inputElement_.checked) allchecked = false;
+ tr.classList.add("is-selected");
+ checkbox.check();
+ });
+
+ if (allchecked) {
+ el.getAttribute("data-workers").split(",").forEach(workerid => {
+ var tr = document.querySelector("tr[data-worker-id=\""+workerid+"\"]");
+ var checkbox = tr.querySelector("label").MaterialCheckbox;
+ tr.classList.remove("is-selected");
+ checkbox.uncheck();
+ });
+ }
+ });
+ });
+
+ var multiselectEl = document.querySelector(".mdl-custom-multiselect");
+ if (multiselectEl !== null) {
+ multiselectEl.addEventListener("custom-multiselect-change", e => {
+ var companies = [];
+ document.querySelectorAll(".mdl-custom-multiselect .mdl-custom-multiselect__item input[type=\"checkbox\"]").forEach(checkbox => {
+ if (checkbox.checked) {
+ companies.push(checkbox.value);
+ }
+ });
+
+ document.querySelectorAll("tr[data-worker-id]").forEach(tr => {
+ toggleTr(tr, companies.includes(tr.getAttribute("data-company-id")));
+ });
+ });
+ }
+
+ document.querySelectorAll("input[name=\"companies\[\]\"]").forEach(input => {
+ input.checked = true;
+ var customevent = document.createEvent("HTMLEvents");
+ customevent.initEvent("change", false, true);
+ input.dispatchEvent(customevent);
+ });
+
+ document.getElementById("format").addEventListener("change", e => {
+ document.getElementById("pdf").style.display = (document.getElementById("format").value != "1" && document.getElementById("format").value != "2" ? "none" : "block");
+ });
+});
diff --git a/src/js/incidents.js b/src/js/incidents.js
new file mode 100644
index 0000000..0397cac
--- /dev/null
+++ b/src/js/incidents.js
@@ -0,0 +1,79 @@
+function getFormData() {
+ var incidents = [];
+
+ document.querySelectorAll("input[type=\"checkbox\"][data-incident]:checked").forEach(el => {
+ incidents.push(el.getAttribute("data-incident"));
+ });
+
+ return incidents;
+}
+
+function getParameters() {
+ var parameters = [];
+ var incidents = getFormData();
+ incidents.forEach(incident => {
+ parameters.push("incidents[]="+incident);
+ });
+
+ if (parameters.length == 0) return false;
+
+ return parameters.join("&");
+}
+
+window.addEventListener("load", function() {
+ document.querySelector(".addincident").addEventListener("click", function() {
+ document.querySelector("#addincident").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ document.querySelector(".addrecurringincident").addEventListener("click", function() {
+ document.querySelector("#addrecurringincident").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ document.querySelector(".filter").addEventListener("click", function() {
+ document.querySelector("#filter").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ if (_showResultsPaginated) {
+ document.getElementById("limit-change").addEventListener("change", _ => {
+ var limit = parseInt(document.getElementById("limit-change").value);
+ var firstIncidentPos = _page*_limit;
+ var page = Math.floor(firstIncidentPos/limit) + 1;
+
+ var url = new URL(location.href);
+ url.searchParams.set("limit", limit);
+ url.searchParams.set("page", page);
+ location.href = url;
+ });
+ }
+
+ document.querySelectorAll(".mdl-checkbox[data-check-all=\"true\"] input[type=\"checkbox\"]").forEach(el => {
+ el.addEventListener("change", e => {
+ el.parentElement.parentElement.parentElement.parentElement.parentElement.querySelectorAll(".mdl-checkbox:not([data-check-all=\"true\"])").forEach(input => {
+ var checkbox = input.MaterialCheckbox;
+ if (checkbox.inputElement_.disabled) return;
+
+ if (el.checked) checkbox.check();
+ else checkbox.uncheck();
+ });
+ });
+ });
+
+ document.getElementById("deleteincidentsbulk").addEventListener("click", e => {
+ var parameters = getParameters();
+
+ if (parameters === false) {
+ document.querySelector(".mdl-js-snackbar").MaterialSnackbar.showSnackbar({
+ message: "Debes seleccionar al menos una incidencia para poder eliminar.",
+ timeout: 5000
+ });
+
+ return;
+ }
+
+ var url = "dynamic/deleteincidentsbulk.php?"+parameters;
+ dynDialog.load(url);
+ });
+});
diff --git a/src/js/incidentsgeneric.js b/src/js/incidentsgeneric.js
new file mode 100644
index 0000000..5d1323f
--- /dev/null
+++ b/src/js/incidentsgeneric.js
@@ -0,0 +1,13 @@
+window.addEventListener("load", function() {
+
+ document.querySelectorAll(".custom-actions-btn").forEach(el => {
+ el.addEventListener("click", e => {
+ var forId = el.getAttribute("id");
+ var menu = document.querySelector("[for=\""+forId+"\"]").parentElement;
+ var overflow = menu.parentElement;
+
+ menu.style.left = el.offsetLeft - menu.offsetWidth + el.offsetWidth - overflow.scrollLeft + 'px';
+ menu.style.top = el.offsetTop + el.offsetHeight - overflow.scrollTop + 'px';
+ });
+ });
+});
diff --git a/src/js/incidenttypes.js b/src/js/incidenttypes.js
new file mode 100644
index 0000000..48e8ae4
--- /dev/null
+++ b/src/js/incidenttypes.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addincident").addEventListener("click", function() {
+ document.querySelector("#addincident").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/index.js b/src/js/index.js
new file mode 100644
index 0000000..8af86b3
--- /dev/null
+++ b/src/js/index.js
@@ -0,0 +1,8 @@
+window.addEventListener("load", function() {
+ if (document.querySelector("#recoverybtn")) {
+ document.querySelector("#recoverybtn").addEventListener("click", function(e) {
+ e.preventDefault();
+ document.querySelector("#recovery").showModal();
+ });
+ }
+});
diff --git a/src/js/invalidatebulkrecords.js b/src/js/invalidatebulkrecords.js
new file mode 100644
index 0000000..cfbe2d5
--- /dev/null
+++ b/src/js/invalidatebulkrecords.js
@@ -0,0 +1,8 @@
+window.addEventListener("load", function() {
+ document.querySelectorAll("tr[data-worker-id]").forEach(tr => {
+ var checkbox = tr.querySelector("input[type=\"checkbox\"]");
+
+ checkbox.setAttribute("name", "workers[]");
+ checkbox.setAttribute("value", tr.getAttribute("data-worker-id"));
+ });
+});
diff --git a/src/js/registry.js b/src/js/registry.js
new file mode 100644
index 0000000..807c4fd
--- /dev/null
+++ b/src/js/registry.js
@@ -0,0 +1,5 @@
+window.addEventListener("load", _ => {
+ document.getElementById("showinvalidated").addEventListener("change", e => {
+ document.getElementById("show-invalidated-form").submit();
+ });
+});
diff --git a/src/js/schedule.js b/src/js/schedule.js
new file mode 100644
index 0000000..d804872
--- /dev/null
+++ b/src/js/schedule.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addday").addEventListener("click", function() {
+ document.querySelector("#addday").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/scheduletemplates.js b/src/js/scheduletemplates.js
new file mode 100644
index 0000000..a236064
--- /dev/null
+++ b/src/js/scheduletemplates.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addtemplate").addEventListener("click", function() {
+ document.querySelector("#addtemplate").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/secondfactor.js b/src/js/secondfactor.js
new file mode 100644
index 0000000..f537146
--- /dev/null
+++ b/src/js/secondfactor.js
@@ -0,0 +1,107 @@
+function verify() {
+ if (!document.getElementById("code").checkValidity()) {
+ document.querySelector(".mdl-js-snackbar").MaterialSnackbar.showSnackbar({
+ message: "El código de verificación debe tener 6 cifras."
+ });
+
+ return;
+ }
+
+ var body = {
+ code: document.getElementById("code").value
+ };
+
+ var content = document.getElementById("content");
+ content.innerHTML = '<div class="mdl-spinner mdl-js-spinner is-active"></div>';
+ content.style.textAlign = "center";
+ componentHandler.upgradeElements(content);
+
+ fetch("ajax/verifysecuritycode.php", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify(body)
+ }).then(response => {
+ if (response.status !== 200) {
+ throw new Error("HTTP status is not 200.");
+ }
+
+ return response.json();
+ }).then(response => {
+ switch (response.status) {
+ case "ok":
+ document.location = "index.php";
+ break;
+
+ case "wrongCode":
+ document.location = "index.php?msg=secondfactorwrongcode";
+ break;
+
+ default:
+ console.error("An unknown status code was returned.");
+ }
+ }).catch(err => console.error("An unexpected error occurred.", err));
+}
+
+function verifyKeypress(e) {
+ if (event.keyCode == 13) {
+ verify();
+ }
+}
+
+function startWebauthn() {
+ fetch("ajax/startwebauthnauthentication.php", {
+ method: "POST"
+ }).then(response => {
+ if (response.status !== 200) {
+ response.text(); // @TODO: Remove this. It is only used so the response is available in Chrome Dev Tools
+ throw new Error("HTTP status is not 200.");
+ }
+
+ return response.json();
+ }).then(response => {
+ recursiveBase64StrToArrayBuffer(response);
+ return response;
+ }).then(getCredentialArgs => {
+ return navigator.credentials.get(getCredentialArgs);
+ }).then(cred => {
+ return {
+ id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
+ clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
+ authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
+ signature : cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null
+ };
+ }).then(JSON.stringify).then(AuthenticatorAttestationResponse => {
+ return window.fetch("ajax/completewebauthnauthentication.php", {
+ method: "POST",
+ body: AuthenticatorAttestationResponse,
+ });
+ }).then(response => {
+ if (response.status !== 200) {
+ response.text(); // @TODO: remove this. It is only used so the response is available in Chrome Dev Tools
+ throw new Error("HTTP status is not 200 (2).");
+ }
+
+ return response.json();
+ }).then(json => {
+ if (json.status == "ok") {
+ document.location = "index.php";
+ }
+ }).catch(err => console.error("An unexpected error occurred.", err));
+}
+
+window.addEventListener("load", function() {
+ if (document.getElementById("totp")) {
+ document.getElementById("verify").addEventListener("click", verify);
+ document.getElementById("code").addEventListener("keypress", verifyKeypress);
+ document.getElementById("code").focus();
+ document.querySelector("a[href=\"#totp\"]").addEventListener("click", _ => {
+ document.getElementById("code").focus();
+ });
+ }
+
+ if (document.getElementById("startwebauthn")) {
+ document.getElementById("startwebauthn").addEventListener("click", startWebauthn);
+ }
+});
diff --git a/src/js/securitykeys.js b/src/js/securitykeys.js
new file mode 100644
index 0000000..9f08e21
--- /dev/null
+++ b/src/js/securitykeys.js
@@ -0,0 +1,50 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addsecuritykey").addEventListener("click", function() {
+ document.querySelector("#addsecuritykey").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ document.getElementById("registersecuritykey").addEventListener("click", e => {
+ e.preventDefault();
+
+ if (document.getElementById("addsecuritykeyform").reportValidity()) {
+ fetch("ajax/addsecuritykey.php", {
+ method: "POST"
+ }).then(response => {
+ if (response.status !== 200) {
+ response.text(); // @TODO: Remove this. It is only used so the response is available in Chrome Dev Tools
+ throw new Error("HTTP status is not 200.");
+ }
+
+ return response.json();
+ }).then(response => {
+ recursiveBase64StrToArrayBuffer(response);
+ return response;
+ }).then(createCredentialArgs => {
+ return navigator.credentials.create(createCredentialArgs);
+ }).then(cred => {
+ return {
+ clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
+ attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null,
+ name: document.getElementById("name").value
+ };
+ }).then(JSON.stringify).then(AuthenticatorAttestationResponse => {
+ return window.fetch("ajax/addsecuritykey2.php", {
+ method: "POST",
+ body: AuthenticatorAttestationResponse,
+ });
+ }).then(response => {
+ if (response.status !== 200) {
+ response.text(); // @TODO: remove this. It is only used so the response is available in Chrome Dev Tools
+ throw new Error("HTTP status is not 200 (2).");
+ }
+
+ return response.json();
+ }).then(json => {
+ if (json.status == "ok") {
+ document.location = "securitykeys.php?msg=securitykeyadded";
+ }
+ }).catch(err => console.error("An unexpected error occurred.", err));
+ }
+ });
+});
diff --git a/src/js/sendbulkpasswords.js b/src/js/sendbulkpasswords.js
new file mode 100644
index 0000000..bb6ac26
--- /dev/null
+++ b/src/js/sendbulkpasswords.js
@@ -0,0 +1,8 @@
+window.addEventListener("load", function() {
+ document.querySelectorAll("tr[data-person-id]").forEach(tr => {
+ var checkbox = tr.querySelector("input[type=\"checkbox\"]");
+
+ checkbox.setAttribute("name", "people[]");
+ checkbox.setAttribute("value", tr.getAttribute("data-person-id"));
+ });
+});
diff --git a/src/js/userincidents.js b/src/js/userincidents.js
new file mode 100644
index 0000000..48e8ae4
--- /dev/null
+++ b/src/js/userincidents.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addincident").addEventListener("click", function() {
+ document.querySelector("#addincident").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/users.js b/src/js/users.js
new file mode 100644
index 0000000..9eb383e
--- /dev/null
+++ b/src/js/users.js
@@ -0,0 +1,28 @@
+window.addEventListener("load", function() {
+ var datatable = $('.datatable').DataTable({
+ paging: false,
+ ordering: false,
+ info: false,
+ searching:true
+ });
+
+ document.querySelector("#usuario").addEventListener("input", function(evt) {
+ this.search(evt.target.value);
+ this.draw(true);
+ }.bind(datatable));
+
+ document.querySelector(".adduser").addEventListener("click", function() {
+ document.querySelector("#adduser").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ document.querySelector(".importcsv").addEventListener("click", function() {
+ document.querySelector("#importcsv").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ document.querySelector(".filter").addEventListener("click", function() {
+ document.querySelector("#filter").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/userschedule.js b/src/js/userschedule.js
new file mode 100644
index 0000000..0fa39cb
--- /dev/null
+++ b/src/js/userschedule.js
@@ -0,0 +1,6 @@
+window.addEventListener("load", function() {
+ document.querySelector(".addschedule").addEventListener("click", function() {
+ document.querySelector("#addschedule").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+});
diff --git a/src/js/validations.js b/src/js/validations.js
new file mode 100644
index 0000000..cecd3b7
--- /dev/null
+++ b/src/js/validations.js
@@ -0,0 +1,55 @@
+function getFormData() {
+ var data = {
+ "incidents": [],
+ "records": []
+ };
+
+ ["incident", "record"].forEach(key => {
+ document.querySelectorAll("input[type=\"checkbox\"][data-"+key+"]:checked").forEach(el => {
+ data[key+"s"].push(el.getAttribute("data-"+key));
+ });
+ });
+
+ return data;
+}
+
+window.addEventListener("load", function() {
+ document.querySelectorAll(".mdl-checkbox[data-check-all=\"true\"] input[type=\"checkbox\"]").forEach(el => {
+ el.addEventListener("change", e => {
+ el.parentElement.parentElement.parentElement.parentElement.parentElement.querySelectorAll(".mdl-checkbox:not([data-check-all=\"true\"])").forEach(input => {
+ var checkbox = input.MaterialCheckbox;
+
+ if (el.checked) checkbox.check();
+ else checkbox.uncheck();
+ });
+ });
+ });
+
+ document.querySelector("#submit").addEventListener("click", e => {
+ var data = getFormData();
+
+ if (data.incidents.length == 0 && data.records.length == 0) {
+ document.querySelector(".mdl-js-snackbar").MaterialSnackbar.showSnackbar({
+ message: "Debes seleccionar al menos una incidencia o registro para poder validar.",
+ timeout: 5000
+ });
+
+ return;
+ }
+
+ var form = document.createElement("form");
+ form.setAttribute("action", "interstitialvalidations.php");
+ form.setAttribute("method", "POST");
+ form.style.display = "none";
+
+ ["incidents", "records"].forEach(key => {
+ var input = document.createElement("input");
+ input.setAttribute("name", key);
+ input.setAttribute("value", data[key]);
+ form.appendChild(input);
+ });
+
+ document.body.appendChild(form);
+ form.submit();
+ });
+});
diff --git a/src/js/workers.js b/src/js/workers.js
new file mode 100644
index 0000000..88ac687
--- /dev/null
+++ b/src/js/workers.js
@@ -0,0 +1,71 @@
+function getRawWorkers() {
+ var parameters = [];
+ document.querySelectorAll("tr[data-worker-id]").forEach(tr => {
+ if (tr.querySelector("input[type=\"checkbox\"]").checked) {
+ parameters.push(tr.getAttribute("data-worker-id"));
+ }
+ });
+
+ return parameters;
+}
+
+function getParameters() {
+ var parameters = [];
+ var workers = getRawWorkers();
+ workers.forEach(worker => {
+ parameters.push("workers[]="+worker);
+ });
+
+ if (parameters.length == 0) return false;
+
+ return parameters.join("&");
+}
+
+window.addEventListener("load", function() {
+ var datatable = $('.datatable').DataTable({
+ paging: false,
+ ordering: false,
+ info: false,
+ searching:true
+ });
+
+ document.querySelector("#usuario").addEventListener("input", function(evt) {
+ this.search(evt.target.value);
+ this.draw(true);
+ }.bind(datatable));
+
+ document.querySelector(".filter").addEventListener("click", function() {
+ document.querySelector("#filter").showModal();
+ /* Or dialog.show(); to show the dialog without a backdrop. */
+ });
+
+ ["copytemplate", "addincidentbulk"].forEach(action => {
+ document.getElementById(action).addEventListener("click", function() {
+ var parameters = getParameters();
+ if (parameters === false) return;
+
+ var url = "dynamic/"+action+".php?"+parameters;
+ dynDialog.load(url);
+ });
+ });
+
+ document.getElementById("addrecurringincident").addEventListener("click", function () {
+ var workers = getRawWorkers();
+ if (workers.length > 1) {
+ if (document.querySelector(".mdl-js-snackbar") === null) {
+ document.body.insertAdjacentHTML('beforeend', '<div class="mdl-snackbar mdl-js-snackbar"><div class="mdl-snackbar__text"></div><button type="button" class="mdl-snackbar__action"></button></div>');
+ componentHandler.upgradeElement(document.querySelector(".mdl-js-snackbar"));
+ }
+
+ document.querySelector(".mdl-js-snackbar").MaterialSnackbar.showSnackbar(
+ {
+ message: "Solo se puede añadir una incidencia recurrente a un solo trabajador.",
+ timeout: 5000
+ }
+ );
+ // Display error message
+ } else if (workers.length == 1) {
+ window.location = "incidents.php?openRecurringFormWorker="+workers[0];
+ }
+ });
+});