document.addEventListener('DOMContentLoaded', function() { // Only initialize if we're on the events tab if (!document.getElementById('events-tab')?.classList.contains('active')) { return; } // Initialize variables let currentPage = parseInt(document.getElementById('currentPage').textContent) || 1; let totalPages = parseInt(document.getElementById('totalPages').textContent) || 1; let isFetching = false; // Get filter elements const eventTypeFilter = document.getElementById('eventTypeFilter'); const dateRangeFilter = document.getElementById('dateRangeFilter'); const userFilter = document.getElementById('userFilter'); const clearFiltersBtn = document.getElementById('clearFilters'); // Get pagination elements const prevPageBtn = document.getElementById('prevPage'); const nextPageBtn = document.getElementById('nextPage'); const currentPageSpan = document.getElementById('currentPage'); const totalPagesSpan = document.getElementById('totalPages'); const eventsTableBody = document.getElementById('eventsTableBody'); // Event details modal const eventDetailsModal = document.getElementById('eventDetailsModal'); const eventDetailsContent = document.getElementById('eventDetailsContent'); // Function to update URL with current filters function updateURL() { const params = new URLSearchParams(window.location.search); params.set('tab', 'events'); params.set('page', currentPage); params.set('event_type', eventTypeFilter.value); params.set('date_range', dateRangeFilter.value); params.set('user_id', userFilter.value); window.history.replaceState({}, '', `${window.location.pathname}?${params.toString()}`); } // Function to update pagination UI function updatePaginationUI(page, total) { currentPage = page; totalPages = total; currentPageSpan.textContent = currentPage; totalPagesSpan.textContent = totalPages; prevPageBtn.disabled = currentPage === 1; nextPageBtn.disabled = currentPage === totalPages; } // Function to fetch filtered events function fetchEvents() { if (isFetching) return; isFetching = true; // Show loading state if (eventsTableBody) { eventsTableBody.innerHTML = 'Loading...'; } const params = new URLSearchParams({ event_type: eventTypeFilter.value, date_range: dateRangeFilter.value, user_id: userFilter.value, page: currentPage }); const csrfToken = document.querySelector('meta[name="csrf-token"]').content; fetch(`/api/events?${params.toString()}`, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-Token': csrfToken } }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { console.log('Received events data:', data); if (!eventsTableBody) { console.error('Could not find events table body element'); return; } // Update table content let tableHtml = ''; if (data.events && data.events.length > 0) { data.events.forEach(event => { tableHtml += ` ${new Date(event.timestamp).toLocaleString()} ${formatEventType(event.event_type)} ${event.user ? `${event.user.username} ${event.user.last_name}` : 'Unknown'} ${event.ip_address || '-'} `; }); } else { tableHtml = 'No events found'; } // Update the table body eventsTableBody.innerHTML = tableHtml; console.log('Updated table content with', data.events.length, 'events'); // Update pagination updatePaginationUI(data.current_page, data.total_pages); // Update URL updateURL(); }) .catch(error => { console.error('Error fetching events:', error); if (eventsTableBody) { eventsTableBody.innerHTML = 'Error loading events'; } }) .finally(() => { isFetching = false; }); } // Helper function to get badge class based on event type function getEventBadgeClass(eventType) { const badgeClasses = { 'user_login': 'bg-info', 'user_logout': 'bg-info', 'user_create': 'bg-success', 'user_delete': 'bg-danger', 'user_update': 'bg-warning', 'file_upload': 'bg-success', 'file_delete': 'bg-danger', 'file_download': 'bg-info', 'file_preview': 'bg-info', 'file_restore': 'bg-warning', 'file_move': 'bg-warning', 'file_rename': 'bg-warning', 'file_star': 'bg-warning', 'file_unstar': 'bg-warning', 'file_delete_permanent': 'bg-danger', 'folder_create': 'bg-success', 'room_create': 'bg-success', 'room_delete': 'bg-danger', 'room_update': 'bg-warning', 'room_open': 'bg-info', 'room_member_add': 'bg-success', 'room_member_remove': 'bg-danger', 'room_member_permissions_update': 'bg-warning', 'room_permission_update': 'bg-warning', 'conversation_create': 'bg-success', 'conversation_update': 'bg-warning', 'conversation_delete': 'bg-danger', 'conversation_open': 'bg-info', 'message_create': 'bg-success', 'attachment_download': 'bg-info' }; return badgeClasses[eventType] || 'bg-secondary'; } // Helper function to format event type for display function formatEventType(eventType) { return eventType.split('_') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); } // Function to load event details function loadEventDetails(eventId) { console.log('Loading details for event:', eventId); const csrfToken = document.querySelector('meta[name="csrf-token"]').content; fetch(`/api/events/${eventId}`, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-Token': csrfToken } }) .then(response => { console.log('Response status:', response.status); return response.json(); }) .then(data => { console.log('Received event data:', data); // Format the details for display const formattedDetails = {}; // Handle details separately if (data.details) { if (typeof data.details === 'object') { formattedDetails['Details'] = JSON.stringify(data.details, null, 2); } else { formattedDetails['Details'] = data.details; } } else { formattedDetails['Details'] = 'No additional details'; } // Convert to formatted string const detailsText = Object.entries(formattedDetails) .map(([key, value]) => `${key}: ${value}`) .join('\n\n'); console.log('Formatted details:', detailsText); eventDetailsContent.textContent = detailsText; }) .catch(error => { console.error('Error loading event details:', error); eventDetailsContent.textContent = 'Error loading event details. Please try again.'; }); } // Add event listeners for filters with debounce let filterTimeout; function debouncedFetch() { clearTimeout(filterTimeout); filterTimeout = setTimeout(() => { currentPage = 1; // Reset to first page when filters change fetchEvents(); }, 300); } eventTypeFilter.addEventListener('change', debouncedFetch); dateRangeFilter.addEventListener('change', debouncedFetch); userFilter.addEventListener('change', debouncedFetch); // Event listener for clear filters clearFiltersBtn.addEventListener('click', function() { eventTypeFilter.value = ''; dateRangeFilter.value = '24h'; userFilter.value = ''; currentPage = 1; fetchEvents(); }); // Event listeners for pagination prevPageBtn.addEventListener('click', function() { if (currentPage > 1) { currentPage--; fetchEvents(); } }); nextPageBtn.addEventListener('click', function() { if (currentPage < totalPages) { currentPage++; fetchEvents(); } }); // Event listener for event details modal eventDetailsModal.addEventListener('show.bs.modal', function(event) { const button = event.relatedTarget; const eventId = button.getAttribute('data-event-id'); loadEventDetails(eventId); }); // Initialize filters from URL parameters const urlParams = new URLSearchParams(window.location.search); eventTypeFilter.value = urlParams.get('event_type') || ''; dateRangeFilter.value = urlParams.get('date_range') || '24h'; userFilter.value = urlParams.get('user_id') || ''; currentPage = parseInt(urlParams.get('page')) || 1; // Initial fetch to ensure pagination is correct fetchEvents(); });