[k7/Infra UI] Integrate with K7 Breadcrumbs (#25938) (#26519)

This changes the header to be conditionally rendered based on the k7design UI setting. If the setting is false, the header is rendered as before. If it is true, the header is hidden and the breadcrumbs are set via the Kibana breadcrumbs api.
This commit is contained in:
Felix Stürmer 2018-12-03 21:59:33 +01:00 committed by GitHub
parent b5fc9dc244
commit 6bcf2417f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 214 additions and 83 deletions

View file

@ -22,6 +22,15 @@ import { uiModules } from 'ui/modules';
import { Breadcrumb, ChromeStartContract } from '../../../../core/public/chrome';
export { Breadcrumb };
export interface BreadcrumbsApi {
get$(): ReturnType<ChromeStartContract['getBreadcrumbs$']>;
set(newBreadcrumbs: Breadcrumb[]): void;
}
export interface WithBreadcrumbsApi {
breadcrumbs: BreadcrumbsApi;
}
let newPlatformChrome: ChromeStartContract;
export function __newPlatformInit__(instance: ChromeStartContract) {
if (newPlatformChrome) {

View file

@ -18,26 +18,27 @@
*/
import { Brand } from '../../../core/public/chrome';
import { WithBreadcrumbsApi } from './api/breadcrumbs';
interface IInjector {
get<T>(injectable: string): T;
}
declare class Chrome {
public addBasePath<T = string>(path: T): T;
public dangerouslyGetActiveInjector(): Promise<IInjector>;
public getBasePath(): string;
public getXsrfToken(): string;
public getKibanaVersion(): string;
public getUiSettingsClient(): any;
public setVisible(visible: boolean): any;
public getInjected(key: string, defaultValue?: any): any;
public setRootController(name: string, Controller: any): any;
public setBrand(brand: Brand): this;
public getBrand(key: keyof Brand): Brand[keyof Brand];
public addApplicationClass(classNames: string | string[]): this;
public removeApplicationClass(classNames: string | string[]): this;
public getApplicationClasses(): string;
declare interface Chrome extends WithBreadcrumbsApi {
addBasePath<T = string>(path: T): T;
dangerouslyGetActiveInjector(): Promise<IInjector>;
getBasePath(): string;
getXsrfToken(): string;
getKibanaVersion(): string;
getUiSettingsClient(): any;
setVisible(visible: boolean): any;
getInjected(key: string, defaultValue?: any): any;
setRootController(name: string, Controller: any): any;
setBrand(brand: Brand): this;
getBrand(key: keyof Brand): Brand[keyof Brand];
addApplicationClass(classNames: string | string[]): this;
removeApplicationClass(classNames: string | string[]): this;
getApplicationClasses(): string;
}
declare const chrome: Chrome;

View file

@ -1,53 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import {
EuiBreadcrumbDefinition,
EuiHeader,
EuiHeaderBreadcrumbs,
EuiHeaderSection,
} from '@elastic/eui';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import React from 'react';
import styled from 'styled-components';
interface HeaderProps {
breadcrumbs?: EuiBreadcrumbDefinition[];
appendSections?: React.ReactNode;
intl: InjectedIntl;
}
export const Header = injectI18n(
class extends React.PureComponent<HeaderProps> {
public static displayName = 'Header';
public render() {
const { breadcrumbs = [], appendSections = null, intl } = this.props;
const staticBreadcrumbs = [
{
href: '#/',
text: intl.formatMessage({
id: 'xpack.infra.header.infrastructureTitle',
defaultMessage: 'Infrastructure',
}),
},
];
return (
<HeaderWrapper>
<EuiHeaderSection>
<EuiHeaderBreadcrumbs breadcrumbs={[...staticBreadcrumbs, ...breadcrumbs]} />
</EuiHeaderSection>
{appendSections}
</HeaderWrapper>
);
}
}
);
const HeaderWrapper = styled(EuiHeader)`
height: 29px;
`;

View file

@ -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 isEqual from 'lodash/fp/isEqual';
import React from 'react';
import { Breadcrumb } from 'ui/chrome/api/breadcrumbs';
interface ExternalHeaderProps {
breadcrumbs?: Breadcrumb[];
setBreadcrumbs: (breadcrumbs: Breadcrumb[]) => void;
}
export class ExternalHeader extends React.Component<ExternalHeaderProps> {
public componentDidMount() {
this.setBreadcrumbs();
}
public componentDidUpdate(prevProps: ExternalHeaderProps) {
if (!isEqual(this.props.breadcrumbs, prevProps.breadcrumbs)) {
this.setBreadcrumbs();
}
}
public render() {
return null;
}
private setBreadcrumbs = () => {
this.props.setBreadcrumbs(this.props.breadcrumbs || []);
};
}

View file

@ -0,0 +1,44 @@
/*
* 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 { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import { Breadcrumb } from 'ui/chrome/api/breadcrumbs';
import { WithKibanaChrome } from '../../containers/with_kibana_chrome';
import { ExternalHeader } from './external_header';
import { LegacyHeader } from './legacy_header';
interface HeaderProps {
breadcrumbs?: Breadcrumb[];
appendSections?: React.ReactNode;
intl: InjectedIntl;
}
export const Header = injectI18n(({ appendSections, breadcrumbs = [], intl }: HeaderProps) => {
const prefixedBreadcrumbs = [
{
href: '#/',
text: intl.formatMessage({
id: 'xpack.infra.header.infrastructureTitle',
defaultMessage: 'Infrastructure',
}),
},
...(breadcrumbs || []),
];
return (
<WithKibanaChrome>
{({ setBreadcrumbs, uiSettings: { k7Design } }) =>
k7Design ? (
<ExternalHeader breadcrumbs={prefixedBreadcrumbs} setBreadcrumbs={setBreadcrumbs} />
) : (
<LegacyHeader appendSections={appendSections} breadcrumbs={prefixedBreadcrumbs} />
)
}
</WithKibanaChrome>
);
});

View file

@ -0,0 +1,7 @@
/*
* 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.
*/
export { Header } from './header';

View file

@ -0,0 +1,32 @@
/*
* 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 { EuiHeader, EuiHeaderBreadcrumbs, EuiHeaderSection } from '@elastic/eui';
import React from 'react';
import styled from 'styled-components';
import { Breadcrumb } from 'ui/chrome/api/breadcrumbs';
interface LegacyHeaderProps {
breadcrumbs?: Breadcrumb[];
appendSections?: React.ReactNode;
}
export const LegacyHeader: React.SFC<LegacyHeaderProps> = ({
appendSections,
breadcrumbs = [],
}) => (
<HeaderWrapper>
<EuiHeaderSection>
<EuiHeaderBreadcrumbs breadcrumbs={breadcrumbs} />
</EuiHeaderSection>
{appendSections}
</HeaderWrapper>
);
const HeaderWrapper = styled(EuiHeader)`
height: 29px;
`;

View file

@ -4,25 +4,81 @@
* you may not use this file except in compliance with the Elastic License.
*/
/*
*
* 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 chrome from 'ui/chrome';
import { Observable, Subscription } from 'rxjs';
import chrome from 'ui/chrome';
import { Breadcrumb } from 'ui/chrome/api/breadcrumbs';
import { RendererFunction } from '../utils/typed_react';
interface WithKibanaChromeProps {
children: RendererFunction<{
basePath: string;
}>;
// replace with import from platform core when available
interface UiSettings {
k7Design: boolean;
}
export const WithKibanaChrome: React.SFC<WithKibanaChromeProps> = ({ children }) =>
children({
// replace with import from platform core when available
type UiSettings$ = Observable<{
key: string;
oldValue: any;
newValue: any;
}>;
interface WithKibanaChromeProps {
children: RendererFunction<
{
setBreadcrumbs: (newBreadcrumbs: Breadcrumb[]) => void;
} & WithKibanaChromeState
>;
}
interface WithKibanaChromeState {
basePath: string;
uiSettings: UiSettings;
}
const uiSettingsKeys = ['k7Design'];
export class WithKibanaChrome extends React.Component<
WithKibanaChromeProps,
WithKibanaChromeState
> {
public state: WithKibanaChromeState = {
uiSettings: {
k7Design: chrome.getUiSettingsClient().get('k7design'),
},
basePath: chrome.getBasePath(),
});
};
private uiSettingsSubscription?: Subscription;
public componentDidMount() {
this.uiSettingsSubscription = (chrome
.getUiSettingsClient()
.getUpdate$() as UiSettings$).subscribe({
next: ({ key, newValue }) => {
if (uiSettingsKeys.includes(key)) {
this.setState(state => ({
...state,
uiSettings: {
...state.uiSettings,
[key]: newValue,
},
}));
}
},
});
}
public componentWillUnmount() {
if (this.uiSettingsSubscription) {
this.uiSettingsSubscription.unsubscribe();
}
}
public render() {
return this.props.children({
...this.state,
setBreadcrumbs: chrome.breadcrumbs.set,
});
}
}