import { api } from "../lib/api.js"; import { modal } from "../lib/modal.js"; class AuditLog extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.items = []; this.actors = []; this.loading = false; this.filters = { actor_id: "", entity_type: "", since: "", q: "" }; this.limit = 50; this.shadowRoot.innerHTML = `

Actividad

Fecha Operador Acción Ruta Resumen
`; } connectedCallback() { this.shadowRoot.getElementById("btnApply").addEventListener("click", () => this.applyFilters()); this.shadowRoot.getElementById("btnRefresh").addEventListener("click", () => this.load()); this.shadowRoot.getElementById("fSearch").addEventListener("keydown", (e) => { if (e.key === "Enter") this.applyFilters(); }); this.loadActors(); this.load(); } applyFilters() { this.filters.actor_id = this.shadowRoot.getElementById("fActor").value || ""; this.filters.entity_type = this.shadowRoot.getElementById("fEntity").value || ""; this.filters.since = this.shadowRoot.getElementById("fSince").value || ""; this.filters.q = this.shadowRoot.getElementById("fSearch").value.trim(); this.load(); } async loadActors() { try { const data = await api.auditActors(); this.actors = data.items || []; const sel = this.shadowRoot.getElementById("fActor"); const current = sel.value; sel.innerHTML = `` + this.actors.map((a) => ``).join(""); sel.value = current; } catch {} } async load() { this.loading = true; this.renderRows(); try { const params = { limit: this.limit }; if (this.filters.actor_id) params.actor_id = this.filters.actor_id; if (this.filters.entity_type) params.entity_type = this.filters.entity_type; if (this.filters.since) params.since = new Date(this.filters.since).toISOString(); if (this.filters.q) params.q = this.filters.q; const data = await api.auditLog(params); this.items = data.items || []; this.loading = false; this.renderRows(); } catch (e) { this.loading = false; this.items = []; this.renderRows(); } } renderRows() { const rows = this.shadowRoot.getElementById("rows"); const footer = this.shadowRoot.getElementById("footer"); if (this.loading) { rows.innerHTML = `Cargando...`; footer.textContent = "—"; return; } if (!this.items.length) { rows.innerHTML = `Sin actividad para los filtros aplicados.`; footer.textContent = "0 eventos"; return; } rows.innerHTML = this.items.map((r) => { const ts = new Date(r.created_at); const tsStr = ts.toLocaleString("es-AR", { day: "2-digit", month: "2-digit", year: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" }); const actor = r.actor_email || r.actor || "system"; const actorClass = r.actor_user_id ? "" : "system"; const actionClass = String(r.action || "").replace(/[^a-z_]/g, ""); return ` ${this.escapeHtml(tsStr)} ${this.escapeHtml(actor)} ${this.escapeHtml(r.action || "—")} ${this.escapeHtml(r.action_path || "")} ${this.escapeHtml(r.summary || `${r.entity_type || ""}${r.entity_id ? "#"+r.entity_id : ""}`)} `; }).join(""); rows.querySelectorAll('button[data-action="details"]').forEach((btn) => { btn.addEventListener("click", () => this.showDetails(btn.dataset.id)); }); footer.textContent = `${this.items.length} evento${this.items.length === 1 ? "" : "s"}${this.items.length >= this.limit ? " (mostrando últimos)" : ""}`; } showDetails(id) { const r = this.items.find((x) => String(x.id) === String(id)); if (!r) return; const lines = []; lines.push(`Fecha: ${new Date(r.created_at).toLocaleString("es-AR")}`); lines.push(`Operador: ${r.actor_email || r.actor || "system"}`); if (r.actor_ip) lines.push(`IP: ${r.actor_ip}`); lines.push(`Acción: ${r.action}`); lines.push(`Entidad: ${r.entity_type || "-"}${r.entity_id ? "#"+r.entity_id : ""}`); if (r.action_path) lines.push(`Ruta: ${r.action_path}`); if (r.summary) lines.push(`Resumen: ${r.summary}`); if (r.changes) lines.push("\nCambios:\n" + JSON.stringify(r.changes, null, 2)); modal.info(lines.join("\n")); } escapeHtml(s) { return String(s ?? "").replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } } customElements.define("audit-log", AuditLog);