Skip to content

Commit

Permalink
[k7/Infra UI] Integrate with K7 Breadcrumbs (elastic#25938)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
weltenwort committed Dec 3, 2018
1 parent 138cbc3 commit 35e8c81
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 82 deletions.
9 changes: 9 additions & 0 deletions src/ui/public/chrome/api/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
31 changes: 16 additions & 15 deletions src/ui/public/chrome/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
53 changes: 0 additions & 53 deletions x-pack/plugins/infra/public/components/header.tsx

This file was deleted.

35 changes: 35 additions & 0 deletions x-pack/plugins/infra/public/components/header/external_header.tsx
Original file line number Diff line number Diff line change
@@ -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 || []);
};
}
44 changes: 44 additions & 0 deletions x-pack/plugins/infra/public/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -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>
);
});
7 changes: 7 additions & 0 deletions x-pack/plugins/infra/public/components/header/index.ts
Original file line number Diff line number Diff line change
@@ -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';
32 changes: 32 additions & 0 deletions x-pack/plugins/infra/public/components/header/legacy_header.tsx
Original file line number Diff line number Diff line change
@@ -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;
`;
84 changes: 70 additions & 14 deletions x-pack/plugins/infra/public/containers/with_kibana_chrome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

// replace with import from platform core when available
interface UiSettings {
k7Design: boolean;
}

// replace with import from platform core when available
type UiSettings$ = Observable<{
key: string;
oldValue: any;
newValue: any;
}>;

interface WithKibanaChromeProps {
children: RendererFunction<{
basePath: string;
}>;
children: RendererFunction<
{
setBreadcrumbs: (newBreadcrumbs: Breadcrumb[]) => void;
} & WithKibanaChromeState
>;
}

interface WithKibanaChromeState {
basePath: string;
uiSettings: UiSettings;
}

export const WithKibanaChrome: React.SFC<WithKibanaChromeProps> = ({ children }) =>
children({
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,
});
}
}

0 comments on commit 35e8c81

Please sign in to comment.