Просмотр исходного кода

Merge branch '15217-panels-without-queries' into move-error-boundry

Peter Holmberg 6 лет назад
Родитель
Сommit
1db5d86b12

+ 1 - 0
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),
+			"noQueries":    panel.NoQueries,
 		}
 	}
 

+ 1 - 0
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"`
+	NoQueries    bool               `json:"noQueries"`
 
 	IncludedInAppId string `json:"-"`
 	PluginDir       string `json:"-"`

+ 41 - 23
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<Props, State> {
     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<Props, State> {
     );
   }
 
+  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.noQueries ?
+            this.renderPanelPlugin(LoadingState.Done, null, width, height)
+          : (
+            <DataPanel
+            datasource={datasource}
+            queries={targets}
+            timeRange={timeRange}
+            isVisible={this.isVisible}
+            widthPixels={width}
+            refreshCounter={refreshCounter}
+            onDataResponse={this.onDataResponse}
+          >
+            {({ loading, panelData }) => {
+              return this.renderPanelPlugin(loading, panelData, width, height);
+            }}
+          </DataPanel>
+          )}
+        </>
+      )}
+      </>
+    );
+  }
+
+
   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 (
       <AutoSizer>
@@ -145,23 +179,7 @@ export class PanelChrome extends PureComponent<Props, State> {
                 scopedVars={panel.scopedVars}
                 links={panel.links}
               />
-              {panel.snapshotData ? (
-                this.renderPanel(false, panel.snapshotData, width, height)
-              ) : (
-                <DataPanel
-                  datasource={datasource}
-                  queries={targets}
-                  timeRange={timeRange}
-                  isVisible={this.isVisible}
-                  widthPixels={width}
-                  refreshCounter={refreshCounter}
-                  onDataResponse={this.onDataResponse}
-                >
-                  {({ loading, panelData }) => {
-                    return this.renderPanel(loading, panelData, width, height);
-                  }}
-                </DataPanel>
-              )}
+              {this.renderHelper(width, height)}
             </div>
           );
         }}

+ 37 - 16
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<PanelEditorProps> {
   constructor(props) {
     super(props);
@@ -72,31 +98,26 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
 
   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.noQueries) {
+      // 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 (

+ 18 - 1
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());
+};

+ 2 - 2
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<Options> {}
@@ -19,7 +19,7 @@ export class GraphPanel extends PureComponent<Props> {
     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,

+ 0 - 1
public/app/plugins/panel/graph2/plugin.json

@@ -2,7 +2,6 @@
   "type": "panel",
   "name": "React Graph",
   "id": "graph2",
-
   "state": "alpha",
 
   "info": {

+ 1 - 1
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<PanelProps> {
-  constructor(props) {
+  constructor(props: PanelProps) {
     super(props);
   }
 

+ 1 - 1
public/app/plugins/panel/text2/plugin.json

@@ -2,8 +2,8 @@
   "type": "panel",
   "name": "Text v2",
   "id": "text2",
-
   "state": "alpha",
+  "noQueries": true,
 
   "info": {
     "author": {

+ 1 - 0
public/app/types/plugins.ts

@@ -9,6 +9,7 @@ export interface PanelPlugin {
   info: any;
   sort: number;
   exports?: PluginExports;
+  noQueries?: boolean;
 }
 
 export interface Plugin {