This commit is contained in:
Mateusz Gruszczyński
2025-11-04 08:26:41 +01:00
parent 34c84f1115
commit 27f9984574
2 changed files with 153 additions and 125 deletions

View File

@@ -1,103 +1,107 @@
document.addEventListener('DOMContentLoaded', function() {
const filterIp = document.getElementById('filter_ip');
const filterStatus = document.getElementById('filter_status');
const filterMethod = document.getElementById('filter_method');
const filterThreats = document.getElementById('filter_threats');
const filterHideStats = document.getElementById('filter_hide_stats');
const resetBtn = document.getElementById('reset_filters');
let currentPage = 1;
let perPage = 50;
let totalLogs = parseInt(document.getElementById('total_count').textContent);
let allLogs = [];
const logsTable = document.getElementById('logs_table');
if (!logsTable) return; // Exit if no logs
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');
const allRows = Array.from(document.querySelectorAll('.log-row'));
// Filter function
function applyFilters() {
const ipValue = filterIp.value.toLowerCase();
const statusValue = filterStatus.value;
const methodValue = filterMethod.value;
const showThreats = filterThreats.checked;
const hideStats = filterHideStats.checked;
let visibleCount = 0;
let threatCount = 0;
let count2xx = 0, count4xx = 0, count5xx = 0;
const uniqueIps = new Set();
allRows.forEach(row => {
const ip = row.dataset.ip;
const status = row.dataset.status;
const method = row.dataset.method;
const hasThreat = row.dataset.threats === '1';
const url = row.querySelector('td:nth-child(4)').textContent.trim();
let show = true;
// IP filter
if (ipValue && !ip.includes(ipValue)) {
show = false;
}
// Status filter
if (statusValue) {
const statusStart = statusValue;
if (!status.startsWith(statusStart)) {
show = false;
}
}
// Method filter
if (methodValue && method !== methodValue) {
show = false;
}
// Threats filter
if (!showThreats && hasThreat) {
show = false;
}
// Hide /stats filter
if (hideStats && url.includes('/stats')) {
show = false;
}
row.style.display = show ? '' : 'none';
if (show) {
visibleCount++;
if (hasThreat) threatCount++;
if (status.startsWith('2')) count2xx++;
if (status.startsWith('4')) count4xx++;
if (status.startsWith('5')) count5xx++;
uniqueIps.add(ip);
}
});
// Update stats
document.getElementById('stat_total').textContent = visibleCount;
document.getElementById('stat_threats').textContent = threatCount;
document.getElementById('stat_2xx').textContent = count2xx;
document.getElementById('stat_4xx').textContent = count4xx;
document.getElementById('stat_5xx').textContent = count5xx;
document.getElementById('stat_ips').textContent = uniqueIps.size;
}
// Event listeners
filterIp.addEventListener('input', applyFilters);
filterStatus.addEventListener('change', applyFilters);
filterMethod.addEventListener('change', applyFilters);
filterThreats.addEventListener('change', applyFilters);
filterHideStats.addEventListener('change', applyFilters);
// Reset button
resetBtn.addEventListener('click', function() {
filterIp.value = '';
filterStatus.value = '';
filterMethod.value = '';
filterThreats.checked = true;
filterHideStats.checked = true;
applyFilters();
perPageSelect.addEventListener('change', function(e) {
perPage = parseInt(e.target.value);
currentPage = 1;
loadLogs();
});
applyFilters();
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;
perPageSelect.value = totalLogs;
loadLogs();
});
function loadLogs() {
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] Załadowano page ${data.page}/${Math.ceil(data.total / data.per_page)}`);
}
})
.catch(error => {
console.error('Error loading logs:', error);
logsContainer.innerHTML = `<tr><td class="alert alert-danger">Błąd załadowania logów</td></tr>`;
});
}
function renderLogs(logs) {
if (!logs || logs.length === 0) {
logsContainer.innerHTML = '<tr><td class="text-center text-muted py-4"><i class="bi bi-inbox"></i> Brak logów</td></tr>';
return;
}
logsContainer.innerHTML = logs.map(entry => `
<tr>
<td>
<small style="font-family: monospace; color: #666;">
<i class="bi bi-clock text-muted me-1"></i>${entry.timestamp || 'N/A'}<br>
<span class="text-muted">${entry.source || 'N/A'}</span><br>
<code style="color: #333; word-break: break-all; display: block; margin-top: 4px;">
${entry.message || 'N/A'}
</code>
</small>
</td>
</tr>
`).join('');
}
function updatePagination(data) {
const totalPages = Math.ceil(data.total / data.per_page);
loadedSpan.textContent = data.logs.length;
currentPageSpan.textContent = data.page;
totalPagesSpan.textContent = totalPages;
prevBtn.disabled = data.page === 1;
nextBtn.disabled = !data.has_more;
}
loadLogs();
});