mirror of https://github.com/grafana/grafana
parent
ad55be9865
commit
146aa7abab
@ -0,0 +1,48 @@ |
|||||||
|
import { react2AngularDirective } from 'app/core/utils/react2angular'; |
||||||
|
import { QueryEditor } from './components/QueryEditor'; |
||||||
|
// import { MetricPicker } from './components/MetricPicker';
|
||||||
|
// import { OptionPicker } from './components/OptionPicker';
|
||||||
|
// import { OptionGroupPicker } from './components/OptionGroupPicker';
|
||||||
|
// import { AggregationPicker } from './components/AggregationPicker';
|
||||||
|
|
||||||
|
export function registerAngularDirectives() { |
||||||
|
// react2AngularDirective('optionPicker', OptionPicker, [
|
||||||
|
// 'options',
|
||||||
|
// 'onChange',
|
||||||
|
// 'selected',
|
||||||
|
// 'searchable',
|
||||||
|
// 'className',
|
||||||
|
// 'placeholder',
|
||||||
|
// ]);
|
||||||
|
// react2AngularDirective('optionGroupPicker', OptionGroupPicker, [
|
||||||
|
// 'groups',
|
||||||
|
// 'onChange',
|
||||||
|
// 'selected',
|
||||||
|
// 'searchable',
|
||||||
|
// 'className',
|
||||||
|
// 'placeholder',
|
||||||
|
// ]);
|
||||||
|
// react2AngularDirective('metricPicker', MetricPicker, [
|
||||||
|
// 'target',
|
||||||
|
// ['onChange', { watchDepth: 'reference' }],
|
||||||
|
// 'defaultProject',
|
||||||
|
// 'metricType',
|
||||||
|
// ['templateSrv', { watchDepth: 'reference' }],
|
||||||
|
// ['datasource', { watchDepth: 'reference' }],
|
||||||
|
// ]);
|
||||||
|
// react2AngularDirective('aggregationPicker', AggregationPicker, [
|
||||||
|
// 'valueType',
|
||||||
|
// 'metricKind',
|
||||||
|
// 'onChange',
|
||||||
|
// 'aggregation',
|
||||||
|
// ['templateSrv', { watchDepth: 'reference' }],
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
react2AngularDirective('queryEditor', QueryEditor, [ |
||||||
|
'target', |
||||||
|
'onChange', |
||||||
|
['uiSegmentSrv', { watchDepth: 'reference' }], |
||||||
|
['datasource', { watchDepth: 'reference' }], |
||||||
|
['templateSrv', { watchDepth: 'reference' }], |
||||||
|
]); |
||||||
|
} |
||||||
@ -0,0 +1,134 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import _ from 'lodash'; |
||||||
|
|
||||||
|
// import { OptionPicker } from './OptionPicker';
|
||||||
|
import { OptionGroupPicker } from './OptionGroupPicker'; |
||||||
|
// import { alignmentPeriods } from '../constants';
|
||||||
|
// import { getAlignmentOptionsByMetric, getAggregationOptionsByMetric } from '../functions';
|
||||||
|
import { getAggregationOptionsByMetric } from '../functions'; |
||||||
|
// import kbn from 'app/core/utils/kbn';
|
||||||
|
|
||||||
|
export interface Props { |
||||||
|
onChange: (metricDescriptor) => void; |
||||||
|
templateSrv: any; |
||||||
|
valueType: string; |
||||||
|
metricKind: string; |
||||||
|
aggregation: { |
||||||
|
crossSeriesReducer: string; |
||||||
|
alignmentPeriod: string; |
||||||
|
perSeriesAligner: string; |
||||||
|
groupBys: string[]; |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
interface State { |
||||||
|
alignmentPeriods: any[]; |
||||||
|
alignOptions: any[]; |
||||||
|
aggOptions: any[]; |
||||||
|
} |
||||||
|
|
||||||
|
export class AggregationPicker extends React.Component<Props, State> { |
||||||
|
state: State = { |
||||||
|
alignmentPeriods: [], |
||||||
|
alignOptions: [], |
||||||
|
aggOptions: [], |
||||||
|
}; |
||||||
|
|
||||||
|
constructor(props) { |
||||||
|
super(props); |
||||||
|
} |
||||||
|
|
||||||
|
componentDidMount() { |
||||||
|
this.setAggOptions(); |
||||||
|
} |
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: Props) { |
||||||
|
const { valueType, metricKind, aggregation } = this.props; |
||||||
|
if ( |
||||||
|
nextProps.valueType !== valueType || |
||||||
|
nextProps.metricKind !== metricKind || |
||||||
|
nextProps.aggregation.groupBys !== aggregation.groupBys |
||||||
|
) { |
||||||
|
this.setAggOptions(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setAggOptions() { |
||||||
|
const { valueType, metricKind, aggregation, templateSrv } = this.props; |
||||||
|
let aggregations = getAggregationOptionsByMetric(valueType, metricKind).map(a => ({ |
||||||
|
...a, |
||||||
|
label: a.text, |
||||||
|
})); |
||||||
|
if (!aggregations.find(o => o.value === templateSrv.replace(aggregation.crossSeriesReducer))) { |
||||||
|
this.deselectAggregationOption('REDUCE_NONE'); |
||||||
|
} |
||||||
|
|
||||||
|
if (aggregation.groupBys.length > 0) { |
||||||
|
aggregations = aggregations.filter(o => o.value !== 'REDUCE_NONE'); |
||||||
|
this.deselectAggregationOption('REDUCE_NONE'); |
||||||
|
} |
||||||
|
this.setState({ |
||||||
|
aggOptions: [ |
||||||
|
this.getTemplateVariablesGroup(), |
||||||
|
{ |
||||||
|
label: 'Aggregations', |
||||||
|
options: aggregations, |
||||||
|
}, |
||||||
|
], |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
deselectAggregationOption(notValidOptionValue: string) { |
||||||
|
const aggregations = getAggregationOptionsByMetric(this.props.valueType, this.props.metricKind); |
||||||
|
const newValue = aggregations.find(o => o.value !== notValidOptionValue); |
||||||
|
this.handleAggregationChange(newValue ? newValue.value : ''); |
||||||
|
} |
||||||
|
|
||||||
|
handleAggregationChange(value) { |
||||||
|
this.props.onChange(value); |
||||||
|
// this.$scope.refresh();
|
||||||
|
} |
||||||
|
|
||||||
|
getTemplateVariablesGroup() { |
||||||
|
return { |
||||||
|
label: 'Template Variables', |
||||||
|
options: this.props.templateSrv.variables.map(v => ({ |
||||||
|
label: `$${v.name}`, |
||||||
|
value: `$${v.name}`, |
||||||
|
})), |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { aggOptions } = this.state; |
||||||
|
const { aggregation } = this.props; |
||||||
|
|
||||||
|
return ( |
||||||
|
<React.Fragment> |
||||||
|
<div className="gf-form-inline"> |
||||||
|
<div className="gf-form"> |
||||||
|
<label className="gf-form-label query-keyword width-9">Aggregation</label> |
||||||
|
<div className="gf-form-select-wrapper gf-form-select-wrapper--caret-indent"> |
||||||
|
<OptionGroupPicker |
||||||
|
onChange={value => this.handleAggregationChange(value)} |
||||||
|
selected={aggregation.crossSeriesReducer} |
||||||
|
groups={aggOptions} |
||||||
|
searchable={true} |
||||||
|
placeholder="Select Aggregation" |
||||||
|
className="width-15" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="gf-form gf-form--grow"> |
||||||
|
<label className="gf-form-label gf-form-label--grow"> |
||||||
|
<a ng-click="ctrl.target.showAggregationOptions = !ctrl.target.showAggregationOptions"> |
||||||
|
<i className="fa fa-caret-down" ng-show="ctrl.target.showAggregationOptions" /> |
||||||
|
<i className="fa fa-caret-right" ng-hide="ctrl.target.showAggregationOptions" /> Advanced Options |
||||||
|
</a> |
||||||
|
</label> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</React.Fragment> |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,239 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import _ from 'lodash'; |
||||||
|
|
||||||
|
import Segment from './Segment'; |
||||||
|
import { QueryMeta, Target } from '../types'; |
||||||
|
import { FilterSegments } from '../filter_segments'; |
||||||
|
|
||||||
|
export interface Props { |
||||||
|
onChange: (metricDescriptor) => void; |
||||||
|
templateSrv: any; |
||||||
|
labelData: QueryMeta; |
||||||
|
loading: Promise<any>; |
||||||
|
target: Target; |
||||||
|
uiSegmentSrv: any; |
||||||
|
} |
||||||
|
|
||||||
|
interface State { |
||||||
|
defaultRemoveGroupByValue: string; |
||||||
|
resourceTypeValue: string; |
||||||
|
groupBySegments: any[]; |
||||||
|
// filterSegments: FilterSegments;
|
||||||
|
filterSegments: any; |
||||||
|
removeSegment?: any; |
||||||
|
} |
||||||
|
|
||||||
|
export class Filter extends React.Component<Props, State> { |
||||||
|
state: State = { |
||||||
|
defaultRemoveGroupByValue: '-- remove group by --', |
||||||
|
resourceTypeValue: 'resource.type', |
||||||
|
groupBySegments: [], |
||||||
|
filterSegments: new FilterSegments(this.getFilterKeys.bind(this), this.getFilterValues.bind(this)), |
||||||
|
}; |
||||||
|
|
||||||
|
constructor(props) { |
||||||
|
super(props); |
||||||
|
} |
||||||
|
|
||||||
|
componentDidMount() { |
||||||
|
this.initSegments(false); |
||||||
|
} |
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps) { |
||||||
|
return this.state.filterSegments.filterSegments.length > 0; |
||||||
|
} |
||||||
|
|
||||||
|
initSegments(hideGroupBys: boolean) { |
||||||
|
this.state.filterSegments.init(this.props.uiSegmentSrv); |
||||||
|
if (!hideGroupBys) { |
||||||
|
this.setState({ |
||||||
|
groupBySegments: this.props.target.aggregation.groupBys.map(groupBy => { |
||||||
|
return this.props.uiSegmentSrv.getSegmentForValue(groupBy); |
||||||
|
}), |
||||||
|
}); |
||||||
|
|
||||||
|
this.ensurePlusButton(this.state.groupBySegments); |
||||||
|
} |
||||||
|
|
||||||
|
this.setState({ |
||||||
|
removeSegment: this.props.uiSegmentSrv.newSegment({ fake: true, value: '-- remove group by --' }), |
||||||
|
}); |
||||||
|
|
||||||
|
this.state.filterSegments.buildSegmentModel(this.props.target.filters); |
||||||
|
} |
||||||
|
|
||||||
|
async createLabelKeyElements() { |
||||||
|
await this.props.loading; |
||||||
|
|
||||||
|
let elements = Object.keys(this.props.labelData.metricLabels || {}).map(l => { |
||||||
|
return this.props.uiSegmentSrv.newSegment({ |
||||||
|
value: `metric.label.${l}`, |
||||||
|
expandable: false, |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
elements = [ |
||||||
|
...elements, |
||||||
|
...Object.keys(this.props.labelData.resourceLabels || {}).map(l => { |
||||||
|
return this.props.uiSegmentSrv.newSegment({ |
||||||
|
value: `resource.label.${l}`, |
||||||
|
expandable: false, |
||||||
|
}); |
||||||
|
}), |
||||||
|
]; |
||||||
|
|
||||||
|
if (this.props.labelData.resourceTypes && this.props.labelData.resourceTypes.length > 0) { |
||||||
|
elements = [ |
||||||
|
...elements, |
||||||
|
this.props.uiSegmentSrv.newSegment({ |
||||||
|
value: this.state.resourceTypeValue, |
||||||
|
expandable: false, |
||||||
|
}), |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
return elements; |
||||||
|
} |
||||||
|
|
||||||
|
async getFilterKeys(segment, removeText?: string) { |
||||||
|
let elements = await this.createLabelKeyElements(); |
||||||
|
|
||||||
|
if (this.props.target.filters.indexOf(this.state.resourceTypeValue) !== -1) { |
||||||
|
elements = elements.filter(e => e.value !== this.state.resourceTypeValue); |
||||||
|
} |
||||||
|
|
||||||
|
const noValueOrPlusButton = !segment || segment.type === 'plus-button'; |
||||||
|
if (noValueOrPlusButton && elements.length === 0) { |
||||||
|
return []; |
||||||
|
} |
||||||
|
|
||||||
|
return [ |
||||||
|
...elements, |
||||||
|
this.props.uiSegmentSrv.newSegment({ fake: true, value: removeText || this.state.defaultRemoveGroupByValue }), |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
async getGroupBys(segment) { |
||||||
|
let elements = await this.createLabelKeyElements(); |
||||||
|
|
||||||
|
elements = elements.filter(e => this.props.target.aggregation.groupBys.indexOf(e.value) === -1); |
||||||
|
const noValueOrPlusButton = !segment || segment.type === 'plus-button'; |
||||||
|
if (noValueOrPlusButton && elements.length === 0) { |
||||||
|
return []; |
||||||
|
} |
||||||
|
|
||||||
|
this.state.removeSegment.value = this.state.defaultRemoveGroupByValue; |
||||||
|
return [...elements, this.state.removeSegment]; |
||||||
|
} |
||||||
|
|
||||||
|
groupByChanged(segment, index) { |
||||||
|
if (segment.value === this.state.removeSegment.value) { |
||||||
|
// this.groupBySegments.splice(index, 1);
|
||||||
|
} else { |
||||||
|
segment.type = 'value'; |
||||||
|
} |
||||||
|
|
||||||
|
const reducer = (memo, seg) => { |
||||||
|
if (!seg.fake) { |
||||||
|
memo.push(seg.value); |
||||||
|
} |
||||||
|
return memo; |
||||||
|
}; |
||||||
|
|
||||||
|
this.props.target.aggregation.groupBys = this.state.groupBySegments.reduce(reducer, []); |
||||||
|
this.ensurePlusButton(this.state.groupBySegments); |
||||||
|
// this.$rootScope.$broadcast('metricTypeChanged');
|
||||||
|
// this.$scope.refresh();
|
||||||
|
} |
||||||
|
|
||||||
|
async getFilters(segment, index) { |
||||||
|
await this.props.loading; |
||||||
|
const hasNoFilterKeys = |
||||||
|
this.props.labelData.metricLabels && Object.keys(this.props.labelData.metricLabels).length === 0; |
||||||
|
return this.state.filterSegments.getFilters(segment, index, hasNoFilterKeys); |
||||||
|
} |
||||||
|
|
||||||
|
getFilterValues(index) { |
||||||
|
const filterKey = this.props.templateSrv.replace(this.state.filterSegments.filterSegments[index - 2].value); |
||||||
|
if ( |
||||||
|
!filterKey || |
||||||
|
!this.props.labelData.metricLabels || |
||||||
|
Object.keys(this.props.labelData.metricLabels).length === 0 |
||||||
|
) { |
||||||
|
return []; |
||||||
|
} |
||||||
|
|
||||||
|
const shortKey = filterKey.substring(filterKey.indexOf('.label.') + 7); |
||||||
|
|
||||||
|
if (filterKey.startsWith('metric.label.') && this.props.labelData.metricLabels.hasOwnProperty(shortKey)) { |
||||||
|
return this.props.labelData.metricLabels[shortKey]; |
||||||
|
} |
||||||
|
|
||||||
|
if (filterKey.startsWith('resource.label.') && this.props.labelData.resourceLabels.hasOwnProperty(shortKey)) { |
||||||
|
return this.props.labelData.resourceLabels[shortKey]; |
||||||
|
} |
||||||
|
|
||||||
|
if (filterKey === this.state.resourceTypeValue) { |
||||||
|
return this.props.labelData.resourceTypes; |
||||||
|
} |
||||||
|
|
||||||
|
return []; |
||||||
|
} |
||||||
|
|
||||||
|
filterSegmentUpdated(segment, index) { |
||||||
|
this.props.target.filters = this.state.filterSegments.filterSegmentUpdated(segment, index); |
||||||
|
// this.$scope.refresh();
|
||||||
|
} |
||||||
|
|
||||||
|
ensurePlusButton(segments) { |
||||||
|
const count = segments.length; |
||||||
|
const lastSegment = segments[Math.max(count - 1, 0)]; |
||||||
|
|
||||||
|
if (!lastSegment || lastSegment.type !== 'plus-button') { |
||||||
|
segments.push(this.props.uiSegmentSrv.newPlusButton()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { filterSegments } = this.state; |
||||||
|
// const { metrifilterSegmentscType } = this.props;
|
||||||
|
|
||||||
|
return ( |
||||||
|
<React.Fragment> |
||||||
|
<div className="gf-form-inline"> |
||||||
|
<div className="gf-form"> |
||||||
|
<span className="gf-form-label query-keyword width-9">Filter</span> |
||||||
|
<div className="gf-form"> |
||||||
|
{filterSegments.filterSegments.map((segment, i) => ( |
||||||
|
<Segment |
||||||
|
key={i} |
||||||
|
segment={segment} |
||||||
|
getOptions={() => this.getFilters(segment, i)} |
||||||
|
onChange={segment => this.filterSegmentUpdated(segment, i)} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="gf-form gf-form--grow"> |
||||||
|
<div className="gf-form-label gf-form-label--grow" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{/* <div className="gf-form-inline" ng-hide="ctrl.$scope.hideGroupBys"> |
||||||
|
<div className="gf-form"> |
||||||
|
<span className="gf-form-label query-keyword width-9">Group By</span> |
||||||
|
<div className="gf-form" ng-repeat="segment in ctrl.groupBySegments"> |
||||||
|
<Segment |
||||||
|
segment="segment" |
||||||
|
get-options="ctrl.getGroupBys(segment)" |
||||||
|
on-change="ctrl.groupByChanged(segment, $index)" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="gf-form gf-form--grow"> |
||||||
|
<div className="gf-form-label gf-form-label--grow" /> |
||||||
|
</div> |
||||||
|
</div> */} |
||||||
|
</React.Fragment> |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,141 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import _ from 'lodash'; |
||||||
|
import appEvents from 'app/core/app_events'; |
||||||
|
|
||||||
|
import { MetricPicker } from './MetricPicker'; |
||||||
|
import { Filter } from './Filter'; |
||||||
|
// import { AggregationPicker } from './AggregationPicker';
|
||||||
|
import { Target, QueryMeta } from '../types'; |
||||||
|
|
||||||
|
export interface Props { |
||||||
|
onChange: (target: Target) => void; |
||||||
|
target: Target; |
||||||
|
datasource: any; |
||||||
|
templateSrv: any; |
||||||
|
uiSegmentSrv: any; |
||||||
|
} |
||||||
|
|
||||||
|
interface State { |
||||||
|
target: Target; |
||||||
|
labelData: QueryMeta; |
||||||
|
loadLabelsPromise: Promise<any>; |
||||||
|
} |
||||||
|
|
||||||
|
const DefaultTarget: Target = { |
||||||
|
defaultProject: 'loading project...', |
||||||
|
metricType: '', |
||||||
|
refId: '', |
||||||
|
service: '', |
||||||
|
unit: '', |
||||||
|
aggregation: { |
||||||
|
crossSeriesReducer: 'REDUCE_MEAN', |
||||||
|
alignmentPeriod: 'stackdriver-auto', |
||||||
|
perSeriesAligner: 'ALIGN_MEAN', |
||||||
|
groupBys: [], |
||||||
|
}, |
||||||
|
filters: [], |
||||||
|
aliasBy: '', |
||||||
|
metricKind: '', |
||||||
|
valueType: '', |
||||||
|
}; |
||||||
|
|
||||||
|
export class QueryEditor extends React.Component<Props, State> { |
||||||
|
state: State = { labelData: null, loadLabelsPromise: null, target: DefaultTarget }; |
||||||
|
|
||||||
|
constructor(props) { |
||||||
|
super(props); |
||||||
|
this.handleMetricTypeChange = this.handleMetricTypeChange.bind(this); |
||||||
|
this.handleAggregationChange = this.handleAggregationChange.bind(this); |
||||||
|
} |
||||||
|
|
||||||
|
componentDidMount() { |
||||||
|
this.setState({ target: this.props.target }); |
||||||
|
this.getLabels(); |
||||||
|
} |
||||||
|
|
||||||
|
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.$rootScope.$broadcast('metricTypeChanged');
|
||||||
|
// this.getLabels();
|
||||||
|
// this.refresh();
|
||||||
|
} |
||||||
|
|
||||||
|
handleAggregationChange(crossSeriesReducer) { |
||||||
|
// this.target.aggregation.crossSeriesReducer = crossSeriesReducer;
|
||||||
|
// this.refresh();
|
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { labelData, loadLabelsPromise, target } = this.state; |
||||||
|
const { defaultProject, metricType } = target; |
||||||
|
const { templateSrv, datasource, uiSegmentSrv } = this.props; |
||||||
|
|
||||||
|
return ( |
||||||
|
<React.Fragment> |
||||||
|
<MetricPicker |
||||||
|
defaultProject={defaultProject} |
||||||
|
metricType={metricType} |
||||||
|
templateSrv={templateSrv} |
||||||
|
datasource={datasource} |
||||||
|
onChange={value => this.handleMetricTypeChange(value)} |
||||||
|
/> |
||||||
|
<Filter |
||||||
|
onChange={() => console.log('change filter')} |
||||||
|
target={target} |
||||||
|
uiSegmentSrv={uiSegmentSrv} |
||||||
|
labelData={labelData} |
||||||
|
templateSrv={templateSrv} |
||||||
|
loading={loadLabelsPromise} |
||||||
|
/> |
||||||
|
{/* target="ctrl.target" refresh="ctrl.refresh()" loading="ctrl.loadLabelsPromise" label-data="ctrl.labelData" */} |
||||||
|
{/* <stackdriver-filter |
||||||
|
target="target" |
||||||
|
refresh="target.refresh()" |
||||||
|
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> |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
import React, { PureComponent } from 'react'; |
||||||
|
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; |
||||||
|
import 'app/core/directives/metric_segment'; |
||||||
|
|
||||||
|
interface QueryEditorProps { |
||||||
|
segment: any; |
||||||
|
getOptions: () => Promise<any[]>; |
||||||
|
onChange: (segment, index) => void; |
||||||
|
key: number; |
||||||
|
} |
||||||
|
|
||||||
|
export default class Segment extends PureComponent<QueryEditorProps, any> { |
||||||
|
element: any; |
||||||
|
component: AngularComponent; |
||||||
|
|
||||||
|
async componentDidMount() { |
||||||
|
if (!this.element) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
const { segment, getOptions, onChange } = this.props; |
||||||
|
const loader = getAngularLoader(); |
||||||
|
const template = '<metric-segment> </metric-segment>'; |
||||||
|
|
||||||
|
const scopeProps = { |
||||||
|
segment, |
||||||
|
onChange, |
||||||
|
getOptions, |
||||||
|
debounce: false, |
||||||
|
}; |
||||||
|
|
||||||
|
this.component = loader.load(this.element, scopeProps, template); |
||||||
|
} |
||||||
|
|
||||||
|
componentWillUnmount() { |
||||||
|
if (this.component) { |
||||||
|
this.component.destroy(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
return <div ref={element => (this.element = element)} style={{ width: '100%' }} />; |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue