mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'react-panel-options' into bar-gauge-poc
This commit is contained in:
commit
42d90fdb7a
@ -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<T = any> {
|
||||
export interface PanelEditorProps<T = any> {
|
||||
options: T;
|
||||
onChange: (options: T) => void;
|
||||
}
|
||||
|
||||
export class ReactPanelPlugin<TOptions = any> {
|
||||
panel: ComponentClass<PanelProps<TOptions>>;
|
||||
editor?: ComponentClass<PanelEditorProps<TOptions>>;
|
||||
defaults?: TOptions;
|
||||
|
||||
constructor(panel: ComponentClass<PanelProps<TOptions>>) {
|
||||
this.panel = panel;
|
||||
}
|
||||
|
||||
setEditor(editor: ComponentClass<PanelEditorProps<TOptions>>) {
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
setDefaults(defaults: TOptions) {
|
||||
this.defaults = defaults;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PanelSize {
|
||||
width: number;
|
||||
height: number;
|
||||
|
@ -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<TQuery extends DataQuery = DataQuery> {
|
||||
@ -81,9 +81,7 @@ export interface PluginExports {
|
||||
|
||||
// Panel plugin
|
||||
PanelCtrl?: any;
|
||||
Panel?: ComponentClass<PanelProps>;
|
||||
PanelOptions?: ComponentClass<PanelOptionsProps>;
|
||||
PanelDefaults?: any;
|
||||
reactPanel: ReactPanelPlugin;
|
||||
}
|
||||
|
||||
export interface PluginMeta {
|
||||
|
@ -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-';
|
||||
|
@ -173,7 +173,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
style={styles}
|
||||
>
|
||||
{plugin.exports.Panel && this.renderReactPanel()}
|
||||
{plugin.exports.reactPanel && this.renderReactPanel()}
|
||||
{plugin.exports.PanelCtrl && this.renderAngularPanel()}
|
||||
</div>
|
||||
)}
|
||||
|
@ -139,7 +139,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
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
|
||||
@ -153,7 +153,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
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}
|
||||
|
@ -6,8 +6,8 @@ import React, { PureComponent } from 'react';
|
||||
import { AlertBox } from 'app/core/components/AlertBox/AlertBox';
|
||||
|
||||
// Types
|
||||
import { PanelProps } from '@grafana/ui';
|
||||
import { PanelPlugin, AppNotificationSeverity } from 'app/types';
|
||||
import { PanelProps, ReactPanelPlugin } from '@grafana/ui';
|
||||
|
||||
interface Props {
|
||||
pluginId: string;
|
||||
@ -64,7 +64,7 @@ export function getPanelPluginNotFound(id: string): PanelPlugin {
|
||||
},
|
||||
|
||||
exports: {
|
||||
Panel: NotFound,
|
||||
reactPanel: new ReactPanelPlugin(NotFound),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -50,33 +50,27 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
getPanelDefaultOptions = () => {
|
||||
getReactPanelOptions = () => {
|
||||
const { panel, plugin } = this.props;
|
||||
|
||||
if (plugin.exports.PanelDefaults) {
|
||||
return panel.getOptions(plugin.exports.PanelDefaults);
|
||||
}
|
||||
|
||||
return panel.getOptions({});
|
||||
return panel.getOptions(plugin.exports.reactPanel.defaults);
|
||||
};
|
||||
|
||||
renderPanelOptions() {
|
||||
const { plugin, angularPanel } = this.props;
|
||||
const { PanelOptions } = plugin.exports;
|
||||
|
||||
if (angularPanel) {
|
||||
return <div ref={element => (this.element = element)} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{PanelOptions ? (
|
||||
<PanelOptions options={this.getPanelDefaultOptions()} onChange={this.onPanelOptionsChanged} />
|
||||
) : (
|
||||
<p>Visualization has no options</p>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
if (plugin.exports.reactPanel) {
|
||||
const PanelEditor = plugin.exports.reactPanel.editor;
|
||||
|
||||
if (PanelEditor) {
|
||||
return <PanelEditor options={this.getReactPanelOptions()} onChange={this.onPanelOptionsChanged} />;
|
||||
}
|
||||
}
|
||||
|
||||
return <p>Visualization has no options</p>;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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) {
|
||||
|
@ -16,9 +16,10 @@ interface Props extends PanelProps<BarGaugeOptions> {}
|
||||
export class BarGaugePanel extends PureComponent<Props> {
|
||||
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;
|
||||
|
||||
@ -29,7 +30,7 @@ export class BarGaugePanel extends PureComponent<Props> {
|
||||
});
|
||||
|
||||
if (vmSeries[0]) {
|
||||
value = vmSeries[0].stats[options.stat];
|
||||
value = vmSeries[0].stats[valueOptions.stat];
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
@ -42,11 +43,14 @@ export class BarGaugePanel extends PureComponent<Props> {
|
||||
{theme => (
|
||||
<BarGauge
|
||||
value={value}
|
||||
{...this.props.options}
|
||||
width={width}
|
||||
height={height}
|
||||
prefix={prefix}
|
||||
suffix={suffix}
|
||||
unit={valueOptions.unit}
|
||||
decimals={valueOptions.decimals}
|
||||
thresholds={options.thresholds}
|
||||
valueMappings={options.valueMappings}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
|
@ -2,14 +2,15 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Components
|
||||
import { ValueOptions } from 'app/plugins/panel/gauge/ValueOptions';
|
||||
import { SingleStatValueEditor } from 'app/plugins/panel/gauge/SingleStatValueEditor';
|
||||
import { ThresholdsEditor, ValueMappingsEditor, PanelOptionsGrid, PanelOptionsGroup, FormField } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { PanelOptionsProps, Threshold, ValueMapping } from '@grafana/ui';
|
||||
import { PanelEditorProps, Threshold, ValueMapping } from '@grafana/ui';
|
||||
import { BarGaugeOptions } from './types';
|
||||
import { SingleStatValueOptions } from '../gauge/types';
|
||||
|
||||
export class BarGaugePanelOptions extends PureComponent<PanelOptionsProps<BarGaugeOptions>> {
|
||||
export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGaugeOptions>> {
|
||||
onThresholdsChanged = (thresholds: Threshold[]) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
@ -22,16 +23,22 @@ export class BarGaugePanelOptions extends PureComponent<PanelOptionsProps<BarGau
|
||||
valueMappings,
|
||||
});
|
||||
|
||||
onValueOptionsChanged = (valueOptions: SingleStatValueOptions) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
valueOptions,
|
||||
});
|
||||
|
||||
onMinValueChange = ({ target }) => this.props.onChange({ ...this.props.options, minValue: target.value });
|
||||
onMaxValueChange = ({ target }) => this.props.onChange({ ...this.props.options, maxValue: target.value });
|
||||
|
||||
render() {
|
||||
const { onChange, options } = this.props;
|
||||
const { options } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<ValueOptions onChange={onChange} options={options} />
|
||||
<SingleStatValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
|
||||
<PanelOptionsGroup title="Gauge">
|
||||
<FormField label="Min value" labelWidth={8} onChange={this.onMinValueChange} value={options.minValue} />
|
||||
<FormField label="Max value" labelWidth={8} onChange={this.onMaxValueChange} value={options.maxValue} />
|
@ -1,5 +1,10 @@
|
||||
import { BarGaugePanel } from './BarGaugePanel';
|
||||
import { BarGaugePanelOptions } from './BarGaugePanelOptions';
|
||||
import { PanelDefaults } from './types';
|
||||
import { ReactPanelPlugin } from '@grafana/ui';
|
||||
|
||||
export { BarGaugePanel as Panel, BarGaugePanelOptions as PanelOptions, PanelDefaults };
|
||||
import { BarGaugePanel } from './BarGaugePanel';
|
||||
import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
||||
import { BarGaugeOptions, defaults } from './types';
|
||||
|
||||
export const reactPanel = new ReactPanelPlugin<BarGaugeOptions>(BarGaugePanel);
|
||||
|
||||
reactPanel.setEditor(BarGaugePanelEditor);
|
||||
reactPanel.setDefaults(defaults);
|
||||
|
@ -1,23 +1,24 @@
|
||||
import { Threshold, ValueMapping } from '@grafana/ui';
|
||||
import { SingleStatValueOptions } from '../gauge/types';
|
||||
|
||||
export interface BarGaugeOptions {
|
||||
minValue: number;
|
||||
maxValue: number;
|
||||
prefix: string;
|
||||
stat: string;
|
||||
suffix: string;
|
||||
unit: string;
|
||||
valueOptions: SingleStatValueOptions;
|
||||
valueMappings: ValueMapping[];
|
||||
thresholds: Threshold[];
|
||||
}
|
||||
|
||||
export const PanelDefaults: BarGaugeOptions = {
|
||||
export const defaults: BarGaugeOptions = {
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
valueOptions: {
|
||||
unit: 'none',
|
||||
stat: 'avg',
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
stat: 'avg',
|
||||
unit: 'none',
|
||||
decimals: null,
|
||||
},
|
||||
thresholds: [{ index: 2, value: 80, color: 'red' }, { index: 0, value: -Infinity, color: 'green' }],
|
||||
valueMappings: [],
|
||||
};
|
||||
|
@ -1,8 +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 class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
export class GaugeOptionsBox extends PureComponent<PanelEditorProps<GaugeOptions>> {
|
||||
onToggleThresholdLabels = () =>
|
||||
this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
|
||||
|
@ -16,9 +16,10 @@ interface Props extends PanelProps<GaugeOptions> {}
|
||||
export class GaugePanel extends PureComponent<Props> {
|
||||
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<Props> {
|
||||
});
|
||||
|
||||
if (vmSeries[0]) {
|
||||
value = vmSeries[0].stats[options.stat];
|
||||
value = vmSeries[0].stats[valueOptions.stat];
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
@ -41,11 +42,14 @@ export class GaugePanel extends PureComponent<Props> {
|
||||
{theme => (
|
||||
<Gauge
|
||||
value={value}
|
||||
{...this.props.options}
|
||||
width={width}
|
||||
height={height}
|
||||
prefix={prefix}
|
||||
suffix={suffix}
|
||||
unit={valueOptions.unit}
|
||||
decimals={valueOptions.decimals}
|
||||
thresholds={options.thresholds}
|
||||
valueMappings={options.valueMappings}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
|
50
public/app/plugins/panel/gauge/GaugePanelEditor.tsx
Normal file
50
public/app/plugins/panel/gauge/GaugePanelEditor.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
PanelEditorProps,
|
||||
ThresholdsEditor,
|
||||
Threshold,
|
||||
PanelOptionsGrid,
|
||||
ValueMappingsEditor,
|
||||
ValueMapping,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import { SingleStatValueEditor } from 'app/plugins/panel/gauge/SingleStatValueEditor';
|
||||
import { GaugeOptionsBox } from './GaugeOptionsBox';
|
||||
import { GaugeOptions, SingleStatValueOptions } from './types';
|
||||
|
||||
export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOptions>> {
|
||||
onThresholdsChanged = (thresholds: Threshold[]) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
thresholds,
|
||||
});
|
||||
|
||||
onValueMappingsChanged = (valueMappings: ValueMapping[]) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
valueMappings,
|
||||
});
|
||||
|
||||
onValueOptionsChanged = (valueOptions: SingleStatValueOptions) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
valueOptions,
|
||||
});
|
||||
|
||||
render() {
|
||||
const { onChange, options } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<SingleStatValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
|
||||
<GaugeOptionsBox onChange={onChange} options={options} />
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={options.valueMappings} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Components
|
||||
import { ValueOptions } from 'app/plugins/panel/gauge/ValueOptions';
|
||||
import { GaugeOptionsEditor } from './GaugeOptionsEditor';
|
||||
import { ThresholdsEditor, ValueMappingsEditor } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { PanelOptionsProps, Threshold, PanelOptionsGrid, ValueMapping } from '@grafana/ui';
|
||||
import { GaugeOptions } from './types';
|
||||
|
||||
export class GaugePanelOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
onThresholdsChanged = (thresholds: Threshold[]) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
thresholds,
|
||||
});
|
||||
|
||||
onValueMappingsChanged = (valueMappings: ValueMapping[]) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
valueMappings,
|
||||
});
|
||||
|
||||
render() {
|
||||
const { onChange, options } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<ValueOptions onChange={onChange} options={options} />
|
||||
<GaugeOptionsEditor onChange={onChange} options={options} />
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={options.valueMappings} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
@ -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,9 +24,13 @@ const statOptions = [
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export class ValueOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
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<Props> {
|
||||
onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value });
|
||||
onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value });
|
||||
|
||||
onDecimalChange = event => {
|
||||
@ -31,7 +40,6 @@ export class ValueOptions extends PureComponent<PanelOptionsProps<GaugeOptions>>
|
||||
};
|
||||
|
||||
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() {
|
@ -1,5 +1,10 @@
|
||||
import { GaugePanelOptions } from './GaugePanelOptions';
|
||||
import { GaugePanel } from './GaugePanel';
|
||||
import { PanelDefaults } from './types';
|
||||
import { ReactPanelPlugin } from '@grafana/ui';
|
||||
|
||||
export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, PanelDefaults };
|
||||
import { GaugePanelEditor } from './GaugePanelEditor';
|
||||
import { GaugePanel } from './GaugePanel';
|
||||
import { GaugeOptions, defaults } from './types';
|
||||
|
||||
export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel);
|
||||
|
||||
reactPanel.setEditor(GaugePanelEditor);
|
||||
reactPanel.setDefaults(defaults);
|
||||
|
@ -1,29 +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 const PanelDefaults: GaugeOptions = {
|
||||
export interface SingleStatValueOptions {
|
||||
unit: string;
|
||||
suffix: string;
|
||||
stat: string;
|
||||
prefix: string;
|
||||
decimals: number;
|
||||
}
|
||||
|
||||
export const defaults: GaugeOptions = {
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
prefix: '',
|
||||
showThresholdMarkers: true,
|
||||
showThresholdLabels: false,
|
||||
valueOptions: {
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
decimals: 0,
|
||||
stat: 'avg',
|
||||
unit: 'none',
|
||||
},
|
||||
valueMappings: [],
|
||||
thresholds: [{ index: 1, value: 80, color: 'red' }, { index: 0, value: -Infinity, color: 'green' }],
|
||||
thresholds: [],
|
||||
};
|
||||
|
@ -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<PanelOptionsProps<Options>> {
|
||||
export class GraphPanelEditor extends PureComponent<PanelEditorProps<Options>> {
|
||||
onToggleLines = () => {
|
||||
this.props.onChange({ ...this.props.options, showLines: !this.props.options.showLines });
|
||||
};
|
@ -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 };
|
||||
|
@ -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<PanelProps> {
|
||||
constructor(props: PanelProps) {
|
||||
@ -11,4 +11,4 @@ export class Text2 extends PureComponent<PanelProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export { Text2 as Panel };
|
||||
export const reactPanel = new ReactPanelPlugin(Text2);
|
||||
|
Loading…
Reference in New Issue
Block a user