mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Tag and Values for Influx are filtered by the selected measurement (#17539)
* Fix: Filters Tags and Values depending on options passed Fixes: #17507 * Fix: Makes sure options is not undefined * Fix: Fixes tests and small button refactor * Chore: PR comments
This commit is contained in:
parent
37e9988e95
commit
51c6b50582
@ -217,7 +217,7 @@ export abstract class DataSourceApi<
|
|||||||
/**
|
/**
|
||||||
* Get tag values for adhoc filters
|
* Get tag values for adhoc filters
|
||||||
*/
|
*/
|
||||||
getTagValues?(options: { key: any }): Promise<MetricFindValue[]>;
|
getTagValues?(options: any): Promise<MetricFindValue[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set after constructor call, as the data source instance is the most common thing to pass around
|
* Set after constructor call, as the data source instance is the most common thing to pass around
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { mount, shallow } from 'enzyme';
|
||||||
import { DataSourceApi } from '@grafana/ui';
|
import { DataSourceApi } from '@grafana/ui';
|
||||||
|
|
||||||
import { AdHocFilterField, DEFAULT_REMOVE_FILTER_VALUE } from './AdHocFilterField';
|
import { AdHocFilterField, DEFAULT_REMOVE_FILTER_VALUE, KeyValuePair, Props } from './AdHocFilterField';
|
||||||
import { AdHocFilter } from './AdHocFilter';
|
import { AdHocFilter } from './AdHocFilter';
|
||||||
import { MockDataSourceApi } from '../../../test/mocks/datasource_srv';
|
import { MockDataSourceApi } from '../../../test/mocks/datasource_srv';
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ describe('<AdHocFilterField />', () => {
|
|||||||
expect(wrapper.find(AdHocFilter).exists()).toBeFalsy();
|
expect(wrapper.find(AdHocFilter).exists()).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add <AdHocFilter /> when onAddFilter is invoked', () => {
|
it('should add <AdHocFilter /> when onAddFilter is invoked', async () => {
|
||||||
const mockOnPairsChanged = jest.fn();
|
const mockOnPairsChanged = jest.fn();
|
||||||
const wrapper = shallow(<AdHocFilterField datasource={mockDataSourceApi} onPairsChanged={mockOnPairsChanged} />);
|
const wrapper = shallow(<AdHocFilterField datasource={mockDataSourceApi} onPairsChanged={mockOnPairsChanged} />);
|
||||||
expect(wrapper.state('pairs')).toEqual([]);
|
expect(wrapper.state('pairs')).toEqual([]);
|
||||||
@ -28,10 +28,13 @@ describe('<AdHocFilterField />', () => {
|
|||||||
.find('button')
|
.find('button')
|
||||||
.first()
|
.first()
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
expect(wrapper.find(AdHocFilter).exists()).toBeTruthy();
|
const asyncCheck = setImmediate(() => {
|
||||||
|
expect(wrapper.find(AdHocFilter).exists()).toBeTruthy();
|
||||||
|
});
|
||||||
|
global.clearImmediate(asyncCheck);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should remove the relavant filter when the '${DEFAULT_REMOVE_FILTER_VALUE}' key is selected`, () => {
|
it(`should remove the relevant filter when the '${DEFAULT_REMOVE_FILTER_VALUE}' key is selected`, () => {
|
||||||
const mockOnPairsChanged = jest.fn();
|
const mockOnPairsChanged = jest.fn();
|
||||||
const wrapper = shallow(<AdHocFilterField datasource={mockDataSourceApi} onPairsChanged={mockOnPairsChanged} />);
|
const wrapper = shallow(<AdHocFilterField datasource={mockDataSourceApi} onPairsChanged={mockOnPairsChanged} />);
|
||||||
expect(wrapper.state('pairs')).toEqual([]);
|
expect(wrapper.state('pairs')).toEqual([]);
|
||||||
@ -40,10 +43,13 @@ describe('<AdHocFilterField />', () => {
|
|||||||
.find('button')
|
.find('button')
|
||||||
.first()
|
.first()
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
expect(wrapper.find(AdHocFilter).exists()).toBeTruthy();
|
const asyncCheck = setImmediate(() => {
|
||||||
|
expect(wrapper.find(AdHocFilter).exists()).toBeTruthy();
|
||||||
|
|
||||||
wrapper.find(AdHocFilter).prop('onKeyChanged')(DEFAULT_REMOVE_FILTER_VALUE);
|
wrapper.find(AdHocFilter).prop('onKeyChanged')(DEFAULT_REMOVE_FILTER_VALUE);
|
||||||
expect(wrapper.find(AdHocFilter).exists()).toBeFalsy();
|
expect(wrapper.find(AdHocFilter).exists()).toBeFalsy();
|
||||||
|
});
|
||||||
|
global.clearImmediate(asyncCheck);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('it should call onPairsChanged when a filter is removed', async () => {
|
it('it should call onPairsChanged when a filter is removed', async () => {
|
||||||
@ -55,11 +61,177 @@ describe('<AdHocFilterField />', () => {
|
|||||||
.find('button')
|
.find('button')
|
||||||
.first()
|
.first()
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
expect(wrapper.find(AdHocFilter).exists()).toBeTruthy();
|
const asyncCheck = setImmediate(() => {
|
||||||
|
expect(wrapper.find(AdHocFilter).exists()).toBeTruthy();
|
||||||
|
|
||||||
wrapper.find(AdHocFilter).prop('onKeyChanged')(DEFAULT_REMOVE_FILTER_VALUE);
|
wrapper.find(AdHocFilter).prop('onKeyChanged')(DEFAULT_REMOVE_FILTER_VALUE);
|
||||||
expect(wrapper.find(AdHocFilter).exists()).toBeFalsy();
|
expect(wrapper.find(AdHocFilter).exists()).toBeFalsy();
|
||||||
|
|
||||||
expect(mockOnPairsChanged.mock.calls.length).toBe(1);
|
expect(mockOnPairsChanged.mock.calls.length).toBe(1);
|
||||||
|
});
|
||||||
|
global.clearImmediate(asyncCheck);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const setup = (propOverrides?: Partial<Props>) => {
|
||||||
|
const datasource: DataSourceApi<any, any> = ({
|
||||||
|
getTagKeys: jest.fn().mockReturnValue([{ text: 'key 1' }, { text: 'key 2' }]),
|
||||||
|
getTagValues: jest.fn().mockReturnValue([{ text: 'value 1' }, { text: 'value 2' }]),
|
||||||
|
} as unknown) as DataSourceApi<any, any>;
|
||||||
|
|
||||||
|
const props: Props = {
|
||||||
|
datasource,
|
||||||
|
onPairsChanged: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
|
const wrapper = mount(<AdHocFilterField {...props} />);
|
||||||
|
const instance = wrapper.instance() as AdHocFilterField;
|
||||||
|
|
||||||
|
return {
|
||||||
|
instance,
|
||||||
|
wrapper,
|
||||||
|
datasource,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('AdHocFilterField', () => {
|
||||||
|
describe('loadTagKeys', () => {
|
||||||
|
describe('when called and there is no extendedOptions', () => {
|
||||||
|
const { instance, datasource } = setup({ extendedOptions: undefined });
|
||||||
|
|
||||||
|
it('then it should return correct keys', async () => {
|
||||||
|
const keys = await instance.loadTagKeys();
|
||||||
|
|
||||||
|
expect(keys).toEqual(['key 1', 'key 2']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then datasource.getTagKeys should be called with an empty object', async () => {
|
||||||
|
await instance.loadTagKeys();
|
||||||
|
|
||||||
|
expect(datasource.getTagKeys).toBeCalledWith({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when called and there is extendedOptions', () => {
|
||||||
|
const extendedOptions = { measurement: 'default' };
|
||||||
|
const { instance, datasource } = setup({ extendedOptions });
|
||||||
|
|
||||||
|
it('then it should return correct keys', async () => {
|
||||||
|
const keys = await instance.loadTagKeys();
|
||||||
|
|
||||||
|
expect(keys).toEqual(['key 1', 'key 2']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then datasource.getTagKeys should be called with extendedOptions', async () => {
|
||||||
|
await instance.loadTagKeys();
|
||||||
|
|
||||||
|
expect(datasource.getTagKeys).toBeCalledWith(extendedOptions);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('loadTagValues', () => {
|
||||||
|
describe('when called and there is no extendedOptions', () => {
|
||||||
|
const { instance, datasource } = setup({ extendedOptions: undefined });
|
||||||
|
|
||||||
|
it('then it should return correct values', async () => {
|
||||||
|
const values = await instance.loadTagValues('key 1');
|
||||||
|
|
||||||
|
expect(values).toEqual(['value 1', 'value 2']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then datasource.getTagValues should be called with the correct key', async () => {
|
||||||
|
await instance.loadTagValues('key 1');
|
||||||
|
|
||||||
|
expect(datasource.getTagValues).toBeCalledWith({ key: 'key 1' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when called and there is extendedOptions', () => {
|
||||||
|
const extendedOptions = { measurement: 'default' };
|
||||||
|
const { instance, datasource } = setup({ extendedOptions });
|
||||||
|
|
||||||
|
it('then it should return correct values', async () => {
|
||||||
|
const values = await instance.loadTagValues('key 1');
|
||||||
|
|
||||||
|
expect(values).toEqual(['value 1', 'value 2']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then datasource.getTagValues should be called with extendedOptions and the correct key', async () => {
|
||||||
|
await instance.loadTagValues('key 1');
|
||||||
|
|
||||||
|
expect(datasource.getTagValues).toBeCalledWith({ measurement: 'default', key: 'key 1' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updatePairs', () => {
|
||||||
|
describe('when called with an empty pairs array', () => {
|
||||||
|
describe('and called with keys', () => {
|
||||||
|
it('then it should return correct pairs', async () => {
|
||||||
|
const { instance } = setup();
|
||||||
|
const pairs: KeyValuePair[] = [];
|
||||||
|
const index = 0;
|
||||||
|
const key: string = undefined;
|
||||||
|
const keys: string[] = ['key 1', 'key 2'];
|
||||||
|
const value: string = undefined;
|
||||||
|
const values: string[] = undefined;
|
||||||
|
const operator: string = undefined;
|
||||||
|
|
||||||
|
const result = instance.updatePairs(pairs, index, { key, keys, value, values, operator });
|
||||||
|
|
||||||
|
expect(result).toEqual([{ key: '', keys, value: '', values: [], operator: '' }]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when called with an non empty pairs array', () => {
|
||||||
|
it('then it should update correct pairs at supplied index', async () => {
|
||||||
|
const { instance } = setup();
|
||||||
|
const pairs: KeyValuePair[] = [
|
||||||
|
{
|
||||||
|
key: 'prev key 1',
|
||||||
|
keys: ['prev key 1', 'prev key 2'],
|
||||||
|
value: 'prev value 1',
|
||||||
|
values: ['prev value 1', 'prev value 2'],
|
||||||
|
operator: '=',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'prev key 3',
|
||||||
|
keys: ['prev key 3', 'prev key 4'],
|
||||||
|
value: 'prev value 3',
|
||||||
|
values: ['prev value 3', 'prev value 4'],
|
||||||
|
operator: '!=',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const index = 1;
|
||||||
|
const key = 'key 3';
|
||||||
|
const keys = ['key 3', 'key 4'];
|
||||||
|
const value = 'value 3';
|
||||||
|
const values = ['value 3', 'value 4'];
|
||||||
|
const operator = '=';
|
||||||
|
|
||||||
|
const result = instance.updatePairs(pairs, index, { key, keys, value, values, operator });
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
key: 'prev key 1',
|
||||||
|
keys: ['prev key 1', 'prev key 2'],
|
||||||
|
value: 'prev value 1',
|
||||||
|
values: ['prev value 1', 'prev value 2'],
|
||||||
|
operator: '=',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'key 3',
|
||||||
|
keys: ['key 3', 'key 4'],
|
||||||
|
value: 'value 3',
|
||||||
|
values: ['value 3', 'value 4'],
|
||||||
|
operator: '=',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
import { DataSourceApi, DataQuery, DataSourceJsonData } from '@grafana/ui';
|
import { DataSourceApi, DataQuery, DataSourceJsonData } from '@grafana/ui';
|
||||||
import { AdHocFilter } from './AdHocFilter';
|
import { AdHocFilter } from './AdHocFilter';
|
||||||
|
|
||||||
export const DEFAULT_REMOVE_FILTER_VALUE = '-- remove filter --';
|
export const DEFAULT_REMOVE_FILTER_VALUE = '-- remove filter --';
|
||||||
|
|
||||||
|
const addFilterButton = (onAddFilter: (event: React.MouseEvent) => void) => (
|
||||||
|
<button className="gf-form-label gf-form-label--btn query-part" onClick={onAddFilter}>
|
||||||
|
<i className="fa fa-plus" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
|
||||||
export interface KeyValuePair {
|
export interface KeyValuePair {
|
||||||
keys: string[];
|
keys: string[];
|
||||||
key: string;
|
key: string;
|
||||||
@ -15,6 +21,7 @@ export interface KeyValuePair {
|
|||||||
export interface Props<TQuery extends DataQuery = DataQuery, TOptions extends DataSourceJsonData = DataSourceJsonData> {
|
export interface Props<TQuery extends DataQuery = DataQuery, TOptions extends DataSourceJsonData = DataSourceJsonData> {
|
||||||
datasource: DataSourceApi<TQuery, TOptions>;
|
datasource: DataSourceApi<TQuery, TOptions>;
|
||||||
onPairsChanged: (pairs: KeyValuePair[]) => void;
|
onPairsChanged: (pairs: KeyValuePair[]) => void;
|
||||||
|
extendedOptions?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
@ -27,58 +34,45 @@ export class AdHocFilterField<
|
|||||||
> extends React.PureComponent<Props<TQuery, TOptions>, State> {
|
> extends React.PureComponent<Props<TQuery, TOptions>, State> {
|
||||||
state: State = { pairs: [] };
|
state: State = { pairs: [] };
|
||||||
|
|
||||||
onKeyChanged = (index: number) => async (key: string) => {
|
componentDidUpdate(prevProps: Props) {
|
||||||
if (key !== DEFAULT_REMOVE_FILTER_VALUE) {
|
if (_.isEqual(prevProps.extendedOptions, this.props.extendedOptions) === false) {
|
||||||
const { datasource, onPairsChanged } = this.props;
|
const pairs = [];
|
||||||
const tagValues = datasource.getTagValues ? await datasource.getTagValues({ key }) : [];
|
|
||||||
const values = tagValues.map(tagValue => tagValue.text);
|
|
||||||
const newPairs = this.updatePairAt(index, { key, values });
|
|
||||||
|
|
||||||
this.setState({ pairs: newPairs });
|
this.setState({ pairs }, () => this.props.onPairsChanged(pairs));
|
||||||
onPairsChanged(newPairs);
|
|
||||||
} else {
|
|
||||||
this.onRemoveFilter(index);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
onValueChanged = (index: number) => (value: string) => {
|
loadTagKeys = async () => {
|
||||||
const newPairs = this.updatePairAt(index, { value });
|
const { datasource, extendedOptions } = this.props;
|
||||||
|
const options = extendedOptions || {};
|
||||||
this.setState({ pairs: newPairs });
|
const tagKeys = datasource.getTagKeys ? await datasource.getTagKeys(options) : [];
|
||||||
this.props.onPairsChanged(newPairs);
|
|
||||||
};
|
|
||||||
|
|
||||||
onOperatorChanged = (index: number) => (operator: string) => {
|
|
||||||
const newPairs = this.updatePairAt(index, { operator });
|
|
||||||
|
|
||||||
this.setState({ pairs: newPairs });
|
|
||||||
this.props.onPairsChanged(newPairs);
|
|
||||||
};
|
|
||||||
|
|
||||||
onAddFilter = async () => {
|
|
||||||
const { pairs } = this.state;
|
|
||||||
const tagKeys = this.props.datasource.getTagKeys ? await this.props.datasource.getTagKeys({}) : [];
|
|
||||||
const keys = tagKeys.map(tagKey => tagKey.text);
|
const keys = tagKeys.map(tagKey => tagKey.text);
|
||||||
const newPairs = pairs.concat({ key: null, operator: null, value: null, keys, values: [] });
|
|
||||||
|
|
||||||
this.setState({ pairs: newPairs });
|
return keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
onRemoveFilter = async (index: number) => {
|
loadTagValues = async (key: string) => {
|
||||||
const { pairs } = this.state;
|
const { datasource, extendedOptions } = this.props;
|
||||||
const newPairs = pairs.reduce((allPairs, pair, pairIndex) => {
|
const options = extendedOptions || {};
|
||||||
if (pairIndex === index) {
|
const tagValues = datasource.getTagValues ? await datasource.getTagValues({ ...options, key }) : [];
|
||||||
return allPairs;
|
const values = tagValues.map(tagValue => tagValue.text);
|
||||||
}
|
|
||||||
return allPairs.concat(pair);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
this.setState({ pairs: newPairs });
|
return values;
|
||||||
this.props.onPairsChanged(newPairs);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private updatePairAt = (index: number, pair: Partial<KeyValuePair>) => {
|
updatePairs(pairs: KeyValuePair[], index: number, pair: Partial<KeyValuePair>) {
|
||||||
const { pairs } = this.state;
|
if (pairs.length === 0) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: pair.key || '',
|
||||||
|
keys: pair.keys || [],
|
||||||
|
operator: pair.operator || '',
|
||||||
|
value: pair.value || '',
|
||||||
|
values: pair.values || [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
const newPairs: KeyValuePair[] = [];
|
const newPairs: KeyValuePair[] = [];
|
||||||
for (let pairIndex = 0; pairIndex < pairs.length; pairIndex++) {
|
for (let pairIndex = 0; pairIndex < pairs.length; pairIndex++) {
|
||||||
const newPair = pairs[pairIndex];
|
const newPair = pairs[pairIndex];
|
||||||
@ -98,17 +92,55 @@ export class AdHocFilterField<
|
|||||||
}
|
}
|
||||||
|
|
||||||
return newPairs;
|
return newPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyChanged = (index: number) => async (key: string) => {
|
||||||
|
if (key !== DEFAULT_REMOVE_FILTER_VALUE) {
|
||||||
|
const { onPairsChanged } = this.props;
|
||||||
|
const values = await this.loadTagValues(key);
|
||||||
|
const pairs = this.updatePairs(this.state.pairs, index, { key, values });
|
||||||
|
|
||||||
|
this.setState({ pairs }, () => onPairsChanged(pairs));
|
||||||
|
} else {
|
||||||
|
this.onRemoveFilter(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onValueChanged = (index: number) => (value: string) => {
|
||||||
|
const pairs = this.updatePairs(this.state.pairs, index, { value });
|
||||||
|
|
||||||
|
this.setState({ pairs }, () => this.props.onPairsChanged(pairs));
|
||||||
|
};
|
||||||
|
|
||||||
|
onOperatorChanged = (index: number) => (operator: string) => {
|
||||||
|
const pairs = this.updatePairs(this.state.pairs, index, { operator });
|
||||||
|
|
||||||
|
this.setState({ pairs }, () => this.props.onPairsChanged(pairs));
|
||||||
|
};
|
||||||
|
|
||||||
|
onAddFilter = async () => {
|
||||||
|
const keys = await this.loadTagKeys();
|
||||||
|
const pairs = this.state.pairs.concat(this.updatePairs([], 0, { keys }));
|
||||||
|
|
||||||
|
this.setState({ pairs }, () => this.props.onPairsChanged(pairs));
|
||||||
|
};
|
||||||
|
|
||||||
|
onRemoveFilter = async (index: number) => {
|
||||||
|
const pairs = this.state.pairs.reduce((allPairs, pair, pairIndex) => {
|
||||||
|
if (pairIndex === index) {
|
||||||
|
return allPairs;
|
||||||
|
}
|
||||||
|
return allPairs.concat(pair);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
this.setState({ pairs });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { pairs } = this.state;
|
const { pairs } = this.state;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{pairs.length < 1 && (
|
{pairs.length < 1 && addFilterButton(this.onAddFilter)}
|
||||||
<button className="gf-form-label gf-form-label--btn query-part" onClick={this.onAddFilter}>
|
|
||||||
<i className="fa fa-plus" />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{pairs.map((pair, index) => {
|
{pairs.map((pair, index) => {
|
||||||
const adHocKey = `adhoc-filter-${index}-${pair.key}-${pair.value}`;
|
const adHocKey = `adhoc-filter-${index}-${pair.key}-${pair.value}`;
|
||||||
return (
|
return (
|
||||||
@ -129,11 +161,7 @@ export class AdHocFilterField<
|
|||||||
<i className="fa fa-minus" />
|
<i className="fa fa-minus" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{index === pairs.length - 1 && (
|
{index === pairs.length - 1 && addFilterButton(this.onAddFilter)}
|
||||||
<button className="gf-form-label gf-form-label--btn" onClick={this.onAddFilter}>
|
|
||||||
<i className="fa fa-plus" />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -118,7 +118,13 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
|
|||||||
</Cascader>
|
</Cascader>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-shrink-1 flex-flow-column-nowrap">
|
<div className="flex-shrink-1 flex-flow-column-nowrap">
|
||||||
{measurement && <AdHocFilterField onPairsChanged={this.onPairsChanged} datasource={datasource} />}
|
{measurement && (
|
||||||
|
<AdHocFilterField
|
||||||
|
onPairsChanged={this.onPairsChanged}
|
||||||
|
datasource={datasource}
|
||||||
|
extendedOptions={{ measurement }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -182,14 +182,14 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO
|
|||||||
return this._seriesQuery(interpolated, options).then(_.curry(this.responseParser.parse)(query));
|
return this._seriesQuery(interpolated, options).then(_.curry(this.responseParser.parse)(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
getTagKeys(options) {
|
getTagKeys(options: any = {}) {
|
||||||
const queryBuilder = new InfluxQueryBuilder({ measurement: '', tags: [] }, this.database);
|
const queryBuilder = new InfluxQueryBuilder({ measurement: options.measurement || '', tags: [] }, this.database);
|
||||||
const query = queryBuilder.buildExploreQuery('TAG_KEYS');
|
const query = queryBuilder.buildExploreQuery('TAG_KEYS');
|
||||||
return this.metricFindQuery(query, options);
|
return this.metricFindQuery(query, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTagValues(options) {
|
getTagValues(options: any = {}) {
|
||||||
const queryBuilder = new InfluxQueryBuilder({ measurement: '', tags: [] }, this.database);
|
const queryBuilder = new InfluxQueryBuilder({ measurement: options.measurement || '', tags: [] }, this.database);
|
||||||
const query = queryBuilder.buildExploreQuery('TAG_VALUES', options.key);
|
const query = queryBuilder.buildExploreQuery('TAG_VALUES', options.key);
|
||||||
return this.metricFindQuery(query, options);
|
return this.metricFindQuery(query, options);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user