import './BillingUsageGraph.styles.scss'; import '../../../lib/uPlotLib/uPlotLib.styles.scss'; import { Color } from '@signozhq/design-tokens'; import { Card, Flex, Typography } from 'antd'; import { getComponentForPanelType } from 'constants/panelTypes'; import { PANEL_TYPES } from 'constants/queryBuilder'; import { PropsTypePropsMap } from 'container/GridPanelSwitch/types'; import { useIsDarkMode } from 'hooks/useDarkMode'; import { useResizeObserver } from 'hooks/useDimensions'; import tooltipPlugin from 'lib/uPlotLib/plugins/tooltipPlugin'; import getAxes from 'lib/uPlotLib/utils/getAxes'; import getRenderer from 'lib/uPlotLib/utils/getRenderer'; import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData'; import { getXAxisScale } from 'lib/uPlotLib/utils/getXAxisScale'; import { getYAxisScale } from 'lib/uPlotLib/utils/getYAxisScale'; import { FC, useMemo, useRef } from 'react'; import uPlot from 'uplot'; import { convertDataToMetricRangePayload, fillMissingValuesForQuantities, } from './utils'; interface BillingUsageGraphProps { data: any; billAmount: number; } const paths = ( u: any, seriesIdx: number, idx0: number, idx1: number, extendGap: boolean, buildClip: boolean, ): uPlot.Series.PathBuilder => { const s = u.series[seriesIdx]; const style = s.drawStyle; const interp = s.lineInterpolation; const renderer = getRenderer(style, interp); return renderer(u, seriesIdx, idx0, idx1, extendGap, buildClip); }; export function BillingUsageGraph(props: BillingUsageGraphProps): JSX.Element { const { data, billAmount } = props; const graphCompatibleData = useMemo( () => convertDataToMetricRangePayload(data), [data], ); const chartData = getUPlotChartData(graphCompatibleData); const graphRef = useRef(null); const isDarkMode = useIsDarkMode(); const containerDimensions = useResizeObserver(graphRef); const { billingPeriodStart: startTime, billingPeriodEnd: endTime } = data; const Component = getComponentForPanelType(PANEL_TYPES.BAR) as FC< PropsTypePropsMap[PANEL_TYPES] >; const getGraphSeries = (color: string, label: string): any => ({ drawStyle: 'bars', paths, lineInterpolation: 'spline', show: true, label, fill: color, stroke: color, width: 2, spanGaps: true, points: { size: 5, show: false, stroke: color, }, }); const uPlotSeries: any = useMemo( () => [ { label: 'Timestamp', stroke: 'purple' }, getGraphSeries( '#DECCBC', graphCompatibleData.data.result[0]?.legend as string, ), getGraphSeries( '#4E74F8', graphCompatibleData.data.result[1]?.legend as string, ), getGraphSeries( '#F24769', graphCompatibleData.data.result[2]?.legend as string, ), ], [graphCompatibleData.data.result], ); const axesOptions = getAxes(isDarkMode, ''); const optionsForChart: uPlot.Options = useMemo( () => ({ id: 'billing-usage-breakdown', series: uPlotSeries, width: containerDimensions.width, height: containerDimensions.height - 30, axes: [ { ...axesOptions[0], grid: { ...axesOptions.grid, show: false, stroke: isDarkMode ? Color.BG_VANILLA_400 : Color.BG_INK_400, }, }, { ...axesOptions[1], stroke: isDarkMode ? Color.BG_SLATE_200 : Color.BG_INK_400, }, ], scales: { x: { ...getXAxisScale(startTime - 86400, endTime), // Minus 86400 from startTime to decrease a day to have a buffer start }, y: { ...getYAxisScale({ series: graphCompatibleData?.data.newResult.data.result, yAxisUnit: '', softMax: null, softMin: null, }), }, }, legend: { show: true, live: false, isolate: true, }, cursor: { lock: false, focus: { prox: 1e6, bias: 1, }, }, focus: { alpha: 0.3, }, padding: [32, 32, 16, 16], plugins: [ tooltipPlugin( fillMissingValuesForQuantities(graphCompatibleData, chartData[0]), '', true, ), ], }), [ axesOptions, chartData, containerDimensions.height, containerDimensions.width, endTime, graphCompatibleData, isDarkMode, startTime, uPlotSeries, ], ); const numberFormatter = new Intl.NumberFormat('en-US'); return ( TOTAL SPENT ${numberFormatter.format(billAmount)}
); }