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.
98 lines
3.6 KiB
TypeScript
98 lines
3.6 KiB
TypeScript
import type { Metadata } from 'next'
|
|
import { notFound } from 'next/navigation'
|
|
import { db } from '@/lib/db'
|
|
import { requireUser } from '@/lib/auth/current'
|
|
import { loadVisibleCase } from '@/lib/cases/service'
|
|
import { loadChangeHistory } from '@/lib/cases/entryService'
|
|
import { de } from '@/lib/i18n/de'
|
|
import { wordDiff } from '@/lib/diff'
|
|
|
|
export const metadata: Metadata = { title: de.entry.changesHeading }
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
/**
|
|
* Änderungsübersicht als eigener Reiter an der Akte.
|
|
*
|
|
* Für die Abteilungsleitung ist das die Ansicht, mit der sie im Zweifel prüft,
|
|
* ob an einer Akte nachträglich gedreht wurde. Sichtbar für alle, die die Akte
|
|
* lesen dürfen - nicht nur für die Leitung. Das ist der ganze Sinn der Sache.
|
|
*/
|
|
export default async function ChangesPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ caseNumber: string }>
|
|
}) {
|
|
const user = await requireUser()
|
|
const { caseNumber } = await params
|
|
|
|
const akte = await loadVisibleCase(user.permissions, caseNumber)
|
|
if (!akte) notFound()
|
|
|
|
const versionen = await loadChangeHistory(user.permissions, akte.id)
|
|
|
|
const namen = new Map(
|
|
(
|
|
await db.user.findMany({
|
|
where: { id: { in: [...new Set(versionen.map((v) => v.editedById))] } },
|
|
select: { id: true, displayName: true },
|
|
})
|
|
).map((u) => [u.id, u.displayName]),
|
|
)
|
|
|
|
return (
|
|
<>
|
|
{/* Aktenzeichen und Titel stehen im Layout, hier nur noch die Überschrift
|
|
des Reiters. */}
|
|
<h2 className="font-condensed">{de.entry.changesHeading}</h2>
|
|
<p className="mt-2 max-w-(--container-measure) text-text-dim">{de.entry.changesIntro}</p>
|
|
|
|
{versionen.length === 0 ? (
|
|
<p className="mt-8 text-text-dim">{de.entry.changesEmpty}</p>
|
|
) : (
|
|
<ol className="mt-8 border-t border-line">
|
|
{versionen.map((version) => (
|
|
<li key={version.id} className="border-b border-line py-5">
|
|
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1 text-2xs text-text-dim">
|
|
<span className="font-condensed">
|
|
{de.entry.versionLabel(version.version)} → {version.version + 1}
|
|
</span>
|
|
<span className="font-mono">
|
|
{namen.get(version.editedById) ?? version.editedById}
|
|
</span>
|
|
<time dateTime={version.editedAt.toISOString()}>
|
|
{version.editedAt.toLocaleString('de-DE')}
|
|
</time>
|
|
</div>
|
|
|
|
{version.changeReason ? (
|
|
<p className="mt-1.5 text-sm">
|
|
<span className="font-condensed text-text-dim">{de.entry.changeReason}: </span>
|
|
{version.changeReason}
|
|
</p>
|
|
) : null}
|
|
|
|
{/* Wortdiff statt zweier Spalten: bei langen Vermerken sieht man
|
|
sonst nicht, was sich geändert hat. */}
|
|
<p className="mt-3 max-w-(--container-measure) text-sm whitespace-pre-wrap">
|
|
{wordDiff(version.body, version.entry.body).map((teil, index) =>
|
|
teil.kind === 'gleich' ? (
|
|
<span key={index}>{teil.text}</span>
|
|
) : teil.kind === 'entfernt' ? (
|
|
<del key={index} className="text-stamp-4 decoration-stamp-4">
|
|
{teil.text}
|
|
</del>
|
|
) : (
|
|
<ins key={index} className="text-stamp-2 no-underline">
|
|
{teil.text}
|
|
</ins>
|
|
),
|
|
)}
|
|
</p>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
)}
|
|
</>
|
|
)
|
|
}
|