feat(vorlagen): Vorlagen (Presets) für Assistent, API und CLI
Gespeicherte Kombinationen aus Distribution, Ressourcen und Profilen. Im Assistenten mit einem Klick vorbelegt oder dort gespeichert; die API nimmt „vorlage“ entgegen (Grundlage für --preset der CLI). Eine Vorlage liegt unter der Anfrage – was die Anfrage selbst sagt, gewinnt. Beim ersten Start wird das Beispiel „Docker-Host klein“ aus der Vorgabe angelegt, einmalig. Closes #012 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { Karte } from "@/components/karte";
|
||||
import { Status } from "@/components/status";
|
||||
import { darf } from "@/server/auth/rechte";
|
||||
import { seiteSchuetzen } from "@/server/auth/zugang";
|
||||
import { vorlagenListe } from "@/server/services/vorlagen";
|
||||
import { VorlageLoeschen } from "./vorlage-loeschen";
|
||||
|
||||
export const metadata: Metadata = { title: "Vorlagen" };
|
||||
|
||||
export default async function Vorlagen() {
|
||||
const benutzer = await seiteSchuetzen("lesen", "/vorlagen");
|
||||
const liste = await vorlagenListe();
|
||||
const pflegen = darf(benutzer.rolle, "vorlagenPflegen");
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
<header>
|
||||
<h1 className="text-2xl font-semibold tracking-tight sm:text-3xl">Vorlagen</h1>
|
||||
<p className="text-muted text-sm">
|
||||
Gespeicherte Kombinationen für den Assistenten und die CLI (
|
||||
<span className="font-mono">--preset</span>). Anlegen: im Assistenten auf der Zusammenfassung „Als
|
||||
Vorlage speichern“.
|
||||
</p>
|
||||
</header>
|
||||
{liste.length === 0 ? (
|
||||
<Karte>
|
||||
<Status art="offen">Noch keine Vorlage.</Status>
|
||||
</Karte>
|
||||
) : (
|
||||
<ul className="grid gap-4 md:grid-cols-2">
|
||||
{liste.map((v) => {
|
||||
const p = v.parameter;
|
||||
const eckdaten = [
|
||||
p.typ?.toUpperCase(),
|
||||
p.distribution,
|
||||
p.cores ? `${p.cores} CPU` : null,
|
||||
p.speicherMb ? `${p.speicherMb / 1024} GB RAM` : null,
|
||||
p.diskGb ? `${p.diskGb} GB Disk` : null,
|
||||
].filter(Boolean);
|
||||
return (
|
||||
<li key={v.name} className="bg-panel border-linie rounded-karte flex flex-col gap-3 border p-5">
|
||||
<div>
|
||||
<p className="font-semibold">{v.titel}</p>
|
||||
<p className="text-muted font-mono text-xs">--preset {v.name}</p>
|
||||
</div>
|
||||
{v.beschreibung ? <p className="text-muted text-sm">{v.beschreibung}</p> : null}
|
||||
<p className="font-mono text-xs">{eckdaten.join(" · ")}</p>
|
||||
{p.profile && p.profile.length > 0 ? (
|
||||
<p className="text-muted text-xs">Profile: {p.profile.join(", ")}</p>
|
||||
) : null}
|
||||
<div className="mt-auto flex flex-wrap items-center gap-3 pt-2">
|
||||
<Link
|
||||
href={`/ausrollen?vorlage=${v.name}`}
|
||||
className="bg-akzent text-akzent-text inline-flex h-11 items-center rounded-lg px-4 text-sm font-semibold sm:h-10"
|
||||
>
|
||||
Ausrollen mit dieser Vorlage
|
||||
</Link>
|
||||
{pflegen ? <VorlageLoeschen name={v.name} /> : null}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user