remove dashboardContext (#23227) (#25188)

This commit is contained in:
Peter Pisljar 2018-11-06 10:53:33 +01:00 committed by GitHub
parent 61ba781748
commit 6a36a77f79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 32 additions and 233 deletions

View file

@ -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: []
}
});
});
});
});

View file

@ -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 };
};
}

View file

@ -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
};

View file

@ -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, {

View file

@ -37,7 +37,7 @@ function create(min, max, dashboardCtx) {
getTimeBounds: () => ({ min, max })
},
() => {},
() => _.cloneDeep(dashboardCtx),
_.cloneDeep(dashboardCtx),
() => (inst.$$$warnCount = (inst.$$$warnCount || 0) + 1)
);
return inst;

View file

@ -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

View file

@ -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),
};

View file

@ -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();
}

View file

@ -27,6 +27,7 @@ export {
decorateQuery,
buildQueryFromFilters,
luceneStringToDsl,
BuildESQueryProvider
} from './search_source';
export {

View file

@ -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';

View file

@ -27,8 +27,12 @@ export interface TimeRange {
to: string;
}
export interface FilterMeta {
disabled: boolean;
}
export interface Filter {
meta: object;
meta: FilterMeta;
query: object;
}

View file

@ -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