buster/web/src/components/charts/BusterChartJS/hooks/useOptions/useOptions.tsx

221 lines
6.4 KiB
TypeScript

import { useMemo } from 'react';
import type { ChartProps } from '../../core';
import type { ChartType as ChartJSChartType, Scale } from 'chart.js';
import type {
BusterChartConfigProps,
BusterChartProps,
ChartEncodes
} from '@/components/charts/interfaces';
import { useInteractions } from './useInteractions';
import { useXAxis } from './useXAxis';
import { useYAxis } from './useYAxis';
import { DeepPartial } from 'utility-types';
import type { PluginChartOptions } from 'chart.js';
import { useTooltipOptions } from './useTooltipOptions.ts/useTooltipOptions';
import { DatasetOption } from '@/components/charts/chartHooks';
import { useY2Axis } from './useY2Axis';
import { AnnotationPluginOptions } from 'chartjs-plugin-annotation';
import { BusterChartTypeComponentProps } from '@/components/charts/interfaces/chartComponentInterfaces';
interface UseOptionsProps {
colors: string[];
selectedChartType: BusterChartConfigProps['selectedChartType'];
columnLabelFormats: NonNullable<BusterChartConfigProps['columnLabelFormats']>;
selectedAxis: ChartEncodes;
columnMetadata: NonNullable<BusterChartProps['columnMetadata']>;
barLayout: BusterChartProps['barLayout'];
barGroupType: BusterChartProps['barGroupType'];
lineGroupType: BusterChartProps['lineGroupType'];
xAxisLabelRotation: NonNullable<BusterChartProps['xAxisLabelRotation']>;
xAxisShowAxisLabel: NonNullable<BusterChartProps['xAxisShowAxisLabel']>;
gridLines: NonNullable<BusterChartProps['gridLines']>;
xAxisAxisTitle: BusterChartProps['xAxisAxisTitle'];
xAxisShowAxisTitle: BusterChartProps['xAxisShowAxisTitle'];
yAxisAxisTitle: BusterChartProps['yAxisAxisTitle'];
yAxisShowAxisTitle: BusterChartProps['yAxisShowAxisTitle'];
y2AxisAxisTitle: BusterChartProps['y2AxisAxisTitle'];
y2AxisShowAxisTitle: BusterChartProps['y2AxisShowAxisTitle'];
onChartReady: BusterChartTypeComponentProps['onChartReady'];
onInitialAnimationEnd: BusterChartTypeComponentProps['onInitialAnimationEnd'];
chartPlugins: DeepPartial<PluginChartOptions<ChartJSChartType>>['plugins'];
chartOptions: ChartProps<ChartJSChartType>['options'];
pieDisplayLabelAs: NonNullable<BusterChartProps['pieDisplayLabelAs']>;
columnSettings: NonNullable<BusterChartProps['columnSettings']>;
tooltipKeys: string[];
datasetOptions: DatasetOption[];
hasMismatchedTooltipsAndMeasures: boolean;
yAxisShowAxisLabel: NonNullable<BusterChartProps['yAxisShowAxisLabel']>;
yAxisStartAxisAtZero: BusterChartProps['yAxisStartAxisAtZero'];
y2AxisShowAxisLabel: BusterChartProps['y2AxisShowAxisLabel'];
y2AxisScaleType: BusterChartProps['y2AxisScaleType'];
y2AxisStartAxisAtZero: BusterChartProps['y2AxisStartAxisAtZero'];
yAxisScaleType: BusterChartProps['yAxisScaleType'];
animate: boolean;
goalLinesAnnotations: AnnotationPluginOptions['annotations'];
trendlineAnnotations: AnnotationPluginOptions['annotations'];
disableTooltip: boolean;
xAxisTimeInterval: BusterChartProps['xAxisTimeInterval'];
}
export const useOptions = ({
columnLabelFormats,
colors,
selectedAxis,
selectedChartType,
columnMetadata,
barLayout,
barGroupType,
lineGroupType,
xAxisLabelRotation,
xAxisShowAxisLabel,
xAxisAxisTitle,
xAxisShowAxisTitle,
gridLines,
onChartReady,
onInitialAnimationEnd,
chartPlugins,
chartOptions,
pieDisplayLabelAs,
columnSettings,
tooltipKeys,
datasetOptions,
hasMismatchedTooltipsAndMeasures,
yAxisAxisTitle,
yAxisShowAxisTitle,
y2AxisAxisTitle,
y2AxisShowAxisTitle,
yAxisShowAxisLabel,
yAxisStartAxisAtZero,
y2AxisShowAxisLabel,
y2AxisScaleType,
y2AxisStartAxisAtZero,
yAxisScaleType,
animate,
goalLinesAnnotations,
trendlineAnnotations,
disableTooltip,
xAxisTimeInterval
}: UseOptionsProps) => {
const xAxis = useXAxis({
columnLabelFormats,
columnSettings,
selectedAxis,
selectedChartType,
xAxisLabelRotation,
xAxisShowAxisLabel,
gridLines,
xAxisAxisTitle,
xAxisShowAxisTitle,
lineGroupType,
barGroupType,
xAxisTimeInterval
});
const yAxis = useYAxis({
columnLabelFormats,
selectedAxis,
selectedChartType,
columnMetadata,
barGroupType,
lineGroupType,
yAxisAxisTitle,
yAxisShowAxisTitle,
yAxisStartAxisAtZero,
yAxisShowAxisLabel,
yAxisScaleType,
gridLines
});
const y2Axis = useY2Axis({
columnLabelFormats,
selectedAxis,
selectedChartType,
y2AxisAxisTitle,
y2AxisShowAxisTitle,
y2AxisShowAxisLabel,
y2AxisScaleType,
y2AxisStartAxisAtZero
});
const isHorizontalBar = useMemo(() => {
return selectedChartType === 'bar' && barLayout === 'horizontal';
}, [selectedChartType, barLayout]);
const scales = useMemo(() => {
if (xAxis === undefined && yAxis === undefined) return undefined;
return {
x: isHorizontalBar ? yAxis : xAxis,
y: isHorizontalBar ? xAxis : yAxis,
y2: y2Axis
};
}, [xAxis, yAxis, y2Axis, isHorizontalBar]);
const chartMounted = useMemo(() => {
return {
onMounted: onChartReady,
onInitialAnimationEnd: onInitialAnimationEnd
};
}, [onChartReady, onInitialAnimationEnd]);
const interaction = useInteractions({ selectedChartType, barLayout });
const tooltipOptions = useTooltipOptions({
columnLabelFormats,
selectedChartType,
tooltipKeys,
barGroupType,
lineGroupType,
pieDisplayLabelAs,
selectedAxis,
columnSettings,
datasetOptions,
hasMismatchedTooltipsAndMeasures,
disableTooltip,
colors
});
const options: ChartProps<ChartJSChartType>['options'] = useMemo(() => {
const chartAnnotations = chartPlugins?.annotation?.annotations;
return {
indexAxis: isHorizontalBar ? 'y' : 'x',
animation: animate ? { duration: 1000 } : false,
responsive: true,
maintainAspectRatio: false,
backgroundColor: colors,
borderColor: colors,
scales,
interaction,
plugins: {
chartMounted,
tooltip: tooltipOptions,
...chartPlugins,
annotation: {
annotations: { ...goalLinesAnnotations, ...chartAnnotations, ...trendlineAnnotations }
},
decimation: {
enabled: datasetOptions[0].source.length > 500,
algorithm: 'min-max'
}
},
...chartOptions
};
}, [
animate,
colors,
scales,
interaction,
chartPlugins,
chartOptions,
chartMounted,
onChartReady,
onInitialAnimationEnd,
isHorizontalBar,
goalLinesAnnotations,
trendlineAnnotations
]);
return options;
};