From 88caa798a9336e16541681fd4e2cfadbad35432a Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Mon, 14 Sep 2020 20:59:21 -0400 Subject: [PATCH] [SECURITY_SOLUTION] Task/hostname policy response ux updates (#76444) --- .../components/formatted_date/index.tsx | 18 +++++++++ .../pages/endpoint_hosts/store/selectors.ts | 6 +++ .../view/details/endpoint_details.tsx | 6 +-- .../endpoint_hosts/view/details/index.tsx | 12 +++++- .../pages/endpoint_hosts/view/index.test.tsx | 4 +- .../pages/endpoint_hosts/view/index.tsx | 40 ++++++++++++------- .../apps/endpoint/endpoint_list.ts | 16 ++++---- 7 files changed, 72 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx index 687d2a36da610..38c2a8583f7e9 100644 --- a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx @@ -22,6 +22,24 @@ export const PreferenceFormattedDate = React.memo<{ dateFormat?: string; value: PreferenceFormattedDate.displayName = 'PreferenceFormattedDate'; +export const PreferenceFormattedDateFromPrimitive = ({ + value, +}: { + value?: string | number | null; +}) => { + if (value == null) { + return getOrEmptyTagFromValue(value); + } + const maybeDate = getMaybeDate(value); + if (!maybeDate.isValid()) { + return getOrEmptyTagFromValue(value); + } + const date = maybeDate.toDate(); + return ; +}; + +PreferenceFormattedDateFromPrimitive.displayName = 'PreferenceFormattedDateFromPrimitive'; + /** * This function may be passed to `Array.find()` to locate the `P1DT` * configuration (sub) setting, a string array that contains two entries diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts index 852bc9791fc90..a3eee8063d6f7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts @@ -72,6 +72,12 @@ export const patternsError = (state: Immutable) => state.patterns const detailsPolicyAppliedResponse = (state: Immutable) => state.policyResponse && state.policyResponse.Endpoint.policy.applied; +/** + * Returns the policy response timestamp from the endpoint after a user modifies a policy. + */ +export const policyResponseTimestamp = (state: Immutable) => + state.policyResponse && state.policyResponse['@timestamp']; + /** * Returns the response configurations from the endpoint after a user modifies a policy. */ diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx index b76b7e51b2c1b..47f4fbb8830ae 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx @@ -125,7 +125,7 @@ export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => return [ { title: i18n.translate('xpack.securitySolution.endpoint.details.policy', { - defaultMessage: 'Integration', + defaultMessage: 'Integration Policy', }), description: ( <> @@ -140,7 +140,7 @@ export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => }, { title: i18n.translate('xpack.securitySolution.endpoint.details.policyStatus', { - defaultMessage: 'Configuration response', + defaultMessage: 'Policy Response', }), description: ( diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx index a37ddd0bd61d9..43d3b39474fc7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx @@ -32,6 +32,7 @@ import { policyResponseFailedOrWarningActionCount, policyResponseError, policyResponseLoading, + policyResponseTimestamp, } from '../../store/selectors'; import { EndpointDetails } from './endpoint_details'; import { PolicyResponse } from './policy_response'; @@ -41,6 +42,7 @@ import { useNavigateByRouterEventHandler } from '../../../../../common/hooks/end import { getEndpointListPath } from '../../../../common/routing'; import { SecurityPageName } from '../../../../../app/types'; import { useFormatUrl } from '../../../../../common/components/link_to'; +import { PreferenceFormattedDateFromPrimitive } from '../../../../../common/components/formatted_date'; export const EndpointDetailsFlyout = memo(() => { const history = useHistory(); @@ -122,6 +124,7 @@ const PolicyResponseFlyoutPanel = memo<{ const loading = useEndpointSelector(policyResponseLoading); const error = useEndpointSelector(policyResponseError); const { formatUrl } = useFormatUrl(SecurityPageName.administration); + const responseTimestamp = useEndpointSelector(policyResponseTimestamp); const [detailsUri, detailsRoutePath] = useMemo( () => [ formatUrl( @@ -161,16 +164,21 @@ const PolicyResponseFlyoutPanel = memo<{

+ + + + + {error && ( } /> diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 14167f25d5b90..2bdf17b806079 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -510,7 +510,7 @@ describe('when on the list page', () => { const renderResult = await renderAndWaitForData(); const linkToReassign = await renderResult.findByTestId('endpointDetailsLinkToIngest'); expect(linkToReassign).not.toBeNull(); - expect(linkToReassign.textContent).toEqual('Reassign Configuration'); + expect(linkToReassign.textContent).toEqual('Reassign Policy'); expect(linkToReassign.getAttribute('href')).toEqual( `/app/ingestManager#/fleet/agents/${agentId}/activity?openReassignFlyout=true` ); @@ -572,7 +572,7 @@ describe('when on the list page', () => { it('should include the sub-panel title', async () => { expect( (await renderResult.findByTestId('endpointDetailsPolicyResponseFlyoutTitle')).textContent - ).toBe('Configuration Response'); + ).toBe('Policy Response'); }); it('should show a configuration section for each protection', async () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 166f1660bf3d6..ecee2bee0c58b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -270,17 +270,20 @@ export const EndpointList = () => { ); const toRouteUrl = formatUrl(toRoutePath); return ( - + + + ); }, }, { field: 'host_status', + width: '9%', name: i18n.translate('xpack.securitySolution.endpoint.list.hostStatus', { defaultMessage: 'Agent Status', }), @@ -303,27 +306,31 @@ export const EndpointList = () => { }, { field: 'metadata.Endpoint.policy.applied', + width: '15%', name: i18n.translate('xpack.securitySolution.endpoint.list.policy', { - defaultMessage: 'Integration', + defaultMessage: 'Integration Policy', }), truncateText: true, // eslint-disable-next-line react/display-name render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied']) => { return ( - - {policy.name} - + + + {policy.name} + + ); }, }, { field: 'metadata.Endpoint.policy.applied', + width: '9%', name: i18n.translate('xpack.securitySolution.endpoint.list.policyStatus', { - defaultMessage: 'Configuration Status', + defaultMessage: 'Policy Status', }), render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied'], item: HostInfo) => { const toRoutePath = getEndpointDetailsPath({ @@ -350,6 +357,7 @@ export const EndpointList = () => { }, { field: 'metadata.host.os.name', + width: '10%', name: i18n.translate('xpack.securitySolution.endpoint.list.os', { defaultMessage: 'Operating System', }), @@ -375,6 +383,7 @@ export const EndpointList = () => { }, { field: 'metadata.agent.version', + width: '5%', name: i18n.translate('xpack.securitySolution.endpoint.list.endpointVersion', { defaultMessage: 'Version', }), @@ -394,6 +403,7 @@ export const EndpointList = () => { }, { field: '', + width: '5%', name: i18n.translate('xpack.securitySolution.endpoint.list.actions', { defaultMessage: 'Actions', }), diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index b0b8d14108004..7485e5db20478 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -22,8 +22,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', @@ -188,8 +188,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'OS', 'Last Seen', 'Alerts', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'IP Address', 'Hostname', 'Sensor Version', @@ -236,8 +236,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', @@ -267,8 +267,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version',