From 060d99821f784cde3164f2924d30da9c5fe1fccd Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Sun, 11 Aug 2019 12:10:43 +0300 Subject: [PATCH] Pass uiSettings to all data plugin services (#42159) * kbn top nav in discover * New top nav in dashboard and vis editor * change kbn top nav directive * Stop using template feature of kbn top nav * Combined css * console top nav * Removed unnecessary use of kbn-top-nav in dev tools app (wrapping tabs) * Changed console menu to new directive * CSS adjustments + functional implementation of top nav menu item * Fixed DevTools top nav toggle * Optional show-border * timelion menu works * Improve filter sorting logic to be more stable * Support showing filter bar as part of top nav * Use search bar in top nav in discover and maps Support search bar with no filter bar (TS) * tmp revert * Align search bar settings accross apps * Reverted change in ML, removed unused css * Added data test subj to top nav menu items * Watch config by value * Some directive magic to make sure that disabledButtons functions are watched correctly. * Fix missing controls from new top nav in some visualizations * showAutoRefreshOnly in input controls visualization * Fixed inspector disabled test * Fix dashboard action links rewrite top nav menu item to functional style * snapshots * Fixed maps filter bar * Remvoed comment * Update Query Bar defaults * Top nav menu item tests * Moved storage instantiation to angular directive * SearchBar jest tests * Query bar additional tests * Top nav menu tests * Pass store into top nav menu correctly * watch store by reference * Added not null assertion * Make index patterns optional (for timepicker only setup) * QueryBar tests again * Search bar tests * Top nav tests * Top nav menu tests * removed unnecessary ui/new_platform mock * Moved discover result count away from top nav * Moved and improved top nav menu css * remove unused translations * Move timepicker (to be deprecated) into old kbn_top_nav * Deleted search-bar and query-bar directives! * moved search bar to kibana_react (it's a generic react component, not a service) * translations * Moved superDatePicker directive to kbn_top_nav (to be deprecated) Deleted unused react_component directives call-out and tool-bar-search-box * Use index patterns from data plugin itself instead of importing from ui/public * Pass uiSettings from top level of data plugin * Pass saved objects client from top level * query bar input to rely on provided localStorage (?) * import QueryBarInput correctly from vis ediror * Query bar input tests - uiSettings * Query bar - uiSettings tests * import QueryBar from data plugin correctly * Use provider to pass config to TSVB query bar inputs * Add query bar input parms to agg types * Standardize shape data plugin and use it to pass uiSettings in. * Removed unnecessary mocks * Fixed test typo * Code review part 1 * Code review part 2 - clean up top nav menu item run interface * Give top nav items better keys * Simplified top nav construction logic in editor * Fixed mock of search bar in top nav test * Moved filter trigger button rendering to helper function * Remove responsiveness from top nav items * vertical align for cases where showSearchBarInline is true (i.e. only menu and time picker in the same row) * Export TopNavMenuData type * Removed unused name attribute in top nav. Use app-name instead. * Minor merge fixes * Update data plugin shape * type fixes * fix core start import * Fixed tests * fix another test mock * Brought back setup.ts for backward compatibility. Chnaged to relative imports * bad import from data plugin * Yet another import :-( * Code revire #1 @lukeelmers * create wrapper for QueryBarInput * use IndexPatterns type * import order * Code review fixes * inject uiSettings into filter-bar directive * Fix some type errors * Fixes * Filter bar context * ts CoreSetupContextProvider * Moved coreCOntext to vis_editor constructor * Reverted filter bar context * Removed editor html ng-show * use saved objects contract + check uiSettings --- .../public/filter/filter_bar/filter_bar.tsx | 9 +- .../filter/filter_bar/filter_editor/index.tsx | 4 + .../filter_editor/phrase_suggestor.tsx | 6 +- .../public/filter/filter_bar/filter_item.tsx | 3 + .../filter_manager/filter_manager.test.ts | 43 +++---- .../filter/filter_manager/filter_manager.ts | 10 +- .../filter_state_manager.test.ts | 30 +++-- .../data/public/filter/filter_service.ts | 8 +- .../index_patterns/index_patterns_service.ts | 15 ++- src/legacy/core_plugins/data/public/plugin.ts | 9 +- .../__snapshots__/query_bar.test.tsx.snap | 112 ------------------ .../query_bar_input.test.tsx.snap | 90 ++++++++++++++ .../query_bar/components/query_bar.test.tsx | 33 +++++- .../query/query_bar/components/query_bar.tsx | 22 ++-- .../components/query_bar_input.test.mocks.ts | 35 ------ .../components/query_bar_input.test.tsx | 12 +- .../query_bar/components/query_bar_input.tsx | 29 +++-- .../query_bar/lib/fetch_index_patterns.ts | 16 ++- .../query/query_bar/lib/get_query_log.ts | 12 +- .../search_bar/components/search_bar.test.tsx | 10 ++ .../search_bar/components/search_bar.tsx | 10 ++ .../data/public/shim/legacy_module.ts | 56 +++++++-- .../public/top_nav_menu/top_nav_menu.test.tsx | 17 ++- .../public/top_nav_menu/top_nav_menu.tsx | 3 + .../public/components/annotations_editor.js | 10 +- .../metrics/public/components/panel_config.js | 1 + .../public/components/panel_config/gauge.js | 8 +- .../components/panel_config/gauge.test.js | 7 ++ .../components/panel_config/markdown.js | 8 +- .../public/components/panel_config/metric.js | 8 +- .../public/components/panel_config/table.js | 9 +- .../components/panel_config/timeseries.js | 8 +- .../public/components/panel_config/top_n.js | 8 +- .../public/components/query_bar_wrapper.js} | 11 +- .../public/components/series_config.js | 9 +- .../public/components/splits/filter.js | 8 +- .../public/components/splits/filter_items.js | 8 +- .../metrics/public/components/vis_editor.js | 35 ++++-- .../components/vis_types/table/config.js | 9 +- .../components/vis_types/timeseries/config.js | 8 +- .../contexts/query_input_bar_context.ts | 32 +++++ .../ui/public/agg_types/buckets/filters.js | 2 +- .../ui/public/agg_types/controls/filter.tsx | 6 +- .../public/index_patterns/index_patterns.ts | 7 +- .../ui/public/kbn_top_nav/kbn_top_nav2.js | 5 + .../filter_editor/filter_editor.js | 1 + .../join_editor/resources/where_expression.js | 1 + 47 files changed, 445 insertions(+), 358 deletions(-) delete mode 100644 src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar.test.tsx.snap rename src/legacy/{ui/public/storage/storage_service.ts => core_plugins/metrics/public/components/query_bar_wrapper.js} (71%) create mode 100644 src/legacy/core_plugins/metrics/public/contexts/query_input_bar_context.ts 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 1f115964709e9..ca2b26cc3202d 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,20 +31,19 @@ import { import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import classNames from 'classnames'; import React, { Component } from 'react'; -import chrome from 'ui/chrome'; +import { UiSettingsClientContract } from 'src/core/public'; import { IndexPattern } from '../../index_patterns'; import { FilterEditor } from './filter_editor'; import { FilterItem } from './filter_item'; import { FilterOptions } from './filter_options'; -const config = chrome.getUiSettingsClient(); - interface Props { filters: Filter[]; onFiltersUpdated: (filters: Filter[]) => void; className: string; indexPatterns: IndexPattern[]; intl: InjectedIntl; + uiSettings: UiSettingsClientContract; } interface State { @@ -103,13 +102,14 @@ class FilterBarUI extends Component { onUpdate={newFilter => this.onUpdate(i, newFilter)} onRemove={() => this.onRemove(i)} indexPatterns={this.props.indexPatterns} + uiSettings={this.props.uiSettings} /> )); } private renderAddFilter() { - const isPinned = config.get('filters:pinnedByDefault'); + const isPinned = this.props.uiSettings.get('filters:pinnedByDefault'); const [indexPattern] = this.props.indexPatterns; const index = indexPattern && indexPattern.id; const newFilter = buildEmptyFilter(isPinned, index); @@ -144,6 +144,7 @@ class FilterBarUI extends Component { onSubmit={this.onAdd} onCancel={this.onCloseAddFilterPopover} key={JSON.stringify(newFilter)} + uiSettings={this.props.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 1bb594c183bc6..0d46e9e7bac63 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,6 +36,7 @@ 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 { @@ -61,6 +62,7 @@ interface Props { onSubmit: (filter: Filter) => void; onCancel: () => void; intl: InjectedIntl; + uiSettings: UiSettingsClientContract; } interface State { @@ -327,6 +329,7 @@ class FilterEditorUI extends Component { value={this.state.params} onChange={this.onParamsChange} data-test-subj="phraseValueInput" + uiSettings={this.props.uiSettings} /> ); case 'phrases': @@ -336,6 +339,7 @@ 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 9cfd3aa4fd331..6b262c66402f2 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,14 @@ */ import { Component } from 'react'; -import chrome from 'ui/chrome'; import { getSuggestions } from 'ui/value_suggestions'; +import { UiSettingsClientContract } from 'src/core/public'; import { Field, IndexPattern } from '../../../index_patterns'; -const config = chrome.getUiSettingsClient(); export interface PhraseSuggestorProps { indexPattern: IndexPattern; field?: Field; + uiSettings: UiSettingsClientContract; } export interface PhraseSuggestorState { @@ -52,7 +52,7 @@ export class PhraseSuggestor extends Component< } protected isSuggestingValues() { - const shouldSuggestValues = config.get('filterEditor:suggestValues'); + const shouldSuggestValues = this.props.uiSettings.get('filterEditor:suggestValues'); const { field } = this.props; return shouldSuggestValues && field && field.aggregatable && field.type === 'string'; } 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 453dafdb29fe3..ee8d660e44f55 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 @@ -28,6 +28,7 @@ import { import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; import classNames from 'classnames'; import React, { Component } from 'react'; +import { UiSettingsClientContract } from 'src/core/public'; import { IndexPattern } from '../../index_patterns'; import { FilterEditor } from './filter_editor'; import { FilterView } from './filter_view'; @@ -40,6 +41,7 @@ interface Props { onUpdate: (filter: Filter) => void; onRemove: () => void; intl: InjectedIntl; + uiSettings: UiSettingsClientContract; } interface State { @@ -169,6 +171,7 @@ 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/filter/filter_manager/filter_manager.test.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.test.ts index 3f3cbd0044a07..8fba16037ed97 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.test.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.test.ts @@ -32,35 +32,20 @@ import { StubIndexPatterns } from './test_helpers/stub_index_pattern'; import { StubState } from './test_helpers/stub_state'; import { getFiltersArray } from './test_helpers/get_filters_array'; -jest.mock( - 'ui/chrome', - () => ({ - getBasePath: jest.fn(() => 'path'), - getUiSettingsClient: jest.fn(() => { - return { - get: () => true, - }; - }), - }), - { virtual: true } -); - -jest.mock('ui/new_platform', () => ({ - npStart: { - core: { - chrome: { - recentlyAccessed: false, - }, - }, - }, - npSetup: { - core: { - uiSettings: { - get: () => true, - }, +import { coreMock } from '../../../../../../core/public/mocks'; +const setupMock = coreMock.createSetup(); + +setupMock.uiSettings.get.mockImplementation((key: string) => { + return true; +}); + +jest.mock('ui/timefilter', () => { + return { + timefilter: { + setTime: jest.fn(), }, - }, -})); + }; +}); describe('filter_manager', () => { let appStateStub: StubState; @@ -79,7 +64,7 @@ describe('filter_manager', () => { appStateStub = new StubState(); globalStateStub = new StubState(); indexPatterns = new StubIndexPatterns(); - filterManager = new FilterManager(indexPatterns as IndexPatterns); + filterManager = new FilterManager(indexPatterns as IndexPatterns, setupMock.uiSettings); readyFilters = getFiltersArray(); // FilterStateManager is tested indirectly. diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts index ccb26c801c701..f230b035de352 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts @@ -22,8 +22,7 @@ import { Filter, isFilterPinned, FilterStateStore } from '@kbn/es-query'; import _ from 'lodash'; import { Subject } from 'rxjs'; -import { npSetup } from 'ui/new_platform'; - +import { UiSettingsClientContract } from 'src/core/public'; // @ts-ignore import { compareFilters } from './lib/compare_filters'; // @ts-ignore @@ -46,9 +45,11 @@ export class FilterManager { private filters: Filter[] = []; private updated$: Subject = new Subject(); private fetch$: Subject = new Subject(); + private uiSettings: UiSettingsClientContract; - constructor(indexPatterns: IndexPatterns) { + constructor(indexPatterns: IndexPatterns, uiSettings: UiSettingsClientContract) { this.indexPatterns = indexPatterns; + this.uiSettings = uiSettings; } private mergeIncomingFilters(partitionedFilters: PartitionedFilters): Filter[] { @@ -144,9 +145,8 @@ export class FilterManager { return; } - const { uiSettings } = npSetup.core; if (pinFilterStatus === undefined) { - pinFilterStatus = uiSettings.get('filters:pinnedByDefault'); + pinFilterStatus = this.uiSettings.get('filters:pinnedByDefault'); } // Set the store of all filters. For now. diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts index 4152a0931b031..778663821f55b 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts @@ -28,22 +28,20 @@ import { getFilter } from './test_helpers/get_stub_filter'; import { FilterManager } from './filter_manager'; import { StubIndexPatterns } from './test_helpers/stub_index_pattern'; -jest.mock('ui/new_platform', () => ({ - npStart: { - core: { - chrome: { - recentlyAccessed: false, - }, - }, - }, - npSetup: { - core: { - uiSettings: { - get: () => true, - }, +import { coreMock } from '../../../../../../core/public/mocks'; +const setupMock = coreMock.createSetup(); + +setupMock.uiSettings.get.mockImplementation((key: string) => { + return true; +}); + +jest.mock('ui/timefilter', () => { + return { + timefilter: { + setTime: jest.fn(), }, - }, -})); + }; +}); describe('filter_state_manager', () => { let appStateStub: StubState; @@ -55,7 +53,7 @@ describe('filter_state_manager', () => { appStateStub = new StubState(); globalStateStub = new StubState(); const indexPatterns = new StubIndexPatterns(); - filterManager = new FilterManager(indexPatterns as IndexPatterns); + filterManager = new FilterManager(indexPatterns as IndexPatterns, setupMock.uiSettings); }); describe('app_state_undefined', () => { diff --git a/src/legacy/core_plugins/data/public/filter/filter_service.ts b/src/legacy/core_plugins/data/public/filter/filter_service.ts index 27cf027e45907..f56534490afc4 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_service.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_service.ts @@ -17,6 +17,7 @@ * under the License. */ +import { UiSettingsClientContract } from 'src/core/public'; import { IndexPatterns } from '../index_patterns'; import { FilterManager } from './filter_manager'; /** @@ -26,14 +27,13 @@ import { FilterManager } from './filter_manager'; export interface FilterServiceDependencies { indexPatterns: IndexPatterns; + uiSettings: UiSettingsClientContract; } export class FilterService { - public setup({ indexPatterns }: FilterServiceDependencies) { - const filterManager = new FilterManager(indexPatterns); - + public setup({ indexPatterns, uiSettings }: FilterServiceDependencies) { return { - filterManager, + filterManager: new FilterManager(indexPatterns, uiSettings), }; } diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts index 74918bebccf08..4ab08c2a60eb0 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts @@ -16,8 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - -import chrome from 'ui/chrome'; // @ts-ignore import { mockFields, mockIndexPattern } from 'ui/index_patterns/fixtures'; // @ts-ignore @@ -36,8 +34,13 @@ import { isFilterable, getFromSavedObject } from 'ui/index_patterns/static_utils // IndexPattern, StaticIndexPattern, Field import * as types from 'ui/index_patterns'; -const config = chrome.getUiSettingsClient(); -const savedObjectsClient = chrome.getSavedObjectsClient(); +import { UiSettingsClientContract, SavedObjectsClientContract } from 'src/core/public'; + +export interface IndexPatternDependencies { + uiSettings: UiSettingsClientContract; + savedObjectsClient: SavedObjectsClientContract; +} + /** * Index Patterns Service * @@ -50,9 +53,9 @@ const savedObjectsClient = chrome.getSavedObjectsClient(); * @internal */ export class IndexPatternsService { - public setup() { + public setup({ uiSettings, savedObjectsClient }: IndexPatternDependencies) { return { - indexPatterns: new IndexPatterns(config, savedObjectsClient), + indexPatterns: new IndexPatterns(uiSettings, savedObjectsClient), }; } diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index f94e10e033a9b..34edb355d2ef8 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -68,13 +68,20 @@ export class DataPlugin implements Plugin - - - - - - - - - - - - - - -`; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap index 00576d05bdcac..b13916a3e5b29 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap @@ -150,6 +150,36 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, } } + uiSettings={ + Object { + "get": [MockFunction] { + "calls": Array [ + Array [ + "history:limit", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "get$": [MockFunction], + "getAll": [MockFunction], + "getSaved$": [MockFunction], + "getUpdate$": [MockFunction], + "getUpdateErrors$": [MockFunction], + "isCustom": [MockFunction], + "isDeclared": [MockFunction], + "isDefault": [MockFunction], + "isOverridden": [MockFunction], + "overrideLocalDefault": [MockFunction], + "remove": [MockFunction], + "set": [MockFunction], + "stop": [MockFunction], + } + } > { + switch (key) { + case 'timepicker:quickRanges': + return [ + { + from: 'now/d', + to: 'now/d', + display: 'Today', + }, + ]; + case 'dateFormat': + return 'YY'; + case 'history:limit': + return 10; + default: + throw new Error(`Unexpected config key: ${key}`); + } +}); + const noop = () => { return; }; @@ -76,6 +98,7 @@ describe('QueryBar', () => { it('Should render the given query', () => { const component = shallowWithIntl( { /> ); - expect(component).toMatchSnapshot(); + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(1); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(1); }); it('Should create a unique PersistedLog based on the appName and query language', () => { shallowWithIntl( { it('Should render only timepicker when no options provided', () => { const component = shallowWithIntl( { it('Should not show timepicker when asked', () => { const component = shallowWithIntl( { it('Should render timepicker with options', () => { const component = shallowWithIntl( { it('Should render only query input bar', () => { const component = shallowWithIntl( { it('Should NOT render query input bar if disabled', () => { const component = shallowWithIntl( { it('Should NOT render query input bar if missing options', () => { const component = shallowWithIntl( void; customSubmitButton?: any; + uiSettings: UiSettingsClientContract; } interface State { @@ -243,13 +242,21 @@ export class QueryBarUI extends Component { public componentDidMount() { if (!this.props.query) return; - this.persistedLog = getQueryLog(this.props.appName, this.props.query.language); + this.persistedLog = getQueryLog( + this.props.uiSettings, + this.props.appName, + this.props.query.language + ); } public componentDidUpdate(prevProps: Props) { if (!this.props.query || !prevProps.query) return; if (prevProps.query.language !== this.props.query.language) { - this.persistedLog = getQueryLog(this.props.appName, this.props.query.language); + this.persistedLog = getQueryLog( + this.props.uiSettings, + this.props.appName, + this.props.query.language + ); } } @@ -281,6 +288,7 @@ export class QueryBarUI extends Component { onChange={this.onChange} onSubmit={this.onInputSubmit} persistedLog={this.persistedLog} + uiSettings={this.props.uiSettings} /> ); @@ -332,7 +340,7 @@ export class QueryBarUI extends Component { }; }); - const commonlyUsedRanges = config + const commonlyUsedRanges = this.props.uiSettings .get('timepicker:quickRanges') .map(({ from, to, display }: { from: string; to: string; display: string }) => { return { @@ -354,7 +362,7 @@ export class QueryBarUI extends Component { showUpdateButton={false} recentlyUsedRanges={recentlyUsedRanges} commonlyUsedRanges={commonlyUsedRanges} - dateFormat={config.get('dateFormat')} + dateFormat={this.props.uiSettings.get('dateFormat')} isAutoRefreshOnly={this.props.showAutoRefreshOnly} /> diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.mocks.ts b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.mocks.ts index b2f308127b0e1..7bdc9a2448363 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.mocks.ts +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.mocks.ts @@ -35,34 +35,6 @@ const mockIndexPattern = { ], }; -const mockChromeFactory = jest.fn(() => { - return { - getBasePath: () => `foo`, - getUiSettingsClient: () => { - return { - get: (key: string) => { - switch (key) { - case 'timepicker:quickRanges': - return [ - { - from: 'now/d', - to: 'now/d', - display: 'Today', - }, - ]; - case 'dateFormat': - return 'YY'; - case 'history:limit': - return 10; - default: - throw new Error(`Unexpected config key: ${key}`); - } - }, - }; - }, - }; -}); - export const mockPersistedLog = { add: jest.fn(), get: jest.fn(() => ['response:200']), @@ -81,16 +53,9 @@ export const mockFetchIndexPatterns = jest .fn() .mockReturnValue(Promise.resolve([mockIndexPattern])); -jest.mock('ui/chrome', () => mockChromeFactory()); -jest.mock('ui/kfetch', () => ({ - kfetch: () => {}, -})); jest.mock('ui/persisted_log', () => ({ PersistedLog: mockPersistedLogFactory, })); -jest.mock('ui/autocomplete_providers', () => ({ - getAutocompleteProvider: mockGetAutocompleteProvider, -})); jest.mock('ui/kfetch', () => ({ kfetch: mockKfetch, })); diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx index ff155dfccdac2..d04c6032980ff 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx @@ -28,6 +28,8 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { QueryLanguageSwitcher } from './language_switcher'; import { QueryBarInput, QueryBarInputUI } from './query_bar_input'; +import { coreMock } from '../../../../../../../core/public/mocks'; +const setupMock = coreMock.createSetup(); import { IndexPattern } from '../../../index'; const noop = () => { @@ -91,6 +93,7 @@ describe('QueryBarInput', () => { indexPatterns={[mockIndexPattern]} store={createMockStorage()} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -107,6 +110,7 @@ describe('QueryBarInput', () => { indexPatterns={[mockIndexPattern]} store={createMockStorage()} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -124,6 +128,7 @@ describe('QueryBarInput', () => { store={createMockStorage()} disableAutoFocus={true} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -143,6 +148,7 @@ describe('QueryBarInput', () => { store={createMockStorage()} disableAutoFocus={true} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -163,6 +169,7 @@ describe('QueryBarInput', () => { store={mockStorage} disableAutoFocus={true} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -187,6 +194,7 @@ describe('QueryBarInput', () => { store={createMockStorage()} disableAutoFocus={true} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -210,6 +218,7 @@ describe('QueryBarInput', () => { store={createMockStorage()} disableAutoFocus={true} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); @@ -238,8 +247,9 @@ describe('QueryBarInput', () => { store={createMockStorage()} disableAutoFocus={true} intl={null as any} + uiSettings={setupMock.uiSettings} /> ); - expect(mockFetchIndexPatterns).toHaveBeenCalledWith(['logstash-*']); + expect(mockFetchIndexPatterns).toHaveBeenCalledWith(['logstash-*'], setupMock.uiSettings); }); }); 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 9bfdc68763721..50628a316209a 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 @@ -30,10 +30,9 @@ import { } from 'ui/autocomplete_providers'; import { debounce, compact, isEqual, omit } from 'lodash'; import { PersistedLog } from 'ui/persisted_log'; -import chrome from 'ui/chrome'; import { kfetch } from 'ui/kfetch'; import { Storage } from 'ui/storage'; -import { localStorage } from 'ui/storage/storage_service'; +import { UiSettingsClientContract } from 'src/core/public'; import { IndexPattern, StaticIndexPattern } from '../../../index_patterns'; import { Query } from '../index'; import { fromUser, matchPairs, toUser } from '../lib'; @@ -43,14 +42,15 @@ import { getQueryLog } from '../lib/get_query_log'; import { fetchIndexPatterns } from '../lib/fetch_index_patterns'; interface Props { + uiSettings: UiSettingsClientContract; indexPatterns: Array; + store: Storage; intl: InjectedIntl; query: Query; appName: string; disableAutoFocus?: boolean; screenTitle?: string; prepend?: any; - store?: Storage; persistedLog?: PersistedLog; bubbleSubmitEvent?: boolean; languageSwitcherPopoverAnchorPosition?: PopoverAnchorPosition; @@ -80,7 +80,6 @@ const KEY_CODES = { END: 35, }; -const config = chrome.getUiSettingsClient(); const recentSearchType: AutocompleteSuggestionType = 'recentSearch'; export class QueryBarInputUI extends Component { @@ -111,7 +110,10 @@ export class QueryBarInputUI extends Component { indexPattern => typeof indexPattern !== 'string' ) as IndexPattern[]; - const objectPatternsFromStrings = (await fetchIndexPatterns(stringPatterns)) as IndexPattern[]; + const objectPatternsFromStrings = (await fetchIndexPatterns( + stringPatterns, + this.props.uiSettings + )) as IndexPattern[]; this.setState({ indexPatterns: [...objectPatterns, ...objectPatternsFromStrings], @@ -123,6 +125,7 @@ export class QueryBarInputUI extends Component { return; } + const uiSettings = this.props.uiSettings; const language = this.props.query.language; const queryString = this.getQueryString(); @@ -138,7 +141,10 @@ export class QueryBarInputUI extends Component { } const indexPatterns = this.state.indexPatterns; - const getAutocompleteSuggestions = autocompleteProvider({ config, indexPatterns }); + const getAutocompleteSuggestions = autocompleteProvider({ + config: uiSettings, + indexPatterns, + }); const { selectionStart, selectionEnd } = this.inputRef; if (selectionStart === null || selectionEnd === null) { @@ -359,11 +365,7 @@ export class QueryBarInputUI extends Component { body: JSON.stringify({ opt_in: language === 'kuery' }), }); - if (this.props.store) { - this.props.store.set('kibana.userQueryLanguage', language); - } else { - localStorage.set('kibana.userQueryLanguage', language); - } + this.props.store.set('kibana.userQueryLanguage', language); const newQuery = { query: '', language }; this.onChange(newQuery); @@ -391,7 +393,7 @@ export class QueryBarInputUI extends Component { public componentDidMount() { this.persistedLog = this.props.persistedLog ? this.props.persistedLog - : getQueryLog(this.props.appName, this.props.query.language); + : getQueryLog(this.props.uiSettings, this.props.appName, this.props.query.language); this.fetchIndexPatterns().then(this.updateSuggestions); } @@ -399,7 +401,7 @@ export class QueryBarInputUI extends Component { public componentDidUpdate(prevProps: Props) { this.persistedLog = this.props.persistedLog ? this.props.persistedLog - : getQueryLog(this.props.appName, this.props.query.language); + : getQueryLog(this.props.uiSettings, this.props.appName, this.props.query.language); if (!isEqual(prevProps.indexPatterns, this.props.indexPatterns)) { this.fetchIndexPatterns().then(this.updateSuggestions); @@ -440,6 +442,7 @@ export class QueryBarInputUI extends Component { 'languageSwitcherPopoverAnchorPosition', 'onChange', 'onSubmit', + 'uiSettings', ]); return ( diff --git a/src/legacy/core_plugins/data/public/query/query_bar/lib/fetch_index_patterns.ts b/src/legacy/core_plugins/data/public/query/query_bar/lib/fetch_index_patterns.ts index 3ba621a8f3d3f..5796623e31f53 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/lib/fetch_index_patterns.ts +++ b/src/legacy/core_plugins/data/public/query/query_bar/lib/fetch_index_patterns.ts @@ -19,11 +19,13 @@ import chrome from 'ui/chrome'; import { isEmpty } from 'lodash'; +import { UiSettingsClientContract } from 'src/core/public'; import { utils as indexPatternUtils } from '../../../index_patterns'; -const config = chrome.getUiSettingsClient(); - -export async function fetchIndexPatterns(indexPatternStrings: string[]) { +export async function fetchIndexPatterns( + indexPatternStrings: string[], + uiSettings: UiSettingsClientContract +) { if (!indexPatternStrings || isEmpty(indexPatternStrings)) { return []; } @@ -40,15 +42,17 @@ export async function fetchIndexPatterns(indexPatternStrings: string[]) { return indexPatternStrings.includes(savedObject.attributes.title as string); }); + const defaultIndex = uiSettings.get('defaultIndex'); + const allMatches = exactMatches.length === indexPatternStrings.length ? exactMatches - : [...exactMatches, await fetchDefaultIndexPattern()]; + : [...exactMatches, await fetchDefaultIndexPattern(defaultIndex)]; return allMatches.map(indexPatternUtils.getFromSavedObject); } -const fetchDefaultIndexPattern = async () => { +const fetchDefaultIndexPattern = async (defaultIndex: string) => { const savedObjectsClient = chrome.getSavedObjectsClient(); - return await savedObjectsClient.get('index-pattern', config.get('defaultIndex')); + return await savedObjectsClient.get('index-pattern', defaultIndex); }; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts b/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts index a3b0fe891ff9f..70dc1d3fe700e 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts +++ b/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts @@ -17,14 +17,16 @@ * under the License. */ -import chrome from 'ui/chrome'; import { PersistedLog } from 'ui/persisted_log'; +import { UiSettingsClientContract } from 'src/core/public'; -const config = chrome.getUiSettingsClient(); - -export function getQueryLog(appName: string, language: string) { +export function getQueryLog( + uiSettings: UiSettingsClientContract, + appName: string, + language: string +) { return new PersistedLog(`typeahead:${appName}-${language}`, { - maxLength: config.get('history:limit'), + maxLength: uiSettings.get('history:limit'), filterDuplicates: true, }); } diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx index 0fccf8bd6f5a4..5026bd04afded 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx @@ -22,6 +22,9 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { SearchBar } from './search_bar'; import { IndexPattern } from 'ui/index_patterns'; +import { coreMock } from '../../../../../../../../src/core/public/mocks'; +const setupMock = coreMock.createSetup(); + jest.mock('../../../../../data/public', () => { return { FilterBar: () =>
, @@ -80,6 +83,7 @@ describe('SearchBar', () => { it('Should render query bar when no options provided (in reality - timepicker)', () => { const component = mountWithIntl( { it('Should render empty when timepicker is off and no options provided', () => { const component = mountWithIntl( { it('Should render filter bar, when required fields are provided', () => { const component = mountWithIntl( { it('Should NOT render filter bar, if disabled', () => { const component = mountWithIntl( { it('Should render query bar, when required fields are provided', () => { const component = mountWithIntl( { it('Should NOT render query bar, if disabled', () => { const component = mountWithIntl( { it('Should render query bar and filter bar', () => { const component = mountWithIntl( { } public render() { + // This is needed, as kbn-top-nav-v2 might render before npSetup.core.uiSettings is set. + // This won't be needed when it's loaded exclusively with React. + if (!this.props.uiSettings) { + return null; + } + let queryBar; if (this.shouldRenderQueryBar()) { queryBar = ( { > { uiModules - .get('app/kibana') - .directive('filterBar', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(FilterBar)); + .get('app/kibana', ['react']) + .directive('filterBar', () => { + return { + restrict: 'E', + template: '', + compile: (elem: any) => { + const child = document.createElement('filter-bar-helper'); + + // Copy attributes to the child directive + for (const attr of elem[0].attributes) { + child.setAttribute(attr.name, attr.value); + } + + child.setAttribute('ui-settings', 'uiSettings'); + + // Append helper directive + elem.append(child); + + const linkFn = ($scope: any) => { + $scope.uiSettings = npSetup.core.uiSettings; + }; + + return linkFn; + }, + }; }) - .directive('applyFiltersPopoverComponent', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(ApplyFiltersPopover)); + .directive('filterBarHelper', (reactDirective: any) => { + return reactDirective(wrapInI18nContext(FilterBar), [ + ['uiSettings', { watchDepth: 'reference' }], + ['onFiltersUpdated', { watchDepth: 'reference' }], + ['indexPatterns', { watchDepth: 'collection' }], + ['filters', { watchDepth: 'collection' }], + ['className', { watchDepth: 'reference' }], + ]); }) + .directive('applyFiltersPopoverComponent', (reactDirective: any) => + reactDirective(wrapInI18nContext(ApplyFiltersPopover)) + ) .directive('applyFiltersPopover', (indexPatterns: IndexPatterns) => { return { template, @@ -57,13 +88,12 @@ export const initLegacyModule = once((): void => { // Each time the new filters change we want to rebuild (not just re-render) the "apply filters" // popover, because it has to reset its state whenever the new filters change. Setting a `key` // property on the component accomplishes this due to how React handles the `key` property. - $scope.$watch('filters', (filters: any) => { - mapAndFlattenFilters(indexPatterns, filters).then((mappedFilters: Filter[]) => { - $scope.state = { - filters: mappedFilters, - key: Date.now(), - }; - }); + $scope.$watch('filters', async (filters: any) => { + const mappedFilters: Filter[] = await mapAndFlattenFilters(indexPatterns, filters); + $scope.state = { + filters: mappedFilters, + key: Date.now(), + }; }); }, }; diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx b/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx index 764e93a8685ea..83212a4c7c64e 100644 --- a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx +++ b/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx @@ -22,6 +22,9 @@ import { TopNavMenu } from './top_nav_menu'; import { TopNavMenuData } from './top_nav_menu_data'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { coreMock } from '../../../../../core/public/mocks'; +const setupMock = coreMock.createSetup(); + jest.mock('../../../../core_plugins/data/public', () => { return { SearchBar: () =>
, @@ -51,25 +54,31 @@ describe('TopNavMenu', () => { ]; it('Should render nothing when no config is provided', () => { - const component = shallowWithIntl(); + const component = shallowWithIntl(); expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0); expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0); }); it('Should render 1 menu item', () => { - const component = shallowWithIntl(); + const component = shallowWithIntl( + + ); expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(1); expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0); }); it('Should render multiple menu items', () => { - const component = shallowWithIntl(); + const component = shallowWithIntl( + + ); expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(menuItems.length); expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0); }); it('Should render search bar', () => { - const component = shallowWithIntl(); + const component = shallowWithIntl( + + ); expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0); expect(component.find(`span > ${SEARCH_BAR_SELECTOR}`).length).toBe(1); diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx b/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx index e0c705ece7b4b..6b1c207982873 100644 --- a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx +++ b/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx @@ -21,12 +21,14 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { I18nProvider } from '@kbn/i18n/react'; +import { UiSettingsClientContract } from 'src/core/public'; import { TopNavMenuData } from './top_nav_menu_data'; import { TopNavMenuItem } from './top_nav_menu_item'; import { SearchBar, SearchBarProps } from '../../../../core_plugins/data/public'; type Props = Partial & { name: string; + uiSettings: UiSettingsClientContract; config?: TopNavMenuData[]; showSearchBar?: boolean; }; @@ -60,6 +62,7 @@ export function TopNavMenu(props: Props) { - this.handleQueryChange(model, query)} - appName={'VisEditor'} indexPatterns={[model.index_pattern]} - store={localStorage} - showDatePicker={false} /> @@ -344,4 +339,5 @@ AnnotationsEditor.propTypes = { model: PropTypes.object, name: PropTypes.string, onChange: PropTypes.func, + uiSettings: PropTypes.object, }; diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config.js b/src/legacy/core_plugins/metrics/public/components/panel_config.js index 2a8647febb912..d1487955887b6 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config.js @@ -25,6 +25,7 @@ import { TablePanelConfig as table } from './panel_config/table'; import { GaugePanelConfig as gauge } from './panel_config/gauge'; import { MarkdownPanelConfig as markdown } from './panel_config/markdown'; import { FormattedMessage } from '@kbn/i18n/react'; + import { FormValidationContext } from '../contexts/form_validation_context'; import { VisDataContext } from '../contexts/vis_data_context'; diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js b/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js index c1f87204f614d..cc2306a5a17f9 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js @@ -43,9 +43,7 @@ import { EuiHorizontalRule, } from '@elastic/eui'; import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; class GaugePanelConfigUi extends Component { @@ -149,15 +147,13 @@ class GaugePanelConfigUi extends Component { } fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[model.index_pattern || model.default_index_pattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.test.js b/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.test.js index 35b6d244498e2..7b8a7061e8bb1 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.test.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.test.js @@ -19,6 +19,13 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; + +jest.mock('plugins/data', () => { + return { + QueryBarInput: () =>
, + }; +}); + import { GaugePanelConfig } from './gauge'; jest.mock('plugins/data', () => { diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js b/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js index f9ba313f2a4a7..b50a0d398edf6 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js @@ -44,11 +44,9 @@ import { } from '@elastic/eui'; const lessC = less(window, { env: 'production' }); import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; +import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from './../../contexts/vis_data_context'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); class MarkdownPanelConfigUi extends Component { constructor(props) { @@ -158,7 +156,7 @@ class MarkdownPanelConfigUi extends Component { } fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[model.index_pattern || model.default_index_pattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js b/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js index a34d65129cce1..6aac01a93194c 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js @@ -39,10 +39,8 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; +import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); export class MetricPanelConfig extends Component { constructor(props) { @@ -114,15 +112,13 @@ export class MetricPanelConfig extends Component { } fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[model.index_pattern || model.default_index_pattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/table.js b/src/legacy/core_plugins/metrics/public/components/panel_config/table.js index 6d1bada7b37d0..c1351952b36a6 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/table.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/table.js @@ -43,11 +43,8 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -import { QueryBarInput } from 'plugins/data'; - export class TablePanelConfig extends Component { constructor(props) { super(props); @@ -233,7 +230,7 @@ export class TablePanelConfig extends Component { } fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[model.index_pattern || model.default_index_pattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js b/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js index 9a43f1c4afd76..6b8147285ead3 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js @@ -42,10 +42,8 @@ import { EuiHorizontalRule, } from '@elastic/eui'; import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../query_bar_wrapper'; class TimeseriesPanelConfigUi extends Component { constructor(props) { super(props); @@ -186,15 +184,13 @@ class TimeseriesPanelConfigUi extends Component { } fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[model.index_pattern || model.default_index_pattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js b/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js index c562b5b4a9741..1cf17b772a1c3 100644 --- a/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js +++ b/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js @@ -42,10 +42,8 @@ import { EuiCode, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../query_bar_wrapper'; export class TopNPanelConfig extends Component { constructor(props) { @@ -142,7 +140,7 @@ export class TopNPanelConfig extends Component { } fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[model.index_pattern || model.default_index_pattern]} - store={localStorage} /> diff --git a/src/legacy/ui/public/storage/storage_service.ts b/src/legacy/core_plugins/metrics/public/components/query_bar_wrapper.js similarity index 71% rename from src/legacy/ui/public/storage/storage_service.ts rename to src/legacy/core_plugins/metrics/public/components/query_bar_wrapper.js index eb697be0ac07a..c8d81c9d2737a 100644 --- a/src/legacy/ui/public/storage/storage_service.ts +++ b/src/legacy/core_plugins/metrics/public/components/query_bar_wrapper.js @@ -17,7 +17,12 @@ * under the License. */ -import { Storage } from './storage'; +import React, { useContext } from 'react'; +import { CoreSetupContext } from '../contexts/query_input_bar_context'; +import { QueryBarInput } from 'plugins/data'; -export const localStorage = new Storage(window.localStorage); -export const sessionStorage = new Storage(window.sessionStorage); +export function QueryBarWrapper(props) { + const coreSetupContext = useContext(CoreSetupContext); + + return ; +} diff --git a/src/legacy/core_plugins/metrics/public/components/series_config.js b/src/legacy/core_plugins/metrics/public/components/series_config.js index 3dad3fb9ad89f..4937e35fd609b 100644 --- a/src/legacy/core_plugins/metrics/public/components/series_config.js +++ b/src/legacy/core_plugins/metrics/public/components/series_config.js @@ -36,10 +36,8 @@ import { EuiSpacer, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; import { getDefaultQueryLanguage } from './lib/get_default_query_language'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from './query_bar_wrapper'; export const SeriesConfig = props => { const defaults = { offset_time: '', value_template: '' }; @@ -63,7 +61,7 @@ export const SeriesConfig = props => { label={} fullWidth > - { query: model.filter && model.filter.query ? model.filter.query : '', }} onChange={filter => props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[seriesIndexPattern]} - store={localStorage} - showDatePicker={false} /> diff --git a/src/legacy/core_plugins/metrics/public/components/splits/filter.js b/src/legacy/core_plugins/metrics/public/components/splits/filter.js index 02277009313b0..cadeb3f13ae21 100644 --- a/src/legacy/core_plugins/metrics/public/components/splits/filter.js +++ b/src/legacy/core_plugins/metrics/public/components/splits/filter.js @@ -21,12 +21,10 @@ import { createSelectHandler } from '../lib/create_select_handler'; import { GroupBySelect } from './group_by_select'; import PropTypes from 'prop-types'; import React from 'react'; -import { QueryBarInput } from 'plugins/data'; -import { Storage } from 'ui/storage'; import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../query_bar_wrapper'; export const SplitByFilter = props => { const { onChange, uiRestrictions, indexPattern } = props; @@ -60,15 +58,13 @@ export const SplitByFilter = props => { /> } > - onChange({ filter })} - appName={'VisEditor'} indexPatterns={[indexPattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/splits/filter_items.js b/src/legacy/core_plugins/metrics/public/components/splits/filter_items.js index 4e27ba8eb545c..5b0e1104c7004 100644 --- a/src/legacy/core_plugins/metrics/public/components/splits/filter_items.js +++ b/src/legacy/core_plugins/metrics/public/components/splits/filter_items.js @@ -24,12 +24,10 @@ import { collectionActions } from '../lib/collection_actions'; import { AddDeleteButtons } from '../add_delete_buttons'; import { ColorPicker } from '../color_picker'; import uuid from 'uuid'; -import { QueryBarInput } from 'plugins/data'; -import { Storage } from 'ui/storage'; import { EuiFieldText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { injectI18n } from '@kbn/i18n/react'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../query_bar_wrapper'; class FilterItemsUi extends Component { constructor(props) { super(props); @@ -79,15 +77,13 @@ class FilterItemsUi extends Component { /> - this.handleQueryChange(model, query)} - appName={'VisEditor'} indexPatterns={[indexPatterns]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/vis_editor.js b/src/legacy/core_plugins/metrics/public/components/vis_editor.js index 26e3fa9e2bde9..176934da1565b 100644 --- a/src/legacy/core_plugins/metrics/public/components/vis_editor.js +++ b/src/legacy/core_plugins/metrics/public/components/vis_editor.js @@ -19,7 +19,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import chrome from 'ui/chrome'; import * as Rx from 'rxjs'; import { share } from 'rxjs/operators'; import { isEqual, isEmpty, debounce } from 'lodash'; @@ -32,8 +31,13 @@ import { brushHandler } from '../lib/create_brush_handler'; import { fetchFields } from '../lib/fetch_fields'; import { extractIndexPatterns } from '../../common/extract_index_patterns'; +import { npSetup } from 'ui/new_platform'; +import { Storage } from 'ui/storage'; +import { CoreSetupContextProvider } from '../contexts/query_input_bar_context'; +const localStorage = new Storage(window.localStorage); + const VIS_STATE_DEBOUNCE_DELAY = 200; -const queryOptions = chrome.getUiSettingsClient().get('query:allowLeadingWildcards'); +const APP_NAME = 'VisEditor'; export class VisEditor extends Component { constructor(props) { @@ -50,6 +54,14 @@ export class VisEditor extends Component { this.onBrush = brushHandler(props.vis.API.timeFilter); this.visDataSubject = new Rx.BehaviorSubject(this.props.visData); this.visData$ = this.visDataSubject.asObservable().pipe(share()); + + // In new_platform, this context should be populated with + // core dependencies required by React components downstream. + this.coreContext = { + appName: APP_NAME, + uiSettings: npSetup.core.uiSettings, + store: localStorage, + }; } get uiState() { @@ -72,6 +84,7 @@ export class VisEditor extends Component { isValidKueryQuery = filterQuery => { if (filterQuery && filterQuery.language === 'kuery') { try { + const queryOptions = this.coreContext.uiSettings.get('query:allowLeadingWildcards'); fromKueryExpression(filterQuery.query, { allowLeadingWildcards: queryOptions }); } catch (error) { return false; @@ -168,14 +181,16 @@ export class VisEditor extends Component { onDataChange={this.onDataChange} />
- + + +
); diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/table/config.js b/src/legacy/core_plugins/metrics/public/components/vis_types/table/config.js index ba83c66286df5..a9a9ec4de7bd7 100644 --- a/src/legacy/core_plugins/metrics/public/components/vis_types/table/config.js +++ b/src/legacy/core_plugins/metrics/public/components/vis_types/table/config.js @@ -40,10 +40,9 @@ import { EuiTitle, } from '@elastic/eui'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import { Storage } from 'ui/storage'; import { getDefaultQueryLanguage } from '../../lib/get_default_query_language'; -import { QueryBarInput } from 'plugins/data'; -const localStorage = new Storage(window.localStorage); + +import { QueryBarWrapper } from '../../query_bar_wrapper'; class TableSeriesConfigUI extends Component { componentWillMount() { const { model } = this.props; @@ -158,7 +157,7 @@ class TableSeriesConfigUI extends Component { label={} fullWidth > - this.props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[this.props.indexPatternForQuery]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/config.js b/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/config.js index 76bc589f5efe7..352b01a832694 100644 --- a/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/config.js +++ b/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/config.js @@ -24,8 +24,6 @@ import { createSelectHandler } from '../../lib/create_select_handler'; import { YesNo } from '../../yes_no'; import { createTextHandler } from '../../lib/create_text_handler'; import { IndexPattern } from '../../index_pattern'; -import { QueryBarInput } from 'plugins/data'; -import { Storage } from 'ui/storage'; import { htmlIdGenerator, EuiComboBox, @@ -41,7 +39,7 @@ import { } from '@elastic/eui'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; import { getDefaultQueryLanguage } from '../../lib/get_default_query_language'; -const localStorage = new Storage(window.localStorage); +import { QueryBarWrapper } from '../../query_bar_wrapper'; export const TimeseriesConfig = injectI18n(function(props) { const handleSelectChange = createSelectHandler(props.onChange); @@ -357,7 +355,7 @@ export const TimeseriesConfig = injectI18n(function(props) { label={} fullWidth > - props.onChange({ filter })} - appName={'VisEditor'} indexPatterns={[seriesIndexPattern]} - store={localStorage} /> diff --git a/src/legacy/core_plugins/metrics/public/contexts/query_input_bar_context.ts b/src/legacy/core_plugins/metrics/public/contexts/query_input_bar_context.ts new file mode 100644 index 0000000000000..f2c0837a05890 --- /dev/null +++ b/src/legacy/core_plugins/metrics/public/contexts/query_input_bar_context.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { Storage } from 'ui/storage'; +import { UiSettingsClientContract } from 'src/core/public'; + +export interface ICoreSetupContext { + appName: string; + uiSettings: UiSettingsClientContract; + store: Storage; +} + +export const CoreSetupContext = React.createContext(null); + +export const CoreSetupContextProvider = CoreSetupContext.Provider; diff --git a/src/legacy/ui/public/agg_types/buckets/filters.js b/src/legacy/ui/public/agg_types/buckets/filters.js index d7553cf81a11a..591da661b7437 100644 --- a/src/legacy/ui/public/agg_types/buckets/filters.js +++ b/src/legacy/ui/public/agg_types/buckets/filters.js @@ -50,7 +50,7 @@ export const filtersBucketAgg = new BucketAggType({ if (!_.size(inFilters)) return; inFilters.forEach((filter) => { - const persistedLog = getQueryLog('filtersAgg', filter.input.language); + const persistedLog = getQueryLog(config, 'filtersAgg', filter.input.language); persistedLog.add(filter.input.query); }); diff --git a/src/legacy/ui/public/agg_types/controls/filter.tsx b/src/legacy/ui/public/agg_types/controls/filter.tsx index ce581837eb83c..86014c50ececb 100644 --- a/src/legacy/ui/public/agg_types/controls/filter.tsx +++ b/src/legacy/ui/public/agg_types/controls/filter.tsx @@ -28,8 +28,10 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AggConfig } from 'ui/vis'; -// @ts-ignore import { Query, QueryBarInput } from 'plugins/data'; +import { npSetup } from 'ui/new_platform'; +import { Storage } from 'ui/storage'; +const localStorage = new Storage(window.localStorage); interface FilterRowProps { id: string; @@ -108,6 +110,8 @@ function FilterRow({ data-test-subj={dataTestSubj} bubbleSubmitEvent={true} languageSwitcherPopoverAnchorPosition="leftDown" + store={localStorage} + uiSettings={npSetup.core.uiSettings} /> {showCustomLabel ? ( diff --git a/src/legacy/ui/public/index_patterns/index_patterns.ts b/src/legacy/ui/public/index_patterns/index_patterns.ts index 908b03963a062..412a9b684a105 100644 --- a/src/legacy/ui/public/index_patterns/index_patterns.ts +++ b/src/legacy/ui/public/index_patterns/index_patterns.ts @@ -18,13 +18,14 @@ */ import { idx } from '@kbn/elastic-idx'; -import { SavedObjectsClientContract, SimpleSavedObject, UiSettingsClient } from 'src/core/public'; +import { SavedObjectsClientContract, SimpleSavedObject } from 'src/core/public'; // @ts-ignore import { fieldFormats } from '../registry/field_formats'; import { IndexPattern } from './_index_pattern'; import { createIndexPatternCache } from './_pattern_cache'; import { IndexPatternsApiClient } from './index_patterns_api_client'; +import { UiSettingsClientContract } from '../../../../core/public'; const indexPatternCache = createIndexPatternCache(); const apiClient = new IndexPatternsApiClient(); @@ -32,11 +33,11 @@ const apiClient = new IndexPatternsApiClient(); export class IndexPatterns { fieldFormats: fieldFormats; - private config: UiSettingsClient; + private config: UiSettingsClientContract; private savedObjectsClient: SavedObjectsClientContract; private savedObjectsCache?: Array>> | null; - constructor(config: UiSettingsClient, savedObjectsClient: SavedObjectsClientContract) { + constructor(config: UiSettingsClientContract, savedObjectsClient: SavedObjectsClientContract) { this.config = config; this.savedObjectsClient = savedObjectsClient; } diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav2.js b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav2.js index 8c1feb922a25b..e4af4192a7fd0 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav2.js +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav2.js @@ -22,6 +22,8 @@ import { wrapInI18nContext } from 'ui/i18n'; import { uiModules } from 'ui/modules'; import { TopNavMenu } from '../../../core_plugins/kibana_react/public'; import { Storage } from 'ui/storage'; +import chrome from 'ui/chrome'; + const module = uiModules.get('kibana'); @@ -44,12 +46,14 @@ module.directive('kbnTopNavV2', () => { // Pass in storage const localStorage = new Storage(window.localStorage); child.setAttribute('store', 'store'); + child.setAttribute('ui-settings', 'uiSettings'); // Append helper directive elem.append(child); const linkFn = ($scope, _, $attr) => { $scope.store = localStorage; + $scope.uiSettings = chrome.getUiSettingsClient(); // Watch config changes $scope.$watch(() => { @@ -89,6 +93,7 @@ module.directive('kbnTopNavV2Helper', (reactDirective) => { ['query', { watchDepth: 'reference' }], ['store', { watchDepth: 'reference' }], + ['uiSettings', { watchDepth: 'reference' }], ['intl', { watchDepth: 'reference' }], ['store', { watchDepth: 'reference' }], diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js index ad74b57389355..44e380b4f834c 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js @@ -92,6 +92,7 @@ export class FilterEditor extends Component { >