use render props pattern
This commit is contained in:
@@ -11,8 +11,10 @@ import { StackdriverPicker } from './StackdriverPicker';
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
onChange: (metricDescriptor) => void;
|
onChange: (metricDescriptor) => void;
|
||||||
templateSrv: any;
|
templateSrv: any;
|
||||||
valueType: string;
|
metricDescriptor: {
|
||||||
metricKind: string;
|
valueType: string;
|
||||||
|
metricKind: string;
|
||||||
|
};
|
||||||
aggregation: {
|
aggregation: {
|
||||||
crossSeriesReducer: string;
|
crossSeriesReducer: string;
|
||||||
alignmentPeriod: string;
|
alignmentPeriod: string;
|
||||||
@@ -39,26 +41,31 @@ export class Aggregations extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.setAggOptions(this.props);
|
if (this.props.metricDescriptor !== null) {
|
||||||
|
this.setAggOptions(this.props);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: Props) {
|
componentWillReceiveProps(nextProps: Props) {
|
||||||
const { valueType, metricKind, aggregation } = this.props;
|
// const { metricDescriptor, aggregation } = this.props;
|
||||||
if (
|
// if (
|
||||||
nextProps.valueType !== valueType ||
|
// (metricDescriptor !== null && nextProps.metricDescriptor.valueType !== metricDescriptor.valueType) ||
|
||||||
nextProps.metricKind !== metricKind ||
|
// nextProps.metricDescriptor.metricKind !== metricDescriptor.metricKind ||
|
||||||
nextProps.aggregation.groupBys !== aggregation.groupBys
|
// nextProps.aggregation.groupBys !== aggregation.groupBys
|
||||||
) {
|
// ) {
|
||||||
|
if (nextProps.metricDescriptor !== null) {
|
||||||
this.setAggOptions(nextProps);
|
this.setAggOptions(nextProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setAggOptions({ valueType, metricKind, aggregation }) {
|
setAggOptions({ metricDescriptor, aggregation }) {
|
||||||
const { templateSrv } = this.props;
|
const { templateSrv } = this.props;
|
||||||
let aggregations = getAggregationOptionsByMetric(valueType, metricKind).map(a => ({
|
let aggregations = getAggregationOptionsByMetric(metricDescriptor.valueType, metricDescriptor.metricKind).map(
|
||||||
...a,
|
a => ({
|
||||||
label: a.text,
|
...a,
|
||||||
}));
|
label: a.text,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
aggregations.length > 0 &&
|
aggregations.length > 0 &&
|
||||||
@@ -75,7 +82,10 @@ export class Aggregations extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deselectAggregationOption(notValidOptionValue: string) {
|
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);
|
const newValue = aggregations.find(o => o.value !== notValidOptionValue);
|
||||||
this.handleAggregationChange(newValue ? newValue.value : '');
|
this.handleAggregationChange(newValue ? newValue.value : '');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
|
||||||
import { QueryMeta, Target } from '../types';
|
import { QueryMeta, Target } from '../types';
|
||||||
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
||||||
@@ -8,14 +9,19 @@ import '../query_filter_ctrl';
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
filtersChanged: (filters) => void;
|
filtersChanged: (filters) => void;
|
||||||
groupBysChanged: (groupBys) => void;
|
groupBysChanged: (groupBys) => void;
|
||||||
|
metricType: string;
|
||||||
templateSrv: any;
|
templateSrv: any;
|
||||||
labelData: QueryMeta;
|
|
||||||
loading: Promise<any>;
|
|
||||||
target: Target;
|
target: Target;
|
||||||
uiSegmentSrv: any;
|
uiSegmentSrv: any;
|
||||||
|
datasource: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Filter extends React.Component<Props, any> {
|
interface State {
|
||||||
|
labelData: QueryMeta;
|
||||||
|
loading: Promise<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Filter extends React.Component<Props, State> {
|
||||||
element: any;
|
element: any;
|
||||||
component: AngularComponent;
|
component: AngularComponent;
|
||||||
|
|
||||||
@@ -24,13 +30,13 @@ export class Filter extends React.Component<Props, any> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { loading, labelData, target, filtersChanged, groupBysChanged } = this.props;
|
const { target, filtersChanged, groupBysChanged } = this.props;
|
||||||
const loader = getAngularLoader();
|
const loader = getAngularLoader();
|
||||||
const template = '<stackdriver-filter> </stackdriver-filter>';
|
const template = '<stackdriver-filter> </stackdriver-filter>';
|
||||||
|
|
||||||
const scopeProps = {
|
const scopeProps = {
|
||||||
loading,
|
loading: this.loadLabels.bind(this),
|
||||||
labelData,
|
labelData: null,
|
||||||
target,
|
target,
|
||||||
filtersChanged,
|
filtersChanged,
|
||||||
groupBysChanged,
|
groupBysChanged,
|
||||||
@@ -39,11 +45,11 @@ export class Filter extends React.Component<Props, any> {
|
|||||||
this.component = loader.load(this.element, scopeProps, template);
|
this.component = loader.load(this.element, scopeProps, template);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate(prevProps: Props) {
|
||||||
const scope = this.component.getScope();
|
if (prevProps.metricType !== this.props.metricType) {
|
||||||
scope.loading = _.clone(this.props.loading);
|
const scope = this.component.getScope();
|
||||||
scope.labelData = _.cloneDeep(this.props.labelData);
|
scope.loading = this.loadLabels(scope);
|
||||||
scope.target = _.cloneDeep(this.props.target);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@@ -52,6 +58,19 @@ export class Filter extends React.Component<Props, any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
render() {
|
||||||
return <div ref={element => (this.element = element)} style={{ width: '100%' }} />;
|
return <div ref={element => (this.element = element)} style={{ width: '100%' }} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export interface Props {
|
|||||||
datasource: any;
|
datasource: any;
|
||||||
defaultProject: string;
|
defaultProject: string;
|
||||||
metricType: string;
|
metricType: string;
|
||||||
|
children?: (renderProps: any) => JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@@ -17,6 +18,7 @@ interface State {
|
|||||||
services: any[];
|
services: any[];
|
||||||
service: string;
|
service: string;
|
||||||
metric: string;
|
metric: string;
|
||||||
|
metricDescriptor: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Metrics extends React.Component<Props, State> {
|
export class Metrics extends React.Component<Props, State> {
|
||||||
@@ -26,6 +28,7 @@ export class Metrics extends React.Component<Props, State> {
|
|||||||
services: [],
|
services: [],
|
||||||
service: '',
|
service: '',
|
||||||
metric: '',
|
metric: '',
|
||||||
|
metricDescriptor: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -68,13 +71,16 @@ export class Metrics extends React.Component<Props, State> {
|
|||||||
const services = this.getServicesList(metricDescriptors);
|
const services = this.getServicesList(metricDescriptors);
|
||||||
const metrics = this.getMetricsList(metricDescriptors);
|
const metrics = this.getMetricsList(metricDescriptors);
|
||||||
const service = metrics.length > 0 ? metrics[0].service : '';
|
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) {
|
getMetricsList(metricDescriptors) {
|
||||||
const selectedMetricDescriptor = metricDescriptors.find(
|
const selectedMetricDescriptor = this.getSelectedMetricDescriptor(this.props.metricType);
|
||||||
md => md.type === this.props.templateSrv.replace(this.props.metricType)
|
|
||||||
);
|
|
||||||
const metricsByService = metricDescriptors.filter(m => m.service === selectedMetricDescriptor.service).map(m => ({
|
const metricsByService = metricDescriptors.filter(m => m.service === selectedMetricDescriptor.service).map(m => ({
|
||||||
service: m.service,
|
service: m.service,
|
||||||
value: m.type,
|
value: m.type,
|
||||||
@@ -103,8 +109,9 @@ export class Metrics extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleMetricTypeChange(value) {
|
handleMetricTypeChange(value) {
|
||||||
const selectedMetricDescriptor = this.state.metricDescriptors.find(md => md.type === value);
|
const metricDescriptor = this.getSelectedMetricDescriptor(value);
|
||||||
this.props.onChange(selectedMetricDescriptor);
|
this.setState({ metricDescriptor });
|
||||||
|
this.props.onChange(metricDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
getServicesList(metricDescriptors) {
|
getServicesList(metricDescriptors) {
|
||||||
@@ -166,6 +173,7 @@ export class Metrics extends React.Component<Props, State> {
|
|||||||
<div className="gf-form-label gf-form-label--grow" />
|
<div className="gf-form-label gf-form-label--grow" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{this.props.children(this.state.metricDescriptor)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import appEvents from 'app/core/app_events';
|
|
||||||
|
|
||||||
import { Metrics } from './Metrics';
|
import { Metrics } from './Metrics';
|
||||||
import { Filter } from './Filter';
|
import { Filter } from './Filter';
|
||||||
import { Aggregations } from './Aggregations';
|
import { Aggregations } from './Aggregations';
|
||||||
import { Target, QueryMeta } from '../types';
|
import { Target } from '../types';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
onQueryChange: (target: Target) => void;
|
onQueryChange: (target: Target) => void;
|
||||||
@@ -18,8 +17,6 @@ export interface Props {
|
|||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
target: Target;
|
target: Target;
|
||||||
labelData: QueryMeta;
|
|
||||||
loadLabelsPromise: Promise<any>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DefaultTarget: Target = {
|
const DefaultTarget: Target = {
|
||||||
@@ -41,85 +38,79 @@ const DefaultTarget: Target = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class QueryEditor extends React.Component<Props, State> {
|
export class QueryEditor extends React.Component<Props, State> {
|
||||||
state: State = { labelData: null, loadLabelsPromise: new Promise(() => {}), target: DefaultTarget };
|
state: State = { target: DefaultTarget };
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.getLabels();
|
|
||||||
this.setState({ target: this.props.target });
|
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 }) {
|
handleMetricTypeChange({ valueType, metricKind, type, unit }) {
|
||||||
this.setState({
|
this.setState(
|
||||||
target: {
|
{
|
||||||
...this.state.target,
|
target: {
|
||||||
...{
|
...this.state.target,
|
||||||
metricType: type,
|
...{
|
||||||
unit,
|
metricType: type,
|
||||||
valueType,
|
unit,
|
||||||
metricKind,
|
valueType,
|
||||||
|
metricKind,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
() => {
|
||||||
|
this.props.onQueryChange(this.state.target);
|
||||||
// this.$rootScope.$broadcast('metricTypeChanged');
|
this.props.onExecuteQuery();
|
||||||
this.getLabels();
|
}
|
||||||
this.props.onQueryChange(this.state.target);
|
);
|
||||||
this.props.onExecuteQuery();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFilterChange(value) {
|
handleFilterChange(value) {
|
||||||
this.setState({
|
this.setState(
|
||||||
target: {
|
{
|
||||||
...this.state.target,
|
target: {
|
||||||
filters: value,
|
...this.state.target,
|
||||||
|
filters: value,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
() => {
|
||||||
this.props.onQueryChange(this.state.target);
|
this.props.onQueryChange(this.state.target);
|
||||||
this.props.onExecuteQuery();
|
this.props.onExecuteQuery();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleGroupBysChange(value) {
|
handleGroupBysChange(value) {
|
||||||
this.setState({
|
this.setState(
|
||||||
target: {
|
{
|
||||||
...this.state.target,
|
target: {
|
||||||
groupBys: value,
|
...this.state.target,
|
||||||
|
groupBys: value,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
() => {
|
||||||
this.props.onQueryChange(this.state.target);
|
this.props.onQueryChange(this.state.target);
|
||||||
this.props.onExecuteQuery();
|
this.props.onExecuteQuery();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAggregationChange(value) {
|
handleAggregationChange(value) {
|
||||||
this.setState({
|
const target = {
|
||||||
target: {
|
...this.state.target,
|
||||||
...this.state.target,
|
aggregation: {
|
||||||
aggregation: {
|
...this.state.target.aggregation,
|
||||||
...this.state.target.aggregation,
|
crossSeriesReducer: value,
|
||||||
crossSeriesReducer: value,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
this.setState({ target }, () => {
|
||||||
|
this.props.onQueryChange(target);
|
||||||
|
this.props.onExecuteQuery();
|
||||||
});
|
});
|
||||||
this.props.onQueryChange(this.state.target);
|
|
||||||
this.props.onExecuteQuery();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { labelData, loadLabelsPromise, target } = this.state;
|
const { target } = this.state;
|
||||||
const { defaultProject, metricType, valueType, metricKind, aggregation } = target;
|
const { defaultProject, metricType, aggregation } = target;
|
||||||
const { templateSrv, datasource, uiSegmentSrv } = this.props;
|
const { templateSrv, datasource, uiSegmentSrv } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -130,46 +121,27 @@ export class QueryEditor extends React.Component<Props, State> {
|
|||||||
templateSrv={templateSrv}
|
templateSrv={templateSrv}
|
||||||
datasource={datasource}
|
datasource={datasource}
|
||||||
onChange={value => this.handleMetricTypeChange(value)}
|
onChange={value => this.handleMetricTypeChange(value)}
|
||||||
/>
|
>
|
||||||
<Filter
|
{metric => (
|
||||||
filtersChanged={value => this.handleFilterChange(value)}
|
<React.Fragment>
|
||||||
groupBysChanged={value => this.handleGroupBysChange(value)}
|
<Filter
|
||||||
target={target}
|
filtersChanged={value => this.handleFilterChange(value)}
|
||||||
uiSegmentSrv={uiSegmentSrv}
|
groupBysChanged={value => this.handleGroupBysChange(value)}
|
||||||
labelData={labelData}
|
target={target}
|
||||||
templateSrv={templateSrv}
|
uiSegmentSrv={uiSegmentSrv}
|
||||||
loading={loadLabelsPromise}
|
templateSrv={templateSrv}
|
||||||
/>
|
datasource={datasource}
|
||||||
<Aggregations
|
metricType={metric ? metric.type : ''}
|
||||||
valueType={valueType}
|
/>
|
||||||
metricKind={metricKind}
|
<Aggregations
|
||||||
templateSrv={templateSrv}
|
metricDescriptor={metric}
|
||||||
aggregation={aggregation}
|
templateSrv={templateSrv}
|
||||||
onChange={value => this.handleAggregationChange(value)}
|
aggregation={aggregation}
|
||||||
/>
|
onChange={value => this.handleAggregationChange(value)}
|
||||||
{/* target="ctrl.target" refresh="ctrl.refresh()" loading="ctrl.loadLabelsPromise" label-data="ctrl.labelData" */}
|
/>
|
||||||
{/* <stackdriver-filter
|
</React.Fragment>
|
||||||
target="target"
|
)}
|
||||||
refresh="target.refresh()"
|
</Metrics>
|
||||||
loading="target.loadLabelsPromise"
|
|
||||||
label-data="target.labelData"
|
|
||||||
/>
|
|
||||||
<aggregation-picker
|
|
||||||
value-type="target.target.valueType"
|
|
||||||
metric-kind="target.target.metricKind"
|
|
||||||
aggregation="target.target.aggregation"
|
|
||||||
alignment-period="target.lastQueryMeta.alignmentPeriod"
|
|
||||||
refresh="target.refresh()"
|
|
||||||
template-srv="target.templateSrv"
|
|
||||||
datasource="target.datasource"
|
|
||||||
on-change="target.handleAggregationChange"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<stackdriver-aggregation
|
|
||||||
target="target.target"
|
|
||||||
alignment-period="target.lastQueryMeta.alignmentPeriod"
|
|
||||||
refresh="target.refresh()"
|
|
||||||
/> */}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user