/** * @fileoverview Manages the events page functionality. * This file handles event filtering, pagination, and modal interactions. */ document.addEventListener('DOMContentLoaded', function() { // Elements const eventTypeFilter = document.getElementById('eventTypeFilter'); const dateRangeFilter = document.getElementById('dateRangeFilter'); const userFilter = document.getElementById('userFilter'); const applyFiltersBtn = document.getElementById('applyFilters'); const eventsTableBody = document.getElementById('eventsTableBody'); const prevPageBtn = document.getElementById('prevPage'); const nextPageBtn = document.getElementById('nextPage'); const currentPageSpan = document.getElementById('currentPage'); const totalPagesSpan = document.getElementById('totalPages'); const eventDetailsModal = document.getElementById('eventDetailsModal'); const eventDetailsContent = document.getElementById('eventDetailsContent'); // State let currentPage = 1; let totalPages = 1; let currentFilters = { eventType: '', dateRange: '24h', userId: '' }; /** * Loads events based on current filters and page */ async function loadEvents() { try { const response = await fetch(`/api/events?page=${currentPage}&${new URLSearchParams(currentFilters)}`); const data = await response.json(); if (data.success) { renderEvents(data.events); updatePagination(data.total_pages); } else { console.error('Failed to load events:', data.error); } } catch (error) { console.error('Error loading events:', error); } } /** * Renders events in the table */ function renderEvents(events) { if (!Array.isArray(events)) { console.error('Invalid events data received:', events); return; } const eventRows = events.map(event => { if (!event || typeof event !== 'object') { console.error('Invalid event data:', event); return ''; } // Determine badge color and text based on event type let badgeClass = 'bg-secondary'; let eventText = event.event_type || 'Unknown Event'; switch(event.event_type) { case 'user_login': badgeClass = 'bg-success'; eventText = 'User Login'; break; case 'user_logout': badgeClass = 'bg-secondary'; eventText = 'User Logout'; break; case 'user_register': badgeClass = 'bg-info'; eventText = 'User Registration'; break; case 'user_update': badgeClass = 'bg-primary'; eventText = 'User Update'; break; case 'file_upload': badgeClass = 'bg-success'; eventText = 'File Upload'; break; case 'file_delete': badgeClass = 'bg-danger'; eventText = 'File Delete'; break; case 'file_download': badgeClass = 'bg-info'; eventText = 'File Download'; break; case 'file_restore': badgeClass = 'bg-warning'; eventText = 'File Restore'; break; case 'file_move': badgeClass = 'bg-primary'; eventText = 'File Move'; break; case 'file_rename': badgeClass = 'bg-info'; eventText = 'File Rename'; break; case 'file_star': badgeClass = 'bg-warning'; eventText = 'File Star'; break; case 'file_unstar': badgeClass = 'bg-secondary'; eventText = 'File Unstar'; break; case 'room_create': badgeClass = 'bg-success'; eventText = 'Room Create'; break; case 'room_delete': badgeClass = 'bg-danger'; eventText = 'Room Delete'; break; case 'room_update': badgeClass = 'bg-primary'; eventText = 'Room Update'; break; case 'room_join': badgeClass = 'bg-info'; eventText = 'Room Join'; break; case 'room_leave': badgeClass = 'bg-secondary'; eventText = 'Room Leave'; break; case 'conversation_create': badgeClass = 'bg-success'; eventText = 'Conversation Create'; break; case 'conversation_delete': badgeClass = 'bg-danger'; eventText = 'Conversation Delete'; break; case 'message_sent': badgeClass = 'bg-primary'; eventText = 'Message Sent'; break; case 'attachment_download': badgeClass = 'bg-info'; eventText = 'Attachment Download'; break; } const timestamp = event.timestamp ? new Date(event.timestamp).toLocaleString() : '-'; const username = event.user?.username || 'Unknown User'; const lastName = event.user?.last_name || ''; const eventId = event.id || ''; const ipAddress = event.ip_address || '-'; return ` ${timestamp} ${eventText} ${username} ${lastName} ${ipAddress} `; }).join(''); eventsTableBody.innerHTML = eventRows; // Add event listeners to detail buttons document.querySelectorAll('[data-event-id]').forEach(button => { button.addEventListener('click', () => { const eventId = button.dataset.eventId; if (eventId) { showEventDetails(eventId); } }); }); } /** * Updates pagination controls */ function updatePagination(total) { totalPages = total; currentPageSpan.textContent = currentPage; totalPagesSpan.textContent = totalPages; prevPageBtn.classList.toggle('disabled', currentPage === 1); nextPageBtn.classList.toggle('disabled', currentPage === totalPages); } /** * Shows event details in modal */ async function showEventDetails(eventId) { try { const response = await fetch(`/api/events/${eventId}`); const data = await response.json(); if (data.success) { const event = data.event; eventDetailsContent.textContent = JSON.stringify(event.details, null, 2); } else { console.error('Failed to load event details:', data.error); } } catch (error) { console.error('Error loading event details:', error); } } /** * Loads users for the user filter */ async function loadUsers() { try { const response = await fetch('/api/users'); const data = await response.json(); const userFilter = document.getElementById('userFilter'); userFilter.innerHTML = ''; data.users.forEach(user => { const option = document.createElement('option'); option.value = user.id; option.textContent = `${user.username} ${user.last_name || ''}`.trim(); userFilter.appendChild(option); }); } catch (error) { console.error('Error loading users:', error); } } // Event Listeners applyFiltersBtn.addEventListener('click', () => { currentFilters = { eventType: eventTypeFilter.value, dateRange: dateRangeFilter.value, userId: userFilter.value }; currentPage = 1; loadEvents(); }); prevPageBtn.addEventListener('click', () => { if (currentPage > 1) { currentPage--; loadEvents(); } }); nextPageBtn.addEventListener('click', () => { if (currentPage < totalPages) { currentPage++; loadEvents(); } }); // Initialize loadUsers(); loadEvents(); });