diff --git a/x-pack/plugins/apm/common/custom_link/index.ts b/x-pack/plugins/apm/common/custom_link/index.ts index bc0ffefd79c4da..00162f50d889a7 100644 --- a/x-pack/plugins/apm/common/custom_link/index.ts +++ b/x-pack/plugins/apm/common/custom_link/index.ts @@ -12,3 +12,11 @@ export const INVALID_LICENSE = i18n.translate( "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.", } ); + +export const NO_PERMISSION_LABEL = i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.noPermissionTooltipLabel', + { + defaultMessage: + "Your user role doesn't have permissions to create custom links", + } +); diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx index 3b4c127aab1e5c..0a3d8f8b1e510d 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx @@ -6,24 +6,14 @@ import { EuiButton, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { NO_PERMISSION_LABEL } from '../../../../../../common/custom_link'; import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context'; export function CreateCustomLinkButton({ onClick }: { onClick: () => void }) { const { core } = useApmPluginContext(); const canSave = core.application.capabilities.apm.save; return ( - + - {children} + + {children} + ); } diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx index 36b370b4069aea..0fe3c461a49372 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx @@ -12,6 +12,8 @@ import { EuiIcon, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { NO_PERMISSION_LABEL } from '../../../../../common/custom_link'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { APMLink } from '../../Links/apm/APMLink'; export function CustomLinkToolbar({ @@ -21,6 +23,9 @@ export function CustomLinkToolbar({ onClickCreate: () => void; showCreateButton?: boolean; }) { + const { core } = useApmPluginContext(); + const canSave = !!core.application.capabilities.apm.save; + return ( @@ -42,17 +47,20 @@ export function CustomLinkToolbar({ {showCreateButton && ( - - - {i18n.translate('xpack.apm.customLink.buttom.create.title', { - defaultMessage: 'Create', - })} - - + + + + {i18n.translate('xpack.apm.customLink.buttom.create.title', { + defaultMessage: 'Create', + })} + + + )} diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx index a32302d2464234..ae22718af8b571 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx @@ -13,6 +13,9 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; +import { EuiToolTip } from '@elastic/eui'; +import { NO_PERMISSION_LABEL } from '../../../../../common/custom_link'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { ActionMenuDivider, Section, @@ -147,6 +150,9 @@ function BottomSection({ toggleShowAll: () => void; onClickCreate: () => void; }) { + const { core } = useApmPluginContext(); + const canSave = !!core.application.capabilities.apm.save; + if (status === FETCH_STATUS.LOADING) { return ; } @@ -154,7 +160,7 @@ function BottomSection({ // render empty prompt if there are no custom links if (isEmpty(customLinks)) { return ( - + {i18n.translate('xpack.apm.customLink.empty', { @@ -163,15 +169,20 @@ function BottomSection({ })} - - {i18n.translate('xpack.apm.customLink.buttom.create', { - defaultMessage: 'Create custom link', - })} - + + + + + {i18n.translate('xpack.apm.customLink.buttom.create', { + defaultMessage: 'Create custom link', + })} + + ); diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx index 6ff395db594f13..48c863b4604820 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx @@ -9,7 +9,11 @@ import React from 'react'; import { MemoryRouter } from 'react-router-dom'; import { License } from '../../../../../licensing/common/license'; import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; -import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; +import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; +import { + mockApmPluginContextValue, + MockApmPluginContextWrapper, +} from '../../../context/apm_plugin/mock_apm_plugin_context'; import { LicenseContext } from '../../../context/license/license_context'; import * as hooks from '../../../hooks/use_fetcher'; import * as apmApi from '../../../services/rest/createCallApmApi'; @@ -20,10 +24,22 @@ import { import { TransactionActionMenu } from './TransactionActionMenu'; import * as Transactions from './__fixtures__/mockData'; +function getMockAPMContext({ canSave }: { canSave: boolean }) { + return ({ + ...mockApmPluginContextValue, + core: { + ...mockApmPluginContextValue.core, + application: { capabilities: { apm: { save: canSave }, ml: {} } }, + }, + } as unknown) as ApmPluginContextValue; +} + function Wrapper({ children }: { children?: React.ReactNode }) { return ( - {children} + + {children} + ); }