瀏覽代碼

working on react data / query exectution

Torkel Ödegaard 7 年之前
父節點
當前提交
cd4619dad1

+ 5 - 1
public/app/core/components/grafana_app.ts

@@ -8,7 +8,8 @@ import appEvents from 'app/core/app_events';
 import Drop from 'tether-drop';
 import colors from 'app/core/utils/colors';
 import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv';
-import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
+import { TimeSrv, setTimeSrv } from 'app/features/dashboard/time_srv';
+import { DatasourceSrv, setDatasourceSrv } from 'app/features/plugins/datasource_srv';
 import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader';
 import { configureStore } from 'app/store/configureStore';
 
@@ -23,12 +24,15 @@ export class GrafanaCtrl {
     contextSrv,
     bridgeSrv,
     backendSrv: BackendSrv,
+    timeSrv: TimeSrv,
     datasourceSrv: DatasourceSrv,
     angularLoader: AngularLoader
   ) {
     // make angular loader service available to react components
     setAngularLoader(angularLoader);
     setBackendSrv(backendSrv);
+    setDatasourceSrv(datasourceSrv);
+    setTimeSrv(timeSrv);
     configureStore();
 
     $scope.init = () => {

+ 54 - 16
public/app/features/dashboard/dashgrid/DataPanel.tsx

@@ -1,5 +1,11 @@
 // Library
-import React, { Component } from 'react';
+import React, { PureComponent } from 'react';
+
+// Services
+import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
+
+// Types
+import { TimeRange, LoadingState } from 'app/types';
 
 interface RenderProps {
   loading: LoadingState;
@@ -9,6 +15,11 @@ interface RenderProps {
 export interface Props {
   datasource: string | null;
   queries: any[];
+  panelId?: number;
+  dashboardId?: number;
+  isVisible?: boolean;
+  timeRange?: TimeRange;
+  refreshCounter: number;
   children: (r: RenderProps) => JSX.Element;
 }
 
@@ -18,16 +29,13 @@ export interface State {
   data: any;
 }
 
-export enum LoadingState {
-  NotStarted = 'NotStarted',
-  Loading = 'Loading',
-  Done = 'Done',
-  Error = 'Error',
-}
-
-export interface PanelProps extends RenderProps {}
+export class DataPanel extends PureComponent<Props, State> {
+  static defaultProps = {
+    isVisible: true,
+    panelId: 1,
+    dashboardId: 1,
+  };
 
-export class DataPanel extends Component<Props, State> {
   constructor(props: Props) {
     super(props);
 
@@ -44,20 +52,50 @@ export class DataPanel extends Component<Props, State> {
   }
 
   issueQueries = async () => {
+    const { isVisible, queries, datasource, panelId, dashboardId, timeRange } = this.props;
+
+    if (!isVisible) {
+      return;
+    }
+
+    if (!queries.length) {
+      this.setState({ data: [], loading: LoadingState.Done });
+      return;
+    }
+
     this.setState({ loading: LoadingState.Loading });
 
-    await new Promise(resolve => {
-      setTimeout(() => {
-        this.setState({ loading: LoadingState.Done, data: [{ value: 10 }], isFirstLoad: false });
-      }, 500);
-    });
+    try {
+      const dataSourceSrv = getDatasourceSrv();
+      const ds = await dataSourceSrv.get(datasource);
+
+      const queryOptions = {
+        timezone: 'browser',
+        panelId: panelId,
+        dashboardId: dashboardId,
+        range: timeRange,
+        rangeRaw: timeRange.raw,
+        interval: '1s',
+        intervalMs: 1000,
+        targets: queries,
+        maxDataPoints: 500,
+        scopedVars: {},
+        cacheTimeout: null,
+      };
+
+      const resp = await ds.query(queryOptions);
+      console.log(resp);
+    } catch (err) {
+      console.log('Loading error', err);
+      this.setState({ loading: LoadingState.Error });
+    }
   };
 
   render() {
     const { data, loading, isFirstLoad } = this.state;
     console.log('data panel render');
 
-    if (isFirstLoad && loading === LoadingState.Loading) {
+    if (isFirstLoad && (loading === LoadingState.Loading || loading === LoadingState.NotStarted)) {
       return (
         <div className="loading">
           <p>Loading</p>

+ 54 - 16
public/app/features/dashboard/dashgrid/PanelChrome.tsx

@@ -1,8 +1,17 @@
-import React, { ComponentClass } from 'react';
+// Libraries
+import React, { ComponentClass, PureComponent } from 'react';
+
+// Services
+import { getTimeSrv } from '../time_srv';
+
+// Components
+import { PanelHeader } from './PanelHeader';
+import { DataPanel } from './DataPanel';
+
+// Types
 import { PanelModel } from '../panel_model';
 import { DashboardModel } from '../dashboard_model';
-import { PanelHeader } from './PanelHeader';
-import { DataPanel, PanelProps } from './DataPanel';
+import { TimeRange, PanelProps } from 'app/types';
 
 export interface Props {
   panel: PanelModel;
@@ -10,30 +19,59 @@ export interface Props {
   component: ComponentClass<PanelProps>;
 }
 
-interface State {}
-
-export class PanelChrome extends React.Component<Props, State> {
-  panelComponent: DataPanel;
+export interface State {
+  refreshCounter: number;
+  timeRange?: TimeRange;
+}
 
+export class PanelChrome extends PureComponent<Props, State> {
   constructor(props) {
     super(props);
+
+    this.state = {
+      refreshCounter: 0,
+    };
   }
 
-  render() {
-    const { datasource, targets } = this.props.panel;
-    const PanelComponent = this.props.component;
+  componentDidMount() {
+    this.props.dashboard.panelInitialized(this.props.panel);
+    this.props.panel.events.on('refresh', this.onRefresh);
+  }
+
+  componentWillUnmount() {
+    this.props.panel.events.off('refresh', this.onRefresh);
+  }
+
+  onRefresh = () => {
+    const timeSrv = getTimeSrv();
+    const timeRange = timeSrv.timeRange();
 
-    // if (!PanelComponent) {
-    //   PanelComponent = dataPanels[type] = DataPanelWrapper(this.props.component);
-    // }
+    this.setState({
+      refreshCounter: this.state.refreshCounter + 1,
+      timeRange: timeRange,
+    });
+  };
 
-    console.log('PanelChrome render', PanelComponent);
+  get isVisible() {
+    return this.props.dashboard.otherPanelInFullscreen(this.props.panel);
+  }
+
+  render() {
+    const { panel, dashboard } = this.props;
+    const { datasource, targets } = panel;
+    const { refreshCounter } = this.state;
+    const PanelComponent = this.props.component;
 
     return (
       <div className="panel-container">
-        <PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
+        <PanelHeader panel={panel} dashboard={dashboard} />
         <div className="panel-content">
-          <DataPanel datasource={datasource} queries={targets}>
+          <DataPanel
+            datasource={datasource}
+            queries={targets}
+            isVisible={this.isVisible}
+            refreshCounter={refreshCounter}
+          >
             {({ loading, data }) => {
               return <PanelComponent loading={loading} data={data} />;
             }}

+ 20 - 10
public/app/features/dashboard/time_srv.ts

@@ -1,9 +1,15 @@
+// Libraries
 import moment from 'moment';
 import _ from 'lodash';
-import coreModule from 'app/core/core_module';
+
+// Utils
 import kbn from 'app/core/utils/kbn';
+import coreModule from 'app/core/core_module';
 import * as dateMath from 'app/core/utils/datemath';
 
+// Types
+import { TimeRange } from 'app/types';
+
 export class TimeSrv {
   time: any;
   refreshTimer: any;
@@ -200,7 +206,7 @@ export class TimeSrv {
     return range;
   }
 
-  timeRange() {
+  timeRange(): TimeRange {
     // make copies if they are moment  (do not want to return out internal moment, because they are mutable!)
     const raw = {
       from: moment.isMoment(this.time.from) ? moment(this.time.from) : this.time.from,
@@ -222,17 +228,21 @@ export class TimeSrv {
     const timespan = range.to.valueOf() - range.from.valueOf();
     const center = range.to.valueOf() - timespan / 2;
 
-    let to = center + timespan * factor / 2;
-    let from = center - timespan * factor / 2;
-
-    if (to > Date.now() && range.to <= Date.now()) {
-      const offset = to - Date.now();
-      from = from - offset;
-      to = Date.now();
-    }
+    const to = center + timespan * factor / 2;
+    const from = center - timespan * factor / 2;
 
     this.setTime({ from: moment.utc(from), to: moment.utc(to) });
   }
 }
 
+let singleton;
+
+export function setTimeSrv(srv: TimeSrv) {
+  singleton = srv;
+}
+
+export function getTimeSrv(): TimeSrv {
+  return singleton;
+}
+
 coreModule.service('timeSrv', TimeSrv);

+ 0 - 1
public/app/features/panel/panel_directive.ts

@@ -145,7 +145,6 @@ module.directive('grafanaPanel', ($rootScope, $document, $timeout) => {
       ctrl.calculatePanelHeight();
 
       ctrl.events.on('render', () => {
-        console.log('panel_directive: render', ctrl.panel.id);
         if (transparentLastState !== ctrl.panel.transparent) {
           panelContainer.toggleClass('panel-transparent', ctrl.panel.transparent === true);
           transparentLastState = ctrl.panel.transparent;

+ 10 - 0
public/app/features/plugins/datasource_srv.ts

@@ -162,5 +162,15 @@ export class DatasourceSrv {
   }
 }
 
+let singleton: DatasourceSrv;
+
+export function setDatasourceSrv(srv: DatasourceSrv) {
+  singleton = srv;
+}
+
+export function getDatasourceSrv(): DatasourceSrv {
+  return singleton;
+}
+
 coreModule.service('datasourceSrv', DatasourceSrv);
 export default DatasourceSrv;

+ 3 - 2
public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.ts

@@ -1,4 +1,5 @@
 import angular from 'angular';
+import coreModule from 'app/core/core_module';
 import _ from 'lodash';
 
 export class CloudWatchQueryParameter {
@@ -239,5 +240,5 @@ export class CloudWatchQueryParameterCtrl {
   }
 }
 
-angular.module('grafana.controllers').directive('cloudwatchQueryParameter', CloudWatchQueryParameter);
-angular.module('grafana.controllers').controller('CloudWatchQueryParameterCtrl', CloudWatchQueryParameterCtrl);
+coreModule.directive('cloudwatchQueryParameter', CloudWatchQueryParameter);
+coreModule.controller('CloudWatchQueryParameterCtrl', CloudWatchQueryParameterCtrl);

+ 3 - 4
public/app/plugins/datasource/elasticsearch/bucket_agg.ts

@@ -1,4 +1,4 @@
-import angular from 'angular';
+import coreModule from 'app/core/core_module';
 import _ from 'lodash';
 import * as queryDef from './query_def';
 
@@ -226,6 +226,5 @@ export class ElasticBucketAggCtrl {
   }
 }
 
-const module = angular.module('grafana.directives');
-module.directive('elasticBucketAgg', elasticBucketAgg);
-module.controller('ElasticBucketAggCtrl', ElasticBucketAggCtrl);
+coreModule.directive('elasticBucketAgg', elasticBucketAgg);
+coreModule.controller('ElasticBucketAggCtrl', ElasticBucketAggCtrl);

+ 3 - 4
public/app/plugins/datasource/elasticsearch/metric_agg.ts

@@ -1,4 +1,4 @@
-import angular from 'angular';
+import coreModule from 'app/core/core_module';
 import _ from 'lodash';
 import * as queryDef from './query_def';
 
@@ -203,6 +203,5 @@ export class ElasticMetricAggCtrl {
   }
 }
 
-const module = angular.module('grafana.directives');
-module.directive('elasticMetricAgg', elasticMetricAgg);
-module.controller('ElasticMetricAggCtrl', ElasticMetricAggCtrl);
+coreModule.directive('elasticMetricAgg', elasticMetricAgg);
+coreModule.controller('ElasticMetricAggCtrl', ElasticMetricAggCtrl);

+ 2 - 2
public/app/plugins/datasource/graphite/add_graphite_func.ts

@@ -1,8 +1,8 @@
-import angular from 'angular';
 import _ from 'lodash';
 import $ from 'jquery';
 import rst2html from 'rst2html';
 import Drop from 'tether-drop';
+import coreModule from 'app/core/core_module';
 
 /** @ngInject */
 export function graphiteAddFunc($compile) {
@@ -130,7 +130,7 @@ export function graphiteAddFunc($compile) {
   };
 }
 
-angular.module('grafana.directives').directive('graphiteAddFunc', graphiteAddFunc);
+coreModule.directive('graphiteAddFunc', graphiteAddFunc);
 
 function createFunctionDropDownMenu(funcDefs) {
   const categories = {};

+ 2 - 2
public/app/plugins/datasource/graphite/func_editor.ts

@@ -1,7 +1,7 @@
-import angular from 'angular';
 import _ from 'lodash';
 import $ from 'jquery';
 import rst2html from 'rst2html';
+import coreModule from 'app/core/core_module';
 
 /** @ngInject */
 export function graphiteFuncEditor($compile, templateSrv, popoverSrv) {
@@ -315,4 +315,4 @@ export function graphiteFuncEditor($compile, templateSrv, popoverSrv) {
   };
 }
 
-angular.module('grafana.directives').directive('graphiteFuncEditor', graphiteFuncEditor);
+coreModule.directive('graphiteFuncEditor', graphiteFuncEditor);

+ 3 - 3
public/app/plugins/datasource/stackdriver/query_aggregation_ctrl.ts

@@ -1,4 +1,4 @@
-import angular from 'angular';
+import coreModule from 'app/core/core_module';
 import _ from 'lodash';
 import * as options from './constants';
 import kbn from 'app/core/utils/kbn';
@@ -83,5 +83,5 @@ export class StackdriverAggregationCtrl {
   }
 }
 
-angular.module('grafana.controllers').directive('stackdriverAggregation', StackdriverAggregation);
-angular.module('grafana.controllers').controller('StackdriverAggregationCtrl', StackdriverAggregationCtrl);
+coreModule.directive('stackdriverAggregation', StackdriverAggregation);
+coreModule.controller('StackdriverAggregationCtrl', StackdriverAggregationCtrl);

+ 3 - 3
public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts

@@ -1,4 +1,4 @@
-import angular from 'angular';
+import coreModule from 'app/core/core_module';
 import _ from 'lodash';
 import { FilterSegments, DefaultRemoveFilterValue } from './filter_segments';
 import appEvents from 'app/core/app_events';
@@ -281,5 +281,5 @@ export class StackdriverFilterCtrl {
   }
 }
 
-angular.module('grafana.controllers').directive('stackdriverFilter', StackdriverFilter);
-angular.module('grafana.controllers').controller('StackdriverFilterCtrl', StackdriverFilterCtrl);
+coreModule.directive('stackdriverFilter', StackdriverFilter);
+coreModule.controller('StackdriverFilterCtrl', StackdriverFilterCtrl);

+ 0 - 1
public/app/plugins/panel/graph/graph.ts

@@ -80,7 +80,6 @@ class GraphElement {
     this.annotations = this.ctrl.annotations || [];
     this.buildFlotPairs(this.data);
     const graphHeight = this.elem.height();
-    console.log('graphHeight', graphHeight);
     updateLegendValues(this.data, this.panel, graphHeight);
 
     this.ctrl.events.emit('render-legend');

+ 2 - 4
public/app/plugins/panel/graph/legend.ts

@@ -1,11 +1,9 @@
-import angular from 'angular';
 import _ from 'lodash';
 import $ from 'jquery';
 import baron from 'baron';
+import coreModule from 'app/core/core_module';
 
-const module = angular.module('grafana.directives');
-
-module.directive('graphLegend', (popoverSrv, $timeout) => {
+coreModule.directive('graphLegend', (popoverSrv, $timeout) => {
   return {
     link: (scope, elem) => {
       let firstRender = true;

+ 2 - 2
public/app/plugins/panel/graph/series_overrides_ctrl.ts

@@ -1,5 +1,5 @@
 import _ from 'lodash';
-import angular from 'angular';
+import coreModule from 'app/core/core_module';
 
 /** @ngInject */
 export function SeriesOverridesCtrl($scope, $element, popoverSrv) {
@@ -156,4 +156,4 @@ export function SeriesOverridesCtrl($scope, $element, popoverSrv) {
   $scope.updateCurrentOverrides();
 }
 
-angular.module('grafana.controllers').controller('SeriesOverridesCtrl', SeriesOverridesCtrl);
+coreModule.controller('SeriesOverridesCtrl', SeriesOverridesCtrl);

+ 3 - 1
public/app/plugins/panel/graph2/module.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
+import { PanelProps } from 'app/types';
 
 interface Options {
   showBars: boolean;
@@ -22,6 +22,8 @@ export class Graph2 extends PureComponent<Props> {
       value = data[0].value;
     }
 
+    console.log('graph2 render');
+
     return <h2>Text Panel {value}</h2>;
   }
 }

+ 3 - 5
public/app/plugins/panel/heatmap/color_legend.ts

@@ -1,12 +1,10 @@
-import angular from 'angular';
 import _ from 'lodash';
 import $ from 'jquery';
 import * as d3 from 'd3';
 import { contextSrv } from 'app/core/core';
 import { tickStep } from 'app/core/utils/ticks';
 import { getColorScale, getOpacityScale } from './color_scale';
-
-const module = angular.module('grafana.directives');
+import coreModule from 'app/core/core_module';
 
 const LEGEND_HEIGHT_PX = 6;
 const LEGEND_WIDTH_PX = 100;
@@ -16,7 +14,7 @@ const LEGEND_VALUE_MARGIN = 0;
 /**
  * Color legend for heatmap editor.
  */
-module.directive('colorLegend', () => {
+coreModule.directive('colorLegend', () => {
   return {
     restrict: 'E',
     template: '<div class="heatmap-color-legend"><svg width="16.5rem" height="24px"></svg></div>',
@@ -52,7 +50,7 @@ module.directive('colorLegend', () => {
 /**
  * Heatmap legend with scale values.
  */
-module.directive('heatmapLegend', () => {
+coreModule.directive('heatmapLegend', () => {
   return {
     restrict: 'E',
     template: `<div class="heatmap-color-legend"><svg width="${LEGEND_WIDTH_PX}px" height="${LEGEND_HEIGHT_PX}px"></svg></div>`,

+ 2 - 2
public/app/plugins/panel/text2/module.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
+import { PanelProps } from 'app/types';
 
 export class Text2 extends PureComponent<PanelProps> {
   constructor(props) {
@@ -14,7 +14,7 @@ export class Text2 extends PureComponent<PanelProps> {
       value = data[0].value;
     }
 
-    return <h2>Graph Panel! {value}</h2>;
+    return <h2>Text Panel! {value}</h2>;
   }
 }
 

+ 5 - 0
public/app/types/index.ts

@@ -9,6 +9,8 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys';
 import { Invitee, OrgUser, User, UsersState } from './user';
 import { DataSource, DataSourcesState } from './datasources';
 import { PluginMeta, Plugin, PluginsState } from './plugins';
+import { TimeRange, LoadingState } from './queries';
+import { PanelProps } from './panel';
 
 export {
   Team,
@@ -45,6 +47,9 @@ export {
   OrgUser,
   User,
   UsersState,
+  TimeRange,
+  LoadingState,
+  PanelProps,
 };
 
 export interface StoreState {

+ 6 - 0
public/app/types/panel.ts

@@ -0,0 +1,6 @@
+import { LoadingState } from './queries';
+
+export interface PanelProps {
+  data: any;
+  loading: LoadingState;
+}

+ 19 - 0
public/app/types/queries.ts

@@ -0,0 +1,19 @@
+import { Moment } from 'moment';
+
+export enum LoadingState {
+  NotStarted = 'NotStarted',
+  Loading = 'Loading',
+  Done = 'Done',
+  Error = 'Error',
+}
+
+export interface RawTimeRange {
+  from: Moment | string;
+  to: Moment | string;
+}
+
+export interface TimeRange {
+  from: Moment;
+  to: Moment;
+  raw: RawTimeRange;
+}