diff --git a/docs/08-suche-und-export.md b/docs/08-suche-und-export.md index 8cfb4e8..aa042b8 100644 --- a/docs/08-suche-und-export.md +++ b/docs/08-suche-und-export.md @@ -14,6 +14,11 @@ Postgres Full-Text-Search, deutsche Konfiguration. Kein Elasticsearch. Filter: Status, Fallart, Zeitraum, Beteiligte, Klassifizierung, Tags, nur meine Fälle. +**Die Suche sucht ohne Angabe über alle Arten.** Wer einen Namen eintippt, will wissen, wo er +vorkommt, und nicht zuerst entscheiden, wonach er sucht. Die gemeinsame Ansicht zeigt je Art +eine Handvoll Treffer als eigenen Block, mit dem Weg in die volle Liste daneben; die einzelnen +Arten bleiben als Filter, und nur dort gibt es Facetten und Blättern. + **Die Sichtbarkeitsprüfung gehört in dieselbe Abfrage**, nicht als Nachfilter. Sonst stimmen Trefferzahl und Seitenlänge nicht und aus den Lücken lässt sich auf verborgene Akten schließen. Gleiches gilt für Facettenzähler. diff --git a/docs/13-entscheidungen.md b/docs/13-entscheidungen.md index 479be25..3de6a61 100644 --- a/docs/13-entscheidungen.md +++ b/docs/13-entscheidungen.md @@ -1213,3 +1213,29 @@ Der Test prüft die Regel und nicht die Zahl: er liest die Polsterung von `.fiel und verlangt, dass Label-Abstand und Reihenabstand darüber liegen. Wer die Polsterung ändert, fällt dort auf. Nachgemessen im Browser mit dem gebauten CSS: 8 px senkrecht gegen 5,6 px Innenpolsterung, 13,6 px waagerecht gegen 11,2 px. + +### Die Suche fängt bei „Alle" an + +Die Suche startete auf den Fallakten, und man musste die Art vorher wählen. Das ist die +falsche Reihenfolge: wer einen Namen eintippt, weiss noch nicht, ob er eine Fallakte, ein +Dokument oder eine Personalakte sucht — er will wissen, **wo** der Name vorkommt. + +`all` ist deshalb der Auslieferungszustand. Die gemeinsame Ansicht zeigt je Art fünf Treffer +als eigenen Block, mit dem Weg in die volle Liste daneben. Getrennte Blöcke und nicht eine +gemischte Liste nach Rang: ein Aktenzeichen neben einem Namen neben einer Dokumentnummer hat +keine erkennbare Ordnung. + +Facetten und Blättern gibt es weiterhin nur bei einer einzelnen Art. Beides bezieht sich auf +**eine** Grundmenge — ein Statusfilter über Fallakten und Personalakten zugleich wäre bei der +einen Art ein Filter und bei der anderen ein Ausschluss. + +### Die Bereiche in der Kopfzeile sind Knöpfe + +Sie waren Textlinks: von einem Fliesstextlink nicht zu unterscheiden und ohne jeden Hinweis +darauf, wo man gerade ist. Jetzt tragen sie dieselbe Knopfform wie alles Bedienbare, und der +Bereich, in dem man steht, ist gefüllt. + +Der gefüllte Zustand trägt **hellen Text statt der Akzentfarbe**: auf der getönten Fläche wäre +Akzent auf Akzent, und der Kontrast fiele unter die Untergrenze aus docs/10-design-system.md. +Aus demselben Grund liegt in einem Knopf steckende Zahl (`.btn-count`) in Mono und gedämpft — +sie ist eine Angabe, kein Teil der Beschriftung. diff --git a/web/app/(app)/layout.tsx b/web/app/(app)/layout.tsx index 439793e..520c8c7 100644 --- a/web/app/(app)/layout.tsx +++ b/web/app/(app)/layout.tsx @@ -3,6 +3,7 @@ import { signOut } from '@/auth' import { requireUser } from '@/lib/auth/current' import { de } from '@/lib/i18n/de' import { PaletteTrigger } from '@/components/palette/PaletteTrigger' +import { NavLinks } from '@/components/NavLinks' import { ProfileMenu } from '@/components/ProfileMenu' import { Avatar } from '@/components/Avatar' import { SearchBar } from '@/components/SearchBar' @@ -40,15 +41,19 @@ export default async function AppLayout({ children }: { children: React.ReactNod {de.app.shortName} - +
diff --git a/web/app/(app)/suche/page.tsx b/web/app/(app)/suche/page.tsx index 34899e2..33f1da8 100644 --- a/web/app/(app)/suche/page.tsx +++ b/web/app/(app)/suche/page.tsx @@ -2,8 +2,14 @@ import type { Metadata } from 'next' import Link from 'next/link' import { db } from '@/lib/db' import { requireUser } from '@/lib/auth/current' -import { parseFilters, toSearchParams, SEARCH_KINDS } from '@/lib/search/query' import { + parseFilters, + toSearchParams, + SEARCH_KINDS, + SEARCH_SCOPES, +} from '@/lib/search/query' +import { + PREVIEW_SIZE, searchCases, searchCounts, searchDocuments, @@ -49,34 +55,50 @@ export default async function SearchPage({ ]) const levelName = new Map(levels.map((l) => [l.level, l.name])) - const [ergebnis, zahlen] = await Promise.all([ - filters.kind === 'document' - ? searchDocuments(user.permissions, filters) - : filters.kind === 'personnel' - ? searchPersonnel(user.permissions, filters) - : searchCases(user.permissions, filters), - // Die Zahlen der anderen Arten. Ohne sie sucht man nach einem Namen, landet - // auf den Fallakten und erfährt nie, dass es dazu auch eine Personalakte - // gibt — der Reiter sieht leer aus wie jeder andere. + const alle = filters.kind === 'all' + + // In der gemeinsamen Ansicht je Art nur eine Handvoll: dort geht es darum, + // **wo** etwas liegt. Der Weg in die volle Liste steht daneben. + const stueck = alle ? { take: PREVIEW_SIZE } : {} + + const [faelle, dokumente, personen, zahlen] = await Promise.all([ + alle || filters.kind === 'case' ? searchCases(user.permissions, filters, stueck) : null, + alle || filters.kind === 'document' + ? searchDocuments(user.permissions, filters, stueck) + : null, + alle || filters.kind === 'personnel' + ? searchPersonnel(user.permissions, filters, stueck) + : null, + // Die Zahlen aller Arten. Ohne sie sucht man nach einem Namen, landet auf + // den Fallakten und erfährt nie, dass es dazu auch eine Personalakte gibt. searchCounts(user.permissions, filters), ]) - const statusTags = filters.kind === 'personnel' ? await listStatusTags() : [] + // Bei einer einzelnen Art hängt alles Weitere an ihr: Facetten, Blättern, + // die Trefferzahl in der Kopfzeile. Bei „Alle" gibt es das nicht — dort ist + // jede Art ein eigener Block mit eigenem Weg in die Vollansicht. + const ergebnis = alle ? null : (faelle ?? dokumente ?? personen)! + const gesamt = alle + ? zahlen.case + zahlen.document + (zahlen.personnel ?? 0) + : (ergebnis?.total ?? 0) + + const statusTags = + alle || filters.kind === 'personnel' ? await listStatusTags() : [] return (

{de.search.heading}

- {de.search.countLabel(ergebnis.total)} + {de.search.countLabel(gesamt)}