import './PiePanelWrapper.styles.scss'; import { Color } from '@signozhq/design-tokens'; import { Group } from '@visx/group'; import { Pie } from '@visx/shape'; import { useTooltip, useTooltipInPortal } from '@visx/tooltip'; import { themeColors } from 'constants/theme'; import { useIsDarkMode } from 'hooks/useDarkMode'; import { generateColor } from 'lib/uPlotLib/utils/generateColor'; import { useRef, useState } from 'react'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { PanelWrapperProps, TooltipData } from './panelWrapper.types'; import { getLabel, lightenColor, tooltipStyles } from './utils'; // refernce: https://www.youtube.com/watch?v=bL3P9CqQkKw function PiePanelWrapper({ queryResponse, widget, }: PanelWrapperProps): JSX.Element { const [active, setActive] = useState<{ label: string; value: string; color: string; } | null>(null); const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip, } = useTooltip(); const { containerRef, TooltipInPortal } = useTooltipInPortal({ scroll: true, detectBounds: true, }); const panelData = queryResponse.data?.payload?.data?.newResult?.data?.result || []; const isDarkMode = useIsDarkMode(); const pieChartData: { label: string; value: string; color: string; }[] = [].concat( ...(panelData .map((d) => d.series?.map((s) => ({ label: d.series?.length === 1 ? getLabel(Object.values(s.labels)[0], widget.query, d.queryName) : getLabel(Object.values(s.labels)[0], {} as Query, d.queryName, true), value: s.values[0].value, color: generateColor( d.series?.length === 1 ? getLabel(Object.values(s.labels)[0], widget.query, d.queryName) : getLabel(Object.values(s.labels)[0], {} as Query, d.queryName, true), isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor, ), })), ) .filter((d) => d !== undefined) as never[]), ); let size = 0; let width = 0; let height = 0; const chartRef = useRef(null); if (chartRef.current) { const { offsetWidth, offsetHeight } = chartRef.current; size = Math.min(offsetWidth, offsetHeight); width = offsetWidth; height = offsetHeight; } const half = size / 2; const getFillColor = (color: string): string => { if (active === null) { return color; } const lightenedColor = lightenColor(color, 0.4); // Adjust the opacity value (0.7 in this case) return active.color === color ? color : lightenedColor; }; return ( <> {!pieChartData.length &&
No data
} {pieChartData.length > 0 && ( <>
parseFloat(data.value)} outerRadius={({ data }): number => { if (!active) return half - 3; return data.label === active.label ? half : half - 3; }} padAngle={0.02} cornerRadius={3} width={size} height={size} > { // eslint-disable-next-line @typescript-eslint/explicit-function-return-type (pie) => pie.arcs.map((arc, index) => { const { label } = arc.data; const [centroidX, centroidY] = pie.path.centroid(arc); const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.6; const arcPath = pie.path(arc); const arcFill = arc.data.color; return ( { showTooltip({ tooltipData: { label, value: arc.data.value, color: arc.data.color, key: label, }, tooltipTop: centroidY + height / 2, tooltipLeft: centroidX + width / 2, }); setActive(arc.data); }} onMouseLeave={(): void => { hideTooltip(); setActive(null); }} > {hasSpaceForLabel && ( {arc.data.label} )} ); }) } {tooltipOpen && tooltipData && (
{tooltipData.key}
{tooltipData.value}
)}
{pieChartData.length > 0 && pieChartData.map((data) => (
{ setActive(data); }} onMouseLeave={(): void => { setActive(null); }} >
{data.label}
))}
)} ); } export default PiePanelWrapper;