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
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die README; an keiner Stelle Bedeutung, nur Zeichensetzung.
82 lines
2.8 KiB
TypeScript
82 lines
2.8 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import { db } from '@/lib/db'
|
|
import { getCurrentUser } from '@/lib/auth/current'
|
|
import { visibleCaseWhere } from '@/lib/access/caseFilter'
|
|
import { visiblePersonnelWhere } from '@/lib/access/personnelFilter'
|
|
import { listRecent } from '@/lib/recent/service'
|
|
|
|
export const runtime = 'nodejs'
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
/** So viele Treffer je Art zeigt die Palette. Mehr passt nicht auf den Schirm. */
|
|
const LIMIT = 5
|
|
|
|
/** So viele Sprünge zeigt die Palette, solange nichts im Feld steht. */
|
|
const RECENT_IN_PALETTE = 6
|
|
|
|
/**
|
|
* Schnellsuche für die Kommandopalette.
|
|
*
|
|
* Bewusst schmal: Aktenzeichen, Titel und Namen, kein Volltext über Inhalte.
|
|
* Wer die Palette öffnet, will springen, nicht recherchieren - dafür gibt es
|
|
* `/suche`.
|
|
*
|
|
* Der Trigram-Index auf `caseNumber` und `displayName` fängt Tippfehler ab,
|
|
* siehe docs/08-suche-und-export.md.
|
|
*/
|
|
export async function GET(request: Request): Promise<Response> {
|
|
const user = await getCurrentUser()
|
|
if (!user) return NextResponse.json({ cases: [], personnel: [] }, { status: 404 })
|
|
|
|
const params = new URL(request.url).searchParams
|
|
|
|
// Leeres Feld: die eigene Sprungliste. Wer die Palette öffnet, will meistens
|
|
// dorthin zurück, wo er eben war - und nicht erst tippen.
|
|
if (params.get('recent') === '1') {
|
|
const zuletzt = await listRecent(user.permissions, RECENT_IN_PALETTE)
|
|
return NextResponse.json({
|
|
cases: [],
|
|
personnel: [],
|
|
recent: zuletzt.map((eintrag) => ({
|
|
href: eintrag.href,
|
|
primary: eintrag.label,
|
|
secondary: eintrag.secondary,
|
|
classification: eintrag.classification,
|
|
})),
|
|
})
|
|
}
|
|
|
|
const begriff = (params.get('q') ?? '').trim().slice(0, 100)
|
|
if (begriff.length < 2) return NextResponse.json({ cases: [], personnel: [] })
|
|
|
|
const enthaelt = { contains: begriff, mode: 'insensitive' as const }
|
|
const darfPersonal =
|
|
user.permissions.isAdmin || user.permissions.permissions.has('personnel.read')
|
|
|
|
const [faelle, personen] = await Promise.all([
|
|
db.case.findMany({
|
|
where: {
|
|
AND: [
|
|
visibleCaseWhere(user.permissions),
|
|
{ OR: [{ caseNumber: enthaelt }, { title: enthaelt }] },
|
|
],
|
|
},
|
|
orderBy: { updatedAt: 'desc' },
|
|
take: LIMIT,
|
|
select: { id: true, caseNumber: true, title: true, classification: true },
|
|
}),
|
|
darfPersonal
|
|
? db.personnelFile.findMany({
|
|
where: {
|
|
AND: [visiblePersonnelWhere(user.permissions), { displayName: enthaelt }],
|
|
},
|
|
orderBy: { displayName: 'asc' },
|
|
take: LIMIT,
|
|
select: { id: true, displayName: true, rank: true, classification: true },
|
|
})
|
|
: Promise.resolve([]),
|
|
])
|
|
|
|
return NextResponse.json({ cases: faelle, personnel: personen })
|
|
}
|