mirror of https://github.com/buster-so/buster.git
enable updates are more efficient
This commit is contained in:
parent
f8be3fa007
commit
1feb7558c2
|
@ -6,18 +6,36 @@ export interface ChartHoverBarPluginOptions {
|
|||
isDarkMode?: boolean;
|
||||
}
|
||||
|
||||
declare module 'chart.js' {
|
||||
interface Chart {
|
||||
$pluginHoverBarManager: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const ChartHoverBarPlugin: Plugin<ChartType, ChartHoverBarPluginOptions> = {
|
||||
id: 'tooltipHoverBar',
|
||||
afterInit: (chart) => {
|
||||
//@ts-ignore
|
||||
const chartType = chart.config.type as ChartType;
|
||||
// Store whether this is a bar chart to avoid checking on every draw
|
||||
chart.$pluginHoverBarManager = {
|
||||
enabled:
|
||||
chartType === 'bar' ||
|
||||
(chartType === 'line' && chart.data.datasets.some((dataset) => dataset.type === 'bar')) //this line is for combo chart
|
||||
};
|
||||
},
|
||||
beforeDraw: (chart, args, options) => {
|
||||
// Early return if not a bar chart (check only once during initialization)
|
||||
if (!chart.$pluginHoverBarManager.enabled) return;
|
||||
|
||||
const {
|
||||
ctx,
|
||||
tooltip,
|
||||
chartArea: { top, bottom },
|
||||
scales: { x }
|
||||
} = chart;
|
||||
const chartType = (chart.config as any).type as ChartType;
|
||||
|
||||
if (chartType !== 'bar') return;
|
||||
|
||||
const tooltipActive = tooltip?.getActiveElements();
|
||||
|
||||
|
|
|
@ -6,39 +6,54 @@ export interface ChartHoverLinePluginOptions {
|
|||
lineDash?: number[];
|
||||
}
|
||||
|
||||
declare module 'chart.js' {
|
||||
interface Chart {
|
||||
$pluginHoverLineManager: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const ChartHoverLinePlugin: Plugin<ChartType, ChartHoverLinePluginOptions> = {
|
||||
id: 'tooltipHoverLine',
|
||||
afterInit: (chart) => {
|
||||
//@ts-ignore
|
||||
const chartType = chart.config.type as ChartType;
|
||||
chart.$pluginHoverLineManager = {
|
||||
enabled: chartType === 'line'
|
||||
};
|
||||
},
|
||||
beforeDraw: (chart, args, options) => {
|
||||
if (!chart.$pluginHoverLineManager.enabled) return;
|
||||
|
||||
const {
|
||||
ctx,
|
||||
tooltip,
|
||||
chartArea: { top, bottom }
|
||||
} = chart;
|
||||
const chartType = (chart.config as any).type as ChartType;
|
||||
if (chartType === 'line') {
|
||||
const tooltipActive = tooltip?.getActiveElements();
|
||||
|
||||
if (tooltipActive && tooltipActive.length) {
|
||||
const activePoint = tooltipActive[0];
|
||||
const x = activePoint.element.x;
|
||||
const topY = top;
|
||||
const bottomY = bottom;
|
||||
const tooltipActive = tooltip?.getActiveElements();
|
||||
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, topY);
|
||||
ctx.lineTo(x, bottomY);
|
||||
ctx.lineWidth = options.lineWidth || 1;
|
||||
ctx.strokeStyle = options.lineColor;
|
||||
if (options.lineDash) {
|
||||
ctx.setLineDash(options.lineDash);
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
if (tooltipActive && tooltipActive.length) {
|
||||
const activePoint = tooltipActive[0];
|
||||
const x = activePoint.element.x;
|
||||
const topY = top;
|
||||
const bottomY = bottom;
|
||||
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, topY);
|
||||
ctx.lineTo(x, bottomY);
|
||||
ctx.lineWidth = options.lineWidth || 1;
|
||||
ctx.strokeStyle = options.lineColor;
|
||||
if (options.lineDash) {
|
||||
ctx.setLineDash(options.lineDash);
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
|
||||
defaults: {
|
||||
lineWidth: 1,
|
||||
lineColor: 'rgba(0,0,0,0.22)',
|
||||
|
|
|
@ -10,11 +10,23 @@ declare module 'chart.js' {
|
|||
interface PluginOptionsByType<TType extends ChartType> {
|
||||
hoverScatter?: ChartHoverScatterPluginOptions | false;
|
||||
}
|
||||
|
||||
interface Chart {
|
||||
$pluginHoverScatterManager: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const ChartHoverScatterPlugin: Plugin<ChartType, ChartHoverScatterPluginOptions> = {
|
||||
id: 'tooltipHoverScatter',
|
||||
|
||||
afterInit: (chart) => {
|
||||
//@ts-ignore
|
||||
const chartType = chart.config.type as ChartType;
|
||||
chart.$pluginHoverScatterManager = {
|
||||
enabled: chartType === 'scatter' || chartType === 'bubble'
|
||||
};
|
||||
},
|
||||
defaults: {
|
||||
color: 'rgba(0,0,0,0.6)',
|
||||
lineWidth: 0.65,
|
||||
|
@ -22,11 +34,9 @@ export const ChartHoverScatterPlugin: Plugin<ChartType, ChartHoverScatterPluginO
|
|||
},
|
||||
|
||||
beforeDraw: (chart, args, options) => {
|
||||
const { ctx, chartArea } = chart;
|
||||
if (!chart.$pluginHoverScatterManager.enabled) return;
|
||||
|
||||
// Only show crosshair for scatter and bubble charts
|
||||
const type = (chart.config as any).type as ChartType;
|
||||
if (type !== 'scatter' && type !== 'bubble') return;
|
||||
const { ctx, chartArea } = chart;
|
||||
|
||||
// Get mouse position from chart
|
||||
const activeElements = chart.getActiveElements();
|
||||
|
|
|
@ -29,6 +29,8 @@ export const ChartTotalizerPlugin: Plugin<ChartType, ChartTotalizerPluginOptions
|
|||
beforeUpdate: (_chart, args, options) => {
|
||||
if (options?.enabled === false) return;
|
||||
|
||||
console.log('here');
|
||||
|
||||
const chart = _chart as TotalizerChart;
|
||||
const stackTotals: Record<string, number> = {};
|
||||
const seriesTotals: number[] = [];
|
||||
|
|
|
@ -29,7 +29,9 @@ export const getLegendItems = ({
|
|||
//@ts-ignore
|
||||
const globalType: ChartType = (chartRef.current?.config.type as 'pie') || ChartType.Bar;
|
||||
const isPieChart = globalType === ChartType.Pie;
|
||||
const data = chartRef.current?.data!;
|
||||
const data = chartRef.current?.data;
|
||||
|
||||
if (!data) return [];
|
||||
|
||||
if (isPieChart) {
|
||||
const labels: string[] = data.labels as string[];
|
||||
|
|
|
@ -13,9 +13,10 @@ import { DeepPartial } from 'utility-types';
|
|||
import type { ScaleChartOptions, Scale, GridLineOptions } from 'chart.js';
|
||||
import { useXAxisTitle } from '../../../commonHelpers/useXAxisTitle';
|
||||
import { useIsStacked } from './useIsStacked';
|
||||
import { formatLabel, isNumericColumnType } from '@/lib';
|
||||
import { formatLabel, isNumericColumnType, truncateText } from '@/lib';
|
||||
import isDate from 'lodash/isDate';
|
||||
import { Chart as ChartJS } from 'chart.js';
|
||||
import { truncate } from 'lodash';
|
||||
|
||||
const DEFAULT_X_AXIS_TICK_CALLBACK = ChartJS.defaults.scales.category.ticks.callback;
|
||||
|
||||
|
@ -88,7 +89,6 @@ export const useXAxis = ({
|
|||
|
||||
if (isComboChart && columnSettings) {
|
||||
const allYAxisKeys = [...selectedAxis.y, ...((selectedAxis as ComboChartAxis).y2 || [])];
|
||||
console.log(allYAxisKeys, columnSettings);
|
||||
const atLeastOneLineVisualization = allYAxisKeys.some(
|
||||
(y) =>
|
||||
columnSettings[y]?.columnVisualization === 'line' ||
|
||||
|
@ -134,7 +134,7 @@ export const useXAxis = ({
|
|||
const xKey = selectedAxis.x[0];
|
||||
const xColumnLabelFormat = xAxisColumnFormats[xKey];
|
||||
const res = formatLabel(rawValue, xColumnLabelFormat);
|
||||
return DEFAULT_X_AXIS_TICK_CALLBACK.call(this, res, index, this.getLabels() as any);
|
||||
return truncateText(res, 20);
|
||||
}
|
||||
|
||||
return DEFAULT_X_AXIS_TICK_CALLBACK.call(this, value, index, this.getLabels() as any);
|
||||
|
|
|
@ -6,7 +6,8 @@ import {
|
|||
getDefaultDateOptions,
|
||||
getDefaultDayOfWeekOptions,
|
||||
getDefaultMonthOptions,
|
||||
getDefaultQuarterOptions
|
||||
getDefaultQuarterOptions,
|
||||
NO_FORMATTING_ITEM
|
||||
} from './dateConfig';
|
||||
import first from 'lodash/last';
|
||||
import { formatDate, getNow } from '@/lib/date';
|
||||
|
@ -47,26 +48,31 @@ export const EditDateFormat: React.FC<{
|
|||
}, [dateFormat, defaultOptions, useAlternateFormats]);
|
||||
|
||||
const selectedOption = useMemo(() => {
|
||||
if (dateFormat === '') return NO_FORMATTING_ITEM;
|
||||
return selectOptions.find((option) => option.value === dateFormat) || first(selectOptions)!;
|
||||
}, [dateFormat, selectOptions]);
|
||||
|
||||
const onChange = useMemoizedFn((value: string) => {
|
||||
onUpdateColumnConfig({
|
||||
dateFormat: value as IColumnLabelFormat['dateFormat']
|
||||
});
|
||||
const onChange = useMemoizedFn((value: IColumnLabelFormat['dateFormat']) => {
|
||||
if (value === NO_FORMATTING_ITEM.value) {
|
||||
onUpdateColumnConfig({
|
||||
dateFormat: ''
|
||||
});
|
||||
} else {
|
||||
onUpdateColumnConfig({
|
||||
dateFormat: value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<LabelAndInput label="Date format">
|
||||
<div className="w-full overflow-hidden">
|
||||
<Select
|
||||
key={convertNumberTo}
|
||||
className="w-full!"
|
||||
items={selectOptions}
|
||||
value={selectedOption.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
key={convertNumberTo}
|
||||
className="w-full!"
|
||||
items={selectOptions}
|
||||
value={selectedOption.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</LabelAndInput>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ import isEmpty from 'lodash/isEmpty';
|
|||
import { useGetCurrencies } from '@/api/buster_rest/nextjs/currency';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
import { ErrorBoundary } from '@/components/ui/error';
|
||||
|
||||
export const SelectAxisDropdownContent: React.FC<{
|
||||
columnSetting: IBusterMetricChartConfig['columnSettings'][string];
|
||||
|
@ -427,11 +428,13 @@ const LabelSettings: React.FC<{
|
|||
if (ComponentsLoop.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className={`${className} flex w-full flex-col space-y-3 overflow-hidden p-3`}>
|
||||
{ComponentsLoop.map(({ key, Component }) => {
|
||||
return <React.Fragment key={key}>{Component}</React.Fragment>;
|
||||
})}
|
||||
</div>
|
||||
<ErrorBoundary>
|
||||
<div className={`${className} flex w-full flex-col space-y-3 overflow-hidden p-3`}>
|
||||
{ComponentsLoop.map(({ key, Component }) => {
|
||||
return <React.Fragment key={key}>{Component}</React.Fragment>;
|
||||
})}
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import { formatDate } from '@/lib';
|
||||
|
||||
const NO_FORMATTING_ID = 'NO_FORMATTING_👻';
|
||||
export const NO_FORMATTING_ITEM = {
|
||||
label: 'No Formatting',
|
||||
value: NO_FORMATTING_ID
|
||||
};
|
||||
|
||||
export const getDefaultDateOptions = (now: Date) => {
|
||||
return [
|
||||
{
|
||||
label: 'Auto Format',
|
||||
value: 'auto'
|
||||
},
|
||||
{
|
||||
label: 'No Formatting',
|
||||
value: ''
|
||||
},
|
||||
NO_FORMATTING_ITEM,
|
||||
{
|
||||
label: formatDate({
|
||||
date: now,
|
||||
|
|
|
@ -43,7 +43,7 @@ const VerticalBarContainer: React.FC<{
|
|||
}> = React.memo(({ showBar, isCompletedStream, status }) => {
|
||||
return (
|
||||
<div className="ml-2 flex w-5 min-w-5 flex-col items-center pt-0.5">
|
||||
<StatusIndicator status={'loading'} />
|
||||
<StatusIndicator status={status} />
|
||||
<VerticalBar show={showBar} isCompletedStream={isCompletedStream} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -81,6 +81,6 @@ export const calculateTextWidth = (text: string, font: string): number => {
|
|||
|
||||
export const truncateText = (text: string, characters: number) => {
|
||||
if (text.length <= characters) return text;
|
||||
const truncatedText = text.slice(0, characters) + '...';
|
||||
const truncatedText = (String(text || '') || '').slice(0, characters) + '...';
|
||||
return truncatedText;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue