mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* Solves several breadcrumb string/object problems, adds title to page * Updates breadcrumb tests and adds title tests * Removes switch logic from route config in favor of a single switch around all routes * Adding draft version of withBreadcrumbs HOC with TS errors * ProvideBreadcrumbs implemented * Adds tests to provide breadcrumb logic * Fixed up generics and tests
This commit is contained in:
parent
5a55e3240a
commit
a8d5e5962f
9 changed files with 334 additions and 201 deletions
|
@ -231,7 +231,6 @@
|
|||
"react-portal": "^3.2.0",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-redux-request": "^1.5.6",
|
||||
"react-router-breadcrumbs-hoc": "1.1.2",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-select": "^1.2.1",
|
||||
"react-shortcuts": "^2.0.0",
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import {
|
||||
matchPath,
|
||||
RouteComponentProps,
|
||||
RouteProps,
|
||||
withRouter
|
||||
} from 'react-router-dom';
|
||||
import { StringMap } from 'x-pack/plugins/apm/typings/common';
|
||||
|
||||
type LocationMatch = Pick<
|
||||
RouteComponentProps<StringMap<string>>,
|
||||
'location' | 'match'
|
||||
>;
|
||||
|
||||
export type BreadcrumbFunction = (props: LocationMatch) => string;
|
||||
|
||||
export interface BreadcrumbRoute extends RouteProps {
|
||||
breadcrumb: string | BreadcrumbFunction | null;
|
||||
}
|
||||
|
||||
export interface Breadcrumb extends LocationMatch {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface RenderProps extends RouteComponentProps {
|
||||
breadcrumbs: Breadcrumb[];
|
||||
}
|
||||
|
||||
export interface ProvideBreadcrumbsProps extends RouteComponentProps {
|
||||
routes: BreadcrumbRoute[];
|
||||
render: (props: RenderProps) => React.ReactElement<any> | null;
|
||||
}
|
||||
|
||||
interface ParseOptions extends LocationMatch {
|
||||
breadcrumb: string | BreadcrumbFunction;
|
||||
}
|
||||
|
||||
const parse = (options: ParseOptions) => {
|
||||
const { breadcrumb, match, location } = options;
|
||||
let value;
|
||||
|
||||
if (typeof breadcrumb === 'function') {
|
||||
value = breadcrumb({ match, location });
|
||||
} else {
|
||||
value = breadcrumb;
|
||||
}
|
||||
|
||||
return { value, match, location };
|
||||
};
|
||||
|
||||
export function getBreadcrumb({
|
||||
location,
|
||||
currentPath,
|
||||
routes
|
||||
}: {
|
||||
location: Location;
|
||||
currentPath: string;
|
||||
routes: BreadcrumbRoute[];
|
||||
}) {
|
||||
return routes.reduce<Breadcrumb | null>((found, { breadcrumb, ...route }) => {
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
|
||||
if (!breadcrumb) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const match = matchPath<StringMap<string>>(currentPath, route);
|
||||
|
||||
if (match) {
|
||||
return parse({
|
||||
breadcrumb,
|
||||
match,
|
||||
location
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}, null);
|
||||
}
|
||||
|
||||
export function getBreadcrumbs({
|
||||
routes,
|
||||
location
|
||||
}: {
|
||||
routes: BreadcrumbRoute[];
|
||||
location: Location;
|
||||
}) {
|
||||
const breadcrumbs: Breadcrumb[] = [];
|
||||
const { pathname } = location;
|
||||
|
||||
pathname
|
||||
.split('?')[0]
|
||||
.replace(/\/$/, '')
|
||||
.split('/')
|
||||
.reduce((acc, next) => {
|
||||
// `/1/2/3` results in match checks for `/1`, `/1/2`, `/1/2/3`.
|
||||
const currentPath = !next ? '/' : `${acc}/${next}`;
|
||||
const breadcrumb = getBreadcrumb({
|
||||
location,
|
||||
currentPath,
|
||||
routes
|
||||
});
|
||||
|
||||
if (breadcrumb) {
|
||||
breadcrumbs.push(breadcrumb);
|
||||
}
|
||||
|
||||
return currentPath === '/' ? '' : currentPath;
|
||||
}, '');
|
||||
|
||||
return breadcrumbs;
|
||||
}
|
||||
|
||||
function ProvideBreadcrumbsComponent({
|
||||
routes = [],
|
||||
render,
|
||||
location,
|
||||
match,
|
||||
history
|
||||
}: ProvideBreadcrumbsProps) {
|
||||
const breadcrumbs = getBreadcrumbs({ routes, location });
|
||||
return render({ breadcrumbs, location, match, history });
|
||||
}
|
||||
|
||||
export const ProvideBreadcrumbs = withRouter(ProvideBreadcrumbsComponent);
|
|
@ -5,32 +5,28 @@
|
|||
*/
|
||||
|
||||
import { Location } from 'history';
|
||||
import { flatten } from 'lodash';
|
||||
import { last } 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 { Breadcrumb, ProvideBreadcrumbs } from './ProvideBreadcrumbs';
|
||||
import { routes } from './routeConfig';
|
||||
|
||||
interface Props {
|
||||
location: Location;
|
||||
breadcrumbs: Array<{
|
||||
breadcrumb: any;
|
||||
match: {
|
||||
url: string;
|
||||
};
|
||||
}>;
|
||||
breadcrumbs: Breadcrumb[];
|
||||
}
|
||||
|
||||
class UpdateBreadcrumbsComponent extends React.Component<Props> {
|
||||
public updateHeaderBreadcrumbs() {
|
||||
const { _g = '', kuery = '' } = toQuery(this.props.location.search);
|
||||
const breadcrumbs = this.props.breadcrumbs.map(({ breadcrumb, match }) => ({
|
||||
text: breadcrumb,
|
||||
const breadcrumbs = this.props.breadcrumbs.map(({ value, match }) => ({
|
||||
text: value,
|
||||
href: `#${match.url}?_g=${_g}&kuery=${kuery}`
|
||||
}));
|
||||
|
||||
const current = last(breadcrumbs) || { text: '' };
|
||||
document.title = current.text;
|
||||
chrome.breadcrumbs.set(breadcrumbs);
|
||||
}
|
||||
|
||||
|
@ -47,12 +43,16 @@ class UpdateBreadcrumbsComponent extends React.Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const flatRoutes = flatten(
|
||||
routes.map(route => (route.switchRoutes ? route.switchRoutes : route))
|
||||
);
|
||||
|
||||
const UpdateBreadcrumbs = withBreadcrumbs(flatRoutes)(
|
||||
UpdateBreadcrumbsComponent
|
||||
);
|
||||
|
||||
export { UpdateBreadcrumbs };
|
||||
export function UpdateBreadcrumbs() {
|
||||
return (
|
||||
<ProvideBreadcrumbs
|
||||
routes={routes}
|
||||
render={({ breadcrumbs, location }) => (
|
||||
<UpdateBreadcrumbsComponent
|
||||
breadcrumbs={breadcrumbs}
|
||||
location={location}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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 { BreadcrumbRoute, getBreadcrumbs } from '../ProvideBreadcrumbs';
|
||||
|
||||
describe('getBreadcrumbs', () => {
|
||||
const getTestRoutes = (): BreadcrumbRoute[] => [
|
||||
{ path: '/a', exact: true, breadcrumb: 'A' },
|
||||
{ path: '/a/ignored', exact: true, breadcrumb: 'Ignored Route' },
|
||||
{
|
||||
path: '/a/:letter',
|
||||
exact: true,
|
||||
breadcrumb: ({ match }) => `Second level: ${match.params.letter}`
|
||||
},
|
||||
{
|
||||
path: '/a/:letter/c',
|
||||
exact: true,
|
||||
breadcrumb: ({ match }) => `Third level: ${match.params.letter}`
|
||||
}
|
||||
];
|
||||
|
||||
const getLocation = () =>
|
||||
({
|
||||
pathname: '/a/b/c/'
|
||||
} as Location);
|
||||
|
||||
it('should return a set of matching breadcrumbs for a given path', () => {
|
||||
const breadcrumbs = getBreadcrumbs({
|
||||
location: getLocation(),
|
||||
routes: getTestRoutes()
|
||||
});
|
||||
|
||||
expect(breadcrumbs.map(b => b.value)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"A",
|
||||
"Second level: b",
|
||||
"Third level: b",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should skip breadcrumbs if breadcrumb is null', () => {
|
||||
const location = getLocation();
|
||||
const routes = getTestRoutes();
|
||||
|
||||
routes[2].breadcrumb = null;
|
||||
|
||||
const breadcrumbs = getBreadcrumbs({
|
||||
location,
|
||||
routes
|
||||
});
|
||||
|
||||
expect(breadcrumbs.map(b => b.value)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"A",
|
||||
"Third level: b",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should skip breadcrumbs if breadcrumb key is missing', () => {
|
||||
const location = getLocation();
|
||||
const routes = getTestRoutes();
|
||||
|
||||
delete routes[2].breadcrumb;
|
||||
|
||||
const breadcrumbs = getBreadcrumbs({ location, routes });
|
||||
|
||||
expect(breadcrumbs.map(b => b.value)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"A",
|
||||
"Third level: b",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should produce matching breadcrumbs even if the pathname has a query string appended', () => {
|
||||
const location = getLocation();
|
||||
const routes = getTestRoutes();
|
||||
|
||||
location.pathname += '?some=thing';
|
||||
|
||||
const breadcrumbs = getBreadcrumbs({
|
||||
location,
|
||||
routes
|
||||
});
|
||||
|
||||
expect(breadcrumbs.map(b => b.value)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"A",
|
||||
"Second level: b",
|
||||
"Third level: b",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
|
@ -46,37 +46,56 @@ function expectBreadcrumbToMatchSnapshot(route) {
|
|||
}
|
||||
|
||||
describe('Breadcrumbs', () => {
|
||||
let realDoc;
|
||||
|
||||
beforeEach(() => {
|
||||
realDoc = global.document;
|
||||
global.document = {
|
||||
title: 'Kibana'
|
||||
};
|
||||
chrome.breadcrumbs.set.mockReset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
global.document = realDoc;
|
||||
});
|
||||
|
||||
it('Homepage', () => {
|
||||
expectBreadcrumbToMatchSnapshot('/');
|
||||
expect(global.document.title).toMatchInlineSnapshot(`"APM"`);
|
||||
});
|
||||
|
||||
it('/:serviceName/errors/:groupId', () => {
|
||||
expectBreadcrumbToMatchSnapshot('/opbeans-node/errors/myGroupId');
|
||||
expect(global.document.title).toMatchInlineSnapshot(`"myGroupId"`);
|
||||
});
|
||||
|
||||
it('/:serviceName/errors', () => {
|
||||
expectBreadcrumbToMatchSnapshot('/opbeans-node/errors');
|
||||
expect(global.document.title).toMatchInlineSnapshot(`"Errors"`);
|
||||
});
|
||||
|
||||
it('/:serviceName', () => {
|
||||
expectBreadcrumbToMatchSnapshot('/opbeans-node');
|
||||
expect(global.document.title).toMatchInlineSnapshot(`"opbeans-node"`);
|
||||
});
|
||||
|
||||
it('/:serviceName/transactions', () => {
|
||||
expectBreadcrumbToMatchSnapshot('/opbeans-node/transactions');
|
||||
expect(global.document.title).toMatchInlineSnapshot(`"Transactions"`);
|
||||
});
|
||||
|
||||
it('/:serviceName/transactions/:transactionType', () => {
|
||||
expectBreadcrumbToMatchSnapshot('/opbeans-node/transactions/request');
|
||||
expect(global.document.title).toMatchInlineSnapshot(`"Transactions"`);
|
||||
});
|
||||
|
||||
it('/:serviceName/transactions/:transactionType/:transactionName', () => {
|
||||
expectBreadcrumbToMatchSnapshot(
|
||||
'/:serviceName/transactions/request/my-transaction-name'
|
||||
'/opbeans-node/transactions/request/my-transaction-name'
|
||||
);
|
||||
expect(global.document.title).toMatchInlineSnapshot(
|
||||
`"my-transaction-name"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,18 +8,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": "opbeans-node",
|
||||
},
|
||||
"path": "/:serviceName",
|
||||
"url": "/opbeans-node",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"text": "opbeans-node",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -32,18 +21,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": "opbeans-node",
|
||||
},
|
||||
"path": "/:serviceName",
|
||||
"url": "/opbeans-node",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"text": "opbeans-node",
|
||||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node/errors?_g=myG&kuery=myKuery",
|
||||
|
@ -60,18 +38,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": "opbeans-node",
|
||||
},
|
||||
"path": "/:serviceName",
|
||||
"url": "/opbeans-node",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"text": "opbeans-node",
|
||||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node/errors?_g=myG&kuery=myKuery",
|
||||
|
@ -79,19 +46,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node/errors/myGroupId?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"groupId": "myGroupId",
|
||||
"serviceName": "opbeans-node",
|
||||
},
|
||||
"path": "/:serviceName/errors/:groupId",
|
||||
"url": "/opbeans-node/errors/myGroupId",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"text": "myGroupId",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -104,18 +59,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": "opbeans-node",
|
||||
},
|
||||
"path": "/:serviceName",
|
||||
"url": "/opbeans-node",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"text": "opbeans-node",
|
||||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node/transactions?_g=myG&kuery=myKuery",
|
||||
|
@ -132,18 +76,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": "opbeans-node",
|
||||
},
|
||||
"path": "/:serviceName",
|
||||
"url": "/opbeans-node",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"text": "opbeans-node",
|
||||
},
|
||||
Object {
|
||||
"href": "#/opbeans-node/transactions?_g=myG&kuery=myKuery",
|
||||
|
@ -159,40 +92,16 @@ Array [
|
|||
"text": "APM",
|
||||
},
|
||||
Object {
|
||||
"href": "#/:serviceName?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": ":serviceName",
|
||||
},
|
||||
"path": "/:serviceName",
|
||||
"url": "/:serviceName",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"href": "#/opbeans-node?_g=myG&kuery=myKuery",
|
||||
"text": "opbeans-node",
|
||||
},
|
||||
Object {
|
||||
"href": "#/:serviceName/transactions?_g=myG&kuery=myKuery",
|
||||
"href": "#/opbeans-node/transactions?_g=myG&kuery=myKuery",
|
||||
"text": "Transactions",
|
||||
},
|
||||
Object {
|
||||
"href": "#/:serviceName/transactions/request/my-transaction-name?_g=myG&kuery=myKuery",
|
||||
"text": <breadcrumb
|
||||
match={
|
||||
Object {
|
||||
"isExact": true,
|
||||
"params": Object {
|
||||
"serviceName": ":serviceName",
|
||||
"transactionName": "my-transaction-name",
|
||||
"transactionType": "request",
|
||||
},
|
||||
"path": "/:serviceName/transactions/:transactionType/:transactionName",
|
||||
"url": "/:serviceName/transactions/request/my-transaction-name",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"href": "#/opbeans-node/transactions/request/my-transaction-name?_g=myG&kuery=myKuery",
|
||||
"text": "my-transaction-name",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
|
|
@ -25,17 +25,11 @@ export default function Main() {
|
|||
<UpdateBreadcrumbs />
|
||||
<Route component={ConnectRouterToRedux} />
|
||||
<Route component={ScrollToTopOnPathChange} />
|
||||
{routes.map((route, i) => {
|
||||
return route.switchRoutes ? (
|
||||
<Switch key={i}>
|
||||
{route.switchRoutes.map((route, i) => (
|
||||
<Route key={i} {...route} />
|
||||
))}
|
||||
</Switch>
|
||||
) : (
|
||||
<Switch>
|
||||
{routes.map((route, i) => (
|
||||
<Route key={i} {...route} />
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</Switch>
|
||||
</MainContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,32 +6,19 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { Redirect, RouteComponentProps, RouteProps } from 'react-router-dom';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { legacyDecodeURIComponent } from 'x-pack/plugins/apm/public/components/shared/Links/url_helpers';
|
||||
import { StringMap } from '../../../../typings/common';
|
||||
// @ts-ignore
|
||||
import ErrorGroupDetails from '../ErrorGroupDetails';
|
||||
import { ServiceDetails } from '../ServiceDetails';
|
||||
import { TransactionDetails } from '../TransactionDetails';
|
||||
import { Home } from './Home';
|
||||
|
||||
interface BreadcrumbArgs {
|
||||
match: {
|
||||
params: StringMap<string>;
|
||||
};
|
||||
}
|
||||
import { BreadcrumbRoute } from './ProvideBreadcrumbs';
|
||||
|
||||
interface RouteParams {
|
||||
serviceName: string;
|
||||
}
|
||||
|
||||
type BreadcrumbFunction = (args: BreadcrumbArgs) => string | undefined;
|
||||
|
||||
interface Route extends RouteProps {
|
||||
switchRoutes?: Route[];
|
||||
breadcrumb?: string | BreadcrumbFunction | null;
|
||||
}
|
||||
|
||||
const renderAsRedirectTo = (to: string) => {
|
||||
return ({ location }: RouteComponentProps<RouteParams>) => (
|
||||
<Redirect
|
||||
|
@ -43,18 +30,57 @@ const renderAsRedirectTo = (to: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const routes: Route[] = [
|
||||
export const routes: BreadcrumbRoute[] = [
|
||||
{
|
||||
exact: true,
|
||||
path: '/',
|
||||
render: renderAsRedirectTo('/services'),
|
||||
breadcrumb: 'APM'
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/invalid-license',
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.invalidLicenseTitle', {
|
||||
defaultMessage: 'Invalid License'
|
||||
}),
|
||||
render: () => (
|
||||
<div>
|
||||
{i18n.translate('xpack.apm.invalidLicenseLabel', {
|
||||
defaultMessage: 'Invalid license'
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services',
|
||||
component: Home,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.servicesTitle', {
|
||||
defaultMessage: 'Services'
|
||||
})
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/traces',
|
||||
component: Home,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.tracesTitle', {
|
||||
defaultMessage: 'Traces'
|
||||
})
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/:serviceName',
|
||||
breadcrumb: ({ match }) => match.params.serviceName,
|
||||
render: (props: RouteComponentProps<RouteParams>) =>
|
||||
renderAsRedirectTo(`/${props.match.params.serviceName}/transactions`)(
|
||||
props
|
||||
)
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/:serviceName/errors/:groupId',
|
||||
component: ErrorGroupDetails,
|
||||
breadcrumb: ({ match }: BreadcrumbArgs) => match.params.groupId
|
||||
breadcrumb: ({ match }) => match.params.groupId
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
|
@ -64,49 +90,6 @@ export const routes: Route[] = [
|
|||
defaultMessage: 'Errors'
|
||||
})
|
||||
},
|
||||
{
|
||||
switchRoutes: [
|
||||
{
|
||||
exact: true,
|
||||
path: '/invalid-license',
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.invalidLicenseTitle', {
|
||||
defaultMessage: 'Invalid License'
|
||||
}),
|
||||
render: () => (
|
||||
<div>
|
||||
{i18n.translate('xpack.apm.invalidLicenseLabel', {
|
||||
defaultMessage: 'Invalid license'
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services',
|
||||
component: Home,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.servicesTitle', {
|
||||
defaultMessage: 'Services'
|
||||
})
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/traces',
|
||||
component: Home,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.tracesTitle', {
|
||||
defaultMessage: 'Traces'
|
||||
})
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/:serviceName',
|
||||
breadcrumb: ({ match }: BreadcrumbArgs) => match.params.serviceName,
|
||||
render: (props: RouteComponentProps<RouteParams>) =>
|
||||
renderAsRedirectTo(`/${props.match.params.serviceName}/transactions`)(
|
||||
props
|
||||
)
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/:serviceName/transactions',
|
||||
|
@ -135,7 +118,7 @@ export const routes: Route[] = [
|
|||
exact: true,
|
||||
path: '/:serviceName/transactions/:transactionType/:transactionName',
|
||||
component: TransactionDetails,
|
||||
breadcrumb: ({ match }: BreadcrumbArgs) =>
|
||||
legacyDecodeURIComponent(match.params.transactionName)
|
||||
breadcrumb: ({ match }) =>
|
||||
legacyDecodeURIComponent(match.params.transactionName) || ''
|
||||
}
|
||||
];
|
||||
|
|
|
@ -17694,11 +17694,6 @@ react-resizable@1.x:
|
|||
prop-types "15.x"
|
||||
react-draggable "^2.2.6 || ^3.0.3"
|
||||
|
||||
react-router-breadcrumbs-hoc@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/react-router-breadcrumbs-hoc/-/react-router-breadcrumbs-hoc-1.1.2.tgz#4fafb620e7c6b876d98f7151f4c85ae5c3157dc0"
|
||||
integrity sha1-T6+2IOfGuHbZj3FR9Mha5cMVfcA=
|
||||
|
||||
react-router-dom@4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue