feat(hosts): Host-Tabelle mit Filtern, CSV-Export und Detailansicht (#007)
Suche ueber Hostname, Key, Server-ID, IP und Rechnungsnummer, fuenf Filter, Sortierung mit nulls-last, Seitenblaettern und CSV-Export. Detailansicht mit sechs Tabs, Notizen, Tags und Token-Widerruf. 59 Tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/** CSV für deutsche Tabellenkalkulationen: Semikolon, UTF-8 mit BOM, Komma als Dezimaltrennzeichen. */
|
||||
|
||||
const datumFormat = new Intl.DateTimeFormat("de-DE", {
|
||||
timeZone: "Europe/Berlin",
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
|
||||
export function csvZelle(wert: string | number | Date | null | undefined): string {
|
||||
if (wert === null || wert === undefined) return "";
|
||||
if (wert instanceof Date) return datumFormat.format(wert);
|
||||
if (typeof wert === "number") {
|
||||
// Ganze Zahlen (z. B. Sockets) ohne Nachkommastellen, Beträge mit zwei.
|
||||
return Number.isInteger(wert)
|
||||
? wert.toLocaleString("de-DE")
|
||||
: wert.toLocaleString("de-DE", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
}
|
||||
|
||||
const text = String(wert);
|
||||
return /[";\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
|
||||
}
|
||||
|
||||
export function csvDatei(
|
||||
kopfzeile: string[],
|
||||
zeilen: (string | number | Date | null | undefined)[][],
|
||||
): string {
|
||||
const inhalt = [kopfzeile, ...zeilen].map((zeile) => zeile.map(csvZelle).join(";")).join("\r\n");
|
||||
// Das BOM sorgt dafür, dass Excel die Umlaute richtig liest.
|
||||
return `\uFEFF${inhalt}\r\n`;
|
||||
}
|
||||
|
||||
export function csvAntwort(inhalt: string, dateiname: string): Response {
|
||||
return new Response(inhalt, {
|
||||
headers: {
|
||||
"Content-Type": "text/csv; charset=utf-8",
|
||||
"Content-Disposition": `attachment; filename="${dateiname}"`,
|
||||
"Cache-Control": "no-store",
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user