From 0c001e4934be29879753458adab88af994a1628e Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Sun, 6 Oct 2019 17:25:24 +0300 Subject: [PATCH] =?UTF-8?q?Move=20ui/value=5Fsuggestions=20=E2=87=92=20NP?= =?UTF-8?q?=20data=20plugin=20(#45762)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bind search bar * create prewired data components * Pass NP data plugin to shim plugin, to access autocomplete Pass storage and autocomplete to createSearchBar method Add appName and autocomplete to IDataPluginServices QueryBarInput to consume autocomplete and appName from context QueryBarTopRow to consume appName from context Remove appName from SearchBar Added AutocompletePublicPluginSetup and AutocompletePublicPluginStart types * Use KibanaContextProvider in vis editor and graph * Use KibanaContextProvider in maps * Use prewirted SearchBar in TopNavMenu * Use KibanaContextProbider in Lens * Fix appName usage in query bar input * fixed query bar top row appName * update tests * fixed bind search bar bug * mock SearchBar * Removed unnecessary mocks * Delete unused mock * Fixed exporting of data plugin types * Updated maps snapshot * Fixed some TS issues * Fixed jest tests * Context adjustments in TSVB * componentWillMount * Code review fixes * Pass dataTestSubj to query bar input * Graph data * - Pass NP data plugin to KibanaReactContext - Move value_suggestions to NP * - Pass NP data plugin to KibanaReactContext - Move value_suggestions to NP * ts fixes * Added karma getSuggestions fake * Refactored kuery autocomplete tests to jest * Filter bar context for directives * updated snapshot * fix diffs * fixed lens test --- .../public/filter/filter_bar/filter_bar.tsx | 47 +++++-- .../filter/filter_bar/filter_editor/index.tsx | 4 - .../filter_editor/phrase_suggestor.tsx | 18 ++- .../filter_editor/phrase_value_input.tsx | 7 +- .../filter_editor/phrases_values_input.tsx | 7 +- .../public/filter/filter_bar/filter_item.tsx | 1 - src/legacy/core_plugins/data/public/plugin.ts | 2 +- .../query_bar/components/query_bar_input.tsx | 2 +- .../components/create_search_bar.tsx | 8 +- .../search_bar/components/search_bar.tsx | 1 - .../data/public/shim/legacy_module.ts | 13 +- src/legacy/core_plugins/data/public/types.ts | 4 +- .../public/components/vis_editor.js | 2 +- .../new_platform/new_platform.karma_mock.js | 4 +- .../vis/editors/default/controls/filter.tsx | 2 +- src/plugins/data/public/mocks.ts | 1 + src/plugins/data/public/plugin.ts | 2 + .../public/suggestions_provider}/index.ts | 6 +- .../data/public/suggestions_provider/types.ts | 23 +++ .../value_suggestions.test.ts | 32 +++-- .../value_suggestions.ts | 15 +- src/plugins/data/public/types.ts | 4 + .../graph/public/angular/templates/index.html | 2 +- x-pack/legacy/plugins/graph/public/app.js | 7 +- .../plugins/graph/public/components/app.tsx | 14 +- .../public/components/search_bar.test.tsx | 2 + .../graph/public/components/search_bar.tsx | 2 + .../autocomplete_providers/__tests__/value.js | 103 -------------- .../public/autocomplete_providers/value.js | 3 +- .../autocomplete_providers/value.test.js | 131 ++++++++++++++++++ .../lens/public/app_plugin/app.test.tsx | 18 ++- .../plugins/lens/public/app_plugin/app.tsx | 19 ++- .../plugins/lens/public/app_plugin/plugin.tsx | 12 +- .../__snapshots__/view.test.js.snap | 2 +- .../connected_components/layer_panel/view.js | 2 +- 35 files changed, 318 insertions(+), 204 deletions(-) rename src/{legacy/ui/public/value_suggestions => plugins/data/public/suggestions_provider}/index.ts (78%) create mode 100644 src/plugins/data/public/suggestions_provider/types.ts rename src/{legacy/ui/public/value_suggestions => plugins/data/public/suggestions_provider}/value_suggestions.test.ts (83%) rename src/{legacy/ui/public/value_suggestions => plugins/data/public/suggestions_provider}/value_suggestions.ts (82%) delete mode 100644 x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js create mode 100644 x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js 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, }} >