// users_log.js - Activity log and active users display let logsPollingInterval = null; let usersPollingInterval = null; async function fetchActiveUsers() { try { const res = await fetch("/api/active_users", { cache: "no-store" }); if (!res.ok) { console.error("Failed to fetch active users:", res.status); return; } const data = await res.json(); displayActiveUsers(data.users || []); } catch (err) { console.error("Error fetching active users:", err); } } function displayActiveUsers(users) { const container = document.getElementById("active-users-list"); if (users.length === 0) { container.innerHTML = '
No active users
'; return; } container.innerHTML = users.map(username => `
${escapeHtml(username)}
`).join(''); } async function fetchActivityLogs() { try { const res = await fetch("/api/activity_logs?limit=200", { cache: "no-store" }); if (!res.ok) { console.error("Failed to fetch activity logs:", res.status); return; } const data = await res.json(); displayActivityLogs(data.logs || []); } catch (err) { console.error("Error fetching activity logs:", err); } } function displayActivityLogs(logs) { const container = document.getElementById("activity-log-container"); if (logs.length === 0) { container.innerHTML = '
No activity logs yet
'; return; } container.innerHTML = logs.map(log => { const time = formatTimestamp(log.timestamp); const details = log.details ? ` - ${escapeHtml(log.details)}` : ''; return `
${time} ${escapeHtml(log.username)} ${escapeHtml(log.action)} ${details ? `${details}` : ''}
`; }).join(''); // Auto-scroll to bottom on first load if (!container.hasAttribute('data-scrolled')) { container.scrollTop = container.scrollHeight; container.setAttribute('data-scrolled', 'true'); } } function formatTimestamp(isoString) { const date = new Date(isoString); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; } function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } async function copyLogsToClipboard() { try { const res = await fetch("/api/activity_logs?limit=1000", { cache: "no-store" }); if (!res.ok) { alert("Failed to fetch logs"); return; } const data = await res.json(); const logs = data.logs || []; if (logs.length === 0) { alert("No logs to copy"); return; } // Format logs as plain text const logText = logs.map(log => { const time = formatTimestamp(log.timestamp); const details = log.details ? ` - ${log.details}` : ''; return `[${time}] ${log.username}: ${log.action}${details}`; }).join('\n'); // Copy to clipboard await navigator.clipboard.writeText(logText); // Show success feedback const btn = document.getElementById("copy-log-btn"); const originalText = btn.textContent; btn.textContent = "Copied!"; btn.style.backgroundColor = "#4CAF50"; setTimeout(() => { btn.textContent = originalText; btn.style.backgroundColor = ""; }, 2000); } catch (err) { console.error("Error copying logs:", err); alert("Failed to copy logs to clipboard"); } } function startPolling() { // Fetch immediately fetchActiveUsers(); fetchActivityLogs(); // Then poll at intervals usersPollingInterval = setInterval(fetchActiveUsers, 10000); // Every 10 seconds logsPollingInterval = setInterval(fetchActivityLogs, 5000); // Every 5 seconds } function stopPolling() { if (usersPollingInterval) { clearInterval(usersPollingInterval); usersPollingInterval = null; } if (logsPollingInterval) { clearInterval(logsPollingInterval); logsPollingInterval = null; } } async function handleLogout() { console.log("handleLogout called"); try { console.log("Sending logout request to /auth/logout"); const response = await fetch("/auth/logout", { method: "POST" }); console.log("Logout response status:", response.status); if (response.ok) { console.log("Logout successful, redirecting to /login"); window.location.href = "/login"; } else { console.error("Logout failed with status:", response.status); window.location.href = "/login"; } } catch (error) { console.error("Error during logout:", error); window.location.href = "/login"; } } function wireUp() { // Attach copy button handler const copyBtn = document.getElementById("copy-log-btn"); if (copyBtn) { copyBtn.addEventListener("click", copyLogsToClipboard); } // Attach logout handler const logoutBtn = document.getElementById("logout-btn"); if (logoutBtn) { logoutBtn.addEventListener("click", handleLogout); } } // Initialize when page loads document.addEventListener("DOMContentLoaded", () => { wireUp(); startPolling(); }); // Stop polling when page is hidden/unloaded document.addEventListener("visibilitychange", () => { if (document.hidden) { stopPolling(); } else { startPolling(); } }); window.addEventListener("beforeunload", () => { stopPolling(); });