diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx index 190110195730..65ade52ef7d3 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx @@ -64,6 +64,7 @@ const AlertsTableComponent: React.FC = ({ endDate, startDate, pageFilters documentType: i18n.ALERTS_DOCUMENT_TYPE, footerText: i18n.TOTAL_COUNT_OF_ALERTS, title: i18n.ALERTS_TABLE_TITLE, + unit: i18n.UNIT, }), [] ); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index 05a33eeba143..163b345da40b 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -154,20 +154,18 @@ const EventsViewerComponent: React.FC = ({ const totalCountMinusDeleted = totalCount > 0 ? totalCount - deletedEventIds.length : 0; + const subtitle = `${ + i18n.SHOWING + }: ${totalCountMinusDeleted.toLocaleString()} ${timelineTypeContext.unit?.( + totalCountMinusDeleted + ) ?? i18n.UNIT(totalCountMinusDeleted)}`; + // TODO: Reset eventDeletedIds/eventLoadingIds on refresh/loadmore (getUpdatedAt) return ( <> {headerFilterGroup} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx index 611452cc7ccd..15759c2efff0 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx @@ -23,6 +23,7 @@ export interface TimelineTypeContextProps { selectAll?: boolean; timelineActions?: TimelineAction[]; title?: string; + unit?: (totalCount: number) => string; } const initTimelineType: TimelineTypeContextProps = { documentType: undefined, @@ -32,6 +33,7 @@ const initTimelineType: TimelineTypeContextProps = { selectAll: false, timelineActions: [], title: undefined, + unit: undefined, }; export const TimelineTypeContext = createContext(initTimelineType); export const useTimelineTypeContext = () => useContext(TimelineTypeContext); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts index 6c9fd5c0ff3b..22fb837ffb80 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts @@ -28,6 +28,7 @@ import { DETECTION_ENGINE_PREPACKAGED_URL, DETECTION_ENGINE_RULES_STATUS_URL, DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL, + DETECTION_ENGINE_TAGS_URL, } from '../../../../common/constants'; import * as i18n from '../../../pages/detection_engine/rules/translations'; @@ -54,61 +55,72 @@ export const addRule = async ({ rule, signal }: AddRulesProps): Promise }; /** - * Fetches all rules or single specified rule from the Detection Engine API + * Fetches all rules from the Detection Engine API * * @param filterOptions desired filters (e.g. filter/sortField/sortOrder) * @param pagination desired pagination options (e.g. page/perPage) - * @param id if specified, will return specific rule if exists * @param signal to cancel request + * */ export const fetchRules = async ({ filterOptions = { filter: '', - sortField: 'name', + sortField: 'enabled', sortOrder: 'desc', + showCustomRules: false, + showElasticRules: false, + tags: [], }, pagination = { page: 1, perPage: 20, total: 0, }, - id, signal, }: FetchRulesProps): Promise => { + const filters = [ + ...(filterOptions.filter.length !== 0 + ? [`alert.attributes.name:%20${encodeURIComponent(filterOptions.filter)}`] + : []), + ...(filterOptions.showCustomRules + ? ['alert.attributes.tags:%20%22__internal_immutable:false%22'] + : []), + ...(filterOptions.showElasticRules + ? ['alert.attributes.tags:%20%22__internal_immutable:true%22'] + : []), + ...(filterOptions.tags?.map(t => `alert.attributes.tags:${encodeURIComponent(t)}`) ?? []), + ]; + const queryParams = [ `page=${pagination.page}`, `per_page=${pagination.perPage}`, `sort_field=${filterOptions.sortField}`, `sort_order=${filterOptions.sortOrder}`, - ...(filterOptions.filter.length !== 0 - ? [`filter=alert.attributes.name:%20${encodeURIComponent(filterOptions.filter)}`] - : []), + ...(filters.length > 0 ? [`filter=${filters.join('%20AND%20')}`] : []), ]; - const endpoint = - id != null - ? `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}?id="${id}"` - : `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}/_find?${queryParams.join('&')}`; - - const response = await fetch(endpoint, { - method: 'GET', - signal, - }); + const response = await fetch( + `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}/_find?${queryParams.join('&')}`, + { + method: 'GET', + credentials: 'same-origin', + headers: { + 'content-type': 'application/json', + 'kbn-xsrf': 'true', + }, + signal, + } + ); await throwIfNotOk(response); - return id != null - ? { - page: 0, - perPage: 1, - total: 1, - data: response.json(), - } - : response.json(); + return response.json(); }; /** * Fetch a Rule by providing a Rule ID * * @param id Rule ID's (not rule_id) + * @param signal to cancel request + * */ export const fetchRuleById = async ({ id, signal }: FetchRuleProps): Promise => { const response = await fetch(`${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}?id=${id}`, { @@ -344,6 +356,27 @@ export const getRuleStatusById = async ({ return response.json(); }; +/** + * Fetch all unique Tags used by Rules + * + * @param signal to cancel request + * + */ +export const fetchTags = async ({ signal }: { signal: AbortSignal }): Promise => { + const response = await fetch(`${chrome.getBasePath()}${DETECTION_ENGINE_TAGS_URL}`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'content-type': 'application/json', + 'kbn-xsrf': 'true', + }, + signal, + }); + + await throwIfNotOk(response); + return response.json(); +}; + /** * Get pre packaged rules Status * diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts index a493e471a9bf..84e008312fef 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts @@ -30,3 +30,10 @@ export const RULE_PREPACKAGED_SUCCESS = i18n.translate( defaultMessage: 'Installed pre-packaged rules from elastic', } ); + +export const TAG_FETCH_FAILURE = i18n.translate( + 'xpack.siem.containers.detectionEngine.tagFetchFailDescription', + { + defaultMessage: 'Failed to fetch Tags', + } +); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts index 0dcd0da5be8f..2e776738547d 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts @@ -114,7 +114,6 @@ export interface PaginationOptions { export interface FetchRulesProps { pagination?: PaginationOptions; filterOptions?: FilterOptions; - id?: string; signal: AbortSignal; } @@ -122,6 +121,9 @@ export interface FilterOptions { filter: string; sortField: string; sortOrder: 'asc' | 'desc'; + showCustomRules?: boolean; + showElasticRules?: boolean; + tags?: string[]; } export interface FetchRulesResponse { diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx index 04475ab1bc17..254e8cbdc9a8 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx @@ -70,6 +70,9 @@ export const useRules = (pagination: PaginationOptions, filterOptions: FilterOpt filterOptions.filter, filterOptions.sortField, filterOptions.sortOrder, + filterOptions.tags?.sort().join(), + filterOptions.showCustomRules, + filterOptions.showElasticRules, ]); return [loading, rules, reFetchRules.current]; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_tags.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_tags.tsx new file mode 100644 index 000000000000..1c961d530422 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_tags.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useEffect, useState } from 'react'; +import { useStateToaster } from '../../../components/toasters'; +import { fetchTags } from './api'; +import { errorToToaster } from '../../../components/ml/api/error_to_toaster'; +import * as i18n from './translations'; + +type Return = [boolean, string[]]; + +/** + * Hook for using the list of Tags from the Detection Engine API + * + */ +export const useTags = (): Return => { + const [tags, setTags] = useState([]); + const [loading, setLoading] = useState(true); + const [, dispatchToaster] = useStateToaster(); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + async function fetchData() { + setLoading(true); + try { + const fetchTagsResult = await fetchTags({ + signal: abortCtrl.signal, + }); + + if (isSubscribed) { + setTags(fetchTagsResult); + } + } catch (error) { + if (isSubscribed) { + errorToToaster({ title: i18n.TAG_FETCH_FAILURE, error, dispatchToaster }); + } + } + if (isSubscribed) { + setLoading(false); + } + } + + fetchData(); + + return () => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, []); + + return [loading, tags]; +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts index b79b3ed091f1..b62247e8f9a4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts @@ -56,13 +56,10 @@ export const mockTableData: TableData[] = [ id: 'abe6c564-050d-45a5-aaf0-386c37dd1f61', immutable: false, isLoading: false, - lastCompletedRun: undefined, - lastResponse: { type: '—' }, - method: 'saved_query', + risk_score: 21, rule: { href: '#/detections/rules/id/abe6c564-050d-45a5-aaf0-386c37dd1f61', name: 'Home Grown!', - status: 'Status Placeholder', }, rule_id: 'b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea', severity: 'low', @@ -108,13 +105,10 @@ export const mockTableData: TableData[] = [ id: '63f06f34-c181-4b2d-af35-f2ace572a1ee', immutable: false, isLoading: false, - lastCompletedRun: undefined, - lastResponse: { type: '—' }, - method: 'saved_query', + risk_score: 21, rule: { href: '#/detections/rules/id/63f06f34-c181-4b2d-af35-f2ace572a1ee', name: 'Home Grown!', - status: 'Status Placeholder', }, rule_id: 'b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea', severity: 'low', diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx index d546c4edb55d..d648854368c2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx @@ -31,6 +31,7 @@ import { RuleSwitch } from '../components/rule_switch'; import { SeverityBadge } from '../components/severity_badge'; import { ActionToaster } from '../../../../components/toasters'; import { getStatusColor } from '../components/rule_status/helpers'; +import { TruncatableText } from '../../../../components/truncatable_text'; const getActions = ( dispatch: React.Dispatch, @@ -84,8 +85,8 @@ export const getColumns = ( width: '24%', }, { - field: 'method', - name: i18n.COLUMN_METHOD, + field: 'risk_score', + name: i18n.COLUMN_RISK_SCORE, truncateText: true, width: '14%', }, @@ -129,13 +130,13 @@ export const getColumns = ( field: 'tags', name: i18n.COLUMN_TAGS, render: (value: TableData['tags']) => ( - <> + {value.map((tag, i) => ( {tag} ))} - + ), truncateText: true, width: '20%', diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts index 07a2f2f27898..3616d4dbaad2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts @@ -10,7 +10,6 @@ import { RuleResponseBuckets, } from '../../../../containers/detection_engine/rules'; import { TableData } from '../types'; -import { getEmptyValue } from '../../../../components/empty_value'; /** * Formats rules into the correct format for the AllRulesTable @@ -26,14 +25,9 @@ export const formatRules = (rules: Rule[], selectedIds?: string[]): TableData[] rule: { href: `#/detections/rules/id/${encodeURIComponent(rule.id)}`, name: rule.name, - status: 'Status Placeholder', }, - method: rule.type, // TODO: Map to i18n? + risk_score: rule.risk_score, severity: rule.severity, - lastCompletedRun: undefined, // TODO: Not available yet - lastResponse: { - type: getEmptyValue(), // TODO: Not available yet - }, tags: rule.tags ?? [], activate: rule.enabled, status: rule.status ?? null, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx index 677033b25883..a4e7d7a3615c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx @@ -6,8 +6,9 @@ import { EuiBasicTable, + EuiButton, EuiContextMenuPanel, - EuiFieldSearch, + EuiEmptyPrompt, EuiLoadingContent, EuiSpacer, } from '@elastic/eui'; @@ -16,7 +17,11 @@ import React, { useCallback, useEffect, useMemo, useReducer, useState } from 're import { useHistory } from 'react-router-dom'; import uuid from 'uuid'; -import { useRules, CreatePreBuiltRules } from '../../../../containers/detection_engine/rules'; +import { + useRules, + CreatePreBuiltRules, + FilterOptions, +} from '../../../../containers/detection_engine/rules'; import { HeaderSection } from '../../../../components/header_section'; import { UtilityBar, @@ -36,6 +41,8 @@ import { EuiBasicTableOnChange, TableData } from '../types'; import { getBatchItems } from './batch_actions'; import { getColumns } from './columns'; import { allRulesReducer, State } from './reducer'; +import { RulesTableFilters } from './rules_table_filters/rules_table_filters'; +import { DETECTION_ENGINE_PAGE_NAME } from '../../../../components/link_to/redirect_to_detection_engine'; const initialState: State = { isLoading: true, @@ -209,6 +216,20 @@ export const AllRules = React.memo( [] ); + const onFilterChangedCallback = useCallback((newFilterOptions: Partial) => { + dispatch({ + type: 'updateFilterOptions', + filterOptions: { + ...filterOptions, + ...newFilterOptions, + }, + }); + dispatch({ + type: 'updatePagination', + pagination: { ...pagination, page: 1 }, + }); + }, []); + return ( <> ( <> {rulesInstalled != null && rulesInstalled > 0 && ( - - { - dispatch({ - type: 'updateFilterOptions', - filterOptions: { - ...filterOptions, - filter: filterString, - }, - }); - dispatch({ - type: 'updatePagination', - pagination: { ...pagination, page: 1 }, - }); - }} - /> + + )} {isInitialLoad && isEmpty(tableData) && ( @@ -301,6 +304,24 @@ export const AllRules = React.memo( isSelectable={!hasNoPermissions ?? false} itemId="id" items={tableData} + noItemsMessage={ + {i18n.NO_RULES}} + titleSize="xs" + body={i18n.NO_RULES_BODY} + actions={ + + {i18n.ADD_NEW_RULE} + + } + /> + } onChange={tableOnChangeCallback} pagination={{ pageIndex: pagination.page - 1, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx new file mode 100644 index 000000000000..daf519f5af69 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback, useEffect, useState } from 'react'; + +import { + EuiFieldSearch, + EuiFilterButton, + EuiFilterGroup, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; +import * as i18n from '../../translations'; + +import { FilterOptions } from '../../../../../containers/detection_engine/rules'; +import { useTags } from '../../../../../containers/detection_engine/rules/use_tags'; +import { TagsFilterPopover } from './tags_filter_popover'; + +interface RulesTableFiltersProps { + onFilterChanged: (filterOptions: Partial) => void; +} + +/** + * Collection of filters for filtering data within the RulesTable. Contains search bar, Elastic/Custom + * Rules filter button toggle, and tag selection + * + * @param onFilterChanged change listener to be notified on filter changes + */ +const RulesTableFiltersComponent = ({ onFilterChanged }: RulesTableFiltersProps) => { + const [filter, setFilter] = useState(''); + const [selectedTags, setSelectedTags] = useState([]); + const [showCustomRules, setShowCustomRules] = useState(false); + const [showElasticRules, setShowElasticRules] = useState(false); + const [isLoadingTags, tags] = useTags(); + + // Propagate filter changes to parent + useEffect(() => { + onFilterChanged({ filter, showCustomRules, showElasticRules, tags: selectedTags }); + }, [filter, selectedTags, showCustomRules, showElasticRules, onFilterChanged]); + + const handleOnSearch = useCallback(filterString => setFilter(filterString.trim()), [setFilter]); + + const handleElasticRulesClick = useCallback(() => { + setShowElasticRules(!showElasticRules); + setShowCustomRules(false); + }, [setShowElasticRules, showElasticRules, setShowCustomRules]); + + const handleCustomRulesClick = useCallback(() => { + setShowCustomRules(!showCustomRules); + setShowElasticRules(false); + }, [setShowElasticRules, showCustomRules, setShowCustomRules]); + + return ( + + + + + + + + + + + + + + + {i18n.ELASTIC_RULES} + + + {i18n.CUSTOM_RULES} + + + + + ); +}; + +RulesTableFiltersComponent.displayName = 'RulesTableFiltersComponent'; + +export const RulesTableFilters = React.memo(RulesTableFiltersComponent); + +RulesTableFilters.displayName = 'RulesTableFilters'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx new file mode 100644 index 000000000000..b9d2c97f063b --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import { + EuiFilterButton, + EuiFilterSelectItem, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiPopover, + EuiText, +} from '@elastic/eui'; +import styled from 'styled-components'; +import * as i18n from '../../translations'; +import { toggleSelectedGroup } from '../../../../../components/ml_popover/jobs_table/filters/toggle_selected_group'; + +interface TagsFilterPopoverProps { + tags: string[]; + onSelectedTagsChanged: Dispatch>; + isLoading: boolean; +} + +const ScrollableDiv = styled.div` + max-height: 250px; + overflow: auto; +`; + +/** + * Popover for selecting tags to filter on + * + * @param tags to display for filtering + * @param onSelectedTagsChanged change listener to be notified when tag selection changes + */ +export const TagsFilterPopoverComponent = ({ + tags, + onSelectedTagsChanged, +}: TagsFilterPopoverProps) => { + const [isTagPopoverOpen, setIsTagPopoverOpen] = useState(false); + const [selectedTags, setSelectedTags] = useState([]); + + useEffect(() => { + onSelectedTagsChanged(selectedTags); + }, [selectedTags.sort().join()]); + + return ( + setIsTagPopoverOpen(!isTagPopoverOpen)} + isSelected={isTagPopoverOpen} + hasActiveFilters={selectedTags.length > 0} + numActiveFilters={selectedTags.length} + > + {i18n.TAGS} + + } + isOpen={isTagPopoverOpen} + closePopover={() => setIsTagPopoverOpen(!isTagPopoverOpen)} + panelPaddingSize="none" + > + + {tags.map((tag, index) => ( + toggleSelectedGroup(tag, selectedTags, setSelectedTags)} + > + {`${tag}`} + + ))} + + {tags.length === 0 && ( + + + + {i18n.NO_TAGS_AVAILABLE} + + + + )} + + ); +}; + +TagsFilterPopoverComponent.displayName = 'TagsFilterPopoverComponent'; + +export const TagsFilterPopover = React.memo(TagsFilterPopoverComponent); + +TagsFilterPopover.displayName = 'TagsFilterPopover'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts index 672aab8ef831..5b1ee049371d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts @@ -213,10 +213,10 @@ export const COLUMN_RULE = i18n.translate( } ); -export const COLUMN_METHOD = i18n.translate( - 'xpack.siem.detectionEngine.rules.allRules.columns.methodTitle', +export const COLUMN_RISK_SCORE = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.columns.riskScoreTitle', { - defaultMessage: 'Method', + defaultMessage: 'Risk score', } ); @@ -255,16 +255,42 @@ export const COLUMN_ACTIVATE = i18n.translate( } ); -export const COLUMN_STATUS = i18n.translate( - 'xpack.siem.detectionEngine.rules.allRules.columns.currentStatusTitle', +export const CUSTOM_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.customRulesTitle', { - defaultMessage: 'Current status', + defaultMessage: 'Custom rules', } ); -export const NO_STATUS = i18n.translate( - 'xpack.siem.detectionEngine.rules.allRules.columns.unknownStatusDescription', + +export const ELASTIC_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.elasticRulesTitle', { - defaultMessage: 'Unknown', + defaultMessage: 'Elastic rules', + } +); + +export const TAGS = i18n.translate('xpack.siem.detectionEngine.rules.allRules.filters.tagsLabel', { + defaultMessage: 'Tags', +}); + +export const NO_TAGS_AVAILABLE = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.noTagsAvailableDescription', + { + defaultMessage: 'No tags available', + } +); + +export const NO_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.noRulesTitle', + { + defaultMessage: 'No rules found', + } +); + +export const NO_RULES_BODY = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.noRulesBodyTitle', + { + defaultMessage: "We weren't able to find any rules with the above filters.", } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts index 5ae516dda5b3..2b50e32a367e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts @@ -30,15 +30,9 @@ export interface TableData { rule: { href: string; name: string; - status: string; }; - method: string; + risk_score: number; severity: string; - lastCompletedRun: string | undefined; - lastResponse: { - type: string; - message?: string; - }; tags: string[]; activate: boolean; isLoading: boolean;