-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Security Solution][List details page]: Manage rules - Selection cleared on navigation #146121
Changes from all commits
b5f3a58
788de21
4d5d59a
8ed6331
50fac2f
3082640
0e66017
c27f980
02c66eb
8bc0c26
28dce70
3559d4e
a56cdf1
e5c1289
cfff10d
3a55691
a4bf586
6b7f2e7
50ceadc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* 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, { memo, useCallback, useMemo } from 'react'; | ||
import { EuiFlexItem, EuiSwitch } from '@elastic/eui'; | ||
import type { Rule } from '../../../../../rule_management/logic/types'; | ||
|
||
export const LinkRuleSwitch = memo( | ||
({ | ||
rule, | ||
linkedRules, | ||
onRuleLinkChange, | ||
}: { | ||
rule: Rule; | ||
linkedRules: Rule[]; | ||
onRuleLinkChange: (rulesSelectedToAdd: Rule[]) => void; | ||
}) => { | ||
const isRuleLinked = useMemo( | ||
() => Boolean(linkedRules.find((r) => r.id === rule.id)), | ||
[linkedRules, rule.id] | ||
); | ||
const onLinkOrUnlinkRule = useCallback( | ||
({ target: { checked } }) => { | ||
const newLinkedRules = !checked | ||
? linkedRules?.filter((item) => item.id !== rule.id) | ||
: [...linkedRules, rule]; | ||
if (typeof onRuleLinkChange === 'function') onRuleLinkChange(newLinkedRules); | ||
}, | ||
[linkedRules, onRuleLinkChange, rule] | ||
); | ||
|
||
return ( | ||
<EuiFlexItem grow={false}> | ||
<EuiSwitch onChange={onLinkOrUnlinkRule} label="" checked={isRuleLinked} /> | ||
</EuiFlexItem> | ||
); | ||
} | ||
); | ||
|
||
LinkRuleSwitch.displayName = 'LinkRuleSwitch'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/* | ||
* 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, { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import { sortBy } from 'lodash'; | ||
import type { | ||
CriteriaWithPagination, | ||
EuiBasicTableColumn, | ||
HorizontalAlignment, | ||
} from '@elastic/eui'; | ||
import { i18n } from '@kbn/i18n'; | ||
import * as myI18n from './translations'; | ||
|
||
import { useFindRulesInMemory } from '../../../../rule_management_ui/components/rules_table/rules_table/use_find_rules_in_memory'; | ||
import type { Rule } from '../../../../rule_management/logic/types'; | ||
import { getRulesTableColumn } from '../utils'; | ||
import { LinkRuleSwitch } from './link_rule_switch'; | ||
|
||
export interface ExceptionsAddToRulesComponentProps { | ||
initiallySelectedRules?: Rule[]; | ||
onRuleSelectionChange: (rulesSelectedToAdd: Rule[]) => void; | ||
} | ||
export const useAddToRulesTable = ({ | ||
initiallySelectedRules, | ||
onRuleSelectionChange, | ||
}: ExceptionsAddToRulesComponentProps) => { | ||
const { data: { rules } = { rules: [], total: 0 }, isFetched } = useFindRulesInMemory({ | ||
isInMemorySorting: true, | ||
filterOptions: { | ||
filter: '', | ||
showCustomRules: false, | ||
showElasticRules: false, | ||
tags: [], | ||
}, | ||
sortingOptions: undefined, | ||
pagination: undefined, | ||
refetchInterval: false, | ||
}); | ||
|
||
const [pagination, setPagination] = useState({ | ||
pageIndex: 0, | ||
initialPageSize: 5, | ||
showPerPageOptions: false, | ||
}); | ||
|
||
const [linkedRules, setLinkedRules] = useState<Rule[]>(initiallySelectedRules || []); | ||
useEffect(() => { | ||
onRuleSelectionChange(linkedRules); | ||
}, [linkedRules, onRuleSelectionChange]); | ||
|
||
const sortedRulesByLinkedRulesOnTop = useMemo( | ||
() => | ||
sortBy(rules, [ | ||
(rule) => { | ||
return initiallySelectedRules?.find((initRule) => initRule.id === rule.id); | ||
}, | ||
]), | ||
[initiallySelectedRules, rules] | ||
); | ||
|
||
const tagOptions = useMemo(() => { | ||
const uniqueTags = sortedRulesByLinkedRulesOnTop.reduce((acc: Set<string>, item: Rule) => { | ||
const { tags } = item; | ||
|
||
tags.forEach((tag) => acc.add(tag)); | ||
return acc; | ||
}, new Set()); | ||
return [...uniqueTags].map((tag) => ({ value: tag, name: tag })); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this could be done in the reduce probably There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! I thought about, but was worried about readability, but I will give it a try There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We discussed it and we found it we need to implement it in two steps as we need to remove duplicates and map the string (tag) to object of |
||
}, [sortedRulesByLinkedRulesOnTop]); | ||
|
||
const searchOptions = useMemo( | ||
() => ({ | ||
box: { | ||
incremental: true, | ||
}, | ||
filters: [ | ||
{ | ||
type: 'field_value_selection' as const, | ||
field: 'tags', | ||
name: i18n.translate( | ||
'xpack.securitySolution.exceptions.addToRulesTable.tagsFilterLabel', | ||
{ | ||
defaultMessage: 'Tags', | ||
} | ||
), | ||
multiSelect: 'or' as const, | ||
options: tagOptions, | ||
}, | ||
], | ||
}), | ||
[tagOptions] | ||
); | ||
|
||
const rulesTableColumnsWithLinkSwitch: Array<EuiBasicTableColumn<Rule>> = useMemo( | ||
() => [ | ||
{ | ||
field: 'link', | ||
name: myI18n.LINK_COLUMN, | ||
align: 'left' as HorizontalAlignment, | ||
'data-test-subj': 'ruleActionLinkRuleSwitch', | ||
render: (_, rule: Rule) => ( | ||
<LinkRuleSwitch rule={rule} linkedRules={linkedRules} onRuleLinkChange={setLinkedRules} /> | ||
), | ||
}, | ||
...getRulesTableColumn(), | ||
], | ||
[linkedRules] | ||
); | ||
const onTableChange = useCallback( | ||
({ page: { index } }: CriteriaWithPagination<never>) => | ||
setPagination({ ...pagination, pageIndex: index }), | ||
[pagination] | ||
); | ||
return { | ||
isLoading: !isFetched, | ||
pagination, | ||
searchOptions, | ||
sortedRulesByLinkedRulesOnTop, | ||
rulesTableColumnsWithLinkSwitch, | ||
addToSelectedRulesDescription: myI18n.ADD_TO_SELECTED_RULES_DESCRIPTION, | ||
onTableChange, | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
disabling Test for now as anyway I need to convert this test to use react-testing-library