Skip to content

Commit

Permalink
Implement Kibana Chrome breadcrumbs
Browse files Browse the repository at this point in the history
- create shared helper (WS will presumably also want this) for generating EUI breadcrumb objects with React Router links+click behavior
- create React component that calls chrome.setBreadcrumbs on page mount
- clean up type definitions - move app-wide props to IAppSearchProps and update most pages/views to simply import it instead of calling their own definitions
  • Loading branch information
cee-chen committed Jul 8, 2020
1 parent cbae563 commit 0e7fd50
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@
import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent, EuiEmptyPrompt, EuiButton } from '@elastic/eui';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { IAppSearchProps } from '../../index';

import { EngineOverviewHeader } from '../engine_overview_header';
import { IEmptyStatesProps } from './types';

import './empty_states.scss';

export const EmptyState: React.FC<IEmptyStatesProps> = ({ appSearchUrl }) => {
export const EmptyState: React.FC<IAppSearchProps> = ({ appSearchUrl, setBreadcrumbs }) => {
return (
<EuiPage restrictWidth className="empty-state">
<SetBreadcrumbs setBreadcrumbs={setBreadcrumbs} isRoot />

<EuiPageBody>
<EngineOverviewHeader appSearchUrl={appSearchUrl} />
<EuiPageContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@

import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent, EuiEmptyPrompt, EuiCode } from '@elastic/eui';

import { EuiButton } from '../../../shared/react_router_helpers';
import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { IAppSearchProps } from '../../index';

import { EngineOverviewHeader } from '../engine_overview_header';
import { IEmptyStatesProps } from './types';

import './empty_states.scss';

export const ErrorState: ReactFC<IEmptyStatesProps> = ({ appSearchUrl }) => {
export const ErrorState: ReactFC<IAppSearchProps> = ({ appSearchUrl, setBreadcrumbs }) => {
return (
<EuiPage restrictWidth className="empty-state">
<SetBreadcrumbs setBreadcrumbs={setBreadcrumbs} isRoot />

<EuiPageBody>
<EngineOverviewHeader />
<EuiPageContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@
import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLoadingContent } from '@elastic/eui';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { IAppSearchProps } from '../../index';

import { EngineOverviewHeader } from '../engine_overview_header';
import { IEmptyStatesProps } from './types';

import './empty_states.scss';

export const LoadingState: React.FC<IEmptyStatesProps> = ({ appSearchUrl }) => {
export const LoadingState: React.FC<IAppSearchProps> = ({ appSearchUrl, setBreadcrumbs }) => {
return (
<EuiPage restrictWidth className="engine-overview empty-state">
<SetBreadcrumbs setBreadcrumbs={setBreadcrumbs} isRoot />

<EuiPageBody>
<EngineOverviewHeader appSearchUrl={appSearchUrl} />
<EuiPageContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@
import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent, EuiEmptyPrompt, EuiCode } from '@elastic/eui';

import { IEmptyStatesProps } from './types';
import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { IAppSearchProps } from '../../index';

import { EngineOverviewHeader } from '../engine_overview_header';
import { getUserName } from '../../utils/get_username';

import './empty_states.scss';

export const NoUserState: React.FC<IEmptyStatesProps> = ({ appSearchUrl }) => {
export const NoUserState: React.FC<IAppSearchProps> = ({ appSearchUrl, setBreadcrumbs }) => {
const username = getUserName();

return (
<EuiPage restrictWidth className="empty-state">
<SetBreadcrumbs setBreadcrumbs={setBreadcrumbs} isRoot />

<EuiPageBody>
<EngineOverviewHeader appSearchUrl={appSearchUrl} />
<EuiPageContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import {
EuiSpacer,
} from '@elastic/eui';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { IAppSearchProps } from '../../index';

import EnginesIcon from '../../assets/engine.svg';
import MetaEnginesIcon from '../../assets/meta_engine.svg';

Expand All @@ -24,12 +27,9 @@ import { EngineTable } from './engine_table';

import './engine_overview.scss';

interface IEngineOverviewProps {
appSearchUrl: string;
http();
}
export const EngineOverview: ReactFC<IAppSearchProps> = props => {
const { http, appSearchUrl } = props;

export const EngineOverview: ReactFC<IEngineOverviewProps> = ({ http, ...props }) => {
const [isLoading, setIsLoading] = useState(true);
const [hasNoAccount, setHasNoAccount] = useState(false);
const [hasErrorConnecting, setHasErrorConnecting] = useState(false);
Expand Down Expand Up @@ -95,8 +95,10 @@ export const EngineOverview: ReactFC<IEngineOverviewProps> = ({ http, ...props }

return (
<EuiPage restrictWidth className="engine-overview">
<SetBreadcrumbs {...props} isRoot />

<EuiPageBody>
<EngineOverviewHeader appSearchUrl={props.appSearchUrl} />
<EngineOverviewHeader appSearchUrl={appSearchUrl} />

<EuiPageContent>
<EuiPageContentHeader>
Expand All @@ -115,7 +117,7 @@ export const EngineOverview: ReactFC<IEngineOverviewProps> = ({ http, ...props }
pageIndex: enginesPage - 1,
onPaginate: setEnginesPage,
}}
appSearchUrl={props.appSearchUrl}
appSearchUrl={appSearchUrl}
/>
</EuiPageContentBody>

Expand All @@ -138,7 +140,7 @@ export const EngineOverview: ReactFC<IEngineOverviewProps> = ({ http, ...props }
pageIndex: metaEnginesPage - 1,
onPaginate: setMetaEnginesPage,
}}
appSearchUrl={props.appSearchUrl}
appSearchUrl={appSearchUrl}
/>
</EuiPageContentBody>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ import {
EuiCodeBlock,
} from '@elastic/eui';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';

import GettingStarted from '../../assets/getting_started.png';
import './setup_guide.scss';

export const SetupGuide: React.FC<> = () => {
export const SetupGuide: React.FC<> = props => {
return (
<EuiPage className="setup-guide">
<SetBreadcrumbs {...props} text="Setup Guide" />
<EuiPageSideBar>
<EuiText color="subdued" size="s">
<strong>Setup Guide</strong>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom';

import { HttpHandler } from 'src/core/public';
import { TSetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';

import { SetupGuide } from './components/setup_guide';
import { EngineOverview } from './components/engine_overview';

interface IAppSearchProps {
export interface IAppSearchProps {
appSearchUrl?: string;
http(): HttpHandler;
setBreadCrumbs(): TSetBreadcrumbs;
}

export const AppSearch: React.FC<IAppSearchProps> = props => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ export const renderApp = (core: CoreStart, params: AppMountParams, config: Clien
<Redirect to="/app_search" />
</Route>
<Route path="/app_search">
<AppSearch http={core.http} appSearchUrl={config.host} />
<AppSearch
http={core.http}
appSearchUrl={config.host}
setBreadcrumbs={core.chrome.setBreadcrumbs}
/>
</Route>
</BrowserRouter>,
params.element
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 { Breadcrumb as EuiBreadcrumb } from '@elastic/eui';
import { History } from 'history';

import { letBrowserHandleEvent } from '../react_router_helpers';

/**
* Generate React-Router-friendly EUI breadcrumb objects
* https://elastic.github.io/eui/#/navigation/breadcrumbs
*/

interface IGenerateBreadcrumbProps {
text: string;
path: string;
history: History;
}

export const generateBreadcrumb = ({ text, path, history }: IGenerateBreadcrumbProps) => ({
text,
href: history.createHref({ pathname: path }),
onClick: event => {
if (letBrowserHandleEvent(event)) return;
event.preventDefault();
history.push(path);
},
});

/**
* Product-specific breadcrumb helpers
*/

type TBreadcrumbs = EuiBreadcrumb[] | [];

export const enterpriseSearchBreadcrumbs = (history: History) => (
breadcrumbs: TBreadcrumbs = []
) => [
generateBreadcrumb({ text: 'Enterprise Search', path: '/', history }),
...breadcrumbs.map(({ text, path }) => generateBreadcrumb({ text, path, history })),
];

export const appSearchBreadcrumbs = (history: History) => (breadcrumbs: TBreadcrumbs = []) =>
enterpriseSearchBreadcrumbs(history)([
{ text: 'App Search', path: '/app_search' },
...breadcrumbs,
]);
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

export interface IEmptyStatesProps {
appSearchUrl: string;
}
export { enterpriseSearchBreadcrumbs } from './generate_breadcrumbs';
export { appSearchBreadcrumbs } from './generate_breadcrumbs';
export { SetAppSearchBreadcrumbs } from './set_breadcrumbs';
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { Breadcrumb as EuiBreadcrumb } from '@elastic/eui';
import { appSearchBreadcrumbs } from './generate_breadcrumbs';

/**
* Small on-mount helper for setting Kibana's chrome breadcrumbs on any App Search view
* @see https://github.com/elastic/kibana/blob/master/src/core/public/chrome/chrome_service.tsx
*/

export type TSetBreadcrumbs = (breadcrumbs: EuiBreadcrumb[]) => void;

interface ISetBreadcrumbsProps {
text: string;
setBreadcrumbs(): setBreadcrumbs;
isRoot?: boolean;
}

export const SetAppSearchBreadcrumbs: React.FC<ISetBreadcrumbsProps> = ({
text,
setBreadcrumbs,
isRoot,
}) => {
const history = useHistory();
const crumb = isRoot ? [] : [{ text, path: history.location.pathname }];

useEffect(() => {
setBreadcrumbs(appSearchBreadcrumbs(history)(crumb));
}, []); // eslint-disable-line

return null;
};

0 comments on commit 0e7fd50

Please sign in to comment.