Server-side term/authority search for the combobox picker (large vocabularies) #43

Open
opened 2026-06-06 10:04:07 +00:00 by logaritmisk · 0 comments
Owner

Context

The term/authority picker (#27, merged de035bd) is a searchable combobox that filters the full option list client-side (useTerms/useAuthorities load everything, cached 5 min). That's fine for the current small vocabularies, but degrades once a vocabulary has hundreds/thousands of terms (large payload, no server filtering). This was explicitly deferred from #27.

What to do

  • Backend: add debounced server-side search endpoints, e.g. GET /api/admin/vocabularies/{id}/terms?q=<text>&limit=<n> (search term_label.label, any lang, scoped to the vocabulary; ILIKE/trigram; return top-N) and extend GET /api/admin/authorities?kind=&q=<text>&limit=<n>. Empty q → first N. ViewInternal.
  • Frontend: have OptionsCombobox (or a server-backed variant) query the endpoint (debounced) via inputValue/onInputValueChange instead of loading the full list, for large vocabularies. Decide the client-vs-server threshold (or always-server).
  • Selected id → label resolution (the tricky part): when editing an object whose stored term/authority id isn't in the current (filtered/server) result set, the combobox still needs to display its label. Add a by-id lookup (GET .../terms/{term_id}, authorities/{id}) or include the selected id in results.
  • Keep the value = id contract + active-locale labels. Mind the bundle (object-form chunk).

References

  • web/src/objects/options-combobox.tsx, web/src/objects/field-input.tsx
  • web/src/api/queries.ts (useTerms, useAuthorities)
  • crates/api/src/admin_vocab.rs (list_terms), crates/api/src/admin_authorities.rs (list_authorities)
  • Design note: docs/superpowers/specs/2026-06-06-searchable-term-authority-picker-design.md ("Out of scope → follow-up issue").

Deferred from #27 (client-side filtering shipped first; server-side search when a vocabulary genuinely grows large).

## Context The term/authority picker (#27, merged `de035bd`) is a searchable combobox that filters the **full** option list **client-side** (`useTerms`/`useAuthorities` load everything, cached 5 min). That's fine for the current small vocabularies, but degrades once a vocabulary has hundreds/thousands of terms (large payload, no server filtering). This was explicitly deferred from #27. ## What to do - **Backend:** add debounced server-side search endpoints, e.g. `GET /api/admin/vocabularies/{id}/terms?q=<text>&limit=<n>` (search `term_label.label`, any lang, scoped to the vocabulary; ILIKE/trigram; return top-N) and extend `GET /api/admin/authorities?kind=&q=<text>&limit=<n>`. Empty `q` → first N. `ViewInternal`. - **Frontend:** have `OptionsCombobox` (or a server-backed variant) query the endpoint (debounced) via `inputValue`/`onInputValueChange` instead of loading the full list, for large vocabularies. Decide the client-vs-server threshold (or always-server). - **Selected id → label resolution (the tricky part):** when editing an object whose stored term/authority id isn't in the current (filtered/server) result set, the combobox still needs to display its label. Add a by-id lookup (`GET .../terms/{term_id}`, `authorities/{id}`) or include the selected id in results. - Keep the `value = id` contract + active-locale labels. Mind the bundle (object-form chunk). ## References - `web/src/objects/options-combobox.tsx`, `web/src/objects/field-input.tsx` - `web/src/api/queries.ts` (`useTerms`, `useAuthorities`) - `crates/api/src/admin_vocab.rs` (`list_terms`), `crates/api/src/admin_authorities.rs` (`list_authorities`) - Design note: `docs/superpowers/specs/2026-06-06-searchable-term-authority-picker-design.md` ("Out of scope → follow-up issue"). _Deferred from #27 (client-side filtering shipped first; server-side search when a vocabulary genuinely grows large)._
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logaritmisk/biggus-dickus#43