@@ -305,6 +305,23 @@ pre.raw-line { background: var(--bs-tertiary-bg); padding: .75rem; border-radius
|
||||
<button class="btn btn-outline-secondary btn-sm ms-2" id="testTelegramBtn"><i class="bi bi-send"></i> Test</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><i class="bi bi-x-circle me-1"></i>False Positives</div>
|
||||
<div class="card-body">
|
||||
<p class="small text-secondary">Lines matching these patterns will be ignored and not trigger any alert.</p>
|
||||
<div class="table-responsive mb-2">
|
||||
<table class="table table-sm mb-0">
|
||||
<thead><tr><th>Pattern</th><th>Description</th><th style="width:50px"></th></tr></thead>
|
||||
<tbody id="falsePositivesBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control font-monospace" id="fpPattern" placeholder="/healthcheck/i">
|
||||
<input type="text" class="form-control" id="fpDescription" placeholder="Description (optional)" style="max-width:200px">
|
||||
<button class="btn btn-primary" id="addFpBtn"><i class="bi bi-plus-lg"></i> Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header"><i class="bi bi-info-circle me-1"></i>How to get your user token</div>
|
||||
<div class="card-body small">
|
||||
@@ -949,6 +966,10 @@ async function loadSettings() {
|
||||
document.getElementById('telegramBotToken').value = res.bot_token || '';
|
||||
document.getElementById('telegramChatId').value = res.chat_id || '';
|
||||
} catch (e) { console.error('load telegram error', e); }
|
||||
|
||||
try {
|
||||
await loadFalsePositives();
|
||||
} catch (e) { console.error('load false positives error', e); }
|
||||
}
|
||||
|
||||
document.getElementById('saveTokensBtn').addEventListener('click', async () => {
|
||||
@@ -1010,6 +1031,54 @@ document.getElementById('testTelegramBtn').addEventListener('click', async () =>
|
||||
btn.innerHTML = '<i class="bi bi-send"></i> Test';
|
||||
});
|
||||
|
||||
// --- FALSE POSITIVES ---
|
||||
let fpItems = [];
|
||||
|
||||
async function loadFalsePositives() {
|
||||
try {
|
||||
fpItems = (await api('/false-positives')) || [];
|
||||
renderFalsePositives();
|
||||
} catch (e) { console.error('fp load error', e); }
|
||||
}
|
||||
|
||||
function renderFalsePositives() {
|
||||
const tbody = document.getElementById('falsePositivesBody');
|
||||
if (!fpItems.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="3" class="text-secondary small text-center">No false positives configured</td></tr>';
|
||||
} else {
|
||||
tbody.innerHTML = fpItems.map(fp => `<tr>
|
||||
<td><code>${esc(fp.pattern)}</code></td>
|
||||
<td class="text-secondary">${esc(fp.description || '')}</td>
|
||||
<td><button class="btn btn-outline-danger btn-sm py-0" onclick="deleteFp(${fp.id})"><i class="bi bi-trash"></i></button></td>
|
||||
</tr>`).join('');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFp(id) {
|
||||
if (!confirm('Delete this false positive pattern?')) return;
|
||||
try {
|
||||
await api('/false-positives/' + id, { method: 'DELETE' });
|
||||
toast('False positive deleted');
|
||||
loadFalsePositives();
|
||||
} catch (e) { toast('Delete failed', 'danger'); }
|
||||
}
|
||||
|
||||
document.getElementById('addFpBtn').addEventListener('click', async () => {
|
||||
const pattern = document.getElementById('fpPattern').value.trim();
|
||||
const description = document.getElementById('fpDescription').value.trim();
|
||||
if (!pattern) { toast('Enter a pattern', 'danger'); return; }
|
||||
try {
|
||||
await api('/false-positives', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ pattern, description }),
|
||||
});
|
||||
document.getElementById('fpPattern').value = '';
|
||||
document.getElementById('fpDescription').value = '';
|
||||
toast('False positive added');
|
||||
loadFalsePositives();
|
||||
} catch (e) { toast('Failed to add', 'danger'); }
|
||||
});
|
||||
|
||||
// --- LOGS ---
|
||||
async function loadLogs(query) {
|
||||
if (!query) {
|
||||
|
||||
Reference in New Issue
Block a user