mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600)
* Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
co-authored by
Torkel Ödegaard
parent
d99a67075f
commit
bf7579d984
@@ -43,8 +43,43 @@ describe('BarGauge Panel Migrations', () => {
|
||||
targets: [],
|
||||
title: 'Usage',
|
||||
type: 'bargauge',
|
||||
} as PanelModel;
|
||||
} as Omit<PanelModel, 'fieldConfig'>;
|
||||
|
||||
expect(barGaugePanelMigrationHandler(panel)).toMatchSnapshot();
|
||||
expect(barGaugePanelMigrationHandler(panel as PanelModel)).toMatchSnapshot();
|
||||
expect((panel as any).fieldConfig).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"defaults": Object {
|
||||
"color": Object {
|
||||
"mode": "thresholds",
|
||||
},
|
||||
"decimals": null,
|
||||
"mappings": Array [],
|
||||
"max": 33,
|
||||
"min": -22,
|
||||
"thresholds": Object {
|
||||
"mode": "absolute",
|
||||
"steps": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"value": -Infinity,
|
||||
},
|
||||
Object {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"value": 40,
|
||||
},
|
||||
Object {
|
||||
"color": "red",
|
||||
"index": 2,
|
||||
"value": 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
"unit": "watt",
|
||||
},
|
||||
"overrides": Array [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
PanelProps,
|
||||
LoadingState,
|
||||
dateTime,
|
||||
FieldConfigSource,
|
||||
toDataFrame,
|
||||
} from '@grafana/data';
|
||||
import { BarGaugeDisplayMode } from '@grafana/ui';
|
||||
@@ -66,13 +67,15 @@ function createBarGaugePanelWithData(data: PanelData): ReactWrapper<PanelProps<B
|
||||
displayMode: BarGaugeDisplayMode.Lcd,
|
||||
fieldOptions: {
|
||||
calcs: ['mean'],
|
||||
defaults: {},
|
||||
values: false,
|
||||
overrides: [],
|
||||
},
|
||||
orientation: VizOrientation.Horizontal,
|
||||
showUnfilled: true,
|
||||
};
|
||||
const fieldConfig: FieldConfigSource = {
|
||||
defaults: {},
|
||||
overrides: [],
|
||||
};
|
||||
|
||||
return mount<BarGaugePanel>(
|
||||
<BarGaugePanel
|
||||
@@ -81,6 +84,8 @@ function createBarGaugePanelWithData(data: PanelData): ReactWrapper<PanelProps<B
|
||||
timeRange={timeRange}
|
||||
timeZone={'utc'}
|
||||
options={options}
|
||||
fieldConfig={fieldConfig}
|
||||
onFieldConfigChange={() => {}}
|
||||
onOptionsChange={() => {}}
|
||||
onChangeTimeRange={() => {}}
|
||||
replaceVariables={s => s}
|
||||
|
||||
@@ -51,9 +51,10 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
};
|
||||
|
||||
getValues = (): FieldDisplay[] => {
|
||||
const { data, options, replaceVariables } = this.props;
|
||||
const { data, options, replaceVariables, fieldConfig } = this.props;
|
||||
return getFieldDisplayValues({
|
||||
...options,
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
|
||||
@@ -2,83 +2,94 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import {
|
||||
ThresholdsEditor,
|
||||
ValueMappingsEditor,
|
||||
PanelOptionsGrid,
|
||||
FieldDisplayEditor,
|
||||
FieldPropertiesEditor,
|
||||
PanelOptionsGroup,
|
||||
FormLabel,
|
||||
Select,
|
||||
DataLinksEditor,
|
||||
Switch,
|
||||
FieldPropertiesEditor,
|
||||
ThresholdsEditor,
|
||||
LegacyValueMappingsEditor,
|
||||
DataLinksEditor,
|
||||
} from '@grafana/ui';
|
||||
import {
|
||||
DataLink,
|
||||
FieldConfig,
|
||||
FieldDisplayOptions,
|
||||
PanelEditorProps,
|
||||
ThresholdsConfig,
|
||||
ValueMapping,
|
||||
FieldDisplayOptions,
|
||||
FieldConfig,
|
||||
DataLink,
|
||||
PanelEditorProps,
|
||||
} from '@grafana/data';
|
||||
import { BarGaugeOptions, displayModes } from './types';
|
||||
import { orientationOptions } from '../gauge/types';
|
||||
import {
|
||||
getDataLinksVariableSuggestions,
|
||||
getCalculationValueDataLinksVariableSuggestions,
|
||||
} from 'app/features/panel/panellinks/link_srv';
|
||||
getDataLinksVariableSuggestions,
|
||||
} from '../../../features/panel/panellinks/link_srv';
|
||||
|
||||
export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGaugeOptions>> {
|
||||
onThresholdsChanged = (thresholds: ThresholdsConfig) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
...current,
|
||||
thresholds,
|
||||
});
|
||||
};
|
||||
|
||||
onValueMappingsChanged = (mappings: ValueMapping[]) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
...current,
|
||||
mappings,
|
||||
});
|
||||
};
|
||||
|
||||
onDisplayOptionsChanged = (fieldOptions: FieldDisplayOptions) =>
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
fieldOptions,
|
||||
});
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
this.onDisplayOptionsChanged({
|
||||
...this.props.options.fieldOptions,
|
||||
defaults: field,
|
||||
});
|
||||
};
|
||||
|
||||
onOrientationChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, orientation: value });
|
||||
onDisplayModeChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, displayMode: value });
|
||||
onToggleShowUnfilled = () => {
|
||||
this.props.onOptionsChange({ ...this.props.options, showUnfilled: !this.props.options.showUnfilled });
|
||||
};
|
||||
|
||||
onDataLinksChanged = (links: DataLink[]) => {
|
||||
this.onDefaultsChange({
|
||||
...this.props.options.fieldOptions.defaults,
|
||||
links,
|
||||
onThresholdsChanged = (thresholds: ThresholdsConfig) => {
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
thresholds,
|
||||
},
|
||||
});
|
||||
};
|
||||
render() {
|
||||
const { options } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { defaults } = fieldOptions;
|
||||
|
||||
onValueMappingsChanged = (mappings: ValueMapping[]) => {
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
mappings,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onDataLinksChanged = (links: DataLink[]) => {
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
links,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onDefaultsChange = (field: FieldConfig, event?: React.SyntheticEvent<HTMLElement>, callback?: () => void) => {
|
||||
this.props.onFieldConfigChange({
|
||||
...this.props.fieldConfig,
|
||||
defaults: field,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { options, fieldConfig } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
const labelWidth = 6;
|
||||
const suggestions = fieldOptions.values
|
||||
? getDataLinksVariableSuggestions(this.props.data.series)
|
||||
: getCalculationValueDataLinksVariableSuggestions(this.props.data.series);
|
||||
const labelWidth = 6;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -105,14 +116,16 @@ export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGauge
|
||||
value={displayModes.find(item => item.value === options.displayMode)}
|
||||
/>
|
||||
</div>
|
||||
{options.displayMode !== 'lcd' && (
|
||||
<Switch
|
||||
label="Unfilled"
|
||||
labelClass={`width-${labelWidth}`}
|
||||
checked={options.showUnfilled}
|
||||
onChange={this.onToggleShowUnfilled}
|
||||
/>
|
||||
)}
|
||||
<>
|
||||
{options.displayMode !== 'lcd' && (
|
||||
<Switch
|
||||
label="Unfilled"
|
||||
labelClass={`width-${labelWidth}`}
|
||||
checked={options.showUnfilled}
|
||||
onChange={this.onToggleShowUnfilled}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</PanelOptionsGroup>
|
||||
<PanelOptionsGroup title="Field">
|
||||
<FieldPropertiesEditor
|
||||
@@ -126,7 +139,7 @@ export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGauge
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
|
||||
@@ -7,37 +7,6 @@ Object {
|
||||
"calcs": Array [
|
||||
"mean",
|
||||
],
|
||||
"defaults": Object {
|
||||
"color": Object {
|
||||
"mode": "thresholds",
|
||||
},
|
||||
"decimals": null,
|
||||
"mappings": Array [],
|
||||
"max": 33,
|
||||
"min": -22,
|
||||
"thresholds": Object {
|
||||
"mode": "absolute",
|
||||
"steps": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"value": -Infinity,
|
||||
},
|
||||
Object {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"value": 40,
|
||||
},
|
||||
Object {
|
||||
"color": "red",
|
||||
"index": 2,
|
||||
"value": 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
"unit": "watt",
|
||||
},
|
||||
"overrides": Array [],
|
||||
"thresholds": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
|
||||
@@ -3,10 +3,12 @@ import { PanelPlugin } from '@grafana/data';
|
||||
import { BarGaugePanel } from './BarGaugePanel';
|
||||
import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
||||
import { BarGaugeOptions, defaults } from './types';
|
||||
import { standardFieldConfig } from '../stat/types';
|
||||
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
|
||||
|
||||
export const plugin = new PanelPlugin<BarGaugeOptions>(BarGaugePanel)
|
||||
.setDefaults(defaults)
|
||||
.setFieldConfigDefaults(standardFieldConfig)
|
||||
.setEditor(BarGaugePanelEditor)
|
||||
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||
.setMigrationHandler(barGaugePanelMigrationHandler);
|
||||
|
||||
@@ -75,9 +75,68 @@ describe('Gauge Panel Migrations', () => {
|
||||
timeShift: null,
|
||||
title: 'Panel Title',
|
||||
type: 'gauge',
|
||||
} as PanelModel;
|
||||
} as Omit<PanelModel, 'fieldConfig'>;
|
||||
|
||||
expect(gaugePanelMigrationHandler(panel)).toMatchSnapshot();
|
||||
const result = gaugePanelMigrationHandler(panel as PanelModel);
|
||||
expect(result).toMatchSnapshot();
|
||||
|
||||
// Ignored due to the API change
|
||||
//@ts-ignore
|
||||
expect(result.fieldOptions.defaults).toBeUndefined();
|
||||
// Ignored due to the API change
|
||||
//@ts-ignore
|
||||
expect(result.fieldOptions.overrides).toBeUndefined();
|
||||
|
||||
expect((panel as PanelModel).fieldConfig).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"defaults": Object {
|
||||
"color": Object {
|
||||
"mode": "thresholds",
|
||||
},
|
||||
"decimals": 3,
|
||||
"mappings": Array [
|
||||
Object {
|
||||
"from": "50",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "BIG",
|
||||
"to": "1000",
|
||||
"type": 2,
|
||||
"value": "",
|
||||
},
|
||||
],
|
||||
"max": "50",
|
||||
"min": "-50",
|
||||
"thresholds": Object {
|
||||
"mode": "absolute",
|
||||
"steps": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"value": -Infinity,
|
||||
},
|
||||
Object {
|
||||
"color": "#EAB839",
|
||||
"index": 1,
|
||||
"value": -25,
|
||||
},
|
||||
Object {
|
||||
"color": "#6ED0E0",
|
||||
"index": 2,
|
||||
"value": 0,
|
||||
},
|
||||
Object {
|
||||
"color": "red",
|
||||
"index": 3,
|
||||
"value": 25,
|
||||
},
|
||||
],
|
||||
},
|
||||
"unit": "accMS2",
|
||||
},
|
||||
"overrides": Array [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('change from angular singlestat to gauge', () => {
|
||||
@@ -95,11 +154,12 @@ describe('Gauge Panel Migrations', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const newOptions = gaugePanelChangedHandler({} as any, 'singlestat', old);
|
||||
expect(newOptions.fieldOptions.defaults.unit).toBe('ms');
|
||||
expect(newOptions.fieldOptions.defaults.min).toBe(-10);
|
||||
expect(newOptions.fieldOptions.defaults.max).toBe(150);
|
||||
expect(newOptions.fieldOptions.defaults.decimals).toBe(7);
|
||||
const panel = {} as PanelModel;
|
||||
const newOptions = gaugePanelChangedHandler(panel, 'singlestat', old);
|
||||
expect(panel.fieldConfig.defaults.unit).toBe('ms');
|
||||
expect(panel.fieldConfig.defaults.min).toBe(-10);
|
||||
expect(panel.fieldConfig.defaults.max).toBe(150);
|
||||
expect(panel.fieldConfig.defaults.decimals).toBe(7);
|
||||
expect(newOptions.showThresholdMarkers).toBe(true);
|
||||
expect(newOptions.showThresholdLabels).toBe(true);
|
||||
});
|
||||
@@ -116,10 +176,10 @@ describe('Gauge Panel Migrations', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const newOptions = gaugePanelChangedHandler({} as any, 'singlestat', old);
|
||||
expect(newOptions.fieldOptions.defaults.unit).toBe('ms');
|
||||
expect(newOptions.fieldOptions.defaults.min).toBe(undefined);
|
||||
expect(newOptions.fieldOptions.defaults.max).toBe(undefined);
|
||||
const panel = {} as PanelModel;
|
||||
gaugePanelChangedHandler(panel, 'singlestat', old);
|
||||
expect(panel.fieldConfig.defaults.unit).toBe('ms');
|
||||
expect(panel.fieldConfig.defaults.min).toBe(undefined);
|
||||
expect(panel.fieldConfig.defaults.max).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,8 +40,9 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
||||
};
|
||||
|
||||
getValues = (): FieldDisplay[] => {
|
||||
const { data, options, replaceVariables } = this.props;
|
||||
const { data, options, replaceVariables, fieldConfig } = this.props;
|
||||
return getFieldDisplayValues({
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
ThresholdsEditor,
|
||||
PanelOptionsGrid,
|
||||
ValueMappingsEditor,
|
||||
FieldDisplayEditor,
|
||||
FieldPropertiesEditor,
|
||||
Switch,
|
||||
PanelOptionsGroup,
|
||||
FieldPropertiesEditor,
|
||||
ThresholdsEditor,
|
||||
LegacyValueMappingsEditor,
|
||||
DataLinksEditor,
|
||||
} from '@grafana/ui';
|
||||
import {
|
||||
PanelEditorProps,
|
||||
FieldDisplayOptions,
|
||||
ThresholdsConfig,
|
||||
ValueMapping,
|
||||
FieldConfig,
|
||||
DataLink,
|
||||
FieldConfig,
|
||||
ValueMapping,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { GaugeOptions } from './types';
|
||||
import {
|
||||
getCalculationValueDataLinksVariableSuggestions,
|
||||
getDataLinksVariableSuggestions,
|
||||
} from 'app/features/panel/panellinks/link_srv';
|
||||
} from '../../../features/panel/panellinks/link_srv';
|
||||
|
||||
export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOptions>> {
|
||||
labelWidth = 6;
|
||||
@@ -37,27 +37,11 @@ export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOption
|
||||
showThresholdMarkers: !this.props.options.showThresholdMarkers,
|
||||
});
|
||||
|
||||
onThresholdsChanged = (thresholds: ThresholdsConfig) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
...current,
|
||||
thresholds,
|
||||
});
|
||||
};
|
||||
|
||||
onValueMappingsChanged = (mappings: ValueMapping[]) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
...current,
|
||||
mappings,
|
||||
});
|
||||
};
|
||||
|
||||
onDisplayOptionsChanged = (
|
||||
fieldOptions: FieldDisplayOptions,
|
||||
event?: React.SyntheticEvent<HTMLElement>,
|
||||
callback?: () => void
|
||||
) =>
|
||||
) => {
|
||||
this.props.onOptionsChange(
|
||||
{
|
||||
...this.props.options,
|
||||
@@ -65,38 +49,57 @@ export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOption
|
||||
},
|
||||
callback
|
||||
);
|
||||
|
||||
onDefaultsChange = (field: FieldConfig, event?: React.SyntheticEvent<HTMLElement>, callback?: () => void) => {
|
||||
this.onDisplayOptionsChanged(
|
||||
{
|
||||
...this.props.options.fieldOptions,
|
||||
defaults: field,
|
||||
},
|
||||
event,
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
onDataLinksChanged = (links: DataLink[], callback?: () => void) => {
|
||||
this.onDefaultsChange(
|
||||
{
|
||||
...this.props.options.fieldOptions.defaults,
|
||||
onThresholdsChanged = (thresholds: ThresholdsConfig) => {
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
thresholds,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onValueMappingsChanged = (mappings: ValueMapping[]) => {
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
mappings,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onDataLinksChanged = (links: DataLink[]) => {
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
links,
|
||||
},
|
||||
undefined,
|
||||
callback
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
this.props.onFieldConfigChange({
|
||||
...this.props.fieldConfig,
|
||||
defaults: field,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { options } = this.props;
|
||||
const { fieldOptions, showThresholdLabels, showThresholdMarkers } = options;
|
||||
const { defaults } = fieldOptions;
|
||||
const { options, fieldConfig } = this.props;
|
||||
const { showThresholdLabels, showThresholdMarkers, fieldOptions } = options;
|
||||
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
const suggestions = fieldOptions.values
|
||||
? getDataLinksVariableSuggestions(this.props.data.series)
|
||||
: getCalculationValueDataLinksVariableSuggestions(this.props.data.series);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
@@ -128,11 +131,9 @@ export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOption
|
||||
value={defaults}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
|
||||
@@ -6,51 +6,6 @@ Object {
|
||||
"calcs": Array [
|
||||
"last",
|
||||
],
|
||||
"defaults": Object {
|
||||
"color": Object {
|
||||
"mode": "thresholds",
|
||||
},
|
||||
"decimals": 3,
|
||||
"mappings": Array [
|
||||
Object {
|
||||
"from": "50",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "BIG",
|
||||
"to": "1000",
|
||||
"type": 2,
|
||||
"value": "",
|
||||
},
|
||||
],
|
||||
"max": "50",
|
||||
"min": "-50",
|
||||
"thresholds": Object {
|
||||
"mode": "absolute",
|
||||
"steps": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"value": -Infinity,
|
||||
},
|
||||
Object {
|
||||
"color": "#EAB839",
|
||||
"index": 1,
|
||||
"value": -25,
|
||||
},
|
||||
Object {
|
||||
"color": "#6ED0E0",
|
||||
"index": 2,
|
||||
"value": 0,
|
||||
},
|
||||
Object {
|
||||
"color": "red",
|
||||
"index": 3,
|
||||
"value": 25,
|
||||
},
|
||||
],
|
||||
},
|
||||
"unit": "accMS2",
|
||||
},
|
||||
},
|
||||
"orientation": "auto",
|
||||
"showThresholdLabels": true,
|
||||
|
||||
@@ -2,10 +2,12 @@ import { PanelPlugin } from '@grafana/data';
|
||||
import { GaugePanelEditor } from './GaugePanelEditor';
|
||||
import { GaugePanel } from './GaugePanel';
|
||||
import { GaugeOptions, defaults } from './types';
|
||||
import { standardFieldConfig } from '../stat/types';
|
||||
import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations';
|
||||
|
||||
export const plugin = new PanelPlugin<GaugeOptions>(GaugePanel)
|
||||
.setDefaults(defaults)
|
||||
.setFieldConfigDefaults(standardFieldConfig)
|
||||
.setEditor(GaugePanelEditor)
|
||||
.setPanelChangeHandler(gaugePanelChangedHandler)
|
||||
.setMigrationHandler(gaugePanelMigrationHandler);
|
||||
|
||||
@@ -14,6 +14,7 @@ export const GraphPanel: React.FunctionComponent<GraphPanelProps> = ({
|
||||
width,
|
||||
height,
|
||||
options,
|
||||
fieldConfig,
|
||||
onOptionsChange,
|
||||
onChangeTimeRange,
|
||||
}) => {
|
||||
@@ -43,6 +44,7 @@ export const GraphPanel: React.FunctionComponent<GraphPanelProps> = ({
|
||||
data={data}
|
||||
timeZone={timeZone}
|
||||
options={options}
|
||||
fieldConfig={fieldConfig}
|
||||
onOptionsChange={onOptionsChange}
|
||||
onChangeTimeRange={onChangeTimeRange}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { GraphSeriesToggler } from '@grafana/ui';
|
||||
import { PanelData, GraphSeriesXY, AbsoluteTimeRange, TimeZone } from '@grafana/data';
|
||||
import { PanelData, GraphSeriesXY, AbsoluteTimeRange, TimeZone, FieldConfigSource } from '@grafana/data';
|
||||
|
||||
import { getGraphSeriesModel } from './getGraphSeriesModel';
|
||||
import { Options, SeriesOptions } from './types';
|
||||
@@ -18,6 +18,7 @@ interface GraphPanelControllerAPI {
|
||||
interface GraphPanelControllerProps {
|
||||
children: (api: GraphPanelControllerAPI) => JSX.Element;
|
||||
options: Options;
|
||||
fieldConfig: FieldConfigSource;
|
||||
data: PanelData;
|
||||
timeZone: TimeZone;
|
||||
onOptionsChange: (options: Options) => void;
|
||||
@@ -44,7 +45,7 @@ export class GraphPanelController extends React.Component<GraphPanelControllerPr
|
||||
props.options.series,
|
||||
props.options.graph,
|
||||
props.options.legend,
|
||||
props.options.fieldOptions
|
||||
props.fieldConfig
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -58,7 +59,7 @@ export class GraphPanelController extends React.Component<GraphPanelControllerPr
|
||||
props.options.series,
|
||||
props.options.graph,
|
||||
props.options.legend,
|
||||
props.options.fieldOptions
|
||||
props.fieldConfig
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@ import _ from 'lodash';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Types
|
||||
import { PanelEditorProps, FieldConfig } from '@grafana/data';
|
||||
import { FieldConfig, PanelEditorProps } from '@grafana/data';
|
||||
import {
|
||||
Switch,
|
||||
LegendOptions,
|
||||
GraphTooltipOptions,
|
||||
PanelOptionsGrid,
|
||||
PanelOptionsGroup,
|
||||
FieldPropertiesEditor,
|
||||
Select,
|
||||
FieldPropertiesEditor,
|
||||
} from '@grafana/ui';
|
||||
import { Options, GraphOptions } from './types';
|
||||
import { GraphLegendEditor } from './GraphLegendEditor';
|
||||
@@ -47,13 +47,10 @@ export class GraphPanelEditor extends PureComponent<PanelEditorProps<Options>> {
|
||||
this.onGraphOptionsChange({ showPoints: !this.props.options.graph.showPoints });
|
||||
};
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
fieldOptions: {
|
||||
...this.props.options.fieldOptions,
|
||||
defaults: field,
|
||||
},
|
||||
onDefaultsChange = (field: FieldConfig, event?: React.SyntheticEvent<HTMLElement>, callback?: () => void) => {
|
||||
this.props.onFieldConfigChange({
|
||||
...this.props.fieldConfig,
|
||||
defaults: field,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -76,7 +73,7 @@ export class GraphPanelEditor extends PureComponent<PanelEditorProps<Options>> {
|
||||
<FieldPropertiesEditor
|
||||
showMinMax={false}
|
||||
onChange={this.onDefaultsChange}
|
||||
value={this.props.options.fieldOptions.defaults}
|
||||
value={this.props.fieldConfig.defaults}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
<PanelOptionsGroup title="Tooltip">
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
GraphSeriesXY,
|
||||
getTimeField,
|
||||
DataFrame,
|
||||
FieldDisplayOptions,
|
||||
getSeriesTimeStep,
|
||||
TimeZone,
|
||||
hasMsResolution,
|
||||
@@ -17,6 +16,7 @@ import {
|
||||
DEFAULT_DATE_TIME_FORMAT,
|
||||
FieldColor,
|
||||
FieldColorMode,
|
||||
FieldConfigSource,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { SeriesOptions, GraphOptions } from './types';
|
||||
@@ -28,7 +28,7 @@ export const getGraphSeriesModel = (
|
||||
seriesOptions: SeriesOptions,
|
||||
graphOptions: GraphOptions,
|
||||
legendOptions: GraphLegendEditorLegendOptions,
|
||||
fieldOptions?: FieldDisplayOptions
|
||||
fieldOptions?: FieldConfigSource
|
||||
) => {
|
||||
const graphs: GraphSeriesXY[] = [];
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@ interface Props extends PanelProps<PieChartOptions> {}
|
||||
|
||||
export class PieChartPanel extends PureComponent<Props> {
|
||||
render() {
|
||||
const { width, height, options, data, replaceVariables } = this.props;
|
||||
const { width, height, options, data, replaceVariables, fieldConfig } = this.props;
|
||||
|
||||
const values = getFieldDisplayValues({
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
data: data.series,
|
||||
theme: config.theme,
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
PanelOptionsGrid,
|
||||
ValueMappingsEditor,
|
||||
FieldDisplayEditor,
|
||||
FieldPropertiesEditor,
|
||||
PanelOptionsGroup,
|
||||
FieldPropertiesEditor,
|
||||
LegacyValueMappingsEditor,
|
||||
} from '@grafana/ui';
|
||||
import { ValueMapping, FieldConfig, PanelEditorProps, FieldDisplayOptions } from '@grafana/data';
|
||||
import { PanelEditorProps, FieldDisplayOptions, ValueMapping, FieldConfig } from '@grafana/data';
|
||||
|
||||
import { PieChartOptionsBox } from './PieChartOptionsBox';
|
||||
import { PieChartOptions } from './types';
|
||||
|
||||
export class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChartOptions>> {
|
||||
onValueMappingsChanged = (mappings: ValueMapping[]) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
mappings,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
mappings,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -27,16 +30,16 @@ export class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChart
|
||||
});
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
this.onDisplayOptionsChanged({
|
||||
...this.props.options.fieldOptions,
|
||||
this.props.onFieldConfigChange({
|
||||
...this.props.fieldConfig,
|
||||
defaults: field,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { onOptionsChange, options, data } = this.props;
|
||||
const { onOptionsChange, options, data, fieldConfig, onFieldConfigChange } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { defaults } = fieldOptions;
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -49,10 +52,15 @@ export class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChart
|
||||
<FieldPropertiesEditor showMinMax={true} onChange={this.onDefaultsChange} value={defaults} />
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<PieChartOptionsBox data={data} onOptionsChange={onOptionsChange} options={options} />
|
||||
<PieChartOptionsBox
|
||||
data={data}
|
||||
onOptionsChange={onOptionsChange}
|
||||
options={options}
|
||||
fieldConfig={fieldConfig}
|
||||
onFieldConfigChange={onFieldConfigChange}
|
||||
/>
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,4 +5,5 @@ import { PieChartOptions, defaults } from './types';
|
||||
|
||||
export const plugin = new PanelPlugin<PieChartOptions>(PieChartPanel)
|
||||
.setDefaults(defaults)
|
||||
.setFieldConfigDefaults({ defaults: { unit: 'short' } })
|
||||
.setEditor(PieChartPanelEditor);
|
||||
|
||||
@@ -14,8 +14,5 @@ export const defaults: PieChartOptions = {
|
||||
fieldOptions: {
|
||||
...standardFieldDisplayOptions,
|
||||
calcs: [ReducerID.last],
|
||||
defaults: {
|
||||
unit: 'short',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -69,10 +69,11 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
||||
};
|
||||
|
||||
getValues = (): FieldDisplay[] => {
|
||||
const { data, options, replaceVariables } = this.props;
|
||||
const { data, options, replaceVariables, fieldConfig } = this.props;
|
||||
|
||||
return getFieldDisplayValues({
|
||||
...options,
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
|
||||
@@ -2,48 +2,53 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import {
|
||||
ThresholdsEditor,
|
||||
PanelOptionsGrid,
|
||||
ValueMappingsEditor,
|
||||
FieldDisplayEditor,
|
||||
FieldPropertiesEditor,
|
||||
PanelOptionsGroup,
|
||||
DataLinksEditor,
|
||||
FormLabel,
|
||||
Select,
|
||||
FieldPropertiesEditor,
|
||||
ThresholdsEditor,
|
||||
LegacyValueMappingsEditor,
|
||||
DataLinksEditor,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import {
|
||||
ThresholdsConfig,
|
||||
ValueMapping,
|
||||
FieldConfig,
|
||||
DataLink,
|
||||
PanelEditorProps,
|
||||
FieldDisplayOptions,
|
||||
FieldConfig,
|
||||
ValueMapping,
|
||||
ThresholdsConfig,
|
||||
DataLink,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { StatPanelOptions, colorModes, graphModes, justifyModes } from './types';
|
||||
import { orientationOptions } from '../gauge/types';
|
||||
|
||||
import {
|
||||
getDataLinksVariableSuggestions,
|
||||
getCalculationValueDataLinksVariableSuggestions,
|
||||
} from 'app/features/panel/panellinks/link_srv';
|
||||
getDataLinksVariableSuggestions,
|
||||
} from '../../../features/panel/panellinks/link_srv';
|
||||
|
||||
export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOptions>> {
|
||||
onThresholdsChanged = (thresholds: ThresholdsConfig) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
thresholds,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
thresholds,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onValueMappingsChanged = (mappings: ValueMapping[]) => {
|
||||
const current = this.props.options.fieldOptions.defaults;
|
||||
this.onDefaultsChange({
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
mappings,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
mappings,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -59,23 +64,28 @@ export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOpt
|
||||
onOrientationChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, orientation: value });
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
this.onDisplayOptionsChanged({
|
||||
...this.props.options.fieldOptions,
|
||||
this.props.onFieldConfigChange({
|
||||
...this.props.fieldConfig,
|
||||
defaults: field,
|
||||
});
|
||||
};
|
||||
|
||||
onDataLinksChanged = (links: DataLink[]) => {
|
||||
this.onDefaultsChange({
|
||||
...this.props.options.fieldOptions.defaults,
|
||||
links,
|
||||
const current = this.props.fieldConfig;
|
||||
this.props.onFieldConfigChange({
|
||||
...current,
|
||||
defaults: {
|
||||
...current.defaults,
|
||||
links,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { options } = this.props;
|
||||
const { options, fieldConfig } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { defaults } = fieldOptions;
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
const suggestions = fieldOptions.values
|
||||
? getDataLinksVariableSuggestions(this.props.data.series)
|
||||
: getCalculationValueDataLinksVariableSuggestions(this.props.data.series);
|
||||
@@ -126,7 +136,6 @@ export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOpt
|
||||
/>
|
||||
</div>
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<PanelOptionsGroup title="Field">
|
||||
<FieldPropertiesEditor
|
||||
showMinMax={true}
|
||||
@@ -138,8 +147,7 @@ export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOpt
|
||||
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { sharedSingleStatMigrationHandler, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
import { StatPanelOptions, defaults } from './types';
|
||||
import { StatPanelOptions, defaults, standardFieldConfig } from './types';
|
||||
import { StatPanel } from './StatPanel';
|
||||
import { StatPanelEditor } from './StatPanelEditor';
|
||||
|
||||
export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel)
|
||||
.setDefaults(defaults)
|
||||
.setFieldConfigDefaults(standardFieldConfig)
|
||||
.setEditor(StatPanelEditor)
|
||||
.setNoPadding()
|
||||
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { SingleStatBaseOptions, BigValueColorMode, BigValueGraphMode, BigValueJustifyMode } from '@grafana/ui';
|
||||
import { VizOrientation, ReducerID, FieldDisplayOptions, SelectableValue, ThresholdsMode } from '@grafana/data';
|
||||
import {
|
||||
VizOrientation,
|
||||
ReducerID,
|
||||
FieldDisplayOptions,
|
||||
SelectableValue,
|
||||
FieldConfigSource,
|
||||
ThresholdsMode,
|
||||
} from '@grafana/data';
|
||||
|
||||
// Structure copied from angular
|
||||
export interface StatPanelOptions extends SingleStatBaseOptions {
|
||||
@@ -26,6 +33,9 @@ export const justifyModes: Array<SelectableValue<BigValueJustifyMode>> = [
|
||||
export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
||||
values: false,
|
||||
calcs: [ReducerID.mean],
|
||||
};
|
||||
|
||||
export const standardFieldConfig: FieldConfigSource = {
|
||||
defaults: {
|
||||
thresholds: {
|
||||
mode: ThresholdsMode.Absolute,
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import { FieldConfigSource } from '@grafana/data';
|
||||
|
||||
export interface Options {
|
||||
fieldOptions: FieldConfigSource;
|
||||
showHeader: boolean;
|
||||
}
|
||||
|
||||
export const defaults: Options = {
|
||||
fieldOptions: {
|
||||
defaults: {},
|
||||
overrides: [],
|
||||
},
|
||||
showHeader: true,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user