mirror of https://github.com/buster-so/buster.git
update chart theme and ticker
This commit is contained in:
parent
27aed66397
commit
e54194d018
|
@ -32,10 +32,9 @@ import { isServer } from '@tanstack/react-query';
|
|||
import './core/plugins/chartjs-plugin-dayjs';
|
||||
import { truncateText } from '@/lib/text';
|
||||
|
||||
import { DeduplicatedTimeScale } from './core/plugins/chartjs-scale-tick-duplicate';
|
||||
import './core/plugins/chartjs-scale-tick-duplicate';
|
||||
|
||||
// Register the scale properly
|
||||
registry.addScales(DeduplicatedTimeScale);
|
||||
|
||||
const fontFamily = isServer
|
||||
? 'Roobert_Pro'
|
||||
|
|
|
@ -23,13 +23,12 @@ declare module 'chart.js' {
|
|||
|
||||
const originalBuildTicks = TimeScale.prototype.buildTicks;
|
||||
|
||||
// Override buildTicks
|
||||
// // Override buildTicks
|
||||
TimeScale.prototype.buildTicks = function () {
|
||||
// Step 1: Get default ticks using the original method
|
||||
// Generate default ticks
|
||||
const defaultTicks = originalBuildTicks.call(this);
|
||||
console.log('defaultTicks', defaultTicks);
|
||||
|
||||
// Step 2: Access tick callback and display format
|
||||
// Access tick callback and display format
|
||||
const tickCallback = this.options.ticks?.callback;
|
||||
const displayFormat =
|
||||
this.options.time?.displayFormats?.[this._unit] ||
|
||||
|
@ -37,30 +36,17 @@ TimeScale.prototype.buildTicks = function () {
|
|||
'MMM';
|
||||
const format = this._adapter.format.bind(this._adapter);
|
||||
|
||||
// Step 3: Track seen labels and collect unique ticks
|
||||
// Deduplicate ticks
|
||||
const seen = new Set();
|
||||
const uniqueTicks = [];
|
||||
|
||||
for (let i = 0; i < defaultTicks.length; i++) {
|
||||
const tick = defaultTicks[i];
|
||||
|
||||
// Step 4: Generate tick label
|
||||
let label;
|
||||
try {
|
||||
if (typeof tickCallback === 'function') {
|
||||
label = tickCallback.call(this, tick.value, i, defaultTicks);
|
||||
} else {
|
||||
label = format(tick.value, displayFormat);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Tick callback error at index', i, e);
|
||||
label = '???';
|
||||
}
|
||||
|
||||
// Ensure label is a string for consistent comparison
|
||||
let label = tickCallback
|
||||
? tickCallback.call(this, tick.value, i, defaultTicks)
|
||||
: format(tick.value, displayFormat);
|
||||
const stringLabel = String(label ?? '');
|
||||
|
||||
// Step 5: Only include tick if label is unique
|
||||
if (!seen.has(stringLabel)) {
|
||||
seen.add(stringLabel);
|
||||
uniqueTicks.push({
|
||||
|
@ -70,67 +56,8 @@ TimeScale.prototype.buildTicks = function () {
|
|||
}
|
||||
}
|
||||
|
||||
// Step 6: Return the filtered ticks
|
||||
// Set the filtered ticks on the axis instance
|
||||
this.ticks = uniqueTicks;
|
||||
|
||||
return uniqueTicks;
|
||||
};
|
||||
|
||||
export class DeduplicatedTimeScale extends TimeScale {
|
||||
static id = 'deduplicated-time';
|
||||
static defaults = TimeScale.defaults;
|
||||
|
||||
/**
|
||||
* Override buildTicks to eliminate duplicate ticks based on formatted values.
|
||||
* @returns {Array} Array of unique tick objects
|
||||
*/
|
||||
buildTicks() {
|
||||
console.log('buildTicks');
|
||||
// Step 1: Get default ticks from parent TimeScale
|
||||
const defaultTicks = super.buildTicks();
|
||||
|
||||
// Step 2: Access tick callback and display format
|
||||
const tickCallback = this.options.ticks?.callback;
|
||||
const displayFormat =
|
||||
this.options.time?.displayFormats?.[this._unit] ||
|
||||
this.options.time?.displayFormats?.month ||
|
||||
'MMM';
|
||||
const format = this._adapter.format.bind(this._adapter);
|
||||
|
||||
// Step 3: Track seen labels and collect unique ticks
|
||||
const seen = new Set();
|
||||
const uniqueTicks = [];
|
||||
|
||||
for (let i = 0; i < defaultTicks.length; i++) {
|
||||
const tick = defaultTicks[i];
|
||||
|
||||
// Step 4: Generate tick label
|
||||
let label;
|
||||
try {
|
||||
if (typeof tickCallback === 'function') {
|
||||
// Pass tick value, index, and ticks array to callback
|
||||
label = tickCallback.call(this, tick.value, i, defaultTicks);
|
||||
} else {
|
||||
// Format using the adapter with the appropriate display format
|
||||
label = format(tick.value, displayFormat);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Tick callback error at index', i, e);
|
||||
label = '???';
|
||||
}
|
||||
|
||||
// Ensure label is a string for consistent comparison
|
||||
const stringLabel = String(label ?? '');
|
||||
|
||||
// Step 5: Only include tick if label is unique
|
||||
if (!seen.has(stringLabel)) {
|
||||
seen.add(stringLabel);
|
||||
uniqueTicks.push({
|
||||
...tick,
|
||||
label: stringLabel // Ensure the tick object has the correct label
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Return the filtered ticks
|
||||
return uniqueTicks;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,8 +155,8 @@ export const useXAxis = ({
|
|||
| 'month'
|
||||
| 'quarter'
|
||||
| 'year';
|
||||
console.log('selected unit', unit);
|
||||
const format = DATE_FORMATS[unit];
|
||||
console.log('auto unit?', { unit, format });
|
||||
return formatLabel(rawValue, { ...xColumnLabelFormat, dateFormat: format });
|
||||
}
|
||||
const res = formatLabel(rawValue, xColumnLabelFormat);
|
||||
|
@ -201,8 +201,6 @@ export const useXAxis = ({
|
|||
return derivedTimeUnit;
|
||||
}, [type, derivedTimeUnit, xAxisTimeInterval]);
|
||||
|
||||
console.log('timeUnit', { timeUnit, derivedTimeUnit });
|
||||
|
||||
const offset = useMemo(() => {
|
||||
if (isScatterChart) return false;
|
||||
if (isLineChart) return lineGroupType !== 'percentage-stack';
|
||||
|
@ -212,7 +210,7 @@ export const useXAxis = ({
|
|||
const memoizedXAxisOptions: DeepPartial<ScaleChartOptions<'bar'>['scales']['x']> | undefined =
|
||||
useMemo(() => {
|
||||
if (isPieChart) return undefined;
|
||||
console.log('type', { type, timeUnit });
|
||||
console.log('type', { type, timeUnit, derivedTimeUnit });
|
||||
return {
|
||||
type,
|
||||
offset,
|
||||
|
@ -231,7 +229,7 @@ export const useXAxis = ({
|
|||
enabled: false //test
|
||||
},
|
||||
autoSkip: false,
|
||||
maxTicksLimit: type === 'time' ? (timeUnit === 'month' ? 11 : 18) : undefined,
|
||||
maxTicksLimit: type === 'time' ? (timeUnit === 'month' ? 12 : 18) : undefined,
|
||||
sampleSize: type === 'time' ? 24 : undefined,
|
||||
display: xAxisShowAxisLabel,
|
||||
callback: tickCallback as any, //I need to use null for auto date
|
||||
|
|
|
@ -377,6 +377,44 @@ export const FixedDateFormat_TimeIntervalTest_Days_WithAutoUnit_UnevenDays: Stor
|
|||
}
|
||||
};
|
||||
|
||||
export const XAxisTimeIntervalWithMismatchingData_Days: Story = {
|
||||
args: {
|
||||
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args,
|
||||
xAxisTimeInterval: 'day',
|
||||
data: Array.from({ length: 31 }, (_, i) => ({
|
||||
date: dayjs('2024-01-01').add(i, 'day').toISOString(),
|
||||
sales: addNoise(i * 15 + 55, 10)
|
||||
})),
|
||||
columnLabelFormats: {
|
||||
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args!.columnLabelFormats,
|
||||
date: {
|
||||
columnType: 'date',
|
||||
style: 'date',
|
||||
dateFormat: 'MMM DD'
|
||||
} satisfies IColumnLabelFormat
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const XAxisTimeIntervalWithMismatchingData_Months: Story = {
|
||||
args: {
|
||||
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args,
|
||||
xAxisTimeInterval: 'month',
|
||||
data: Array.from({ length: 14 }, (_, i) => ({
|
||||
date: dayjs('2024-01-01').add(i, 'month').toISOString(),
|
||||
sales: addNoise(i * 15 + 55, 10)
|
||||
})),
|
||||
columnLabelFormats: {
|
||||
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args!.columnLabelFormats,
|
||||
date: {
|
||||
columnType: 'date',
|
||||
style: 'date',
|
||||
dateFormat: 'MMM DD'
|
||||
} satisfies IColumnLabelFormat
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Simple X and Y axis with numeric values
|
||||
export const NumericXY: Story = {
|
||||
args: {
|
||||
|
|
Loading…
Reference in New Issue