13 KiB
Austauschformat für Vorlagen
Eine Vorlage lässt sich als JSON-Datei exportieren und wieder einspielen. Diese Datei beschreibt das Format — für jemanden, der eine Vorlage von Hand schreiben oder ein Skript dafür bauen will.
Die Prüfung liegt in src/lib/vorlagen-format.ts, Export und
Import in src/server/services/vorlagen-austausch.ts.
Beide benutzen dasselbe Schema: was hier steht, gilt für den Export, den Import und den Editor.
Wozu das Format da ist
Eine exportierte Vorlage soll sich in eine andere Laufzettel-Installation einspielen lassen. Deshalb enthält das Dokument nur das, was eine Vorlage inhaltlich ausmacht: Kopfdaten, Variablen, Abschnitte, Schritte. Alles, was nur in der Quellinstallation eine Bedeutung hat, bleibt draußen.
Nicht im Dokument enthalten:
- Kennungen (
id,versionId,abschnittId) — sie zeigen in der Zielinstallation ins Leere - Zeitstempel (
erstelltAm,geaendertAm,veroeffentlichtAm) und der veröffentlichende Benutzer - Kundenbezug (
kundeId) — eine eingespielte Vorlage gilt zunächst für alle Kunden; wer sie einem Kunden zuordnen will, tut das danach in der Oberfläche position— die Reihenfolge steckt in der Reihenfolge der Listen. Zwei Wahrheiten über dieselbe Reihenfolge laufen früher oder später auseinander.- Läufe, Schrittergebnisse, Kommentare und das Protokoll — das ist Betriebsgeschehen, keine Vorlage
- der Status der Version und das Archiv-Kennzeichen
Beispiel
Das folgende Dokument ist vollständig: zwei Abschnitte, zwei Variablen und ein BEFEHL-Schritt mit
Platzhaltern. JSON kennt keine Kommentare — die Zeilen mit // müssen vor dem Import raus.
{
// Fassung des Austauschformats, derzeit immer 1.
"format": 1,
"name": "Onboarding Notebook",
"beschreibung": "Neue Person, neues Gerät.",
"kategorie": "Onboarding",
"schlagworte": ["notebook", "eintritt"],
// Nur zur Information: welche Version der Quelle exportiert wurde. Beim
// Import wird der Wert gelesen und nicht übernommen.
"version": 3,
"struktur": {
// Wird beim Start eines Laufs abgefragt und füllt die Platzhalter.
"variablen": [
{ "schluessel": "vorname", "beschriftung": "Vorname", "typ": "TEXT", "pflicht": true },
{
"schluessel": "abteilung",
"beschriftung": "Abteilung",
"typ": "AUSWAHL",
"optionen": ["IT", "Vertrieb", "Buchhaltung"]
}
],
// Die Reihenfolge dieser Liste ist die Reihenfolge in der Ansicht.
"abschnitte": [
{
"titel": "Vorbereitung",
"schritte": [
{ "titel": "Gerät auspacken", "pflicht": true },
{
"titel": "Seriennummer erfassen",
"hilfetext": "Aufkleber auf der Unterseite. **Nicht** die Artikelnummer.",
"typ": "TEXT",
"pflicht": true,
"konfig": { "mehrzeilig": false },
"dokuUrl": "https://intern.example/seriennummern"
},
{
"titel": "Arbeitsspeicher prüfen",
"typ": "ZAHL",
"konfig": { "min": 8, "max": 64, "einheit": "GB" }
}
]
},
{
"titel": "Konto",
"schritte": [
{
"titel": "Benutzerkonto anlegen",
"typ": "BEFEHL",
"pflicht": true,
// Die Platzhalter werden erst beim Abarbeiten ersetzt; hier stehen
// sie wörtlich.
"konfig": {
"shell": "powershell",
"befehl": "New-ADUser -Name \"{{vorname}}\" -Department \"{{abteilung}}\""
}
},
{ "titel": "Eintrittsdatum hinterlegen", "typ": "DATUM" }
]
}
]
}
}
Felder
Kopf
| Feld | Pflicht | Bedeutung |
|---|---|---|
format |
Pflicht | Fassung des Austauschformats. Derzeit 1; ein anderer Wert wird abgewiesen. |
name |
Pflicht | Name der Vorlage, nicht leer. Namen sind nicht eindeutig. |
beschreibung |
optional | Ein bis zwei Sätze, was die Vorlage abdeckt. |
kategorie |
optional | Freitext, gruppiert die Vorlagenliste (etwa Onboarding). |
schlagworte |
optional | Liste nicht leerer Texte; Standard []. |
version |
optional | Versionsnummer der exportierten Quelle. Reine Information, siehe unten. |
struktur |
Pflicht | Objekt mit variablen und abschnitte. |
struktur
| Feld | Pflicht | Bedeutung |
|---|---|---|
variablen |
optional | Liste von Variablen in Abfragereihenfolge; Standard []. |
abschnitte |
optional | Liste von Abschnitten in Anzeigereihenfolge; Standard []. |
Variable
| Feld | Pflicht | Bedeutung |
|---|---|---|
schluessel |
Pflicht | Der Name im Platzhalter {{schluessel}}. Regeln siehe unten. |
beschriftung |
Pflicht | Was im Startformular über dem Feld steht, nicht leer. |
typ |
optional | TEXT, ZAHL, AUSWAHL oder DATUM; Standard TEXT. |
optionen |
optional | Nur bei AUSWAHL: die Auswahlwerte in Anzeigereihenfolge; Standard []. |
pflicht |
optional | true verlangt eine Eingabe beim Start; Standard false. |
Ein Schlüssel darf in einem Dokument nur einmal vorkommen. Ein zweiter Eintrag mit demselben Schlüssel ist ein Fehler und kein stilles Überschreiben — sonst verschwände eine Variable, ohne dass es jemand merkt.
Abschnitt
| Feld | Pflicht | Bedeutung |
|---|---|---|
titel |
Pflicht | Überschrift, nicht leer und ohne Nummer — siehe unten. |
schritte |
optional | Liste von Schritten in Abarbeitungsreihenfolge; Standard []. |
Abschnitte werden überall mit einer zweistelligen Nummer angezeigt (01 · Vorbereitung). Diese
Nummer wird aus der Position abgeleitet und nie gespeichert. Stünde sie im Titel, wäre sie beim
ersten Umsortieren falsch — und niemand ginge hinterher durch und zöge sie nach. Trägt ein Titel
dennoch eine vorangestellte Nummer mit · als Trenner (ältere Dateien taten das), wird sie beim
Öffnen im Editor entfernt, damit nicht 01 · 01 · Vorbereitung dasteht; mit dem nächsten Speichern
gilt der bereinigte Titel. Andere Trenner bleiben unangetastet: „2. Etage prüfen“ ist ein Titel und
keine Nummerierung.
Schritt
| Feld | Pflicht | Bedeutung |
|---|---|---|
titel |
Pflicht | Was zu tun ist, nicht leer. Darf Platzhalter enthalten. |
hilfetext |
optional | Markdown, in der Abarbeitungsansicht ausklappbar. Kein rohes HTML. |
typ |
optional | Einer der Schritt-Typen unten; Standard HAKEN. |
pflicht |
optional | Pflichtschritte müssen vor dem Abschluss erledigt oder ausdrücklich als nicht zutreffend markiert sein; Standard false. |
konfig |
optional | Typabhängige Einzelheiten; Standard {}. Siehe unten. |
dokuUrl |
optional | Link auf eine Anleitung. Muss eine gültige Adresse sein. |
Schritt-Typen und ihre konfig
| Typ | Was der Techniker tut | Schlüssel in konfig |
|---|---|---|
HAKEN |
abhaken | keine |
TEXT |
Text eintragen | mehrzeilig (true/false) |
ZAHL |
Zahl eintragen | min, max (Zahlen), einheit (Text, höchstens 40 Zeichen) |
AUSWAHL |
aus einer Liste wählen | optionen (Liste nicht leerer Texte, in Anzeigereihenfolge) |
DATUM |
Datum wählen | keine |
BEFEHL |
Befehl kopieren und ausführen | shell (powershell, bash oder cmd), befehl (Text) |
min und max sind Hinweise: ein Wert außerhalb wird markiert, nicht blockiert.
konfig wird nachsichtig geprüft. Unbekannte Schlüssel bleiben erhalten — eine Datei aus einer
späteren Fassung verliert hier nichts, auch wenn diese Fassung die Schlüssel nicht kennt. Was die
Anwendung kennt, wird geprüft: shell etwa akzeptiert nur die drei genannten Werte.
Ein Schlüssel, der nicht zum Typ passt, ist kein Fehler; er wird schlicht nicht beachtet. Wer den
Typ eines Schritts ändert, räumt die konfig also besser selbst auf.
Platzhalter und Variablenschlüssel
Ein Variablenschlüssel muss der Form ^[a-z][a-z0-9_]{0,39}$ entsprechen: Beginn mit einem
Kleinbuchstaben, danach Kleinbuchstaben, Ziffern und Unterstrich, höchstens 40 Zeichen.
vorname, ad_gruppe und raum2 sind in Ordnung; Vorname, mit-strich, 2te_wahl und ein
leerer Schlüssel nicht.
Die Strenge hat einen Grund: der Schlüssel steht als {{schluessel}} in Titeln, Hilfetexten und
Befehlen. Ein Platzhalter wird genau mit diesem Muster wiedererkannt. Wäre Vor-Name erlaubt,
müsste der Suchausdruck Groß- und Kleinschreibung, Striche und Leerzeichen auseinanderhalten — und
{{Vor-Name}} in einem PowerShell-Befehl wäre nicht mehr von dessen eigener Syntax zu trennen.
Deshalb: ein Zeichensatz, eine Regel, keine Ausnahmen.
Geschweifte Klammern dürfen Leerzeichen enthalten ({{ vorname }} wird erkannt). Neben den
Variablen der Vorlage gibt es eingebaute Platzhalter — {{generiertes_passwort}} etwa —, die nicht
im Austauschdokument stehen und auch nirgends gespeichert werden.
Was beim Import passiert
- Das Dokument wird gegen das Schema geprüft. Schlägt das fehl, wird nichts geschrieben.
- Es entsteht eine neue Vorlage — der Import schreibt nie in eine bestehende hinein.
- Die Vorlage bekommt genau eine Version:
version = 1, StatusENTWURF. Eine eingespielte Vorlage wird bewusst nicht sofort veröffentlicht; der Redakteur sieht sie sich erst an, ergänzt vielleicht etwas und veröffentlicht dann. Erst danach lässt sich ein Lauf daran starten. positionwird aus der Reihenfolge der Listen abgeleitet (0, 1, 2 …).- Das mitgeschickte
version-Feld wird nicht übernommen. Eine Vorlage, die in der Quelle auf Version 7 stand, fängt hier wieder bei 1 an — die Versionsgeschichte der Quelle wandert nicht mit. - Der Vorlagenname kommt so an, wie er im Dokument steht. Gibt es ihn schon, ist das kein Fehler und es wird nichts angehängt: Vorlagennamen sind nicht eindeutig.
- Alles geschieht in einer Transaktion. Ein Fehler auf halbem Weg hinterlässt keine halbe Vorlage.
- Ein Protokolleintrag mit der Aktion
Vorlage importierthält fest, wer die Vorlage eingespielt hat.
Wird das Dokument abgewiesen, nennt die Meldung die erste Beanstandung samt Pfad, etwa:
struktur.abschnitte.1.schritte.2.titel: Ein Schritt braucht einen Titel.
Wie sich das Format ändern darf
Das Feld format ist die Fassung des Formats, nicht die der Anwendung. Es gilt:
- Neue optionale Felder und neue
konfig-Schlüssel erhöhenformatnicht. Alte Dateien bleiben gültig, und weilkonfignachsichtig geprüft wird, überleben neue Schlüssel auch einen Rundlauf durch eine ältere Fassung. - Neue Schritt- und Variablentypen erhöhen
formatebenfalls nicht. Eine Fassung, die den Typ nicht kennt, weist die Datei allerdings ab, weil der Typ eine geprüfte Aufzählung ist. - Erst eine Änderung, die alte Dateien unbrauchbar macht — ein umbenanntes Pflichtfeld, eine
andere Verschachtelung —, erhöht
formatauf2. - Ein unbekannter
format-Wert wird mit einer klaren Meldung abgewiesen, nie geraten. Ein Import, der die Hälfte versteht und die andere Hälfte still verwirft, wäre schlimmer als ein Fehlschlag.
Die Zahl steht als FORMAT_VERSION in src/lib/vorlagen-format.ts an genau einer Stelle.