Move filter manager ⇒ NP (#48391)

* Moved filterManager to NP plugin

* Fixed applying filters to dashbaord.

* Minor fixes

* fixed types

* fix jest tests mock of filter

* Updated karma mccks

* Fixed lens test

* fixed import

* Removed comment
This commit is contained in:
Liza Katz 2019-10-29 11:55:24 +02:00 committed by GitHub
parent c3996e293c
commit 19c4f872cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 306 additions and 252 deletions

View file

@ -25,8 +25,8 @@ import {
createAction,
IncompatibleActionError,
} from '../../../../../../plugins/ui_actions/public';
import { changeTimeFilter, extractTimeFilter, FilterManager } from '../filter_manager';
import { TimefilterContract } from '../../timefilter';
import { FilterManager } from '../../../../../../plugins/data/public';
import { TimefilterContract, changeTimeFilter, extractTimeFilter } from '../../timefilter';
import { applyFiltersPopover } from '../apply_filters/apply_filters_popover';
import { IndexPatternsStart } from '../../index_patterns';
export const GLOBAL_APPLY_FILTER_ACTION = 'GLOBAL_APPLY_FILTER_ACTION';

View file

@ -33,7 +33,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component } from 'react';
import { IndexPattern } from '../../index_patterns';
import { getFilterDisplayText } from '../filter_bar/filter_editor/lib/get_filter_display_text';
import { mapAndFlattenFilters } from '../filter_manager/lib/map_and_flatten_filters';
import { mapAndFlattenFilters } from '../../../../../../plugins/data/public';
import { getDisplayValueFromFilter } from '../filter_bar/filter_editor/lib/get_display_value';
interface Props {

View file

@ -24,7 +24,7 @@ import { FilterStateManager } from './filter_state_manager';
import { StubState } from './test_helpers/stub_state';
import { getFilter } from './test_helpers/get_stub_filter';
import { FilterManager } from './filter_manager';
import { FilterManager } from '../../../../../../plugins/data/public';
import { coreMock } from '../../../../../../core/public/mocks';
const setupMock = coreMock.createSetup();
@ -101,25 +101,29 @@ describe('filter_state_manager', () => {
});
test('should update filter manager global filters', done => {
const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
globalStateStub.filters.push(f1);
setTimeout(() => {
const updateSubscription = filterManager.getUpdates$().subscribe(() => {
expect(filterManager.getGlobalFilters()).toHaveLength(1);
if (updateSubscription) {
updateSubscription.unsubscribe();
}
done();
}, 100);
});
const f1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'age', 34);
globalStateStub.filters.push(f1);
});
test('should update filter manager app filters', done => {
expect(filterManager.getAppFilters()).toHaveLength(0);
test('should update filter manager app filter', done => {
const updateSubscription = filterManager.getUpdates$().subscribe(() => {
expect(filterManager.getAppFilters()).toHaveLength(1);
if (updateSubscription) {
updateSubscription.unsubscribe();
}
done();
});
const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
appStateStub.filters.push(f1);
setTimeout(() => {
expect(filterManager.getAppFilters()).toHaveLength(1);
done();
}, 100);
});
test('should update URL when filter manager filters are set', () => {

View file

@ -21,7 +21,7 @@ import { FilterStateStore } from '@kbn/es-query';
import _ from 'lodash';
import { State } from 'ui/state_management/state';
import { FilterManager } from './filter_manager';
import { FilterManager } from '../../../../../../plugins/data/public';
type GetAppStateFunc = () => State | undefined | null;

View file

@ -17,10 +17,4 @@
* under the License.
*/
export { FilterManager } from './filter_manager';
export { FilterStateManager } from './filter_state_manager';
export { uniqFilters } from './lib/uniq_filters';
export { extractTimeFilter } from './lib/extract_time_filter';
export { changeTimeFilter } from './lib/change_time_filter';
export { onlyDisabledFiltersChanged } from './lib/only_disabled';

View file

@ -17,8 +17,6 @@
* under the License.
*/
export * from './filter_service';
export { FilterBar } from './filter_bar';
export { ApplyFiltersPopover } from './apply_filters';

View file

@ -43,14 +43,7 @@ export { SearchBar, SearchBarProps, SavedQueryAttributes, SavedQuery } from './s
/** @public static code */
export * from '../common';
export {
FilterManager,
FilterStateManager,
uniqFilters,
extractTimeFilter,
changeTimeFilter,
onlyDisabledFiltersChanged,
} from './filter/filter_manager';
export { FilterStateManager } from './filter/filter_manager';
export {
CONTAINS_SPACES,
getFromSavedObject,
@ -69,4 +62,11 @@ export {
mockIndexPattern,
} from './index_patterns';
export { TimeHistoryContract, TimefilterContract, getTime, InputTimeRange } from './timefilter';
export {
TimeHistoryContract,
TimefilterContract,
getTime,
InputTimeRange,
extractTimeFilter,
changeTimeFilter,
} from './timefilter';

View file

@ -17,14 +17,12 @@
* under the License.
*/
import { filterServiceMock } from './filter/filter_service.mock';
import { indexPatternsServiceMock } from './index_patterns/index_patterns_service.mock';
import { queryServiceMock } from './query/query_service.mock';
import { timefilterServiceMock } from './timefilter/timefilter_service.mock';
function createDataSetupMock() {
return {
filter: filterServiceMock.createSetupContract(),
indexPatterns: indexPatternsServiceMock.createSetupContract(),
query: queryServiceMock.createSetupContract(),
timefilter: timefilterServiceMock.createSetupContract(),

View file

@ -20,7 +20,6 @@
import { CoreSetup, CoreStart, Plugin } from 'kibana/public';
import { SearchService, SearchStart, createSearchBar, StatetfulSearchBarProps } from './search';
import { QueryService, QuerySetup } from './query';
import { FilterService, FilterSetup, FilterStart } from './filter';
import { TimefilterService, TimefilterSetup } from './timefilter';
import { IndexPatternsService, IndexPatternsSetup, IndexPatternsStart } from './index_patterns';
import {
@ -60,7 +59,6 @@ export interface DataSetup {
query: QuerySetup;
timefilter: TimefilterSetup;
indexPatterns: IndexPatternsSetup;
filter: FilterSetup;
}
/**
@ -72,7 +70,6 @@ export interface DataStart {
query: QuerySetup;
timefilter: TimefilterSetup;
indexPatterns: IndexPatternsStart;
filter: FilterStart;
search: SearchStart;
ui: {
SearchBar: React.ComponentType<StatetfulSearchBarProps>;
@ -93,8 +90,6 @@ export interface DataStart {
export class DataPlugin
implements
Plugin<DataSetup, DataStart, DataPluginSetupDependencies, DataPluginStartDependencies> {
// Exposed services, sorted alphabetically
private readonly filter: FilterService = new FilterService();
private readonly indexPatterns: IndexPatternsService = new IndexPatternsService();
private readonly query: QueryService = new QueryService();
private readonly search: SearchService = new SearchService();
@ -109,14 +104,10 @@ export class DataPlugin
uiSettings,
store: __LEGACY.storage,
});
const filterService = this.filter.setup({
uiSettings,
});
this.setupApi = {
indexPatterns: this.indexPatterns.setup(),
query: this.query.setup(),
timefilter: timefilterService,
filter: filterService,
};
return this.setupApi;
@ -142,12 +133,11 @@ export class DataPlugin
data,
store: __LEGACY.storage,
timefilter: this.setupApi.timefilter,
filterManager: this.setupApi.filter.filterManager,
});
uiActions.registerAction(
createFilterAction(
this.setupApi.filter.filterManager,
data.query.filterManager,
this.setupApi.timefilter.timefilter,
indexPatternsService
)
@ -167,7 +157,6 @@ export class DataPlugin
public stop() {
this.indexPatterns.stop();
this.filter.stop();
this.query.stop();
this.search.stop();
this.timefilter.stop();

View file

@ -25,7 +25,7 @@ import { DataPublicPluginStart } from 'src/plugins/data/public';
import { Storage } from '../../../types';
import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
import { TimefilterSetup } from '../../../timefilter';
import { FilterManager, SearchBar } from '../../../';
import { SearchBar } from '../../../';
import { SearchBarOwnProps } from '.';
interface StatefulSearchBarDeps {
@ -33,16 +33,15 @@ interface StatefulSearchBarDeps {
data: DataPublicPluginStart;
store: Storage;
timefilter: TimefilterSetup;
filterManager: FilterManager;
}
export type StatetfulSearchBarProps = SearchBarOwnProps & {
appName: string;
};
const defaultFiltersUpdated = (filterManager: FilterManager) => {
const defaultFiltersUpdated = (data: DataPublicPluginStart) => {
return (filters: Filter[]) => {
filterManager.setFilters(filters);
data.query.filterManager.setFilters(filters);
};
};
@ -55,16 +54,11 @@ const defaultOnRefreshChange = (timefilter: TimefilterSetup) => {
};
};
export function createSearchBar({
core,
store,
timefilter,
filterManager,
data,
}: StatefulSearchBarDeps) {
export function createSearchBar({ core, store, timefilter, data }: StatefulSearchBarDeps) {
// App name should come from the core application service.
// Until it's available, we'll ask the user to provide it for the pre-wired component.
return (props: StatetfulSearchBarProps) => {
const { filterManager } = data.query;
const tfRefreshInterval = timefilter.timefilter.getRefreshInterval();
const fmFilters = filterManager.getFilters();
const [refreshInterval, setRefreshInterval] = useState(tfRefreshInterval.value);
@ -124,7 +118,7 @@ export function createSearchBar({
refreshInterval={refreshInterval}
isRefreshPaused={refreshPaused}
filters={filters}
onFiltersUpdated={defaultFiltersUpdated(filterManager)}
onFiltersUpdated={defaultFiltersUpdated(data)}
onRefreshChange={defaultOnRefreshChange(timefilter)}
{...props}
/>

View file

@ -25,9 +25,6 @@ import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import { npStart } from 'ui/new_platform';
import { FilterBar, ApplyFiltersPopover } from '../filter';
// @ts-ignore
import { mapAndFlattenFilters } from '../filter/filter_manager/lib/map_and_flatten_filters';
import { IndexPatterns } from '../index_patterns/index_patterns';
/** @internal */

View file

@ -23,3 +23,5 @@ export * from './types';
export { Timefilter, TimefilterContract } from './timefilter';
export { TimeHistory, TimeHistoryContract } from './time_history';
export { getTime } from './get_time';
export { changeTimeFilter } from './lib/change_time_filter';
export { extractTimeFilter } from './lib/extract_time_filter';

View file

@ -19,7 +19,7 @@
import { RangeFilter } from '@kbn/es-query';
import { changeTimeFilter } from './change_time_filter';
import { TimeRange } from 'src/plugins/data/public';
import { timefilterServiceMock } from '../../../timefilter/timefilter_service.mock';
import { timefilterServiceMock } from '../timefilter_service.mock';
const timefilterMock = timefilterServiceMock.createSetupContract();
const timefilter = timefilterMock.timefilter;

View file

@ -20,7 +20,7 @@
import moment from 'moment';
import { keys } from 'lodash';
import { RangeFilter } from '@kbn/es-query';
import { TimefilterContract } from '../../../timefilter';
import { TimefilterContract } from '../timefilter';
export function convertRangeFilterToTimeRange(filter: RangeFilter) {
const key = keys(filter.range)[0];

View file

@ -26,6 +26,7 @@ import {
import { PhraseFilterManager } from './filter_manager/phrase_filter_manager';
import { createSearchSource } from './create_search_source';
import { i18n } from '@kbn/i18n';
import { npStart } from 'ui/new_platform';
import chrome from 'ui/chrome';
import { start as data } from '../../../../core_plugins/data/public/legacy';
@ -187,9 +188,10 @@ export async function listControlFactory(controlParams, useTimeFilter, SearchSou
// ignore not found error and return control so it can be displayed in disabled state.
}
const { filterManager } = npStart.plugins.data.query;
return new ListControl(
controlParams,
new PhraseFilterManager(controlParams.id, controlParams.fieldName, indexPattern, data.filter.filterManager),
new PhraseFilterManager(controlParams.id, controlParams.fieldName, indexPattern, filterManager),
useTimeFilter,
SearchSource,
);

View file

@ -24,6 +24,28 @@ jest.mock('ui/timefilter', () => ({
createFilter: jest.fn(),
}));
jest.mock('ui/new_platform', () => ({
npStart: {
plugins: {
data: {
query: {
filterManager: {
fieldName: 'myNumberField',
getIndexPattern: () => ({
fields: { getByName: name => {
const fields = { myField: { name: 'myField' } };
return fields[name];
} }
}),
getAppFilters: jest.fn().mockImplementation(() => ([])),
getGlobalFilters: jest.fn().mockImplementation(() => ([])),
}
}
}
},
},
}));
jest.mock('../../../../core_plugins/data/public/legacy', () => ({
start: {
indexPatterns: {
@ -36,19 +58,6 @@ jest.mock('../../../../core_plugins/data/public/legacy', () => ({
}),
}
},
filter: {
filterManager: {
fieldName: 'myNumberField',
getIndexPattern: () => ({
fields: { getByName: name => {
const fields = { myField: { name: 'myField' } };
return fields[name];
} }
}),
getAppFilters: jest.fn().mockImplementation(() => ([])),
getGlobalFilters: jest.fn().mockImplementation(() => ([])),
}
}
}
}));

View file

@ -27,6 +27,7 @@ import { RangeFilterManager } from './filter_manager/range_filter_manager';
import { createSearchSource } from './create_search_source';
import { i18n } from '@kbn/i18n';
import { start as data } from '../../../../core_plugins/data/public/legacy';
import { npStart } from 'ui/new_platform';
const minMaxAgg = (field) => {
const aggBody = {};
@ -106,9 +107,10 @@ export async function rangeControlFactory(controlParams, useTimeFilter, SearchSo
} catch (err) {
// ignore not found error and return control so it can be displayed in disabled state.
}
const { filterManager } = npStart.plugins.data.query;
return new RangeControl(
controlParams,
new RangeFilterManager(controlParams.id, controlParams.fieldName, indexPattern, data.filter.filterManager),
new RangeFilterManager(controlParams.id, controlParams.fieldName, indexPattern, filterManager),
useTimeFilter,
SearchSource,
);

View file

@ -32,6 +32,28 @@ jest.mock('ui/timefilter', () => ({
createFilter: jest.fn(),
}));
jest.mock('ui/new_platform', () => ({
npStart: {
plugins: {
data: {
query: {
filterManager: {
fieldName: 'myNumberField',
getIndexPattern: () => ({
fields: { getByName: name => {
const fields = { myNumberField: { name: 'myNumberField' } };
return fields[name];
}
} }),
getAppFilters: jest.fn().mockImplementation(() => ([])),
getGlobalFilters: jest.fn().mockImplementation(() => ([])),
}
}
}
},
},
}));
jest.mock('../../../../core_plugins/data/public/legacy', () => ({
start: {
indexPatterns: {
@ -44,19 +66,6 @@ jest.mock('../../../../core_plugins/data/public/legacy', () => ({
} }),
}
},
filter: {
filterManager: {
fieldName: 'myNumberField',
getIndexPattern: () => ({
fields: { getByName: name => {
const fields = { myNumberField: { name: 'myNumberField' } };
return fields[name];
}
} }),
getAppFilters: jest.fn().mockImplementation(() => ([])),
getGlobalFilters: jest.fn().mockImplementation(() => ([])),
}
}
}
}));

View file

@ -23,7 +23,7 @@ import { I18nContext } from 'ui/i18n';
import { InputControlVis } from './components/vis/input_control_vis';
import { controlFactory } from './control/control_factory';
import { getLineageMap } from './lineage';
import { start as data } from '../../../core_plugins/data/public/legacy';
import { npStart } from 'ui/new_platform';
import { SearchSource } from '../../../ui/public/courier/search_source/search_source';
class VisController {
@ -34,7 +34,7 @@ class VisController {
this.queryBarUpdateHandler = this.updateControlsFromKbn.bind(this);
this.filterManager = data.filter.filterManager;
this.filterManager = npStart.plugins.data.query.filterManager;
this.updateSubsciption = this.filterManager.getUpdates$()
.subscribe(this.queryBarUpdateHandler);
}

View file

@ -22,8 +22,9 @@ import { Subscription } from 'rxjs';
import { Filter, FilterStateStore } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import { TExecuteTriggerActions } from 'src/plugins/ui_actions/public';
import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../../plugins/data/public';
import { setup as data } from '../../../../data/public/legacy';
import { getTime, onlyDisabledFiltersChanged, Query } from '../../../../data/public';
import { Query, getTime } from '../../../../data/public';
import {
APPLY_FILTER_TRIGGER,
Container,
@ -46,7 +47,6 @@ import {
RequestAdapter,
SearchSource,
} from '../kibana_services';
import { TimeRange } from '../../../../../../plugins/data/public';
import { SEARCH_EMBEDDABLE_TYPE } from './constants';
interface SearchScope extends ng.IScope {

View file

@ -30,14 +30,14 @@ import {
import { Subscription } from 'rxjs';
import * as Rx from 'rxjs';
import { Filter } from '@kbn/es-query';
import { TimeRange } from '../../../../../../plugins/data/public';
import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../../plugins/data/public';
import {
EmbeddableInput,
EmbeddableOutput,
Embeddable,
Container,
} from '../../../../../../plugins/embeddable/public';
import { Query, onlyDisabledFiltersChanged } from '../../../../data/public';
import { Query } from '../../../../data/public';
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
const getKeys = <T extends {}>(o: T): Array<keyof T> => Object.keys(o) as Array<keyof T>;

View file

@ -21,9 +21,8 @@ import { get } from 'lodash';
import { GeohashLayer } from './geohash_layer';
import { BaseMapsVisualizationProvider } from './base_maps_visualization';
import { TileMapTooltipFormatterProvider } from './editors/_tooltip_formatter';
import { npStart } from 'ui/new_platform';
import { getFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities';
import { start as data } from '../../../core_plugins/data/public/legacy';
const filterManager = data.filter.filterManager;
export const createTileMapVisualization = ({ serviceSettings, $injector }) => {
const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings);
@ -189,6 +188,7 @@ export const createTileMapVisualization = ({ serviceSettings, $injector }) => {
filter[filterName] = { ignore_unmapped: true };
filter[filterName][field] = filterData;
const { filterManager } = npStart.plugins.data.query;
filterManager.addFilters([filter]);
this.vis.updateState();

View file

@ -23,6 +23,7 @@ import { VegaView } from './vega_view/vega_view';
import { VegaMapView } from './vega_view/vega_map_view';
import { timefilter } from 'ui/timefilter';
import { start as data } from '../../../core_plugins/data/public/legacy';
import { npStart } from 'ui/new_platform';
import { findIndexPatternByTitle } from '../../data/public/index_patterns';
@ -99,11 +100,12 @@ export const createVegaVisualization = ({ serviceSettings }) => class VegaVisual
this._vegaView = null;
}
const { filterManager } = npStart.plugins.data.query;
const vegaViewParams = {
parentEl: this._el,
vegaParser,
serviceSettings,
queryfilter: data.filter.filterManager,
queryfilter: filterManager,
timefilter: timefilter,
findIndex: this.findIndex.bind(this),
};

View file

@ -24,7 +24,7 @@ import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { getFilterGenerator } from '..';
import { FilterBarQueryFilterProvider } from '../../filter_manager/query_filter';
import { uniqFilters } from '../../../../core_plugins/data/public/filter/filter_manager/lib/uniq_filters';
import { uniqFilters } from '../../../../../plugins/data/public';
import { getPhraseScript } from '@kbn/es-query';
let queryFilter;
let filterGen;

View file

@ -18,12 +18,10 @@
*/
import { FilterStateManager } from 'plugins/data';
import { npStart } from 'ui/new_platform';
export function FilterBarQueryFilterProvider(getAppState, globalState) {
// TODO: this is imported here to avoid circular imports.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { start } = require('../../../core_plugins/data/public/legacy');
const filterManager = start.filter.filterManager;
const { filterManager } = npStart.plugins.data.query;
const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager);
const queryFilter = {};

View file

@ -39,6 +39,9 @@ export const npSetup = {
},
},
data: {
query: {
filterManager: sinon.fake(),
},
},
inspector: {
registerView: () => undefined,
@ -73,6 +76,24 @@ export const npStart = {
},
data: {
getSuggestions: sinon.fake(),
query: {
filterManager: {
getFetches$: sinon.fake(),
getFilters: sinon.fake(),
getAppFilters: sinon.fake(),
getGlobalFilters: sinon.fake(),
removeFilter: sinon.fake(),
addFilters: sinon.fake(),
setFilters: sinon.fake(),
removeAll: sinon.fake(),
getUpdates$: () => {
return {
subscribe: () => {}
};
},
},
},
},
inspector: {
isAvailable: () => false,

View file

@ -20,7 +20,7 @@
import _ from 'lodash';
import { pushFilterBarFilters } from '../push_filters';
import { onBrushEvent } from './brush_event';
import { uniqFilters } from '../../../../core_plugins/data/public';
import { uniqFilters } from '../../../../../plugins/data/public';
import { toggleFilterNegated } from '@kbn/es-query';
/**
* For terms aggregations on `__other__` buckets, this assembles a list of applicable filter

View file

@ -28,7 +28,8 @@ import { toastNotifications } from 'ui/notify';
import { AggConfigs } from 'ui/agg_types/agg_configs';
import { SearchSource } from 'ui/courier';
import { QueryFilter } from 'ui/filter_manager/query_filter';
import { TimeRange } from 'src/plugins/data/public';
import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../plugins/data/public';
import { registries } from '../../../../core_plugins/interpreter/public/registries';
import { Inspector } from '../../inspector';
import { Adapters } from '../../inspector/types';
@ -42,7 +43,7 @@ import { Vis } from '../../vis';
import { VisFiltersProvider } from '../../vis/vis_filters';
import { PipelineDataLoader } from './pipeline_data_loader';
import { visualizationLoader } from './visualization_loader';
import { onlyDisabledFiltersChanged, Query } from '../../../../core_plugins/data/public';
import { Query } from '../../../../core_plugins/data/public';
import { DataAdapter, RequestAdapter } from '../../inspector/adapters';

View file

@ -34,3 +34,5 @@ export * from './types';
export { IRequestTypesMap, IResponseTypesMap } from './search';
export * from './search';
export * from './query';

View file

@ -18,6 +18,7 @@
*/
import { Plugin } from '.';
import { searchSetupMock } from './search/mocks';
import { queryServiceMock } from './query/mocks';
export type Setup = jest.Mocked<ReturnType<Plugin['setup']>>;
export type Start = jest.Mocked<ReturnType<Plugin['start']>>;
@ -29,19 +30,23 @@ const autocompleteMock: any = {
};
const createSetupContract = (): Setup => {
const querySetupMock = queryServiceMock.createSetupContract();
const setupContract: Setup = {
autocomplete: autocompleteMock as Setup['autocomplete'],
search: searchSetupMock,
query: querySetupMock,
};
return setupContract;
};
const createStartContract = (): Start => {
const queryStartMock = queryServiceMock.createStartContract();
const startContract: Start = {
autocomplete: autocompleteMock as Start['autocomplete'],
getSuggestions: jest.fn(),
search: { search: jest.fn() },
query: queryStartMock,
};
return startContract;
};

View file

@ -18,23 +18,29 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { AutocompleteProviderRegister } from './autocomplete_provider';
import { DataPublicPluginSetup, DataPublicPluginStart } from './types';
import { SearchService } from './search/search_service';
import { AutocompleteProviderRegister } from './autocomplete_provider';
import { getSuggestionsProvider } from './suggestions_provider';
import { SearchService } from './search/search_service';
import { QueryService } from './query';
export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPublicPluginStart> {
private readonly autocomplete = new AutocompleteProviderRegister();
private readonly searchService: SearchService;
private readonly queryService: QueryService;
constructor(initializerContext: PluginInitializerContext) {
this.searchService = new SearchService(initializerContext);
this.queryService = new QueryService();
}
public setup(core: CoreSetup): DataPublicPluginSetup {
return {
autocomplete: this.autocomplete,
search: this.searchService.setup(core),
query: this.queryService.setup({
uiSettings: core.uiSettings,
}),
};
}
@ -43,6 +49,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
autocomplete: this.autocomplete,
getSuggestions: getSuggestionsProvider(core.uiSettings, core.http),
search: this.searchService.start(core),
query: this.queryService.start(),
};
}

View file

@ -22,15 +22,11 @@ import sinon from 'sinon';
import { Subscription } from 'rxjs';
import { Filter, FilterStateStore } from '@kbn/es-query';
import { FilterStateManager } from './filter_state_manager';
import { FilterManager } from './filter_manager';
import { getFilter } from './test_helpers/get_stub_filter';
import { StubState } from './test_helpers/stub_state';
import { getFiltersArray } from './test_helpers/get_filters_array';
import { coreMock } from '../../../../../../core/public/mocks';
import { coreMock } from '../../../../../core/public/mocks';
const setupMock = coreMock.createSetup();
setupMock.uiSettings.get.mockImplementation((key: string) => {
@ -38,9 +34,6 @@ setupMock.uiSettings.get.mockImplementation((key: string) => {
});
describe('filter_manager', () => {
let appStateStub: StubState;
let globalStateStub: StubState;
let updateSubscription: Subscription | undefined;
let fetchSubscription: Subscription | undefined;
let updateListener: sinon.SinonSpy<any[], any>;
@ -50,20 +43,8 @@ describe('filter_manager', () => {
beforeEach(() => {
updateListener = sinon.stub();
appStateStub = new StubState();
globalStateStub = new StubState();
filterManager = new FilterManager(setupMock.uiSettings);
readyFilters = getFiltersArray();
// FilterStateManager is tested indirectly.
// Therefore, we don't need it's instance.
new FilterStateManager(
globalStateStub,
() => {
return appStateStub;
},
filterManager
);
});
afterEach(async () => {
@ -84,32 +65,6 @@ describe('filter_manager', () => {
expect(updateSubscription).toBeInstanceOf(Subscription);
expect(fetchSubscription).toBeInstanceOf(Subscription);
});
test('should observe global state', done => {
updateSubscription = filterManager.getUpdates$().subscribe(() => {
expect(filterManager.getGlobalFilters()).toHaveLength(1);
if (updateSubscription) {
updateSubscription.unsubscribe();
}
done();
});
const f1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'age', 34);
globalStateStub.filters.push(f1);
});
test('should observe app state', done => {
updateSubscription = filterManager.getUpdates$().subscribe(() => {
expect(filterManager.getAppFilters()).toHaveLength(1);
if (updateSubscription) {
updateSubscription.unsubscribe();
}
done();
});
const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
appStateStub.filters.push(f1);
});
});
describe('get \\ set filters', () => {
@ -222,10 +177,11 @@ describe('filter_manager', () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters(f1);
expect(filterManager.getAppFilters()).toHaveLength(1);
const appFilters = filterManager.getAppFilters();
expect(appFilters).toHaveLength(1);
expect(appFilters[0]).toEqual(f1);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
expect(updateListener.callCount).toBe(1);
expect(appStateStub.filters.length).toBe(1);
});
test('app state should accept array', async () => {
@ -233,9 +189,10 @@ describe('filter_manager', () => {
const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'female');
filterManager.addFilters([f1]);
filterManager.addFilters([f2]);
expect(filterManager.getAppFilters()).toHaveLength(2);
const appFilters = filterManager.getAppFilters();
expect(appFilters).toHaveLength(2);
expect(appFilters).toEqual([f2, f1]);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
expect(appStateStub.filters.length).toBe(2);
});
test('global state should accept a single filer', async () => {
@ -243,9 +200,10 @@ describe('filter_manager', () => {
const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.addFilters(f1);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
const globalFilters = filterManager.getGlobalFilters();
expect(globalFilters).toHaveLength(1);
expect(globalFilters[0]).toEqual(f1);
expect(updateListener.callCount).toBe(1);
expect(globalStateStub.filters.length).toBe(1);
});
test('global state should be accept array', async () => {
@ -253,8 +211,9 @@ describe('filter_manager', () => {
const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'gender', 'female');
filterManager.addFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(2);
expect(globalStateStub.filters.length).toBe(2);
const globalFilters = filterManager.getGlobalFilters();
expect(globalFilters).toHaveLength(2);
expect(globalFilters).toEqual([f2, f1]);
});
test('add multiple filters at once', async () => {
@ -370,7 +329,6 @@ describe('filter_manager', () => {
filterManager.addFilters(negatedFilter);
// The negated filter should overwrite the positive one
expect(globalStateStub.filters.length).toBe(1);
expect(filterManager.getFilters()).toHaveLength(1);
expect(filterManager.getFilters()[0]).toEqual(negatedFilter);
});
@ -383,16 +341,16 @@ describe('filter_manager', () => {
filterManager.addFilters(negatedFilter);
// The negated filter should overwrite the positive one
expect(globalStateStub.filters.length).toBe(1);
expect(globalStateStub.filters[0]).toEqual(negatedFilter);
expect(filterManager.getFilters()).toHaveLength(1);
expect(filterManager.getFilters()[0]).toEqual(negatedFilter);
// Add negate: false version of the filter
const filter = _.cloneDeep(readyFilters[0]);
filter.meta.negate = false;
filterManager.addFilters(filter);
expect(globalStateStub.filters.length).toBe(1);
expect(globalStateStub.filters[0]).toEqual(filter);
expect(filterManager.getFilters()).toHaveLength(1);
expect(filterManager.getFilters()[0]).toEqual(filter);
});
test('should fire the update and fetch events', async function() {
@ -409,10 +367,6 @@ describe('filter_manager', () => {
filterManager.addFilters(readyFilters);
// updates should trigger state saves
expect(appStateStub.save.callCount).toBe(1);
expect(globalStateStub.save.callCount).toBe(1);
// this time, events should be emitted
expect(fetchStub).toBeCalledTimes(1);
expect(updateStub).toBeCalledTimes(1);
@ -420,25 +374,25 @@ describe('filter_manager', () => {
});
describe('filter reconciliation', function() {
test('should de-dupe appStateStub filters being added', async function() {
test('should de-dupe app filters being added', async function() {
const newFilter = _.cloneDeep(readyFilters[1]);
filterManager.addFilters(readyFilters, false);
expect(appStateStub.filters.length).toBe(3);
expect(filterManager.getFilters()).toHaveLength(3);
filterManager.addFilters(newFilter, false);
expect(appStateStub.filters.length).toBe(3);
expect(filterManager.getFilters()).toHaveLength(3);
});
test('should de-dupe globalStateStub filters being added', async function() {
test('should de-dupe global filters being added', async function() {
const newFilter = _.cloneDeep(readyFilters[1]);
filterManager.addFilters(readyFilters, true);
expect(globalStateStub.filters.length).toBe(3);
expect(filterManager.getFilters()).toHaveLength(3);
filterManager.addFilters(newFilter, true);
expect(globalStateStub.filters.length).toBe(3);
expect(filterManager.getFilters()).toHaveLength(3);
});
test('should de-dupe globalStateStub filters being set', async () => {
test('should de-dupe global filters being set', async () => {
const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
const f2 = _.cloneDeep(f1);
filterManager.setFilters([f1, f2]);
@ -447,7 +401,7 @@ describe('filter_manager', () => {
expect(filterManager.getFilters()).toHaveLength(1);
});
test('should de-dupe appStateStub filters being set', async () => {
test('should de-dupe app filters being set', async () => {
const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
const f2 = _.cloneDeep(f1);
filterManager.setFilters([f1, f2]);
@ -475,7 +429,7 @@ describe('filter_manager', () => {
});
});
test('should merge conflicting appStateStub filters', async function() {
test('should merge conflicting app filters', async function() {
filterManager.addFilters(readyFilters, true);
const appFilter = _.cloneDeep(readyFilters[1]);
appFilter.meta.negate = true;
@ -580,16 +534,16 @@ describe('filter_manager', () => {
test('should remove the filter from appStateStub', async function() {
filterManager.addFilters(readyFilters, false);
expect(appStateStub.filters).toHaveLength(3);
expect(filterManager.getAppFilters()).toHaveLength(3);
filterManager.removeFilter(readyFilters[0]);
expect(appStateStub.filters).toHaveLength(2);
expect(filterManager.getAppFilters()).toHaveLength(2);
});
test('should remove the filter from globalStateStub', async function() {
filterManager.addFilters(readyFilters, true);
expect(globalStateStub.filters).toHaveLength(3);
expect(filterManager.getGlobalFilters()).toHaveLength(3);
filterManager.removeFilter(readyFilters[0]);
expect(globalStateStub.filters).toHaveLength(2);
expect(filterManager.getGlobalFilters()).toHaveLength(2);
});
test('should fire the update and fetch events', async function() {
@ -619,8 +573,8 @@ describe('filter_manager', () => {
filterManager.removeFilter(readyFilters[0]);
expect(globalStateStub.filters).toHaveLength(1);
expect(appStateStub.filters).toHaveLength(1);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
});
test('should remove matching filters by comparison', async function() {
@ -629,12 +583,12 @@ describe('filter_manager', () => {
filterManager.removeFilter(_.cloneDeep(readyFilters[0]));
expect(globalStateStub.filters).toHaveLength(1);
expect(appStateStub.filters).toHaveLength(1);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
filterManager.removeFilter(_.cloneDeep(readyFilters[2]));
expect(globalStateStub.filters).toHaveLength(1);
expect(appStateStub.filters).toHaveLength(0);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
});
test('should do nothing with a non-matching filter', async function() {
@ -645,19 +599,19 @@ describe('filter_manager', () => {
missedFilter.meta.negate = !readyFilters[0].meta.negate;
filterManager.removeFilter(missedFilter);
expect(globalStateStub.filters).toHaveLength(2);
expect(appStateStub.filters).toHaveLength(1);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(2);
});
test('should remove all the filters from both states', async function() {
filterManager.addFilters([readyFilters[0], readyFilters[1]], true);
filterManager.addFilters([readyFilters[2]], false);
expect(globalStateStub.filters).toHaveLength(2);
expect(appStateStub.filters).toHaveLength(1);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(2);
filterManager.removeAll();
expect(globalStateStub.filters).toHaveLength(0);
expect(appStateStub.filters).toHaveLength(0);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
});
});

View file

@ -28,7 +28,7 @@ import { compareFilters } from './lib/compare_filters';
import { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
import { uniqFilters } from './lib/uniq_filters';
import { onlyDisabledFiltersChanged } from './lib/only_disabled';
import { PartitionedFilters } from './partitioned_filters';
import { PartitionedFilters } from './types';
export class FilterManager {
private filters: Filter[] = [];

View file

@ -0,0 +1,24 @@
/*
* 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.
*/
export { FilterManager } from './filter_manager';
export { uniqFilters } from './lib/uniq_filters';
export { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
export { onlyDisabledFiltersChanged } from './lib/only_disabled';

View file

@ -20,16 +20,16 @@
import { Filter } from '@kbn/es-query';
import { reduceRight } from 'lodash';
import { mapMatchAll } from './map_match_all';
import { mapPhrase } from './map_phrase';
import { mapPhrases } from './map_phrases';
import { mapRange } from './map_range';
import { mapExists } from './map_exists';
import { mapMissing } from './map_missing';
import { mapQueryString } from './map_query_string';
import { mapGeoBoundingBox } from './map_geo_bounding_box';
import { mapGeoPolygon } from './map_geo_polygon';
import { mapDefault } from './map_default';
import { mapMatchAll } from './mappers/map_match_all';
import { mapPhrase } from './mappers/map_phrase';
import { mapPhrases } from './mappers/map_phrases';
import { mapRange } from './mappers/map_range';
import { mapExists } from './mappers/map_exists';
import { mapMissing } from './mappers/map_missing';
import { mapQueryString } from './mappers/map_query_string';
import { mapGeoBoundingBox } from './mappers/map_geo_bounding_box';
import { mapGeoPolygon } from './mappers/map_geo_polygon';
import { mapDefault } from './mappers/map_default';
import { generateMappingChain } from './generate_mapping_chain';
export function mapFilter(filter: Filter) {

View file

@ -0,0 +1,45 @@
/*
* 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 { Filter, FilterStateStore } from '@kbn/es-query';
export function getFilter(
store: FilterStateStore,
disabled: boolean,
negated: boolean,
queryKey: string,
queryValue: any
): Filter {
return {
$state: {
store,
},
meta: {
index: 'logstash-*',
disabled,
negate: negated,
alias: null,
},
query: {
match: {
[queryKey]: queryValue,
},
},
};
}

View file

@ -17,12 +17,6 @@
* under the License.
*/
export class StubIndexPatterns {
async get(index: string) {
return {
fields: {
getByName: () => undefined,
},
};
}
}
export * from './query_service';
export * from './filter_manager';

View file

@ -17,12 +17,12 @@
* under the License.
*/
import { FilterService, FilterStart, FilterSetup } from '.';
import { QueryService, QueryStart, QuerySetup } from '.';
type FilterServiceClientContract = PublicMethodsOf<FilterService>;
type QueryServiceClientContract = PublicMethodsOf<QueryService>;
const createSetupContractMock = () => {
const setupContract: jest.Mocked<FilterSetup> = {
const setupContract: jest.Mocked<QuerySetup> = {
filterManager: jest.fn() as any,
};
@ -30,7 +30,7 @@ const createSetupContractMock = () => {
};
const createStartContractMock = () => {
const startContract: jest.Mocked<FilterStart> = {
const startContract: jest.Mocked<QueryStart> = {
filterManager: jest.fn() as any,
};
@ -38,7 +38,7 @@ const createStartContractMock = () => {
};
const createMock = () => {
const mocked: jest.Mocked<FilterServiceClientContract> = {
const mocked: jest.Mocked<QueryServiceClientContract> = {
setup: jest.fn(),
start: jest.fn(),
stop: jest.fn(),
@ -49,7 +49,7 @@ const createMock = () => {
return mocked;
};
export const filterServiceMock = {
export const queryServiceMock = {
create: createMock,
createSetupContract: createSetupContractMock,
createStartContract: createStartContractMock,

View file

@ -21,18 +21,18 @@ import { UiSettingsClientContract } from 'src/core/public';
import { FilterManager } from './filter_manager';
/**
* Filter Service
* Query Service
* @internal
*/
export interface FilterServiceDependencies {
export interface QueryServiceDependencies {
uiSettings: UiSettingsClientContract;
}
export class FilterService {
export class QueryService {
filterManager!: FilterManager;
public setup({ uiSettings }: FilterServiceDependencies) {
public setup({ uiSettings }: QueryServiceDependencies) {
this.filterManager = new FilterManager(uiSettings);
return {
@ -52,5 +52,5 @@ export class FilterService {
}
/** @public */
export type FilterSetup = ReturnType<FilterService['setup']>;
export type FilterStart = ReturnType<FilterService['start']>;
export type QuerySetup = ReturnType<QueryService['setup']>;
export type QueryStart = ReturnType<QueryService['start']>;

View file

@ -22,15 +22,18 @@ export * from './autocomplete_provider/types';
import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.';
import { ISearchSetup, ISearchStart } from './search';
import { IGetSuggestions } from './suggestions_provider/types';
import { QuerySetup, QueryStart } from './query';
export interface DataPublicPluginSetup {
autocomplete: AutocompletePublicPluginSetup;
search: ISearchSetup;
query: QuerySetup;
}
export interface DataPublicPluginStart {
autocomplete: AutocompletePublicPluginStart;
getSuggestions: IGetSuggestions;
search: ISearchStart;
query: QueryStart;
}
export { IGetSuggestions } from './suggestions_provider/types';

View file

@ -97,6 +97,11 @@ describe('Lens App', () => {
},
},
},
data: {
query: {
filterManager: createMockFilterManager(),
},
},
dataShim: {
indexPatterns: {
indexPatterns: {
@ -106,9 +111,6 @@ describe('Lens App', () => {
},
},
timefilter: { history: {} },
filter: {
filterManager: createMockFilterManager(),
},
},
store: {
get: jest.fn(),
@ -592,7 +594,7 @@ describe('Lens App', () => {
const instance = mount(<App {...args} />);
args.dataShim.filter.filterManager.setFilters([
args.data.query.filterManager.setFilters([
buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
]);
@ -723,7 +725,7 @@ describe('Lens App', () => {
query: { query: 'new', language: 'lucene' },
});
args.dataShim.filter.filterManager.setFilters([
args.data.query.filterManager.setFilters([
buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
]);
instance.update();

View file

@ -82,10 +82,9 @@ export function App({
const { lastKnownDoc } = state;
useEffect(() => {
const subscription = dataShim.filter.filterManager.getUpdates$().subscribe({
const subscription = data.query.filterManager.getUpdates$().subscribe({
next: () => {
setState(s => ({ ...s, filters: dataShim.filter.filterManager.getFilters() }));
setState(s => ({ ...s, filters: data.query.filterManager.getFilters() }));
trackUiEvent('app_filters_updated');
},
});
@ -227,9 +226,7 @@ export function App({
setState(s => ({ ...s, savedQuery }));
}}
onSavedQueryUpdated={savedQuery => {
dataShim.filter.filterManager.setFilters(
savedQuery.attributes.filters || state.filters
);
data.query.filterManager.setFilters(savedQuery.attributes.filters || state.filters);
setState(s => ({
...s,
savedQuery: { ...savedQuery }, // Shallow query for reference issues
@ -242,7 +239,7 @@ export function App({
}));
}}
onClearSavedQuery={() => {
dataShim.filter.filterManager.removeAll();
data.query.filterManager.removeAll();
setState(s => ({
...s,
savedQuery: undefined,

View file

@ -54,6 +54,7 @@ import {
} from '../../common/constants';
import { FilterStateStore } from '@kbn/es-query';
import { start as data } from '../../../../../../src/legacy/core_plugins/data/public/legacy';
import { npStart } from 'ui/new_platform';
const { savedQueryService } = data.search.services;
@ -62,7 +63,7 @@ const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-maps-root';
const app = uiModules.get(MAP_APP_PATH, []);
app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppState, globalState) => {
const { filterManager } = npStart.plugins.data.query;
const savedMap = $route.current.locals.map;
let unsubscribe;
let initialLayerListConfig;
@ -98,7 +99,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
$scope.$evalAsync(() => {
// appState
$state.query = $scope.query;
$state.filters = data.filter.filterManager.getAppFilters();
$state.filters = filterManager.getAppFilters();
$state.save();
// globalState
@ -107,7 +108,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
pause: $scope.refreshConfig.isPaused,
value: $scope.refreshConfig.interval,
};
globalState.filters = data.filter.filterManager.getGlobalFilters();
globalState.filters = filterManager.getGlobalFilters();
globalState.save();
});
}
@ -198,8 +199,8 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
/* End of Saved Queries */
async function onQueryChange({ filters, query, time }) {
if (filters) {
await data.filter.filterManager.setFilters(filters); // Maps and merges filters
$scope.filters = data.filter.filterManager.getFilters();
filterManager.setFilters(filters); // Maps and merges filters
$scope.filters = filterManager.getFilters();
}
if (query) {
$scope.query = query;

View file

@ -11,7 +11,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import 'mapbox-gl/dist/mapbox-gl.css';
import { Embeddable, APPLY_FILTER_TRIGGER } from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { onlyDisabledFiltersChanged } from '../../../../../../src/legacy/core_plugins/data/public';
import { onlyDisabledFiltersChanged } from '../../../../../../src/plugins/data/public';
import { I18nContext } from 'ui/i18n';

View file

@ -17,6 +17,7 @@ import { TimeRange, Query } from 'src/plugins/data/common/types';
import { SavedQuery } from 'src/legacy/core_plugins/data/public';
import { OnTimeChangeProps } from '@elastic/eui';
import { npStart } from 'ui/new_platform';
import { start as data } from '../../../../../../../src/legacy/core_plugins/data/public/legacy';
import { inputsActions } from '../../store/inputs';
@ -39,12 +40,11 @@ import { timelineActions, hostsActions, networkActions } from '../../store/actio
const {
ui: { SearchBar },
filter,
search,
timefilter,
} = data;
export const siemFilterManager = filter.filterManager;
export const siemFilterManager = npStart.plugins.data.query.filterManager;
export const savedQueryService = search.services.savedQueryService;
interface SiemSearchBarRedux {