Die Bedienungsanleitung hatte zu jedem alten Abschnitt ein Bild und zu keinem der sechs neuen. Sechs Aufnahmen kommen dazu: Logo im Code, Dublettenwarnung, Filter nach Art, Freigabe je Gruppe, Kurzhilfe und der Bericht einer geprueften Domain. Das Skript dafuer lief seit einer Umbenennung ins Leere — es wartete auf einen Dialogtitel "Ziel bearbeiten", der inzwischen "Code bearbeiten" heisst. Damit sind auch die uebrigen sechzehn Bilder neu; sie stammten noch aus 1.2.0 und zeigten eine aeltere Oberflaeche. schuss() kann jetzt einen Ausschnitt aufnehmen statt der ganzen Seite — fuer Dialoge und einzelne Karten, bei denen die volle Seite mehr verdeckt als zeigt. Das Beispiellogo entsteht im Skript, damit kein ungepflegtes Bild im Repo liegt. In der Kopfdoku steht jetzt, dass BASE_URL der Instanz auf dieselbe Adresse zeigen muss wie BASE — sonst erreicht die Anwendung sich beim Domain-Check nicht selbst und das Bild zeigt einen Fehlschlag.
150 lines
6.8 KiB
TypeScript
150 lines
6.8 KiB
TypeScript
import pkg from "../../package.json";
|
|
|
|
/**
|
|
* Änderungsverlauf der Anwendung — die einzige Quelle dafür.
|
|
*
|
|
* Hieraus entsteht beides: die Seite unter `/version` und die `CHANGELOG.md`
|
|
* im Wurzelverzeichnis (`npm run changelog`). Zwei gepflegte Listen liefen
|
|
* unweigerlich auseinander; eine Prüfung wacht darüber, dass die erzeugte
|
|
* Datei zu dieser Quelle passt.
|
|
*
|
|
* Die Einträge bis 1.5.0 sind aus dem Abschnitt „Gebaut“ der Roadmap und der
|
|
* Git-Historie zusammengetragen: Versionsnummern gab es damals nicht, deshalb
|
|
* ist je **Erscheinungstag** eine gebildet. Nachträglich vergeben, aber die
|
|
* Daten selbst stimmen. Ab 1.6.0 trägt jede Fassung einen Git-Tag.
|
|
*/
|
|
export type ChangelogEntry = {
|
|
version: string;
|
|
/** ISO-Datum, an dem der Stand entstanden ist. */
|
|
date: string;
|
|
/** Eine Zeile zur Einordnung — was diese Version ausmacht. */
|
|
summary: string;
|
|
changes: string[];
|
|
};
|
|
|
|
export const CHANGELOG: readonly ChangelogEntry[] = [
|
|
{
|
|
version: "1.7.1",
|
|
date: "2026-08-21",
|
|
summary: "Bilder zu den neuen Funktionen in der Bedienungsanleitung.",
|
|
changes: [
|
|
"Die Bedienungsanleitung zeigt die Funktionen aus 1.7.0 jetzt auch im Bild: Logo im Code, Dublettenwarnung, Filter nach Art, Freigabe je Gruppe, Kurzhilfe und Domain-Bericht.",
|
|
"Alle übrigen Bilder mit erneuert — sie stammten noch aus 1.2.0.",
|
|
"Das Skript, das die Bilder erzeugt, lief seit einer Umbenennung ins Leere und tut es wieder.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.7.0",
|
|
date: "2026-08-21",
|
|
summary: "Logo im Code, Freigabe je Gruppe und ein Domain-Check.",
|
|
changes: [
|
|
"Ein Logo in der Mitte des Codes — das der Installation oder ein eigenes je Code, 10 bis 25 % der Kantenlänge. Die Fehlerkorrektur springt dabei auf H.",
|
|
"QR-Typen lassen sich je Gruppe freigeben. Die Grundeinstellung bleibt die Grundlage; eine globale Abschaltung gewinnt immer.",
|
|
"Der Knopf „Prüfen“ bei jeder Domain meldet DNS, Zertifikat, Erreichbarkeit — und ob dahinter wirklich diese Installation steht.",
|
|
"Eine Kurzhilfe auf der Domain-Seite führt in sechs Schritten auf, was für eine neue Domain einzurichten ist.",
|
|
"„Meine Codes“ lässt sich nach Art filtern: alle, nur dynamische, nur statische.",
|
|
"Beim Ablegen eines statischen Codes wird gewarnt, wenn derselbe Inhalt schon in der Gruppe liegt.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.6.0",
|
|
date: "2026-08-21",
|
|
summary: "Sichtbare Version mit Änderungsverlauf.",
|
|
changes: [
|
|
"Die laufende Version steht in der Fußzeile und führt auf eine Seite mit dem vollständigen Änderungsverlauf.",
|
|
"Der Verlauf wird an einer Stelle gepflegt; die CHANGELOG.md im Projekt entsteht daraus.",
|
|
"Die Roadmap verweist für Vergangenes auf den Changelog und behält den Blick nach vorn.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.5.0",
|
|
date: "2026-08-20",
|
|
summary: "Statische Codes lassen sich benennen und ablegen.",
|
|
changes: [
|
|
"Das Feld „Name“ gilt in beiden Betriebsarten, nicht mehr nur bei dynamischen Codes.",
|
|
"Der Name bestimmt den Dateinamen beim Herunterladen.",
|
|
"Ein statischer Code lässt sich in „Meine Codes“ ablegen — als Schnappschuss ohne Kurz-Link und ohne Scan-Zähler.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.4.0",
|
|
date: "2026-08-17",
|
|
summary: "Sprechende Kurz-Links und eine früh erkannte Fehlkonfiguration.",
|
|
changes: [
|
|
"Kurz-Links selbst vergeben und nachträglich ändern, mit „/“ als Trenner.",
|
|
"Die vorherige Adresse bleibt gültig und lässt sich einzeln freigeben — gedruckte Codes bleiben gültig.",
|
|
"Vergeben und Ändern ist Administratoren vorbehalten und in der Verwaltung für Bearbeiter freigebbar.",
|
|
"Weicht BASE_URL von der aufgerufenen Adresse ab, meldet die Anmeldung das sofort statt erst am Ende.",
|
|
"Auf der Anmeldeseite steht nicht mehr, wie die Anmeldung konfiguriert ist.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.3.0",
|
|
date: "2026-08-16",
|
|
summary: "Eigenes Erscheinungsbild und ein Dark Mode.",
|
|
changes: [
|
|
"Name, Logo, Favicon und Akzentfarbe sind im Admin-Bereich einstellbar.",
|
|
"Hell und dunkel folgen dem Betriebssystem, mit Umschalter für eine eigene Wahl.",
|
|
"Das Update-Skript erklärt, warum ein Vorspulen scheitert, statt nur abzubrechen.",
|
|
"Die Authentik-Anleitung sagt deutlicher, wie die Redirect URI zu bilden ist.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.2.0",
|
|
date: "2026-08-15",
|
|
summary: "Single Sign-on, Dokumentation und eine Sicherheitsdurchsicht.",
|
|
changes: [
|
|
"Anmeldung über Authentik und andere OIDC-Anbieter, mit PKCE und geprüftem ID-Token.",
|
|
"Bedienungsanleitung mit Bildern, Funktionsübersicht und Roadmap.",
|
|
"Anmeldung und Sitzungen nach OWASP durchgesehen und gehärtet: stärkere Passwort-Parameter, Längengrenze, Herkunftsprüfung, Schutzheader, absolute Sitzungsdauer.",
|
|
"Auf der Startseite steht „nur dynamisch“ statt eines nichtssagenden Abzeichens an jeder Kachel.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.1.0",
|
|
date: "2026-08-14",
|
|
summary: "Alle fünfzehn QR-Typen, Anmeldung, Gruppen und mehrere Domains.",
|
|
changes: [
|
|
"Vierzehn weitere QR-Typen — von vCard und WLAN bis PDF, Bild und Feedback.",
|
|
"Landingpages als eigene Gattung für Typen ohne fremdes Ziel.",
|
|
"Datei-Upload mit Inhaltsprüfung, Größengrenze und Aufräumen.",
|
|
"Anmeldung, Benutzer, Gruppen und die Rollen Administrator, Bearbeiter und Betrachter.",
|
|
"Mehrere Domains für Kurz-URLs, den Gruppen zugeteilt.",
|
|
"„Meine Codes“ als Liste mit Suche, Sortierung und Gruppenfilter.",
|
|
"Einzelne QR-Typen lassen sich in der Verwaltung ausblenden.",
|
|
],
|
|
},
|
|
{
|
|
version: "1.0.0",
|
|
date: "2026-08-13",
|
|
summary: "Erste lauffähige Fassung.",
|
|
changes: [
|
|
"Next.js-Anwendung und PostgreSQL als Docker-Compose-Stack, Migrationen beim Start.",
|
|
"QR-Typ Website, statisch und dynamisch, mit Kurz-URL, Weiterleitung und Scan-Zähler.",
|
|
"Gestaltung mit Farben, Kontrastwarnung, Größe, Fehlerkorrektur und Rand.",
|
|
"Download als PNG und SVG, serverseitig gerendert.",
|
|
"Update-Skript für Linux, macOS und Windows.",
|
|
],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Die laufende Version.
|
|
*
|
|
* Aus der `package.json`, damit es genau eine Stelle gibt, an der sie steht.
|
|
* Der Wert wird beim Bauen eingesetzt — im Container liegt kein Git, aus dem
|
|
* sich sonst etwas ableiten ließe.
|
|
*/
|
|
export const APP_VERSION: string = pkg.version;
|
|
|
|
/** Der Eintrag zur laufenden Version, falls er im Verlauf steht. */
|
|
export function currentEntry(): ChangelogEntry | undefined {
|
|
return CHANGELOG.find((eintrag) => eintrag.version === APP_VERSION);
|
|
}
|
|
|
|
/** Datum als „21.08.2026“ — ohne Abhängigkeit von der Zeitzone des Servers. */
|
|
export function formatChangelogDate(iso: string): string {
|
|
const [jahr, monat, tag] = iso.split("-");
|
|
return `${tag}.${monat}.${jahr}`;
|
|
}
|