Browse Source

Moved more metrics tab to react

Torkel Ödegaard 7 years ago
parent
commit
4591c3555c

+ 1 - 1
public/app/features/dashboard/dashboard_migration.ts

@@ -143,7 +143,7 @@ export class DashboardMigrator {
       panelUpgrades.push(panel => {
         _.each(panel.targets, target => {
           if (!target.refId) {
-            target.refId = this.dashboard.getNextQueryLetter(panel);
+            target.refId = panel.getNextQueryLetter();
           }
         });
       });

+ 0 - 10
public/app/features/dashboard/dashboard_model.ts

@@ -806,16 +806,6 @@ export class DashboardModel {
     return this.timezone === 'browser' ? moment(date).fromNow() : moment.utc(date).fromNow();
   }
 
-  getNextQueryLetter(panel) {
-    const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-
-    return _.find(letters, refId => {
-      return _.every(panel.targets, other => {
-        return other.refId !== refId;
-      });
-    });
-  }
-
   isTimezoneUtc() {
     return this.getTimezone() === 'utc';
   }

+ 90 - 21
public/app/features/dashboard/dashgrid/QueriesTab.tsx

@@ -1,21 +1,27 @@
+// Libraries
 import React, { SFC, PureComponent } from 'react';
+import Remarkable from 'remarkable';
+import _ from 'lodash';
+
+// Components
 import DataSourceOption from './DataSourceOption';
-import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
 import { EditorTabBody } from './EditorTabBody';
 import { DataSourcePicker } from './DataSourcePicker';
-import { PanelModel } from '../panel_model';
-import { DashboardModel } from '../dashboard_model';
-import './../../panel/metrics_tab';
-import config from 'app/core/config';
 import { QueryInspector } from './QueryInspector';
 import { TimeRangeOptions } from './TimeRangeOptions';
+import './../../panel/metrics_tab';
+import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab';
 
 // Services
 import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
 import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
-import { DataSourceSelectItem } from 'app/types';
+import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
+import config from 'app/core/config';
 
-import Remarkable from 'remarkable';
+// Types
+import { PanelModel } from '../panel_model';
+import { DashboardModel } from '../dashboard_model';
+import { DataSourceSelectItem, DataQuery } from 'app/types';
 
 interface Props {
   panel: PanelModel;
@@ -40,7 +46,7 @@ interface LoadingPlaceholderProps {
 const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text }) => <h2>{text}</h2>;
 
 export class QueriesTab extends PureComponent<Props, State> {
-  element: any;
+  element: HTMLElement;
   component: AngularComponent;
   datasources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources();
   backendSrv: BackendSrv = getBackendSrv();
@@ -59,20 +65,30 @@ export class QueriesTab extends PureComponent<Props, State> {
     };
   }
 
+  getAngularQueryComponentScope(): AngularQueryComponentScope {
+    const { panel, dashboard } = this.props;
+
+    return {
+      panel: panel,
+      dashboard: dashboard,
+      refresh: () => panel.refresh(),
+      render: () => panel.render,
+      addQuery: this.onAddQuery,
+      moveQuery: this.onMoveQuery,
+      removeQuery: this.onRemoveQuery,
+      events: panel.events,
+    };
+  }
+
   componentDidMount() {
     if (!this.element) {
       return;
     }
 
-    const { panel, dashboard } = this.props;
     const loader = getAngularLoader();
     const template = '<metrics-tab />';
     const scopeProps = {
-      ctrl: {
-        panel: panel,
-        dashboard: dashboard,
-        refresh: () => panel.refresh(),
-      },
+      ctrl: this.getAngularQueryComponentScope(),
     };
 
     this.component = loader.load(this.element, scopeProps, template);
@@ -87,6 +103,7 @@ export class QueriesTab extends PureComponent<Props, State> {
   onChangeDataSource = datasource => {
     const { panel } = this.props;
     const { currentDatasource } = this.state;
+
     // switching to mixed
     if (datasource.meta.mixed) {
       panel.targets.forEach(target => {
@@ -95,10 +112,16 @@ export class QueriesTab extends PureComponent<Props, State> {
           target.datasource = config.defaultDatasource;
         }
       });
-    } else if (currentDatasource && currentDatasource.meta.mixed) {
-      panel.targets.forEach(target => {
-        delete target.datasource;
-      });
+    } else if (currentDatasource) {
+      // if switching from mixed
+      if (currentDatasource.meta.mixed) {
+        for (const target of panel.targets) {
+          delete target.datasource;
+        }
+      } else if (currentDatasource.meta.id !== datasource.meta.id) {
+        // we are changing data source type, clear queries
+        panel.targets = [{ refId: 'A' }];
+      }
     }
 
     panel.datasource = datasource.value;
@@ -227,9 +250,41 @@ export class QueriesTab extends PureComponent<Props, State> {
     return isLoading ? <LoadingPlaceholder text="Loading help..." /> : helpHtml;
   };
 
+  onAddQuery = (query?: DataQuery) => {
+    this.props.panel.addQuery(query);
+    this.forceUpdate();
+  };
+
+  onAddQueryClick = () => {
+    this.props.panel.addQuery();
+    this.component.digest();
+    this.forceUpdate();
+  };
+
+  onRemoveQuery = (query: DataQuery) => {
+    const { panel } = this.props;
+
+    const index = _.indexOf(panel.targets, query);
+    panel.targets.splice(index, 1);
+    panel.refresh();
+
+    this.forceUpdate();
+  };
+
+  onMoveQuery = (query: DataQuery, direction: number) => {
+    const { panel } = this.props;
+
+    const index = _.indexOf(panel.targets, query);
+    _.move(panel.targets, index, index + direction);
+
+    this.forceUpdate();
+  };
+
   render() {
+    const { panel } = this.props;
     const { currentDatasource } = this.state;
     const { hasQueryHelp } = currentDatasource.meta;
+
     const dsInformation = {
       title: currentDatasource.name,
       imgSrc: currentDatasource.meta.info.logos.small,
@@ -266,9 +321,23 @@ export class QueriesTab extends PureComponent<Props, State> {
 
     return (
       <EditorTabBody heading="Queries" main={dsInformation} toolbarItems={[options, queryInspector, dsHelp]}>
-        <>
-          <div ref={element => (this.element = element)} style={{ width: '100%' }} />
-        </>
+        <div className="query-editor-rows gf-form-group">
+          <div ref={element => (this.element = element)} />
+
+          <div className="gf-form-query">
+            <div className="gf-form gf-form-query-letter-cell">
+              <label className="gf-form-label">
+                <span className="gf-form-query-letter-cell-carret muted">
+                  <i className="fa fa-caret-down" />
+                </span>
+                <span className="gf-form-query-letter-cell-letter">{panel.getNextQueryLetter()}</span>
+              </label>
+              <button className="btn btn-secondary gf-form-btn" onClick={this.onAddQueryClick}>
+                Add Query
+              </button>
+            </div>
+          </div>
+        </div>
       </EditorTabBody>
     );
   }

+ 18 - 0
public/app/features/dashboard/panel_model.ts

@@ -1,6 +1,7 @@
 import { Emitter } from 'app/core/utils/emitter';
 import _ from 'lodash';
 import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants';
+import { DataQuery } from 'app/types';
 
 export interface GridPos {
   x: number;
@@ -237,6 +238,23 @@ export class PanelModel {
     this.restorePanelOptions(pluginId);
   }
 
+  addQuery(query?: DataQuery) {
+    query = query || { refId: 'A' };
+    (query.refId = this.getNextQueryLetter()), (query.isNew = true);
+
+    this.targets.push(query);
+  }
+
+  getNextQueryLetter(): string {
+    const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+    return _.find(letters, refId => {
+      return _.every(this.targets, other => {
+        return other.refId !== refId;
+      });
+    });
+  }
+
   destroy() {
     this.events.emit('panel-teardown');
     this.events.removeAllListeners();

+ 9 - 167
public/app/features/panel/metrics_tab.ts

@@ -1,181 +1,24 @@
 // Libraries
 import _ from 'lodash';
-import Remarkable from 'remarkable';
 
 // Services & utils
 import coreModule from 'app/core/core_module';
-import config from 'app/core/config';
 import { Emitter } from 'app/core/utils/emitter';
 
 // Types
 import { DashboardModel } from '../dashboard/dashboard_model';
+import { PanelModel } from '../dashboard/panel_model';
+import { DataQuery } from 'app/types';
 
-export class MetricsTabCtrl {
-  dsName: string;
-  panel: any;
-  panelCtrl: any;
-  datasources: any[];
-  datasourceInstance: any;
-  nextRefId: string;
+export interface AngularQueryComponentScope {
+  panel: PanelModel;
   dashboard: DashboardModel;
-  panelDsValue: any;
-  addQueryDropdown: any;
-  queryTroubleshooterOpen: boolean;
-  helpOpen: boolean;
-  optionsOpen: boolean;
-  hasQueryHelp: boolean;
-  helpHtml: string;
-  queryOptions: any;
   events: Emitter;
-
-  /** @ngInject */
-  constructor($scope, private $sce, datasourceSrv, private backendSrv) {
-    this.panelCtrl = $scope.ctrl;
-    $scope.ctrl = this;
-
-    this.panel = this.panelCtrl.panel;
-    this.panel.datasource = this.panel.datasource || null;
-    this.panel.targets = this.panel.targets || [{}];
-
-    this.dashboard = this.panelCtrl.dashboard;
-    this.datasources = datasourceSrv.getMetricSources();
-    this.panelDsValue = this.panelCtrl.panel.datasource;
-
-    // added here as old query controller expects this on panelCtrl but
-    // they are getting MetricsTabCtrl instead
-    this.events = this.panel.events;
-
-    for (const ds of this.datasources) {
-      if (ds.value === this.panelDsValue) {
-        this.datasourceInstance = ds;
-      }
-    }
-
-    this.addQueryDropdown = { text: 'Add Query', value: null, fake: true };
-
-    // update next ref id
-    this.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
-    this.updateDatasourceOptions();
-  }
-
-  updateDatasourceOptions() {
-    if (this.datasourceInstance) {
-      this.hasQueryHelp = this.datasourceInstance.meta.hasQueryHelp;
-      this.queryOptions = this.datasourceInstance.meta.queryOptions;
-    }
-  }
-
-  getOptions(includeBuiltin) {
-    return Promise.resolve(
-      this.datasources
-        .filter(value => {
-          return includeBuiltin || !value.meta.builtIn;
-        })
-        .map(ds => {
-          return { value: ds.value, text: ds.name, datasource: ds };
-        })
-    );
-  }
-
-  datasourceChanged(option) {
-    if (!option) {
-      return;
-    }
-
-    this.setDatasource(option.datasource);
-    this.updateDatasourceOptions();
-  }
-
-  setDatasource(datasource) {
-    // switching to mixed
-    if (datasource.meta.mixed) {
-      _.each(this.panel.targets, target => {
-        target.datasource = this.panel.datasource;
-        if (!target.datasource) {
-          target.datasource = config.defaultDatasource;
-        }
-      });
-    } else if (this.datasourceInstance) {
-      // if switching from mixed
-      if (this.datasourceInstance.meta.mixed) {
-        _.each(this.panel.targets, target => {
-          delete target.datasource;
-        });
-      } else if (this.datasourceInstance.meta.id !== datasource.meta.id) {
-        // we are changing data source type, clear queries
-        this.panel.targets = [{ refId: 'A' }];
-        this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
-      }
-    }
-
-    this.datasourceInstance = datasource;
-    this.panel.datasource = datasource.value;
-    this.panel.refresh();
-  }
-
-  addMixedQuery(option) {
-    if (!option) {
-      return;
-    }
-
-    this.panelCtrl.addQuery({
-      isNew: true,
-      datasource: option.datasource.name,
-    });
-    this.addQueryDropdown = { text: 'Add Query', value: null, fake: true };
-  }
-
-  toggleHelp() {
-    this.optionsOpen = false;
-    this.queryTroubleshooterOpen = false;
-    this.helpOpen = !this.helpOpen;
-
-    this.backendSrv.get(`/api/plugins/${this.datasourceInstance.meta.id}/markdown/query_help`).then(res => {
-      const md = new Remarkable();
-      this.helpHtml = this.$sce.trustAsHtml(md.render(res));
-    });
-  }
-
-  toggleOptions() {
-    this.helpOpen = false;
-    this.queryTroubleshooterOpen = false;
-    this.optionsOpen = !this.optionsOpen;
-  }
-
-  toggleQueryTroubleshooter() {
-    this.helpOpen = false;
-    this.optionsOpen = false;
-    this.queryTroubleshooterOpen = !this.queryTroubleshooterOpen;
-  }
-
-  addQuery(query?) {
-    query = query || {};
-    query.refId = this.dashboard.getNextQueryLetter(this.panel);
-    query.isNew = true;
-
-    this.panel.targets.push(query);
-    this.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
-  }
-
-  refresh() {
-    this.panel.refresh();
-  }
-
-  render() {
-    this.panel.render();
-  }
-
-  removeQuery(target) {
-    const index = _.indexOf(this.panel.targets, target);
-    this.panel.targets.splice(index, 1);
-    this.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
-    this.panel.refresh();
-  }
-
-  moveQuery(target, direction) {
-    const index = _.indexOf(this.panel.targets, target);
-    _.move(this.panel.targets, index, index + direction);
-  }
+  refresh: () => void;
+  render: () => void;
+  removeQuery: (query: DataQuery) => void;
+  addQuery: (query?: DataQuery) => void;
+  moveQuery: (query: DataQuery, direction: number) => void;
 }
 
 /** @ngInject */
@@ -185,7 +28,6 @@ export function metricsTabDirective() {
     restrict: 'E',
     scope: true,
     templateUrl: 'public/app/features/panel/partials/metrics_tab.html',
-    controller: MetricsTabCtrl,
   };
 }
 

+ 17 - 20
public/app/features/panel/partials/metrics_tab.html

@@ -1,5 +1,3 @@
-
-<div class="query-editor-rows gf-form-group" ng-if="ctrl.datasourceInstance">
 	<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
 		<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
 			<plugin-component type="query-ctrl">
@@ -7,21 +5,20 @@
 		</rebuild-on-change>
 	</div>
 
-	<div class="gf-form-query">
-		<div class="gf-form gf-form-query-letter-cell">
-			<label class="gf-form-label">
-				<span class="gf-form-query-letter-cell-carret">
-					<i class="fa fa-caret-down"></i>
-				</span>
-				<span class="gf-form-query-letter-cell-letter">{{ctrl.nextRefId}}</span>
-			</label>
-			<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.datasourceInstance.meta.mixed">
-				Add Query
-			</button>
-			<div class="dropdown" ng-if="ctrl.datasourceInstance.meta.mixed">
-				<gf-form-dropdown model="ctrl.addQueryDropdown" get-options="ctrl.getOptions(false)" on-change="ctrl.addMixedQuery($option)">
-				</gf-form-dropdown>
-			</div>
-		</div>
-	</div>
-</div>
+	<!-- <div class="gf&#45;form&#45;query"> -->
+	<!-- 	<div class="gf&#45;form gf&#45;form&#45;query&#45;letter&#45;cell"> -->
+	<!-- 		<label class="gf&#45;form&#45;label"> -->
+	<!-- 			<span class="gf&#45;form&#45;query&#45;letter&#45;cell&#45;carret"> -->
+	<!-- 				<i class="fa fa&#45;caret&#45;down"></i> -->
+	<!-- 			</span> -->
+	<!-- 			<span class="gf&#45;form&#45;query&#45;letter&#45;cell&#45;letter">{{ctrl.nextRefId}}</span> -->
+	<!-- 		</label> -->
+	<!-- 		<button class="btn btn&#45;secondary gf&#45;form&#45;btn" ng&#45;click="ctrl.addQuery()" ng&#45;hide="ctrl.datasourceInstance.meta.mixed"> -->
+	<!-- 			Add Query -->
+	<!-- 		</button> -->
+	<!-- 		<div class="dropdown" ng&#45;if="ctrl.datasourceInstance.meta.mixed"> -->
+	<!-- 			<gf&#45;form&#45;dropdown model="ctrl.addQueryDropdown" get&#45;options="ctrl.getOptions(false)" on&#45;change="ctrl.addMixedQuery($option)"> -->
+	<!-- 			</gf&#45;form&#45;dropdown> -->
+	<!-- 		</div> -->
+	<!-- 	</div> -->
+	<!-- </div> -->

+ 1 - 1
public/app/features/panel/query_editor_row.ts

@@ -20,7 +20,7 @@ export class QueryRowCtrl {
     this.hideEditorRowActions = this.panelCtrl.hideEditorRowActions;
 
     if (!this.target.refId) {
-      this.target.refId = this.panelCtrl.dashboard.getNextQueryLetter(this.panel);
+      this.target.refId = this.panel.getNextQueryLetter();
     }
 
     this.toggleCollapse(true);

+ 0 - 1
public/sass/components/_gf-form.scss

@@ -110,7 +110,6 @@ $input-border: 1px solid $input-border-color;
 
   &--grow {
     flex-grow: 1;
-    min-height: 2.6rem;
   }
 
   &--error {