Commit 2221a8c5 by Ryan McKinley Committed by GitHub

GraphNG: remove graph2 panel (keep the parts needed for explore) (#30124)

parent 0d8d96bd
...@@ -13,7 +13,7 @@ import { config } from '@grafana/runtime'; ...@@ -13,7 +13,7 @@ import { config } from '@grafana/runtime';
import { groupBy } from 'lodash'; import { groupBy } from 'lodash';
import { ExplorePanelData } from '../../../types'; import { ExplorePanelData } from '../../../types';
import { getGraphSeriesModel } from '../../../plugins/panel/graph2/getGraphSeriesModel'; import { getGraphSeriesModel } from '../flotgraph/getGraphSeriesModel';
import { dataFrameToLogsModel } from '../../../core/logs_model'; import { dataFrameToLogsModel } from '../../../core/logs_model';
import { refreshIntervalToSortOrder } from '../../../core/utils/explore'; import { refreshIntervalToSortOrder } from '../../../core/utils/explore';
import { LegendDisplayMode } from '@grafana/ui'; import { LegendDisplayMode } from '@grafana/ui';
......
...@@ -39,7 +39,6 @@ const tempoPlugin = async () => ...@@ -39,7 +39,6 @@ const tempoPlugin = async () =>
await import(/* webpackChunkName: "tempoPlugin" */ 'app/plugins/datasource/tempo/module'); await import(/* webpackChunkName: "tempoPlugin" */ 'app/plugins/datasource/tempo/module');
import * as textPanel from 'app/plugins/panel/text/module'; import * as textPanel from 'app/plugins/panel/text/module';
import * as graph2Panel from 'app/plugins/panel/graph2/module';
import * as graph3Panel from 'app/plugins/panel/graph3/module'; import * as graph3Panel from 'app/plugins/panel/graph3/module';
import * as graphPanel from 'app/plugins/panel/graph/module'; import * as graphPanel from 'app/plugins/panel/graph/module';
import * as dashListPanel from 'app/plugins/panel/dashlist/module'; import * as dashListPanel from 'app/plugins/panel/dashlist/module';
...@@ -82,7 +81,6 @@ const builtInPlugins: any = { ...@@ -82,7 +81,6 @@ const builtInPlugins: any = {
'app/plugins/datasource/tempo/module': tempoPlugin, 'app/plugins/datasource/tempo/module': tempoPlugin,
'app/plugins/panel/text/module': textPanel, 'app/plugins/panel/text/module': textPanel,
'app/plugins/panel/graph2/module': graph2Panel,
'app/plugins/panel/graph3/module': graph3Panel, 'app/plugins/panel/graph3/module': graph3Panel,
'app/plugins/panel/graph/module': graphPanel, 'app/plugins/panel/graph/module': graphPanel,
'app/plugins/panel/dashlist/module': dashListPanel, 'app/plugins/panel/dashlist/module': dashListPanel,
......
import React from 'react';
import { GraphWithLegend, Chart } from '@grafana/ui';
import { PanelProps } from '@grafana/data';
import { Options } from './types';
import { GraphPanelController } from './GraphPanelController';
interface GraphPanelProps extends PanelProps<Options> {}
export const GraphPanel: React.FunctionComponent<GraphPanelProps> = ({
data,
timeRange,
timeZone,
width,
height,
options,
fieldConfig,
onOptionsChange,
onChangeTimeRange,
}) => {
if (!data) {
return (
<div className="panel-empty">
<p>No data found in response</p>
</div>
);
}
const {
graph: { showLines, showBars, showPoints },
legend: legendOptions,
tooltipOptions,
} = options;
const graphProps = {
showBars,
showLines,
showPoints,
tooltipOptions,
};
return (
<GraphPanelController
data={data}
timeZone={timeZone}
options={options}
fieldConfig={fieldConfig}
onOptionsChange={onOptionsChange}
onChangeTimeRange={onChangeTimeRange}
>
{({ onSeriesToggle, onHorizontalRegionSelected, ...controllerApi }) => {
return (
<GraphWithLegend
timeRange={timeRange}
timeZone={timeZone}
width={width}
height={height}
legendDisplayMode={legendOptions.displayMode}
placement={legendOptions.placement}
sortLegendBy={legendOptions.sortBy}
sortLegendDesc={legendOptions.sortDesc}
onSeriesToggle={onSeriesToggle}
onHorizontalRegionSelected={onHorizontalRegionSelected}
{...graphProps}
{...controllerApi}
>
<Chart.Tooltip mode={tooltipOptions.mode} />
</GraphWithLegend>
);
}}
</GraphPanelController>
);
};
import React from 'react';
import { GraphSeriesToggler } from '@grafana/ui';
import { PanelData, GraphSeriesXY, AbsoluteTimeRange, TimeZone, FieldConfigSource } from '@grafana/data';
import { getGraphSeriesModel } from './getGraphSeriesModel';
import { Options, SeriesOptions } from './types';
import { SeriesColorChangeHandler, SeriesAxisToggleHandler } from '@grafana/ui/src/components/Graph/GraphWithLegend';
interface GraphPanelControllerAPI {
series: GraphSeriesXY[];
onSeriesAxisToggle: SeriesAxisToggleHandler;
onSeriesColorChange: SeriesColorChangeHandler;
onSeriesToggle: (label: string, event: React.MouseEvent<HTMLElement>) => void;
onToggleSort: (sortBy: string) => void;
onHorizontalRegionSelected: (from: number, to: number) => void;
}
interface GraphPanelControllerProps {
children: (api: GraphPanelControllerAPI) => JSX.Element;
options: Options;
fieldConfig: FieldConfigSource;
data: PanelData;
timeZone: TimeZone;
onOptionsChange: (options: Options) => void;
onChangeTimeRange: (timeRange: AbsoluteTimeRange) => void;
}
interface GraphPanelControllerState {
graphSeriesModel: GraphSeriesXY[];
}
export class GraphPanelController extends React.Component<GraphPanelControllerProps, GraphPanelControllerState> {
constructor(props: GraphPanelControllerProps) {
super(props);
this.onSeriesColorChange = this.onSeriesColorChange.bind(this);
this.onSeriesAxisToggle = this.onSeriesAxisToggle.bind(this);
this.onToggleSort = this.onToggleSort.bind(this);
this.onHorizontalRegionSelected = this.onHorizontalRegionSelected.bind(this);
this.state = {
graphSeriesModel: getGraphSeriesModel(
props.data.series,
props.timeZone,
props.options.series || {},
props.options.graph,
props.options.legend,
props.fieldConfig
),
};
}
static getDerivedStateFromProps(props: GraphPanelControllerProps, state: GraphPanelControllerState) {
return {
...state,
graphSeriesModel: getGraphSeriesModel(
props.data.series,
props.timeZone,
props.options.series || {},
props.options.graph,
props.options.legend,
props.fieldConfig
),
};
}
onSeriesOptionsUpdate(label: string, optionsUpdate: SeriesOptions) {
const { onOptionsChange, options } = this.props;
const updatedSeriesOptions: { [label: string]: SeriesOptions } = { ...options.series };
updatedSeriesOptions[label] = optionsUpdate;
onOptionsChange({
...options,
series: updatedSeriesOptions,
});
}
onSeriesAxisToggle(label: string, yAxis: number) {
const {
options: { series },
} = this.props;
const seriesOptionsUpdate: SeriesOptions = series[label]
? {
...series[label],
yAxis: {
...series[label].yAxis,
index: yAxis,
},
}
: {
yAxis: {
index: yAxis,
},
};
this.onSeriesOptionsUpdate(label, seriesOptionsUpdate);
}
onSeriesColorChange(label: string, color: string) {
const {
options: { series },
} = this.props;
const seriesOptionsUpdate: SeriesOptions = series[label]
? {
...series[label],
color,
}
: {
color,
};
this.onSeriesOptionsUpdate(label, seriesOptionsUpdate);
}
onToggleSort(sortBy: string) {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
legend: {
...options.legend,
sortBy,
sortDesc: sortBy === options.legend.sortBy ? !options.legend.sortDesc : false,
},
});
}
onHorizontalRegionSelected(from: number, to: number) {
const { onChangeTimeRange } = this.props;
onChangeTimeRange({ from, to });
}
render() {
const { children } = this.props;
const { graphSeriesModel } = this.state;
return (
<GraphSeriesToggler series={graphSeriesModel}>
{({ onSeriesToggle, toggledSeries }) => {
return children({
series: toggledSeries,
onSeriesColorChange: this.onSeriesColorChange,
onSeriesAxisToggle: this.onSeriesAxisToggle,
onToggleSort: this.onToggleSort,
onSeriesToggle: onSeriesToggle,
onHorizontalRegionSelected: this.onHorizontalRegionSelected,
});
}}
</GraphSeriesToggler>
);
}
}
# Text Panel - Native Plugin
The Text Panel is **included** with Grafana.
The Text Panel is a very simple panel that displays text. The source text is written in the Markdown syntax meaning you can format the text. Read [GitHub's Mastering Markdown](https://guides.github.com/features/mastering-markdown/) to learn more.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 82.59 82.5"><defs><style>.cls-1{fill:#3865ab;}.cls-2{fill:#84aff1;}.cls-3{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" y1="21.17" x2="82.59" y2="21.17" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f2cc0c"/><stop offset="1" stop-color="#ff9830"/></linearGradient></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><rect class="cls-1" x="73.22" y="19.61" width="8" height="62.89" rx="1"/><rect class="cls-1" x="1.78" y="53.61" width="8" height="28.89" rx="1"/><path class="cls-2" d="M8.78,82.5h-6a1,1,0,0,1-1-1V71.61h8V81.5A1,1,0,0,1,8.78,82.5Z"/><path class="cls-2" d="M80.22,82.5h-6a1,1,0,0,1-1-1V46.61h8V81.5A1,1,0,0,1,80.22,82.5Z"/><rect class="cls-1" x="58.93" y="49.61" width="8" height="32.89" rx="1"/><path class="cls-2" d="M65.93,82.5h-6a1,1,0,0,1-1-1V64.61h8V81.5A1,1,0,0,1,65.93,82.5Z"/><rect class="cls-1" x="44.64" y="38.61" width="8" height="43.89" rx="1"/><path class="cls-2" d="M51.64,82.5h-6a1,1,0,0,1-1-1V75.61h8V81.5A1,1,0,0,1,51.64,82.5Z"/><rect class="cls-1" x="30.36" y="27.61" width="8" height="54.89" rx="1"/><path class="cls-2" d="M37.36,82.5h-6a1,1,0,0,1-1-1V42.61h8V81.5A1,1,0,0,1,37.36,82.5Z"/><rect class="cls-1" x="16.07" y="37.61" width="8" height="44.89" rx="1"/><path class="cls-2" d="M23.07,82.5h-6a1,1,0,0,1-1-1V55.61h8V81.5A1,1,0,0,1,23.07,82.5Z"/><path class="cls-3" d="M2,42.33a2,2,0,0,1-1.44-.61,2,2,0,0,1,0-2.83l26-25a2,2,0,0,1,2.2-.39L54.56,25,79.18.58A2,2,0,0,1,82,3.42L56.41,28.75a2,2,0,0,1-2.22.41L28.42,17.71l-25,24.06A2,2,0,0,1,2,42.33Z"/></g></g></svg>
\ No newline at end of file
import { PanelPlugin } from '@grafana/data';
import { GraphPanel } from './GraphPanel';
import { Options } from './types';
export const plugin = new PanelPlugin<Options>(GraphPanel).useFieldConfig().setPanelOptions(builder => {
builder
.addBooleanSwitch({
path: 'graph.showBars',
name: 'Show bars',
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'graph.showLines',
name: 'Show lines',
description: '',
defaultValue: true,
})
.addBooleanSwitch({
path: 'graph.showPoints',
name: 'Show poins',
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'legend.isVisible',
name: 'Show legend',
description: '',
defaultValue: true,
})
.addBooleanSwitch({
path: 'legend.asTable',
name: 'Display legend as table',
description: '',
defaultValue: false,
})
.addRadio({
path: 'legend.placement',
name: 'Legend placement',
description: '',
defaultValue: 'under',
settings: {
options: [
{ value: 'under', label: 'Below graph' },
{ value: 'right', label: 'Right to the graph' },
],
},
})
.addRadio({
path: 'tooltipOptions.mode',
name: 'Tooltip mode',
description: '',
defaultValue: 'single',
settings: {
options: [
{ value: 'single', label: 'Single series' },
{ value: 'multi', label: 'All series' },
],
},
});
});
{
"type": "panel",
"name": "React graph",
"id": "graph2",
"state": "alpha",
"info": {
"author": {
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"logos": {
"small": "img/icn-graph-panel.svg",
"large": "img/icn-graph-panel.svg"
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment