mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[RAM] Alert table reset pagination after filter (#157216)
## Summary Fix https://github.com/elastic/kibana/issues/157133 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
252d1a88d5
commit
ee3d4e4744
4 changed files with 144 additions and 12 deletions
|
@ -219,6 +219,10 @@ const AlertsTableStateWithQueryProvider = ({
|
|||
initialBrowserFields: propBrowserFields,
|
||||
});
|
||||
|
||||
const onPageChange = useCallback((_pagination: RuleRegistrySearchRequestPagination) => {
|
||||
setPagination(_pagination);
|
||||
}, []);
|
||||
|
||||
const [
|
||||
isLoading,
|
||||
{
|
||||
|
@ -236,6 +240,7 @@ const AlertsTableStateWithQueryProvider = ({
|
|||
featureIds,
|
||||
query,
|
||||
pagination,
|
||||
onPageChange,
|
||||
runtimeMappings,
|
||||
sort,
|
||||
skip: false,
|
||||
|
@ -261,10 +266,6 @@ const AlertsTableStateWithQueryProvider = ({
|
|||
fetchCases
|
||||
);
|
||||
|
||||
const onPageChange = useCallback((_pagination: RuleRegistrySearchRequestPagination) => {
|
||||
setPagination(_pagination);
|
||||
}, []);
|
||||
|
||||
const initialBulkActionsState = useReducer(bulkActionsReducer, {
|
||||
rowSelection: new Map<number, RowSelectionState>(),
|
||||
isAllSelected: false,
|
||||
|
@ -318,7 +319,7 @@ const AlertsTableStateWithQueryProvider = ({
|
|||
oldAlertsData,
|
||||
onPageChange,
|
||||
onSortChange,
|
||||
pagination.pageIndex,
|
||||
pagination,
|
||||
refresh,
|
||||
sort,
|
||||
updatedAt,
|
||||
|
@ -374,7 +375,7 @@ const AlertsTableStateWithQueryProvider = ({
|
|||
memoizedCases,
|
||||
columns,
|
||||
flyoutSize,
|
||||
pagination.pageSize,
|
||||
pagination,
|
||||
id,
|
||||
leadingControlColumns,
|
||||
showExpandToDetails,
|
||||
|
|
|
@ -11,6 +11,8 @@ import { act, renderHook } from '@testing-library/react-hooks';
|
|||
import { useFetchAlerts, FetchAlertsArgs, FetchAlertResp } from './use_fetch_alerts';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { IKibanaSearchResponse } from '@kbn/data-plugin/public';
|
||||
import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { useState } from 'react';
|
||||
|
||||
jest.mock('../../../../common/lib/kibana');
|
||||
|
||||
|
@ -88,6 +90,7 @@ const expectedResponse: FetchAlertResp = {
|
|||
|
||||
describe('useFetchAlerts', () => {
|
||||
let clock: sinon.SinonFakeTimers;
|
||||
const onPageChangeMock = jest.fn();
|
||||
const args: FetchAlertsArgs = {
|
||||
featureIds: ['siem'],
|
||||
fields: [
|
||||
|
@ -101,6 +104,7 @@ describe('useFetchAlerts', () => {
|
|||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
},
|
||||
onPageChange: onPageChangeMock,
|
||||
sort: [],
|
||||
skip: false,
|
||||
};
|
||||
|
@ -474,4 +478,75 @@ describe('useFetchAlerts', () => {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('reset pagination when query is used', async () => {
|
||||
const useWrapperHook = ({ query }: { query: Pick<QueryDslQueryContainer, 'bool' | 'ids'> }) => {
|
||||
const [pagination, setPagination] = useState({ pageIndex: 5, pageSize: 10 });
|
||||
const handlePagination = (newPagination: { pageIndex: number; pageSize: number }) => {
|
||||
onPageChangeMock(newPagination);
|
||||
setPagination(newPagination);
|
||||
};
|
||||
const result = useFetchAlerts({
|
||||
...args,
|
||||
pagination,
|
||||
onPageChange: handlePagination,
|
||||
query,
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const { rerender } = renderHook(
|
||||
({ initialValue }) =>
|
||||
useWrapperHook({
|
||||
query: initialValue,
|
||||
}),
|
||||
{
|
||||
initialProps: { initialValue: {} },
|
||||
}
|
||||
);
|
||||
|
||||
expect(dataSearchMock).lastCalledWith(
|
||||
{
|
||||
featureIds: args.featureIds,
|
||||
fields: [...args.fields],
|
||||
pagination: {
|
||||
pageIndex: 5,
|
||||
pageSize: 10,
|
||||
},
|
||||
query: {},
|
||||
sort: args.sort,
|
||||
},
|
||||
{ abortSignal: expect.anything(), strategy: 'privateRuleRegistryAlertsSearchStrategy' }
|
||||
);
|
||||
|
||||
rerender({
|
||||
initialValue: {
|
||||
ids: {
|
||||
values: ['alert-id-1'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(dataSearchMock).lastCalledWith(
|
||||
{
|
||||
featureIds: args.featureIds,
|
||||
fields: [...args.fields],
|
||||
pagination: {
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
},
|
||||
query: {
|
||||
ids: {
|
||||
values: ['alert-id-1'],
|
||||
},
|
||||
},
|
||||
sort: args.sort,
|
||||
},
|
||||
{ abortSignal: expect.anything(), strategy: 'privateRuleRegistryAlertsSearchStrategy' }
|
||||
);
|
||||
expect(onPageChangeMock).lastCalledWith({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,6 +15,7 @@ import { Subscription } from 'rxjs';
|
|||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
||||
import type {
|
||||
RuleRegistrySearchRequest,
|
||||
RuleRegistrySearchRequestPagination,
|
||||
RuleRegistrySearchResponse,
|
||||
} from '@kbn/rule-registry-plugin/common/search_strategy';
|
||||
import type {
|
||||
|
@ -36,12 +37,13 @@ export interface FetchAlertsArgs {
|
|||
pageIndex: number;
|
||||
pageSize: number;
|
||||
};
|
||||
onPageChange: (pagination: RuleRegistrySearchRequestPagination) => void;
|
||||
runtimeMappings?: MappingRuntimeFields;
|
||||
sort: SortCombinations[];
|
||||
skip: boolean;
|
||||
}
|
||||
|
||||
type AlertRequest = Omit<FetchAlertsArgs, 'featureIds' | 'skip'>;
|
||||
type AlertRequest = Omit<FetchAlertsArgs, 'featureIds' | 'skip' | 'onPageChange'>;
|
||||
|
||||
type Refetch = () => void;
|
||||
|
||||
|
@ -67,7 +69,7 @@ export interface FetchAlertResp {
|
|||
type AlertResponseState = Omit<FetchAlertResp, 'getInspectQuery' | 'refetch'>;
|
||||
interface AlertStateReducer {
|
||||
loading: boolean;
|
||||
request: Omit<FetchAlertsArgs, 'skip'>;
|
||||
request: Omit<FetchAlertsArgs, 'skip' | 'onPageChange'>;
|
||||
response: AlertResponseState;
|
||||
}
|
||||
|
||||
|
@ -81,7 +83,7 @@ type AlertActions =
|
|||
ecsAlertsData: unknown[];
|
||||
}
|
||||
| { type: 'resetPagination' }
|
||||
| { type: 'request'; request: Omit<FetchAlertsArgs, 'skip'> };
|
||||
| { type: 'request'; request: Omit<FetchAlertsArgs, 'skip' | 'onPageChange'> };
|
||||
|
||||
const initialAlertState: AlertStateReducer = {
|
||||
loading: false,
|
||||
|
@ -146,6 +148,7 @@ export type UseFetchAlerts = ({
|
|||
fields,
|
||||
query,
|
||||
pagination,
|
||||
onPageChange,
|
||||
runtimeMappings,
|
||||
skip,
|
||||
sort,
|
||||
|
@ -155,6 +158,7 @@ const useFetchAlerts = ({
|
|||
fields,
|
||||
query,
|
||||
pagination,
|
||||
onPageChange,
|
||||
runtimeMappings,
|
||||
skip,
|
||||
sort,
|
||||
|
@ -279,6 +283,9 @@ const useFetchAlerts = ({
|
|||
[skip, data, featureIds, query, fields]
|
||||
);
|
||||
|
||||
// FUTURE ENGINEER
|
||||
// This useEffect is only to fetch the alert when these props below changed
|
||||
// fields, pagination, sort, runtimeMappings
|
||||
useEffect(() => {
|
||||
if (featureIds.length === 0) {
|
||||
return;
|
||||
|
@ -287,7 +294,7 @@ const useFetchAlerts = ({
|
|||
featureIds,
|
||||
fields,
|
||||
pagination,
|
||||
query,
|
||||
query: prevAlertRequest.current?.query ?? {},
|
||||
runtimeMappings,
|
||||
sort,
|
||||
};
|
||||
|
@ -300,7 +307,37 @@ const useFetchAlerts = ({
|
|||
request: newAlertRequest,
|
||||
});
|
||||
}
|
||||
}, [featureIds, fields, pagination, query, sort, runtimeMappings]);
|
||||
}, [featureIds, fields, pagination, sort, runtimeMappings]);
|
||||
|
||||
// FUTURE ENGINEER
|
||||
// This useEffect is only to fetch the alert when query props changed
|
||||
// because we want to reset the pageIndex of pagination to 0
|
||||
useEffect(() => {
|
||||
if (featureIds.length === 0 || !prevAlertRequest.current) {
|
||||
return;
|
||||
}
|
||||
const resetPagination = {
|
||||
pageIndex: 0,
|
||||
pageSize: prevAlertRequest.current?.pagination?.pageSize ?? 50,
|
||||
};
|
||||
const newAlertRequest = {
|
||||
...prevAlertRequest.current,
|
||||
featureIds,
|
||||
pagination: resetPagination,
|
||||
query,
|
||||
};
|
||||
|
||||
if (
|
||||
(newAlertRequest?.fields ?? []).length > 0 &&
|
||||
!deepEqual(newAlertRequest.query, prevAlertRequest.current.query)
|
||||
) {
|
||||
dispatch({
|
||||
type: 'request',
|
||||
request: newAlertRequest,
|
||||
});
|
||||
onPageChange(resetPagination);
|
||||
}
|
||||
}, [featureIds, onPageChange, query]);
|
||||
|
||||
useEffect(() => {
|
||||
if (alertRequest.featureIds.length > 0 && !deepEqual(alertRequest, prevAlertRequest.current)) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { useCallback, useContext, useState } from 'react';
|
||||
import { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { RuleRegistrySearchRequestPagination } from '@kbn/rule-registry-plugin/common';
|
||||
import { BulkActionsVerbs } from '../../../../types';
|
||||
import { BulkActionsContext } from '../bulk_actions/context';
|
||||
|
@ -75,6 +75,25 @@ export function usePagination({ onPageChange, pageIndex, pageSize }: PaginationP
|
|||
[onChangePageIndex, pagination.pageIndex, pagination.pageSize]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setPagination((prevPagination) => {
|
||||
const newPagination = { ...prevPagination };
|
||||
let updated = false;
|
||||
if (prevPagination.pageIndex !== pageIndex) {
|
||||
updated = true;
|
||||
newPagination.pageIndex = pageIndex;
|
||||
}
|
||||
if (prevPagination.pageSize !== pageSize) {
|
||||
updated = true;
|
||||
newPagination.pageSize = pageSize;
|
||||
}
|
||||
if (updated === true) {
|
||||
return newPagination;
|
||||
}
|
||||
return prevPagination;
|
||||
});
|
||||
}, [pageIndex, pageSize]);
|
||||
|
||||
return {
|
||||
pagination,
|
||||
onChangePageSize,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue