Skip to content

Commit 2599da3

Browse files
Merge branch 'master' into scottybollinger/migrate-settings
2 parents 4ba2337 + bb70c6a commit 2599da3

42 files changed

Lines changed: 436 additions & 496 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

x-pack/plugins/apm/common/custom_link/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@ export const INVALID_LICENSE = i18n.translate(
1212
"To create custom links, you must be subscribed to an Elastic Gold license or above. With it, you'll have the ability to create custom links to improve your workflow when analyzing your services.",
1313
}
1414
);
15+
16+
export const NO_PERMISSION_LABEL = i18n.translate(
17+
'xpack.apm.settings.customizeUI.customLink.noPermissionTooltipLabel',
18+
{
19+
defaultMessage:
20+
"Your user role doesn't have permissions to create custom links",
21+
}
22+
);

x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,14 @@
66
import { EuiButton, EuiToolTip } from '@elastic/eui';
77
import { i18n } from '@kbn/i18n';
88
import React from 'react';
9+
import { NO_PERMISSION_LABEL } from '../../../../../../common/custom_link';
910
import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context';
1011

1112
export function CreateCustomLinkButton({ onClick }: { onClick: () => void }) {
1213
const { core } = useApmPluginContext();
1314
const canSave = core.application.capabilities.apm.save;
1415
return (
15-
<EuiToolTip
16-
content={
17-
!canSave &&
18-
i18n.translate(
19-
'xpack.apm.settings.customizeUI.customLink.noPermissionTooltipLabel',
20-
{
21-
defaultMessage:
22-
"Your user role doesn't have permissions to create custom links",
23-
}
24-
)
25-
}
26-
>
16+
<EuiToolTip content={!canSave && NO_PERMISSION_LABEL}>
2717
<EuiButton
2818
color="primary"
2919
fill

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

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { LatencyChart } from '../../shared/charts/latency_chart';
1616
import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart';
1717
import { TransactionErrorRateChart } from '../../shared/charts/transaction_error_rate_chart';
1818
import { SearchBar } from '../../shared/search_bar';
19+
import { UserExperienceCallout } from '../transaction_overview/user_experience_callout';
1920
import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table';
2021
import { ServiceOverviewErrorsTable } from './service_overview_errors_table';
2122
import { ServiceOverviewInstancesTable } from './service_overview_instances_table';
@@ -51,13 +52,19 @@ export function ServiceOverview({
5152
'xpack.apm.serviceOverview.searchBar.transactionTypeLabel',
5253
{ defaultMessage: 'Type: {transactionType}', values: { transactionType } }
5354
);
55+
const isRumAgent = isRumAgentName(agentName);
5456

5557
return (
5658
<AnnotationsContextProvider>
5759
<ChartPointerEventContextProvider>
5860
<SearchBar prepend={transactionTypeLabel} />
5961
<EuiPage>
6062
<EuiFlexGroup direction="column" gutterSize="s">
63+
{isRumAgent && (
64+
<EuiFlexItem>
65+
<UserExperienceCallout serviceName={serviceName} />
66+
</EuiFlexItem>
67+
)}
6168
<EuiFlexItem>
6269
<EuiPanel>
6370
<LatencyChart height={200} />
@@ -87,7 +94,7 @@ export function ServiceOverview({
8794
gutterSize="s"
8895
responsive={false}
8996
>
90-
{!isRumAgentName(agentName) && (
97+
{!isRumAgent && (
9198
<EuiFlexItem grow={3}>
9299
<TransactionErrorRateChart
93100
height={chartHeight}
@@ -111,20 +118,24 @@ export function ServiceOverview({
111118
<EuiFlexItem grow={3}>
112119
<TransactionBreakdownChart showAnnotations={false} />
113120
</EuiFlexItem>
114-
<EuiFlexItem grow={7}>
115-
<EuiPanel>
116-
<ServiceOverviewDependenciesTable
117-
serviceName={serviceName}
118-
/>
119-
</EuiPanel>
120-
</EuiFlexItem>
121+
{!isRumAgent && (
122+
<EuiFlexItem grow={7}>
123+
<EuiPanel>
124+
<ServiceOverviewDependenciesTable
125+
serviceName={serviceName}
126+
/>
127+
</EuiPanel>
128+
</EuiFlexItem>
129+
)}
121130
</EuiFlexGroup>
122131
</EuiFlexItem>
123-
<EuiFlexItem>
124-
<EuiPanel>
125-
<ServiceOverviewInstancesTable serviceName={serviceName} />
126-
</EuiPanel>
127-
</EuiFlexItem>
132+
{!isRumAgent && (
133+
<EuiFlexItem>
134+
<EuiPanel>
135+
<ServiceOverviewInstancesTable serviceName={serviceName} />
136+
</EuiPanel>
137+
</EuiFlexItem>
138+
)}
128139
</EuiFlexGroup>
129140
</EuiPage>
130141
</ChartPointerEventContextProvider>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) {
123123
<EuiFlexItem grow={7}>
124124
{transactionType === TRANSACTION_PAGE_LOAD && (
125125
<>
126-
<UserExperienceCallout />
126+
<UserExperienceCallout serviceName={serviceName} />
127127
<EuiSpacer size="s" />
128128
</>
129129
)}

x-pack/plugins/apm/public/components/app/transaction_overview/user_experience_callout.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@ import { EuiButton, EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui';
99
import { i18n } from '@kbn/i18n';
1010
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
1111

12-
export function UserExperienceCallout() {
12+
interface Props {
13+
serviceName: string;
14+
}
15+
export function UserExperienceCallout({ serviceName }: Props) {
1316
const { core } = useApmPluginContext();
14-
const userExperienceHref = core.http.basePath.prepend(`/app/ux`);
17+
const userExperienceHref = core.http.basePath.prepend(
18+
`/app/ux?serviceName=${serviceName}`
19+
);
1520

1621
return (
1722
<EuiCallOut

x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.test.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,33 @@
77
import { act, fireEvent, render } from '@testing-library/react';
88
import React, { ReactNode } from 'react';
99
import { MemoryRouter } from 'react-router-dom';
10-
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
10+
import { ApmPluginContextValue } from '../../../../context/apm_plugin/apm_plugin_context';
11+
import {
12+
mockApmPluginContextValue,
13+
MockApmPluginContextWrapper,
14+
} from '../../../../context/apm_plugin/mock_apm_plugin_context';
1115
import {
1216
expectTextsInDocument,
1317
expectTextsNotInDocument,
1418
} from '../../../../utils/testHelpers';
1519
import { CustomLinkToolbar } from './CustomLinkToolbar';
1620

21+
function getMockAPMContext({ canSave }: { canSave: boolean }) {
22+
return ({
23+
...mockApmPluginContextValue,
24+
core: {
25+
...mockApmPluginContextValue.core,
26+
application: { capabilities: { apm: { save: canSave }, ml: {} } },
27+
},
28+
} as unknown) as ApmPluginContextValue;
29+
}
30+
1731
function Wrapper({ children }: { children?: ReactNode }) {
1832
return (
1933
<MemoryRouter>
20-
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
34+
<MockApmPluginContextWrapper value={getMockAPMContext({ canSave: true })}>
35+
{children}
36+
</MockApmPluginContextWrapper>
2137
</MemoryRouter>
2238
);
2339
}

x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
EuiIcon,
1313
} from '@elastic/eui';
1414
import { i18n } from '@kbn/i18n';
15+
import { NO_PERMISSION_LABEL } from '../../../../../common/custom_link';
16+
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
1517
import { APMLink } from '../../Links/apm/APMLink';
1618

1719
export function CustomLinkToolbar({
@@ -21,6 +23,9 @@ export function CustomLinkToolbar({
2123
onClickCreate: () => void;
2224
showCreateButton?: boolean;
2325
}) {
26+
const { core } = useApmPluginContext();
27+
const canSave = !!core.application.capabilities.apm.save;
28+
2429
return (
2530
<EuiFlexGroup>
2631
<EuiFlexItem>
@@ -42,17 +47,20 @@ export function CustomLinkToolbar({
4247
</EuiToolTip>
4348
</EuiFlexItem>
4449
{showCreateButton && (
45-
<EuiFlexItem grow={false}>
46-
<EuiButtonEmpty
47-
iconType="plusInCircle"
48-
size="xs"
49-
onClick={onClickCreate}
50-
>
51-
{i18n.translate('xpack.apm.customLink.buttom.create.title', {
52-
defaultMessage: 'Create',
53-
})}
54-
</EuiButtonEmpty>
55-
</EuiFlexItem>
50+
<EuiToolTip content={!canSave && NO_PERMISSION_LABEL}>
51+
<EuiFlexItem grow={false}>
52+
<EuiButtonEmpty
53+
isDisabled={!canSave}
54+
iconType="plusInCircle"
55+
size="xs"
56+
onClick={onClickCreate}
57+
>
58+
{i18n.translate('xpack.apm.customLink.buttom.create.title', {
59+
defaultMessage: 'Create',
60+
})}
61+
</EuiButtonEmpty>
62+
</EuiFlexItem>
63+
</EuiToolTip>
5664
)}
5765
</EuiFlexGroup>
5866
</EuiFlexItem>

x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import {
1313
} from '@elastic/eui';
1414
import { i18n } from '@kbn/i18n';
1515
import { isEmpty } from 'lodash';
16+
import { EuiToolTip } from '@elastic/eui';
17+
import { NO_PERMISSION_LABEL } from '../../../../../common/custom_link';
18+
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
1619
import {
1720
ActionMenuDivider,
1821
Section,
@@ -147,14 +150,17 @@ function BottomSection({
147150
toggleShowAll: () => void;
148151
onClickCreate: () => void;
149152
}) {
153+
const { core } = useApmPluginContext();
154+
const canSave = !!core.application.capabilities.apm.save;
155+
150156
if (status === FETCH_STATUS.LOADING) {
151157
return <LoadingStatePrompt />;
152158
}
153159

154160
// render empty prompt if there are no custom links
155161
if (isEmpty(customLinks)) {
156162
return (
157-
<EuiFlexGroup>
163+
<EuiFlexGroup responsive={false} direction="column" gutterSize="none">
158164
<EuiFlexItem>
159165
<EuiText size="xs" grow={false} style={{ width: px(300) }}>
160166
{i18n.translate('xpack.apm.customLink.empty', {
@@ -163,15 +169,20 @@ function BottomSection({
163169
})}
164170
</EuiText>
165171
<EuiSpacer size="s" />
166-
<EuiButtonEmpty
167-
iconType="plusInCircle"
168-
size="xs"
169-
onClick={onClickCreate}
170-
>
171-
{i18n.translate('xpack.apm.customLink.buttom.create', {
172-
defaultMessage: 'Create custom link',
173-
})}
174-
</EuiButtonEmpty>
172+
</EuiFlexItem>
173+
<EuiFlexItem style={{ alignItems: 'center' }}>
174+
<EuiToolTip content={!canSave && NO_PERMISSION_LABEL}>
175+
<EuiButtonEmpty
176+
isDisabled={!canSave}
177+
iconType="plusInCircle"
178+
size="xs"
179+
onClick={onClickCreate}
180+
>
181+
{i18n.translate('xpack.apm.customLink.buttom.create', {
182+
defaultMessage: 'Create custom link',
183+
})}
184+
</EuiButtonEmpty>
185+
</EuiToolTip>
175186
</EuiFlexItem>
176187
</EuiFlexGroup>
177188
);

x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import React from 'react';
99
import { MemoryRouter } from 'react-router-dom';
1010
import { License } from '../../../../../licensing/common/license';
1111
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
12-
import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
12+
import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context';
13+
import {
14+
mockApmPluginContextValue,
15+
MockApmPluginContextWrapper,
16+
} from '../../../context/apm_plugin/mock_apm_plugin_context';
1317
import { LicenseContext } from '../../../context/license/license_context';
1418
import * as hooks from '../../../hooks/use_fetcher';
1519
import * as apmApi from '../../../services/rest/createCallApmApi';
@@ -20,10 +24,22 @@ import {
2024
import { TransactionActionMenu } from './TransactionActionMenu';
2125
import * as Transactions from './__fixtures__/mockData';
2226

27+
function getMockAPMContext({ canSave }: { canSave: boolean }) {
28+
return ({
29+
...mockApmPluginContextValue,
30+
core: {
31+
...mockApmPluginContextValue.core,
32+
application: { capabilities: { apm: { save: canSave }, ml: {} } },
33+
},
34+
} as unknown) as ApmPluginContextValue;
35+
}
36+
2337
function Wrapper({ children }: { children?: React.ReactNode }) {
2438
return (
2539
<MemoryRouter>
26-
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
40+
<MockApmPluginContextWrapper value={getMockAPMContext({ canSave: true })}>
41+
{children}
42+
</MockApmPluginContextWrapper>
2743
</MemoryRouter>
2844
);
2945
}

x-pack/plugins/enterprise_search/public/applications/__mocks__/flash_messages_logic.mock.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,21 @@ export const mockFlashMessagesActions = {
1515
setQueuedMessages: jest.fn(),
1616
clearQueuedMessages: jest.fn(),
1717
};
18+
19+
export const mockFlashMessageHelpers = {
20+
flashAPIErrors: jest.fn(),
21+
setSuccessMessage: jest.fn(),
22+
setErrorMessage: jest.fn(),
23+
setQueuedSuccessMessage: jest.fn(),
24+
setQueuedErrorMessage: jest.fn(),
25+
clearFlashMessages: jest.fn(),
26+
};
27+
28+
jest.mock('../shared/flash_messages', () => ({
29+
...(jest.requireActual('../shared/flash_messages') as object),
30+
...mockFlashMessageHelpers,
31+
FlashMessagesLogic: {
32+
values: mockFlashMessagesValues,
33+
actions: mockFlashMessagesActions,
34+
},
35+
}));

0 commit comments

Comments
 (0)