Skip to content

Commit

Permalink
[Fleet] Add Integration Policy Page Improvements (#114556) (#114762)
Browse files Browse the repository at this point in the history
* Show add agent link instead of 0 agents

* Add popover

* open and close popover

* fill button

* add popover to agent cell

* PR feedback

* only add offset to props if it's provided

* make code clearer

* Update x-pack/plugins/fleet/public/components/add_agent_help_popover.tsx

Co-authored-by: Dave Snider <dave.snider@gmail.com>

* remove unused import

* whitespace

Co-authored-by: Dave Snider <dave.snider@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Mark Hopkin <mark.hopkin@elastic.co>
Co-authored-by: Dave Snider <dave.snider@gmail.com>
  • Loading branch information
3 people authored Oct 13, 2021
1 parent 9540d0b commit 6fea49f
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ import { Redirect, useRouteMatch, Switch, Route, useHistory, useLocation } from
import { i18n } from '@kbn/i18n';
import { FormattedMessage, FormattedDate } from '@kbn/i18n/react';
import {
EuiButtonEmpty,
EuiDescriptionList,
EuiDescriptionListDescription,
EuiDescriptionListTitle,
EuiFlexGroup,
EuiFlexItem,
EuiI18nNumber,
EuiIconTip,
EuiTitle,
EuiText,
EuiLink,
EuiPortal,
EuiSpacer,
EuiButtonEmpty,
EuiI18nNumber,
EuiDescriptionList,
EuiDescriptionListTitle,
EuiDescriptionListDescription,
EuiText,
EuiTitle,
} from '@elastic/eui';
import type { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab';
import styled from 'styled-components';
Expand All @@ -36,7 +38,7 @@ import {
useFleetStatus,
useIntraAppState,
} from '../../../hooks';
import { Loading, Error } from '../../../components';
import { Loading, Error, AgentEnrollmentFlyout, AddAgentHelpPopover } from '../../../components';
import { WithHeaderLayout } from '../../../layouts';
import { LinkedAgentCount, AgentPolicyActionMenu } from '../components';

Expand All @@ -58,16 +60,24 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
const agentPolicyRequest = useGetOneAgentPolicy(policyId);
const agentPolicy = agentPolicyRequest.data ? agentPolicyRequest.data.item : null;
const { isLoading, error, sendRequest: refreshAgentPolicy } = agentPolicyRequest;
const queryParams = new URLSearchParams(useLocation().search);
const openEnrollmentFlyoutOpenByDefault = queryParams.get('openEnrollmentFlyout') === 'true';
const openAddAgentHelpPopoverOpenByDefault = queryParams.get('showAddAgentHelp') === 'true';
const [redirectToAgentPolicyList] = useState<boolean>(false);
const [isEnrollmentFlyoutOpen, setIsEnrollmentFlyoutOpen] = useState<boolean>(
openEnrollmentFlyoutOpenByDefault
);
const [isAddAgentHelpPopoverOpen, setIsAddAgentHelpPopoverOpen] = useState<boolean>(
openAddAgentHelpPopoverOpenByDefault
);
const agentStatusRequest = useGetAgentStatus(policyId);
const { refreshAgentStatus } = agentStatusRequest;
const {
application: { navigateToApp },
} = useStartServices();
const routeState = useIntraAppState<AgentPolicyDetailsDeployAgentAction>();
const agentStatus = agentStatusRequest.data?.results;
const queryParams = new URLSearchParams(useLocation().search);
const openEnrollmentFlyoutOpenByDefault = queryParams.get('openEnrollmentFlyout') === 'true';

const { isReady: isFleetReady } = useFleetStatus();

const headerLeftContent = useMemo(
Expand Down Expand Up @@ -138,6 +148,25 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
[getHref, isLoading, agentPolicy, policyId]
);

const onCancelEnrollment = useMemo(() => {
if (routeState && routeState.onDoneNavigateTo && isFleetReady) {
const [appId, options] = routeState.onDoneNavigateTo;
return () => navigateToApp(appId, options);
}

return undefined;
}, [isFleetReady, navigateToApp, routeState]);

const addAgentLink = (
<EuiLink
onClick={() => {
setIsAddAgentHelpPopoverOpen(false);
setIsEnrollmentFlyoutOpen(true);
}}
>
<FormattedMessage id="xpack.fleet.policyDetails.addAgentButton" defaultMessage="Add agent" />
</EuiLink>
);
const headerRightContent = useMemo(
() =>
agentPolicy ? (
Expand Down Expand Up @@ -168,15 +197,25 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
{ isDivider: true },
{
label: i18n.translate('xpack.fleet.policyDetails.summary.usedBy', {
defaultMessage: 'Used by',
defaultMessage: 'Agents',
}),
content: (
<LinkedAgentCount
count={(agentStatus && agentStatus.total) || 0}
agentPolicyId={(agentPolicy && agentPolicy.id) || ''}
showAgentText
/>
),
content:
agentStatus && agentStatus!.total ? (
<LinkedAgentCount
count={agentStatus.total}
agentPolicyId={(agentPolicy && agentPolicy.id) || ''}
showAgentText
/>
) : (
<AddAgentHelpPopover
button={addAgentLink}
isOpen={isAddAgentHelpPopoverOpen}
offset={15}
closePopover={() => {
setIsAddAgentHelpPopoverOpen(false);
}}
/>
),
},
{ isDivider: true },
{
Expand All @@ -203,16 +242,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
onCopySuccess={(newAgentPolicy: AgentPolicy) => {
history.push(getPath('policy_details', { policyId: newAgentPolicy.id }));
}}
enrollmentFlyoutOpenByDefault={openEnrollmentFlyoutOpenByDefault}
onCancelEnrollment={
routeState && routeState.onDoneNavigateTo && isFleetReady
? () =>
navigateToApp(
routeState.onDoneNavigateTo![0],
routeState.onDoneNavigateTo![1]
)
: undefined
}
onCancelEnrollment={onCancelEnrollment}
/>
),
},
Expand All @@ -237,7 +267,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
</EuiFlexGroup>
) : undefined,
/* eslint-disable-next-line react-hooks/exhaustive-deps */
[agentPolicy, policyId, agentStatus]
[agentPolicy, policyId, agentStatus, isAddAgentHelpPopoverOpen]
);

const headerTabs = useMemo(() => {
Expand Down Expand Up @@ -303,8 +333,28 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
);
}

return <AgentPolicyDetailsContent agentPolicy={agentPolicy} />;
}, [agentPolicy, policyId, error, isLoading, redirectToAgentPolicyList]);
return (
<>
{isEnrollmentFlyoutOpen && (
<EuiPortal>
<AgentEnrollmentFlyout
agentPolicy={agentPolicy}
onClose={onCancelEnrollment || (() => setIsEnrollmentFlyoutOpen(false))}
/>
</EuiPortal>
)}
<AgentPolicyDetailsContent agentPolicy={agentPolicy} />;
</>
);
}, [
redirectToAgentPolicyList,
isLoading,
error,
agentPolicy,
isEnrollmentFlyoutOpen,
onCancelEnrollment,
policyId,
]);

