mirror of
https://github.com/hyzendust/hyzendust.github.io.git
synced 2026-06-30 23:12:16 +02:00
236 lines
6.1 KiB
HTML
236 lines
6.1 KiB
HTML
{{ define "main" }}
|
|
|
|
<div id="admin-gate" style="display: none">
|
|
<p>You do not have permission to access this page.</p>
|
|
</div>
|
|
|
|
<div id="admin-panel" style="display: none">
|
|
<h1>User Management</h1>
|
|
<label class="admin-search" for="admin-user-search">
|
|
<span class="admin-search__label">Search users</span>
|
|
<input
|
|
id="admin-user-search"
|
|
class="admin-search__input"
|
|
type="search"
|
|
placeholder="Search by username or email"
|
|
autocomplete="off"
|
|
/>
|
|
</label>
|
|
<div id="admin-msg" class="auth-message" style="display: none" aria-live="polite"></div>
|
|
<div id="admin-table-wrap"></div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
var BACKEND = 'https://backend.freedoms4.org/admin.php';
|
|
var username = localStorage.getItem('f4_username');
|
|
|
|
var gate = document.getElementById('admin-gate');
|
|
var panel = document.getElementById('admin-panel');
|
|
var msg = document.getElementById('admin-msg');
|
|
var wrap = document.getElementById('admin-table-wrap');
|
|
var search = document.getElementById('admin-user-search');
|
|
var allUsers = [];
|
|
|
|
if (username !== 'hyzen') {
|
|
gate.style.display = '';
|
|
return;
|
|
}
|
|
panel.style.display = '';
|
|
|
|
function showMsg(text, type) {
|
|
msg.textContent = text;
|
|
msg.className = 'auth-message auth-message--' + type;
|
|
msg.style.display = 'block';
|
|
setTimeout(function () {
|
|
msg.style.display = 'none';
|
|
}, 3000);
|
|
}
|
|
|
|
function escHtml(s) {
|
|
return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
}
|
|
|
|
function renderTable(users) {
|
|
if (!users.length) {
|
|
wrap.innerHTML = '<p>No matching users found.</p>';
|
|
return;
|
|
}
|
|
|
|
var adminIndex = users.findIndex(function (u) {
|
|
return u.username === username;
|
|
});
|
|
var adminUser = adminIndex === -1 ? null : users[adminIndex];
|
|
var otherUsers = users.filter(function (u) {
|
|
return u.username !== username;
|
|
});
|
|
var html =
|
|
'<table class="admin-table">' +
|
|
'<tbody><tr class="admin-table__header">' +
|
|
'<th>#</th><th>Username</th><th>Email</th><th>Joined</th><th>Status</th>' +
|
|
(adminUser ? '<th rowspan="2">Actions</th>' : '<th>Actions</th>') +
|
|
'</tr>';
|
|
|
|
function userRow(u, isCurrentUser) {
|
|
var joined = new Date(u.created_at).toLocaleDateString();
|
|
var blocked = u.blocked === true || u.blocked === 't' || u.blocked === '1';
|
|
var status = isCurrentUser
|
|
? '<span class="admin-badge admin-badge--admin">Admin</span>'
|
|
: blocked
|
|
? '<span class="admin-badge admin-badge--blocked">Blocked</span>'
|
|
: '<span class="admin-badge admin-badge--active">Active</span>';
|
|
var blockBtn = '';
|
|
var deleteBtn = '';
|
|
|
|
if (!isCurrentUser) {
|
|
blockBtn = blocked
|
|
? '<button class="admin-btn admin-btn--unblock" data-id="' +
|
|
u.id +
|
|
'" data-action="unblock_user">Unblock</button>'
|
|
: '<button class="admin-btn admin-btn--block" data-id="' +
|
|
u.id +
|
|
'" data-action="block_user">Block</button>';
|
|
|
|
deleteBtn =
|
|
'<button class="admin-btn admin-btn--delete" data-id="' +
|
|
u.id +
|
|
'" data-username="' +
|
|
escHtml(u.username) +
|
|
'" data-action="delete_user">Delete Records</button>';
|
|
}
|
|
|
|
return (
|
|
'<tr id="user-row-' +
|
|
u.id +
|
|
'">' +
|
|
'<td>' +
|
|
u.id +
|
|
'</td>' +
|
|
'<td>' +
|
|
escHtml(u.username) +
|
|
'</td>' +
|
|
'<td>' +
|
|
escHtml(u.email) +
|
|
'</td>' +
|
|
'<td>' +
|
|
joined +
|
|
'</td>' +
|
|
'<td>' +
|
|
status +
|
|
'</td>' +
|
|
(isCurrentUser
|
|
? ''
|
|
: '<td class="admin-actions">' + blockBtn + ' ' + deleteBtn + '</td>') +
|
|
'</tr>'
|
|
);
|
|
}
|
|
|
|
if (adminUser) {
|
|
html += userRow(adminUser, true);
|
|
}
|
|
otherUsers.forEach(function (u) {
|
|
html += userRow(u, false);
|
|
});
|
|
|
|
html += '</tbody></table>';
|
|
wrap.innerHTML = html;
|
|
|
|
wrap.querySelectorAll('[data-action]').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
var action = btn.dataset.action;
|
|
var id = parseInt(btn.dataset.id, 10);
|
|
var uname = btn.dataset.username || '';
|
|
|
|
if (action === 'delete_user') {
|
|
if (
|
|
!confirm(
|
|
'Permanently delete user "' + uname + '"? This cannot be undone.'
|
|
)
|
|
)
|
|
return;
|
|
} else if (action === 'block_user') {
|
|
if (
|
|
!confirm(
|
|
"This will permanently delete the user's email history and cannot be undone"
|
|
)
|
|
)
|
|
return;
|
|
}
|
|
|
|
btn.disabled = true;
|
|
|
|
fetch(BACKEND, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
body: JSON.stringify({ action: action, user_id: id }),
|
|
})
|
|
.then(function (r) {
|
|
return r.json();
|
|
})
|
|
.then(function (data) {
|
|
if (data.success) {
|
|
if (action === 'delete_user') {
|
|
allUsers = allUsers.filter(function (u) {
|
|
return Number(u.id) !== id;
|
|
});
|
|
filterUsers();
|
|
showMsg('User deleted.', 'success');
|
|
} else {
|
|
loadUsers();
|
|
}
|
|
} else {
|
|
showMsg(data.message || 'Action failed.', 'error');
|
|
btn.disabled = false;
|
|
}
|
|
})
|
|
.catch(function () {
|
|
showMsg('Network error.', 'error');
|
|
btn.disabled = false;
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function loadUsers() {
|
|
wrap.innerHTML = '<p>Loading…</p>';
|
|
fetch(BACKEND + '?action=list_users', {
|
|
credentials: 'include',
|
|
})
|
|
.then(function (r) {
|
|
return r.json();
|
|
})
|
|
.then(function (data) {
|
|
if (data.success) {
|
|
allUsers = data.users;
|
|
filterUsers();
|
|
} else {
|
|
wrap.innerHTML =
|
|
'<p class="admin-error">' +
|
|
escHtml(data.message || 'Failed to load users.') +
|
|
'</p>';
|
|
}
|
|
})
|
|
.catch(function () {
|
|
wrap.innerHTML = '<p class="admin-error">Network error.</p>';
|
|
});
|
|
}
|
|
|
|
function filterUsers() {
|
|
var query = search.value.trim().toLowerCase();
|
|
var users = allUsers.filter(function (u) {
|
|
return (
|
|
!query ||
|
|
String(u.username).toLowerCase().includes(query) ||
|
|
String(u.email).toLowerCase().includes(query)
|
|
);
|
|
});
|
|
renderTable(users);
|
|
}
|
|
|
|
search.addEventListener('input', filterUsers);
|
|
loadUsers();
|
|
})();
|
|
</script>
|
|
{{ end }}
|