diff --git a/public/pages/Correlations/components/FilterGroup.tsx b/public/pages/Correlations/components/FilterGroup.tsx index 889a0b8a1..661525e81 100644 --- a/public/pages/Correlations/components/FilterGroup.tsx +++ b/public/pages/Correlations/components/FilterGroup.tsx @@ -13,7 +13,7 @@ import { EuiFieldSearch, FilterChecked, EuiPopoverFooter, - EuiButtonEmpty, + EuiButtonGroup, } from '@elastic/eui'; export type FilterItem = { @@ -31,6 +31,19 @@ export interface LogTypeFilterGroupProps { setItems: (items: FilterItem[]) => void; } +type SelectionToggleOptionIds = 'select_all' | 'deselect_all'; + +const selectionToggleButtons = [ + { + id: 'select_all', + label: 'Select all', + }, + { + id: 'deselect_all', + label: 'Deselect all', + }, +]; + export const FilterGroup: React.FC = ({ groupName, items, @@ -39,7 +52,10 @@ export const FilterGroup: React.FC = ({ setItems, }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [showActiveFilters, setShowActiveFilters] = useState(false); + const [filterUpdated, setFilterUpdated] = useState(false); + const [selectionToggleSelectedId, setSelectionToggleSelectedId] = useState< + SelectionToggleOptionIds + >('select_all'); const onButtonClick = () => { setIsPopoverOpen(!isPopoverOpen); @@ -62,6 +78,18 @@ export const FilterGroup: React.FC = ({ ...newItems[index], checked: undefined, }; + + // This means, it is not a grouping label, + // so we need to switch off the grouping label too if it exists + if (!newItems[index].childOptionIds) { + for (let i = index - 1; i >= 0; i--) { + // Found the parent grouping label + if (newItems[i].childOptionIds) { + newItems[i].checked = undefined; + break; + } + } + } break; default: @@ -69,7 +97,29 @@ export const FilterGroup: React.FC = ({ ...newItems[index], checked: 'on', }; + + // This means, it is not a grouping label, + // so we need to switch ON the grouping label if all children are checked + if (!newItems[index].childOptionIds) { + let i: number; + for (i = index - 1; i >= 0; i--) { + const childIds = newItems[i].childOptionIds; + // Found the parent grouping label + if (childIds) { + let allChecked = true; + newItems.forEach((item) => { + if (childIds.has(item.id)) { + allChecked = allChecked && !!item.checked; + } + }); + newItems[i].checked = allChecked ? 'on' : undefined; + break; + } + } + } } + + // If a grouping label is toggled, toggle all its children const childIds = newItems[index].childOptionIds; if (childIds) { newItems.forEach((item) => { @@ -80,7 +130,12 @@ export const FilterGroup: React.FC = ({ } setItems(newItems); - setShowActiveFilters(true); + setFilterUpdated(!newItems.every((item) => item.checked)); + } + + function onSelectionToggleChange(optionId: string) { + setSelectionToggleSelectedId(optionId as SelectionToggleOptionIds); + toggleAll(optionId === 'select_all' ? 'on' : undefined); } function toggleAll(state: 'on' | undefined) { @@ -90,7 +145,7 @@ export const FilterGroup: React.FC = ({ })); setItems(newItems); - setShowActiveFilters(!!state); + setFilterUpdated(!state); } function search(term: string) { @@ -100,18 +155,18 @@ export const FilterGroup: React.FC = ({ item.visible = item.id.toLowerCase().includes(term); }); setItems(newItems); - setShowActiveFilters(true); + setFilterUpdated(true); } + const numActiveFilters = items.filter((item) => !item.childOptionIds && item.checked === 'on') + .length; const button = ( item.checked === 'on')} - numActiveFilters={ - showActiveFilters ? items.filter((item) => item.checked === 'on').length : undefined - } + hasActiveFilters={filterUpdated} + numActiveFilters={numActiveFilters > 0 ? numActiveFilters : undefined} > {groupName} @@ -127,7 +182,7 @@ export const FilterGroup: React.FC = ({ panelPaddingSize="none" > - +
= ({
{hasFooter && ( -
- toggleAll('on')}>Select all - toggleAll(undefined)}>Deselect all -
+
)} diff --git a/public/pages/Correlations/components/FindingCard.tsx b/public/pages/Correlations/components/FindingCard.tsx index 2305c1de8..69358544f 100644 --- a/public/pages/Correlations/components/FindingCard.tsx +++ b/public/pages/Correlations/components/FindingCard.tsx @@ -14,6 +14,8 @@ import { EuiHorizontalRule, EuiToolTip, EuiDescriptionList, + EuiText, + EuiIcon, } from '@elastic/eui'; import { getSeverityLabel, getSeverityColor, getLabelFromLogType } from '../utils/constants'; import { DataStore } from '../../../store/DataStore'; @@ -43,19 +45,19 @@ export const FindingCard: React.FC = ({ }) => { const list = [ { - title: 'Detection rule', - description: detectionRule.name, + title: Detection rule, + description: {detectionRule.name}, }, ]; if (finding.correlationRule) { list.unshift({ - title: 'Correlation score', - description: finding.correlationRule.name, + title: Correlation rule, + description: {finding.correlationRule.name}, }); } - const badgePadding = '2px 7px'; + const badgePadding = '0px 4px'; const { text: severityText, background } = getSeverityColor(detectionRule.severity); const header = ( @@ -65,7 +67,7 @@ export const FindingCard: React.FC = ({ {getSeverityLabel(detectionRule.severity)} - + {getLabelFromLogType(logType)} @@ -90,7 +92,9 @@ export const FindingCard: React.FC = ({ ); - const attrList = ; + const attrList = ( + + ); const relatedFindingCard = ( @@ -98,13 +102,25 @@ export const FindingCard: React.FC = ({ -

Correlation score

+ + Correlation score{' '} + + + +
- {correlationData?.score} + + {correlationData?.score} + - {timestamp} + + {timestamp} +
diff --git a/public/pages/Correlations/containers/CorrelationsContainer.tsx b/public/pages/Correlations/containers/CorrelationsContainer.tsx index aa052930c..ea2966f6f 100644 --- a/public/pages/Correlations/containers/CorrelationsContainer.tsx +++ b/public/pages/Correlations/containers/CorrelationsContainer.tsx @@ -444,7 +444,7 @@ export class Correlations extends React.Component - + @@ -462,11 +462,11 @@ export class Correlations extends React.Component - - +

Finding

+ - +
+

Correlated Findings ({findingCardsData.correlatedFindings.length})

@@ -508,45 +509,45 @@ export class Correlations extends React.Component - -

Correlations

-
+ + + +

Correlations

+
+
+ + + +
- - - - - - - - - - - Reset filters - - + + + + + + - + Reset filters