mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
GraphNG: stats in legend (#30251)
* StatsPickerEditor - add more config to the options ui * Show calcs in the legend * Refactor the way legend items are created * Progress on refresh * Migration update * Use human-readable names in the legend stats * Disable pointer cursor in table header
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { ApplyFieldOverrideOptions, DataTransformerConfig, dateMath, FieldColorModeId, PanelData } from '@grafana/data';
|
||||
import { GraphNG, Table } from '@grafana/ui';
|
||||
import { GraphNG, LegendDisplayMode, Table } from '@grafana/ui';
|
||||
import { config } from 'app/core/config';
|
||||
import React, { FC, useMemo, useState } from 'react';
|
||||
import { useObservable } from 'react-use';
|
||||
@@ -54,7 +54,14 @@ export const TestStuffPage: FC = () => {
|
||||
|
||||
{data && (
|
||||
<div style={{ padding: '16px' }}>
|
||||
<GraphNG width={1200} height={300} data={data.series} timeRange={data.timeRange} timeZone="browser" />
|
||||
<GraphNG
|
||||
width={1200}
|
||||
height={300}
|
||||
data={data.series}
|
||||
legend={{ displayMode: LegendDisplayMode.List, placement: 'bottom', calcs: [] }}
|
||||
timeRange={data.timeRange}
|
||||
timeZone="browser"
|
||||
/>
|
||||
<hr></hr>
|
||||
<Table data={data.series[0]} width={1200} height={300} />
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,60 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Graph Migrations legend 1`] = `
|
||||
Object {
|
||||
"fieldConfig": Object {
|
||||
"defaults": Object {
|
||||
"custom": Object {
|
||||
"axisPlacement": "auto",
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 50,
|
||||
"lineInterpolation": "stepAfter",
|
||||
"lineWidth": 5,
|
||||
"pointSize": 6,
|
||||
"showPoints": "never",
|
||||
"spanNulls": true,
|
||||
},
|
||||
"nullValueMode": "null",
|
||||
"unit": "short",
|
||||
},
|
||||
"overrides": Array [
|
||||
Object {
|
||||
"matcher": Object {
|
||||
"id": "byName",
|
||||
"options": "A-series",
|
||||
},
|
||||
"properties": Array [
|
||||
Object {
|
||||
"id": "color",
|
||||
"value": Object {
|
||||
"fixedColor": "red",
|
||||
"mode": "fixed",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"options": Object {
|
||||
"graph": Object {},
|
||||
"legend": Object {
|
||||
"calcs": Array [
|
||||
"mean",
|
||||
"lastNotNull",
|
||||
"max",
|
||||
"min",
|
||||
"sum",
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
},
|
||||
"tooltipOptions": Object {
|
||||
"mode": "single",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Graph Migrations simple bars 1`] = `
|
||||
Object {
|
||||
"fieldConfig": Object {
|
||||
@@ -16,6 +71,7 @@ Object {
|
||||
"options": Object {
|
||||
"graph": Object {},
|
||||
"legend": Object {
|
||||
"calcs": Array [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
},
|
||||
@@ -50,7 +106,14 @@ Object {
|
||||
"options": Object {
|
||||
"graph": Object {},
|
||||
"legend": Object {
|
||||
"displayMode": "list",
|
||||
"calcs": Array [
|
||||
"mean",
|
||||
"lastNotNull",
|
||||
"max",
|
||||
"min",
|
||||
"sum",
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
},
|
||||
"tooltipOptions": Object {
|
||||
@@ -98,6 +161,7 @@ Object {
|
||||
"options": Object {
|
||||
"graph": Object {},
|
||||
"legend": Object {
|
||||
"calcs": Array [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
},
|
||||
@@ -179,6 +243,7 @@ Object {
|
||||
"options": Object {
|
||||
"graph": Object {},
|
||||
"legend": Object {
|
||||
"calcs": Array [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
},
|
||||
|
||||
@@ -39,6 +39,15 @@ describe('Graph Migrations', () => {
|
||||
panel.options = graphPanelChangedHandler(panel, 'graph', old);
|
||||
expect(panel).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('legend', () => {
|
||||
const old: any = {
|
||||
angular: legend,
|
||||
};
|
||||
const panel = {} as PanelModel;
|
||||
panel.options = graphPanelChangedHandler(panel, 'graph', old);
|
||||
expect(panel).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
const stairscase = {
|
||||
@@ -306,3 +315,97 @@ const stepedColordLine = {
|
||||
timeShift: null,
|
||||
datasource: null,
|
||||
};
|
||||
|
||||
const legend = {
|
||||
aliasColors: {
|
||||
'A-series': 'red',
|
||||
},
|
||||
dashLength: 10,
|
||||
fieldConfig: {
|
||||
defaults: {
|
||||
custom: {},
|
||||
},
|
||||
overrides: [],
|
||||
},
|
||||
fill: 5,
|
||||
gridPos: {
|
||||
h: 9,
|
||||
w: 12,
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
id: 2,
|
||||
legend: {
|
||||
avg: true,
|
||||
current: true,
|
||||
max: false,
|
||||
min: false,
|
||||
show: true,
|
||||
total: true,
|
||||
values: true,
|
||||
alignAsTable: true,
|
||||
},
|
||||
lines: true,
|
||||
linewidth: 5,
|
||||
maxDataPoints: 20,
|
||||
nullPointMode: 'null',
|
||||
options: {
|
||||
alertThreshold: true,
|
||||
},
|
||||
pluginVersion: '7.4.0-pre',
|
||||
pointradius: 2,
|
||||
renderer: 'flot',
|
||||
seriesOverrides: [],
|
||||
spaceLength: 10,
|
||||
steppedLine: true,
|
||||
thresholds: [],
|
||||
timeRegions: [],
|
||||
title: 'Panel Title',
|
||||
tooltip: {
|
||||
shared: true,
|
||||
sort: 0,
|
||||
value_type: 'individual',
|
||||
},
|
||||
type: 'graph',
|
||||
xaxis: {
|
||||
buckets: null,
|
||||
mode: 'time',
|
||||
name: null,
|
||||
show: true,
|
||||
values: [],
|
||||
},
|
||||
yaxes: [
|
||||
{
|
||||
$$hashKey: 'object:38',
|
||||
format: 'short',
|
||||
label: null,
|
||||
logBase: 1,
|
||||
max: null,
|
||||
min: null,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
$$hashKey: 'object:39',
|
||||
format: 'short',
|
||||
label: null,
|
||||
logBase: 1,
|
||||
max: null,
|
||||
min: null,
|
||||
show: true,
|
||||
},
|
||||
],
|
||||
yaxis: {
|
||||
align: false,
|
||||
alignLevel: null,
|
||||
},
|
||||
bars: false,
|
||||
dashes: false,
|
||||
fillGradient: 0,
|
||||
hiddenSeries: false,
|
||||
percentage: false,
|
||||
points: false,
|
||||
stack: false,
|
||||
timeFrom: null,
|
||||
timeShift: null,
|
||||
datasource: null,
|
||||
};
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import {
|
||||
ConfigOverrideRule,
|
||||
DynamicConfigValue,
|
||||
FieldColorModeId,
|
||||
FieldConfig,
|
||||
FieldConfigProperty,
|
||||
FieldConfigSource,
|
||||
FieldMatcherID,
|
||||
fieldReducers,
|
||||
NullValueMode,
|
||||
PanelModel,
|
||||
fieldReducers,
|
||||
ConfigOverrideRule,
|
||||
FieldMatcherID,
|
||||
DynamicConfigValue,
|
||||
FieldConfigProperty,
|
||||
FieldColorModeId,
|
||||
} from '@grafana/data';
|
||||
import { GraphFieldConfig, LegendDisplayMode } from '@grafana/ui';
|
||||
import {
|
||||
FillGradientMode,
|
||||
AxisPlacement,
|
||||
DrawStyle,
|
||||
FillGradientMode,
|
||||
LineInterpolation,
|
||||
LineStyle,
|
||||
PointVisibility,
|
||||
@@ -256,15 +256,29 @@ export function flotToGraphOptions(angular: any): { fieldConfig: FieldConfigSour
|
||||
legend: {
|
||||
displayMode: LegendDisplayMode.List,
|
||||
placement: 'bottom',
|
||||
calcs: [],
|
||||
},
|
||||
tooltipOptions: {
|
||||
mode: 'single',
|
||||
},
|
||||
};
|
||||
|
||||
if (angular.legend?.values) {
|
||||
const show = getReducersFromLegend(angular.legend?.values);
|
||||
console.log('Migrate Legend', show);
|
||||
// Legend config migration
|
||||
const legendConfig = angular.legend;
|
||||
if (legendConfig) {
|
||||
if (legendConfig.show) {
|
||||
options.legend.displayMode = legendConfig.alignAsTable ? LegendDisplayMode.Table : LegendDisplayMode.List;
|
||||
} else {
|
||||
options.legend.displayMode = LegendDisplayMode.Hidden;
|
||||
}
|
||||
|
||||
if (legendConfig.rightSide) {
|
||||
options.legend.placement = 'right';
|
||||
}
|
||||
|
||||
if (angular.legend.values) {
|
||||
options.legend.calcs = getReducersFromLegend(angular.legend);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
import { PanelPlugin, standardEditorsRegistry, StatsPickerConfigSettings } from '@grafana/data';
|
||||
import { GraphFieldConfig, LegendDisplayMode } from '@grafana/ui';
|
||||
import { TimeSeriesPanel } from './TimeSeriesPanel';
|
||||
import { graphPanelChangedHandler } from './migrations';
|
||||
import { Options } from './types';
|
||||
import { getGraphFieldConfig, defaultGraphConfig } from './config';
|
||||
import { defaultGraphConfig, getGraphFieldConfig } from './config';
|
||||
|
||||
export const plugin = new PanelPlugin<Options, GraphFieldConfig>(TimeSeriesPanel)
|
||||
.setPanelChangeHandler(graphPanelChangedHandler)
|
||||
@@ -48,5 +48,17 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(TimeSeriesPanel
|
||||
],
|
||||
},
|
||||
showIf: c => c.legend.displayMode !== LegendDisplayMode.Hidden,
|
||||
})
|
||||
.addCustomEditor<StatsPickerConfigSettings, string[]>({
|
||||
id: 'legend.calcs',
|
||||
path: 'legend.calcs',
|
||||
name: 'Legend calculations',
|
||||
description: 'Choose a reducer functions / calculations to include in legend',
|
||||
editor: standardEditorsRegistry.get('stats-picker').editor as any,
|
||||
defaultValue: [],
|
||||
settings: {
|
||||
allowMultiple: true,
|
||||
},
|
||||
showIf: currentConfig => currentConfig.legend.displayMode !== LegendDisplayMode.Hidden,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user