mirror of https://github.com/buster-so/buster.git
start building timescale
This commit is contained in:
parent
ddde654a0a
commit
1cf88971eb
|
@ -7,6 +7,7 @@ declare module 'chart.js' {
|
||||||
export const ChartJSTickDuplicatePlugin: Plugin<ChartType> = {
|
export const ChartJSTickDuplicatePlugin: Plugin<ChartType> = {
|
||||||
id: 'chartjs-plugin-tick-duplicate',
|
id: 'chartjs-plugin-tick-duplicate',
|
||||||
afterBuildTicks(chart) {
|
afterBuildTicks(chart) {
|
||||||
|
console.log('afterBuildTicks');
|
||||||
const scale = chart.scales['x'];
|
const scale = chart.scales['x'];
|
||||||
if (!scale || scale.type !== 'time') return;
|
if (!scale || scale.type !== 'time') return;
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ export const ChartJSTickDuplicatePlugin: Plugin<ChartType> = {
|
||||||
const displayFormat = scale.options.time.displayFormats?.month || 'MMM';
|
const displayFormat = scale.options.time.displayFormats?.month || 'MMM';
|
||||||
const tickCallback = scale.options.ticks?.callback;
|
const tickCallback = scale.options.ticks?.callback;
|
||||||
|
|
||||||
const allTicks = scale._generate(); // raw ticks
|
const allTicks = scale._generate(); // raw generated ticks
|
||||||
const values = allTicks.map((t) => t.value ?? t);
|
const values = allTicks.map((t) => t.value ?? t);
|
||||||
|
|
||||||
const seenLabels = new Set();
|
const seenLabels = new Set();
|
||||||
|
@ -26,7 +27,6 @@ export const ChartJSTickDuplicatePlugin: Plugin<ChartType> = {
|
||||||
let label;
|
let label;
|
||||||
try {
|
try {
|
||||||
if (typeof tickCallback === 'function') {
|
if (typeof tickCallback === 'function') {
|
||||||
// ✅ this is the KEY FIX: preserve `this` as the scale
|
|
||||||
label = tickCallback.call(scale, value, i, values);
|
label = tickCallback.call(scale, value, i, values);
|
||||||
} else {
|
} else {
|
||||||
label = adapter.format(value, displayFormat);
|
label = adapter.format(value, displayFormat);
|
||||||
|
@ -49,23 +49,57 @@ export const ChartJSTickDuplicatePlugin: Plugin<ChartType> = {
|
||||||
const max = scale.max ?? Math.max(...values);
|
const max = scale.max ?? Math.max(...values);
|
||||||
const spacing = (max - min) / (unique.length - 1);
|
const spacing = (max - min) / (unique.length - 1);
|
||||||
|
|
||||||
scale._customTicks = unique.map((u, i) => ({
|
scale.ticks = unique.map((u, i) => ({
|
||||||
value: min + spacing * i,
|
value: min + i * spacing,
|
||||||
label: u.label
|
label: u.label
|
||||||
}));
|
}));
|
||||||
|
|
||||||
scale.ticks = scale._customTicks;
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDraw(chart) {
|
|
||||||
const scale = chart.scales['x'];
|
|
||||||
if (!scale?._customTicks) return;
|
|
||||||
|
|
||||||
scale.ticks = scale._customTicks.map((t) => ({
|
|
||||||
...t,
|
|
||||||
label: t.label
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChartJSTickDuplicatePlugin;
|
export default ChartJSTickDuplicatePlugin;
|
||||||
|
|
||||||
|
import { TimeScale } from 'chart.js';
|
||||||
|
|
||||||
|
export class DeduplicatedTimeScale extends TimeScale {
|
||||||
|
static id = 'time';
|
||||||
|
static defaults = {
|
||||||
|
...TimeScale.defaults
|
||||||
|
};
|
||||||
|
generateTicks() {
|
||||||
|
const baseTicks = super.generateTicks(); // Chart.js handles spacing, maxTicksLimit, etc.
|
||||||
|
const tickCallback = this.options.ticks?.callback;
|
||||||
|
const format = this._adapter.format;
|
||||||
|
const displayFormat = this.options.time?.displayFormats?.month || 'MMM';
|
||||||
|
|
||||||
|
const seenLabels = new Set();
|
||||||
|
const dedupedTicks = [];
|
||||||
|
|
||||||
|
const values = baseTicks.map((t) => t.value);
|
||||||
|
|
||||||
|
for (let i = 0; i < baseTicks.length; i++) {
|
||||||
|
const tick = baseTicks[i];
|
||||||
|
|
||||||
|
let label;
|
||||||
|
try {
|
||||||
|
if (typeof tickCallback === 'function') {
|
||||||
|
// Call with same context Chart.js uses
|
||||||
|
label = tickCallback.call(this, tick.value, i, values);
|
||||||
|
} else {
|
||||||
|
label = format(tick.value, displayFormat);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
label = '???';
|
||||||
|
console.warn('Tick callback error at index', i, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stringLabel = String(label);
|
||||||
|
|
||||||
|
if (!seenLabels.has(stringLabel)) {
|
||||||
|
seenLabels.add(stringLabel);
|
||||||
|
dedupedTicks.push(tick); // original tick object (value + major flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dedupedTicks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -332,13 +332,17 @@ export const FixedDateFormat_TimeIntervalTest_UnevenMonthsAutoUnit_BUSTED: Story
|
||||||
export const FixedDateFormat_TimeIntervalTest_Days_WithForcedUnit: Story = {
|
export const FixedDateFormat_TimeIntervalTest_Days_WithForcedUnit: Story = {
|
||||||
args: {
|
args: {
|
||||||
...AutoDateFormat_TimeIntervalTest_Days_WithForcedUnit.args,
|
...AutoDateFormat_TimeIntervalTest_Days_WithForcedUnit.args,
|
||||||
|
data: Array.from({ length: 131 }, (_, i) => ({
|
||||||
|
date: dayjs('2024-01-01').add(i, 'day').toISOString(),
|
||||||
|
sales: addNoise(i * 15 + 55, 10)
|
||||||
|
})),
|
||||||
xAxisTimeInterval: 'day',
|
xAxisTimeInterval: 'day',
|
||||||
columnLabelFormats: {
|
columnLabelFormats: {
|
||||||
...AutoDateFormat_TimeIntervalTest_Days_WithForcedUnit.args!.columnLabelFormats,
|
...AutoDateFormat_TimeIntervalTest_Days_WithForcedUnit.args!.columnLabelFormats,
|
||||||
date: {
|
date: {
|
||||||
columnType: 'date',
|
columnType: 'date',
|
||||||
style: 'date',
|
style: 'date',
|
||||||
dateFormat: 'MMM DD'
|
dateFormat: 'MMM DD, YYYY'
|
||||||
} satisfies IColumnLabelFormat
|
} satisfies IColumnLabelFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue