Wire FilterBar to server-side filter query language (ticket 016)

Send the raw filter string to GET /api/logs and GET /api/timeline
instead of doing a naive client-side substring match, surface the
API's 400 parse error inline under the FilterBar input, and drop the
now-dead visibleLogs client-side filtering in App.tsx.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
Hugh Kaznowski
2026-09-05 13:18:11 +01:00
co-authored by Claude Sonnet 5
parent 57d23c62e9
commit 10753cc9f8
3 changed files with 55 additions and 26 deletions
+11 -9
View File
@@ -14,6 +14,7 @@ export default function App() {
const [buckets, setBuckets] = useState<TimelineBucket[]>([])
const [range, setRange] = useState<TimeRange | null>(null)
const [filter, setFilter] = useState('')
const [filterError, setFilterError] = useState<string | null>(null)
useEffect(() => {
let cancelled = false
@@ -22,16 +23,19 @@ export default function App() {
try {
const [nextStats, nextBuckets, nextLogs] = await Promise.all([
fetchStats(),
fetchTimeline({ startMs: range?.startMs, endMs: range?.endMs }),
fetchLogs({ startMs: range?.startMs, endMs: range?.endMs, limit: 1000 }),
fetchTimeline({ startMs: range?.startMs, endMs: range?.endMs, filter: filter || undefined }),
fetchLogs({ startMs: range?.startMs, endMs: range?.endMs, limit: 1000, filter: filter || undefined }),
])
if (!cancelled) {
setStats(nextStats)
setBuckets(nextBuckets)
setLogs(nextLogs)
setFilterError(null)
}
} catch (err) {
if (!cancelled) {
setFilterError(err instanceof Error ? err.message : String(err))
}
} catch {
// engine not reachable yet; retry on next tick
}
}
@@ -41,17 +45,15 @@ export default function App() {
cancelled = true
clearInterval(id)
}
}, [range])
const visibleLogs = filter ? logs.filter((l) => l.text.includes(filter)) : logs
}, [range, filter])
return (
<div className="flex h-screen w-screen overflow-hidden">
<NavMenu stats={stats} />
<div className="flex min-w-0 flex-1 flex-col">
<FilterBar value={filter} onChange={setFilter} />
<FilterBar value={filter} onChange={setFilter} error={filterError} />
<LogTimeline buckets={buckets} range={range} onSelectRange={setRange} />
<LogPreview logs={visibleLogs} />
<LogPreview logs={logs} />
<ComingSoon title="Metrics" />
<ComingSoon title="Dashboards" />
</div>