Skip to content

Commit

Permalink
[SecuritySolution] add global filter to topN (#112401) (#112802)
Browse files Browse the repository at this point in the history
* add global filter to topN

* sort lines

* add unit test

* fix duplicate queries

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Angela Chuang <6295984+angorayc@users.noreply.github.com>
  • Loading branch information
kibanamachine and angorayc authored Sep 22, 2021
1 parent 3a0bd67 commit 42b6cbd
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
<InspectButtonContainer>
{tGridEnabled ? (
timelinesUi.getTGrid<'embedded'>({
id,
type: 'embedded',
additionalFilters,
browserFields,
bulkActions,
columns,
Expand All @@ -189,29 +188,30 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
end,
entityType,
filters: globalFilters,
filterStatus: currentFilter,
globalFullScreen,
graphEventId,
graphOverlay,
hasAlertsCrud,
id,
indexNames: selectedPatterns,
indexPattern,
isLive,
isLoadingIndexPattern,
itemsPerPage,
itemsPerPageOptions: itemsPerPageOptions!,
kqlMode,
query,
leadingControlColumns,
onRuleChange,
query,
renderCellValue,
rowRenderers,
setQuery,
start,
sort,
additionalFilters,
graphEventId,
filterStatus: currentFilter,
leadingControlColumns,
trailingControlColumns,
start,
tGridEventRenderedViewEnabled,
trailingControlColumns,
type: 'embedded',
unit,
})
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useSourcererScope } from '../../../containers/sourcerer';
import { TooltipWithKeyboardShortcut } from '../../accessibility';
import { getAdditionalScreenReaderOnlyContext } from '../utils';
import { SHOW_TOP_N_KEYBOARD_SHORTCUT } from '../keyboard_shortcut_constants';
import { Filter } from '../../../../../../../../src/plugins/data/public';

const SHOW_TOP = (fieldName: string) =>
i18n.translate('xpack.securitySolution.hoverActions.showTopTooltip', {
Expand All @@ -35,11 +36,12 @@ interface Props {
Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon | typeof EuiContextMenuItem;
enablePopOver?: boolean;
field: string;
globalFilters?: Filter[];
onClick: () => void;
onFilterAdded?: () => void;
ownFocus: boolean;
showTopN: boolean;
showTooltip?: boolean;
showTopN: boolean;
timelineId?: string | null;
value?: string[] | string | null;
}
Expand All @@ -56,6 +58,7 @@ export const ShowTopNButton: React.FC<Props> = React.memo(
showTopN,
timelineId,
value,
globalFilters,
}) => {
const activeScope: SourcererScopeName =
timelineId === TimelineId.active
Expand Down Expand Up @@ -128,9 +131,10 @@ export const ShowTopNButton: React.FC<Props> = React.memo(
timelineId={timelineId ?? undefined}
toggleTopN={onClick}
value={value}
globalFilters={globalFilters}
/>
),
[browserFields, field, indexPattern, onClick, onFilterAdded, timelineId, value]
[browserFields, field, indexPattern, onClick, onFilterAdded, timelineId, value, globalFilters]
);

return showTopN ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,60 @@ let testProps = {
};

describe('StatefulTopN', () => {
describe('rendering globalFilter', () => {
let wrapper: ReactWrapper;
const globalFilters = [
{
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'signal.rule.id',
params: {
query: 'd62249f0-1632-11ec-b035-19607969bc20',
},
},
query: {
match_phrase: {
'signal.rule.id': 'd62249f0-1632-11ec-b035-19607969bc20',
},
},
},
];
beforeEach(() => {
wrapper = mount(
<TestProviders store={store}>
<StatefulTopN {...testProps} globalFilters={globalFilters} />
</TestProviders>
);
});

test(`provides filters from non Redux state when rendering in alerts table`, () => {
const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props;

expect(props.filters).toEqual([
{
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'signal.rule.id',
params: {
query: 'd62249f0-1632-11ec-b035-19607969bc20',
},
},
query: {
match_phrase: {
'signal.rule.id': 'd62249f0-1632-11ec-b035-19607969bc20',
},
},
},
]);
});
});

describe('rendering in a global NON-timeline context', () => {
let wrapper: ReactWrapper;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ const makeMapStateToProps = () => {
// The mapped Redux state provided to this component includes the global
// filters that appear at the top of most views in the app, and all the
// filters in the active timeline:
const mapStateToProps = (state: State) => {
const mapStateToProps = (state: State, ownProps: { globalFilters?: Filter[] }) => {
const activeTimeline: TimelineModel = getTimeline(state, TimelineId.active) ?? timelineDefaults;
const activeTimelineFilters = activeTimeline.filters ?? EMPTY_FILTERS;
const activeTimelineInput: inputsModel.InputsRange = getInputsTimeline(state);

const { globalFilters } = ownProps;
return {
activeTimelineEventType: activeTimeline.eventType,
activeTimelineFilters:
Expand All @@ -59,7 +59,7 @@ const makeMapStateToProps = () => {
dataProviders:
activeTimeline.activeTab === TimelineTabs.query ? activeTimeline.dataProviders : [],
globalQuery: getGlobalQuerySelector(state),
globalFilters: getGlobalFiltersQuerySelector(state),
globalFilters: globalFilters ?? getGlobalFiltersQuerySelector(state),
kqlMode: activeTimeline.kqlMode,
};
};
Expand All @@ -82,6 +82,7 @@ export interface OwnProps {
toggleTopN: () => void;
onFilterAdded?: () => void;
value?: string[] | string | null;
globalFilters?: Filter[];
}
type PropsFromRedux = ConnectedProps<typeof connector>;
type Props = OwnProps & PropsFromRedux;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import React, { useCallback, useState, useMemo } from 'react';
import { Filter } from '../../../../../../../src/plugins/data/public';

import type {
BrowserFields,
Expand Down Expand Up @@ -167,11 +168,13 @@ export const defaultCellActions: TGridCellAction[] = [
({
browserFields,
data,
globalFilters,
timelineId,
pageSize,
}: {
browserFields: BrowserFields;
data: TimelineNonEcsData[][];
globalFilters?: Filter[];
timelineId: string;
pageSize: number;
}) =>
Expand Down Expand Up @@ -205,6 +208,7 @@ export const defaultCellActions: TGridCellAction[] = [
enablePopOver
data-test-subj="hover-actions-show-top-n"
field={columnId}
globalFilters={globalFilters}
onClick={onClick}
onFilterAdded={onFilterAdded}
ownFocus={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,6 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
const alertsTableDefaultFilters = useMemo(
() => [
...buildAlertsRuleIdFilter(ruleId),
...filters,
...(ruleRegistryEnabled
? [
// TODO: Once we are past experimental phase this code should be removed
Expand All @@ -400,7 +399,7 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
: [...buildShowBuildingBlockFilter(showBuildingBlockAlerts)]),
...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts),
],
[ruleId, filters, ruleRegistryEnabled, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts]
[ruleId, ruleRegistryEnabled, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts]
);

const alertMergedFilters = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { ReactNode } from 'react';

import { EuiDataGridColumn, EuiDataGridColumnCellActionProps } from '@elastic/eui';
import { IFieldSubType } from '../../../../../../../src/plugins/data/common';
import { Filter, IFieldSubType } from '../../../../../../../src/plugins/data/common';
import { BrowserFields } from '../../../search_strategy/index_fields';
import { TimelineNonEcsData } from '../../../search_strategy/timeline';

Expand Down Expand Up @@ -45,14 +45,16 @@ export type ColumnId = string;
export type TGridCellAction = ({
browserFields,
data,
timelineId,
globalFilters,
pageSize,
timelineId,
}: {
browserFields: BrowserFields;
/** each row of data is represented as one TimelineNonEcsData[] */
data: TimelineNonEcsData[][];
timelineId: string;
globalFilters?: Filter[];
pageSize: number;
timelineId: string;
}) => (props: EuiDataGridColumnCellActionProps) => ReactNode;

/** The specification of a column header */
Expand Down
18 changes: 11 additions & 7 deletions x-pack/plugins/timelines/public/components/t_grid/body/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import type { EuiTheme } from '../../../../../../../src/plugins/kibana_react/com
import { ViewSelection } from '../event_rendered_view/selector';
import { EventRenderedView } from '../event_rendered_view';
import { useDataGridHeightHack } from './height_hack';
import { Filter } from '../../../../../../../src/plugins/data/public';

const StatefulAlertStatusBulkActions = lazy(
() => import('../toolbar/bulk_actions/alert_status_bulk_actions')
Expand All @@ -86,6 +87,7 @@ interface OwnProps {
bulkActions?: BulkActionsProp;
data: TimelineItem[];
defaultCellActions?: TGridCellAction[];
filters?: Filter[];
filterQuery: string;
filterStatus?: AlertStatus;
id: string;
Expand Down Expand Up @@ -300,15 +302,18 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
data,
defaultCellActions,
filterQuery,
filters,
filterStatus,
hasAlertsCrud,
hasAlertsCrudPermissions,
id,
indexNames,
isEventViewer = false,
isLoading,
isSelectAllChecked,
itemsPerPageOptions,
leadingControlColumns = EMPTY_CONTROL_COLUMNS,
loadingEventIds,
isLoading,
loadPage,
onRuleChange,
pageSize,
Expand All @@ -322,11 +327,9 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
tableView = 'gridView',
tabType,
totalItems,
totalSelectAllAlerts,
trailingControlColumns = EMPTY_CONTROL_COLUMNS,
unit = defaultUnit,
hasAlertsCrud,
hasAlertsCrudPermissions,
totalSelectAllAlerts,
}) => {
const dispatch = useDispatch();
const getManageTimeline = useMemo(() => tGridSelectors.getManageTimelineById(), []);
Expand Down Expand Up @@ -641,10 +644,11 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
columnHeaders.map((header) => {
const buildAction = (tGridCellAction: TGridCellAction) =>
tGridCellAction({
data: data.map((row) => row.data),
browserFields,
timelineId: id,
data: data.map((row) => row.data),
globalFilters: filters,
pageSize,
timelineId: id,
});

return {
Expand All @@ -653,7 +657,7 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
header.tGridCellActions?.map(buildAction) ?? defaultCellActions?.map(buildAction),
};
}),
[browserFields, columnHeaders, data, defaultCellActions, id, pageSize]
[browserFields, columnHeaders, data, defaultCellActions, id, pageSize, filters]
);

const renderTGridCellValue = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,30 +347,31 @@ const TGridIntegratedComponent: React.FC<TGridIntegratedProps> = ({
>
<ScrollableFlexItem grow={1}>
<StatefulBody
hasAlertsCrud={hasAlertsCrud}
activePage={pageInfo.activePage}
browserFields={browserFields}
bulkActions={bulkActions}
filterQuery={filterQuery}
data={nonDeletedEvents}
defaultCellActions={defaultCellActions}
filterQuery={filterQuery}
filters={filters}
filterStatus={filterStatus}
hasAlertsCrud={hasAlertsCrud}
id={id}
indexNames={indexNames}
isEventViewer={true}
itemsPerPageOptions={itemsPerPageOptions}
leadingControlColumns={leadingControlColumns}
loadPage={loadPage}
onRuleChange={onRuleChange}
pageSize={itemsPerPage}
refetch={refetch}
renderCellValue={renderCellValue}
rowRenderers={rowRenderers}
tabType={TimelineTabs.query}
tableView={tableView}
tabType={TimelineTabs.query}
totalItems={totalCountMinusDeleted}
unit={unit}
filterStatus={filterStatus}
leadingControlColumns={leadingControlColumns}
trailingControlColumns={trailingControlColumns}
refetch={refetch}
indexNames={indexNames}
unit={unit}
/>
</ScrollableFlexItem>
</FullWidthFlexGroup>
Expand Down

0 comments on commit 42b6cbd

Please sign in to comment.