mirror of
https://github.com/grafana/grafana.git
synced 2025-02-09 23:16:16 -06:00
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
This commit is contained in:
parent
9035ce4d18
commit
074073787d
@ -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 {
|
||||
|
@ -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}
|
||||
|
@ -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),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -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.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 <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() {
|
||||
|
@ -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<PanelOptionsProps<GaugeOptions>> {
|
||||
export class GaugeOptionsBox extends PureComponent<PanelEditorProps<GaugeOptions>> {
|
||||
onToggleThresholdLabels = () =>
|
||||
this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
|
||||
|
@ -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 { ValueOptions } from 'app/plugins/panel/gauge/ValueOptions';
|
||||
import { GaugeOptionsBox } from './GaugeOptionsBox';
|
||||
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<PanelOptionsProps<GaugeOptions>> {
|
||||
static defaultProps = defaultProps;
|
||||
|
||||
export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOptions>> {
|
||||
onThresholdsChanged = (thresholds: Threshold[]) =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
@ -50,7 +32,7 @@ export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<G
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<ValueOptions onChange={onChange} options={options} />
|
||||
<GaugeOptionsEditor onChange={onChange} options={options} />
|
||||
<GaugeOptionsBox onChange={onChange} options={options} />
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
@ -1,7 +1,13 @@
|
||||
// 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 { FormField, FormLabel, PanelOptionsGroup, Select } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { GaugeOptions } from './types';
|
||||
import { PanelEditorProps } from '@grafana/ui';
|
||||
|
||||
const statOptions = [
|
||||
{ value: 'min', label: 'Min' },
|
||||
@ -19,7 +25,7 @@ const statOptions = [
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
export class ValueOptions extends PureComponent<PanelEditorProps<GaugeOptions>> {
|
||||
onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value });
|
||||
|
||||
onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value });
|
||||
|
@ -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<GaugeOptions>(GaugePanel);
|
||||
|
||||
reactPanel.setEditor(GaugePanelEditor);
|
||||
reactPanel.setDefaults(defaults);
|
||||
|
@ -13,3 +13,17 @@ export interface GaugeOptions {
|
||||
thresholds: Threshold[];
|
||||
unit: string;
|
||||
}
|
||||
|
||||
export const defaults: GaugeOptions = {
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
prefix: '',
|
||||
showThresholdMarkers: true,
|
||||
showThresholdLabels: false,
|
||||
suffix: '',
|
||||
decimals: 0,
|
||||
stat: 'avg',
|
||||
unit: 'none',
|
||||
valueMappings: [],
|
||||
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