mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Alerting] "Create alert" and alert list design improvements (#63515)
* added header to actions section * adjusted some spacing in Create Alert * lighter text in Actions section headings * fixed bulk actions dropdown * improve alert collapsed item actions * improve dropdown and adjust some buttos * adjust font size of steps to match hierarchy * need to check master * improve collapsed actions menu * added periods to help texts * going back to EuiButtonEmpty to be able to use isLoading * fix prop * remove Fragment * remove translations we're not using * Fix functional tests Co-authored-by: Mike Cote <mikecote@users.noreply.github.com>
This commit is contained in:
parent
dc9bfb5d0f
commit
c13a026b01
14 changed files with 426 additions and 328 deletions
|
@ -15960,7 +15960,7 @@
|
|||
"xpack.triggersActionsUI.sections.alertAdd.saveButtonLabel": "保存",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.saveErrorNotificationText": "アラートを作成できません。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.saveSuccessNotificationText": "「{alertName}」 を保存しました",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.selectIndex": "インデックスを選択してください。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.selectIndex": "インデックスを選択してください",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.threshold.closeIndexPopoverLabel": "閉じる",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.threshold.fixErrorInExpressionBelowValidationMessage": "下の表現のエラーを修正してください。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.threshold.howToBroadenSearchQueryDescription": "* で検索クエリの範囲を広げます。",
|
||||
|
@ -16044,7 +16044,6 @@
|
|||
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle": "ミュート",
|
||||
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle": "ミュート解除",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteTitle": "削除",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.enableTitle": "有効にする",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle": "ミュート",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle": "アクション",
|
||||
"xpack.triggersActionsUI.components.emptyPrompt.emptyButton": "アラートの作成",
|
||||
|
@ -16757,4 +16756,4 @@
|
|||
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。",
|
||||
"xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15957,7 +15957,7 @@
|
|||
"xpack.triggersActionsUI.sections.addModalConnectorForm.updateSuccessNotificationText": "已创建“{connectorName}”",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.cancelButtonLabel": "取消",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.conditionPrompt": "定义条件。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.conditionPrompt": "定义条件",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.errorLoadingAlertVisualizationTitle": "无法加载告警可视化",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.flyoutTitle": "创建告警",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.loadingAlertVisualizationDescription": "正在加载告警可视化……",
|
||||
|
@ -15965,7 +15965,7 @@
|
|||
"xpack.triggersActionsUI.sections.alertAdd.saveButtonLabel": "保存",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.saveErrorNotificationText": "无法创建告警。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.saveSuccessNotificationText": "已保存“{alertName}”",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.selectIndex": "选择索引。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.selectIndex": "选择索引",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.threshold.closeIndexPopoverLabel": "关闭",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.threshold.fixErrorInExpressionBelowValidationMessage": "表达式包含错误。",
|
||||
"xpack.triggersActionsUI.sections.alertAdd.threshold.howToBroadenSearchQueryDescription": "使用 * 可扩大您的查询范围。",
|
||||
|
@ -16049,7 +16049,6 @@
|
|||
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle": "静音",
|
||||
"xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle": "取消静音",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteTitle": "删除",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.enableTitle": "启用",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle": "静音",
|
||||
"xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.popoverButtonTitle": "操作",
|
||||
"xpack.triggersActionsUI.components.emptyPrompt.emptyButton": "创建告警",
|
||||
|
@ -16762,4 +16761,4 @@
|
|||
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。",
|
||||
"xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,13 @@
|
|||
.actAlertVisualization__chart {
|
||||
height: $euiSize * 15;
|
||||
height: $euiSize * 14;
|
||||
}
|
||||
|
||||
.actAddAlertSteps {
|
||||
.euiStep__titleWrapper {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.euiStep__title {
|
||||
@include euiTitle('xs');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<IndexThr
|
|||
const firstSetOfSteps = [
|
||||
{
|
||||
title: i18n.translate('xpack.triggersActionsUI.sections.alertAdd.selectIndex', {
|
||||
defaultMessage: 'Select an index.',
|
||||
defaultMessage: 'Select an index',
|
||||
}),
|
||||
children: (
|
||||
<>
|
||||
|
@ -396,7 +396,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<IndexThr
|
|||
},
|
||||
{
|
||||
title: i18n.translate('xpack.triggersActionsUI.sections.alertAdd.conditionPrompt', {
|
||||
defaultMessage: 'Define the condition.',
|
||||
defaultMessage: 'Define the condition',
|
||||
}),
|
||||
children: (
|
||||
<>
|
||||
|
@ -445,12 +445,10 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<IndexThr
|
|||
</Fragment>
|
||||
) : null}
|
||||
<EuiSpacer size="l" />
|
||||
<EuiSteps steps={firstSetOfSteps} />
|
||||
<EuiSpacer size="l" />
|
||||
<EuiSteps className="actAddAlertSteps" steps={firstSetOfSteps} />
|
||||
<div className="actAlertVisualization__chart">
|
||||
{canShowVizualization ? (
|
||||
<Fragment>
|
||||
<EuiSpacer size="xl" />
|
||||
<EuiEmptyPrompt
|
||||
iconType="visBarVertical"
|
||||
body={
|
||||
|
|
|
@ -33,8 +33,6 @@ export const EmptyPrompt = ({ onCTAClicked }: { onCTAClicked: () => void }) => (
|
|||
data-test-subj="createFirstAlertButton"
|
||||
key="create-action"
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
iconSide="left"
|
||||
onClick={onCTAClicked}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -25,6 +25,8 @@ import {
|
|||
EuiIconTip,
|
||||
EuiLink,
|
||||
EuiCallOut,
|
||||
EuiHorizontalRule,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { HttpSetup, ToastsApi } from 'kibana/public';
|
||||
import { loadActionTypes, loadAllActions } from '../../lib/action_connector_api';
|
||||
|
@ -256,81 +258,87 @@ export const ActionForm = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<EuiAccordion
|
||||
initialIsOpen={true}
|
||||
key={index}
|
||||
id={index.toString()}
|
||||
className="actAccordionActionForm"
|
||||
buttonContentClassName="actAccordionActionForm__button"
|
||||
data-test-subj={`alertActionAccordion-${defaultActionGroupId}`}
|
||||
buttonContent={
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon type={actionTypeRegistered.iconClass} size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="s">
|
||||
<h5>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
defaultMessage="{actionConnectorName}"
|
||||
id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeEditTitle"
|
||||
values={{
|
||||
actionConnectorName: `${actionConnector.name} ${
|
||||
actionConnector.isPreconfigured ? preconfiguredMessage : ''
|
||||
}`,
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
{checkEnabledResult.isEnabled === false && (
|
||||
<Fragment>
|
||||
<EuiIconTip
|
||||
type="alert"
|
||||
color="danger"
|
||||
content={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.actionDisabledTitle',
|
||||
{
|
||||
defaultMessage: 'This action is disabled',
|
||||
}
|
||||
)}
|
||||
position="right"
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="cross"
|
||||
color="danger"
|
||||
className="actAccordionActionForm__extraAction"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.accordion.deleteIconAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Delete',
|
||||
}
|
||||
)}
|
||||
onClick={() => {
|
||||
const updatedActions = actions.filter((_item: AlertAction, i: number) => i !== index);
|
||||
setAlertProperty(updatedActions);
|
||||
setIsAddActionPanelOpen(
|
||||
updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length === 0
|
||||
);
|
||||
setActiveActionItem(undefined);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
paddingSize="l"
|
||||
>
|
||||
{accordionContent}
|
||||
</EuiAccordion>
|
||||
<Fragment>
|
||||
<EuiAccordion
|
||||
initialIsOpen={true}
|
||||
key={index}
|
||||
id={index.toString()}
|
||||
className="actAccordionActionForm"
|
||||
buttonContentClassName="actAccordionActionForm__button"
|
||||
data-test-subj={`alertActionAccordion-${defaultActionGroupId}`}
|
||||
buttonContent={
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon type={actionTypeRegistered.iconClass} size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText>
|
||||
<p>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
defaultMessage="{actionConnectorName}"
|
||||
id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeEditTitle"
|
||||
values={{
|
||||
actionConnectorName: `${actionConnector.name} ${
|
||||
actionConnector.isPreconfigured ? preconfiguredMessage : ''
|
||||
}`,
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
{checkEnabledResult.isEnabled === false && (
|
||||
<Fragment>
|
||||
<EuiIconTip
|
||||
type="alert"
|
||||
color="danger"
|
||||
content={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.actionDisabledTitle',
|
||||
{
|
||||
defaultMessage: 'This action is disabled',
|
||||
}
|
||||
)}
|
||||
position="right"
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="cross"
|
||||
color="danger"
|
||||
className="actAccordionActionForm__extraAction"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.accordion.deleteIconAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Delete',
|
||||
}
|
||||
)}
|
||||
onClick={() => {
|
||||
const updatedActions = actions.filter(
|
||||
(_item: AlertAction, i: number) => i !== index
|
||||
);
|
||||
setAlertProperty(updatedActions);
|
||||
setIsAddActionPanelOpen(
|
||||
updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length ===
|
||||
0
|
||||
);
|
||||
setActiveActionItem(undefined);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
paddingSize="l"
|
||||
>
|
||||
{accordionContent}
|
||||
</EuiAccordion>
|
||||
<EuiSpacer size="xs" />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -341,96 +349,103 @@ export const ActionForm = ({
|
|||
const actionTypeRegistered = actionTypeRegistry.get(actionItem.actionTypeId);
|
||||
if (!actionTypeRegistered || actionItem.group !== defaultActionGroupId) return null;
|
||||
return (
|
||||
<EuiAccordion
|
||||
initialIsOpen={true}
|
||||
key={index}
|
||||
id={index.toString()}
|
||||
className="actAccordionActionForm"
|
||||
buttonContentClassName="actAccordionActionForm__button"
|
||||
data-test-subj={`alertActionAccordion-${defaultActionGroupId}`}
|
||||
buttonContent={
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon type={actionTypeRegistered.iconClass} size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="s">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
defaultMessage="{actionConnectorName}"
|
||||
id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeEditTitle"
|
||||
values={{
|
||||
actionConnectorName: actionTypeRegistered.actionTypeTitle,
|
||||
}}
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="cross"
|
||||
color="danger"
|
||||
className="actAccordionActionForm__extraAction"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.accordion.deleteIconAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Delete',
|
||||
}
|
||||
)}
|
||||
onClick={() => {
|
||||
const updatedActions = actions.filter((_item: AlertAction, i: number) => i !== index);
|
||||
setAlertProperty(updatedActions);
|
||||
setIsAddActionPanelOpen(
|
||||
updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length === 0
|
||||
);
|
||||
setActiveActionItem(undefined);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
paddingSize="l"
|
||||
>
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
emptyActionsIds.find((emptyId: string) => actionItem.id === emptyId) ? (
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertForm.emptyConnectorsLabel"
|
||||
defaultMessage="No {actionTypeName} connectors."
|
||||
values={{
|
||||
actionTypeName,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<EuiCallOut
|
||||
title={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.unableToLoadConnectorTitle',
|
||||
{
|
||||
defaultMessage: 'Unable to load connector.',
|
||||
}
|
||||
)}
|
||||
color="warning"
|
||||
/>
|
||||
)
|
||||
<Fragment>
|
||||
<EuiAccordion
|
||||
initialIsOpen={true}
|
||||
key={index}
|
||||
id={index.toString()}
|
||||
className="actAccordionActionForm"
|
||||
buttonContentClassName="actAccordionActionForm__button"
|
||||
data-test-subj={`alertActionAccordion-${defaultActionGroupId}`}
|
||||
buttonContent={
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon type={actionTypeRegistered.iconClass} size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="{actionConnectorName}"
|
||||
id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeEditTitle"
|
||||
values={{
|
||||
actionConnectorName: actionTypeRegistered.actionTypeTitle,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
actions={[
|
||||
<EuiButton
|
||||
color="primary"
|
||||
fill
|
||||
data-test-subj="createActionConnectorButton"
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="cross"
|
||||
color="danger"
|
||||
className="actAccordionActionForm__extraAction"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.accordion.deleteIconAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Delete',
|
||||
}
|
||||
)}
|
||||
onClick={() => {
|
||||
setActiveActionItem({ actionTypeId: actionItem.actionTypeId, index });
|
||||
setAddModalVisibility(true);
|
||||
const updatedActions = actions.filter(
|
||||
(_item: AlertAction, i: number) => i !== index
|
||||
);
|
||||
setAlertProperty(updatedActions);
|
||||
setIsAddActionPanelOpen(
|
||||
updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length ===
|
||||
0
|
||||
);
|
||||
setActiveActionItem(undefined);
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertForm.addConnectorButtonLabel"
|
||||
defaultMessage="Create a connector"
|
||||
/>
|
||||
</EuiButton>,
|
||||
]}
|
||||
/>
|
||||
</EuiAccordion>
|
||||
/>
|
||||
}
|
||||
paddingSize="l"
|
||||
>
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
emptyActionsIds.find((emptyId: string) => actionItem.id === emptyId) ? (
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertForm.emptyConnectorsLabel"
|
||||
defaultMessage="No {actionTypeName} connectors."
|
||||
values={{
|
||||
actionTypeName,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<EuiCallOut
|
||||
title={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.alertForm.unableToLoadConnectorTitle',
|
||||
{
|
||||
defaultMessage: 'Unable to load connector.',
|
||||
}
|
||||
)}
|
||||
color="warning"
|
||||
/>
|
||||
)
|
||||
}
|
||||
actions={[
|
||||
<EuiButton
|
||||
color="primary"
|
||||
fill
|
||||
size="s"
|
||||
data-test-subj="createActionConnectorButton"
|
||||
onClick={() => {
|
||||
setActiveActionItem({ actionTypeId: actionItem.actionTypeId, index });
|
||||
setAddModalVisibility(true);
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertForm.addConnectorButtonLabel"
|
||||
defaultMessage="Create a connector"
|
||||
/>
|
||||
</EuiButton>,
|
||||
]}
|
||||
/>
|
||||
</EuiAccordion>
|
||||
<EuiSpacer size="xs" />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -537,19 +552,34 @@ export const ActionForm = ({
|
|||
</SectionLoading>
|
||||
) : (
|
||||
<Fragment>
|
||||
{alertActionsList}
|
||||
<EuiSpacer size="m" />
|
||||
{isAddActionPanelOpen === false ? (
|
||||
<EuiButton
|
||||
iconType="plusInCircle"
|
||||
data-test-subj="addAlertActionButton"
|
||||
onClick={() => setIsAddActionPanelOpen(true)}
|
||||
>
|
||||
<EuiTitle size="s">
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertForm.addActionButtonLabel"
|
||||
defaultMessage="Add action"
|
||||
defaultMessage="Actions"
|
||||
id="xpack.triggersActionsUI.sections.alertForm.actionSectionsTitle"
|
||||
/>
|
||||
</EuiButton>
|
||||
</h4>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
{alertActionsList}
|
||||
{isAddActionPanelOpen === false ? (
|
||||
<div>
|
||||
<EuiHorizontalRule />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
size="s"
|
||||
data-test-subj="addAlertActionButton"
|
||||
onClick={() => setIsAddActionPanelOpen(true)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertForm.addActionButtonLabel"
|
||||
defaultMessage="Add action"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
) : null}
|
||||
{isAddActionPanelOpen ? (
|
||||
<Fragment>
|
||||
|
@ -558,7 +588,7 @@ export const ActionForm = ({
|
|||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
defaultMessage="Actions: Select an action type"
|
||||
defaultMessage="Select an action type"
|
||||
id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeTitle"
|
||||
/>
|
||||
</h5>
|
||||
|
@ -571,6 +601,7 @@ export const ActionForm = ({
|
|||
<EuiLink
|
||||
href={VIEW_LICENSE_OPTIONS_LINK}
|
||||
target="_blank"
|
||||
external
|
||||
className="actActionForm__getMoreActionsLink"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
@ -584,7 +615,7 @@ export const ActionForm = ({
|
|||
)}
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup gutterSize="s" wrap>
|
||||
<EuiFlexGroup justifyContent="spaceBetween" gutterSize="s" wrap>
|
||||
{isLoadingActionTypes ? (
|
||||
<SectionLoading>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -338,8 +338,6 @@ export const ActionsConnectorsList: React.FunctionComponent = () => {
|
|||
data-test-subj="createActionButton"
|
||||
key="create-action"
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
iconSide="left"
|
||||
onClick={() => setAddFlyoutVisibility(true)}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -280,8 +280,6 @@ export const AlertsList: React.FunctionComponent = () => {
|
|||
key="create-alert"
|
||||
data-test-subj="createAlertButton"
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
iconSide="left"
|
||||
onClick={() => setAlertFlyoutVisibility(true)}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
.actCollapsedItemActions {
|
||||
.euiContextMenuItem:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.actCollapsedItemActions__item {
|
||||
padding: $euiSizeM;
|
||||
}
|
||||
|
||||
.actCollapsedItemActions__delete {
|
||||
display: flex;
|
||||
|
||||
.actCollapsedItemActions__deleteIcon {
|
||||
width: $euiSwitchWidthCompressed;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.actCollapsedItemActions__deleteLabel {
|
||||
padding-left: $euiSizeS;
|
||||
padding-top: $euiSizeXS * .5;
|
||||
}
|
||||
}
|
|
@ -8,12 +8,15 @@ import { i18n } from '@kbn/i18n';
|
|||
import React, { useState } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiButtonIcon,
|
||||
EuiFormRow,
|
||||
EuiPopover,
|
||||
EuiPopoverFooter,
|
||||
EuiContextMenuPanel,
|
||||
EuiContextMenuItem,
|
||||
EuiSwitch,
|
||||
EuiHorizontalRule,
|
||||
EuiText,
|
||||
EuiSpacer,
|
||||
EuiIcon,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { AlertTableItem } from '../../../../types';
|
||||
|
@ -23,6 +26,7 @@ import {
|
|||
ComponentOpts as BulkOperationsComponentOpts,
|
||||
withBulkAlertOperations,
|
||||
} from '../../common/components/with_bulk_alert_api_operations';
|
||||
import './collapsed_item_actions.scss';
|
||||
|
||||
export type ComponentOpts = {
|
||||
item: AlertTableItem;
|
||||
|
@ -64,68 +68,93 @@ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
|
|||
isOpen={isPopoverOpen}
|
||||
closePopover={() => setIsPopoverOpen(false)}
|
||||
ownFocus
|
||||
panelPaddingSize="none"
|
||||
data-test-subj="collapsedItemActions"
|
||||
>
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
name="enable"
|
||||
disabled={!canSave}
|
||||
checked={item.enabled}
|
||||
data-test-subj="enableSwitch"
|
||||
onChange={async () => {
|
||||
if (item.enabled) {
|
||||
await disableAlert(item);
|
||||
} else {
|
||||
await enableAlert(item);
|
||||
<EuiContextMenuPanel className="actCollapsedItemActions" hasFocus={false}>
|
||||
<div className="actCollapsedItemActions__item">
|
||||
<EuiSwitch
|
||||
name="disable"
|
||||
disabled={!canSave}
|
||||
compressed
|
||||
checked={!item.enabled}
|
||||
data-test-subj="disableSwitch"
|
||||
onChange={async () => {
|
||||
if (item.enabled) {
|
||||
await disableAlert(item);
|
||||
} else {
|
||||
await enableAlert(item);
|
||||
}
|
||||
onAlertChanged();
|
||||
}}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableTitle"
|
||||
defaultMessage="Disable"
|
||||
/>
|
||||
}
|
||||
onAlertChanged();
|
||||
}}
|
||||
label={
|
||||
/>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText color="subdued" size="xs">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.enableTitle"
|
||||
defaultMessage="Enable"
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.disableHelpText"
|
||||
defaultMessage="When disabled, the alert is not checked."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
name="mute"
|
||||
checked={item.muteAll}
|
||||
disabled={!(canSave && item.enabled)}
|
||||
data-test-subj="muteSwitch"
|
||||
onChange={async () => {
|
||||
if (item.muteAll) {
|
||||
await unmuteAlert(item);
|
||||
} else {
|
||||
await muteAlert(item);
|
||||
</EuiText>
|
||||
</div>
|
||||
<div className="actCollapsedItemActions__item">
|
||||
<EuiSwitch
|
||||
name="mute"
|
||||
checked={item.muteAll}
|
||||
disabled={!(canSave && item.enabled)}
|
||||
compressed
|
||||
data-test-subj="muteSwitch"
|
||||
onChange={async () => {
|
||||
if (item.muteAll) {
|
||||
await unmuteAlert(item);
|
||||
} else {
|
||||
await muteAlert(item);
|
||||
}
|
||||
onAlertChanged();
|
||||
}}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle"
|
||||
defaultMessage="Mute"
|
||||
/>
|
||||
}
|
||||
onAlertChanged();
|
||||
}}
|
||||
label={
|
||||
/>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText color="subdued" size="xs">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteTitle"
|
||||
defaultMessage="Mute"
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.muteHelpText"
|
||||
defaultMessage="When muted, the alert is checked, but no action is performed."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiPopoverFooter>
|
||||
<EuiFormRow>
|
||||
<EuiButtonEmpty
|
||||
isDisabled={!canDelete}
|
||||
iconType="trash"
|
||||
color="text"
|
||||
data-test-subj="deleteAlert"
|
||||
onClick={() => setAlertsToDelete([item.id])}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.collapsedItemActons.deleteTitle"
|
||||
defaultMessage="Delete"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFormRow>
|
||||
</EuiPopoverFooter>
|
||||
</EuiText>
|
||||
</div>
|
||||
<EuiHorizontalRule margin="none" />
|
||||
<EuiContextMenuItem
|
||||
disabled={!canDelete}
|
||||
data-test-subj="deleteAlert"
|
||||
onClick={() => setAlertsToDelete([item.id])}
|
||||
>
|
||||
<div className="actCollapsedItemActions__delete">
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
.actBulkActionPopover__deleteAll {
|
||||
.euiButtonEmpty__text {
|
||||
padding-top: $euiSizeXS;
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useState, Fragment } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiButtonEmpty } from '@elastic/eui';
|
||||
import { EuiButtonEmpty, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
|
||||
|
||||
import { Alert } from '../../../../types';
|
||||
import { useAppDependencies } from '../../../app_context';
|
||||
|
@ -15,6 +15,7 @@ import {
|
|||
withBulkAlertOperations,
|
||||
ComponentOpts as BulkOperationsComponentOpts,
|
||||
} from './with_bulk_alert_api_operations';
|
||||
import './alert_quick_edit_buttons.scss';
|
||||
|
||||
export type ComponentOpts = {
|
||||
selectedItems: Alert[];
|
||||
|
@ -147,72 +148,84 @@ export const AlertQuickEditButtons: React.FunctionComponent<ComponentOpts> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFlexGroup alignItems="baseline" direction="column" gutterSize="none">
|
||||
{!allAlertsMuted && (
|
||||
<EuiButtonEmpty
|
||||
onClick={onmMuteAllClick}
|
||||
isLoading={isMutingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="muteAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle"
|
||||
defaultMessage="Mute"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
<EuiFlexItem>
|
||||
<EuiButtonEmpty
|
||||
onClick={onmMuteAllClick}
|
||||
isLoading={isMutingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="muteAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.muteAllTitle"
|
||||
defaultMessage="Mute"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{allAlertsMuted && (
|
||||
<EuiButtonEmpty
|
||||
onClick={onUnmuteAllClick}
|
||||
isLoading={isUnmutingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="unmuteAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle"
|
||||
defaultMessage="Unmute"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
<EuiFlexItem>
|
||||
<EuiButtonEmpty
|
||||
onClick={onUnmuteAllClick}
|
||||
isLoading={isUnmutingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="unmuteAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.unmuteAllTitle"
|
||||
defaultMessage="Unmute"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{allAlertsDisabled && (
|
||||
<EuiButtonEmpty
|
||||
onClick={onEnableAllClick}
|
||||
isLoading={isEnablingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="enableAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.enableAllTitle"
|
||||
defaultMessage="Enable"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
<EuiFlexItem>
|
||||
<EuiButtonEmpty
|
||||
onClick={onEnableAllClick}
|
||||
isLoading={isEnablingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="enableAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.enableAllTitle"
|
||||
defaultMessage="Enable"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{!allAlertsDisabled && (
|
||||
<EuiFlexItem>
|
||||
<EuiButtonEmpty
|
||||
onClick={onDisableAllClick}
|
||||
isLoading={isDisablingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="disableAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.disableAllTitle"
|
||||
defaultMessage="Disable"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
<EuiFlexItem>
|
||||
<EuiButtonEmpty
|
||||
onClick={onDisableAllClick}
|
||||
isLoading={isDisablingAlerts}
|
||||
onClick={deleteSelectedItems}
|
||||
isLoading={isDeletingAlerts}
|
||||
iconType="trash"
|
||||
color="danger"
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="disableAll"
|
||||
data-test-subj="deleteAll"
|
||||
className="actBulkActionPopover__deleteAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.disableAllTitle"
|
||||
defaultMessage="Disable"
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.deleteAllTitle"
|
||||
defaultMessage="Delete"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
)}
|
||||
|
||||
<EuiButtonEmpty
|
||||
onClick={deleteSelectedItems}
|
||||
isLoading={isDeletingAlerts}
|
||||
isDisabled={isPerformingAction}
|
||||
data-test-subj="deleteAll"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.alertsList.bulkActionPopover.deleteAllTitle"
|
||||
defaultMessage="Delete"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</Fragment>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, Fragment } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiButton, EuiFormRow, EuiPopover } from '@elastic/eui';
|
||||
import { EuiButton, EuiPopover } from '@elastic/eui';
|
||||
|
||||
export const BulkOperationPopover: React.FunctionComponent = ({ children }) => {
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
|
@ -16,6 +16,7 @@ export const BulkOperationPopover: React.FunctionComponent = ({ children }) => {
|
|||
isOpen={isPopoverOpen}
|
||||
closePopover={() => setIsPopoverOpen(false)}
|
||||
data-test-subj="bulkAction"
|
||||
panelPaddingSize="s"
|
||||
button={
|
||||
<EuiButton
|
||||
iconType="arrowDown"
|
||||
|
@ -31,11 +32,7 @@ export const BulkOperationPopover: React.FunctionComponent = ({ children }) => {
|
|||
>
|
||||
{children &&
|
||||
React.Children.map(children, child =>
|
||||
React.isValidElement(child) ? (
|
||||
<EuiFormRow>{React.cloneElement(child, {})}</EuiFormRow>
|
||||
) : (
|
||||
child
|
||||
)
|
||||
React.isValidElement(child) ? <Fragment>{React.cloneElement(child, {})}</Fragment> : child
|
||||
)}
|
||||
</EuiPopover>
|
||||
);
|
||||
|
|
|
@ -343,15 +343,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
await pageObjects.triggersActionsUI.toggleSwitch('enableSwitch');
|
||||
await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch');
|
||||
|
||||
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
|
||||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
const enableSwitchAfterDisable = await testSubjects.find('enableSwitch');
|
||||
const isChecked = await enableSwitchAfterDisable.getAttribute('aria-checked');
|
||||
expect(isChecked).to.eql('false');
|
||||
const disableSwitchAfterDisable = await testSubjects.find('disableSwitch');
|
||||
const isChecked = await disableSwitchAfterDisable.getAttribute('aria-checked');
|
||||
expect(isChecked).to.eql('true');
|
||||
});
|
||||
|
||||
it('should re-enable single alert', async () => {
|
||||
|
@ -361,21 +361,21 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
await pageObjects.triggersActionsUI.toggleSwitch('enableSwitch');
|
||||
await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch');
|
||||
|
||||
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
|
||||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
await pageObjects.triggersActionsUI.toggleSwitch('enableSwitch');
|
||||
await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch');
|
||||
|
||||
await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name);
|
||||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
const enableSwitchAfterReEnable = await testSubjects.find('enableSwitch');
|
||||
const isChecked = await enableSwitchAfterReEnable.getAttribute('aria-checked');
|
||||
expect(isChecked).to.eql('true');
|
||||
const disableSwitchAfterReEnable = await testSubjects.find('disableSwitch');
|
||||
const isChecked = await disableSwitchAfterReEnable.getAttribute('aria-checked');
|
||||
expect(isChecked).to.eql('false');
|
||||
});
|
||||
|
||||
it('should mute single alert', async () => {
|
||||
|
@ -507,9 +507,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
const enableSwitch = await testSubjects.find('enableSwitch');
|
||||
const isChecked = await enableSwitch.getAttribute('aria-checked');
|
||||
expect(isChecked).to.eql('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 () => {
|
||||
|
@ -532,9 +532,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
await testSubjects.click('collapsedItemActions');
|
||||
|
||||
const enableSwitch = await testSubjects.find('enableSwitch');
|
||||
const isChecked = await enableSwitch.getAttribute('aria-checked');
|
||||
expect(isChecked).to.eql('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 () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue