Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
TableId,
} from '@kbn/securitysolution-data-table';
import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy';
import { useGroupTakeActionsItems } from '../../../../detections/hooks/alerts_table/use_group_take_action_items';
import {
defaultGroupStatsAggregations,
defaultGroupStatsRenderer,
Expand Down Expand Up @@ -559,6 +560,11 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
confirmManualRuleRun,
} = useManualRuleRunConfirmation();

const groupTakeActionItems = useGroupTakeActionsItems({
currentStatus: currentAlertStatusFilterValue,
showAlertStatusActions: Boolean(hasIndexWrite) && Boolean(hasIndexMaintenance),
});

const accordionExtraActionGroupStats = useMemo(
() => ({
aggregations: defaultGroupStatsAggregations,
Expand Down Expand Up @@ -796,14 +802,12 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
<GroupedAlertsTable
accordionButtonContent={defaultGroupTitleRenderers}
accordionExtraActionGroupStats={accordionExtraActionGroupStats}
currentAlertStatusFilterValue={currentAlertStatusFilterValue}
defaultFilters={alertMergedFilters}
defaultGroupingOptions={defaultGroupingOptions}
from={from}
globalFilters={filters}
globalQuery={query}
hasIndexMaintenance={hasIndexMaintenance ?? false}
hasIndexWrite={hasIndexWrite ?? false}
groupTakeActionItems={groupTakeActionItems}
loading={loading}
renderChildComponent={renderGroupedAlertTable}
runtimeMappings={sourcererDataView?.runtimeFieldMap as RunTimeMappings}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ const testProps: AlertsTableComponentProps = {
query: 'query',
language: 'language',
},
hasIndexMaintenance: true,
hasIndexWrite: true,
loading: false,
renderChildComponent,
runtimeMappings: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import { isEmpty, isEqual } from 'lodash/fp';
import type { Storage } from '@kbn/kibana-utils-plugin/public';
import type { TableIdLiteral } from '@kbn/securitysolution-data-table';
import type { GetGroupStats, GroupingArgs, GroupPanelRenderer } from '@kbn/grouping/src';
import type { GroupTakeActionItems } from './types';
import type { AlertsGroupingAggregation } from './grouping_settings/types';
import { groupIdSelector } from '../../../common/store/grouping/selectors';
import { useDeepEqualSelector } from '../../../common/hooks/use_selector';
import { updateGroups } from '../../../common/store/grouping/actions';
import type { Status } from '../../../../common/api/detection_engine';
import { defaultUnit } from '../../../common/components/toolbar/unit';
import { useSourcererDataView } from '../../../sourcerer/containers';
import type { RunTimeMappings } from '../../../sourcerer/store/model';
Expand Down Expand Up @@ -56,7 +56,6 @@ export interface AlertsTableComponentProps {
*/
renderer: GetGroupStats<AlertsGroupingAggregation>;
};
currentAlertStatusFilterValue?: Status[];
defaultFilters?: Filter[];
/**
* Default values to display in the group selection dropdown.
Expand All @@ -66,8 +65,11 @@ export interface AlertsTableComponentProps {
from: string;
globalFilters: Filter[];
globalQuery: Query;
hasIndexMaintenance: boolean;
hasIndexWrite: boolean;
/**
* Allows to customize the content of the Take actions button rendered at the group level.
* If no value is provided, the Take actins button is not displayed.
*/
groupTakeActionItems?: GroupTakeActionItems;
loading: boolean;
renderChildComponent: (groupingFilters: Filter[]) => React.ReactElement;
runtimeMappings: RunTimeMappings;
Expand Down Expand Up @@ -326,6 +328,7 @@ const GroupedAlertsTableComponent: React.FC<AlertsTableComponentProps> = (props)
getGrouping={getGrouping}
groupingLevel={level}
groupStatsAggregations={groupStatusAggregations}
groupTakeActionItems={props.groupTakeActionItems}
onGroupClose={() => resetGroupChildrenPagination(level)}
pageIndex={pageIndex[level] ?? DEFAULT_PAGE_INDEX}
pageSize={pageSize[level] ?? DEFAULT_PAGE_SIZE}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common';
import type { DynamicGroupingProps } from '@kbn/grouping/src';
import { parseGroupingQuery } from '@kbn/grouping/src';
import type { TableIdLiteral } from '@kbn/securitysolution-data-table';
import type { GroupTakeActionItems } from './types';
import type { RunTimeMappings } from '../../../sourcerer/store/model';
import { SourcererScopeName } from '../../../sourcerer/store/model';
import { combineQueries } from '../../../common/lib/kuery';
import type { AlertsGroupingAggregation } from './grouping_settings/types';
import type { Status } from '../../../../common/api/detection_engine';
import { InspectButton } from '../../../common/components/inspect';
import { useSourcererDataView } from '../../../sourcerer/containers';
import { useKibana } from '../../../common/lib/kibana';
Expand All @@ -31,13 +31,12 @@ import { buildTimeRangeFilter } from './helpers';
import * as i18n from './translations';
import { useQueryAlerts } from '../../containers/detection_engine/alerts/use_query';
import { ALERTS_QUERY_NAMES } from '../../containers/detection_engine/alerts/constants';
import { getAlertsGroupingQuery, useGroupTakeActionsItems } from './grouping_settings';
import { getAlertsGroupingQuery } from './grouping_settings';

const ALERTS_GROUPING_ID = 'alerts-grouping';
const DEFAULT_FILTERS: Filter[] = [];

interface OwnProps {
currentAlertStatusFilterValue?: Status[];
defaultFilters?: Filter[];
from: string;
getGrouping: (
Expand All @@ -51,8 +50,11 @@ interface OwnProps {
* This is then used to render values in the EuiAccordion `extraAction` section.
*/
groupStatsAggregations: (field: string) => NamedAggregation[];
hasIndexMaintenance: boolean;
hasIndexWrite: boolean;
/**
* Allows to customize the content of the Take actions button rendered at the group level.
* If no value is provided, the Take actins button is not displayed.
*/
groupTakeActionItems?: GroupTakeActionItems;
loading: boolean;
onGroupClose: () => void;
pageIndex: number;
Expand All @@ -71,16 +73,14 @@ interface OwnProps {
export type AlertsTableComponentProps = OwnProps;

export const GroupedSubLevelComponent: React.FC<AlertsTableComponentProps> = ({
currentAlertStatusFilterValue,
defaultFilters = DEFAULT_FILTERS,
from,
getGrouping,
globalFilters,
globalQuery,
groupingLevel,
groupStatsAggregations,
hasIndexMaintenance,
hasIndexWrite,
groupTakeActionItems,
loading,
onGroupClose,
pageIndex,
Expand Down Expand Up @@ -109,7 +109,7 @@ export const GroupedSubLevelComponent: React.FC<AlertsTableComponentProps> = ({
indexPattern,
browserFields,
filters: [
...(defaultFilters ?? []),
...defaultFilters,
...globalFilters,
...customFilters,
...(parentGroupingFilter ? JSON.parse(parentGroupingFilter) : []),
Expand Down Expand Up @@ -243,20 +243,18 @@ export const GroupedSubLevelComponent: React.FC<AlertsTableComponentProps> = ({
[uniqueQueryId]
);

const takeActionItems = useGroupTakeActionsItems({
currentStatus: currentAlertStatusFilterValue,
showAlertStatusActions: hasIndexWrite && hasIndexMaintenance,
});

const getTakeActionItems = useCallback(
(groupFilters: Filter[], groupNumber: number) =>
takeActionItems({
(groupFilters: Filter[], groupNumber: number) => {
const takeActionParams = {
groupNumber,
query: getGlobalQuery([...(defaultFilters ?? []), ...groupFilters])?.filterQuery,
selectedGroup,
tableId,
}),
[defaultFilters, getGlobalQuery, selectedGroup, tableId, takeActionItems]
};

return groupTakeActionItems?.(takeActionParams) ?? [];
},
[defaultFilters, getGlobalQuery, groupTakeActionItems, selectedGroup, tableId]
);

const onChangeGroupsItemsPerPage = useCallback(
Expand All @@ -280,13 +278,14 @@ export const GroupedSubLevelComponent: React.FC<AlertsTableComponentProps> = ({
onGroupClose,
renderChildComponent,
selectedGroup,
takeActionItems: getTakeActionItems,
...(groupTakeActionItems && { takeActionItems: getTakeActionItems }),
}),
[
aggs,
getGrouping,
getTakeActionItems,
groupingLevel,
groupTakeActionItems,
inspect,
isLoadingGroups,
loading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ export * from './default_grouping_options';
export * from './default_group_stats_aggregations';
export * from './default_group_stats_renderers';
export * from './default_group_title_renderers';
export * from './group_take_action_items';
export * from './query_builder';
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import type { Status } from '../../../../common/api/detection_engine';
import type { Note } from '../../../../common/api/timeline';
import type { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider';
import type { TimelineModel } from '../../../timelines/store/model';
import type { inputsModel } from '../../../common/store';
import type { ControlColumnProps, RowRenderer } from '../../../../common/types';

export interface SetEventsLoadingProps {
Expand All @@ -30,23 +29,6 @@ export interface SetEventsDeletedProps {
isDeleted: boolean;
}

export interface UpdateAlertsStatusProps {
alertIds: string[];
status: Status;
selectedStatus: Status;
}

export type UpdateAlertsStatusCallback = (
refetchQuery: inputsModel.Refetch,
{ alertIds, status, selectedStatus }: UpdateAlertsStatusProps
) => void;

export type UpdateAlertsStatus = ({
alertIds,
status,
selectedStatus,
}: UpdateAlertsStatusProps) => void;

export interface UpdateAlertStatusActionProps {
query?: string;
alertIds: string[];
Expand Down Expand Up @@ -99,3 +81,22 @@ export type SecurityAlertsTableProps = AlertsTablePropsWithRef<SecurityAlertsTab
export type GetSecurityAlertsTableProp<PropKey extends keyof SecurityAlertsTableProps> =
NonNullable<SecurityAlertsTableProps[PropKey]>;
export type { AlertWithLegacyFormats } from '@kbn/response-ops-alerts-table/types';

export type GroupTakeActionItems = (props: {
/**
* Query to run when an item is clicked (meaning when an alert status is updated)
*/
query?: string;
/**
* Id of the table (used for telemetry)
*/
tableId: string;
/**
* Group number to know which group to apply the logic to. This value is coming from the callback in the kbn-grouping package.
*/
groupNumber: number;
/**
* Selected group to know which group is extended/visible. This is coming from the getLevel function in the detections alert grouping code.
*/
selectedGroup: string;
}) => JSX.Element[];
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
* 2.0.
*/

import { waitFor, renderHook } from '@testing-library/react';
import { renderHook, waitFor } from '@testing-library/react';
import React from 'react';
import { TestProviders } from '../../../../common/mock';
import { useGroupTakeActionsItems } from '.';
import { TestProviders } from '../../../common/mock';
import { useGroupTakeActionsItems } from './use_group_take_action_items';

describe('useGroupTakeActionsItems', () => {
const wrapperContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
Expand Down
Loading