diff --git a/public/app/plugins/datasource/stackdriver/components/Aggregations.tsx b/public/app/plugins/datasource/stackdriver/components/Aggregations.tsx index a1a2410dada..44bd2cdd92b 100644 --- a/public/app/plugins/datasource/stackdriver/components/Aggregations.tsx +++ b/public/app/plugins/datasource/stackdriver/components/Aggregations.tsx @@ -11,8 +11,10 @@ import { StackdriverPicker } from './StackdriverPicker'; export interface Props { onChange: (metricDescriptor) => void; templateSrv: any; - valueType: string; - metricKind: string; + metricDescriptor: { + valueType: string; + metricKind: string; + }; aggregation: { crossSeriesReducer: string; alignmentPeriod: string; @@ -39,26 +41,31 @@ export class Aggregations extends React.Component { } componentDidMount() { - this.setAggOptions(this.props); + if (this.props.metricDescriptor !== null) { + this.setAggOptions(this.props); + } } componentWillReceiveProps(nextProps: Props) { - const { valueType, metricKind, aggregation } = this.props; - if ( - nextProps.valueType !== valueType || - nextProps.metricKind !== metricKind || - nextProps.aggregation.groupBys !== aggregation.groupBys - ) { + // const { metricDescriptor, aggregation } = this.props; + // if ( + // (metricDescriptor !== null && nextProps.metricDescriptor.valueType !== metricDescriptor.valueType) || + // nextProps.metricDescriptor.metricKind !== metricDescriptor.metricKind || + // nextProps.aggregation.groupBys !== aggregation.groupBys + // ) { + if (nextProps.metricDescriptor !== null) { this.setAggOptions(nextProps); } } - setAggOptions({ valueType, metricKind, aggregation }) { + setAggOptions({ metricDescriptor, aggregation }) { const { templateSrv } = this.props; - let aggregations = getAggregationOptionsByMetric(valueType, metricKind).map(a => ({ - ...a, - label: a.text, - })); + let aggregations = getAggregationOptionsByMetric(metricDescriptor.valueType, metricDescriptor.metricKind).map( + a => ({ + ...a, + label: a.text, + }) + ); if ( aggregations.length > 0 && @@ -75,7 +82,10 @@ export class Aggregations extends React.Component { } deselectAggregationOption(notValidOptionValue: string) { - const aggregations = getAggregationOptionsByMetric(this.props.valueType, this.props.metricKind); + const aggregations = getAggregationOptionsByMetric( + this.props.metricDescriptor.valueType, + this.props.metricDescriptor.metricKind + ); const newValue = aggregations.find(o => o.value !== notValidOptionValue); this.handleAggregationChange(newValue ? newValue.value : ''); } diff --git a/public/app/plugins/datasource/stackdriver/components/Filter.tsx b/public/app/plugins/datasource/stackdriver/components/Filter.tsx index 03ee301e774..aab0d2e7be9 100644 --- a/public/app/plugins/datasource/stackdriver/components/Filter.tsx +++ b/public/app/plugins/datasource/stackdriver/components/Filter.tsx @@ -1,5 +1,6 @@ import React from 'react'; import _ from 'lodash'; +import appEvents from 'app/core/app_events'; import { QueryMeta, Target } from '../types'; import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; @@ -8,14 +9,19 @@ import '../query_filter_ctrl'; export interface Props { filtersChanged: (filters) => void; groupBysChanged: (groupBys) => void; + metricType: string; templateSrv: any; - labelData: QueryMeta; - loading: Promise; target: Target; uiSegmentSrv: any; + datasource: any; } -export class Filter extends React.Component { +interface State { + labelData: QueryMeta; + loading: Promise; +} + +export class Filter extends React.Component { element: any; component: AngularComponent; @@ -24,13 +30,13 @@ export class Filter extends React.Component { return; } - const { loading, labelData, target, filtersChanged, groupBysChanged } = this.props; + const { target, filtersChanged, groupBysChanged } = this.props; const loader = getAngularLoader(); const template = ' '; const scopeProps = { - loading, - labelData, + loading: this.loadLabels.bind(this), + labelData: null, target, filtersChanged, groupBysChanged, @@ -39,11 +45,11 @@ export class Filter extends React.Component { this.component = loader.load(this.element, scopeProps, template); } - componentDidUpdate() { - const scope = this.component.getScope(); - scope.loading = _.clone(this.props.loading); - scope.labelData = _.cloneDeep(this.props.labelData); - scope.target = _.cloneDeep(this.props.target); + componentDidUpdate(prevProps: Props) { + if (prevProps.metricType !== this.props.metricType) { + const scope = this.component.getScope(); + scope.loading = this.loadLabels(scope); + } } componentWillUnmount() { @@ -52,6 +58,19 @@ export class Filter extends React.Component { } } + async loadLabels(scope) { + return new Promise(async resolve => { + try { + const { meta } = await this.props.datasource.getLabels(this.props.target.metricType, this.props.target.refId); + scope.labelData = meta; + resolve(); + } catch (error) { + appEvents.emit('alert-error', ['Error', 'Error loading metric labels for ' + this.props.target.metricType]); + resolve(); + } + }); + } + render() { return
(this.element = element)} style={{ width: '100%' }} />; } diff --git a/public/app/plugins/datasource/stackdriver/components/Metrics.tsx b/public/app/plugins/datasource/stackdriver/components/Metrics.tsx index 1a1035ef2e1..f2f1399593f 100644 --- a/public/app/plugins/datasource/stackdriver/components/Metrics.tsx +++ b/public/app/plugins/datasource/stackdriver/components/Metrics.tsx @@ -9,6 +9,7 @@ export interface Props { datasource: any; defaultProject: string; metricType: string; + children?: (renderProps: any) => JSX.Element; } interface State { @@ -17,6 +18,7 @@ interface State { services: any[]; service: string; metric: string; + metricDescriptor: any; } export class Metrics extends React.Component { @@ -26,6 +28,7 @@ export class Metrics extends React.Component { services: [], service: '', metric: '', + metricDescriptor: null, }; constructor(props) { @@ -68,13 +71,16 @@ export class Metrics extends React.Component { const services = this.getServicesList(metricDescriptors); const metrics = this.getMetricsList(metricDescriptors); const service = metrics.length > 0 ? metrics[0].service : ''; - this.setState({ metricDescriptors, services, metrics, service: service }); + const metricDescriptor = this.getSelectedMetricDescriptor(this.props.metricType); + this.setState({ metricDescriptors, services, metrics, service: service, metricDescriptor }); + } + + getSelectedMetricDescriptor(metricType) { + return this.state.metricDescriptors.find(md => md.type === this.props.templateSrv.replace(metricType)); } getMetricsList(metricDescriptors) { - const selectedMetricDescriptor = metricDescriptors.find( - md => md.type === this.props.templateSrv.replace(this.props.metricType) - ); + const selectedMetricDescriptor = this.getSelectedMetricDescriptor(this.props.metricType); const metricsByService = metricDescriptors.filter(m => m.service === selectedMetricDescriptor.service).map(m => ({ service: m.service, value: m.type, @@ -103,8 +109,9 @@ export class Metrics extends React.Component { } handleMetricTypeChange(value) { - const selectedMetricDescriptor = this.state.metricDescriptors.find(md => md.type === value); - this.props.onChange(selectedMetricDescriptor); + const metricDescriptor = this.getSelectedMetricDescriptor(value); + this.setState({ metricDescriptor }); + this.props.onChange(metricDescriptor); } getServicesList(metricDescriptors) { @@ -166,6 +173,7 @@ export class Metrics extends React.Component {
+ {this.props.children(this.state.metricDescriptor)} ); } diff --git a/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx b/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx index dbac6a60bb2..bd4b76dff91 100644 --- a/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx +++ b/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx @@ -1,11 +1,10 @@ import React from 'react'; import _ from 'lodash'; -import appEvents from 'app/core/app_events'; import { Metrics } from './Metrics'; import { Filter } from './Filter'; import { Aggregations } from './Aggregations'; -import { Target, QueryMeta } from '../types'; +import { Target } from '../types'; export interface Props { onQueryChange: (target: Target) => void; @@ -18,8 +17,6 @@ export interface Props { interface State { target: Target; - labelData: QueryMeta; - loadLabelsPromise: Promise; } const DefaultTarget: Target = { @@ -41,85 +38,79 @@ const DefaultTarget: Target = { }; export class QueryEditor extends React.Component { - state: State = { labelData: null, loadLabelsPromise: new Promise(() => {}), target: DefaultTarget }; + state: State = { target: DefaultTarget }; componentDidMount() { - this.getLabels(); this.setState({ target: this.props.target }); } - async getLabels() { - const loadLabelsPromise = new Promise(async resolve => { - try { - const { meta } = await this.props.datasource.getLabels(this.props.target.metricType, this.props.target.refId); - this.setState({ labelData: meta }); - resolve(); - } catch (error) { - appEvents.emit('alert-error', ['Error', 'Error loading metric labels for ' + this.props.target.metricType]); - resolve(); - } - }); - this.setState({ loadLabelsPromise }); - } - handleMetricTypeChange({ valueType, metricKind, type, unit }) { - this.setState({ - target: { - ...this.state.target, - ...{ - metricType: type, - unit, - valueType, - metricKind, + this.setState( + { + target: { + ...this.state.target, + ...{ + metricType: type, + unit, + valueType, + metricKind, + }, }, }, - }); - - // this.$rootScope.$broadcast('metricTypeChanged'); - this.getLabels(); - this.props.onQueryChange(this.state.target); - this.props.onExecuteQuery(); + () => { + this.props.onQueryChange(this.state.target); + this.props.onExecuteQuery(); + } + ); } handleFilterChange(value) { - this.setState({ - target: { - ...this.state.target, - filters: value, + this.setState( + { + target: { + ...this.state.target, + filters: value, + }, }, - }); - this.props.onQueryChange(this.state.target); - this.props.onExecuteQuery(); + () => { + this.props.onQueryChange(this.state.target); + this.props.onExecuteQuery(); + } + ); } handleGroupBysChange(value) { - this.setState({ - target: { - ...this.state.target, - groupBys: value, + this.setState( + { + target: { + ...this.state.target, + groupBys: value, + }, }, - }); - this.props.onQueryChange(this.state.target); - this.props.onExecuteQuery(); + () => { + this.props.onQueryChange(this.state.target); + this.props.onExecuteQuery(); + } + ); } handleAggregationChange(value) { - this.setState({ - target: { - ...this.state.target, - aggregation: { - ...this.state.target.aggregation, - crossSeriesReducer: value, - }, + const target = { + ...this.state.target, + aggregation: { + ...this.state.target.aggregation, + crossSeriesReducer: value, }, + }; + this.setState({ target }, () => { + this.props.onQueryChange(target); + this.props.onExecuteQuery(); }); - this.props.onQueryChange(this.state.target); - this.props.onExecuteQuery(); } render() { - const { labelData, loadLabelsPromise, target } = this.state; - const { defaultProject, metricType, valueType, metricKind, aggregation } = target; + const { target } = this.state; + const { defaultProject, metricType, aggregation } = target; const { templateSrv, datasource, uiSegmentSrv } = this.props; return ( @@ -130,46 +121,27 @@ export class QueryEditor extends React.Component { templateSrv={templateSrv} datasource={datasource} onChange={value => this.handleMetricTypeChange(value)} - /> - this.handleFilterChange(value)} - groupBysChanged={value => this.handleGroupBysChange(value)} - target={target} - uiSegmentSrv={uiSegmentSrv} - labelData={labelData} - templateSrv={templateSrv} - loading={loadLabelsPromise} - /> - this.handleAggregationChange(value)} - /> - {/* target="ctrl.target" refresh="ctrl.refresh()" loading="ctrl.loadLabelsPromise" label-data="ctrl.labelData" */} - {/* - - - */} + > + {metric => ( + + this.handleFilterChange(value)} + groupBysChanged={value => this.handleGroupBysChange(value)} + target={target} + uiSegmentSrv={uiSegmentSrv} + templateSrv={templateSrv} + datasource={datasource} + metricType={metric ? metric.type : ''} + /> + this.handleAggregationChange(value)} + /> + + )} + ); }