From 8d9c347cb1b2cec4b3a84104c72db8be1b5cac91 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:22:16 +0100 Subject: [PATCH 01/20] fix: Add missing typing --- public/app/plugins/panel/graph2/GraphPanel.tsx | 4 ++-- public/app/plugins/panel/text2/module.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/panel/graph2/GraphPanel.tsx b/public/app/plugins/panel/graph2/GraphPanel.tsx index 01e5b2d819d..f1fc2b43d51 100644 --- a/public/app/plugins/panel/graph2/GraphPanel.tsx +++ b/public/app/plugins/panel/graph2/GraphPanel.tsx @@ -9,7 +9,7 @@ import { processTimeSeries } from '@grafana/ui/src/utils'; import { Graph } from '@grafana/ui'; // Types -import { PanelProps, NullValueMode } from '@grafana/ui/src/types'; +import { PanelProps, NullValueMode, TimeSeriesVMs } from '@grafana/ui/src/types'; import { Options } from './types'; interface Props extends PanelProps {} @@ -19,7 +19,7 @@ export class GraphPanel extends PureComponent { const { panelData, timeRange, width, height } = this.props; const { showLines, showBars, showPoints } = this.props.options; - let vmSeries; + let vmSeries: TimeSeriesVMs; if (panelData.timeSeries) { vmSeries = processTimeSeries({ timeSeries: panelData.timeSeries, diff --git a/public/app/plugins/panel/text2/module.tsx b/public/app/plugins/panel/text2/module.tsx index 68523ff0880..cc3ec016273 100644 --- a/public/app/plugins/panel/text2/module.tsx +++ b/public/app/plugins/panel/text2/module.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { PanelProps } from '@grafana/ui'; export class Text2 extends PureComponent { - constructor(props) { + constructor(props: PanelProps) { super(props); } From a8a9bca07b04f7a92975edecdd8b1d3645b28ef1 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:26:23 +0100 Subject: [PATCH 02/20] feat: Introduce IsDataPanel attribute to plugin.json --- pkg/api/frontendsettings.go | 1 + pkg/plugins/models.go | 1 + public/app/plugins/panel/gauge/plugin.json | 1 + public/app/plugins/panel/graph2/plugin.json | 2 +- public/app/plugins/panel/text2/plugin.json | 2 +- public/app/types/plugins.ts | 1 + 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index ed7054050e4..238a3965641 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -145,6 +145,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf "info": panel.Info, "hideFromList": panel.HideFromList, "sort": getPanelSort(panel.Id), + "isDataPanel": panel.IsDataPanel, } } diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 5ac436205c1..e37b1fcf7d9 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -47,6 +47,7 @@ type PluginBase struct { BaseUrl string `json:"baseUrl"` HideFromList bool `json:"hideFromList,omitempty"` State PluginState `json:"state,omitempty"` + IsDataPanel bool `json:"isDataPanel"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` diff --git a/public/app/plugins/panel/gauge/plugin.json b/public/app/plugins/panel/gauge/plugin.json index 58437779d25..733d2281cf4 100644 --- a/public/app/plugins/panel/gauge/plugin.json +++ b/public/app/plugins/panel/gauge/plugin.json @@ -2,6 +2,7 @@ "type": "panel", "name": "Gauge", "id": "gauge", + "isDataPanel": true, "info": { "author": { diff --git a/public/app/plugins/panel/graph2/plugin.json b/public/app/plugins/panel/graph2/plugin.json index 9cb6a1f78a4..9b2a915a597 100644 --- a/public/app/plugins/panel/graph2/plugin.json +++ b/public/app/plugins/panel/graph2/plugin.json @@ -2,7 +2,7 @@ "type": "panel", "name": "React Graph", "id": "graph2", - + "isDataPanel": true, "state": "alpha", "info": { diff --git a/public/app/plugins/panel/text2/plugin.json b/public/app/plugins/panel/text2/plugin.json index 53885dbd0f4..cd4ff424d89 100644 --- a/public/app/plugins/panel/text2/plugin.json +++ b/public/app/plugins/panel/text2/plugin.json @@ -2,8 +2,8 @@ "type": "panel", "name": "Text v2", "id": "text2", - "state": "alpha", + "isDataPanel": false, "info": { "author": { diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 51c3b7b0476..0c5c53eb6f0 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -9,6 +9,7 @@ export interface PanelPlugin { info: any; sort: number; exports?: PluginExports; + isDataPanel?: boolean; } export interface Plugin { From 8d4caa593e924304f3dccdb06b541bf0bed69972 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:31:05 +0100 Subject: [PATCH 03/20] feat: Add util to convert snapshotData to PanelData --- public/app/features/dashboard/utils/panel.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index c0d753477a7..c60a153d889 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -4,7 +4,8 @@ import store from 'app/core/store'; // Models import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { TimeRange } from '@grafana/ui'; +import { PanelData, TimeRange, TimeSeries } from '@grafana/ui'; +import { TableData } from '@grafana/ui/src'; // Utils import { isString as _isString } from 'lodash'; @@ -168,3 +169,19 @@ export function getResolution(panel: PanelModel): number { return panel.maxDataPoints ? panel.maxDataPoints : Math.ceil(width * (panel.gridPos.w / 24)); } + +const isTimeSeries = (data: any): data is TimeSeries => data && data.hasOwnProperty('datapoints'); +const isTableData = (data: any): data is TableData => data && data.hasOwnProperty('columns'); +export const snapshotDataToPanelData = (panel: PanelModel): PanelData => { + const snapshotData = panel.snapshotData; + if (isTimeSeries(snapshotData[0])) { + return { + timeSeries: snapshotData + } as PanelData; + } else if (isTableData(snapshotData[0])) { + return { + tableData: snapshotData[0] + } as PanelData; + } + throw new Error('snapshotData is invalid:' + snapshotData.toString()); +}; From ec02ddd27b1c595fad0d721bde261022057602ec Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:34:50 +0100 Subject: [PATCH 04/20] feat: Only use the DataPanel component when panel plugin has isDataPanel set to true in plugin.json. And fix PanelData when using snapshots --- .../dashboard/dashgrid/PanelChrome.tsx | 64 ++++++++++++------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index b02d9479dcc..1f9a2a32a5d 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -10,14 +10,14 @@ import { PanelHeader } from './PanelHeader/PanelHeader'; import { DataPanel } from './DataPanel'; // Utils -import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; +import { applyPanelTimeOverrides, snapshotDataToPanelData } from 'app/features/dashboard/utils/panel'; import { PANEL_HEADER_HEIGHT } from 'app/core/constants'; import { profiler } from 'app/core/profiler'; // Types import { DashboardModel, PanelModel } from '../state'; import { PanelPlugin } from 'app/types'; -import { TimeRange, LoadingState } from '@grafana/ui'; +import { TimeRange, LoadingState, PanelData } from '@grafana/ui'; import variables from 'sass/_variables.scss'; import templateSrv from 'app/features/templating/template_srv'; @@ -94,7 +94,7 @@ export class PanelChrome extends PureComponent { return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); } - renderPanel(loading, panelData, width, height): JSX.Element { + 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; @@ -121,11 +121,45 @@ export class PanelChrome extends PureComponent { ); } + renderHelper = (width: number, height: number): JSX.Element => { + const { panel, plugin } = this.props; + const { refreshCounter, timeRange } = this.state; + const { datasource, targets } = panel; + return ( + <> + {panel.snapshotData && panel.snapshotData.length > 0 ? ( + this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) + ) : ( + <> + {plugin.isDataPanel === true ? + + {({ loading, panelData }) => { + return this.renderPanelPlugin(loading, panelData, width, height); + }} + + : ( + this.renderPanelPlugin(LoadingState.Done, null, width, height) + )} + + )} + + ); + } + + render() { - const { panel, dashboard } = this.props; - const { refreshCounter, timeRange, timeInfo } = this.state; + const { dashboard, panel } = this.props; + const { timeInfo } = this.state; + const { transparent } = panel; - const { datasource, targets, transparent } = panel; const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`; return ( @@ -145,23 +179,7 @@ export class PanelChrome extends PureComponent { scopedVars={panel.scopedVars} links={panel.links} /> - {panel.snapshotData ? ( - this.renderPanel(false, panel.snapshotData, width, height) - ) : ( - - {({ loading, panelData }) => { - return this.renderPanel(loading, panelData, width, height); - }} - - )} + {this.renderHelper(width, height)} ); }} From 0019e0ffc9fc4d9e7768165b2022d18624528d2f Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 11 Feb 2019 16:20:32 +0100 Subject: [PATCH 05/20] chore: Only show Queries tab for panel plugins with isDataPanel set to true --- .../dashboard/panel_editor/PanelEditor.tsx | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index bfdc13bc8f2..37240389373 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -30,6 +30,32 @@ interface PanelEditorTab { text: string; } +enum PanelEditorTabIds { + Queries = 'queries', + Visualization = 'visualization', + Advanced = 'advanced', + Alert = 'alert' +} + +interface PanelEditorTab { + id: string; + text: string; +} + +const panelEditorTabTexts = { + [PanelEditorTabIds.Queries]: 'Queries', + [PanelEditorTabIds.Visualization]: 'Visualization', + [PanelEditorTabIds.Advanced]: 'Panel Options', + [PanelEditorTabIds.Alert]: 'Alert', +}; + +const getPanelEditorTab = (tabId: PanelEditorTabIds): PanelEditorTab => { + return { + id: tabId, + text: panelEditorTabTexts[tabId] + }; +}; + export class PanelEditor extends PureComponent { constructor(props) { super(props); @@ -72,31 +98,26 @@ export class PanelEditor extends PureComponent { render() { const { plugin } = this.props; - let activeTab = store.getState().location.query.tab || 'queries'; + let activeTab: PanelEditorTabIds = store.getState().location.query.tab || PanelEditorTabIds.Queries; const tabs: PanelEditorTab[] = [ - { id: 'queries', text: 'Queries' }, - { id: 'visualization', text: 'Visualization' }, - { id: 'advanced', text: 'Panel Options' }, + getPanelEditorTab(PanelEditorTabIds.Queries), + getPanelEditorTab(PanelEditorTabIds.Visualization), + getPanelEditorTab(PanelEditorTabIds.Advanced), ]; // handle panels that do not have queries tab - if (plugin.exports.PanelCtrl) { - if (!plugin.exports.PanelCtrl.prototype.onDataReceived) { - // remove queries tab - tabs.shift(); - // switch tab - if (activeTab === 'queries') { - activeTab = 'visualization'; - } + if (!plugin.isDataPanel) { + // remove queries tab + tabs.shift(); + // switch tab + if (activeTab === PanelEditorTabIds.Queries) { + activeTab = PanelEditorTabIds.Visualization; } } if (config.alertingEnabled && plugin.id === 'graph') { - tabs.push({ - id: 'alert', - text: 'Alert', - }); + tabs.push(getPanelEditorTab(PanelEditorTabIds.Alert)); } return ( From 2db9cb3d93f1a44e859a176ca41c541445856fae Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 09:48:46 +0100 Subject: [PATCH 06/20] chore: Rename isDataPanel to noQueries --- pkg/api/frontendsettings.go | 2 +- pkg/plugins/models.go | 2 +- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 8 ++++---- .../app/features/dashboard/panel_editor/PanelEditor.tsx | 2 +- public/app/plugins/panel/gauge/plugin.json | 1 - public/app/plugins/panel/graph2/plugin.json | 1 - public/app/plugins/panel/text2/plugin.json | 2 +- public/app/types/plugins.ts | 2 +- 8 files changed, 9 insertions(+), 11 deletions(-) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 238a3965641..cb401577140 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -145,7 +145,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf "info": panel.Info, "hideFromList": panel.HideFromList, "sort": getPanelSort(panel.Id), - "isDataPanel": panel.IsDataPanel, + "noQueries": panel.NoQueries, } } diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index e37b1fcf7d9..7584981fc6c 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -47,7 +47,7 @@ type PluginBase struct { BaseUrl string `json:"baseUrl"` HideFromList bool `json:"hideFromList,omitempty"` State PluginState `json:"state,omitempty"` - IsDataPanel bool `json:"isDataPanel"` + NoQueries bool `json:"noQueries"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 1f9a2a32a5d..d658ace43dd 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -131,8 +131,10 @@ export class PanelChrome extends PureComponent { this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) ) : ( <> - {plugin.isDataPanel === true ? - { return this.renderPanelPlugin(loading, panelData, width, height); }} - : ( - this.renderPanelPlugin(LoadingState.Done, null, width, height) )} )} diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index 37240389373..31274a6ad26 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -107,7 +107,7 @@ export class PanelEditor extends PureComponent { ]; // handle panels that do not have queries tab - if (!plugin.isDataPanel) { + if (plugin.noQueries === true) { // remove queries tab tabs.shift(); // switch tab diff --git a/public/app/plugins/panel/gauge/plugin.json b/public/app/plugins/panel/gauge/plugin.json index 733d2281cf4..58437779d25 100644 --- a/public/app/plugins/panel/gauge/plugin.json +++ b/public/app/plugins/panel/gauge/plugin.json @@ -2,7 +2,6 @@ "type": "panel", "name": "Gauge", "id": "gauge", - "isDataPanel": true, "info": { "author": { diff --git a/public/app/plugins/panel/graph2/plugin.json b/public/app/plugins/panel/graph2/plugin.json index 9b2a915a597..b11f93c9adc 100644 --- a/public/app/plugins/panel/graph2/plugin.json +++ b/public/app/plugins/panel/graph2/plugin.json @@ -2,7 +2,6 @@ "type": "panel", "name": "React Graph", "id": "graph2", - "isDataPanel": true, "state": "alpha", "info": { diff --git a/public/app/plugins/panel/text2/plugin.json b/public/app/plugins/panel/text2/plugin.json index cd4ff424d89..661ac4671ef 100644 --- a/public/app/plugins/panel/text2/plugin.json +++ b/public/app/plugins/panel/text2/plugin.json @@ -3,7 +3,7 @@ "name": "Text v2", "id": "text2", "state": "alpha", - "isDataPanel": false, + "noQueries": true, "info": { "author": { diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 0c5c53eb6f0..101f649eda9 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -9,7 +9,7 @@ export interface PanelPlugin { info: any; sort: number; exports?: PluginExports; - isDataPanel?: boolean; + noQueries?: boolean; } export interface Plugin { From be58e275a5093aaa1c39f6921b322df34b8d5f69 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 09:55:09 +0100 Subject: [PATCH 07/20] chore: PR feedback, shorten boolean check --- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 2 +- public/app/features/dashboard/panel_editor/PanelEditor.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index d658ace43dd..3be9c361a83 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -131,7 +131,7 @@ export class PanelChrome extends PureComponent { this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) ) : ( <> - {plugin.noQueries === true ? + {plugin.noQueries ? this.renderPanelPlugin(LoadingState.Done, null, width, height) : ( { ]; // handle panels that do not have queries tab - if (plugin.noQueries === true) { + if (plugin.noQueries) { // remove queries tab tabs.shift(); // switch tab From 0811fbd6d0909b0d22beecf64f7969b7475af9d8 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:22:16 +0100 Subject: [PATCH 08/20] fix: Add missing typing --- public/app/plugins/panel/graph2/GraphPanel.tsx | 4 ++-- public/app/plugins/panel/text2/module.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/panel/graph2/GraphPanel.tsx b/public/app/plugins/panel/graph2/GraphPanel.tsx index 01e5b2d819d..f1fc2b43d51 100644 --- a/public/app/plugins/panel/graph2/GraphPanel.tsx +++ b/public/app/plugins/panel/graph2/GraphPanel.tsx @@ -9,7 +9,7 @@ import { processTimeSeries } from '@grafana/ui/src/utils'; import { Graph } from '@grafana/ui'; // Types -import { PanelProps, NullValueMode } from '@grafana/ui/src/types'; +import { PanelProps, NullValueMode, TimeSeriesVMs } from '@grafana/ui/src/types'; import { Options } from './types'; interface Props extends PanelProps {} @@ -19,7 +19,7 @@ export class GraphPanel extends PureComponent { const { panelData, timeRange, width, height } = this.props; const { showLines, showBars, showPoints } = this.props.options; - let vmSeries; + let vmSeries: TimeSeriesVMs; if (panelData.timeSeries) { vmSeries = processTimeSeries({ timeSeries: panelData.timeSeries, diff --git a/public/app/plugins/panel/text2/module.tsx b/public/app/plugins/panel/text2/module.tsx index 68523ff0880..cc3ec016273 100644 --- a/public/app/plugins/panel/text2/module.tsx +++ b/public/app/plugins/panel/text2/module.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { PanelProps } from '@grafana/ui'; export class Text2 extends PureComponent { - constructor(props) { + constructor(props: PanelProps) { super(props); } From c4b2dcefbe88cfe84793fcf0fca48fe1ff781351 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:26:23 +0100 Subject: [PATCH 09/20] feat: Introduce IsDataPanel attribute to plugin.json --- pkg/api/frontendsettings.go | 1 + pkg/plugins/models.go | 1 + public/app/plugins/panel/gauge/plugin.json | 1 + public/app/plugins/panel/graph2/plugin.json | 2 +- public/app/plugins/panel/text2/plugin.json | 2 +- public/app/types/plugins.ts | 1 + 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index ed7054050e4..238a3965641 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -145,6 +145,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf "info": panel.Info, "hideFromList": panel.HideFromList, "sort": getPanelSort(panel.Id), + "isDataPanel": panel.IsDataPanel, } } diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 5ac436205c1..e37b1fcf7d9 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -47,6 +47,7 @@ type PluginBase struct { BaseUrl string `json:"baseUrl"` HideFromList bool `json:"hideFromList,omitempty"` State PluginState `json:"state,omitempty"` + IsDataPanel bool `json:"isDataPanel"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` diff --git a/public/app/plugins/panel/gauge/plugin.json b/public/app/plugins/panel/gauge/plugin.json index 58437779d25..733d2281cf4 100644 --- a/public/app/plugins/panel/gauge/plugin.json +++ b/public/app/plugins/panel/gauge/plugin.json @@ -2,6 +2,7 @@ "type": "panel", "name": "Gauge", "id": "gauge", + "isDataPanel": true, "info": { "author": { diff --git a/public/app/plugins/panel/graph2/plugin.json b/public/app/plugins/panel/graph2/plugin.json index 9cb6a1f78a4..9b2a915a597 100644 --- a/public/app/plugins/panel/graph2/plugin.json +++ b/public/app/plugins/panel/graph2/plugin.json @@ -2,7 +2,7 @@ "type": "panel", "name": "React Graph", "id": "graph2", - + "isDataPanel": true, "state": "alpha", "info": { diff --git a/public/app/plugins/panel/text2/plugin.json b/public/app/plugins/panel/text2/plugin.json index 53885dbd0f4..cd4ff424d89 100644 --- a/public/app/plugins/panel/text2/plugin.json +++ b/public/app/plugins/panel/text2/plugin.json @@ -2,8 +2,8 @@ "type": "panel", "name": "Text v2", "id": "text2", - "state": "alpha", + "isDataPanel": false, "info": { "author": { diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 51c3b7b0476..0c5c53eb6f0 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -9,6 +9,7 @@ export interface PanelPlugin { info: any; sort: number; exports?: PluginExports; + isDataPanel?: boolean; } export interface Plugin { From 3f64d61fd28641227e0aee00b1bbf0da70c4a486 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:31:05 +0100 Subject: [PATCH 10/20] feat: Add util to convert snapshotData to PanelData --- public/app/features/dashboard/utils/panel.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index c0d753477a7..c60a153d889 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -4,7 +4,8 @@ import store from 'app/core/store'; // Models import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { TimeRange } from '@grafana/ui'; +import { PanelData, TimeRange, TimeSeries } from '@grafana/ui'; +import { TableData } from '@grafana/ui/src'; // Utils import { isString as _isString } from 'lodash'; @@ -168,3 +169,19 @@ export function getResolution(panel: PanelModel): number { return panel.maxDataPoints ? panel.maxDataPoints : Math.ceil(width * (panel.gridPos.w / 24)); } + +const isTimeSeries = (data: any): data is TimeSeries => data && data.hasOwnProperty('datapoints'); +const isTableData = (data: any): data is TableData => data && data.hasOwnProperty('columns'); +export const snapshotDataToPanelData = (panel: PanelModel): PanelData => { + const snapshotData = panel.snapshotData; + if (isTimeSeries(snapshotData[0])) { + return { + timeSeries: snapshotData + } as PanelData; + } else if (isTableData(snapshotData[0])) { + return { + tableData: snapshotData[0] + } as PanelData; + } + throw new Error('snapshotData is invalid:' + snapshotData.toString()); +}; From d3115325a9b2a797c0de5263bc0b60c7189cb716 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 7 Feb 2019 21:34:50 +0100 Subject: [PATCH 11/20] feat: Only use the DataPanel component when panel plugin has isDataPanel set to true in plugin.json. And fix PanelData when using snapshots --- .../dashboard/dashgrid/PanelChrome.tsx | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index b29be4b389d..3b56b9ad07e 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -10,14 +10,14 @@ import { PanelHeader } from './PanelHeader/PanelHeader'; import { DataPanel } from './DataPanel'; // Utils -import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; +import { applyPanelTimeOverrides, snapshotDataToPanelData } from 'app/features/dashboard/utils/panel'; import { PANEL_HEADER_HEIGHT } from 'app/core/constants'; import { profiler } from 'app/core/profiler'; // Types import { DashboardModel, PanelModel } from '../state'; import { PanelPlugin } from 'app/types'; -import { TimeRange, LoadingState } from '@grafana/ui'; +import { TimeRange, LoadingState, PanelData } from '@grafana/ui'; import variables from 'sass/_variables.scss'; import templateSrv from 'app/features/templating/template_srv'; @@ -94,7 +94,7 @@ export class PanelChrome extends PureComponent { return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); } - renderPanel(loading, panelData, width, height): JSX.Element { + 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; @@ -121,11 +121,46 @@ export class PanelChrome extends PureComponent { ); } + renderHelper = (width: number, height: number): JSX.Element => { + const { panel, plugin } = this.props; + const { refreshCounter, timeRange } = this.state; + const { datasource, targets } = panel; + return ( + <> + {panel.snapshotData && panel.snapshotData.length > 0 ? ( + this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) + ) : ( + <> + {plugin.isDataPanel === true ? + + {({ loading, panelData }) => { + return this.renderPanelPlugin(loading, panelData, width, height); + }} + + : ( + this.renderPanelPlugin(LoadingState.Done, null, width, height) + )} + + )} + + ); + } + + render() { - const { panel, dashboard } = this.props; - const { refreshCounter, timeRange, timeInfo } = this.state; + const { dashboard, panel } = this.props; + const { timeInfo } = this.state; + const { transparent } = panel; - const { datasource, targets, transparent } = panel; const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`; return ( @@ -145,24 +180,7 @@ export class PanelChrome extends PureComponent { scopedVars={panel.scopedVars} links={panel.links} /> - {panel.snapshotData ? ( - this.renderPanel(false, panel.snapshotData, width, height) - ) : ( - - {({ loading, panelData }) => { - return this.renderPanel(loading, panelData, width, height); - }} - - )} + {this.renderHelper(width, height)} ); }} From b7b1a79405794b5277325cb90ef89178257af324 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 11 Feb 2019 16:20:32 +0100 Subject: [PATCH 12/20] chore: Only show Queries tab for panel plugins with isDataPanel set to true --- .../dashboard/panel_editor/PanelEditor.tsx | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index bfdc13bc8f2..37240389373 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -30,6 +30,32 @@ interface PanelEditorTab { text: string; } +enum PanelEditorTabIds { + Queries = 'queries', + Visualization = 'visualization', + Advanced = 'advanced', + Alert = 'alert' +} + +interface PanelEditorTab { + id: string; + text: string; +} + +const panelEditorTabTexts = { + [PanelEditorTabIds.Queries]: 'Queries', + [PanelEditorTabIds.Visualization]: 'Visualization', + [PanelEditorTabIds.Advanced]: 'Panel Options', + [PanelEditorTabIds.Alert]: 'Alert', +}; + +const getPanelEditorTab = (tabId: PanelEditorTabIds): PanelEditorTab => { + return { + id: tabId, + text: panelEditorTabTexts[tabId] + }; +}; + export class PanelEditor extends PureComponent { constructor(props) { super(props); @@ -72,31 +98,26 @@ export class PanelEditor extends PureComponent { render() { const { plugin } = this.props; - let activeTab = store.getState().location.query.tab || 'queries'; + let activeTab: PanelEditorTabIds = store.getState().location.query.tab || PanelEditorTabIds.Queries; const tabs: PanelEditorTab[] = [ - { id: 'queries', text: 'Queries' }, - { id: 'visualization', text: 'Visualization' }, - { id: 'advanced', text: 'Panel Options' }, + getPanelEditorTab(PanelEditorTabIds.Queries), + getPanelEditorTab(PanelEditorTabIds.Visualization), + getPanelEditorTab(PanelEditorTabIds.Advanced), ]; // handle panels that do not have queries tab - if (plugin.exports.PanelCtrl) { - if (!plugin.exports.PanelCtrl.prototype.onDataReceived) { - // remove queries tab - tabs.shift(); - // switch tab - if (activeTab === 'queries') { - activeTab = 'visualization'; - } + if (!plugin.isDataPanel) { + // remove queries tab + tabs.shift(); + // switch tab + if (activeTab === PanelEditorTabIds.Queries) { + activeTab = PanelEditorTabIds.Visualization; } } if (config.alertingEnabled && plugin.id === 'graph') { - tabs.push({ - id: 'alert', - text: 'Alert', - }); + tabs.push(getPanelEditorTab(PanelEditorTabIds.Alert)); } return ( From 075fb8e91cdcff2b08580865a71ee7fa8a0910b6 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 09:48:46 +0100 Subject: [PATCH 13/20] chore: Rename isDataPanel to noQueries --- pkg/api/frontendsettings.go | 2 +- pkg/plugins/models.go | 2 +- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 9 +++++---- .../app/features/dashboard/panel_editor/PanelEditor.tsx | 2 +- public/app/plugins/panel/gauge/plugin.json | 1 - public/app/plugins/panel/graph2/plugin.json | 1 - public/app/plugins/panel/text2/plugin.json | 2 +- public/app/types/plugins.ts | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 238a3965641..cb401577140 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -145,7 +145,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf "info": panel.Info, "hideFromList": panel.HideFromList, "sort": getPanelSort(panel.Id), - "isDataPanel": panel.IsDataPanel, + "noQueries": panel.NoQueries, } } diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index e37b1fcf7d9..7584981fc6c 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -47,7 +47,7 @@ type PluginBase struct { BaseUrl string `json:"baseUrl"` HideFromList bool `json:"hideFromList,omitempty"` State PluginState `json:"state,omitempty"` - IsDataPanel bool `json:"isDataPanel"` + NoQueries bool `json:"noQueries"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 3b56b9ad07e..ca2f96d6044 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -131,8 +131,11 @@ export class PanelChrome extends PureComponent { this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) ) : ( <> - {plugin.isDataPanel === true ? - { return this.renderPanelPlugin(loading, panelData, width, height); }} - : ( - this.renderPanelPlugin(LoadingState.Done, null, width, height) )} )} diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index 37240389373..31274a6ad26 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -107,7 +107,7 @@ export class PanelEditor extends PureComponent { ]; // handle panels that do not have queries tab - if (!plugin.isDataPanel) { + if (plugin.noQueries === true) { // remove queries tab tabs.shift(); // switch tab diff --git a/public/app/plugins/panel/gauge/plugin.json b/public/app/plugins/panel/gauge/plugin.json index 733d2281cf4..58437779d25 100644 --- a/public/app/plugins/panel/gauge/plugin.json +++ b/public/app/plugins/panel/gauge/plugin.json @@ -2,7 +2,6 @@ "type": "panel", "name": "Gauge", "id": "gauge", - "isDataPanel": true, "info": { "author": { diff --git a/public/app/plugins/panel/graph2/plugin.json b/public/app/plugins/panel/graph2/plugin.json index 9b2a915a597..b11f93c9adc 100644 --- a/public/app/plugins/panel/graph2/plugin.json +++ b/public/app/plugins/panel/graph2/plugin.json @@ -2,7 +2,6 @@ "type": "panel", "name": "React Graph", "id": "graph2", - "isDataPanel": true, "state": "alpha", "info": { diff --git a/public/app/plugins/panel/text2/plugin.json b/public/app/plugins/panel/text2/plugin.json index cd4ff424d89..661ac4671ef 100644 --- a/public/app/plugins/panel/text2/plugin.json +++ b/public/app/plugins/panel/text2/plugin.json @@ -3,7 +3,7 @@ "name": "Text v2", "id": "text2", "state": "alpha", - "isDataPanel": false, + "noQueries": true, "info": { "author": { diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 0c5c53eb6f0..101f649eda9 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -9,7 +9,7 @@ export interface PanelPlugin { info: any; sort: number; exports?: PluginExports; - isDataPanel?: boolean; + noQueries?: boolean; } export interface Plugin { From b5dbf26dc4f9513ea0e5a0bbbc83c0196573c987 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 09:55:09 +0100 Subject: [PATCH 14/20] chore: PR feedback, shorten boolean check --- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 3 +-- public/app/features/dashboard/panel_editor/PanelEditor.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index ca2f96d6044..138f299091b 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -131,8 +131,7 @@ export class PanelChrome extends PureComponent { this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) ) : ( <> - - {plugin.noQueries === true ? + {plugin.noQueries ? this.renderPanelPlugin(LoadingState.Done, null, width, height) : ( { ]; // handle panels that do not have queries tab - if (plugin.noQueries === true) { + if (plugin.noQueries) { // remove queries tab tabs.shift(); // switch tab From 01208ccd68dace126dc71e4bfb94be225f51fa01 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 12:25:10 +0100 Subject: [PATCH 15/20] chore: Rename renderHelper > renderDataPanel and move logic to smaller functions --- .../dashboard/dashgrid/PanelChrome.tsx | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 138f299091b..ffc5ef7b904 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -94,6 +94,25 @@ export class PanelChrome extends PureComponent { return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); } + get hasPanelSnapshot() { + const { panel } = this.props; + return panel.snapshotData && panel.snapshotData.length; + } + + get hasDataPanel() { + return !this.props.plugin.noQueries && !this.hasPanelSnapshot; + } + + get getDataForPanel() { + const { panel, plugin } = this.props; + + if (plugin.noQueries) { + return null; + } + + return this.hasPanelSnapshot ? snapshotDataToPanelData(panel) : null; + } + renderPanelPlugin(loading: LoadingState, panelData: PanelData, width: number, height: number): JSX.Element { const { panel, plugin } = this.props; const { timeRange, renderCounter } = this.state; @@ -121,20 +140,14 @@ export class PanelChrome extends PureComponent { ); } - renderHelper = (width: number, height: number): JSX.Element => { - const { panel, plugin } = this.props; + renderDataPanel = (width: number, height: number): JSX.Element => { + const { panel } = this.props; const { refreshCounter, timeRange } = this.state; const { datasource, targets } = panel; return ( <> - {panel.snapshotData && panel.snapshotData.length > 0 ? ( - this.renderPanelPlugin(LoadingState.Done, snapshotDataToPanelData(panel), width, height) - ) : ( - <> - {plugin.noQueries ? - this.renderPanelPlugin(LoadingState.Done, null, width, height) - : ( - { isVisible={this.isVisible} widthPixels={width} refreshCounter={refreshCounter} - onDataResponse={this.onDataResponse} - > + onDataResponse={this.onDataResponse} > {({ loading, panelData }) => { return this.renderPanelPlugin(loading, panelData, width, height); }} - )} - - )} + ) : ( + this.renderPanelPlugin(LoadingState.Done, this.getDataForPanel, width, height) + )} ); } - render() { const { dashboard, panel } = this.props; const { timeInfo } = this.state; @@ -180,7 +191,7 @@ export class PanelChrome extends PureComponent { scopedVars={panel.scopedVars} links={panel.links} /> - {this.renderHelper(width, height)} + {this.renderDataPanel(width, height)} ); }} From d5918498daa5abe3bdde362c383943016d68a407 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 12:26:34 +0100 Subject: [PATCH 16/20] chore: Rename renderDataPanel to renderPanel --- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index ffc5ef7b904..46880a871a3 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 { ); } - renderDataPanel = (width: number, height: number): JSX.Element => { + renderPanel = (width: number, height: number): JSX.Element => { const { panel } = this.props; const { refreshCounter, timeRange } = this.state; const { datasource, targets } = panel; @@ -191,7 +191,7 @@ export class PanelChrome extends PureComponent { scopedVars={panel.scopedVars} links={panel.links} /> - {this.renderDataPanel(width, height)} + {this.renderPanel(width, height)} ); }} From c3965e332d4402a6ddc5c6a8be78bcdd36cf1093 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 12 Feb 2019 12:27:49 +0100 Subject: [PATCH 17/20] chore: Rename renderPanel to renderPanelBody --- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 46880a871a3..309fa118251 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 { ); } - renderPanel = (width: number, height: number): JSX.Element => { + renderPanelBody = (width: number, height: number): JSX.Element => { const { panel } = this.props; const { refreshCounter, timeRange } = this.state; const { datasource, targets } = panel; @@ -191,7 +191,7 @@ export class PanelChrome extends PureComponent { scopedVars={panel.scopedVars} links={panel.links} /> - {this.renderPanel(width, height)} + {this.renderPanelBody(width, height)} ); }} From a1453607a9efc21e45a82d53dcc9979bb5ac0369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 12 Feb 2019 16:05:29 +0100 Subject: [PATCH 18/20] Changed noQueries to a dataFormats array that will allow a panel to define supported formats and prefered (first in array) --- pkg/api/frontendsettings.go | 2 +- pkg/plugins/models.go | 1 - pkg/plugins/panel_plugin.go | 5 +++++ .../dashboard/dashgrid/PanelChrome.tsx | 19 +++++++------------ .../dashgrid/PanelPluginNotFound.tsx | 1 + .../dashboard/panel_editor/PanelEditor.tsx | 6 +++--- .../features/plugins/__mocks__/pluginMocks.ts | 3 ++- .../app/plugins/panel/alertlist/plugin.json | 2 ++ public/app/plugins/panel/dashlist/plugin.json | 4 +++- .../app/plugins/panel/pluginlist/plugin.json | 2 ++ public/app/types/plugins.ts | 7 ++++++- 11 files changed, 32 insertions(+), 20 deletions(-) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index cb401577140..d13f0a26ab0 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -145,7 +145,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf "info": panel.Info, "hideFromList": panel.HideFromList, "sort": getPanelSort(panel.Id), - "noQueries": panel.NoQueries, + "dataFormats": panel.DataFormats, } } diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 7584981fc6c..5ac436205c1 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -47,7 +47,6 @@ type PluginBase struct { BaseUrl string `json:"baseUrl"` HideFromList bool `json:"hideFromList,omitempty"` State PluginState `json:"state,omitempty"` - NoQueries bool `json:"noQueries"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` diff --git a/pkg/plugins/panel_plugin.go b/pkg/plugins/panel_plugin.go index 49cbfb19fc6..b90fd41e465 100644 --- a/pkg/plugins/panel_plugin.go +++ b/pkg/plugins/panel_plugin.go @@ -4,6 +4,7 @@ import "encoding/json" type PanelPlugin struct { FrontendPluginBase + DataFormats []string `json:"dataFormats"` } func (p *PanelPlugin) Load(decoder *json.Decoder, pluginDir string) error { @@ -15,6 +16,10 @@ func (p *PanelPlugin) Load(decoder *json.Decoder, pluginDir string) error { return err } + if p.DataFormats == nil { + p.DataFormats = []string{"time_series", "table"} + } + Panels[p.Id] = p return nil } diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 309fa118251..b050b1ff5e1 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -99,18 +99,12 @@ export class PanelChrome extends PureComponent { return panel.snapshotData && panel.snapshotData.length; } - get hasDataPanel() { - return !this.props.plugin.noQueries && !this.hasPanelSnapshot; + get needsQueryExecution() { + return this.hasPanelSnapshot || this.props.plugin.dataFormats.length > 0; } get getDataForPanel() { - const { panel, plugin } = this.props; - - if (plugin.noQueries) { - return null; - } - - return this.hasPanelSnapshot ? snapshotDataToPanelData(panel) : null; + return this.hasPanelSnapshot ? snapshotDataToPanelData(this.props.panel) : null; } renderPanelPlugin(loading: LoadingState, panelData: PanelData, width: number, height: number): JSX.Element { @@ -146,7 +140,7 @@ export class PanelChrome extends PureComponent { const { datasource, targets } = panel; return ( <> - {this.hasDataPanel ? ( + {this.needsQueryExecution ? ( { isVisible={this.isVisible} widthPixels={width} refreshCounter={refreshCounter} - onDataResponse={this.onDataResponse} > + onDataResponse={this.onDataResponse} + > {({ loading, panelData }) => { return this.renderPanelPlugin(loading, panelData, width, height); }} @@ -165,7 +160,7 @@ export class PanelChrome extends PureComponent { )} ); - } + }; render() { const { dashboard, panel } = this.props; diff --git a/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx b/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx index 18b307b5ea5..3f835bdbac2 100644 --- a/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx +++ b/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx @@ -46,6 +46,7 @@ export function getPanelPluginNotFound(id: string): PanelPlugin { sort: 100, module: '', baseUrl: '', + dataFormats: [], info: { author: { name: '', diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index 7b8298deebf..74870b25f07 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -34,7 +34,7 @@ enum PanelEditorTabIds { Queries = 'queries', Visualization = 'visualization', Advanced = 'advanced', - Alert = 'alert' + Alert = 'alert', } interface PanelEditorTab { @@ -52,7 +52,7 @@ const panelEditorTabTexts = { const getPanelEditorTab = (tabId: PanelEditorTabIds): PanelEditorTab => { return { id: tabId, - text: panelEditorTabTexts[tabId] + text: panelEditorTabTexts[tabId], }; }; @@ -107,7 +107,7 @@ export class PanelEditor extends PureComponent { ]; // handle panels that do not have queries tab - if (plugin.noQueries) { + if (plugin.dataFormats.length === 0) { // remove queries tab tabs.shift(); // switch tab diff --git a/public/app/features/plugins/__mocks__/pluginMocks.ts b/public/app/features/plugins/__mocks__/pluginMocks.ts index b922840cb43..ab78f8094b3 100644 --- a/public/app/features/plugins/__mocks__/pluginMocks.ts +++ b/public/app/features/plugins/__mocks__/pluginMocks.ts @@ -1,4 +1,4 @@ -import { Plugin, PanelPlugin } from 'app/types'; +import { Plugin, PanelPlugin, PanelDataFormat } from 'app/types'; export const getMockPlugins = (amount: number): Plugin[] => { const plugins = []; @@ -38,6 +38,7 @@ export const getPanelPlugin = (options: { id: string; sort?: number; hideFromLis id: options.id, name: options.id, sort: options.sort || 1, + dataFormats: [PanelDataFormat.TimeSeries], info: { author: { name: options.id + 'name', diff --git a/public/app/plugins/panel/alertlist/plugin.json b/public/app/plugins/panel/alertlist/plugin.json index ff36a572f2b..130c307ae6c 100644 --- a/public/app/plugins/panel/alertlist/plugin.json +++ b/public/app/plugins/panel/alertlist/plugin.json @@ -3,6 +3,8 @@ "name": "Alert List", "id": "alertlist", + "dataFormats": [], + "info": { "description": "Shows list of alerts and their current status", "author": { diff --git a/public/app/plugins/panel/dashlist/plugin.json b/public/app/plugins/panel/dashlist/plugin.json index 9dcde08a598..11f9db928b0 100644 --- a/public/app/plugins/panel/dashlist/plugin.json +++ b/public/app/plugins/panel/dashlist/plugin.json @@ -3,12 +3,14 @@ "name": "Dashboard list", "id": "dashlist", + "dataFormats": [], + "info": { "description": "List of dynamic links to other dashboards", "author": { "name": "Grafana Project", "url": "https://grafana.com" -}, + }, "logos": { "small": "img/icn-dashlist-panel.svg", "large": "img/icn-dashlist-panel.svg" diff --git a/public/app/plugins/panel/pluginlist/plugin.json b/public/app/plugins/panel/pluginlist/plugin.json index b955177f1bc..8927b25b880 100644 --- a/public/app/plugins/panel/pluginlist/plugin.json +++ b/public/app/plugins/panel/pluginlist/plugin.json @@ -3,6 +3,8 @@ "name": "Plugin list", "id": "pluginlist", + "dataFormats": [], + "info": { "description": "Plugin List for Grafana", "author": { diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 101f649eda9..d812cf5d81e 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -9,7 +9,12 @@ export interface PanelPlugin { info: any; sort: number; exports?: PluginExports; - noQueries?: boolean; + dataFormats: PanelDataFormat[]; +} + +export enum PanelDataFormat { + Table = 'table', + TimeSeries = 'time_series', } export interface Plugin { From 57086608935960d0fdf5283a82b5d5869e7b401d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 12 Feb 2019 16:15:05 +0100 Subject: [PATCH 19/20] Updated a few plugin json files with dataFormats --- public/app/plugins/panel/gauge/plugin.json | 2 ++ public/app/plugins/panel/graph/plugin.json | 5 +++-- public/app/plugins/panel/heatmap/plugin.json | 2 ++ public/app/plugins/panel/singlestat/plugin.json | 5 +++-- public/app/plugins/panel/table/plugin.json | 5 +++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/panel/gauge/plugin.json b/public/app/plugins/panel/gauge/plugin.json index 58437779d25..6dde42127be 100644 --- a/public/app/plugins/panel/gauge/plugin.json +++ b/public/app/plugins/panel/gauge/plugin.json @@ -3,6 +3,8 @@ "name": "Gauge", "id": "gauge", + "dataFormats": ["time_series"], + "info": { "author": { "name": "Grafana Project", diff --git a/public/app/plugins/panel/graph/plugin.json b/public/app/plugins/panel/graph/plugin.json index c0c8e8db290..81f7c6c54cf 100644 --- a/public/app/plugins/panel/graph/plugin.json +++ b/public/app/plugins/panel/graph/plugin.json @@ -3,12 +3,14 @@ "name": "Graph", "id": "graph", + "dataFormats": ["time_series", "table"], + "info": { "description": "Graph Panel for Grafana", "author": { "name": "Grafana Project", "url": "https://grafana.com" -}, + }, "logos": { "small": "img/icn-graph-panel.svg", "large": "img/icn-graph-panel.svg" @@ -16,4 +18,3 @@ "version": "5.0.0" } } - diff --git a/public/app/plugins/panel/heatmap/plugin.json b/public/app/plugins/panel/heatmap/plugin.json index 723d8e886a0..0073c600bb6 100644 --- a/public/app/plugins/panel/heatmap/plugin.json +++ b/public/app/plugins/panel/heatmap/plugin.json @@ -3,6 +3,8 @@ "name": "Heatmap", "id": "heatmap", + "dataFormats": ["time_series"], + "info": { "description": "Heatmap Panel for Grafana", "author": { diff --git a/public/app/plugins/panel/singlestat/plugin.json b/public/app/plugins/panel/singlestat/plugin.json index 5e36ab5cf4e..e64d0ec7fe0 100644 --- a/public/app/plugins/panel/singlestat/plugin.json +++ b/public/app/plugins/panel/singlestat/plugin.json @@ -3,12 +3,14 @@ "name": "Singlestat", "id": "singlestat", + "dataFormats": ["time_series", "table"], + "info": { "description": "Singlestat Panel for Grafana", "author": { "name": "Grafana Project", "url": "https://grafana.com" -}, + }, "logos": { "small": "img/icn-singlestat-panel.svg", "large": "img/icn-singlestat-panel.svg" @@ -16,4 +18,3 @@ "version": "5.0.0" } } - diff --git a/public/app/plugins/panel/table/plugin.json b/public/app/plugins/panel/table/plugin.json index 3b6cbaae876..212688fbfa8 100644 --- a/public/app/plugins/panel/table/plugin.json +++ b/public/app/plugins/panel/table/plugin.json @@ -3,12 +3,14 @@ "name": "Table", "id": "table", + "dataFormats": ["table", "time_series"], + "info": { "description": "Table Panel for Grafana", "author": { "name": "Grafana Project", "url": "https://grafana.com" -}, + }, "logos": { "small": "img/icn-table-panel.svg", "large": "img/icn-table-panel.svg" @@ -16,4 +18,3 @@ "version": "5.0.0" } } - From 88ef2e1d3212284e2fa9b05536626cca05a27754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 12 Feb 2019 18:31:35 +0100 Subject: [PATCH 20/20] Fixed a minor plugin json lingering issue --- public/app/plugins/panel/text/plugin.json | 4 +++- public/app/plugins/panel/text2/plugin.json | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/text/plugin.json b/public/app/plugins/panel/text/plugin.json index 6152bd322b5..4e678bdc312 100644 --- a/public/app/plugins/panel/text/plugin.json +++ b/public/app/plugins/panel/text/plugin.json @@ -3,11 +3,13 @@ "name": "Text", "id": "text", + "dataFormats": [], + "info": { "author": { "name": "Grafana Project", "url": "https://grafana.com" -}, + }, "logos": { "small": "img/icn-text-panel.svg", "large": "img/icn-text-panel.svg" diff --git a/public/app/plugins/panel/text2/plugin.json b/public/app/plugins/panel/text2/plugin.json index 661ac4671ef..840bb820696 100644 --- a/public/app/plugins/panel/text2/plugin.json +++ b/public/app/plugins/panel/text2/plugin.json @@ -3,7 +3,8 @@ "name": "Text v2", "id": "text2", "state": "alpha", - "noQueries": true, + + "dataFormats": [], "info": { "author": {