mirror of https://github.com/buster-so/buster.git
update trendline
This commit is contained in:
parent
38ea7378d3
commit
5cf34201b4
|
@ -548,6 +548,27 @@ pub struct Trendline {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(alias = "trend_line_color")]
|
#[serde(alias = "trend_line_color")]
|
||||||
pub trend_line_color: Option<String>,
|
pub trend_line_color: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "trendline_label_position_offset")]
|
||||||
|
pub trendline_label_position_offset: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "projection")]
|
||||||
|
pub projection: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "line_style")]
|
||||||
|
pub line_style: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "offset")]
|
||||||
|
pub offset: Option<i32>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "polynomial_order")]
|
||||||
|
pub polynomial_order: Option<i32>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "aggregate_all_categories")]
|
||||||
|
pub aggregate_all_categories: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(alias = "id")]
|
||||||
|
pub id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
@ -705,7 +726,7 @@ pub enum MetricValueAggregate {
|
||||||
Count,
|
Count,
|
||||||
Max,
|
Max,
|
||||||
Min,
|
Min,
|
||||||
First
|
First,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
|
|
@ -22,10 +22,10 @@ export interface Trendline {
|
||||||
| 'median'; //default is linear trend
|
| 'median'; //default is linear trend
|
||||||
trendLineColor?: string | null | 'inherit'; //OPTIONAL: default is #000000, inherit will inherit the color from the line/bar
|
trendLineColor?: string | null | 'inherit'; //OPTIONAL: default is #000000, inherit will inherit the color from the line/bar
|
||||||
columnId: string;
|
columnId: string;
|
||||||
trendlineLabelPositionOffset?: number; //OPTIONAL: default is 0.85. Goes from 0 to 1.
|
trendlineLabelPositionOffset?: number; //OPTIONAL: default is 0.85. Goes from 0 to 1. This is where the label will be placed on the trendline.
|
||||||
projection?: boolean; //OPTIONAL: default is false. if true, the trendline will be projected to the end of the chart.
|
projection?: boolean; //OPTIONAL: default is false. if true, the trendline will be projected to the end of the chart.
|
||||||
lineStyle?: 'solid' | 'dotted' | 'dashed' | 'dashdot';
|
lineStyle?: 'solid' | 'dotted' | 'dashed' | 'dashdot';
|
||||||
offset?: number; //OPTIONAL: default is -15. if true, the trendline will be projected to the end of the chart.
|
offset?: number; //OPTIONAL: default is 0. if true, the label will be offset vertically from the trendline.
|
||||||
polynomialOrder?: number;
|
polynomialOrder?: number;
|
||||||
aggregateAllCategories?: boolean; //OPTIONAL: default is true. if true, the trendline will be calculated for all categories. if false, the trendline will be calculated for the category specified in the columnId.
|
aggregateAllCategories?: boolean; //OPTIONAL: default is true. if true, the trendline will be calculated for all categories. if false, the trendline will be calculated for the category specified in the columnId.
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|
|
@ -20,6 +20,7 @@ interface ColorPickerProps {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
showInput?: boolean;
|
showInput?: boolean;
|
||||||
showPicker?: boolean;
|
showPicker?: boolean;
|
||||||
|
pickerBackgroundImage?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorPickerWrapperVariants = cva('border p-0.5 rounded cursor-pointer shadow', {
|
const colorPickerWrapperVariants = cva('border p-0.5 rounded cursor-pointer shadow', {
|
||||||
|
@ -47,6 +48,7 @@ const ColorPicker = ({
|
||||||
children,
|
children,
|
||||||
showInput = true,
|
showInput = true,
|
||||||
showPicker = true,
|
showPicker = true,
|
||||||
|
pickerBackgroundImage,
|
||||||
...props
|
...props
|
||||||
}: ColorPickerProps) => {
|
}: ColorPickerProps) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
@ -89,7 +91,12 @@ const ColorPicker = ({
|
||||||
<PopoverRoot onOpenChange={setOpen} open={open}>
|
<PopoverRoot onOpenChange={setOpen} open={open}>
|
||||||
<PopoverTrigger asChild disabled={disabled}>
|
<PopoverTrigger asChild disabled={disabled}>
|
||||||
<div>
|
<div>
|
||||||
<ColorPickerInputBox parsedValue={parsedValue} size={size} disabled={disabled} />
|
<ColorPickerInputBox
|
||||||
|
parsedValue={parsedValue}
|
||||||
|
size={size}
|
||||||
|
disabled={disabled}
|
||||||
|
pickerBackgroundImage={pickerBackgroundImage}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-full" align="end" side="bottom">
|
<PopoverContent className="w-full" align="end" side="bottom">
|
||||||
|
@ -116,16 +123,19 @@ ColorPicker.displayName = 'ColorPicker';
|
||||||
const ColorPickerInputBox = ({
|
const ColorPickerInputBox = ({
|
||||||
parsedValue,
|
parsedValue,
|
||||||
size,
|
size,
|
||||||
disabled
|
disabled,
|
||||||
|
pickerBackgroundImage
|
||||||
}: {
|
}: {
|
||||||
parsedValue: string;
|
parsedValue: string;
|
||||||
size: 'default' | 'small' | 'tall';
|
size: 'default' | 'small' | 'tall';
|
||||||
disabled: boolean | undefined;
|
disabled: boolean | undefined;
|
||||||
|
pickerBackgroundImage: string | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
const backgroundStyle =
|
const backgroundStyle =
|
||||||
parsedValue === 'inherit'
|
parsedValue === 'inherit' || pickerBackgroundImage
|
||||||
? {
|
? {
|
||||||
backgroundImage:
|
backgroundImage:
|
||||||
|
pickerBackgroundImage ||
|
||||||
'linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)'
|
'linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)'
|
||||||
}
|
}
|
||||||
: { backgroundColor: parsedValue };
|
: { backgroundColor: parsedValue };
|
||||||
|
|
|
@ -177,6 +177,7 @@ export const MetricStylingApp: React.FC<{
|
||||||
barShowTotalAtTop={barShowTotalAtTop}
|
barShowTotalAtTop={barShowTotalAtTop}
|
||||||
rowCount={rowCount}
|
rowCount={rowCount}
|
||||||
pieSortBy={pieSortBy}
|
pieSortBy={pieSortBy}
|
||||||
|
colors={colors}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ import { TypeToLabel } from './config';
|
||||||
import { JOIN_CHARACTER } from '@/components/ui/charts/commonHelpers';
|
import { JOIN_CHARACTER } from '@/components/ui/charts/commonHelpers';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
import { TrendlineLabelPositionOffset } from './TrendlineLabelPositionOffset';
|
import { TrendlineLabelPositionOffset } from './TrendlineLabelPositionOffset';
|
||||||
import { TrendlineProjection } from './TrendlineProjection';
|
|
||||||
import { TrendlineLineStyle } from './TrendlineLineStyle';
|
import { TrendlineLineStyle } from './TrendlineLineStyle';
|
||||||
import { TrendlineOffset } from './TrendlineOffset';
|
import { TrendlineOffset } from './TrendlineOffset';
|
||||||
import { TrendlinePolynomialOrder } from './TrendlinePolynomialOrder';
|
|
||||||
import { TrendlineAggregateAllCategories } from './TrendlineAggregateAllCategories';
|
import { TrendlineAggregateAllCategories } from './TrendlineAggregateAllCategories';
|
||||||
|
// import { TrendlineProjection } from './TrendlineProjection';
|
||||||
|
// import { TrendlinePolynomialOrder } from './TrendlinePolynomialOrder';
|
||||||
|
|
||||||
export interface LoopTrendline extends Trendline {
|
export interface LoopTrendline extends Trendline {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -32,6 +32,7 @@ export interface LoopTrendline extends Trendline {
|
||||||
|
|
||||||
export const EditTrendline: React.FC<{
|
export const EditTrendline: React.FC<{
|
||||||
trendlines: IBusterMetricChartConfig['trendlines'];
|
trendlines: IBusterMetricChartConfig['trendlines'];
|
||||||
|
colors: string[];
|
||||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||||
selectedAxis: ChartEncodes;
|
selectedAxis: ChartEncodes;
|
||||||
columnMetadata: ColumnMetaData[];
|
columnMetadata: ColumnMetaData[];
|
||||||
|
@ -40,6 +41,7 @@ export const EditTrendline: React.FC<{
|
||||||
}> = React.memo(
|
}> = React.memo(
|
||||||
({
|
({
|
||||||
trendlines,
|
trendlines,
|
||||||
|
colors,
|
||||||
onUpdateChartConfig,
|
onUpdateChartConfig,
|
||||||
selectedAxis,
|
selectedAxis,
|
||||||
columnMetadata,
|
columnMetadata,
|
||||||
|
@ -175,6 +177,7 @@ export const EditTrendline: React.FC<{
|
||||||
onDeleteTrendline={onDeleteTrendline}
|
onDeleteTrendline={onDeleteTrendline}
|
||||||
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
||||||
isNewTrend={newTrendIds.has(trend.id)}
|
isNewTrend={newTrendIds.has(trend.id)}
|
||||||
|
colors={colors}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
|
@ -193,6 +196,7 @@ const EditTrendlineItem: React.FC<{
|
||||||
yAxisEncodes: string[];
|
yAxisEncodes: string[];
|
||||||
xAxisEncodes: string[];
|
xAxisEncodes: string[];
|
||||||
categoryEncodes: string[] | undefined;
|
categoryEncodes: string[] | undefined;
|
||||||
|
colors: string[];
|
||||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||||
onUpdateExisitingTrendline: (trend: LoopTrendline) => void;
|
onUpdateExisitingTrendline: (trend: LoopTrendline) => void;
|
||||||
onDeleteTrendline: (id: string) => void;
|
onDeleteTrendline: (id: string) => void;
|
||||||
|
@ -205,6 +209,7 @@ const EditTrendlineItem: React.FC<{
|
||||||
yAxisEncodes,
|
yAxisEncodes,
|
||||||
xAxisEncodes,
|
xAxisEncodes,
|
||||||
categoryEncodes,
|
categoryEncodes,
|
||||||
|
colors,
|
||||||
selectedChartType,
|
selectedChartType,
|
||||||
onUpdateExisitingTrendline,
|
onUpdateExisitingTrendline,
|
||||||
onDeleteTrendline
|
onDeleteTrendline
|
||||||
|
@ -234,6 +239,7 @@ const EditTrendlineItem: React.FC<{
|
||||||
columnLabelFormats={columnLabelFormats}
|
columnLabelFormats={columnLabelFormats}
|
||||||
yAxisEncodes={yAxisEncodes}
|
yAxisEncodes={yAxisEncodes}
|
||||||
xAxisEncodes={xAxisEncodes}
|
xAxisEncodes={xAxisEncodes}
|
||||||
|
colors={colors}
|
||||||
categoryEncodes={categoryEncodes}
|
categoryEncodes={categoryEncodes}
|
||||||
selectedChartType={selectedChartType}
|
selectedChartType={selectedChartType}
|
||||||
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
||||||
|
@ -249,6 +255,7 @@ const TrendlineItemContent: React.FC<{
|
||||||
columnMetadata: ColumnMetaData[];
|
columnMetadata: ColumnMetaData[];
|
||||||
yAxisEncodes: string[];
|
yAxisEncodes: string[];
|
||||||
xAxisEncodes: string[];
|
xAxisEncodes: string[];
|
||||||
|
colors: string[];
|
||||||
categoryEncodes: string[] | undefined;
|
categoryEncodes: string[] | undefined;
|
||||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||||
|
@ -256,6 +263,7 @@ const TrendlineItemContent: React.FC<{
|
||||||
}> = React.memo(
|
}> = React.memo(
|
||||||
({
|
({
|
||||||
trend,
|
trend,
|
||||||
|
colors,
|
||||||
categoryEncodes,
|
categoryEncodes,
|
||||||
yAxisEncodes,
|
yAxisEncodes,
|
||||||
xAxisEncodes,
|
xAxisEncodes,
|
||||||
|
@ -316,6 +324,7 @@ const TrendlineItemContent: React.FC<{
|
||||||
|
|
||||||
<TrendlineColorPicker
|
<TrendlineColorPicker
|
||||||
trend={trend}
|
trend={trend}
|
||||||
|
colors={colors}
|
||||||
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorPicker } from '@/components/ui/color-picker';
|
import { ColorPicker } from '@/components/ui/color-picker';
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { LabelAndInput } from '../../Common';
|
import { LabelAndInput } from '../../Common';
|
||||||
import { LoopTrendline } from './EditTrendline';
|
import { LoopTrendline } from './EditTrendline';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
|
@ -8,10 +8,12 @@ import { Switch } from '@/components/ui/switch';
|
||||||
export const TrendlineColorPicker = React.memo(
|
export const TrendlineColorPicker = React.memo(
|
||||||
({
|
({
|
||||||
trend,
|
trend,
|
||||||
|
colors,
|
||||||
onUpdateExisitingTrendline
|
onUpdateExisitingTrendline
|
||||||
}: {
|
}: {
|
||||||
trend: LoopTrendline;
|
trend: LoopTrendline;
|
||||||
onUpdateExisitingTrendline: (trend: LoopTrendline) => void;
|
onUpdateExisitingTrendline: (trend: LoopTrendline) => void;
|
||||||
|
colors: string[];
|
||||||
}) => {
|
}) => {
|
||||||
const onChangeComplete = useMemoizedFn((color: string) => {
|
const onChangeComplete = useMemoizedFn((color: string) => {
|
||||||
const hexColor = color;
|
const hexColor = color;
|
||||||
|
@ -24,6 +26,16 @@ export const TrendlineColorPicker = React.memo(
|
||||||
|
|
||||||
const isInheritColor = trend.trendLineColor === 'inherit';
|
const isInheritColor = trend.trendLineColor === 'inherit';
|
||||||
|
|
||||||
|
const pickerBackgroundImage = useMemo(() => {
|
||||||
|
if (isInheritColor) {
|
||||||
|
const colorsToUse = colors.slice(0, 4);
|
||||||
|
return `repeating-linear-gradient(90deg, ${colorsToUse
|
||||||
|
.map((color, index) => `${color} ${index * 25}%, ${color} ${(index + 1) * 25}%`)
|
||||||
|
.join(', ')})`;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [colors, isInheritColor]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LabelAndInput label="Color">
|
<LabelAndInput label="Color">
|
||||||
<div className="flex w-full items-center justify-end">
|
<div className="flex w-full items-center justify-end">
|
||||||
|
@ -31,6 +43,7 @@ export const TrendlineColorPicker = React.memo(
|
||||||
size="small"
|
size="small"
|
||||||
showInput={!isInheritColor}
|
showInput={!isInheritColor}
|
||||||
showPicker={!isInheritColor}
|
showPicker={!isInheritColor}
|
||||||
|
pickerBackgroundImage={pickerBackgroundImage}
|
||||||
value={trend.trendLineColor || '#000000'}
|
value={trend.trendLineColor || '#000000'}
|
||||||
onChangeComplete={onChangeComplete}>
|
onChangeComplete={onChangeComplete}>
|
||||||
<LabelAndInput label="Inherit color">
|
<LabelAndInput label="Inherit color">
|
||||||
|
|
|
@ -72,7 +72,8 @@ export const StylingAppStyling: React.FC<
|
||||||
barShowTotalAtTop,
|
barShowTotalAtTop,
|
||||||
yAxisShowAxisTitle,
|
yAxisShowAxisTitle,
|
||||||
rowCount,
|
rowCount,
|
||||||
pieSortBy
|
pieSortBy,
|
||||||
|
colors
|
||||||
}) => {
|
}) => {
|
||||||
const { onUpdateMetricChartConfig } = useUpdateMetricChart();
|
const { onUpdateMetricChartConfig } = useUpdateMetricChart();
|
||||||
|
|
||||||
|
@ -175,6 +176,7 @@ export const StylingAppStyling: React.FC<
|
||||||
lineGroupType={lineGroupType}
|
lineGroupType={lineGroupType}
|
||||||
barGroupType={barGroupType}
|
barGroupType={barGroupType}
|
||||||
onUpdateChartConfig={onUpdateChartConfig}
|
onUpdateChartConfig={onUpdateChartConfig}
|
||||||
|
colors={colors}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -477,7 +479,8 @@ const EtcSettings: React.FC<
|
||||||
columnMetadata,
|
columnMetadata,
|
||||||
columnLabelFormats,
|
columnLabelFormats,
|
||||||
lineGroupType,
|
lineGroupType,
|
||||||
barGroupType
|
barGroupType,
|
||||||
|
colors
|
||||||
}) => {
|
}) => {
|
||||||
const isScatterChart = selectedChartType === 'scatter';
|
const isScatterChart = selectedChartType === 'scatter';
|
||||||
const isPieChart = selectedChartType === 'pie';
|
const isPieChart = selectedChartType === 'pie';
|
||||||
|
@ -546,6 +549,7 @@ const EtcSettings: React.FC<
|
||||||
columnMetadata={columnMetadata}
|
columnMetadata={columnMetadata}
|
||||||
selectedChartType={selectedChartType}
|
selectedChartType={selectedChartType}
|
||||||
onUpdateChartConfig={onUpdateChartConfig}
|
onUpdateChartConfig={onUpdateChartConfig}
|
||||||
|
colors={colors}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue