Harden dashboard realtime state and controls

This commit is contained in:
jjbrunton committed 2026-08-08 15:41:58 +01:00
1 parent 4b3f00729f
commit d108903174
21 files changed
+422 -29

No files matched your search

@@ -1,6 +1,6 @@
import { useEffect, useReducer, useRef, useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import type { ActivityItem, ChatSyncStatus, DashboardEvent } from '../../../../../packages/api-contracts/src/index.js';
import { useDashboardRealtime } from '../../app/realtime-provider.js';
import {
createLiveConsoleState,
reduceLiveConsoleState,
@@ -9,12 +9,7 @@ import {
type ConsoleLevelFilter,
} from './live-console-model.js';
import { useActivityQuery, useFetchAllChatsMutation, useLogsQuery, useSyncStatusQuery, useTriggerChatSyncMutation } from './operations-queries.js';
import {
createBrowserEventSource,
createDashboardRealtimeClient,
queryKeysForDashboardEvent,
type RealtimeConnectionSnapshot,
} from './realtime-client.js';
import type { RealtimeConnectionSnapshot } from './realtime-client.js';
import './operations.css';
function formatTimestamp(timestamp: number | string): string {
@@ -73,7 +68,7 @@ export interface OperationsPageProps {
}
export function OperationsPage({ realtimeEnabled = true }: OperationsPageProps) {
const queryClient = useQueryClient();
const realtime = useDashboardRealtime();
const activityQuery = useActivityQuery();
const logsQuery = useLogsQuery();
const syncQuery = useSyncStatusQuery();
@@ -84,10 +79,7 @@ export function OperationsPage({ realtimeEnabled = true }: OperationsPageProps)
reduceLiveConsoleState,
createLiveConsoleState(500),
);
const [connection, setConnection] = useState<RealtimeConnectionSnapshot>({
status: 'idle',
isStale: true,
});
const connection = realtimeEnabled ? realtime.connection : { status: 'idle', isStale: true } as const;
const consoleEnd = useRef<HTMLDivElement>(null);
useEffect(() => {
@@ -106,10 +98,7 @@ export function OperationsPage({ realtimeEnabled = true }: OperationsPageProps)
}, [logsQuery.data]);
useEffect(() => {
if (!realtimeEnabled || typeof EventSource === 'undefined') {
setConnection({ status: 'idle', isStale: true });
return;
}
if (!realtimeEnabled) return;
function onEvent(event: DashboardEvent): void {
if (event.type === 'log.created') {
const entry: ConsoleEntry = {
@@ -121,18 +110,9 @@ export function OperationsPage({ realtimeEnabled = true }: OperationsPageProps)
};
dispatchConsole({ type: 'append', entry });
}
for (const queryKey of queryKeysForDashboardEvent(event)) {
void queryClient.invalidateQueries({ queryKey });
}
}
const client = createDashboardRealtimeClient({
sourceFactory: createBrowserEventSource,
onEvent,
onStateChange: setConnection,
});
client.start();
return () => client.stop();
}, [queryClient, realtimeEnabled]);
return realtime.subscribe(onEvent);
}, [realtime, realtimeEnabled]);
const visibleEntries = selectVisibleConsoleEntries(consoleState);
const syncBusy = syncQuery.data?.syncing === true || syncMutation.isPending || fetchAllMutation.isPending;