diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx index 90dec12fb814d..066adb1e3275e 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx @@ -31,12 +31,13 @@ import { import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import classNames from 'classnames'; import React, { useState } from 'react'; -import { UiSettingsClientContract } from 'src/core/public'; +import { CoreStart } from 'src/core/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { IndexPattern } from '../../index_patterns'; import { FilterEditor } from './filter_editor'; import { FilterItem } from './filter_item'; import { FilterOptions } from './filter_options'; -import { useKibana } from '../../../../../../plugins/kibana_react/public'; +import { useKibana, KibanaContextProvider } from '../../../../../../plugins/kibana_react/public'; interface Props { filters: Filter[]; @@ -45,18 +46,45 @@ interface Props { indexPatterns: IndexPattern[]; intl: InjectedIntl; - // Only for directives! - uiSettings?: UiSettingsClientContract; + // TODO: Only for filter-bar directive! + uiSettings?: CoreStart['uiSettings']; + docLinks?: CoreStart['docLinks']; + pluginDataStart?: DataPublicPluginStart; } function FilterBarUI(props: Props) { const [isAddFilterPopoverOpen, setIsAddFilterPopoverOpen] = useState(false); const kibana = useKibana(); - let { uiSettings } = kibana.services; - if (!uiSettings) { - // Only for directives! - uiSettings = props.uiSettings; + const uiSettings = kibana.services.uiSettings || props.uiSettings; + if (!uiSettings) return null; + + function hasContext() { + return Boolean(kibana.services.uiSettings); + } + + function wrapInContextIfMissing(content: JSX.Element) { + // TODO: Relevant only as long as directives are used! + if (!hasContext()) { + if (props.docLinks && props.uiSettings && props.pluginDataStart) { + return ( + + {content} + + ); + } else { + throw new Error( + 'Rending filter bar requires providing sufficient context: uiSettings, docLinks and NP data plugin' + ); + } + } + return content; } function onFiltersUpdated(filters: Filter[]) { @@ -100,7 +128,7 @@ function FilterBarUI(props: Props) { ); - return ( + return wrapInContextIfMissing( setIsAddFilterPopoverOpen(false)} key={JSON.stringify(newFilter)} - uiSettings={uiSettings!} /> diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/index.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/index.tsx index 64487df5b22d4..5b295a759d694 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/index.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/index.tsx @@ -36,7 +36,6 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import { get } from 'lodash'; import React, { Component } from 'react'; -import { UiSettingsClientContract } from 'src/core/public'; import { Field, IndexPattern } from '../../../index_patterns'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; import { @@ -62,7 +61,6 @@ interface Props { onSubmit: (filter: Filter) => void; onCancel: () => void; intl: InjectedIntl; - uiSettings: UiSettingsClientContract; } interface State { @@ -343,7 +341,6 @@ class FilterEditorUI extends Component { value={this.state.params} onChange={this.onParamsChange} data-test-subj="phraseValueInput" - uiSettings={this.props.uiSettings} /> ); case 'phrases': @@ -353,7 +350,6 @@ class FilterEditorUI extends Component { field={this.state.selectedField} values={this.state.params} onChange={this.onParamsChange} - uiSettings={this.props.uiSettings} /> ); case 'range': diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx index 6b262c66402f2..9ef5f546c0be0 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx @@ -18,14 +18,17 @@ */ import { Component } from 'react'; -import { getSuggestions } from 'ui/value_suggestions'; -import { UiSettingsClientContract } from 'src/core/public'; import { Field, IndexPattern } from '../../../index_patterns'; +import { + withKibana, + KibanaReactContextValue, +} from '../../../../../../../plugins/kibana_react/public'; +import { IDataPluginServices } from '../../../types'; export interface PhraseSuggestorProps { + kibana: KibanaReactContextValue; indexPattern: IndexPattern; field?: Field; - uiSettings: UiSettingsClientContract; } export interface PhraseSuggestorState { @@ -38,10 +41,11 @@ export interface PhraseSuggestorState { * aggregatable), we pull out the common logic for requesting suggestions into this component * which both of them extend. */ -export class PhraseSuggestor extends Component< +export class PhraseSuggestorUI extends Component< T, PhraseSuggestorState > { + private services = this.props.kibana.services; public state: PhraseSuggestorState = { suggestions: [], isLoading: false, @@ -52,7 +56,7 @@ export class PhraseSuggestor extends Component< } protected isSuggestingValues() { - const shouldSuggestValues = this.props.uiSettings.get('filterEditor:suggestValues'); + const shouldSuggestValues = this.services.uiSettings.get('filterEditor:suggestValues'); const { field } = this.props; return shouldSuggestValues && field && field.aggregatable && field.type === 'string'; } @@ -67,7 +71,9 @@ export class PhraseSuggestor extends Component< return; } this.setState({ isLoading: true }); - const suggestions = await getSuggestions(indexPattern.title, field, value); + const suggestions = await this.services.data.getSuggestions(indexPattern.title, field, value); this.setState({ suggestions, isLoading: false }); } } + +export const PhraseSuggestor = withKibana(PhraseSuggestorUI); diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx index 0696bacc568b5..7ef51f88ba57e 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx @@ -22,8 +22,9 @@ import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; import { uniq } from 'lodash'; import React from 'react'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; -import { PhraseSuggestor, PhraseSuggestorProps } from './phrase_suggestor'; +import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor'; import { ValueInputType } from './value_input_type'; +import { withKibana } from '../../../../../../../plugins/kibana_react/public'; interface Props extends PhraseSuggestorProps { value?: string; @@ -31,7 +32,7 @@ interface Props extends PhraseSuggestorProps { intl: InjectedIntl; } -class PhraseValueInputUI extends PhraseSuggestor { +class PhraseValueInputUI extends PhraseSuggestorUI { public render() { return ( ) { return GenericComboBox(props); } -export const PhraseValueInput = injectI18n(PhraseValueInputUI); +export const PhraseValueInput = injectI18n(withKibana(PhraseValueInputUI)); diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrases_values_input.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrases_values_input.tsx index d35e49b6b07ce..f3b30e2ad5fd9 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrases_values_input.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrases_values_input.tsx @@ -22,7 +22,8 @@ import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; import { uniq } from 'lodash'; import React from 'react'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; -import { PhraseSuggestor, PhraseSuggestorProps } from './phrase_suggestor'; +import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor'; +import { withKibana } from '../../../../../../../plugins/kibana_react/public'; interface Props extends PhraseSuggestorProps { values?: string[]; @@ -30,7 +31,7 @@ interface Props extends PhraseSuggestorProps { intl: InjectedIntl; } -class PhrasesValuesInputUI extends PhraseSuggestor { +class PhrasesValuesInputUI extends PhraseSuggestorUI { public render() { const { suggestions } = this.state; const { values, intl, onChange } = this.props; @@ -64,4 +65,4 @@ function StringComboBox(props: GenericComboBoxProps) { return GenericComboBox(props); } -export const PhrasesValuesInput = injectI18n(PhrasesValuesInputUI); +export const PhrasesValuesInput = injectI18n(withKibana(PhrasesValuesInputUI)); diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx index 250f6ad209fa7..21259cec51d3a 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx @@ -171,7 +171,6 @@ class FilterItemUI extends Component { indexPatterns={this.props.indexPatterns} onSubmit={this.onSubmit} onCancel={this.closePopover} - uiSettings={this.props.uiSettings} /> ), diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index b487651175d47..7f2c92cb5c6fe 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -127,10 +127,10 @@ export class DataPlugin public start(core: CoreStart, { __LEGACY, data }: DataPluginStartDependencies) { const SearchBar = createSearchBar({ core, + data, store: __LEGACY.storage, timefilter: this.setupApi.timefilter, filterManager: this.setupApi.filter.filterManager, - autocomplete: data.autocomplete, }); return { diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx index 685a793b4de3d..1b232128c744a 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx @@ -134,8 +134,8 @@ export class QueryBarInputUI extends Component { const queryString = this.getQueryString(); const recentSearchSuggestions = this.getRecentSearchSuggestions(queryString); + const autocompleteProvider = this.services.data.autocomplete.getProvider(language); - const autocompleteProvider = this.services.autocomplete.getProvider(language); if ( !autocompleteProvider || !Array.isArray(this.state.indexPatterns) || diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx index bf40cb8e7e0b6..c84e460a1556c 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { Filter } from '@kbn/es-query'; import { CoreStart } from 'src/core/public'; -import { AutocompletePublicPluginStart } from 'src/plugins/data/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { Storage } from '../../../types'; import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public'; import { TimefilterSetup } from '../../../timefilter'; @@ -29,10 +29,10 @@ import { SearchBarOwnProps } from '.'; interface StatefulSearchBarDeps { core: CoreStart; + data: DataPublicPluginStart; store: Storage; timefilter: TimefilterSetup; filterManager: FilterManager; - autocomplete: AutocompletePublicPluginStart; } export type StatetfulSearchBarProps = SearchBarOwnProps & { @@ -59,7 +59,7 @@ export function createSearchBar({ store, timefilter, filterManager, - autocomplete, + 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. @@ -71,7 +71,7 @@ export function createSearchBar({ void; // Query bar - should be in SearchBarInjectedDeps query?: Query; // Show when user has privileges to save diff --git a/src/legacy/core_plugins/data/public/shim/legacy_module.ts b/src/legacy/core_plugins/data/public/shim/legacy_module.ts index 4e81a5d4294e6..fea9409b2ec68 100644 --- a/src/legacy/core_plugins/data/public/shim/legacy_module.ts +++ b/src/legacy/core_plugins/data/public/shim/legacy_module.ts @@ -24,7 +24,7 @@ import { Filter } from '@kbn/es-query'; // @ts-ignore import { uiModules } from 'ui/modules'; -import { npSetup, npStart } from 'ui/new_platform'; +import { npStart } from 'ui/new_platform'; import { FilterBar, ApplyFiltersPopover } from '../filter'; import template from './apply_filter_directive.html'; @@ -49,14 +49,16 @@ export const initLegacyModule = once((): void => { } child.setAttribute('ui-settings', 'uiSettings'); - child.setAttribute('http', 'http'); + child.setAttribute('doc-links', 'docLinks'); + child.setAttribute('plugin-data-start', 'pluginDataStart'); // Append helper directive elem.append(child); const linkFn = ($scope: any) => { - $scope.uiSettings = npSetup.core.uiSettings; - $scope.http = npSetup.core.http; + $scope.uiSettings = npStart.core.uiSettings; + $scope.docLinks = npStart.core.docLinks; + $scope.pluginDataStart = npStart.plugins.data; }; return linkFn; @@ -66,11 +68,12 @@ export const initLegacyModule = once((): void => { .directive('filterBarHelper', (reactDirective: any) => { return reactDirective(wrapInI18nContext(FilterBar), [ ['uiSettings', { watchDepth: 'reference' }], - ['http', { watchDepth: 'reference' }], + ['docLinks', { watchDepth: 'reference' }], ['onFiltersUpdated', { watchDepth: 'reference' }], ['indexPatterns', { watchDepth: 'collection' }], ['filters', { watchDepth: 'collection' }], ['className', { watchDepth: 'reference' }], + ['pluginDataStart', { watchDepth: 'reference' }], ]); }) .directive('applyFiltersPopoverComponent', (reactDirective: any) => diff --git a/src/legacy/core_plugins/data/public/types.ts b/src/legacy/core_plugins/data/public/types.ts index 0ef7e483dd63f..2c02a9b764755 100644 --- a/src/legacy/core_plugins/data/public/types.ts +++ b/src/legacy/core_plugins/data/public/types.ts @@ -18,7 +18,7 @@ */ import { UiSettingsClientContract, CoreStart } from 'src/core/public'; -import { AutocompletePublicPluginStart } from 'src/plugins/data/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; export interface Storage { get: (key: string) => any; @@ -34,5 +34,5 @@ export interface IDataPluginServices extends Partial { notifications: CoreStart['notifications']; http: CoreStart['http']; store: Storage; - autocomplete: AutocompletePublicPluginStart; + data: DataPublicPluginStart; } diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js index 389a84babae87..3497a35f5c99d 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js @@ -170,7 +170,7 @@ export class VisEditor extends Component { services={{ appName: APP_NAME, store: localStorage, - autocomplete: npStart.plugins.data.autocomplete, + data: npStart.plugins.data, ...npStart.core, }} > diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 29868dc9767dc..bbfa8bd329c65 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -65,7 +65,9 @@ export const npStart = { registerRenderer: sinon.fake(), registerType: sinon.fake(), }, - data: {}, + data: { + getSuggestions: sinon.fake(), + }, inspector: { isAvailable: () => false, open: () => ({ diff --git a/src/legacy/ui/public/vis/editors/default/controls/filter.tsx b/src/legacy/ui/public/vis/editors/default/controls/filter.tsx index cceaf86b5d85c..2c0a2b6be37f8 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/filter.tsx +++ b/src/legacy/ui/public/vis/editors/default/controls/filter.tsx @@ -95,7 +95,7 @@ function FilterRow({ services={{ appName: 'filtersAgg', store: localStorage, - autocomplete: npStart.plugins.data.autocomplete, + data: npStart.plugins.data, ...npStart.core, }} > diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index df5b68ac409a0..b2d311912b982 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -38,6 +38,7 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { const startContract: Start = { autocomplete: autocompleteMock as Start['autocomplete'], + getSuggestions: jest.fn(), }; return startContract; }; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index eb31647767360..a3fa8005560ae 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -20,6 +20,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; import { AutocompleteProviderRegister } from './autocomplete_provider'; import { DataPublicPluginSetup, DataPublicPluginStart } from './types'; +import { getSuggestionsProvider } from './suggestions_provider'; export class DataPublicPlugin implements Plugin { private readonly autocomplete = new AutocompleteProviderRegister(); @@ -35,6 +36,7 @@ export class DataPublicPlugin implements Plugin any; diff --git a/src/legacy/ui/public/value_suggestions/value_suggestions.test.ts b/src/plugins/data/public/suggestions_provider/value_suggestions.test.ts similarity index 83% rename from src/legacy/ui/public/value_suggestions/value_suggestions.test.ts rename to src/plugins/data/public/suggestions_provider/value_suggestions.test.ts index d6d0a7dc003e6..13ccbbd9f3dde 100644 --- a/src/legacy/ui/public/value_suggestions/value_suggestions.test.ts +++ b/src/plugins/data/public/suggestions_provider/value_suggestions.test.ts @@ -17,21 +17,23 @@ * under the License. */ +// TODO: remove when index patterns are moved here. jest.mock('ui/new_platform'); jest.mock('ui/index_patterns'); import { mockFields, mockIndexPattern } from 'ui/index_patterns'; import { getSuggestionsProvider } from './value_suggestions'; +import { UiSettingsClientContract } from 'kibana/public'; describe('getSuggestions', () => { let getSuggestions: any; - let fetch: any; + let http: any; describe('with value suggestions disabled', () => { beforeEach(() => { - const config = { get: () => false }; - fetch = jest.fn(); - getSuggestions = getSuggestionsProvider(config, fetch); + const config = { get: (key: string) => false } as UiSettingsClientContract; + http = { fetch: jest.fn() }; + getSuggestions = getSuggestionsProvider(config, http); }); it('should return an empty array', async () => { @@ -40,15 +42,15 @@ describe('getSuggestions', () => { const query = ''; const suggestions = await getSuggestions(index, field, query); expect(suggestions).toEqual([]); - expect(fetch).not.toHaveBeenCalled(); + expect(http.fetch).not.toHaveBeenCalled(); }); }); describe('with value suggestions enabled', () => { beforeEach(() => { - const config = { get: () => true }; - fetch = jest.fn(); - getSuggestions = getSuggestionsProvider(config, fetch); + const config = { get: (key: string) => true } as UiSettingsClientContract; + http = { fetch: jest.fn() }; + getSuggestions = getSuggestionsProvider(config, http); }); it('should return true/false for boolean fields', async () => { @@ -57,7 +59,7 @@ describe('getSuggestions', () => { const query = ''; const suggestions = await getSuggestions(index, field, query); expect(suggestions).toEqual([true, false]); - expect(fetch).not.toHaveBeenCalled(); + expect(http.fetch).not.toHaveBeenCalled(); }); it('should return an empty array if the field type is not a string or boolean', async () => { @@ -66,7 +68,7 @@ describe('getSuggestions', () => { const query = ''; const suggestions = await getSuggestions(index, field, query); expect(suggestions).toEqual([]); - expect(fetch).not.toHaveBeenCalled(); + expect(http.fetch).not.toHaveBeenCalled(); }); it('should return an empty array if the field is not aggregatable', async () => { @@ -75,7 +77,7 @@ describe('getSuggestions', () => { const query = ''; const suggestions = await getSuggestions(index, field, query); expect(suggestions).toEqual([]); - expect(fetch).not.toHaveBeenCalled(); + expect(http.fetch).not.toHaveBeenCalled(); }); it('should otherwise request suggestions', async () => { @@ -85,7 +87,7 @@ describe('getSuggestions', () => { ); const query = ''; await getSuggestions(index, field, query); - expect(fetch).toHaveBeenCalled(); + expect(http.fetch).toHaveBeenCalled(); }); it('should cache results if using the same index/field/query/filter', async () => { @@ -96,7 +98,7 @@ describe('getSuggestions', () => { const query = ''; await getSuggestions(index, field, query); await getSuggestions(index, field, query); - expect(fetch).toHaveBeenCalledTimes(1); + expect(http.fetch).toHaveBeenCalledTimes(1); }); it('should cache results for only one minute', async () => { @@ -113,7 +115,7 @@ describe('getSuggestions', () => { await getSuggestions(index, field, query); Date.now = now; - expect(fetch).toHaveBeenCalledTimes(2); + expect(http.fetch).toHaveBeenCalledTimes(2); }); it('should not cache results if using a different index/field/query', async () => { @@ -128,7 +130,7 @@ describe('getSuggestions', () => { await getSuggestions('logstash-*', fields[0], 'query'); await getSuggestions('logstash-*', fields[1], ''); await getSuggestions('logstash-*', fields[1], 'query'); - expect(fetch).toHaveBeenCalledTimes(8); + expect(http.fetch).toHaveBeenCalledTimes(8); }); }); }); diff --git a/src/legacy/ui/public/value_suggestions/value_suggestions.ts b/src/plugins/data/public/suggestions_provider/value_suggestions.ts similarity index 82% rename from src/legacy/ui/public/value_suggestions/value_suggestions.ts rename to src/plugins/data/public/suggestions_provider/value_suggestions.ts index 31e42e9945ede..03eaa5d9594d2 100644 --- a/src/legacy/ui/public/value_suggestions/value_suggestions.ts +++ b/src/plugins/data/public/suggestions_provider/value_suggestions.ts @@ -18,16 +18,17 @@ */ import { memoize } from 'lodash'; -import { Field } from 'ui/index_patterns'; + +import { UiSettingsClientContract, HttpServiceBase } from 'src/core/public'; +import { IGetSuggestions, Field } from './types'; export function getSuggestionsProvider( - config: { get: (key: string) => any }, - fetch: (...options: any[]) => any -) { + uiSettings: UiSettingsClientContract, + http: HttpServiceBase +): IGetSuggestions { const requestSuggestions = memoize( (index: string, field: Field, query: string, boolFilter: any = []) => { - return fetch({ - pathname: `/api/kibana/suggestions/values/${index}`, + return http.fetch(`/api/kibana/suggestions/values/${index}`, { method: 'POST', body: JSON.stringify({ query, field: field.name, boolFilter }), }); @@ -36,7 +37,7 @@ export function getSuggestionsProvider( ); return async (index: string, field: Field, query: string, boolFilter?: any) => { - const shouldSuggestValues = config.get('filterEditor:suggestValues'); + const shouldSuggestValues = uiSettings.get('filterEditor:suggestValues'); if (field.type === 'boolean') { return [true, false]; } else if (!shouldSuggestValues || !field.aggregatable || field.type !== 'string') { diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 23308304b8ff8..70406b4dc0c0a 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -20,10 +20,14 @@ export * from './autocomplete_provider/types'; import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.'; +import { IGetSuggestions } from './suggestions_provider/types'; export interface DataPublicPluginSetup { autocomplete: AutocompletePublicPluginSetup; } export interface DataPublicPluginStart { autocomplete: AutocompletePublicPluginStart; + getSuggestions: IGetSuggestions; } + +export { IGetSuggestions } from './suggestions_provider/types'; diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html index 9e9356f30642e..e291271bb1d6c 100644 --- a/x-pack/legacy/plugins/graph/public/angular/templates/index.html +++ b/x-pack/legacy/plugins/graph/public/angular/templates/index.html @@ -17,7 +17,7 @@ is-initialized="workspaceInitialized || savedWorkspace.id" initial-query="initialQuery" on-fill-workspace="fillWorkspace" - autocomplete-start="autocompleteStart" + plugin-data-start="pluginDataStart" core-start="coreStart" store="store" > diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 2cd3e13013d9a..4e33d0995cbc8 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -106,9 +106,10 @@ app.directive('graphApp', function (reactDirective) { ['onQuerySubmit', { watchDepth: 'reference' }], ['initialQuery', { watchDepth: 'reference' }], ['confirmWipeWorkspace', { watchDepth: 'reference' }], - ['autocompleteStart', { watchDepth: 'reference' }], ['coreStart', { watchDepth: 'reference' }], - ['reduxStore', { watchDepth: 'reference' }] + ['pluginDataStart', { watchDepth: 'reference' }], + ['store', { watchDepth: 'reference' }], + ['reduxStore', { watchDepth: 'reference' }], ]); }); @@ -321,9 +322,9 @@ app.controller('graphuiPlugin', function ( chrome, }); + $scope.pluginDataStart = npStart.plugins.data; $scope.store = new Storage(window.localStorage); $scope.coreStart = npStart.core; - $scope.autocompleteStart = npStart.plugins.data.autocomplete; $scope.loading = false; $scope.spymode = 'request'; diff --git a/x-pack/legacy/plugins/graph/public/components/app.tsx b/x-pack/legacy/plugins/graph/public/components/app.tsx index efc8c1bfcc00a..56b1c9563bece 100644 --- a/x-pack/legacy/plugins/graph/public/components/app.tsx +++ b/x-pack/legacy/plugins/graph/public/components/app.tsx @@ -5,12 +5,13 @@ */ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { Provider } from 'react-redux'; import React, { useState } from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import { Storage } from 'ui/storage'; import { CoreStart } from 'kibana/public'; -import { AutocompletePublicPluginStart } from 'src/plugins/data/public'; import { FieldManager } from './field_manager'; import { SearchBarProps, SearchBar } from './search_bar'; import { GraphStore } from '../state_management'; @@ -20,7 +21,8 @@ import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_reac export interface GraphAppProps extends SearchBarProps { coreStart: CoreStart; - autocompleteStart: AutocompletePublicPluginStart; + // This is not named dataStart because of Angular treating data- prefix differently + pluginDataStart: DataPublicPluginStart; store: Storage; reduxStore: GraphStore; isInitialized: boolean; @@ -29,16 +31,16 @@ export interface GraphAppProps extends SearchBarProps { export function GraphApp(props: GraphAppProps) { const [pickerOpen, setPickerOpen] = useState(false); - const { coreStart, autocompleteStart, store, reduxStore, ...searchBarProps } = props; + const { coreStart, pluginDataStart, store, reduxStore, ...searchBarProps } = props; return ( diff --git a/x-pack/legacy/plugins/graph/public/components/search_bar.test.tsx b/x-pack/legacy/plugins/graph/public/components/search_bar.test.tsx index 760b2aba5ba16..6dfa6b9796e52 100644 --- a/x-pack/legacy/plugins/graph/public/components/search_bar.test.tsx +++ b/x-pack/legacy/plugins/graph/public/components/search_bar.test.tsx @@ -17,6 +17,7 @@ import { I18nProvider } from '@kbn/i18n/react'; jest.mock('ui/new_platform'); import { openSourceModal } from '../services/source_modal'; + import { GraphStore, setDatasource } from '../state_management'; import { ReactWrapper } from 'enzyme'; import { createMockGraphStore } from '../state_management/mocks'; @@ -82,6 +83,7 @@ describe('search_bar', () => { function mountSearchBar() { jest.clearAllMocks(); const wrappedSearchBar = wrapSearchBarInContext({ ...defaultProps }); + instance = mountWithIntl({wrappedSearchBar}); } diff --git a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx index ae0d32cd5f686..11e5d353cadaf 100644 --- a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx @@ -18,6 +18,7 @@ import { IndexPattern, } from '../../../../../../src/legacy/core_plugins/data/public'; import { openSourceModal } from '../services/source_modal'; + import { GraphState, datasourceSelector, @@ -31,6 +32,7 @@ export interface OuterSearchBarProps { isLoading: boolean; initialQuery?: string; onQuerySubmit: (query: string) => void; + confirmWipeWorkspace: (onConfirm: () => void) => void; indexPatternProvider: IndexPatternProvider; } diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js deleted file mode 100644 index 8524b1c890f5f..0000000000000 --- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import fetchMock from 'fetch-mock'; -import { getSuggestionsProvider } from '../value'; -import indexPatternResponse from '../__fixtures__/index_pattern_response.json'; - -describe('Kuery value suggestions', function () { - let config; - let indexPatterns; - let getSuggestions; - - const mockValues = ['foo', 'bar']; - const fetchUrlMatcher = /\/api\/kibana\/suggestions\/values\/*/; - - beforeEach(() => fetchMock.post(fetchUrlMatcher, mockValues)); - afterEach(() => fetchMock.restore()); - - beforeEach(() => { - config = getConfigStub(true); - indexPatterns = [indexPatternResponse]; - getSuggestions = getSuggestionsProvider({ config, indexPatterns }); - }); - - it('should return a function', function () { - expect(typeof getSuggestions).to.be('function'); - }); - - it('should return boolean suggestions for boolean fields', async () => { - const fieldName = 'ssl'; - const prefix = ''; - const suffix = ''; - const suggestions = await getSuggestions({ fieldName, prefix, suffix }); - expect(suggestions.map(({ text }) => text)).to.eql(['true ', 'false ']); - }); - - it('should filter boolean suggestions for boolean fields', async () => { - const fieldName = 'ssl'; - const prefix = 'fa'; - const suffix = ''; - const suggestions = await getSuggestions({ fieldName, prefix, suffix }); - expect(suggestions.map(({ text }) => text)).to.eql(['false ']); - }); - - it('should not make a request for non-aggregatable fields', async () => { - const fieldName = 'non-sortable'; - const prefix = ''; - const suffix = ''; - const suggestions = await getSuggestions({ fieldName, prefix, suffix }); - expect(fetchMock.called(fetchUrlMatcher)).to.be(false); - expect(suggestions).to.eql([]); - }); - - it('should not make a request for non-string fields', async () => { - const fieldName = 'bytes'; - const prefix = ''; - const suffix = ''; - const suggestions = await getSuggestions({ fieldName, prefix, suffix }); - expect(fetchMock.called(fetchUrlMatcher)).to.be(false); - expect(suggestions).to.eql([]); - }); - - it('should make a request for string fields', async () => { - const fieldName = 'machine.os.raw'; - const prefix = ''; - const suffix = ''; - const suggestions = await getSuggestions({ fieldName, prefix, suffix }); - - const lastCall = fetchMock.lastCall(fetchUrlMatcher, 'POST'); - - expect(lastCall.request._bodyInit, '{"query":"","field":"machine.os.raw","boolFilter":[]}'); - expect(lastCall[0]).to.match(/\/api\/kibana\/suggestions\/values\/logstash-\*/); - expect(lastCall[1]).to.eql({ - method: 'POST', - headers: { - 'content-type': 'application/json', - 'kbn-version': '1.2.3', - }, - }); - expect(suggestions.map(({ text }) => text)).to.eql(['"foo" ', '"bar" ']); - }); - - it('should not have descriptions', async () => { - const fieldName = 'ssl'; - const prefix = ''; - const suffix = ''; - const suggestions = await getSuggestions({ fieldName, prefix, suffix }); - expect(suggestions.length).to.be.greaterThan(0); - suggestions.forEach(suggestion => { - expect(suggestion.description).to.not.be.ok(); - }); - }); -}); - -function getConfigStub(suggestValues) { - const get = sinon.stub().returns(suggestValues); - return { get }; -} diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js index 36fb77a30acd0..66e62e884e9b3 100644 --- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js +++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js @@ -6,7 +6,7 @@ import { flatten } from 'lodash'; import { escapeQuotes } from './escape_kuery'; -import { getSuggestions } from 'ui/value_suggestions'; +import { npStart } from 'ui/new_platform'; const type = 'value'; @@ -29,6 +29,7 @@ export function getSuggestionsProvider({ indexPatterns, boolFilter }) { }) { const fields = allFields.filter(field => field.name === fieldName); const query = `${prefix}${suffix}`; + const { getSuggestions } = npStart.plugins.data; const suggestionsByField = fields.map(field => { return getSuggestions(field.indexPatternTitle, field, query, boolFilter).then(data => { diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js new file mode 100644 index 0000000000000..c59917ebdc3bf --- /dev/null +++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getSuggestionsProvider } from './value'; +import indexPatternResponse from './__fixtures__/index_pattern_response.json'; + +import { npStart } from 'ui/new_platform'; + +jest.mock('ui/new_platform', () => ({ + npStart: { + plugins: { + data: { + getSuggestions: (_, field) => { + let res; + if (field.type === 'boolean') { + res = [true, false]; + } else if (field.name === 'machine.os') { + res = ['Windo"ws', 'Mac\'', 'Linux']; + } else { + res = []; + } + return Promise.resolve(res); + } + }, + } + } +})); + + +describe('Kuery value suggestions', function () { + let indexPatterns; + let getSuggestions; + + beforeEach(() => { + indexPatterns = [indexPatternResponse]; + getSuggestions = getSuggestionsProvider({ indexPatterns }); + jest.clearAllMocks(); + }); + + test('should return a function', function () { + expect(typeof getSuggestions).toBe('function'); + }); + + test('should not search for non existing field', async () => { + const fieldName = 'i_dont_exist'; + const prefix = ''; + const suffix = ''; + const spy = jest.spyOn(npStart.plugins.data, 'getSuggestions'); + const suggestions = await getSuggestions({ fieldName, prefix, suffix }); + expect(suggestions.map(({ text }) => text)).toEqual([]); + expect(spy).toHaveBeenCalledTimes(0); + }); + + + test('should format suggestions', async () => { + const fieldName = 'ssl'; // Has results with quotes in mock + const prefix = ''; + const suffix = ''; + const start = 1; + const end = 5; + const suggestions = await getSuggestions({ fieldName, prefix, suffix, start, end }); + expect(suggestions[0].type).toEqual('value'); + expect(suggestions[0].start).toEqual(start); + expect(suggestions[0].end).toEqual(end); + }); + + describe('Boolean suggestions', function () { + test('should stringify boolean fields', async () => { + const fieldName = 'ssl'; + const prefix = ''; + const suffix = ''; + const spy = jest.spyOn(npStart.plugins.data, 'getSuggestions'); + const suggestions = await getSuggestions({ fieldName, prefix, suffix }); + expect(suggestions.map(({ text }) => text)).toEqual(['true ', 'false ']); + expect(spy).toHaveBeenCalledTimes(1); + }); + + test('should filter out boolean suggestions', async () => { + const fieldName = 'ssl'; // Has results with quotes in mock + const prefix = 'fa'; + const suffix = ''; + const suggestions = await getSuggestions({ fieldName, prefix, suffix }); + expect(suggestions.length).toEqual(1); + }); + + }); + + + describe('String suggestions', function () { + test('should merge prefix and suffix', async () => { + const fieldName = 'machine.os.raw'; + const prefix = 'he'; + const suffix = 'llo'; + const spy = jest.spyOn(npStart.plugins.data, 'getSuggestions'); + await getSuggestions({ fieldName, prefix, suffix }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toBeCalledWith(expect.any(String), expect.any(Object), prefix + suffix, undefined); + }); + + test('should escape quotes in suggestions', async () => { + const fieldName = 'machine.os'; // Has results with quotes in mock + const prefix = ''; + const suffix = ''; + const suggestions = await getSuggestions({ fieldName, prefix, suffix }); + expect(suggestions[0].text).toEqual('"Windo\\"ws" '); + expect(suggestions[1].text).toEqual('"Mac\'" '); + expect(suggestions[2].text).toEqual('"Linux" '); + }); + + test('should filter out string suggestions', async () => { + const fieldName = 'machine.os'; // Has results with quotes in mock + const prefix = 'banana'; + const suffix = ''; + const suggestions = await getSuggestions({ fieldName, prefix, suffix }); + expect(suggestions.length).toEqual(0); + }); + + test('should partially filter out string suggestions - case insensitive', async () => { + const fieldName = 'machine.os'; // Has results with quotes in mock + const prefix = 'ma'; + const suffix = ''; + const suggestions = await getSuggestions({ fieldName, prefix, suffix }); + expect(suggestions.length).toEqual(1); + }); + }); + + +}); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index 103697ef9148a..9c4b0fa737428 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -13,6 +13,10 @@ import { EditorFrameInstance } from '../types'; import { Storage } from 'ui/storage'; import { Document, SavedObjectStore } from '../persistence'; import { mount } from 'enzyme'; + +import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; +const dataStartMock = dataPluginMock.createStartContract(); + import { TopNavMenu, TopNavMenuData, @@ -68,8 +72,9 @@ describe('Lens App', () => { function makeDefaultArgs(): jest.Mocked<{ editorFrame: EditorFrameInstance; + data: typeof dataStartMock; core: typeof core; - data: DataStart; + dataShim: DataStart; store: Storage; docId?: string; docStorage: SavedObjectStore; @@ -87,7 +92,7 @@ describe('Lens App', () => { }, }, }, - data: { + dataShim: { indexPatterns: { indexPatterns: { get: jest.fn(id => { @@ -110,8 +115,9 @@ describe('Lens App', () => { redirectTo: jest.fn(id => {}), } as unknown) as jest.Mocked<{ editorFrame: EditorFrameInstance; + data: typeof dataStartMock; core: typeof core; - data: DataStart; + dataShim: DataStart; store: Storage; docId?: string; docStorage: SavedObjectStore; @@ -224,7 +230,7 @@ describe('Lens App', () => { await waitForPromises(); expect(args.docStorage.load).toHaveBeenCalledWith('1234'); - expect(args.data.indexPatterns.indexPatterns.get).toHaveBeenCalledWith('1'); + expect(args.dataShim.indexPatterns.indexPatterns.get).toHaveBeenCalledWith('1'); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ query: 'fake query', @@ -492,7 +498,7 @@ describe('Lens App', () => { const instance = mount(); - args.data.filter.filterManager.setFilters([ + args.dataShim.filter.filterManager.setFilters([ buildExistsFilter({ name: 'myfield' }, { id: 'index1' }), ]); @@ -623,7 +629,7 @@ describe('Lens App', () => { query: { query: 'new', language: 'lucene' }, }); - args.data.filter.filterManager.setFilters([ + args.dataShim.filter.filterManager.setFilters([ buildExistsFilter({ name: 'myfield' }, { id: 'index1' }), ]); instance.update(); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx index 3ee901d201aa5..4746b1cac3ecd 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx @@ -9,6 +9,8 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { Storage } from 'ui/storage'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; + import { CoreStart, NotificationsStart } from 'src/core/public'; import { DataStart, @@ -43,6 +45,7 @@ interface State { export function App({ editorFrame, data, + dataShim, core, store, docId, @@ -50,8 +53,9 @@ export function App({ redirectTo, }: { editorFrame: EditorFrameInstance; + data: DataPublicPluginStart; core: CoreStart; - data: DataStart; + dataShim: DataStart; store: Storage; docId?: string; docStorage: SavedObjectStore; @@ -77,9 +81,9 @@ export function App({ const lastKnownDocRef = useRef(undefined); useEffect(() => { - const subscription = data.filter.filterManager.getUpdates$().subscribe({ + const subscription = dataShim.filter.filterManager.getUpdates$().subscribe({ next: () => { - setState(s => ({ ...s, filters: data.filter.filterManager.getFilters() })); + setState(s => ({ ...s, filters: dataShim.filter.filterManager.getFilters() })); }, }); return () => { @@ -112,7 +116,7 @@ export function App({ .then(doc => { getAllIndexPatterns( doc.state.datasourceMetaData.filterableIndexPatterns, - data.indexPatterns.indexPatterns, + dataShim.indexPatterns.indexPatterns, core.notifications ) .then(indexPatterns => { @@ -164,6 +168,7 @@ export function App({ ({ ...s, savedQuery })); }} onSavedQueryUpdated={savedQuery => { - data.filter.filterManager.setFilters( + dataShim.filter.filterManager.setFilters( savedQuery.attributes.filters || state.filters ); setState(s => ({ @@ -245,7 +250,7 @@ export function App({ })); }} onClearSavedQuery={() => { - data.filter.filterManager.removeAll(); + dataShim.filter.filterManager.removeAll(); setState(s => ({ ...s, savedQuery: undefined, @@ -290,7 +295,7 @@ export function App({ ) { getAllIndexPatterns( filterableIndexPatterns, - data.indexPatterns.indexPatterns, + dataShim.indexPatterns.indexPatterns, core.notifications ).then(indexPatterns => { if (indexPatterns) { diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx index 3b3b12533d74b..2668946fec47b 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx @@ -11,8 +11,9 @@ import chrome from 'ui/chrome'; import { Storage } from 'ui/storage'; import { CoreSetup, CoreStart } from 'src/core/public'; import { npSetup, npStart } from 'ui/new_platform'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public'; -import { start as dataStart } from '../../../../../../src/legacy/core_plugins/data/public/legacy'; +import { start as dataShimStart } from '../../../../../../src/legacy/core_plugins/data/public/legacy'; import { editorFrameSetup, editorFrameStart, editorFrameStop } from '../editor_frame_plugin'; import { indexPatternDatasourceSetup, indexPatternDatasourceStop } from '../indexpattern_plugin'; import { SavedObjectIndexStore } from '../persistence'; @@ -26,7 +27,8 @@ import { App } from './app'; import { EditorFrameInstance } from '../types'; export interface LensPluginStartDependencies { - data: DataStart; + data: DataPublicPluginStart; + dataShim: DataStart; } export class AppPlugin { private instance: EditorFrameInstance | null = null; @@ -50,7 +52,7 @@ export class AppPlugin { editorFrameSetupInterface.registerDatasource('indexpattern', indexPattern); } - start(core: CoreStart, { data }: LensPluginStartDependencies) { + start(core: CoreStart, { data, dataShim }: LensPluginStartDependencies) { if (this.store === null) { throw new Error('Start lifecycle called before setup lifecycle'); } @@ -66,6 +68,7 @@ export class AppPlugin { app.setup(npSetup.core, {}); -export const appStart = () => app.start(npStart.core, { data: dataStart }); +export const appStart = () => + app.start(npStart.core, { dataShim: dataShimStart, data: npStart.plugins.data }); export const appStop = () => app.stop(); diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap index 4c9ef61478ab4..c3d4ff673e3d5 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap @@ -5,7 +5,7 @@ exports[`LayerPanel is rendered 1`] = ` services={ Object { "appName": "maps", - "autocomplete": undefined, + "data": undefined, "store": Storage { "clear": [Function], "get": [Function], diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js index 9efbfe45da29c..28afabc40bd75 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js @@ -155,7 +155,7 @@ export class LayerPanel extends React.Component { services={{ appName: 'maps', store: localStorage, - autocomplete: npStart.plugins.autocomplete, + data: npStart.plugins.data, ...npStart.core, }} >