From abddb442a188101e86d6b160f830527cd8b5afb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 18 Feb 2019 11:41:14 +0100 Subject: [PATCH] Changed how react panels store their options (#15468) Changed how react panels store their options * Added a ReactPanelPlugin as the interface that react panels export, this way react panels have clearer api, and gives us hooks to handle migrations and a way for panel to handle panel changes in the future * Moved gauge value options into a sub oject and made editor more generic, will be moved out of gauge pane later and shared between singlestat, gauge, bargauge, honecomb * Also remove nested options prop that was there due to bug * Added missing Gauge props * Fixed gauge issue that will require migration later and also value options editor did not handle null decimals or 0 decimals * Fixed unit tests * More fixes for react panels --- .../grafana-ui/src/components/Gauge/Gauge.tsx | 2 +- packages/grafana-ui/src/types/panel.ts | 21 +++++++++- packages/grafana-ui/src/types/plugin.ts | 6 +-- public/app/core/constants.ts | 1 - .../__snapshots__/DashboardPage.test.tsx.snap | 10 ++--- .../dashboard/dashgrid/DashboardPanel.tsx | 2 +- .../features/dashboard/dashgrid/DataPanel.tsx | 21 +++++----- .../dashboard/dashgrid/PanelChrome.tsx | 4 +- .../dashgrid/PanelPluginNotFound.tsx | 4 +- .../panel_editor/VisualizationTab.tsx | 28 ++++++-------- .../dashboard/state/DashboardMigrator.test.ts | 2 +- .../dashboard/state/DashboardMigrator.ts | 26 ++++++++++++- .../dashboard/state/PanelModel.test.ts | 14 +++++++ .../features/dashboard/state/PanelModel.ts | 27 +++++-------- ...eOptionsEditor.tsx => GaugeOptionsBox.tsx} | 9 ++++- public/app/plugins/panel/gauge/GaugePanel.tsx | 16 ++++++-- ...ePanelOptions.tsx => GaugePanelEditor.tsx} | 38 +++++++------------ ...eOptions.tsx => SingleStatValueEditor.tsx} | 35 +++++++++++++---- public/app/plugins/panel/gauge/module.tsx | 12 ++++-- public/app/plugins/panel/gauge/types.ts | 30 ++++++++++++--- ...hPanelOptions.tsx => GraphPanelEditor.tsx} | 4 +- public/app/plugins/panel/graph2/module.tsx | 4 +- public/app/plugins/panel/text2/module.tsx | 4 +- 23 files changed, 203 insertions(+), 117 deletions(-) rename public/app/plugins/panel/gauge/{GaugeOptionsEditor.tsx => GaugeOptionsBox.tsx} (85%) rename public/app/plugins/panel/gauge/{GaugePanelOptions.tsx => GaugePanelEditor.tsx} (52%) rename public/app/plugins/panel/gauge/{ValueOptions.tsx => SingleStatValueEditor.tsx} (74%) rename public/app/plugins/panel/graph2/{GraphPanelOptions.tsx => GraphPanelEditor.tsx} (91%) diff --git a/packages/grafana-ui/src/components/Gauge/Gauge.tsx b/packages/grafana-ui/src/components/Gauge/Gauge.tsx index a7435a56b3c..b8c257f4138 100644 --- a/packages/grafana-ui/src/components/Gauge/Gauge.tsx +++ b/packages/grafana-ui/src/components/Gauge/Gauge.tsx @@ -9,7 +9,7 @@ import { Themeable } from '../../index'; type TimeSeriesValue = string | number | null; export interface Props extends Themeable { - decimals: number; + decimals?: number | null; height: number; valueMappings: ValueMapping[]; maxValue: number; diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index 4eda85f9a28..2da48b0fec6 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -1,3 +1,4 @@ +import { ComponentClass } from 'react'; import { TimeSeries, LoadingState, TableData } from './data'; import { TimeRange } from './time'; @@ -19,11 +20,29 @@ export interface PanelData { tableData?: TableData; } -export interface PanelOptionsProps { +export interface PanelEditorProps { options: T; onChange: (options: T) => void; } +export class ReactPanelPlugin { + panel: ComponentClass>; + editor?: ComponentClass>; + defaults?: TOptions; + + constructor(panel: ComponentClass>) { + this.panel = panel; + } + + setEditor(editor: ComponentClass>) { + this.editor = editor; + } + + setDefaults(defaults: TOptions) { + this.defaults = defaults; + } +} + export interface PanelSize { width: number; height: number; diff --git a/packages/grafana-ui/src/types/plugin.ts b/packages/grafana-ui/src/types/plugin.ts index c8f156c08dc..e2dda8ad407 100644 --- a/packages/grafana-ui/src/types/plugin.ts +++ b/packages/grafana-ui/src/types/plugin.ts @@ -1,5 +1,5 @@ import { ComponentClass } from 'react'; -import { PanelProps, PanelOptionsProps } from './panel'; +import { ReactPanelPlugin } from './panel'; import { DataQueryOptions, DataQuery, DataQueryResponse, QueryHint, QueryFixAction } from './datasource'; export interface DataSourceApi { @@ -81,9 +81,7 @@ export interface PluginExports { // Panel plugin PanelCtrl?: any; - Panel?: ComponentClass; - PanelOptions?: ComponentClass; - PanelDefaults?: any; + reactPanel: ReactPanelPlugin; } export interface PluginMeta { diff --git a/public/app/core/constants.ts b/public/app/core/constants.ts index 7d295b27726..d51c4cf83d6 100644 --- a/public/app/core/constants.ts +++ b/public/app/core/constants.ts @@ -14,4 +14,3 @@ export const DASHBOARD_TOP_PADDING = 20; export const PANEL_HEADER_HEIGHT = 27; export const PANEL_BORDER = 2; -export const PANEL_OPTIONS_KEY_PREFIX = 'options-'; diff --git a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap index 002cac2306e..f60e60c43a8 100644 --- a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap +++ b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap @@ -78,7 +78,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` ], "refresh": undefined, "revision": undefined, - "schemaVersion": 17, + "schemaVersion": 18, "snapshot": undefined, "style": "dark", "tags": Array [], @@ -190,7 +190,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` ], "refresh": undefined, "revision": undefined, - "schemaVersion": 17, + "schemaVersion": 18, "snapshot": undefined, "style": "dark", "tags": Array [], @@ -313,7 +313,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti ], "refresh": undefined, "revision": undefined, - "schemaVersion": 17, + "schemaVersion": 18, "snapshot": undefined, "style": "dark", "tags": Array [], @@ -423,7 +423,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti ], "refresh": undefined, "revision": undefined, - "schemaVersion": 17, + "schemaVersion": 18, "snapshot": undefined, "style": "dark", "tags": Array [], @@ -518,7 +518,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti ], "refresh": undefined, "revision": undefined, - "schemaVersion": 17, + "schemaVersion": 18, "snapshot": undefined, "style": "dark", "tags": Array [], diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index bb2470cff17..9aeddd5a0d9 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -173,7 +173,7 @@ export class DashboardPanel extends PureComponent { onMouseLeave={this.onMouseLeave} style={styles} > - {plugin.exports.Panel && this.renderReactPanel()} + {plugin.exports.reactPanel && this.renderReactPanel()} {plugin.exports.PanelCtrl && this.renderAngularPanel()} )} diff --git a/public/app/features/dashboard/dashgrid/DataPanel.tsx b/public/app/features/dashboard/dashgrid/DataPanel.tsx index 0675c7afa60..9718e150e2a 100644 --- a/public/app/features/dashboard/dashgrid/DataPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DataPanel.tsx @@ -162,7 +162,7 @@ export class DataPanel extends Component { } onError(message, err); - this.setState({ isFirstLoad: false }); + this.setState({ isFirstLoad: false, loading: LoadingState.Error }); } }; @@ -187,7 +187,8 @@ export class DataPanel extends Component { const { loading, isFirstLoad } = this.state; const panelData = this.getPanelData(); - if (isFirstLoad && loading === LoadingState.Loading) { + // do not render component until we have first data + if (isFirstLoad && (loading === LoadingState.Loading || loading === LoadingState.NotStarted)) { return this.renderLoadingState(); } @@ -201,21 +202,17 @@ export class DataPanel extends Component { return ( <> - {this.renderLoadingState()} + {loading === LoadingState.Loading && this.renderLoadingState()} {this.props.children({ loading, panelData })} ); } private renderLoadingState(): JSX.Element { - const { loading } = this.state; - if (loading === LoadingState.Loading) { - return ( -
- -
- ); - } - return null; + return ( +
+ +
+ ); } } diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 29fe307e941..23c92b23837 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -140,7 +140,7 @@ export class PanelChrome extends PureComponent { renderPanelPlugin(loading: LoadingState, panelData: PanelData, width: number, height: number): JSX.Element { const { panel, plugin } = this.props; const { timeRange, renderCounter } = this.state; - const PanelComponent = plugin.exports.Panel; + const PanelComponent = plugin.exports.reactPanel.panel; // This is only done to increase a counter that is used by backend // image rendering (phantomjs/headless chrome) to know when to capture image @@ -154,7 +154,7 @@ export class PanelChrome extends PureComponent { loading={loading} panelData={panelData} timeRange={timeRange} - options={panel.getOptions(plugin.exports.PanelDefaults)} + options={panel.getOptions(plugin.exports.reactPanel.defaults)} width={width - 2 * variables.panelhorizontalpadding} height={height - PANEL_HEADER_HEIGHT - variables.panelverticalpadding} renderCounter={renderCounter} diff --git a/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx b/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx index 3f835bdbac2..4067f361f06 100644 --- a/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx +++ b/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx @@ -3,7 +3,7 @@ import _ from 'lodash'; import React, { PureComponent } from 'react'; // Types -import { PanelProps } from '@grafana/ui'; +import { PanelProps, ReactPanelPlugin } from '@grafana/ui'; import { PanelPlugin } from 'app/types'; interface Props { @@ -63,7 +63,7 @@ export function getPanelPluginNotFound(id: string): PanelPlugin { }, exports: { - Panel: NotFound, + reactPanel: new ReactPanelPlugin(NotFound), }, }; } diff --git a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx index f9d8b3df607..8a904961a4f 100644 --- a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx +++ b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx @@ -50,33 +50,27 @@ export class VisualizationTab extends PureComponent { }; } - getPanelDefaultOptions = () => { + getReactPanelOptions = () => { const { panel, plugin } = this.props; - - if (plugin.exports.PanelDefaults) { - return panel.getOptions(plugin.exports.PanelDefaults.options); - } - - return panel.getOptions(plugin.exports.PanelDefaults); + return panel.getOptions(plugin.exports.reactPanel.defaults); }; renderPanelOptions() { const { plugin, angularPanel } = this.props; - const { PanelOptions } = plugin.exports; if (angularPanel) { return
(this.element = element)} />; } - return ( - <> - {PanelOptions ? ( - - ) : ( -

Visualization has no options

- )} - - ); + if (plugin.exports.reactPanel) { + const PanelEditor = plugin.exports.reactPanel.editor; + + if (PanelEditor) { + return ; + } + } + + return

