mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PlotLegend: Memoize for better performance (#56123)
This commit is contained in:
parent
08ffcfdf16
commit
e819ed0f51
@ -9,8 +9,8 @@ export interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
|||||||
gradient?: string;
|
gradient?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SeriesIcon = React.forwardRef<HTMLDivElement, Props>(
|
export const SeriesIcon = React.memo(
|
||||||
({ color, className, gradient, ...restProps }, ref) => {
|
React.forwardRef<HTMLDivElement, Props>(({ color, className, gradient, ...restProps }, ref) => {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
let cssColor: string;
|
let cssColor: string;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export const SeriesIcon = React.forwardRef<HTMLDivElement, Props>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
return <div data-testid="series-icon" ref={ref} className={className} style={styles} {...restProps} />;
|
return <div data-testid="series-icon" ref={ref} className={className} style={styles} {...restProps} />;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
SeriesIcon.displayName = 'SeriesIcon';
|
SeriesIcon.displayName = 'SeriesIcon';
|
||||||
|
@ -110,4 +110,4 @@ export function VizLegend<T>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VizLegend.displayName = 'Legend';
|
VizLegend.displayName = 'VizLegend';
|
||||||
|
@ -15,7 +15,7 @@ interface Props {
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName, color, gradient, readonly }) => {
|
export const VizLegendSeriesIcon = React.memo(({ seriesName, color, gradient, readonly }: Props) => {
|
||||||
const { onSeriesColorChange } = usePanelContext();
|
const { onSeriesColorChange } = usePanelContext();
|
||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
(color: string) => {
|
(color: string) => {
|
||||||
@ -40,6 +40,6 @@ export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <SeriesIcon color={color} gradient={gradient} />;
|
return <SeriesIcon color={color} gradient={gradient} />;
|
||||||
};
|
});
|
||||||
|
|
||||||
VizLegendSeriesIcon.displayName = 'VizLegendSeriesIcon';
|
VizLegendSeriesIcon.displayName = 'VizLegendSeriesIcon';
|
||||||
|
@ -27,115 +27,110 @@ interface PlotLegendProps extends VizLegendOptions, Omit<VizLayoutLegendProps, '
|
|||||||
config: UPlotConfigBuilder;
|
config: UPlotConfigBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PlotLegend: React.FC<PlotLegendProps> = ({
|
export const PlotLegend: React.FC<PlotLegendProps> = React.memo(
|
||||||
data,
|
({ data, config, placement, calcs, displayMode, ...vizLayoutLegendProps }) => {
|
||||||
config,
|
const theme = useTheme2();
|
||||||
placement,
|
const legendItems = config
|
||||||
calcs,
|
.getSeries()
|
||||||
displayMode,
|
.map<VizLegendItem | undefined>((s) => {
|
||||||
...vizLayoutLegendProps
|
const seriesConfig = s.props;
|
||||||
}) => {
|
const fieldIndex = seriesConfig.dataFrameFieldIndex;
|
||||||
const theme = useTheme2();
|
const axisPlacement = config.getAxisPlacement(s.props.scaleKey);
|
||||||
const legendItems = config
|
|
||||||
.getSeries()
|
|
||||||
.map<VizLegendItem | undefined>((s) => {
|
|
||||||
const seriesConfig = s.props;
|
|
||||||
const fieldIndex = seriesConfig.dataFrameFieldIndex;
|
|
||||||
const axisPlacement = config.getAxisPlacement(s.props.scaleKey);
|
|
||||||
|
|
||||||
if (!fieldIndex) {
|
if (!fieldIndex) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const field = data[fieldIndex.frameIndex]?.fields[fieldIndex.fieldIndex];
|
const field = data[fieldIndex.frameIndex]?.fields[fieldIndex.fieldIndex];
|
||||||
|
|
||||||
if (!field || field.config.custom?.hideFrom?.legend) {
|
if (!field || field.config.custom?.hideFrom?.legend) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const label = getFieldDisplayName(field, data[fieldIndex.frameIndex]!, data);
|
const label = getFieldDisplayName(field, data[fieldIndex.frameIndex]!, data);
|
||||||
const scaleColor = getFieldSeriesColor(field, theme);
|
const scaleColor = getFieldSeriesColor(field, theme);
|
||||||
const seriesColor = scaleColor.color;
|
const seriesColor = scaleColor.color;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
disabled: !(seriesConfig.show ?? true),
|
disabled: !(seriesConfig.show ?? true),
|
||||||
fieldIndex,
|
fieldIndex,
|
||||||
color: seriesColor,
|
color: seriesColor,
|
||||||
label,
|
label,
|
||||||
yAxis: axisPlacement === AxisPlacement.Left ? 1 : 2,
|
yAxis: axisPlacement === AxisPlacement.Left ? 1 : 2,
|
||||||
getDisplayValues: () => {
|
getDisplayValues: () => {
|
||||||
if (!calcs?.length) {
|
if (!calcs?.length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
|
||||||
|
|
||||||
const fmt = field.display ?? defaultFormatter;
|
|
||||||
let countFormatter: DisplayProcessor | null = null;
|
|
||||||
|
|
||||||
const fieldCalcs = reduceField({
|
|
||||||
field,
|
|
||||||
reducers: calcs,
|
|
||||||
});
|
|
||||||
|
|
||||||
return calcs.map<DisplayValue>((reducerId) => {
|
|
||||||
const fieldReducer = fieldReducers.get(reducerId);
|
|
||||||
let formatter = fmt;
|
|
||||||
|
|
||||||
if (fieldReducer.id === ReducerID.diffperc) {
|
|
||||||
formatter = getDisplayProcessor({
|
|
||||||
field: {
|
|
||||||
...field,
|
|
||||||
config: {
|
|
||||||
...field.config,
|
|
||||||
unit: 'percent',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
theme,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
const fmt = field.display ?? defaultFormatter;
|
||||||
fieldReducer.id === ReducerID.count ||
|
let countFormatter: DisplayProcessor | null = null;
|
||||||
fieldReducer.id === ReducerID.changeCount ||
|
|
||||||
fieldReducer.id === ReducerID.distinctCount
|
const fieldCalcs = reduceField({
|
||||||
) {
|
field,
|
||||||
if (!countFormatter) {
|
reducers: calcs,
|
||||||
countFormatter = getDisplayProcessor({
|
});
|
||||||
|
|
||||||
|
return calcs.map<DisplayValue>((reducerId) => {
|
||||||
|
const fieldReducer = fieldReducers.get(reducerId);
|
||||||
|
let formatter = fmt;
|
||||||
|
|
||||||
|
if (fieldReducer.id === ReducerID.diffperc) {
|
||||||
|
formatter = getDisplayProcessor({
|
||||||
field: {
|
field: {
|
||||||
...field,
|
...field,
|
||||||
config: {
|
config: {
|
||||||
...field.config,
|
...field.config,
|
||||||
unit: 'none',
|
unit: 'percent',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
theme,
|
theme,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
formatter = countFormatter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
if (
|
||||||
...formatter(fieldCalcs[reducerId]),
|
fieldReducer.id === ReducerID.count ||
|
||||||
title: fieldReducer.name,
|
fieldReducer.id === ReducerID.changeCount ||
|
||||||
description: fieldReducer.description,
|
fieldReducer.id === ReducerID.distinctCount
|
||||||
};
|
) {
|
||||||
});
|
if (!countFormatter) {
|
||||||
},
|
countFormatter = getDisplayProcessor({
|
||||||
getItemKey: () => `${label}-${fieldIndex.frameIndex}-${fieldIndex.fieldIndex}`,
|
field: {
|
||||||
};
|
...field,
|
||||||
})
|
config: {
|
||||||
.filter((i) => i !== undefined) as VizLegendItem[];
|
...field.config,
|
||||||
|
unit: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
theme,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
formatter = countFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return {
|
||||||
<VizLayout.Legend placement={placement} {...vizLayoutLegendProps}>
|
...formatter(fieldCalcs[reducerId]),
|
||||||
<VizLegend
|
title: fieldReducer.name,
|
||||||
placement={placement}
|
description: fieldReducer.description,
|
||||||
items={legendItems}
|
};
|
||||||
displayMode={displayMode}
|
});
|
||||||
sortBy={vizLayoutLegendProps.sortBy}
|
},
|
||||||
sortDesc={vizLayoutLegendProps.sortDesc}
|
getItemKey: () => `${label}-${fieldIndex.frameIndex}-${fieldIndex.fieldIndex}`,
|
||||||
/>
|
};
|
||||||
</VizLayout.Legend>
|
})
|
||||||
);
|
.filter((i) => i !== undefined) as VizLegendItem[];
|
||||||
};
|
|
||||||
|
return (
|
||||||
|
<VizLayout.Legend placement={placement} {...vizLayoutLegendProps}>
|
||||||
|
<VizLegend
|
||||||
|
placement={placement}
|
||||||
|
items={legendItems}
|
||||||
|
displayMode={displayMode}
|
||||||
|
sortBy={vizLayoutLegendProps.sortBy}
|
||||||
|
sortDesc={vizLayoutLegendProps.sortDesc}
|
||||||
|
/>
|
||||||
|
</VizLayout.Legend>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
PlotLegend.displayName = 'PlotLegend';
|
PlotLegend.displayName = 'PlotLegend';
|
||||||
|
Loading…
Reference in New Issue
Block a user