This commit is contained in:
lda committed 2026-04-12 03:11:02 +07:00
1 parent d0006f2db5
commit 5efcdf75ea
5 files changed
+323 -10

No files matched your search

+56 -1
View File
@@ -1,3 +1,5 @@
import { useMemo, useState } from "react";
import type { AuditEvent } from "@/api";
type Props = {
@@ -6,13 +8,66 @@ type Props = {
};
export function AuditPage({ events, onRefresh }: Props) {
const [eventType, setEventType] = useState("all");
const [outcome, setOutcome] = useState("all");
const [needle, setNeedle] = useState("");
const eventTypes = useMemo(
() => ["all", ...Array.from(new Set(events.map((e) => e.event_type))).sort()],
[events],
);
const outcomes = useMemo(
() => ["all", ...Array.from(new Set(events.map((e) => e.outcome))).sort()],
[events],
);
const filtered = useMemo(() => {
const q = needle.trim().toLowerCase();
return events.filter((e) => {
if (eventType !== "all" && e.event_type !== eventType) return false;
if (outcome !== "all" && e.outcome !== outcome) return false;
if (!q) return true;
return (
e.message.toLowerCase().includes(q)
|| e.event_type.toLowerCase().includes(q)
|| e.outcome.toLowerCase().includes(q)
|| (e.actor_id || "").toLowerCase().includes(q)
|| (e.agent_id || "").toLowerCase().includes(q)
);
});
}, [events, eventType, outcome, needle]);
return (
<section className="card span-full">
<div className="row-head">
<h2>Recent Audit Events</h2>
<button onClick={() => void onRefresh()}>Refresh</button>
</div>
<pre className="output">{JSON.stringify(events, null, 2)}</pre>
<div className="grid-3 compact">
<label>
Event type
<select value={eventType} onChange={(e) => setEventType(e.target.value)}>
{eventTypes.map((v) => (
<option key={v} value={v}>{v}</option>
))}
</select>
</label>
<label>
Outcome
<select value={outcome} onChange={(e) => setOutcome(e.target.value)}>
{outcomes.map((v) => (
<option key={v} value={v}>{v}</option>
))}
</select>
</label>
<label>
Search
<input value={needle} onChange={(e) => setNeedle(e.target.value)} placeholder="message, agent, actor" />
</label>
</div>
<p className="muted">Showing {filtered.length} of {events.length}</p>
<pre className="output">{JSON.stringify(filtered, null, 2)}</pre>
</section>
);
}