Spaces:
Running
Running
File size: 4,314 Bytes
d70361b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | /** Audit Log viewer — user activity trail (login/logout, uploads, detections,
* reports, admin/master-data changes). */
(function () {
const PAGE_SIZE = 50;
const wrap = document.getElementById('audit-log-table-wrap');
const meta = document.getElementById('audit-log-meta');
const subtitle = document.getElementById('audit-log-subtitle');
if (!wrap) return;
let auditPage = 0;
function fillSelect(select, values, current) {
if (!select) return;
const placeholder = select.options[0];
select.innerHTML = '';
select.appendChild(placeholder);
values.forEach((v) => {
const opt = document.createElement('option');
opt.value = v;
opt.textContent = v;
select.appendChild(opt);
});
if (current) select.value = current;
}
async function loadFilters() {
try {
const data = await ddaApi('GET', '/api/dda/audit-log/filters');
fillSelect(document.getElementById('audit-filter-action'), data.actions || []);
fillSelect(document.getElementById('audit-filter-module'), data.modules || []);
fillSelect(document.getElementById('audit-filter-role'), data.roles || []);
} catch (_) { /* filter dropdowns are a nice-to-have; ignore failures */ }
}
async function loadAuditLog() {
const params = new URLSearchParams({ limit: String(PAGE_SIZE), offset: String(auditPage * PAGE_SIZE) });
const action = document.getElementById('audit-filter-action')?.value || '';
const module = document.getElementById('audit-filter-module')?.value || '';
const role = document.getElementById('audit-filter-role')?.value || '';
const from = document.getElementById('audit-filter-from')?.value || '';
const to = document.getElementById('audit-filter-to')?.value || '';
if (action) params.set('action', action);
if (module) params.set('module', module);
if (role) params.set('role', role);
if (from) params.set('from', from);
if (to) params.set('to', to);
try {
const data = await ddaApi('GET', '/api/dda/audit-log?' + params.toString());
const rows = data.logs || [];
if (subtitle) subtitle.textContent = `User activity audit trail — ${data.total || 0} total records`;
if (meta) meta.textContent = `${rows.length ? auditPage * PAGE_SIZE + 1 : 0}–${auditPage * PAGE_SIZE + rows.length} of ${data.total || 0}`;
const totalPages = Math.max(1, Math.ceil((data.total || 0) / PAGE_SIZE));
renderPaginationControls(document.getElementById('audit-log-pagination'), auditPage, totalPages, (p) => {
auditPage = p;
loadAuditLog();
});
if (!rows.length) {
wrap.innerHTML = '<p class="dim">No audit events match these filters.</p>';
return;
}
wrap.innerHTML = `
<table class="dda-logs-table">
<thead>
<tr><th>Timestamp (IST)</th><th>User</th><th>Role</th><th>Action</th><th>Module</th><th>Details</th></tr>
</thead>
<tbody>
${rows.map((r) => `
<tr>
<td><time class="dda-date">${typeof formatDateIst === 'function' ? formatDateIst(r.timestamp) : escapeHtml(r.timestamp || '')}</time></td>
<td>${escapeHtml(r.user || '—')}</td>
<td>${escapeHtml(r.role || '—')}</td>
<td class="dda-action-cell">${escapeHtml(r.action)}</td>
<td>${escapeHtml(r.module || '—')}</td>
<td class="dda-log-msg">${escapeHtml(r.newValue || r.oldValue || '')}</td>
</tr>`).join('')}
</tbody>
</table>`;
} catch (err) {
wrap.innerHTML = `<p class="dim">${escapeHtml(err.message || 'Could not load the audit log.')}</p>`;
}
}
document.getElementById('btn-audit-refresh')?.addEventListener('click', loadAuditLog);
document.getElementById('btn-audit-filter')?.addEventListener('click', () => { auditPage = 0; loadAuditLog(); });
document.getElementById('btn-audit-reset')?.addEventListener('click', () => {
['audit-filter-action', 'audit-filter-module', 'audit-filter-role', 'audit-filter-from', 'audit-filter-to'].forEach((id) => {
const el = document.getElementById(id);
if (el) el.value = '';
});
auditPage = 0;
loadAuditLog();
});
loadFilters().then(loadAuditLog);
})();
|