fix(ui): include SSE live data when project filter is active (#1315)

When a project filter was selected in the Web UI, all SSE live data
(observations, summaries, prompts) was completely discarded. Only
paginated API data was shown, meaning new real-time events were
invisible until the user refreshed the page.

Fix: filter SSE data by project before merging with paginated data,
instead of discarding it entirely.

Fixes #1313

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
GigiTiti-Kai
2026-03-13 12:01:48 +09:00
committed by GitHub
parent 1fac57535e
commit b88566dcdd
2 changed files with 15 additions and 19 deletions
+13 -16
View File
@@ -25,29 +25,26 @@ export function App() {
const { preference, resolvedTheme, setThemePreference } = useTheme(); const { preference, resolvedTheme, setThemePreference } = useTheme();
const pagination = usePagination(currentFilter); const pagination = usePagination(currentFilter);
// When filtering by project: ONLY use paginated data (API-filtered) // Merge SSE live data with paginated data, filtering by project when active
// When showing all projects: merge SSE live data with paginated data
const allObservations = useMemo(() => { const allObservations = useMemo(() => {
if (currentFilter) { const live = currentFilter
// Project filter active: API handles filtering, ignore SSE items ? observations.filter(o => o.project === currentFilter)
return paginatedObservations; : observations;
} return mergeAndDeduplicateByProject(live, paginatedObservations);
// No filter: merge SSE + paginated, deduplicate by ID
return mergeAndDeduplicateByProject(observations, paginatedObservations);
}, [observations, paginatedObservations, currentFilter]); }, [observations, paginatedObservations, currentFilter]);
const allSummaries = useMemo(() => { const allSummaries = useMemo(() => {
if (currentFilter) { const live = currentFilter
return paginatedSummaries; ? summaries.filter(s => s.project === currentFilter)
} : summaries;
return mergeAndDeduplicateByProject(summaries, paginatedSummaries); return mergeAndDeduplicateByProject(live, paginatedSummaries);
}, [summaries, paginatedSummaries, currentFilter]); }, [summaries, paginatedSummaries, currentFilter]);
const allPrompts = useMemo(() => { const allPrompts = useMemo(() => {
if (currentFilter) { const live = currentFilter
return paginatedPrompts; ? prompts.filter(p => p.project === currentFilter)
} : prompts;
return mergeAndDeduplicateByProject(prompts, paginatedPrompts); return mergeAndDeduplicateByProject(live, paginatedPrompts);
}, [prompts, paginatedPrompts, currentFilter]); }, [prompts, paginatedPrompts, currentFilter]);
// Toggle context preview modal // Toggle context preview modal
+2 -3
View File
@@ -5,10 +5,9 @@
/** /**
* Merge real-time SSE items with paginated items, removing duplicates by ID * Merge real-time SSE items with paginated items, removing duplicates by ID
* NOTE: This should ONLY be used when no project filter is active. * Callers should pre-filter liveItems by project when a filter is active.
* When filtering, use ONLY paginated data (API-filtered).
* *
* @param liveItems - Items from SSE stream (unfiltered) * @param liveItems - Items from SSE stream (pre-filtered if needed)
* @param paginatedItems - Items from pagination API * @param paginatedItems - Items from pagination API
* @returns Merged and deduplicated array * @returns Merged and deduplicated array
*/ */