mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Actionable Observability] Add links to navigate from alerts table and flyout to rule generate it Co-authored-by: Ersin Erdal <92688503+ersin-erdal@users.noreply.github.com>
This commit is contained in:
parent
51956998de
commit
cdafd322c7
9 changed files with 244 additions and 126 deletions
|
@ -24,6 +24,7 @@ import { EuiSelect } from '@elastic/eui';
|
|||
import { uniqBy } from 'lodash';
|
||||
import { Alert } from '../../../../../../alerting/common';
|
||||
import { usePluginContext } from '../../../../hooks/use_plugin_context';
|
||||
import { paths } from '../../../../config';
|
||||
|
||||
const ALL_TYPES = 'ALL_TYPES';
|
||||
const allTypes = {
|
||||
|
@ -41,8 +42,8 @@ export function AlertsSection({ alerts }: Props) {
|
|||
const { config, core } = usePluginContext();
|
||||
const [filter, setFilter] = useState(ALL_TYPES);
|
||||
const manageLink = config.unsafe.alertingExperience.enabled
|
||||
? core.http.basePath.prepend(`/app/observability/alerts`)
|
||||
: core.http.basePath.prepend(`/app/management/insightsAndAlerting/triggersActions/rules`);
|
||||
? core.http.basePath.prepend(paths.observability.alerts)
|
||||
: core.http.basePath.prepend(paths.management.rules);
|
||||
const filterOptions = uniqBy(alerts, (alert) => alert.consumer).map(({ consumer }) => ({
|
||||
value: consumer,
|
||||
text: consumer,
|
||||
|
@ -89,9 +90,7 @@ export function AlertsSection({ alerts }: Props) {
|
|||
<EuiFlexGroup direction="column" gutterSize="s" key={alert.id}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLink
|
||||
href={core.http.basePath.prepend(
|
||||
`/app/management/insightsAndAlerting/triggersActions/alert/${alert.id}`
|
||||
)}
|
||||
href={core.http.basePath.prepend(paths.management.alertDetails(alert.id))}
|
||||
>
|
||||
<EuiText size="s">{alert.name}</EuiText>
|
||||
</EuiLink>
|
||||
|
|
9
x-pack/plugins/observability/public/config/index.ts
Normal file
9
x-pack/plugins/observability/public/config/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { paths } from './paths';
|
||||
export { translations } from './translations';
|
19
x-pack/plugins/observability/public/config/paths.ts
Normal file
19
x-pack/plugins/observability/public/config/paths.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const paths = {
|
||||
observability: {
|
||||
alerts: '/app/observability/alerts',
|
||||
},
|
||||
management: {
|
||||
rules: '/app/management/insightsAndAlerting/triggersActions/rules',
|
||||
ruleDetails: (ruleId: string) =>
|
||||
`/app/management/insightsAndAlerting/triggersActions/rule/${encodeURI(ruleId)}`,
|
||||
alertDetails: (alertId: string) =>
|
||||
`/app/management/insightsAndAlerting/triggersActions/alert/${encodeURI(alertId)}`,
|
||||
},
|
||||
};
|
104
x-pack/plugins/observability/public/config/translations.ts
Normal file
104
x-pack/plugins/observability/public/config/translations.ts
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
export const translations = {
|
||||
alertsTable: {
|
||||
viewDetailsTextLabel: i18n.translate('xpack.observability.alertsTable.viewDetailsTextLabel', {
|
||||
defaultMessage: 'View details',
|
||||
}),
|
||||
viewInAppTextLabel: i18n.translate('xpack.observability.alertsTable.viewInAppTextLabel', {
|
||||
defaultMessage: 'View in app',
|
||||
}),
|
||||
moreActionsTextLabel: i18n.translate('xpack.observability.alertsTable.moreActionsTextLabel', {
|
||||
defaultMessage: 'More actions',
|
||||
}),
|
||||
notEnoughPermissions: i18n.translate('xpack.observability.alertsTable.notEnoughPermissions', {
|
||||
defaultMessage: 'Additional privileges required',
|
||||
}),
|
||||
statusColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.statusColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Alert Status',
|
||||
}
|
||||
),
|
||||
lastUpdatedColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.lastUpdatedColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Last updated',
|
||||
}
|
||||
),
|
||||
durationColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.durationColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Duration',
|
||||
}
|
||||
),
|
||||
reasonColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.reasonColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Reason',
|
||||
}
|
||||
),
|
||||
actionsTextLabel: i18n.translate('xpack.observability.alertsTable.actionsTextLabel', {
|
||||
defaultMessage: 'Actions',
|
||||
}),
|
||||
loadingTextLabel: i18n.translate('xpack.observability.alertsTable.loadingTextLabel', {
|
||||
defaultMessage: 'loading alerts',
|
||||
}),
|
||||
footerTextLabel: i18n.translate('xpack.observability.alertsTable.footerTextLabel', {
|
||||
defaultMessage: 'alerts',
|
||||
}),
|
||||
showingAlertsTitle: (totalAlerts: number) =>
|
||||
i18n.translate('xpack.observability.alertsTable.showingAlertsTitle', {
|
||||
values: { totalAlerts },
|
||||
defaultMessage: '{totalAlerts, plural, =1 {alert} other {alerts}}',
|
||||
}),
|
||||
viewRuleDetailsButtonText: i18n.translate(
|
||||
'xpack.observability.alertsTable.viewRuleDetailsButtonText',
|
||||
{
|
||||
defaultMessage: 'View rule details',
|
||||
}
|
||||
),
|
||||
},
|
||||
alertsFlyout: {
|
||||
statusLabel: i18n.translate('xpack.observability.alertsFlyout.statusLabel', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
lastUpdatedLabel: i18n.translate('xpack.observability.alertsFlyout.lastUpdatedLabel', {
|
||||
defaultMessage: 'Last updated',
|
||||
}),
|
||||
durationLabel: i18n.translate('xpack.observability.alertsFlyout.durationLabel', {
|
||||
defaultMessage: 'Duration',
|
||||
}),
|
||||
expectedValueLabel: i18n.translate('xpack.observability.alertsFlyout.expectedValueLabel', {
|
||||
defaultMessage: 'Expected value',
|
||||
}),
|
||||
actualValueLabel: i18n.translate('xpack.observability.alertsFlyout.actualValueLabel', {
|
||||
defaultMessage: 'Actual value',
|
||||
}),
|
||||
ruleTypeLabel: i18n.translate('xpack.observability.alertsFlyout.ruleTypeLabel', {
|
||||
defaultMessage: 'Rule type',
|
||||
}),
|
||||
reasonTitle: i18n.translate('xpack.observability.alertsFlyout.reasonTitle', {
|
||||
defaultMessage: 'Reason',
|
||||
}),
|
||||
viewRulesDetailsLinkText: i18n.translate(
|
||||
'xpack.observability.alertsFlyout.viewRulesDetailsLinkText',
|
||||
{
|
||||
defaultMessage: 'View rule details',
|
||||
}
|
||||
),
|
||||
documentSummaryTitle: i18n.translate('xpack.observability.alertsFlyout.documentSummaryTitle', {
|
||||
defaultMessage: 'Document Summary',
|
||||
}),
|
||||
viewInAppButtonText: i18n.translate('xpack.observability.alertsFlyout.viewInAppButtonText', {
|
||||
defaultMessage: 'View in app',
|
||||
}),
|
||||
},
|
||||
};
|
|
@ -15,11 +15,12 @@ import {
|
|||
EuiFlyoutFooter,
|
||||
EuiFlyoutHeader,
|
||||
EuiFlyoutProps,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type {
|
||||
ALERT_DURATION as ALERT_DURATION_TYPED,
|
||||
ALERT_EVALUATION_THRESHOLD as ALERT_EVALUATION_THRESHOLD_TYPED,
|
||||
|
@ -47,6 +48,7 @@ import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observ
|
|||
import { parseAlert } from '../parse_alert';
|
||||
import { AlertStatusIndicator } from '../../../components/shared/alert_status_indicator';
|
||||
import { ExperimentalBadge } from '../../../components/shared/experimental_badge';
|
||||
import { translations, paths } from '../../../config';
|
||||
|
||||
type AlertsFlyoutProps = {
|
||||
alert?: TopAlert;
|
||||
|
@ -77,6 +79,7 @@ export function AlertsFlyout({
|
|||
const { services } = useKibana();
|
||||
const { http } = services;
|
||||
const prepend = http?.basePath.prepend;
|
||||
|
||||
const decoratedAlerts = useMemo(() => {
|
||||
const parseObservabilityAlert = parseAlert(observabilityRuleTypeRegistry);
|
||||
return (alerts ?? []).map(parseObservabilityAlert);
|
||||
|
@ -90,11 +93,12 @@ export function AlertsFlyout({
|
|||
return null;
|
||||
}
|
||||
|
||||
const ruleId = alertData.fields['kibana.alert.rule.uuid'] ?? null;
|
||||
const linkToRule = ruleId && prepend ? prepend(paths.management.ruleDetails(ruleId)) : null;
|
||||
|
||||
const overviewListItems = [
|
||||
{
|
||||
title: i18n.translate('xpack.observability.alertsFlyout.statusLabel', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
title: translations.alertsFlyout.statusLabel,
|
||||
description: (
|
||||
<AlertStatusIndicator
|
||||
alertStatus={alertData.active ? ALERT_STATUS_ACTIVE : ALERT_STATUS_RECOVERED}
|
||||
|
@ -102,52 +106,55 @@ export function AlertsFlyout({
|
|||
),
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.observability.alertsFlyout.lastUpdatedLabel', {
|
||||
defaultMessage: 'Last updated',
|
||||
}),
|
||||
title: translations.alertsFlyout.lastUpdatedLabel,
|
||||
description: (
|
||||
<span title={alertData.start.toString()}>{moment(alertData.start).format(dateFormat)}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.observability.alertsFlyout.durationLabel', {
|
||||
defaultMessage: 'Duration',
|
||||
}),
|
||||
title: translations.alertsFlyout.durationLabel,
|
||||
description: asDuration(alertData.fields[ALERT_DURATION], { extended: true }),
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.observability.alertsFlyout.expectedValueLabel', {
|
||||
defaultMessage: 'Expected value',
|
||||
}),
|
||||
title: translations.alertsFlyout.expectedValueLabel,
|
||||
description: alertData.fields[ALERT_EVALUATION_THRESHOLD] ?? '-',
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.observability.alertsFlyout.actualValueLabel', {
|
||||
defaultMessage: 'Actual value',
|
||||
}),
|
||||
title: translations.alertsFlyout.actualValueLabel,
|
||||
description: alertData.fields[ALERT_EVALUATION_VALUE] ?? '-',
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.observability.alertsFlyout.ruleTypeLabel', {
|
||||
defaultMessage: 'Rule type',
|
||||
}),
|
||||
title: translations.alertsFlyout.ruleTypeLabel,
|
||||
description: alertData.fields[ALERT_RULE_CATEGORY] ?? '-',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiFlyout onClose={onClose} size="s" data-test-subj="alertsFlyout">
|
||||
<EuiFlyoutHeader>
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<ExperimentalBadge />
|
||||
<EuiSpacer size="s" />
|
||||
<EuiTitle size="m" data-test-subj="alertsFlyoutTitle">
|
||||
<h2>{alertData.fields[ALERT_RULE_NAME]}</h2>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s">{alertData.reason}</EuiText>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<EuiTitle size="xs">
|
||||
<h4>{translations.alertsFlyout.reasonTitle}</h4>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s">{alertData.reason}</EuiText>
|
||||
<EuiSpacer size="s" />
|
||||
{!!linkToRule && (
|
||||
<EuiLink href={linkToRule} data-test-subj="viewRuleDetailsFlyout">
|
||||
{translations.alertsFlyout.viewRulesDetailsLinkText}
|
||||
</EuiLink>
|
||||
)}
|
||||
<EuiHorizontalRule size="full" />
|
||||
<EuiTitle size="xs">
|
||||
<h4>{translations.alertsFlyout.documentSummaryTitle}</h4>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiDescriptionList
|
||||
compressed={true}
|
||||
type="responsiveColumn"
|
||||
|
@ -173,7 +180,7 @@ export function AlertsFlyout({
|
|||
data-test-subj="alertsFlyoutViewInAppButton"
|
||||
fill
|
||||
>
|
||||
View in app
|
||||
{translations.alertsFlyout.viewInAppButtonText}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -34,10 +34,12 @@ import {
|
|||
EuiDataGridColumn,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiContextMenuItem,
|
||||
EuiContextMenuPanel,
|
||||
EuiPopover,
|
||||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import React, { Suspense, useMemo, useState, useCallback, useEffect } from 'react';
|
||||
import usePrevious from 'react-use/lib/usePrevious';
|
||||
|
@ -65,7 +67,7 @@ import { getDefaultCellActions } from './default_cell_actions';
|
|||
import { LazyAlertsFlyout } from '../..';
|
||||
import { parseAlert } from './parse_alert';
|
||||
import { CoreStart } from '../../../../../../src/core/public';
|
||||
import { translations } from './translations';
|
||||
import { translations, paths } from '../../config';
|
||||
|
||||
const ALERT_DURATION: typeof ALERT_DURATION_TYPED = ALERT_DURATION_NON_TYPED;
|
||||
const ALERT_REASON: typeof ALERT_REASON_TYPED = ALERT_REASON_NON_TYPED;
|
||||
|
@ -115,25 +117,25 @@ export const columns: Array<
|
|||
> = [
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
displayAsText: translations.statusColumnDescription,
|
||||
displayAsText: translations.alertsTable.statusColumnDescription,
|
||||
id: ALERT_STATUS,
|
||||
initialWidth: 110,
|
||||
},
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
displayAsText: translations.lastUpdatedColumnDescription,
|
||||
displayAsText: translations.alertsTable.lastUpdatedColumnDescription,
|
||||
id: TIMESTAMP,
|
||||
initialWidth: 230,
|
||||
},
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
displayAsText: translations.durationColumnDescription,
|
||||
displayAsText: translations.alertsTable.durationColumnDescription,
|
||||
id: ALERT_DURATION,
|
||||
initialWidth: 116,
|
||||
},
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
displayAsText: translations.reasonColumnDescription,
|
||||
displayAsText: translations.alertsTable.reasonColumnDescription,
|
||||
id: ALERT_REASON,
|
||||
linkField: '*',
|
||||
},
|
||||
|
@ -188,6 +190,7 @@ function ObservabilityActions({
|
|||
const toggleActionsPopover = useCallback((id) => {
|
||||
setActionsPopover((current) => (current ? null : id));
|
||||
}, []);
|
||||
|
||||
const casePermissions = useGetUserCasesPermissions();
|
||||
const event = useMemo(() => {
|
||||
return {
|
||||
|
@ -219,6 +222,9 @@ function ObservabilityActions({
|
|||
onUpdateFailure: onAlertStatusUpdated,
|
||||
});
|
||||
|
||||
const ruleId = alert.fields['kibana.alert.rule.uuid'] ?? null;
|
||||
const linkToRule = ruleId ? prepend(paths.management.ruleDetails(ruleId)) : null;
|
||||
|
||||
const actionsMenuItems = useMemo(() => {
|
||||
return [
|
||||
...(casePermissions?.crud
|
||||
|
@ -240,37 +246,56 @@ function ObservabilityActions({
|
|||
]
|
||||
: []),
|
||||
...(alertPermissions.crud ? statusActionItems : []),
|
||||
...(!!linkToRule
|
||||
? [
|
||||
<EuiContextMenuItem
|
||||
key="viewRuleDetails"
|
||||
data-test-subj="viewRuleDetails"
|
||||
href={linkToRule}
|
||||
>
|
||||
{translations.alertsTable.viewRuleDetailsButtonText}
|
||||
</EuiContextMenuItem>,
|
||||
]
|
||||
: []),
|
||||
];
|
||||
}, [afterCaseSelection, casePermissions, timelines, event, statusActionItems, alertPermissions]);
|
||||
}, [
|
||||
afterCaseSelection,
|
||||
casePermissions,
|
||||
timelines,
|
||||
event,
|
||||
statusActionItems,
|
||||
alertPermissions,
|
||||
linkToRule,
|
||||
]);
|
||||
|
||||
const actionsToolTip =
|
||||
actionsMenuItems.length <= 0
|
||||
? translations.notEnoughPermissions
|
||||
: translations.moreActionsTextLabel;
|
||||
? translations.alertsTable.notEnoughPermissions
|
||||
: translations.alertsTable.moreActionsTextLabel;
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup gutterSize="none" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={translations.viewDetailsTextLabel}>
|
||||
<EuiToolTip content={translations.alertsTable.viewDetailsTextLabel}>
|
||||
<EuiButtonIcon
|
||||
size="s"
|
||||
iconType="expand"
|
||||
color="text"
|
||||
onClick={() => setFlyoutAlert(alert)}
|
||||
data-test-subj="openFlyoutButton"
|
||||
aria-label={translations.viewDetailsTextLabel}
|
||||
aria-label={translations.alertsTable.viewDetailsTextLabel}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={translations.viewInAppTextLabel}>
|
||||
<EuiToolTip content={translations.alertsTable.viewInAppTextLabel}>
|
||||
<EuiButtonIcon
|
||||
size="s"
|
||||
href={prepend(alert.link ?? '')}
|
||||
iconType="eye"
|
||||
color="text"
|
||||
aria-label={translations.viewInAppTextLabel}
|
||||
aria-label={translations.alertsTable.viewInAppTextLabel}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
|
@ -280,7 +305,6 @@ function ObservabilityActions({
|
|||
<EuiToolTip content={actionsToolTip}>
|
||||
<EuiButtonIcon
|
||||
display="empty"
|
||||
disabled={actionsMenuItems.length <= 0}
|
||||
size="s"
|
||||
color="text"
|
||||
iconType="boxesHorizontal"
|
||||
|
@ -345,7 +369,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
id: 'expand',
|
||||
width: 120,
|
||||
headerCellRender: () => {
|
||||
return <EventsThContent>{translations.actionsTextLabel}</EventsThContent>;
|
||||
return <EventsThContent>{translations.alertsTable.actionsTextLabel}</EventsThContent>;
|
||||
},
|
||||
rowCellRender: (actionProps: ActionProps) => {
|
||||
return (
|
||||
|
@ -377,8 +401,8 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
hasAlertsCrudPermissions,
|
||||
indexNames,
|
||||
itemsPerPageOptions: [10, 25, 50],
|
||||
loadingText: translations.loadingTextLabel,
|
||||
footerText: translations.footerTextLabel,
|
||||
loadingText: translations.alertsTable.loadingTextLabel,
|
||||
footerText: translations.alertsTable.footerTextLabel,
|
||||
query: {
|
||||
query: `${ALERT_WORKFLOW_STATUS}: ${workflowStatus}${kuery !== '' ? ` and ${kuery}` : ''}`,
|
||||
language: 'kuery',
|
||||
|
@ -399,7 +423,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
|
|||
filterStatus: workflowStatus as AlertWorkflowStatus,
|
||||
leadingControlColumns,
|
||||
trailingControlColumns,
|
||||
unit: (totalAlerts: number) => translations.showingAlertsTitle(totalAlerts),
|
||||
unit: (totalAlerts: number) => translations.alertsTable.showingAlertsTitle(totalAlerts),
|
||||
};
|
||||
}, [
|
||||
casePermissions,
|
||||
|
|
|
@ -1,61 +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 { i18n } from '@kbn/i18n';
|
||||
|
||||
export const translations = {
|
||||
viewDetailsTextLabel: i18n.translate('xpack.observability.alertsTable.viewDetailsTextLabel', {
|
||||
defaultMessage: 'View details',
|
||||
}),
|
||||
viewInAppTextLabel: i18n.translate('xpack.observability.alertsTable.viewInAppTextLabel', {
|
||||
defaultMessage: 'View in app',
|
||||
}),
|
||||
moreActionsTextLabel: i18n.translate('xpack.observability.alertsTable.moreActionsTextLabel', {
|
||||
defaultMessage: 'More actions',
|
||||
}),
|
||||
notEnoughPermissions: i18n.translate('xpack.observability.alertsTable.notEnoughPermissions', {
|
||||
defaultMessage: 'Additional privileges required',
|
||||
}),
|
||||
statusColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.statusColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Alert Status',
|
||||
}
|
||||
),
|
||||
lastUpdatedColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.lastUpdatedColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Last updated',
|
||||
}
|
||||
),
|
||||
durationColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.durationColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Duration',
|
||||
}
|
||||
),
|
||||
reasonColumnDescription: i18n.translate(
|
||||
'xpack.observability.alertsTGrid.reasonColumnDescription',
|
||||
{
|
||||
defaultMessage: 'Reason',
|
||||
}
|
||||
),
|
||||
actionsTextLabel: i18n.translate('xpack.observability.alertsTable.actionsTextLabel', {
|
||||
defaultMessage: 'Actions',
|
||||
}),
|
||||
loadingTextLabel: i18n.translate('xpack.observability.alertsTable.loadingTextLabel', {
|
||||
defaultMessage: 'loading alerts',
|
||||
}),
|
||||
footerTextLabel: i18n.translate('xpack.observability.alertsTable.footerTextLabel', {
|
||||
defaultMessage: 'alerts',
|
||||
}),
|
||||
showingAlertsTitle: (totalAlerts: number) =>
|
||||
i18n.translate('xpack.observability.alertsTable.showingAlertsTitle', {
|
||||
values: { totalAlerts },
|
||||
defaultMessage: '{totalAlerts, plural, =1 {alert} other {alerts}}',
|
||||
}),
|
||||
};
|
|
@ -18,6 +18,9 @@ const DATE_WITH_DATA = {
|
|||
const ALERTS_FLYOUT_SELECTOR = 'alertsFlyout';
|
||||
const FILTER_FOR_VALUE_BUTTON_SELECTOR = 'filterForValue';
|
||||
const ALERTS_TABLE_CONTAINER_SELECTOR = 'events-viewer-panel';
|
||||
const VIEW_RULE_DETAILS_SELECTOR = 'viewRuleDetails';
|
||||
const VIEW_RULE_DETAILS_FLYOUT_SELECTOR = 'viewRuleDetailsFlyout';
|
||||
|
||||
const ACTION_COLUMN_INDEX = 1;
|
||||
|
||||
type WorkflowStatus = 'open' | 'acknowledged' | 'closed';
|
||||
|
@ -150,6 +153,10 @@ export function ObservabilityAlertsCommonProvider({
|
|||
return await testSubjects.existOrFail('alertsFlyoutViewInAppButton');
|
||||
};
|
||||
|
||||
const getAlertsFlyoutViewRuleDetailsLinkOrFail = async () => {
|
||||
return await testSubjects.existOrFail('viewRuleDetailsFlyout');
|
||||
};
|
||||
|
||||
const getAlertsFlyoutDescriptionListTitles = async (): Promise<WebElementWrapper[]> => {
|
||||
const flyout = await getAlertsFlyout();
|
||||
return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListTitle', flyout);
|
||||
|
@ -179,6 +186,13 @@ export function ObservabilityAlertsCommonProvider({
|
|||
await actionsOverflowButton.click();
|
||||
};
|
||||
|
||||
const viewRuleDetailsButtonClick = async () => {
|
||||
return await (await testSubjects.find(VIEW_RULE_DETAILS_SELECTOR)).click();
|
||||
};
|
||||
const viewRuleDetailsLinkClick = async () => {
|
||||
return await (await testSubjects.find(VIEW_RULE_DETAILS_FLYOUT_SELECTOR)).click();
|
||||
};
|
||||
|
||||
// Workflow status
|
||||
const setWorkflowStatusForRow = async (rowIndex: number, workflowStatus: WorkflowStatus) => {
|
||||
await openActionsMenuForRow(rowIndex);
|
||||
|
@ -259,5 +273,8 @@ export function ObservabilityAlertsCommonProvider({
|
|||
navigateWithoutFilter,
|
||||
getExperimentalDisclaimer,
|
||||
getActionsButtonByIndex,
|
||||
viewRuleDetailsButtonClick,
|
||||
viewRuleDetailsLinkClick,
|
||||
getAlertsFlyoutViewRuleDetailsLinkOrFail,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,8 +20,9 @@ const TOTAL_ALERTS_CELL_COUNT = 198;
|
|||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const find = getService('find');
|
||||
|
||||
describe('Observability alerts', function () {
|
||||
describe('Observability alerts 1', function () {
|
||||
this.tags('includeFirefox');
|
||||
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
@ -178,6 +179,10 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
it('Displays a View in App button', async () => {
|
||||
await observability.alerts.common.getAlertsFlyoutViewInAppButtonOrFail();
|
||||
});
|
||||
|
||||
it('Displays a View rule details link', async () => {
|
||||
await observability.alerts.common.getAlertsFlyoutViewRuleDetailsLinkOrFail();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -213,28 +218,23 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Actions Button', () => {
|
||||
before(async () => {
|
||||
await observability.users.setTestUserRole(
|
||||
observability.users.defineBasicObservabilityRole({
|
||||
observabilityCases: ['read'],
|
||||
logs: ['read'],
|
||||
})
|
||||
);
|
||||
await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs');
|
||||
await observability.alerts.common.navigateToTimeWithData();
|
||||
});
|
||||
describe('Actions Button', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs');
|
||||
await observability.alerts.common.navigateToTimeWithData();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await observability.users.restoreDefaultTestUserRole();
|
||||
await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs');
|
||||
});
|
||||
after(async () => {
|
||||
await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs');
|
||||
});
|
||||
|
||||
it('Is disabled when a user has only read privilages', async () => {
|
||||
const actionsButton = await observability.alerts.common.getActionsButtonByIndex(0);
|
||||
expect(await actionsButton.getAttribute('disabled')).to.be('true');
|
||||
it('Opens rule details page when click on "View Rule Details"', async () => {
|
||||
const actionsButton = await observability.alerts.common.getActionsButtonByIndex(0);
|
||||
await actionsButton.click();
|
||||
await observability.alerts.common.viewRuleDetailsButtonClick();
|
||||
expect(await find.existsByCssSelector('[title="Rules and Connectors"]')).to.eql(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue