Skip to content

Commit e06db90

Browse files
Michael Bunsenclaude
authored andcommitted
feat(ui): align model-agreement hook with BE rename + multi-value query params
- Rename `agreed_under_order_*` → `agreed_any_rank_*` to match the endpoint's dropped ORDER threshold (0565f06). - Add optional `agreement_coarsest_rank` + `agreed_coarser_rank_*` fields to the response type (not consumed yet — UI follows in #1308). - Widen `filters` to accept arrays and append repeated query params so multi-value filters (e.g. `algorithm`, `not_algorithm` — backend reads via `request.query_params.getlist(...)`) survive. Per CodeRabbit review. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 0b1975a commit e06db90

1 file changed

Lines changed: 25 additions & 8 deletions

File tree

ui/src/data-services/hooks/occurrences/stats/useModelAgreement.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,45 @@ interface ModelAgreementResponse {
1010
no_prediction_count: number
1111
agreed_exact_count: number
1212
agreed_exact_pct: number
13-
agreed_under_order_count: number
14-
agreed_under_order_pct: number
13+
agreed_any_rank_count: number
14+
agreed_any_rank_pct: number
15+
// Only populated when the caller passes ?agreement_coarsest_rank=<RANK>.
16+
agreement_coarsest_rank: string | null
17+
agreed_coarser_rank_count: number | null
18+
agreed_coarser_rank_pct: number | null
1519
}
1620

21+
type FilterPrimitive = string | number | boolean
22+
type FilterValue = FilterPrimitive | FilterPrimitive[] | null | undefined
23+
1724
// Accepts an arbitrary filter map so the occurrence list page's filter state
1825
// can be threaded through unchanged (deployment, event, taxon, score
19-
// thresholds, apply_defaults, etc).
26+
// thresholds, apply_defaults, etc). Arrays are appended as repeated query
27+
// params so multi-select filters (e.g. `algorithm`, `not_algorithm`, which
28+
// the backend reads via `request.query_params.getlist(...)`) survive.
2029
export const useModelAgreement = (
2130
projectId?: string,
22-
filters?: Record<string, string | number | boolean | undefined>
31+
filters?: Record<string, FilterValue>
2332
) => {
2433
const url = `${API_URL}/${API_ROUTES.OCCURRENCES}/stats/model-agreement/`
2534

2635
const params = new URLSearchParams()
2736
if (projectId) params.set('project_id', projectId)
2837
if (filters) {
2938
Object.entries(filters).forEach(([key, value]) => {
30-
if (value !== undefined && value !== '' && value !== null) {
31-
params.set(key, String(value))
39+
if (value === undefined || value === null || value === '') return
40+
if (Array.isArray(value)) {
41+
value.forEach((item) => {
42+
if (item !== undefined && item !== null && item !== '') {
43+
params.append(key, String(item))
44+
}
45+
})
46+
return
3247
}
48+
params.set(key, String(value))
3349
})
3450
}
51+
const queryString = params.toString()
3552

3653
const { data, isLoading, isFetching, error } =
3754
useAuthorizedQuery<ModelAgreementResponse>({
@@ -40,9 +57,9 @@ export const useModelAgreement = (
4057
'stats',
4158
'model-agreement',
4259
projectId,
43-
filters,
60+
queryString,
4461
],
45-
url: `${url}?${params.toString()}`,
62+
url: `${url}?${queryString}`,
4663
})
4764

4865
return {

0 commit comments

Comments
 (0)