[SecuritySolution] add global filter to topN (#112401)
* add global filter to topN * sort lines * add unit test * fix duplicate queries Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
0cbdf3f259
commit
210fb50d0b
|
@ -177,8 +177,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
||||||
<InspectButtonContainer>
|
<InspectButtonContainer>
|
||||||
{tGridEnabled ? (
|
{tGridEnabled ? (
|
||||||
timelinesUi.getTGrid<'embedded'>({
|
timelinesUi.getTGrid<'embedded'>({
|
||||||
id,
|
additionalFilters,
|
||||||
type: 'embedded',
|
|
||||||
browserFields,
|
browserFields,
|
||||||
bulkActions,
|
bulkActions,
|
||||||
columns,
|
columns,
|
||||||
|
@ -189,9 +188,12 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
||||||
end,
|
end,
|
||||||
entityType,
|
entityType,
|
||||||
filters: globalFilters,
|
filters: globalFilters,
|
||||||
|
filterStatus: currentFilter,
|
||||||
globalFullScreen,
|
globalFullScreen,
|
||||||
|
graphEventId,
|
||||||
graphOverlay,
|
graphOverlay,
|
||||||
hasAlertsCrud,
|
hasAlertsCrud,
|
||||||
|
id,
|
||||||
indexNames: selectedPatterns,
|
indexNames: selectedPatterns,
|
||||||
indexPattern,
|
indexPattern,
|
||||||
isLive,
|
isLive,
|
||||||
|
@ -199,19 +201,17 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemsPerPageOptions: itemsPerPageOptions!,
|
itemsPerPageOptions: itemsPerPageOptions!,
|
||||||
kqlMode,
|
kqlMode,
|
||||||
query,
|
leadingControlColumns,
|
||||||
onRuleChange,
|
onRuleChange,
|
||||||
|
query,
|
||||||
renderCellValue,
|
renderCellValue,
|
||||||
rowRenderers,
|
rowRenderers,
|
||||||
setQuery,
|
setQuery,
|
||||||
start,
|
|
||||||
sort,
|
sort,
|
||||||
additionalFilters,
|
start,
|
||||||
graphEventId,
|
|
||||||
filterStatus: currentFilter,
|
|
||||||
leadingControlColumns,
|
|
||||||
trailingControlColumns,
|
|
||||||
tGridEventRenderedViewEnabled,
|
tGridEventRenderedViewEnabled,
|
||||||
|
trailingControlColumns,
|
||||||
|
type: 'embedded',
|
||||||
unit,
|
unit,
|
||||||
})
|
})
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { useSourcererScope } from '../../../containers/sourcerer';
|
||||||
import { TooltipWithKeyboardShortcut } from '../../accessibility';
|
import { TooltipWithKeyboardShortcut } from '../../accessibility';
|
||||||
import { getAdditionalScreenReaderOnlyContext } from '../utils';
|
import { getAdditionalScreenReaderOnlyContext } from '../utils';
|
||||||
import { SHOW_TOP_N_KEYBOARD_SHORTCUT } from '../keyboard_shortcut_constants';
|
import { SHOW_TOP_N_KEYBOARD_SHORTCUT } from '../keyboard_shortcut_constants';
|
||||||
|
import { Filter } from '../../../../../../../../src/plugins/data/public';
|
||||||
|
|
||||||
const SHOW_TOP = (fieldName: string) =>
|
const SHOW_TOP = (fieldName: string) =>
|
||||||
i18n.translate('xpack.securitySolution.hoverActions.showTopTooltip', {
|
i18n.translate('xpack.securitySolution.hoverActions.showTopTooltip', {
|
||||||
|
@ -35,11 +36,12 @@ interface Props {
|
||||||
Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon | typeof EuiContextMenuItem;
|
Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon | typeof EuiContextMenuItem;
|
||||||
enablePopOver?: boolean;
|
enablePopOver?: boolean;
|
||||||
field: string;
|
field: string;
|
||||||
|
globalFilters?: Filter[];
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
onFilterAdded?: () => void;
|
onFilterAdded?: () => void;
|
||||||
ownFocus: boolean;
|
ownFocus: boolean;
|
||||||
showTopN: boolean;
|
|
||||||
showTooltip?: boolean;
|
showTooltip?: boolean;
|
||||||
|
showTopN: boolean;
|
||||||
timelineId?: string | null;
|
timelineId?: string | null;
|
||||||
value?: string[] | string | null;
|
value?: string[] | string | null;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +58,7 @@ export const ShowTopNButton: React.FC<Props> = React.memo(
|
||||||
showTopN,
|
showTopN,
|
||||||
timelineId,
|
timelineId,
|
||||||
value,
|
value,
|
||||||
|
globalFilters,
|
||||||
}) => {
|
}) => {
|
||||||
const activeScope: SourcererScopeName =
|
const activeScope: SourcererScopeName =
|
||||||
timelineId === TimelineId.active
|
timelineId === TimelineId.active
|
||||||
|
@ -128,9 +131,10 @@ export const ShowTopNButton: React.FC<Props> = React.memo(
|
||||||
timelineId={timelineId ?? undefined}
|
timelineId={timelineId ?? undefined}
|
||||||
toggleTopN={onClick}
|
toggleTopN={onClick}
|
||||||
value={value}
|
value={value}
|
||||||
|
globalFilters={globalFilters}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[browserFields, field, indexPattern, onClick, onFilterAdded, timelineId, value]
|
[browserFields, field, indexPattern, onClick, onFilterAdded, timelineId, value, globalFilters]
|
||||||
);
|
);
|
||||||
|
|
||||||
return showTopN ? (
|
return showTopN ? (
|
||||||
|
|
|
@ -160,6 +160,60 @@ let testProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('StatefulTopN', () => {
|
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', () => {
|
describe('rendering in a global NON-timeline context', () => {
|
||||||
let wrapper: ReactWrapper;
|
let wrapper: ReactWrapper;
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,11 @@ const makeMapStateToProps = () => {
|
||||||
// The mapped Redux state provided to this component includes the global
|
// 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 that appear at the top of most views in the app, and all the
|
||||||
// filters in the active timeline:
|
// 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 activeTimeline: TimelineModel = getTimeline(state, TimelineId.active) ?? timelineDefaults;
|
||||||
const activeTimelineFilters = activeTimeline.filters ?? EMPTY_FILTERS;
|
const activeTimelineFilters = activeTimeline.filters ?? EMPTY_FILTERS;
|
||||||
const activeTimelineInput: inputsModel.InputsRange = getInputsTimeline(state);
|
const activeTimelineInput: inputsModel.InputsRange = getInputsTimeline(state);
|
||||||
|
const { globalFilters } = ownProps;
|
||||||
return {
|
return {
|
||||||
activeTimelineEventType: activeTimeline.eventType,
|
activeTimelineEventType: activeTimeline.eventType,
|
||||||
activeTimelineFilters:
|
activeTimelineFilters:
|
||||||
|
@ -59,7 +59,7 @@ const makeMapStateToProps = () => {
|
||||||
dataProviders:
|
dataProviders:
|
||||||
activeTimeline.activeTab === TimelineTabs.query ? activeTimeline.dataProviders : [],
|
activeTimeline.activeTab === TimelineTabs.query ? activeTimeline.dataProviders : [],
|
||||||
globalQuery: getGlobalQuerySelector(state),
|
globalQuery: getGlobalQuerySelector(state),
|
||||||
globalFilters: getGlobalFiltersQuerySelector(state),
|
globalFilters: globalFilters ?? getGlobalFiltersQuerySelector(state),
|
||||||
kqlMode: activeTimeline.kqlMode,
|
kqlMode: activeTimeline.kqlMode,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -82,6 +82,7 @@ export interface OwnProps {
|
||||||
toggleTopN: () => void;
|
toggleTopN: () => void;
|
||||||
onFilterAdded?: () => void;
|
onFilterAdded?: () => void;
|
||||||
value?: string[] | string | null;
|
value?: string[] | string | null;
|
||||||
|
globalFilters?: Filter[];
|
||||||
}
|
}
|
||||||
type PropsFromRedux = ConnectedProps<typeof connector>;
|
type PropsFromRedux = ConnectedProps<typeof connector>;
|
||||||
type Props = OwnProps & PropsFromRedux;
|
type Props = OwnProps & PropsFromRedux;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useState, useMemo } from 'react';
|
import React, { useCallback, useState, useMemo } from 'react';
|
||||||
|
import { Filter } from '../../../../../../../src/plugins/data/public';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
BrowserFields,
|
BrowserFields,
|
||||||
|
@ -167,11 +168,13 @@ export const defaultCellActions: TGridCellAction[] = [
|
||||||
({
|
({
|
||||||
browserFields,
|
browserFields,
|
||||||
data,
|
data,
|
||||||
|
globalFilters,
|
||||||
timelineId,
|
timelineId,
|
||||||
pageSize,
|
pageSize,
|
||||||
}: {
|
}: {
|
||||||
browserFields: BrowserFields;
|
browserFields: BrowserFields;
|
||||||
data: TimelineNonEcsData[][];
|
data: TimelineNonEcsData[][];
|
||||||
|
globalFilters?: Filter[];
|
||||||
timelineId: string;
|
timelineId: string;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}) =>
|
}) =>
|
||||||
|
@ -205,6 +208,7 @@ export const defaultCellActions: TGridCellAction[] = [
|
||||||
enablePopOver
|
enablePopOver
|
||||||
data-test-subj="hover-actions-show-top-n"
|
data-test-subj="hover-actions-show-top-n"
|
||||||
field={columnId}
|
field={columnId}
|
||||||
|
globalFilters={globalFilters}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onFilterAdded={onFilterAdded}
|
onFilterAdded={onFilterAdded}
|
||||||
ownFocus={false}
|
ownFocus={false}
|
||||||
|
|
|
@ -391,7 +391,6 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
|
||||||
const alertsTableDefaultFilters = useMemo(
|
const alertsTableDefaultFilters = useMemo(
|
||||||
() => [
|
() => [
|
||||||
...buildAlertsRuleIdFilter(ruleId),
|
...buildAlertsRuleIdFilter(ruleId),
|
||||||
...filters,
|
|
||||||
...(ruleRegistryEnabled
|
...(ruleRegistryEnabled
|
||||||
? [
|
? [
|
||||||
// TODO: Once we are past experimental phase this code should be removed
|
// TODO: Once we are past experimental phase this code should be removed
|
||||||
|
@ -400,7 +399,7 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
|
||||||
: [...buildShowBuildingBlockFilter(showBuildingBlockAlerts)]),
|
: [...buildShowBuildingBlockFilter(showBuildingBlockAlerts)]),
|
||||||
...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts),
|
...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts),
|
||||||
],
|
],
|
||||||
[ruleId, filters, ruleRegistryEnabled, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts]
|
[ruleId, ruleRegistryEnabled, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts]
|
||||||
);
|
);
|
||||||
|
|
||||||
const alertMergedFilters = useMemo(
|
const alertMergedFilters = useMemo(
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
import { EuiDataGridColumn, EuiDataGridColumnCellActionProps } from '@elastic/eui';
|
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 { BrowserFields } from '../../../search_strategy/index_fields';
|
||||||
import { TimelineNonEcsData } from '../../../search_strategy/timeline';
|
import { TimelineNonEcsData } from '../../../search_strategy/timeline';
|
||||||
|
|
||||||
|
@ -45,14 +45,16 @@ export type ColumnId = string;
|
||||||
export type TGridCellAction = ({
|
export type TGridCellAction = ({
|
||||||
browserFields,
|
browserFields,
|
||||||
data,
|
data,
|
||||||
timelineId,
|
globalFilters,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
timelineId,
|
||||||
}: {
|
}: {
|
||||||
browserFields: BrowserFields;
|
browserFields: BrowserFields;
|
||||||
/** each row of data is represented as one TimelineNonEcsData[] */
|
/** each row of data is represented as one TimelineNonEcsData[] */
|
||||||
data: TimelineNonEcsData[][];
|
data: TimelineNonEcsData[][];
|
||||||
timelineId: string;
|
globalFilters?: Filter[];
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
|
timelineId: string;
|
||||||
}) => (props: EuiDataGridColumnCellActionProps) => ReactNode;
|
}) => (props: EuiDataGridColumnCellActionProps) => ReactNode;
|
||||||
|
|
||||||
/** The specification of a column header */
|
/** The specification of a column header */
|
||||||
|
|
|
@ -74,6 +74,7 @@ import type { EuiTheme } from '../../../../../../../src/plugins/kibana_react/com
|
||||||
import { ViewSelection } from '../event_rendered_view/selector';
|
import { ViewSelection } from '../event_rendered_view/selector';
|
||||||
import { EventRenderedView } from '../event_rendered_view';
|
import { EventRenderedView } from '../event_rendered_view';
|
||||||
import { useDataGridHeightHack } from './height_hack';
|
import { useDataGridHeightHack } from './height_hack';
|
||||||
|
import { Filter } from '../../../../../../../src/plugins/data/public';
|
||||||
|
|
||||||
const StatefulAlertStatusBulkActions = lazy(
|
const StatefulAlertStatusBulkActions = lazy(
|
||||||
() => import('../toolbar/bulk_actions/alert_status_bulk_actions')
|
() => import('../toolbar/bulk_actions/alert_status_bulk_actions')
|
||||||
|
@ -86,6 +87,7 @@ interface OwnProps {
|
||||||
bulkActions?: BulkActionsProp;
|
bulkActions?: BulkActionsProp;
|
||||||
data: TimelineItem[];
|
data: TimelineItem[];
|
||||||
defaultCellActions?: TGridCellAction[];
|
defaultCellActions?: TGridCellAction[];
|
||||||
|
filters?: Filter[];
|
||||||
filterQuery: string;
|
filterQuery: string;
|
||||||
filterStatus?: AlertStatus;
|
filterStatus?: AlertStatus;
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -300,15 +302,18 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
||||||
data,
|
data,
|
||||||
defaultCellActions,
|
defaultCellActions,
|
||||||
filterQuery,
|
filterQuery,
|
||||||
|
filters,
|
||||||
filterStatus,
|
filterStatus,
|
||||||
|
hasAlertsCrud,
|
||||||
|
hasAlertsCrudPermissions,
|
||||||
id,
|
id,
|
||||||
indexNames,
|
indexNames,
|
||||||
isEventViewer = false,
|
isEventViewer = false,
|
||||||
|
isLoading,
|
||||||
isSelectAllChecked,
|
isSelectAllChecked,
|
||||||
itemsPerPageOptions,
|
itemsPerPageOptions,
|
||||||
leadingControlColumns = EMPTY_CONTROL_COLUMNS,
|
leadingControlColumns = EMPTY_CONTROL_COLUMNS,
|
||||||
loadingEventIds,
|
loadingEventIds,
|
||||||
isLoading,
|
|
||||||
loadPage,
|
loadPage,
|
||||||
onRuleChange,
|
onRuleChange,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
@ -322,11 +327,9 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
||||||
tableView = 'gridView',
|
tableView = 'gridView',
|
||||||
tabType,
|
tabType,
|
||||||
totalItems,
|
totalItems,
|
||||||
|
totalSelectAllAlerts,
|
||||||
trailingControlColumns = EMPTY_CONTROL_COLUMNS,
|
trailingControlColumns = EMPTY_CONTROL_COLUMNS,
|
||||||
unit = defaultUnit,
|
unit = defaultUnit,
|
||||||
hasAlertsCrud,
|
|
||||||
hasAlertsCrudPermissions,
|
|
||||||
totalSelectAllAlerts,
|
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const getManageTimeline = useMemo(() => tGridSelectors.getManageTimelineById(), []);
|
const getManageTimeline = useMemo(() => tGridSelectors.getManageTimelineById(), []);
|
||||||
|
@ -641,10 +644,11 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
||||||
columnHeaders.map((header) => {
|
columnHeaders.map((header) => {
|
||||||
const buildAction = (tGridCellAction: TGridCellAction) =>
|
const buildAction = (tGridCellAction: TGridCellAction) =>
|
||||||
tGridCellAction({
|
tGridCellAction({
|
||||||
data: data.map((row) => row.data),
|
|
||||||
browserFields,
|
browserFields,
|
||||||
timelineId: id,
|
data: data.map((row) => row.data),
|
||||||
|
globalFilters: filters,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
timelineId: id,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -653,7 +657,7 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
||||||
header.tGridCellActions?.map(buildAction) ?? defaultCellActions?.map(buildAction),
|
header.tGridCellActions?.map(buildAction) ?? defaultCellActions?.map(buildAction),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
[browserFields, columnHeaders, data, defaultCellActions, id, pageSize]
|
[browserFields, columnHeaders, data, defaultCellActions, id, pageSize, filters]
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderTGridCellValue = useMemo(() => {
|
const renderTGridCellValue = useMemo(() => {
|
||||||
|
|
|
@ -347,30 +347,31 @@ const TGridIntegratedComponent: React.FC<TGridIntegratedProps> = ({
|
||||||
>
|
>
|
||||||
<ScrollableFlexItem grow={1}>
|
<ScrollableFlexItem grow={1}>
|
||||||
<StatefulBody
|
<StatefulBody
|
||||||
hasAlertsCrud={hasAlertsCrud}
|
|
||||||
activePage={pageInfo.activePage}
|
activePage={pageInfo.activePage}
|
||||||
browserFields={browserFields}
|
browserFields={browserFields}
|
||||||
bulkActions={bulkActions}
|
bulkActions={bulkActions}
|
||||||
filterQuery={filterQuery}
|
|
||||||
data={nonDeletedEvents}
|
data={nonDeletedEvents}
|
||||||
defaultCellActions={defaultCellActions}
|
defaultCellActions={defaultCellActions}
|
||||||
|
filterQuery={filterQuery}
|
||||||
|
filters={filters}
|
||||||
|
filterStatus={filterStatus}
|
||||||
|
hasAlertsCrud={hasAlertsCrud}
|
||||||
id={id}
|
id={id}
|
||||||
|
indexNames={indexNames}
|
||||||
isEventViewer={true}
|
isEventViewer={true}
|
||||||
itemsPerPageOptions={itemsPerPageOptions}
|
itemsPerPageOptions={itemsPerPageOptions}
|
||||||
|
leadingControlColumns={leadingControlColumns}
|
||||||
loadPage={loadPage}
|
loadPage={loadPage}
|
||||||
onRuleChange={onRuleChange}
|
onRuleChange={onRuleChange}
|
||||||
pageSize={itemsPerPage}
|
pageSize={itemsPerPage}
|
||||||
|
refetch={refetch}
|
||||||
renderCellValue={renderCellValue}
|
renderCellValue={renderCellValue}
|
||||||
rowRenderers={rowRenderers}
|
rowRenderers={rowRenderers}
|
||||||
tabType={TimelineTabs.query}
|
|
||||||
tableView={tableView}
|
tableView={tableView}
|
||||||
|
tabType={TimelineTabs.query}
|
||||||
totalItems={totalCountMinusDeleted}
|
totalItems={totalCountMinusDeleted}
|
||||||
unit={unit}
|
|
||||||
filterStatus={filterStatus}
|
|
||||||
leadingControlColumns={leadingControlColumns}
|
|
||||||
trailingControlColumns={trailingControlColumns}
|
trailingControlColumns={trailingControlColumns}
|
||||||
refetch={refetch}
|
unit={unit}
|
||||||
indexNames={indexNames}
|
|
||||||
/>
|
/>
|
||||||
</ScrollableFlexItem>
|
</ScrollableFlexItem>
|
||||||
</FullWidthFlexGroup>
|
</FullWidthFlexGroup>
|
||||||
|
|
Loading…
Reference in a new issue