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(alias = "trend_line_color")]
|
||||
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)]
|
||||
|
@ -705,7 +726,7 @@ pub enum MetricValueAggregate {
|
|||
Count,
|
||||
Max,
|
||||
Min,
|
||||
First
|
||||
First,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
|
|
@ -22,10 +22,10 @@ export interface Trendline {
|
|||
| 'median'; //default is linear trend
|
||||
trendLineColor?: string | null | 'inherit'; //OPTIONAL: default is #000000, inherit will inherit the color from the line/bar
|
||||
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.
|
||||
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;
|
||||
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;
|
||||
|
|
|
@ -20,6 +20,7 @@ interface ColorPickerProps {
|
|||
children?: React.ReactNode;
|
||||
showInput?: boolean;
|
||||
showPicker?: boolean;
|
||||
pickerBackgroundImage?: string;
|
||||
}
|
||||
|
||||
const colorPickerWrapperVariants = cva('border p-0.5 rounded cursor-pointer shadow', {
|
||||
|
@ -47,6 +48,7 @@ const ColorPicker = ({
|
|||
children,
|
||||
showInput = true,
|
||||
showPicker = true,
|
||||
pickerBackgroundImage,
|
||||
...props
|
||||
}: ColorPickerProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
@ -89,7 +91,12 @@ const ColorPicker = ({
|
|||
<PopoverRoot onOpenChange={setOpen} open={open}>
|
||||
<PopoverTrigger asChild disabled={disabled}>
|
||||
<div>
|
||||
<ColorPickerInputBox parsedValue={parsedValue} size={size} disabled={disabled} />
|
||||
<ColorPickerInputBox
|
||||
parsedValue={parsedValue}
|
||||
size={size}
|
||||
disabled={disabled}
|
||||
pickerBackgroundImage={pickerBackgroundImage}
|
||||
/>
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full" align="end" side="bottom">
|
||||
|
@ -116,16 +123,19 @@ ColorPicker.displayName = 'ColorPicker';
|
|||
const ColorPickerInputBox = ({
|
||||
parsedValue,
|
||||
size,
|
||||
disabled
|
||||
disabled,
|
||||
pickerBackgroundImage
|
||||
}: {
|
||||
parsedValue: string;
|
||||
size: 'default' | 'small' | 'tall';
|
||||
disabled: boolean | undefined;
|
||||
pickerBackgroundImage: string | undefined;
|
||||
}) => {
|
||||
const backgroundStyle =
|
||||
parsedValue === 'inherit'
|
||||
parsedValue === 'inherit' || pickerBackgroundImage
|
||||
? {
|
||||
backgroundImage:
|
||||
pickerBackgroundImage ||
|
||||
'linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)'
|
||||
}
|
||||
: { backgroundColor: parsedValue };
|
||||
|
|
|
@ -177,6 +177,7 @@ export const MetricStylingApp: React.FC<{
|
|||
barShowTotalAtTop={barShowTotalAtTop}
|
||||
rowCount={rowCount}
|
||||
pieSortBy={pieSortBy}
|
||||
colors={colors}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ import { TypeToLabel } from './config';
|
|||
import { JOIN_CHARACTER } from '@/components/ui/charts/commonHelpers';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { TrendlineLabelPositionOffset } from './TrendlineLabelPositionOffset';
|
||||
import { TrendlineProjection } from './TrendlineProjection';
|
||||
import { TrendlineLineStyle } from './TrendlineLineStyle';
|
||||
import { TrendlineOffset } from './TrendlineOffset';
|
||||
import { TrendlinePolynomialOrder } from './TrendlinePolynomialOrder';
|
||||
import { TrendlineAggregateAllCategories } from './TrendlineAggregateAllCategories';
|
||||
// import { TrendlineProjection } from './TrendlineProjection';
|
||||
// import { TrendlinePolynomialOrder } from './TrendlinePolynomialOrder';
|
||||
|
||||
export interface LoopTrendline extends Trendline {
|
||||
id: string;
|
||||
|
@ -32,6 +32,7 @@ export interface LoopTrendline extends Trendline {
|
|||
|
||||
export const EditTrendline: React.FC<{
|
||||
trendlines: IBusterMetricChartConfig['trendlines'];
|
||||
colors: string[];
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
selectedAxis: ChartEncodes;
|
||||
columnMetadata: ColumnMetaData[];
|
||||
|
@ -40,6 +41,7 @@ export const EditTrendline: React.FC<{
|
|||
}> = React.memo(
|
||||
({
|
||||
trendlines,
|
||||
colors,
|
||||
onUpdateChartConfig,
|
||||
selectedAxis,
|
||||
columnMetadata,
|
||||
|
@ -175,6 +177,7 @@ export const EditTrendline: React.FC<{
|
|||
onDeleteTrendline={onDeleteTrendline}
|
||||
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
||||
isNewTrend={newTrendIds.has(trend.id)}
|
||||
colors={colors}
|
||||
/>
|
||||
</motion.div>
|
||||
))}
|
||||
|
@ -193,6 +196,7 @@ const EditTrendlineItem: React.FC<{
|
|||
yAxisEncodes: string[];
|
||||
xAxisEncodes: string[];
|
||||
categoryEncodes: string[] | undefined;
|
||||
colors: string[];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
onUpdateExisitingTrendline: (trend: LoopTrendline) => void;
|
||||
onDeleteTrendline: (id: string) => void;
|
||||
|
@ -205,6 +209,7 @@ const EditTrendlineItem: React.FC<{
|
|||
yAxisEncodes,
|
||||
xAxisEncodes,
|
||||
categoryEncodes,
|
||||
colors,
|
||||
selectedChartType,
|
||||
onUpdateExisitingTrendline,
|
||||
onDeleteTrendline
|
||||
|
@ -234,6 +239,7 @@ const EditTrendlineItem: React.FC<{
|
|||
columnLabelFormats={columnLabelFormats}
|
||||
yAxisEncodes={yAxisEncodes}
|
||||
xAxisEncodes={xAxisEncodes}
|
||||
colors={colors}
|
||||
categoryEncodes={categoryEncodes}
|
||||
selectedChartType={selectedChartType}
|
||||
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
||||
|
@ -249,6 +255,7 @@ const TrendlineItemContent: React.FC<{
|
|||
columnMetadata: ColumnMetaData[];
|
||||
yAxisEncodes: string[];
|
||||
xAxisEncodes: string[];
|
||||
colors: string[];
|
||||
categoryEncodes: string[] | undefined;
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
|
@ -256,6 +263,7 @@ const TrendlineItemContent: React.FC<{
|
|||
}> = React.memo(
|
||||
({
|
||||
trend,
|
||||
colors,
|
||||
categoryEncodes,
|
||||
yAxisEncodes,
|
||||
xAxisEncodes,
|
||||
|
@ -316,6 +324,7 @@ const TrendlineItemContent: React.FC<{
|
|||
|
||||
<TrendlineColorPicker
|
||||
trend={trend}
|
||||
colors={colors}
|
||||
onUpdateExisitingTrendline={onUpdateExisitingTrendline}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ColorPicker } from '@/components/ui/color-picker';
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { LabelAndInput } from '../../Common';
|
||||
import { LoopTrendline } from './EditTrendline';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
|
@ -8,10 +8,12 @@ import { Switch } from '@/components/ui/switch';
|
|||
export const TrendlineColorPicker = React.memo(
|
||||
({
|
||||
trend,
|
||||
colors,
|
||||
onUpdateExisitingTrendline
|
||||
}: {
|
||||
trend: LoopTrendline;
|
||||
onUpdateExisitingTrendline: (trend: LoopTrendline) => void;
|
||||
colors: string[];
|
||||
}) => {
|
||||
const onChangeComplete = useMemoizedFn((color: string) => {
|
||||
const hexColor = color;
|
||||
|
@ -24,6 +26,16 @@ export const TrendlineColorPicker = React.memo(
|
|||
|
||||
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 (
|
||||
<LabelAndInput label="Color">
|
||||
<div className="flex w-full items-center justify-end">
|
||||
|
@ -31,6 +43,7 @@ export const TrendlineColorPicker = React.memo(
|
|||
size="small"
|
||||
showInput={!isInheritColor}
|
||||
showPicker={!isInheritColor}
|
||||
pickerBackgroundImage={pickerBackgroundImage}
|
||||
value={trend.trendLineColor || '#000000'}
|
||||
onChangeComplete={onChangeComplete}>
|
||||
<LabelAndInput label="Inherit color">
|
||||
|
|
|
@ -72,7 +72,8 @@ export const StylingAppStyling: React.FC<
|
|||
barShowTotalAtTop,
|
||||
yAxisShowAxisTitle,
|
||||
rowCount,
|
||||
pieSortBy
|
||||
pieSortBy,
|
||||
colors
|
||||
}) => {
|
||||
const { onUpdateMetricChartConfig } = useUpdateMetricChart();
|
||||
|
||||
|
@ -175,6 +176,7 @@ export const StylingAppStyling: React.FC<
|
|||
lineGroupType={lineGroupType}
|
||||
barGroupType={barGroupType}
|
||||
onUpdateChartConfig={onUpdateChartConfig}
|
||||
colors={colors}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -477,7 +479,8 @@ const EtcSettings: React.FC<
|
|||
columnMetadata,
|
||||
columnLabelFormats,
|
||||
lineGroupType,
|
||||
barGroupType
|
||||
barGroupType,
|
||||
colors
|
||||
}) => {
|
||||
const isScatterChart = selectedChartType === 'scatter';
|
||||
const isPieChart = selectedChartType === 'pie';
|
||||
|
@ -546,6 +549,7 @@ const EtcSettings: React.FC<
|
|||
columnMetadata={columnMetadata}
|
||||
selectedChartType={selectedChartType}
|
||||
onUpdateChartConfig={onUpdateChartConfig}
|
||||
colors={colors}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue