/** * Kennzahlen und Diagramme. * * Alle zwoelf Diagramme aus dem Plan erscheinen. Das eine ohne Datengrundlage * — die Ressourcenlast der Agenten — steht mit dabei und sagt, was fehlt. * Dieselbe Regel wie in der Uebersicht: Ein weggelassenes Diagramm sieht aus wie * ein vergessenes, ein leeres wie eine Anlage ohne Betrieb. */ import { useCallback, useState } from 'react'; import { useApiResource } from '../../api/useApiResource'; import { ErrorState, LoadingState } from '../../components/PageState'; import { LineChart } from './LineChart'; import { fetchChart, fetchChartCatalog } from './metricsApi'; import type { Chart, ChartCatalog, ChartDefinition } from './metricsApi'; /** Auswaehlbare Zeitraeume mit ihrer Beschriftung. */ const RANGE_OPTIONS: readonly { readonly value: string; readonly label: string }[] = [ { value: '1h', label: 'Letzte Stunde' }, { value: '24h', label: 'Letzte 24 Stunden' }, { value: '7d', label: 'Letzte 7 Tage' }, { value: '30d', label: 'Letzte 30 Tage' }, { value: '90d', label: 'Letzte 90 Tage' }, { value: '1y', label: 'Letztes Jahr' }, ]; /** Zeigt die Kennzahlen. */ export function MetricsPage(): React.JSX.Element { const [selectedRange, setSelectedRange] = useState('7d'); const loadCatalog = useCallback((abortSignal: AbortSignal) => fetchChartCatalog(abortSignal), []); const { loadState, data, loadError, reload } = useApiResource(loadCatalog); return (

Kennzahlen

{data !== null && ( {data.available_count} von {data.charts.length} Diagrammen haben eine Datengrundlage )}
{loadState === 'loading' && } {loadState === 'failed' && loadError !== null && ( )} {loadState === 'loaded' && data !== null && (
{data.charts.map((chartDefinition) => ( ))}
)}
); } /** Eigenschaften einer Diagrammkachel. */ interface ChartCardProperties { /** Das darzustellende Diagramm. */ readonly definition: ChartDefinition; /** Der gewaehlte Zeitraum. */ readonly timeRange: string; } /** Zeigt ein einzelnes Diagramm. */ function ChartCard({ definition, timeRange }: ChartCardProperties): React.JSX.Element { const loadChart = useCallback( (abortSignal: AbortSignal) => fetchChart(definition.metric, timeRange, abortSignal), [definition.metric, timeRange], ); // Ein Diagramm ohne Datengrundlage wird gar nicht erst abgerufen: Der Server // antwortete mit 501, und ein Fehler in der Oberflaeche saehe aus wie eine // Stoerung. Es ist keine — die Funktion gibt es nur noch nicht. const { loadState, data, loadError, reload } = useApiResource( loadChart, definition.available ? `${definition.metric}|${timeRange}` : 'unavailable', ); if (!definition.available) { return (

{definition.title}

noch nicht verfuegbar

{definition.unavailable_reason}

); } return (

{definition.title}

{definition.description}

{loadState === 'loading' && } {loadState === 'failed' && loadError !== null && ( )} {loadState === 'loaded' && data !== null && ( <> {/* Der Hinweis ordnet ein, was die Kurve wert ist: Zwei Punkte sehen aus wie ein Trend und sind keiner. */} {data.note !== undefined && data.note !== '' && (

{data.note}

)} )}
); }