fix: move status filtering server-side in Dashboard search
The Dashboard was fetching 50 results without a status filter and filtering client-side, causing fewer matches when filtering by error compared to route-specific pages that filter server-side. Now passes statusFilters to the OpenSearch query. Backend supports comma-separated status values for multi-select filters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -179,8 +179,20 @@ public class OpenSearchIndex implements SearchIndex {
|
||||
}
|
||||
|
||||
// Keyword filters (use .keyword sub-field for exact matching on dynamically mapped text fields)
|
||||
if (request.status() != null)
|
||||
filter.add(termQuery("status.keyword", request.status()));
|
||||
if (request.status() != null && !request.status().isBlank()) {
|
||||
String[] statuses = request.status().split(",");
|
||||
if (statuses.length == 1) {
|
||||
filter.add(termQuery("status.keyword", statuses[0].trim()));
|
||||
} else {
|
||||
filter.add(Query.of(q -> q.terms(t -> t
|
||||
.field("status.keyword")
|
||||
.terms(tv -> tv.value(
|
||||
java.util.Arrays.stream(statuses)
|
||||
.map(String::trim)
|
||||
.map(FieldValue::of)
|
||||
.toList())))));
|
||||
}
|
||||
}
|
||||
if (request.routeId() != null)
|
||||
filter.add(termQuery("route_id.keyword", request.routeId()));
|
||||
if (request.agentId() != null)
|
||||
|
||||
@@ -213,12 +213,18 @@ export default function Dashboard() {
|
||||
// ─── API hooks ───────────────────────────────────────────────────────────
|
||||
const { data: stats } = useExecutionStats(timeFrom, timeTo, routeId, appId)
|
||||
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, routeId, appId)
|
||||
// Convert design-system status filters (lowercase) to API status param (uppercase)
|
||||
const statusParam = statusFilters.size > 0
|
||||
? [...statusFilters].map(s => s.toUpperCase()).join(',')
|
||||
: undefined
|
||||
|
||||
const { data: searchResult } = useSearchExecutions(
|
||||
{
|
||||
timeFrom,
|
||||
timeTo,
|
||||
routeId: routeId || undefined,
|
||||
application: appId || undefined,
|
||||
status: statusParam,
|
||||
sortField,
|
||||
sortDir,
|
||||
offset: 0,
|
||||
@@ -230,17 +236,11 @@ export default function Dashboard() {
|
||||
const { data: diagram } = useDiagramLayout(detail?.diagramContentHash ?? null)
|
||||
|
||||
// ─── Rows ────────────────────────────────────────────────────────────────
|
||||
const allRows: Row[] = useMemo(
|
||||
const rows: Row[] = useMemo(
|
||||
() => (searchResult?.data || []).map((e: ExecutionSummary) => ({ ...e, id: e.executionId })),
|
||||
[searchResult],
|
||||
)
|
||||
|
||||
// Apply global status filters (time filtering is done server-side via timeFrom/timeTo)
|
||||
const rows: Row[] = useMemo(() => {
|
||||
if (statusFilters.size === 0) return allRows
|
||||
return allRows.filter((r) => statusFilters.has(r.status.toLowerCase() as any))
|
||||
}, [allRows, statusFilters])
|
||||
|
||||
// ─── KPI items ───────────────────────────────────────────────────────────
|
||||
const totalCount = stats?.totalCount ?? 0
|
||||
const failedCount = stats?.failedCount ?? 0
|
||||
|
||||
Reference in New Issue
Block a user