/** * HAProxy Logs Management * Pagination and dynamic loading of logs */ document.addEventListener('DOMContentLoaded', function() { let currentPage = 1; let perPage = 50; let totalLogs = parseInt(document.getElementById('total_count').textContent); const logsContainer = document.getElementById('logs_container'); const perPageSelect = document.getElementById('logs_per_page'); const refreshBtn = document.getElementById('refresh_logs_btn'); const prevBtn = document.getElementById('prev_btn'); const nextBtn = document.getElementById('next_btn'); const loadAllBtn = document.getElementById('load_all_btn'); const loadedSpan = document.getElementById('loaded_count'); const currentPageSpan = document.getElementById('current_page'); const totalPagesSpan = document.getElementById('total_pages'); // Event Listeners perPageSelect.addEventListener('change', function(e) { perPage = parseInt(e.target.value); currentPage = 1; loadLogs(); }); refreshBtn.addEventListener('click', function() { currentPage = 1; loadLogs(); }); prevBtn.addEventListener('click', function() { if (currentPage > 1) { currentPage--; loadLogs(); } }); nextBtn.addEventListener('click', function() { const totalPages = Math.ceil(totalLogs / perPage); if (currentPage < totalPages) { currentPage++; loadLogs(); } }); loadAllBtn.addEventListener('click', function() { perPage = totalLogs; currentPage = 1; if (perPageSelect.querySelector(`option[value="${totalLogs}"]`)) { perPageSelect.value = totalLogs; } loadLogs(); }); /** * Load logs from API with pagination */ function loadLogs() { console.log(`[Logs] Loading page ${currentPage} with ${perPage} per page`); fetch('/api/logs', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ page: currentPage, per_page: perPage }) }) .then(response => response.json()) .then(data => { if (data.success) { renderLogs(data.logs); updatePagination(data); console.log(`[Logs] Successfully loaded page ${data.page}/${Math.ceil(data.total / data.per_page)}`); } else { showError(data.error || 'Unknown error'); } }) .catch(error => { console.error('[Logs] Error loading logs:', error); showError('Failed to load logs. Please try again.'); }); } /** * Render logs in the table */ function renderLogs(logs) { if (!logs || logs.length === 0) { logsContainer.innerHTML = ' No logs available'; return; } logsContainer.innerHTML = logs.map(entry => ` ${escapeHtml(entry.timestamp || 'N/A')}
${escapeHtml(entry.source || 'N/A')}
${escapeHtml(entry.message || 'N/A')}
`).join(''); } /** * Update pagination controls */ function updatePagination(data) { const totalPages = Math.ceil(data.total / data.per_page); loadedSpan.textContent = data.logs.length; currentPageSpan.textContent = data.page; totalPagesSpan.textContent = totalPages; // Disable/enable navigation buttons prevBtn.disabled = data.page === 1; nextBtn.disabled = !data.has_more; } /** * Show error message */ function showError(message) { logsContainer.innerHTML = `
${escapeHtml(message)}
`; } /** * Escape HTML to prevent XSS */ function escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, m => map[m]); } // Initial load loadLogs(); });