diff --git a/public/app/plugins/datasource/stackdriver/components/OptionGroupPicker.tsx b/public/app/plugins/datasource/stackdriver/components/OptionGroupPicker.tsx new file mode 100644 index 00000000000..7401b226413 --- /dev/null +++ b/public/app/plugins/datasource/stackdriver/components/OptionGroupPicker.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import Select from 'react-select'; +import _ from 'lodash'; + +import GroupHeading from 'app/core/components/Picker/GroupHeading'; +import DescriptionOption from 'app/core/components/Picker/DescriptionOption'; +import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer'; +import ResetStyles from 'app/core/components/Picker/ResetStyles'; +import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage'; + +export interface Props { + onChange: (value: string) => void; + groups: any[]; + searchable: boolean; + selected: string; + placeholder?: string; + className?: string; +} + +export class OptionGroupPicker extends React.Component { + constructor(props) { + super(props); + } + + render() { + const { onChange, groups, selected, placeholder, className, searchable } = this.props; + const options = _.flatten(groups.map(o => o.options)); + const selectedOption = options.find(option => option.value === selected); + + return ( + { NoOptionsMessage, }} styles={ResetStyles} - isDisabled={false} + isSearchable={searchable} + maxMenuHeight={50} onChange={option => onChange(option.value)} getOptionValue={i => i.value} getOptionLabel={i => i.label} diff --git a/public/app/plugins/datasource/stackdriver/partials/query.filter.html b/public/app/plugins/datasource/stackdriver/partials/query.filter.html index 1d87c8a3005..df3821ac463 100644 --- a/public/app/plugins/datasource/stackdriver/partials/query.filter.html +++ b/public/app/plugins/datasource/stackdriver/partials/query.filter.html @@ -5,8 +5,9 @@ onChange="ctrl.handleServiceChange" selected="ctrl.service" options="ctrl.services" - placeholder="ctrl.defaultDropdownValue" - className="width-12" + searchable="false" + placeholder="ctrl.defaultServiceValue" + className=""width-15"" >
@@ -14,13 +15,14 @@
Metric - + className=""width-15"" + >
diff --git a/public/app/plugins/datasource/stackdriver/query_ctrl.ts b/public/app/plugins/datasource/stackdriver/query_ctrl.ts index 4a881d3c8df..48ea8ce140a 100644 --- a/public/app/plugins/datasource/stackdriver/query_ctrl.ts +++ b/public/app/plugins/datasource/stackdriver/query_ctrl.ts @@ -3,6 +3,7 @@ import { QueryCtrl } from 'app/plugins/sdk'; import './query_aggregation_ctrl'; import './query_filter_ctrl'; import { OptionPicker } from './components/OptionPicker'; +import { OptionGroupPicker } from './components/OptionGroupPicker'; import { react2AngularDirective } from 'app/core/utils/react2angular'; export interface QueryMeta { @@ -70,6 +71,15 @@ export class StackdriverQueryCtrl extends QueryCtrl { 'options', 'onChange', 'selected', + 'searchable', + 'className', + 'placeholder', + ]); + react2AngularDirective('optionGroupPicker', OptionGroupPicker, [ + 'groups', + 'onChange', + 'selected', + 'searchable', 'className', 'placeholder', ]); diff --git a/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts b/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts index 7926da9aa1c..dd7178ecca0 100644 --- a/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts +++ b/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts @@ -36,6 +36,7 @@ export class StackdriverFilterCtrl { metricType: string; metricDescriptors: any[]; metrics: any[]; + metricGroups: any[]; services: any[]; groupBySegments: any[]; filterSegments: FilterSegments; @@ -52,6 +53,7 @@ export class StackdriverFilterCtrl { this.metricDescriptors = []; this.metrics = []; + this.metricGroups = []; this.services = []; this.getCurrentProject() @@ -106,6 +108,7 @@ export class StackdriverFilterCtrl { this.metricDescriptors = await this.datasource.getMetricTypes(this.target.defaultProject); this.services = this.getServicesList(); this.metrics = this.getMetricsList(); + this.metricGroups = this.getMetricGroups(); return this.metricDescriptors; } else { return []; @@ -113,11 +116,11 @@ export class StackdriverFilterCtrl { } getServicesList() { - const defaultValue = { value: this.$scope.defaultServiceValue, text: this.$scope.defaultServiceValue }; + const defaultValue = { value: this.$scope.defaultServiceValue, label: this.$scope.defaultServiceValue }; const services = this.metricDescriptors.map(m => { return { value: m.service, - label: m.serviceShortName, + label: _.startCase(m.serviceShortName), }; }); @@ -128,6 +131,37 @@ export class StackdriverFilterCtrl { return services.length > 0 ? [defaultValue, ..._.uniqBy(services, 'value')] : []; } + getMetricGroups() { + return this.metrics.reduce((acc, curr) => { + const group = acc.find(group => group.service === curr.service); + if (group) { + group.options = [...group.options, { value: curr.value, label: curr.label }]; + } else { + acc = [ + ...acc, + { + label: _.startCase(curr.serviceShortName), + service: curr.service, + options: [{ value: curr.value, label: curr.label }], + }, + ]; + } + return acc; + }, []); + } + + insertTemplateVariables(options) { + const templateVariables = { + label: 'Template Variables', + options: this.templateSrv.variables.map(v => ({ + label: `$${v.name}`, + value: `$${v.name}`, + description: `$${v.definition}`, + })), + }; + return [templateVariables, { label: 'Metrics', options }]; + } + getMetricsList() { const metrics = this.metricDescriptors.map(m => { return { @@ -178,6 +212,7 @@ export class StackdriverFilterCtrl { handleServiceChange(service) { this.target.service = this.service = service; this.metrics = this.getMetricsList(); + this.metricGroups = this.getMetricGroups(); this.setMetricType(); this.getLabels(); if (!this.metrics.find(m => m.value === this.target.metricType)) {