Viz: get UPlotChart out of the timeRange business (#70412)

This commit is contained in:
Leon Sorokin 2023-06-21 13:10:25 -05:00 committed by GitHub
parent ce6f73bd32
commit 1db0ace5e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 16 additions and 75 deletions

View File

@ -5303,9 +5303,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"], [0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"]
[0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
], ],
"public/app/plugins/panel/live/LiveChannelEditor.tsx:5381": [ "public/app/plugins/panel/live/LiveChannelEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "0"],

View File

@ -248,7 +248,7 @@ export class GraphNG extends Component<GraphNGProps, GraphNGState> {
} }
render() { render() {
const { width, height, children, timeRange, renderLegend } = this.props; const { width, height, children, renderLegend } = this.props;
const { config, alignedFrame, alignedData } = this.state; const { config, alignedFrame, alignedData } = this.state;
if (!config) { if (!config) {
@ -263,7 +263,6 @@ export class GraphNG extends Component<GraphNGProps, GraphNGState> {
data={alignedData!} data={alignedData!}
width={vizWidth} width={vizWidth}
height={vizHeight} height={vizHeight}
timeRange={timeRange}
plotRef={(u) => ((this.plotInstance as React.MutableRefObject<uPlot>).current = u)} plotRef={(u) => ((this.plotInstance as React.MutableRefObject<uPlot>).current = u)}
> >
{children ? children(config, alignedFrame) : null} {children ? children(config, alignedFrame) : null}

View File

@ -202,9 +202,7 @@ export class Sparkline extends PureComponent<SparklineProps, State> {
render() { render() {
const { data, configBuilder } = this.state; const { data, configBuilder } = this.state;
const { width, height, sparkline } = this.props; const { width, height } = this.props;
return ( return <UPlotChart data={data} config={configBuilder} width={width} height={height} />;
<UPlotChart data={data} config={configBuilder} width={width} height={height} timeRange={sparkline.timeRange!} />
);
} }
} }

View File

@ -3,7 +3,7 @@ import createMockRaf from 'mock-raf';
import React from 'react'; import React from 'react';
import uPlot from 'uplot'; import uPlot from 'uplot';
import { dateTime, FieldConfig, FieldType, MutableDataFrame } from '@grafana/data'; import { FieldConfig, FieldType, MutableDataFrame } from '@grafana/data';
import { GraphFieldConfig, GraphDrawStyle } from '@grafana/schema'; import { GraphFieldConfig, GraphDrawStyle } from '@grafana/schema';
import { UPlotChart } from './Plot'; import { UPlotChart } from './Plot';
@ -49,15 +49,9 @@ const mockData = () => {
} as FieldConfig<GraphFieldConfig>, } as FieldConfig<GraphFieldConfig>,
}); });
const timeRange = {
from: dateTime(1602673200000),
to: dateTime(1602680400000),
raw: { from: '1602673200000', to: '1602680400000' },
};
const config = new UPlotConfigBuilder(); const config = new UPlotConfigBuilder();
config.addSeries({} as SeriesProps); config.addSeries({} as SeriesProps);
return { data: data, timeRange, config }; return { data: data, config };
}; };
describe('UPlotChart', () => { describe('UPlotChart', () => {
@ -73,13 +67,12 @@ describe('UPlotChart', () => {
}); });
it('destroys uPlot instance when component unmounts', () => { it('destroys uPlot instance when component unmounts', () => {
const { data, timeRange, config } = mockData(); const { data, config } = mockData();
const { unmount } = render( const { unmount } = render(
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} // mock data={preparePlotData2(data, getStackingGroups(data))} // mock
config={config} config={config}
timeRange={timeRange}
width={100} width={100}
height={100} height={100}
/> />
@ -92,13 +85,12 @@ describe('UPlotChart', () => {
describe('data update', () => { describe('data update', () => {
it('skips uPlot reinitialization when there are no field config changes', () => { it('skips uPlot reinitialization when there are no field config changes', () => {
const { data, timeRange, config } = mockData(); const { data, config } = mockData();
const { rerender } = render( const { rerender } = render(
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} // mock data={preparePlotData2(data, getStackingGroups(data))} // mock
config={config} config={config}
timeRange={timeRange}
width={100} width={100}
height={100} height={100}
/> />
@ -112,7 +104,6 @@ describe('UPlotChart', () => {
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} // changed data={preparePlotData2(data, getStackingGroups(data))} // changed
config={config} config={config}
timeRange={timeRange}
width={100} width={100}
height={100} height={100}
/> />
@ -124,15 +115,9 @@ describe('UPlotChart', () => {
describe('config update', () => { describe('config update', () => {
it('skips uPlot intialization for width and height equal 0', async () => { it('skips uPlot intialization for width and height equal 0', async () => {
const { data, timeRange, config } = mockData(); const { data, config } = mockData();
const { queryAllByTestId } = render( const { queryAllByTestId } = render(
<UPlotChart <UPlotChart data={preparePlotData2(data, getStackingGroups(data))} config={config} width={0} height={0} />
data={preparePlotData2(data, getStackingGroups(data))}
config={config}
timeRange={timeRange}
width={0}
height={0}
/>
); );
expect(queryAllByTestId('uplot-main-div')).toHaveLength(1); expect(queryAllByTestId('uplot-main-div')).toHaveLength(1);
@ -140,13 +125,12 @@ describe('UPlotChart', () => {
}); });
it('reinitializes uPlot when config changes', () => { it('reinitializes uPlot when config changes', () => {
const { data, timeRange, config } = mockData(); const { data, config } = mockData();
const { rerender } = render( const { rerender } = render(
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} // frame data={preparePlotData2(data, getStackingGroups(data))} // frame
config={config} config={config}
timeRange={timeRange}
width={100} width={100}
height={100} height={100}
/> />
@ -161,7 +145,6 @@ describe('UPlotChart', () => {
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} data={preparePlotData2(data, getStackingGroups(data))}
config={nextConfig} config={nextConfig}
timeRange={timeRange}
width={100} width={100}
height={100} height={100}
/> />
@ -172,13 +155,12 @@ describe('UPlotChart', () => {
}); });
it('skips uPlot reinitialization when only dimensions change', () => { it('skips uPlot reinitialization when only dimensions change', () => {
const { data, timeRange, config } = mockData(); const { data, config } = mockData();
const { rerender } = render( const { rerender } = render(
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} // frame data={preparePlotData2(data, getStackingGroups(data))} // frame
config={config} config={config}
timeRange={timeRange}
width={100} width={100}
height={100} height={100}
/> />
@ -189,7 +171,6 @@ describe('UPlotChart', () => {
<UPlotChart <UPlotChart
data={preparePlotData2(data, getStackingGroups(data))} // frame data={preparePlotData2(data, getStackingGroups(data))} // frame
config={config} config={config}
timeRange={timeRange}
width={200} width={200}
height={200} height={200}
/> />

View File

@ -16,16 +16,6 @@ function sameConfig(prevProps: PlotProps, nextProps: PlotProps) {
return nextProps.config === prevProps.config; return nextProps.config === prevProps.config;
} }
function sameTimeRange(prevProps: PlotProps, nextProps: PlotProps) {
let prevTime = prevProps.timeRange;
let nextTime = nextProps.timeRange;
return (
prevTime === nextTime ||
(nextTime.from.valueOf() === prevTime.from.valueOf() && nextTime.to.valueOf() === prevTime.to.valueOf())
);
}
type UPlotChartState = { type UPlotChartState = {
plot: uPlot | null; plot: uPlot | null;
}; };
@ -100,11 +90,6 @@ export class UPlotChart extends Component<PlotProps, UPlotChartState> {
this.reinitPlot(); this.reinitPlot();
} else if (!sameData(prevProps, this.props)) { } else if (!sameData(prevProps, this.props)) {
plot?.setData(this.props.data as AlignedData); plot?.setData(this.props.data as AlignedData);
} else if (!sameTimeRange(prevProps, this.props)) {
plot?.setScale('x', {
min: this.props.timeRange.from.valueOf(),
max: this.props.timeRange.to.valueOf(),
});
} }
} }

View File

@ -1,8 +1,6 @@
import React from 'react'; import React from 'react';
import uPlot, { Options, AlignedData } from 'uplot'; import uPlot, { Options, AlignedData } from 'uplot';
import { TimeRange } from '@grafana/data';
import { UPlotConfigBuilder } from './config/UPlotConfigBuilder'; import { UPlotConfigBuilder } from './config/UPlotConfigBuilder';
export type PlotConfig = Pick< export type PlotConfig = Pick<
@ -23,7 +21,6 @@ export interface PlotProps {
width: number; width: number;
height: number; height: number;
config: UPlotConfigBuilder; config: UPlotConfigBuilder;
timeRange: TimeRange;
children?: React.ReactNode; children?: React.ReactNode;
// Reference to uPlot instance // Reference to uPlot instance
plotRef?: (u: uPlot) => void; plotRef?: (u: uPlot) => void;

View File

@ -192,7 +192,7 @@ export const HeatmapPanel = ({
<> <>
<VizLayout width={width} height={height} legend={renderLegend()}> <VizLayout width={width} height={height} legend={renderLegend()}>
{(vizWidth: number, vizHeight: number) => ( {(vizWidth: number, vizHeight: number) => (
<UPlotChart config={builder} data={facets as any} width={vizWidth} height={vizHeight} timeRange={timeRange}> <UPlotChart config={builder} data={facets as any} width={vizWidth} height={vizHeight}>
{/*children ? children(config, alignedFrame) : null*/} {/*children ? children(config, alignedFrame) : null*/}
</UPlotChart> </UPlotChart>
)} )}

View File

@ -323,13 +323,7 @@ export class Histogram extends React.Component<HistogramProps, State> {
return ( return (
<VizLayout width={width} height={height} legend={this.renderLegend(config)}> <VizLayout width={width} height={height} legend={this.renderLegend(config)}>
{(vizWidth: number, vizHeight: number) => ( {(vizWidth: number, vizHeight: number) => (
<UPlotChart <UPlotChart config={this.state.config!} data={this.state.alignedData} width={vizWidth} height={vizHeight}>
config={this.state.config!}
data={this.state.alignedData}
width={vizWidth}
height={vizHeight}
timeRange={null as any}
>
{children ? children(config, alignedFrame) : null} {children ? children(config, alignedFrame) : null}
</UPlotChart> </UPlotChart>
)} )}

View File

@ -1,15 +1,7 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { import { DataFrame, Field, formattedValueToString, getFieldDisplayName, GrafanaTheme2, LinkModel } from '@grafana/data';
DataFrame,
Field,
formattedValueToString,
getFieldDisplayName,
GrafanaTheme2,
LinkModel,
TimeRange,
} from '@grafana/data';
import { LinkButton, useStyles2, VerticalGroup, VizTooltipOptions } from '@grafana/ui'; import { LinkButton, useStyles2, VerticalGroup, VizTooltipOptions } from '@grafana/ui';
import { findField } from 'app/features/dimensions'; import { findField } from 'app/features/dimensions';
import { getTitleFromHref } from 'app/features/explore/utils/links'; import { getTitleFromHref } from 'app/features/explore/utils/links';
@ -39,7 +31,6 @@ export interface Props {
seriesMapping: SeriesMapping; seriesMapping: SeriesMapping;
hoveredPointIndex: number; // the hovered point hoveredPointIndex: number; // the hovered point
options: VizTooltipOptions; options: VizTooltipOptions;
range: TimeRange;
} }
export const TooltipView = ({ export const TooltipView = ({
@ -50,7 +41,6 @@ export const TooltipView = ({
rowIndex, rowIndex,
hoveredPointIndex, hoveredPointIndex,
options, options,
range,
}: Props) => { }: Props) => {
const style = useStyles2(getStyles); const style = useStyles2(getStyles);

View File

@ -215,7 +215,7 @@ export const XYChartPanel2 = (props: Props) => {
<> <>
<VizLayout width={props.width} height={props.height} legend={renderLegend()}> <VizLayout width={props.width} height={props.height} legend={renderLegend()}>
{(vizWidth: number, vizHeight: number) => ( {(vizWidth: number, vizHeight: number) => (
<UPlotChart config={builder} data={facets} width={vizWidth} height={vizHeight} timeRange={props.timeRange} /> <UPlotChart config={builder} data={facets} width={vizWidth} height={vizHeight} />
)} )}
</VizLayout> </VizLayout>
<Portal> <Portal>
@ -252,7 +252,6 @@ export const XYChartPanel2 = (props: Props) => {
rowIndex={hover.xIndex} rowIndex={hover.xIndex}
hoveredPointIndex={hover.scatterIndex} hoveredPointIndex={hover.scatterIndex}
data={props.data.series} data={props.data.series}
range={props.timeRange}
/> />
</VizTooltipContainer> </VizTooltipContainer>
)} )}