From 69091b4f5a784b45750d75c607adf1b2bb010b59 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 16 Nov 2021 13:58:03 +0100 Subject: [PATCH 01/25] Add AlertStatus types --- x-pack/plugins/observability/common/typings.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/x-pack/plugins/observability/common/typings.ts b/x-pack/plugins/observability/common/typings.ts index bccb0f4491009..012f91af56fee 100644 --- a/x-pack/plugins/observability/common/typings.ts +++ b/x-pack/plugins/observability/common/typings.ts @@ -25,3 +25,13 @@ export interface ApmIndicesConfig { apmAgentConfigurationIndex: string; apmCustomLinkIndex: string; } +export enum AlertStatus { + All = 'all', + Active = 'active', + Recovered = 'recovered', +} +export interface AlertStatusFilter { + status: AlertStatus; + query: string; + label: string; +} From 38f182944538e8c1f6a0b1a04ead76b1da761f10 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 16 Nov 2021 13:58:27 +0100 Subject: [PATCH 02/25] Add alert status filter component --- .../pages/alerts/alerts_status_filter.tsx | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx new file mode 100644 index 0000000000000..8aebddd346159 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiButtonGroup, EuiButtonGroupOptionProps } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { AlertStatus, AlertStatusFilter } from '../../../common/typings'; + +export interface AlertStatusFilterProps { + status: AlertStatus; + onChange: (id: string, value: string) => void; +} + +export const allAlerts: AlertStatusFilter = { + status: AlertStatus.All, + query: '', + label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.openButtonLabel', { + defaultMessage: 'Show all', + }), +}; + +export const activeAlerts: AlertStatusFilter = { + status: AlertStatus.Active, + query: `kibana.alert.status : "active"`, + label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel', { + defaultMessage: 'Active', + }), +}; + +export const recoveredAlerts: AlertStatusFilter = { + status: AlertStatus.Recovered, + query: `kibana.alert.status : "recovered"`, + label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.closedButtonLabel', { + defaultMessage: 'Recovered', + }), +}; + +const options: EuiButtonGroupOptionProps[] = [ + { + id: allAlerts.status, + label: allAlerts.label, + value: allAlerts.query, + 'data-test-subj': 'workflow-status-filter-open-button', + }, + { + id: activeAlerts.status, + label: activeAlerts.label, + value: activeAlerts.query, + 'data-test-subj': 'workflow-status-filter-acknowledged-button', + }, + { + id: recoveredAlerts.status, + label: recoveredAlerts.label, + value: recoveredAlerts.query, + 'data-test-subj': 'workflow-status-filter-closed-button', + }, +]; + +export function AlertsStatusFilter({ status, onChange }: AlertStatusFilterProps) { + return ( + + ); +} From f4cb043b69cca6d162c458c8c84f02701d38f5b6 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 16 Nov 2021 14:00:46 +0100 Subject: [PATCH 03/25] Remove Filter in action from the t grid table --- .../public/pages/alerts/alerts_table_t_grid.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index dac2b0951ae05..7ab226f20e612 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -54,7 +54,6 @@ import { getRenderCellValue } from './render_cell_value'; import { observabilityFeatureId } from '../../../common'; import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; -import { getDefaultCellActions } from './default_cell_actions'; import { LazyAlertsFlyout } from '../..'; import { parseAlert } from './parse_alert'; import { CoreStart } from '../../../../../../src/core/public'; @@ -67,7 +66,6 @@ interface AlertsTableTGridProps { kuery: string; workflowStatus: AlertWorkflowStatus; setRefetch: (ref: () => void) => void; - addToQuery: (value: string) => void; } interface ObservabilityActionsProps extends ActionProps { @@ -314,7 +312,7 @@ function ObservabilityActions({ } export function AlertsTableTGrid(props: AlertsTableTGridProps) { - const { indexNames, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch, addToQuery } = props; + const { indexNames, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch } = props; const prevWorkflowStatus = usePrevious(workflowStatus); const { timelines, @@ -381,7 +379,6 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { type, columns, deletedEventIds, - defaultCellActions: getDefaultCellActions({ addToQuery }), end: rangeTo, filters: [], hasAlertsCrudPermissions, @@ -413,7 +410,6 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { }; }, [ casePermissions, - addToQuery, rangeTo, hasAlertsCrudPermissions, indexNames, From 788078177647834ac7cb058b32bfbd9f69715acc Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 16 Nov 2021 14:20:43 +0100 Subject: [PATCH 04/25] Update group buttons to applied Alert status filter instead of Workflow status --- .../public/pages/alerts/index.tsx | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index a3c060f5dc5df..480ce27f45c26 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -9,10 +9,10 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { IndexPatternBase } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; -import React, { useCallback, useRef } from 'react'; +import React, { useCallback, useRef, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields'; -import type { AlertWorkflowStatus } from '../../../common/typings'; +import { AlertStatus } from '../../../common/typings'; import { ExperimentalBadge } from '../../components/shared/experimental_badge'; import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { useFetcher } from '../../hooks/use_fetcher'; @@ -26,7 +26,7 @@ import { AlertsSearchBar } from './alerts_search_bar'; import { AlertsTableTGrid } from './alerts_table_t_grid'; import { Provider, alertsPageStateContainer, useAlertsPageStateContainer } from './state_container'; import './styles.scss'; -import { WorkflowStatusFilter } from './workflow_status_filter'; +import { AlertsStatusFilter } from './alerts_status_filter'; import { AlertsDisclaimer } from './alerts_disclaimer'; export interface TopAlert { @@ -39,22 +39,17 @@ export interface TopAlert { const NO_INDEX_NAMES: string[] = []; const NO_INDEX_PATTERNS: IndexPatternBase[] = []; +const ALERT_STATUS_REGEX = + /\s*and\s*kibana\.alert\.status\s*:\s*".+?"|kibana\.alert\.status\s*:\s*".+?"/gm; function AlertsPage() { const { core, plugins, ObservabilityPageTemplate } = usePluginContext(); + const [alertFilterStatus, setAlertFilterStatus] = useState(AlertStatus.All); const { prepend } = core.http.basePath; const refetch = useRef<() => void>(); const timefilterService = useTimefilterService(); - const { - rangeFrom, - setRangeFrom, - rangeTo, - setRangeTo, - kuery, - setKuery, - workflowStatus, - setWorkflowStatus, - } = useAlertsPageStateContainer(); + const { rangeFrom, setRangeFrom, rangeTo, setRangeTo, kuery, setKuery, workflowStatus } = + useAlertsPageStateContainer(); useBreadcrumbs([ { @@ -103,12 +98,14 @@ function AlertsPage() { ]; }, [indexNames]); - const setWorkflowStatusFilter = useCallback( - (value: AlertWorkflowStatus) => { - setWorkflowStatus(value); - }, - [setWorkflowStatus] - ); + // Keep the Workflow status code commented (no delete) as requested: https://github.com/elastic/kibana/issues/117686 + + // const setWorkflowStatusFilter = useCallback( + // (value: AlertWorkflowStatus) => { + // setWorkflowStatus(value); + // }, + // [setWorkflowStatus] + // ); const onQueryChange = useCallback( ({ dateRange, query }) => { @@ -124,15 +121,24 @@ function AlertsPage() { [rangeFrom, setRangeFrom, rangeTo, setRangeTo, kuery, setKuery, timefilterService] ); - const addToQuery = useCallback( - (value: string) => { - let output = value; - if (kuery !== '') { - output = `${kuery} and ${value}`; + const setAlertStatusFilter = useCallback( + (id: string, query: string) => { + setAlertFilterStatus(id as AlertStatus); + // Updating the KQL query bar alongside with user inputs is tricky. + // To avoid issue, this function always remove the AlertFilter and add it + // at the end of the query, each time the filter is added/updated/removed (Show All) + // NOTE: This (query appending) will be changed entirely: https://github.com/elastic/kibana/issues/116135 + let output = kuery; + if (kuery === '') { + output = query; + } else { + const queryWithoutAlertFilter = kuery.replace(ALERT_STATUS_REGEX, ''); + output = `${queryWithoutAlertFilter} and ${query}`; } onQueryChange({ dateRange: { from: rangeFrom, to: rangeTo }, - query: output, + // Clean up the kuery from unwanted trailing/ahead ANDs after appending and removing filters. + query: output.replace(/^\s*and\s*|\s*and\s*$/gm, ''), }); }, [kuery, onQueryChange, rangeFrom, rangeTo] @@ -194,7 +200,9 @@ function AlertsPage() { - + {/* Keep the Workflow status code commented (no delete) as requested: https://github.com/elastic/kibana/issues/117686*/} + {/* */} + @@ -207,7 +215,6 @@ function AlertsPage() { kuery={kuery} workflowStatus={workflowStatus} setRefetch={setRefetch} - addToQuery={addToQuery} /> From b17d8db5007dda50a5262960e712f03f27d4d5df Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 16 Nov 2021 15:12:05 +0100 Subject: [PATCH 05/25] Keep the Alert status button in sync when typing and first page load --- .../public/pages/alerts/index.tsx | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index 480ce27f45c26..9a781b8657098 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -9,7 +9,7 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { IndexPatternBase } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; -import React, { useCallback, useRef, useState } from 'react'; +import React, { useCallback, useRef, useState, useEffect } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields'; import { AlertStatus } from '../../../common/typings'; @@ -51,6 +51,10 @@ function AlertsPage() { const { rangeFrom, setRangeFrom, rangeTo, setRangeTo, kuery, setKuery, workflowStatus } = useAlertsPageStateContainer(); + useEffect(() => { + syncAlertStatusFilterStatus(kuery as string); + }, [kuery]); + useBreadcrumbs([ { text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { @@ -112,15 +116,30 @@ function AlertsPage() { if (rangeFrom === dateRange.from && rangeTo === dateRange.to && kuery === (query ?? '')) { return refetch.current && refetch.current(); } - timefilterService.setTime(dateRange); setRangeFrom(dateRange.from); setRangeTo(dateRange.to); setKuery(query); + syncAlertStatusFilterStatus(query as string); }, [rangeFrom, setRangeFrom, rangeTo, setRangeTo, kuery, setKuery, timefilterService] ); + const syncAlertStatusFilterStatus = (query: string) => { + const [, alertStatus] = /\s*kibana\.alert\.status\s*:\s*"(.*?)"/.exec(query) || []; + if (!alertStatus) return; + switch (alertStatus.toLowerCase()) { + case 'active': + setAlertFilterStatus(AlertStatus.Active); + break; + case 'recovered': + setAlertFilterStatus(AlertStatus.Recovered); + break; + default: + setAlertFilterStatus(AlertStatus.All); + break; + } + }; const setAlertStatusFilter = useCallback( (id: string, query: string) => { setAlertFilterStatus(id as AlertStatus); From ec3be8c4207c388e3a746c33440e14aa2802706d Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 17 Nov 2021 17:11:44 +0100 Subject: [PATCH 06/25] Fix data test object name and translation keys label --- .../public/pages/alerts/alerts_status_filter.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx index 8aebddd346159..6acd6f63410bf 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx @@ -18,7 +18,7 @@ export interface AlertStatusFilterProps { export const allAlerts: AlertStatusFilter = { status: AlertStatus.All, query: '', - label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.openButtonLabel', { + label: i18n.translate('xpack.observability.alerts.alertStatusFilter.showAll', { defaultMessage: 'Show all', }), }; @@ -26,7 +26,7 @@ export const allAlerts: AlertStatusFilter = { export const activeAlerts: AlertStatusFilter = { status: AlertStatus.Active, query: `kibana.alert.status : "active"`, - label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel', { + label: i18n.translate('xpack.observability.alerts.alertStatusFilter.active', { defaultMessage: 'Active', }), }; @@ -34,7 +34,7 @@ export const activeAlerts: AlertStatusFilter = { export const recoveredAlerts: AlertStatusFilter = { status: AlertStatus.Recovered, query: `kibana.alert.status : "recovered"`, - label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.closedButtonLabel', { + label: i18n.translate('xpack.observability.alerts.alertStatusFilter.recovered', { defaultMessage: 'Recovered', }), }; @@ -44,19 +44,19 @@ const options: EuiButtonGroupOptionProps[] = [ id: allAlerts.status, label: allAlerts.label, value: allAlerts.query, - 'data-test-subj': 'workflow-status-filter-open-button', + 'data-test-subj': 'alert-status-filter-show-all-button', }, { id: activeAlerts.status, label: activeAlerts.label, value: activeAlerts.query, - 'data-test-subj': 'workflow-status-filter-acknowledged-button', + 'data-test-subj': 'alert-status-filter-active-button', }, { id: recoveredAlerts.status, label: recoveredAlerts.label, value: recoveredAlerts.query, - 'data-test-subj': 'workflow-status-filter-closed-button', + 'data-test-subj': 'alert-status-filter-recovered-button', }, ]; From 391945b86b1ad6529ff054d8b6cb879d364ff1c8 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 17 Nov 2021 17:57:19 +0100 Subject: [PATCH 07/25] Add possibility to hide the bulk actions --- .../public/pages/alerts/alerts_table_t_grid.tsx | 2 ++ .../timelines/common/types/timeline/actions/index.ts | 1 + .../public/hooks/use_status_bulk_action_items.tsx | 9 +++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index 7ab226f20e612..4374501d3975a 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -204,6 +204,8 @@ function ObservabilityActions({ setEventsDeleted, onUpdateSuccess: onAlertStatusUpdated, onUpdateFailure: onAlertStatusUpdated, + // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686 + hideBulkActions: true, }); const ruleId = alert.fields['kibana.alert.rule.uuid'] ?? null; diff --git a/x-pack/plugins/timelines/common/types/timeline/actions/index.ts b/x-pack/plugins/timelines/common/types/timeline/actions/index.ts index 0662c63f35edd..1f44a2fa1f122 100644 --- a/x-pack/plugins/timelines/common/types/timeline/actions/index.ts +++ b/x-pack/plugins/timelines/common/types/timeline/actions/index.ts @@ -62,6 +62,7 @@ export interface StatusBulkActionsProps { onUpdateSuccess?: OnUpdateAlertStatusSuccess; onUpdateFailure?: OnUpdateAlertStatusError; timelineId?: string; + hideBulkActions?: boolean; } export interface HeaderActionProps { width: number; diff --git a/x-pack/plugins/timelines/public/hooks/use_status_bulk_action_items.tsx b/x-pack/plugins/timelines/public/hooks/use_status_bulk_action_items.tsx index c6e0e13c4dcb4..e04be5a6c81ed 100644 --- a/x-pack/plugins/timelines/public/hooks/use_status_bulk_action_items.tsx +++ b/x-pack/plugins/timelines/public/hooks/use_status_bulk_action_items.tsx @@ -27,6 +27,7 @@ export const useStatusBulkActionItems = ({ onUpdateSuccess, onUpdateFailure, timelineId, + hideBulkActions = false, }: StatusBulkActionsProps) => { const { updateAlertStatus } = useUpdateAlertsStatus(timelineId != null); const { addSuccess, addError, addWarning } = useAppToasts(); @@ -122,7 +123,7 @@ export const useStatusBulkActionItems = ({ const items = useMemo(() => { const actionItems = []; - if (currentStatus !== FILTER_OPEN) { + if (!hideBulkActions && currentStatus !== FILTER_OPEN) { actionItems.push( ); } - if (currentStatus !== FILTER_ACKNOWLEDGED) { + if (!hideBulkActions && currentStatus !== FILTER_ACKNOWLEDGED) { actionItems.push( ); } - if (currentStatus !== FILTER_CLOSED) { + if (!hideBulkActions && currentStatus !== FILTER_CLOSED) { actionItems.push( Date: Thu, 18 Nov 2021 11:24:04 +0100 Subject: [PATCH 08/25] Update how hide the bulk actions --- .../pages/alerts/alerts_table_t_grid.tsx | 87 ++++++++----------- .../common/types/timeline/actions/index.ts | 1 - .../hooks/use_status_bulk_action_items.tsx | 9 +- 3 files changed, 41 insertions(+), 56 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index 4374501d3975a..e1a07bdaf5e18 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -13,8 +13,6 @@ import { ALERT_DURATION, ALERT_REASON, - ALERT_RULE_CONSUMER, - ALERT_RULE_PRODUCER, ALERT_STATUS, ALERT_WORKFLOW_STATUS, TIMESTAMP, @@ -34,13 +32,9 @@ import { import styled from 'styled-components'; import React, { Suspense, useMemo, useState, useCallback, useEffect } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; -import { get } from 'lodash'; -import { - getAlertsPermissions, - useGetUserAlertsPermissions, -} from '../../hooks/use_alert_permission'; +import { getAlertsPermissions } from '../../hooks/use_alert_permission'; import type { TimelinesUIStart, TGridType, SortDirection } from '../../../../timelines/public'; -import { useStatusBulkActionItems } from '../../../../timelines/public'; + import type { TopAlert } from './'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import type { @@ -144,21 +138,21 @@ function ObservabilityActions({ const [openActionsPopoverId, setActionsPopover] = useState(null); const { timelines, - application: { capabilities }, + application: {}, } = useKibana().services; const parseObservabilityAlert = useMemo( () => parseAlert(observabilityRuleTypeRegistry), [observabilityRuleTypeRegistry] ); - const alertDataConsumer = useMemo( - () => get(dataFieldEs, ALERT_RULE_CONSUMER, [''])[0], - [dataFieldEs] - ); - const alertDataProducer = useMemo( - () => get(dataFieldEs, ALERT_RULE_PRODUCER, [''])[0], - [dataFieldEs] - ); + // const alertDataConsumer = useMemo( + // () => get(dataFieldEs, ALERT_RULE_CONSUMER, [''])[0], + // [dataFieldEs] + // ); + // const alertDataProducer = useMemo( + // () => get(dataFieldEs, ALERT_RULE_PRODUCER, [''])[0], + // [dataFieldEs] + // ); const alert = parseObservabilityAlert(dataFieldEs); const { prepend } = core.http.basePath; @@ -184,29 +178,29 @@ function ObservabilityActions({ }; }, [data, eventId, ecsData]); - const onAlertStatusUpdated = useCallback(() => { - setActionsPopover(null); - if (refetch) { - refetch(); - } - }, [setActionsPopover, refetch]); - - const alertPermissions = useGetUserAlertsPermissions( - capabilities, - alertDataConsumer === 'alerts' ? alertDataProducer : alertDataConsumer - ); - - const statusActionItems = useStatusBulkActionItems({ - eventIds: [eventId], - currentStatus, - indexName: ecsData._index ?? '', - setEventsLoading, - setEventsDeleted, - onUpdateSuccess: onAlertStatusUpdated, - onUpdateFailure: onAlertStatusUpdated, - // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686 - hideBulkActions: true, - }); + // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686 + + // const onAlertStatusUpdated = useCallback(() => { + // setActionsPopover(null); + // if (refetch) { + // refetch(); + // } + // }, [setActionsPopover, refetch]); + + // const alertPermissions = useGetUserAlertsPermissions( + // capabilities, + // alertDataConsumer === 'alerts' ? alertDataProducer : alertDataConsumer + // ); + + // const statusActionItems = useStatusBulkActionItems({ + // eventIds: [eventId], + // currentStatus, + // indexName: ecsData._index ?? '', + // setEventsLoading, + // setEventsDeleted, + // onUpdateSuccess: onAlertStatusUpdated, + // onUpdateFailure: onAlertStatusUpdated, + // }); const ruleId = alert.fields['kibana.alert.rule.uuid'] ?? null; const linkToRule = ruleId ? prepend(paths.management.ruleDetails(ruleId)) : null; @@ -231,7 +225,8 @@ function ObservabilityActions({ }), ] : []), - ...(alertPermissions.crud ? statusActionItems : []), + // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686 + // ...(alertPermissions.crud ? statusActionItems : []), ...(!!linkToRule ? [ { const { updateAlertStatus } = useUpdateAlertsStatus(timelineId != null); const { addSuccess, addError, addWarning } = useAppToasts(); @@ -123,7 +122,7 @@ export const useStatusBulkActionItems = ({ const items = useMemo(() => { const actionItems = []; - if (!hideBulkActions && currentStatus !== FILTER_OPEN) { + if (currentStatus !== FILTER_OPEN) { actionItems.push( ); } - if (!hideBulkActions && currentStatus !== FILTER_ACKNOWLEDGED) { + if (currentStatus !== FILTER_ACKNOWLEDGED) { actionItems.push( ); } - if (!hideBulkActions && currentStatus !== FILTER_CLOSED) { + if (currentStatus !== FILTER_CLOSED) { actionItems.push( Date: Thu, 18 Nov 2021 16:13:58 +0100 Subject: [PATCH 09/25] Fix showCheckboxes hardcoded "true". Instead use the leadingControlColumns props --- .../timelines/public/components/t_grid/standalone/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx index 1cb13a9d6cbb9..3eeba04cae8c5 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx @@ -320,7 +320,7 @@ const TGridStandaloneComponent: React.FC = ({ indexNames, itemsPerPage: itemsPerPageStore, itemsPerPageOptions, - showCheckboxes: true, + showCheckboxes: leadingControlColumns[0].showCheckboxes ?? true, }) ); dispatch( From b4f8df498ba123ac2be5adaedf3e66527f1eab04 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Thu, 18 Nov 2021 16:15:27 +0100 Subject: [PATCH 10/25] Hide the leading checkboxes in the T Grid with the bulk actions --- .../observability/public/pages/alerts/alerts_table_t_grid.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index e1a07bdaf5e18..56a5d60e1ad8a 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -41,6 +41,7 @@ import type { ActionProps, AlertWorkflowStatus, ColumnHeaderOptions, + ControlColumnProps, RowRenderer, } from '../../../../timelines/common'; @@ -336,11 +337,12 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { } }, []); - const leadingControlColumns = useMemo(() => { + const leadingControlColumns: ControlColumnProps[] = useMemo(() => { return [ { id: 'expand', width: 120, + showCheckboxes: true, headerCellRender: () => { return {translations.alertsTable.actionsTextLabel}; }, From 80132a3c5f7ef7112a19f42f86537c70a46fdc15 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Fri, 19 Nov 2021 10:32:09 +0100 Subject: [PATCH 11/25] Update showCheckboxes to false --- .../observability/public/pages/alerts/alerts_table_t_grid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index 56a5d60e1ad8a..446a1913710d2 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -342,7 +342,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { { id: 'expand', width: 120, - showCheckboxes: true, + showCheckboxes: false, headerCellRender: () => { return {translations.alertsTable.actionsTextLabel}; }, From 67bf04d6291c92bc5cec510b9b1b1b9f58105f41 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Fri, 19 Nov 2021 19:27:18 +0100 Subject: [PATCH 12/25] Fix test as the leading checkboxes are hidden --- .../observability_functional/apps/observability/alerts/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index 2b760b65a1c46..f65604bfd7b5c 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -16,7 +16,7 @@ async function asyncForEach(array: T[], callback: (item: T, index: number) => const ACTIVE_ALERTS_CELL_COUNT = 78; const RECOVERED_ALERTS_CELL_COUNT = 120; -const TOTAL_ALERTS_CELL_COUNT = 198; +const TOTAL_ALERTS_CELL_COUNT = 165; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); From 1b82d802ca15bcf4c83759e963ea954c811f25ba Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Mon, 22 Nov 2021 10:50:16 +0100 Subject: [PATCH 13/25] Update tests --- .../observability_functional/apps/observability/alerts/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index f65604bfd7b5c..55ea27c906cbb 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -15,7 +15,7 @@ async function asyncForEach(array: T[], callback: (item: T, index: number) => } const ACTIVE_ALERTS_CELL_COUNT = 78; -const RECOVERED_ALERTS_CELL_COUNT = 120; +const RECOVERED_ALERTS_CELL_COUNT = 100; const TOTAL_ALERTS_CELL_COUNT = 165; export default ({ getService }: FtrProviderContext) => { From 338da2db9656de5022568e2b31fcdcf1c49916b4 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Mon, 22 Nov 2021 11:54:43 +0100 Subject: [PATCH 14/25] Get back disabledCellActions as it's required by T Grid --- .../public/pages/alerts/alerts_table_t_grid.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index 102b6846d355a..4e1aee5906a5f 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -301,7 +301,7 @@ function ObservabilityActions({ ); } // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686 -/* + const FIELDS_WITHOUT_CELL_ACTIONS = [ '@timestamp', 'signal.rule.risk_score', @@ -309,7 +309,6 @@ const FIELDS_WITHOUT_CELL_ACTIONS = [ 'kibana.alert.duration.us', 'kibana.alert.reason', ]; -*/ export function AlertsTableTGrid(props: AlertsTableTGridProps) { const { indexNames, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch } = props; @@ -382,7 +381,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { deletedEventIds, // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686 // defaultCellActions: getDefaultCellActions({ addToQuery }), - // disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS, + disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS, end: rangeTo, filters: [], hasAlertsCrudPermissions, From b1562d6d5342538d5cb4c4e092f35f72b6852dd2 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Mon, 22 Nov 2021 16:43:23 +0100 Subject: [PATCH 15/25] Update tests to skip test related to Workflow action buttons --- .../apps/observability/alerts/bulk_actions.ts | 12 ++++++------ .../apps/observability/alerts/index.ts | 2 +- .../observability/alerts/state_synchronization.ts | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts b/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts index 749324a39ba20..d318f1f900b1e 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts @@ -25,7 +25,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { const retry = getService('retry'); - describe('Observability alerts / Bulk actions', function () { + describe.skip('Observability alerts / Bulk actions', function () { this.tags('includeFirefox'); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); @@ -84,7 +84,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe('When user has all priviledges for apm app', () => { + describe.skip('When user has all priviledges for apm app', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ @@ -108,7 +108,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe('when checkbox is clicked', async () => { + describe.skip('when checkbox is clicked', async () => { it('shows bulk actions container', async () => { const apmCheckboxes = await observability.alerts.bulkActions.getCheckboxSelectorPerProducer('apm'); @@ -126,7 +126,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe('When user has read permissions for logs', () => { + describe.skip('When user has read permissions for logs', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ @@ -145,7 +145,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe('When user has read permissions for apm', () => { + describe.skip('When user has read permissions for apm', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ @@ -164,7 +164,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe('When user has mixed permissions for observability apps', () => { + describe.skip('When user has mixed permissions for observability apps', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index 55ea27c906cbb..5317127d5e9e6 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -186,7 +186,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('Cell actions', () => { + describe.skip('Cell actions', () => { beforeEach(async () => { await retry.try(async () => { const cells = await observability.alerts.common.getTableCells(); diff --git a/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts b/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts index 5a03f72e540b3..c351b45b2ea93 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts @@ -39,7 +39,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await assertAlertsPageState({ kuery: 'kibana.alert.evaluation.threshold > 75', - workflowStatus: 'Closed', + // workflowStatus: 'Closed', timeRange: '~ a month ago - ~ 10 days ago', }); }); @@ -55,7 +55,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await assertAlertsPageState({ kuery: '', - workflowStatus: 'Open', + // workflowStatus: 'Open', timeRange: 'Last 15 minutes', }); }); @@ -77,15 +77,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { async function assertAlertsPageState(expected: { kuery: string; - workflowStatus: string; + // workflowStatus: string; timeRange: string; }) { expect(await (await observability.alerts.common.getQueryBar()).getVisibleText()).to.be( expected.kuery ); - expect(await observability.alerts.common.getWorkflowStatusFilterValue()).to.be( - expected.workflowStatus - ); + // expect(await observability.alerts.common.getWorkflowStatusFilterValue()).to.be( + // expected.workflowStatus + // ); const timeRange = await observability.alerts.common.getTimeRange(); expect(timeRange).to.be(expected.timeRange); } From 3e6c8c6f1da07d01bacd399e8e0eb348a6065cd1 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Mon, 22 Nov 2021 18:24:00 +0100 Subject: [PATCH 16/25] Skip workflow tests --- .../apps/observability/alerts/workflow_status.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts index 4976c1c225aba..7b9e1eec0b7c6 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts @@ -13,7 +13,7 @@ const OPEN_ALERTS_ROWS_COUNT = 33; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); - describe('alert workflow status', function () { + describe.skip('alert workflow status', function () { this.tags('includeFirefox'); const observability = getService('observability'); From 3ae465d845e81debc56a9cece08f0fb5e7d51c07 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 23 Nov 2021 11:39:05 +0100 Subject: [PATCH 17/25] Revert fix showCheckboxes --- .../timelines/public/components/t_grid/standalone/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx index a72979545fcf2..cc065c505537a 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx @@ -319,7 +319,7 @@ const TGridStandaloneComponent: React.FC = ({ indexNames, itemsPerPage: itemsPerPageStore, itemsPerPageOptions, - showCheckboxes: leadingControlColumns[0].showCheckboxes ?? true, + showCheckboxes: true, }) ); dispatch( From 762ba4d771bf218de9296ccb03c0dcdcff88c7d2 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 23 Nov 2021 12:18:42 +0100 Subject: [PATCH 18/25] Remove unused imports --- .../public/pages/alerts/alerts_table_t_grid.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index c8e59e4f4008f..dec05864bbe94 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -32,11 +32,8 @@ import { import styled from 'styled-components'; import React, { Suspense, useMemo, useState, useCallback, useEffect } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; -import { get, pick } from 'lodash'; -import { - getAlertsPermissions, - useGetUserAlertsPermissions, -} from '../../hooks/use_alert_permission'; +import { pick } from 'lodash'; +import { getAlertsPermissions } from '../../hooks/use_alert_permission'; import type { TimelinesUIStart, TGridType, @@ -44,7 +41,7 @@ import type { TGridModel, SortDirection, } from '../../../../timelines/public'; -import { useStatusBulkActionItems } from '../../../../timelines/public'; + import type { TopAlert } from './'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import type { From 963b34edbf0889377b4c18bb68c36f77ef6d9ef2 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 23 Nov 2021 12:57:13 +0100 Subject: [PATCH 19/25] Revert the o11y tests as the checkBoxes fix is reverted --- .../apps/observability/alerts/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index 5317127d5e9e6..c026358d0ea37 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -15,8 +15,8 @@ async function asyncForEach(array: T[], callback: (item: T, index: number) => } const ACTIVE_ALERTS_CELL_COUNT = 78; -const RECOVERED_ALERTS_CELL_COUNT = 100; -const TOTAL_ALERTS_CELL_COUNT = 165; +const RECOVERED_ALERTS_CELL_COUNT = 120; +const TOTAL_ALERTS_CELL_COUNT = 198; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); From 3ade6061250f1154a2b9c48808d7a2985867de6a Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 23 Nov 2021 15:21:58 +0100 Subject: [PATCH 20/25] Reactive the tests effected by checkBoxes --- .../apps/observability/alerts/bulk_actions.ts | 12 ++++++------ .../apps/observability/alerts/workflow_status.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts b/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts index d318f1f900b1e..749324a39ba20 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/bulk_actions.ts @@ -25,7 +25,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { const retry = getService('retry'); - describe.skip('Observability alerts / Bulk actions', function () { + describe('Observability alerts / Bulk actions', function () { this.tags('includeFirefox'); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); @@ -84,7 +84,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe.skip('When user has all priviledges for apm app', () => { + describe('When user has all priviledges for apm app', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ @@ -108,7 +108,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe.skip('when checkbox is clicked', async () => { + describe('when checkbox is clicked', async () => { it('shows bulk actions container', async () => { const apmCheckboxes = await observability.alerts.bulkActions.getCheckboxSelectorPerProducer('apm'); @@ -126,7 +126,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe.skip('When user has read permissions for logs', () => { + describe('When user has read permissions for logs', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ @@ -145,7 +145,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe.skip('When user has read permissions for apm', () => { + describe('When user has read permissions for apm', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ @@ -164,7 +164,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { }); }); - describe.skip('When user has mixed permissions for observability apps', () => { + describe('When user has mixed permissions for observability apps', () => { before(async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ diff --git a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts index 7b9e1eec0b7c6..4976c1c225aba 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts @@ -13,7 +13,7 @@ const OPEN_ALERTS_ROWS_COUNT = 33; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); - describe.skip('alert workflow status', function () { + describe('alert workflow status', function () { this.tags('includeFirefox'); const observability = getService('observability'); From 1682878fa977dc65a8a5e2b0a1b10b9a11d91072 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 23 Nov 2021 17:20:27 +0100 Subject: [PATCH 21/25] Skip alert workflow status --- .../apps/observability/alerts/workflow_status.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts index 4976c1c225aba..9f6c781306749 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts @@ -13,7 +13,8 @@ const OPEN_ALERTS_ROWS_COUNT = 33; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); - describe('alert workflow status', function () { + // Keep the Workflow status code commented (no delete) as requested: https://github.com/elastic/kibana/issues/117686 + describe.skip('alert workflow status', function () { this.tags('includeFirefox'); const observability = getService('observability'); From 8c8f1143445c63e4a56db4cc5989da0b99224e4a Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 24 Nov 2021 18:46:41 +0100 Subject: [PATCH 22/25] [Code review] use predefined types --- .../plugins/observability/common/typings.ts | 15 ++++++++----- .../pages/alerts/alerts_status_filter.tsx | 20 +++++++++++------ .../public/pages/alerts/index.tsx | 22 +++++++------------ 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/observability/common/typings.ts b/x-pack/plugins/observability/common/typings.ts index 012f91af56fee..1e247fd06739f 100644 --- a/x-pack/plugins/observability/common/typings.ts +++ b/x-pack/plugins/observability/common/typings.ts @@ -7,6 +7,10 @@ import * as t from 'io-ts'; export type Maybe = T | null | undefined; +import { + ALERT_STATUS_ACTIVE, + ALERT_STATUS_RECOVERED, +} from '@kbn/rule-data-utils/alerts_as_data_status'; export const alertWorkflowStatusRt = t.keyof({ open: null, @@ -25,13 +29,12 @@ export interface ApmIndicesConfig { apmAgentConfigurationIndex: string; apmCustomLinkIndex: string; } -export enum AlertStatus { - All = 'all', - Active = 'active', - Recovered = 'recovered', -} +export type AlertStatusFilterButton = + | typeof ALERT_STATUS_ACTIVE + | typeof ALERT_STATUS_RECOVERED + | ''; export interface AlertStatusFilter { - status: AlertStatus; + status: AlertStatusFilterButton; query: string; label: string; } diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx index 6acd6f63410bf..38c753bbebf3b 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx @@ -8,15 +8,21 @@ import { EuiButtonGroup, EuiButtonGroupOptionProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { AlertStatus, AlertStatusFilter } from '../../../common/typings'; +import { + ALERT_STATUS_ACTIVE, + ALERT_STATUS_RECOVERED, +} from '@kbn/rule-data-utils/alerts_as_data_status'; +import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names'; +import { AlertStatusFilterButton } from '../../../common/typings'; +import { AlertStatusFilter } from '../../../common/typings'; export interface AlertStatusFilterProps { - status: AlertStatus; + status: AlertStatusFilterButton; onChange: (id: string, value: string) => void; } export const allAlerts: AlertStatusFilter = { - status: AlertStatus.All, + status: '', query: '', label: i18n.translate('xpack.observability.alerts.alertStatusFilter.showAll', { defaultMessage: 'Show all', @@ -24,16 +30,16 @@ export const allAlerts: AlertStatusFilter = { }; export const activeAlerts: AlertStatusFilter = { - status: AlertStatus.Active, - query: `kibana.alert.status : "active"`, + status: ALERT_STATUS_ACTIVE, + query: `${ALERT_STATUS}: "${ALERT_STATUS_ACTIVE}"`, label: i18n.translate('xpack.observability.alerts.alertStatusFilter.active', { defaultMessage: 'Active', }), }; export const recoveredAlerts: AlertStatusFilter = { - status: AlertStatus.Recovered, - query: `kibana.alert.status : "recovered"`, + status: ALERT_STATUS_RECOVERED, + query: `${ALERT_STATUS}: "${ALERT_STATUS_RECOVERED}"`, label: i18n.translate('xpack.observability.alerts.alertStatusFilter.recovered', { defaultMessage: 'Recovered', }), diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index 9a781b8657098..0c43a899ddfc2 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -11,8 +11,9 @@ import { IndexPatternBase } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import React, { useCallback, useRef, useState, useEffect } from 'react'; import useAsync from 'react-use/lib/useAsync'; +import { AlertStatus } from '@kbn/rule-data-utils/alerts_as_data_status'; +import { AlertStatusFilterButton } from '../../../common/typings'; import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields'; -import { AlertStatus } from '../../../common/typings'; import { ExperimentalBadge } from '../../components/shared/experimental_badge'; import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { useFetcher } from '../../hooks/use_fetcher'; @@ -44,7 +45,7 @@ const ALERT_STATUS_REGEX = function AlertsPage() { const { core, plugins, ObservabilityPageTemplate } = usePluginContext(); - const [alertFilterStatus, setAlertFilterStatus] = useState(AlertStatus.All); + const [alertFilterStatus, setAlertFilterStatus] = useState('' as AlertStatusFilterButton); const { prepend } = core.http.basePath; const refetch = useRef<() => void>(); const timefilterService = useTimefilterService(); @@ -127,22 +128,15 @@ function AlertsPage() { const syncAlertStatusFilterStatus = (query: string) => { const [, alertStatus] = /\s*kibana\.alert\.status\s*:\s*"(.*?)"/.exec(query) || []; - if (!alertStatus) return; - switch (alertStatus.toLowerCase()) { - case 'active': - setAlertFilterStatus(AlertStatus.Active); - break; - case 'recovered': - setAlertFilterStatus(AlertStatus.Recovered); - break; - default: - setAlertFilterStatus(AlertStatus.All); - break; + if (!alertStatus) { + setAlertFilterStatus(''); + return; } + setAlertFilterStatus(alertStatus.toLowerCase() as AlertStatus); }; const setAlertStatusFilter = useCallback( (id: string, query: string) => { - setAlertFilterStatus(id as AlertStatus); + setAlertFilterStatus(id as AlertStatusFilterButton); // Updating the KQL query bar alongside with user inputs is tricky. // To avoid issue, this function always remove the AlertFilter and add it // at the end of the query, each time the filter is added/updated/removed (Show All) From 2a0774f430a91f345b6d905b989d9f7c63441344 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 24 Nov 2021 18:50:28 +0100 Subject: [PATCH 23/25] Remove unused prop --- .../observability/public/pages/alerts/alerts_table_t_grid.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index dec05864bbe94..4b64ae07ddf06 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -377,7 +377,6 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { { id: 'expand', width: 120, - showCheckboxes: false, headerCellRender: () => { return {translations.alertsTable.actionsTextLabel}; }, From 6ebbb683c9a76f4804f90811ee54ee98ad21495d Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Thu, 25 Nov 2021 14:26:16 +0100 Subject: [PATCH 24/25] Use the alert-data index name in the RegEx --- .../observability/public/pages/alerts/index.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index 0c43a899ddfc2..943622ba98905 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -12,6 +12,8 @@ import { i18n } from '@kbn/i18n'; import React, { useCallback, useRef, useState, useEffect } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { AlertStatus } from '@kbn/rule-data-utils/alerts_as_data_status'; +import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names'; + import { AlertStatusFilterButton } from '../../../common/typings'; import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields'; import { ExperimentalBadge } from '../../components/shared/experimental_badge'; @@ -37,11 +39,16 @@ export interface TopAlert { link?: string; active: boolean; } - +const regExpEscape = (str: string) => str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); const NO_INDEX_NAMES: string[] = []; const NO_INDEX_PATTERNS: IndexPatternBase[] = []; -const ALERT_STATUS_REGEX = - /\s*and\s*kibana\.alert\.status\s*:\s*".+?"|kibana\.alert\.status\s*:\s*".+?"/gm; +const BASE_ALERT_REGEX = new RegExp(`\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*"(.*?|\\*?)"`); +const ALERT_STATUS_REGEX = new RegExp( + `\\s*and\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*".+?"|${regExpEscape( + ALERT_STATUS + )}\\s*:\\s*".+?"`, + 'gm' +); function AlertsPage() { const { core, plugins, ObservabilityPageTemplate } = usePluginContext(); @@ -127,7 +134,7 @@ function AlertsPage() { ); const syncAlertStatusFilterStatus = (query: string) => { - const [, alertStatus] = /\s*kibana\.alert\.status\s*:\s*"(.*?)"/.exec(query) || []; + const [, alertStatus] = BASE_ALERT_REGEX.exec(query) || []; if (!alertStatus) { setAlertFilterStatus(''); return; @@ -145,6 +152,7 @@ function AlertsPage() { if (kuery === '') { output = query; } else { + // console.log(ALERT_STATUS_REGEX); const queryWithoutAlertFilter = kuery.replace(ALERT_STATUS_REGEX, ''); output = `${queryWithoutAlertFilter} and ${query}`; } From 029bbea38342a1ce10b21e8ad92055b7c8aa93e5 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Thu, 25 Nov 2021 14:36:23 +0100 Subject: [PATCH 25/25] Detect * in KQL as "show al"l alert filter --- x-pack/plugins/observability/public/pages/alerts/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index 943622ba98905..2636463bcfd7a 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -44,9 +44,9 @@ const NO_INDEX_NAMES: string[] = []; const NO_INDEX_PATTERNS: IndexPatternBase[] = []; const BASE_ALERT_REGEX = new RegExp(`\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*"(.*?|\\*?)"`); const ALERT_STATUS_REGEX = new RegExp( - `\\s*and\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*".+?"|${regExpEscape( + `\\s*and\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*(".+?"|\\*?)|${regExpEscape( ALERT_STATUS - )}\\s*:\\s*".+?"`, + )}\\s*:\\s*(".+?"|\\*?)`, 'gm' );