mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Fleet] Refactor of install package button code (#131015)
* move install integration button to separate component * move install path generation to util function * small refactor * add unit tests * rorder deps to make diff less noisy
This commit is contained in:
parent
349cca2b77
commit
f62530bae9
6 changed files with 243 additions and 102 deletions
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { EuiButtonWithTooltip } from '../../../../../components';
|
||||
|
||||
interface AddIntegrationButtonProps {
|
||||
userCanInstallPackages?: boolean;
|
||||
missingSecurityConfiguration: boolean;
|
||||
packageName: string;
|
||||
href: string;
|
||||
onClick: Function;
|
||||
}
|
||||
|
||||
export function AddIntegrationButton(props: AddIntegrationButtonProps) {
|
||||
const { userCanInstallPackages, missingSecurityConfiguration, packageName, href, onClick } =
|
||||
props;
|
||||
|
||||
const tooltip = !userCanInstallPackages
|
||||
? {
|
||||
content: missingSecurityConfiguration ? (
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.epm.addPackagePolicyButtonSecurityRequiredTooltip"
|
||||
defaultMessage="To add Elastic Agent Integrations, you must have security enabled and have the All privilege for Fleet. Contact your administrator."
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.epm.addPackagePolicyButtonPrivilegesRequiredTooltip"
|
||||
defaultMessage="Elastic Agent Integrations require the All privilege for Fleet and All privilege for Integrations. Contact your administrator."
|
||||
/>
|
||||
),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<EuiButtonWithTooltip
|
||||
fill
|
||||
isDisabled={!userCanInstallPackages}
|
||||
iconType="plusInCircle"
|
||||
href={href}
|
||||
onClick={(e) => onClick(e)}
|
||||
data-test-subj="addIntegrationPolicyButton"
|
||||
tooltip={tooltip}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.epm.addPackagePolicyButtonText"
|
||||
defaultMessage="Add {packageName}"
|
||||
values={{
|
||||
packageName,
|
||||
}}
|
||||
/>
|
||||
</EuiButtonWithTooltip>
|
||||
);
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
export { AddIntegrationButton } from './add_integration_button';
|
||||
export { UpdateIcon } from './update_icon';
|
||||
export { IntegrationAgentPolicyCount } from './integration_agent_policy_count';
|
||||
export { IconPanel, LoadingIconPanel } from './icon_panel';
|
||||
|
|
|
@ -35,26 +35,25 @@ import {
|
|||
useAuthz,
|
||||
usePermissionCheck,
|
||||
} from '../../../../hooks';
|
||||
import {
|
||||
PLUGIN_ID,
|
||||
INTEGRATIONS_PLUGIN_ID,
|
||||
INTEGRATIONS_ROUTING_PATHS,
|
||||
pagePathGetters,
|
||||
} from '../../../../constants';
|
||||
import { INTEGRATIONS_ROUTING_PATHS } from '../../../../constants';
|
||||
import { useGetPackageInfoByKey, useLink, useAgentPolicyContext } from '../../../../hooks';
|
||||
import { pkgKeyFromPackageInfo } from '../../../../services';
|
||||
import type {
|
||||
CreatePackagePolicyRouteState,
|
||||
DetailViewPanelName,
|
||||
PackageInfo,
|
||||
} from '../../../../types';
|
||||
import type { DetailViewPanelName, PackageInfo } from '../../../../types';
|
||||
import { InstallStatus } from '../../../../types';
|
||||
import { Error, EuiButtonWithTooltip, Loading } from '../../../../components';
|
||||
import { Error, Loading } from '../../../../components';
|
||||
import type { WithHeaderLayoutProps } from '../../../../layouts';
|
||||
import { WithHeaderLayout } from '../../../../layouts';
|
||||
import { RELEASE_BADGE_DESCRIPTION, RELEASE_BADGE_LABEL } from '../../components/release_badge';
|
||||
|
||||
import { IntegrationAgentPolicyCount, UpdateIcon, IconPanel, LoadingIconPanel } from './components';
|
||||
import { getInstallPkgRouteOptions } from './utils';
|
||||
|
||||
import {
|
||||
IntegrationAgentPolicyCount,
|
||||
UpdateIcon,
|
||||
IconPanel,
|
||||
LoadingIconPanel,
|
||||
AddIntegrationButton,
|
||||
} from './components';
|
||||
import { AssetsPage } from './assets';
|
||||
import { OverviewPage } from './overview';
|
||||
import { PackagePoliciesPage } from './policies';
|
||||
|
@ -257,7 +256,6 @@ export function Detail() {
|
|||
const handleAddIntegrationPolicyClick = useCallback<ReactEventHandler>(
|
||||
(ev) => {
|
||||
ev.preventDefault();
|
||||
|
||||
// The object below, given to `createHref` is explicitly accessing keys of `location` in order
|
||||
// to ensure that dependencies to this `useCallback` is set correctly (because `location` is mutable)
|
||||
const currentPath = history.createHref({
|
||||
|
@ -266,65 +264,14 @@ export function Detail() {
|
|||
hash,
|
||||
});
|
||||
|
||||
const path = pagePathGetters.add_integration_to_policy({
|
||||
const navigateOptions = getInstallPkgRouteOptions({
|
||||
currentPath,
|
||||
integration,
|
||||
agentPolicyId: agentPolicyIdFromContext,
|
||||
pkgkey,
|
||||
...(integration ? { integration } : {}),
|
||||
...(agentPolicyIdFromContext ? { agentPolicyId: agentPolicyIdFromContext } : {}),
|
||||
})[1];
|
||||
|
||||
let redirectToPath: CreatePackagePolicyRouteState['onSaveNavigateTo'] &
|
||||
CreatePackagePolicyRouteState['onCancelNavigateTo'];
|
||||
let onSaveQueryParams: CreatePackagePolicyRouteState['onSaveQueryParams'];
|
||||
if (agentPolicyIdFromContext) {
|
||||
redirectToPath = [
|
||||
PLUGIN_ID,
|
||||
{
|
||||
path: pagePathGetters.policy_details({
|
||||
policyId: agentPolicyIdFromContext,
|
||||
})[1],
|
||||
},
|
||||
];
|
||||
|
||||
onSaveQueryParams = {
|
||||
showAddAgentHelp: true,
|
||||
openEnrollmentFlyout: true,
|
||||
};
|
||||
} else {
|
||||
redirectToPath = [
|
||||
INTEGRATIONS_PLUGIN_ID,
|
||||
{
|
||||
path: pagePathGetters.integration_details_policies({
|
||||
pkgkey,
|
||||
...(integration ? { integration } : {}),
|
||||
})[1],
|
||||
},
|
||||
];
|
||||
|
||||
onSaveQueryParams = {
|
||||
showAddAgentHelp: { renameKey: 'showAddAgentHelpForPolicyId', policyIdAsValue: true },
|
||||
openEnrollmentFlyout: { renameKey: 'addAgentToPolicyId', policyIdAsValue: true },
|
||||
};
|
||||
}
|
||||
|
||||
const redirectBackRouteState: CreatePackagePolicyRouteState = {
|
||||
onSaveNavigateTo: redirectToPath,
|
||||
onSaveQueryParams,
|
||||
onCancelNavigateTo: [
|
||||
INTEGRATIONS_PLUGIN_ID,
|
||||
{
|
||||
path: pagePathGetters.integration_details_overview({
|
||||
pkgkey,
|
||||
...(integration ? { integration } : {}),
|
||||
})[1],
|
||||
},
|
||||
],
|
||||
onCancelUrl: currentPath,
|
||||
};
|
||||
|
||||
services.application.navigateToApp(PLUGIN_ID, {
|
||||
path,
|
||||
state: redirectBackRouteState,
|
||||
});
|
||||
|
||||
services.application.navigateToApp(...navigateOptions);
|
||||
},
|
||||
[
|
||||
history,
|
||||
|
@ -375,10 +322,8 @@ export function Detail() {
|
|||
{ isDivider: true },
|
||||
{
|
||||
content: (
|
||||
<EuiButtonWithTooltip
|
||||
fill
|
||||
isDisabled={!userCanInstallPackages}
|
||||
iconType="plusInCircle"
|
||||
<AddIntegrationButton
|
||||
userCanInstallPackages={userCanInstallPackages}
|
||||
href={getHref('add_integration_to_policy', {
|
||||
pkgkey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -386,34 +331,10 @@ export function Detail() {
|
|||
? { agentPolicyId: agentPolicyIdFromContext }
|
||||
: {}),
|
||||
})}
|
||||
missingSecurityConfiguration={missingSecurityConfiguration}
|
||||
packageName={integrationInfo?.title || packageInfo.title}
|
||||
onClick={handleAddIntegrationPolicyClick}
|
||||
data-test-subj="addIntegrationPolicyButton"
|
||||
tooltip={
|
||||
!userCanInstallPackages
|
||||
? {
|
||||
content: missingSecurityConfiguration ? (
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.epm.addPackagePolicyButtonSecurityRequiredTooltip"
|
||||
defaultMessage="To add Elastic Agent Integrations, you must have security enabled and have the All privilege for Fleet. Contact your administrator."
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.epm.addPackagePolicyButtonPrivilegesRequiredTooltip"
|
||||
defaultMessage="Elastic Agent Integrations require the All privilege for Fleet and All privilege for Integrations. Contact your administrator."
|
||||
/>
|
||||
),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.epm.addPackagePolicyButtonText"
|
||||
defaultMessage="Add {packageName}"
|
||||
values={{
|
||||
packageName: integrationInfo?.title || packageInfo.title,
|
||||
}}
|
||||
/>
|
||||
</EuiButtonWithTooltip>
|
||||
/>
|
||||
),
|
||||
},
|
||||
].map((item, index) => (
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getInstallPkgRouteOptions } from '.';
|
||||
|
||||
// this is always the same
|
||||
const expectedOnCancelNavigateTo = [
|
||||
'integrations',
|
||||
{
|
||||
path: '/detail/myintegration-1.0.0/overview?integration=myintegration',
|
||||
},
|
||||
];
|
||||
|
||||
describe('getInstallPkgRouteOptions', () => {
|
||||
it('should redirect to integrations app on save if no agentPolicyId present', () => {
|
||||
const opts = {
|
||||
currentPath: 'currentPath',
|
||||
integration: 'myintegration',
|
||||
pkgkey: 'myintegration-1.0.0',
|
||||
};
|
||||
|
||||
const expectedRedirectURl = '/detail/myintegration-1.0.0/policies?integration=myintegration';
|
||||
|
||||
const expectedOptions = {
|
||||
path: '/integrations/myintegration-1.0.0/add-integration/myintegration',
|
||||
state: {
|
||||
onCancelUrl: 'currentPath',
|
||||
onCancelNavigateTo: expectedOnCancelNavigateTo,
|
||||
onSaveNavigateTo: ['integrations', { path: expectedRedirectURl }],
|
||||
onSaveQueryParams: {
|
||||
showAddAgentHelp: { renameKey: 'showAddAgentHelpForPolicyId', policyIdAsValue: true },
|
||||
openEnrollmentFlyout: { renameKey: 'addAgentToPolicyId', policyIdAsValue: true },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(getInstallPkgRouteOptions(opts)).toEqual(['fleet', expectedOptions]);
|
||||
});
|
||||
|
||||
it('should redirect to fleet app on save if agentPolicyId present', () => {
|
||||
const opts = {
|
||||
currentPath: 'currentPath',
|
||||
integration: 'myintegration',
|
||||
pkgkey: 'myintegration-1.0.0',
|
||||
agentPolicyId: '12345',
|
||||
};
|
||||
|
||||
const expectedRedirectURl = '/policies/12345';
|
||||
|
||||
const expectedOptions = {
|
||||
path: '/integrations/myintegration-1.0.0/add-integration/myintegration?policyId=12345',
|
||||
state: {
|
||||
onCancelUrl: 'currentPath',
|
||||
onCancelNavigateTo: expectedOnCancelNavigateTo,
|
||||
onSaveNavigateTo: ['fleet', { path: expectedRedirectURl }],
|
||||
onSaveQueryParams: {
|
||||
showAddAgentHelp: true,
|
||||
openEnrollmentFlyout: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(getInstallPkgRouteOptions(opts)).toEqual(['fleet', expectedOptions]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { CreatePackagePolicyRouteState } from '../../../../../types';
|
||||
import { PLUGIN_ID, INTEGRATIONS_PLUGIN_ID, pagePathGetters } from '../../../../../constants';
|
||||
|
||||
/*
|
||||
* When the install package button is pressed, this fn decides which page to navigate to
|
||||
* by generating the options to be passed to `services.application.navigateToApp`.
|
||||
*/
|
||||
export const getInstallPkgRouteOptions = ({
|
||||
currentPath,
|
||||
integration,
|
||||
agentPolicyId,
|
||||
pkgkey,
|
||||
}: {
|
||||
currentPath: string;
|
||||
integration: string | null;
|
||||
agentPolicyId?: string;
|
||||
pkgkey: string;
|
||||
}): [string, { path: string; state: unknown }] => {
|
||||
const integrationOpts: { integration?: string } = integration ? { integration } : {};
|
||||
const path = pagePathGetters.add_integration_to_policy({
|
||||
pkgkey,
|
||||
...integrationOpts,
|
||||
...(agentPolicyId ? { agentPolicyId } : {}),
|
||||
})[1];
|
||||
|
||||
let redirectToPath: CreatePackagePolicyRouteState['onSaveNavigateTo'] &
|
||||
CreatePackagePolicyRouteState['onCancelNavigateTo'];
|
||||
let onSaveQueryParams: CreatePackagePolicyRouteState['onSaveQueryParams'];
|
||||
if (agentPolicyId) {
|
||||
redirectToPath = [
|
||||
PLUGIN_ID,
|
||||
{
|
||||
path: pagePathGetters.policy_details({
|
||||
policyId: agentPolicyId,
|
||||
})[1],
|
||||
},
|
||||
];
|
||||
|
||||
onSaveQueryParams = {
|
||||
showAddAgentHelp: true,
|
||||
openEnrollmentFlyout: true,
|
||||
};
|
||||
} else {
|
||||
redirectToPath = [
|
||||
INTEGRATIONS_PLUGIN_ID,
|
||||
{
|
||||
path: pagePathGetters.integration_details_policies({
|
||||
pkgkey,
|
||||
...integrationOpts,
|
||||
})[1],
|
||||
},
|
||||
];
|
||||
|
||||
onSaveQueryParams = {
|
||||
showAddAgentHelp: { renameKey: 'showAddAgentHelpForPolicyId', policyIdAsValue: true },
|
||||
openEnrollmentFlyout: { renameKey: 'addAgentToPolicyId', policyIdAsValue: true },
|
||||
};
|
||||
}
|
||||
|
||||
const state: CreatePackagePolicyRouteState = {
|
||||
onSaveNavigateTo: redirectToPath,
|
||||
onSaveQueryParams,
|
||||
onCancelNavigateTo: [
|
||||
INTEGRATIONS_PLUGIN_ID,
|
||||
{
|
||||
path: pagePathGetters.integration_details_overview({
|
||||
pkgkey,
|
||||
...integrationOpts,
|
||||
})[1],
|
||||
},
|
||||
],
|
||||
onCancelUrl: currentPath,
|
||||
};
|
||||
|
||||
return [PLUGIN_ID, { path, state }];
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export { getInstallPkgRouteOptions } from './get_install_route_options';
|
Loading…
Add table
Add a link
Reference in a new issue