attempt to set max and min

This commit is contained in:
Nate Kelley 2025-09-24 21:02:24 -06:00
parent 2f035ec70d
commit 84a6af7730
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
2 changed files with 88 additions and 10 deletions

View File

@ -7,6 +7,7 @@ import {
DEFAULT_CHART_CONFIG,
DEFAULT_COLUMN_LABEL_FORMAT,
} from '@buster/server-shared/metrics';
import { fa } from '@faker-js/faker';
import type {
CartesianScaleTypeRegistry,
Scale,
@ -20,7 +21,7 @@ import type { BusterChartProps } from '../../../BusterChart.types';
import { formatYAxisLabel, yAxisSimilar } from '../../../commonHelpers';
import { useY2AxisTitle } from './axisHooks/useY2AxisTitle';
export const DEFAULT_Y2_AXIS_COUNT = 7;
export const DEFAULT_Y2_AXIS_COUNT = 9;
export const useY2Axis = ({
columnLabelFormats,
@ -47,6 +48,7 @@ export const useY2Axis = ({
const selectedAxis = selectedAxisProp as ComboChartAxis;
const y2AxisKeys = selectedAxis.y2 || [];
const yAxisMinValue = yAxis?.min;
const yAxisMaxValue = yAxis?.max;
const y2AxisKeysString = useMemo(() => {
return y2AxisKeys.join(',');
@ -116,6 +118,7 @@ export const useY2Axis = ({
includeBounds: true,
},
min: yAxisMinValue,
max: yAxisMaxValue,
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},

View File

@ -1,11 +1,14 @@
/** biome-ignore-all lint/style/noNonNullAssertion: false positive */
import round from 'lodash/round';
import { useMemo } from 'react';
import type { BusterChartProps } from '../../../BusterChart.types';
const MIN_PERCENT_DIFFERENCE = 1.5;
const MIN_PERCENT_DIFFERENCE = 2;
const MAX_PERCENT_DIFFERENCE = 2;
const MIN_OFFSET = 1.1;
const MAX_OFFSET = 1.1;
const PERCENTAGE_STEP = 5;
export const useYTickValues = ({
hasY2Axis,
@ -25,23 +28,34 @@ export const useYTickValues = ({
const shouldUseMinAndMaxValues = hasY2Axis && columnMetadata && selectedChartType === 'combo';
const checkValues = useMemo(() => {
if (!shouldUseMinAndMaxValues) return [];
return [...yAxisKeys, ...y2AxisKeys];
}, [yAxisKeys, y2AxisKeys]);
}, [yAxisKeys, y2AxisKeys, shouldUseMinAndMaxValues]);
const hasOnePercentageValue = useMemo(() => {
if (!shouldUseMinAndMaxValues) return false;
return checkValues.some((key) => {
const columnFormat = columnLabelFormats[key];
return columnFormat?.style === 'percent';
});
}, [checkValues, columnLabelFormats, shouldUseMinAndMaxValues]);
const allYValuesArePercentage = useMemo(() => {
if (!shouldUseMinAndMaxValues) return false;
return checkValues.every((key) => {
const columnFormat = columnLabelFormats[key];
return columnFormat?.style === 'percent';
});
}, [checkValues, columnLabelFormats]);
}, [checkValues, columnLabelFormats, shouldUseMinAndMaxValues]);
const columnMap = useMemo(() => {
if (!columnMetadata) return new Map();
if (!columnMetadata || !shouldUseMinAndMaxValues) return new Map();
return new Map(columnMetadata.map((col) => [col.name, col]));
}, [columnMetadata]);
}, [columnMetadata, shouldUseMinAndMaxValues]);
// Calculate min/max ranges for y-axis columns
const yAxisRange = useMemo(() => {
if (!shouldUseMinAndMaxValues) return { min: Infinity, max: -Infinity };
return yAxisKeys.reduce(
(acc, key) => {
const column = columnMap.get(key);
@ -55,10 +69,11 @@ export const useYTickValues = ({
},
{ min: Infinity, max: -Infinity }
);
}, [yAxisKeys, columnMap]);
}, [yAxisKeys, columnMap, shouldUseMinAndMaxValues]);
// Calculate min/max ranges for y2-axis columns
const y2AxisRange = useMemo(() => {
if (!shouldUseMinAndMaxValues) return { min: Infinity, max: -Infinity };
return y2AxisKeys.reduce(
(acc, key) => {
const column = columnMap.get(key);
@ -72,7 +87,7 @@ export const useYTickValues = ({
},
{ min: Infinity, max: -Infinity }
);
}, [y2AxisKeys, columnMap]);
}, [y2AxisKeys, columnMap, shouldUseMinAndMaxValues]);
const minTickValue: number | undefined = useMemo(() => {
if (!shouldUseMinAndMaxValues) return undefined;
@ -110,9 +125,16 @@ export const useYTickValues = ({
// If both min and max values are similar, use the lowest min value
if (minValuesAreSimilar && maxValuesAreSimilar) {
return Math.min(yAxisRange.min, y2AxisRange.min) * MIN_OFFSET;
if (hasOnePercentageValue) {
// If there's at least one percentage value, round the min to the nearest lower multiple of 5
const min = Math.min(yAxisRange.min, y2AxisRange.min) * MIN_OFFSET;
return Math.floor(min / PERCENTAGE_STEP) * PERCENTAGE_STEP;
}
return round(Math.min(yAxisRange.min, y2AxisRange.min) * MIN_OFFSET, 0);
}
}, [
hasOnePercentageValue,
columnLabelFormats,
yAxisRange,
y2AxisRange,
@ -122,7 +144,60 @@ export const useYTickValues = ({
allYValuesArePercentage,
]);
const maxTickValue: number | undefined = undefined;
const maxTickValue: number | undefined = useMemo(() => {
if (!shouldUseMinAndMaxValues) return undefined;
// If all Y values are percentages, return the highest value
if (allYValuesArePercentage) {
const highestValue = checkValues.reduce((max, key) => {
const column = columnMap.get(key);
return Math.max(max, Number(column?.max_value ?? 0));
}, -Infinity);
if (highestValue === -Infinity) return undefined;
if (highestValue < 1) return 1;
return highestValue;
}
// Reset infinities if no valid data found
if (yAxisRange.min === Infinity) yAxisRange.min = 0;
if (yAxisRange.max === -Infinity) yAxisRange.max = 0;
if (y2AxisRange.min === Infinity) y2AxisRange.min = 0;
if (y2AxisRange.max === -Infinity) y2AxisRange.max = 0;
// Check if min values are within 150% of each other
const minValuesAreSimilar =
Math.abs(yAxisRange.min) > 0 && Math.abs(y2AxisRange.min) > 0
? Math.max(yAxisRange.min, y2AxisRange.min) / Math.min(yAxisRange.min, y2AxisRange.min) <=
MIN_PERCENT_DIFFERENCE
: yAxisRange.min === y2AxisRange.min;
// Check if max values are within 200% of each other
const maxValuesAreSimilar =
Math.abs(yAxisRange.max) > 0 && Math.abs(y2AxisRange.max) > 0
? Math.max(yAxisRange.max, y2AxisRange.max) / Math.min(yAxisRange.max, y2AxisRange.max) <=
MAX_PERCENT_DIFFERENCE
: yAxisRange.max === y2AxisRange.max;
// If both min and max values are similar, use the highest max value
if (minValuesAreSimilar && maxValuesAreSimilar) {
if (hasOnePercentageValue) {
// If there's at least one percentage value, round the max to the nearest higher multiple of 5
const max = Math.max(yAxisRange.max, y2AxisRange.max) * MAX_OFFSET;
return Math.ceil(max / PERCENTAGE_STEP) * PERCENTAGE_STEP;
}
return round(Math.max(yAxisRange.max, y2AxisRange.max) * MAX_OFFSET, 0);
}
}, [
hasOnePercentageValue,
columnLabelFormats,
yAxisRange,
y2AxisRange,
shouldUseMinAndMaxValues,
columnMap,
checkValues,
allYValuesArePercentage,
]);
return {
minTickValue,