mirror of
https://github.com/grafana/grafana.git
synced 2025-09-26 04:34:28 +08:00
143 lines
4.4 KiB
TypeScript
143 lines
4.4 KiB
TypeScript
import React, { PureComponent, ReactNode } from 'react';
|
|
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
|
import { StoreState } from 'app/types';
|
|
import { AdHocVariableFilter, AdHocVariableModel } from 'app/features/templating/types';
|
|
import { SegmentAsync } from '@grafana/ui';
|
|
import { VariablePickerProps } from '../../pickers/types';
|
|
import { OperatorSegment } from './OperatorSegment';
|
|
import { MetricFindValue, SelectableValue } from '@grafana/data';
|
|
import { AdHocFilterBuilder } from './AdHocFilterBuilder';
|
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
|
import { ConditionSegment } from './ConditionSegment';
|
|
import { addFilter, changeFilter, removeFilter } from '../actions';
|
|
|
|
interface OwnProps extends VariablePickerProps<AdHocVariableModel> {}
|
|
|
|
interface ConnectedProps {}
|
|
|
|
interface DispatchProps {
|
|
addFilter: typeof addFilter;
|
|
removeFilter: typeof removeFilter;
|
|
changeFilter: typeof changeFilter;
|
|
}
|
|
|
|
type Props = OwnProps & ConnectedProps & DispatchProps;
|
|
|
|
const REMOVE_FILTER_KEY = '-- remove filter --';
|
|
const REMOVE_VALUE = { label: REMOVE_FILTER_KEY, value: REMOVE_FILTER_KEY };
|
|
export class AdHocPickerUnconnected extends PureComponent<Props> {
|
|
onChange = (index: number, prop: string) => (key: SelectableValue<string>) => {
|
|
const { id, filters } = this.props.variable;
|
|
const { value } = key;
|
|
|
|
if (key.value === REMOVE_FILTER_KEY) {
|
|
return this.props.removeFilter(id!, index);
|
|
}
|
|
|
|
return this.props.changeFilter(id!, {
|
|
index,
|
|
filter: {
|
|
...filters[index],
|
|
[prop]: value,
|
|
},
|
|
});
|
|
};
|
|
|
|
appendFilterToVariable = (filter: AdHocVariableFilter) => {
|
|
const { id } = this.props.variable;
|
|
this.props.addFilter(id!, filter);
|
|
};
|
|
|
|
fetchFilterKeys = async () => {
|
|
const { variable } = this.props;
|
|
const ds = await getDatasourceSrv().get(variable.datasource!);
|
|
|
|
if (!ds || !ds.getTagKeys) {
|
|
return [];
|
|
}
|
|
|
|
const metrics = await ds.getTagKeys();
|
|
return metrics.map(m => ({ label: m.text, value: m.text }));
|
|
};
|
|
|
|
fetchFilterKeysWithRemove = async () => {
|
|
const keys = await this.fetchFilterKeys();
|
|
return [REMOVE_VALUE, ...keys];
|
|
};
|
|
|
|
fetchFilterValues = async (key: string) => {
|
|
const { variable } = this.props;
|
|
const ds = await getDatasourceSrv().get(variable.datasource!);
|
|
|
|
if (!ds || !ds.getTagValues) {
|
|
return [];
|
|
}
|
|
|
|
const metrics = await ds.getTagValues({ key });
|
|
return metrics.map((m: MetricFindValue) => ({ label: m.text, value: m.text }));
|
|
};
|
|
|
|
render() {
|
|
const { filters } = this.props.variable;
|
|
|
|
return (
|
|
<div className="gf-form-inline">
|
|
{this.renderFilters(filters)}
|
|
<AdHocFilterBuilder
|
|
appendBefore={filters.length > 0 ? <ConditionSegment label="AND" /> : null}
|
|
onLoadKeys={this.fetchFilterKeys}
|
|
onLoadValues={this.fetchFilterValues}
|
|
onCompleted={this.appendFilterToVariable}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderFilters(filters: AdHocVariableFilter[]) {
|
|
return filters.reduce((segments: ReactNode[], filter, index) => {
|
|
if (segments.length > 0) {
|
|
segments.push(<ConditionSegment label="AND" />);
|
|
}
|
|
segments.push(this.renderFilterSegments(filter, index));
|
|
return segments;
|
|
}, []);
|
|
}
|
|
|
|
renderFilterSegments(filter: AdHocVariableFilter, index: number) {
|
|
return (
|
|
<React.Fragment key={`filter-${index}`}>
|
|
<div className="gf-form">
|
|
<SegmentAsync
|
|
className="query-segment-key"
|
|
value={filter.key}
|
|
onChange={this.onChange(index, 'key')}
|
|
loadOptions={this.fetchFilterKeysWithRemove}
|
|
/>
|
|
</div>
|
|
<div className="gf-form">
|
|
<OperatorSegment value={filter.operator} onChange={this.onChange(index, 'operator')} />
|
|
</div>
|
|
<div className="gf-form">
|
|
<SegmentAsync
|
|
className="query-segment-value"
|
|
value={filter.value}
|
|
onChange={this.onChange(index, 'value')}
|
|
loadOptions={() => this.fetchFilterValues(filter.key)}
|
|
/>
|
|
</div>
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
}
|
|
|
|
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = {
|
|
addFilter,
|
|
removeFilter,
|
|
changeFilter,
|
|
};
|
|
|
|
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = state => ({});
|
|
|
|
export const AdHocPicker = connect(mapStateToProps, mapDispatchToProps)(AdHocPickerUnconnected);
|
|
AdHocPicker.displayName = 'AdHocPicker';
|