/**
* User Management UI
*/
let currentEditUserId = null;
document.addEventListener('DOMContentLoaded', function() {
loadUsers();
document.getElementById('createUserBtn').addEventListener('click', createUser);
document.getElementById('updateUserBtn').addEventListener('click', updateUser);
});
function loadUsers() {
fetch('/api/users')
.then(r => r.json())
.then(data => {
if (data.success) {
renderUsers(data.users);
}
})
.catch(e => console.error('Error loading users:', e));
}
function renderUsers(users) {
const tbody = document.getElementById('usersList');
if (users.length === 0) {
tbody.innerHTML = '
| No users found |
';
return;
}
tbody.innerHTML = users.map(user => `
| ${escapeHtml(user.username)} |
${user.is_admin ? 'Admin' : 'User'}
|
${formatDate(user.created_at)} |
${user.last_login ? formatDate(user.last_login) : 'Never'} |
${user.id !== getUserId() ? `
` : ''}
|
`).join('');
}
function createUser() {
const username = document.getElementById('newUsername').value;
const password = document.getElementById('newPassword').value;
const isAdmin = document.getElementById('newIsAdmin').checked;
fetch('/api/users', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ username, password, is_admin: isAdmin })
})
.then(r => r.json())
.then(data => {
if (data.success) {
bootstrap.Modal.getInstance(document.getElementById('newUserModal')).hide();
document.getElementById('newUserForm').reset();
loadUsers();
showAlert('User created successfully', 'success');
} else {
showAlert(data.error, 'danger');
}
})
.catch(e => showAlert(e.message, 'danger'));
}
function editUser(userId, username, isAdmin) {
currentEditUserId = userId;
document.getElementById('editUsername').textContent = username;
document.getElementById('editIsAdmin').checked = isAdmin;
new bootstrap.Modal(document.getElementById('editUserModal')).show();
}
function updateUser() {
const password = document.getElementById('editPassword').value;
const isAdmin = document.getElementById('editIsAdmin').checked;
const body = { is_admin: isAdmin };
if (password) body.password = password;
fetch(`/api/users/${currentEditUserId}`, {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(body)
})
.then(r => r.json())
.then(data => {
if (data.success) {
bootstrap.Modal.getInstance(document.getElementById('editUserModal')).hide();
loadUsers();
showAlert('User updated successfully', 'success');
} else {
showAlert(data.error, 'danger');
}
})
.catch(e => showAlert(e.message, 'danger'));
}
function deleteUser(userId, username) {
if (!confirm(`Delete user '${username}'?`)) return;
fetch(`/api/users/${userId}`, {method: 'DELETE'})
.then(r => r.json())
.then(data => {
if (data.success) {
loadUsers();
showAlert('User deleted successfully', 'success');
} else {
showAlert(data.error, 'danger');
}
})
.catch(e => showAlert(e.message, 'danger'));
}
function showAlert(message, type) {
const alert = document.createElement('div');
alert.className = `alert alert-${type} alert-dismissible fade show`;
alert.innerHTML = `
${message}
`;
document.querySelector('.card-body').prepend(alert);
setTimeout(() => alert.remove(), 5000);
}
function formatDate(dateStr) {
return new Date(dateStr).toLocaleDateString('en-US', {
year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit'
});
}
function escapeHtml(text) {
const map = {'&': '&', '<': '<', '>': '>', '"': '"', "'": '''};
return text.replace(/[&<>"']/g, m => map[m]);
}
function getUserId() {
// Extract from current user endpoint
let userId = null;
fetch('/api/current-user')
.then(r => r.json())
.then(data => { userId = data.id; });
return userId;
}