-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[7.x] [Security Solution][Resolver] standardize resolver panel compon…
- Loading branch information
1 parent
e07b87f
commit d14c436
Showing
8 changed files
with
871 additions
and
871 deletions.
There are no files selected for viewing
90 changes: 45 additions & 45 deletions
90
...esolver/view/panels/process_cube_icon.tsx → ...resolver/view/panels/cube_for_process.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,45 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { memo } from 'react'; | ||
import { useResolverTheme } from '../assets'; | ||
|
||
/** | ||
* During user testing, one user indicated they wanted to see stronger visual relationships between | ||
* Nodes on the graph and what's in the table. Using the same symbol in both places (as below) could help with that. | ||
*/ | ||
export const CubeForProcess = memo(function CubeForProcess({ | ||
isProcessTerminated, | ||
}: { | ||
isProcessTerminated: boolean; | ||
}) { | ||
const { cubeAssetsForNode } = useResolverTheme(); | ||
const { cubeSymbol, descriptionText } = cubeAssetsForNode(isProcessTerminated, false); | ||
|
||
return ( | ||
<> | ||
<svg | ||
style={{ position: 'relative', top: '0.4em', marginRight: '.25em' }} | ||
className="table-process-icon" | ||
width="1.5em" | ||
height="1.5em" | ||
viewBox="0 0 1 1" | ||
> | ||
<desc>{descriptionText}</desc> | ||
<use | ||
role="presentation" | ||
xlinkHref={cubeSymbol} | ||
x={0} | ||
y={0} | ||
width={1} | ||
height={1} | ||
opacity="1" | ||
className="cube" | ||
/> | ||
</svg> | ||
</> | ||
); | ||
}); | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { memo } from 'react'; | ||
import { useResolverTheme } from '../assets'; | ||
|
||
/** | ||
* During user testing, one user indicated they wanted to see stronger visual relationships between | ||
* Nodes on the graph and what's in the table. Using the same symbol in both places (as below) could help with that. | ||
*/ | ||
export const CubeForProcess = memo(function CubeForProcess({ | ||
isProcessTerminated, | ||
}: { | ||
isProcessTerminated: boolean; | ||
}) { | ||
const { cubeAssetsForNode } = useResolverTheme(); | ||
const { cubeSymbol, descriptionText } = cubeAssetsForNode(isProcessTerminated, false); | ||
|
||
return ( | ||
<> | ||
<svg | ||
style={{ position: 'relative', top: '0.4em', marginRight: '.25em' }} | ||
className="table-process-icon" | ||
width="1.5em" | ||
height="1.5em" | ||
viewBox="0 0 1 1" | ||
> | ||
<desc>{descriptionText}</desc> | ||
<use | ||
role="presentation" | ||
xlinkHref={cubeSymbol} | ||
x={0} | ||
y={0} | ||
width={1} | ||
height={1} | ||
opacity="1" | ||
className="cube" | ||
/> | ||
</svg> | ||
</> | ||
); | ||
}); |
288 changes: 144 additions & 144 deletions
288
...w/panels/panel_content_related_counts.tsx → .../view/panels/event_counts_for_process.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,144 +1,144 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { memo, useMemo } from 'react'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { EuiBasicTableColumn, EuiButtonEmpty, EuiSpacer, EuiInMemoryTable } from '@elastic/eui'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { CrumbInfo, StyledBreadcrumbs } from './panel_content_utilities'; | ||
|
||
import * as event from '../../../../common/endpoint/models/event'; | ||
import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; | ||
|
||
/** | ||
* This view gives counts for all the related events of a process grouped by related event type. | ||
* It should look something like: | ||
* | ||
* | Count | Event Type | | ||
* | :--------------------- | :------------------------- | | ||
* | 5 | DNS | | ||
* | 12 | Registry | | ||
* | 2 | Network | | ||
* | ||
*/ | ||
export const EventCountsForProcess = memo(function EventCountsForProcess({ | ||
processEvent, | ||
pushToQueryParams, | ||
relatedStats, | ||
}: { | ||
processEvent: ResolverEvent; | ||
pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; | ||
relatedStats: ResolverNodeStats; | ||
}) { | ||
interface EventCountsTableView { | ||
name: string; | ||
count: number; | ||
} | ||
|
||
const relatedEventsState = { stats: relatedStats.events.byCategory }; | ||
const processName = processEvent && event.eventName(processEvent); | ||
const processEntityId = event.entityId(processEvent); | ||
/** | ||
* totalCount: This will reflect the aggregated total by category for all related events | ||
* e.g. [dns,file],[dns,file],[registry] will have an aggregate total of 5. This is to keep the | ||
* total number consistent with the "broken out" totals we see elsewhere in the app. | ||
* E.g. on the rleated list by type, the above would show as: | ||
* 2 dns | ||
* 2 file | ||
* 1 registry | ||
* So it would be extremely disorienting to show the user a "3" above that as a total. | ||
*/ | ||
const totalCount = Object.values(relatedStats.events.byCategory).reduce( | ||
(sum, val) => sum + val, | ||
0 | ||
); | ||
const eventsString = i18n.translate( | ||
'xpack.securitySolution.endpoint.resolver.panel.processEventCounts.events', | ||
{ | ||
defaultMessage: 'Events', | ||
} | ||
); | ||
const crumbs = useMemo(() => { | ||
return [ | ||
{ | ||
text: eventsString, | ||
onClick: () => { | ||
pushToQueryParams({ crumbId: '', crumbEvent: '' }); | ||
}, | ||
}, | ||
{ | ||
text: processName, | ||
onClick: () => { | ||
pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); | ||
}, | ||
}, | ||
{ | ||
text: ( | ||
<> | ||
<FormattedMessage | ||
id="xpack.securitySolution.endpoint.resolver.panel.relatedCounts.numberOfEventsInCrumb" | ||
values={{ totalCount }} | ||
defaultMessage="{totalCount} Events" | ||
/> | ||
</> | ||
), | ||
onClick: () => { | ||
pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); | ||
}, | ||
}, | ||
]; | ||
}, [processName, totalCount, processEntityId, pushToQueryParams, eventsString]); | ||
const rows = useMemo(() => { | ||
return Object.entries(relatedEventsState.stats).map( | ||
([eventType, count]): EventCountsTableView => { | ||
return { | ||
name: eventType, | ||
count, | ||
}; | ||
} | ||
); | ||
}, [relatedEventsState]); | ||
const columns = useMemo<Array<EuiBasicTableColumn<EventCountsTableView>>>( | ||
() => [ | ||
{ | ||
field: 'count', | ||
name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.count', { | ||
defaultMessage: 'Count', | ||
}), | ||
width: '20%', | ||
sortable: true, | ||
}, | ||
{ | ||
field: 'name', | ||
name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.eventType', { | ||
defaultMessage: 'Event Type', | ||
}), | ||
width: '80%', | ||
sortable: true, | ||
render(name: string) { | ||
return ( | ||
<EuiButtonEmpty | ||
onClick={() => { | ||
pushToQueryParams({ crumbId: event.entityId(processEvent), crumbEvent: name }); | ||
}} | ||
> | ||
{name} | ||
</EuiButtonEmpty> | ||
); | ||
}, | ||
}, | ||
], | ||
[pushToQueryParams, processEvent] | ||
); | ||
return ( | ||
<> | ||
<StyledBreadcrumbs breadcrumbs={crumbs} /> | ||
<EuiSpacer size="l" /> | ||
<EuiInMemoryTable<EventCountsTableView> items={rows} columns={columns} sorting /> | ||
</> | ||
); | ||
}); | ||
EventCountsForProcess.displayName = 'EventCountsForProcess'; | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { memo, useMemo } from 'react'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { EuiBasicTableColumn, EuiButtonEmpty, EuiSpacer, EuiInMemoryTable } from '@elastic/eui'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { CrumbInfo, StyledBreadcrumbs } from './panel_content_utilities'; | ||
|
||
import * as event from '../../../../common/endpoint/models/event'; | ||
import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; | ||
|
||
/** | ||
* This view gives counts for all the related events of a process grouped by related event type. | ||
* It should look something like: | ||
* | ||
* | Count | Event Type | | ||
* | :--------------------- | :------------------------- | | ||
* | 5 | DNS | | ||
* | 12 | Registry | | ||
* | 2 | Network | | ||
* | ||
*/ | ||
export const EventCountsForProcess = memo(function EventCountsForProcess({ | ||
processEvent, | ||
pushToQueryParams, | ||
relatedStats, | ||
}: { | ||
processEvent: ResolverEvent; | ||
pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; | ||
relatedStats: ResolverNodeStats; | ||
}) { | ||
interface EventCountsTableView { | ||
name: string; | ||
count: number; | ||
} | ||
|
||
const relatedEventsState = { stats: relatedStats.events.byCategory }; | ||
const processName = processEvent && event.eventName(processEvent); | ||
const processEntityId = event.entityId(processEvent); | ||
/** | ||
* totalCount: This will reflect the aggregated total by category for all related events | ||
* e.g. [dns,file],[dns,file],[registry] will have an aggregate total of 5. This is to keep the | ||
* total number consistent with the "broken out" totals we see elsewhere in the app. | ||
* E.g. on the rleated list by type, the above would show as: | ||
* 2 dns | ||
* 2 file | ||
* 1 registry | ||
* So it would be extremely disorienting to show the user a "3" above that as a total. | ||
*/ | ||
const totalCount = Object.values(relatedStats.events.byCategory).reduce( | ||
(sum, val) => sum + val, | ||
0 | ||
); | ||
const eventsString = i18n.translate( | ||
'xpack.securitySolution.endpoint.resolver.panel.processEventCounts.events', | ||
{ | ||
defaultMessage: 'Events', | ||
} | ||
); | ||
const crumbs = useMemo(() => { | ||
return [ | ||
{ | ||
text: eventsString, | ||
onClick: () => { | ||
pushToQueryParams({ crumbId: '', crumbEvent: '' }); | ||
}, | ||
}, | ||
{ | ||
text: processName, | ||
onClick: () => { | ||
pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); | ||
}, | ||
}, | ||
{ | ||
text: ( | ||
<> | ||
<FormattedMessage | ||
id="xpack.securitySolution.endpoint.resolver.panel.relatedCounts.numberOfEventsInCrumb" | ||
values={{ totalCount }} | ||
defaultMessage="{totalCount} Events" | ||
/> | ||
</> | ||
), | ||
onClick: () => { | ||
pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); | ||
}, | ||
}, | ||
]; | ||
}, [processName, totalCount, processEntityId, pushToQueryParams, eventsString]); | ||
const rows = useMemo(() => { | ||
return Object.entries(relatedEventsState.stats).map( | ||
([eventType, count]): EventCountsTableView => { | ||
return { | ||
name: eventType, | ||
count, | ||
}; | ||
} | ||
); | ||
}, [relatedEventsState]); | ||
const columns = useMemo<Array<EuiBasicTableColumn<EventCountsTableView>>>( | ||
() => [ | ||
{ | ||
field: 'count', | ||
name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.count', { | ||
defaultMessage: 'Count', | ||
}), | ||
width: '20%', | ||
sortable: true, | ||
}, | ||
{ | ||
field: 'name', | ||
name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.eventType', { | ||
defaultMessage: 'Event Type', | ||
}), | ||
width: '80%', | ||
sortable: true, | ||
render(name: string) { | ||
return ( | ||
<EuiButtonEmpty | ||
onClick={() => { | ||
pushToQueryParams({ crumbId: event.entityId(processEvent), crumbEvent: name }); | ||
}} | ||
> | ||
{name} | ||
</EuiButtonEmpty> | ||
); | ||
}, | ||
}, | ||
], | ||
[pushToQueryParams, processEvent] | ||
); | ||
return ( | ||
<> | ||
<StyledBreadcrumbs breadcrumbs={crumbs} /> | ||
<EuiSpacer size="l" /> | ||
<EuiInMemoryTable<EventCountsTableView> items={rows} columns={columns} sorting /> | ||
</> | ||
); | ||
}); | ||
EventCountsForProcess.displayName = 'EventCountsForProcess'; |
Oops, something went wrong.