Files
govoplan-search/docs/INTERFACE_PATTERN_MIGRATION.md
T
zemion 6ad7c6e0ef
Module Package Release / publish-packages (push) Successful in 11s
Release govoplan-search v0.1.20: centralize filtering and refresh behavior
2026-09-08 01:32:53 +02:00

86 lines
6.0 KiB
Markdown

# Search Interface Pattern Migration
This is the bounded interface-pattern evidence for GovOPlaN Search. Search owns
presentation and aggregation; source modules continue to own result data and
authorization, and optional external engines remain provider capabilities.
| Surface | Task and archetype | Consequence and state contract |
| --- | --- | --- |
| Title-bar Search command and overlay | Global or context-sensitive focused lookup | The left-most titlebar command, F3, and Ctrl/Cmd+K open the same focus-contained Core dialog with a full-width query field. Arrow keys move through the listbox, Enter opens the selected result, Escape closes it and restores focus. |
| Overlay and page filters | Shared Search-owned `SearchFilters` with Core multi-select dropdowns | Modules and Result types use one implementation with visible selection summaries, Select all, Deselect all, and Clear filters. Multiple selected values are alternatives within a group; both groups must match. Tab, Space, and Escape work inside the Search dialog without closing it when only a dropdown should close. |
| `/search` | Full-page search/results fallback | Query and filters are URL-stable, including explicitly empty selections. Clearing filters preserves the query, context, and unrelated URL parameters. Loading, empty, provider-partial, failed, and paged states remain inside the result region. |
| Result entries | Permission-filtered list-detail destinations | A source module supplies the title, safe summary, breadcrumbs, and destination. Search does not infer or bypass source authorization. |
| Administration > Search index | Operator table and bounded recovery actions | Operators inspect source coverage and queue health, process pending changes, reconcile module activation, and advance one bounded rebuild page at a time. Quarantined work remains visible. |
All surfaces use Core buttons, icon buttons, dialog, alerts, loading, scrolling,
and documentation-help primitives. Provider diagnostics are partial-state
evidence: safe results remain usable and a failing provider is identified
without exposing source data. Search has no destructive action. The responsive
layout collapses filters and results at narrow widths, and result activation is
available without pointer interaction.
## Filter and request contract
Both Search surfaces use the same Search-owned selection, catalogue, and request
helpers; the visual dropdown and its selection body are shared Core components,
also used by DataGrid and Notifications. Search does not define a second popover
or a parallel removable-chip interface.
- All selected means unrestricted (`null` in the UI). Select all does not freeze
the list to the currently loaded catalogue; newly available sources remain
eligible. No options selected (`[]`) intentionally returns no results without
calling search providers. A subset uses OR within its group and AND across
the module and result-type groups.
- The existing API remains compatible: omitted or empty `module` and
`resource_type` arrays still mean unrestricted. The UI's `matchNone` shortcut
never becomes a backend request parameter. `/search` uses `module_none=1` and
`resource_type_none=1` to preserve explicit empty selections; these flags take
precedence over contradictory repeated values. Subsets keep the existing
repeated URL parameters.
- Contextual overlay search remains bounded to its module and declared result
types. An empty intersection is no match, not an instruction to search all
types. Clear filters preserves the active context and query. Global module
selections are retained when temporarily switching to contextual search.
- Choices combine source catalogue metadata, observed result values, and
previously selected values that are no longer in the catalogue, so stale
selections remain removable. Labels use source descriptors and localized
module names. This is not a faceted result-count endpoint: catalogue entries
do not establish object access or guarantee matching objects.
- Query, filter, context, account/tenant authority, or API identity changes abort obsolete requests and
discard their results and cursors. The shared lifecycle also guards delayed
and load-more responses, so a previous search cannot populate the new search
or remain keyboard-activatable during the overlay debounce. Cookie-backed
tenant switches invalidate results even when the API token stays unchanged.
## Bedienung auf Deutsch
Die Suchüberlagerung und die vollständige Suchseite verwenden dieselben
Auswahllisten für **Module** und **Ergebnistypen**. Mehrere gewählte Werte sind
Alternativen innerhalb einer Gruppe; zwischen den Gruppen gilt eine gemeinsame
Einschränkung. **Alle auswählen** hebt die Einschränkung auf. **Alle abwählen**
zeigt bewusst keine Ergebnisse und startet keine Anbietersuche. **Filter
zurücksetzen** behält Suchbegriff und aktuellen Kontext bei.
Im Modulkontext bleiben die Ergebnisse auf das Modul und seine vorgesehenen
Typen begrenzt; eine unvereinbare Auswahl erweitert die Suche niemals. Die
vollständige Suchseite erhält auch eine ausdrücklich leere Auswahl in ihrer
URL. Die Optionen stammen aus Quellenkatalog und beobachteten Ergebnissen,
nicht aus einer berechtigungsgefilterten Trefferzählung. Unabhängig von den
Filtern prüft die Quelle weiterhin die Berechtigung für jedes Ergebnis.
Mit Tab werden die Filtersteuerungen erreicht, die Leertaste schaltet Optionen
um. Escape schließt zuerst die geöffnete Auswahlliste und setzt den Fokus auf
ihre Schaltfläche zurück; erst ein weiteres Escape schließt die
Suchüberlagerung. Bei einem Such- oder Filterwechsel werden veraltete Anfragen
und Ergebnisse verworfen, auch beim Nachladen weiterer Ergebnisseiten.
Das gilt auch bei einem Konto- oder Mandantenwechsel mit unverändertem API-Token.
Verification:
- `npm run test:search-filters`
- `npm run test:search-overlay`
- `npm run test:interface-pattern`
- the Core TypeScript graph, structural localization audit, theme check, module
permutations, and full-product bundle budget
- Search backend compatibility, cursor binding, and bilingual manifest tests