[Alerting UI]Changed rules table to support visual indication for disabled and muted alerts (#104190)

* [Alerting UI]Changed rules table to support visual indication for disabled or muted alerts

* changed columns styles due to the mockup

* added tests

* fixed quotas

* fixed popover

* fixed due to the lates UI updates

* fixed errors

* moved enabled to a separate component

* fixed tests

* fixed due to comments

* Update x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.scss

Co-authored-by: Mike Côté <mikecote@users.noreply.github.com>

* removed test code

* fixed tests

* fixed due to comments

* fixed due to comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Mike Côté <mikecote@users.noreply.github.com>
This commit is contained in:
Yuliia Naumenko 2021-07-20 18:41:15 +03:00 committed by GitHub
parent 05c29efab5
commit d91c6d0cfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 412 additions and 257 deletions

View file

@ -22829,7 +22829,6 @@
"xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.active": "アクティブ", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.active": "アクティブ",
"xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive": "OK", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive": "OK",
"xpack.triggersActionsUI.sections.alertDetails.alerts.disabledRuleTitle": "無効なルール", "xpack.triggersActionsUI.sections.alertDetails.alerts.disabledRuleTitle": "無効なルール",
"xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle": "無効にする",
"xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle": "ミュート", "xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle": "ミュート",
"xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle": "閉じる", "xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle": "閉じる",
"xpack.triggersActionsUI.sections.alertDetails.editAlertButtonLabel": "編集", "xpack.triggersActionsUI.sections.alertDetails.editAlertButtonLabel": "編集",
@ -22883,10 +22882,8 @@
"xpack.triggersActionsUI.sections.alertsList.alertErrorReasonReading": "ルールの読み取り中にエラーが発生しました。", "xpack.triggersActionsUI.sections.alertsList.alertErrorReasonReading": "ルールの読み取り中にエラーが発生しました。",
"xpack.triggersActionsUI.sections.alertsList.alertErrorReasonRunning": "ルールの実行中にエラーが発生しました。", "xpack.triggersActionsUI.sections.alertsList.alertErrorReasonRunning": "ルールの実行中にエラーが発生しました。",
"xpack.triggersActionsUI.sections.alertsList.alertErrorReasonUnknown": "不明な理由でエラーが発生しました。", "xpack.triggersActionsUI.sections.alertsList.alertErrorReasonUnknown": "不明な理由でエラーが発生しました。",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsCount": "アクション",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTex": "アクション", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTex": "アクション",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.alertTypeTitle": "型", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.alertTypeTitle": "型",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.intervalTitle": "次の間隔で実行",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.nameTitle": "名前", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.nameTitle": "名前",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.statusTitle": "ステータス", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.statusTitle": "ステータス",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.tagsText": "タグ", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.tagsText": "タグ",
@ -22908,10 +22905,7 @@
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.failedToUnmuteRulesMessage": "ルールをミュート解除できませんでした", "xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.failedToUnmuteRulesMessage": "ルールをミュート解除できませんでした",
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle": "ミュート", "xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle": "ミュート",
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle": "ミュート解除", "xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle": "ミュート解除",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteTitle": "削除",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableHelpText": "無効にすると、ルールは確認されません。",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle": "無効にする", "xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle": "無効にする",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteHelpText": "ミュートにすると、ルールは確認されますが、アクションは実行されません。",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle": "ミュート", "xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle": "ミュート",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle": "アクション", "xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle": "アクション",
"xpack.triggersActionsUI.sections.alertsList.dismissBunnerButtonLabel": "閉じる", "xpack.triggersActionsUI.sections.alertsList.dismissBunnerButtonLabel": "閉じる",

View file

@ -23185,7 +23185,6 @@
"xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.active": "活动", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.active": "活动",
"xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive": "确定", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive": "确定",
"xpack.triggersActionsUI.sections.alertDetails.alerts.disabledRuleTitle": "已禁用规则", "xpack.triggersActionsUI.sections.alertDetails.alerts.disabledRuleTitle": "已禁用规则",
"xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle": "禁用",
"xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle": "静音", "xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle": "静音",
"xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle": "关闭", "xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle": "关闭",
"xpack.triggersActionsUI.sections.alertDetails.editAlertButtonLabel": "编辑", "xpack.triggersActionsUI.sections.alertDetails.editAlertButtonLabel": "编辑",
@ -23239,10 +23238,8 @@
"xpack.triggersActionsUI.sections.alertsList.alertErrorReasonReading": "读取规则时发生错误。", "xpack.triggersActionsUI.sections.alertsList.alertErrorReasonReading": "读取规则时发生错误。",
"xpack.triggersActionsUI.sections.alertsList.alertErrorReasonRunning": "运行规则时发生错误。", "xpack.triggersActionsUI.sections.alertsList.alertErrorReasonRunning": "运行规则时发生错误。",
"xpack.triggersActionsUI.sections.alertsList.alertErrorReasonUnknown": "由于未知原因发生错误。", "xpack.triggersActionsUI.sections.alertsList.alertErrorReasonUnknown": "由于未知原因发生错误。",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsCount": "操作",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTex": "操作", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTex": "操作",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.alertTypeTitle": "类型", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.alertTypeTitle": "类型",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.intervalTitle": "运行间隔",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.nameTitle": "名称", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.nameTitle": "名称",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.statusTitle": "状态", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.statusTitle": "状态",
"xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.tagsText": "标签", "xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.tagsText": "标签",
@ -23265,10 +23262,7 @@
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.failedToUnmuteRulesMessage": "无法取消静音规则", "xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.failedToUnmuteRulesMessage": "无法取消静音规则",
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle": "静音", "xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle": "静音",
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle": "取消静音", "xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle": "取消静音",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteTitle": "删除",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableHelpText": "禁用后,将不检查规则。",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle": "禁用", "xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle": "禁用",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteHelpText": "静音后,将检查规则,但不执行操作。",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle": "静音", "xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle": "静音",
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle": "操作", "xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle": "操作",
"xpack.triggersActionsUI.sections.alertsList.dismissBunnerButtonLabel": "关闭", "xpack.triggersActionsUI.sections.alertsList.dismissBunnerButtonLabel": "关闭",

View file

@ -359,16 +359,16 @@ describe('disable button', () => {
<AlertDetails alert={alert} alertType={alertType} actionTypes={[]} {...mockAlertApis} /> <AlertDetails alert={alert} alertType={alertType} actionTypes={[]} {...mockAlertApis} />
) )
.find(EuiSwitch) .find(EuiSwitch)
.find('[name="disable"]') .find('[name="enable"]')
.first(); .first();
expect(enableButton.props()).toMatchObject({ expect(enableButton.props()).toMatchObject({
checked: false, checked: true,
disabled: false, disabled: false,
}); });
}); });
it('should render a disable button when alert is disabled', () => { it('should render a enable button when alert is disabled', () => {
const alert = mockAlert({ const alert = mockAlert({
enabled: false, enabled: false,
}); });
@ -390,11 +390,11 @@ describe('disable button', () => {
<AlertDetails alert={alert} alertType={alertType} actionTypes={[]} {...mockAlertApis} /> <AlertDetails alert={alert} alertType={alertType} actionTypes={[]} {...mockAlertApis} />
) )
.find(EuiSwitch) .find(EuiSwitch)
.find('[name="disable"]') .find('[name="enable"]')
.first(); .first();
expect(enableButton.props()).toMatchObject({ expect(enableButton.props()).toMatchObject({
checked: true, checked: false,
disabled: false, disabled: false,
}); });
}); });
@ -428,7 +428,7 @@ describe('disable button', () => {
/> />
) )
.find(EuiSwitch) .find(EuiSwitch)
.find('[name="disable"]') .find('[name="enable"]')
.first(); .first();
enableButton.simulate('click'); enableButton.simulate('click');
@ -468,7 +468,7 @@ describe('disable button', () => {
/> />
) )
.find(EuiSwitch) .find(EuiSwitch)
.find('[name="disable"]') .find('[name="enable"]')
.first(); .first();
enableButton.simulate('click'); enableButton.simulate('click');
@ -531,14 +531,14 @@ describe('disable button', () => {
// Disable the alert // Disable the alert
await act(async () => { await act(async () => {
wrapper.find('[data-test-subj="disableSwitch"] .euiSwitch__button').first().simulate('click'); wrapper.find('[data-test-subj="enableSwitch"] .euiSwitch__button').first().simulate('click');
await nextTick(); await nextTick();
}); });
expect(disableAlert).toHaveBeenCalled(); expect(disableAlert).toHaveBeenCalled();
// Enable the alert // Enable the alert
await act(async () => { await act(async () => {
wrapper.find('[data-test-subj="disableSwitch"] .euiSwitch__button').first().simulate('click'); wrapper.find('[data-test-subj="enableSwitch"] .euiSwitch__button').first().simulate('click');
await nextTick(); await nextTick();
}); });
expect(enableAlert).toHaveBeenCalled(); expect(enableAlert).toHaveBeenCalled();

View file

@ -219,10 +219,10 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
<EuiFlexGroup justifyContent="flexEnd" wrap responsive={false} gutterSize="m"> <EuiFlexGroup justifyContent="flexEnd" wrap responsive={false} gutterSize="m">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiSwitch <EuiSwitch
name="disable" name="enable"
disabled={!canSaveAlert || !alertType.enabledInLicense} disabled={!canSaveAlert || !alertType.enabledInLicense}
checked={!isEnabled} checked={isEnabled}
data-test-subj="disableSwitch" data-test-subj="enableSwitch"
onChange={async () => { onChange={async () => {
if (isEnabled) { if (isEnabled) {
setIsEnabled(false); setIsEnabled(false);
@ -237,8 +237,8 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
}} }}
label={ label={
<FormattedMessage <FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle" id="xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.enableTitle"
defaultMessage="Disable" defaultMessage="Enable"
/> />
} }
/> />

View file

@ -133,6 +133,7 @@ export const AlertEdit = ({
aria-labelledby="flyoutAlertEditTitle" aria-labelledby="flyoutAlertEditTitle"
size="m" size="m"
maxWidth={620} maxWidth={620}
ownFocus={false}
> >
<EuiFlyoutHeader hasBorder> <EuiFlyoutHeader hasBorder>
<EuiTitle size="s" data-test-subj="editAlertFlyoutTitle"> <EuiTitle size="s" data-test-subj="editAlertFlyoutTitle">

View file

@ -95,13 +95,13 @@ export const AlertStatusFilter: React.FunctionComponent<AlertStatusFilterProps>
export function getHealthColor(status: AlertExecutionStatuses) { export function getHealthColor(status: AlertExecutionStatuses) {
switch (status) { switch (status) {
case 'active': case 'active':
return 'primary'; return 'success';
case 'error': case 'error':
return 'danger'; return 'danger';
case 'ok': case 'ok':
return 'subdued'; return 'subdued';
case 'pending': case 'pending':
return 'success'; return 'accent';
default: default:
return 'warning'; return 'warning';
} }

View file

@ -5,3 +5,29 @@
color: $euiColorDarkShade; color: $euiColorDarkShade;
} }
} }
.euiTableRow {
&:hover,
&:focus-within,
&[class*='-isActive'] {
.alertSidebarItem__action {
opacity: 1;
}
}
}
/**
* 1. Only visually hide the action, so that it's still accessible to screen readers.
* 2. When tabbed to, this element needs to be visible for keyboard accessibility.
*/
.alertSidebarItem__action {
opacity: 0; /* 1 */
&.alertSidebarItem__mobile {
opacity: 1;
}
&:focus {
opacity: 1; /* 2 */
}
}

View file

@ -368,7 +368,7 @@ describe('alerts_list component with items', () => {
it('sorts alerts when clicking the name column', async () => { it('sorts alerts when clicking the name column', async () => {
await setup(); await setup();
wrapper wrapper
.find('[data-test-subj="tableHeaderCell_name_0"] .euiTableHeaderButton') .find('[data-test-subj="tableHeaderCell_name_1"] .euiTableHeaderButton')
.first() .first()
.simulate('click'); .simulate('click');
@ -386,6 +386,28 @@ describe('alerts_list component with items', () => {
}) })
); );
}); });
it('sorts alerts when clicking the enabled column', async () => {
await setup();
wrapper
.find('[data-test-subj="tableHeaderCell_enabled_0"] .euiTableHeaderButton')
.first()
.simulate('click');
await act(async () => {
await nextTick();
wrapper.update();
});
expect(loadAlerts).toHaveBeenLastCalledWith(
expect.objectContaining({
sort: {
field: 'enabled',
direction: 'asc',
},
})
);
});
}); });
describe('alerts_list component empty with show only capability', () => { describe('alerts_list component empty with show only capability', () => {

View file

@ -28,12 +28,13 @@ import {
EuiText, EuiText,
EuiToolTip, EuiToolTip,
EuiTableSortingType, EuiTableSortingType,
EuiButtonIcon,
} from '@elastic/eui'; } from '@elastic/eui';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { ActionType, Alert, AlertTableItem, AlertTypeIndex, Pagination } from '../../../../types'; import { ActionType, Alert, AlertTableItem, AlertTypeIndex, Pagination } from '../../../../types';
import { AlertAdd } from '../../alert_form'; import { AlertAdd, AlertEdit } from '../../alert_form';
import { BulkOperationPopover } from '../../common/components/bulk_operation_popover'; import { BulkOperationPopover } from '../../common/components/bulk_operation_popover';
import { AlertQuickEditButtonsWithApi as AlertQuickEditButtons } from '../../common/components/alert_quick_edit_buttons'; import { AlertQuickEditButtonsWithApi as AlertQuickEditButtons } from '../../common/components/alert_quick_edit_buttons';
import { CollapsedItemActionsWithApi as CollapsedItemActions } from './collapsed_item_actions'; import { CollapsedItemActionsWithApi as CollapsedItemActions } from './collapsed_item_actions';
@ -44,6 +45,8 @@ import {
loadAlerts, loadAlerts,
loadAlertAggregations, loadAlertAggregations,
loadAlertTypes, loadAlertTypes,
disableAlert,
enableAlert,
deleteAlerts, deleteAlerts,
} from '../../../lib/alert_api'; } from '../../../lib/alert_api';
import { loadActionTypes } from '../../../lib/action_connector_api'; import { loadActionTypes } from '../../../lib/action_connector_api';
@ -65,6 +68,7 @@ import './alerts_list.scss';
import { CenterJustifiedSpinner } from '../../../components/center_justified_spinner'; import { CenterJustifiedSpinner } from '../../../components/center_justified_spinner';
import { ManageLicenseModal } from './manage_license_modal'; import { ManageLicenseModal } from './manage_license_modal';
import { checkAlertTypeEnabled } from '../../../lib/check_alert_type_enabled'; import { checkAlertTypeEnabled } from '../../../lib/check_alert_type_enabled';
import { RuleEnabledSwitch } from './rule_enabled_switch';
const ENTER_KEY = 13; const ENTER_KEY = 13;
@ -102,6 +106,9 @@ export const AlertsList: React.FunctionComponent = () => {
const [alertStatusesFilter, setAlertStatusesFilter] = useState<string[]>([]); const [alertStatusesFilter, setAlertStatusesFilter] = useState<string[]>([]);
const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState<boolean>(false); const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState<boolean>(false);
const [dismissAlertErrors, setDismissAlertErrors] = useState<boolean>(false); const [dismissAlertErrors, setDismissAlertErrors] = useState<boolean>(false);
const [editFlyoutVisible, setEditFlyoutVisibility] = useState<boolean>(false);
const [currentRuleToEdit, setCurrentRuleToEdit] = useState<AlertTableItem | null>(null);
const [sort, setSort] = useState<EuiTableSortingType<AlertTableItem>['sort']>({ const [sort, setSort] = useState<EuiTableSortingType<AlertTableItem>['sort']>({
field: 'name', field: 'name',
direction: 'asc', direction: 'asc',
@ -131,6 +138,10 @@ export const AlertsList: React.FunctionComponent = () => {
totalItemCount: 0, totalItemCount: 0,
}); });
const [alertsToDelete, setAlertsToDelete] = useState<string[]>([]); const [alertsToDelete, setAlertsToDelete] = useState<string[]>([]);
const onRuleEdit = (ruleItem: AlertTableItem) => {
setEditFlyoutVisibility(true);
setCurrentRuleToEdit(ruleItem);
};
useEffect(() => { useEffect(() => {
loadAlertsData(); loadAlertsData();
@ -169,15 +180,14 @@ export const AlertsList: React.FunctionComponent = () => {
(async () => { (async () => {
try { try {
const result = await loadActionTypes({ http }); const result = await loadActionTypes({ http });
setActionTypes( const sortedResult = result
result
.filter( .filter(
// TODO: Remove "DEFAULT_HIDDEN_ACTION_TYPES" when cases connector is available across Kibana. // TODO: Remove "DEFAULT_HIDDEN_ACTION_TYPES" when cases connector is available across Kibana.
// Issue: https://github.com/elastic/kibana/issues/82502. // Issue: https://github.com/elastic/kibana/issues/82502.
({ id }) => actionTypeRegistry.has(id) && !DEFAULT_HIDDEN_ACTION_TYPES.includes(id) ({ id }) => actionTypeRegistry.has(id) && !DEFAULT_HIDDEN_ACTION_TYPES.includes(id)
) )
.sort((a, b) => a.name.localeCompare(b.name)) .sort((a, b) => a.name.localeCompare(b.name));
); setActionTypes(sortedResult);
} catch (e) { } catch (e) {
toasts.addDanger({ toasts.addDanger({
title: i18n.translate( title: i18n.translate(
@ -309,6 +319,26 @@ export const AlertsList: React.FunctionComponent = () => {
}; };
const alertsTableColumns = [ const alertsTableColumns = [
{
field: 'enabled',
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.enabledTitle',
{ defaultMessage: 'Enabled' }
),
width: '90px',
render(_enabled: boolean | undefined, item: AlertTableItem) {
return (
<RuleEnabledSwitch
disableAlert={async () => await disableAlert({ http, id: item.id })}
enableAlert={async () => await enableAlert({ http, id: item.id })}
item={item}
onAlertChanged={() => loadAlertsData()}
/>
);
},
sortable: true,
'data-test-subj': 'alertsTableCell-enabled',
},
{ {
field: 'name', field: 'name',
name: i18n.translate( name: i18n.translate(
@ -317,7 +347,7 @@ export const AlertsList: React.FunctionComponent = () => {
), ),
sortable: true, sortable: true,
truncateText: true, truncateText: true,
width: '35%', width: '30%',
'data-test-subj': 'alertsTableCell-name', 'data-test-subj': 'alertsTableCell-name',
render: (name: string, alert: AlertTableItem) => { render: (name: string, alert: AlertTableItem) => {
const ruleType = alertTypesState.data.get(alert.alertTypeId); const ruleType = alertTypesState.data.get(alert.alertTypeId);
@ -357,37 +387,12 @@ export const AlertsList: React.FunctionComponent = () => {
), ),
sortable: true, sortable: true,
truncateText: false, truncateText: false,
width: '150px', width: '120px',
'data-test-subj': 'alertsTableCell-status', 'data-test-subj': 'alertsTableCell-status',
render: (executionStatus: AlertExecutionStatus, item: AlertTableItem) => { render: (_executionStatus: AlertExecutionStatus, item: AlertTableItem) => {
return renderAlertExecutionStatus(item.executionStatus, item); return renderAlertExecutionStatus(item.executionStatus, item);
}, },
}, },
{
field: 'tagsText',
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.tagsText',
{ defaultMessage: 'Tags' }
),
sortable: false,
'data-test-subj': 'alertsTableCell-tagsText',
},
{
field: 'actionsCount',
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsCount',
{ defaultMessage: 'Actions' }
),
render: (count: number, item: AlertTableItem) => {
return (
<EuiBadge color="hollow" key={item.id}>
{count}
</EuiBadge>
);
},
sortable: false,
'data-test-subj': 'alertsTableCell-actionsCount',
},
{ {
field: 'alertType', field: 'alertType',
name: i18n.translate( name: i18n.translate(
@ -396,29 +401,115 @@ export const AlertsList: React.FunctionComponent = () => {
), ),
sortable: false, sortable: false,
truncateText: true, truncateText: true,
render: (_count: number, item: AlertTableItem) => (
<EuiBadge color="default">{item.alertType}</EuiBadge>
),
'data-test-subj': 'alertsTableCell-alertType', 'data-test-subj': 'alertsTableCell-alertType',
}, },
{ {
field: 'schedule.interval', field: 'tagsText',
name: i18n.translate( name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.intervalTitle', 'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.tagsText',
{ defaultMessage: 'Tags' }
),
sortable: false,
'data-test-subj': 'alertsTableCell-tagsText',
render: (_count: number, item: AlertTableItem) => (
<div className="eui-textTruncate" title={item.tagsText}>
{item.tagsText}
</div>
),
},
{
field: 'schedule.interval',
width: '6%',
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.scheduleTitle',
{ defaultMessage: 'Runs every' } { defaultMessage: 'Runs every' }
), ),
sortable: false, sortable: false,
truncateText: false, truncateText: false,
'data-test-subj': 'alertsTableCell-interval', 'data-test-subj': 'alertsTableCell-interval',
}, },
{
width: '9%',
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTitle',
{ defaultMessage: 'Actions' }
),
render: (item: AlertTableItem) => {
return (
<EuiFlexGroup wrap responsive={false} gutterSize="s">
<EuiFlexItem grow={false}>{item.actionsCount}</EuiFlexItem>
<EuiFlexItem grow={false}>
<div>
{item.muteAll ? (
<EuiBadge data-test-subj="mutedActionsBadge" color="hollow">
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.mutedBadge"
defaultMessage="Muted"
/>
</EuiBadge>
) : null}
</div>
</EuiFlexItem>
</EuiFlexGroup>
);
},
'data-test-subj': 'alertsTableCell-actions',
},
{ {
name: '', name: '',
width: '40px', width: '10%',
render(item: AlertTableItem) { render(item: AlertTableItem) {
return ( return (
<EuiFlexGroup justifyContent="spaceBetween" gutterSize="s">
<EuiFlexItem grow={false} className="alertSidebarItem">
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButtonIcon
color={'primary'}
title={i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.editButtonTooltip',
{ defaultMessage: 'Edit' }
)}
className="alertSidebarItem__action"
onClick={() => onRuleEdit(item)}
iconType={'pencil'}
aria-label={i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.editAriaLabel',
{ defaultMessage: 'Edit' }
)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon
color={'danger'}
title={i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.deleteButtonTooltip',
{ defaultMessage: 'Delete' }
)}
className="alertSidebarItem__action"
onClick={() => setAlertsToDelete([item.id])}
iconType={'trash'}
aria-label={i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.deleteAriaLabel',
{ defaultMessage: 'Delete' }
)}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<CollapsedItemActions <CollapsedItemActions
key={item.id} key={item.id}
item={item} item={item}
onAlertChanged={() => loadAlertsData()} onAlertChanged={() => loadAlertsData()}
setAlertsToDelete={setAlertsToDelete} setAlertsToDelete={setAlertsToDelete}
onEditAlert={() => onRuleEdit(item)}
/> />
</EuiFlexItem>
</EuiFlexGroup>
); );
}, },
}, },
@ -621,7 +712,7 @@ export const AlertsList: React.FunctionComponent = () => {
</EuiText> </EuiText>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiHealth color="primary" data-test-subj="totalActiveAlertsCount"> <EuiHealth color="success" data-test-subj="totalActiveAlertsCount">
<FormattedMessage <FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.totalStausesActiveDescription" id="xpack.triggersActionsUI.sections.alertsList.totalStausesActiveDescription"
defaultMessage="Active: {totalStausesActive}" defaultMessage="Active: {totalStausesActive}"
@ -650,7 +741,7 @@ export const AlertsList: React.FunctionComponent = () => {
</EuiHealth> </EuiHealth>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiHealth color="success" data-test-subj="totalPendingAlertsCount"> <EuiHealth color="accent" data-test-subj="totalPendingAlertsCount">
<FormattedMessage <FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.totalStausesPendingDescription" id="xpack.triggersActionsUI.sections.alertsList.totalStausesPendingDescription"
defaultMessage="Pending: {totalStausesPending}" defaultMessage="Pending: {totalStausesPending}"
@ -802,6 +893,17 @@ export const AlertsList: React.FunctionComponent = () => {
onSave={loadAlertsData} onSave={loadAlertsData}
/> />
)} )}
{editFlyoutVisible && currentRuleToEdit && (
<AlertEdit
initialAlert={currentRuleToEdit}
onClose={() => {
setEditFlyoutVisibility(false);
}}
actionTypeRegistry={actionTypeRegistry}
alertTypeRegistry={alertTypeRegistry}
onSave={loadAlertsData}
/>
)}
</section> </section>
); );
}; };

View file

@ -4,20 +4,6 @@
} }
} }
.actCollapsedItemActions__item { button[data-test-subj='deleteAlert'] {
padding: $euiSizeM; color: $euiColorDanger;
}
.actCollapsedItemActions__delete {
display: flex;
.actCollapsedItemActions__deleteIcon {
width: $euiSwitchWidthCompressed;
text-align: center;
}
.actCollapsedItemActions__deleteLabel {
padding-left: $euiSizeS;
padding-top: $euiSizeXS * .5;
}
} }

View file

@ -8,18 +8,7 @@
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { asyncScheduler } from 'rxjs'; import { asyncScheduler } from 'rxjs';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonIcon, EuiPopover, EuiContextMenu } from '@elastic/eui';
import {
EuiButtonIcon,
EuiPopover,
EuiContextMenuPanel,
EuiContextMenuItem,
EuiSwitch,
EuiHorizontalRule,
EuiText,
EuiSpacer,
EuiIcon,
} from '@elastic/eui';
import { AlertTableItem } from '../../../../types'; import { AlertTableItem } from '../../../../types';
import { import {
@ -32,6 +21,7 @@ export type ComponentOpts = {
item: AlertTableItem; item: AlertTableItem;
onAlertChanged: () => void; onAlertChanged: () => void;
setAlertsToDelete: React.Dispatch<React.SetStateAction<string[]>>; setAlertsToDelete: React.Dispatch<React.SetStateAction<string[]>>;
onEditAlert: (item: AlertTableItem) => void;
} & BulkOperationsComponentOpts; } & BulkOperationsComponentOpts;
export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
@ -42,6 +32,7 @@ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
unmuteAlert, unmuteAlert,
muteAlert, muteAlert,
setAlertsToDelete, setAlertsToDelete,
onEditAlert,
}: ComponentOpts) => { }: ComponentOpts) => {
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false); const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
const [isDisabled, setIsDisabled] = useState<boolean>(!item.enabled); const [isDisabled, setIsDisabled] = useState<boolean>(!item.enabled);
@ -54,7 +45,7 @@ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
const button = ( const button = (
<EuiButtonIcon <EuiButtonIcon
disabled={!item.isEditable} disabled={!item.isEditable}
iconType="boxesVertical" iconType="boxesHorizontal"
onClick={() => setIsPopoverOpen(!isPopoverOpen)} onClick={() => setIsPopoverOpen(!isPopoverOpen)}
aria-label={i18n.translate( aria-label={i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle', 'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle',
@ -63,58 +54,15 @@ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
/> />
); );
return ( const panels = [
<EuiPopover {
button={button} id: 0,
isOpen={isPopoverOpen} hasFocus: false,
closePopover={() => setIsPopoverOpen(false)} items: [
ownFocus {
panelPaddingSize="none" disabled: !(item.isEditable && !isDisabled) || !item.enabledInLicense,
data-test-subj="collapsedItemActions" 'data-test-subj': 'muteButton',
> onClick: async () => {
<EuiContextMenuPanel className="actCollapsedItemActions" hasFocus={false}>
<div className="actCollapsedItemActions__item">
<EuiSwitch
name="disable"
disabled={!item.isEditable || !item.enabledInLicense}
compressed
checked={isDisabled}
data-test-subj="disableSwitch"
onChange={async () => {
const enabled = !isDisabled;
asyncScheduler.schedule(async () => {
if (enabled) {
await disableAlert({ ...item, enabled });
} else {
await enableAlert({ ...item, enabled });
}
onAlertChanged();
}, 10);
setIsDisabled(!isDisabled);
}}
label={
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle"
defaultMessage="Disable"
/>
}
/>
<EuiSpacer size="xs" />
<EuiText color="subdued" size="xs">
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableHelpText"
defaultMessage="When disabled, the rule is not checked."
/>
</EuiText>
</div>
<div className="actCollapsedItemActions__item">
<EuiSwitch
name="mute"
checked={isMuted}
disabled={!(item.isEditable && !isDisabled) || !item.enabledInLicense}
compressed
data-test-subj="muteSwitch"
onChange={async () => {
const muteAll = isMuted; const muteAll = isMuted;
asyncScheduler.schedule(async () => { asyncScheduler.schedule(async () => {
if (muteAll) { if (muteAll) {
@ -125,45 +73,82 @@ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
onAlertChanged(); onAlertChanged();
}, 10); }, 10);
setIsMuted(!isMuted); setIsMuted(!isMuted);
}} setIsPopoverOpen(!isPopoverOpen);
label={ },
<FormattedMessage name: isMuted
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle" ? i18n.translate(
defaultMessage="Mute" 'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.unmuteTitle',
/> { defaultMessage: 'Unmute' }
)
: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle',
{ defaultMessage: 'Mute' }
),
},
{
disabled: !item.isEditable || !item.enabledInLicense,
'data-test-subj': 'disableButton',
onClick: async () => {
const enabled = !isDisabled;
asyncScheduler.schedule(async () => {
if (enabled) {
await disableAlert({ ...item, enabled });
} else {
await enableAlert({ ...item, enabled });
} }
/> onAlertChanged();
<EuiSpacer size="xs" /> }, 10);
<EuiText color="subdued" size="xs"> setIsDisabled(!isDisabled);
<FormattedMessage setIsPopoverOpen(!isPopoverOpen);
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteHelpText" },
defaultMessage="When muted, the rule is checked, but no action is performed." name: isDisabled
/> ? i18n.translate(
</EuiText> 'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.enableTitle',
</div> { defaultMessage: 'Enable' }
<EuiHorizontalRule margin="none" /> )
<EuiContextMenuItem : i18n.translate(
disabled={!item.isEditable} 'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle',
data-test-subj="deleteAlert" { defaultMessage: 'Disable' }
onClick={() => setAlertsToDelete([item.id])} ),
},
{
disabled: !item.isEditable,
'data-test-subj': 'editAlert',
onClick: () => {
setIsPopoverOpen(!isPopoverOpen);
onEditAlert(item);
},
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.editTitle',
{ defaultMessage: 'Edit rule' }
),
},
{
disabled: !item.isEditable,
'data-test-subj': 'deleteAlert',
onClick: () => {
setIsPopoverOpen(!isPopoverOpen);
setAlertsToDelete([item.id]);
},
name: i18n.translate(
'xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteRuleTitle',
{ defaultMessage: 'Delete rule' }
),
},
],
},
];
return (
<EuiPopover
button={button}
isOpen={isPopoverOpen}
closePopover={() => setIsPopoverOpen(false)}
ownFocus
panelPaddingSize="none"
data-test-subj="collapsedItemActions"
> >
<div className="actCollapsedItemActions__delete"> <EuiContextMenu initialPanelId={0} panels={panels} className="actCollapsedItemActions" />
<div className="actCollapsedItemActions__deleteIcon">
<EuiIcon color="danger" type="trash" />
</div>
<div className="actCollapsedItemActions__deleteLabel">
<EuiText size="s" color="danger">
<p>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteTitle"
defaultMessage="Delete"
/>
</p>
</EuiText>
</div>
</div>
</EuiContextMenuItem>
</EuiContextMenuPanel>
</EuiPopover> </EuiPopover>
); );
}; };

View file

@ -0,0 +1,54 @@
/*
* 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 { asyncScheduler } from 'rxjs';
import React, { useEffect, useState } from 'react';
import { EuiSwitch } from '@elastic/eui';
import { Alert, AlertTableItem } from '../../../../types';
interface ComponentOpts {
item: AlertTableItem;
onAlertChanged: () => void;
enableAlert: (alert: Alert) => Promise<void>;
disableAlert: (alert: Alert) => Promise<void>;
}
export const RuleEnabledSwitch: React.FunctionComponent<ComponentOpts> = ({
item,
onAlertChanged,
disableAlert,
enableAlert,
}: ComponentOpts) => {
const [isEnabled, setIsEnabled] = useState<boolean>(!item.enabled);
useEffect(() => {
setIsEnabled(item.enabled);
}, [item.enabled]);
return (
<EuiSwitch
name="enable"
disabled={!item.isEditable || !item.enabledInLicense}
compressed
checked={isEnabled}
data-test-subj="enableSwitch"
onChange={async () => {
const enabled = isEnabled;
asyncScheduler.schedule(async () => {
if (enabled) {
await disableAlert({ ...item, enabled });
} else {
await enableAlert({ ...item, enabled });
}
onAlertChanged();
}, 10);
setIsEnabled(!isEnabled);
}}
label=""
/>
);
};

View file

@ -177,11 +177,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await testSubjects.click('collapsedItemActions'); await testSubjects.click('collapsedItemActions');
await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); await testSubjects.click('disableButton');
await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied( await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied(
createdAlert.name, createdAlert.name,
'disableSwitch', 'enableSwitch',
'true' 'true'
); );
}); });
@ -194,10 +194,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await testSubjects.click('collapsedItemActions'); await testSubjects.click('collapsedItemActions');
await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); await testSubjects.click('disableButton');
await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied( await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied(
createdAlert.name, createdAlert.name,
'disableSwitch', 'enableSwitch',
'false' 'false'
); );
}); });
@ -209,12 +209,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await testSubjects.click('collapsedItemActions'); await testSubjects.click('collapsedItemActions');
await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); await testSubjects.click('muteButton');
await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied(
createdAlert.name, await retry.tryForTime(30000, async () => {
'muteSwitch', await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
'true' const muteBadge = await testSubjects.find('mutedActionsBadge');
); expect(await muteBadge.isDisplayed()).to.eql(true);
});
}); });
it('should unmute single alert', async () => { it('should unmute single alert', async () => {
@ -226,12 +227,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await testSubjects.click('collapsedItemActions'); await testSubjects.click('collapsedItemActions');
await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); await testSubjects.click('muteButton');
await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied( await retry.tryForTime(30000, async () => {
createdAlert.name, await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
'muteSwitch', await testSubjects.missingOrFail('mutedActionsBadge');
'false' });
);
}); });
it('should delete single alert', async () => { it('should delete single alert', async () => {
@ -273,11 +273,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
await testSubjects.click('collapsedItemActions'); await retry.tryForTime(30000, async () => {
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
const muteSwitch = await testSubjects.find('muteSwitch'); const muteBadge = await testSubjects.find('mutedActionsBadge');
const isChecked = await muteSwitch.getAttribute('aria-checked'); expect(await muteBadge.isDisplayed()).to.eql(true);
expect(isChecked).to.eql('true'); });
}); });
it('should unmute all selection', async () => { it('should unmute all selection', async () => {
@ -296,13 +296,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
// Mute all button shows after clicking unmute all // Mute all button shows after clicking unmute all
await testSubjects.existOrFail('muteAll'); await testSubjects.existOrFail('muteAll');
await retry.tryForTime(30000, async () => {
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
await testSubjects.missingOrFail('mutedActionsBadge');
await testSubjects.click('collapsedItemActions'); });
const muteSwitch = await testSubjects.find('muteSwitch');
const isChecked = await muteSwitch.getAttribute('aria-checked');
expect(isChecked).to.eql('false');
}); });
it('should disable all selection', async () => { it('should disable all selection', async () => {
@ -319,13 +316,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
// Enable all button shows after clicking disable all // Enable all button shows after clicking disable all
await testSubjects.existOrFail('enableAll'); await testSubjects.existOrFail('enableAll');
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied(
createdAlert.name,
await testSubjects.click('collapsedItemActions'); 'enableSwitch',
'false'
const disableSwitch = await testSubjects.find('disableSwitch'); );
const isChecked = await disableSwitch.getAttribute('aria-checked');
expect(isChecked).to.eql('true');
}); });
it('should enable all selection', async () => { it('should enable all selection', async () => {
@ -344,13 +339,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
// Disable all button shows after clicking enable all // Disable all button shows after clicking enable all
await testSubjects.existOrFail('disableAll'); await testSubjects.existOrFail('disableAll');
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); await pageObjects.triggersActionsUI.ensureRuleActionToggleApplied(
createdAlert.name,
await testSubjects.click('collapsedItemActions'); 'enableSwitch',
'true'
const disableSwitch = await testSubjects.find('disableSwitch'); );
const isChecked = await disableSwitch.getAttribute('aria-checked');
expect(isChecked).to.eql('false');
}); });
it('should delete all selection', async () => { it('should delete all selection', async () => {

View file

@ -146,23 +146,23 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
}); });
it('should disable the alert', async () => { it('should disable the alert', async () => {
const disableSwitch = await testSubjects.find('disableSwitch'); const enableSwitch = await testSubjects.find('enableSwitch');
const isChecked = await disableSwitch.getAttribute('aria-checked'); const isChecked = await enableSwitch.getAttribute('aria-checked');
expect(isChecked).to.eql('false'); expect(isChecked).to.eql('true');
await disableSwitch.click(); await enableSwitch.click();
const disableSwitchAfterDisabling = await testSubjects.find('disableSwitch'); const disableSwitchAfterDisabling = await testSubjects.find('enableSwitch');
const isCheckedAfterDisabling = await disableSwitchAfterDisabling.getAttribute( const isCheckedAfterDisabling = await disableSwitchAfterDisabling.getAttribute(
'aria-checked' 'aria-checked'
); );
expect(isCheckedAfterDisabling).to.eql('true'); expect(isCheckedAfterDisabling).to.eql('false');
}); });
it('shouldnt allow you to mute a disabled alert', async () => { it('shouldnt allow you to mute a disabled alert', async () => {
const disabledDisableSwitch = await testSubjects.find('disableSwitch'); const disabledEnableSwitch = await testSubjects.find('enableSwitch');
expect(await disabledDisableSwitch.getAttribute('aria-checked')).to.eql('true'); expect(await disabledEnableSwitch.getAttribute('aria-checked')).to.eql('false');
const muteSwitch = await testSubjects.find('muteSwitch'); const muteSwitch = await testSubjects.find('muteSwitch');
expect(await muteSwitch.getAttribute('aria-checked')).to.eql('false'); expect(await muteSwitch.getAttribute('aria-checked')).to.eql('false');
@ -177,18 +177,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
}); });
it('should reenable a disabled the alert', async () => { it('should reenable a disabled the alert', async () => {
const disableSwitch = await testSubjects.find('disableSwitch'); const enableSwitch = await testSubjects.find('enableSwitch');
const isChecked = await disableSwitch.getAttribute('aria-checked'); const isChecked = await enableSwitch.getAttribute('aria-checked');
expect(isChecked).to.eql('true'); expect(isChecked).to.eql('false');
await disableSwitch.click(); await enableSwitch.click();
const disableSwitchAfterReenabling = await testSubjects.find('disableSwitch'); const disableSwitchAfterReenabling = await testSubjects.find('enableSwitch');
const isCheckedAfterDisabling = await disableSwitchAfterReenabling.getAttribute( const isCheckedAfterDisabling = await disableSwitchAfterReenabling.getAttribute(
'aria-checked' 'aria-checked'
); );
expect(isCheckedAfterDisabling).to.eql('false'); expect(isCheckedAfterDisabling).to.eql('true');
}); });
it('should mute the alert', async () => { it('should mute the alert', async () => {

View file

@ -190,8 +190,6 @@ export function TriggersActionsPageProvider({ getService }: FtrProviderContext)
) { ) {
await retry.tryForTime(30000, async () => { await retry.tryForTime(30000, async () => {
await this.searchAlerts(ruleName); await this.searchAlerts(ruleName);
await testSubjects.click('collapsedItemActions');
const switchControl = await testSubjects.find(switchName); const switchControl = await testSubjects.find(switchName);
const isChecked = await switchControl.getAttribute('aria-checked'); const isChecked = await switchControl.getAttribute('aria-checked');
expect(isChecked).to.eql(shouldBeCheckedAsString); expect(isChecked).to.eql(shouldBeCheckedAsString);