diff --git a/x-pack/plugins/apm/public/components/app/Main/Breadcrumbs.js b/x-pack/plugins/apm/public/components/app/Main/Breadcrumbs.js
deleted file mode 100644
index 74870aef9e860..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Main/Breadcrumbs.js
+++ /dev/null
@@ -1,80 +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 React from 'react';
-import { withBreadcrumbs } from 'react-router-breadcrumbs-hoc';
-import { flatten, capitalize } from 'lodash';
-import chrome from 'ui/chrome';
-import { toQuery } from '../../shared/Links/url_helpers';
-import { routes } from './routeConfig';
-
-class Breadcrumbs extends React.Component {
- updateHeaderBreadcrumbs() {
- const { _g = '', kuery = '' } = toQuery(this.props.location.search);
- const breadcrumbs = this.props.breadcrumbs.map(({ breadcrumb, match }) => ({
- text: breadcrumb,
- href: `#${match.url}?_g=${_g}&kuery=${kuery}`
- }));
-
- chrome.breadcrumbs.set(breadcrumbs);
- }
-
- componentDidMount() {
- this.updateHeaderBreadcrumbs();
- }
-
- componentDidUpdate() {
- this.updateHeaderBreadcrumbs();
- }
-
- render() {
- const { breadcrumbs, location, showPluginBreadcrumbs } = this.props;
- const { _g = '', kuery = '' } = toQuery(location.search);
-
- // If we don't display plugin breadcrumbs, render null, but continue
- // to push updates to header.
- if (!showPluginBreadcrumbs) {
- return null;
- }
-
- return (
-
- {breadcrumbs.map(({ breadcrumb, path, match }, i) => {
- const isLast = i === breadcrumbs.length - 1;
- return (
-
- {isLast ? (
-
{
- if (node && document.title !== node.textContent) {
- document.title = capitalize(node.textContent);
- }
- }}
- >
- {breadcrumb}
-
- ) : (
-
- {breadcrumb}
-
- )}
-
- );
- })}
-
- );
- }
-}
-
-const flatRoutes = flatten(
- routes.map(route => (route.switch ? route.routes : route))
-);
-
-export default withBreadcrumbs(flatRoutes)(Breadcrumbs);
diff --git a/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.ts b/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.ts
new file mode 100644
index 0000000000000..45fe37e9bf8c1
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 { Location } from 'history';
+import { flatten } from 'lodash';
+import React from 'react';
+// @ts-ignore
+import { withBreadcrumbs } from 'react-router-breadcrumbs-hoc';
+import chrome from 'ui/chrome';
+import { toQuery } from '../../shared/Links/url_helpers';
+import { routes } from './routeConfig';
+
+interface Props {
+ location: Location;
+ breadcrumbs: Array<{
+ breadcrumb: any;
+ match: {
+ url: string;
+ };
+ }>;
+}
+
+class UpdateBreadcrumbsComponent extends React.Component {
+ public updateHeaderBreadcrumbs() {
+ const { _g = '', kuery = '' } = toQuery(this.props.location.search);
+ const breadcrumbs = this.props.breadcrumbs.map(({ breadcrumb, match }) => ({
+ text: breadcrumb,
+ href: `#${match.url}?_g=${_g}&kuery=${kuery}`
+ }));
+
+ chrome.breadcrumbs.set(breadcrumbs);
+ }
+
+ public componentDidMount() {
+ this.updateHeaderBreadcrumbs();
+ }
+
+ public componentDidUpdate() {
+ this.updateHeaderBreadcrumbs();
+ }
+
+ public render() {
+ return null;
+ }
+}
+
+const flatRoutes = flatten(
+ routes.map(route => (route.switchRoutes ? route.switchRoutes : route))
+);
+
+const UpdateBreadcrumbs = withBreadcrumbs(flatRoutes)(
+ UpdateBreadcrumbsComponent
+);
+
+export { UpdateBreadcrumbs };
diff --git a/x-pack/plugins/apm/public/components/app/Main/__test__/Breadcrumbs.test.js b/x-pack/plugins/apm/public/components/app/Main/__test__/UpdateBreadcrumbs.test.js
similarity index 76%
rename from x-pack/plugins/apm/public/components/app/Main/__test__/Breadcrumbs.test.js
rename to x-pack/plugins/apm/public/components/app/Main/__test__/UpdateBreadcrumbs.test.js
index be57500928f4b..28337f771255d 100644
--- a/x-pack/plugins/apm/public/components/app/Main/__test__/Breadcrumbs.test.js
+++ b/x-pack/plugins/apm/public/components/app/Main/__test__/UpdateBreadcrumbs.test.js
@@ -7,15 +7,14 @@
import React from 'react';
import { mount } from 'enzyme';
import { MemoryRouter } from 'react-router-dom';
-
-import Breadcrumbs from '../Breadcrumbs';
-import { toJson } from '../../../../utils/testHelpers';
+import { UpdateBreadcrumbs } from '../UpdateBreadcrumbs';
+import chrome from 'ui/chrome';
jest.mock(
'ui/chrome',
() => ({
breadcrumbs: {
- set: () => {}
+ set: jest.fn()
},
getBasePath: () => `/some/base/path`,
getUiSettingsClient: () => {
@@ -37,17 +36,20 @@ jest.mock(
);
function expectBreadcrumbToMatchSnapshot(route) {
- const wrapper = mount(
+ mount(
-
+
);
- expect(
- toJson(wrapper.find('.kuiLocalBreadcrumb').children())
- ).toMatchSnapshot();
+ expect(chrome.breadcrumbs.set).toHaveBeenCalledTimes(1);
+ expect(chrome.breadcrumbs.set.mock.calls[0][0]).toMatchSnapshot();
}
describe('Breadcrumbs', () => {
+ beforeEach(() => {
+ chrome.breadcrumbs.set.mockReset();
+ });
+
it('Homepage', () => {
expectBreadcrumbToMatchSnapshot('/');
});
@@ -77,13 +79,4 @@ describe('Breadcrumbs', () => {
'/:serviceName/transactions/request/my-transaction-name'
);
});
-
- it('does not render breadcrumbs when showPluginBreadcrumbs = false', () => {
- const wrapper = mount(
-
-
-
- );
- expect(wrapper.find('.kuiLocalBreadcrumbs').exists()).toEqual(false);
- });
});
diff --git a/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Breadcrumbs.test.js.snap b/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Breadcrumbs.test.js.snap
deleted file mode 100644
index 73aded84664bb..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Breadcrumbs.test.js.snap
+++ /dev/null
@@ -1,120 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Breadcrumbs /:serviceName 1`] = `
-Array [
-
- APM
- ,
-
- opbeans-node
- ,
-]
-`;
-
-exports[`Breadcrumbs /:serviceName/errors 1`] = `
-Array [
-
- APM
- ,
-
- opbeans-node
- ,
-
- Errors
- ,
-]
-`;
-
-exports[`Breadcrumbs /:serviceName/errors/:groupId 1`] = `
-Array [
-
- APM
- ,
-
- opbeans-node
- ,
-
- Errors
- ,
-
- myGroupId
- ,
-]
-`;
-
-exports[`Breadcrumbs /:serviceName/transactions 1`] = `
-Array [
-
- APM
- ,
-
- opbeans-node
- ,
-
- Transactions
- ,
-]
-`;
-
-exports[`Breadcrumbs /:serviceName/transactions/:transactionType 1`] = `
-Array [
-
- APM
- ,
-
- opbeans-node
- ,
-
- Transactions
- ,
-]
-`;
-
-exports[`Breadcrumbs /:serviceName/transactions/:transactionType/:transactionName 1`] = `
-Array [
-
- APM
- ,
-
- :serviceName
- ,
-
- Transactions
- ,
-
- my-transaction-name
- ,
-]
-`;
-
-exports[`Breadcrumbs Homepage 1`] = `
-
- APM
-
-`;
diff --git a/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/UpdateBreadcrumbs.test.js.snap b/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/UpdateBreadcrumbs.test.js.snap
new file mode 100644
index 0000000000000..681c20d1424df
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/UpdateBreadcrumbs.test.js.snap
@@ -0,0 +1,207 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Breadcrumbs /:serviceName 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+ Object {
+ "href": "#/opbeans-node?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+]
+`;
+
+exports[`Breadcrumbs /:serviceName/errors 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+ Object {
+ "href": "#/opbeans-node?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+ Object {
+ "href": "#/opbeans-node/errors?_g=myG&kuery=myKuery",
+ "text": "Errors",
+ },
+]
+`;
+
+exports[`Breadcrumbs /:serviceName/errors/:groupId 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+ Object {
+ "href": "#/opbeans-node?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+ Object {
+ "href": "#/opbeans-node/errors?_g=myG&kuery=myKuery",
+ "text": "Errors",
+ },
+ Object {
+ "href": "#/opbeans-node/errors/myGroupId?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+]
+`;
+
+exports[`Breadcrumbs /:serviceName/transactions 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+ Object {
+ "href": "#/opbeans-node?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+ Object {
+ "href": "#/opbeans-node/transactions?_g=myG&kuery=myKuery",
+ "text": "Transactions",
+ },
+]
+`;
+
+exports[`Breadcrumbs /:serviceName/transactions/:transactionType 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+ Object {
+ "href": "#/opbeans-node?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+ Object {
+ "href": "#/opbeans-node/transactions?_g=myG&kuery=myKuery",
+ "text": "Transactions",
+ },
+]
+`;
+
+exports[`Breadcrumbs /:serviceName/transactions/:transactionType/:transactionName 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+ Object {
+ "href": "#/:serviceName?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+ Object {
+ "href": "#/:serviceName/transactions?_g=myG&kuery=myKuery",
+ "text": "Transactions",
+ },
+ Object {
+ "href": "#/:serviceName/transactions/request/my-transaction-name?_g=myG&kuery=myKuery",
+ "text": ,
+ },
+]
+`;
+
+exports[`Breadcrumbs Homepage 1`] = `
+Array [
+ Object {
+ "href": "#/?_g=myG&kuery=myKuery",
+ "text": "APM",
+ },
+]
+`;
diff --git a/x-pack/plugins/apm/public/components/app/Main/index.js b/x-pack/plugins/apm/public/components/app/Main/index.js
index f08a59ec020fe..865bf756f7663 100644
--- a/x-pack/plugins/apm/public/components/app/Main/index.js
+++ b/x-pack/plugins/apm/public/components/app/Main/index.js
@@ -11,6 +11,7 @@ import { routes } from './routeConfig';
import ScrollToTopOnPathChange from './ScrollToTopOnPathChange';
import { px, units, unit, topNavHeight } from '../../../style/variables';
import ConnectRouterToRedux from '../../shared/ConnectRouterToRedux';
+import { UpdateBreadcrumbs } from './UpdateBreadcrumbs';
const MainContainer = styled.div`
min-width: ${px(unit * 50)};
@@ -21,12 +22,13 @@ const MainContainer = styled.div`
export default function Main() {
return (
+
{routes.map((route, i) => {
- return route.switch ? (
+ return route.switchRoutes ? (
- {route.routes.map((route, i) => (
+ {route.switchRoutes.map((route, i) => (
))}
diff --git a/x-pack/plugins/apm/public/components/app/Main/routeConfig.tsx b/x-pack/plugins/apm/public/components/app/Main/routeConfig.tsx
index bc59dd934fa08..bbdb1076d9426 100644
--- a/x-pack/plugins/apm/public/components/app/Main/routeConfig.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/routeConfig.tsx
@@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
-import { Redirect, RouteComponentProps } from 'react-router-dom';
+import { Redirect, RouteComponentProps, RouteProps } from 'react-router-dom';
import { legacyDecodeURIComponent } from 'x-pack/plugins/apm/public/components/shared/Links/url_helpers';
import { StringMap } from '../../../../typings/common';
// @ts-ignore
@@ -25,6 +25,13 @@ interface RouteParams {
serviceName: string;
}
+type BreadcrumbFunction = (args: BreadcrumbArgs) => string | null;
+
+interface Route extends RouteProps {
+ switchRoutes?: Route[];
+ breadcrumb?: string | BreadcrumbFunction | null;
+}
+
const renderAsRedirectTo = (to: string) => {
return ({ location }: RouteComponentProps) => (
{
);
};
-export const routes = [
+export const routes: Route[] = [
{
exact: true,
path: '/',
@@ -58,8 +65,7 @@ export const routes = [
})
},
{
- switch: true,
- routes: [
+ switchRoutes: [
{
exact: true,
path: '/invalid-license',
diff --git a/x-pack/plugins/apm/public/index.js b/x-pack/plugins/apm/public/index.js
index 77a91e3eae43c..74b246fab9488 100644
--- a/x-pack/plugins/apm/public/index.js
+++ b/x-pack/plugins/apm/public/index.js
@@ -18,7 +18,6 @@ import './style/global_overrides.css';
import template from './templates/index.html';
import Main from './components/app/Main';
-import Breadcrumbs from './components/app/Main/Breadcrumbs';
import { initTimepicker } from './utils/timepicker';
import configureStore from './store/config/configureStore';
@@ -33,17 +32,6 @@ chrome.setRootTemplate(template);
const store = configureStore();
initTimepicker(history, store.dispatch).then(() => {
- const showPluginBreadcrumbs = !chrome
- .getUiSettingsClient()
- .get('k7design', false);
-
- ReactDOM.render(
-
-
- ,
- document.getElementById('react-apm-breadcrumbs')
- );
-
ReactDOM.render(
diff --git a/x-pack/plugins/apm/public/templates/index.html b/x-pack/plugins/apm/public/templates/index.html
index af514d69098b8..b38dee3e344aa 100644
--- a/x-pack/plugins/apm/public/templates/index.html
+++ b/x-pack/plugins/apm/public/templates/index.html
@@ -1,11 +1,5 @@
-
-
-
-
+
+
diff --git a/x-pack/plugins/apm/public/utils/timepicker/index.js b/x-pack/plugins/apm/public/utils/timepicker/index.js
index 505682d177db5..b0c35cd43eb65 100644
--- a/x-pack/plugins/apm/public/utils/timepicker/index.js
+++ b/x-pack/plugins/apm/public/utils/timepicker/index.js
@@ -15,7 +15,7 @@ let currentInterval;
// hack to wait for angular template to be ready
const waitForAngularReady = new Promise(resolve => {
const checkInterval = setInterval(() => {
- const hasElm = !!document.querySelector('#react-apm-breadcrumbs');
+ const hasElm = !!document.querySelector('#kibana-angular-template');
if (hasElm) {
clearInterval(checkInterval);
resolve();