2020-10-22 16:50:40 +00:00
|
|
|
import { checkCheckboxes, populateUsers, populateRadios } from "./modules/accounts.js";
|
|
|
|
import { _post, _get, _delete, rmAttr, addAttr } from "./modules/common.js";
|
|
|
|
import { populateProfiles } from "./modules/settings.js";
|
|
|
|
import { Focus, Unfocus, createEl, storeDefaults } from "./modules/admin.js";
|
|
|
|
|
|
|
|
interface aWindow extends Window {
|
|
|
|
changeEmail(icon: HTMLElement, id: string): void;
|
2020-09-20 13:48:17 +00:00
|
|
|
}
|
|
|
|
|
2020-10-22 16:50:40 +00:00
|
|
|
declare var window: aWindow;
|
|
|
|
|
2020-09-21 21:03:20 +00:00
|
|
|
const validateEmail = (email: string): boolean => /\S+@\S+\.\S+/.test(email);
|
2020-09-20 13:48:17 +00:00
|
|
|
|
2020-10-22 16:50:40 +00:00
|
|
|
window.changeEmail = (icon: HTMLElement, id: string): void => {
|
2020-09-20 13:48:17 +00:00
|
|
|
const iconContent = icon.outerHTML;
|
|
|
|
icon.setAttribute('class', '');
|
2020-09-21 21:03:20 +00:00
|
|
|
const entry = icon.nextElementSibling as HTMLInputElement;
|
2020-09-20 13:48:17 +00:00
|
|
|
const ogEmail = entry.value;
|
|
|
|
entry.readOnly = false;
|
|
|
|
entry.classList.remove('form-control-plaintext');
|
|
|
|
entry.classList.add('form-control');
|
|
|
|
if (ogEmail == "") {
|
|
|
|
entry.placeholder = 'Address';
|
|
|
|
}
|
2020-09-21 21:03:20 +00:00
|
|
|
const tick = createEl(`
|
2020-09-20 13:48:17 +00:00
|
|
|
<i class="fa fa-check d-inline-block icon-button text-success" style="margin-left: 0.5rem; margin-right: 0.5rem;"></i>
|
2020-09-21 21:03:20 +00:00
|
|
|
`);
|
2020-09-20 13:48:17 +00:00
|
|
|
tick.onclick = (): void => {
|
|
|
|
const newEmail = entry.value;
|
|
|
|
if (!validateEmail(newEmail) || newEmail == ogEmail) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cross.remove();
|
2020-09-21 21:03:20 +00:00
|
|
|
const spinner = createEl(`
|
2020-09-20 13:48:17 +00:00
|
|
|
<div class="spinner-border spinner-border-sm" role="status" style="width: 1rem; height: 1rem; margin-left: 0.5rem;">
|
|
|
|
<span class="sr-only">Saving...</span>
|
|
|
|
</div>
|
2020-09-21 21:03:20 +00:00
|
|
|
`);
|
|
|
|
tick.replaceWith(spinner);
|
2020-09-20 13:48:17 +00:00
|
|
|
let send = {};
|
|
|
|
send[id] = newEmail;
|
2020-09-24 13:03:25 +00:00
|
|
|
_post("/users/emails", send, function (): void {
|
2020-09-20 13:48:17 +00:00
|
|
|
if (this.readyState == 4) {
|
2020-09-21 21:03:20 +00:00
|
|
|
if (this.status == 200 || this.status == 204) {
|
2020-09-20 13:48:17 +00:00
|
|
|
entry.nextElementSibling.remove();
|
|
|
|
} else {
|
|
|
|
entry.value = ogEmail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
icon.outerHTML = iconContent;
|
|
|
|
entry.readOnly = true;
|
|
|
|
entry.classList.remove('form-control');
|
|
|
|
entry.classList.add('form-control-plaintext');
|
|
|
|
entry.placeholder = '';
|
|
|
|
};
|
2020-09-21 21:03:20 +00:00
|
|
|
const cross = createEl(`
|
2020-09-20 13:48:17 +00:00
|
|
|
<i class="fa fa-close d-inline-block icon-button text-danger"></i>
|
2020-09-21 21:03:20 +00:00
|
|
|
`);
|
2020-09-20 13:48:17 +00:00
|
|
|
cross.onclick = (): void => {
|
|
|
|
tick.remove();
|
|
|
|
cross.remove();
|
|
|
|
icon.outerHTML = iconContent;
|
|
|
|
entry.readOnly = true;
|
|
|
|
entry.classList.remove('form-control');
|
|
|
|
entry.classList.add('form-control-plaintext');
|
|
|
|
entry.placeholder = '';
|
|
|
|
entry.value = ogEmail;
|
|
|
|
};
|
|
|
|
icon.parentNode.appendChild(tick);
|
|
|
|
icon.parentNode.appendChild(cross);
|
|
|
|
};
|
|
|
|
|
|
|
|
(<HTMLInputElement>document.getElementById('selectAll')).onclick = function (): void {
|
|
|
|
const checkboxes: NodeListOf<HTMLInputElement> = document.getElementById('accountsList').querySelectorAll('input[type=checkbox]');
|
2020-09-21 21:03:20 +00:00
|
|
|
for (let i = 0; i < checkboxes.length; i++) {
|
2020-09-20 13:48:17 +00:00
|
|
|
checkboxes[i].checked = (<HTMLInputElement>this).checked;
|
|
|
|
}
|
2020-09-21 21:03:20 +00:00
|
|
|
checkCheckboxes();
|
2020-09-20 13:48:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
(<HTMLInputElement>document.getElementById('deleteModalNotify')).onclick = function (): void {
|
|
|
|
const textbox: HTMLElement = document.getElementById('deleteModalReasonBox');
|
|
|
|
if ((<HTMLInputElement>this).checked) {
|
|
|
|
Focus(textbox);
|
|
|
|
} else {
|
|
|
|
Unfocus(textbox);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-21 21:03:20 +00:00
|
|
|
(<HTMLButtonElement>document.getElementById('accountsTabDelete')).onclick = function (): void {
|
|
|
|
const deleteButton = this as HTMLButtonElement;
|
2020-09-20 13:48:17 +00:00
|
|
|
const checkboxes: NodeListOf<HTMLInputElement> = document.getElementById('accountsList').querySelectorAll('input[type=checkbox]:checked');
|
|
|
|
let selected: Array<string> = new Array(checkboxes.length);
|
2020-09-21 21:03:20 +00:00
|
|
|
for (let i = 0; i < checkboxes.length; i++) {
|
2020-09-20 13:48:17 +00:00
|
|
|
selected[i] = checkboxes[i].id.replace("select_", "");
|
|
|
|
}
|
|
|
|
let title = " user";
|
|
|
|
let msg = "Notify user";
|
|
|
|
if (selected.length > 1) {
|
|
|
|
title += "s";
|
|
|
|
msg += "s";
|
|
|
|
}
|
|
|
|
title = `Delete ${selected.length} ${title}`;
|
|
|
|
msg += " of account deletion";
|
|
|
|
|
|
|
|
document.getElementById('deleteModalTitle').textContent = title;
|
2020-09-21 21:03:20 +00:00
|
|
|
const dmNotify = document.getElementById('deleteModalNotify') as HTMLInputElement;
|
2020-09-20 13:48:17 +00:00
|
|
|
dmNotify.checked = false;
|
|
|
|
document.getElementById('deleteModalNotifyLabel').textContent = msg;
|
2020-09-21 21:03:20 +00:00
|
|
|
const dmReason = document.getElementById('deleteModalReason') as HTMLTextAreaElement;
|
2020-09-20 13:48:17 +00:00
|
|
|
dmReason.value = '';
|
|
|
|
Unfocus(document.getElementById('deleteModalReasonBox'));
|
2020-09-21 21:03:20 +00:00
|
|
|
const dmSend = document.getElementById('deleteModalSend') as HTMLButtonElement;
|
2020-09-20 13:48:17 +00:00
|
|
|
dmSend.textContent = 'Delete';
|
|
|
|
dmSend.onclick = function (): void {
|
2020-09-21 21:03:20 +00:00
|
|
|
const button = this as HTMLButtonElement;
|
2020-09-20 13:48:17 +00:00
|
|
|
const send = {
|
|
|
|
'users': selected,
|
|
|
|
'notify': dmNotify.checked,
|
|
|
|
'reason': dmReason.value
|
|
|
|
};
|
2020-09-24 13:03:25 +00:00
|
|
|
_delete("/users", send, function (): void {
|
2020-09-20 13:48:17 +00:00
|
|
|
if (this.readyState == 4) {
|
2020-09-21 21:03:20 +00:00
|
|
|
if (this.status == 500) {
|
|
|
|
if ("error" in this.reponse) {
|
2020-09-20 13:48:17 +00:00
|
|
|
button.textContent = 'Failed';
|
|
|
|
} else {
|
|
|
|
button.textContent = 'Partial fail (check console)';
|
2020-09-21 21:03:20 +00:00
|
|
|
console.log(this.response);
|
2020-09-20 13:48:17 +00:00
|
|
|
}
|
|
|
|
setTimeout((): void => {
|
|
|
|
Unfocus(deleteButton);
|
2020-10-22 16:50:40 +00:00
|
|
|
window.Modals.delete.hide();
|
2020-09-20 13:48:17 +00:00
|
|
|
}, 4000);
|
|
|
|
} else {
|
|
|
|
Unfocus(deleteButton);
|
2020-10-22 16:50:40 +00:00
|
|
|
window.Modals.delete.hide()
|
2020-09-20 13:48:17 +00:00
|
|
|
}
|
|
|
|
populateUsers();
|
|
|
|
checkCheckboxes();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2020-10-22 16:50:40 +00:00
|
|
|
window.Modals.delete.show();
|
2020-09-20 13:48:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
(<HTMLInputElement>document.getElementById('selectAll')).checked = false;
|
|
|
|
|
|
|
|
(<HTMLButtonElement>document.getElementById('accountsTabSetDefaults')).onclick = function (): void {
|
|
|
|
const checkboxes: NodeListOf<HTMLInputElement> = document.getElementById('accountsList').querySelectorAll('input[type=checkbox]:checked');
|
|
|
|
let userIDs: Array<string> = new Array(checkboxes.length);
|
2020-10-22 16:50:40 +00:00
|
|
|
for (let i = 0; i < checkboxes.length; i++){
|
2020-09-20 13:48:17 +00:00
|
|
|
userIDs[i] = checkboxes[i].id.replace("select_", "");
|
|
|
|
}
|
|
|
|
if (userIDs.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
populateRadios();
|
|
|
|
let userString = 'user';
|
|
|
|
if (userIDs.length > 1) {
|
|
|
|
userString += "s";
|
|
|
|
}
|
2020-09-22 23:01:07 +00:00
|
|
|
populateProfiles(true);
|
|
|
|
const profileSelect = document.getElementById('profileSelect') as HTMLSelectElement;
|
|
|
|
profileSelect.textContent = '';
|
2020-10-22 16:50:40 +00:00
|
|
|
for (let i = 0; i < window.availableProfiles.length; i++) {
|
2020-09-22 23:01:07 +00:00
|
|
|
profileSelect.innerHTML += `
|
2020-10-22 16:50:40 +00:00
|
|
|
<option value="${window.availableProfiles[i]}" ${(i == 0) ? "selected" : ""}>${window.availableProfiles[i]}</option>
|
2020-09-22 23:01:07 +00:00
|
|
|
`;
|
|
|
|
}
|
2020-09-20 13:48:17 +00:00
|
|
|
document.getElementById('defaultsTitle').textContent = `Apply settings to ${userIDs.length} ${userString}`;
|
|
|
|
document.getElementById('userDefaultsDescription').textContent = `
|
2020-09-22 23:01:07 +00:00
|
|
|
Apply settings from an existing profile or source settings from a user.
|
2020-09-20 13:48:17 +00:00
|
|
|
`;
|
|
|
|
document.getElementById('storeHomescreenLabel').textContent = `Apply homescreen layout`;
|
|
|
|
Focus(document.getElementById('defaultsSourceSection'));
|
2020-09-22 23:01:07 +00:00
|
|
|
(<HTMLSelectElement>document.getElementById('defaultsSource')).value = 'profile';
|
|
|
|
Focus(document.getElementById('profileSelectBox'));
|
2020-09-24 22:57:42 +00:00
|
|
|
Unfocus(document.getElementById('defaultUserRadiosBox'));
|
2020-09-22 23:01:07 +00:00
|
|
|
Unfocus(document.getElementById('newProfileBox'));
|
2020-09-20 13:48:17 +00:00
|
|
|
document.getElementById('storeDefaults').onclick = (): void => storeDefaults(userIDs);
|
2020-10-22 16:50:40 +00:00
|
|
|
window.Modals.userDefaults.show();
|
2020-09-20 13:48:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
(<HTMLSelectElement>document.getElementById('defaultsSource')).addEventListener('change', function (): void {
|
2020-09-24 22:57:42 +00:00
|
|
|
const radios = document.getElementById('defaultUserRadiosBox');
|
2020-09-22 23:01:07 +00:00
|
|
|
const profileBox = document.getElementById('profileSelectBox');
|
|
|
|
if (this.value == 'profile') {
|
2020-09-20 13:48:17 +00:00
|
|
|
Unfocus(radios);
|
2020-09-22 23:01:07 +00:00
|
|
|
Focus(profileBox);
|
2020-09-20 13:48:17 +00:00
|
|
|
} else {
|
2020-09-22 23:01:07 +00:00
|
|
|
Unfocus(profileBox);
|
2020-09-20 13:48:17 +00:00
|
|
|
Focus(radios);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
(<HTMLButtonElement>document.getElementById('newUserCreate')).onclick = function (): void {
|
2020-09-21 21:03:20 +00:00
|
|
|
const button = this as HTMLButtonElement;
|
|
|
|
const ogText = button.textContent;
|
|
|
|
button.innerHTML = `
|
2020-09-20 13:48:17 +00:00
|
|
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Creating...
|
|
|
|
`;
|
|
|
|
const email: string = (<HTMLInputElement>document.getElementById('newUserEmail')).value;
|
|
|
|
var username: string = email;
|
|
|
|
if (document.getElementById('newUserName') != null) {
|
|
|
|
username = (<HTMLInputElement>document.getElementById('newUserName')).value;
|
|
|
|
}
|
|
|
|
const password: string = (<HTMLInputElement>document.getElementById('newUserPassword')).value;
|
|
|
|
if (!validateEmail(email) && email != "") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const send = {
|
|
|
|
'username': username,
|
|
|
|
'password': password,
|
|
|
|
'email': email
|
|
|
|
};
|
2020-09-24 13:03:25 +00:00
|
|
|
_post("/users", send, function (): void {
|
2020-09-20 13:48:17 +00:00
|
|
|
if (this.readyState == 4) {
|
|
|
|
rmAttr(button, 'btn-primary');
|
2020-09-21 21:03:20 +00:00
|
|
|
if (this.status == 200) {
|
2020-09-20 13:48:17 +00:00
|
|
|
addAttr(button, 'btn-success');
|
|
|
|
button.textContent = 'Success';
|
|
|
|
setTimeout((): void => {
|
|
|
|
rmAttr(button, 'btn-success');
|
2020-09-21 21:03:20 +00:00
|
|
|
addAttr(button, 'btn-primary');
|
2020-09-20 13:48:17 +00:00
|
|
|
button.textContent = ogText;
|
2020-10-22 16:50:40 +00:00
|
|
|
window.Modals.newUser.hide();
|
2020-09-20 13:48:17 +00:00
|
|
|
}, 1000);
|
2020-09-21 21:03:20 +00:00
|
|
|
populateUsers();
|
2020-09-20 13:48:17 +00:00
|
|
|
} else {
|
|
|
|
addAttr(button, 'btn-danger');
|
2020-09-21 21:03:20 +00:00
|
|
|
if ("error" in this.response) {
|
|
|
|
button.textContent = this.response["error"];
|
2020-09-20 13:48:17 +00:00
|
|
|
} else {
|
|
|
|
button.textContent = 'Failed';
|
|
|
|
}
|
|
|
|
setTimeout((): void => {
|
|
|
|
rmAttr(button, 'btn-danger');
|
|
|
|
addAttr(button, 'btn-primary');
|
|
|
|
button.textContent = ogText;
|
|
|
|
}, 2000);
|
2020-09-21 21:03:20 +00:00
|
|
|
populateUsers();
|
2020-09-20 13:48:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
(<HTMLButtonElement>document.getElementById('accountsTabAddUser')).onclick = function (): void {
|
|
|
|
(<HTMLInputElement>document.getElementById('newUserEmail')).value = '';
|
|
|
|
(<HTMLInputElement>document.getElementById('newUserPassword')).value = '';
|
|
|
|
if (document.getElementById('newUserName') != null) {
|
|
|
|
(<HTMLInputElement>document.getElementById('newUserName')).value = '';
|
|
|
|
}
|
2020-10-22 16:50:40 +00:00
|
|
|
window.Modals.newUser.show();
|
2020-09-20 13:48:17 +00:00
|
|
|
};
|