From abc98bab93a3bcdfe1e7cbb43bf63b632bbf2c60 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 17 Jul 2020 14:33:57 -0400 Subject: [PATCH 01/71] search renders but doesn't work --- src/core/public/chrome/chrome_service.tsx | 1 + .../nav_controls/nav_controls_service.ts | 17 +++- .../chrome/ui/header/collapsible_nav.tsx | 6 +- src/core/public/chrome/ui/header/header.tsx | 70 +++++++++------ .../public/chrome/ui/header/header_logo.tsx | 4 +- .../chrome/ui/header/header_nav_controls.tsx | 7 +- src/core/public/rendering/_base.scss | 15 ++-- src/plugins/console/public/styles/_app.scss | 5 -- src/plugins/dev_tools/public/index.scss | 4 - src/plugins/timelion/public/_app.scss | 4 +- x-pack/plugins/global_search_bar/kibana.json | 10 +++ .../public/components/search_bar.tsx | 88 +++++++++++++++++++ .../plugins/global_search_bar/public/index.ts | 11 +++ .../global_search_bar/public/plugin.tsx | 45 ++++++++++ x-pack/plugins/maps/public/_main.scss | 3 +- .../painless_lab/public/styles/_index.scss | 4 +- .../searchprofiler/public/styles/_index.scss | 4 +- 17 files changed, 241 insertions(+), 57 deletions(-) create mode 100644 x-pack/plugins/global_search_bar/kibana.json create mode 100644 x-pack/plugins/global_search_bar/public/components/search_bar.tsx create mode 100644 x-pack/plugins/global_search_bar/public/index.ts create mode 100644 x-pack/plugins/global_search_bar/public/plugin.tsx diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index d29120e6ee9ac..949f96c1e69ea 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -234,6 +234,7 @@ export class ChromeService { navLinks$={navLinks.getNavLinks$()} recentlyAccessed$={recentlyAccessed.get$()} navControlsLeft$={navControls.getLeft$()} + navControlsCenter$={navControls.getCenter$()} navControlsRight$={navControls.getRight$()} onIsLockedUpdate={setIsNavDrawerLocked} isLocked$={getIsNavDrawerLocked$} diff --git a/src/core/public/chrome/nav_controls/nav_controls_service.ts b/src/core/public/chrome/nav_controls/nav_controls_service.ts index 167948e01cb36..2638f40c77dc4 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -45,14 +45,18 @@ export interface ChromeNavControl { * @public */ export interface ChromeNavControls { - /** Register a nav control to be presented on the left side of the chrome header. */ + /** Register a nav control to be presented on the bottom-left side of the chrome header. */ registerLeft(navControl: ChromeNavControl): void; - /** Register a nav control to be presented on the right side of the chrome header. */ + /** Register a nav control to be presented on the top-right side of the chrome header. */ registerRight(navControl: ChromeNavControl): void; + /** Register a nav control to be presented on the top-center side of the chrome header. */ + registerCenter(navControl: ChromeNavControl): void; /** @internal */ getLeft$(): Observable; /** @internal */ getRight$(): Observable; + /** @internal */ + getCenter$(): Observable; } /** @internal */ @@ -62,6 +66,7 @@ export class NavControlsService { public start() { const navControlsLeft$ = new BehaviorSubject>(new Set()); const navControlsRight$ = new BehaviorSubject>(new Set()); + const navControlsCenter$ = new BehaviorSubject>(new Set()); return { // In the future, registration should be moved to the setup phase. This @@ -72,6 +77,9 @@ export class NavControlsService { registerRight: (navControl: ChromeNavControl) => navControlsRight$.next(new Set([...navControlsRight$.value.values(), navControl])), + registerCenter: (navControl: ChromeNavControl) => + navControlsCenter$.next(new Set([...navControlsCenter$.value.values(), navControl])), + getLeft$: () => navControlsLeft$.pipe( map((controls) => sortBy([...controls.values()], 'order')), @@ -82,6 +90,11 @@ export class NavControlsService { map((controls) => sortBy([...controls.values()], 'order')), takeUntil(this.stop$) ), + getCenter$: () => + navControlsCenter$.pipe( + map((controls) => sortBy([...controls.values()], 'order')), + takeUntil(this.stop$) + ), }; } diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx index 5abd14312f4a6..69849906ec914 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx @@ -79,7 +79,7 @@ interface Props { basePath: HttpStart['basePath']; id: string; isLocked: boolean; - isOpen: boolean; + isNavOpen: boolean; homeHref: string; legacyMode: boolean; navLinks$: Rx.Observable; @@ -95,7 +95,7 @@ export function CollapsibleNav({ basePath, id, isLocked, - isOpen, + isNavOpen, homeHref, legacyMode, storage = window.localStorage, @@ -132,7 +132,7 @@ export function CollapsibleNav({ aria-label={i18n.translate('core.ui.primaryNav.screenReaderLabel', { defaultMessage: 'Primary', })} - isOpen={isOpen} + isOpen={isNavOpen} isDocked={isLocked} onClose={closeNav} > diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 3da3caaaa4a4f..e1f0328187f25 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -103,7 +103,7 @@ export function Header({ const isVisible = useObservable(observables.isVisible$, true); const navType = useObservable(observables.navType$, 'modern'); const isLocked = useObservable(observables.isLocked$, false); - const [isOpen, setIsOpen] = useState(false); + const [isNavOpen, setIsNavOpen] = useState(false); if (!isVisible) { return ; @@ -125,6 +125,42 @@ export function Header({ <>
+ , + ], + borders: 'none', + }, + { + ...(observables.navControlsCenter$ && { + items: [], + }), + borders: 'none', + }, + { + items: [ + , + , + ], + borders: 'none', + }, + ]} + /> + {navType === 'modern' ? ( @@ -134,9 +170,9 @@ export function Header({ aria-label={i18n.translate('core.ui.primaryNav.toggleNavAriaLabel', { defaultMessage: 'Toggle primary navigation', })} - onClick={() => setIsOpen(!isOpen)} - aria-expanded={isOpen} - aria-pressed={isOpen} + onClick={() => setIsNavOpen(!isNavOpen)} + aria-expanded={isNavOpen} + aria-pressed={isNavOpen} aria-controls={navId} ref={toggleCollapsibleNavRef} > @@ -153,14 +189,7 @@ export function Header({ )} - - - + @@ -171,19 +200,6 @@ export function Header({ /> - - - - - - - - {navType === 'modern' ? ( { - setIsOpen(false); + setIsNavOpen(false); if (toggleCollapsibleNavRef.current) { toggleCollapsibleNavRef.current.focus(); } diff --git a/src/core/public/chrome/ui/header/header_logo.tsx b/src/core/public/chrome/ui/header/header_logo.tsx index 9bec946b6b76e..dee93ecb1a804 100644 --- a/src/core/public/chrome/ui/header/header_logo.tsx +++ b/src/core/public/chrome/ui/header/header_logo.tsx @@ -105,6 +105,8 @@ export function HeaderLogo({ href, navigateToApp, ...observables }: Props) { aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel', { defaultMessage: 'Go to home page', })} - /> + > + Elastic + ); } diff --git a/src/core/public/chrome/ui/header/header_nav_controls.tsx b/src/core/public/chrome/ui/header/header_nav_controls.tsx index 0941f7b27b662..8d9d8097fd8e3 100644 --- a/src/core/public/chrome/ui/header/header_nav_controls.tsx +++ b/src/core/public/chrome/ui/header/header_nav_controls.tsx @@ -26,7 +26,7 @@ import { HeaderExtension } from './header_extension'; interface Props { navControls$: Observable; - side: 'left' | 'right'; + side?: 'left' | 'right'; } export function HeaderNavControls({ navControls$, side }: Props) { @@ -41,7 +41,10 @@ export function HeaderNavControls({ navControls$, side }: Props) { return ( <> {navControls.map((navControl: ChromeNavControl, index: number) => ( - + ))} diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index 211e9c03beea5..6564b531b9c23 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -1,5 +1,8 @@ @import '@elastic/eui/src/global_styling/variables/header'; @import '@elastic/eui/src/components/nav_drawer/variables'; +@include euiHeaderAffordForFixed($euiHeaderHeightCompensation * 2); + +$headerOffset: $euiHeaderHeightCompensation * 2; /** * stretch the root element of the Kibana application to set the base-size that @@ -26,14 +29,14 @@ margin: 0 auto; &:not(.hidden-chrome) { - top: $euiHeaderChildSize; - left: $euiHeaderChildSize; + top: $headerOffset; + left: $headerOffset; // HOTFIX: Temporary fix for flyouts not inside portals // SASSTODO: Find an actual solution .euiFlyout { - top: $euiHeaderChildSize; - height: calc(100% - #{$euiHeaderChildSize}); + top: $headerOffset; + height: calc(100% - #{$headerOffset}); } @include euiBreakpoint('xs', 's') { @@ -73,12 +76,12 @@ display: flex; flex-flow: column nowrap; margin: 0 auto; - min-height: calc(100vh - #{$euiHeaderHeightCompensation}); + min-height: calc(100vh - #{$headerOffset}); @include internetExplorerOnly { // IE specific bug with min-height in flex container, described in the next link // https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items - height: calc(100vh - #{$euiHeaderHeightCompensation}); + height: calc(100vh - #{$headerOffset}); } &.hidden-chrome { diff --git a/src/plugins/console/public/styles/_app.scss b/src/plugins/console/public/styles/_app.scss index baf4cf1cbd143..3c7ab2c7c00b8 100644 --- a/src/plugins/console/public/styles/_app.scss +++ b/src/plugins/console/public/styles/_app.scss @@ -1,11 +1,6 @@ // TODO: Move all of the styles here (should be modularised by, e.g., CSS-in-JS or CSS modules). -@import '@elastic/eui/src/global_styling/variables/header'; - -// This value is calculated to static value using SCSS because calc in calc has issues in IE11 -$headerHeightOffset: $euiHeaderHeightCompensation * 2; #consoleRoot { - height: calc(100vh - #{$headerHeightOffset}); display: flex; flex: 1 1 auto; // Make sure the editor actions don't create scrollbars on this container diff --git a/src/plugins/dev_tools/public/index.scss b/src/plugins/dev_tools/public/index.scss index c9d8dc7470656..4bec602ea42db 100644 --- a/src/plugins/dev_tools/public/index.scss +++ b/src/plugins/dev_tools/public/index.scss @@ -16,10 +16,6 @@ } } -.devApp { - height: 100%; -} - .devAppWrapper { display: flex; flex-direction: column; diff --git a/src/plugins/timelion/public/_app.scss b/src/plugins/timelion/public/_app.scss index 3142e1d23cf10..f7549970598c4 100644 --- a/src/plugins/timelion/public/_app.scss +++ b/src/plugins/timelion/public/_app.scss @@ -1,8 +1,10 @@ @import '@elastic/eui/src/global_styling/variables/header'; +$headerOffset: $euiHeaderHeightCompensation * 2; + .timApp { position: relative; - min-height: calc(100vh - #{$euiHeaderChildSize}); + min-height: calc(100vh - #{$headerOffset}); background: $euiColorEmptyShade; [ng-click] { diff --git a/x-pack/plugins/global_search_bar/kibana.json b/x-pack/plugins/global_search_bar/kibana.json new file mode 100644 index 0000000000000..0b10f51b123c1 --- /dev/null +++ b/x-pack/plugins/global_search_bar/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "globalSearchBar", + "version": "8.0.0", + "kibanaVersion": "kibana", + "server": false, + "ui": true, + "requiredPlugins": ["globalSearch", "globalSearchProviders"], + "optionalPlugins": [], + "configPath": ["xpack", "global_search_bar"] +} diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx new file mode 100644 index 0000000000000..466683fab26e2 --- /dev/null +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState } from 'react'; +import { + EuiSelectable, + EuiPopover, + EuiPopoverFooter, + EuiText, + EuiFlexGroup, + EuiFlexItem, + EuiBadge, +} from '@elastic/eui'; + +export function SearchBar(globalSearch: any) { + const [isSearchFocused, setSearchFocus] = useState(false); + // console.log(globalSearch); + // globalSearch.find('discover').subscribe({ + // next: ({ results }) => { + // console.log(results); + // }, + // }); + return ( + { + setSearchFocus(true); + }, + onBlur: () => setSearchFocus(false), + placeholder: 'Search for anything...', + incremental: true, + compressed: true, + onSearch: (/* term */) => { + // console.log(globalSearch.find(term)); + }, + }} + listProps={{ + rowHeight: 68, + }} + options={[ + { label: 'hello' }, + { label: 'two' }, + // { label: 'three' }, + // { label: 'hello' }, + // { label: 'two' }, + // { label: 'three' }, + ]} + // onChange={(str) => { + // console.log(str); + // // call global search API + // // export class GlobalSearchProvidersPlugin implements Plugin<{}, {}, {}, GlobalSearchProvidersPluginStartDeps> { setup( { getStartServices }: CoreSetup<{}, {}>, { globalSearch }: GlobalSearchProvidersPluginSetupDeps ) { return {}; } start(core, { globalSearch }: GlobalSearchProvidersPluginStartDeps) { globalSearch.find('term') return {}; }} + // }} + > + {(list, search) => ( + <> + setSearchFocus(false)} + panelPaddingSize={'none'} + hasArrow={false} + > +
{list}
+ + + + + Quickly search using + + {/* TODO this is for mac only */} + Command + K + + + + +
+ + )} +
+ ); +} diff --git a/x-pack/plugins/global_search_bar/public/index.ts b/x-pack/plugins/global_search_bar/public/index.ts new file mode 100644 index 0000000000000..cb8a7da916197 --- /dev/null +++ b/x-pack/plugins/global_search_bar/public/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializer } from 'src/core/public'; +import { GlobalSearchProvidersPlugin, GlobalSearchBarPluginSetupDeps } from './plugin'; + +export const plugin: PluginInitializer<{}, {}, GlobalSearchBarPluginSetupDeps, {}> = () => + new GlobalSearchProvidersPlugin(); diff --git a/x-pack/plugins/global_search_bar/public/plugin.tsx b/x-pack/plugins/global_search_bar/public/plugin.tsx new file mode 100644 index 0000000000000..7da4aad35a1ee --- /dev/null +++ b/x-pack/plugins/global_search_bar/public/plugin.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import React from 'react'; +import { I18nProvider } from '@kbn/i18n/react'; +import ReactDOM from 'react-dom'; +import { SearchBar } from '../public/components/search_bar'; +import { GlobalSearchPluginSetup } from '../../global_search/public'; + +export interface GlobalSearchBarPluginSetupDeps { + globalSearch: GlobalSearchPluginSetup; +} + +export class GlobalSearchProvidersPlugin + implements Plugin<{}, {}, GlobalSearchBarPluginSetupDeps, {}> { + private search: GlobalSearchPluginSetup | undefined = undefined; + + public setup(coreSetup: CoreSetup<{}, {}>, { globalSearch }: GlobalSearchBarPluginSetupDeps) { + this.search = globalSearch; + return {}; + } + + public start(core: CoreStart) { + core.chrome.navControls.registerCenter({ + order: 1000, + mount: (target) => this.mount(target), + }); + return {}; + } + + private mount(targetDomElement: HTMLElement) { + ReactDOM.render( + + + , + targetDomElement + ); + + return () => ReactDOM.unmountComponentAtNode(targetDomElement); + } +} diff --git a/x-pack/plugins/maps/public/_main.scss b/x-pack/plugins/maps/public/_main.scss index 46bc66715f92a..8ef92cfe8b87f 100644 --- a/x-pack/plugins/maps/public/_main.scss +++ b/x-pack/plugins/maps/public/_main.scss @@ -1,10 +1,11 @@ @import '@elastic/eui/src/global_styling/variables/header'; +$headerOffset: $euiHeaderHeightCompensation * 2; // sass-lint:disable no-ids #maps-plugin { display: flex; flex-direction: column; - height: calc(100vh - #{$euiHeaderHeightCompensation}); + height: calc(100vh - #{$headerOffset}); width: 100%; overflow: hidden; } diff --git a/x-pack/plugins/painless_lab/public/styles/_index.scss b/x-pack/plugins/painless_lab/public/styles/_index.scss index c45b0068ded21..0a6b84523424a 100644 --- a/x-pack/plugins/painless_lab/public/styles/_index.scss +++ b/x-pack/plugins/painless_lab/public/styles/_index.scss @@ -41,10 +41,10 @@ $bottomBarHeight: $euiSize * 3; } // This value is calculated to static value using SCSS because calc in calc has issues in IE11 -$headerHeightOffset: $euiHeaderHeightCompensation * 2; +$headerOffset: $euiHeaderHeightCompensation * 3; .painlessLabMainContainer { - height: calc(100vh - #{$headerHeightOffset} - #{$bottomBarHeight}); + height: calc(100vh - #{$headerOffset} - #{$bottomBarHeight}); } .painlessLabPanelsContainer { diff --git a/x-pack/plugins/searchprofiler/public/styles/_index.scss b/x-pack/plugins/searchprofiler/public/styles/_index.scss index a33fcc9da53d5..0631966157d12 100644 --- a/x-pack/plugins/searchprofiler/public/styles/_index.scss +++ b/x-pack/plugins/searchprofiler/public/styles/_index.scss @@ -16,8 +16,6 @@ } .prfDevTool__page { - height: 100%; - display: flex; flex: 1 1 auto; &__body { @@ -48,7 +46,7 @@ } // This value is calculated to static value using SCSS because calc in calc has issues in IE11 -$headerHeightOffset: $euiHeaderHeightCompensation * 2; +$headerHeightOffset: $euiHeaderHeightCompensation * 3; .appRoot { height: calc(100vh - #{$headerHeightOffset}); From 012c19324d6af76fb95d2ba8be270e25497580fb Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 20 Jul 2020 19:19:31 -0400 Subject: [PATCH 02/71] rendering in-progress --- x-pack/plugins/global_search_bar/kibana.json | 2 +- .../public/components/search_bar.tsx | 61 ++++++++++++------- .../global_search_bar/public/plugin.tsx | 17 +++--- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/global_search_bar/kibana.json b/x-pack/plugins/global_search_bar/kibana.json index 0b10f51b123c1..2d4ffa34d346f 100644 --- a/x-pack/plugins/global_search_bar/kibana.json +++ b/x-pack/plugins/global_search_bar/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "server": false, "ui": true, - "requiredPlugins": ["globalSearch", "globalSearchProviders"], + "requiredPlugins": ["globalSearch"], "optionalPlugins": [], "configPath": ["xpack", "global_search_bar"] } diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 466683fab26e2..5c3b54aace24d 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -13,22 +13,23 @@ import { EuiFlexGroup, EuiFlexItem, EuiBadge, + EuiIcon, } from '@elastic/eui'; +import { map, takeUntil } from 'rxjs/operators'; +import { GlobalSearchResultProvider } from '../../global_search/public'; -export function SearchBar(globalSearch: any) { +export function SearchBar({ globalSearch }: GlobalSearchResultProvider) { const [isSearchFocused, setSearchFocus] = useState(false); - // console.log(globalSearch); - // globalSearch.find('discover').subscribe({ - // next: ({ results }) => { - // console.log(results); - // }, - // }); + const [options, setOptions] = useState([]); + const [isLoading, setLoadingState] = useState(false); + return ( { setSearchFocus(true); @@ -37,26 +38,42 @@ export function SearchBar(globalSearch: any) { placeholder: 'Search for anything...', incremental: true, compressed: true, - onSearch: (/* term */) => { - // console.log(globalSearch.find(term)); + onSearch: async (term) => { + const arr = []; + setLoadingState(true); + globalSearch.find(term, {}).subscribe({ + next: ({ results }) => { + arr.push(...results); + setOptions([...arr]); + }, + error: () => { + // TODO + }, + complete: () => { + setLoadingState(false); + }, + }); }, }} listProps={{ rowHeight: 68, }} - options={[ - { label: 'hello' }, - { label: 'two' }, - // { label: 'three' }, - // { label: 'hello' }, - // { label: 'two' }, - // { label: 'three' }, - ]} - // onChange={(str) => { - // console.log(str); - // // call global search API - // // export class GlobalSearchProvidersPlugin implements Plugin<{}, {}, {}, GlobalSearchProvidersPluginStartDeps> { setup( { getStartServices }: CoreSetup<{}, {}>, { globalSearch }: GlobalSearchProvidersPluginSetupDeps ) { return {}; } start(core, { globalSearch }: GlobalSearchProvidersPluginStartDeps) { globalSearch.find('term') return {}; }} - // }} + options={options.map((option) => ({ key: option.id, ...option }))} + renderOption={(option, searchValue) => ( + + {option.icon && } + {option.title} + + + Go to + + + + )} > {(list, search) => ( <> diff --git a/x-pack/plugins/global_search_bar/public/plugin.tsx b/x-pack/plugins/global_search_bar/public/plugin.tsx index 7da4aad35a1ee..5e20ea55074fc 100644 --- a/x-pack/plugins/global_search_bar/public/plugin.tsx +++ b/x-pack/plugins/global_search_bar/public/plugin.tsx @@ -4,38 +4,37 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { CoreStart, Plugin } from 'src/core/public'; import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import ReactDOM from 'react-dom'; import { SearchBar } from '../public/components/search_bar'; import { GlobalSearchPluginSetup } from '../../global_search/public'; -export interface GlobalSearchBarPluginSetupDeps { - globalSearch: GlobalSearchPluginSetup; +export interface GlobalSearchBarPluginStartDeps { + globalSearch: GlobalSearchPluginStart; } export class GlobalSearchProvidersPlugin implements Plugin<{}, {}, GlobalSearchBarPluginSetupDeps, {}> { private search: GlobalSearchPluginSetup | undefined = undefined; - public setup(coreSetup: CoreSetup<{}, {}>, { globalSearch }: GlobalSearchBarPluginSetupDeps) { - this.search = globalSearch; + public async setup() { return {}; } - public start(core: CoreStart) { + public start(core: CoreStart, { globalSearch }: GlobalSearchBarPluginStartDeps) { core.chrome.navControls.registerCenter({ order: 1000, - mount: (target) => this.mount(target), + mount: (target) => this.mount(target, globalSearch), }); return {}; } - private mount(targetDomElement: HTMLElement) { + private mount(targetDomElement: HTMLElement, globalSearch: GlobalSearchPluginStart) { ReactDOM.render( - + , targetDomElement ); From 76ae0e36400a7c5a58a6d5d790d7208504dc3ace Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 21 Jul 2020 18:15:54 -0400 Subject: [PATCH 03/71] can now navigate to search and cmd+k works --- .../public/components/search_bar.tsx | 86 ++++++++++++++----- .../global_search_bar/public/plugin.tsx | 18 ++-- 2 files changed, 76 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 5c3b54aace24d..9400cc2f6885c 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState } from 'react'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; import { EuiSelectable, EuiPopover, @@ -14,14 +14,59 @@ import { EuiFlexItem, EuiBadge, EuiIcon, + keys, } from '@elastic/eui'; -import { map, takeUntil } from 'rxjs/operators'; -import { GlobalSearchResultProvider } from '../../global_search/public'; +import { ApplicationStart } from 'kibana/public'; +import { GlobalSearchResultProvider, GlobalSearchResult } from '../../../global_search/public'; -export function SearchBar({ globalSearch }: GlobalSearchResultProvider) { +interface Props { + globalSearch: GlobalSearchResultProvider; + navigateToUrl: ApplicationStart['navigateToUrl']; +} + +export function SearchBar({ globalSearch, navigateToUrl }: Props) { const [isSearchFocused, setSearchFocus] = useState(false); - const [options, setOptions] = useState([]); + const [options, setOptions] = useState([] as GlobalSearchResult[]); const [isLoading, setLoadingState] = useState(false); + const [searchRef, setSearchRef] = useState(null); + + const onSearch = useCallback( + (term: string) => { + const arr: GlobalSearchResult[] = []; + setLoadingState(true); + globalSearch.find(term, {}).subscribe({ + next: ({ results }) => { + arr.push(...results); + setOptions([...arr]); + }, + error: () => { + // TODO + }, + complete: () => { + setLoadingState(false); + }, + }); + }, + [globalSearch] + ); + + useEffect(() => { + onSearch(''); + }, [onSearch]); + + useEffect(() => { + const openSearch = (event: KeyboardEvent) => { + if (event.key === 'k' && event.metaKey) { + // TODO if windows, use ctrl + if (searchRef) searchRef.focus(); + } + }; + window.addEventListener('keydown', openSearch); + + return () => { + window.removeEventListener('keydown', openSearch); + }; + }, [searchRef]); return ( { setSearchFocus(true); @@ -38,21 +84,8 @@ export function SearchBar({ globalSearch }: GlobalSearchResultProvider) { placeholder: 'Search for anything...', incremental: true, compressed: true, - onSearch: async (term) => { - const arr = []; - setLoadingState(true); - globalSearch.find(term, {}).subscribe({ - next: ({ results }) => { - arr.push(...results); - setOptions([...arr]); - }, - error: () => { - // TODO - }, - complete: () => { - setLoadingState(false); - }, - }); + inputRef: (ref: HTMLInputElement) => { + setSearchRef(ref); }, }} listProps={{ @@ -74,6 +107,19 @@ export function SearchBar({ globalSearch }: GlobalSearchResultProvider) { )} + onChange={(selected) => { + const { url } = selected.find(({ checked }) => checked === 'on'); + + if (typeof url === 'string') { + if (url.startsWith('https://')) { + window.location.assign(url); + } else { + navigateToUrl(url); + } + } else { + // TODO + } + }} > {(list, search) => ( <> diff --git a/x-pack/plugins/global_search_bar/public/plugin.tsx b/x-pack/plugins/global_search_bar/public/plugin.tsx index 5e20ea55074fc..109832858b59a 100644 --- a/x-pack/plugins/global_search_bar/public/plugin.tsx +++ b/x-pack/plugins/global_search_bar/public/plugin.tsx @@ -8,17 +8,15 @@ import { CoreStart, Plugin } from 'src/core/public'; import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import ReactDOM from 'react-dom'; +import { ApplicationStart } from 'kibana/public'; import { SearchBar } from '../public/components/search_bar'; -import { GlobalSearchPluginSetup } from '../../global_search/public'; +import { GlobalSearchPluginStart } from '../../global_search/public'; export interface GlobalSearchBarPluginStartDeps { globalSearch: GlobalSearchPluginStart; } -export class GlobalSearchProvidersPlugin - implements Plugin<{}, {}, GlobalSearchBarPluginSetupDeps, {}> { - private search: GlobalSearchPluginSetup | undefined = undefined; - +export class GlobalSearchProvidersPlugin implements Plugin<{}, {}> { public async setup() { return {}; } @@ -26,15 +24,19 @@ export class GlobalSearchProvidersPlugin public start(core: CoreStart, { globalSearch }: GlobalSearchBarPluginStartDeps) { core.chrome.navControls.registerCenter({ order: 1000, - mount: (target) => this.mount(target, globalSearch), + mount: (target) => this.mount(target, globalSearch, core.application.navigateToUrl), }); return {}; } - private mount(targetDomElement: HTMLElement, globalSearch: GlobalSearchPluginStart) { + private mount( + targetDomElement: HTMLElement, + globalSearch: GlobalSearchPluginStart, + navigateToUrl: ApplicationStart['navigateToUrl'] + ) { ReactDOM.render( - + , targetDomElement ); From 4a8ca958960f21ad729a5a59254a2d4609171b33 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 23 Jul 2020 12:27:23 -0400 Subject: [PATCH 04/71] Fixing i18n and cross-os keyboard shortcut --- .../public/components/search_bar.tsx | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 9400cc2f6885c..8bbf066d1ceff 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { EuiSelectable, EuiPopover, @@ -14,9 +14,9 @@ import { EuiFlexItem, EuiBadge, EuiIcon, - keys, } from '@elastic/eui'; import { ApplicationStart } from 'kibana/public'; +import { FormattedMessage } from '@kbn/i18n/react'; import { GlobalSearchResultProvider, GlobalSearchResult } from '../../../global_search/public'; interface Props { @@ -29,6 +29,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { const [options, setOptions] = useState([] as GlobalSearchResult[]); const [isLoading, setLoadingState] = useState(false); const [searchRef, setSearchRef] = useState(null); + const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; const onSearch = useCallback( (term: string) => { @@ -56,8 +57,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { useEffect(() => { const openSearch = (event: KeyboardEvent) => { - if (event.key === 'k' && event.metaKey) { - // TODO if windows, use ctrl + if (event.key === 'k' && (isWindows ? event.ctrlKey : event.metaKey)) { if (searchRef) searchRef.focus(); } }; @@ -66,7 +66,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { return () => { window.removeEventListener('keydown', openSearch); }; - }, [searchRef]); + }, [searchRef, isWindows]); return ( {list} - - - Quickly search using - - {/* TODO this is for mac only */} - Command + K + + + {isWindows ? 'Command + K' : 'Ctrl + K'}, + }} + /> From 84dbd9873599f4645d022d398564acb0f7f4b986 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 23 Jul 2020 12:27:48 -0400 Subject: [PATCH 05/71] updating jest snapshots --- .../collapsible_nav.test.tsx.snap | 1397 +-- .../header/__snapshots__/header.test.tsx.snap | 8834 +++++++++++------ .../chrome/ui/header/collapsible_nav.test.tsx | 18 +- 3 files changed, 6170 insertions(+), 4079 deletions(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 9ecbc055e3320..2a57ff56c8c43 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -122,7 +122,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` homeHref="/" id="collapsibe-nav" isLocked={false} - isOpen={true} + isNavOpen={true} legacyMode={false} navLinks$={ BehaviorSubject { @@ -3550,7 +3550,7 @@ exports[`CollapsibleNav renders the default nav 1`] = ` homeHref="/" id="collapsibe-nav" isLocked={false} - isOpen={false} + isNavOpen={false} legacyMode={false} navLinks$={ BehaviorSubject { @@ -3785,6 +3785,7 @@ exports[`CollapsibleNav renders the default nav 2`] = ` homeHref="/" id="collapsibe-nav" isLocked={false} + isNavOpen={false} isOpen={true} legacyMode={false} navLinks$={ @@ -3901,23 +3902,255 @@ exports[`CollapsibleNav renders the default nav 2`] = ` data-test-subj="collapsibleNav" id="collapsibe-nav" isDocked={false} - isOpen={true} + isOpen={false} + onClose={[Function]} + /> +
+`; + +exports[`CollapsibleNav renders the default nav 3`] = ` + + -
- - - -
-
- -
- - - - - -`; - -exports[`CollapsibleNav renders the default nav 3`] = ` - - - - - - -
- -
-
-
- - -
- } + disabled={true} onActivation={[Function]} onDeactivation={[Function]} persistentFocus={false} @@ -4946,189 +4226,6 @@ exports[`CollapsibleNav renders the default nav 3`] = ` - -
- } onActivation={[Function]} onDeactivation={[Function]} persistentFocus={false} diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index ce56b19f82cd0..c68db8d99a77f 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -2284,268 +2284,350 @@ exports[`Header renders 2`] = ` > -
- -
- -
- - - -
-
- -
- , + ], + }, + Object { + "borders": "none", + }, + Object { + "borders": "none", + "items": Array [ + - - - -
- - - - -
- - -
- - - - - - - - - - -
- -
- , + , + ], + }, + ] + } + theme="dark" + > +
+ +
+ + + + +
+ +
+ - - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} - > - -
-
- - - -
-
-
-
- -
-
-
- + -
-
-
- - + + + + } + closePopover={[Function]} + data-test-subj="helpMenuButton" + display="inlineBlock" + hasArrow={true} + id="headerHelpMenu" + isOpen={false} + ownFocus={true} + panelPaddingSize="m" + repositionOnScroll={true} + > + +
+
+ + + +
+
+
+
+ + +
+ + +
+ +
+
+
+ +
+ + +
+ +
+ +
+ + + +
+
+ +
+ + +
+ + + + + + + + + +
+ + -
- -
- -
- - - -
-
+ sections={ + Array [ + Object { + "borders": "none", + "items": Array [ + , + ], + }, + Object { + "borders": "none", + }, + Object { + "borders": "none", + "items": Array [ + , + , + ], + }, + ] + } + theme="dark" + > +
+ +
- - -
- - - - -
- - -
- - - - - - - - - + + + +
+
+
- +
- - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} + + + + } + closePopover={[Function]} + data-test-subj="helpMenuButton" + display="inlineBlock" + hasArrow={true} + id="headerHelpMenu" + isOpen={false} + ownFocus={true} + panelPaddingSize="m" + repositionOnScroll={true} + > + +
+
+ + + +
+
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+ + +
+ +
+ +
+ + - -
-
- - - - +
+ + +
+ +
+ -
-
+ "thrownError": null, + } + } + side="left" + /> +
+ + + + + + + + +
-
- -
- - -
- - - -
-
-
- -
- , + ], + }, + Object { + "borders": "none", + }, + Object { + "borders": "none", + "items": Array [ + - - - -
- - - - -
- - , + -
- - , + ], + }, + ] + } + theme="dark" + > +
+ - - - - - - - + "hasError": false, + "isStopped": false, + "observers": Array [ + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + ], + "thrownError": null, + } + } + navigateToApp={[MockFunction]} + > + + + + + +
+
- +
+ +
+ +
+
+
+
+
+ + +
+ +
+ + +
+ + + +
+
+
+ +
+
+ + + + + + + +
{ const component = mount( { const component = mount( @@ -149,9 +149,9 @@ describe('CollapsibleNav', () => { clickGroup(component, 'kibana'); clickGroup(component, 'recentlyViewed'); expectShownNavLinksCount(component, 1); - component.setProps({ isOpen: false }); + component.setProps({ isNavOpen: false }); expectNavIsClosed(component); - component.setProps({ isOpen: true }); + component.setProps({ isNavOpen: true }); expectShownNavLinksCount(component, 1); }); @@ -162,14 +162,14 @@ describe('CollapsibleNav', () => { const component = mount( ); component.setProps({ closeNav: () => { - component.setProps({ isOpen: false }); + component.setProps({ isNavOpen: false }); onClose(); }, }); @@ -177,11 +177,11 @@ describe('CollapsibleNav', () => { component.find('[data-test-subj="collapsibleNavGroup-recentlyViewed"] a').simulate('click'); expect(onClose.callCount).toEqual(1); expectNavIsClosed(component); - component.setProps({ isOpen: true }); + component.setProps({ isNavOpen: true }); component.find('[data-test-subj="collapsibleNavGroup-kibana"] a').simulate('click'); expect(onClose.callCount).toEqual(2); expectNavIsClosed(component); - component.setProps({ isOpen: true }); + component.setProps({ isNavOpen: true }); component.find('[data-test-subj="collapsibleNavGroup-noCategory"] a').simulate('click'); expect(onClose.callCount).toEqual(3); expectNavIsClosed(component); From 41908f5d1eff99f9783e5ec9d32a95431a28565a Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 23 Jul 2020 13:38:04 -0400 Subject: [PATCH 06/71] adding docs --- docs/developer/architecture/code-exploration.asciidoc | 5 +++++ x-pack/plugins/global_search_bar/README.md | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 x-pack/plugins/global_search_bar/README.md diff --git a/docs/developer/architecture/code-exploration.asciidoc b/docs/developer/architecture/code-exploration.asciidoc index f18a6c2f14926..3e800d13ad1da 100644 --- a/docs/developer/architecture/code-exploration.asciidoc +++ b/docs/developer/architecture/code-exploration.asciidoc @@ -399,6 +399,11 @@ The GlobalSearch plugin provides an easy way to search for various objects, such or dashboards from the Kibana instance, from both server and client-side plugins +- {kib-repo}blob/{branch}/x-pack/plugins/global_search_bar/README.md[globalSearchBar] + +The GlobalSearchBar plugin provides a search interface for navigating Kibana. (It is the UI to the GlobalSearch plugin.) + + - {kib-repo}blob/{branch}/x-pack/plugins/global_search_providers[globalSearchProviders] WARNING: Missing README. diff --git a/x-pack/plugins/global_search_bar/README.md b/x-pack/plugins/global_search_bar/README.md new file mode 100644 index 0000000000000..e16aac39e3f4e --- /dev/null +++ b/x-pack/plugins/global_search_bar/README.md @@ -0,0 +1,3 @@ +# Kibana GlobalSearchBar plugin + +The GlobalSearchBar plugin provides a search interface for navigating Kibana. (It is the UI to the GlobalSearch plugin.) From 35256fb75dffd411cd09cb45a28b0a946973c0b7 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 23 Jul 2020 16:26:45 -0400 Subject: [PATCH 07/71] test fixes --- src/core/public/chrome/ui/header/header.tsx | 1 + .../global_search_bar/public/components/search_bar.tsx | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index e1f0328187f25..988247c320c25 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -69,6 +69,7 @@ export interface HeaderProps { helpSupportUrl$: Observable; legacyMode: boolean; navControlsLeft$: Observable; + navControlsCenter$: Observable; navControlsRight$: Observable; basePath: HttpStart['basePath']; isLocked$: Observable; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 8bbf066d1ceff..8301bc1f87ed1 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { ApplicationStart } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { GlobalSearchResultProvider, GlobalSearchResult } from '../../../global_search/public'; interface Props { @@ -87,6 +88,9 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { inputRef: (ref: HTMLInputElement) => { setSearchRef(ref); }, + 'aria-label': i18n.translate('core.ui.primaryNav.screenReaderLabel', { + defaultMessage: 'Search for anything...', + }), }} listProps={{ rowHeight: 68, From c4acc048da70b89a686a6980378c8769306cb1f4 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 23 Jul 2020 17:31:07 -0400 Subject: [PATCH 08/71] fix header size in tests --- .../kbn-test/src/functional_test_runner/lib/config/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index e1d3bf1a8d901..701171876ad2c 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -262,7 +262,7 @@ export const schema = Joi.object() // settings for the find service layout: Joi.object() .keys({ - fixedHeaderHeight: Joi.number().default(50), + fixedHeaderHeight: Joi.number().default(100), }) .default(), From 58be5fd12759ef8dcc050a5d5a55d21b48f45f89 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 29 Jul 2020 16:12:16 -0400 Subject: [PATCH 09/71] update public api docs --- ...na-plugin-core-public.chromenavcontrols.md | 5 ++-- ...public.chromenavcontrols.registercenter.md | 24 +++++++++++++++++++ ...e-public.chromenavcontrols.registerleft.md | 2 +- ...-public.chromenavcontrols.registerright.md | 2 +- src/core/public/public.api.md | 3 +++ 5 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md index bca69adeef66b..47365782599ed 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md @@ -30,6 +30,7 @@ chrome.navControls.registerLeft({ | Method | Description | | --- | --- | -| [registerLeft(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerleft.md) | Register a nav control to be presented on the left side of the chrome header. | -| [registerRight(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerright.md) | Register a nav control to be presented on the right side of the chrome header. | +| [registerCenter(navControl)](./kibana-plugin-core-public.chromenavcontrols.registercenter.md) | Register a nav control to be presented on the top-center side of the chrome header. | +| [registerLeft(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerleft.md) | Register a nav control to be presented on the bottom-left side of the chrome header. | +| [registerRight(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerright.md) | Register a nav control to be presented on the top-right side of the chrome header. | diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md new file mode 100644 index 0000000000000..2f921050e58dd --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeNavControls](./kibana-plugin-core-public.chromenavcontrols.md) > [registerCenter](./kibana-plugin-core-public.chromenavcontrols.registercenter.md) + +## ChromeNavControls.registerCenter() method + +Register a nav control to be presented on the top-center side of the chrome header. + +Signature: + +```typescript +registerCenter(navControl: ChromeNavControl): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| navControl | ChromeNavControl | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md index c5c78bf9fb1da..514c44bd9d710 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md @@ -4,7 +4,7 @@ ## ChromeNavControls.registerLeft() method -Register a nav control to be presented on the left side of the chrome header. +Register a nav control to be presented on the bottom-left side of the chrome header. Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md index 12058f1d16ab9..eb56e0e38c6c9 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md @@ -4,7 +4,7 @@ ## ChromeNavControls.registerRight() method -Register a nav control to be presented on the right side of the chrome header. +Register a nav control to be presented on the top-right side of the chrome header. Signature: diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index c811209dfa80f..ddbf64d4f6d0b 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -391,10 +391,13 @@ export interface ChromeNavControl { // @public export interface ChromeNavControls { + // @internal (undocumented) + getCenter$(): Observable; // @internal (undocumented) getLeft$(): Observable; // @internal (undocumented) getRight$(): Observable; + registerCenter(navControl: ChromeNavControl): void; registerLeft(navControl: ChromeNavControl): void; registerRight(navControl: ChromeNavControl): void; } From faf0616c59f5ce8fd216f95afbddec36e93c80f9 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 30 Jul 2020 14:39:38 -0400 Subject: [PATCH 10/71] test fix attempt 1 --- test/functional/page_objects/time_picker.ts | 5 +++-- .../apps/maps/embeddable/tooltip_filter_actions.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index 8a726cee444c1..a712126c680c4 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -127,10 +127,11 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo await testSubjects.click('superDatePickerAbsoluteTab'); await testSubjects.click('superDatePickerAbsoluteDateInput'); await this.inputValue('superDatePickerAbsoluteDateInput', toTime); - await common.sleep(500); // set from time - await testSubjects.click('superDatePickerstartDatePopoverButton'); + await retry.try(async () => { + await testSubjects.click('superDatePickerstartDatePopoverButton'); + }); await this.waitPanelIsGone(panel); panel = await this.getTimePickerPanel(); await testSubjects.click('superDatePickerAbsoluteTab'); diff --git a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js index a996910d4787a..13c487eba99ec 100644 --- a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js +++ b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js @@ -20,7 +20,7 @@ export default function ({ getPageObjects, getService }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('dash for tooltip filter action test'); - await PageObjects.maps.lockTooltipAtPosition(200, -200); + await PageObjects.maps.lockTooltipAtPosition(200, -150); }); it('should display create filter button when tooltip is locked', async () => { From 5d3fdcd7dba0b2e3a281d33a5d7ec2afab6be730 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 30 Jul 2020 16:11:29 -0400 Subject: [PATCH 11/71] test fix attempt 2 --- test/functional/page_objects/time_picker.ts | 5 ++--- .../apps/maps/embeddable/tooltip_filter_actions.js | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index a712126c680c4..8a726cee444c1 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -127,11 +127,10 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo await testSubjects.click('superDatePickerAbsoluteTab'); await testSubjects.click('superDatePickerAbsoluteDateInput'); await this.inputValue('superDatePickerAbsoluteDateInput', toTime); + await common.sleep(500); // set from time - await retry.try(async () => { - await testSubjects.click('superDatePickerstartDatePopoverButton'); - }); + await testSubjects.click('superDatePickerstartDatePopoverButton'); await this.waitPanelIsGone(panel); panel = await this.getTimePickerPanel(); await testSubjects.click('superDatePickerAbsoluteTab'); diff --git a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js index 13c487eba99ec..cfaaa1f993355 100644 --- a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js +++ b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js @@ -20,7 +20,7 @@ export default function ({ getPageObjects, getService }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('dash for tooltip filter action test'); - await PageObjects.maps.lockTooltipAtPosition(200, -150); + await PageObjects.maps.lockTooltipAtPosition(200, -250); }); it('should display create filter button when tooltip is locked', async () => { From 35608a16c26955a7e1605452567d5ed5724beac3 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 30 Jul 2020 16:19:29 -0400 Subject: [PATCH 12/71] fixing ts issues --- src/core/public/chrome/chrome_service.mock.ts | 2 ++ src/core/public/chrome/ui/header/header.test.tsx | 1 + .../plugins/global_search_bar/public/components/search_bar.tsx | 1 + 3 files changed, 4 insertions(+) diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index c9a05ff4e08fe..961fd8c6665bc 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -53,8 +53,10 @@ const createStartContractMock = () => { }, navControls: { registerLeft: jest.fn(), + registerCenter: jest.fn(), registerRight: jest.fn(), getLeft$: jest.fn(), + getCenter$: jest.fn(), getRight$: jest.fn(), }, setAppTitle: jest.fn(), diff --git a/src/core/public/chrome/ui/header/header.test.tsx b/src/core/public/chrome/ui/header/header.test.tsx index a9fa15d43182b..cdc22f83ee8cc 100644 --- a/src/core/public/chrome/ui/header/header.test.tsx +++ b/src/core/public/chrome/ui/header/header.test.tsx @@ -52,6 +52,7 @@ function mockProps() { helpSupportUrl$: new BehaviorSubject(''), legacyMode: false, navControlsLeft$: new BehaviorSubject([]), + navControlsCenter$: new BehaviorSubject([]), navControlsRight$: new BehaviorSubject([]), basePath: http.basePath, isLocked$: new BehaviorSubject(false), diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 8301bc1f87ed1..f8696126de745 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -36,6 +36,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { (term: string) => { const arr: GlobalSearchResult[] = []; setLoadingState(true); + // @ts-ignore this is a bug, TODO, {} should be optional globalSearch.find(term, {}).subscribe({ next: ({ results }) => { arr.push(...results); From f756b3b0005b56a6142f9ce30abcaf62f0836ebb Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 30 Jul 2020 18:17:47 -0400 Subject: [PATCH 13/71] plugin test in place --- x-pack/test/plugin_functional/test_suites/global_search/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/plugin_functional/test_suites/global_search/index.ts b/x-pack/test/plugin_functional/test_suites/global_search/index.ts index d765e87add105..a54e6933be69b 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/index.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/index.ts @@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { this.tags('ciGroup7'); loadTestFile(require.resolve('./global_search_api')); loadTestFile(require.resolve('./global_search_providers')); + loadTestFile(require.resolve('./global_search_bar')); }); } From efda98955c6cf99dfbcb2c13ec8c384afb9e9e69 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 31 Jul 2020 17:43:19 -0400 Subject: [PATCH 14/71] new test --- .../global_search/global_search_bar.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts diff --git a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts new file mode 100644 index 0000000000000..a1346f8fa05e5 --- /dev/null +++ b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; +// import { GlobalSearchResult } from '../../../../plugins/global_search/common/types'; +// import { GlobalSearchTestApi } from '../../plugins/global_search_test/public/types'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { common } = getPageObjects(['common']); + // const browser = getService('browser'); + + // const findResultsWithAPI = async (t: string): Promise => { + // return browser.executeAsync(async (term, cb) => { + // const { start } = window.__coreProvider; + // const globalSearchTestApi: GlobalSearchTestApi = start.plugins.globalSearchTest; + // globalSearchTestApi.findTest(term).then(cb); + // }, t); + // }; + + describe('GlobalSearchBar', function () { + beforeEach(async function () { + // await common.navigateToApp('globalSearchTestApp'); + }); + + it('works', async () => { + // const results = await findResultsWithAPI('no_match'); + // TODO + expect(true).to.be(true); + }); + }); +} From 35b80b7fb12aba91fc7ad7569654b5aa64c1dddb Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 4 Aug 2020 18:38:03 -0400 Subject: [PATCH 15/71] move focus on new page and remove loading state --- .../public/components/search_bar.tsx | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index f8696126de745..aade3ff87fc8a 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -28,16 +28,17 @@ interface Props { export function SearchBar({ globalSearch, navigateToUrl }: Props) { const [isSearchFocused, setSearchFocus] = useState(false); const [options, setOptions] = useState([] as GlobalSearchResult[]); - const [isLoading, setLoadingState] = useState(false); + // const [isLoading, setLoadingState] = useState(false); const [searchRef, setSearchRef] = useState(null); const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; const onSearch = useCallback( (term: string) => { const arr: GlobalSearchResult[] = []; - setLoadingState(true); + // setLoadingState(true); // @ts-ignore this is a bug, TODO, {} should be optional globalSearch.find(term, {}).subscribe({ + // @ts-ignore this is a bug, TODO, TS thinks results don't exist, they exist next: ({ results }) => { arr.push(...results); setOptions([...arr]); @@ -46,7 +47,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { // TODO }, complete: () => { - setLoadingState(false); + // setLoadingState(false); }, }); }, @@ -59,8 +60,11 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { useEffect(() => { const openSearch = (event: KeyboardEvent) => { - if (event.key === 'k' && (isWindows ? event.ctrlKey : event.metaKey)) { - if (searchRef) searchRef.focus(); + if (event.key === 's' && (isWindows ? event.ctrlKey : event.metaKey)) { + if (searchRef) { + event.preventDefault(); + searchRef.focus(); + } } }; window.addEventListener('keydown', openSearch); @@ -76,7 +80,6 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { height={300} singleSelection={true} searchProps={{ - isLoading, onSearch, 'data-test-subj': 'header-search', onFocus: () => { @@ -97,7 +100,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { rowHeight: 68, }} options={options.map((option) => ({ key: option.id, ...option }))} - renderOption={(option, searchValue) => ( + renderOption={(option) => ( {option.icon && } {option.title} @@ -122,6 +125,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { } else { // else is relative path navigateToUrl(url); + (document.querySelector('a') as HTMLElement).focus(); // assumption that header link is first, is this bad assumption? } } else { // else is url obj @@ -152,7 +156,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { id="searchBar.shortcut" defaultMessage="Quickly search using {shortcut}" values={{ - shortcut: {isWindows ? 'Command + K' : 'Ctrl + K'}, + shortcut: {isWindows ? 'Command + S' : 'Ctrl + S'}, }} /> From ad565d244de4e728f32ebba238f3dd473dc85d04 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 5 Aug 2020 17:24:41 -0400 Subject: [PATCH 16/71] tests, tests, and alphabetizing initial list --- test/functional/page_objects/time_picker.ts | 4 +- test/functional/services/listing_table.ts | 2 +- x-pack/plugins/global_search/public/index.ts | 2 +- .../public/components/search_bar.tsx | 46 ++++++++++++++----- .../plugins/global_search_bar/public/index.ts | 5 +- .../maps/embeddable/tooltip_filter_actions.js | 2 +- .../global_search/global_search_bar.ts | 2 +- 7 files changed, 43 insertions(+), 20 deletions(-) diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index 8a726cee444c1..237dc8946ae0e 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -39,7 +39,7 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo const find = getService('find'); const browser = getService('browser'); const testSubjects = getService('testSubjects'); - const { header, common } = getPageObjects(['header', 'common']); + const { header } = getPageObjects(['header']); const kibanaServer = getService('kibanaServer'); class TimePicker { @@ -127,7 +127,7 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo await testSubjects.click('superDatePickerAbsoluteTab'); await testSubjects.click('superDatePickerAbsoluteDateInput'); await this.inputValue('superDatePickerAbsoluteDateInput', toTime); - await common.sleep(500); + await browser.pressKeys(browser.keys.ESCAPE); // close popover because sometimes browser can't find start input // set from time await testSubjects.click('superDatePickerstartDatePopoverButton'); diff --git a/test/functional/services/listing_table.ts b/test/functional/services/listing_table.ts index fa42eb60fa410..ad33c0649ef43 100644 --- a/test/functional/services/listing_table.ts +++ b/test/functional/services/listing_table.ts @@ -33,7 +33,7 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider */ class ListingTable { private async getSearchFilter() { - const searchFilter = await find.allByCssSelector('.euiFieldSearch'); + const searchFilter = await find.allByCssSelector('main .euiFieldSearch'); return searchFilter[0]; } diff --git a/x-pack/plugins/global_search/public/index.ts b/x-pack/plugins/global_search/public/index.ts index 18483cea72540..2092a121fbdd5 100644 --- a/x-pack/plugins/global_search/public/index.ts +++ b/x-pack/plugins/global_search/public/index.ts @@ -31,4 +31,4 @@ export { GlobalSearchPluginStart, GlobalSearchResultProvider, } from './types'; -export { GlobalSearchFindOptions } from './services/types'; +export { SearchServiceStart, GlobalSearchFindOptions } from './services'; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index aade3ff87fc8a..535e624513dbb 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -14,14 +14,15 @@ import { EuiFlexItem, EuiBadge, EuiIcon, + EuiSelectableOption, } from '@elastic/eui'; import { ApplicationStart } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { GlobalSearchResultProvider, GlobalSearchResult } from '../../../global_search/public'; +import { SearchServiceStart, GlobalSearchResult } from '../../../global_search/public'; interface Props { - globalSearch: GlobalSearchResultProvider; + globalSearch: SearchServiceStart; navigateToUrl: ApplicationStart['navigateToUrl']; } @@ -34,14 +35,34 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { const onSearch = useCallback( (term: string) => { - const arr: GlobalSearchResult[] = []; + let arr: GlobalSearchResult[] = []; // setLoadingState(true); - // @ts-ignore this is a bug, TODO, {} should be optional globalSearch.find(term, {}).subscribe({ - // @ts-ignore this is a bug, TODO, TS thinks results don't exist, they exist next: ({ results }) => { - arr.push(...results); - setOptions([...arr]); + if (results.length === 0) return; + + // if no search term, filter to only applications and sort alphabetically + if (term.length === 0) { + results = results.filter(({ type }: GlobalSearchResult) => type === 'application'); + + arr = [...results, ...arr].sort((a, b) => { + const titleA = a.title.toUpperCase(); // ignore upper and lowercase + const titleB = b.title.toUpperCase(); // ignore upper and lowercase + if (titleA < titleB) { + return -1; + } + if (titleA > titleB) { + return 1; + } + + // titles must be equal + return 0; + }); + } else { + arr.push(...results); + } + + setOptions([...arr.map((option) => ({ key: option.id, ...option }))]); }, error: () => { // TODO @@ -99,8 +120,10 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { listProps={{ rowHeight: 68, }} - options={options.map((option) => ({ key: option.id, ...option }))} - renderOption={(option) => ( + // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works + options={options} + // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works + renderOption={(option: EuiSelectableOption & GlobalSearchResult) => ( {option.icon && } {option.title} @@ -115,8 +138,9 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { )} - onChange={(selected) => { - const { url } = selected.find(({ checked }) => checked === 'on'); + // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works + onChange={(selected: Array) => { + const { url } = selected.find(({ checked }) => checked === 'on')!; if (typeof url === 'string') { if (url.startsWith('https://')) { diff --git a/x-pack/plugins/global_search_bar/public/index.ts b/x-pack/plugins/global_search_bar/public/index.ts index cb8a7da916197..758d95c7e9ba8 100644 --- a/x-pack/plugins/global_search_bar/public/index.ts +++ b/x-pack/plugins/global_search_bar/public/index.ts @@ -5,7 +5,6 @@ */ import { PluginInitializer } from 'src/core/public'; -import { GlobalSearchProvidersPlugin, GlobalSearchBarPluginSetupDeps } from './plugin'; +import { GlobalSearchProvidersPlugin } from './plugin'; -export const plugin: PluginInitializer<{}, {}, GlobalSearchBarPluginSetupDeps, {}> = () => - new GlobalSearchProvidersPlugin(); +export const plugin: PluginInitializer<{}, {}, {}, {}> = () => new GlobalSearchProvidersPlugin(); diff --git a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js index cfaaa1f993355..a996910d4787a 100644 --- a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js +++ b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js @@ -20,7 +20,7 @@ export default function ({ getPageObjects, getService }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('dash for tooltip filter action test'); - await PageObjects.maps.lockTooltipAtPosition(200, -250); + await PageObjects.maps.lockTooltipAtPosition(200, -200); }); it('should display create filter button when tooltip is locked', async () => { diff --git a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts index a1346f8fa05e5..570076bf5c955 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts @@ -10,7 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; // import { GlobalSearchTestApi } from '../../plugins/global_search_test/public/types'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const { common } = getPageObjects(['common']); + // const { common } = getPageObjects(['common']); // const browser = getService('browser'); // const findResultsWithAPI = async (t: string): Promise => { From 5544b76f793857da939194d7c50323d3b31b7c98 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 6 Aug 2020 18:08:05 -0400 Subject: [PATCH 17/71] fixing bugs --- .../public/application/ui/app_container.tsx | 4 +- .../public/components/search_bar.tsx | 104 +++++++++++------- 2 files changed, 68 insertions(+), 40 deletions(-) diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index 332c31c64b6ba..427b957673975 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -90,7 +90,9 @@ export const AppContainer: FunctionComponent = ({ // eslint-disable-next-line no-console console.error(e); } finally { - setShowSpinner(false); + if (elementRef.current) { + setShowSpinner(false); + } setIsMounting(false); } }; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 535e624513dbb..4a6d5d0b6e566 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; import { EuiSelectable, EuiPopover, @@ -21,63 +21,93 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { SearchServiceStart, GlobalSearchResult } from '../../../global_search/public'; +const useIfMounted = () => { + const isMounted = useRef(true); + useEffect( + () => () => { + isMounted.current = false; + }, + [] + ); + + const ifMounted = useCallback((func) => { + if (isMounted.current && func) { + func(); + } + }, []); + + return ifMounted; +}; + interface Props { globalSearch: SearchServiceStart; navigateToUrl: ApplicationStart['navigateToUrl']; } export function SearchBar({ globalSearch, navigateToUrl }: Props) { + const ifMounted = useIfMounted(); const [isSearchFocused, setSearchFocus] = useState(false); - const [options, setOptions] = useState([] as GlobalSearchResult[]); + const [term, setTerm] = useState(null); + const [options, _setOptions] = useState([] as GlobalSearchResult[]); // const [isLoading, setLoadingState] = useState(false); const [searchRef, setSearchRef] = useState(null); const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; const onSearch = useCallback( - (term: string) => { + (currentTerm: string) => { + if (currentTerm === term) return; + const setOptions = (_options: GlobalSearchResult[]) => { + ifMounted(() => + _setOptions([..._options.map((option) => ({ key: option.id, ...option }))]) + ); + }; + let arr: GlobalSearchResult[] = []; // setLoadingState(true); - globalSearch.find(term, {}).subscribe({ + globalSearch.find(currentTerm, {}).subscribe({ next: ({ results }) => { - if (results.length === 0) return; - - // if no search term, filter to only applications and sort alphabetically - if (term.length === 0) { - results = results.filter(({ type }: GlobalSearchResult) => type === 'application'); - - arr = [...results, ...arr].sort((a, b) => { - const titleA = a.title.toUpperCase(); // ignore upper and lowercase - const titleB = b.title.toUpperCase(); // ignore upper and lowercase - if (titleA < titleB) { - return -1; - } - if (titleA > titleB) { - return 1; - } - - // titles must be equal - return 0; - }); - } else { + // if something was searched + if (currentTerm.length > 0) { arr.push(...results); + setOptions(arr); + return; } - setOptions([...arr.map((option) => ({ key: option.id, ...option }))]); + // if searchbar is empty, filter to only applications and sort alphabetically + results = results.filter(({ type }: GlobalSearchResult) => type === 'application'); + + arr = [...results, ...arr].sort((a, b) => { + const titleA = a.title.toUpperCase(); // ignore upper and lowercase + const titleB = b.title.toUpperCase(); // ignore upper and lowercase + if (titleA < titleB) { + return -1; + } + if (titleA > titleB) { + return 1; + } + + // titles must be equal + return 0; + }); + + setOptions(arr); }, error: () => { // TODO }, complete: () => { + ifMounted(() => setTerm(currentTerm)); // setLoadingState(false); }, }); }, - [globalSearch] + [globalSearch, term, ifMounted] ); useEffect(() => { onSearch(''); - }, [onSearch]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); useEffect(() => { const openSearch = (event: KeyboardEvent) => { @@ -139,21 +169,17 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { )} // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works - onChange={(selected: Array) => { + onChange={async (selected: Array) => { const { url } = selected.find(({ checked }) => checked === 'on')!; - if (typeof url === 'string') { - if (url.startsWith('https://')) { - // if absolute path - window.location.assign(url); - } else { - // else is relative path - navigateToUrl(url); - (document.querySelector('a') as HTMLElement).focus(); // assumption that header link is first, is this bad assumption? - } + if (url.startsWith('https://')) { + // if absolute path + window.location.assign(url); } else { - // else is url obj - // TODO + // else is relative path + await navigateToUrl(url); + // a simplified "get first tabbale element" with likely subjects + (document.activeElement as HTMLElement).blur(); } }} > From acdec95373e6aa8fd5f3d8112750a4df4985394f Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 10 Aug 2020 16:43:18 -0400 Subject: [PATCH 18/71] i18n fixes --- x-pack/.i18nrc.json | 6 +++++- .../global_search_bar/public/components/search_bar.tsx | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index d0055008eb9bf..1f9e30d03c7ba 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -2,7 +2,10 @@ "prefix": "xpack", "paths": { "xpack.actions": "plugins/actions", - "xpack.uiActionsEnhanced": ["plugins/ui_actions_enhanced", "examples/ui_actions_enhanced_examples"], + "xpack.uiActionsEnhanced": [ + "plugins/ui_actions_enhanced", + "examples/ui_actions_enhanced_examples" + ], "xpack.alerts": "plugins/alerts", "xpack.alertingBuiltins": "plugins/alerting_builtins", "xpack.apm": ["legacy/plugins/apm", "plugins/apm"], @@ -20,6 +23,7 @@ "xpack.features": "plugins/features", "xpack.fileUpload": "plugins/file_upload", "xpack.globalSearch": ["plugins/global_search"], + "xpack.globalSearchBar": ["plugins/global_search_bar"], "xpack.graph": ["plugins/graph"], "xpack.grokDebugger": "plugins/grokdebugger", "xpack.idxMgmt": "plugins/index_management", diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 4a6d5d0b6e566..45240c3206f67 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -143,7 +143,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { inputRef: (ref: HTMLInputElement) => { setSearchRef(ref); }, - 'aria-label': i18n.translate('core.ui.primaryNav.screenReaderLabel', { + 'aria-label': i18n.translate('xpack.globalSearchBar.primaryNav.screenReaderLabel', { defaultMessage: 'Search for anything...', }), }} @@ -203,7 +203,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { > {isWindows ? 'Command + S' : 'Ctrl + S'}, From f3f4e67fa3569737efe6bbcf6d04d61c74728c77 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 11 Aug 2020 18:18:27 -0400 Subject: [PATCH 19/71] functional test and bug fixes --- .../public/components/search_bar.tsx | 18 +++++--- .../global_search/global_search_bar.ts | 42 ++++++++++--------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 45240c3206f67..fd0cb7551e318 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useCallback, useRef, FocusEvent } from 'react'; import { EuiSelectable, EuiPopover, @@ -51,6 +51,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { const [options, _setOptions] = useState([] as GlobalSearchResult[]); // const [isLoading, setLoadingState] = useState(false); const [searchRef, setSearchRef] = useState(null); + const [panelRef, setPanelRef] = useState(null); const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; const onSearch = useCallback( @@ -111,7 +112,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { useEffect(() => { const openSearch = (event: KeyboardEvent) => { - if (event.key === 's' && (isWindows ? event.ctrlKey : event.metaKey)) { + if (event.key === 's' && event.ctrlKey) { if (searchRef) { event.preventDefault(); searchRef.focus(); @@ -136,7 +137,11 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { onFocus: () => { setSearchFocus(true); }, - onBlur: () => setSearchFocus(false), + onBlur: (e: FocusEvent) => { + if (!panelRef?.contains(e.relatedTarget as HTMLButtonElement)) { + setSearchFocus(false); + } + }, placeholder: 'Search for anything...', incremental: true, compressed: true, @@ -154,7 +159,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { options={options} // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works renderOption={(option: EuiSelectableOption & GlobalSearchResult) => ( - + {option.icon && } {option.title} @@ -180,6 +185,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { await navigateToUrl(url); // a simplified "get first tabbale element" with likely subjects (document.activeElement as HTMLElement).blur(); + setSearchFocus(false); } }} > @@ -191,6 +197,8 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { closePopover={() => setSearchFocus(false)} panelPaddingSize={'none'} hasArrow={false} + panelRef={setPanelRef} + className="foo" >
{list}
@@ -206,7 +214,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { id="xpack.globalSearchBar.searchBar.shortcut" defaultMessage="Quickly search using {shortcut}" values={{ - shortcut: {isWindows ? 'Command + S' : 'Ctrl + S'}, + shortcut: {isWindows ? 'Ctrl + S' : 'Command + S'}, }} />
diff --git a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts index 570076bf5c955..2b7ae3e576590 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts @@ -6,30 +6,34 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; -// import { GlobalSearchResult } from '../../../../plugins/global_search/common/types'; -// import { GlobalSearchTestApi } from '../../plugins/global_search_test/public/types'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - // const { common } = getPageObjects(['common']); - // const browser = getService('browser'); - - // const findResultsWithAPI = async (t: string): Promise => { - // return browser.executeAsync(async (term, cb) => { - // const { start } = window.__coreProvider; - // const globalSearchTestApi: GlobalSearchTestApi = start.plugins.globalSearchTest; - // globalSearchTestApi.findTest(term).then(cb); - // }, t); - // }; - describe('GlobalSearchBar', function () { - beforeEach(async function () { - // await common.navigateToApp('globalSearchTestApp'); + const { common } = getPageObjects(['common']); + const find = getService('find'); + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + + before(async () => { + await common.navigateToApp('home'); }); - it('works', async () => { - // const results = await findResultsWithAPI('no_match'); - // TODO - expect(true).to.be(true); + it('basically works', async () => { + const field = await testSubjects.find('header-search'); + await field.click(); + + expect((await testSubjects.findAll('header-search-option')).length).to.be(15); + + field.type('d'); + + const options = await testSubjects.findAll('header-search-option'); + + expect(options.length).to.be(6); + + await options[1].click(); + + expect(await browser.getCurrentUrl()).to.contain('discover'); + expect(await (await find.activeElement()).getTagName()).to.be('body'); }); }); } From 54708dce6a05e8f3a30f5077b73baa34f00a70cd Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 11 Aug 2020 18:21:09 -0400 Subject: [PATCH 20/71] keyboard shortcut fix --- .../plugins/global_search_bar/public/components/search_bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index fd0cb7551e318..315b042ffbd3f 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -112,7 +112,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { useEffect(() => { const openSearch = (event: KeyboardEvent) => { - if (event.key === 's' && event.ctrlKey) { + if (event.key === 's' && (isWindows ? event.ctrlKey : event.metaKey)) { if (searchRef) { event.preventDefault(); searchRef.focus(); From cb71f832cbc18654752b69e3ce1a2e5464c3f554 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 12 Aug 2020 16:38:38 -0400 Subject: [PATCH 21/71] jest snapshot update --- .../header/__snapshots__/header.test.tsx.snap | 529 +++++++++++++++++- 1 file changed, 525 insertions(+), 4 deletions(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index c68db8d99a77f..e7f70a34d5581 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -403,6 +403,17 @@ exports[`Header renders 1`] = ` "thrownError": null, } } + navControlsCenter$={ + BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + } + } navControlsLeft$={ BehaviorSubject { "_isScalar": false, @@ -1921,6 +1932,55 @@ exports[`Header renders 2`] = ` "thrownError": null, } } + navControlsCenter$={ + BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [ + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + ], + "thrownError": null, + } + } navControlsLeft$={ BehaviorSubject { "_isScalar": false, @@ -2439,6 +2499,59 @@ exports[`Header renders 2`] = ` }, Object { "borders": "none", + "items": Array [ + , + ], }, Object { "borders": "none", @@ -3445,6 +3558,74 @@ exports[`Header renders 2`] = `
+ +
+ +
+ +
+
+
+
@@ -7130,6 +7311,55 @@ exports[`Header renders 3`] = ` "thrownError": null, } } + navControlsCenter$={ + BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [ + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + ], + "thrownError": null, + } + } navControlsLeft$={ BehaviorSubject { "_isScalar": false, @@ -7642,13 +7872,66 @@ exports[`Header renders 3`] = ` "thrownError": null, } } - navigateToApp={[MockFunction]} + navigateToApp={[MockFunction]} + />, + ], + }, + Object { + "borders": "none", + "items": Array [ + , ], }, - Object { - "borders": "none", - }, Object { "borders": "none", "items": Array [ @@ -8654,6 +8937,74 @@ exports[`Header renders 3`] = `
+ +
+ +
+ +
+
+
+
@@ -13559,6 +13910,55 @@ exports[`Header renders 4`] = ` "thrownError": null, } } + navControlsCenter$={ + BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [ + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + ], + "thrownError": null, + } + } navControlsLeft$={ BehaviorSubject { "_isScalar": false, @@ -14077,6 +14477,59 @@ exports[`Header renders 4`] = ` }, Object { "borders": "none", + "items": Array [ + , + ], }, Object { "borders": "none", @@ -15083,6 +15536,74 @@ exports[`Header renders 4`] = `
+ +
+ +
+ +
+
+
+
From f064043b0f9e98ea3f4ae99373b9290fcad39fc3 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 12 Aug 2020 16:56:07 -0400 Subject: [PATCH 22/71] clear search after navigate --- .../plugins/global_search_bar/public/components/search_bar.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 315b042ffbd3f..9b35cb0385ce0 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -185,7 +185,9 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { await navigateToUrl(url); // a simplified "get first tabbale element" with likely subjects (document.activeElement as HTMLElement).blur(); + setTerm(''); setSearchFocus(false); + searchRef.value = ''; } }} > From 1c1a76643470769ab325d0ced43a0007dcf98ebf Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 12 Aug 2020 17:36:08 -0400 Subject: [PATCH 23/71] typecheck --- .../public/components/search_bar.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 9b35cb0385ce0..f484abc3602ff 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -177,17 +177,13 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { onChange={async (selected: Array) => { const { url } = selected.find(({ checked }) => checked === 'on')!; - if (url.startsWith('https://')) { - // if absolute path - window.location.assign(url); - } else { - // else is relative path + if (url.startsWith('https://')) window.location.assign(url); + else { await navigateToUrl(url); - // a simplified "get first tabbale element" with likely subjects (document.activeElement as HTMLElement).blur(); setTerm(''); setSearchFocus(false); - searchRef.value = ''; + if (searchRef) searchRef.value = ''; } }} > @@ -200,7 +196,6 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { panelPaddingSize={'none'} hasArrow={false} panelRef={setPanelRef} - className="foo" >
{list}
From cc66bf4f692e971bcc072599ff21dc3248086c51 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 13 Aug 2020 18:40:59 -0400 Subject: [PATCH 24/71] UX fixes --- .../public/components/search_bar.tsx | 57 ++++++++++--------- .../global_search_bar/public/plugin.tsx | 2 +- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index f484abc3602ff..1866379a92653 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -40,7 +40,7 @@ const useIfMounted = () => { }; interface Props { - globalSearch: SearchServiceStart; + globalSearch: SearchServiceStart['find']; navigateToUrl: ApplicationStart['navigateToUrl']; } @@ -65,11 +65,14 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { let arr: GlobalSearchResult[] = []; // setLoadingState(true); - globalSearch.find(currentTerm, {}).subscribe({ + globalSearch(currentTerm, {}).subscribe({ next: ({ results }) => { - // if something was searched if (currentTerm.length > 0) { - arr.push(...results); + arr = [...results, ...arr].sort((a, b) => { + if (a.score < b.score) return 1; + if (a.score > b.score) return -1; + return 0; + }); setOptions(arr); return; } @@ -80,14 +83,8 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { arr = [...results, ...arr].sort((a, b) => { const titleA = a.title.toUpperCase(); // ignore upper and lowercase const titleB = b.title.toUpperCase(); // ignore upper and lowercase - if (titleA < titleB) { - return -1; - } - if (titleA > titleB) { - return 1; - } - - // titles must be equal + if (titleA < titleB) return -1; + if (titleA > titleB) return 1; return 0; }); @@ -159,19 +156,25 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { options={options} // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works renderOption={(option: EuiSelectableOption & GlobalSearchResult) => ( - - {option.icon && } - {option.title} - - - Go to - - - + <> + + {option.icon && } + + {option.title} +
+ {(option.type as string) !== 'application' && option.type} +
+ + + Go to + + +
+ )} // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works onChange={async (selected: Array) => { @@ -179,9 +182,9 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { if (url.startsWith('https://')) window.location.assign(url); else { - await navigateToUrl(url); + navigateToUrl(url); (document.activeElement as HTMLElement).blur(); - setTerm(''); + onSearch(''); setSearchFocus(false); if (searchRef) searchRef.value = ''; } diff --git a/x-pack/plugins/global_search_bar/public/plugin.tsx b/x-pack/plugins/global_search_bar/public/plugin.tsx index 109832858b59a..9d38aedd65e03 100644 --- a/x-pack/plugins/global_search_bar/public/plugin.tsx +++ b/x-pack/plugins/global_search_bar/public/plugin.tsx @@ -36,7 +36,7 @@ export class GlobalSearchProvidersPlugin implements Plugin<{}, {}> { ) { ReactDOM.render( - + , targetDomElement ); From 1feb24cc53c5dd72a9f14fb0503b33ef81e45972 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 17 Aug 2020 18:07:08 -0400 Subject: [PATCH 25/71] clearning out old nav --- src/core/public/chrome/chrome_service.tsx | 14 --- src/core/public/chrome/ui/header/_index.scss | 9 -- src/core/public/chrome/ui/header/header.tsx | 116 +++++++----------- src/core/public/rendering/_base.scss | 59 +-------- src/core/public/styles/_base.scss | 11 -- .../kibana/server/ui_setting_defaults.js | 20 --- .../management_app/components/form/_form.scss | 15 --- .../management_app/components/form/form.tsx | 17 +-- .../public/application/_dashboard_app.scss | 1 - .../components/fullscreen/fullscreen.scss | 13 +- .../public/components/search_bar.tsx | 5 +- .../create_package_config_page/index.tsx | 11 +- .../components/settings/index.tsx | 12 +- .../edit_package_config_page/index.tsx | 11 +- .../application/components/main_controls.tsx | 12 +- 15 files changed, 55 insertions(+), 271 deletions(-) delete mode 100644 src/plugins/advanced_settings/public/management_app/components/form/_form.scss diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 949f96c1e69ea..470c22ad7f3af 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -164,10 +164,6 @@ export class ChromeService { const getIsNavDrawerLocked$ = isNavDrawerLocked$.pipe(takeUntil(this.stop$)); - // TODO #64541 - // Can delete - const getNavType$ = uiSettings.get$('pageNavigation').pipe(takeUntil(this.stop$)); - const isIE = () => { const ua = window.navigator.userAgent; const msie = ua.indexOf('MSIE '); // IE 10 or older @@ -238,7 +234,6 @@ export class ChromeService { navControlsRight$={navControls.getRight$()} onIsLockedUpdate={setIsNavDrawerLocked} isLocked$={getIsNavDrawerLocked$} - navType$={getNavType$} /> ), @@ -299,8 +294,6 @@ export class ChromeService { getIsNavDrawerLocked$: () => getIsNavDrawerLocked$, - getNavType$: () => getNavType$, - getCustomNavLink$: () => customNavLink$.pipe(takeUntil(this.stop$)), setCustomNavLink: (customNavLink?: ChromeNavLink) => { @@ -462,13 +455,6 @@ export interface ChromeStart { * Get an observable of the current locked state of the nav drawer. */ getIsNavDrawerLocked$(): Observable; - - /** - * Get the navigation type - * TODO #64541 - * Can delete - */ - getNavType$(): Observable; } /** @internal */ diff --git a/src/core/public/chrome/ui/header/_index.scss b/src/core/public/chrome/ui/header/_index.scss index e3b73abbcabc2..44cd864278325 100644 --- a/src/core/public/chrome/ui/header/_index.scss +++ b/src/core/public/chrome/ui/header/_index.scss @@ -1,14 +1,5 @@ @include euiHeaderAffordForFixed; -// TODO #64541 -// Delete this block -.chrHeaderWrapper:not(.headerWrapper) { - width: 100%; - position: fixed; - top: 0; - z-index: 10; -} - .chrHeaderHelpMenu__version { text-transform: none; } diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 988247c320c25..1ba39e7307c2c 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -43,7 +43,7 @@ import { import { InternalApplicationStart } from '../../../application/types'; import { HttpStart } from '../../../http'; import { ChromeHelpExtension } from '../../chrome_service'; -import { NavType, OnIsLockedUpdate } from './'; +import { OnIsLockedUpdate } from './'; import { CollapsibleNav } from './collapsible_nav'; import { HeaderBadge } from './header_badge'; import { HeaderBreadcrumbs } from './header_breadcrumbs'; @@ -73,7 +73,6 @@ export interface HeaderProps { navControlsRight$: Observable; basePath: HttpStart['basePath']; isLocked$: Observable; - navType$: Observable; loadingCount$: ReturnType; onIsLockedUpdate: OnIsLockedUpdate; } @@ -102,7 +101,6 @@ export function Header({ ...observables }: HeaderProps) { const isVisible = useObservable(observables.isVisible$, true); - const navType = useObservable(observables.navType$, 'modern'); const isLocked = useObservable(observables.isLocked$, false); const [isNavOpen, setIsNavOpen] = useState(false); @@ -113,14 +111,7 @@ export function Header({ const navDrawerRef = createRef(); const toggleCollapsibleNavRef = createRef(); const navId = htmlIdGenerator()(); - const className = classnames( - 'chrHeaderWrapper', // TODO #64541 - delete this - 'hide-for-sharing', - { - 'chrHeaderWrapper--navIsLocked': isLocked, - headerWrapper: navType === 'modern', - } - ); + const className = classnames('hide-for-sharing'); return ( <> @@ -164,31 +155,21 @@ export function Header({ - {navType === 'modern' ? ( - - setIsNavOpen(!isNavOpen)} - aria-expanded={isNavOpen} - aria-pressed={isNavOpen} - aria-controls={navId} - ref={toggleCollapsibleNavRef} - > - - - - ) : ( - // TODO #64541 - // Delete this block - - - {renderMenuTrigger(() => navDrawerRef.current?.toggleOpen())} - - - )} + + setIsNavOpen(!isNavOpen)} + aria-expanded={isNavOpen} + aria-pressed={isNavOpen} + aria-controls={navId} + ref={toggleCollapsibleNavRef} + > + + + @@ -201,43 +182,34 @@ export function Header({ /> + + + + {/* TODO app content goes here */} + + - {navType === 'modern' ? ( - { - setIsNavOpen(false); - if (toggleCollapsibleNavRef.current) { - toggleCollapsibleNavRef.current.focus(); - } - }} - customNavLink$={observables.customNavLink$} - /> - ) : ( - // TODO #64541 - // Delete this block - - )} + + { + setIsNavOpen(false); + if (toggleCollapsibleNavRef.current) { + toggleCollapsibleNavRef.current.focus(); + } + }} + customNavLink$={observables.customNavLink$} + />
); diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index 6564b531b9c23..89a003b6be313 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -15,64 +15,7 @@ $headerOffset: $euiHeaderHeightCompensation * 2; min-height: 100%; } -// TODO #64541 -// Delete this block -.chrHeaderWrapper:not(.headerWrapper) ~ .app-wrapper { - display: flex; - flex-flow: column nowrap; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - z-index: 5; - margin: 0 auto; - - &:not(.hidden-chrome) { - top: $headerOffset; - left: $headerOffset; - - // HOTFIX: Temporary fix for flyouts not inside portals - // SASSTODO: Find an actual solution - .euiFlyout { - top: $headerOffset; - height: calc(100% - #{$headerOffset}); - } - - @include euiBreakpoint('xs', 's') { - left: 0; - } - } - - /** - * 1. Dirty, but we need to override the .kbnGlobalNav-isOpen state - * when we're looking at the log-in screen. - */ - &.hidden-chrome { - left: 0 !important; /* 1 */ - } - - .navbar-right { - margin-right: 0; - } -} - -// TODO #64541 -// Delete this block -@include euiBreakpoint('xl') { - .chrHeaderWrapper--navIsLocked:not(.headerWrapper) { - ~ .app-wrapper:not(.hidden-chrome) { - // Shrink the content from the left so it's no longer overlapped by the nav drawer (ALWAYS) - left: $euiNavDrawerWidthExpanded !important; // sass-lint:disable-line no-important - transition: left $euiAnimSpeedFast $euiAnimSlightResistance; - } - } -} - -// TODO #64541 -// Remove .headerWrapper and header conditionals -.headerWrapper ~ .app-wrapper, -:not(header) ~ .app-wrapper { +.app-wrapper { display: flex; flex-flow: column nowrap; margin: 0 auto; diff --git a/src/core/public/styles/_base.scss b/src/core/public/styles/_base.scss index 9b06b526fc7dd..9c71b3a8d5e32 100644 --- a/src/core/public/styles/_base.scss +++ b/src/core/public/styles/_base.scss @@ -1,17 +1,6 @@ @import '@elastic/eui/src/components/collapsible_nav/variables'; // Application Layout -// chrome-context -// TODO #64541 -// Delete this block -.chrHeaderWrapper:not(.headerWrapper) .content { - display: flex; - flex-flow: row nowrap; - width: 100%; - height: 100%; - overflow: hidden; -} - .application, .app-container { > * { diff --git a/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js index 625c2c02510db..4594a9e95f848 100644 --- a/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js @@ -380,25 +380,5 @@ export function getUiSettingDefaults() { category: ['accessibility'], requiresPageReload: true, }, - pageNavigation: { - name: i18n.translate('kbn.advancedSettings.pageNavigationName', { - defaultMessage: 'Side nav style', - }), - value: 'modern', - description: i18n.translate('kbn.advancedSettings.pageNavigationDesc', { - defaultMessage: 'Change the style of navigation', - }), - type: 'select', - options: ['modern', 'legacy'], - optionLabels: { - modern: i18n.translate('kbn.advancedSettings.pageNavigationModern', { - defaultMessage: 'Modern', - }), - legacy: i18n.translate('kbn.advancedSettings.pageNavigationLegacy', { - defaultMessage: 'Legacy', - }), - }, - schema: schema.oneOf([schema.literal('modern'), schema.literal('legacy')]), - }, }; } diff --git a/src/plugins/advanced_settings/public/management_app/components/form/_form.scss b/src/plugins/advanced_settings/public/management_app/components/form/_form.scss deleted file mode 100644 index 8d768d200fdd2..0000000000000 --- a/src/plugins/advanced_settings/public/management_app/components/form/_form.scss +++ /dev/null @@ -1,15 +0,0 @@ -@import '@elastic/eui/src/global_styling/variables/header'; -@import '@elastic/eui/src/components/nav_drawer/variables'; - -// TODO #64541 -// Delete this whole file -.mgtAdvancedSettingsForm__bottomBar { - margin-left: $euiNavDrawerWidthCollapsed; - z-index: 9; // Puts it inuder the nav drawer when expanded - &--pushForNav { - margin-left: $euiNavDrawerWidthExpanded; - } - @include euiBreakpoint('xs', 's') { - margin-left: 0; - } -} diff --git a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx index 5533f684870d9..bc2d44b045f6a 100644 --- a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx @@ -326,23 +326,8 @@ export class Form extends PureComponent { renderBottomBar = () => { const areChangesInvalid = this.areChangesInvalid(); - - // TODO #64541 - // Delete these classes - let bottomBarClasses = ''; - const pageNav = this.props.settings.general.find( - (setting) => setting.name === 'pageNavigation' - ); - - if (pageNav?.value === 'legacy') { - bottomBarClasses = classNames('mgtAdvancedSettingsForm__bottomBar', { - // eslint-disable-next-line @typescript-eslint/naming-convention - 'mgtAdvancedSettingsForm__bottomBar--pushForNav': - localStorage.getItem(NAV_IS_LOCKED_KEY) === 'true', - }); - } return ( - + { const isMounted = useRef(true); @@ -40,7 +40,7 @@ const useIfMounted = () => { }; interface Props { - globalSearch: SearchServiceStart['find']; + globalSearch: GlobalSearchPluginStart['find']; navigateToUrl: ApplicationStart['navigateToUrl']; } @@ -181,6 +181,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { const { url } = selected.find(({ checked }) => checked === 'on')!; if (url.startsWith('https://')) window.location.assign(url); + // TODO should we be worried about http://? else { navigateToUrl(url); (document.activeElement as HTMLElement).blur(); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx index 74cbcdca512db..6319666037ff8 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx @@ -398,16 +398,7 @@ export const CreatePackageConfigPage: React.FunctionComponent = () => { )} - {/* TODO #64541 - Remove classes */} - + {!isLoadingSecondStep && agentConfig && packageInfo && formState === 'INVALID' ? ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx index dfdd63bd984dd..0903a73b6ee0d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx @@ -152,17 +152,9 @@ export const ConfigSettingsView = memo<{ config: AgentConfig }>( history.push(getPath('configurations_list')); }} /> - {/* TODO #64541 - Remove classes */} + {hasChanges ? ( - + { )} {configurePackage} - {/* TODO #64541 - Remove classes */} - + {agentConfig && packageInfo && formState === 'INVALID' ? ( diff --git a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx index 4d44ae0176103..4e4bca363e374 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx @@ -88,18 +88,8 @@ export function MainControls({ , ]; - // TODO #64541 - // Can delete all this class stuff - let classes = ''; - if (isNavLegacy) { - classes = classNames('painlessLab__bottomBar', { - // eslint-disable-next-line @typescript-eslint/naming-convention - 'painlessLab__bottomBar-isNavDrawerLocked': isNavDrawerLocked, - }); - } - return ( - + From 7b7a92543ccac529d174feb1c9e1d870f27e0fb0 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 18 Aug 2020 10:37:31 -0400 Subject: [PATCH 26/71] adding jest tests --- .../__snapshots__/search_bar.test.tsx.snap | 296 ++++++++++++++++++ .../public/components/search_bar.test.tsx | 42 +++ 2 files changed, 338 insertions(+) create mode 100644 x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap create mode 100644 x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap new file mode 100644 index 0000000000000..934ffa1d200ed --- /dev/null +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -0,0 +1,296 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SearchBar basically works 1`] = ` + + +
+ + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={false} + isOpen={false} + ownFocus={false} + panelPaddingSize="none" + panelRef={[Function]} + > + +
+
+ + + +
+
+ + + + +
+ + +
+
+ + + +
+
+ + +
+ + +`; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx new file mode 100644 index 0000000000000..edd626a0a4362 --- /dev/null +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { SearchBar } from '../components/search_bar'; +import { globalSearchPluginMock } from '../../../global_search/public/mocks'; +import { GlobalSearchPluginStart } from '../../../global_search/public'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; + +describe('SearchBar', () => { + let searchService: GlobalSearchPluginStart; + let findSpy: jest.SpyInstance; + + beforeEach(() => { + searchService = globalSearchPluginMock.createStartContract(); + findSpy = jest.spyOn(globalSearchPluginMock, 'createStartContract'); + }); + + it('basically works', async () => { + const component = mountWithIntl( + + ); + expect(component).toMatchSnapshot(); // popover closed + // expect(findSpy).toHaveBeenCalledTimes(1); + // expect(findSpy).toHaveBeenCalledWith(''); + + // component.find('input[data-test-subj="header-search"]').simulate('keydown', { key: 'd' }); + // expect(component).toMatchSnapshot(); // popover open + // expect(findSpy).toHaveBeenCalledTimes(1); + // expect(findSpy).toHaveBeenCalledWith('d'); + + // click on result + // navigate to new page + // click into into search bar, results rendered like new + }); + it('supports keyboard shortcuts', () => { + // cmd/ctrl+s focuses search bar, popover opens, results rendered + }); +}); From 52f5fc0ab647815176a7b3a40b3cb0ebf331894d Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 18 Aug 2020 10:55:17 -0400 Subject: [PATCH 27/71] removing leftover empty sass files --- .../public/management_app/components/_index.scss | 1 - .../public/management_app/components/form/_index.scss | 1 - src/plugins/advanced_settings/public/management_app/index.scss | 2 -- 3 files changed, 4 deletions(-) delete mode 100644 src/plugins/advanced_settings/public/management_app/components/_index.scss delete mode 100644 src/plugins/advanced_settings/public/management_app/components/form/_index.scss diff --git a/src/plugins/advanced_settings/public/management_app/components/_index.scss b/src/plugins/advanced_settings/public/management_app/components/_index.scss deleted file mode 100644 index d2d2e38947f76..0000000000000 --- a/src/plugins/advanced_settings/public/management_app/components/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './form/index'; diff --git a/src/plugins/advanced_settings/public/management_app/components/form/_index.scss b/src/plugins/advanced_settings/public/management_app/components/form/_index.scss deleted file mode 100644 index 2ef4ef1d20ce9..0000000000000 --- a/src/plugins/advanced_settings/public/management_app/components/form/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './form'; diff --git a/src/plugins/advanced_settings/public/management_app/index.scss b/src/plugins/advanced_settings/public/management_app/index.scss index aa1980692f7b7..5f473c519dda6 100644 --- a/src/plugins/advanced_settings/public/management_app/index.scss +++ b/src/plugins/advanced_settings/public/management_app/index.scss @@ -1,3 +1 @@ @import './advanced_settings'; - -@import './components/index'; From b72b9ffaf8aa8aa5cb3cc014da6715d1cc073e39 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 18 Aug 2020 17:10:33 -0400 Subject: [PATCH 28/71] fixing all the tests --- ...gin-core-public.chromestart.getnavtype_.md | 17 -- .../kibana-plugin-core-public.chromestart.md | 1 - ...kibana-plugin-core-public.doclinksstart.md | 2 +- src/core/public/chrome/chrome_service.mock.ts | 2 - src/core/public/chrome/chrome_service.tsx | 1 - .../public/chrome/ui/header/header.test.tsx | 8 - src/core/public/chrome/ui/header/header.tsx | 17 -- .../public/chrome/ui/header/nav_drawer.tsx | 85 --------- src/core/public/public.api.md | 1 - .../management_app/components/form/form.tsx | 2 - .../__snapshots__/asset.stories.storyshot | 178 ------------------ .../__snapshots__/search_bar.test.tsx.snap | 168 +++++++++-------- .../public/application/components/main.tsx | 1 - .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - x-pack/test/accessibility/config.ts | 11 +- 16 files changed, 99 insertions(+), 403 deletions(-) delete mode 100644 docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md delete mode 100644 src/core/public/chrome/ui/header/nav_drawer.tsx diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md deleted file mode 100644 index 09864be43996d..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md +++ /dev/null @@ -1,17 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeStart](./kibana-plugin-core-public.chromestart.md) > [getNavType$](./kibana-plugin-core-public.chromestart.getnavtype_.md) - -## ChromeStart.getNavType$() method - -Get the navigation type TODO \#64541 Can delete - -Signature: - -```typescript -getNavType$(): Observable; -``` -Returns: - -`Observable` - diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.md index e983ad50d2afe..2594848ef0847 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromestart.md @@ -59,7 +59,6 @@ core.chrome.setHelpExtension(elem => { | [getHelpExtension$()](./kibana-plugin-core-public.chromestart.gethelpextension_.md) | Get an observable of the current custom help conttent | | [getIsNavDrawerLocked$()](./kibana-plugin-core-public.chromestart.getisnavdrawerlocked_.md) | Get an observable of the current locked state of the nav drawer. | | [getIsVisible$()](./kibana-plugin-core-public.chromestart.getisvisible_.md) | Get an observable of the current visibility state of the chrome. | -| [getNavType$()](./kibana-plugin-core-public.chromestart.getnavtype_.md) | Get the navigation type TODO \#64541 Can delete | | [removeApplicationClass(className)](./kibana-plugin-core-public.chromestart.removeapplicationclass.md) | Remove a className added with addApplicationClass(). If className is unknown it is ignored. | | [setAppTitle(appTitle)](./kibana-plugin-core-public.chromestart.setapptitle.md) | Sets the current app's title | | [setBadge(badge)](./kibana-plugin-core-public.chromestart.setbadge.md) | Override the current badge | diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index fa2d9090e3159..4644dc432bc9a 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly drilldowns: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly drilldowns: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly visualize: Record<string, string>;
} | | diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 961fd8c6665bc..40e50c4d9dbad 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -75,7 +75,6 @@ const createStartContractMock = () => { setHelpExtension: jest.fn(), setHelpSupportUrl: jest.fn(), getIsNavDrawerLocked$: jest.fn(), - getNavType$: jest.fn(), getCustomNavLink$: jest.fn(), setCustomNavLink: jest.fn(), }; @@ -88,7 +87,6 @@ const createStartContractMock = () => { startContract.getCustomNavLink$.mockReturnValue(new BehaviorSubject(undefined)); startContract.getHelpExtension$.mockReturnValue(new BehaviorSubject(undefined)); startContract.getIsNavDrawerLocked$.mockReturnValue(new BehaviorSubject(false)); - startContract.getNavType$.mockReturnValue(new BehaviorSubject('modern' as NavType)); return startContract; }; diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 470c22ad7f3af..154de8b978360 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -37,7 +37,6 @@ import { ChromeNavControls, NavControlsService } from './nav_controls'; import { ChromeNavLinks, NavLinksService, ChromeNavLink } from './nav_links'; import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed'; import { Header } from './ui'; -import { NavType } from './ui/header'; import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; diff --git a/src/core/public/chrome/ui/header/header.test.tsx b/src/core/public/chrome/ui/header/header.test.tsx index cdc22f83ee8cc..2a921bd562f8d 100644 --- a/src/core/public/chrome/ui/header/header.test.tsx +++ b/src/core/public/chrome/ui/header/header.test.tsx @@ -21,7 +21,6 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { BehaviorSubject } from 'rxjs'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { NavType } from '.'; import { httpServiceMock } from '../../../http/http_service.mock'; import { applicationServiceMock } from '../../../mocks'; import { Header } from './header'; @@ -56,7 +55,6 @@ function mockProps() { navControlsRight$: new BehaviorSubject([]), basePath: http.basePath, isLocked$: new BehaviorSubject(false), - navType$: new BehaviorSubject('modern' as NavType), loadingCount$: new BehaviorSubject(0), onIsLockedUpdate: () => {}, }; @@ -73,7 +71,6 @@ describe('Header', () => { const isVisible$ = new BehaviorSubject(false); const breadcrumbs$ = new BehaviorSubject([{ text: 'test' }]); const isLocked$ = new BehaviorSubject(false); - const navType$ = new BehaviorSubject('modern' as NavType); const navLinks$ = new BehaviorSubject([ { id: 'kibana', title: 'kibana', baseUrl: '', legacy: false }, ]); @@ -94,7 +91,6 @@ describe('Header', () => { navLinks$={navLinks$} recentlyAccessed$={recentlyAccessed$} isLocked$={isLocked$} - navType$={navType$} customNavLink$={customNavLink$} /> ); @@ -107,9 +103,5 @@ describe('Header', () => { act(() => isLocked$.next(true)); component.update(); expect(component).toMatchSnapshot(); - - act(() => navType$.next('legacy' as NavType)); - component.update(); - expect(component).toMatchSnapshot(); }); }); diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 1ba39e7307c2c..25e5076a19b95 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -23,8 +23,6 @@ import { EuiHeaderSectionItem, EuiHeaderSectionItemButton, EuiIcon, - EuiNavDrawer, - EuiShowFor, htmlIdGenerator, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -50,7 +48,6 @@ import { HeaderBreadcrumbs } from './header_breadcrumbs'; import { HeaderHelpMenu } from './header_help_menu'; import { HeaderLogo } from './header_logo'; import { HeaderNavControls } from './header_nav_controls'; -import { NavDrawer } from './nav_drawer'; export interface HeaderProps { kibanaVersion: string; @@ -77,19 +74,6 @@ export interface HeaderProps { onIsLockedUpdate: OnIsLockedUpdate; } -function renderMenuTrigger(toggleOpen: () => void) { - return ( - - - - ); -} - export function Header({ kibanaVersion, kibanaDocLink, @@ -108,7 +92,6 @@ export function Header({ return ; } - const navDrawerRef = createRef(); const toggleCollapsibleNavRef = createRef(); const navId = htmlIdGenerator()(); const className = classnames('hide-for-sharing'); diff --git a/src/core/public/chrome/ui/header/nav_drawer.tsx b/src/core/public/chrome/ui/header/nav_drawer.tsx deleted file mode 100644 index ee4bff6cc0ac4..0000000000000 --- a/src/core/public/chrome/ui/header/nav_drawer.tsx +++ /dev/null @@ -1,85 +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 { EuiHorizontalRule, EuiNavDrawer, EuiNavDrawerGroup } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { useObservable } from 'react-use'; -import { Observable } from 'rxjs'; -import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem, CoreStart } from '../../..'; -import { InternalApplicationStart } from '../../../application/types'; -import { HttpStart } from '../../../http'; -import { OnIsLockedUpdate } from './'; -import { createEuiListItem, createRecentNavLink } from './nav_link'; -import { RecentLinks } from './recent_links'; - -export interface Props { - appId$: InternalApplicationStart['currentAppId$']; - basePath: HttpStart['basePath']; - isLocked?: boolean; - legacyMode: boolean; - navLinks$: Observable; - recentlyAccessed$: Observable; - navigateToApp: CoreStart['application']['navigateToApp']; - onIsLockedUpdate?: OnIsLockedUpdate; -} - -function NavDrawerRenderer( - { isLocked, onIsLockedUpdate, basePath, legacyMode, navigateToApp, ...observables }: Props, - ref: React.Ref -) { - const appId = useObservable(observables.appId$, ''); - const navLinks = useObservable(observables.navLinks$, []).filter((link) => !link.hidden); - const recentNavLinks = useObservable(observables.recentlyAccessed$, []).map((link) => - createRecentNavLink(link, navLinks, basePath) - ); - - return ( - - {RecentLinks({ recentNavLinks })} - - - createEuiListItem({ - link, - legacyMode, - appId, - basePath, - navigateToApp, - dataTestSubj: 'navDrawerAppsMenuLink', - }) - )} - aria-label={i18n.translate('core.ui.primaryNavList.screenReaderLabel', { - defaultMessage: 'Primary navigation links', - })} - /> - - ); -} - -export const NavDrawer = React.forwardRef(NavDrawerRenderer); diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 5f639853b7507..8c9be2901cbf4 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -363,7 +363,6 @@ export interface ChromeStart { getHelpExtension$(): Observable; getIsNavDrawerLocked$(): Observable; getIsVisible$(): Observable; - getNavType$(): Observable; navControls: ChromeNavControls; navLinks: ChromeNavLinks; recentlyAccessed: ChromeRecentlyAccessed; diff --git a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx index bc2d44b045f6a..0378d816fd2c3 100644 --- a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx @@ -18,7 +18,6 @@ */ import React, { PureComponent, Fragment } from 'react'; -import classNames from 'classnames'; import { EuiFlexGroup, @@ -45,7 +44,6 @@ import { Field, getEditableValue } from '../field'; import { FieldSetting, SettingsChanges, FieldState } from '../../types'; type Category = string; -const NAV_IS_LOCKED_KEY = 'core.chrome.isLocked'; interface FormProps { settings: Record; diff --git a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot index 87205b363e697..14791cd3d8b25 100644 --- a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot @@ -355,181 +355,3 @@ exports[`Storyshots components/Assets/Asset marker 1`] = `
`; - -exports[`Storyshots components/Assets/Asset redux 1`] = ` -
-
-
-
-
- Asset thumbnail -
-
-
-
-

- - airplane - -
- - - ( - 1 - kb) - - -

-
-
-
-
- - - -
-
- -
- -
-
-
-
- -
- -
-
-
-
- - - -
-
-
-
-
-`; diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 934ffa1d200ed..893e8825600b6 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -154,25 +154,18 @@ exports[`SearchBar basically works 1`] = `
+ + [Function] + } closePopover={[Function]} display="inlineBlock" @@ -197,95 +190,118 @@ exports[`SearchBar basically works 1`] = `
- - - -
- - - - -
- + + + +
- -
-
- - - + + + +
diff --git a/x-pack/plugins/painless_lab/public/application/components/main.tsx b/x-pack/plugins/painless_lab/public/application/components/main.tsx index 5216149596d28..4930053b140fa 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main.tsx @@ -7,7 +7,6 @@ import React, { useState, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { NavType } from 'src/core/public'; import { formatRequestPayload, formatJson } from '../lib/format'; import { exampleScript } from '../constants'; import { PayloadFormat } from '../types'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 3daa936f5be58..b88eed9ac410d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2770,10 +2770,6 @@ "kbn.advancedSettings.notifications.infoLifetimeTitle": "情報通知時間", "kbn.advancedSettings.notifications.warningLifetimeText": "警告通知が画面に表示されるミリ秒単位での時間です。{infinityValue} に設定すると無効になります。", "kbn.advancedSettings.notifications.warningLifetimeTitle": "警告通知時間", - "kbn.advancedSettings.pageNavigationDesc": "ナビゲーションのスタイルを変更", - "kbn.advancedSettings.pageNavigationLegacy": "レガシー", - "kbn.advancedSettings.pageNavigationModern": "モダン", - "kbn.advancedSettings.pageNavigationName": "サイドナビゲーションスタイル", "kbn.advancedSettings.storeUrlText": "URL は長くなりすぎてブラウザが対応できない場合があります。セッションストレージに URL の一部を保存することがで この問題に対処できるかテストしています。結果を教えてください!", "kbn.advancedSettings.storeUrlTitle": "セッションストレージに URL を格納", "kbn.advancedSettings.themeVersionText": "現在のバージョンと次のバージョンのKibanaで使用されるテーマを切り替えます。この設定を適用するにはページの更新が必要です。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f396d950f7526..0e6956ce94372 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2771,10 +2771,6 @@ "kbn.advancedSettings.notifications.infoLifetimeTitle": "信息通知生存时间", "kbn.advancedSettings.notifications.warningLifetimeText": "在屏幕上显示警告通知的时间(毫秒)。设置为 {infinityValue} 将禁用。", "kbn.advancedSettings.notifications.warningLifetimeTitle": "警告通知生存时间", - "kbn.advancedSettings.pageNavigationDesc": "更改导航样式", - "kbn.advancedSettings.pageNavigationLegacy": "旧版", - "kbn.advancedSettings.pageNavigationModern": "现代", - "kbn.advancedSettings.pageNavigationName": "侧边导航样式", "kbn.advancedSettings.storeUrlText": "URL 有时会变得过长,以使得某些浏览器无法处理。为此,我们正在测试将 URL 的各个组成部分存储在会话存储中是否会有帮助。请告知我们这样做的效果!", "kbn.advancedSettings.storeUrlTitle": "将 URL 存储在会话存储中", "kbn.advancedSettings.themeVersionText": "在用于 Kibana 当前和下一版本的主题间切换。需要刷新页面,才能应用设置。", diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index 7f4543d014def..79e0134cd578f 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -15,11 +15,12 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...functionalConfig.getAll(), testFiles: [ - require.resolve('./apps/login_page'), - require.resolve('./apps/home'), - require.resolve('./apps/grok_debugger'), - require.resolve('./apps/search_profiler'), - require.resolve('./apps/uptime'), + // TODO enable tests again after EUI is merged + // require.resolve('./apps/login_page'), + // require.resolve('./apps/home'), + // require.resolve('./apps/grok_debugger'), + // require.resolve('./apps/search_profiler'), + // require.resolve('./apps/uptime'), ], pageObjects, services, From 03fac9fe9391f006f3b958fdba54d92031c757f6 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 18 Aug 2020 17:15:17 -0400 Subject: [PATCH 29/71] changing keyboard shortcut --- .../global_search_bar/public/components/search_bar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 7ae206122e0d0..3f3ab68d9bea4 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -109,7 +109,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { useEffect(() => { const openSearch = (event: KeyboardEvent) => { - if (event.key === 's' && (isWindows ? event.ctrlKey : event.metaKey)) { + if (event.key === '/' && (isWindows ? event.ctrlKey : event.metaKey)) { if (searchRef) { event.preventDefault(); searchRef.focus(); @@ -215,7 +215,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { id="xpack.globalSearchBar.searchBar.shortcut" defaultMessage="Quickly search using {shortcut}" values={{ - shortcut: {isWindows ? 'Ctrl + S' : 'Command + S'}, + shortcut: {isWindows ? 'Ctrl + /' : 'Command + /'}, }} /> From 9009e31ec4f9d5273639857cbf56e56cca8f3a37 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 18 Aug 2020 19:10:00 -0400 Subject: [PATCH 30/71] more test failure fixes --- src/core/public/chrome/chrome_service.mock.ts | 9 +- .../collapsible_nav.test.tsx.snap | 7371 ++++++++++------- .../header/__snapshots__/header.test.tsx.snap | 5903 +------------ .../public/components/search_bar.test.tsx | 8 +- .../create_package_config_page/index.tsx | 11 - .../components/settings/index.tsx | 15 +- .../edit_package_config_page/index.tsx | 15 +- .../public/application/components/main.tsx | 26 +- .../application/components/main_controls.tsx | 1 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - x-pack/test/accessibility/config.ts | 2 +- 12 files changed, 4511 insertions(+), 8854 deletions(-) diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 40e50c4d9dbad..ab786a97635a0 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -17,14 +17,7 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; -import { - ChromeBadge, - ChromeBrand, - ChromeBreadcrumb, - ChromeService, - InternalChromeStart, - NavType, -} from './'; +import { ChromeBadge, ChromeBrand, ChromeBreadcrumb, ChromeService, InternalChromeStart } from './'; const createStartContractMock = () => { const startContract: DeeplyMockedKeys = { diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 2a57ff56c8c43..118a55b93f581 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -378,7 +378,9 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
- - -
- } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - > - - +
+ } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + returnFocus={[Function]} + shards={Array []} + sideCar={ + Object { + "assignMedium": [Function], + "assignSyncMedium": [Function], + "options": Object { + "async": true, + "ssr": false, + }, + "read": [Function], + "useMedium": [Function], + } + } + > + -
- + + Custom link + + + + +
- -
-
+
- +
+ + Home + + + + +
-
-
- -
-
-
-
+ + +
+ -
-
-
-
-
-
- -
-
-
-
-
-
    -
  • - - - discover - - -
  • - visualize + recent 1
  • @@ -1442,16 +1364,18 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem euiListGroupItem--small euiListGroupItem--subdued euiListGroupItem-isClickable" > - dashboard + recent 2 @@ -1461,731 +1385,1966 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
+
- -
-
-
-
+ + +
+
+
- + + visualize + + + +
  • + + + dashboard + + +
  • + +
    -
    -
    - +
    +
    +
    +
    -

    - Security -

    +
  • + + + metrics + + +
  • +
  • + + + logs + + +
  • +
    - - +
    +
    -
    -
    + +
    +
    +
    - + + siem + + + + +
    -
    -
    - -
    -
    -
    -
    + + +
    +
    +
    - + + monitoring + + + + +
    -
    -
    - + + canvas + + + + +
    -
    -
    -
      -
    • - -
    • -
    +
    + + Dock navigation + + + + +
    -
    - - -
    - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - /> - - + } - } - > -
    - -
    + - - - -
    -
    - - -
    - -
    -
    - -
    - -
    -
    - -
      + + Custom link + + + +
    +
    +
    +
    +
    +
    - -
  • - - -
  • -
    - - -
    - - - -
    - - - - -

    - Recently viewed -

    -
    -
    -
    - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-recentlyViewed" - id="mockId" - initialIsOpen={true} - onToggle={[Function]} - paddingSize="none" - > -
    -
    -
    +
    - + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
      +
    • + +
    • +
    +
    +
    +
    + + +
    + } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + returnFocus={[Function]} + shards={Array []} + > + + + + } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + returnFocus={[Function]} + shards={Array []} + /> + + + + +
    +
    - - - - -
    -
    - -
    - - - - - - - -

    - Kibana -

    -
    -
    - - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-kibana" - id="mockId" +
    +
    +
    + -
    + + +

    + Recently viewed +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-recentlyViewed" + id="mockId" + initialIsOpen={true} onToggle={[Function]} + paddingSize="none" >
    - +
    +
    + +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    + +
    + + -
    + + + + +

    + Kibana +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-kibana" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    +
    + +
    +
    + +
    - -

    - Kibana -

    -
    + + +
    - -
    - - - -
    -
    + +
    +
    +
    +
    + - + + + + + +

    + Observability +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-observability" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" > -
    +
    -
    - -
    + + + +
    +
    + +
    +
    +
    -
  • - - - dashboard - - -
  • - - - -
    +
  • + + + metrics + + +
  • + + +
  • + + + logs + + +
  • +
    + + +
    +
    +
    +
    -
    -
    - - - - - - - - - - -

    - Observability -

    -
    -
    -
    - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-observability" - id="mockId" - initialIsOpen={true} - onToggle={[Function]} - paddingSize="none" - > -
    -
    + + - -
    -
    - -
    +
    -
    - -
    + + + +
    +
    + +
    +
    +
    -
  • - - - logs - - -
  • - - - -
    +
  • + + + siem + + +
  • + + + +
    +
    +
    +
    -
    -
    -
    - - - - - - - - - -

    - Security -

    -
    -
    -
    - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-security" - id="mockId" - initialIsOpen={true} - onToggle={[Function]} - paddingSize="none" - > -
    -
    + + - -
    -
    - -
    +
    -
    - -
      - + + + + +
      -
    • +
      + +

      + Management +

      +
      +
      + +
    • +
      +
      + +
    +
    + +
    +
    +
    + - - - siem - - - - - - -
    +
  • + + + monitoring + + +
  • + + + +
    +
    +
    +
    - -
    -
    - - - - - - -

    - Management -

    -
    -
    - - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-management" - id="mockId" - initialIsOpen={true} - onToggle={[Function]} - paddingSize="none" - > -
    -
    + + - -
    -
    + + + + + +
    +
    +
    + - -
    +
    -
    - -
      +
      + + Dock navigation + + , } } + color="subdued" + data-test-subj="collapsible-nav-lock" + iconType="lockOpen" + label="Dock navigation" + onClick={[Function]} + size="xs" > - -
    • - - - monitoring - - -
    • -
      -
    -
    -
    +
    + + + Dock navigation + + + + + +
    - -
    + +
    - - - -
    + -
    - - - -
    -
    -
    - - -
    -
    - -
      - -
      - - Dock navigation - - , - } - } - color="subdued" - data-test-subj="collapsible-nav-lock" - iconType="lockOpen" - label="Dock navigation" - onClick={[Function]} - size="xs" +
      + + -
    • - -
    • - -
    -
    -
    -
    -
    -
    + close + + + + + + + +
    -
    - - +
    - - - - -
    -
    + + - + > + + + + + + + + + +
    @@ -4166,511 +5689,553 @@ exports[`CollapsibleNav renders the default nav 3`] = ` onTouchEnd={[Function]} onTouchStart={[Function]} > - -
    -
    -
    - - - -
    + - -
    - - - - , + } + } + color="subdued" + data-test-subj="collapsible-nav-lock" + iconType="lock" + label="Undock navigation" + onClick={[Function]} + size="xs" + > +
  • + +
  • + + + +
    + + + + + + + - - close - - - - - - - - -
    - + + + +
    + + + + close + + + + + + + + +
    + +
    + + +
    diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index b43ac8b1148bb..3f83383ef729d 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -454,55 +454,6 @@ exports[`Header renders 1`] = ` "thrownError": null, } } - navType$={ - BehaviorSubject { - "_isScalar": false, - "_value": "modern", - "closed": false, - "hasError": false, - "isStopped": false, - "observers": Array [ - Subscriber { - "_parentOrParents": null, - "_subscriptions": Array [ - SubjectSubscription { - "_parentOrParents": [Circular], - "_subscriptions": null, - "closed": false, - "subject": [Circular], - "subscriber": [Circular], - }, - ], - "closed": false, - "destination": SafeSubscriber { - "_complete": undefined, - "_context": [Circular], - "_error": undefined, - "_next": [Function], - "_parentOrParents": null, - "_parentSubscriber": [Circular], - "_subscriptions": null, - "closed": false, - "destination": Object { - "closed": true, - "complete": [Function], - "error": [Function], - "next": [Function], - }, - "isStopped": false, - "syncErrorThrowable": false, - "syncErrorThrown": false, - "syncErrorValue": null, - }, - "isStopped": false, - "syncErrorThrowable": true, - "syncErrorThrown": false, - "syncErrorValue": null, - }, - ], - "thrownError": null, - } - } onIsLockedUpdate={[Function]} recentlyAccessed$={ BehaviorSubject { @@ -2172,55 +2123,6 @@ exports[`Header renders 2`] = ` "thrownError": null, } } - navType$={ - BehaviorSubject { - "_isScalar": false, - "_value": "modern", - "closed": false, - "hasError": false, - "isStopped": false, - "observers": Array [ - Subscriber { - "_parentOrParents": null, - "_subscriptions": Array [ - SubjectSubscription { - "_parentOrParents": [Circular], - "_subscriptions": null, - "closed": false, - "subject": [Circular], - "subscriber": [Circular], - }, - ], - "closed": false, - "destination": SafeSubscriber { - "_complete": undefined, - "_context": [Circular], - "_error": undefined, - "_next": [Function], - "_parentOrParents": null, - "_parentSubscriber": [Circular], - "_subscriptions": null, - "closed": false, - "destination": Object { - "closed": true, - "complete": [Function], - "error": [Function], - "next": [Function], - }, - "isStopped": false, - "syncErrorThrowable": false, - "syncErrorThrown": false, - "syncErrorValue": null, - }, - "isStopped": false, - "syncErrorThrowable": true, - "syncErrorThrown": false, - "syncErrorValue": null, - }, - ], - "thrownError": null, - } - } onIsLockedUpdate={[Function]} recentlyAccessed$={ BehaviorSubject { @@ -2339,7 +2241,7 @@ exports[`Header renders 2`] = `
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    `; - -exports[`Header renders 4`] = ` -
    - -
    -
    -
    - -
    - , - ], - }, - Object { - "borders": "none", - "items": Array [ - , - ], - }, - Object { - "borders": "none", - "items": Array [ - , - , - ], - }, - ] - } - theme="dark" - > -
    - -
    - - - - -
    - -
    - -
    -
    -
    -
    - -
    - -
    - - - - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} - > - -
    -
    - - - -
    -
    -
    -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - - -
    - -
    - - -
    - - - -
    -
    -
    - -
    - - -
    - - - - - - - - - -
    - - - - - - - - -
    -
    -`; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx index edd626a0a4362..ffa0d08f8a8ca 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -10,13 +10,17 @@ import { globalSearchPluginMock } from '../../../global_search/public/mocks'; import { GlobalSearchPluginStart } from '../../../global_search/public'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; +jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ + htmlIdGenerator: () => () => 'mockId', +})); + describe('SearchBar', () => { let searchService: GlobalSearchPluginStart; - let findSpy: jest.SpyInstance; + // let findSpy: jest.SpyInstance; beforeEach(() => { searchService = globalSearchPluginMock.createStartContract(); - findSpy = jest.spyOn(globalSearchPluginMock, 'createStartContract'); + // findSpy = jest.spyOn(globalSearchPluginMock, 'createStartContract'); }); it('basically works', async () => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx index 6319666037ff8..059246450da73 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/index.tsx @@ -56,8 +56,6 @@ const StepsWithLessPadding = styled(EuiSteps)` export const CreatePackageConfigPage: React.FunctionComponent = () => { const { notifications, - chrome: { getIsNavDrawerLocked$ }, - uiSettings, application: { navigateToApp }, } = useCore(); const { @@ -70,15 +68,6 @@ export const CreatePackageConfigPage: React.FunctionComponent = () => { const history = useHistory(); const routeState = useIntraAppState(); const from: CreatePackageConfigFrom = configId ? 'config' : 'package'; - const [isNavDrawerLocked, setIsNavDrawerLocked] = useState(false); - - useEffect(() => { - const subscription = getIsNavDrawerLocked$().subscribe((newIsNavDrawerLocked: boolean) => { - setIsNavDrawerLocked(newIsNavDrawerLocked); - }); - - return () => subscription.unsubscribe(); - }); // Agent config and package info states const [agentConfig, setAgentConfig] = useState(); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx index 0903a73b6ee0d..5e0dd29162f7d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/settings/index.tsx @@ -33,11 +33,7 @@ const FormWrapper = styled.div` export const ConfigSettingsView = memo<{ config: AgentConfig }>( ({ config: originalAgentConfig }) => { - const { - notifications, - chrome: { getIsNavDrawerLocked$ }, - uiSettings, - } = useCore(); + const { notifications } = useCore(); const { fleet: { enabled: isFleetEnabled }, } = useConfig(); @@ -45,7 +41,6 @@ export const ConfigSettingsView = memo<{ config: AgentConfig }>( const { getPath } = useLink(); const hasWriteCapabilites = useCapabilities().write; const refreshConfig = useConfigRefresh(); - const [isNavDrawerLocked, setIsNavDrawerLocked] = useState(false); const [agentConfig, setAgentConfig] = useState({ ...originalAgentConfig, }); @@ -55,14 +50,6 @@ export const ConfigSettingsView = memo<{ config: AgentConfig }>( const [withSysMonitoring, setWithSysMonitoring] = useState(true); const validation = agentConfigFormValidation(agentConfig); - useEffect(() => { - const subscription = getIsNavDrawerLocked$().subscribe((newIsNavDrawerLocked: boolean) => { - setIsNavDrawerLocked(newIsNavDrawerLocked); - }); - - return () => subscription.unsubscribe(); - }); - const updateAgentConfig = (updatedFields: Partial) => { setAgentConfig({ ...agentConfig, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx index a9f6a0a049302..6275b503480e3 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx @@ -43,11 +43,7 @@ import { StepConfigurePackage } from '../create_package_config_page/step_configu import { StepDefinePackageConfig } from '../create_package_config_page/step_define_package_config'; export const EditPackageConfigPage: React.FunctionComponent = () => { - const { - notifications, - chrome: { getIsNavDrawerLocked$ }, - uiSettings, - } = useCore(); + const { notifications } = useCore(); const { fleet: { enabled: isFleetEnabled }, } = useConfig(); @@ -56,15 +52,6 @@ export const EditPackageConfigPage: React.FunctionComponent = () => { } = useRouteMatch(); const history = useHistory(); const { getHref, getPath } = useLink(); - const [isNavDrawerLocked, setIsNavDrawerLocked] = useState(false); - - useEffect(() => { - const subscription = getIsNavDrawerLocked$().subscribe((newIsNavDrawerLocked: boolean) => { - setIsNavDrawerLocked(newIsNavDrawerLocked); - }); - - return () => subscription.unsubscribe(); - }); // Agent config, package info, and package config states const [isLoadingData, setIsLoadingData] = useState(true); diff --git a/x-pack/plugins/painless_lab/public/application/components/main.tsx b/x-pack/plugins/painless_lab/public/application/components/main.tsx index 4930053b140fa..06499994e5609 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main.tsx @@ -21,10 +21,7 @@ export const Main: React.FunctionComponent = () => { const { store: { payload, validation }, updatePayload, - services: { - http, - chrome: { getIsNavDrawerLocked$, getNavType$ }, - }, + services: { http }, links, } = useAppContext(); @@ -42,25 +39,6 @@ export const Main: React.FunctionComponent = () => { setRequestFlyoutOpen(!isRequestFlyoutOpen); }; - const [isNavDrawerLocked, setIsNavDrawerLocked] = useState(false); - const [isNavLegacy, setIsNavLegacy] = useState(false); - - useEffect(() => { - const subscription = getIsNavDrawerLocked$().subscribe((newIsNavDrawerLocked: boolean) => { - setIsNavDrawerLocked(newIsNavDrawerLocked); - }); - - return () => subscription.unsubscribe(); - }); - - useEffect(() => { - const subscription = getNavType$().subscribe((navType: NavType) => { - setIsNavLegacy(navType === 'legacy'); - }); - - return () => subscription.unsubscribe(); - }); - return (
    @@ -86,8 +64,6 @@ export const Main: React.FunctionComponent = () => { isLoading={inProgress} toggleRequestFlyout={toggleRequestFlyout} isRequestFlyoutOpen={isRequestFlyoutOpen} - isNavDrawerLocked={isNavDrawerLocked} - isNavLegacy={isNavLegacy} reset={() => updatePayload({ code: exampleScript })} /> diff --git a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx index 4e4bca363e374..822aeaea95318 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx @@ -14,7 +14,6 @@ import { EuiButtonEmpty, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import classNames from 'classnames'; import { Links } from '../../links'; interface Props { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b88eed9ac410d..dd2d7d7a9f1c1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -489,7 +489,6 @@ "core.ui.chrome.headerGlobalNav.helpMenuOpenGitHubIssueTitle": "GitHubで問題を開く", "core.ui.chrome.headerGlobalNav.helpMenuTitle": "ヘルプ", "core.ui.chrome.headerGlobalNav.helpMenuVersion": "v {version}", - "core.ui.chrome.headerGlobalNav.toggleSideNavAriaLabel": "サイドナビゲーションを切り替える", "core.ui.chrome.sideGlobalNav.viewRecentItemsFlyoutTitle": "最近のアイテム", "core.ui.chrome.sideGlobalNav.viewRecentItemsLabel": "最近閲覧", "core.ui.EmptyRecentlyViewed": "最近閲覧したアイテムはありません", @@ -513,7 +512,6 @@ "core.ui.primaryNav.pinnedLinksAriaLabel": "ピン留めされたリンク", "core.ui.primaryNav.screenReaderLabel": "プライマリ", "core.ui.primaryNav.toggleNavAriaLabel": "プライマリナビゲーションを切り替える", - "core.ui.primaryNavList.screenReaderLabel": "プライマリナビゲーションリンク", "core.ui.primaryNavSection.dockAriaLabel": "プライマリナビゲーションリンクを固定する", "core.ui.primaryNavSection.dockLabel": "ナビゲーションを固定する", "core.ui.primaryNavSection.screenReaderLabel": "プライマリナビゲーションリンク、{category}", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0e6956ce94372..7878ce07b679d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -489,7 +489,6 @@ "core.ui.chrome.headerGlobalNav.helpMenuOpenGitHubIssueTitle": "在 GitHub 中提出问题", "core.ui.chrome.headerGlobalNav.helpMenuTitle": "帮助", "core.ui.chrome.headerGlobalNav.helpMenuVersion": "v {version}", - "core.ui.chrome.headerGlobalNav.toggleSideNavAriaLabel": "切换侧导航", "core.ui.chrome.sideGlobalNav.viewRecentItemsFlyoutTitle": "最近项", "core.ui.chrome.sideGlobalNav.viewRecentItemsLabel": "最近查看", "core.ui.EmptyRecentlyViewed": "没有最近查看的项目", @@ -513,7 +512,6 @@ "core.ui.primaryNav.pinnedLinksAriaLabel": "置顶链接", "core.ui.primaryNav.screenReaderLabel": "主分片", "core.ui.primaryNav.toggleNavAriaLabel": "切换主导航", - "core.ui.primaryNavList.screenReaderLabel": "主导航链接", "core.ui.primaryNavSection.dockAriaLabel": "停靠主导航", "core.ui.primaryNavSection.dockLabel": "停靠导航", "core.ui.primaryNavSection.screenReaderLabel": "主导航链接, {category}", diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index 79e0134cd578f..bfcea264f3026 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -15,8 +15,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...functionalConfig.getAll(), testFiles: [ + require.resolve('./apps/login_page'), // TODO enable tests again after EUI is merged - // require.resolve('./apps/login_page'), // require.resolve('./apps/home'), // require.resolve('./apps/grok_debugger'), // require.resolve('./apps/search_profiler'), From 122e70ca254184cd6692031960d880dbf12967fc Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 19 Aug 2020 17:56:08 -0400 Subject: [PATCH 31/71] fixing tests again --- .../components/__snapshots__/search_bar.test.tsx.snap | 10 +++++----- .../public/components/search_bar.tsx | 2 +- .../applications/ingest_manager/layouts/default.tsx | 1 - .../details_page/components/settings/index.tsx | 2 +- .../public/application/components/main_controls.tsx | 11 +---------- 5 files changed, 8 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 893e8825600b6..51fceafd512ef 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -203,7 +203,7 @@ exports[`SearchBar basically works 1`] = ` incremental={true} inputRef={[Function]} key="listSearch" - listId="ie43f8d70-e18d-11ea-a274-31d7159f902f_listbox" + listId="mockId" onBlur={[Function]} onChange={[Function]} onFocus={[Function]} @@ -214,11 +214,11 @@ exports[`SearchBar basically works 1`] = ` { + inputRef: (ref: HTMLInputElement | null) => { setSearchRef(ref); }, 'aria-label': i18n.translate('xpack.globalSearchBar.primaryNav.screenReaderLabel', { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index d72c927cd307c..ea9192102e79e 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -42,7 +42,6 @@ export const DefaultLayout: React.FunctionComponent = ({ }) => { const { getHref } = useLink(); const { fleet } = useConfig(); - const { uiSettings } = useCore(); const [isSettingsFlyoutOpen, setIsSettingsFlyoutOpen] = React.useState(false); return ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx index fdd1dc2969a53..075f64f5b0a49 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { memo, useState, useEffect } from 'react'; +import React, { memo, useState } from 'react'; import { useHistory } from 'react-router-dom'; import styled from 'styled-components'; import { EuiBottomBar, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; diff --git a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx index 822aeaea95318..e6a61995ac78a 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx @@ -22,18 +22,9 @@ interface Props { isLoading: boolean; reset: () => void; links: Links; - isNavDrawerLocked: boolean; - isNavLegacy: boolean; } -export function MainControls({ - toggleRequestFlyout, - isRequestFlyoutOpen, - reset, - links, - isNavDrawerLocked, - isNavLegacy, -}: Props) { +export function MainControls({ toggleRequestFlyout, isRequestFlyoutOpen, reset, links }: Props) { const [isHelpOpen, setIsHelpOpen] = useState(false); const items = [ From cdb8d3d8c663f6c15effdc6c46d80ded57daadca Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 19 Aug 2020 18:19:13 -0400 Subject: [PATCH 32/71] removing unused imports --- .../public/applications/ingest_manager/layouts/default.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index ea9192102e79e..70d8ec8d2c870 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -5,11 +5,11 @@ */ import React from 'react'; import styled from 'styled-components'; -import { EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiButtonEmpty } from '@elastic/eui'; +import { EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { Section } from '../sections'; import { AlphaMessaging, SettingFlyout } from '../components'; -import { useLink, useConfig, useCore } from '../hooks'; +import { useLink, useConfig } from '../hooks'; interface Props { showSettings?: boolean; From 770662235a70517ef934de52ec7fc9568e7693d1 Mon Sep 17 00:00:00 2001 From: Ryan Keairns Date: Thu, 20 Aug 2020 16:37:08 -0500 Subject: [PATCH 33/71] Update plugins to show parent, solution icons in search results --- src/plugins/dashboard/public/plugin.tsx | 2 +- src/plugins/dev_tools/public/plugin.ts | 2 +- src/plugins/discover/public/plugin.ts | 2 +- src/plugins/management/public/plugin.ts | 2 +- .../components/newsfeed_header_nav_button.tsx | 2 +- src/plugins/timelion/public/plugin.ts | 2 +- src/plugins/visualize/public/plugin.ts | 2 +- x-pack/plugins/apm/public/plugin.ts | 3 ++- x-pack/plugins/canvas/public/plugin.tsx | 2 +- .../plugins/enterprise_search/common/constants.ts | 1 + x-pack/plugins/enterprise_search/public/plugin.ts | 8 +++++++- x-pack/plugins/graph/public/plugin.ts | 2 +- x-pack/plugins/infra/public/plugin.ts | 4 ++-- x-pack/plugins/ingest_manager/public/plugin.ts | 2 +- x-pack/plugins/maps/common/constants.ts | 1 + x-pack/plugins/maps/public/plugin.ts | 4 ++-- x-pack/plugins/ml/common/constants/app.ts | 1 + x-pack/plugins/ml/public/plugin.ts | 4 ++-- x-pack/plugins/observability/public/plugin.ts | 1 + .../plugins/security_solution/common/constants.ts | 1 + x-pack/plugins/security_solution/public/plugin.tsx | 13 +++++++------ x-pack/plugins/uptime/public/apps/plugin.ts | 2 +- 22 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 2a36f2d801850..da8ff48199925 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -281,7 +281,7 @@ export class DashboardPlugin id: DashboardConstants.DASHBOARDS_ID, title: 'Dashboard', order: 2500, - euiIconType: 'dashboardApp', + euiIconType: 'logoKibana', defaultPath: `#${DashboardConstants.LANDING_PAGE_PATH}`, updater$: this.appStateUpdater, category: DEFAULT_APP_CATEGORIES.kibana, diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index 45fa3634bc87e..d2e184f41362a 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -60,7 +60,7 @@ export class DevToolsPlugin implements Plugin { defaultMessage: 'Dev Tools', }), updater$: this.appStateUpdater, - euiIconType: 'devToolsApp', + euiIconType: 'logoElastic', order: 9010, category: DEFAULT_APP_CATEGORIES.management, mount: async (params: AppMountParameters) => { diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts index 015f4267646c1..46baa05184646 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.ts @@ -237,7 +237,7 @@ export class DiscoverPlugin title: 'Discover', updater$: this.appStateUpdater.asObservable(), order: 1000, - euiIconType: 'discoverApp', + euiIconType: 'logoKibana', defaultPath: '#/', category: DEFAULT_APP_CATEGORIES.kibana, mount: async (params: AppMountParameters) => { diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index 8be130b4028c6..373e695ce717f 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -66,7 +66,7 @@ export class ManagementPlugin implements Plugin { aria-label="Newsfeed menu" onClick={showFlyout} > - + {showBadge ? ( ▪ diff --git a/src/plugins/timelion/public/plugin.ts b/src/plugins/timelion/public/plugin.ts index a92ced20cb6d1..24d1b9eb3fb65 100644 --- a/src/plugins/timelion/public/plugin.ts +++ b/src/plugins/timelion/public/plugin.ts @@ -91,7 +91,7 @@ export class TimelionPlugin implements Plugin { title: 'Timelion', order: 8000, defaultPath: '#/', - euiIconType: 'timelionApp', + euiIconType: 'logoKibana', category: DEFAULT_APP_CATEGORIES.kibana, updater$: this.appStateUpdater.asObservable(), mount: async (params: AppMountParameters) => { diff --git a/src/plugins/visualize/public/plugin.ts b/src/plugins/visualize/public/plugin.ts index 8794593d6c958..80f1a9e28c3f6 100644 --- a/src/plugins/visualize/public/plugin.ts +++ b/src/plugins/visualize/public/plugin.ts @@ -142,7 +142,7 @@ export class VisualizePlugin id: 'visualize', title: 'Visualize', order: 8000, - euiIconType: 'visualizeApp', + euiIconType: 'logoKibana', defaultPath: '#/', category: DEFAULT_APP_CATEGORIES.kibana, updater$: this.appStateUpdater.asObservable(), diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index cf729fe0ff301..0934c7f70755e 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -101,7 +101,7 @@ export class ApmPlugin implements Plugin { id: 'apm', title: 'APM', order: 8300, - euiIconType: 'apmApp', + euiIconType: 'logoObservability', appRoute: '/app/apm', icon: 'plugins/apm/public/icon.svg', category: DEFAULT_APP_CATEGORIES.observability, @@ -121,6 +121,7 @@ export class ApmPlugin implements Plugin { id: 'csm', title: 'Client Side Monitoring', order: 8500, + euiIconType: 'logoObservability', category: DEFAULT_APP_CATEGORIES.observability, async mount(params: AppMountParameters) { diff --git a/x-pack/plugins/canvas/public/plugin.tsx b/x-pack/plugins/canvas/public/plugin.tsx index 0269774a446c1..11d24e166825a 100644 --- a/x-pack/plugins/canvas/public/plugin.tsx +++ b/x-pack/plugins/canvas/public/plugin.tsx @@ -88,7 +88,7 @@ export class CanvasPlugin category: DEFAULT_APP_CATEGORIES.kibana, id: 'canvas', title: 'Canvas', - euiIconType: 'canvasApp', + euiIconType: 'logoKibana', order: 3000, updater$: this.appUpdater, mount: async (params: AppMountParameters) => { diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts index c5839df4c603b..d02348e6a50f3 100644 --- a/x-pack/plugins/enterprise_search/common/constants.ts +++ b/x-pack/plugins/enterprise_search/common/constants.ts @@ -12,6 +12,7 @@ export const ENTERPRISE_SEARCH_PLUGIN = { defaultMessage: 'Enterprise Search', }), URL: '/app/enterprise_search', + LOGO: 'logoEnterpriseSearch', }; export const APP_SEARCH_PLUGIN = { diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index 0d392eefe0aa2..c24dd813f44bd 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -20,7 +20,11 @@ import { import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { LicensingPluginSetup } from '../../licensing/public'; -import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../common/constants'; +import { + ENTERPRISE_SEARCH_PLUGIN, + APP_SEARCH_PLUGIN, + WORKPLACE_SEARCH_PLUGIN, +} from '../common/constants'; import { getPublicUrl, ExternalUrl, @@ -55,6 +59,7 @@ export class EnterpriseSearchPlugin implements Plugin { core.application.register({ id: APP_SEARCH_PLUGIN.ID, title: APP_SEARCH_PLUGIN.NAME, + euiIconType: ENTERPRISE_SEARCH_PLUGIN.LOGO, appRoute: APP_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { @@ -74,6 +79,7 @@ export class EnterpriseSearchPlugin implements Plugin { core.application.register({ id: WORKPLACE_SEARCH_PLUGIN.ID, title: WORKPLACE_SEARCH_PLUGIN.NAME, + euiIconType: ENTERPRISE_SEARCH_PLUGIN.LOGO, appRoute: WORKPLACE_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { diff --git a/x-pack/plugins/graph/public/plugin.ts b/x-pack/plugins/graph/public/plugin.ts index 5b2566ffab7c0..0cd7d1b31addb 100644 --- a/x-pack/plugins/graph/public/plugin.ts +++ b/x-pack/plugins/graph/public/plugin.ts @@ -74,7 +74,7 @@ export class GraphPlugin title: 'Graph', order: 6000, appRoute: '/app/graph', - euiIconType: 'graphApp', + euiIconType: 'logoKibana', category: DEFAULT_APP_CATEGORIES.kibana, mount: async (params: AppMountParameters) => { const [coreStart, pluginsStart] = await core.getStartServices(); diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index 2dda664a7f675..ebe58bf63431d 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -50,7 +50,7 @@ export class Plugin implements InfraClientPluginClass { title: i18n.translate('xpack.infra.logs.pluginTitle', { defaultMessage: 'Logs', }), - euiIconType: 'logsApp', + euiIconType: 'logoObservability', order: 8100, appRoute: '/app/logs', category: DEFAULT_APP_CATEGORIES.observability, @@ -68,7 +68,7 @@ export class Plugin implements InfraClientPluginClass { title: i18n.translate('xpack.infra.metrics.pluginTitle', { defaultMessage: 'Metrics', }), - euiIconType: 'metricsApp', + euiIconType: 'logoObservability', order: 8200, appRoute: '/app/metrics', category: DEFAULT_APP_CATEGORIES.observability, diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index a8cc7b72eb17f..39c755938c7b2 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -73,7 +73,7 @@ export class IngestManagerPlugin category: DEFAULT_APP_CATEGORIES.management, title: i18n.translate('xpack.ingestManager.appTitle', { defaultMessage: 'Ingest Manager' }), order: 9020, - euiIconType: 'savedObjectsApp', + euiIconType: 'logoElastic', async mount(params: AppMountParameters) { const [coreStart, startDeps] = (await core.getStartServices()) as [ CoreStart, diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 363122ac62212..cece2717dd754 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -26,6 +26,7 @@ export const EMS_TILES_VECTOR_TILE_PATH = 'vector/tile'; export const MAP_SAVED_OBJECT_TYPE = 'map'; export const APP_ID = 'maps'; export const APP_ICON = 'gisApp'; +export const APP_ICON_SOLUTION = 'logoKibana'; export const INITIAL_LAYERS_KEY = 'initialLayers'; export const MAPS_APP_PATH = `app/${APP_ID}`; diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 9bb79f2937c68..526df2d0df0d8 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -30,7 +30,7 @@ import { featureCatalogueEntry } from './feature_catalogue_entry'; import { getMapsVisTypeAlias } from './maps_vis_type_alias'; import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { VisualizationsSetup } from '../../../../src/plugins/visualizations/public'; -import { APP_ICON, APP_ID, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; +import { APP_ICON_SOLUTION, APP_ID, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../src/plugins/ui_actions/public'; import { createMapsUrlGenerator } from './url_generator'; import { visualizeGeoFieldAction } from './trigger_actions/visualize_geo_field_action'; @@ -119,7 +119,7 @@ export class MapsPlugin title: getAppTitle(), order: 4000, icon: `plugins/${APP_ID}/icon.svg`, - euiIconType: APP_ICON, + euiIconType: APP_ICON_SOLUTION, category: DEFAULT_APP_CATEGORIES.kibana, // @ts-expect-error async mount(context, params) { diff --git a/x-pack/plugins/ml/common/constants/app.ts b/x-pack/plugins/ml/common/constants/app.ts index 2f3e2fc22374d..97dd7a7b0fef5 100644 --- a/x-pack/plugins/ml/common/constants/app.ts +++ b/x-pack/plugins/ml/common/constants/app.ts @@ -6,3 +6,4 @@ export const PLUGIN_ID = 'ml'; export const PLUGIN_ICON = 'machineLearningApp'; +export const PLUGIN_ICON_SOLUTION = 'logoKibana'; diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index ff59d46de758d..010ab45a6f8c0 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -29,7 +29,7 @@ import { LicensingPluginSetup } from '../../licensing/public'; import { registerManagementSection } from './application/management'; import { LicenseManagementUIPluginSetup } from '../../license_management/public'; import { setDependencyCache } from './application/util/dependency_cache'; -import { PLUGIN_ICON, PLUGIN_ID } from '../common/constants/app'; +import { PLUGIN_ICON_SOLUTION, PLUGIN_ID } from '../common/constants/app'; import { registerFeature } from './register_feature'; import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public'; import { registerMlUiActions } from './ui_actions'; @@ -72,7 +72,7 @@ export class MlPlugin implements Plugin { defaultMessage: 'Machine Learning', }), order: 5000, - euiIconType: PLUGIN_ICON, + euiIconType: PLUGIN_ICON_SOLUTION, appRoute: '/app/ml', category: DEFAULT_APP_CATEGORIES.kibana, updater$: this.appUpdater, diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 335ce897dce7b..e1e0f27034489 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -28,6 +28,7 @@ export class Plugin implements PluginClass { @@ -149,7 +150,7 @@ export class Plugin implements IPlugin { @@ -176,7 +177,7 @@ export class Plugin implements IPlugin { @@ -203,7 +204,7 @@ export class Plugin implements IPlugin { @@ -230,7 +231,7 @@ export class Plugin implements IPlugin { @@ -257,7 +258,7 @@ export class Plugin implements IPlugin { diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts index cf750434ab324..aa2ea15850901 100644 --- a/x-pack/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/plugins/uptime/public/apps/plugin.ts @@ -87,7 +87,7 @@ export class UptimePlugin core.application.register({ appRoute: '/app/uptime#/', id: PLUGIN.ID, - euiIconType: 'uptimeApp', + euiIconType: 'logoObservability', order: 8400, title: PLUGIN.TITLE, category: DEFAULT_APP_CATEGORIES.observability, From ac8db18536ba051ad32e4df88ed4fa2de3a2da01 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 26 Aug 2020 13:36:33 -0400 Subject: [PATCH 34/71] adding autogenerated plugin list --- docs/developer/plugin-list.asciidoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index b3180a7a03874..b4a5787d8f486 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -337,6 +337,10 @@ and actions. or dashboards from the Kibana instance, from both server and client-side plugins +|{kib-repo}blob/{branch}/x-pack/plugins/global_search_bar/README.md[globalSearchBar] +|The GlobalSearchBar plugin provides a search interface for navigating Kibana. (It is the UI to the GlobalSearch plugin.) + + |{kib-repo}blob/{branch}/x-pack/plugins/global_search_providers[globalSearchProviders] |WARNING: Missing README. From 82efd4192f30a51521456f6e94e82cbde51a869d Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 26 Aug 2020 15:47:06 -0400 Subject: [PATCH 35/71] snapshot updates --- .../collapsible_nav.test.tsx.snap | 6717 +++++------------ .../header/__snapshots__/header.test.tsx.snap | 1281 ++-- 2 files changed, 2384 insertions(+), 5614 deletions(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 118a55b93f581..3b38672ef891d 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -378,9 +378,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-recentlyViewed" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    +
    + +
    +
    + +
    +
    +
    + -
    - -
    -
    -
    + + + + +
  • + + + recent 2 + + +
  • +
    + + +
    +
    +
    +
    +
    +
    + + + +
    +
    + +
    + + + + + + + +

    + Kibana +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-kibana" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    +
    + -
    -
    -
    + data-euiicon-type="logoKibana" + size="l" + /> + +
    + +
    - + Kibana + +
    -
    +
    -
    -
    + + + +
    +
    + +
    -
    - -
    - -
    -
    -
    - -
    -
    -
    -
    + + + + - -
    -
    -
    + dashboard + + + + + +
    +
    +
    +
    +
    + + + + + + + + + + +

    + Observability +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-observability" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    +
    + -
    -
    -
    -
    -
    - -
    -
    +
    -
    -
    -
    -
    - -
    -
    -
    -
    - -
    + Observability + +
    -
    -
    -
    -
    - -
    -
    -
    -
    -
      -
    • - -
    • -
    -
    +
    - - - - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - returnFocus={[Function]} - shards={Array []} - sideCar={ - Object { - "assignMedium": [Function], - "assignSyncMedium": [Function], - "options": Object { - "async": true, - "ssr": false, - }, - "read": [Function], - "useMedium": [Function], - } - } - > - - + - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - returnFocus={[Function]} - shards={Array []} - sideCar={ - Object { - "assignMedium": [Function], - "assignSyncMedium": [Function], - "options": Object { - "async": true, - "ssr": false, - }, - "read": [Function], - "useMedium": [Function], - } - } + + + +
    +
    + + - + +

    - - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - returnFocus={[Function]} - shards={Array []} - > - - - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - returnFocus={[Function]} - shards={Array []} - /> - - - - + + + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-management" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    -

    +
    -
    -
    - + + + + + +
    + +
    +
    +
    -
    -
    - - - -
    -
    - - + + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    + + + +
    +
    +
    + + +
    +
    + +
      +
      + - -
        - -
        - - Dock navigation - - , - } - } - color="subdued" - data-test-subj="collapsible-nav-lock" - iconType="lockOpen" - label="Dock navigation" - onClick={[Function]} - size="xs" - > -
      • - -
      • - -
      -
      -
      -
    - - -
    - - - + , } } + color="subdued" + data-test-subj="collapsible-nav-lock" + iconType="lockOpen" + label="Dock navigation" + onClick={[Function]} + size="xs" > - - - - + + + + + - -
    - - + + +
    + + + + + + + +
    @@ -5672,573 +2704,442 @@ exports[`CollapsibleNav renders the default nav 3`] = ` clickOutsideDisables={true} disabled={true} > - - -
    - - - +
    -
    + - + + +
    +
    + +
    + + + + + +

    + Recently viewed +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-recentlyViewed" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    +
    + +
    +
    + +
    +
    +
    + - -
    - - - +

    + No recently viewed items +

    -
    -
    -
    - - +
    + +
    +
    +
    + +
    + + + + +
    +
    + +
    + + +
    +
    + +
      - - - -

      - Recently viewed -

      -
      -
      - - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-recentlyViewed" - id="mockId" - initialIsOpen={true} - onToggle={[Function]} - paddingSize="none" - > -
      -
      - -
      -
      - -
      -
      -
      - -
      - -
      -

      - No recently viewed items -

      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      - -
      - , } - > - -
      -
      - -
        - -
        - - Undock navigation - - , - } - } - color="subdued" - data-test-subj="collapsible-nav-lock" - iconType="lock" - label="Undock navigation" - onClick={[Function]} - size="xs" - > -
      • - -
      • - -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - + + + +
    +
    - -
    + + +
    + + + +
    - - + } + > + + +
    + + + + close + + + + + + + + +
    diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index 3f83383ef729d..2010980d2e8d5 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -11229,766 +11229,635 @@ exports[`Header renders 3`] = ` clickOutsideDisables={true} disabled={true} > - - -
    - - - +
    + +
      + +
    • + +
    • +
      +
    +
    +
    +
    + +
    + + +
    +
    + +
    + +
    + } + >
    - -
    -
    +
    + +
    + + + + + +

    + Recently viewed +

    +
    +
    + + } + className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" + data-test-subj="collapsibleNavGroup-recentlyViewed" + id="mockId" + initialIsOpen={true} + onToggle={[Function]} + paddingSize="none" + > +
    +
    + +
    +
    + +
    +
    +
    -
    - -
    -
    - - - -
    -
    -
    -
    - - + + + + + +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + +
    + +
    +
    + +
      + - - - -

      - Recently viewed -

      -
      -
      - - } - className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-recentlyViewed" - id="mockId" - initialIsOpen={true} - onToggle={[Function]} - paddingSize="none" +
    • -
      -
      - +
    • +
      +
    +
    +
    +
    +
    + + +
    +
    + +
      + +
      - -
      - - - - -
      - -
      - -

      - Recently viewed -

      -
      -
      -
      -
      -
      + Undock navigation
      - -
      -
      - -
      -
      -
      - - - -
      -
      -
      -
      -
      -
      - - - -
      -
      - -
      - -
      -
      - -
        - -
      • - -
      • -
        -
      -
      -
      -
      -
      - , } - > - -
      -
      - -
        - -
        - - Undock navigation - - , - } - } - color="subdued" - data-test-subj="collapsible-nav-lock" - iconType="lock" - label="Undock navigation" - onClick={[Function]} - size="xs" - > -
      • - -
      • - -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - + + +
      +
    +
    - -
    + + +
    + + + +
    - - + } + > + + +
    + + + + close + + + + + + + + +
    From 86ad1d33599dec3946c524f268a45f27896dfe3b Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 27 Aug 2020 14:04:29 -0400 Subject: [PATCH 36/71] add passing test --- test/accessibility/apps/management.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/accessibility/apps/management.ts b/test/accessibility/apps/management.ts index b37500f5b15dd..08177f54ee881 100644 --- a/test/accessibility/apps/management.ts +++ b/test/accessibility/apps/management.ts @@ -64,8 +64,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - // Will be enabling this and field formatters after this issue is addressed: https://github.com/elastic/kibana/issues/60030 - it.skip('Edit field type', async () => { + it('Edit field type', async () => { await PageObjects.settings.clickEditFieldFormat(); await a11y.testAppSnapshot(); }); From db88ceda24cf998dac0785d9daa7964a31ce6c80 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 27 Aug 2020 20:13:31 -0400 Subject: [PATCH 37/71] adding tests for searching behavior --- .../__snapshots__/search_bar.test.tsx.snap | 357 +++--------------- .../public/components/search_bar.test.tsx | 90 +++-- 2 files changed, 117 insertions(+), 330 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 51fceafd512ef..0d3a96792d29d 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -1,312 +1,51 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`SearchBar basically works 1`] = ` - - -
    - - [Function] - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={false} - isOpen={false} - ownFocus={false} - panelPaddingSize="none" - panelRef={[Function]} - > - -
    -
    - - - - -
    -
    - - - - -
    - - -
    -
    - - - - -
    -
    - - -
    - - +exports[`SearchBar correctly filters and sorts results 1`] = ` +Array [ + Object { + "id": "Canvas", + "key": "Canvas", + "score": 42, + "title": "Canvas", + "type": "application", + "url": "/app/test/Canvas", + }, + Object { + "id": "Discover", + "key": "Discover", + "score": 42, + "title": "Discover", + "type": "application", + "url": "/app/test/Discover", + }, + Object { + "id": "Graph", + "key": "Graph", + "score": 42, + "title": "Graph", + "type": "application", + "url": "/app/test/Graph", + }, +] +`; + +exports[`SearchBar correctly filters and sorts results 2`] = ` +Array [ + Object { + "id": "Discover", + "key": "Discover", + "score": 42, + "title": "Discover", + "type": "application", + "url": "/app/test/Discover", + }, + Object { + "id": "My Dashboard", + "key": "My Dashboard", + "score": 42, + "title": "My Dashboard", + "type": "test", + "url": "/app/test/My Dashboard", + }, +] `; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx index ffa0d08f8a8ca..39bba49bee5cf 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -4,41 +4,89 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ReactWrapper } from 'enzyme'; import React from 'react'; -import { SearchBar } from '../components/search_bar'; -import { globalSearchPluginMock } from '../../../global_search/public/mocks'; -import { GlobalSearchPluginStart } from '../../../global_search/public'; +import { act } from 'react-dom/test-utils'; +import { of } from 'rxjs'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { + GlobalSearchBatchedResults, + GlobalSearchPluginStart, + GlobalSearchResult, +} from '../../../global_search/public'; +import { globalSearchPluginMock } from '../../../global_search/public/mocks'; +import { SearchBar } from '../components/search_bar'; + +type Result = { id: string; type: string } | string; + +const createResult = (result: Result): GlobalSearchResult => { + const id = typeof result === 'string' ? result : result.id; + const type = typeof result === 'string' ? 'application' : result.type; + + return { + id, + type, + title: id, + url: `/app/test/${id}`, + score: 42, + }; +}; + +const createBatch = (...results: Result[]): GlobalSearchBatchedResults => ({ + results: results.map(createResult), +}); jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ htmlIdGenerator: () => () => 'mockId', })); +const getSelectableProps: any = (component: any) => component.find('EuiSelectable').props(); +const getSearchProps: any = (component: any) => component.find('EuiFieldSearch').props(); + describe('SearchBar', () => { let searchService: GlobalSearchPluginStart; - // let findSpy: jest.SpyInstance; + let findSpy: jest.SpyInstance; beforeEach(() => { searchService = globalSearchPluginMock.createStartContract(); - // findSpy = jest.spyOn(globalSearchPluginMock, 'createStartContract'); + findSpy = jest.spyOn(searchService, 'find'); }); - it('basically works', async () => { - const component = mountWithIntl( - - ); - expect(component).toMatchSnapshot(); // popover closed - // expect(findSpy).toHaveBeenCalledTimes(1); - // expect(findSpy).toHaveBeenCalledWith(''); - - // component.find('input[data-test-subj="header-search"]').simulate('keydown', { key: 'd' }); - // expect(component).toMatchSnapshot(); // popover open - // expect(findSpy).toHaveBeenCalledTimes(1); - // expect(findSpy).toHaveBeenCalledWith('d'); - - // click on result - // navigate to new page - // click into into search bar, results rendered like new + it('correctly filters and sorts results', async () => { + const navigate = jest.fn(); + let component: ReactWrapper; + findSpy + .mockReturnValueOnce( + of( + createBatch('Discover', 'Canvas'), + createBatch({ id: 'Visualize', type: 'test' }, 'Graph') + ) + ) + .mockReturnValueOnce(of(createBatch('Discover', { id: 'My Dashboard', type: 'test' }))); + + act(() => { + component = mountWithIntl( + + ); + }); + expect(findSpy).toHaveBeenCalledTimes(1); + expect(findSpy).toHaveBeenCalledWith('', {}); + act(() => { + component.update(); + expect(getSelectableProps(component).options).toMatchSnapshot(); // default list + component.find('input[data-test-subj="header-search"]').simulate('focus'); + }); + expect(findSpy).toHaveBeenCalledTimes(1); + + act(() => { + component.update(); + getSearchProps(component).onSearch('d'); + }); + act(() => { + component.update(); + expect(getSelectableProps(component).options).toMatchSnapshot(); // list filtered + }); + expect(findSpy).toHaveBeenCalledTimes(2); }); it('supports keyboard shortcuts', () => { // cmd/ctrl+s focuses search bar, popover opens, results rendered From 9de5e9bcbe0d70f6116d341d92f5a15f5297fb13 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 31 Aug 2020 21:11:56 -0400 Subject: [PATCH 38/71] EUI search template --- .../collapsible_nav.test.tsx.snap | 12 + .../header/__snapshots__/header.test.tsx.snap | 2 + .../__snapshots__/search_bar.test.tsx.snap | 50 +++-- .../public/components/search_bar.tsx | 208 +++++++----------- 4 files changed, 121 insertions(+), 151 deletions(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 0713bc6969084..9812f8c60f75d 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -650,6 +650,8 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` data-test-subj="collapsibleNavGroup-recentlyViewed" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > @@ -901,6 +903,8 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` data-test-subj="collapsibleNavGroup-kibana" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > @@ -1188,6 +1192,8 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` data-test-subj="collapsibleNavGroup-observability" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > @@ -1436,6 +1442,8 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` data-test-subj="collapsibleNavGroup-securitySolution" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > @@ -1636,6 +1644,8 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` data-test-subj="collapsibleNavGroup-management" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > @@ -2857,6 +2867,8 @@ exports[`CollapsibleNav renders the default nav 3`] = ` data-test-subj="collapsibleNavGroup-recentlyViewed" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index 25f901a47ae07..160344259bb67 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -11499,6 +11499,8 @@ exports[`Header renders 3`] = ` data-test-subj="collapsibleNavGroup-recentlyViewed" id="mockId" initialIsOpen={true} + isLoading={false} + isLoadingMessage={false} onToggle={[Function]} paddingSize="none" > diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 0d3a96792d29d..69b4d27d922d4 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -3,27 +3,30 @@ exports[`SearchBar correctly filters and sorts results 1`] = ` Array [ Object { - "id": "Canvas", + "append": undefined, + "className": "euiSelectableTemplateSitewide__listItem", "key": "Canvas", - "score": 42, - "title": "Canvas", - "type": "application", + "label": "Canvas", + "prepend": undefined, + "title": "Canvasundefinedundefined", "url": "/app/test/Canvas", }, Object { - "id": "Discover", + "append": undefined, + "className": "euiSelectableTemplateSitewide__listItem", "key": "Discover", - "score": 42, - "title": "Discover", - "type": "application", + "label": "Discover", + "prepend": undefined, + "title": "Discoverundefinedundefined", "url": "/app/test/Discover", }, Object { - "id": "Graph", + "append": undefined, + "className": "euiSelectableTemplateSitewide__listItem", "key": "Graph", - "score": 42, - "title": "Graph", - "type": "application", + "label": "Graph", + "prepend": undefined, + "title": "Graphundefinedundefined", "url": "/app/test/Graph", }, ] @@ -32,19 +35,26 @@ Array [ exports[`SearchBar correctly filters and sorts results 2`] = ` Array [ Object { - "id": "Discover", + "append": undefined, + "className": "euiSelectableTemplateSitewide__listItem", "key": "Discover", - "score": 42, - "title": "Discover", - "type": "application", + "label": "Discover", + "prepend": undefined, + "title": "Discoverundefinedundefined", "url": "/app/test/Discover", }, Object { - "id": "My Dashboard", + "append": undefined, + "className": "euiSelectableTemplateSitewide__listItem", "key": "My Dashboard", - "score": 42, - "title": "My Dashboard", - "type": "test", + "label": "My Dashboard", + "meta": Array [ + Object { + "text": "Test", + }, + ], + "prepend": undefined, + "title": "My Dashboard • Test", "url": "/app/test/My Dashboard", }, ] diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 06e86b2c5dc2e..5942b62c7a95b 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -4,21 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect, useCallback, useRef, FocusEvent } from 'react'; import { - EuiSelectable, - EuiPopover, - EuiPopoverFooter, EuiText, + EuiBadge, + EuiSelectableTemplateSitewide, + EuiSelectableTemplateSitewideOption, EuiFlexGroup, EuiFlexItem, - EuiBadge, - EuiIcon, - EuiSelectableOption, } from '@elastic/eui'; +import React, { useState, useEffect, useRef, useCallback } from 'react'; import { ApplicationStart } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; import { GlobalSearchPluginStart, GlobalSearchResult } from '../../../global_search/public'; const useIfMounted = () => { @@ -44,30 +40,37 @@ interface Props { navigateToUrl: ApplicationStart['navigateToUrl']; } +const cleanMeta = (str: string) => (str.charAt(0).toUpperCase() + str.slice(1)).replace(/-/g, ' '); + export function SearchBar({ globalSearch, navigateToUrl }: Props) { const ifMounted = useIfMounted(); - const [isSearchFocused, setSearchFocus] = useState(false); - const [term, setTerm] = useState(null); - const [options, _setOptions] = useState([] as GlobalSearchResult[]); - // const [isLoading, setLoadingState] = useState(false); + const [searchValue, setSearchValue] = useState(null); const [searchRef, setSearchRef] = useState(null); - const [panelRef, setPanelRef] = useState(null); + const [options, _setOptions] = useState([] as EuiSelectableTemplateSitewideOption[]); const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; const onSearch = useCallback( - (currentTerm: string) => { - if (currentTerm === term) return; + (currentValue: string) => { + if (currentValue === searchValue) return; const setOptions = (_options: GlobalSearchResult[]) => { ifMounted(() => - _setOptions([..._options.map((option) => ({ key: option.id, ...option }))]) + _setOptions([ + ..._options.map((option) => ({ + key: option.id, + label: option.title, + url: option.url, + ...(option.icon && { icon: { type: option.icon } }), + ...(option.type && + option.type !== 'application' && { meta: [{ text: cleanMeta(option.type) }] }), + })), + ]) ); }; let arr: GlobalSearchResult[] = []; - // setLoadingState(true); - globalSearch(currentTerm, {}).subscribe({ + globalSearch(currentValue, {}).subscribe({ next: ({ results }) => { - if (currentTerm.length > 0) { + if (currentValue.length > 0) { arr = [...results, ...arr].sort((a, b) => { if (a.score < b.score) return 1; if (a.score > b.score) return -1; @@ -94,137 +97,80 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { // TODO }, complete: () => { - ifMounted(() => setTerm(currentTerm)); - // setLoadingState(false); + ifMounted(() => setSearchValue(currentValue)); }, }); }, - [globalSearch, term, ifMounted] + [globalSearch, searchValue, ifMounted] ); - useEffect(() => { - onSearch(''); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const onWindowKeyDown = (event: any) => { + if (event.key === '/' && (isWindows ? event.ctrlKey : event.metaKey)) { + if (searchRef) { + event.preventDefault(); + searchRef.focus(); + } + } + }; + + const onChange = (selected: EuiSelectableTemplateSitewideOption[]) => { + // @ts-ignore - ts error is "union type is too complex to express" + const { url } = selected.find(({ checked }) => checked === 'on'); + + // TODO should we be worried about http://? + if (url.startsWith('https://')) window.location.assign(url); + else { + navigateToUrl(url); + (document.activeElement as HTMLElement).blur(); + onSearch(''); + // setSearchFocus(false); + if (searchRef) searchRef.value = ''; + } + }; useEffect(() => { - const openSearch = (event: KeyboardEvent) => { - if (event.key === '/' && (isWindows ? event.ctrlKey : event.metaKey)) { - if (searchRef) { - event.preventDefault(); - searchRef.focus(); - } - } - }; - window.addEventListener('keydown', openSearch); + window.addEventListener('keydown', onWindowKeyDown); return () => { - window.removeEventListener('keydown', openSearch); + window.removeEventListener('resize', onWindowKeyDown); }; - }, [searchRef, isWindows]); + }); + + useEffect(() => { + onSearch(''); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( - { - setSearchFocus(true); - }, - onBlur: (e: FocusEvent) => { - if (!panelRef?.contains(e.relatedTarget as HTMLButtonElement)) { - setSearchFocus(false); - } - }, - placeholder: 'Search for anything...', - incremental: true, - compressed: true, - inputRef: (ref: HTMLInputElement | null) => { - setSearchRef(ref); - }, - 'aria-label': i18n.translate('xpack.globalSearchBar.primaryNav.screenReaderLabel', { - defaultMessage: 'Search for anything...', - }), + inputRef: setSearchRef, }} - listProps={{ - rowHeight: 68, - }} - // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works - options={options} - // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works - renderOption={(option: EuiSelectableOption & GlobalSearchResult) => ( - <> - - {option.icon && } - - {option.title} -
    - {(option.type as string) !== 'application' && option.type} + popoverFooter={ + + + + - - Go to - + {isWindows ? 'Ctrl + /' : 'Command + /'} - - )} - // @ts-ignore EUI TS doesn't allow not list options to be passed but it all works - onChange={async (selected: Array) => { - const { url } = selected.find(({ checked }) => checked === 'on')!; - - if (url.startsWith('https://')) window.location.assign(url); - // TODO should we be worried about http://? - else { - navigateToUrl(url); - (document.activeElement as HTMLElement).blur(); - onSearch(''); - setSearchFocus(false); - if (searchRef) searchRef.value = ''; - } - }} - > - {(list, search) => ( - <> - setSearchFocus(false)} - panelPaddingSize={'none'} - hasArrow={false} - panelRef={setPanelRef} - > -
    {list}
    - - - - - {isWindows ? 'Ctrl + /' : 'Command + /'}, - }} - /> - - - - -
    - - )} -
    + + } + /> ); } From d684023a59a118eb3ebad9cdd7114747d9aba129 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 1 Sep 2020 12:06:11 -0400 Subject: [PATCH 39/71] fixing graph test --- x-pack/test/functional/apps/graph/graph.ts | 2 +- x-pack/test/functional/page_objects/graph_page.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/graph/graph.ts b/x-pack/test/functional/apps/graph/graph.ts index 68e5045c1f36c..7971b101cea07 100644 --- a/x-pack/test/functional/apps/graph/graph.ts +++ b/x-pack/test/functional/apps/graph/graph.ts @@ -13,7 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const browser = getService('browser'); - describe('graph', function () { + describe('foooo', function () { before(async () => { await browser.setWindowSize(1600, 1000); log.debug('load graph/secrepo data'); diff --git a/x-pack/test/functional/page_objects/graph_page.ts b/x-pack/test/functional/page_objects/graph_page.ts index 88f7e42e65254..639add8b0e904 100644 --- a/x-pack/test/functional/page_objects/graph_page.ts +++ b/x-pack/test/functional/page_objects/graph_page.ts @@ -200,7 +200,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon } async getSearchFilter() { - const searchFilter = await find.allByCssSelector('.euiFieldSearch'); + const searchFilter = await find.allByCssSelector('main .euiFieldSearch'); return searchFilter[0]; } From 84020f239dcd9652a0df4a65870809313e089d00 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 1 Sep 2020 19:19:38 -0400 Subject: [PATCH 40/71] misc cleanup --- .../public/components/search_bar.test.tsx | 39 +++++++++++++- .../public/components/search_bar.tsx | 52 ++++++++++++------- .../plugins/global_search_bar/public/index.ts | 4 +- .../global_search_bar/public/plugin.tsx | 2 +- x-pack/test/accessibility/config.ts | 11 ++-- x-pack/test/functional/apps/graph/graph.ts | 2 +- 6 files changed, 79 insertions(+), 31 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx index 39bba49bee5cf..6e7bccc1249bd 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -88,7 +88,44 @@ describe('SearchBar', () => { }); expect(findSpy).toHaveBeenCalledTimes(2); }); - it('supports keyboard shortcuts', () => { + + // TODO unskip + it.skip('supports keyboard shortcuts', () => { // cmd/ctrl+s focuses search bar, popover opens, results rendered + let component: ReactWrapper; + + act(() => { + component = mountWithIntl( + + ); + }); + + act(() => { + const searchEvent = new KeyboardEvent('keydown', { + key: '/', + ctrlKey: true, + metaKey: true, + } as any); + window.dispatchEvent(searchEvent); + }); + + act(() => { + component.update(); + }); + + act(() => { + const searchEvent = new KeyboardEvent('keydown', { + key: 'a', + } as any); + window.dispatchEvent(searchEvent); + }); + + act(() => { + component.update(); + }); + + act(() => { + expect(component.find('input').getDOMNode().getAttribute('value')).toBe('a'); + }); }); }); diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 5942b62c7a95b..830a8fac1f55d 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -5,16 +5,17 @@ */ import { - EuiText, EuiBadge, - EuiSelectableTemplateSitewide, - EuiSelectableTemplateSitewideOption, EuiFlexGroup, EuiFlexItem, + EuiSelectableTemplateSitewide, + EuiSelectableTemplateSitewideOption, + EuiText, } from '@elastic/eui'; -import React, { useState, useEffect, useRef, useCallback } from 'react'; -import { ApplicationStart } from 'kibana/public'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ApplicationStart } from 'kibana/public'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { GlobalSearchPluginStart, GlobalSearchResult } from '../../../global_search/public'; const useIfMounted = () => { @@ -41,6 +42,7 @@ interface Props { } const cleanMeta = (str: string) => (str.charAt(0).toUpperCase() + str.slice(1)).replace(/-/g, ' '); +const blurEvent = new FocusEvent('blur'); export function SearchBar({ globalSearch, navigateToUrl }: Props) { const ifMounted = useIfMounted(); @@ -94,7 +96,9 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { setOptions(arr); }, error: () => { - // TODO + // TODO #74430 - add telemetry to see if errors are happening + // Not doing anything on error right now because it'll either just show the previous + // results or empty results which is basically what we want anyways }, complete: () => { ifMounted(() => setSearchValue(currentValue)); @@ -104,7 +108,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { [globalSearch, searchValue, ifMounted] ); - const onWindowKeyDown = (event: any) => { + const onWindowKeyDown = (event: KeyboardEvent) => { if (event.key === '/' && (isWindows ? event.ctrlKey : event.metaKey)) { if (searchRef) { event.preventDefault(); @@ -117,14 +121,15 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { // @ts-ignore - ts error is "union type is too complex to express" const { url } = selected.find(({ checked }) => checked === 'on'); - // TODO should we be worried about http://? - if (url.startsWith('https://')) window.location.assign(url); + if (/^https?:\/\//.test(url)) window.location.assign(url); else { navigateToUrl(url); (document.activeElement as HTMLElement).blur(); onSearch(''); - // setSearchFocus(false); - if (searchRef) searchRef.value = ''; + if (searchRef) { + searchRef.value = ''; + searchRef.dispatchEvent(blurEvent); + } } }; @@ -149,6 +154,10 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { onSearch, 'data-test-subj': 'header-search', inputRef: setSearchRef, + isClearable: false, + placeholder: i18n.translate('xpack.globalSearchBar.searchBar.placeholder', { + defaultMessage: 'Search Elastic', + }), }} popoverFooter={ @@ -159,15 +168,18 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { responsive={false} wrap > - - - - - {isWindows ? 'Ctrl + /' : 'Command + /'} - + Quickly search using:, + how: ( + + {isWindows ? 'Ctrl + S' : 'Command + S'} + + ), + }} + /> } diff --git a/x-pack/plugins/global_search_bar/public/index.ts b/x-pack/plugins/global_search_bar/public/index.ts index 758d95c7e9ba8..9e11c43ce872c 100644 --- a/x-pack/plugins/global_search_bar/public/index.ts +++ b/x-pack/plugins/global_search_bar/public/index.ts @@ -5,6 +5,6 @@ */ import { PluginInitializer } from 'src/core/public'; -import { GlobalSearchProvidersPlugin } from './plugin'; +import { GlobalSearchBarPlugin } from './plugin'; -export const plugin: PluginInitializer<{}, {}, {}, {}> = () => new GlobalSearchProvidersPlugin(); +export const plugin: PluginInitializer<{}, {}, {}, {}> = () => new GlobalSearchBarPlugin(); diff --git a/x-pack/plugins/global_search_bar/public/plugin.tsx b/x-pack/plugins/global_search_bar/public/plugin.tsx index 9d38aedd65e03..0c8cc2e64726a 100644 --- a/x-pack/plugins/global_search_bar/public/plugin.tsx +++ b/x-pack/plugins/global_search_bar/public/plugin.tsx @@ -16,7 +16,7 @@ export interface GlobalSearchBarPluginStartDeps { globalSearch: GlobalSearchPluginStart; } -export class GlobalSearchProvidersPlugin implements Plugin<{}, {}> { +export class GlobalSearchBarPlugin implements Plugin<{}, {}> { public async setup() { return {}; } diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index 11a1862106792..0a95805754314 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -16,12 +16,11 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [ require.resolve('./apps/login_page'), - // TODO uncomment after EUI is upgraded, before merging - // require.resolve('./apps/home'), - // require.resolve('./apps/grok_debugger'), - // require.resolve('./apps/search_profiler'), - // require.resolve('./apps/uptime'), - // require.resolve('./apps/painless_lab'), + require.resolve('./apps/home'), + require.resolve('./apps/grok_debugger'), + require.resolve('./apps/search_profiler'), + require.resolve('./apps/uptime'), + require.resolve('./apps/painless_lab'), ], pageObjects, services, diff --git a/x-pack/test/functional/apps/graph/graph.ts b/x-pack/test/functional/apps/graph/graph.ts index 7971b101cea07..68e5045c1f36c 100644 --- a/x-pack/test/functional/apps/graph/graph.ts +++ b/x-pack/test/functional/apps/graph/graph.ts @@ -13,7 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const browser = getService('browser'); - describe('foooo', function () { + describe('graph', function () { before(async () => { await browser.setWindowSize(1600, 1000); log.debug('load graph/secrepo data'); From 8e6d3e5ddaef4cc43c78aa6586b766f245a4e10e Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Wed, 2 Sep 2020 15:13:16 +0200 Subject: [PATCH 41/71] add and wire HeaderActionMenu component --- .../header/__snapshots__/header.test.tsx.snap | 196 +++++++++++++++++- src/core/public/chrome/ui/header/header.tsx | 3 +- .../ui/header/header_action_menu.test.tsx | 139 +++++++++++++ .../chrome/ui/header/header_action_menu.tsx | 64 ++++++ 4 files changed, 397 insertions(+), 5 deletions(-) create mode 100644 src/core/public/chrome/ui/header/header_action_menu.test.tsx create mode 100644 src/core/public/chrome/ui/header/header_action_menu.tsx diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index 23541433b6819..82bb7f9600609 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -618,7 +618,45 @@ exports[`Header renders 2`] = ` "closed": false, "hasError": false, "isStopped": false, - "observers": Array [], + "observers": Array [ + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + ], "thrownError": null, }, "currentAppId$": Observable { @@ -5611,7 +5649,63 @@ exports[`Header renders 2`] = ` >
    + > + +
    + +
    @@ -5976,7 +6070,45 @@ exports[`Header renders 3`] = ` "closed": false, "hasError": false, "isStopped": false, - "observers": Array [], + "observers": Array [ + Subscriber { + "_parentOrParents": null, + "_subscriptions": Array [ + SubjectSubscription { + "_parentOrParents": [Circular], + "_subscriptions": null, + "closed": false, + "subject": [Circular], + "subscriber": [Circular], + }, + ], + "closed": false, + "destination": SafeSubscriber { + "_complete": undefined, + "_context": [Circular], + "_error": undefined, + "_next": [Function], + "_parentOrParents": null, + "_parentSubscriber": [Circular], + "_subscriptions": null, + "closed": false, + "destination": Object { + "closed": true, + "complete": [Function], + "error": [Function], + "next": [Function], + }, + "isStopped": false, + "syncErrorThrowable": false, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + "isStopped": false, + "syncErrorThrowable": true, + "syncErrorThrown": false, + "syncErrorValue": null, + }, + ], "thrownError": null, }, "currentAppId$": Observable { @@ -10969,7 +11101,63 @@ exports[`Header renders 3`] = ` >
    + > + +
    + +
    diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 7ae347a8a4b99..1e13f276db670 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -48,6 +48,7 @@ import { HeaderBreadcrumbs } from './header_breadcrumbs'; import { HeaderHelpMenu } from './header_help_menu'; import { HeaderLogo } from './header_logo'; import { HeaderNavControls } from './header_nav_controls'; +import { HeaderActionMenu } from './header_action_menu'; export interface HeaderProps { kibanaVersion: string; @@ -169,7 +170,7 @@ export function Header({ - {/* TODO app content goes here */} + diff --git a/src/core/public/chrome/ui/header/header_action_menu.test.tsx b/src/core/public/chrome/ui/header/header_action_menu.test.tsx new file mode 100644 index 0000000000000..a124c8ab66969 --- /dev/null +++ b/src/core/public/chrome/ui/header/header_action_menu.test.tsx @@ -0,0 +1,139 @@ +/* + * 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 { mount, ReactWrapper } from 'enzyme'; +import { act } from 'react-dom/test-utils'; +import { BehaviorSubject } from 'rxjs'; +import { HeaderActionMenu } from './header_action_menu'; +import { MountPoint, UnmountCallback } from '../../../types'; + +type MockedUnmount = jest.MockedFunction; + +describe('HeaderActionMenu', () => { + let component: ReactWrapper; + let menuMount$: BehaviorSubject; + let unmounts: Record; + + beforeEach(() => { + menuMount$ = new BehaviorSubject(undefined); + unmounts = {}; + }); + + const refresh = () => { + new Promise(async (resolve) => { + if (component) { + act(() => { + component.update(); + }); + } + setImmediate(() => resolve(component)); // flushes any pending promises + }); + }; + + const createMountPoint = (id: string, content: string = id): MountPoint => ( + root + ): MockedUnmount => { + const container = document.createElement('DIV'); + // eslint-disable-next-line no-unsanitized/property + container.innerHTML = content; + root.appendChild(container); + const unmount = jest.fn(() => container.remove()); + unmounts[id] = unmount; + return unmount; + }; + + it('mounts the current value of the provided observable', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
    FOO
    "` + ); + }); + + it('clears the content of the component when emitting undefined', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
    FOO
    "` + ); + + act(() => { + menuMount$.next(undefined); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
    "` + ); + }); + + it('updates the dom when a new mount point is emitted', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
    FOO
    "` + ); + + act(() => { + menuMount$.next(createMountPoint('BAR')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
    BAR
    "` + ); + }); + + it('calls the previous mount point `unmount` when mounting a new mount point', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(Object.keys(unmounts)).toEqual(['FOO']); + expect(unmounts.FOO).not.toHaveBeenCalled(); + + act(() => { + menuMount$.next(createMountPoint('BAR')); + }); + await refresh(); + + expect(Object.keys(unmounts)).toEqual(['FOO', 'BAR']); + expect(unmounts.FOO).toHaveBeenCalledTimes(1); + expect(unmounts.BAR).not.toHaveBeenCalled(); + }); +}); diff --git a/src/core/public/chrome/ui/header/header_action_menu.tsx b/src/core/public/chrome/ui/header/header_action_menu.tsx new file mode 100644 index 0000000000000..3a7a09608ba66 --- /dev/null +++ b/src/core/public/chrome/ui/header/header_action_menu.tsx @@ -0,0 +1,64 @@ +/* + * 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, { FC, useRef, useLayoutEffect, useState } from 'react'; +import { Observable } from 'rxjs'; +import { MountPoint, UnmountCallback } from '../../../types'; + +interface HeaderActionMenuProps { + actionMenu$: Observable; +} + +export const HeaderActionMenu: FC = ({ actionMenu$ }) => { + // useObservable relies on useState under the hood. The signature is type SetStateAction = S | ((prevState: S) => S); + // As we got a Observable here, React's setState setter assume he's getting a `(prevState: S) => S` signature, + // therefore executing the mount method, causing everything to crash. + // piping the observable before calling `useObservable` causes the effect to always having a new reference, as + // the piped observable is a new instance on every render, causing infinite loops. + // this is why we use `useLayoutEffect` manually here. + const [mounter, setMounter] = useState<{ mount: MountPoint | undefined }>({ mount: undefined }); + useLayoutEffect(() => { + const s = actionMenu$.subscribe((value) => { + setMounter({ mount: value }); + }); + return () => s.unsubscribe(); + }, [actionMenu$]); + + const elementRef = useRef(null); + const unmountRef = useRef(null); + + useLayoutEffect(() => { + if (unmountRef.current) { + unmountRef.current(); + unmountRef.current = null; + } + + if (mounter.mount && elementRef.current) { + try { + unmountRef.current = mounter.mount(elementRef.current); + } catch (e) { + // TODO: use client-side logger when feature is implemented + // eslint-disable-next-line no-console + console.error(e); + } + } + }, [mounter]); + + return
    ; +}; From 7b8125d388353e04e0b07efbd1ae0715c87824c1 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Wed, 2 Sep 2020 15:15:01 +0200 Subject: [PATCH 42/71] fix event type --- .../plugins/global_search_bar/public/components/search_bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 830a8fac1f55d..be25056ef0970 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -137,7 +137,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { window.addEventListener('keydown', onWindowKeyDown); return () => { - window.removeEventListener('resize', onWindowKeyDown); + window.removeEventListener('keydown', onWindowKeyDown); }; }); From b208bdee677a730dc0bcfc72f014e17a41bfa334 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Wed, 2 Sep 2020 15:55:56 +0200 Subject: [PATCH 43/71] fireproof MountPointPortal against concurrent react / portal target unmounts --- src/plugins/kibana_react/public/util/index.ts | 1 + .../public/util/mount_point_portal.tsx | 23 ++++++++--- src/plugins/kibana_react/public/util/utils.ts | 38 +++++++++++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/plugins/kibana_react/public/util/utils.ts diff --git a/src/plugins/kibana_react/public/util/index.ts b/src/plugins/kibana_react/public/util/index.ts index a6f3f87535f46..030dd4aec0f12 100644 --- a/src/plugins/kibana_react/public/util/index.ts +++ b/src/plugins/kibana_react/public/util/index.ts @@ -19,3 +19,4 @@ export { toMountPoint } from './to_mount_point'; export { MountPointPortal } from './mount_point_portal'; +export { useIfMounted } from './utils'; diff --git a/src/plugins/kibana_react/public/util/mount_point_portal.tsx b/src/plugins/kibana_react/public/util/mount_point_portal.tsx index b762fba88791e..0249302763772 100644 --- a/src/plugins/kibana_react/public/util/mount_point_portal.tsx +++ b/src/plugins/kibana_react/public/util/mount_point_portal.tsx @@ -21,6 +21,7 @@ import { i18n } from '@kbn/i18n'; import React, { useRef, useEffect, useState, Component } from 'react'; import ReactDOM from 'react-dom'; import { MountPoint } from 'kibana/public'; +import { useIfMounted } from './utils'; interface MountPointPortalProps { setMountPoint: (mountPoint: MountPoint) => void; @@ -33,20 +34,30 @@ export const MountPointPortal: React.FC = ({ children, se // state used to force re-renders when the element changes const [shouldRender, setShouldRender] = useState(false); const el = useRef(); + const ifMounted = useIfMounted(); useEffect(() => { setMountPoint((element) => { - el.current = element; - setShouldRender(true); + ifMounted(() => { + el.current = element; + setShouldRender(true); + }); return () => { - setShouldRender(false); - el.current = undefined; + // the component can be unmounted from the dom before the portal target actually + // calls the `unmount` function. This is a no-op but show a scary warning in the console + // so we use a ifMounted effect to avoid it. + ifMounted(() => { + setShouldRender(false); + el.current = undefined; + }); }; }); return () => { - setShouldRender(false); - el.current = undefined; + ifMounted(() => { + setShouldRender(false); + el.current = undefined; + }); }; }, [setMountPoint]); diff --git a/src/plugins/kibana_react/public/util/utils.ts b/src/plugins/kibana_react/public/util/utils.ts new file mode 100644 index 0000000000000..23d4ac2ec4851 --- /dev/null +++ b/src/plugins/kibana_react/public/util/utils.ts @@ -0,0 +1,38 @@ +/* + * 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 { useCallback, useEffect, useRef } from 'react'; + +export const useIfMounted = () => { + const isMounted = useRef(true); + useEffect( + () => () => { + isMounted.current = false; + }, + [] + ); + + const ifMounted = useCallback((func) => { + if (isMounted.current && func) { + func(); + } + }, []); + + return ifMounted; +}; From abbc1b30b036c32cbb0ec83c4baf88a05e3b219b Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Wed, 2 Sep 2020 15:59:57 +0200 Subject: [PATCH 44/71] wire setHeaderActionMenu API to dashboard app TopNavMenu --- src/plugins/dashboard/public/application/application.ts | 2 ++ .../public/application/dashboard_app_controller.tsx | 6 +++++- src/plugins/dashboard/public/plugin.tsx | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/dashboard/public/application/application.ts b/src/plugins/dashboard/public/application/application.ts index 21f423d009ee7..fcfae88d58bc7 100644 --- a/src/plugins/dashboard/public/application/application.ts +++ b/src/plugins/dashboard/public/application/application.ts @@ -31,6 +31,7 @@ import { SavedObjectsClientContract, PluginInitializerContext, ScopedHistory, + AppMountParameters, } from 'kibana/public'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { Storage } from '../../../kibana_utils/public'; @@ -72,6 +73,7 @@ export interface RenderDeps { navigateToDefaultApp: KibanaLegacyStart['navigateToDefaultApp']; navigateToLegacyKibanaUrl: KibanaLegacyStart['navigateToLegacyKibanaUrl']; scopedHistory: () => ScopedHistory; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; savedObjects: SavedObjectsStart; restorePreviousUrl: () => void; } diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index 0d20fdee07df5..24fedc19369a8 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -144,6 +144,7 @@ export class DashboardAppController { i18n: i18nStart, }, history, + setHeaderActionMenu, kbnUrlStateStorage, usageCollection, navigation, @@ -682,7 +683,10 @@ export class DashboardAppController { }; const dashboardNavBar = document.getElementById('dashboardChrome'); const updateNavBar = () => { - ReactDOM.render(, dashboardNavBar); + ReactDOM.render( + , + dashboardNavBar + ); }; const unmountNavBar = () => { diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 3dbf6d9d3997e..068e475039865 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -331,6 +331,7 @@ export class DashboardPlugin localStorage: new Storage(localStorage), usageCollection, scopedHistory: () => this.currentHistory!, + setHeaderActionMenu: params.setHeaderActionMenu, savedObjects, restorePreviousUrl, }; From 8f8eacc760124b8deba5ea898513bdaafce5f251 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 1 Sep 2020 16:55:04 -0700 Subject: [PATCH 45/71] [Reporting] Add functional test for Reports in non-default spaces (#76053) * [Reporting] Add functional test for Download CSV in non-default space * skip tests * unskip * rm comment Co-authored-by: Elastic Machine --- .../ecommerce_kibana_spaces/data.json.gz | Bin 0 -> 1752 bytes .../ecommerce_kibana_spaces/mappings.json | 2635 +++++++++++++++++ .../reporting_and_security.config.ts | 1 - .../reporting_and_security/index.ts | 3 +- .../reporting_and_security/network_policy.ts | 2 +- .../reporting_and_security/spaces.ts | 76 + .../reporting_and_security/usage.ts | 2 +- 7 files changed, 2715 insertions(+), 4 deletions(-) create mode 100644 x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json.gz create mode 100644 x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/mappings.json create mode 100644 x-pack/test/reporting_api_integration/reporting_and_security/spaces.ts diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json.gz b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..06e83f8c267d6618669bd8641c79c3dda19c1679 GIT binary patch literal 1752 zcmV;}1}FI+iwFpY>qcJ!17u-zVJ>QOZ*Bn9TU&3VI23;GuZVbDH3$f~z}srNm1d>s ztftv{n6^R=IElA_Gsbk9t@7XZ*jxgHWXQDJ#8Rt}S72+JT*fmDu0Q-*7$7789rioD> zjR!_Q7*4Q*(Res9XL5QmqZlbB)gQ?W#i*bsG-dvF<)UY?Mx_Co<^+d9B4)XJxz~J} z#{6D$jmvv2MiGX`d(9)ky#@rqp(G@nk$53#IGF-90rFkm@d2ob&&Y~n_~y=0m|#J| zi1|x23&j+irGkbQ3x*en*QpGn;F{6siuzxL2$N!#&E8?7z!1pP~;+kLSRFrT+}KdEA9vt(RXr$)sn{e{7oxBYmd&o9~eI> z1=b^bHzYN!%Z@_bOO56MJ3Uhf+GA zg?xUFd)pS6DwMM;MuXJniQXCQ2`#+}R!vK!yN7F777%;QV(85BL5VjYiR|E^DC?(^Q<@} zy9ry`vvRm4-m^|HEqK8Nzo+7aCv(a3&x_qJ(Va3MrpXyyeR#-k*2)XBoJ9CqT$;TB ztm5A6_E5Xtjfb)s`!tHgj{7$)Z`~B#w1_O2{4MA!W(j=MujV#y?P_Cvq#L`l2%*Wl z#H|;MOHjby9E;mhgShBq8J5vECVgu(wJg_mT+7mp ziSaE%x497in~RH=*W8TuX*?$jccL4>_0e~pv(a^l&Qbz;OCz8^eQcVq&~~Qb zeYlTM^H2CIL{t$i)JwwegKLb$Nk(;CWn?bmcIobDqhPur{DV>)x&uoeSk|khm}5I$ zb}hp3Kp>bsVKKc7i&eAFqHAWW+H^^h9{lko?&S!2b@qQn)>rvVw{ItB+Z~wtWHNZu z*c6~-IirXL?!b329*o}jjg4~thV9mMP!;u(a3Nl!Ldq7oMWD{lvwyJ9KVgn)6NLH2+oPE(vn$bFP9)x3dCH=w1SK2YlKSv81T&!~>Dz2Zm+Zwu$;f8=HOGo{jqs0)q;iv4N0dIf3nGJWCuO zvlmJ_4-^#))P+GHT;qcbyaHc2-xoZ;DYtrp-~luBA_Sryc+>JD)R7DSQh zaK*ZfR{hA*1`43eiA<+&jQXZAH3qIZcCCp%F(AP=`hUR*r)+mI**K-!sm6WNo|;f7 z3|(WS4<^HJt>w}mP%ibZ3hVFP(70ER36()lW#%-GOs`e;Cf51LUxzsAqFpc6me}bIdYe#FxD&q_tKj@0WI$WU&n4pZ^|)+myIXZaLvq*;(W{VHwpt ubBwXUgzfn~p^WdX@ahr%HnX^n!MqXay6#DbmTp { + describe('Network Policy', () => { before(async () => { await esArchiver.load(archive); // includes a canvas worksheet with an offending image URL }); diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/spaces.ts b/x-pack/test/reporting_api_integration/reporting_and_security/spaces.ts new file mode 100644 index 0000000000000..0145ca2a18092 --- /dev/null +++ b/x-pack/test/reporting_api_integration/reporting_and_security/spaces.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import * as Rx from 'rxjs'; +import { filter, first, map, switchMap, tap, timeout } from 'rxjs/operators'; +import { FtrProviderContext } from '../ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const reportingAPI = getService('reportingAPI'); + const supertest = getService('supertest'); + const log = getService('log'); + + const getCompleted$ = (downloadPath: string) => { + return Rx.interval(2000).pipe( + tap(() => log.debug(`checking report status at ${downloadPath}...`)), + switchMap(() => supertest.get(downloadPath)), + filter(({ status: statusCode }) => statusCode === 200), + map((response) => response.text), + first(), + timeout(15000) + ); + }; + + describe('Exports from Non-default Space', () => { + before(async () => { + await esArchiver.load('reporting/ecommerce'); + await esArchiver.load('reporting/ecommerce_kibana_spaces'); // dashboard in non default space + }); + + after(async () => { + await esArchiver.unload('reporting/ecommerce'); + await esArchiver.unload('reporting/ecommerce_kibana_spaces'); + }); + + afterEach(async () => { + await reportingAPI.deleteAllReports(); + }); + + it('should complete a job of CSV saved search export in non-default space', async () => { + const downloadPath = await reportingAPI.postJob( + `/s/non_default_space/api/reporting/generate/csv?jobParams=%28browserTimezone%3AUTC%2CconflictedTypesFields%3A%21%28%29%2Cfields%3A%21%28order_date%2Ccategory%2Ccustomer_first_name%2Ccustomer_full_name%2Ctotal_quantity%2Ctotal_unique_products%2Ctaxless_total_price%2Ctaxful_total_price%2Ccurrency%29%2CindexPatternId%3A%27067dec90-e7ee-11ea-a730-d58e9ea7581b%27%2CmetaFields%3A%21%28_source%2C_id%2C_type%2C_index%2C_score%29%2CobjectType%3Asearch%2CsearchRequest%3A%28body%3A%28_source%3A%28includes%3A%21%28order_date%2Ccategory%2Ccustomer_first_name%2Ccustomer_full_name%2Ctotal_quantity%2Ctotal_unique_products%2Ctaxless_total_price%2Ctaxful_total_price%2Ccurrency%29%29%2Cdocvalue_fields%3A%21%28%28field%3Aorder_date%2Cformat%3Adate_time%29%29%2Cquery%3A%28bool%3A%28filter%3A%21%28%28match_all%3A%28%29%29%2C%28range%3A%28order_date%3A%28format%3Astrict_date_optional_time%2Cgte%3A%272019-06-11T08%3A24%3A16.425Z%27%2Clte%3A%272019-07-13T09%3A31%3A07.520Z%27%29%29%29%29%2Cmust%3A%21%28%29%2Cmust_not%3A%21%28%29%2Cshould%3A%21%28%29%29%29%2Cscript_fields%3A%28%29%2Csort%3A%21%28%28order_date%3A%28order%3Adesc%2Cunmapped_type%3Aboolean%29%29%29%2Cstored_fields%3A%21%28order_date%2Ccategory%2Ccustomer_first_name%2Ccustomer_full_name%2Ctotal_quantity%2Ctotal_unique_products%2Ctaxless_total_price%2Ctaxful_total_price%2Ccurrency%29%2Cversion%3A%21t%29%2Cindex%3A%27ecommerce%2A%27%29%2Ctitle%3A%27Ecom%20Search%27%29` + ); + + // Retry the download URL until a "completed" response status is returned + const completed$ = getCompleted$(downloadPath); + const reportCompleted = await completed$.toPromise(); + expect(reportCompleted).to.match(/^"order_date",/); + }); + + it('should complete a job of PNG export of a dashboard in non-default space', async () => { + const downloadPath = await reportingAPI.postJob( + `/s/non_default_space/api/reporting/generate/png?jobParams=%28browserTimezone%3AUTC%2Clayout%3A%28dimensions%3A%28height%3A512%2Cwidth%3A2402%29%2Cid%3Apng%29%2CobjectType%3Adashboard%2CrelativeUrl%3A%27%2Fs%2Fnon_default_space%2Fapp%2Fdashboards%23%2Fview%2F3c9ee360-e7ee-11ea-a730-d58e9ea7581b%3F_g%3D%28filters%3A%21%21%28%29%2CrefreshInterval%3A%28pause%3A%21%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3A%21%272019-06-10T03%3A17%3A28.800Z%21%27%2Cto%3A%21%272019-07-14T19%3A25%3A06.385Z%21%27%29%29%26_a%3D%28description%3A%21%27%21%27%2Cfilters%3A%21%21%28%29%2CfullScreenMode%3A%21%21f%2Coptions%3A%28hidePanelTitles%3A%21%21f%2CuseMargins%3A%21%21t%29%2Cquery%3A%28language%3Akuery%2Cquery%3A%21%27%21%27%29%2CtimeRestore%3A%21%21t%2Ctitle%3A%21%27Ecom%2520Dashboard%2520Non%2520Default%2520Space%21%27%2CviewMode%3Aview%29%27%2Ctitle%3A%27Ecom%20Dashboard%20Non%20Default%20Space%27%29` + ); + + const completed$: Rx.Observable = getCompleted$(downloadPath); + const reportCompleted = await completed$.toPromise(); + expect(reportCompleted).to.not.be(null); + }); + + it('should complete a job of PDF export of a dashboard in non-default space', async () => { + const downloadPath = await reportingAPI.postJob( + `/s/non_default_space/api/reporting/generate/printablePdf?jobParams=%28browserTimezone%3AUTC%2Clayout%3A%28dimensions%3A%28height%3A512%2Cwidth%3A2402%29%2Cid%3Apreserve_layout%29%2CobjectType%3Adashboard%2CrelativeUrls%3A%21%28%27%2Fs%2Fnon_default_space%2Fapp%2Fdashboards%23%2Fview%2F3c9ee360-e7ee-11ea-a730-d58e9ea7581b%3F_g%3D%28filters%3A%21%21%28%29%2CrefreshInterval%3A%28pause%3A%21%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3A%21%272019-06-10T03%3A17%3A28.800Z%21%27%2Cto%3A%21%272019-07-14T19%3A25%3A06.385Z%21%27%29%29%26_a%3D%28description%3A%21%27%21%27%2Cfilters%3A%21%21%28%29%2CfullScreenMode%3A%21%21f%2Coptions%3A%28hidePanelTitles%3A%21%21f%2CuseMargins%3A%21%21t%29%2Cquery%3A%28language%3Akuery%2Cquery%3A%21%27%21%27%29%2CtimeRestore%3A%21%21t%2Ctitle%3A%21%27Ecom%2520Dashboard%2520Non%2520Default%2520Space%21%27%2CviewMode%3Aview%29%27%29%2Ctitle%3A%27Ecom%20Dashboard%20Non%20Default%20Space%27%29` + ); + + const completed$ = getCompleted$(downloadPath); + const reportCompleted = await completed$.toPromise(); + expect(reportCompleted).to.not.be(null); + }); + }); +} diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/usage.ts b/x-pack/test/reporting_api_integration/reporting_and_security/usage.ts index 24e68b3917d6c..feda5c1386e98 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/usage.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/usage.ts @@ -21,7 +21,7 @@ export default function ({ getService }: FtrProviderContext) { const reportingAPI = getService('reportingAPI'); const usageAPI = getService('usageAPI'); - describe('reporting usage', () => { + describe('Usage', () => { before(async () => { await esArchiver.load(OSS_KIBANA_ARCHIVE_PATH); await esArchiver.load(OSS_DATA_ARCHIVE_PATH); From 5fc63b0264259ab625a445e15b573bf1c3607c54 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 2 Sep 2020 12:24:58 -0400 Subject: [PATCH 46/71] test fixes --- .../application/dashboard_app_controller.tsx | 5 ++- .../__snapshots__/search_bar.test.tsx.snap | 36 +++++++++++---- .../public/components/search_bar.test.tsx | 45 ++++--------------- .../public/components/search_bar.tsx | 1 - .../apps/dashboard/reporting/screenshots.ts | 2 + .../functional/apps/discover/reporting.ts | 1 + .../functional/apps/visualize/reporting.ts | 1 + 7 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index 24fedc19369a8..d8c7a427b7c96 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -684,7 +684,10 @@ export class DashboardAppController { const dashboardNavBar = document.getElementById('dashboardChrome'); const updateNavBar = () => { ReactDOM.render( - , + , dashboardNavBar ); }; diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 69b4d27d922d4..7591bec5fafda 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -34,6 +34,15 @@ Array [ exports[`SearchBar correctly filters and sorts results 2`] = ` Array [ + Object { + "append": undefined, + "className": "euiSelectableTemplateSitewide__listItem", + "key": "Canvas", + "label": "Canvas", + "prepend": undefined, + "title": "Canvasundefinedundefined", + "url": "/app/test/Canvas", + }, Object { "append": undefined, "className": "euiSelectableTemplateSitewide__listItem", @@ -46,16 +55,25 @@ Array [ Object { "append": undefined, "className": "euiSelectableTemplateSitewide__listItem", - "key": "My Dashboard", - "label": "My Dashboard", - "meta": Array [ - Object { - "text": "Test", - }, - ], + "key": "Graph", + "label": "Graph", "prepend": undefined, - "title": "My Dashboard • Test", - "url": "/app/test/My Dashboard", + "title": "Graphundefinedundefined", + "url": "/app/test/Graph", }, ] `; + +exports[`SearchBar supports keyboard shortcuts 1`] = ` + +`; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx index 6e7bccc1249bd..195db2df5d763 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -89,43 +89,16 @@ describe('SearchBar', () => { expect(findSpy).toHaveBeenCalledTimes(2); }); - // TODO unskip - it.skip('supports keyboard shortcuts', () => { - // cmd/ctrl+s focuses search bar, popover opens, results rendered - let component: ReactWrapper; + it('supports keyboard shortcuts', () => { + mountWithIntl(); - act(() => { - component = mountWithIntl( - - ); - }); + const searchEvent = new KeyboardEvent('keydown', { + key: '/', + ctrlKey: true, + metaKey: true, + } as any); + window.dispatchEvent(searchEvent); - act(() => { - const searchEvent = new KeyboardEvent('keydown', { - key: '/', - ctrlKey: true, - metaKey: true, - } as any); - window.dispatchEvent(searchEvent); - }); - - act(() => { - component.update(); - }); - - act(() => { - const searchEvent = new KeyboardEvent('keydown', { - key: 'a', - } as any); - window.dispatchEvent(searchEvent); - }); - - act(() => { - component.update(); - }); - - act(() => { - expect(component.find('input').getDOMNode().getAttribute('value')).toBe('a'); - }); + expect(document.activeElement).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index be25056ef0970..d17db8a17cf8a 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -154,7 +154,6 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { onSearch, 'data-test-subj': 'header-search', inputRef: setSearchRef, - isClearable: false, placeholder: i18n.translate('xpack.globalSearchBar.searchBar.placeholder', { defaultMessage: 'Search Elastic', }), diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts index cf70e5a7b8b6c..588e7e7378d46 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts @@ -50,6 +50,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('becomes available when saved', async () => { + await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.dashboard.saveDashboard('My PDF Dashboard'); await PageObjects.reporting.openPdfReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); @@ -84,6 +85,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('becomes available when saved', async () => { + await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.dashboard.saveDashboard('My PNG Dash'); await PageObjects.reporting.openPngReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); diff --git a/x-pack/test/functional/apps/discover/reporting.ts b/x-pack/test/functional/apps/discover/reporting.ts index 7181bf0c74271..ba5ebb5991d24 100644 --- a/x-pack/test/functional/apps/discover/reporting.ts +++ b/x-pack/test/functional/apps/discover/reporting.ts @@ -39,6 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('becomes available when saved', async () => { + await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.discover.saveSearch('my search - expectEnabledGenerateReportButton'); await PageObjects.reporting.openCsvReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); diff --git a/x-pack/test/functional/apps/visualize/reporting.ts b/x-pack/test/functional/apps/visualize/reporting.ts index d1cea5a4481b1..acea6a19ae3e8 100644 --- a/x-pack/test/functional/apps/visualize/reporting.ts +++ b/x-pack/test/functional/apps/visualize/reporting.ts @@ -47,6 +47,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('becomes available when saved', async () => { + await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.reporting.setTimepickerInDataRange(); await PageObjects.visEditor.clickBucket('X-axis'); await PageObjects.visEditor.selectAggregation('Date Histogram'); From 905adaabd9b7639f1224403523d34c10c8a2fc31 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 2 Sep 2020 16:11:45 -0400 Subject: [PATCH 47/71] test fixes v2 --- .../__snapshots__/search_bar.test.tsx.snap | 22 ++++++++----------- .../apps/dashboard/reporting/screenshots.ts | 6 ++--- .../functional/apps/discover/reporting.ts | 1 - .../functional/apps/visualize/reporting.ts | 1 - 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 7591bec5fafda..357c9b09b30ee 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -34,15 +34,6 @@ Array [ exports[`SearchBar correctly filters and sorts results 2`] = ` Array [ - Object { - "append": undefined, - "className": "euiSelectableTemplateSitewide__listItem", - "key": "Canvas", - "label": "Canvas", - "prepend": undefined, - "title": "Canvasundefinedundefined", - "url": "/app/test/Canvas", - }, Object { "append": undefined, "className": "euiSelectableTemplateSitewide__listItem", @@ -55,11 +46,16 @@ Array [ Object { "append": undefined, "className": "euiSelectableTemplateSitewide__listItem", - "key": "Graph", - "label": "Graph", + "key": "My Dashboard", + "label": "My Dashboard", + "meta": Array [ + Object { + "text": "Test", + }, + ], "prepend": undefined, - "title": "Graphundefinedundefined", - "url": "/app/test/Graph", + "title": "My Dashboard • Test", + "url": "/app/test/My Dashboard", }, ] `; diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts index 588e7e7378d46..b50904cd86274 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts @@ -23,6 +23,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const log = getService('log'); const config = getService('config'); const es = getService('es'); + const testSubjects = getService('testSubjects'); describe('Screenshots', () => { before('initialize tests', async () => { @@ -41,16 +42,16 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - describe('Print PDF button', () => { + describe('foo', () => { it('is not available if new', async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); await PageObjects.reporting.openPdfReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); + await (await testSubjects.find('kibanaChrome')).clickMouseButton(); // close popover }); it('becomes available when saved', async () => { - await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.dashboard.saveDashboard('My PDF Dashboard'); await PageObjects.reporting.openPdfReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); @@ -85,7 +86,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('becomes available when saved', async () => { - await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.dashboard.saveDashboard('My PNG Dash'); await PageObjects.reporting.openPngReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); diff --git a/x-pack/test/functional/apps/discover/reporting.ts b/x-pack/test/functional/apps/discover/reporting.ts index ba5ebb5991d24..7181bf0c74271 100644 --- a/x-pack/test/functional/apps/discover/reporting.ts +++ b/x-pack/test/functional/apps/discover/reporting.ts @@ -39,7 +39,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('becomes available when saved', async () => { - await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.discover.saveSearch('my search - expectEnabledGenerateReportButton'); await PageObjects.reporting.openCsvReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); diff --git a/x-pack/test/functional/apps/visualize/reporting.ts b/x-pack/test/functional/apps/visualize/reporting.ts index acea6a19ae3e8..d1cea5a4481b1 100644 --- a/x-pack/test/functional/apps/visualize/reporting.ts +++ b/x-pack/test/functional/apps/visualize/reporting.ts @@ -47,7 +47,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('becomes available when saved', async () => { - await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.reporting.setTimepickerInDataRange(); await PageObjects.visEditor.clickBucket('X-axis'); await PageObjects.visEditor.selectAggregation('Date Histogram'); From 1235272b49fecf507b3a4cb6407a30340bc623f9 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 2 Sep 2020 16:50:57 -0400 Subject: [PATCH 48/71] test rename --- x-pack/test/functional/apps/dashboard/reporting/screenshots.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts index b50904cd86274..62be250c1175f 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts @@ -42,7 +42,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - describe('foo', () => { + describe('Print PDF button', () => { it('is not available if new', async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); From fc76d58532346bf3f7206a48def8a0becb0dd222 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 2 Sep 2020 18:20:09 -0400 Subject: [PATCH 49/71] test fix v3 --- x-pack/test/functional/apps/dashboard/reporting/screenshots.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts index 62be250c1175f..912bce22b1b21 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts @@ -83,6 +83,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.dashboard.clickNewDashboard(); await PageObjects.reporting.openPngReportingPanel(); expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); + await (await testSubjects.find('kibanaChrome')).clickMouseButton(); // close popover }); it('becomes available when saved', async () => { From 4e9ce622485ac61898f2d7e056700728a012d178 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Thu, 3 Sep 2020 10:17:50 +0200 Subject: [PATCH 50/71] wire setHeaderActionMenu to lens app TopNavMenu --- x-pack/plugins/lens/public/app_plugin/app.test.tsx | 3 +++ x-pack/plugins/lens/public/app_plugin/app.tsx | 3 +++ x-pack/plugins/lens/public/app_plugin/mounter.tsx | 1 + 3 files changed, 7 insertions(+) diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 2b979f064b8eb..fd809c3b7e3b6 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -135,6 +135,7 @@ describe('Lens App', () => { redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; originatingApp: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; history: History; getAppNameFromId?: (appId: string) => string | undefined; }> { @@ -175,6 +176,7 @@ describe('Lens App', () => { }, redirectTo: jest.fn((id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => {}), onAppLeave: jest.fn(), + setHeaderActionMenu: jest.fn(), history: createMemoryHistory(), } as unknown) as jest.Mocked<{ navigation: typeof navigationStartMock; @@ -187,6 +189,7 @@ describe('Lens App', () => { redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; originatingApp: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; history: History; getAppNameFromId?: (appId: string) => string | undefined; }>; diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index 021ca8b182b2b..56a86d20ebe0f 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -71,6 +71,7 @@ export function App({ originatingApp, navigation, onAppLeave, + setHeaderActionMenu, history, getAppNameFromId, }: { @@ -84,6 +85,7 @@ export function App({ redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; originatingApp?: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; history: History; getAppNameFromId?: (appId: string) => string | undefined; }) { @@ -416,6 +418,7 @@ export function App({
    ); From f48d2bff46a4ae2a21db8e27c1c5ae6ad19e3d1d Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Thu, 3 Sep 2020 10:37:23 +0200 Subject: [PATCH 51/71] wire setHeaderActionMenu to maps app TopNavMenu --- .../maps/public/routing/maps_router.js | 19 ++++++++++++++++--- .../routes/maps_app/load_map_and_render.js | 1 + .../routing/routes/maps_app/maps_app_view.js | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/maps/public/routing/maps_router.js b/x-pack/plugins/maps/public/routing/maps_router.js index f0f5234e3f989..9572e7c243e42 100644 --- a/x-pack/plugins/maps/public/routing/maps_router.js +++ b/x-pack/plugins/maps/public/routing/maps_router.js @@ -27,7 +27,10 @@ import { LoadMapAndRender } from './routes/maps_app/load_map_and_render'; export let goToSpecifiedPath; export let kbnUrlStateStorage; -export async function renderApp(context, { appBasePath, element, history, onAppLeave }) { +export async function renderApp( + context, + { appBasePath, element, history, onAppLeave, setHeaderActionMenu } +) { goToSpecifiedPath = (path) => history.push(path); kbnUrlStateStorage = createKbnUrlStateStorage({ useHash: false, @@ -35,14 +38,22 @@ export async function renderApp(context, { appBasePath, element, history, onAppL ...withNotifyOnErrors(getToasts()), }); - render(, element); + render( + , + element + ); return () => { unmountComponentAtNode(element); }; } -const App = ({ history, appBasePath, onAppLeave }) => { +const App = ({ history, appBasePath, onAppLeave, setHeaderActionMenu }) => { const store = getStore(); const I18nContext = getCoreI18n().Context; @@ -74,6 +85,7 @@ const App = ({ history, appBasePath, onAppLeave }) => { @@ -85,6 +97,7 @@ const App = ({ history, appBasePath, onAppLeave }) => { render={() => ( diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js index eebbb17582821..f3278e9016a20 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js @@ -60,6 +60,7 @@ export const LoadMapAndRender = class extends React.Component { diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js index 485b0ed7682fa..73cbb2ef70208 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js @@ -311,6 +311,7 @@ export class MapsAppView extends React.Component { const { TopNavMenu } = getNavigation().ui; return ( Date: Thu, 3 Sep 2020 11:30:40 +0200 Subject: [PATCH 52/71] wire setHeaderActionMenu to visualize app TopNavMenu --- .../public/application/components/visualize_top_nav.tsx | 3 +++ src/plugins/visualize/public/application/types.ts | 2 ++ src/plugins/visualize/public/plugin.ts | 2 ++ 3 files changed, 7 insertions(+) diff --git a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx index 130561b6245ae..dfd3c09f51ed5 100644 --- a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx +++ b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx @@ -61,6 +61,7 @@ const TopNav = ({ }: VisualizeTopNavProps) => { const { services } = useKibana(); const { TopNavMenu } = services.navigation.ui; + const { setHeaderActionMenu } = services; const { embeddableHandler, vis } = visInstance; const [inspectorSession, setInspectorSession] = useState(); const openInspector = useCallback(() => { @@ -151,6 +152,7 @@ const TopNav = ({ void; scopedHistory: ScopedHistory; dashboard: DashboardStart; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; } export interface SavedVisInstance { diff --git a/src/plugins/visualize/public/plugin.ts b/src/plugins/visualize/public/plugin.ts index 91307033a1f14..30339d49a0743 100644 --- a/src/plugins/visualize/public/plugin.ts +++ b/src/plugins/visualize/public/plugin.ts @@ -196,12 +196,14 @@ export class VisualizePlugin scopedHistory: params.history, restorePreviousUrl, dashboard: pluginsStart.dashboard, + setHeaderActionMenu: params.setHeaderActionMenu, }; params.element.classList.add('visAppWrapper'); const { renderApp } = await import('./application'); const unmount = renderApp(params, services); return () => { + params.element.classList.remove('visAppWrapper'); unlistenParentHistory(); unmount(); appUnMounted(); From 2ecd22641cb39e1beaf1490dbf2a70827764617c Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Thu, 3 Sep 2020 17:39:12 +0200 Subject: [PATCH 53/71] adapt kbn-top-nav ng component and wire setHeaderActionMenu to discover app TopNavMenu --- .../discover/public/application/angular/discover.html | 1 + src/plugins/discover/public/application/angular/discover.js | 2 ++ src/plugins/discover/public/kibana_services.ts | 6 +++++- src/plugins/discover/public/plugin.ts | 3 +++ src/plugins/kibana_legacy/public/angular/kbn_top_nav.js | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/plugins/discover/public/application/angular/discover.html b/src/plugins/discover/public/application/angular/discover.html index 94f13e1cd8132..e0e452aaa41c5 100644 --- a/src/plugins/discover/public/application/angular/discover.html +++ b/src/plugins/discover/public/application/angular/discover.html @@ -5,6 +5,7 @@

    {{screenTitle}}

    (uiActions = pluginUiActions); export const getUiActions = () => uiActions; +export const [getHeaderActionMenuMounter, setHeaderActionMenuMounter] = createGetterSetter< + AppMountParameters['setHeaderActionMenu'] +>('headerActionMenuMounter'); + export const [getUrlTracker, setUrlTracker] = createGetterSetter<{ setTrackedUrl: (url: string) => void; restorePreviousUrl: () => void; diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts index 46baa05184646..350672481e3b6 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.ts @@ -53,6 +53,7 @@ import { setUrlTracker, setAngularModule, setServices, + setHeaderActionMenuMounter, setUiActions, setScopedHistory, getScopedHistory, @@ -248,6 +249,7 @@ export class DiscoverPlugin throw Error('Discover plugin method initializeInnerAngular is undefined'); } setScopedHistory(params.history); + setHeaderActionMenuMounter(params.setHeaderActionMenu); syncHistoryLocations(); appMounted(); const { @@ -261,6 +263,7 @@ export class DiscoverPlugin params.element.classList.add('dscAppWrapper'); const unmount = await renderApp(innerAngularName, params.element); return () => { + params.element.classList.remove('dscAppWrapper'); unmount(); appUnMounted(); }; diff --git a/src/plugins/kibana_legacy/public/angular/kbn_top_nav.js b/src/plugins/kibana_legacy/public/angular/kbn_top_nav.js index b3fbe8baadec3..c34e2487b32d4 100644 --- a/src/plugins/kibana_legacy/public/angular/kbn_top_nav.js +++ b/src/plugins/kibana_legacy/public/angular/kbn_top_nav.js @@ -74,6 +74,7 @@ export function createTopNavDirective() { export const createTopNavHelper = ({ TopNavMenu }) => (reactDirective) => { return reactDirective(TopNavMenu, [ ['config', { watchDepth: 'value' }], + ['setMenuMountPoint', { watchDepth: 'reference' }], ['disabledButtons', { watchDepth: 'reference' }], ['query', { watchDepth: 'reference' }], From 1fab8ca47f5a21bcd0d513b73e3a0f9852ad9f0d Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 3 Sep 2020 12:17:52 -0400 Subject: [PATCH 54/71] search box styles update --- .../public/components/__snapshots__/search_bar.test.tsx.snap | 2 +- .../plugins/global_search_bar/public/components/search_bar.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index 357c9b09b30ee..f7e4bfd1c961c 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -66,7 +66,7 @@ exports[`SearchBar supports keyboard shortcuts 1`] = ` aria-haspopup="listbox" aria-label="Filter options" autocomplete="off" - class="euiFieldSearch euiFieldSearch--fullWidth euiSelectableSearch euiSelectableTemplateSitewide__search" + class="euiFieldSearch euiFieldSearch--fullWidth euiFieldSearch--compressed euiSelectableSearch euiSelectableTemplateSitewide__search" data-test-subj="header-search" placeholder="Search Elastic" type="search" diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index d17db8a17cf8a..50e013330618f 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -154,6 +154,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { onSearch, 'data-test-subj': 'header-search', inputRef: setSearchRef, + compressed: true, placeholder: i18n.translate('xpack.globalSearchBar.searchBar.placeholder', { defaultMessage: 'Search Elastic', }), From e8e2fed9715f47567176e6a7f832ca26f481ddda Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 3 Sep 2020 23:33:11 -0400 Subject: [PATCH 55/71] add debounce --- .../public/components/search_bar.test.tsx | 39 +++++------ .../public/components/search_bar.tsx | 70 ++++++++----------- 2 files changed, 46 insertions(+), 63 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx index 195db2df5d763..0d1e8725b4911 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReactWrapper } from 'enzyme'; import React from 'react'; -import { act } from 'react-dom/test-utils'; +import { wait } from '@testing-library/react'; import { of } from 'rxjs'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { @@ -50,11 +49,11 @@ describe('SearchBar', () => { beforeEach(() => { searchService = globalSearchPluginMock.createStartContract(); findSpy = jest.spyOn(searchService, 'find'); + jest.useFakeTimers(); }); it('correctly filters and sorts results', async () => { const navigate = jest.fn(); - let component: ReactWrapper; findSpy .mockReturnValueOnce( of( @@ -64,29 +63,23 @@ describe('SearchBar', () => { ) .mockReturnValueOnce(of(createBatch('Discover', { id: 'My Dashboard', type: 'test' }))); - act(() => { - component = mountWithIntl( - - ); - }); + const component = mountWithIntl( + + ); + + expect(findSpy).toHaveBeenCalledTimes(0); + component.find('input[data-test-subj="header-search"]').simulate('focus'); + jest.runAllTimers(); + component.update(); expect(findSpy).toHaveBeenCalledTimes(1); expect(findSpy).toHaveBeenCalledWith('', {}); - act(() => { - component.update(); - expect(getSelectableProps(component).options).toMatchSnapshot(); // default list - component.find('input[data-test-subj="header-search"]').simulate('focus'); - }); - expect(findSpy).toHaveBeenCalledTimes(1); - - act(() => { - component.update(); - getSearchProps(component).onSearch('d'); - }); - act(() => { - component.update(); - expect(getSelectableProps(component).options).toMatchSnapshot(); // list filtered - }); + expect(getSelectableProps(component).options).toMatchSnapshot(); + await wait(() => getSearchProps(component).onSearch('d')); + jest.runAllTimers(); + component.update(); + expect(getSelectableProps(component).options).toMatchSnapshot(); expect(findSpy).toHaveBeenCalledTimes(2); + expect(findSpy).toHaveBeenCalledWith('d', {}); }); it('supports keyboard shortcuts', () => { diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 50e013330618f..a7c882f702cf6 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -16,6 +16,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { ApplicationStart } from 'kibana/public'; import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { useDebounce, useEvent } from 'react-use'; import { GlobalSearchPluginStart, GlobalSearchResult } from '../../../global_search/public'; const useIfMounted = () => { @@ -46,33 +47,35 @@ const blurEvent = new FocusEvent('blur'); export function SearchBar({ globalSearch, navigateToUrl }: Props) { const ifMounted = useIfMounted(); - const [searchValue, setSearchValue] = useState(null); + const [searchValue, setSearchValue] = useState(''); const [searchRef, setSearchRef] = useState(null); const [options, _setOptions] = useState([] as EuiSelectableTemplateSitewideOption[]); const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; - const onSearch = useCallback( - (currentValue: string) => { - if (currentValue === searchValue) return; - const setOptions = (_options: GlobalSearchResult[]) => { - ifMounted(() => - _setOptions([ - ..._options.map((option) => ({ - key: option.id, - label: option.title, - url: option.url, - ...(option.icon && { icon: { type: option.icon } }), - ...(option.type && - option.type !== 'application' && { meta: [{ text: cleanMeta(option.type) }] }), - })), - ]) - ); - }; + const setOptions = useCallback( + (_options: GlobalSearchResult[]) => { + ifMounted(() => + _setOptions([ + ..._options.map((option) => ({ + key: option.id, + label: option.title, + url: option.url, + ...(option.icon && { icon: { type: option.icon } }), + ...(option.type && + option.type !== 'application' && { meta: [{ text: cleanMeta(option.type) }] }), + })), + ]) + ); + }, + [ifMounted, _setOptions] + ); + useDebounce( + () => { let arr: GlobalSearchResult[] = []; - globalSearch(currentValue, {}).subscribe({ + globalSearch(searchValue, {}).subscribe({ next: ({ results }) => { - if (currentValue.length > 0) { + if (searchValue.length > 0) { arr = [...results, ...arr].sort((a, b) => { if (a.score < b.score) return 1; if (a.score > b.score) return -1; @@ -100,15 +103,14 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { // Not doing anything on error right now because it'll either just show the previous // results or empty results which is basically what we want anyways }, - complete: () => { - ifMounted(() => setSearchValue(currentValue)); - }, + complete: () => {}, }); }, - [globalSearch, searchValue, ifMounted] + 250, + [searchValue] ); - const onWindowKeyDown = (event: KeyboardEvent) => { + const onKeyDown = (event: KeyboardEvent) => { if (event.key === '/' && (isWindows ? event.ctrlKey : event.metaKey)) { if (searchRef) { event.preventDefault(); @@ -125,7 +127,6 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { else { navigateToUrl(url); (document.activeElement as HTMLElement).blur(); - onSearch(''); if (searchRef) { searchRef.value = ''; searchRef.dispatchEvent(blurEvent); @@ -133,25 +134,14 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { } }; - useEffect(() => { - window.addEventListener('keydown', onWindowKeyDown); - - return () => { - window.removeEventListener('keydown', onWindowKeyDown); - }; - }); - - useEffect(() => { - onSearch(''); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useEvent('keydown', onKeyDown); return ( Quickly search using:, how: ( - {isWindows ? 'Ctrl + S' : 'Command + S'} + {isWindows ? 'Ctrl + /' : 'Command + /'} ), }} From dda98411ce0465a37c122940da9276eac5f04163 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Fri, 4 Sep 2020 08:01:33 +0200 Subject: [PATCH 56/71] adapt setHeaderActionMenu to graph app TopNavMenu --- x-pack/plugins/graph/public/angular/templates/index.html | 2 +- x-pack/plugins/graph/public/app.js | 2 ++ x-pack/plugins/graph/public/application.ts | 2 ++ x-pack/plugins/graph/public/components/_app.scss | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/graph/public/angular/templates/index.html b/x-pack/plugins/graph/public/angular/templates/index.html index 50385008d7b2b..10bbb2e8ec6c7 100644 --- a/x-pack/plugins/graph/public/angular/templates/index.html +++ b/x-pack/plugins/graph/public/angular/templates/index.html @@ -1,6 +1,6 @@
    - +
    diff --git a/x-pack/plugins/graph/public/app.js b/x-pack/plugins/graph/public/app.js index fd2b96e0570f6..183f8bddead11 100644 --- a/x-pack/plugins/graph/public/app.js +++ b/x-pack/plugins/graph/public/app.js @@ -53,6 +53,7 @@ export function initGraphApp(angularModule, deps) { graphSavePolicy, overlays, savedObjects, + setHeaderActionMenu, } = deps; const app = angularModule; @@ -465,6 +466,7 @@ export function initGraphApp(angularModule, deps) { }; // ===== Menubar configuration ========= + $scope.setHeaderActionMenu = setHeaderActionMenu; $scope.topNavMenu = []; $scope.topNavMenu.push({ key: 'new', diff --git a/x-pack/plugins/graph/public/application.ts b/x-pack/plugins/graph/public/application.ts index a9ba464016157..90e87ff4ec85e 100644 --- a/x-pack/plugins/graph/public/application.ts +++ b/x-pack/plugins/graph/public/application.ts @@ -27,6 +27,7 @@ import { SavedObjectsClientContract, ToastsStart, OverlayStart, + AppMountParameters, } from 'kibana/public'; // @ts-ignore import { initGraphApp } from './app'; @@ -73,6 +74,7 @@ export interface GraphDependencies { overlays: OverlayStart; savedObjects: SavedObjectsStart; kibanaLegacy: KibanaLegacyStart; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; } export const renderApp = ({ appBasePath, element, kibanaLegacy, ...deps }: GraphDependencies) => { diff --git a/x-pack/plugins/graph/public/components/_app.scss b/x-pack/plugins/graph/public/components/_app.scss index f6984f5369a30..b9b23e596a05e 100644 --- a/x-pack/plugins/graph/public/components/_app.scss +++ b/x-pack/plugins/graph/public/components/_app.scss @@ -1,3 +1,3 @@ .gphGraph__bar { - margin: 0px $euiSizeS $euiSizeS $euiSizeS; + margin: $euiSizeS; } From 3fe5a5c6d064c4f9360e92aa9a64851c9617ce35 Mon Sep 17 00:00:00 2001 From: Ryan Keairns Date: Fri, 4 Sep 2020 09:30:12 -0500 Subject: [PATCH 57/71] update logo for security administration --- x-pack/plugins/security_solution/public/plugin.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 670eb294edd6c..01f63f3bb2ddf 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -296,7 +296,7 @@ export class Plugin implements IPlugin { From fc5fb78bc5553018a54d4a129501937c6efdc4c0 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 4 Sep 2020 18:42:41 -0400 Subject: [PATCH 58/71] Addresses PR feedback --- .../public/components/search_bar.tsx | 31 +++++++++++++++++-- .../security_solution/public/plugin.tsx | 1 - 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index a7c882f702cf6..9f39d97f412f6 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -11,6 +11,7 @@ import { EuiSelectableTemplateSitewide, EuiSelectableTemplateSitewideOption, EuiText, + EuiSelectableMessage, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -42,6 +43,16 @@ interface Props { navigateToUrl: ApplicationStart['navigateToUrl']; } +const clearField = (field: HTMLInputElement) => { + const nativeInputValue = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); + const nativeInputValueSetter = nativeInputValue ? nativeInputValue.set : undefined; + if (nativeInputValueSetter) { + nativeInputValueSetter.call(field, ''); + } + + field.dispatchEvent(new Event('change')); +}; + const cleanMeta = (str: string) => (str.charAt(0).toUpperCase() + str.slice(1)).replace(/-/g, ' '); const blurEvent = new FocusEvent('blur'); @@ -128,7 +139,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { navigateToUrl(url); (document.activeElement as HTMLElement).blur(); if (searchRef) { - searchRef.value = ''; + clearField(searchRef); searchRef.dispatchEvent(blurEvent); } } @@ -149,6 +160,22 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { defaultMessage: 'Search Elastic', }), }} + emptyMessage={ + +

    + +

    +

    + +

    +
    + } popoverFooter={ Quickly search using:, + what: Shortcut, how: ( {isWindows ? 'Ctrl + /' : 'Command + /'} diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 01f63f3bb2ddf..80c92ed1b7737 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -32,7 +32,6 @@ import { } from './types'; import { APP_ID, - APP_ICON, APP_ICON_SOLUTION, APP_DETECTIONS_PATH, APP_HOSTS_PATH, From 51f130f147df317b78d09c52fd202107fb3e742c Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 4 Sep 2020 18:48:00 -0400 Subject: [PATCH 59/71] fixes canvas fullscreen --- .../chrome/ui/header/__snapshots__/header.test.tsx.snap | 4 ++-- src/core/public/chrome/ui/header/header.tsx | 2 +- .../plugins/canvas/public/components/fullscreen/fullscreen.js | 2 ++ .../canvas/public/components/fullscreen/fullscreen.scss | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index 91b098a484cee..9f3f114cdeb3d 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -2295,7 +2295,7 @@ exports[`Header renders 2`] = `
    (); const navId = htmlIdGenerator()(); - const className = classnames('hide-for-sharing'); + const className = classnames('hide-for-sharing', 'headerGlobalNav'); return ( <> diff --git a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js index eb982d015a212..2f57f7eb77c87 100644 --- a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js +++ b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js @@ -30,10 +30,12 @@ export class Fullscreen extends React.Component { componentDidMount() { this.win.addEventListener('resize', this.onWindowResize); + document.querySelector('.app-wrapper').classList.add('hidden-chrome'); } componentWillUnmount() { this.win.removeEventListener('resize', this.onWindowResize); + document.querySelector('.app-wrapper').classList.remove('hidden-chrome'); } getWindowSize = () => ({ diff --git a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss index edd681a2c33e8..3ea008752e387 100644 --- a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss +++ b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss @@ -24,6 +24,7 @@ body.canvas-isFullscreen { // sass-lint:disable-line no-qualifying-elements } // hide all the interface parts + .headerGlobalNav, .canvasLayout__stageHeader, .canvasLayout__sidebar, .canvasLayout__footer, From 2f0484897a8f9c4ddf384982610416d8e0149187 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 4 Sep 2020 23:53:07 -0400 Subject: [PATCH 60/71] i18n fix --- .../plugins/global_search_bar/public/components/search_bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 9f39d97f412f6..9e16097e9f39b 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -170,7 +170,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) {

    From c94d60e5d7591ff88602c006d3ac75d539254484 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 8 Sep 2020 18:02:04 -0400 Subject: [PATCH 61/71] Canvas fullscreen fix Co-authored-by: Poff Poffenberger --- .../plugins/canvas/public/components/fullscreen/fullscreen.js | 2 -- .../canvas/public/components/fullscreen/fullscreen.scss | 1 - x-pack/plugins/canvas/public/lib/fullscreen.js | 4 ++++ x-pack/plugins/canvas/public/services/platform.ts | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js index 2f57f7eb77c87..eb982d015a212 100644 --- a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js +++ b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js @@ -30,12 +30,10 @@ export class Fullscreen extends React.Component { componentDidMount() { this.win.addEventListener('resize', this.onWindowResize); - document.querySelector('.app-wrapper').classList.add('hidden-chrome'); } componentWillUnmount() { this.win.removeEventListener('resize', this.onWindowResize); - document.querySelector('.app-wrapper').classList.remove('hidden-chrome'); } getWindowSize = () => ({ diff --git a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss index 3ea008752e387..edd681a2c33e8 100644 --- a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss +++ b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss @@ -24,7 +24,6 @@ body.canvas-isFullscreen { // sass-lint:disable-line no-qualifying-elements } // hide all the interface parts - .headerGlobalNav, .canvasLayout__stageHeader, .canvasLayout__sidebar, .canvasLayout__footer, diff --git a/x-pack/plugins/canvas/public/lib/fullscreen.js b/x-pack/plugins/canvas/public/lib/fullscreen.js index bb9990d4f5457..6ad52d591c9c4 100644 --- a/x-pack/plugins/canvas/public/lib/fullscreen.js +++ b/x-pack/plugins/canvas/public/lib/fullscreen.js @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { platformService } from '../services'; + export const fullscreenClass = 'canvas-isFullscreen'; export function setFullscreen(fullscreen, doc = document) { @@ -13,8 +15,10 @@ export function setFullscreen(fullscreen, doc = document) { const isFullscreen = bodyClassList.contains(fullscreenClass); if (enabled && !isFullscreen) { + platformService.getService().setFullscreen(false); bodyClassList.add(fullscreenClass); } else if (!enabled && isFullscreen) { bodyClassList.remove(fullscreenClass); + platformService.getService().setFullscreen(true); } } diff --git a/x-pack/plugins/canvas/public/services/platform.ts b/x-pack/plugins/canvas/public/services/platform.ts index 92c378e9aa597..65e50bce454ad 100644 --- a/x-pack/plugins/canvas/public/services/platform.ts +++ b/x-pack/plugins/canvas/public/services/platform.ts @@ -45,6 +45,7 @@ export const platformServiceFactory: CanvasServiceFactory = ( getUISetting: coreStart.uiSettings.get.bind(coreStart.uiSettings), setBreadcrumbs: coreStart.chrome.setBreadcrumbs, setRecentlyAccessed: coreStart.chrome.recentlyAccessed.add, + setFullscreen: coreStart.chrome.setIsVisible, // TODO: these should go away. We want thin accessors, not entire objects. // Entire objects are hard to mock, and hide our dependency on the external service. From e6b46d07f8a61b5f76f5054e7ddcc14fa5edd9b9 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 9 Sep 2020 16:41:58 -0400 Subject: [PATCH 62/71] addressing PR feedback --- .../public/application/ui/app_container.tsx | 2 +- .../header/__snapshots__/header.test.tsx.snap | 5994 ----------------- .../public/chrome/ui/header/header.test.tsx | 6 +- src/core/public/chrome/ui/header/header.tsx | 2 +- .../canvas/public/services/platform.ts | 2 + .../canvas/public/services/stubs/platform.ts | 1 + .../public/components/search_bar.tsx | 52 +- 7 files changed, 27 insertions(+), 6032 deletions(-) diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index 8fedc423d8d63..089d1cf3f3ced 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -96,8 +96,8 @@ export const AppContainer: FunctionComponent = ({ } finally { if (elementRef.current) { setShowSpinner(false); + setIsMounting(false); } - setIsMounting(false); } }; diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index 9f3f114cdeb3d..505f242794212 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -1,6000 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Header renders 1`] = ` -
    - -
    -
    -
    - -
    -`; - -exports[`Header renders 2`] = ` -
    - -
    -
    -
    - -
    -
    - , - ], - }, - Object { - "borders": "none", - "items": Array [ - , - ], - }, - Object { - "borders": "none", - "items": Array [ - , - , - ], - }, - ] - } - theme="dark" - > -
    - -
    - - - - -
    - -
    - -
    -
    -
    -
    - -
    - -
    - - - - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} - > - -
    -
    - - - -
    -
    -
    -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - - -
    - -
    - -
    - - - -
    -
    - -
    - - -
    - - - - - - - - - - -
    - -
    - -
    - -
    - -
    - -
    - -
    - - - -
    -
    -`; - -exports[`Header renders 3`] = `
    { customNavLink$={customNavLink$} /> ); - expect(component).toMatchSnapshot(); + expect(component.find('EuiHeader').exists()).toBeFalsy(); act(() => isVisible$.next(true)); component.update(); - expect(component).toMatchSnapshot(); + expect(component.find('EuiHeader').exists()).toBeTruthy(); + expect(component.find('nav[aria-label="Primary"]').exists()).toBeFalsy(); act(() => isLocked$.next(true)); component.update(); + expect(component.find('nav[aria-label="Primary"]').exists()).toBeTruthy(); expect(component).toMatchSnapshot(); }); }); diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 5ce8614e2a50c..7ec03ea4c6da6 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -83,7 +83,7 @@ export function Header({ homeHref, ...observables }: HeaderProps) { - const isVisible = useObservable(observables.isVisible$, true); + const isVisible = useObservable(observables.isVisible$, false); const isLocked = useObservable(observables.isLocked$, false); const [isNavOpen, setIsNavOpen] = useState(false); diff --git a/x-pack/plugins/canvas/public/services/platform.ts b/x-pack/plugins/canvas/public/services/platform.ts index 65e50bce454ad..a27c57f32cf9f 100644 --- a/x-pack/plugins/canvas/public/services/platform.ts +++ b/x-pack/plugins/canvas/public/services/platform.ts @@ -10,6 +10,7 @@ import { IUiSettingsClient, ChromeBreadcrumb, IBasePath, + ChromeStart, } from '../../../../../src/core/public'; import { CanvasServiceFactory } from '.'; @@ -22,6 +23,7 @@ export interface PlatformService { getUISetting: (key: string, defaultValue?: any) => any; setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => void; setRecentlyAccessed: (link: string, label: string, id: string) => void; + setFullscreen: ChromeStart['setIsVisible']; // TODO: these should go away. We want thin accessors, not entire objects. // Entire objects are hard to mock, and hide our dependency on the external service. diff --git a/x-pack/plugins/canvas/public/services/stubs/platform.ts b/x-pack/plugins/canvas/public/services/stubs/platform.ts index 9ada579573502..bef3b2609537c 100644 --- a/x-pack/plugins/canvas/public/services/stubs/platform.ts +++ b/x-pack/plugins/canvas/public/services/stubs/platform.ts @@ -20,4 +20,5 @@ export const platformService: PlatformService = { getSavedObjects: noop, getSavedObjectsClient: noop, getUISettings: noop, + setFullscreen: noop, }; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 9e16097e9f39b..4cd266e9b82d0 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -17,27 +17,11 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { ApplicationStart } from 'kibana/public'; import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { useDebounce, useEvent } from 'react-use'; +import useDebounce from 'react-use/lib/useDebounce'; +import useEvent from 'react-use/lib/useEvent'; +import useMountedState from 'react-use/lib/useMountedState'; import { GlobalSearchPluginStart, GlobalSearchResult } from '../../../global_search/public'; -const useIfMounted = () => { - const isMounted = useRef(true); - useEffect( - () => () => { - isMounted.current = false; - }, - [] - ); - - const ifMounted = useCallback((func) => { - if (isMounted.current && func) { - func(); - } - }, []); - - return ifMounted; -}; - interface Props { globalSearch: GlobalSearchPluginStart['find']; navigateToUrl: ApplicationStart['navigateToUrl']; @@ -57,7 +41,7 @@ const cleanMeta = (str: string) => (str.charAt(0).toUpperCase() + str.slice(1)). const blurEvent = new FocusEvent('blur'); export function SearchBar({ globalSearch, navigateToUrl }: Props) { - const ifMounted = useIfMounted(); + const isMounted = useMountedState(); const [searchValue, setSearchValue] = useState(''); const [searchRef, setSearchRef] = useState(null); const [options, _setOptions] = useState([] as EuiSelectableTemplateSitewideOption[]); @@ -65,20 +49,20 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { const setOptions = useCallback( (_options: GlobalSearchResult[]) => { - ifMounted(() => - _setOptions([ - ..._options.map((option) => ({ - key: option.id, - label: option.title, - url: option.url, - ...(option.icon && { icon: { type: option.icon } }), - ...(option.type && - option.type !== 'application' && { meta: [{ text: cleanMeta(option.type) }] }), - })), - ]) - ); + if (!isMounted()) return; + + _setOptions([ + ..._options.map((option) => ({ + key: option.id, + label: option.title, + url: option.url, + ...(option.icon && { icon: { type: option.icon } }), + ...(option.type && + option.type !== 'application' && { meta: [{ text: cleanMeta(option.type) }] }), + })), + ]); }, - [ifMounted, _setOptions] + [isMounted, _setOptions] ); useDebounce( @@ -192,7 +176,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { what: Shortcut, how: ( - {isWindows ? 'Ctrl + /' : 'Command + /'} + {isWindows ? 'Control + /' : 'Command + /'} ), }} From dede90e24234bb0d51c8b576cbf12c38844d5f52 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 9 Sep 2020 17:42:19 -0400 Subject: [PATCH 63/71] maps topnavmenu fix after bad merge --- .../plugins/global_search_bar/public/components/search_bar.tsx | 2 +- .../maps/public/routing/routes/maps_app/load_map_and_render.tsx | 1 + .../maps/public/routing/routes/maps_app/maps_app_view.tsx | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 4cd266e9b82d0..b7f1b6c2a8c8f 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -16,7 +16,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { ApplicationStart } from 'kibana/public'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import useEvent from 'react-use/lib/useEvent'; import useMountedState from 'react-use/lib/useMountedState'; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx index 358099f5f866b..b980756daad20 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx @@ -19,6 +19,7 @@ interface Props { onAppLeave: AppMountParameters['onAppLeave']; stateTransfer: EmbeddableStateTransfer; originatingApp?: string; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; } interface State { diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx index 61af302d2d865..abc3462caf6b4 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx @@ -88,6 +88,7 @@ interface Props { setIsLayerTOCOpen: (isLayerTOCOpen: boolean) => void; setOpenTOCDetails: (openTOCDetails: string[]) => void; query: MapQuery | undefined; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; } interface State { From 5bd40cf127151d4c57369bd82b4a0fbfaa331685 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 10 Sep 2020 10:53:42 -0400 Subject: [PATCH 64/71] fix keyboard shortcut for linux --- .../global_search_bar/public/components/search_bar.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index b7f1b6c2a8c8f..50bd22bc9f41b 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -45,7 +45,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { const [searchValue, setSearchValue] = useState(''); const [searchRef, setSearchRef] = useState(null); const [options, _setOptions] = useState([] as EuiSelectableTemplateSitewideOption[]); - const isWindows = navigator.platform.toLowerCase().indexOf('win') >= 0; + const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0; const setOptions = useCallback( (_options: GlobalSearchResult[]) => { @@ -106,7 +106,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { ); const onKeyDown = (event: KeyboardEvent) => { - if (event.key === '/' && (isWindows ? event.ctrlKey : event.metaKey)) { + if (event.key === '/' && (isMac ? event.metaKey : event.ctrlKey)) { if (searchRef) { event.preventDefault(); searchRef.focus(); @@ -176,7 +176,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { what: Shortcut, how: ( - {isWindows ? 'Control + /' : 'Command + /'} + {isMac ? 'Command + /' : 'Control + /'} ), }} From d4fe0c3ed5511bc2c8b04b609f76816b887b7597 Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 10 Sep 2020 12:52:49 -0400 Subject: [PATCH 65/71] Use EuiHeaderLink(s) for TopNavMenu --- .../public/top_nav_menu/_index.scss | 17 +++----------- .../public/top_nav_menu/top_nav_menu.tsx | 23 ++++--------------- .../public/top_nav_menu/top_nav_menu_item.tsx | 10 ++++---- 3 files changed, 11 insertions(+), 39 deletions(-) diff --git a/src/plugins/navigation/public/top_nav_menu/_index.scss b/src/plugins/navigation/public/top_nav_menu/_index.scss index a6ddf7a8b4264..44a76b7700ee0 100644 --- a/src/plugins/navigation/public/top_nav_menu/_index.scss +++ b/src/plugins/navigation/public/top_nav_menu/_index.scss @@ -1,15 +1,4 @@ -.kbnTopNavMenu__wrapper { - z-index: 5; - - .kbnTopNavMenu { - padding: $euiSizeS 0; - - .kbnTopNavItemEmphasized { - padding: 0 $euiSizeS; - } - } - - .kbnTopNavMenu-isFullScreen { - padding: 0; - } +.kbnTopNavMenu > * > * { + // TEMP fix to adjust spacing between EuiHeaderList__list items + margin: 0 $euiSizeXS; } diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx index b284c60bac5de..a27addeb14393 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx @@ -18,7 +18,7 @@ */ import React, { ReactElement } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiHeaderLinks } from '@elastic/eui'; import classNames from 'classnames'; import { MountPoint } from '../../../../core/public'; @@ -81,31 +81,16 @@ export function TopNavMenu(props: TopNavMenuProps): ReactElement | null { function renderItems(): ReactElement[] | null { if (!config || config.length === 0) return null; return config.map((menuItem: TopNavMenuData, i: number) => { - return ( - - - - ); + return ; }); } function renderMenu(className: string): ReactElement | null { if (!config || config.length === 0) return null; return ( - + {renderItems()} - + ); } diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx index b058ef0de448b..96a205b737273 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx @@ -19,9 +19,7 @@ import { upperFirst, isFunction } from 'lodash'; import React, { MouseEvent } from 'react'; -import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; - -import { EuiButton } from '@elastic/eui'; +import { EuiToolTip, EuiButton, EuiHeaderLink } from '@elastic/eui'; import { TopNavMenuData } from './top_nav_menu_data'; export function TopNavMenuItem(props: TopNavMenuData) { @@ -50,13 +48,13 @@ export function TopNavMenuItem(props: TopNavMenuData) { }; const btn = props.emphasize ? ( - + {upperFirst(props.label || props.id!)} ) : ( - + {upperFirst(props.label || props.id!)} - + ); const tooltip = getTooltip(); From e367824d21c8a0f504b17a3249ae0759abbe27d8 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 10 Sep 2020 16:30:26 -0400 Subject: [PATCH 66/71] test fix for new top nav --- .../navigation/public/top_nav_menu/top_nav_menu.test.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx index f21e5680e8f61..212bc19208ca8 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx @@ -164,7 +164,10 @@ describe('TopNavMenu', () => { // menu is rendered outside of the component expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0); - expect(portalTarget.getElementsByTagName('BUTTON').length).toBe(menuItems.length); + + const buttons = portalTarget.querySelectorAll('button'); + expect(buttons.length).toBe(menuItems.length + 1); // should be n+1 buttons in mobile for popover button + expect(buttons[buttons.length - 1].getAttribute('aria-label')).toBe('Open navigation menu'); // last button should be mobile button }); }); }); From 71a78f864321dcb83cdb95d7b26e49bc23cb72ba Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 10 Sep 2020 16:42:15 -0400 Subject: [PATCH 67/71] css cleanup --- src/core/public/_variables.scss | 3 +++ src/core/public/index.scss | 2 +- src/core/public/rendering/_base.scss | 12 +----------- src/plugins/timelion/public/_app.scss | 5 ----- x-pack/plugins/maps/public/_main.scss | 3 +-- 5 files changed, 6 insertions(+), 19 deletions(-) create mode 100644 src/core/public/_variables.scss diff --git a/src/core/public/_variables.scss b/src/core/public/_variables.scss new file mode 100644 index 0000000000000..46fdf68bc2073 --- /dev/null +++ b/src/core/public/_variables.scss @@ -0,0 +1,3 @@ +@import '@elastic/eui/src/global_styling/variables/header'; + +$headerOffset: $euiHeaderHeightCompensation * 2; diff --git a/src/core/public/index.scss b/src/core/public/index.scss index c2ad2841d5a77..6ba9254e5d381 100644 --- a/src/core/public/index.scss +++ b/src/core/public/index.scss @@ -1,6 +1,6 @@ +@import './variables'; @import './core'; @import './chrome/index'; @import './overlays/index'; @import './rendering/index'; @import './styles/index'; - diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index 89a003b6be313..f5a97b5fac09d 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -1,8 +1,4 @@ -@import '@elastic/eui/src/global_styling/variables/header'; -@import '@elastic/eui/src/components/nav_drawer/variables'; -@include euiHeaderAffordForFixed($euiHeaderHeightCompensation * 2); - -$headerOffset: $euiHeaderHeightCompensation * 2; +@include euiHeaderAffordForFixed($headerOffset); /** * stretch the root element of the Kibana application to set the base-size that @@ -21,12 +17,6 @@ $headerOffset: $euiHeaderHeightCompensation * 2; margin: 0 auto; min-height: calc(100vh - #{$headerOffset}); - @include internetExplorerOnly { - // IE specific bug with min-height in flex container, described in the next link - // https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items - height: calc(100vh - #{$headerOffset}); - } - &.hidden-chrome { min-height: 100vh; } diff --git a/src/plugins/timelion/public/_app.scss b/src/plugins/timelion/public/_app.scss index f7549970598c4..8b9078caba5a8 100644 --- a/src/plugins/timelion/public/_app.scss +++ b/src/plugins/timelion/public/_app.scss @@ -1,10 +1,5 @@ -@import '@elastic/eui/src/global_styling/variables/header'; - -$headerOffset: $euiHeaderHeightCompensation * 2; - .timApp { position: relative; - min-height: calc(100vh - #{$headerOffset}); background: $euiColorEmptyShade; [ng-click] { diff --git a/x-pack/plugins/maps/public/_main.scss b/x-pack/plugins/maps/public/_main.scss index 8ef92cfe8b87f..8c3b09213dead 100644 --- a/x-pack/plugins/maps/public/_main.scss +++ b/x-pack/plugins/maps/public/_main.scss @@ -1,5 +1,4 @@ -@import '@elastic/eui/src/global_styling/variables/header'; -$headerOffset: $euiHeaderHeightCompensation * 2; +@import '../../../../src/core/public/variables'; // sass-lint:disable no-ids #maps-plugin { From e882849aedd6795b22cc5c68ec8d2938acb35910 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Thu, 10 Sep 2020 17:02:26 -0400 Subject: [PATCH 68/71] css var change --- src/core/public/_variables.scss | 2 +- src/core/public/rendering/_base.scss | 4 ++-- x-pack/plugins/maps/public/_main.scss | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/public/_variables.scss b/src/core/public/_variables.scss index 46fdf68bc2073..8c054e770bd4b 100644 --- a/src/core/public/_variables.scss +++ b/src/core/public/_variables.scss @@ -1,3 +1,3 @@ @import '@elastic/eui/src/global_styling/variables/header'; -$headerOffset: $euiHeaderHeightCompensation * 2; +$kbnHeaderOffset: $euiHeaderHeightCompensation * 2; diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index f5a97b5fac09d..b806ac270331d 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -1,4 +1,4 @@ -@include euiHeaderAffordForFixed($headerOffset); +@include euiHeaderAffordForFixed($kbnHeaderOffset); /** * stretch the root element of the Kibana application to set the base-size that @@ -15,7 +15,7 @@ display: flex; flex-flow: column nowrap; margin: 0 auto; - min-height: calc(100vh - #{$headerOffset}); + min-height: calc(100vh - #{$kbnHeaderOffset}); &.hidden-chrome { min-height: 100vh; diff --git a/x-pack/plugins/maps/public/_main.scss b/x-pack/plugins/maps/public/_main.scss index 8c3b09213dead..5ce3bf4e2b998 100644 --- a/x-pack/plugins/maps/public/_main.scss +++ b/x-pack/plugins/maps/public/_main.scss @@ -4,7 +4,7 @@ #maps-plugin { display: flex; flex-direction: column; - height: calc(100vh - #{$headerOffset}); + height: calc(100vh - #{$kbnHeaderOffset}); width: 100%; overflow: hidden; } From e33f1f8d73190682e498843281c1d51fc0307643 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 14 Sep 2020 11:24:24 -0400 Subject: [PATCH 69/71] PR feedback --- .github/CODEOWNERS | 1 + x-pack/plugins/global_search/public/index.ts | 2 +- .../public/components/search_bar.tsx | 14 +++++--------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bcb4774475849..8b03b325ff559 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -85,6 +85,7 @@ # Exclude tutorial resources folder for now because they are not owned by Kibana app and most will move out soon /src/legacy/core_plugins/kibana/public/home/*.ts @elastic/kibana-core-ui /src/legacy/core_plugins/kibana/public/home/np_ready/ @elastic/kibana-core-ui +/x-pack/plugins/global_search_bar/ @elastic/kibana-core-ui # Observability UIs /x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui diff --git a/x-pack/plugins/global_search/public/index.ts b/x-pack/plugins/global_search/public/index.ts index 2092a121fbdd5..18483cea72540 100644 --- a/x-pack/plugins/global_search/public/index.ts +++ b/x-pack/plugins/global_search/public/index.ts @@ -31,4 +31,4 @@ export { GlobalSearchPluginStart, GlobalSearchResultProvider, } from './types'; -export { SearchServiceStart, GlobalSearchFindOptions } from './services'; +export { GlobalSearchFindOptions } from './services/types'; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 50bd22bc9f41b..b417321f3b76b 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -115,17 +115,13 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { }; const onChange = (selected: EuiSelectableTemplateSitewideOption[]) => { - // @ts-ignore - ts error is "union type is too complex to express" const { url } = selected.find(({ checked }) => checked === 'on'); - if (/^https?:\/\//.test(url)) window.location.assign(url); - else { - navigateToUrl(url); - (document.activeElement as HTMLElement).blur(); - if (searchRef) { - clearField(searchRef); - searchRef.dispatchEvent(blurEvent); - } + navigateToUrl(url); + (document.activeElement as HTMLElement).blur(); + if (searchRef) { + clearField(searchRef); + searchRef.dispatchEvent(blurEvent); } }; From ea4825b13a2da8df440b39da8068179908feccc3 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 14 Sep 2020 12:11:22 -0400 Subject: [PATCH 70/71] type fix --- .../plugins/global_search_bar/public/components/search_bar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index b417321f3b76b..748c301ef632d 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -115,6 +115,7 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { }; const onChange = (selected: EuiSelectableTemplateSitewideOption[]) => { + // @ts-ignore - ts error is "union type is too complex to express" const { url } = selected.find(({ checked }) => checked === 'on'); navigateToUrl(url); From 880a540bc7403f25cb734130e4b75ad41ea8ad62 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Mon, 14 Sep 2020 13:28:09 -0400 Subject: [PATCH 71/71] translation fix --- .../public/components/search_bar.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index 748c301ef632d..25ca1b07321c7 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -166,6 +166,37 @@ export function SearchBar({ globalSearch, navigateToUrl }: Props) { responsive={false} wrap > + + + + ), + commandDescription: ( + + + {isMac ? ( + + ) : ( + + )} + + + ), + }} + />