diff --git a/public/app/plugins/datasource/stackdriver/partials/query.aggregation.html b/public/app/plugins/datasource/stackdriver/partials/query.aggregation.html
new file mode 100755
index 00000000000..f48d0d9f565
--- /dev/null
+++ b/public/app/plugins/datasource/stackdriver/partials/query.aggregation.html
@@ -0,0 +1,42 @@
+
+
\ No newline at end of file
diff --git a/public/app/plugins/datasource/stackdriver/partials/query.editor.html b/public/app/plugins/datasource/stackdriver/partials/query.editor.html
index 891dab6d93c..71ae3dc6328 100755
--- a/public/app/plugins/datasource/stackdriver/partials/query.editor.html
+++ b/public/app/plugins/datasource/stackdriver/partials/query.editor.html
@@ -31,48 +31,7 @@
-
-
+
Alias By
diff --git a/public/app/plugins/datasource/stackdriver/query_aggregation_ctrl.ts b/public/app/plugins/datasource/stackdriver/query_aggregation_ctrl.ts
new file mode 100644
index 00000000000..79161e0ca8c
--- /dev/null
+++ b/public/app/plugins/datasource/stackdriver/query_aggregation_ctrl.ts
@@ -0,0 +1,73 @@
+import angular from 'angular';
+import _ from 'lodash';
+import * as options from './constants';
+
+export class StackdriverAggregation {
+ constructor() {
+ return {
+ templateUrl: 'public/app/plugins/datasource/stackdriver/partials/query.aggregation.html',
+ controller: 'StackdriverAggregationCtrl',
+ restrict: 'E',
+ scope: {
+ target: '=',
+ refresh: '&',
+ },
+ };
+ }
+}
+
+export class StackdriverAggregationCtrl {
+ target: any;
+ alignOptions: any[];
+ aggOptions: any[];
+ refresh: () => void;
+
+ constructor(private $scope) {
+ this.aggOptions = options.aggOptions;
+ this.alignOptions = options.alignOptions;
+ $scope.alignmentPeriods = options.alignmentPeriods;
+ $scope.getAlignOptions = this.getAlignOptions;
+ $scope.getAggOptions = this.getAggOptions;
+ $scope.onAlignmentChange = this.onAlignmentChange;
+ $scope.onAggregationChange = this.onAggregationChange;
+ this.refresh = $scope.refresh;
+ }
+
+ onAlignmentChange(newVal) {
+ if (newVal === 'ALIGN_NONE') {
+ this.target.aggregation.crossSeriesReducer = 'REDUCE_NONE';
+ }
+ this.refresh();
+ }
+
+ onAggregationChange(newVal) {
+ if (newVal !== 'REDUCE_NONE') {
+ const newAlignmentOption = options.alignOptions.find(o => o.value !== 'ALIGN_NONE');
+ this.target.aggregation.perSeriesAligner = newAlignmentOption ? newAlignmentOption.value : '';
+ }
+ this.refresh();
+ }
+
+ getAlignOptions() {
+ return !this.target.valueType
+ ? options.alignOptions
+ : options.alignOptions.filter(i => {
+ return (
+ i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
+ );
+ });
+ }
+
+ getAggOptions() {
+ return !this.target.metricKind
+ ? options.aggOptions
+ : options.aggOptions.filter(i => {
+ return (
+ i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
+ );
+ });
+ }
+}
+
+angular.module('grafana.controllers').directive('stackdriverAggregation', StackdriverAggregation);
+angular.module('grafana.controllers').controller('StackdriverAggregationCtrl', StackdriverAggregationCtrl);
diff --git a/public/app/plugins/datasource/stackdriver/query_ctrl.ts b/public/app/plugins/datasource/stackdriver/query_ctrl.ts
index db276650e65..be98e9bf3ec 100644
--- a/public/app/plugins/datasource/stackdriver/query_ctrl.ts
+++ b/public/app/plugins/datasource/stackdriver/query_ctrl.ts
@@ -1,8 +1,8 @@
import _ from 'lodash';
import { QueryCtrl } from 'app/plugins/sdk';
import appEvents from 'app/core/app_events';
-import * as options from './constants';
import { FilterSegments, DefaultRemoveFilterValue } from './filter_segments';
+import './query_aggregation_ctrl';
export interface QueryMeta {
rawQuery: string;
@@ -55,8 +55,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
valueType: '',
};
- alignOptions: any[];
- aggOptions: any[];
groupBySegments: any[];
removeSegment: any;
showHelp: boolean;
@@ -74,9 +72,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
- this.stackdriverConstants = options;
- this.aggOptions = options.aggOptions;
- this.alignOptions = options.alignOptions;
this.getCurrentProject()
.then(this.getMetricTypes.bind(this))
@@ -155,6 +150,9 @@ export class StackdriverQueryCtrl extends QueryCtrl {
this.metricLabels = data.results[this.target.refId].meta.metricLabels;
this.resourceLabels = data.results[this.target.refId].meta.resourceLabels;
+
+ this.target.valueType = data.results[this.target.refId].meta.valueType;
+ this.target.metricKind = data.results[this.target.refId].meta.metricKind;
resolve();
} catch (error) {
resolve();
@@ -264,31 +262,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
}
}
- getAlignOptions() {
- return !this.target.valueType
- ? options.alignOptions
- : options.alignOptions.filter(i => {
- return (
- i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
- );
- });
- }
-
- getAggOptions() {
- if (this.target.aggregation.perSeriesAligner === 'ALIGN_NONE') {
- this.target.aggregation.crossSeriesReducer = options.aggOptions[0].value;
- return options.aggOptions.slice(0, 1);
- }
-
- return !this.target.metricKind
- ? options.aggOptions
- : options.aggOptions.filter(i => {
- return (
- i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
- );
- });
- }
-
onDataReceived(dataList) {
this.lastQueryError = null;
this.lastQueryMeta = null;
@@ -297,8 +270,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
if (anySeriesFromQuery) {
this.lastQueryMeta = anySeriesFromQuery.meta;
this.lastQueryMeta.rawQueryString = decodeURIComponent(this.lastQueryMeta.rawQuery);
- this.target.valueType = anySeriesFromQuery.meta.valueType;
- this.target.metricKind = anySeriesFromQuery.meta.metricKind;
}
}
diff --git a/public/app/plugins/datasource/stackdriver/specs/query_aggregation_ctrl.test.ts b/public/app/plugins/datasource/stackdriver/specs/query_aggregation_ctrl.test.ts
new file mode 100644
index 00000000000..aebd2a12dd6
--- /dev/null
+++ b/public/app/plugins/datasource/stackdriver/specs/query_aggregation_ctrl.test.ts
@@ -0,0 +1,81 @@
+import { StackdriverAggregationCtrl } from '../query_aggregation_ctrl';
+
+describe('StackdriverAggregationCtrl', () => {
+ let ctrl;
+ describe('aggregation and alignment options', () => {
+ beforeEach(() => {
+ ctrl = createCtrlWithFakes();
+ });
+ describe('when new query result is returned from the server', () => {
+ describe('and result is double and gauge', () => {
+ beforeEach(async () => {
+ ctrl.target.valueType = 'DOUBLE';
+ ctrl.target.metricKind = 'GAUGE';
+ });
+
+ it('should populate all aggregate options except two', () => {
+ const result = ctrl.getAggOptions();
+ expect(result.length).toBe(11);
+ expect(result.map(o => o.value)).toEqual(
+ expect.not.arrayContaining(['REDUCE_COUNT_TRUE', 'REDUCE_COUNT_FALSE'])
+ );
+ });
+
+ it('should populate all alignment options except two', () => {
+ const result = ctrl.getAlignOptions();
+ console.log(result.map(o => o.value));
+ expect(result.length).toBe(10);
+ expect(result.map(o => o.value)).toEqual(
+ expect.not.arrayContaining(['REDUCE_COUNT_TRUE', 'REDUCE_COUNT_FALSE'])
+ );
+ });
+ });
+ });
+
+ describe('when a user a user select ALIGN_NONE and a reducer is selected', () => {
+ beforeEach(async () => {
+ ctrl.target.aggregation.crossSeriesReducer = 'RANDOM_REDUCER';
+ ctrl.onAlignmentChange('ALIGN_NONE');
+ });
+ it('should set REDUCE_NONE as selected aggregation', () => {
+ expect(ctrl.target.aggregation.crossSeriesReducer).toBe('REDUCE_NONE');
+ });
+ });
+
+ describe('when a user a user select a reducer and no alignment is selected', () => {
+ beforeEach(async () => {
+ ctrl.target.aggregation.crossSeriesReducer = 'REDUCE_NONE';
+ ctrl.target.aggregation.perSeriesAligner = 'ALIGN_NONE';
+ ctrl.onAggregationChange('ALIGN_NONE');
+ });
+
+ it('should set an alignment', () => {
+ expect(ctrl.target.aggregation.perSeriesAligner).not.toBe('ALIGN_NONE');
+ });
+ });
+ });
+});
+
+function createCtrlWithFakes() {
+ StackdriverAggregationCtrl.prototype.target = createTarget();
+ return new StackdriverAggregationCtrl({ refresh: () => {} });
+}
+
+function createTarget(existingFilters?: string[]) {
+ return {
+ project: {
+ id: '',
+ name: '',
+ },
+ metricType: 'ametric',
+ refId: 'A',
+ aggregation: {
+ crossSeriesReducer: '',
+ alignmentPeriod: '',
+ perSeriesAligner: '',
+ groupBys: [],
+ },
+ filters: existingFilters || [],
+ aliasBy: '',
+ };
+}