[RAC] Enable workflow status filtering (#108215)
Co-authored-by: Jason Rhodes <jason.matthew.rhodes@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
60af98a1b7
commit
5fd903b7fe
|
@ -8,8 +8,12 @@ import * as t from 'io-ts';
|
|||
|
||||
export type Maybe<T> = T | null | undefined;
|
||||
|
||||
export const alertStatusRt = t.union([t.literal('all'), t.literal('open'), t.literal('closed')]);
|
||||
export type AlertStatus = t.TypeOf<typeof alertStatusRt>;
|
||||
export const alertWorkflowStatusRt = t.keyof({
|
||||
open: null,
|
||||
acknowledged: null,
|
||||
closed: null,
|
||||
});
|
||||
export type AlertWorkflowStatus = t.TypeOf<typeof alertWorkflowStatusRt>;
|
||||
|
||||
export interface ApmIndicesConfig {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
|
|
@ -13,21 +13,22 @@
|
|||
import {
|
||||
AlertConsumers as AlertConsumersTyped,
|
||||
ALERT_DURATION as ALERT_DURATION_TYPED,
|
||||
ALERT_STATUS as ALERT_STATUS_TYPED,
|
||||
ALERT_REASON as ALERT_REASON_TYPED,
|
||||
ALERT_RULE_CONSUMER,
|
||||
ALERT_STATUS as ALERT_STATUS_TYPED,
|
||||
ALERT_WORKFLOW_STATUS as ALERT_WORKFLOW_STATUS_TYPED,
|
||||
} from '@kbn/rule-data-utils';
|
||||
// @ts-expect-error importing from a place other than root because we want to limit what we import from this package
|
||||
import { AlertConsumers as AlertConsumersNonTyped } from '@kbn/rule-data-utils/target_node/alerts_as_data_rbac';
|
||||
import {
|
||||
ALERT_DURATION as ALERT_DURATION_NON_TYPED,
|
||||
ALERT_STATUS as ALERT_STATUS_NON_TYPED,
|
||||
ALERT_REASON as ALERT_REASON_NON_TYPED,
|
||||
ALERT_STATUS as ALERT_STATUS_NON_TYPED,
|
||||
ALERT_WORKFLOW_STATUS as ALERT_WORKFLOW_STATUS_NON_TYPED,
|
||||
TIMESTAMP,
|
||||
// @ts-expect-error importing from a place other than root because we want to limit what we import from this package
|
||||
} from '@kbn/rule-data-utils/target_node/technical_field_names';
|
||||
|
||||
// @ts-expect-error importing from a place other than root because we want to limit what we import from this package
|
||||
import { AlertConsumers as AlertConsumersNonTyped } from '@kbn/rule-data-utils/target_node/alerts_as_data_rbac';
|
||||
|
||||
import {
|
||||
EuiButtonIcon,
|
||||
EuiDataGridColumn,
|
||||
|
@ -47,7 +48,7 @@ import type { TopAlert } from './';
|
|||
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import type {
|
||||
ActionProps,
|
||||
AlertStatus,
|
||||
AlertWorkflowStatus,
|
||||
ColumnHeaderOptions,
|
||||
RowRenderer,
|
||||
} from '../../../../timelines/common';
|
||||
|
@ -63,21 +64,22 @@ import { CoreStart } from '../../../../../../src/core/public';
|
|||
|
||||
const AlertConsumers: typeof AlertConsumersTyped = AlertConsumersNonTyped;
|
||||
const ALERT_DURATION: typeof ALERT_DURATION_TYPED = ALERT_DURATION_NON_TYPED;
|
||||
const ALERT_STATUS: typeof ALERT_STATUS_TYPED = ALERT_STATUS_NON_TYPED;
|
||||
const ALERT_REASON: typeof ALERT_REASON_TYPED = ALERT_REASON_NON_TYPED;
|
||||
const ALERT_STATUS: typeof ALERT_STATUS_TYPED = ALERT_STATUS_NON_TYPED;
|
||||
const ALERT_WORKFLOW_STATUS: typeof ALERT_WORKFLOW_STATUS_TYPED = ALERT_WORKFLOW_STATUS_NON_TYPED;
|
||||
|
||||
interface AlertsTableTGridProps {
|
||||
indexName: string;
|
||||
rangeFrom: string;
|
||||
rangeTo: string;
|
||||
kuery: string;
|
||||
status: string;
|
||||
workflowStatus: AlertWorkflowStatus;
|
||||
setRefetch: (ref: () => void) => void;
|
||||
addToQuery: (value: string) => void;
|
||||
}
|
||||
|
||||
interface ObservabilityActionsProps extends ActionProps {
|
||||
currentStatus: AlertStatus;
|
||||
currentStatus: AlertWorkflowStatus;
|
||||
setFlyoutAlert: React.Dispatch<React.SetStateAction<TopAlert | undefined>>;
|
||||
}
|
||||
|
||||
|
@ -288,7 +290,7 @@ function ObservabilityActions({
|
|||
}
|
||||
|
||||
export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
||||
const { indexName, rangeFrom, rangeTo, kuery, status, setRefetch, addToQuery } = props;
|
||||
const { indexName, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch, addToQuery } = props;
|
||||
const { timelines } = useKibana<{ timelines: TimelinesUIStart }>().services;
|
||||
|
||||
const [flyoutAlert, setFlyoutAlert] = useState<TopAlert | undefined>(undefined);
|
||||
|
@ -313,14 +315,14 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
return (
|
||||
<ObservabilityActions
|
||||
{...actionProps}
|
||||
currentStatus={status as AlertStatus}
|
||||
currentStatus={workflowStatus}
|
||||
setFlyoutAlert={setFlyoutAlert}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
}, [status]);
|
||||
}, [workflowStatus]);
|
||||
|
||||
const tGridProps = useMemo(() => {
|
||||
const type: TGridType = 'standalone';
|
||||
|
@ -345,7 +347,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
defaultMessage: 'alerts',
|
||||
}),
|
||||
query: {
|
||||
query: `${ALERT_STATUS}: ${status}${kuery !== '' ? ` and ${kuery}` : ''}`,
|
||||
query: `${ALERT_WORKFLOW_STATUS}: ${workflowStatus}${kuery !== '' ? ` and ${kuery}` : ''}`,
|
||||
language: 'kuery',
|
||||
},
|
||||
renderCellValue: getRenderCellValue({ rangeFrom, rangeTo, setFlyoutAlert }),
|
||||
|
@ -359,7 +361,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
sortDirection,
|
||||
},
|
||||
],
|
||||
filterStatus: status as AlertStatus,
|
||||
filterStatus: workflowStatus as AlertWorkflowStatus,
|
||||
leadingControlColumns,
|
||||
trailingControlColumns,
|
||||
unit: (totalAlerts: number) =>
|
||||
|
@ -376,7 +378,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
rangeFrom,
|
||||
rangeTo,
|
||||
setRefetch,
|
||||
status,
|
||||
workflowStatus,
|
||||
addToQuery,
|
||||
]);
|
||||
const handleFlyoutClose = () => setFlyoutAlert(undefined);
|
||||
|
|
|
@ -10,16 +10,16 @@ import { i18n } from '@kbn/i18n';
|
|||
import React, { useCallback, useMemo, useRef } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields';
|
||||
import type { AlertStatus } from '../../../common/typings';
|
||||
import type { AlertWorkflowStatus } from '../../../common/typings';
|
||||
import { ExperimentalBadge } from '../../components/shared/experimental_badge';
|
||||
import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
|
||||
import { useFetcher } from '../../hooks/use_fetcher';
|
||||
import { usePluginContext } from '../../hooks/use_plugin_context';
|
||||
import { RouteParams } from '../../routes';
|
||||
import { callObservabilityApi } from '../../services/call_observability_api';
|
||||
import { AlertsSearchBar } from './alerts_search_bar';
|
||||
import { AlertsTableTGrid } from './alerts_table_t_grid';
|
||||
import { StatusFilter } from './status_filter';
|
||||
import { useFetcher } from '../../hooks/use_fetcher';
|
||||
import { callObservabilityApi } from '../../services/call_observability_api';
|
||||
import { WorkflowStatusFilter } from './workflow_status_filter';
|
||||
import './styles.scss';
|
||||
|
||||
export interface TopAlert {
|
||||
|
@ -44,7 +44,7 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
|
|||
rangeFrom = 'now-15m',
|
||||
rangeTo = 'now',
|
||||
kuery = 'kibana.alert.status: "open"', // TODO change hardcoded values as part of another PR
|
||||
status = 'open',
|
||||
workflowStatus = 'open',
|
||||
},
|
||||
} = routeParams;
|
||||
|
||||
|
@ -72,10 +72,10 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
|
|||
[dynamicIndexPatternResp]
|
||||
);
|
||||
|
||||
const setStatusFilter = useCallback(
|
||||
(value: AlertStatus) => {
|
||||
const setWorkflowStatusFilter = useCallback(
|
||||
(value: AlertWorkflowStatus) => {
|
||||
const nextSearchParams = new URLSearchParams(history.location.search);
|
||||
nextSearchParams.set('status', value);
|
||||
nextSearchParams.set('workflowStatus', value);
|
||||
history.push({
|
||||
...history.location,
|
||||
search: nextSearchParams.toString(),
|
||||
|
@ -172,29 +172,27 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
|
|||
onQueryChange={onQueryChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup direction="column">
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup justifyContent="flexStart">
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<StatusFilter status={status} onChange={setStatusFilter} />
|
||||
<WorkflowStatusFilter status={workflowStatus} onChange={setWorkflowStatusFilter} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<AlertsTableTGrid
|
||||
indexName={dynamicIndexPattern.length > 0 ? dynamicIndexPattern[0].title : ''}
|
||||
rangeFrom={rangeFrom}
|
||||
rangeTo={rangeTo}
|
||||
kuery={kuery}
|
||||
status={status}
|
||||
workflowStatus={workflowStatus}
|
||||
setRefetch={setRefetch}
|
||||
addToQuery={addToQuery}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</ObservabilityPageTemplate>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* 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 { EuiFilterButton, EuiFilterGroup } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import type { AlertStatus } from '../../../common/typings';
|
||||
|
||||
export interface StatusFilterProps {
|
||||
status: AlertStatus;
|
||||
onChange: (value: AlertStatus) => void;
|
||||
}
|
||||
|
||||
export function StatusFilter({ status = 'open', onChange }: StatusFilterProps) {
|
||||
return (
|
||||
<EuiFilterGroup
|
||||
aria-label={i18n.translate('xpack.observability.alerts.statusFilterAriaLabel', {
|
||||
defaultMessage: 'Filter alerts by open and closed status',
|
||||
})}
|
||||
>
|
||||
<EuiFilterButton
|
||||
data-test-subj="StatusFilter open button"
|
||||
hasActiveFilters={status === 'open'}
|
||||
onClick={() => onChange('open')}
|
||||
withNext={true}
|
||||
>
|
||||
{i18n.translate('xpack.observability.alerts.statusFilter.openButtonLabel', {
|
||||
defaultMessage: 'Open',
|
||||
})}
|
||||
</EuiFilterButton>
|
||||
<EuiFilterButton
|
||||
data-test-subj="StatusFilter closed button"
|
||||
hasActiveFilters={status === 'closed'}
|
||||
onClick={() => onChange('closed')}
|
||||
withNext={true}
|
||||
>
|
||||
{i18n.translate('xpack.observability.alerts.statusFilter.closedButtonLabel', {
|
||||
defaultMessage: 'Closed',
|
||||
})}
|
||||
</EuiFilterButton>
|
||||
<EuiFilterButton
|
||||
data-test-subj="StatusFilter all button"
|
||||
hasActiveFilters={status === 'all'}
|
||||
onClick={() => onChange('all')}
|
||||
>
|
||||
{i18n.translate('xpack.observability.alerts.statusFilter.allButtonLabel', {
|
||||
defaultMessage: 'All',
|
||||
})}
|
||||
</EuiFilterButton>
|
||||
</EuiFilterGroup>
|
||||
);
|
||||
}
|
|
@ -6,24 +6,24 @@
|
|||
*/
|
||||
|
||||
import React, { ComponentProps, useState } from 'react';
|
||||
import type { AlertStatus } from '../../../common/typings';
|
||||
import { StatusFilter } from './status_filter';
|
||||
import type { AlertWorkflowStatus } from '../../../common/typings';
|
||||
import { WorkflowStatusFilter } from './workflow_status_filter';
|
||||
|
||||
type Args = ComponentProps<typeof StatusFilter>;
|
||||
type Args = ComponentProps<typeof WorkflowStatusFilter>;
|
||||
|
||||
export default {
|
||||
title: 'app/Alerts/StatusFilter',
|
||||
component: StatusFilter,
|
||||
component: WorkflowStatusFilter,
|
||||
argTypes: {
|
||||
onChange: { action: 'change' },
|
||||
},
|
||||
};
|
||||
|
||||
export function Example({ onChange }: Args) {
|
||||
const [status, setStatus] = useState<AlertStatus>('open');
|
||||
const [status, setStatus] = useState<AlertWorkflowStatus>('open');
|
||||
|
||||
return (
|
||||
<StatusFilter
|
||||
<WorkflowStatusFilter
|
||||
status={status}
|
||||
onChange={(value) => {
|
||||
setStatus(value);
|
|
@ -7,27 +7,27 @@
|
|||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import type { AlertStatus } from '../../../common/typings';
|
||||
import { StatusFilter } from './status_filter';
|
||||
import type { AlertWorkflowStatus } from '../../../common/typings';
|
||||
import { WorkflowStatusFilter } from './workflow_status_filter';
|
||||
|
||||
describe('StatusFilter', () => {
|
||||
describe('render', () => {
|
||||
it('renders', () => {
|
||||
const onChange = jest.fn();
|
||||
const status: AlertStatus = 'all';
|
||||
const status: AlertWorkflowStatus = 'open';
|
||||
const props = { onChange, status };
|
||||
|
||||
expect(() => render(<StatusFilter {...props} />)).not.toThrowError();
|
||||
expect(() => render(<WorkflowStatusFilter {...props} />)).not.toThrowError();
|
||||
});
|
||||
|
||||
(['all', 'open', 'closed'] as AlertStatus[]).map((status) => {
|
||||
(['open', 'acknowledged', 'closed'] as AlertWorkflowStatus[]).map((status) => {
|
||||
describe(`when clicking the ${status} button`, () => {
|
||||
it('calls the onChange callback with "${status}"', () => {
|
||||
const onChange = jest.fn();
|
||||
const props = { onChange, status };
|
||||
|
||||
const { getByTestId } = render(<StatusFilter {...props} />);
|
||||
const button = getByTestId(`StatusFilter ${status} button`);
|
||||
const { getByTestId } = render(<WorkflowStatusFilter {...props} />);
|
||||
const button = getByTestId(`WorkflowStatusFilter ${status} button`);
|
||||
|
||||
button.click();
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 type { AlertWorkflowStatus } from '../../../common/typings';
|
||||
|
||||
export interface WorkflowStatusFilterProps {
|
||||
status: AlertWorkflowStatus;
|
||||
onChange: (value: AlertWorkflowStatus) => void;
|
||||
}
|
||||
|
||||
const options: Array<EuiButtonGroupOptionProps & { id: AlertWorkflowStatus }> = [
|
||||
{
|
||||
id: 'open',
|
||||
label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.openButtonLabel', {
|
||||
defaultMessage: 'Open',
|
||||
}),
|
||||
'data-test-subj': 'WorkflowStatusFilter open button',
|
||||
},
|
||||
{
|
||||
id: 'acknowledged',
|
||||
label: i18n.translate(
|
||||
'xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Acknowledged',
|
||||
}
|
||||
),
|
||||
'data-test-subj': 'WorkflowStatusFilter acknowledged button',
|
||||
},
|
||||
{
|
||||
id: 'closed',
|
||||
label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.closedButtonLabel', {
|
||||
defaultMessage: 'Closed',
|
||||
}),
|
||||
'data-test-subj': 'WorkflowStatusFilter closed button',
|
||||
},
|
||||
];
|
||||
|
||||
export function WorkflowStatusFilter({ status = 'open', onChange }: WorkflowStatusFilterProps) {
|
||||
return (
|
||||
<EuiButtonGroup
|
||||
legend="Filter by"
|
||||
color="primary"
|
||||
options={options}
|
||||
idSelected={status}
|
||||
onChange={(id) => onChange(id as AlertWorkflowStatus)}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import React from 'react';
|
||||
import { alertStatusRt } from '../../common/typings';
|
||||
import { alertWorkflowStatusRt } from '../../common/typings';
|
||||
import { ExploratoryViewPage } from '../components/shared/exploratory_view';
|
||||
import { AlertsPage } from '../pages/alerts';
|
||||
import { AllCasesPage } from '../pages/cases/all_cases';
|
||||
|
@ -93,7 +93,7 @@ export const routes = {
|
|||
rangeFrom: t.string,
|
||||
rangeTo: t.string,
|
||||
kuery: t.string,
|
||||
status: alertStatusRt,
|
||||
workflowStatus: alertWorkflowStatusRt,
|
||||
refreshPaused: jsonRt.pipe(t.boolean),
|
||||
refreshInterval: jsonRt.pipe(t.number),
|
||||
}),
|
||||
|
|
|
@ -24,16 +24,17 @@ import {
|
|||
ALERT_DURATION,
|
||||
ALERT_END,
|
||||
ALERT_ID,
|
||||
ALERT_START,
|
||||
ALERT_STATUS,
|
||||
ALERT_UUID,
|
||||
EVENT_ACTION,
|
||||
EVENT_KIND,
|
||||
ALERT_RULE_CONSUMER,
|
||||
ALERT_RULE_TYPE_ID,
|
||||
ALERT_RULE_UUID,
|
||||
TIMESTAMP,
|
||||
ALERT_START,
|
||||
ALERT_STATUS,
|
||||
ALERT_UUID,
|
||||
ALERT_WORKFLOW_STATUS,
|
||||
EVENT_ACTION,
|
||||
EVENT_KIND,
|
||||
SPACE_IDS,
|
||||
TIMESTAMP,
|
||||
} from '../../common/technical_rule_data_field_names';
|
||||
import { IRuleDataClient } from '../rule_data_client';
|
||||
import { AlertExecutorOptionsWithExtraServices } from '../types';
|
||||
|
@ -263,6 +264,7 @@ export const createLifecycleExecutor = (
|
|||
|
||||
event[ALERT_START] = started;
|
||||
event[ALERT_UUID] = alertUuid;
|
||||
event[ALERT_WORKFLOW_STATUS] = event[ALERT_WORKFLOW_STATUS] ?? 'open';
|
||||
|
||||
// not sure why typescript needs the non-null assertion here
|
||||
// we already assert the value is not undefined with the ternary
|
||||
|
|
|
@ -199,6 +199,7 @@ describe('createLifecycleRuleTypeFactory', () => {
|
|||
"kibana.alert.rule.uuid": "alertId",
|
||||
"kibana.alert.start": "2021-06-16T09:01:00.000Z",
|
||||
"kibana.alert.status": "open",
|
||||
"kibana.alert.workflow_status": "open",
|
||||
"kibana.space_ids": Array [
|
||||
"spaceId",
|
||||
],
|
||||
|
@ -221,6 +222,7 @@ describe('createLifecycleRuleTypeFactory', () => {
|
|||
"kibana.alert.rule.uuid": "alertId",
|
||||
"kibana.alert.start": "2021-06-16T09:01:00.000Z",
|
||||
"kibana.alert.status": "open",
|
||||
"kibana.alert.workflow_status": "open",
|
||||
"kibana.space_ids": Array [
|
||||
"spaceId",
|
||||
],
|
||||
|
|
|
@ -5,34 +5,47 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiPanel, EuiLoadingContent } from '@elastic/eui';
|
||||
import { EuiLoadingContent, EuiPanel } from '@elastic/eui';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { connect, ConnectedProps, useDispatch } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import { esQuery, Filter } from '../../../../../../../src/plugins/data/public';
|
||||
import { Status } from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { Filter, esQuery } from '../../../../../../../src/plugins/data/public';
|
||||
import { RowRendererId, TimelineIdLiteral } from '../../../../common/types/timeline';
|
||||
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
|
||||
import { StatefulEventsViewer } from '../../../common/components/events_viewer';
|
||||
import { HeaderSection } from '../../../common/components/header_section';
|
||||
import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features';
|
||||
import { combineQueries } from '../../../timelines/components/timeline/helpers';
|
||||
import { useKibana } from '../../../common/lib/kibana';
|
||||
import { inputsSelectors, State, inputsModel } from '../../../common/store';
|
||||
import { timelineActions, timelineSelectors } from '../../../timelines/store/timeline';
|
||||
import { TimelineModel } from '../../../timelines/store/timeline/model';
|
||||
import { timelineDefaults } from '../../../timelines/store/timeline/defaults';
|
||||
import { updateAlertStatusAction } from './actions';
|
||||
import {
|
||||
requiredFieldsForActions,
|
||||
alertsDefaultModel,
|
||||
buildAlertStatusFilter,
|
||||
alertsDefaultModelRuleRegistry,
|
||||
buildAlertStatusFilterRuleRegistry,
|
||||
} from './default_config';
|
||||
import { AditionalFiltersAction, AlertsUtilityBar } from './alerts_utility_bar';
|
||||
displayErrorToast,
|
||||
displaySuccessToast,
|
||||
useStateToaster,
|
||||
} from '../../../common/components/toasters';
|
||||
import { useSourcererScope } from '../../../common/containers/sourcerer';
|
||||
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
|
||||
import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features';
|
||||
import { useInvalidFilterQuery } from '../../../common/hooks/use_invalid_filter_query';
|
||||
import { defaultCellActions } from '../../../common/lib/cell_actions/default_cell_actions';
|
||||
import { useKibana } from '../../../common/lib/kibana';
|
||||
import { inputsModel, inputsSelectors, State } from '../../../common/store';
|
||||
import { SourcererScopeName } from '../../../common/store/sourcerer/model';
|
||||
import * as i18nCommon from '../../../common/translations';
|
||||
import { DEFAULT_COLUMN_MIN_WIDTH } from '../../../timelines/components/timeline/body/constants';
|
||||
import { defaultRowRenderers } from '../../../timelines/components/timeline/body/renderers';
|
||||
import { combineQueries } from '../../../timelines/components/timeline/helpers';
|
||||
import { timelineActions, timelineSelectors } from '../../../timelines/store/timeline';
|
||||
import { timelineDefaults } from '../../../timelines/store/timeline/defaults';
|
||||
import { TimelineModel } from '../../../timelines/store/timeline/model';
|
||||
import { columns, RenderCellValue } from '../../configurations/security_solution_detections';
|
||||
import { updateAlertStatusAction } from './actions';
|
||||
import { AditionalFiltersAction, AlertsUtilityBar } from './alerts_utility_bar';
|
||||
import {
|
||||
alertsDefaultModel,
|
||||
alertsDefaultModelRuleRegistry,
|
||||
buildAlertStatusFilter,
|
||||
buildAlertStatusFilterRuleRegistry,
|
||||
requiredFieldsForActions,
|
||||
} from './default_config';
|
||||
import { buildTimeRangeFilter } from './helpers';
|
||||
import * as i18n from './translations';
|
||||
import {
|
||||
SetEventsDeletedProps,
|
||||
|
@ -40,19 +53,6 @@ import {
|
|||
UpdateAlertsStatusCallback,
|
||||
UpdateAlertsStatusProps,
|
||||
} from './types';
|
||||
import {
|
||||
useStateToaster,
|
||||
displaySuccessToast,
|
||||
displayErrorToast,
|
||||
} from '../../../common/components/toasters';
|
||||
import { SourcererScopeName } from '../../../common/store/sourcerer/model';
|
||||
import { useSourcererScope } from '../../../common/containers/sourcerer';
|
||||
import { buildTimeRangeFilter } from './helpers';
|
||||
import { defaultRowRenderers } from '../../../timelines/components/timeline/body/renderers';
|
||||
import { columns, RenderCellValue } from '../../configurations/security_solution_detections';
|
||||
import { useInvalidFilterQuery } from '../../../common/hooks/use_invalid_filter_query';
|
||||
import { DEFAULT_COLUMN_MIN_WIDTH } from '../../../timelines/components/timeline/body/constants';
|
||||
import { defaultCellActions } from '../../../common/lib/cell_actions/default_cell_actions';
|
||||
|
||||
interface OwnProps {
|
||||
defaultFilters?: Filter[];
|
||||
|
@ -165,7 +165,7 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
text: i18nCommon.UPDATE_ALERT_STATUS_FAILED_DETAILED(updated, conflicts),
|
||||
});
|
||||
} else {
|
||||
let title: string;
|
||||
let title = '';
|
||||
switch (status) {
|
||||
case 'closed':
|
||||
title = i18n.CLOSED_ALERT_SUCCESS_TOAST(updated);
|
||||
|
@ -173,7 +173,6 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
case 'open':
|
||||
title = i18n.OPENED_ALERT_SUCCESS_TOAST(updated);
|
||||
break;
|
||||
case 'in-progress':
|
||||
case 'acknowledged':
|
||||
title = i18n.ACKNOWLEDGED_ALERT_SUCCESS_TOAST(updated);
|
||||
}
|
||||
|
@ -185,7 +184,7 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
|
||||
const onAlertStatusUpdateFailure = useCallback(
|
||||
(status: Status, error: Error) => {
|
||||
let title: string;
|
||||
let title = '';
|
||||
switch (status) {
|
||||
case 'closed':
|
||||
title = i18n.CLOSED_ALERT_FAILED_TOAST;
|
||||
|
@ -193,7 +192,6 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
case 'open':
|
||||
title = i18n.OPENED_ALERT_FAILED_TOAST;
|
||||
break;
|
||||
case 'in-progress':
|
||||
case 'acknowledged':
|
||||
title = i18n.ACKNOWLEDGED_ALERT_FAILED_TOAST;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@ import { useCallback } from 'react';
|
|||
import { useDispatch } from 'react-redux';
|
||||
import { useGetUserAlertsPermissions } from '@kbn/alerts';
|
||||
|
||||
import { useStatusBulkActionItems } from '../../../../../../timelines/public';
|
||||
import { Status } from '../../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { timelineActions } from '../../../../timelines/store/timeline';
|
||||
import { SetEventsDeletedProps, SetEventsLoadingProps } from '../types';
|
||||
import { useStatusBulkActionItems } from '../../../../../../timelines/public';
|
||||
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { SERVER_APP_ID } from '../../../../../common/constants';
|
||||
interface Props {
|
||||
|
|
|
@ -118,10 +118,12 @@ export interface BulkActionsObjectProp {
|
|||
}
|
||||
export type BulkActionsProp = boolean | BulkActionsObjectProp;
|
||||
|
||||
export type AlertWorkflowStatus = 'open' | 'closed' | 'acknowledged';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* TODO: remove when `acknowledged` migrations are finished
|
||||
*/
|
||||
export type InProgressStatus = 'in-progress';
|
||||
|
||||
export type AlertStatus = 'open' | 'closed' | 'acknowledged' | InProgressStatus;
|
||||
export type AlertStatus = AlertWorkflowStatus | InProgressStatus;
|
||||
|
|
|
@ -18138,10 +18138,6 @@
|
|||
"xpack.monitoring.updateLicenseTitle": "ライセンスの更新",
|
||||
"xpack.monitoring.useAvailableLicenseDescription": "すでに新しいライセンスがある場合は、今すぐアップロードしてください。",
|
||||
"xpack.observability.alerts.searchBarPlaceholder": "\"domain\": \"ecommerce\" AND (\"service.name\":\"ProductCatalogService\" …)",
|
||||
"xpack.observability.alerts.statusFilter.allButtonLabel": "すべて",
|
||||
"xpack.observability.alerts.statusFilter.closedButtonLabel": "終了",
|
||||
"xpack.observability.alerts.statusFilter.openButtonLabel": "開く",
|
||||
"xpack.observability.alerts.statusFilterAriaLabel": "未解決および終了ステータスでアラートをフィルター",
|
||||
"xpack.observability.alertsDisclaimerLinkText": "アラートとアクション",
|
||||
"xpack.observability.alertsDisclaimerText": "このページには実験アラートビューが表示されます。ここに表示されるデータは、アラートを正確に表していない可能性があります。アラートの非実験リストは、スタック管理のアラートとアクション設定にあります。",
|
||||
"xpack.observability.alertsDisclaimerTitle": "実験的",
|
||||
|
|
|
@ -18547,10 +18547,6 @@
|
|||
"xpack.monitoring.updateLicenseTitle": "更新您的许可证",
|
||||
"xpack.monitoring.useAvailableLicenseDescription": "如果您已经持有新的许可证,请立即上传。",
|
||||
"xpack.observability.alerts.searchBarPlaceholder": "\"domain\": \"ecommerce\" AND (\"service.name\":\"ProductCatalogService\" …)",
|
||||
"xpack.observability.alerts.statusFilter.allButtonLabel": "全部",
|
||||
"xpack.observability.alerts.statusFilter.closedButtonLabel": "已关闭",
|
||||
"xpack.observability.alerts.statusFilter.openButtonLabel": "打开",
|
||||
"xpack.observability.alerts.statusFilterAriaLabel": "按未结和关闭状态筛选告警",
|
||||
"xpack.observability.alertsDisclaimerLinkText": "告警和操作",
|
||||
"xpack.observability.alertsDisclaimerText": "此页面显示实验性告警视图。此处显示的数据可能无法准确表示告警。在“堆栈管理”的“告警和操作”中提供了告警的非实验性列表。",
|
||||
"xpack.observability.alertsDisclaimerTitle": "实验性",
|
||||
|
|
|
@ -9,11 +9,11 @@ import expect from '@kbn/expect';
|
|||
import {
|
||||
ALERT_DURATION,
|
||||
ALERT_END,
|
||||
ALERT_RULE_UUID,
|
||||
ALERT_START,
|
||||
ALERT_STATUS,
|
||||
ALERT_UUID,
|
||||
EVENT_KIND,
|
||||
ALERT_RULE_UUID,
|
||||
} from '@kbn/rule-data-utils';
|
||||
import { merge, omit } from 'lodash';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
|
@ -393,6 +393,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
"kibana.alert.status": Array [
|
||||
"open",
|
||||
],
|
||||
"kibana.alert.workflow_status": Array [
|
||||
"open",
|
||||
],
|
||||
"kibana.space_ids": Array [
|
||||
"default",
|
||||
],
|
||||
|
@ -500,6 +503,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
"kibana.alert.status": Array [
|
||||
"closed",
|
||||
],
|
||||
"kibana.alert.workflow_status": Array [
|
||||
"open",
|
||||
],
|
||||
"kibana.space_ids": Array [
|
||||
"default",
|
||||
],
|
||||
|
|
Loading…
Reference in a new issue