mirror of https://github.com/buster-so/buster.git
trendline max and mins
This commit is contained in:
parent
e9a6c26415
commit
6f44c99e2d
|
@ -22,4 +22,5 @@ export interface Trendline {
|
|||
| 'median'; //default is linear trend
|
||||
trendLineColor?: string | null; //OPTIONAL: default is #000000
|
||||
columnId: string;
|
||||
id?: string;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ describe('useTrendlines', () => {
|
|||
trendlines: [] as TrendlineDataset[],
|
||||
columnLabelFormats: {} as Record<string, IColumnLabelFormat | undefined>,
|
||||
selectedChartType: 'line' as ChartType,
|
||||
lineGroupType: null
|
||||
lineGroupType: null,
|
||||
barGroupType: null
|
||||
};
|
||||
|
||||
it('returns the expected structure', () => {
|
||||
|
@ -153,6 +154,7 @@ describe('useTrendlines', () => {
|
|||
const columnId = 'col1';
|
||||
const props = {
|
||||
...defaultProps,
|
||||
|
||||
trendlines: [
|
||||
mockTrendlineDataset({
|
||||
id: 'test-linear-slope',
|
||||
|
|
|
@ -282,14 +282,14 @@ export const trendlineDatasetCreator: Record<
|
|||
},
|
||||
|
||||
average: (trendline, datasetsWithTicks) => {
|
||||
const datasets = datasetsWithTicks.datasets;
|
||||
const selectedDataset = datasets.find((dataset) => dataset.id === trendline.columnId);
|
||||
const { validData, ticks, xAxisColumn, selectedDatasets } = getValidDataAndTicks(
|
||||
datasetsWithTicks.datasets,
|
||||
trendline
|
||||
);
|
||||
|
||||
if (!selectedDataset?.data || selectedDataset.data.length === 0) return [];
|
||||
|
||||
// Filter out null/undefined values
|
||||
const validData = selectedDataset.data.filter((value) => value !== null && value !== undefined);
|
||||
if (!selectedDatasets || selectedDatasets.length === 0 || validData.length === 0) return [];
|
||||
|
||||
// Sum all valid values and divide by the count
|
||||
if (validData.length === 0) return [];
|
||||
|
||||
// Sum all valid values and divide by the count
|
||||
|
@ -313,14 +313,12 @@ export const trendlineDatasetCreator: Record<
|
|||
},
|
||||
|
||||
min: (trendline, datasetsWithTicks) => {
|
||||
const datasets = datasetsWithTicks.datasets;
|
||||
const selectedDataset = datasets.find((dataset) => dataset.id === trendline.columnId);
|
||||
const { validData, ticks, xAxisColumn, selectedDatasets } = getValidDataAndTicks(
|
||||
datasetsWithTicks.datasets,
|
||||
trendline
|
||||
);
|
||||
|
||||
if (!selectedDataset?.data || selectedDataset.data.length === 0) return [];
|
||||
|
||||
// Filter out null/undefined values
|
||||
const validData = selectedDataset.data.filter((value) => value !== null && value !== undefined);
|
||||
if (validData.length === 0) return [];
|
||||
if (!selectedDatasets || selectedDatasets.length === 0 || validData.length === 0) return [];
|
||||
|
||||
// Use the first valid value as initial accumulator
|
||||
const min = validData.reduce<number>((acc, datapoint) => {
|
||||
|
@ -341,14 +339,12 @@ export const trendlineDatasetCreator: Record<
|
|||
},
|
||||
|
||||
max: (trendline, datasetsWithTicks) => {
|
||||
const datasets = datasetsWithTicks.datasets;
|
||||
const selectedDataset = datasets.find((dataset) => dataset.id === trendline.columnId);
|
||||
const { validData, ticks, xAxisColumn, selectedDatasets } = getValidDataAndTicks(
|
||||
datasetsWithTicks.datasets,
|
||||
trendline
|
||||
);
|
||||
|
||||
if (!selectedDataset?.data || selectedDataset.data.length === 0) return [];
|
||||
|
||||
// Filter out null/undefined values
|
||||
const validData = selectedDataset.data.filter((value) => value !== null && value !== undefined);
|
||||
if (validData.length === 0) return [];
|
||||
if (!selectedDatasets || selectedDatasets.length === 0 || validData.length === 0) return [];
|
||||
|
||||
// Use the first valid value as initial accumulator
|
||||
const max = validData.reduce<number>((acc, datapoint) => {
|
||||
|
@ -369,15 +365,15 @@ export const trendlineDatasetCreator: Record<
|
|||
},
|
||||
|
||||
median: (trendline, datasetsWithTicks) => {
|
||||
const datasets = datasetsWithTicks.datasets;
|
||||
const selectedDataset = datasets.find((dataset) => dataset.id === trendline.columnId);
|
||||
const { validData, ticks, xAxisColumn, selectedDatasets } = getValidDataAndTicks(
|
||||
datasetsWithTicks.datasets,
|
||||
trendline
|
||||
);
|
||||
|
||||
if (!selectedDataset?.data || selectedDataset.data.length === 0) return [];
|
||||
if (!selectedDatasets || selectedDatasets.length === 0 || validData.length === 0) return [];
|
||||
|
||||
// Sort the data and get the middle value
|
||||
const sortedData = [...selectedDataset.data]
|
||||
.filter((value) => value !== null && value !== undefined)
|
||||
.sort((a, b) => (a as number) - (b as number));
|
||||
const sortedData = [...validData].sort((a, b) => (a as number) - (b as number));
|
||||
|
||||
let median: number;
|
||||
const midIndex = Math.floor(sortedData.length / 2);
|
||||
|
|
|
@ -42,8 +42,9 @@ export const useDataTrendlineOptions = ({
|
|||
!hasTrendlines ||
|
||||
!datasetOptions ||
|
||||
!datasetOptions.datasets.length
|
||||
)
|
||||
) {
|
||||
return [] as TrendlineDataset[];
|
||||
}
|
||||
|
||||
const trendlineDatasets: TrendlineDataset[] = [];
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import { EditTrendlineShowLine } from './EditTrendlineShowLine';
|
|||
import { EditTrendlineOption } from './EditTrendlineOption';
|
||||
import { TypeToLabel } from './config';
|
||||
import { JOIN_CHARACTER } from '@/components/ui/charts/commonHelpers';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
export interface LoopTrendline extends Trendline {
|
||||
id: string;
|
||||
|
@ -40,7 +41,7 @@ export const EditTrendline: React.FC<{
|
|||
selectedChartType
|
||||
}) => {
|
||||
const [trends, _setTrends] = useState<LoopTrendline[]>(
|
||||
trendlines.map((trend) => ({ ...trend, id: uuidv4() }))
|
||||
trendlines.map((trend) => ({ ...trend, id: trend.id || uuidv4() }))
|
||||
);
|
||||
const [newTrendIds, { add: addNewTrendId }] = useSet<string>();
|
||||
|
||||
|
@ -60,13 +61,30 @@ export const EditTrendline: React.FC<{
|
|||
}, []);
|
||||
|
||||
const onAddTrendline = useMemoizedFn(() => {
|
||||
const getNewType = () => {
|
||||
const types = [
|
||||
'linear_regression',
|
||||
'polynomial_regression',
|
||||
'exponential_regression',
|
||||
'logarithmic_regression',
|
||||
'average',
|
||||
'min',
|
||||
'max',
|
||||
'median'
|
||||
] as const;
|
||||
return types[Math.floor(Math.random() * types.length)];
|
||||
};
|
||||
|
||||
const hasLinearRegression = trends.some((trend) => trend.type === 'linear_regression');
|
||||
const type = hasLinearRegression ? getNewType() : ('linear_regression' as const);
|
||||
|
||||
const newTrendline: Required<LoopTrendline> = {
|
||||
id: uuidv4(),
|
||||
show: true,
|
||||
showTrendlineLabel: false,
|
||||
trendlineLabel: null,
|
||||
type: 'linear_regression',
|
||||
trendLineColor: null,
|
||||
type,
|
||||
trendLineColor: '#FF0000',
|
||||
columnId: selectedAxis.y[0] || ''
|
||||
};
|
||||
|
||||
|
@ -77,12 +95,8 @@ export const EditTrendline: React.FC<{
|
|||
});
|
||||
|
||||
const onUpdateTrendlines = useMemoizedFn((trends: LoopTrendline[]) => {
|
||||
const newTrends = trends.map(({ id, ...rest }) => ({
|
||||
...rest
|
||||
}));
|
||||
|
||||
setTimeout(() => {
|
||||
onUpdateChartConfig({ trendlines: newTrends });
|
||||
onUpdateChartConfig({ trendlines: trends });
|
||||
}, 30);
|
||||
});
|
||||
|
||||
|
@ -120,7 +134,13 @@ export const EditTrendline: React.FC<{
|
|||
};
|
||||
}, [trends]);
|
||||
|
||||
//TODO: fix the bug where we need to "reset" the trends when the reset button is clicked
|
||||
useEffect(() => {
|
||||
const updatedTrends = trendlines.map((trend) => ({ ...trend, id: trend.id || uuidv4() }));
|
||||
|
||||
if (!isEqual(updatedTrends, trends)) {
|
||||
_setTrends(updatedTrends);
|
||||
}
|
||||
}, [trendlines]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-2.5">
|
||||
|
|
Loading…
Reference in New Issue