Commit 35e62bbb by Torkel Ödegaard

wip: react panel options architecture

parent dd4eab17
...@@ -21,6 +21,7 @@ export interface Props { ...@@ -21,6 +21,7 @@ export interface Props {
export interface State { export interface State {
refreshCounter: number; refreshCounter: number;
renderCounter: number;
timeRange?: TimeRange; timeRange?: TimeRange;
} }
...@@ -30,11 +31,13 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -30,11 +31,13 @@ export class PanelChrome extends PureComponent<Props, State> {
this.state = { this.state = {
refreshCounter: 0, refreshCounter: 0,
renderCounter: 0,
}; };
} }
componentDidMount() { componentDidMount() {
this.props.panel.events.on('refresh', this.onRefresh); this.props.panel.events.on('refresh', this.onRefresh);
this.props.panel.events.on('render', this.onRender);
this.props.dashboard.panelInitialized(this.props.panel); this.props.dashboard.panelInitialized(this.props.panel);
} }
...@@ -52,6 +55,13 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -52,6 +55,13 @@ export class PanelChrome extends PureComponent<Props, State> {
}); });
}; };
onRender = () => {
console.log('onRender');
this.setState({
renderCounter: this.state.renderCounter + 1,
});
};
get isVisible() { get isVisible() {
return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); return !this.props.dashboard.otherPanelInFullscreen(this.props.panel);
} }
...@@ -59,9 +69,11 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -59,9 +69,11 @@ export class PanelChrome extends PureComponent<Props, State> {
render() { render() {
const { panel, dashboard } = this.props; const { panel, dashboard } = this.props;
const { datasource, targets } = panel; const { datasource, targets } = panel;
const { refreshCounter, timeRange } = this.state; const { timeRange, renderCounter, refreshCounter } = this.state;
const PanelComponent = this.props.component; const PanelComponent = this.props.component;
console.log('Panel chrome render');
return ( return (
<div className="panel-container"> <div className="panel-container">
<PanelHeader panel={panel} dashboard={dashboard} /> <PanelHeader panel={panel} dashboard={dashboard} />
...@@ -74,7 +86,16 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -74,7 +86,16 @@ export class PanelChrome extends PureComponent<Props, State> {
refreshCounter={refreshCounter} refreshCounter={refreshCounter}
> >
{({ loading, timeSeries }) => { {({ loading, timeSeries }) => {
return <PanelComponent loading={loading} timeSeries={timeSeries} timeRange={timeRange} />; console.log('panelcrome inner render');
return (
<PanelComponent
loading={loading}
timeSeries={timeSeries}
timeRange={timeRange}
options={panel.getOptions()}
renderCounter={renderCounter}
/>
);
}} }}
</DataPanel> </DataPanel>
</div> </div>
......
import React from 'react'; import React, { PureComponent } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { store } from 'app/store/configureStore';
import { QueriesTab } from './QueriesTab'; import { QueriesTab } from './QueriesTab';
import { PanelPlugin, PluginExports } from 'app/types/plugins';
import { VizTypePicker } from './VizTypePicker'; import { VizTypePicker } from './VizTypePicker';
import { store } from 'app/store/configureStore';
import { updateLocation } from 'app/core/actions'; import { updateLocation } from 'app/core/actions';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { PanelPlugin, PluginExports } from 'app/types/plugins';
interface PanelEditorProps { interface PanelEditorProps {
panel: PanelModel; panel: PanelModel;
dashboard: DashboardModel; dashboard: DashboardModel;
...@@ -22,7 +25,7 @@ interface PanelEditorTab { ...@@ -22,7 +25,7 @@ interface PanelEditorTab {
icon: string; icon: string;
} }
export class PanelEditor extends React.Component<PanelEditorProps, any> { export class PanelEditor extends PureComponent<PanelEditorProps> {
tabs: PanelEditorTab[]; tabs: PanelEditorTab[];
constructor(props) { constructor(props) {
...@@ -39,16 +42,20 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> { ...@@ -39,16 +42,20 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
} }
renderPanelOptions() { renderPanelOptions() {
const { pluginExports } = this.props; const { pluginExports, panel } = this.props;
if (pluginExports.PanelOptions) { if (pluginExports.PanelOptionsComponent) {
const PanelOptions = pluginExports.PanelOptions; const OptionsComponent = pluginExports.PanelOptionsComponent;
return <PanelOptions />; return <OptionsComponent options={panel.getOptions()} onChange={this.onPanelOptionsChanged} />;
} else { } else {
return <p>Visualization has no options</p>; return <p>Visualization has no options</p>;
} }
} }
onPanelOptionsChanged = (options: any) => {
this.props.panel.updateOptions(options);
};
renderVizTab() { renderVizTab() {
return ( return (
<div className="viz-editor"> <div className="viz-editor">
...@@ -70,6 +77,7 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> { ...@@ -70,6 +77,7 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
partial: true, partial: true,
}) })
); );
this.forceUpdate();
}; };
render() { render() {
......
...@@ -60,6 +60,21 @@ export class PanelModel { ...@@ -60,6 +60,21 @@ export class PanelModel {
_.defaultsDeep(this, _.cloneDeep(defaults)); _.defaultsDeep(this, _.cloneDeep(defaults));
} }
getOptions() {
return this[this.getOptionsKey()] || {};
}
updateOptions(options: object) {
const update: any = {};
update[this.getOptionsKey()] = options;
Object.assign(this, update);
this.render();
}
private getOptionsKey() {
return this.type + 'Options';
}
getSaveModel() { getSaveModel() {
const model: any = {}; const model: any = {};
for (const property in this) { for (const property in this) {
...@@ -121,10 +136,6 @@ export class PanelModel { ...@@ -121,10 +136,6 @@ export class PanelModel {
this.events.emit('panel-initialized'); this.events.emit('panel-initialized');
} }
initEditMode() {
this.events.emit('panel-init-edit-mode');
}
changeType(pluginId: string) { changeType(pluginId: string) {
this.type = pluginId; this.type = pluginId;
......
...@@ -32,9 +32,9 @@ export class SettingsCtrl { ...@@ -32,9 +32,9 @@ export class SettingsCtrl {
this.$scope.$on('$destroy', () => { this.$scope.$on('$destroy', () => {
this.dashboard.updateSubmenuVisibility(); this.dashboard.updateSubmenuVisibility();
this.dashboard.startRefresh();
setTimeout(() => { setTimeout(() => {
this.$rootScope.appEvent('dash-scroll', { restore: true }); this.$rootScope.appEvent('dash-scroll', { restore: true });
this.dashboard.startRefresh();
}); });
}); });
......
// Libraries
import _ from 'lodash'; import _ from 'lodash';
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
// Components
import Graph from 'app/viz/Graph'; import Graph from 'app/viz/Graph';
import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
import { Switch } from 'app/core/components/Switch/Switch'; import { Switch } from 'app/core/components/Switch/Switch';
// Types import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
import { PanelProps, NullValueMode } from 'app/types'; import { PanelProps, NullValueMode } from 'app/types';
interface Options { interface Options {
...@@ -18,9 +15,7 @@ interface Options { ...@@ -18,9 +15,7 @@ interface Options {
onChange: (options: Options) => void; onChange: (options: Options) => void;
} }
interface Props extends PanelProps { interface Props extends PanelProps<Options> {}
options: Options;
}
export class Graph2 extends PureComponent<Props> { export class Graph2 extends PureComponent<Props> {
constructor(props) { constructor(props) {
...@@ -29,17 +24,26 @@ export class Graph2 extends PureComponent<Props> { ...@@ -29,17 +24,26 @@ export class Graph2 extends PureComponent<Props> {
render() { render() {
const { timeSeries, timeRange } = this.props; const { timeSeries, timeRange } = this.props;
const { showLines, showBars, showPoints } = this.props.options;
const vmSeries = getTimeSeriesVMs({ const vmSeries = getTimeSeriesVMs({
timeSeries: timeSeries, timeSeries: timeSeries,
nullValueMode: NullValueMode.Ignore, nullValueMode: NullValueMode.Ignore,
}); });
return <Graph timeSeries={vmSeries} timeRange={timeRange} />; return (
<Graph
timeSeries={vmSeries}
timeRange={timeRange}
showLines={showLines}
showPoints={showPoints}
showBars={showBars}
/>
);
} }
} }
export class TextOptions extends PureComponent<Options> { export class GraphOptions extends PureComponent<Options> {
onToggleLines = () => { onToggleLines = () => {
const options = this.props as Options; const options = this.props as Options;
...@@ -49,6 +53,15 @@ export class TextOptions extends PureComponent<Options> { ...@@ -49,6 +53,15 @@ export class TextOptions extends PureComponent<Options> {
}); });
}; };
onTogglePoints = () => {
const options = this.props as Options;
this.props.onChange({
...options,
showPoints: !this.props.showPoints,
});
};
render() { render() {
const { showBars, showPoints, showLines } = this.props; const { showBars, showPoints, showLines } = this.props;
...@@ -58,11 +71,11 @@ export class TextOptions extends PureComponent<Options> { ...@@ -58,11 +71,11 @@ export class TextOptions extends PureComponent<Options> {
<h5 className="page-heading">Draw Modes</h5> <h5 className="page-heading">Draw Modes</h5>
<Switch label="Lines" labelClass="width-5" checked={showLines} onChange={this.onToggleLines} /> <Switch label="Lines" labelClass="width-5" checked={showLines} onChange={this.onToggleLines} />
<Switch label="Bars" labelClass="width-5" checked={showBars} onChange={this.onToggleLines} /> <Switch label="Bars" labelClass="width-5" checked={showBars} onChange={this.onToggleLines} />
<Switch label="Points" labelClass="width-5" checked={showPoints} onChange={this.onToggleLines} /> <Switch label="Points" labelClass="width-5" checked={showPoints} onChange={this.onTogglePoints} />
</div> </div>
</div> </div>
); );
} }
} }
export { Graph2 as PanelComponent, TextOptions as PanelOptions }; export { Graph2 as PanelComponent, GraphOptions as PanelOptionsComponent };
import { LoadingState, TimeSeries, TimeRange } from './series'; import { LoadingState, TimeSeries, TimeRange } from './series';
export interface PanelProps { export interface PanelProps<T = any> {
timeSeries: TimeSeries[]; timeSeries: TimeSeries[];
timeRange: TimeRange; timeRange: TimeRange;
loading: LoadingState; loading: LoadingState;
options: T;
renderCounter: number;
}
export interface PanelOptionProps<T = any> {
options: T;
onChange: (options: T) => void;
} }
import { ComponentClass } from 'react';
import { PanelProps, PanelOptionProps } from './panel';
export interface PluginExports { export interface PluginExports {
PanelCtrl?;
PanelComponent?: any;
Datasource?: any; Datasource?: any;
QueryCtrl?: any; QueryCtrl?: any;
ConfigCtrl?: any; ConfigCtrl?: any;
AnnotationsQueryCtrl?: any; AnnotationsQueryCtrl?: any;
PanelOptions?: any;
ExploreQueryField?: any; ExploreQueryField?: any;
ExploreStartPage?: any; ExploreStartPage?: any;
// Panel plugin
PanelCtrl?;
PanelComponent?: ComponentClass<PanelProps>;
PanelOptionsComponent: ComponentClass<PanelOptionProps>;
} }
export interface PanelPlugin { export interface PanelPlugin {
......
...@@ -34,37 +34,22 @@ function time_format(ticks, min, max) { ...@@ -34,37 +34,22 @@ function time_format(ticks, min, max) {
return '%H:%M'; return '%H:%M';
} }
const FLOT_OPTIONS = {
legend: {
show: false,
},
series: {
lines: {
linewidth: 1,
zero: false,
},
shadowSize: 0,
},
grid: {
minBorderMargin: 0,
markings: [],
backgroundColor: null,
borderWidth: 0,
// hoverable: true,
clickable: true,
color: '#a1a1a1',
margin: { left: 0, right: 0 },
labelMarginX: 0,
},
};
interface GraphProps { interface GraphProps {
timeSeries: TimeSeriesVMs; timeSeries: TimeSeriesVMs;
timeRange: TimeRange; timeRange: TimeRange;
showLines?: boolean;
showPoints?: boolean;
showBars?: boolean;
size?: { width: number; height: number }; size?: { width: number; height: number };
} }
export class Graph extends PureComponent<GraphProps> { export class Graph extends PureComponent<GraphProps> {
static defaultProps = {
showLines: true,
showPoints: false,
showBars: false,
};
element: any; element: any;
componentDidUpdate(prevProps: GraphProps) { componentDidUpdate(prevProps: GraphProps) {
...@@ -82,7 +67,7 @@ export class Graph extends PureComponent<GraphProps> { ...@@ -82,7 +67,7 @@ export class Graph extends PureComponent<GraphProps> {
} }
draw() { draw() {
const { size, timeSeries, timeRange } = this.props; const { size, timeSeries, timeRange, showLines, showBars, showPoints } = this.props;
if (!size) { if (!size) {
return; return;
...@@ -92,7 +77,31 @@ export class Graph extends PureComponent<GraphProps> { ...@@ -92,7 +77,31 @@ export class Graph extends PureComponent<GraphProps> {
const min = timeRange.from.valueOf(); const min = timeRange.from.valueOf();
const max = timeRange.to.valueOf(); const max = timeRange.to.valueOf();
const dynamicOptions = { const flotOptions = {
legend: {
show: false,
},
series: {
lines: {
show: showLines,
linewidth: 1,
zero: false,
},
points: {
show: showPoints,
fill: 1,
fillColor: false,
radius: 2,
},
bars: {
show: showBars,
fill: 1,
barWidth: 1,
zero: false,
lineWidth: 0,
},
shadowSize: 0,
},
xaxis: { xaxis: {
mode: 'time', mode: 'time',
min: min, min: min,
...@@ -101,15 +110,24 @@ export class Graph extends PureComponent<GraphProps> { ...@@ -101,15 +110,24 @@ export class Graph extends PureComponent<GraphProps> {
ticks: ticks, ticks: ticks,
timeformat: time_format(ticks, min, max), timeformat: time_format(ticks, min, max),
}, },
grid: {
minBorderMargin: 0,
markings: [],
backgroundColor: null,
borderWidth: 0,
// hoverable: true,
clickable: true,
color: '#a1a1a1',
margin: { left: 0, right: 0 },
labelMarginX: 0,
},
}; };
const options = { try {
...FLOT_OPTIONS, $.plot(this.element, timeSeries, flotOptions);
...dynamicOptions, } catch (err) {
}; console.log('Graph rendering error', err, flotOptions, timeSeries);
}
console.log('plot', timeSeries, options);
$.plot(this.element, timeSeries, options);
} }
render() { render() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment