summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/directives/EventsTab.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-06 20:06:30 +0000
committersoryu <soryu@soryu.co>2026-02-06 20:15:27 +0000
commit1b692b8cde4a888c8a35af69231f181b57bf5619 (patch)
tree74ce25ce6ee5fb4536b53404e1a0ae923e85c30d /makima/frontend/src/components/directives/EventsTab.tsx
parent139be135c2086d725e4f040e744bb25acd436549 (diff)
downloadsoryu-1b692b8cde4a888c8a35af69231f181b57bf5619.tar.gz
soryu-1b692b8cde4a888c8a35af69231f181b57bf5619.zip
Fix: Cleanup old chain code
Diffstat (limited to 'makima/frontend/src/components/directives/EventsTab.tsx')
-rw-r--r--makima/frontend/src/components/directives/EventsTab.tsx77
1 files changed, 77 insertions, 0 deletions
diff --git a/makima/frontend/src/components/directives/EventsTab.tsx b/makima/frontend/src/components/directives/EventsTab.tsx
new file mode 100644
index 0000000..4dd739a
--- /dev/null
+++ b/makima/frontend/src/components/directives/EventsTab.tsx
@@ -0,0 +1,77 @@
+import { useMemo } from "react";
+import type { DirectiveWithProgress } from "../../lib/api";
+import { useDirectiveEventSubscription } from "../../hooks/useDirectives";
+
+export function EventsTab({ directive }: { directive: DirectiveWithProgress }) {
+ // Subscribe to real-time events via SSE
+ const { events: streamEvents, isConnected, error: sseError } = useDirectiveEventSubscription(directive.id);
+
+ // Combine initial events with streamed events (avoiding duplicates)
+ const allEvents = useMemo(() => {
+ const eventMap = new Map();
+ // Add initial events first
+ directive.recentEvents.forEach((e) => eventMap.set(e.id, e));
+ // Add streamed events (will override any duplicates)
+ streamEvents.forEach((e) => eventMap.set(e.id, e));
+ // Sort by created_at descending (most recent first)
+ return Array.from(eventMap.values()).sort(
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
+ );
+ }, [directive.recentEvents, streamEvents]);
+
+ return (
+ <div className="space-y-4">
+ {/* Connection status */}
+ <div className="flex items-center justify-between text-[10px] font-mono">
+ <div className="flex items-center gap-2">
+ <span className={isConnected ? "text-green-400" : "text-[#556677]"}>
+ {isConnected ? "\u25CF Live" : "\u25CB Connecting..."}
+ </span>
+ {sseError && <span className="text-red-400">{sseError}</span>}
+ </div>
+ <span className="text-[#556677]">{allEvents.length} events</span>
+ </div>
+
+ {/* Event list */}
+ {allEvents.length === 0 ? (
+ <div className="text-center py-8">
+ <p className="font-mono text-sm text-[#556677]">No events yet</p>
+ </div>
+ ) : (
+ <div className="space-y-2">
+ {allEvents.map((event) => {
+ const severityColors: Record<string, string> = {
+ info: "text-[#75aafc]",
+ warning: "text-yellow-400",
+ error: "text-red-400",
+ critical: "text-red-600",
+ };
+ const severityColor = severityColors[event.severity] || "text-[#556677]";
+
+ return (
+ <div
+ key={event.id}
+ className="p-3 bg-[rgba(117,170,252,0.02)] border border-[rgba(117,170,252,0.1)]"
+ >
+ <div className="flex items-center justify-between">
+ <div className="flex items-center gap-2">
+ <span className={`font-mono text-xs ${severityColor}`}>{event.eventType}</span>
+ <span className="font-mono text-[10px] text-[#556677]">{event.actorType}</span>
+ </div>
+ <span className="font-mono text-[10px] text-[#556677]">
+ {new Date(event.createdAt).toLocaleString()}
+ </span>
+ </div>
+ {event.eventData != null && (
+ <pre className="font-mono text-[10px] text-[#556677] mt-1 overflow-x-auto">
+ {JSON.stringify(event.eventData, null, 2)}
+ </pre>
+ )}
+ </div>
+ );
+ })}
+ </div>
+ )}
+ </div>
+ );
+}