Skip to content
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][EuiInMemoryTable] Replace usage of deprecated ref method with controlled selection.selected API #175726

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
import React, { useCallback, useMemo, useRef } from 'react';
import { Loader } from '../../../../common/components/loader';
import { useBoolState } from '../../../../common/hooks/use_bool_state';
import { useValueChanged } from '../../../../common/hooks/use_value_changed';
import { PrePackagedRulesPrompt } from '../../../../detections/components/rules/pre_packaged_rules/load_empty_prompt';
import type { Rule } from '../../../rule_management/logic';
import * as i18n from '../../../../detections/pages/detection_engine/rules/translations';
Expand Down Expand Up @@ -61,7 +60,6 @@ export const RulesTables = React.memo<RulesTableProps>(({ selectedTab }) => {
const hasPermissions = hasUserCRUDPermission(canUserCRUD);
const isUpgradingSecurityPackages = useIsUpgradingSecurityPackages();

const tableRef = useRef<EuiBasicTable>(null);
const rulesTableContext = useRulesTableContext();
const { data: ruleManagementFilters } = useRuleManagementFilters();

Expand Down Expand Up @@ -171,14 +169,6 @@ export const RulesTables = React.memo<RulesTableProps>(({ selectedTab }) => {

const isSelectAllCalled = useRef(false);

// TODO Remove this synchronization logic after https://github.com/elastic/eui/issues/6184 is implemented
// Synchronize selectedRuleIds with EuiBasicTable's selected rows
useValueChanged((ruleIds) => {
if (tableRef.current != null) {
tableRef.current.setSelection(rules.filter((rule) => ruleIds.includes(rule.id)));
}
}, selectedRuleIds);

const isTableSelectable =
hasPermissions &&
(selectedTab === AllRulesTabs.management || selectedTab === AllRulesTabs.monitoring);
Expand All @@ -187,30 +177,12 @@ export const RulesTables = React.memo<RulesTableProps>(({ selectedTab }) => {
() => ({
selectable: (item: Rule) => !loadingRuleIds.includes(item.id),
onSelectionChange: (selected: Rule[]) => {
/**
* EuiBasicTable doesn't provide declarative API to control selected rows.
* This limitation requires us to synchronize selection state manually using setSelection().
* But it creates a chain reaction when the user clicks Select All:
* selectAll() -> setSelection() -> onSelectionChange() -> setSelection().
* To break the chain we should check whether the onSelectionChange was triggered
* by the Select All action or not.
*
*/
if (isSelectAllCalled.current) {
isSelectAllCalled.current = false;
// Handle special case of unselecting all rules via checkbox
// after all rules were selected via Bulk select.
if (selected.length === 0) {
setIsAllSelected(false);
setSelectedRuleIds([]);
}
} else {
setSelectedRuleIds(selected.map(({ id }) => id));
setIsAllSelected(false);
}
setSelectedRuleIds(selected.map(({ id }) => id));
setIsAllSelected(false);
},
selected: selectedRuleIds.map((id) => ({ id } as Rule)), // EuiBasicTable only needs the itemId
}),
[loadingRuleIds, setIsAllSelected, setSelectedRuleIds]
[loadingRuleIds, setIsAllSelected, setSelectedRuleIds, selectedRuleIds]
);

const toggleSelectAll = useCallback(() => {
Expand Down Expand Up @@ -329,7 +301,6 @@ export const RulesTables = React.memo<RulesTableProps>(({ selectedTab }) => {
noItemsMessage={NO_ITEMS_MESSAGE}
onChange={tableOnChangeCallback}
pagination={paginationMemo}
ref={tableRef}
selection={isTableSelectable ? euiBasicTableSelectionProps : undefined}
sorting={{
sort: {
Expand Down