diff --git a/x-pack/plugins/uptime/public/components/common/alerts/uptime_edit_alert_flyout.tsx b/x-pack/plugins/uptime/public/components/common/alerts/uptime_edit_alert_flyout.tsx new file mode 100644 index 0000000000000..cdc3632545c5c --- /dev/null +++ b/x-pack/plugins/uptime/public/components/common/alerts/uptime_edit_alert_flyout.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { Alert, AlertEdit } from '../../../../../../plugins/triggers_actions_ui/public'; + +interface Props { + alertFlyoutVisible: boolean; + initialAlert: Alert; + setAlertFlyoutVisibility: React.Dispatch>; +} + +export const UptimeEditAlertFlyoutComponent = ({ + alertFlyoutVisible, + initialAlert, + setAlertFlyoutVisibility, +}: Props) => { + const onClose = () => { + setAlertFlyoutVisibility(false); + }; + return alertFlyoutVisible ? : null; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx index 7971c4eb58350..c8260721ff84a 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx @@ -22,7 +22,12 @@ import { useMonitorId } from '../../../hooks'; import { setAlertFlyoutType, setAlertFlyoutVisible } from '../../../state/actions'; import { useAnomalyAlert } from './use_anomaly_alert'; import { ConfirmAlertDeletion } from './confirm_alert_delete'; -import { deleteAnomalyAlertAction } from '../../../state/alerts/alerts'; +import { + deleteAnomalyAlertAction, + getAnomalyAlertAction, + isAnomalyAlertDeleting, +} from '../../../state/alerts/alerts'; +import { UptimeEditAlertFlyoutComponent } from '../../common/alerts/uptime_edit_alert_flyout'; interface Props { hasMLJob: boolean; @@ -33,11 +38,14 @@ interface Props { export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Props) => { const [isPopOverOpen, setIsPopOverOpen] = useState(false); + const [isFlyoutOpen, setIsFlyoutOpen] = useState(false); + const { basePath } = useContext(UptimeSettingsContext); const canDeleteMLJob = useSelector(canDeleteMLJobSelector); const isMLJobCreating = useSelector(isMLJobCreatingSelector); + const isAlertDeleting = useSelector(isAnomalyAlertDeleting); const { loading: isMLJobLoading } = useSelector(hasMLJobSelector); @@ -54,7 +62,7 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro const deleteAnomalyAlert = () => dispatch(deleteAnomalyAlertAction.get({ alertId: anomalyAlert?.id as string })); - const showLoading = isMLJobCreating || isMLJobLoading; + const showLoading = isMLJobCreating || isMLJobLoading || isAlertDeleting; const btnText = hasMLJob ? labels.ANOMALY_DETECTION : labels.ENABLE_ANOMALY_DETECTION; @@ -63,7 +71,7 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro data-test-subj={hasMLJob ? 'uptimeManageMLJobBtn' : 'uptimeEnableAnomalyBtn'} onClick={hasMLJob ? () => setIsPopOverOpen(true) : onEnableJob} disabled={hasMLJob && !canDeleteMLJob} - isLoading={isMLJobCreating || isMLJobLoading} + isLoading={showLoading} size="s" aria-label={labels.ENABLE_MANAGE_JOB} > @@ -85,21 +93,27 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro dateRange: { from: dateRangeStart, to: dateRangeEnd }, }), }, - { - name: anomalyAlert ? labels.DISABLE_ANOMALY_ALERT : labels.ENABLE_ANOMALY_ALERT, - 'data-test-subj': anomalyAlert - ? 'uptimeDisableAnomalyAlertBtn' - : 'uptimeEnableAnomalyAlertBtn', - icon: , - onClick: () => { - if (anomalyAlert) { - setIsConfirmAlertDeleteOpen(true); - } else { - dispatch(setAlertFlyoutType(CLIENT_ALERT_TYPES.DURATION_ANOMALY)); - dispatch(setAlertFlyoutVisible(true)); - } - }, - }, + ...(anomalyAlert + ? [ + { + name: 'Anomaly alert', + icon: 'bell', + 'data-test-subj': 'uptimeManageAnomalyAlertBtn', + panel: 1, + }, + ] + : [ + { + name: labels.ENABLE_ANOMALY_ALERT, + 'data-test-subj': 'uptimeEnableAnomalyAlertBtn', + icon: 'bell', + onClick: () => { + dispatch(setAlertFlyoutType(CLIENT_ALERT_TYPES.DURATION_ANOMALY)); + dispatch(setAlertFlyoutVisible(true)); + setIsPopOverOpen(false); + }, + }, + ]), { name: labels.DISABLE_ANOMALY_DETECTION, 'data-test-subj': 'uptimeDeleteMLJobBtn', @@ -111,6 +125,27 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro }, ], }, + { + id: 1, + title: 'Anomaly alert', + items: [ + { + name: 'Edit', + 'data-test-subj': 'uptimeEditAnomalyAlertBtn', + onClick: () => { + setIsFlyoutOpen(true); + setIsPopOverOpen(false); + }, + }, + { + name: 'Disable', + 'data-test-subj': 'uptimeDisableAnomalyAlertBtn', + onClick: () => { + setIsConfirmAlertDeleteOpen(true); + }, + }, + ], + }, ]; return ( @@ -138,6 +173,14 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro }} /> )} + { + setIsFlyoutOpen(false); + dispatch(getAnomalyAlertAction.get({ monitorId })); + }} + /> ); }; diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/anomaly_alert/anomaly_alert.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/anomaly_alert/anomaly_alert.tsx index 1428a7f526fc2..dd732f0b7e24b 100644 --- a/x-pack/plugins/uptime/public/components/overview/alerts/anomaly_alert/anomaly_alert.tsx +++ b/x-pack/plugins/uptime/public/components/overview/alerts/anomaly_alert/anomaly_alert.tsx @@ -16,7 +16,7 @@ import { useSelector } from 'react-redux'; import React, { useEffect, useState } from 'react'; import { AnomalyTranslations } from './translations'; import { AlertExpressionPopover } from '../alert_expression_popover'; -import { DEFAULT_SEVERITY, SelectSeverity } from './select_severity'; +import { DEFAULT_SEVERITY, SelectSeverity, SEVERITY_OPTIONS } from './select_severity'; import { monitorIdSelector } from '../../../../state/selectors'; import { getSeverityColor, getSeverityType } from '../../../../../../ml/public'; @@ -40,6 +40,14 @@ export function AnomalyAlertComponent({ setAlertParams, alertParams }: Props) { setAlertParams('severity', severity.val); }, [severity, setAlertParams]); + useEffect(() => { + if (alertParams.severity !== undefined) { + setSeverity(SEVERITY_OPTIONS.find(({ val }) => val === alertParams.severity)!); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return ( <> diff --git a/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx b/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx index c1f802c2d0c91..c277e87c1ed74 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx +++ b/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx @@ -25,5 +25,5 @@ export const initDurationAnomalyAlertType: AlertTypeInitializer = ({ name, validate: () => ({ errors: {} }), defaultActionMessage, - requiresAppContext: false, + requiresAppContext: true, }); diff --git a/x-pack/plugins/uptime/public/state/alerts/alerts.ts b/x-pack/plugins/uptime/public/state/alerts/alerts.ts index 5273a33102565..aeb81bb413aa7 100644 --- a/x-pack/plugins/uptime/public/state/alerts/alerts.ts +++ b/x-pack/plugins/uptime/public/state/alerts/alerts.ts @@ -163,3 +163,4 @@ export const alertsSelector = ({ alerts }: AppState) => alerts.alerts; export const isAlertDeletedSelector = ({ alerts }: AppState) => alerts.alertDeletion; export const anomalyAlertSelector = ({ alerts }: AppState) => alerts.anomalyAlert; +export const isAnomalyAlertDeleting = ({ alerts }: AppState) => alerts.anomalyAlertDeletion.loading; diff --git a/x-pack/test/functional/apps/uptime/ml_anomaly.ts b/x-pack/test/functional/apps/uptime/ml_anomaly.ts index 20491a063caf8..6930996921823 100644 --- a/x-pack/test/functional/apps/uptime/ml_anomaly.ts +++ b/x-pack/test/functional/apps/uptime/ml_anomaly.ts @@ -40,7 +40,6 @@ export default ({ getService }: FtrProviderContext) => { it('can create job successfully', async () => { await uptime.ml.createMLJob(); - // await uptime.navigation.refreshApp(); }); it('can open ML Manage Menu', async () => { diff --git a/x-pack/test/functional/services/uptime/ml_anomaly.ts b/x-pack/test/functional/services/uptime/ml_anomaly.ts index ac9f6ab2b3d14..cdeec2129e459 100644 --- a/x-pack/test/functional/services/uptime/ml_anomaly.ts +++ b/x-pack/test/functional/services/uptime/ml_anomaly.ts @@ -66,8 +66,8 @@ export function UptimeMLAnomalyProvider({ getService }: FtrProviderContext) { return await testSubjects.click('uptimeEnableAnomalyAlertBtn'); }, - async disableAnomalyAlertIsVisible() { - return await testSubjects.exists('uptimeDisableAnomalyAlertBtn'); + async manageAnomalyAlertIsVisible() { + return await testSubjects.exists('uptimeManageAnomalyAlertBtn'); }, async changeAlertThreshold(level: string) { diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/anomaly_alert.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/anomaly_alert.ts index 03343bff642c3..55ef7e9784ff4 100644 --- a/x-pack/test/functional_with_es_ssl/apps/uptime/anomaly_alert.ts +++ b/x-pack/test/functional_with_es_ssl/apps/uptime/anomaly_alert.ts @@ -111,7 +111,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('change button to disable anomaly alert', async () => { await uptime.ml.openMLManageMenu(); - expect(uptime.ml.disableAnomalyAlertIsVisible()).to.eql(true); + expect(uptime.ml.manageAnomalyAlertIsVisible()).to.eql(true); }); it('can delete job successfully', async () => {