Bisher liess sich der laufenden Anwendung nicht ansehen, welche Fassung sie ist. Nach einem Update war damit auch nicht zu erkennen, ob es angekommen ist — die haeufigste Frage im Betrieb. Die Fussleiste nennt jetzt die Version und fuehrt auf /version mit dem vollstaendigen Verlauf. Zusammengetragen ist er aus dem, was es schon gab: dem Abschnitt „Gebaut" der Roadmap und der Git-Historie. Gepflegt wird der Verlauf an genau einer Stelle, src/lib/changelog.ts. Daraus entsteht sowohl die Seite als auch die CHANGELOG.md (npm run changelog); eine Pruefung mit --check wacht darueber, dass beides zusammenpasst. Zwei gepflegte Listen liefen unweigerlich auseinander, und ein Changelog, der nicht stimmt, ist schlimmer als keiner. Die Historie hatte keine Tags. Die Eintraege sind deshalb nach Erscheinungstag zu Versionen zusammengefasst — die Nummern sind nachtraeglich vergeben, die Daten stammen aus den Commits. Zu jeder Version gibt es jetzt einen annotierten Tag im Repo; v1.6.0 folgt beim Merge. Die Roadmap fuehrt den Verlauf nicht mehr doppelt, sondern verweist darauf und behaelt den Blick nach vorn. Refs #9
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
import type { Metadata } from "next";
|
|
import Link from "next/link";
|
|
|
|
import { Icon } from "@/components/icons";
|
|
import { Badge, Card } from "@/components/ui";
|
|
import { requirePageActor } from "@/lib/auth/guard";
|
|
import {
|
|
APP_VERSION,
|
|
CHANGELOG,
|
|
formatChangelogDate,
|
|
} from "@/lib/changelog";
|
|
|
|
export const metadata: Metadata = { title: "Version und Änderungen" };
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export default async function VersionPage() {
|
|
await requirePageActor();
|
|
|
|
return (
|
|
<div className="mx-auto max-w-3xl px-4 py-8 sm:px-6 sm:py-10">
|
|
<Link
|
|
href="/"
|
|
className="mb-5 inline-flex items-center gap-1.5 rounded-lg text-sm font-medium text-slate-600 transition-colors hover:text-slate-900"
|
|
>
|
|
<Icon name="arrowLeft" className="size-4" />
|
|
Zur Typ-Auswahl
|
|
</Link>
|
|
|
|
<div className="mb-7">
|
|
<h1 className="text-2xl font-bold tracking-tight text-slate-900 sm:text-3xl">
|
|
Version und Änderungen
|
|
</h1>
|
|
<p className="mt-2 text-slate-600">
|
|
Hier läuft Version{" "}
|
|
<span className="font-semibold text-slate-900">{APP_VERSION}</span>.
|
|
Darunter steht, was in welcher Fassung dazugekommen ist.
|
|
</p>
|
|
<p className="mt-2 text-sm text-slate-500">
|
|
Nach einem Update lohnt ein Blick hierher: Steht oben noch die alte
|
|
Nummer, läuft der Container noch mit dem alten Abbild.
|
|
</p>
|
|
</div>
|
|
|
|
<ol className="space-y-4">
|
|
{CHANGELOG.map((eintrag) => {
|
|
const laeuft = eintrag.version === APP_VERSION;
|
|
return (
|
|
<li key={eintrag.version}>
|
|
<Card>
|
|
<div className="mb-3 flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
|
<h2 className="text-lg font-semibold text-slate-900">
|
|
{eintrag.version}
|
|
</h2>
|
|
<span className="text-sm text-slate-500 tabular-nums">
|
|
{formatChangelogDate(eintrag.date)}
|
|
</span>
|
|
{laeuft ? (
|
|
<Badge tone="accent">läuft hier</Badge>
|
|
) : null}
|
|
</div>
|
|
|
|
<p className="mb-3 text-slate-600">{eintrag.summary}</p>
|
|
|
|
<ul className="space-y-1.5 text-sm text-slate-700">
|
|
{eintrag.changes.map((zeile) => (
|
|
<li key={zeile} className="flex gap-2.5">
|
|
<span
|
|
aria-hidden="true"
|
|
className="mt-2 size-1.5 shrink-0 rounded-full bg-slate-300"
|
|
/>
|
|
<span>{zeile}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</Card>
|
|
</li>
|
|
);
|
|
})}
|
|
</ol>
|
|
</div>
|
|
);
|
|
}
|