Add menu enable toggle, user status, and mobile/UI polish
- Admin menu page: mobile item cards now put Actions in the top-right
corner next to Status, matching the desktop row layout instead of
stacking at the bottom; same treatment applied to announcements and
users for consistency across all three admin lists
- Center button label text everywhere via .btn { justify-content: center }
instead of one-off overrides
- Add a Disable/Enable Menu toggle to the admin menu toolbar; the public
menu page shows its existing "menu being updated" message while disabled
- Add an Enabled/Disabled status to user accounts, with its own toggle
badge, guardrails against disabling your own account or the last
enabled account, and an immediate session kick for anyone disabled
mid-session
- Fix the announcement banner / hero tagline "·" separators to hide only
when their neighboring text actually wraps onto a different line,
instead of a fixed breakpoint or always-on dot
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eab20899de
commit
cd4c6c1969
13 files changed
+405
-50
No files matched your search
+37
-3
@@ -152,10 +152,38 @@ document.getElementById('form-password').addEventListener('submit', async (e) =>
|
||||
}
|
||||
});
|
||||
|
||||
// Delegate row actions: Change Password, Delete
|
||||
// Delegate row actions: toggle Status, Change Password, Delete
|
||||
document.getElementById('users-rows').addEventListener('click', async (e) => {
|
||||
const { target } = e;
|
||||
|
||||
// The status badge itself is the toggle button — same convention as the
|
||||
// menu items and announcements lists. Self's badge renders as a plain
|
||||
// (non-button) span, so this never matches your own row.
|
||||
if (target.classList.contains('btn-toggle-user')) {
|
||||
target.disabled = true;
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append('action', 'toggle_user_enabled');
|
||||
fd.append('user_id', target.dataset.id);
|
||||
fd.append('csrf_token', csrfToken);
|
||||
|
||||
try {
|
||||
const data = await postForm(fd);
|
||||
if (data.success) {
|
||||
target.className = `status-badge btn-toggle-user ${data.status_class}`;
|
||||
target.textContent = data.status_badge;
|
||||
target.title = `Click to mark as ${data.is_enabled ? 'disabled' : 'enabled'}`;
|
||||
} else {
|
||||
alert(data.error || 'Failed to update user status.');
|
||||
}
|
||||
} catch {
|
||||
alert('Network error. Please try again.');
|
||||
} finally {
|
||||
target.disabled = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.classList.contains('btn-change-password')) {
|
||||
openPasswordModal(target.dataset.id, target.dataset.username);
|
||||
return;
|
||||
@@ -197,14 +225,20 @@ function insertUserRow(user) {
|
||||
// data-username is set via dataset below, never interpolated into the
|
||||
// HTML string — escapeHtml() only escapes for text-content positions,
|
||||
// not attribute values, so it can't safely build an attribute string.
|
||||
// A user you just created is never "you" — the current admin's own row
|
||||
// already exists — so its Status badge always renders as the clickable
|
||||
// toggle, never the plain self span (see users.php for that variant).
|
||||
row.innerHTML = `
|
||||
<div data-label="Status">
|
||||
<button type="button" class="status-badge btn-toggle-user active" data-id="${user.id}" title="Click to mark as disabled">● Enabled</button>
|
||||
</div>
|
||||
<div data-label="Username"><strong>${escapeHtml(user.username)}</strong></div>
|
||||
<div data-label="Role">${escapeHtml(user.role.charAt(0).toUpperCase() + user.role.slice(1))}</div>
|
||||
<div class="font-mono timestamp-cell" data-label="Created">${escapeHtml(user.created_at)}</div>
|
||||
<div data-label="Actions"><div class="row-actions">
|
||||
<div data-label="Actions"><div class="row-actions"><div class="action-stack">
|
||||
<button type="button" class="btn btn-outline btn-sm btn-change-password" data-id="${user.id}">Change Password</button>
|
||||
<button type="button" class="btn btn-danger btn-sm btn-delete-user" data-id="${user.id}">Delete</button>
|
||||
</div></div>
|
||||
</div></div></div>
|
||||
`;
|
||||
row.querySelector('.btn-change-password').dataset.username = user.username;
|
||||
|
||||
|
||||
Reference in new issue
Block a user