Skip to content

Commit 7952475

Browse files
committed
Add search bar to admin servers page (filter by server name or owner)
1 parent dab2953 commit 7952475

2 files changed

Lines changed: 48 additions & 7 deletions

File tree

public/js/admin.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,17 +501,23 @@ function updateAdminNav() {
501501
}
502502

503503
let adminServersPage = 1;
504+
let adminServersSearch = '';
504505

505506
async function renderAdminServers() {
506507
document.querySelectorAll('.admin-page').forEach(p => p.classList.remove('active'));
507508
const el = $a('#admin-page-servers');
508509
if (!el) return;
509510
el.classList.add('active');
511+
adminServersSearch = '';
510512
el.innerHTML = ahtml`
511513
<div class="page-header">
512514
<h1 class="page-title">All Servers</h1>
513515
<p class="page-subtitle">All servers across all users</p>
514516
</div>
517+
<div class="search-wrapper" style="margin-bottom:16px;max-width:400px" id="admin-servers-search-wrapper">
518+
<span data-lucide="search"></span>
519+
<input type="text" id="admin-servers-search" placeholder="Search by server name or owner...">
520+
</div>
515521
<div class="table-container">
516522
<table>
517523
<thead>
@@ -531,6 +537,19 @@ async function renderAdminServers() {
531537
</div>
532538
`;
533539

540+
const searchInput = $a('#admin-servers-search');
541+
if (searchInput) {
542+
let searchTimer;
543+
searchInput.addEventListener('input', () => {
544+
clearTimeout(searchTimer);
545+
searchTimer = setTimeout(() => {
546+
adminServersSearch = searchInput.value.trim();
547+
adminServersPage = 1;
548+
fetchAdminServers(1);
549+
}, 400);
550+
});
551+
}
552+
534553
await fetchAdminServers(adminServersPage);
535554
}
536555

@@ -539,9 +558,11 @@ async function fetchAdminServers(pageNum) {
539558
const limit = 10;
540559
const offset = (pageNum - 1) * limit;
541560
const paginationEl = $a('#admin-servers-pagination');
561+
const params = new URLSearchParams({ limit, offset });
562+
if (adminServersSearch) params.set('search', adminServersSearch);
542563

543564
try {
544-
const data = await adminApi(`/servers?limit=${limit}&offset=${offset}`);
565+
const data = await adminApi(`/servers?${params.toString()}`);
545566
const tbody = $a('#admin-servers-tbody');
546567
if (!tbody) return;
547568

routes/admin.js

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,24 @@ router.get('/servers', authenticateToken, requireAdmin, async (req, res) => {
138138
try {
139139
const limit = Math.min(parseInt(req.query.limit, 10) || 10, 50);
140140
const offset = Math.max(parseInt(req.query.offset, 10) || 0, 0);
141+
const search = (req.query.search || '').trim().toLowerCase();
141142

142-
const result = await getAllServers(limit, offset);
143-
const { servers: paginatedServers, total } = result;
144-
const page = Math.floor(offset / limit) + 1;
145-
const totalPages = Math.ceil(total / limit) || 1;
143+
let allServers;
144+
if (search) {
145+
const result = await getAllServers();
146+
allServers = Array.isArray(result) ? result : result.servers || [];
147+
} else {
148+
const result = await getAllServers(limit, offset);
149+
allServers = result.servers || [];
150+
}
146151

147152
const users = await query('SELECT id, email, username, ptero_user_id FROM users');
148153
const userMap = {};
149154
for (const u of users) {
150155
userMap[u.ptero_user_id] = { id: u.id, email: u.email, username: u.username };
151156
}
152157

153-
for (const s of paginatedServers) {
158+
for (const s of allServers) {
154159
s.owner = userMap[s.user] || { id: null, email: 'Unknown', username: 'Unknown' };
155160
try {
156161
const meta = await query('SELECT * FROM server_meta WHERE ptero_server_id = ?', [s.id]);
@@ -160,7 +165,22 @@ router.get('/servers', authenticateToken, requireAdmin, async (req, res) => {
160165
}
161166
}
162167

163-
res.json({ servers: paginatedServers, total, page, totalPages, limit });
168+
let filtered = allServers;
169+
if (search) {
170+
filtered = allServers.filter(s => {
171+
const name = (s.name || '').toLowerCase();
172+
const ownerName = (s.owner?.username || '').toLowerCase();
173+
const ownerEmail = (s.owner?.email || '').toLowerCase();
174+
return name.includes(search) || ownerName.includes(search) || ownerEmail.includes(search);
175+
});
176+
}
177+
178+
const filteredTotal = filtered.length;
179+
const page = Math.floor(offset / limit) + 1;
180+
const totalPages = Math.ceil(filteredTotal / limit) || 1;
181+
const sliced = filtered.slice(offset, offset + limit);
182+
183+
res.json({ servers: sliced, total: filteredTotal, page, totalPages, limit });
164184
} catch (err) {
165185
console.error('Admin servers list error:', err.message);
166186
res.status(500).json({ error: 'Failed to fetch servers' });

0 commit comments

Comments
 (0)