diff --git a/.i18nrc.json b/.i18nrc.json index 8bef2448040bf..f376b7580fad4 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -2,6 +2,7 @@ "paths": { "common.ui": "src/legacy/ui", "data": "src/legacy/core_plugins/data", + "kibana_react": "src/legacy/core_plugins/kibana_react", "server": "src/legacy/server", "console": "src/legacy/core_plugins/console", "core": "src/core", diff --git a/src/legacy/core_plugins/console/public/index.html b/src/legacy/core_plugins/console/public/index.html index f3e4b2a8708c8..91bcb05bf64cc 100644 --- a/src/legacy/core_plugins/console/public/index.html +++ b/src/legacy/core_plugins/console/public/index.html @@ -1,4 +1,7 @@ - +
diff --git a/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts b/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts index 4b9b598da8d4f..3b5fae6ff669d 100644 --- a/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts +++ b/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts @@ -28,7 +28,7 @@ import { showHelpPanel } from './help_show_panel'; export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { return [ { - key: 'history', + id: 'history', label: i18n.translate('console.topNav.historyTabLabel', { defaultMessage: 'History', }), @@ -36,12 +36,12 @@ export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { defaultMessage: 'History', }), run: () => { - toggleHistory(); + $scope.$evalAsync(toggleHistory); }, testId: 'consoleHistoryButton', }, { - key: 'settings', + id: 'settings', label: i18n.translate('console.topNav.settingsTabLabel', { defaultMessage: 'Settings', }), @@ -54,7 +54,7 @@ export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { testId: 'consoleSettingsButton', }, { - key: 'help', + id: 'help', label: i18n.translate('console.topNav.helpTabLabel', { defaultMessage: 'Help', }), diff --git a/src/legacy/core_plugins/data/public/filter/index.tsx b/src/legacy/core_plugins/data/public/filter/index.tsx index 997dae3854b4c..d4dba0d834ffe 100644 --- a/src/legacy/core_plugins/data/public/filter/index.tsx +++ b/src/legacy/core_plugins/data/public/filter/index.tsx @@ -18,3 +18,5 @@ */ export { FilterService, FilterSetup } from './filter_service'; + +export { FilterBar } from './filter_bar'; diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index 20be02510e61b..9cce64b0c5741 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -24,7 +24,6 @@ // @ts-ignore import { renderersRegistry } from 'plugins/interpreter/registries'; import { ExpressionsService, ExpressionsSetup } from './expressions'; -import { SearchService, SearchSetup } from './search'; import { QueryService, QuerySetup } from './query'; import { FilterService, FilterSetup } from './filter'; import { IndexPatternsService, IndexPatternsSetup } from './index_patterns'; @@ -34,14 +33,12 @@ export class DataPlugin { private readonly expressions: ExpressionsService; private readonly filter: FilterService; private readonly indexPatterns: IndexPatternsService; - private readonly search: SearchService; private readonly query: QueryService; constructor() { this.indexPatterns = new IndexPatternsService(); this.filter = new FilterService(); this.query = new QueryService(); - this.search = new SearchService(); this.expressions = new ExpressionsService(); } @@ -61,7 +58,6 @@ export class DataPlugin { filter: this.filter.setup({ indexPatterns: indexPatternsService.indexPatterns, }), - search: this.search.setup(), query: this.query.setup(), }; } @@ -70,7 +66,6 @@ export class DataPlugin { this.expressions.stop(); this.indexPatterns.stop(); this.filter.stop(); - this.search.stop(); this.query.stop(); } } @@ -80,7 +75,6 @@ export interface DataSetup { expressions: ExpressionsSetup; indexPatterns: IndexPatternsSetup; filter: FilterSetup; - search: SearchSetup; query: QuerySetup; } @@ -89,7 +83,8 @@ export { ExpressionRenderer, ExpressionRendererProps, ExpressionRunner } from '. /** @public types */ export { IndexPattern, StaticIndexPattern, StaticIndexPatternField, Field } from './index_patterns'; -export { Query } from './query'; +export { Query, QueryBar } from './query'; +export { FilterBar } from './filter'; export { FilterManager, FilterStateManager, uniqFilters } from './filter/filter_manager'; /** @public static code */ diff --git a/src/legacy/core_plugins/data/public/query/index.ts b/src/legacy/core_plugins/data/public/query/index.ts index 9a4d1b4f50c10..976d868241ddd 100644 --- a/src/legacy/core_plugins/data/public/query/index.ts +++ b/src/legacy/core_plugins/data/public/query/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { QueryService, QuerySetup, Query } from './query_service'; +export * from './query_service'; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar.test.tsx.snap index bc0b15ca88e3e..8680f269d93ed 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar.test.tsx.snap +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar.test.tsx.snap @@ -2,9 +2,9 @@ exports[`QueryBar Should render the given query 1`] = ` - + + + + + + + + `; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.test.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.test.tsx index 2be00deb16d9e..a612581bf7b85 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.test.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.test.tsx @@ -66,6 +66,8 @@ const mockIndexPattern = { }; describe('QueryBar', () => { + const QUERY_INPUT_SELECTOR = 'InjectIntl(QueryBarInputUI)'; + const TIMEPICKER_SELECTOR = 'EuiSuperDatePicker'; beforeEach(() => { jest.clearAllMocks(); }); @@ -102,4 +104,104 @@ describe('QueryBar', () => { expect(mockPersistedLogFactory.mock.calls[0][0]).toBe('typeahead:discover-kuery'); }); + + it('Should render only timepicker when no options provided', () => { + const component = shallowWithIntl( + + ); + + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(0); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(1); + }); + + it('Should disable timepicker when asked', () => { + const component = shallowWithIntl( + + ); + + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(0); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(0); + }); + + it('Should render timepicker with options', () => { + const component = shallowWithIntl( + + ); + + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(0); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(1); + }); + + it('Should render only query input bar', () => { + const component = shallowWithIntl( + + ); + + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(1); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(0); + }); + + it('Should NOT render query input bar if disabled', () => { + const component = shallowWithIntl( + + ); + + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(0); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(0); + }); + + it('Should NOT render query input bar if missing options', () => { + const component = shallowWithIntl( + + ); + + expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(0); + expect(component.find(TIMEPICKER_SELECTOR).length).toBe(0); + }); }); diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.tsx index e1df6286bd120..19a584e34a978 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar.tsx @@ -18,7 +18,6 @@ */ import { doesKueryExpressionHaveLuceneSyntaxError } from '@kbn/es-query'; -import { IndexPattern } from 'ui/index_patterns'; import classNames from 'classnames'; import _ from 'lodash'; @@ -37,6 +36,7 @@ import { documentationLinks } from 'ui/documentation_links'; import { Toast, toastNotifications } from 'ui/notify'; import chrome from 'ui/chrome'; import { PersistedLog } from 'ui/persisted_log'; +import { IndexPattern } from '../../../index_patterns'; import { QueryBarInput } from './query_bar_input'; import { getQueryLog } from '../lib/get_query_log'; @@ -50,15 +50,16 @@ interface DateRange { } interface Props { - query: Query; - onSubmit: (payload: { dateRange: DateRange; query: Query }) => void; + query?: Query; + onSubmit: (payload: { dateRange: DateRange; query?: Query }) => void; disableAutoFocus?: boolean; appName: string; - screenTitle: string; - indexPatterns: Array; + screenTitle?: string; + indexPatterns?: Array; store: Storage; intl: InjectedIntl; prepend?: any; + showQueryInput?: boolean; showDatePicker?: boolean; dateRangeFrom?: string; dateRangeTo?: string; @@ -70,7 +71,7 @@ interface Props { } interface State { - query: Query; + query?: Query; inputIsPristine: boolean; currentProps?: Props; dateRangeFrom: string; @@ -79,22 +80,30 @@ interface State { } export class QueryBarUI extends Component { + public static defaultProps = { + showQueryInput: true, + showDatePicker: true, + showAutoRefreshOnly: false, + }; + public static getDerivedStateFromProps(nextProps: Props, prevState: State) { if (isEqual(prevState.currentProps, nextProps)) { return null; } let nextQuery = null; - if (nextProps.query.query !== prevState.query.query) { - nextQuery = { - query: nextProps.query.query, - language: nextProps.query.language, - }; - } else if (nextProps.query.language !== prevState.query.language) { - nextQuery = { - query: '', - language: nextProps.query.language, - }; + if (nextProps.query && prevState.query) { + if (nextProps.query.query !== prevState.query.query) { + nextQuery = { + query: nextProps.query.query, + language: nextProps.query.language, + }; + } else if (nextProps.query.language !== prevState.query.language) { + nextQuery = { + query: '', + language: nextProps.query.language, + }; + } } let nextDateRange = null; @@ -134,7 +143,7 @@ export class QueryBarUI extends Component { See https://github.com/elastic/kibana/issues/14086 */ public state = { - query: { + query: this.props.query && { query: this.props.query.query, language: this.props.query.language, }, @@ -149,20 +158,26 @@ export class QueryBarUI extends Component { private persistedLog: PersistedLog | undefined; + private isQueryDirty = () => { + return ( + !!this.props.query && !!this.state.query && this.state.query.query !== this.props.query.query + ); + }; + public isDirty = () => { if (!this.props.showDatePicker) { - return this.state.query.query !== this.props.query.query; + return this.isQueryDirty(); } return ( - this.state.query.query !== this.props.query.query || + this.isQueryDirty() || this.state.dateRangeFrom !== this.props.dateRangeFrom || this.state.dateRangeTo !== this.props.dateRangeTo ); }; public onClickSubmitButton = (event: React.MouseEvent) => { - if (this.persistedLog) { + if (this.persistedLog && this.state.query) { this.persistedLog.add(this.state.query.query); } this.onSubmit(() => event.preventDefault()); @@ -209,7 +224,7 @@ export class QueryBarUI extends Component { }); this.props.onSubmit({ - query: { + query: this.state.query && { query: this.state.query.query, language: this.state.query.language, }, @@ -227,10 +242,12 @@ export class QueryBarUI extends Component { }; public componentDidMount() { + if (!this.props.query) return; this.persistedLog = getQueryLog(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); } @@ -243,25 +260,40 @@ export class QueryBarUI extends Component { return ( - - - + {this.renderQueryInput()} {this.renderUpdateButton()} ); } + private renderQueryInput() { + if (!this.shouldRenderQueryInput()) return; + return ( + + + + ); + } + + private shouldRenderDatePicker() { + return this.props.showDatePicker || this.props.showAutoRefreshOnly; + } + + private shouldRenderQueryInput() { + return this.props.showQueryInput && this.props.indexPatterns && this.props.query; + } + private renderUpdateButton() { const button = this.props.customSubmitButton ? ( React.cloneElement(this.props.customSubmitButton, { onClick: this.onClickSubmitButton }) @@ -274,7 +306,7 @@ export class QueryBarUI extends Component { /> ); - if (!this.props.showDatePicker) { + if (!this.shouldRenderDatePicker()) { return button; } @@ -287,7 +319,7 @@ export class QueryBarUI extends Component { } private renderDatePicker() { - if (!this.props.showDatePicker) { + if (!this.shouldRenderDatePicker()) { return null; } @@ -330,6 +362,7 @@ export class QueryBarUI extends Component { } private handleLuceneSyntaxWarning() { + if (!this.state.query) return; const { intl, store } = this.props; const { query, language } = this.state.query; if ( 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 30736e9fd5a5e..b2f308127b0e1 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 @@ -42,6 +42,16 @@ const mockChromeFactory = jest.fn(() => { 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: diff --git a/src/legacy/core_plugins/data/public/query/query_bar/index.ts b/src/legacy/core_plugins/data/public/query/query_bar/index.ts index c761681847c8e..d182123d401d9 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/index.ts +++ b/src/legacy/core_plugins/data/public/query/query_bar/index.ts @@ -22,7 +22,4 @@ export { fromUser } from './lib/from_user'; export { toUser } from './lib/to_user'; export { getQueryLog } from './lib/get_query_log'; -// @ts-ignore -export { setupDirective } from './directive'; - export { Query } from '../../../../../../plugins/data/common/query/types'; diff --git a/src/legacy/core_plugins/data/public/query/query_service.ts b/src/legacy/core_plugins/data/public/query/query_service.ts index be678776f7526..745fb1bac686b 100644 --- a/src/legacy/core_plugins/data/public/query/query_service.ts +++ b/src/legacy/core_plugins/data/public/query/query_service.ts @@ -17,15 +17,7 @@ * under the License. */ -import { once } from 'lodash'; -import { - QueryBar, - QueryBarInput, - fromUser, - toUser, - getQueryLog, - setupDirective as setupQueryBarDirective, -} from './query_bar'; +import { QueryBar, QueryBarInput, fromUser, toUser, getQueryLog } from './query_bar'; /** * Query Service @@ -35,7 +27,6 @@ import { export class QueryService { public setup() { return { - loadLegacyDirectives: once(setupQueryBarDirective), helpers: { fromUser, toUser, @@ -56,4 +47,4 @@ export class QueryService { /** @public */ export type QuerySetup = ReturnType; -export { Query } from './query_bar'; +export { Query, QueryBar } from './query_bar'; diff --git a/src/legacy/core_plugins/data/public/search/search_bar/directive/index.js b/src/legacy/core_plugins/data/public/search/search_bar/directive/index.js deleted file mode 100644 index 4b3546fc7d226..0000000000000 --- a/src/legacy/core_plugins/data/public/search/search_bar/directive/index.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import 'ngreact'; -import { wrapInI18nContext } from 'ui/i18n'; -import { uiModules } from 'ui/modules'; -import { SearchBar } from '../components'; - -const app = uiModules.get('app/data', ['react']); - -export function setupDirective() { - app.directive('searchBar', (reactDirective, localStorage) => { - return reactDirective( - wrapInI18nContext(SearchBar), - [ - ['query', { watchDepth: 'reference' }], - ['store', { watchDepth: 'reference' }], - ['intl', { watchDepth: 'reference' }], - - ['onQuerySubmit', { watchDepth: 'reference' }], - ['onFiltersUpdated', { watchDepth: 'reference' }], - ['onRefreshChange', { watchDepth: 'reference' }], - - ['indexPatterns', { watchDepth: 'collection' }], - ['filters', { watchDepth: 'collection' }], - - 'appName', - 'screenTitle', - 'showFilterBar', - 'showQueryBar', - 'showDatePicker', - 'dateRangeFrom', - 'dateRangeTo', - 'isRefreshPaused', - 'refreshInterval', - 'disableAutoFocus', - 'showAutoRefreshOnly', - ], - {}, - { - store: localStorage, - }, - ); - }); -} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index 1e226ab804bdc..4b77a7e3733ca 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -3,30 +3,26 @@ ng-class="{'dshAppContainer--withMargins': model.useMargins}" > - - -
- -
- -
-
-
+ + - - -
- -
-

- - - -

-
- {{(hits || 0) | number:0}} - -
-
- - -
- -
-
-
+ + +
+
- - - -
- -
+
+
+ {{ ::'kbn.visualize.linkedToSearchInfoText' | i18n: { defaultMessage: 'Linked to Saved Search' } }} + - - -
- -
-
+ {{ savedVis.savedSearch.title }} + +   + + +
- +
+ + + + - - -
-
- - - - - -
-
-
+ + + +
diff --git a/src/legacy/ui/public/kbn_top_nav/_kbn_top_nav.scss b/src/legacy/ui/public/kbn_top_nav/_kbn_top_nav.scss index 8b58691cd18ca..47fd377681c9f 100644 --- a/src/legacy/ui/public/kbn_top_nav/_kbn_top_nav.scss +++ b/src/legacy/ui/public/kbn_top_nav/_kbn_top_nav.scss @@ -2,6 +2,10 @@ * 1. Make sure the timepicker is always one right, even if the main menu doesn't exist */ +kbn-top-nav { + z-index: 5; +} + .kbnTopNav { background-color: $euiPageBackgroundColor; border-bottom: $euiBorderThin; diff --git a/src/legacy/ui/public/kbn_top_nav/index.js b/src/legacy/ui/public/kbn_top_nav/index.js index 8a93972c4b226..4bca1972e9904 100644 --- a/src/legacy/ui/public/kbn_top_nav/index.js +++ b/src/legacy/ui/public/kbn_top_nav/index.js @@ -18,3 +18,4 @@ */ import './kbn_top_nav'; +import './kbn_top_nav2'; diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js index 24d0f612dc5f7..c184301735684 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js @@ -55,7 +55,7 @@ import _ from 'lodash'; import angular from 'angular'; -import '../timepicker'; +import './timepicker'; import '../watch_multi'; import '../directives/input_focus'; import { uiModules } from '../modules'; 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 new file mode 100644 index 0000000000000..c0b886f9fb86f --- /dev/null +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav2.js @@ -0,0 +1,122 @@ +/* + * 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 'ngreact'; +import { wrapInI18nContext } from 'ui/i18n'; +import { uiModules } from 'ui/modules'; +import { TopNavMenu } from '../../../core_plugins/kibana_react/public'; +import { Storage } from 'ui/storage'; + +const module = uiModules.get('kibana'); + +module.directive('kbnTopNavV2', () => { + return { + restrict: 'E', + template: '', + compile: (elem) => { + const child = document.createElement('kbn-top-nav-v2-helper'); + + // Copy attributes to the child directive + for (const attr of elem[0].attributes) { + child.setAttribute(attr.name, attr.value); + } + + // Add a special attribute that will change every time that one + // of the config array's disableButton function return value changes. + child.setAttribute('disabled-buttons', 'disabledButtons'); + + // Pass in storage + const localStorage = new Storage(window.localStorage); + child.setAttribute('store', 'store'); + + // Append helper directive + elem.append(child); + + const linkFn = ($scope, _, $attr) => { + $scope.store = localStorage; + + // Watch config changes + $scope.$watch(() => { + const config = $scope.$eval($attr.config); + return config.map((item) => { + // Copy key into id, as it's a reserved react propery. + // This is done for Angular directive backward compatibility. + // In React only id is recognized. + if (item.key && !item.id) { + item.id = item.key; + } + + // Watch the disableButton functions + if (typeof item.disableButton === 'function') { + return item.disableButton(); + } + return item.disableButton; + }); + }, (newVal) => { + $scope.disabledButtons = newVal; + }, + true); + }; + + return linkFn; + } + }; +}); + +module.directive('kbnTopNavV2Helper', (reactDirective) => { + return reactDirective( + wrapInI18nContext(TopNavMenu), + [ + ['name', { watchDepth: 'reference' }], + ['config', { watchDepth: 'value' }], + ['disabledButtons', { watchDepth: 'reference' }], + + ['query', { watchDepth: 'reference' }], + ['store', { watchDepth: 'reference' }], + ['intl', { watchDepth: 'reference' }], + ['store', { watchDepth: 'reference' }], + + ['onQuerySubmit', { watchDepth: 'reference' }], + ['onFiltersUpdated', { watchDepth: 'reference' }], + ['onRefreshChange', { watchDepth: 'reference' }], + + ['indexPatterns', { watchDepth: 'collection' }], + ['filters', { watchDepth: 'collection' }], + + // All modifiers default to true. + // Set to false to hide subcomponents. + 'showSearchBar', + 'showFilterBar', + 'showQueryBar', + 'showQueryInput', + 'showDatePicker', + + 'showSearchBarInline', + + 'appName', + 'screenTitle', + 'dateRangeFrom', + 'dateRangeTo', + 'isRefreshPaused', + 'refreshInterval', + 'disableAutoFocus', + 'showAutoRefreshOnly', + ], + ); +}); diff --git a/src/legacy/ui/public/timepicker/index.js b/src/legacy/ui/public/kbn_top_nav/timepicker/index.js similarity index 100% rename from src/legacy/ui/public/timepicker/index.js rename to src/legacy/ui/public/kbn_top_nav/timepicker/index.js diff --git a/src/legacy/ui/public/timepicker/kbn_global_timepicker.html b/src/legacy/ui/public/kbn_top_nav/timepicker/kbn_global_timepicker.html similarity index 100% rename from src/legacy/ui/public/timepicker/kbn_global_timepicker.html rename to src/legacy/ui/public/kbn_top_nav/timepicker/kbn_global_timepicker.html diff --git a/src/legacy/ui/public/timepicker/kbn_global_timepicker.js b/src/legacy/ui/public/kbn_top_nav/timepicker/kbn_global_timepicker.js similarity index 88% rename from src/legacy/ui/public/timepicker/kbn_global_timepicker.js rename to src/legacy/ui/public/kbn_top_nav/timepicker/kbn_global_timepicker.js index 2ff0e8b1c8f54..7c60cd16b0bf3 100644 --- a/src/legacy/ui/public/timepicker/kbn_global_timepicker.js +++ b/src/legacy/ui/public/kbn_top_nav/timepicker/kbn_global_timepicker.js @@ -17,12 +17,35 @@ * under the License. */ -import { uiModules } from '../modules'; +import { uiModules } from '../../modules'; import toggleHtml from './kbn_global_timepicker.html'; import { timefilter } from 'ui/timefilter'; import { timeHistory } from 'ui/timefilter/time_history'; +import { + EuiSuperDatePicker, +} from '@elastic/eui'; + +uiModules + .get('kibana') + .directive('superDatePicker', reactDirective => reactDirective(EuiSuperDatePicker, [ + 'start', + 'end', + 'isPaused', + 'refreshInterval', + 'commonlyUsedRanges', + 'dateFormat', + 'recentlyUsedRanges', + 'onTimeChange', + 'onRefreshChange', + 'isAutoRefreshOnly', + 'commonlyUsedRanges', + 'dateFormat', + 'recentlyUsedRanges', + ])); + + uiModules .get('kibana') .directive('kbnGlobalTimepicker', (globalState, config) => { diff --git a/src/legacy/ui/public/react_components.js b/src/legacy/ui/public/react_components.js index 6a0c52a59f640..91044142e942c 100644 --- a/src/legacy/ui/public/react_components.js +++ b/src/legacy/ui/public/react_components.js @@ -19,44 +19,19 @@ import 'ngreact'; -import { - KuiToolBarSearchBox, -} from '@kbn/ui-framework/components'; - import { EuiConfirmModal, EuiIcon, EuiIconTip, - EuiCallOut, - EuiSuperDatePicker, } from '@elastic/eui'; import { uiModules } from './modules'; const app = uiModules.get('app/kibana', ['react']); -app.directive('toolBarSearchBox', reactDirective => reactDirective(KuiToolBarSearchBox)); - app.directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal)); app.directive('icon', reactDirective => reactDirective(EuiIcon)); app.directive('iconTip', reactDirective => reactDirective(EuiIconTip, ['content', 'type', 'position', 'title', 'color'])); -app.directive('callOut', reactDirective => reactDirective(EuiCallOut, ['title', 'color', 'size', 'iconType', 'children'])); - -app.directive('superDatePicker', reactDirective => reactDirective(EuiSuperDatePicker, [ - 'start', - 'end', - 'isPaused', - 'refreshInterval', - 'commonlyUsedRanges', - 'dateFormat', - 'recentlyUsedRanges', - 'onTimeChange', - 'onRefreshChange', - 'isAutoRefreshOnly', - 'commonlyUsedRanges', - 'dateFormat', - 'recentlyUsedRanges', -])); diff --git a/src/legacy/ui/public/styles/_legacy/_base.scss b/src/legacy/ui/public/styles/_legacy/_base.scss index 2cf7e1e309046..aad90a99ac357 100644 --- a/src/legacy/ui/public/styles/_legacy/_base.scss +++ b/src/legacy/ui/public/styles/_legacy/_base.scss @@ -59,8 +59,8 @@ input[type="checkbox"], padding-bottom: $euiSizeS; } - > kbn-top-nav { - z-index: 5; + .globalQueryBar { + padding: 0px $euiSizeS $euiSizeS $euiSizeS; } > nav, diff --git a/src/legacy/ui/public/timepicker/relative_options.js b/src/legacy/ui/public/timepicker/relative_options.js deleted file mode 100644 index 097eb13b8327d..0000000000000 --- a/src/legacy/ui/public/timepicker/relative_options.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export const relativeOptions = [ - { text: i18n.translate('common.ui.timepicker.relOpts.secondsAgo', { defaultMessage: 'Seconds ago' }), value: 's' }, - { text: i18n.translate('common.ui.timepicker.relOpts.minutesAgo', { defaultMessage: 'Minutes ago' }), value: 'm' }, - { text: i18n.translate('common.ui.timepicker.relOpts.hoursAgo', { defaultMessage: 'Hours ago' }), value: 'h' }, - { text: i18n.translate('common.ui.timepicker.relOpts.daysAgo', { defaultMessage: 'Days ago' }), value: 'd' }, - { text: i18n.translate('common.ui.timepicker.relOpts.weeksAgo', { defaultMessage: 'Weeks ago' }), value: 'w' }, - { text: i18n.translate('common.ui.timepicker.relOpts.monthsAgo', { defaultMessage: 'Months ago' }), value: 'M' }, - { text: i18n.translate('common.ui.timepicker.relOpts.yearsAgo', { defaultMessage: 'Years ago' }), value: 'y' }, - - { text: i18n.translate('common.ui.timepicker.relOpts.secondsFromNow', { defaultMessage: 'Seconds from now' }), value: 's+' }, - { text: i18n.translate('common.ui.timepicker.relOpts.minutesFromNow', { defaultMessage: 'Minutes from now' }), value: 'm+' }, - { text: i18n.translate('common.ui.timepicker.relOpts.hoursFromNow', { defaultMessage: 'Hours from now' }), value: 'h+' }, - { text: i18n.translate('common.ui.timepicker.relOpts.daysFromNow', { defaultMessage: 'Days from now' }), value: 'd+' }, - { text: i18n.translate('common.ui.timepicker.relOpts.weeksFromNow', { defaultMessage: 'Weeks from now' }), value: 'w+' }, - { text: i18n.translate('common.ui.timepicker.relOpts.monthsFromNow', { defaultMessage: 'Months from now' }), value: 'M+' }, - { text: i18n.translate('common.ui.timepicker.relOpts.yearsFromNow', { defaultMessage: 'Years from now' }), value: 'y+' }, - -]; diff --git a/test/functional/services/inspector.js b/test/functional/services/inspector.js index 393af9f7d5897..67d3c1113103b 100644 --- a/test/functional/services/inspector.js +++ b/test/functional/services/inspector.js @@ -30,7 +30,7 @@ export function InspectorProvider({ getService }) { return new class Inspector { async getIsEnabled() { - const ariaDisabled = await testSubjects.getAttribute('openInspectorButton', 'aria-disabled'); + const ariaDisabled = await testSubjects.getAttribute('openInspectorButton', 'disabled'); return ariaDisabled !== 'true'; } diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 89a265d81ed4b..ca29b5ae5c604 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -36,7 +36,6 @@ import 'plugins/kibana/dashboard'; import 'ui/vislib'; import 'ui/agg_response'; import 'ui/agg_types'; -import 'ui/timepicker'; import 'leaflet'; import { npStart } from 'ui/new_platform'; diff --git a/x-pack/legacy/plugins/maps/public/angular/map.html b/x-pack/legacy/plugins/maps/public/angular/map.html index c95117d906d16..13e6c038327c5 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map.html +++ b/x-pack/legacy/plugins/maps/public/angular/map.html @@ -1,30 +1,22 @@
- -
- -
- - -
-
-
-
- -
-
+ +
diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 38ad432387d24..afda01fcb7841 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -332,7 +332,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta timefilter.disableAutoRefreshSelector(); $scope.showDatePicker = true; // used by query-bar directive to enable timepikcer in query bar $scope.topNavMenu = [{ - key: i18n.translate('xpack.maps.mapController.fullScreenButtonLabel', { + id: i18n.translate('xpack.maps.mapController.fullScreenButtonLabel', { defaultMessage: `full screen` }), description: i18n.translate('xpack.maps.mapController.fullScreenDescription', { @@ -343,7 +343,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta store.dispatch(enableFullScreen()); } }, { - key: i18n.translate('xpack.maps.mapController.openInspectorButtonLabel', { + id: i18n.translate('xpack.maps.mapController.openInspectorButtonLabel', { defaultMessage: `inspect` }), description: i18n.translate('xpack.maps.mapController.openInspectorDescription', { @@ -355,7 +355,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta Inspector.open(inspectorAdapters, {}); } }, ...(capabilities.get().maps.save ? [{ - key: i18n.translate('xpack.maps.mapController.saveMapButtonLabel', { + id: i18n.translate('xpack.maps.mapController.saveMapButtonLabel', { defaultMessage: `save` }), description: i18n.translate('xpack.maps.mapController.saveMapDescription', { diff --git a/x-pack/legacy/plugins/maps/public/index.js b/x-pack/legacy/plugins/maps/public/index.js index 1afc4a2bbab3e..64f34a05272f5 100644 --- a/x-pack/legacy/plugins/maps/public/index.js +++ b/x-pack/legacy/plugins/maps/public/index.js @@ -22,7 +22,6 @@ import { capabilities } from 'ui/capabilities'; import chrome from 'ui/chrome'; import routes from 'ui/routes'; import 'ui/kbn_top_nav'; -import 'ui/angular-bootstrap'; // required for kbn-top-nav button tooltips import { uiModules } from 'ui/modules'; import { docTitle } from 'ui/doc_title'; import 'ui/autoload/styles'; @@ -36,9 +35,6 @@ import mapTemplate from './angular/map.html'; import { MapListing } from './components/map_listing'; import { recentlyAccessed } from 'ui/persisted_log'; -import { data } from 'plugins/data/setup'; -data.query.loadLegacyDirectives(); - const app = uiModules.get('app/maps', ['ngRoute', 'react']); app.directive('mapListing', function (reactDirective) { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 272f56542ac22..286fdae99f680 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -565,20 +565,6 @@ "common.ui.stateManagement.unableToParseUrlErrorMessage": "URL をパースできません", "common.ui.stateManagement.unableToRestoreUrlErrorMessage": "URL を完全に復元できません。共有機能を使用していることを確認してください。", "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。", - "common.ui.timepicker.relOpts.daysAgo": "日前", - "common.ui.timepicker.relOpts.daysFromNow": "現在からの日数", - "common.ui.timepicker.relOpts.hoursAgo": "時間前", - "common.ui.timepicker.relOpts.hoursFromNow": "現在からの時間数", - "common.ui.timepicker.relOpts.minutesAgo": "分前", - "common.ui.timepicker.relOpts.minutesFromNow": "現在からの分数", - "common.ui.timepicker.relOpts.monthsAgo": "か月前", - "common.ui.timepicker.relOpts.monthsFromNow": "現在からの月数", - "common.ui.timepicker.relOpts.secondsAgo": "秒前", - "common.ui.timepicker.relOpts.secondsFromNow": "現在からの秒数", - "common.ui.timepicker.relOpts.weeksAgo": "週間前", - "common.ui.timepicker.relOpts.weeksFromNow": "現在からの週数", - "common.ui.timepicker.relOpts.yearsAgo": "年前", - "common.ui.timepicker.relOpts.yearsFromNow": "現在からの年数", "common.ui.topNav.closeAriaLabel": "閉じる", "common.ui.topNav.toggleViewAriaLabel": "{optLabel} ビューを切り替える", "common.ui.url.replacementFailedErrorMessage": "置換に失敗、未解決の表現式: {expr}", @@ -826,9 +812,9 @@ "data.query.queryBar.syntaxOptionsDescription": "{docsLink} (KQL) は、シンプルなクエリ構文とスクリプトフィールドのサポートを提供します。また、KQL はベーシックライセンス以上をご利用の場合、自動入力も提供します。KQL をオフにすると、Kibana は Lucene を使用します。", "data.query.queryBar.syntaxOptionsDescription.docsLinkText": "こちら", "data.query.queryBar.syntaxOptionsTitle": "構文オプション", - "data.search.searchBar.filtersButtonClickToHideTitle": "選択して表示", - "data.search.searchBar.filtersButtonClickToShowTitle": "選択して非表示", - "data.search.searchBar.filtersButtonFiltersAppliedTitle": "フィルターが適用されました。", + "kibana_react.search.searchBar.filtersButtonClickToHideTitle": "選択して表示", + "kibana_react.search.searchBar.filtersButtonClickToShowTitle": "選択して非表示", + "kibana_react.search.searchBar.filtersButtonFiltersAppliedTitle": "フィルターが適用されました。", "embeddableApi.actionPanel.title": "オプション", "embeddableApi.actions.applyFilterActionTitle": "現在のビューにフィルターを適用", "embeddableApi.addPanel.createNew": "新規 {factoryName} を作成", @@ -1566,9 +1552,6 @@ "kbn.discover.notifications.notSavedSearchTitle": "検索「{savedSearchTitle}」は保存されませんでした。", "kbn.discover.notifications.savedSearchTitle": "検索「{savedSearchTitle}」が保存されました。", "kbn.discover.painlessError.painlessScriptedFieldErrorMessage": "Painless スクリプトのフィールド「{script}」のエラー.", - "kbn.discover.reloadSavedSearchAriaLabel": "保存された検索を再読み込みします", - "kbn.discover.reloadSavedSearchButton": "再読み込み", - "kbn.discover.reloadSavedSearchTooltip": "保存された検索を再読み込みします", "kbn.discover.rootBreadcrumb": "ディスカバリ", "kbn.discover.savedSearch.newSavedSearchTitle": "新しく保存された検索", "kbn.discover.savedSearch.savedObjectName": "保存された検索", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 50e156120a3dc..6a47b105c5c11 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -565,20 +565,6 @@ "common.ui.stateManagement.unableToParseUrlErrorMessage": "无法解析 URL", "common.ui.stateManagement.unableToRestoreUrlErrorMessage": "无法完整还原 URL,确保使用共享功能。", "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "Kibana 无法将历史记录项存储在您的会话中,因为其已满,并且似乎没有任何可安全删除的项。\n\n通常可通过移至新的标签页来解决此问题,但这会导致更大的问题。如果您有规律地看到此消息,请在 {gitHubIssuesUrl} 提交问题。", - "common.ui.timepicker.relOpts.daysAgo": "天前", - "common.ui.timepicker.relOpts.daysFromNow": "自现在开始的天数", - "common.ui.timepicker.relOpts.hoursAgo": "小时前", - "common.ui.timepicker.relOpts.hoursFromNow": "自现在开始的小时数", - "common.ui.timepicker.relOpts.minutesAgo": "分钟前", - "common.ui.timepicker.relOpts.minutesFromNow": "自现在开始的分钟数", - "common.ui.timepicker.relOpts.monthsAgo": "个月前", - "common.ui.timepicker.relOpts.monthsFromNow": "自现在开始的月份数", - "common.ui.timepicker.relOpts.secondsAgo": "秒前", - "common.ui.timepicker.relOpts.secondsFromNow": "自现在开始的秒数", - "common.ui.timepicker.relOpts.weeksAgo": "周前", - "common.ui.timepicker.relOpts.weeksFromNow": "自现在开始的周数", - "common.ui.timepicker.relOpts.yearsAgo": "年前", - "common.ui.timepicker.relOpts.yearsFromNow": "自现在开始的年数", "common.ui.topNav.closeAriaLabel": "关闭", "common.ui.topNav.toggleViewAriaLabel": "切换 {optLabel} 视图", "common.ui.url.replacementFailedErrorMessage": "替换失败,未解析的表达式:{expr}", @@ -826,9 +812,9 @@ "data.query.queryBar.syntaxOptionsDescription": "{docsLink} (KQL) 提供简化查询语法并支持脚本字段。如果您具有基本许可或更高级别的许可,KQL 还提供自动填充功能。如果关闭 KQL,Kibana 将使用 Lucene。", "data.query.queryBar.syntaxOptionsDescription.docsLinkText": "此处", "data.query.queryBar.syntaxOptionsTitle": "语法选项", - "data.search.searchBar.filtersButtonClickToHideTitle": "选择以显示", - "data.search.searchBar.filtersButtonClickToShowTitle": "选择以隐藏", - "data.search.searchBar.filtersButtonFiltersAppliedTitle": "个筛选已应用。", + "kibana_react.search.searchBar.filtersButtonClickToHideTitle": "选择以显示", + "kibana_react.search.searchBar.filtersButtonClickToShowTitle": "选择以隐藏", + "kibana_react.search.searchBar.filtersButtonFiltersAppliedTitle": "个筛选已应用。", "embeddableApi.actionPanel.title": "选项", "embeddableApi.actions.applyFilterActionTitle": "将筛选应用于当前视图", "embeddableApi.addPanel.createNew": "创建新的{factoryName}", @@ -1566,9 +1552,6 @@ "kbn.discover.notifications.notSavedSearchTitle": "搜索 “{savedSearchTitle}” 未保存。", "kbn.discover.notifications.savedSearchTitle": "搜索 “{savedSearchTitle}” 已保存", "kbn.discover.painlessError.painlessScriptedFieldErrorMessage": "Painless 脚本字段 “{script}” 有错误。", - "kbn.discover.reloadSavedSearchAriaLabel": "重新加载已保存搜索", - "kbn.discover.reloadSavedSearchButton": "重新加载", - "kbn.discover.reloadSavedSearchTooltip": "重新加载已保存搜索", "kbn.discover.rootBreadcrumb": "Discover", "kbn.discover.savedSearch.newSavedSearchTitle": "新保存的搜索", "kbn.discover.savedSearch.savedObjectName": "已保存搜索",