Files
AfiS-Aktensystem/web/lib/search/query.ts
T
Harlekin e0b03ea336
Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
Gedankenstriche durch Bindestriche ersetzt
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die
README; an keiner Stelle Bedeutung, nur Zeichensetzung.
2026-09-04 08:54:52 +02:00

72 lines
2.5 KiB
TypeScript

/**
* Die Filter einer Suche, als Adressparameter und als Objekt.
*
* Ohne Abhängigkeiten: die Suchseite baut damit ihre Adresse, und gespeicherte
* Ansichten sind nichts anderes als eine solche Adresse. Dass beides dieselbe
* Darstellung benutzt, ist der Punkt - eine Ansicht ist ein Lesezeichen.
*/
/** Die Arten, über die einzeln gesucht werden kann. */
export const SEARCH_KINDS = ['case', 'document', 'personnel'] as const
export type SearchKind = (typeof SEARCH_KINDS)[number]
/**
* Was in der Adresse stehen kann. `all` ist der Auslieferungszustand: wer
* einen Namen eintippt, will wissen, wo er überhaupt vorkommt, und nicht
* zuerst entscheiden, wonach er sucht. Die einzelnen Arten bleiben als Filter.
*/
export const SEARCH_SCOPES = ['all', ...SEARCH_KINDS] as const
export type SearchScope = (typeof SEARCH_SCOPES)[number]
export type SearchFilters = {
q: string
kind: SearchScope
status?: string
templateKey?: string
classification?: number
/** Nur Akten, an denen der Suchende beteiligt ist. */
mine?: boolean
/** Wiedervorlage bis einschliesslich diesem Tag. */
dueBefore?: string
/** Seit diesem Zeitpunkt geändert, ISO. */
changedSince?: string
/** Seit diesem Zeitpunkt **nicht** geändert, ISO. */
idleSince?: string
cursor?: string
}
export function parseFilters(params: URLSearchParams | Record<string, string | undefined>): SearchFilters {
const get = (name: string): string | undefined => {
const wert = params instanceof URLSearchParams ? params.get(name) : params[name]
return wert && wert.length > 0 ? wert : undefined
}
const kind = get('kind')
const stufe = get('classification')
return {
q: (get('q') ?? '').slice(0, 200),
kind: (SEARCH_SCOPES as readonly string[]).includes(kind ?? '')
? (kind as SearchScope)
: 'all',
status: get('status'),
templateKey: get('templateKey'),
classification: stufe !== undefined && /^[0-5]$/.test(stufe) ? Number(stufe) : undefined,
mine: get('mine') === '1',
dueBefore: get('dueBefore'),
changedSince: get('changedSince'),
idleSince: get('idleSince'),
cursor: get('cursor'),
}
}
/** Zurück in eine Adresse. Leere Filter fallen weg, damit sie kurz bleibt. */
export function toSearchParams(filters: Partial<SearchFilters>): string {
const params = new URLSearchParams()
for (const [name, wert] of Object.entries(filters)) {
if (wert === undefined || wert === '' || wert === false) continue
params.set(name, wert === true ? '1' : String(wert))
}
return params.toString()
}