'use client' import { useState } from 'react' import dayjs from 'dayjs' import { DateTimeFormats } from './Charts.constants' import { numberFormatter } from './Charts.utils' import { MultiAttribute } from './ComposedChartHandler' import { Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { cn } from 'ui' interface CustomIconProps { color: string } const CustomIcon = ({ color }: CustomIconProps) => ( ) const MaxConnectionsIcon = () => ( ) interface TooltipProps { active?: boolean payload?: any[] label?: string | number attributes?: MultiAttribute[] isPercentage?: boolean valuePrecision?: number showMaxValue?: boolean showTotal?: boolean } export const formatBytes = (bytes: number, precision: number = 1) => { if (bytes === 0) return '0 Bytes' const k = 1024 const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return `${(bytes / Math.pow(k, i)).toFixed(precision)} ${sizes[i]}` } const isMaxAttribute = (attributes?: MultiAttribute[]) => attributes?.find((a) => a.isMaxValue) /** * Calculate the total aggregate of the chart values * by summing the values of the attributes * that are not in the `ignoreAttributes` array */ export const calculateTotalChartAggregate = ( payload: { dataKey: string; value: number }[], ignoreAttributes?: string[] ) => payload ?.filter((p) => !ignoreAttributes?.includes(p.dataKey)) .reduce((acc, curr) => acc + curr.value, 0) const CustomTooltip = ({ active, payload, attributes, isPercentage, valuePrecision, showTotal, }: TooltipProps) => { if (active && payload && payload.length) { const timestamp = payload[0].payload.timestamp const maxValueAttribute = isMaxAttribute(attributes) const maxValueData = maxValueAttribute && payload?.find((p: any) => p.dataKey === maxValueAttribute.attribute) const maxValue = maxValueData?.value const isRamChart = payload?.some((p: any) => p.dataKey.toLowerCase().includes('ram_')) const total = showTotal && calculateTotalChartAggregate( payload, maxValueAttribute?.attribute ? [maxValueAttribute.attribute] : [] ) const getIcon = (name: string, color: string) => { switch (name.toLowerCase().includes('max')) { case false: return default: return } } const LabelItem = ({ entry }: { entry: any }) => { const attribute = attributes?.find((a: MultiAttribute) => a.attribute === entry.name) const percentage = ((entry.value / maxValue) * 100).toFixed(1) const isMax = entry.dataKey === maxValueAttribute?.attribute return (
{getIcon(entry.name, entry.color)} {attribute?.label || entry.name} {isRamChart ? formatBytes(entry.value, valuePrecision) : numberFormatter(entry.value, valuePrecision)} {isPercentage ? '%' : ''} {/* Show percentage if max value is set */} {!!maxValueData && !isMax && ( ({percentage}%) )}
) } return (

{dayjs(timestamp).format(DateTimeFormats.FULL_SECONDS)}

{payload.reverse().map((entry: any, index: number) => ( ))} {active && showTotal && (
Total
{isRamChart ? formatBytes(total as number, 1) : numberFormatter(total as number)} {isPercentage ? '%' : ''} {maxValueAttribute && !isNaN((total as number) / maxValueData?.value) && isFinite((total as number) / maxValueData?.value) && ( ({(((total as number) / maxValueData?.value) * 100).toFixed(1)}%) )}
)}
) } return null } interface CustomLabelProps { payload?: any[] attributes?: MultiAttribute[] showMaxValue?: boolean onLabelHover?: (label: string | null) => void } const CustomLabel = ({ payload, attributes, showMaxValue, onLabelHover }: CustomLabelProps) => { const items = payload ?? [] const maxValueAttribute = isMaxAttribute(attributes) const [hoveredLabel, setHoveredLabel] = useState(null) const handleMouseEnter = (label: string) => { setHoveredLabel(label) onLabelHover?.(label) } const handleMouseLeave = () => { setHoveredLabel(null) onLabelHover?.(null) } const getIcon = (name: string, color: string) => { switch (name === maxValueAttribute?.attribute) { case true: return default: return } } const LabelItem = ({ entry }: { entry: any }) => { const attribute = attributes?.find((a) => a.attribute === entry.name) const isMax = entry.name === maxValueAttribute?.attribute const isHovered = hoveredLabel === entry.name const Label = () => (
{getIcon(entry.name, entry.color)} {attribute?.label || entry.name}
) if (!showMaxValue && isMax) return null return (
handleMouseEnter(entry.name)} onMouseOutCapture={handleMouseLeave} > {!!attribute?.tooltip ? ( {attribute.tooltip} ) : (
) } return (
{items?.map((entry, index) => )}
) } export { CustomTooltip, CustomLabel }