[Search Sessions] Fix search session indicator in Amsterdam theme (#90153)
This commit is contained in:
parent
87e83860ce
commit
c1ec73bea9
|
@ -4271,55 +4271,6 @@ exports[`Header renders 1`] = `
|
||||||
"thrownError": null,
|
"thrownError": null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
breadcrumbsAppendExtension$={
|
|
||||||
BehaviorSubject {
|
|
||||||
"_isScalar": false,
|
|
||||||
"_value": undefined,
|
|
||||||
"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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<EuiHeaderBreadcrumbs
|
<EuiHeaderBreadcrumbs
|
||||||
breadcrumbs={
|
breadcrumbs={
|
||||||
|
|
|
@ -28,3 +28,18 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header__breadcrumbsWithExtensionContainer {
|
||||||
|
overflow: hidden; // enables text-ellipsis in the last breadcrumb
|
||||||
|
.euiHeaderBreadcrumbs {
|
||||||
|
// stop breadcrumbs from growing.
|
||||||
|
// this makes the extension appear right next to the last breadcrumb
|
||||||
|
flex-grow: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
|
||||||
|
overflow: hidden; // enables text-ellipsis in the last breadcrumb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.header__breadcrumbsAppendExtension {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { StubBrowserStorage, mountWithIntl } from '@kbn/test/jest';
|
||||||
import { httpServiceMock } from '../../../http/http_service.mock';
|
import { httpServiceMock } from '../../../http/http_service.mock';
|
||||||
import { applicationServiceMock } from '../../../mocks';
|
import { applicationServiceMock } from '../../../mocks';
|
||||||
import { Header } from './header';
|
import { Header } from './header';
|
||||||
|
import { ChromeBreadcrumbsAppendExtension } from '../../chrome_service';
|
||||||
|
|
||||||
jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
|
jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
|
||||||
htmlIdGenerator: () => () => 'mockId',
|
htmlIdGenerator: () => () => 'mockId',
|
||||||
|
@ -71,6 +72,9 @@ describe('Header', () => {
|
||||||
const recentlyAccessed$ = new BehaviorSubject([
|
const recentlyAccessed$ = new BehaviorSubject([
|
||||||
{ link: '', label: 'dashboard', id: 'dashboard' },
|
{ link: '', label: 'dashboard', id: 'dashboard' },
|
||||||
]);
|
]);
|
||||||
|
const breadcrumbsAppendExtension$ = new BehaviorSubject<
|
||||||
|
undefined | ChromeBreadcrumbsAppendExtension
|
||||||
|
>(undefined);
|
||||||
const component = mountWithIntl(
|
const component = mountWithIntl(
|
||||||
<Header
|
<Header
|
||||||
{...mockProps()}
|
{...mockProps()}
|
||||||
|
@ -80,6 +84,7 @@ describe('Header', () => {
|
||||||
recentlyAccessed$={recentlyAccessed$}
|
recentlyAccessed$={recentlyAccessed$}
|
||||||
isLocked$={isLocked$}
|
isLocked$={isLocked$}
|
||||||
customNavLink$={customNavLink$}
|
customNavLink$={customNavLink$}
|
||||||
|
breadcrumbsAppendExtension$={breadcrumbsAppendExtension$}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
expect(component.find('EuiHeader').exists()).toBeFalsy();
|
expect(component.find('EuiHeader').exists()).toBeFalsy();
|
||||||
|
@ -93,5 +98,19 @@ describe('Header', () => {
|
||||||
component.update();
|
component.update();
|
||||||
expect(component.find('nav[aria-label="Primary"]').exists()).toBeTruthy();
|
expect(component.find('nav[aria-label="Primary"]').exists()).toBeTruthy();
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
|
|
||||||
|
act(() =>
|
||||||
|
breadcrumbsAppendExtension$.next({
|
||||||
|
content: (root: HTMLDivElement) => {
|
||||||
|
root.innerHTML = '<div class="my-extension">__render__</div>';
|
||||||
|
return () => (root.innerHTML = '');
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
component.update();
|
||||||
|
expect(component.find('HeaderExtension').exists()).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
component.find('HeaderExtension').getDOMNode().querySelector('.my-extension')
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
EuiFlexGroup,
|
||||||
EuiHeader,
|
EuiHeader,
|
||||||
EuiHeaderSection,
|
EuiHeaderSection,
|
||||||
EuiHeaderSectionItem,
|
EuiHeaderSectionItem,
|
||||||
|
@ -40,6 +41,7 @@ import { HeaderHelpMenu } from './header_help_menu';
|
||||||
import { HeaderLogo } from './header_logo';
|
import { HeaderLogo } from './header_logo';
|
||||||
import { HeaderNavControls } from './header_nav_controls';
|
import { HeaderNavControls } from './header_nav_controls';
|
||||||
import { HeaderActionMenu } from './header_action_menu';
|
import { HeaderActionMenu } from './header_action_menu';
|
||||||
|
import { HeaderExtension } from './header_extension';
|
||||||
|
|
||||||
export interface HeaderProps {
|
export interface HeaderProps {
|
||||||
kibanaVersion: string;
|
kibanaVersion: string;
|
||||||
|
@ -73,11 +75,13 @@ export function Header({
|
||||||
basePath,
|
basePath,
|
||||||
onIsLockedUpdate,
|
onIsLockedUpdate,
|
||||||
homeHref,
|
homeHref,
|
||||||
|
breadcrumbsAppendExtension$,
|
||||||
...observables
|
...observables
|
||||||
}: HeaderProps) {
|
}: HeaderProps) {
|
||||||
const isVisible = useObservable(observables.isVisible$, false);
|
const isVisible = useObservable(observables.isVisible$, false);
|
||||||
const isLocked = useObservable(observables.isLocked$, false);
|
const isLocked = useObservable(observables.isLocked$, false);
|
||||||
const [isNavOpen, setIsNavOpen] = useState(false);
|
const [isNavOpen, setIsNavOpen] = useState(false);
|
||||||
|
const breadcrumbsAppendExtension = useObservable(breadcrumbsAppendExtension$);
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
return <LoadingIndicator loadingCount$={observables.loadingCount$} showAsBar />;
|
return <LoadingIndicator loadingCount$={observables.loadingCount$} showAsBar />;
|
||||||
|
@ -87,6 +91,10 @@ export function Header({
|
||||||
const navId = htmlIdGenerator()();
|
const navId = htmlIdGenerator()();
|
||||||
const className = classnames('hide-for-sharing', 'headerGlobalNav');
|
const className = classnames('hide-for-sharing', 'headerGlobalNav');
|
||||||
|
|
||||||
|
const Breadcrumbs = (
|
||||||
|
<HeaderBreadcrumbs appTitle$={observables.appTitle$} breadcrumbs$={observables.breadcrumbs$} />
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header className={className} data-test-subj="headerGlobalNav">
|
<header className={className} data-test-subj="headerGlobalNav">
|
||||||
|
@ -157,11 +165,23 @@ export function Header({
|
||||||
<HeaderNavControls side="left" navControls$={observables.navControlsLeft$} />
|
<HeaderNavControls side="left" navControls$={observables.navControlsLeft$} />
|
||||||
</EuiHeaderSection>
|
</EuiHeaderSection>
|
||||||
|
|
||||||
<HeaderBreadcrumbs
|
{!breadcrumbsAppendExtension ? (
|
||||||
appTitle$={observables.appTitle$}
|
Breadcrumbs
|
||||||
breadcrumbs$={observables.breadcrumbs$}
|
) : (
|
||||||
breadcrumbsAppendExtension$={observables.breadcrumbsAppendExtension$}
|
<EuiFlexGroup
|
||||||
/>
|
responsive={false}
|
||||||
|
wrap={false}
|
||||||
|
alignItems={'center'}
|
||||||
|
className={'header__breadcrumbsWithExtensionContainer'}
|
||||||
|
gutterSize={'none'}
|
||||||
|
>
|
||||||
|
{Breadcrumbs}
|
||||||
|
<HeaderExtension
|
||||||
|
extension={breadcrumbsAppendExtension.content}
|
||||||
|
containerClassName={'header__breadcrumbsAppendExtension'}
|
||||||
|
/>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
)}
|
||||||
|
|
||||||
<HeaderBadge badge$={observables.badge$} />
|
<HeaderBadge badge$={observables.badge$} />
|
||||||
|
|
||||||
|
|
|
@ -11,17 +11,12 @@ import React from 'react';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { HeaderBreadcrumbs } from './header_breadcrumbs';
|
import { HeaderBreadcrumbs } from './header_breadcrumbs';
|
||||||
import { ChromeBreadcrumbsAppendExtension } from '../../chrome_service';
|
|
||||||
|
|
||||||
describe('HeaderBreadcrumbs', () => {
|
describe('HeaderBreadcrumbs', () => {
|
||||||
it('renders updates to the breadcrumbs$ observable', () => {
|
it('renders updates to the breadcrumbs$ observable', () => {
|
||||||
const breadcrumbs$ = new BehaviorSubject([{ text: 'First' }]);
|
const breadcrumbs$ = new BehaviorSubject([{ text: 'First' }]);
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<HeaderBreadcrumbs
|
<HeaderBreadcrumbs appTitle$={new BehaviorSubject('')} breadcrumbs$={breadcrumbs$} />
|
||||||
appTitle$={new BehaviorSubject('')}
|
|
||||||
breadcrumbs$={breadcrumbs$}
|
|
||||||
breadcrumbsAppendExtension$={new BehaviorSubject(undefined)}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
expect(wrapper.find('.euiBreadcrumb')).toMatchSnapshot();
|
expect(wrapper.find('.euiBreadcrumb')).toMatchSnapshot();
|
||||||
|
|
||||||
|
@ -33,29 +28,4 @@ describe('HeaderBreadcrumbs', () => {
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('.euiBreadcrumb')).toMatchSnapshot();
|
expect(wrapper.find('.euiBreadcrumb')).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders breadcrumbs extension', () => {
|
|
||||||
const breadcrumbs$ = new BehaviorSubject([{ text: 'First' }]);
|
|
||||||
const breadcrumbsAppendExtension$ = new BehaviorSubject<
|
|
||||||
undefined | ChromeBreadcrumbsAppendExtension
|
|
||||||
>({
|
|
||||||
content: (root: HTMLDivElement) => {
|
|
||||||
root.innerHTML = '<div class="my-extension">__render__</div>';
|
|
||||||
return () => (root.innerHTML = '');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<HeaderBreadcrumbs
|
|
||||||
appTitle$={new BehaviorSubject('')}
|
|
||||||
breadcrumbs$={breadcrumbs$}
|
|
||||||
breadcrumbsAppendExtension$={breadcrumbsAppendExtension$}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper.find('.euiBreadcrumb').getDOMNode().querySelector('my-extension')).toBeDefined();
|
|
||||||
act(() => breadcrumbsAppendExtension$.next(undefined));
|
|
||||||
wrapper.update();
|
|
||||||
expect(wrapper.find('.euiBreadcrumb').getDOMNode().querySelector('my-extension')).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,24 +6,21 @@
|
||||||
* Public License, v 1.
|
* Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EuiFlexGroup, EuiHeaderBreadcrumbs } from '@elastic/eui';
|
import { EuiHeaderBreadcrumbs } from '@elastic/eui';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import useObservable from 'react-use/lib/useObservable';
|
import useObservable from 'react-use/lib/useObservable';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ChromeBreadcrumb, ChromeBreadcrumbsAppendExtension } from '../../chrome_service';
|
import { ChromeBreadcrumb } from '../../chrome_service';
|
||||||
import { HeaderExtension } from './header_extension';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
appTitle$: Observable<string>;
|
appTitle$: Observable<string>;
|
||||||
breadcrumbs$: Observable<ChromeBreadcrumb[]>;
|
breadcrumbs$: Observable<ChromeBreadcrumb[]>;
|
||||||
breadcrumbsAppendExtension$: Observable<ChromeBreadcrumbsAppendExtension | undefined>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HeaderBreadcrumbs({ appTitle$, breadcrumbs$, breadcrumbsAppendExtension$ }: Props) {
|
export function HeaderBreadcrumbs({ appTitle$, breadcrumbs$ }: Props) {
|
||||||
const appTitle = useObservable(appTitle$, 'Kibana');
|
const appTitle = useObservable(appTitle$, 'Kibana');
|
||||||
const breadcrumbs = useObservable(breadcrumbs$, []);
|
const breadcrumbs = useObservable(breadcrumbs$, []);
|
||||||
const breadcrumbsAppendExtension = useObservable(breadcrumbsAppendExtension$);
|
|
||||||
let crumbs = breadcrumbs;
|
let crumbs = breadcrumbs;
|
||||||
|
|
||||||
if (breadcrumbs.length === 0 && appTitle) {
|
if (breadcrumbs.length === 0 && appTitle) {
|
||||||
|
@ -40,14 +37,5 @@ export function HeaderBreadcrumbs({ appTitle$, breadcrumbs$, breadcrumbsAppendEx
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (breadcrumbsAppendExtension && crumbs[crumbs.length - 1]) {
|
|
||||||
const lastCrumb = crumbs[crumbs.length - 1];
|
|
||||||
lastCrumb.text = (
|
|
||||||
<EuiFlexGroup responsive={false} gutterSize={'none'} alignItems={'baseline'}>
|
|
||||||
<div className="eui-textTruncate">{lastCrumb.text}</div>
|
|
||||||
<HeaderExtension extension={breadcrumbsAppendExtension.content} />
|
|
||||||
</EuiFlexGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <EuiHeaderBreadcrumbs breadcrumbs={crumbs} max={10} data-test-subj="breadcrumbs" />;
|
return <EuiHeaderBreadcrumbs breadcrumbs={crumbs} max={10} data-test-subj="breadcrumbs" />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { MountPoint } from '../../../types';
|
||||||
interface Props {
|
interface Props {
|
||||||
extension?: MountPoint<HTMLDivElement>;
|
extension?: MountPoint<HTMLDivElement>;
|
||||||
display?: 'block' | 'inlineBlock';
|
display?: 'block' | 'inlineBlock';
|
||||||
|
containerClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HeaderExtension extends React.Component<Props> {
|
export class HeaderExtension extends React.Component<Props> {
|
||||||
|
@ -39,6 +40,7 @@ export class HeaderExtension extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={this.ref}
|
ref={this.ref}
|
||||||
|
className={this.props.containerClassName}
|
||||||
style={{ display: this.props.display === 'inlineBlock' ? 'inline-block' : undefined }}
|
style={{ display: this.props.display === 'inlineBlock' ? 'inline-block' : undefined }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue