mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
parent
61ba781748
commit
6a36a77f79
12 changed files with 32 additions and 233 deletions
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import { dashboardContextProvider } from '../dashboard_context';
|
||||
|
||||
describe('Dashboard Context', () => {
|
||||
|
||||
describe('with query bar', () => {
|
||||
let Private;
|
||||
let getAppState;
|
||||
let getDashboardContext;
|
||||
beforeEach(() => {
|
||||
Private = sinon.stub().returns({
|
||||
getFilters() {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty must and must not when there are no filters or queries', () => {
|
||||
getAppState = sinon.stub().returns({
|
||||
query: {
|
||||
language: 'lucene',
|
||||
query: null
|
||||
}
|
||||
});
|
||||
getDashboardContext = dashboardContextProvider(Private, getAppState);
|
||||
const context = getDashboardContext();
|
||||
expect(context).to.eql({
|
||||
bool: {
|
||||
must: [],
|
||||
must_not: []
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should add a valid query to must', () => {
|
||||
getAppState = sinon.stub().returns({
|
||||
query: {
|
||||
language: 'lucene',
|
||||
query: '*'
|
||||
}
|
||||
});
|
||||
getDashboardContext = dashboardContextProvider(Private, getAppState);
|
||||
const context = getDashboardContext();
|
||||
expect(context).to.eql({
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
query_string: {
|
||||
query: '*'
|
||||
}
|
||||
}
|
||||
],
|
||||
must_not: []
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with filter bar', () => {
|
||||
let Private;
|
||||
let getAppState;
|
||||
let getDashboardContext;
|
||||
beforeEach(() => {
|
||||
getAppState = sinon.stub().returns({ query: { language: 'something-else' } });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
getAppState.resetHistory();
|
||||
});
|
||||
|
||||
it('should add a valid filter to must', () => {
|
||||
Private = sinon.stub().returns({
|
||||
getFilters() {
|
||||
return [
|
||||
{ meta: { negate: false }, term: { foo: 'bar' } }
|
||||
];
|
||||
}
|
||||
});
|
||||
getDashboardContext = dashboardContextProvider(Private, getAppState);
|
||||
const context = getDashboardContext();
|
||||
expect(context).to.eql({
|
||||
bool: {
|
||||
must: [{ term: { foo: 'bar' } }],
|
||||
must_not: []
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should add a valid filter to must_not', () => {
|
||||
Private = sinon.stub().returns({
|
||||
getFilters() {
|
||||
return [
|
||||
{ meta: { negate: true }, term: { foo: 'bar' } }
|
||||
];
|
||||
}
|
||||
});
|
||||
getDashboardContext = dashboardContextProvider(Private, getAppState);
|
||||
const context = getDashboardContext();
|
||||
expect(context).to.eql({
|
||||
bool: {
|
||||
must: [],
|
||||
must_not: [{ term: { foo: 'bar' } }]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add a disabled filter', () => {
|
||||
Private = sinon.stub().returns({
|
||||
getFilters() {
|
||||
return [
|
||||
{ meta: { negate: true, disabled: true }, term: { foo: 'bar' } }
|
||||
];
|
||||
}
|
||||
});
|
||||
getDashboardContext = dashboardContextProvider(Private, getAppState);
|
||||
const context = getDashboardContext();
|
||||
expect(context).to.eql({
|
||||
bool: {
|
||||
must: [],
|
||||
must_not: []
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// This file is used by Timelion and TSVB
|
||||
import _ from 'lodash';
|
||||
import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter';
|
||||
import 'ui/state_management/app_state';
|
||||
import { luceneStringToDsl, migrateFilter } from 'ui/courier';
|
||||
|
||||
export function dashboardContextProvider(Private, getAppState) {
|
||||
return () => {
|
||||
const appState = getAppState();
|
||||
const queryFilter = Private(FilterBarQueryFilterProvider);
|
||||
const bool = { must: [], must_not: [] };
|
||||
if (!appState) { return { bool: bool }; }
|
||||
const filterBarFilters = queryFilter.getFilters();
|
||||
const queryBarQuery = appState.query;
|
||||
|
||||
if (queryBarQuery.language === 'lucene') {
|
||||
// Add the query bar filter, its handled differently.
|
||||
const query = luceneStringToDsl(queryBarQuery.query);
|
||||
if (query) { bool.must.push(query); }
|
||||
}
|
||||
|
||||
// Add each of the filter bar filters
|
||||
_.each(filterBarFilters, function (filter) {
|
||||
const esFilter = _.omit(filter, function (val, key) {
|
||||
if (key === 'meta' || key[0] === '$') { return true; }
|
||||
return false;
|
||||
});
|
||||
|
||||
if (filter.meta.disabled) { return; }
|
||||
if (filter.meta.negate) {
|
||||
bool.must_not = bool.must_not || [];
|
||||
if (esFilter.query || esFilter) { bool.must_not.push(migrateFilter(esFilter.query || esFilter)); }
|
||||
} else {
|
||||
bool.must = bool.must || [];
|
||||
if (esFilter.query || esFilter) { bool.must.push(migrateFilter(esFilter.query || esFilter)); }
|
||||
}
|
||||
});
|
||||
|
||||
return { bool: bool };
|
||||
};
|
||||
}
|
|
@ -18,17 +18,17 @@
|
|||
*/
|
||||
|
||||
import { validateInterval } from '../lib/validate_interval';
|
||||
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
||||
import { timezoneProvider } from 'ui/vis/lib/timezone';
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
import { BuildESQueryProvider } from 'ui/courier';
|
||||
|
||||
const MetricsRequestHandlerProvider = function (Private, Notifier, config, $http) {
|
||||
const dashboardContext = Private(dashboardContextProvider);
|
||||
const notify = new Notifier({ location: 'Metrics' });
|
||||
const buildEsQuery = Private(BuildESQueryProvider);
|
||||
|
||||
return {
|
||||
name: 'metrics',
|
||||
handler: function (vis, { uiState, timeRange }) {
|
||||
handler: function (vis, { uiState, timeRange, filters, query }) {
|
||||
const timezone = Private(timezoneProvider)();
|
||||
return new Promise((resolve) => {
|
||||
const panel = vis.params;
|
||||
|
@ -39,7 +39,7 @@ const MetricsRequestHandlerProvider = function (Private, Notifier, config, $http
|
|||
if (panel && panel.id) {
|
||||
const params = {
|
||||
timerange: { timezone, ...parsedTimeRange },
|
||||
filters: [dashboardContext()],
|
||||
filters: [buildEsQuery(vis.indexPattern, [query], filters)],
|
||||
panels: [panel],
|
||||
state: uiStateObj
|
||||
};
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
||||
|
||||
import { BuildESQueryProvider } from 'ui/courier';
|
||||
import { timezoneProvider } from 'ui/vis/lib/timezone';
|
||||
|
||||
const TimelionRequestHandlerProvider = function (Private, Notifier, $http) {
|
||||
const timezone = Private(timezoneProvider)();
|
||||
const dashboardContext = Private(dashboardContextProvider);
|
||||
const buildEsQuery = Private(BuildESQueryProvider);
|
||||
|
||||
const notify = new Notifier({
|
||||
location: 'Timelion'
|
||||
|
@ -31,7 +31,7 @@ const TimelionRequestHandlerProvider = function (Private, Notifier, $http) {
|
|||
|
||||
return {
|
||||
name: 'timelion',
|
||||
handler: function (vis, { timeRange }) {
|
||||
handler: function (vis, { timeRange, filters, query }) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const expression = vis.params.expression;
|
||||
|
@ -41,7 +41,7 @@ const TimelionRequestHandlerProvider = function (Private, Notifier, $http) {
|
|||
sheet: [expression],
|
||||
extended: {
|
||||
es: {
|
||||
filter: dashboardContext()
|
||||
filter: buildEsQuery(vis.indexPattern, [query], filters)
|
||||
}
|
||||
},
|
||||
time: _.extend(timeRange, {
|
||||
|
|
|
@ -37,7 +37,7 @@ function create(min, max, dashboardCtx) {
|
|||
getTimeBounds: () => ({ min, max })
|
||||
},
|
||||
() => {},
|
||||
() => _.cloneDeep(dashboardCtx),
|
||||
_.cloneDeep(dashboardCtx),
|
||||
() => (inst.$$$warnCount = (inst.$$$warnCount || 0) + 1)
|
||||
);
|
||||
return inst;
|
||||
|
|
|
@ -35,10 +35,10 @@ const TIMEFIELD = '%timefield%';
|
|||
*/
|
||||
export class EsQueryParser {
|
||||
|
||||
constructor(timeCache, searchCache, dashboardContext, onWarning) {
|
||||
constructor(timeCache, searchCache, filters, onWarning) {
|
||||
this._timeCache = timeCache;
|
||||
this._searchCache = searchCache;
|
||||
this._dashboardContext = dashboardContext;
|
||||
this._filters = filters;
|
||||
this._onWarning = onWarning;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ export class EsQueryParser {
|
|||
|
||||
if (context) {
|
||||
// Use dashboard context
|
||||
const newQuery = this._dashboardContext();
|
||||
const newQuery = _.cloneDeep(this._filters);
|
||||
if (timefield) {
|
||||
newQuery.bool.must.push(body.query);
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ export class EsQueryParser {
|
|||
const item = obj[pos];
|
||||
if (isQuery && (item === MUST_CLAUSE || item === MUST_NOT_CLAUSE)) {
|
||||
const ctxTag = item === MUST_CLAUSE ? 'must' : 'must_not';
|
||||
const ctx = this._dashboardContext();
|
||||
const ctx = _.cloneDeep(this._filters);
|
||||
if (ctx && ctx.bool && ctx.bool[ctxTag]) {
|
||||
if (Array.isArray(ctx.bool[ctxTag])) {
|
||||
// replace one value with an array of values
|
||||
|
|
|
@ -47,7 +47,7 @@ const DEFAULT_PARSER = 'elasticsearch';
|
|||
|
||||
export class VegaParser {
|
||||
|
||||
constructor(spec, searchCache, timeCache, dashboardContext, serviceSettings) {
|
||||
constructor(spec, searchCache, timeCache, filters, serviceSettings) {
|
||||
this.spec = spec;
|
||||
this.hideWarnings = false;
|
||||
this.error = undefined;
|
||||
|
@ -55,7 +55,7 @@ export class VegaParser {
|
|||
|
||||
const onWarn = this._onWarning.bind(this);
|
||||
this._urlParsers = {
|
||||
elasticsearch: new EsQueryParser(timeCache, searchCache, dashboardContext, onWarn),
|
||||
elasticsearch: new EsQueryParser(timeCache, searchCache, filters, onWarn),
|
||||
emsfile: new EmsFileParser(serviceSettings),
|
||||
url: new UrlParser(onWarn),
|
||||
};
|
||||
|
|
|
@ -18,24 +18,25 @@
|
|||
*/
|
||||
|
||||
import { VegaParser } from './data_model/vega_parser';
|
||||
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
||||
import { SearchCache } from './data_model/search_cache';
|
||||
import { TimeCache } from './data_model/time_cache';
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
import { BuildESQueryProvider } from 'ui/courier';
|
||||
|
||||
export function VegaRequestHandlerProvider(Private, es, serviceSettings) {
|
||||
|
||||
const dashboardContext = Private(dashboardContextProvider);
|
||||
const buildEsQuery = Private(BuildESQueryProvider);
|
||||
const searchCache = new SearchCache(es, { max: 10, maxAge: 4 * 1000 });
|
||||
const timeCache = new TimeCache(timefilter, 3 * 1000);
|
||||
|
||||
|
||||
return {
|
||||
|
||||
name: 'vega',
|
||||
|
||||
handler(vis, { timeRange }) {
|
||||
handler(vis, { timeRange, filters, query }) {
|
||||
timeCache.setTimeRange(timeRange);
|
||||
const vp = new VegaParser(vis.params.spec, searchCache, timeCache, dashboardContext, serviceSettings);
|
||||
const filtersDsl = buildEsQuery(vis.indexPattern, [query], filters);
|
||||
const vp = new VegaParser(vis.params.spec, searchCache, timeCache, filtersDsl, serviceSettings);
|
||||
return vp.parseAsync();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ export {
|
|||
decorateQuery,
|
||||
buildQueryFromFilters,
|
||||
luceneStringToDsl,
|
||||
BuildESQueryProvider
|
||||
} from './search_source';
|
||||
|
||||
export {
|
||||
|
|
|
@ -20,4 +20,4 @@
|
|||
export { SearchSourceProvider } from './search_source';
|
||||
export { migrateFilter } from './migrate_filter';
|
||||
export { decorateQuery } from './decorate_query';
|
||||
export { buildQueryFromFilters, luceneStringToDsl } from './build_query';
|
||||
export { buildQueryFromFilters, luceneStringToDsl, BuildESQueryProvider } from './build_query';
|
||||
|
|
|
@ -27,8 +27,12 @@ export interface TimeRange {
|
|||
to: string;
|
||||
}
|
||||
|
||||
export interface FilterMeta {
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
meta: object;
|
||||
meta: FilterMeta;
|
||||
query: object;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,9 @@ export class VisualizeDataLoader {
|
|||
const requestHandlerResponse = await this.requestHandler(this.vis, {
|
||||
partialRows: this.vis.params.partialRows || this.vis.type.requiresPartialRows,
|
||||
...params,
|
||||
filters: params.filters
|
||||
? params.filters.filter(filter => !filter.meta.disabled)
|
||||
: undefined,
|
||||
});
|
||||
|
||||
// No need to call the response handler when there have been no data nor has been there changes
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue