mirror of https://github.com/buster-so/buster.git
scatter x axis formatter
This commit is contained in:
parent
e66f26f7a2
commit
3656ee586c
|
@ -284,4 +284,132 @@ describe('useXAxis', () => {
|
|||
expect(result.current?.title?.display).toBe(false);
|
||||
expect(result.current?.title?.text).toBe('');
|
||||
});
|
||||
|
||||
it('should correctly set xAxisColumnFormats and firstXColumnLabelFormat', () => {
|
||||
// Test with default category column
|
||||
const { result } = renderHook(() => useXAxis(defaultProps));
|
||||
|
||||
// Get the internal state to verify xAxisColumnFormats and firstXColumnLabelFormat
|
||||
// We need to access the useXAxis hook results
|
||||
expect(result.current).toBeDefined();
|
||||
|
||||
// For scatter chart
|
||||
const scatterProps = {
|
||||
...defaultProps,
|
||||
selectedChartType: ChartType.Scatter,
|
||||
selectedAxis: {
|
||||
x: ['numeric_column'],
|
||||
y: ['numeric_column']
|
||||
} as ChartEncodes
|
||||
};
|
||||
|
||||
const { result: scatterResult } = renderHook(() => useXAxis(scatterProps));
|
||||
expect(scatterResult.current).toBeDefined();
|
||||
expect(scatterResult.current?.type).toBe('linear');
|
||||
|
||||
// For multiple x-axis columns
|
||||
const multipleColumnsProps = {
|
||||
...defaultProps,
|
||||
selectedAxis: {
|
||||
x: ['category_column', 'numeric_column'],
|
||||
y: ['numeric_column']
|
||||
} as ChartEncodes
|
||||
};
|
||||
|
||||
const { result: multiResult } = renderHook(() => useXAxis(multipleColumnsProps));
|
||||
expect(multiResult.current).toBeDefined();
|
||||
expect(multiResult.current?.type).toBe('category');
|
||||
|
||||
// For unsupported chart type (pie)
|
||||
const pieProps = {
|
||||
...defaultProps,
|
||||
selectedChartType: ChartType.Pie
|
||||
};
|
||||
|
||||
const { result: pieResult } = renderHook(() => useXAxis(pieProps));
|
||||
expect(pieResult.current).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should correctly handle firstXColumnLabelFormat for scatter chart', () => {
|
||||
// Specifically test the firstXColumnLabelFormat logic for scatter charts
|
||||
const scatterProps = {
|
||||
...defaultProps,
|
||||
selectedChartType: ChartType.Scatter,
|
||||
selectedAxis: {
|
||||
x: ['numeric_column'],
|
||||
y: ['numeric_column']
|
||||
} as ChartEncodes
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => useXAxis(scatterProps));
|
||||
|
||||
// Verify that scatter charts get proper formatting with minimumFractionDigits and maximumFractionDigits set to 0
|
||||
expect(result.current).toBeDefined();
|
||||
expect(result.current?.type).toBe('linear');
|
||||
|
||||
// Test the tick callback formatting
|
||||
// We can't directly access the firstXColumnLabelFormat from outside the hook,
|
||||
// but we can test its effects through the tick callback behavior
|
||||
expect(result.current?.ticks?.callback).toBeDefined();
|
||||
|
||||
// Verify custom column label formats are applied
|
||||
const customFormatProps = {
|
||||
...scatterProps,
|
||||
columnLabelFormats: {
|
||||
...defaultProps.columnLabelFormats,
|
||||
numeric_column: {
|
||||
...DEFAULT_COLUMN_LABEL_FORMAT,
|
||||
columnType: 'number' as SimplifiedColumnType,
|
||||
style: 'number' as const,
|
||||
minimumFractionDigits: 3,
|
||||
maximumFractionDigits: 3
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { result: customResult } = renderHook(() => useXAxis(customFormatProps));
|
||||
expect(customResult.current).toBeDefined();
|
||||
expect(customResult.current?.type).toBe('linear');
|
||||
});
|
||||
|
||||
it('should apply correct column formats for date columns with different formats', () => {
|
||||
// Test with custom date format
|
||||
const customDateFormatProps = {
|
||||
...defaultProps,
|
||||
selectedChartType: ChartType.Line,
|
||||
selectedAxis: {
|
||||
x: ['date_column'],
|
||||
y: ['numeric_column']
|
||||
} as ChartEncodes,
|
||||
columnLabelFormats: {
|
||||
...defaultProps.columnLabelFormats,
|
||||
date_column: {
|
||||
...defaultProps.columnLabelFormats.date_column,
|
||||
dateFormat: 'YYYY-MM-DD'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => useXAxis(customDateFormatProps));
|
||||
expect(result.current).toBeDefined();
|
||||
expect(result.current?.type).toBe('time');
|
||||
expect(result.current?.ticks?.callback).toBeDefined();
|
||||
|
||||
// Test with auto date format
|
||||
const autoDateFormatProps = {
|
||||
...customDateFormatProps,
|
||||
columnLabelFormats: {
|
||||
...defaultProps.columnLabelFormats,
|
||||
date_column: {
|
||||
...defaultProps.columnLabelFormats.date_column,
|
||||
dateFormat: 'auto'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { result: autoResult } = renderHook(() => useXAxis(autoDateFormatProps));
|
||||
expect(autoResult.current).toBeDefined();
|
||||
expect(autoResult.current?.type).toBe('time');
|
||||
expect(autoResult.current?.ticks?.callback).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -67,6 +67,17 @@ export const useXAxis = ({
|
|||
}, {});
|
||||
}, [selectedAxis.x, columnLabelFormats, isSupportedType]);
|
||||
|
||||
const firstXColumnLabelFormat = useMemo(() => {
|
||||
if (isScatterChart) {
|
||||
return {
|
||||
...xAxisColumnFormats[selectedAxis.x[0]],
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0
|
||||
};
|
||||
}
|
||||
return xAxisColumnFormats[selectedAxis.x[0]];
|
||||
}, [isScatterChart, xAxisColumnFormats, selectedAxis.x]);
|
||||
|
||||
const stacked = useIsStacked({ selectedChartType, lineGroupType, barGroupType });
|
||||
|
||||
const grid: DeepPartial<GridLineOptions> | undefined = useMemo(() => {
|
||||
|
@ -79,10 +90,9 @@ export const useXAxis = ({
|
|||
const type: DeepPartial<ScaleChartOptions<'bar'>['scales']['x']['type']> = useMemo(() => {
|
||||
const xAxisKeys = Object.keys(xAxisColumnFormats);
|
||||
const xAxisKeysLength = xAxisKeys.length;
|
||||
const firstXKey = xAxisKeys[0];
|
||||
|
||||
if (xAxisKeysLength === 1) {
|
||||
const xIsDate = xAxisColumnFormats[firstXKey].columnType === 'date';
|
||||
const xIsDate = firstXColumnLabelFormat.columnType === 'date';
|
||||
|
||||
if ((isLineChart || isScatterChart) && xIsDate) {
|
||||
return 'time';
|
||||
|
@ -101,17 +111,24 @@ export const useXAxis = ({
|
|||
}
|
||||
|
||||
if (isScatterChart && xAxisKeysLength === 1) {
|
||||
const isNumeric = isNumericColumnType(xAxisColumnFormats[firstXKey]?.columnType);
|
||||
const isNumeric = isNumericColumnType(firstXColumnLabelFormat?.columnType);
|
||||
if (isNumeric) return 'linear';
|
||||
}
|
||||
|
||||
return 'category';
|
||||
}, [isScatterChart, isComboChart, isLineChart, columnSettings, xAxisColumnFormats]);
|
||||
}, [
|
||||
isScatterChart,
|
||||
isComboChart,
|
||||
isLineChart,
|
||||
columnSettings,
|
||||
xAxisColumnFormats,
|
||||
firstXColumnLabelFormat
|
||||
]);
|
||||
|
||||
const derivedTimeUnit = useMemo(() => {
|
||||
if (type !== 'time') return false;
|
||||
|
||||
const fmt = xAxisColumnFormats[selectedAxis.x[0]].dateFormat;
|
||||
const fmt = firstXColumnLabelFormat.dateFormat;
|
||||
if (!fmt || fmt === 'auto') return false;
|
||||
|
||||
// look for patterns in your DATE_FORMATS keys
|
||||
|
@ -122,7 +139,7 @@ export const useXAxis = ({
|
|||
if (/H{1,2}/.test(fmt)) return 'hour';
|
||||
// fall back
|
||||
return false;
|
||||
}, [xAxisColumnFormats, selectedAxis.x]);
|
||||
}, [firstXColumnLabelFormat]);
|
||||
|
||||
const title = useXAxisTitle({
|
||||
xAxis: selectedAxis.x,
|
||||
|
@ -141,8 +158,7 @@ export const useXAxis = ({
|
|||
const rawValue = this.getLabelForValue(value as number);
|
||||
|
||||
if (type === 'time' || isDate(rawValue)) {
|
||||
const xKey = selectedAxis.x[0];
|
||||
const xColumnLabelFormat = xAxisColumnFormats[xKey];
|
||||
const xColumnLabelFormat = firstXColumnLabelFormat;
|
||||
const isAutoFormat = xColumnLabelFormat.dateFormat === 'auto';
|
||||
if (isAutoFormat) {
|
||||
const unit = (this.chart.scales['x'] as TimeScale)._unit as
|
||||
|
@ -162,6 +178,11 @@ export const useXAxis = ({
|
|||
return truncateText(res, 24);
|
||||
}
|
||||
|
||||
if (isScatterChart) {
|
||||
//raw value does not work for scatter charts, it returns the value as a string
|
||||
return formatLabel(value, firstXColumnLabelFormat);
|
||||
}
|
||||
|
||||
return DEFAULT_X_AXIS_TICK_CALLBACK.call(this, value, index, this.getLabels() as any);
|
||||
});
|
||||
|
||||
|
|
|
@ -81,7 +81,9 @@ export const formatLabel = (
|
|||
if (style === 'currency') {
|
||||
formattedText = formatNumber(roundedNumber, {
|
||||
currency,
|
||||
compact: compactNumbers
|
||||
compact: compactNumbers,
|
||||
minimumFractionDigits: Math.min(minimumFractionDigits, maximumFractionDigits),
|
||||
maximumFractionDigits: Math.max(minimumFractionDigits, maximumFractionDigits)
|
||||
});
|
||||
} else {
|
||||
formattedText = formatNumber(roundedNumber, {
|
||||
|
|
Loading…
Reference in New Issue