import { useEffect, useState } from "react"; import { getAudit, type AuditEvent } from "../api"; import { PanelHead } from "./IntegrationsView"; // Activity — connector/browser tool history, restructured onto the IntegrationsView page shell // (centered panel + PanelHead + cards), replacing the legacy `page-view` layout. Read-only: // filterable, with sanitized arguments. const CARD = "rounded-xl2 border border-line bg-panel"; const INPUT = "px-3 py-1.5 rounded-lg border border-line bg-paper text-[13px] text-ink outline-none focus:border-accent"; const BTN_ACCENT = "text-[12.5px] px-3 py-1.5 rounded-lg bg-accent text-white shrink-0"; export function AuditView() { const [events, setEvents] = useState([]); const [sessionFilter, setSessionFilter] = useState(""); const [connectorFilter, setConnectorFilter] = useState(""); const [toolFilter, setToolFilter] = useState(""); const refresh = () => getAudit({ limit: 150, session_id: sessionFilter.trim() || undefined, connector: connectorFilter.trim() || undefined, tool: toolFilter.trim() || undefined, }) .then(setEvents) .catch(() => setEvents([])); useEffect(() => { refresh(); }, []); return (
setSessionFilter(e.target.value)} /> setConnectorFilter(e.target.value)} /> setToolFilter(e.target.value)} />
{events.length === 0 ? (
No audit events yet.
) : (
{events.map((ev) => ( ))}
)}
); } function AuditRow({ ev }: { ev: AuditEvent }) { return (
{ev.tool} {ev.connector || "tool"} · {ev.stage || ev.status || "event"} · {ev.timestamp}
session {ev.session_id || "-"} {ev.approval ? `· ${ev.approval}` : ""} {ev.status ? `· ${ev.status}` : ""}
{ev.resource &&
resource: {ev.resource}
} {ev.args && Object.keys(ev.args).length > 0 && (
{formatAuditArgs(ev.args)}
)} {(ev.reason || ev.result_preview) && (
{ev.reason || ev.result_preview}
)}
); } function formatAuditArgs(args: Record) { return Object.entries(args) .map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`) .join(" "); }