407 lines
16 KiB
JavaScript
407 lines
16 KiB
JavaScript
async function loadData (block) {
|
|
const source = block.dataset.source;
|
|
block.classList.remove ("loaded");
|
|
try {
|
|
const response = await fetch (source);
|
|
if (response.ok) {
|
|
const items = await response.json();
|
|
var itemLoaders = [];
|
|
|
|
if (Array.isArray (items)) {
|
|
const template = block.querySelector ("template");
|
|
const tableBody = block.querySelector ("table tbody");
|
|
tableBody.innerHTML = "";
|
|
items.forEach (item => {
|
|
const clone = template.content.cloneNode (true);
|
|
const loader = window["populate" + block.dataset.item] (clone, item);
|
|
if (loader != null) {
|
|
itemLoaders.push (loader);
|
|
}
|
|
tableBody.appendChild (clone);
|
|
tableBody.lastElementChild.dataset.itemid = item.id;
|
|
});
|
|
} else {
|
|
const loader = window["populate" + block.dataset.item] (block, items);
|
|
if (loader != null) {
|
|
itemLoaders.push (loader);
|
|
}
|
|
}
|
|
|
|
block.classList.add ("loaded");
|
|
|
|
for (const loader of itemLoaders) {
|
|
await loader();
|
|
}
|
|
} else {
|
|
if ((response.status == 401) || (response.status == 403)) {
|
|
document.location.href = document.body.dataset.baseurl;
|
|
} else {
|
|
block.classList.add ("failed");
|
|
}
|
|
}
|
|
} catch (error) {
|
|
block.classList.add ("failed");
|
|
}
|
|
}
|
|
|
|
function populateUser (row, user) {
|
|
row.querySelector (".email").innerText = user.email;
|
|
row.querySelector (".fullname").innerText = user.fullName;
|
|
row.querySelector (".roles").innerText = user.roles.join (", ");
|
|
row.querySelector (".active").innerText = user.isActive ? "✓" : "";
|
|
}
|
|
|
|
async function displayUser (container, dialog, userUrl) {
|
|
dialog.querySelectorAll (".error")
|
|
.forEach (element => {
|
|
element.hidden = true;
|
|
});
|
|
const response = await fetch (userUrl);
|
|
if (response.ok) {
|
|
const user = await response.json();
|
|
dialog.querySelector ("input[name=userid]").value = user.id;
|
|
dialog.querySelector ("input[name=email]").value = user.email;
|
|
dialog.querySelector ("input[name=fullname]").value = user.fullName;
|
|
dialog.querySelector ("input[name=active]").checked = user.isActive;
|
|
dialog.querySelectorAll ("input.role")
|
|
.forEach (checkbox => {
|
|
checkbox.checked = user.roles.includes (checkbox.value);
|
|
});
|
|
|
|
container.classList.add ("loaded");
|
|
} else {
|
|
if ((response.status == 401) || (response.status == 403)) {
|
|
document.location.href = document.body.dataset.baseurl;
|
|
} else {
|
|
container.classList.add ("failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
function emptyUser (dialog) {
|
|
dialog.querySelector ("input[name=email]").value = null;
|
|
dialog.querySelector ("input[name=fullname]").value = null;
|
|
dialog.querySelectorAll ("input[name=role]")
|
|
.forEach (checkbox => {
|
|
checkbox.checked = false;
|
|
});
|
|
dialog.querySelectorAll (".error")
|
|
.forEach (element => {
|
|
element.hidden = true;
|
|
});
|
|
dialog.querySelector ("button.invite").disabled = false;
|
|
}
|
|
|
|
function selectUser (event) {
|
|
const row = event.target.closest ("tbody tr");
|
|
|
|
if (row && this.contains (row)) {
|
|
const dialog = document.querySelector (this.dataset.dialog);
|
|
|
|
window["display" + this.dataset.item] (this, dialog, this.dataset.source + "/" + row.dataset.itemid);
|
|
dialog.showModal();
|
|
dialog.querySelector ("input[name=email]").focus();
|
|
} else if (event.target.classList.contains ("new")) {
|
|
const dialog = document.querySelector (event.target.dataset.dialog);
|
|
|
|
window["empty" + this.dataset.item] (dialog);
|
|
dialog.showModal();
|
|
dialog.querySelector ("input[name=email]").focus();
|
|
}
|
|
}
|
|
|
|
async function saveUser (event) {
|
|
event.preventDefault();
|
|
|
|
const dialog = event.target.closest ("dialog");
|
|
|
|
if (event.submitter.classList.contains ("save")) {
|
|
const userId = event.target.querySelector ("input[name=userid]").value;
|
|
const email = event.target.querySelector ("input[name=email]").value;
|
|
const fullname = event.target.querySelector ("input[name=fullname]").value;
|
|
const isActive = event.target.querySelector ("input[name=active]").checked;
|
|
const roles = Array.from (event.target.querySelectorAll ("input[name=role]:checked")).map (checkbox => { return checkbox.value });
|
|
let valid = true;
|
|
|
|
if (email) {
|
|
dialog.querySelector (".error[for=email]").hidden = true;
|
|
} else {
|
|
dialog.querySelector (".error[for=email]").hidden = false;
|
|
valid = false;
|
|
}
|
|
if (fullname) {
|
|
dialog.querySelector (".error[for=fullname]").hidden = true;
|
|
} else {
|
|
dialog.querySelector (".error[for=fullname]").hidden = false;
|
|
valid = false;
|
|
}
|
|
|
|
if (valid) {
|
|
event.target.querySelector ("button.save").disabled = true;
|
|
|
|
try {
|
|
const url = dialog.dataset.saveUrl + "/" + userId;
|
|
const response = await fetch (url,
|
|
{
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify ({email: email, fullname: fullname, isActive: isActive, roles: roles})
|
|
});
|
|
if (response.ok) {
|
|
dialog.close();
|
|
event.target.querySelector ("button.save").disabled = false;
|
|
loadData (document.querySelector (".users.loading"));
|
|
|
|
return true;
|
|
} else {
|
|
console.error (url + " returned " + response.status);
|
|
dialog.querySelector (".error#failure").hidden = false;
|
|
dialog.querySelector ("button.save").disabled = false;
|
|
|
|
if ((response.status == 401) || (response.status == 403)) {
|
|
document.location.href = document.body.dataset.baseurl;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
console.error (error);
|
|
dialog.querySelector (".error#failure").hidden = false;
|
|
dialog.querySelector ("button.save").disabled = false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
dialog.close();
|
|
}
|
|
}
|
|
|
|
async function inviteUser (event) {
|
|
event.preventDefault();
|
|
|
|
const dialog = event.target.closest ("dialog");
|
|
|
|
if (event.submitter.classList.contains ("invite")) {
|
|
const email = event.target.querySelector ("input[name=email]").value;
|
|
const fullname = event.target.querySelector ("input[name=fullname").value;
|
|
const roles = Array.from (event.target.querySelectorAll ("input[name=role]:checked")).map (checkbox => { return checkbox.value });
|
|
let valid = true;
|
|
|
|
if (email) {
|
|
dialog.querySelector (".error[for=email]").hidden = true;
|
|
} else {
|
|
dialog.querySelector (".error[for=email]").hidden = false;
|
|
valid = false;
|
|
}
|
|
if (fullname) {
|
|
dialog.querySelector (".error[for=fullname]").hidden = true;
|
|
} else {
|
|
dialog.querySelector (".error[for=fullname]").hidden = false;
|
|
valid = false;
|
|
}
|
|
|
|
if (valid) {
|
|
event.target.querySelector ("button.invite").disabled = true;
|
|
|
|
try {
|
|
const url = dialog.dataset.inviteUrl;
|
|
const response = await fetch (url,
|
|
{
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify ({email: email, fullname: fullname, roles: roles})
|
|
});
|
|
if (response.ok) {
|
|
dialog.close();
|
|
event.target.querySelector ("button.invite").disabled = false;
|
|
loadData (document.querySelector (".users.loading"));
|
|
|
|
return true;
|
|
} else {
|
|
console.error (url + " returned " + response.status);
|
|
dialog.querySelector (".error#failure").hidden = false;
|
|
dialog.querySelector ("button.invite").disabled = false;
|
|
|
|
if ((response.status == 401) || (response.status == 403)) {
|
|
document.location.href = document.body.dataset.baseurl;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
console.error (error);
|
|
dialog.querySelector (".error#failure").hidden = false;
|
|
dialog.querySelector ("button.invite").disabled = false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
dialog.close();
|
|
}
|
|
}
|
|
|
|
function populatePassword (container, token) {
|
|
container.querySelector (".email").innerText = token.email;
|
|
container.querySelector ("button.save").disabled = false;
|
|
container.querySelector (".invalidPassword").hidden = true;
|
|
}
|
|
|
|
async function savePassword (event) {
|
|
event.preventDefault();
|
|
|
|
if (event.submitter.classList.contains ("save")) {
|
|
const password = event.target.querySelector ("input[name=password]").value;
|
|
const saveUrl = event.target.dataset.saveUrl;
|
|
const loginUrl = event.target.dataset.loginUrl;
|
|
|
|
if (password && (password.length >= 12)) {
|
|
try {
|
|
event.target.querySelector ("button.save").disabled = true;
|
|
event.target.querySelector (".invalidPassword").hidden = true;
|
|
const response = await fetch (saveUrl,
|
|
{
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify ({password: password})
|
|
});
|
|
if (response.ok) {
|
|
document.location.href = loginUrl;
|
|
|
|
return true;
|
|
} else {
|
|
console.error (saveUrl + " returned " + response.status);
|
|
event.target.querySelector (".error#failure").hidden = false;
|
|
event.target.querySelector ("button.save").disabled = false;
|
|
|
|
return false;
|
|
}
|
|
} catch (error) {
|
|
console.error (saveUrl + " returned " + error);
|
|
event.target.querySelector (".error#failure").hidden = false;
|
|
event.target.querySelector ("button.save").disabled = false;
|
|
}
|
|
} else {
|
|
event.target.querySelector (".invalidPassword").hidden = false;
|
|
return false;
|
|
}
|
|
} else {
|
|
dialog.close();
|
|
}
|
|
}
|
|
|
|
async function login (event) {
|
|
event.preventDefault();
|
|
|
|
const email = event.target.querySelector ("input[name=email]").value;
|
|
const password = event.target.querySelector ("input[name=password]").value;
|
|
const loginUrl = event.target.dataset.loginUrl;
|
|
|
|
if (email && password) {
|
|
try {
|
|
event.target.querySelector ("button#login").disabled = true;
|
|
event.target.querySelector (".error#failure").hidden = true;
|
|
event.target.querySelector (".invalidEmail").hidden = true;
|
|
event.target.querySelector (".invalidPassword").hidden = true;
|
|
|
|
const response = await fetch (loginUrl,
|
|
{
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify ({email: email, password: password})
|
|
});
|
|
if (response.ok) {
|
|
event.target.querySelector ("button#login").disabled = false;
|
|
|
|
document.location.href = document.body.dataset.baseurl;
|
|
|
|
return true;
|
|
} else {
|
|
console.error (loginUrl + " returned " + response.status);
|
|
event.target.querySelector (".error#failure").hidden = false;
|
|
event.target.querySelector ("button#login").disabled = false;
|
|
|
|
return false;
|
|
}
|
|
} catch (error) {
|
|
console.error (loginUrl + " returned " + error);
|
|
event.target.querySelector (".error#failure").hidden = false;
|
|
event.target.querySelector ("button#login").disabled = false;
|
|
}
|
|
|
|
return true;
|
|
} else {
|
|
event.target.querySelector (".invalidEmail").hidden = email;
|
|
event.target.querySelector (".invalidPassword").hidden = password;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function showForgotPassword (event) {
|
|
event.preventDefault();
|
|
|
|
document.querySelector ("form#login").hidden = true;
|
|
document.querySelector ("form#forgot").hidden = false;
|
|
}
|
|
|
|
async function submitForgotPassword (event) {
|
|
event.preventDefault();
|
|
|
|
const email = event.target.querySelector ("input[name=email]").value;
|
|
const resetUrl = event.target.dataset.resetUrl;
|
|
|
|
if (email) {
|
|
try {
|
|
event.target.querySelector ("button#reset-password").disabled = true;
|
|
const response = await fetch (resetUrl,
|
|
{
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify ({email: email})
|
|
});
|
|
if (response.ok) {
|
|
document.querySelector ("form#forgot").hidden = true;
|
|
document.querySelector ("div#reset-info").hidden = false;
|
|
|
|
return true;
|
|
} else {
|
|
console.error (saveUrl + " returned " + response.status);
|
|
event.target.querySelector (".error#failure").hidden = false;
|
|
event.target.querySelector ("button#reset-password").disabled = false;
|
|
|
|
return false;
|
|
}
|
|
} catch (error) {
|
|
console.error (saveUrl + " returned " + error);
|
|
event.target.querySelector (".error#failure").hidden = false;
|
|
event.target.querySelector ("button#reset-password").disabled = false;
|
|
}
|
|
} else {
|
|
event.target.querySelector (".invalidEmail").hidden = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function setupGlobalEnvironment() {
|
|
document.querySelectorAll (".loading")
|
|
.forEach (function (block) {
|
|
loadData (block);
|
|
block.addEventListener ("click", window["select" + block.dataset.item]);
|
|
});
|
|
document.querySelectorAll ("form#login")
|
|
.forEach (function (form) {
|
|
form.addEventListener ("submit", login);
|
|
});
|
|
document.querySelectorAll ("button#forgot-password")
|
|
.forEach (function (button) {
|
|
button.addEventListener ("click", showForgotPassword);
|
|
});
|
|
document.querySelectorAll ("form#forgot")
|
|
.forEach (function (form) {
|
|
form.addEventListener ("submit", submitForgotPassword);
|
|
});
|
|
}
|
|
|
|
document.addEventListener ("DOMContentLoaded", setupGlobalEnvironment);
|