From 711e5afa6025a4744f825e45279110a278799824 Mon Sep 17 00:00:00 2001 From: Riccardo Forina Date: Thu, 21 Dec 2023 16:24:47 +0100 Subject: [PATCH] Add distribution chart --- .../[kafkaId]/nodes/DistributionChart.tsx | 142 ++++++++++++++++++ .../[locale]/kafka/[kafkaId]/nodes/page.tsx | 16 +- 2 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 ui/app/[locale]/kafka/[kafkaId]/nodes/DistributionChart.tsx diff --git a/ui/app/[locale]/kafka/[kafkaId]/nodes/DistributionChart.tsx b/ui/app/[locale]/kafka/[kafkaId]/nodes/DistributionChart.tsx new file mode 100644 index 000000000..a9c79d30c --- /dev/null +++ b/ui/app/[locale]/kafka/[kafkaId]/nodes/DistributionChart.tsx @@ -0,0 +1,142 @@ +"use client"; + +import { useChartWidth } from "@/app/[locale]/kafka/[kafkaId]/overview/useChartWidth"; +import { + Chart, + ChartAxis, + ChartBar, + ChartLegend, + ChartStack, + ChartVoronoiContainer, +} from "@/libs/patternfly/react-charts"; +import { + Card, + CardBody, + CardHeader, + CardTitle, + ToggleGroup, + ToggleGroupItem, + Tooltip, +} from "@/libs/patternfly/react-core"; +import { HelpIcon } from "@/libs/patternfly/react-icons"; +import { useState } from "react"; + +export function DistributionChart({ + data, +}: { + data: Record; +}) { + const [containerRef, width] = useChartWidth(); + const [includeLeaders, setIncludeLeaders] = useState(true); + const [includeFollowers, setIncludeFollowers] = useState(true); + const label = + includeFollowers || includeLeaders + ? includeLeaders && includeFollowers + ? "total partitions" + : includeLeaders + ? "leaders" + : "followers" + : "total partitions"; + return ( + + + + Partitions distribution (% of total){" "} + + + + + + + + v.leaders + acc, + 0, + )})`} + buttonId="toggle-group-compact-1" + isSelected={includeLeaders} + onChange={() => setIncludeLeaders((v) => !v)} + /> + v.followers + acc, + 0, + )})`} + buttonId="toggle-group-compact-2" + isSelected={includeFollowers} + onChange={() => setIncludeFollowers((v) => !v)} + /> + +
+ `${datum.name} ${label}: ${datum.y}`} + constrainToVisibleArea + /> + } + legendOrientation="horizontal" + legendPosition="bottom" + legendComponent={ + [ + { + name: `Broker ${node} ${label}`, + }, + ])} + itemsPerRow={width > 600 ? 3 : 1} + /> + } + height={100} + padding={{ + bottom: 70, + left: 0, + right: 0, // Adjusted to accommodate legend + top: 30, + }} + width={width} + > + + + {Object.entries(data).map(([node, data], idx) => ( + + ))} + + +
+
+
+ ); +} diff --git a/ui/app/[locale]/kafka/[kafkaId]/nodes/page.tsx b/ui/app/[locale]/kafka/[kafkaId]/nodes/page.tsx index e18e7a20f..c44baa9e8 100644 --- a/ui/app/[locale]/kafka/[kafkaId]/nodes/page.tsx +++ b/ui/app/[locale]/kafka/[kafkaId]/nodes/page.tsx @@ -1,5 +1,6 @@ import { getKafkaClusterKpis } from "@/api/kafka/actions"; import { KafkaParams } from "@/app/[locale]/kafka/[kafkaId]/kafka.params"; +import { DistributionChart } from "@/app/[locale]/kafka/[kafkaId]/nodes/DistributionChart"; import { Node, NodesTable, @@ -37,9 +38,18 @@ export default async function NodesPage({ params }: { params: KafkaParams }) { }; }); + const data = Object.fromEntries( + nodes.map((n) => { + return [n.id, { followers: n.followers, leaders: n.leaders }]; + }), + ); + return ( - - - + <> + + + + + ); }