Initial features of accounts tab
It's rough right now, but the accounts tab shows a list of users and info. Right now the only action available is to apply settings (from template or another user) to a selection of users. More to come.
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
document.getElementById('selectAll').onclick = function() {
|
||||
const checkboxes = document.getElementById('accountsList').querySelectorAll('input[type=checkbox]');
|
||||
for (check of checkboxes) {
|
||||
check.checked = this.checked;
|
||||
}
|
||||
checkCheckboxes();
|
||||
};
|
||||
|
||||
function checkCheckboxes() {
|
||||
const defaultsButton = document.getElementById('accountsTabSetDefaults');
|
||||
const checkboxes = document.getElementById('accountsList').querySelectorAll('input[type=checkbox]');
|
||||
let checked = false;
|
||||
for (check of checkboxes) {
|
||||
if (check.checked) {
|
||||
checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!checked) {
|
||||
defaultsButton.classList.add('unfocused');
|
||||
} else if (defaultsButton.classList.contains('unfocused')) {
|
||||
defaultsButton.classList.remove('unfocused');
|
||||
}
|
||||
}
|
||||
|
||||
var jfUsers = [];
|
||||
|
||||
function populateUsers() {
|
||||
const acList = document.getElementById('accountsList');
|
||||
acList.innerHTML = `
|
||||
<div class="d-flex align-items-center">
|
||||
<strong>Getting Users...</strong>
|
||||
<div class="spinner-border ml-auto" role="status" aria-hidden="true"></div>
|
||||
</div>`;
|
||||
acList.parentNode.querySelector('thead').classList.add('unfocused');
|
||||
const accountsList = document.createElement('tbody');
|
||||
accountsList.id = 'accountsList';
|
||||
const template = function(id, username, email, lastActive, admin) {
|
||||
let isAdmin = "No";
|
||||
if (admin) {
|
||||
isAdmin = "Yes";
|
||||
}
|
||||
return `
|
||||
<td scope="row"><input class="form-check-input" type="checkbox" value="" id="select_${id}" onclick="checkCheckboxes();"></td>
|
||||
<td>${username}</td>
|
||||
<td>${email}</td>
|
||||
<td>${lastActive}</td>
|
||||
<td>${isAdmin}</td>
|
||||
<td><i class="fa fa-eye icon-button" id="viewConfig_${id}"></i></td>`;
|
||||
};
|
||||
|
||||
let req = new XMLHttpRequest();
|
||||
req.responseType = 'json';
|
||||
req.open("GET", "/getUsers", true);
|
||||
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||
req.onreadystatechange = function() {
|
||||
if (this.readyState == 4) {
|
||||
if (this.status == 200) {
|
||||
jfUsers = req.response['users'];
|
||||
for (user of jfUsers) {
|
||||
let tr = document.createElement('tr');
|
||||
tr.innerHTML = template(user['id'], user['name'], user['email'], user['last_active'], user['admin']);
|
||||
accountsList.appendChild(tr);
|
||||
}
|
||||
const header = acList.parentNode.querySelector('thead');
|
||||
if (header.classList.contains('unfocused')) {
|
||||
header.classList.remove('unfocused');
|
||||
}
|
||||
acList.replaceWith(accountsList);
|
||||
}
|
||||
}
|
||||
};
|
||||
req.send();
|
||||
}
|
||||
|
||||
document.getElementById('selectAll').checked = false;
|
||||
|
||||
document.getElementById('accountsTabSetDefaults').onclick = function() {
|
||||
const checkboxes = document.getElementById('accountsList').querySelectorAll('input[type=checkbox]');
|
||||
let userIDs = [];
|
||||
for (check of checkboxes) {
|
||||
if (check.checked) {
|
||||
userIDs.push(check.id.replace('select_', ''));
|
||||
}
|
||||
}
|
||||
if (userIDs.length == 0) {
|
||||
return;
|
||||
}
|
||||
let radioList = document.getElementById('defaultUserRadios');
|
||||
radioList.textContent = '';
|
||||
let first = true;
|
||||
for (user of jfUsers) {
|
||||
let radio = document.createElement('div');
|
||||
radio.classList.add('radio');
|
||||
let checked = 'checked';
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
checked = '';
|
||||
}
|
||||
radio.innerHTML = `
|
||||
<label><input type="radio" name="defaultRadios" id="select_${user['id']}" style="margin-right: 1rem;" ${checked}>${user['name']}</label>`;
|
||||
radioList.appendChild(radio);
|
||||
}
|
||||
let userstring = 'user';
|
||||
if (userIDs.length > 1) {
|
||||
userstring += 's';
|
||||
}
|
||||
document.getElementById('defaultsTitle').textContent = `Apply settings to ${userIDs.length} ${userstring}`;
|
||||
document.getElementById('userDefaultsDescription').textContent = `
|
||||
Create an account and configure it to your liking, then choose it from below to apply to your selected users.`;
|
||||
document.getElementById('storeHomescreenLabel').textContent = `Apply homescreen layout`;
|
||||
if (document.getElementById('defaultsSourceSection').classList.contains('unfocused')) {
|
||||
document.getElementById('defaultsSourceSection').classList.remove('unfocused');
|
||||
}
|
||||
document.getElementById('defaultsSource').value = 'userTemplate';
|
||||
document.getElementById('defaultUserRadios').classList.add('unfocused');
|
||||
document.getElementById('storeDefaults').onclick = function() {
|
||||
storeDefaults(userIDs);
|
||||
};
|
||||
userDefaultsModal.show();
|
||||
};
|
||||
|
||||
document.getElementById('defaultsSource').addEventListener('change', function() {
|
||||
const radios = document.getElementById('defaultUserRadios');
|
||||
if (this.value == 'userTemplate') {
|
||||
radios.classList.add('unfocused');
|
||||
} else if (radios.classList.contains('unfocused')) {
|
||||
radios.classList.remove('unfocused');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
+112
-39
@@ -1,3 +1,36 @@
|
||||
const tabs = {
|
||||
invitesEl: document.getElementById('invitesTab'),
|
||||
accountsEl: document.getElementById('accountsTab'),
|
||||
invitesTabButton: document.getElementById('invitesTabButton'),
|
||||
accountsTabButton: document.getElementById('accountsTabButton'),
|
||||
invites: function() {
|
||||
if (tabs.invitesEl.classList.contains('unfocused')) {
|
||||
tabs.accountsEl.classList.add('unfocused');
|
||||
tabs.invitesEl.classList.remove('unfocused');
|
||||
}
|
||||
if (tabs.invitesTabButton.classList.contains("text-muted")) {
|
||||
tabs.invitesTabButton.classList.remove("text-muted");
|
||||
tabs.accountsTabButton.classList.add("text-muted");
|
||||
}
|
||||
},
|
||||
accounts: function() {
|
||||
populateUsers();
|
||||
if (tabs.accountsEl.classList.contains('unfocused')) {
|
||||
tabs.invitesEl.classList.add('unfocused');
|
||||
tabs.accountsEl.classList.remove('unfocused');
|
||||
}
|
||||
if (tabs.accountsTabButton.classList.contains("text-muted")) {
|
||||
tabs.accountsTabButton.classList.remove("text-muted");
|
||||
tabs.invitesTabButton.classList.add("text-muted");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tabs.invitesTabButton.onclick = tabs.invites;
|
||||
tabs.accountsTabButton.onclick = tabs.accounts;
|
||||
|
||||
tabs.invites();
|
||||
|
||||
// Used for theme change animation
|
||||
function whichTransitionEvent() {
|
||||
let t;
|
||||
@@ -638,7 +671,7 @@ document.getElementById('openDefaultsWizard').onclick = function() {
|
||||
checked = '';
|
||||
}
|
||||
radio.innerHTML =
|
||||
`<label><input type="radio" name="defaultRadios" id="default_${user['name']}" style="margin-right: 1rem;" ${checked}>${user['name']}</label>`;
|
||||
`<label><input type="radio" name="defaultRadios" id="select_${user['id']}" style="margin-right: 1rem;" ${checked}>${user['name']}</label>`;
|
||||
radioList.appendChild(radio);
|
||||
}
|
||||
let button = document.getElementById('openDefaultsWizard');
|
||||
@@ -655,6 +688,19 @@ document.getElementById('openDefaultsWizard').onclick = function() {
|
||||
submitButton.classList.add('btn-primary');
|
||||
}
|
||||
settingsModal.hide();
|
||||
document.getElementById('defaultsTitle').textContent = `New user defaults`;
|
||||
document.getElementById('userDefaultsDescription').textContent = `
|
||||
Create an account and configure it to your liking, then choose it from below to store the settings as a template for all new users.`;
|
||||
document.getElementById('storeHomescreenLabel').textContent = `Store homescreen layout`;
|
||||
document.getElementById('defaultsSource').value = 'fromUser';
|
||||
document.getElementById('defaultsSourceSection').classList.add('unfocused');
|
||||
document.getElementById('storeDefaults').onclick = function() {
|
||||
storeDefaults('all');
|
||||
};
|
||||
const list = document.getElementById('defaultUserRadios');
|
||||
if (list.classList.contains('unfocused')) {
|
||||
list.classList.remove('unfocused');
|
||||
}
|
||||
userDefaultsModal.show();
|
||||
}
|
||||
}
|
||||
@@ -662,54 +708,81 @@ document.getElementById('openDefaultsWizard').onclick = function() {
|
||||
req.send();
|
||||
};
|
||||
|
||||
document.getElementById('storeDefaults').onclick = function () {
|
||||
function storeDefaults(users) {
|
||||
this.disabled = true;
|
||||
this.innerHTML =
|
||||
'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="margin-right: 0.5rem;"></span>' +
|
||||
'Loading...';
|
||||
let button = document.getElementById('storeDefaults');
|
||||
let radios = document.getElementsByName('defaultRadios');
|
||||
let id = '';
|
||||
for (let radio of radios) {
|
||||
if (radio.checked) {
|
||||
let data = {
|
||||
'username': radio.id.slice(8),
|
||||
'homescreen': false};
|
||||
if (document.getElementById('storeDefaultHomescreen').checked) {
|
||||
data['homescreen'] = true;
|
||||
}
|
||||
let req = new XMLHttpRequest();
|
||||
req.open("POST", "/setDefaults", true);
|
||||
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
req.onreadystatechange = function() {
|
||||
if (this.readyState == 4) {
|
||||
if (this.status == 200 || this.status == 204) {
|
||||
button.textContent = "Success";
|
||||
if (button.classList.contains('btn-danger')) {
|
||||
button.classList.remove('btn-danger');
|
||||
} else if (button.classList.contains('btn-primary')) {
|
||||
button.classList.remove('btn-primary');
|
||||
}
|
||||
button.classList.add('btn-success');
|
||||
button.disabled = false;
|
||||
setTimeout(function() { userDefaultsModal.hide(); }, 1000);
|
||||
} else {
|
||||
button.textContent = "Failed";
|
||||
button.classList.remove('btn-primary');
|
||||
button.classList.add('btn-danger');
|
||||
setTimeout(function() {
|
||||
let button = document.getElementById('storeDefaults');
|
||||
button.textContent = "Submit";
|
||||
button.classList.remove('btn-danger');
|
||||
button.classList.add('btn-primary');
|
||||
button.disabled = false;
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
req.send(JSON.stringify(data));
|
||||
id = radio.id.replace('select_', '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
let route = '/setDefaults';
|
||||
let data = {
|
||||
'from': 'user',
|
||||
'id': id,
|
||||
'homescreen': false
|
||||
};
|
||||
if (document.getElementById('defaultsSource').value == 'userTemplate') {
|
||||
data['from'] = 'template';
|
||||
}
|
||||
if (users != 'all') {
|
||||
data['apply_to'] = users;
|
||||
route = '/applySettings';
|
||||
}
|
||||
if (document.getElementById('storeDefaultHomescreen').checked) {
|
||||
data['homescreen'] = true;
|
||||
}
|
||||
let req = new XMLHttpRequest();
|
||||
req.open("POST", route, true);
|
||||
req.responseType = 'json';
|
||||
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
req.onreadystatechange = function() {
|
||||
if (this.readyState == 4) {
|
||||
if (this.status == 200 || this.status == 204) {
|
||||
button.textContent = "Success";
|
||||
if (button.classList.contains('btn-danger')) {
|
||||
button.classList.remove('btn-danger');
|
||||
} else if (button.classList.contains('btn-primary')) {
|
||||
button.classList.remove('btn-primary');
|
||||
}
|
||||
button.classList.add('btn-success');
|
||||
button.disabled = false;
|
||||
setTimeout(function() {
|
||||
let button = document.getElementById('storeDefaults');
|
||||
button.textContent = "Submit";
|
||||
button.classList.remove('btn-success');
|
||||
button.classList.add('btn-primary');
|
||||
button.disabled = false;
|
||||
userDefaultsModal.hide();
|
||||
}, 1000);
|
||||
} else {
|
||||
if ("error" in req.response) {
|
||||
button.textContent = req.response["error"];
|
||||
} else if (("policy" in req.response) || ("homescreen" in req.response)) {
|
||||
button.textContent = "Failed (Check JS Console)";
|
||||
} else {
|
||||
button.textContent = "Failed";
|
||||
}
|
||||
button.classList.remove('btn-primary');
|
||||
button.classList.add('btn-danger');
|
||||
setTimeout(function() {
|
||||
let button = document.getElementById('storeDefaults');
|
||||
button.textContent = "Submit";
|
||||
button.classList.remove('btn-danger');
|
||||
button.classList.add('btn-primary');
|
||||
button.disabled = false;
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
req.send(JSON.stringify(data));
|
||||
};
|
||||
|
||||
var ombiDefaultsModal = '';
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user