return (
<AgentPolicyRefreshContext.Provider value={{ refresh: refreshAgentPolicy }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ import { createIntegrationsTestRendererMock } from '../../../../../../../../mock

import { PackagePolicyAgentsCell } from './package_policy_agents_cell';

function renderCell({ agentCount = 0, agentPolicyId = '123', onAddAgent = () => {} }) {
function renderCell({
agentCount = 0,
agentPolicyId = '123',
onAddAgent = () => {},
hasHelpPopover = false,
}) {
const renderer = createIntegrationsTestRendererMock();

return renderer.render(
<PackagePolicyAgentsCell
agentCount={agentCount}
agentPolicyId={agentPolicyId}
onAddAgent={onAddAgent}
hasHelpPopover={hasHelpPopover}
/>
);
}
Expand All @@ -40,4 +46,25 @@ describe('PackagePolicyAgentsCell', () => {
expect(utils.queryByText('9999')).toBeInTheDocument();
});
});

test('it should display help popover if count is 0 and hasHelpPopover=true', async () => {
const utils = renderCell({ agentCount: 0, hasHelpPopover: true });
await act(async () => {
expect(utils.queryByText('9999')).not.toBeInTheDocument();
expect(utils.queryByText('Add agent')).toBeInTheDocument();
expect(
utils.container.querySelector('[data-test-subj="addAgentHelpPopover"]')
).toBeInTheDocument();
});
});
test('it should not display help popover if count is > 0 and hasHelpPopover=true', async () => {
const utils = renderCell({ agentCount: 9999, hasHelpPopover: true });
await act(async () => {
expect(utils.queryByText('9999')).toBeInTheDocument();
expect(utils.queryByText('Add agent')).not.toBeInTheDocument();
expect(
utils.container.querySelector('[data-test-subj="addAgentHelpPopover"]')
).not.toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,43 @@
* 2.0.
*/

import React from 'react';
import React, { useState } from 'react';

import { EuiButton } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

import { LinkedAgentCount } from '../../../../../../components';
import { LinkedAgentCount, AddAgentHelpPopover } from '../../../../../../components';

const AddAgentButton = ({ onAddAgent }: { onAddAgent: () => void }) => (
<EuiButton iconType="plusInCircle" data-test-subj="addAgentButton" onClick={onAddAgent}>
<FormattedMessage
id="xpack.fleet.epm.packageDetails.integrationList.addAgent"
defaultMessage="Add agent"
/>
</EuiButton>
);

const AddAgentButtonWithPopover = ({ onAddAgent }: { onAddAgent: () => void }) => {
const button = <AddAgentButton onAddAgent={onAddAgent} />;
const [isHelpOpen, setIsHelpOpen] = useState<boolean>(true);
return (
<AddAgentHelpPopover
button={button}
isOpen={isHelpOpen}
closePopover={() => setIsHelpOpen(false)}
/>
);
};

export const PackagePolicyAgentsCell = ({
agentPolicyId,
agentCount = 0,
onAddAgent,
hasHelpPopover = false,
}: {
agentPolicyId: string;
agentCount?: number;
hasHelpPopover?: boolean;
onAddAgent: () => void;
}) => {
if (agentCount > 0) {
Expand All @@ -31,12 +54,9 @@ export const PackagePolicyAgentsCell = ({
);
}

return (
<EuiButton iconType="plusInCircle" data-test-subj="addAgentButton" onClick={onAddAgent}>
<FormattedMessage
id="xpack.fleet.epm.packageDetails.integrationList.addAgent"
defaultMessage="Add agent"
/>
</EuiButton>
);
if (!hasHelpPopover) {
return <AddAgentButton onAddAgent={onAddAgent} />;
}

return <AddAgentButtonWithPopover onAddAgent={onAddAgent} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
() => queryParams.get('addAgentToPolicyId'),
[queryParams]
);
const showAddAgentHelpForPolicyId = useMemo(
() => queryParams.get('showAddAgentHelpForPolicyId'),
[queryParams]
);
const [flyoutOpenForPolicyId, setFlyoutOpenForPolicyId] = useState<string | null>(
agentPolicyIdFromParams
);
Expand Down Expand Up @@ -294,6 +298,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
agentPolicyId={agentPolicy.id}
agentCount={agentPolicy.agents}
onAddAgent={() => setFlyoutOpenForPolicyId(agentPolicy.id)}
hasHelpPopover={showAddAgentHelpForPolicyId === agentPolicy.id}
/>
);
},
Expand Down Expand Up @@ -321,7 +326,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
},
},
],
[getHref, viewDataStep]
[getHref, showAddAgentHelpForPolicyId, viewDataStep]
);

const noItemsMessage = useMemo(() => {
Expand Down
Loading

0 comments on commit 6fea49f

Please sign in to comment.