Replace all inline onclick handlers with addEventListener
All checks were successful
Build and Push Frontend Docker Image / build (push) Successful in 57s

Inline onclick handlers on async functions fail silently when
promises reject. This affected delete buttons, edit buttons,
modal close/cancel buttons, and pagination.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-01-08 00:28:32 +00:00
parent 965559f88d
commit ff54cf7363

View File

@@ -479,11 +479,28 @@ async function loadUsers() {
</div>
</div>
<div class="user-actions">
<button class="btn btn-sm btn-secondary" onclick="editUser(${user.id})">Edit</button>
${user.id !== currentUser.id ? `<button class="btn btn-sm btn-danger" onclick="deleteUser(${user.id})">Delete</button>` : ''}
<button class="btn btn-sm btn-secondary edit-user-btn" data-user-id="${user.id}">Edit</button>
${user.id !== currentUser.id ? `<button class="btn btn-sm btn-danger delete-user-btn" data-user-id="${user.id}">Delete</button>` : ''}
</div>
</div>
`).join('');
container.querySelectorAll('.edit-user-btn').forEach(btn => {
btn.addEventListener('click', () => editUser(parseInt(btn.dataset.userId, 10)));
});
container.querySelectorAll('.delete-user-btn').forEach(btn => {
btn.addEventListener('click', async () => {
const userId = parseInt(btn.dataset.userId, 10);
if (!confirm('Are you sure you want to delete this user?')) return;
try {
await api(`/users/${userId}`, { method: 'DELETE' });
loadUsers();
} catch (error) {
alert(error.message);
}
});
});
} catch (error) {
container.innerHTML = `<p class="error-message">${error.message}</p>`;
}
@@ -493,7 +510,7 @@ document.getElementById('add-user-btn').addEventListener('click', () => {
showModal(`
<div class="modal-header">
<h3>Add User</h3>
<button class="modal-close" onclick="hideModal()">&times;</button>
<button class="modal-close">&times;</button>
</div>
<form id="add-user-form">
<div class="form-group">
@@ -512,7 +529,7 @@ document.getElementById('add-user-btn').addEventListener('click', () => {
<label><input type="checkbox" name="isAdmin"> Admin</label>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="hideModal()">Cancel</button>
<button type="button" class="btn btn-secondary modal-cancel-btn">Cancel</button>
<button type="submit" class="btn btn-primary">Create</button>
</div>
</form>
@@ -548,7 +565,7 @@ async function editUser(id) {
showModal(`
<div class="modal-header">
<h3>Edit User: ${escapeHtml(user.username)}</h3>
<button class="modal-close" onclick="hideModal()">&times;</button>
<button class="modal-close">&times;</button>
</div>
<form id="edit-user-form">
<div class="form-group">
@@ -571,7 +588,7 @@ async function editUser(id) {
<input type="password" name="newPassword" minlength="12" placeholder="New password">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="hideModal()">Cancel</button>
<button type="button" class="btn btn-secondary modal-cancel-btn">Cancel</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
@@ -610,17 +627,6 @@ async function editUser(id) {
}
}
async function deleteUser(id) {
if (!confirm('Are you sure you want to delete this user?')) return;
try {
await api(`/users/${id}`, { method: 'DELETE' });
loadUsers();
} catch (error) {
alert(error.message);
}
}
async function loadAdminGallery(page = 1) {
adminCurrentPage = page;
const grid = document.getElementById('admin-gallery-grid');
@@ -639,8 +645,14 @@ async function loadAdminGallery(page = 1) {
// Modal
function showModal(content) {
document.getElementById('modal-content').innerHTML = content;
const modalContent = document.getElementById('modal-content');
modalContent.innerHTML = content;
document.getElementById('modal-overlay').classList.remove('hidden');
// Attach close handlers to modal-close buttons and cancel buttons
modalContent.querySelectorAll('.modal-close, .modal-cancel-btn').forEach(btn => {
btn.addEventListener('click', hideModal);
});
}
function hideModal() {
@@ -660,18 +672,26 @@ function renderPagination(container, pagination, loadFn) {
}
let html = '';
html += `<button ${page === 1 ? 'disabled' : ''} onclick="(${loadFn.name})(${page - 1})">Prev</button>`;
html += `<button class="pagination-btn" data-page="${page - 1}" ${page === 1 ? 'disabled' : ''}>Prev</button>`;
for (let i = 1; i <= totalPages; i++) {
if (i === 1 || i === totalPages || (i >= page - 1 && i <= page + 1)) {
html += `<button class="${i === page ? 'active' : ''}" onclick="(${loadFn.name})(${i})">${i}</button>`;
html += `<button class="pagination-btn ${i === page ? 'active' : ''}" data-page="${i}">${i}</button>`;
} else if (i === page - 2 || i === page + 2) {
html += '<span>...</span>';
}
}
html += `<button ${page === totalPages ? 'disabled' : ''} onclick="(${loadFn.name})(${page + 1})">Next</button>`;
html += `<button class="pagination-btn" data-page="${page + 1}" ${page === totalPages ? 'disabled' : ''}>Next</button>`;
container.innerHTML = html;
container.querySelectorAll('.pagination-btn').forEach(btn => {
btn.addEventListener('click', () => {
if (!btn.disabled) {
loadFn(parseInt(btn.dataset.page, 10));
}
});
});
}
// Utilities