From dd4eab17222dcc8e3efc74d66a71e3845ad1e658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 5 Nov 2018 13:44:09 +0100 Subject: [PATCH 1/5] panel options wip --- public/app/plugins/panel/graph2/module.tsx | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 4011458bea9..7bb2ab48e40 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -12,6 +12,10 @@ import { PanelProps, NullValueMode } from 'app/types'; interface Options { showBars: boolean; + showLines: boolean; + showPoints: boolean; + + onChange: (options: Options) => void; } interface Props extends PanelProps { @@ -35,14 +39,27 @@ export class Graph2 extends PureComponent { } } -export class TextOptions extends PureComponent { - onChange = () => {}; +export class TextOptions extends PureComponent { + onToggleLines = () => { + const options = this.props as Options; + + this.props.onChange({ + ...options, + showLines: !this.props.showLines, + }); + }; render() { + const { showBars, showPoints, showLines } = this.props; + return ( -
-
Draw Modes
- +
+
+
Draw Modes
+ + + +
); } From 35e62bbbe0eebfc9b2cc025800c4f3982c55e2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 5 Nov 2018 17:46:09 +0100 Subject: [PATCH 2/5] wip: react panel options architecture --- .../dashboard/dashgrid/PanelChrome.tsx | 25 +++++- .../dashboard/dashgrid/PanelEditor.tsx | 28 ++++--- public/app/features/dashboard/panel_model.ts | 19 ++++- .../features/dashboard/settings/settings.ts | 2 +- public/app/plugins/panel/graph2/module.tsx | 35 +++++--- public/app/types/panel.ts | 9 +- public/app/types/plugins.ts | 11 ++- public/app/viz/Graph.tsx | 84 +++++++++++-------- 8 files changed, 148 insertions(+), 65 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 82b366d8126..953dfd62368 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -21,6 +21,7 @@ export interface Props { export interface State { refreshCounter: number; + renderCounter: number; timeRange?: TimeRange; } @@ -30,11 +31,13 @@ export class PanelChrome extends PureComponent { this.state = { refreshCounter: 0, + renderCounter: 0, }; } componentDidMount() { this.props.panel.events.on('refresh', this.onRefresh); + this.props.panel.events.on('render', this.onRender); this.props.dashboard.panelInitialized(this.props.panel); } @@ -52,6 +55,13 @@ export class PanelChrome extends PureComponent { }); }; + onRender = () => { + console.log('onRender'); + this.setState({ + renderCounter: this.state.renderCounter + 1, + }); + }; + get isVisible() { return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); } @@ -59,9 +69,11 @@ export class PanelChrome extends PureComponent { render() { const { panel, dashboard } = this.props; const { datasource, targets } = panel; - const { refreshCounter, timeRange } = this.state; + const { timeRange, renderCounter, refreshCounter } = this.state; const PanelComponent = this.props.component; + console.log('Panel chrome render'); + return (
@@ -74,7 +86,16 @@ export class PanelChrome extends PureComponent { refreshCounter={refreshCounter} > {({ loading, timeSeries }) => { - return ; + console.log('panelcrome inner render'); + return ( + + ); }}
diff --git a/public/app/features/dashboard/dashgrid/PanelEditor.tsx b/public/app/features/dashboard/dashgrid/PanelEditor.tsx index 26ac8b7d2c1..9d98621f9b6 100644 --- a/public/app/features/dashboard/dashgrid/PanelEditor.tsx +++ b/public/app/features/dashboard/dashgrid/PanelEditor.tsx @@ -1,12 +1,15 @@ -import React from 'react'; +import React, { PureComponent } from 'react'; import classNames from 'classnames'; + +import { QueriesTab } from './QueriesTab'; +import { VizTypePicker } from './VizTypePicker'; + +import { store } from 'app/store/configureStore'; +import { updateLocation } from 'app/core/actions'; + import { PanelModel } from '../panel_model'; import { DashboardModel } from '../dashboard_model'; -import { store } from 'app/store/configureStore'; -import { QueriesTab } from './QueriesTab'; import { PanelPlugin, PluginExports } from 'app/types/plugins'; -import { VizTypePicker } from './VizTypePicker'; -import { updateLocation } from 'app/core/actions'; interface PanelEditorProps { panel: PanelModel; @@ -22,7 +25,7 @@ interface PanelEditorTab { icon: string; } -export class PanelEditor extends React.Component { +export class PanelEditor extends PureComponent { tabs: PanelEditorTab[]; constructor(props) { @@ -39,16 +42,20 @@ export class PanelEditor extends React.Component { } renderPanelOptions() { - const { pluginExports } = this.props; + const { pluginExports, panel } = this.props; - if (pluginExports.PanelOptions) { - const PanelOptions = pluginExports.PanelOptions; - return ; + if (pluginExports.PanelOptionsComponent) { + const OptionsComponent = pluginExports.PanelOptionsComponent; + return ; } else { return

Visualization has no options

; } } + onPanelOptionsChanged = (options: any) => { + this.props.panel.updateOptions(options); + }; + renderVizTab() { return (
@@ -70,6 +77,7 @@ export class PanelEditor extends React.Component { partial: true, }) ); + this.forceUpdate(); }; render() { diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index d82368d8dd7..ed032a118fe 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -60,6 +60,21 @@ export class PanelModel { _.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() { const model: any = {}; for (const property in this) { @@ -121,10 +136,6 @@ export class PanelModel { this.events.emit('panel-initialized'); } - initEditMode() { - this.events.emit('panel-init-edit-mode'); - } - changeType(pluginId: string) { this.type = pluginId; diff --git a/public/app/features/dashboard/settings/settings.ts b/public/app/features/dashboard/settings/settings.ts index b6a70ee4b98..1e8d96a54cb 100755 --- a/public/app/features/dashboard/settings/settings.ts +++ b/public/app/features/dashboard/settings/settings.ts @@ -32,9 +32,9 @@ export class SettingsCtrl { this.$scope.$on('$destroy', () => { this.dashboard.updateSubmenuVisibility(); - this.dashboard.startRefresh(); setTimeout(() => { this.$rootScope.appEvent('dash-scroll', { restore: true }); + this.dashboard.startRefresh(); }); }); diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 7bb2ab48e40..68068268dd4 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -1,13 +1,10 @@ -// Libraries import _ from 'lodash'; import React, { PureComponent } from 'react'; -// Components import Graph from 'app/viz/Graph'; -import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; import { Switch } from 'app/core/components/Switch/Switch'; -// Types +import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; import { PanelProps, NullValueMode } from 'app/types'; interface Options { @@ -18,9 +15,7 @@ interface Options { onChange: (options: Options) => void; } -interface Props extends PanelProps { - options: Options; -} +interface Props extends PanelProps {} export class Graph2 extends PureComponent { constructor(props) { @@ -29,17 +24,26 @@ export class Graph2 extends PureComponent { render() { const { timeSeries, timeRange } = this.props; + const { showLines, showBars, showPoints } = this.props.options; const vmSeries = getTimeSeriesVMs({ timeSeries: timeSeries, nullValueMode: NullValueMode.Ignore, }); - return ; + return ( + + ); } } -export class TextOptions extends PureComponent { +export class GraphOptions extends PureComponent { onToggleLines = () => { const options = this.props as Options; @@ -49,6 +53,15 @@ export class TextOptions extends PureComponent { }); }; + onTogglePoints = () => { + const options = this.props as Options; + + this.props.onChange({ + ...options, + showPoints: !this.props.showPoints, + }); + }; + render() { const { showBars, showPoints, showLines } = this.props; @@ -58,11 +71,11 @@ export class TextOptions extends PureComponent {
Draw Modes
- +
); } } -export { Graph2 as PanelComponent, TextOptions as PanelOptions }; +export { Graph2 as PanelComponent, GraphOptions as PanelOptionsComponent }; diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 5ece77fc5aa..5207c17ada9 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -1,7 +1,14 @@ import { LoadingState, TimeSeries, TimeRange } from './series'; -export interface PanelProps { +export interface PanelProps { timeSeries: TimeSeries[]; timeRange: TimeRange; loading: LoadingState; + options: T; + renderCounter: number; +} + +export interface PanelOptionProps { + options: T; + onChange: (options: T) => void; } diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 1b5499f88b7..4b172c0eef4 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -1,13 +1,18 @@ +import { ComponentClass } from 'react'; +import { PanelProps, PanelOptionProps } from './panel'; + export interface PluginExports { - PanelCtrl?; - PanelComponent?: any; Datasource?: any; QueryCtrl?: any; ConfigCtrl?: any; AnnotationsQueryCtrl?: any; - PanelOptions?: any; ExploreQueryField?: any; ExploreStartPage?: any; + + // Panel plugin + PanelCtrl?; + PanelComponent?: ComponentClass; + PanelOptionsComponent: ComponentClass; } export interface PanelPlugin { diff --git a/public/app/viz/Graph.tsx b/public/app/viz/Graph.tsx index fab65225715..5d99f4e0c7f 100644 --- a/public/app/viz/Graph.tsx +++ b/public/app/viz/Graph.tsx @@ -34,37 +34,22 @@ function time_format(ticks, min, max) { 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 { timeSeries: TimeSeriesVMs; timeRange: TimeRange; + showLines?: boolean; + showPoints?: boolean; + showBars?: boolean; size?: { width: number; height: number }; } export class Graph extends PureComponent { + static defaultProps = { + showLines: true, + showPoints: false, + showBars: false, + }; + element: any; componentDidUpdate(prevProps: GraphProps) { @@ -82,7 +67,7 @@ export class Graph extends PureComponent { } draw() { - const { size, timeSeries, timeRange } = this.props; + const { size, timeSeries, timeRange, showLines, showBars, showPoints } = this.props; if (!size) { return; @@ -92,7 +77,31 @@ export class Graph extends PureComponent { const min = timeRange.from.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: { mode: 'time', min: min, @@ -101,15 +110,24 @@ export class Graph extends PureComponent { ticks: ticks, 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 = { - ...FLOT_OPTIONS, - ...dynamicOptions, - }; - - console.log('plot', timeSeries, options); - $.plot(this.element, timeSeries, options); + try { + $.plot(this.element, timeSeries, flotOptions); + } catch (err) { + console.log('Graph rendering error', err, flotOptions, timeSeries); + } } render() { From 9393b06166564bd80d483aff48fef145d35e6e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 5 Nov 2018 10:31:39 -0800 Subject: [PATCH 3/5] basic panel options working --- .../dashboard/dashgrid/PanelEditor.tsx | 1 + public/app/plugins/panel/graph2/module.tsx | 27 ++++++++++--------- public/app/types/index.ts | 3 ++- public/app/types/panel.ts | 2 +- public/app/types/plugins.ts | 4 +-- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelEditor.tsx b/public/app/features/dashboard/dashgrid/PanelEditor.tsx index 9d98621f9b6..371ed22fff7 100644 --- a/public/app/features/dashboard/dashgrid/PanelEditor.tsx +++ b/public/app/features/dashboard/dashgrid/PanelEditor.tsx @@ -54,6 +54,7 @@ export class PanelEditor extends PureComponent { onPanelOptionsChanged = (options: any) => { this.props.panel.updateOptions(options); + this.forceUpdate(); }; renderVizTab() { diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 68068268dd4..a666d762062 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -5,7 +5,7 @@ import Graph from 'app/viz/Graph'; import { Switch } from 'app/core/components/Switch/Switch'; import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; -import { PanelProps, NullValueMode } from 'app/types'; +import { PanelProps, PanelOptionsProps, NullValueMode } from 'app/types'; interface Options { showBars: boolean; @@ -43,34 +43,37 @@ export class Graph2 extends PureComponent { } } -export class GraphOptions extends PureComponent { +export class GraphOptions extends PureComponent> { onToggleLines = () => { - const options = this.props as Options; - this.props.onChange({ - ...options, - showLines: !this.props.showLines, + ...this.props.options, + showLines: !this.props.options.showLines, + }); + }; + + onToggleBars = () => { + this.props.onChange({ + ...this.props.options, + showBars: !this.props.options.showBars, }); }; onTogglePoints = () => { - const options = this.props as Options; - this.props.onChange({ - ...options, - showPoints: !this.props.showPoints, + ...this.props.options, + showPoints: !this.props.options.showPoints, }); }; render() { - const { showBars, showPoints, showLines } = this.props; + const { showBars, showPoints, showLines } = this.props.options; return (
Draw Modes
- +
diff --git a/public/app/types/index.ts b/public/app/types/index.ts index c51622682d4..fc176fed7e2 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -20,7 +20,7 @@ import { DataQueryResponse, DataQueryOptions, } from './series'; -import { PanelProps } from './panel'; +import { PanelProps, PanelOptionsProps } from './panel'; import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins'; import { Organization, OrganizationPreferences, OrganizationState } from './organization'; import { @@ -69,6 +69,7 @@ export { TimeRange, LoadingState, PanelProps, + PanelOptionsProps, TimeSeries, TimeSeriesVM, TimeSeriesVMs, diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 5207c17ada9..7febd0cad26 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -8,7 +8,7 @@ export interface PanelProps { renderCounter: number; } -export interface PanelOptionProps { +export interface PanelOptionsProps { options: T; onChange: (options: T) => void; } diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 4b172c0eef4..817777669d8 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -1,5 +1,5 @@ import { ComponentClass } from 'react'; -import { PanelProps, PanelOptionProps } from './panel'; +import { PanelProps, PanelOptionsProps } from './panel'; export interface PluginExports { Datasource?: any; @@ -12,7 +12,7 @@ export interface PluginExports { // Panel plugin PanelCtrl?; PanelComponent?: ComponentClass; - PanelOptionsComponent: ComponentClass; + PanelOptionsComponent: ComponentClass; } export interface PanelPlugin { From b9612aaa231b54cf2973b486fb35916a38e9e0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 5 Nov 2018 10:38:55 -0800 Subject: [PATCH 4/5] minor code style change --- public/app/plugins/panel/graph2/module.tsx | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index a666d762062..837109f6be7 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -45,24 +45,15 @@ export class Graph2 extends PureComponent { export class GraphOptions extends PureComponent> { onToggleLines = () => { - this.props.onChange({ - ...this.props.options, - showLines: !this.props.options.showLines, - }); + this.props.onChange({ showLines: !this.props.options.showLines, ...this.props.options }); }; onToggleBars = () => { - this.props.onChange({ - ...this.props.options, - showBars: !this.props.options.showBars, - }); + this.props.onChange({ showBars: !this.props.options.showBars, ...this.props.options }); }; onTogglePoints = () => { - this.props.onChange({ - ...this.props.options, - showPoints: !this.props.options.showPoints, - }); + this.props.onChange({ showPoints: !this.props.options.showPoints, ...this.props.options }); }; render() { From 562411af1af4c62cbbc1f92ee6e231b65f785651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 6 Nov 2018 07:23:02 +0100 Subject: [PATCH 5/5] fixed options --- public/app/plugins/panel/graph2/module.tsx | 6 +-- public/app/viz/Graph.tsx | 52 +++++++++++----------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 837109f6be7..b132d3374f1 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -45,15 +45,15 @@ export class Graph2 extends PureComponent { export class GraphOptions extends PureComponent> { onToggleLines = () => { - this.props.onChange({ showLines: !this.props.options.showLines, ...this.props.options }); + this.props.onChange({ ...this.props.options, showLines: !this.props.options.showLines }); }; onToggleBars = () => { - this.props.onChange({ showBars: !this.props.options.showBars, ...this.props.options }); + this.props.onChange({ ...this.props.options, showBars: !this.props.options.showBars }); }; onTogglePoints = () => { - this.props.onChange({ showPoints: !this.props.options.showPoints, ...this.props.options }); + this.props.onChange({ ...this.props.options, showPoints: !this.props.options.showPoints }); }; render() { diff --git a/public/app/viz/Graph.tsx b/public/app/viz/Graph.tsx index 5d99f4e0c7f..566080fbc92 100644 --- a/public/app/viz/Graph.tsx +++ b/public/app/viz/Graph.tsx @@ -8,32 +8,6 @@ import 'vendor/flot/jquery.flot.time'; // Types import { TimeRange, TimeSeriesVMs } from 'app/types'; -// Copied from graph.ts -function time_format(ticks, min, max) { - if (min && max && ticks) { - const range = max - min; - const secPerTick = range / ticks / 1000; - const oneDay = 86400000; - const oneYear = 31536000000; - - if (secPerTick <= 45) { - return '%H:%M:%S'; - } - if (secPerTick <= 7200 || range <= oneDay) { - return '%H:%M'; - } - if (secPerTick <= 80000) { - return '%m/%d %H:%M'; - } - if (secPerTick <= 2419200 || range <= oneYear) { - return '%m/%d'; - } - return '%Y-%m'; - } - - return '%H:%M'; -} - interface GraphProps { timeSeries: TimeSeriesVMs; timeRange: TimeRange; @@ -139,4 +113,30 @@ export class Graph extends PureComponent { } } +// Copied from graph.ts +function time_format(ticks, min, max) { + if (min && max && ticks) { + const range = max - min; + const secPerTick = range / ticks / 1000; + const oneDay = 86400000; + const oneYear = 31536000000; + + if (secPerTick <= 45) { + return '%H:%M:%S'; + } + if (secPerTick <= 7200 || range <= oneDay) { + return '%H:%M'; + } + if (secPerTick <= 80000) { + return '%m/%d %H:%M'; + } + if (secPerTick <= 2419200 || range <= oneYear) { + return '%m/%d'; + } + return '%Y-%m'; + } + + return '%H:%M'; +} + export default withSize()(Graph);