Files
geointel/src/client/components/ServerWidgetAdvancedConfigurator.tsx
T
Jens d5ea270329
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s
Update GeoIntel project files
2026-07-25 23:43:08 +02:00

307 lines
9.5 KiB
TypeScript

import {
ArrowDown,
ArrowUp,
BarChart3,
ServerCog,
SlidersHorizontal,
} from "lucide-react";
import type {
Preferences,
PreferencesPatch,
WidgetChartType,
} from "../../shared/contracts";
interface Props {
preferences: Preferences;
onChange: (patch: PreferencesPatch, message: string) => void;
}
const statMetrics = [
{
label: "CPU cores",
display: "CPU-kernen",
description: "Logische CPU-capaciteit die de Docker-host meldt.",
},
{
label: "Memory capacity",
display: "Geheugencapaciteit",
description: "Totaal geheugen uit de alleen-lezen inventarisservice.",
},
{
label: "Stopped containers",
display: "Gestopte containers",
description: "Aanwezige containers die momenteel niet actief zijn.",
},
{
label: "Array state",
display: "Arraystatus",
description: "Overzicht van de Unraid-array- en pariteitsstatus.",
},
{
label: "Storage used",
display: "Opslag gebruikt",
description: "Gebruikte capaciteit van de gemelde array en pools.",
},
{
label: "Hottest temperature",
display: "Hoogste temperatuur",
description: "Hoogste beschikbare temperatuur van host- of opslagsensoren.",
},
{
label: "UPS battery",
display: "UPS-batterij",
description:
"UPS-status en resterende batterij indien ingesteld in Unraid.",
},
];
const chartMetrics: Array<[string, string]> = [
["Running containers", "Actieve containers"],
["Stopped containers", "Gestopte containers"],
["Images", "Images"],
["Memory capacity", "Geheugencapaciteit"],
["Storage used", "Opslag gebruikt"],
["Hottest temperature", "Hoogste temperatuur"],
["Parity errors", "Pariteitsfouten"],
["UPS battery", "UPS-batterij"],
];
export function ServerWidgetAdvancedConfigurator({
preferences,
onChange,
}: Props) {
const labels = statMetrics.map((metric) => metric.label);
const ordered = [
...preferences.serverWidgetMetricOrder.filter((label) =>
labels.includes(label),
),
...labels.filter(
(label) => !preferences.serverWidgetMetricOrder.includes(label),
),
].filter((label) => !preferences.serverWidgetHiddenMetrics.includes(label));
const move = (index: number, direction: -1 | 1) => {
const target = index + direction;
if (!ordered[target]) return;
const next = [...ordered];
[next[index], next[target]] = [next[target]!, next[index]!];
onChange(
{ serverWidgetMetricOrder: next },
"Volgorde van Unraid-metingen bijgewerkt",
);
};
return (
<details className="widget-advanced-config server-advanced-config">
<summary>
<ServerCog size={14} /> Volledige Unraid-paneelconfiguratie
</summary>
<section className="widget-config-section" aria-label="Unraid-grafiek">
<header>
<BarChart3 size={14} />
<span>
<strong>Servertrendgrafiek</strong>
<small>
Toon geschiedenis van Docker-inventaris, opslag, temperatuur,
pariteit of UPS.
</small>
</span>
</header>
<div className="widget-advanced-grid">
<label>
<span>Reeks</span>
<select
name="serverWidgetChartMetric"
value={preferences.serverWidgetChartMetric}
onChange={(event) =>
onChange(
{ serverWidgetChartMetric: event.target.value },
"Unraid-grafiekreeks bijgewerkt",
)
}
>
{chartMetrics.map(([metric, display]) => (
<option key={metric} value={metric}>
{display}
</option>
))}
</select>
</label>
<label>
<span>Grafiekstijl</span>
<select
name="serverWidgetChartType"
value={preferences.serverWidgetChartType}
onChange={(event) =>
onChange(
{
serverWidgetChartType: event.target
.value as WidgetChartType,
},
"Unraid-grafiekstijl bijgewerkt",
)
}
>
<option value="line">Lijn</option>
<option value="area">Vlak</option>
<option value="bar">Balken</option>
</select>
</label>
<label>
<span>Geschiedenisvenster</span>
<select
name="serverWidgetChartSamples"
value={preferences.serverWidgetChartSamples}
onChange={(event) =>
onChange(
{ serverWidgetChartSamples: Number(event.target.value) },
"Unraid-grafiekvenster bijgewerkt",
)
}
>
{[10, 20, 30, 45, 60].map((samples) => (
<option key={samples} value={samples}>
Laatste {samples} metingen
</option>
))}
</select>
</label>
<label>
<span>Maximum aantal statistieken</span>
<select
name="serverWidgetStatLimit"
value={preferences.serverWidgetStatLimit}
onChange={(event) =>
onChange(
{ serverWidgetStatLimit: Number(event.target.value) },
"Limiet voor Unraid-statistieken bijgewerkt",
)
}
>
{[3, 4, 5, 6, 7, 8].map((limit) => (
<option key={limit} value={limit}>
{limit} statistieken
</option>
))}
</select>
</label>
<button
type="button"
className={
preferences.serverWidgetShowChart
? "sparkline-toggle active"
: "sparkline-toggle"
}
aria-pressed={preferences.serverWidgetShowChart}
onClick={() =>
onChange(
{
serverWidgetShowChart: !preferences.serverWidgetShowChart,
},
"Zichtbaarheid van Unraid-grafiek bijgewerkt",
)
}
>
<BarChart3 size={15} />
<span>
<strong>Grafiek tonen</strong>
<small>Geschiedenis blijft alleen in het geheugen</small>
</span>
</button>
<button
type="button"
className={
preferences.serverWidgetShowLegend
? "sparkline-toggle active"
: "sparkline-toggle"
}
aria-pressed={preferences.serverWidgetShowLegend}
onClick={() =>
onChange(
{
serverWidgetShowLegend: !preferences.serverWidgetShowLegend,
},
"Legenda van Unraid-grafiek bijgewerkt",
)
}
>
<SlidersHorizontal size={15} />
<span>
<strong>Legenda tonen</strong>
<small>Reeks, laatste waarde en metingen</small>
</span>
</button>
</div>
</section>
<div className="metric-visibility-list" aria-label="Unraid-statistieken">
<strong>Serverstatistieken</strong>
<small>
Kies welke eigen Unraid- en Docker-hostsignalen de kaart mag tonen.
</small>
<div>
{statMetrics.map((metric) => {
const visible = !preferences.serverWidgetHiddenMetrics.includes(
metric.label,
);
return (
<button
type="button"
key={metric.label}
className={visible ? "active" : ""}
aria-pressed={visible}
onClick={() =>
onChange(
{
serverWidgetHiddenMetrics: visible
? [
...preferences.serverWidgetHiddenMetrics,
metric.label,
]
: preferences.serverWidgetHiddenMetrics.filter(
(label) => label !== metric.label,
),
},
`${metric.display} ${visible ? "verborgen" : "ingeschakeld"}`,
)
}
>
<span>{metric.display}</span>
<small>{metric.description}</small>
</button>
);
})}
</div>
</div>
{ordered.length > 1 && (
<div
className="metric-order-list"
aria-label="Volgorde van Unraid-metingen"
>
{ordered.map((metric, index) => (
<span key={metric}>
<strong>
{statMetrics.find((item) => item.label === metric)?.display ??
metric}
</strong>
<button
type="button"
disabled={index === 0}
onClick={() => move(index, -1)}
aria-label={`${metric} eerder plaatsen`}
>
<ArrowUp size={12} />
</button>
<button
type="button"
disabled={index === ordered.length - 1}
onClick={() => move(index, 1)}
aria-label={`${metric} later plaatsen`}
>
<ArrowDown size={12} />
</button>
</span>
))}
</div>
)}
</details>
);
}