Visualization has no options

; } componentDidMount() { diff --git a/public/app/features/dashboard/state/DashboardMigrator.test.ts b/public/app/features/dashboard/state/DashboardMigrator.test.ts index fdb309b5db5..e4b29eeddfc 100644 --- a/public/app/features/dashboard/state/DashboardMigrator.test.ts +++ b/public/app/features/dashboard/state/DashboardMigrator.test.ts @@ -127,7 +127,7 @@ describe('DashboardModel', () => { }); it('dashboard schema version should be set to latest', () => { - expect(model.schemaVersion).toBe(17); + expect(model.schemaVersion).toBe(18); }); it('graph thresholds should be migrated', () => { diff --git a/public/app/features/dashboard/state/DashboardMigrator.ts b/public/app/features/dashboard/state/DashboardMigrator.ts index ba631102b81..1aa310308d5 100644 --- a/public/app/features/dashboard/state/DashboardMigrator.ts +++ b/public/app/features/dashboard/state/DashboardMigrator.ts @@ -22,7 +22,7 @@ export class DashboardMigrator { let i, j, k, n; const oldVersion = this.dashboard.schemaVersion; const panelUpgrades = []; - this.dashboard.schemaVersion = 17; + this.dashboard.schemaVersion = 18; if (oldVersion === this.dashboard.schemaVersion) { return; @@ -387,6 +387,30 @@ export class DashboardMigrator { }); } + if (oldVersion < 18) { + // migrate change to gauge options + panelUpgrades.push(panel => { + if (panel['options-gauge']) { + panel.options = panel['options-gauge']; + panel.options.valueOptions = { + unit: panel.options.unit, + stat: panel.options.stat, + decimals: panel.options.decimals, + prefix: panel.options.prefix, + suffix: panel.options.suffix, + }; + // this options prop was due to a bug + delete panel.options.options; + delete panel.options.unit; + delete panel.options.stat; + delete panel.options.decimals; + delete panel.options.prefix; + delete panel.options.suffix; + delete panel['options-gauge']; + } + }); + } + if (panelUpgrades.length === 0) { return; } diff --git a/public/app/features/dashboard/state/PanelModel.test.ts b/public/app/features/dashboard/state/PanelModel.test.ts index a7e112c7ba5..d96838dc640 100644 --- a/public/app/features/dashboard/state/PanelModel.test.ts +++ b/public/app/features/dashboard/state/PanelModel.test.ts @@ -55,5 +55,19 @@ describe('PanelModel', () => { expect(model.alert).toBe(undefined); }); }); + + describe('get panel options', () => { + it('should apply defaults', () => { + model.options = { existingProp: 10 }; + const options = model.getOptions({ + defaultProp: true, + existingProp: 0, + }); + + expect(options.defaultProp).toBe(true); + expect(options.existingProp).toBe(10); + expect(model.options).toBe(options); + }); + }); }); }); diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 2c0ff674e8a..fda586d2776 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -3,7 +3,6 @@ import _ from 'lodash'; // Types import { Emitter } from 'app/core/utils/emitter'; -import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants'; import { DataQuery, TimeSeries } from '@grafana/ui'; import { TableData } from '@grafana/ui/src'; @@ -92,6 +91,7 @@ export class PanelModel { timeFrom?: any; timeShift?: any; hideTimeOverride?: any; + options: object; maxDataPoints?: number; interval?: string; @@ -105,8 +105,6 @@ export class PanelModel { hasRefreshed: boolean; events: Emitter; cacheTimeout?: any; - - // cache props between plugins cachedPluginOptions?: any; constructor(model) { @@ -134,20 +132,14 @@ export class PanelModel { } getOptions(panelDefaults) { - return _.defaultsDeep(this[this.getOptionsKey()] || {}, panelDefaults); + return _.defaultsDeep(this.options || {}, panelDefaults); } updateOptions(options: object) { - const update: any = {}; - update[this.getOptionsKey()] = options; - Object.assign(this, update); + this.options = options; this.render(); } - private getOptionsKey() { - return PANEL_OPTIONS_KEY_PREFIX + this.type; - } - getSaveModel() { const model: any = {}; for (const property in this) { @@ -240,14 +232,15 @@ export class PanelModel { // for angular panels only we need to remove all events and let angular panels do some cleanup if (fromAngularPanel) { this.destroy(); + } - for (const key of _.keys(this)) { - if (mustKeepProps[key]) { - continue; - } - - delete this[key]; + // remove panel type specific options + for (const key of _.keys(this)) { + if (mustKeepProps[key]) { + continue; } + + delete this[key]; } this.restorePanelOptions(pluginId); diff --git a/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx b/public/app/plugins/panel/gauge/GaugeOptionsBox.tsx similarity index 85% rename from public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx rename to public/app/plugins/panel/gauge/GaugeOptionsBox.tsx index 50e2a344a9b..b5d6acca806 100644 --- a/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx +++ b/public/app/plugins/panel/gauge/GaugeOptionsBox.tsx @@ -1,9 +1,14 @@ +// Libraries import React, { PureComponent } from 'react'; -import { FormField, PanelOptionsProps, PanelOptionsGroup, Switch } from '@grafana/ui'; +// Components +import { Switch, PanelOptionsGroup } from '@grafana/ui'; + +// Types +import { FormField, PanelEditorProps } from '@grafana/ui'; import { GaugeOptions } from './types'; -export default class GaugeOptionsEditor extends PureComponent> { +export class GaugeOptionsBox extends PureComponent> { onToggleThresholdLabels = () => this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels }); diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index 5cb256ee1aa..e7e60a7c417 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -16,9 +16,10 @@ interface Props extends PanelProps {} export class GaugePanel extends PureComponent { render() { const { panelData, width, height, onInterpolate, options } = this.props; + const { valueOptions } = options; - const prefix = onInterpolate(options.prefix); - const suffix = onInterpolate(options.suffix); + const prefix = onInterpolate(valueOptions.prefix); + const suffix = onInterpolate(valueOptions.suffix); let value: TimeSeriesValue; if (panelData.timeSeries) { @@ -28,7 +29,7 @@ export class GaugePanel extends PureComponent { }); if (vmSeries[0]) { - value = vmSeries[0].stats[options.stat]; + value = vmSeries[0].stats[valueOptions.stat]; } else { value = null; } @@ -41,11 +42,18 @@ export class GaugePanel extends PureComponent { {theme => ( )} diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelEditor.tsx similarity index 52% rename from public/app/plugins/panel/gauge/GaugePanelOptions.tsx rename to public/app/plugins/panel/gauge/GaugePanelEditor.tsx index 84726ac88bf..63031f9d895 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelEditor.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { - PanelOptionsProps, + PanelEditorProps, ThresholdsEditor, Threshold, PanelOptionsGrid, @@ -8,29 +8,11 @@ import { ValueMapping, } from '@grafana/ui'; -import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; -import GaugeOptionsEditor from './GaugeOptionsEditor'; -import { GaugeOptions } from './types'; - -export const defaultProps = { - options: { - minValue: 0, - maxValue: 100, - prefix: '', - showThresholdMarkers: true, - showThresholdLabels: false, - suffix: '', - decimals: 0, - stat: 'avg', - unit: 'none', - valueMappings: [], - thresholds: [], - }, -}; - -export default class GaugePanelOptions extends PureComponent> { - static defaultProps = defaultProps; +import { SingleStatValueEditor } from 'app/plugins/panel/gauge/SingleStatValueEditor'; +import { GaugeOptionsBox } from './GaugeOptionsBox'; +import { GaugeOptions, SingleStatValueOptions } from './types'; +export class GaugePanelEditor extends PureComponent> { onThresholdsChanged = (thresholds: Threshold[]) => this.props.onChange({ ...this.props.options, @@ -43,14 +25,20 @@ export default class GaugePanelOptions extends PureComponent + this.props.onChange({ + ...this.props.options, + valueOptions, + }); + render() { const { onChange, options } = this.props; return ( <> - - + + diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/SingleStatValueEditor.tsx similarity index 74% rename from public/app/plugins/panel/gauge/ValueOptions.tsx rename to public/app/plugins/panel/gauge/SingleStatValueEditor.tsx index 1fdccadddf2..86c177bb5e5 100644 --- a/public/app/plugins/panel/gauge/ValueOptions.tsx +++ b/public/app/plugins/panel/gauge/SingleStatValueEditor.tsx @@ -1,7 +1,12 @@ +// Libraries import React, { PureComponent } from 'react'; -import { FormField, FormLabel, PanelOptionsProps, PanelOptionsGroup, Select } from '@grafana/ui'; + +// Components import UnitPicker from 'app/core/components/Select/UnitPicker'; -import { GaugeOptions } from './types'; +import { FormField, FormLabel, PanelOptionsGroup, Select } from '@grafana/ui'; + +// Types +import { SingleStatValueOptions } from './types'; const statOptions = [ { value: 'min', label: 'Min' }, @@ -19,24 +24,40 @@ const statOptions = [ const labelWidth = 6; -export default class ValueOptions extends PureComponent> { - onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); +export interface Props { + options: SingleStatValueOptions; + onChange: (valueOptions: SingleStatValueOptions) => void; +} +export class SingleStatValueEditor extends PureComponent { + onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); onDecimalChange = event => { if (!isNaN(event.target.value)) { - this.props.onChange({ ...this.props.options, decimals: event.target.value }); + this.props.onChange({ + ...this.props.options, + decimals: parseInt(event.target.value, 10), + }); + } else { + this.props.onChange({ + ...this.props.options, + decimals: null, + }); } }; onPrefixChange = event => this.props.onChange({ ...this.props.options, prefix: event.target.value }); - onSuffixChange = event => this.props.onChange({ ...this.props.options, suffix: event.target.value }); render() { const { stat, unit, decimals, prefix, suffix } = this.props.options; + let decimalsString = ''; + if (Number.isFinite(decimals)) { + decimalsString = decimals.toString(); + } + return (
@@ -57,7 +78,7 @@ export default class ValueOptions extends PureComponent diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 783e4825657..a32cb7cd538 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,4 +1,10 @@ -import GaugePanelOptions, { defaultProps } from './GaugePanelOptions'; -import { GaugePanel } from './GaugePanel'; +import { ReactPanelPlugin } from '@grafana/ui'; -export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, defaultProps as PanelDefaults }; +import { GaugePanelEditor } from './GaugePanelEditor'; +import { GaugePanel } from './GaugePanel'; +import { GaugeOptions, defaults } from './types'; + +export const reactPanel = new ReactPanelPlugin(GaugePanel); + +reactPanel.setEditor(GaugePanelEditor); +reactPanel.setDefaults(defaults); diff --git a/public/app/plugins/panel/gauge/types.ts b/public/app/plugins/panel/gauge/types.ts index 42262178dc8..10dd475eff5 100644 --- a/public/app/plugins/panel/gauge/types.ts +++ b/public/app/plugins/panel/gauge/types.ts @@ -1,15 +1,35 @@ import { Threshold, ValueMapping } from '@grafana/ui'; export interface GaugeOptions { - decimals: number; valueMappings: ValueMapping[]; maxValue: number; minValue: number; - prefix: string; showThresholdLabels: boolean; showThresholdMarkers: boolean; - stat: string; - suffix: string; thresholds: Threshold[]; - unit: string; + valueOptions: SingleStatValueOptions; } + +export interface SingleStatValueOptions { + unit: string; + suffix: string; + stat: string; + prefix: string; + decimals?: number | null; +} + +export const defaults: GaugeOptions = { + minValue: 0, + maxValue: 100, + showThresholdMarkers: true, + showThresholdLabels: false, + valueOptions: { + prefix: '', + suffix: '', + decimals: null, + stat: 'avg', + unit: 'none', + }, + valueMappings: [], + thresholds: [], +}; diff --git a/public/app/plugins/panel/graph2/GraphPanelOptions.tsx b/public/app/plugins/panel/graph2/GraphPanelEditor.tsx similarity index 91% rename from public/app/plugins/panel/graph2/GraphPanelOptions.tsx rename to public/app/plugins/panel/graph2/GraphPanelEditor.tsx index a9c2d299589..80b17ccd5c4 100644 --- a/public/app/plugins/panel/graph2/GraphPanelOptions.tsx +++ b/public/app/plugins/panel/graph2/GraphPanelEditor.tsx @@ -3,10 +3,10 @@ import _ from 'lodash'; import React, { PureComponent } from 'react'; // Types -import { PanelOptionsProps, Switch } from '@grafana/ui'; +import { PanelEditorProps, Switch } from '@grafana/ui'; import { Options } from './types'; -export class GraphPanelOptions extends PureComponent> { +export class GraphPanelEditor extends PureComponent> { onToggleLines = () => { this.props.onChange({ ...this.props.options, showLines: !this.props.options.showLines }); }; diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 762d5609541..a3a3fadf6bf 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -1,4 +1,4 @@ import { GraphPanel } from './GraphPanel'; -import { GraphPanelOptions } from './GraphPanelOptions'; +import { GraphPanelEditor } from './GraphPanelEditor'; -export { GraphPanel as Panel, GraphPanelOptions as PanelOptions }; +export { GraphPanel as Panel, GraphPanelEditor as PanelOptions }; diff --git a/public/app/plugins/panel/text2/module.tsx b/public/app/plugins/panel/text2/module.tsx index cc3ec016273..884a5927a19 100644 --- a/public/app/plugins/panel/text2/module.tsx +++ b/public/app/plugins/panel/text2/module.tsx @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { PanelProps } from '@grafana/ui'; +import { PanelProps, ReactPanelPlugin } from '@grafana/ui'; export class Text2 extends PureComponent { constructor(props: PanelProps) { @@ -11,4 +11,4 @@ export class Text2 extends PureComponent { } } -export { Text2 as Panel }; +export const reactPanel = new ReactPanelPlugin(Text2);