diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx index dc6a0ea238310..1d1dd112da377 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx @@ -10,6 +10,8 @@ import { mount, shallow } from 'enzyme'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { fetchExceptionListsItemsByListIds } from '@kbn/securitysolution-list-api'; + import { ExceptionsViewer } from '.'; import { useKibana } from '../../../../common/lib/kibana'; import { TestProviders } from '../../../../common/mock'; @@ -20,6 +22,7 @@ import * as i18n from './translations'; jest.mock('../../../../common/lib/kibana'); jest.mock('@kbn/securitysolution-list-hooks'); +jest.mock('@kbn/securitysolution-list-api'); jest.mock('../../logic/use_find_references'); jest.mock('react', () => { const r = jest.requireActual('react'); @@ -78,6 +81,8 @@ describe('ExceptionsViewer', () => { }, }); + (fetchExceptionListsItemsByListIds as jest.Mock).mockReturnValue({ total: 0 }); + (useFindExceptionListReferences as jest.Mock).mockReturnValue([ false, false, @@ -130,6 +135,7 @@ describe('ExceptionsViewer', () => { exceptionToEdit: null, viewerState: 'loading', exceptionLists: [], + exceptionsToShow: { active: true }, }, jest.fn(), ]); @@ -168,6 +174,7 @@ describe('ExceptionsViewer', () => { exceptionToEdit: null, viewerState: 'empty_search', exceptionLists: [], + exceptionsToShow: { active: true }, }, jest.fn(), ]); @@ -206,6 +213,7 @@ describe('ExceptionsViewer', () => { exceptionToEdit: null, viewerState: 'empty', exceptionLists: [], + exceptionsToShow: { active: true }, }, jest.fn(), ]); @@ -250,6 +258,7 @@ describe('ExceptionsViewer', () => { exceptionToEdit: null, viewerState: 'empty', exceptionLists: [], + exceptionsToShow: { active: true }, }, jest.fn(), ]); @@ -294,6 +303,7 @@ describe('ExceptionsViewer', () => { exceptionToEdit: null, viewerState: null, exceptionLists: [], + exceptionsToShow: { active: true }, }, jest.fn(), ]); @@ -328,6 +338,7 @@ describe('ExceptionsViewer', () => { exceptionToEdit: sampleExceptionItem, viewerState: null, exceptionLists: [], + exceptionsToShow: { active: true }, }, jest.fn(), ]); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx index fb0528f248619..3b4117d370a7d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx @@ -45,7 +45,7 @@ const StyledText = styled(EuiText)` font-style: italic; `; -const STATES_SEARCH_HIDDEN: ViewerState[] = ['error', 'empty']; +const STATES_FILTERS_HIDDEN: ViewerState[] = ['error']; const STATES_PAGINATION_UTILITY_HIDDEN: ViewerState[] = [ 'loading', 'empty_search', @@ -299,6 +299,24 @@ const ExceptionsViewerComponent = ({ ] ); + const totalExceptionCount = useMemo(async () => { + const abortCtrl = new AbortController(); + + if (exceptionListsToQuery.length === 0) { + return 0; + } + + const { total } = await fetchExceptionListsItemsByListIds({ + filter: undefined, + http: services.http, + listIds: exceptionListsToQuery.map((list) => list.list_id), + namespaceTypes, + pagination: {}, + signal: abortCtrl.signal, + }); + return total; + }, [exceptionListsToQuery, namespaceTypes, services.http]); + const handleGetExceptionListItems = useCallback( async (options?: GetExceptionItemProps) => { try { @@ -314,7 +332,9 @@ const ExceptionsViewerComponent = ({ }, }); - setViewerState(total > 0 ? null : 'empty'); + setViewerState( + total > 0 ? null : (await totalExceptionCount) > 0 ? 'empty_search' : 'empty' + ); } catch (e) { setViewerState('error'); @@ -324,7 +344,7 @@ const ExceptionsViewerComponent = ({ }); } }, - [handleFetchItems, setExceptions, setViewerState, toasts] + [handleFetchItems, setExceptions, setViewerState, toasts, totalExceptionCount] ); const handleSearch = useCallback( @@ -485,27 +505,25 @@ const ExceptionsViewerComponent = ({ {isEndpointSpecified ? i18n.ENDPOINT_EXCEPTIONS_TAB_ABOUT : i18n.EXCEPTIONS_TAB_ABOUT} - {!STATES_SEARCH_HIDDEN.includes(viewerState) && ( - - )} - {!STATES_PAGINATION_UTILITY_HIDDEN.includes(viewerState) && ( + {!STATES_FILTERS_HIDDEN.includes(viewerState) && ( <> - - + + )} + { totalItemCount: 105, pageSizeOptions: [5, 10, 20, 50, 100], }} - exceptionsToShow={{}} + exceptionsToShow={{ active: true }} onChangeExceptionsToShow={(optionId: string) => {}} lastUpdated={1660534202} /> @@ -44,7 +44,7 @@ describe('ExceptionsViewerUtility', () => { totalItemCount: 1, pageSizeOptions: [5, 10, 20, 50, 100], }} - exceptionsToShow={{}} + exceptionsToShow={{ active: true }} onChangeExceptionsToShow={(optionId: string) => {}} lastUpdated={Date.now()} /> diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx index 7edb968356901..925d09a4ae938 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx @@ -60,7 +60,7 @@ const ExceptionsViewerUtilityComponent: React.FC = defaultMessage="Showing {partOne} of {partTwo}" values={{ partOne: ( - {`1-${Math.min( + {`${pagination.totalItemCount === 0 ? '0' : '1'}-${Math.min( pagination.pageSize, pagination.totalItemCount )}`}