Add server monitoring and database backup pages

New sidebar sections wired to the backend's new admin APIs:
- Monitoring: live request/error-rate/latency stats plus a recent-requests
  table, polling every 8s.
- Backups: create/list/download database backups (auth'd blob download
  since the endpoint requires a Bearer token, not a plain link).
This commit is contained in:
2026-09-19 22:17:44 +03:30
parent 7cf6c78c77
commit 3480eac2b0
4 changed files with 413 additions and 1 deletions
+69
View File
@@ -306,3 +306,72 @@ export function rejectUser(id: number, reason: string) {
body: JSON.stringify({ reason }),
});
}
// ---------------- ادمین: مانیتورینگ ----------------
export interface MonitoringSummary {
total_requests: number;
total_errors: number;
error_rate_pct: number;
avg_latency_ms: number;
p95_latency_ms: number;
requests_last_min: number;
started_at: string;
uptime_seconds: number;
}
export interface RequestLogEntry {
time: string;
method: string;
path: string;
status_code: number;
duration_ms: number;
client_ip: string;
user_id?: number;
}
export function getMonitoringSummary() {
return authRequest<MonitoringSummary>("/admin/monitoring/summary");
}
export function getRecentRequests(limit = 100) {
return authRequest<RequestLogEntry[]>(`/admin/monitoring/requests?limit=${limit}`);
}
// ---------------- ادمین: بک‌آپ دیتابیس ----------------
export interface BackupInfo {
filename: string;
size_bytes: number;
created_at: string;
}
export function listBackups() {
return authRequest<BackupInfo[]>("/admin/backups");
}
export function createBackup() {
return authRequest<BackupInfo>("/admin/backups", { method: "POST" });
}
// دانلود بک‌آپ نیاز به هدر Authorization داره (اندپوینت فقط-ادمینه)، پس نمی‌شه
// مستقیم از یک <a href> استفاده کرد؛ فایل رو با fetch احرازهویت‌شده می‌گیریم و
// خودمون دانلودش رو با یک لینک موقت شبیه‌سازی می‌کنیم.
export async function downloadBackup(filename: string) {
const token = tokenStore.getAccess();
const res = await fetch(`${API_BASE}/admin/backups/${encodeURIComponent(filename)}`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
});
if (!res.ok) {
throw new ApiError("دانلود بک‌آپ ناموفق بود", res.status);
}
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
}