Ts
This commit is contained in:
1 parent
d0006f2db5
commit
5efcdf75ea
5 files changed
+323
-10
No files matched your search
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user