Skip to content

Commit ac2334e

Browse files
committed
Empty message for APM service map (elastic#59518)
When only one node is displayed, show an empty message. Also: * Start adding a basic Jest test for the ServiceMap component * Fix bug where EuiDocsLink was rendering "children" instead of the actual children Closes elastic#59326. Closes elastic#59128.
1 parent 8ed96a0 commit ac2334e

File tree

4 files changed

+94
-2
lines changed

4 files changed

+94
-2
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { EuiCallOut } from '@elastic/eui';
8+
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
9+
import { i18n } from '@kbn/i18n';
10+
import React from 'react';
11+
import styled from 'styled-components';
12+
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
13+
14+
const EmptyBannerCallOut = styled(EuiCallOut)`
15+
margin: ${lightTheme.gutterTypes.gutterSmall};
16+
/* Add some extra margin so it displays to the right of the controls. */
17+
margin-left: calc(
18+
${lightTheme.gutterTypes.gutterLarge} +
19+
${lightTheme.gutterTypes.gutterExtraLarge}
20+
);
21+
position: absolute;
22+
z-index: 1;
23+
`;
24+
25+
export function EmptyBanner() {
26+
return (
27+
<EmptyBannerCallOut
28+
title={i18n.translate('xpack.apm.serviceMap.emptyBanner.title', {
29+
defaultMessage: "Looks like there's only a single service."
30+
})}
31+
>
32+
{i18n.translate('xpack.apm.serviceMap.emptyBanner.message', {
33+
defaultMessage:
34+
"We will map out connected services and external requests if we can detect them. Please make sure you're running the latest version of the APM agent."
35+
})}{' '}
36+
<ElasticDocsLink section="/apm/get-started" path="/agents.html">
37+
{i18n.translate('xpack.apm.serviceMap.emptyBanner.docsLink', {
38+
defaultMessage: 'Learn more in the docs'
39+
})}
40+
</ElasticDocsLink>
41+
</EmptyBannerCallOut>
42+
);
43+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { render } from '@testing-library/react';
8+
import React, { FunctionComponent } from 'react';
9+
import { License } from '../../../../../../../plugins/licensing/common/license';
10+
import { LicenseContext } from '../../../context/LicenseContext';
11+
import { MockApmPluginContextWrapper } from '../../../utils/testHelpers';
12+
import { ServiceMap } from './';
13+
14+
const expiredLicense = new License({
15+
signature: 'test signature',
16+
license: {
17+
expiryDateInMillis: 0,
18+
mode: 'platinum',
19+
status: 'expired',
20+
type: 'platinum',
21+
uid: '1'
22+
}
23+
});
24+
25+
const Wrapper: FunctionComponent = ({ children }) => {
26+
return (
27+
<LicenseContext.Provider value={expiredLicense}>
28+
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
29+
</LicenseContext.Provider>
30+
);
31+
};
32+
33+
describe('ServiceMap', () => {
34+
describe('with an inactive license', () => {
35+
it('renders the license banner', async () => {
36+
expect(
37+
(
38+
await render(<ServiceMap />, {
39+
wrapper: Wrapper
40+
}).findAllByText(/Platinum/)
41+
).length
42+
).toBeGreaterThan(0);
43+
});
44+
});
45+
});

x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ import { useLicense } from '../../../hooks/useLicense';
2626
import { useLoadingIndicator } from '../../../hooks/useLoadingIndicator';
2727
import { useLocation } from '../../../hooks/useLocation';
2828
import { useUrlParams } from '../../../hooks/useUrlParams';
29+
import { callApmApi } from '../../../services/rest/createCallApmApi';
2930
import { Controls } from './Controls';
3031
import { Cytoscape } from './Cytoscape';
32+
import { EmptyBanner } from './EmptyBanner';
3133
import { getCytoscapeElements } from './get_cytoscape_elements';
3234
import { PlatinumLicensePrompt } from './PlatinumLicensePrompt';
3335
import { Popover } from './Popover';
3436
import { useRefDimensions } from './useRefDimensions';
35-
import { callApmApi } from '../../../services/rest/createCallApmApi';
3637

3738
interface ServiceMapProps {
3839
serviceName?: string;
@@ -214,6 +215,9 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
214215
style={cytoscapeDivStyle}
215216
>
216217
<Controls />
218+
{serviceName && renderedElements.current.length === 1 && (
219+
<EmptyBanner />
220+
)}
217221
<Popover focusedServiceName={serviceName} />
218222
</Cytoscape>
219223
</div>

x-pack/legacy/plugins/apm/public/components/shared/Links/ElasticDocsLink.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function ElasticDocsLink({ section, path, children, ...rest }: Props) {
2323
children(href)
2424
) : (
2525
<EuiLink href={href} {...rest}>
26-
children
26+
{children}
2727
</EuiLink>
2828
);
2929
}

0 commit comments

Comments
 (0)