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 9ba216b80f14e..d090f5a3bc590 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 @@ -6,20 +6,21 @@ */ import React, { useCallback, useMemo, useEffect, useReducer } from 'react'; -import { EuiPanel, EuiSpacer } from '@elastic/eui'; +import { EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; import type { ExceptionListItemSchema, UseExceptionListItemsSuccess, Pagination, - ExceptionListTypeEnum, } from '@kbn/securitysolution-io-ts-list-types'; +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { transformInput } from '@kbn/securitysolution-list-hooks'; import { deleteExceptionListItemById, fetchExceptionListsItemsByListIds, } from '@kbn/securitysolution-list-api'; +import styled from 'styled-components'; import { DEFAULT_INDEX_PATTERN } from '../../../../../common/constants'; import { useUserData } from '../../../../detections/components/user_info'; import { useKibana, useToasts } from '../../../../common/lib/kibana'; @@ -37,6 +38,10 @@ import * as i18n from './translations'; import { useFindExceptionListReferences } from '../../logic/use_find_references'; import type { Rule } from '../../../../detections/containers/detection_engine/rules/types'; +const StyledText = styled(EuiText)` + font-style: italic; +`; + const STATES_SEARCH_HIDDEN: ViewerState[] = ['error', 'empty']; const STATES_PAGINATION_UTILITY_HIDDEN: ViewerState[] = [ 'loading', @@ -51,7 +56,7 @@ const initialState: State = { pageIndex: 0, pageSize: 25, totalItemCount: 0, - pageSizeOptions: [1, 5, 10, 25, 50, 100, 200, 300], + pageSizeOptions: [5, 10, 25, 50, 100, 200, 300], }, exceptions: [], exceptionToEdit: null, @@ -154,7 +159,18 @@ const ExceptionsViewerComponent = ({ [dispatch] ); - const [_, allReferences] = useFindExceptionListReferences(exceptionListsToQuery); + const [isLoadingReferences, isFetchReferencesError, allReferences] = + useFindExceptionListReferences(exceptionListsToQuery); + + useEffect(() => { + if (isFetchReferencesError) { + setViewerState('error'); + } else if (viewerState == null && isLoadingReferences) { + setViewerState('loading'); + } else if (viewerState === 'loading' && !isLoadingReferences) { + setViewerState(null); + } + }, [isLoadingReferences, isFetchReferencesError, setViewerState, viewerState]); const handleFetchItems = useCallback( async (options?: GetExceptionItemProps) => { @@ -212,12 +228,8 @@ const ExceptionsViewerComponent = ({ const handleGetExceptionListItems = useCallback( async (options?: GetExceptionItemProps) => { try { - setViewerState('loading'); - const { pageIndex, itemsPerPage, total, data } = await handleFetchItems(options); - setViewerState(total > 0 ? null : 'empty'); - setExceptions({ exceptions: data, pagination: { @@ -226,6 +238,8 @@ const ExceptionsViewerComponent = ({ total, }, }); + + setViewerState(total > 0 ? null : 'empty'); } catch (e) { setViewerState('error'); @@ -367,6 +381,12 @@ const ExceptionsViewerComponent = ({ <> + + {listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.ENDPOINT_EXCEPTIONS_TAB_ABOUT + : i18n.EXCEPTIONS_TAB_ABOUT} + + {!STATES_SEARCH_HIDDEN.includes(viewerState) && ( { return listType === ExceptionListTypeEnum.ENDPOINT - ? i18n.ADD_TO_ENDPOINT_LIST - : i18n.ADD_TO_DETECTIONS_LIST; + ? sharedI18n.ADD_TO_ENDPOINT_LIST + : sharedI18n.ADD_TO_DETECTIONS_LIST; }, [listType]); return ( @@ -84,7 +85,7 @@ const ExceptionsViewerSearchBarComponent = ({ values: { itemName }, defaultMessage: '"{itemName}" deleted successfully.', }); + +export const ENDPOINT_EXCEPTIONS_TAB_ABOUT = i18n.translate( + 'xpack.securitySolution.exceptions.allExceptionItems.exceptionEndpointDetailsDescription', + { + defaultMessage: + 'Endpoint exceptions are added to both the detection rule and the Elastic Endpoint agent on your hosts.', + } +); + +export const EXCEPTIONS_TAB_ABOUT = i18n.translate( + 'xpack.securitySolution.exceptions.allExceptionItems.exceptionDetectionDetailsDescription', + { + defaultMessage: 'Rule exceptions are added to the detection rule.', + } +); + +export const SEARCH_PLACEHOLDER = i18n.translate( + 'xpack.securitySolution.exceptions.allExceptionItems.searchPlaceholder', + { + defaultMessage: 'Filter exceptions using simple query syntax, for example, name:"my list"', + } +); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx index f30d5aeb598a0..f7628f0014d23 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx @@ -14,7 +14,7 @@ import { useToasts } from '../../../common/lib/kibana'; import type { FindRulesReferencedByExceptionsListProp } from '../../../detections/containers/detection_engine/rules/types'; import * as i18n from '../utils/translations'; -export type ReturnUseFindExceptionListReferences = [boolean, RuleReferences | null]; +export type ReturnUseFindExceptionListReferences = [boolean, boolean, RuleReferences | null]; export interface RuleReferences { [key: string]: RuleReferenceSchema[]; @@ -28,6 +28,7 @@ export const useFindExceptionListReferences = ( ): ReturnUseFindExceptionListReferences => { const toasts = useToasts(); const [isLoading, setIsLoading] = useState(false); + const [errorExists, setErrorExists] = useState(false); const [references, setReferences] = useState(null); const listRefs = useMemo((): FindRulesReferencedByExceptionsListProp[] => { return ruleExceptionLists.map((list) => { @@ -61,11 +62,13 @@ export const useFindExceptionListReferences = ( }, {}); if (isSubscribed) { + setErrorExists(false); setIsLoading(false); setReferences(results); } } catch (error) { if (isSubscribed) { + setErrorExists(true); setIsLoading(false); toasts.addError(error, { title: i18n.ERROR_FETCHING_REFERENCES_TITLE }); } @@ -73,6 +76,7 @@ export const useFindExceptionListReferences = ( }; if (listRefs.length === 0 && isSubscribed) { + setErrorExists(false); setIsLoading(false); setReferences(null); } else { @@ -85,5 +89,5 @@ export const useFindExceptionListReferences = ( }; }, [ruleExceptionLists, listRefs, toasts]); - return [isLoading, references]; + return [isLoading, errorExists, references]; }; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/translations.ts index b22d4030384a3..8baf21db15c0d 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/translations.ts @@ -155,9 +155,9 @@ export const referenceErrorMessage = (referenceCount: number) => }); export const EXCEPTION_LIST_SEARCH_PLACEHOLDER = i18n.translate( - 'xpack.securitySolution.exceptions.searchPlaceholder', + 'xpack.securitySolution.detectionEngine.rules.all.exceptions.searchPlaceholder', { - defaultMessage: 'e.g. Example List Name', + defaultMessage: 'Search by name or list_id', } ); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 60b692e720ec0..09d5ebabd0d0a 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -28301,7 +28301,6 @@ "xpack.securitySolution.exceptions.referenceModalCancelButton": "Annuler", "xpack.securitySolution.exceptions.referenceModalDeleteButton": "Retirer la liste d'exceptions", "xpack.securitySolution.exceptions.referenceModalTitle": "Retirer la liste d'exceptions", - "xpack.securitySolution.exceptions.searchPlaceholder": "par ex. Exemple de liste de noms", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "Ajouter un nouveau commentaire...", "xpack.securitySolution.exceptions.viewer.addToClipboard": "Commentaire", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "Ajouter une exception à une règle", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0aa5fa39b93e0..32c2dbbf5f01e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -28276,7 +28276,6 @@ "xpack.securitySolution.exceptions.referenceModalCancelButton": "キャンセル", "xpack.securitySolution.exceptions.referenceModalDeleteButton": "例外リストを削除", "xpack.securitySolution.exceptions.referenceModalTitle": "例外リストを削除", - "xpack.securitySolution.exceptions.searchPlaceholder": "例:例外リスト名", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "新しいコメントを追加...", "xpack.securitySolution.exceptions.viewer.addToClipboard": "コメント", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "ルール例外の追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index baf98e70b8dd0..48fe03474e196 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -28310,7 +28310,6 @@ "xpack.securitySolution.exceptions.referenceModalCancelButton": "取消", "xpack.securitySolution.exceptions.referenceModalDeleteButton": "移除例外列表", "xpack.securitySolution.exceptions.referenceModalTitle": "移除例外列表", - "xpack.securitySolution.exceptions.searchPlaceholder": "例如,示例列表名称", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "添加新注释......", "xpack.securitySolution.exceptions.viewer.addToClipboard": "注释", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "添加规则例外",