import { css } from '@emotion/css'; import React, { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { GrafanaTheme2, NavModelItem } from '@grafana/data'; import { Alert, Button, Field, FieldSet, Input, LinkButton, LoadingPlaceholder, useStyles2 } from '@grafana/ui'; import { AlertmanagerConfig, AlertManagerCortexConfig, MuteTimeInterval, } from 'app/plugins/datasource/alertmanager/types'; import { useDispatch } from 'app/types'; import { useAlertManagerSourceName } from '../../hooks/useAlertManagerSourceName'; import { useAlertManagersByPermission } from '../../hooks/useAlertManagerSources'; import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector'; import { updateAlertManagerConfigAction } from '../../state/actions'; import { MuteTimingFields } from '../../types/mute-timing-form'; import { renameMuteTimings } from '../../utils/alertmanager'; import { makeAMLink } from '../../utils/misc'; import { createMuteTiming, defaultTimeInterval } from '../../utils/mute-timings'; import { initialAsyncRequestState } from '../../utils/redux'; import { AlertManagerPicker } from '../AlertManagerPicker'; import { AlertingPageWrapper } from '../AlertingPageWrapper'; import { ProvisionedResource, ProvisioningAlert } from '../Provisioning'; import { MuteTimingTimeInterval } from './MuteTimingTimeInterval'; interface Props { muteTiming?: MuteTimeInterval; showError?: boolean; provenance?: string; loading?: boolean; } const useDefaultValues = (muteTiming?: MuteTimeInterval): MuteTimingFields => { const defaultValues = { name: '', time_intervals: [defaultTimeInterval], }; if (!muteTiming) { return defaultValues; } const intervals = muteTiming.time_intervals.map((interval) => ({ times: interval.times ?? defaultTimeInterval.times, weekdays: interval.weekdays?.join(', ') ?? defaultTimeInterval.weekdays, days_of_month: interval.days_of_month?.join(', ') ?? defaultTimeInterval.days_of_month, months: interval.months?.join(', ') ?? defaultTimeInterval.months, years: interval.years?.join(', ') ?? defaultTimeInterval.years, location: interval.location ?? defaultTimeInterval.location, })); return { name: muteTiming.name, time_intervals: intervals, }; }; const defaultPageNav: Partial = { icon: 'sitemap', }; const MuteTimingForm = ({ muteTiming, showError, loading, provenance }: Props) => { const dispatch = useDispatch(); const alertManagers = useAlertManagersByPermission('notification'); const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers); const styles = useStyles2(getStyles); const [updating, setUpdating] = useState(false); const defaultAmCortexConfig = { alertmanager_config: {}, template_files: {} }; const amConfigs = useUnifiedAlertingSelector((state) => state.amConfigs); const { result = defaultAmCortexConfig } = (alertManagerSourceName && amConfigs[alertManagerSourceName]) || initialAsyncRequestState; const config: AlertmanagerConfig = result?.alertmanager_config ?? {}; const defaultValues = useDefaultValues(muteTiming); const formApi = useForm({ defaultValues }); const onSubmit = (values: MuteTimingFields) => { const newMuteTiming = createMuteTiming(values); const muteTimings = muteTiming ? config?.mute_time_intervals?.filter(({ name }) => name !== muteTiming.name) : config.mute_time_intervals; const newConfig: AlertManagerCortexConfig = { ...result, alertmanager_config: { ...config, route: muteTiming && newMuteTiming.name !== muteTiming.name ? renameMuteTimings(newMuteTiming.name, muteTiming.name, config.route ?? {}) : config.route, mute_time_intervals: [...(muteTimings || []), newMuteTiming], }, }; const saveAction = dispatch( updateAlertManagerConfigAction({ newConfig, oldConfig: result, alertManagerSourceName: alertManagerSourceName!, successMessage: 'Mute timing saved', redirectPath: '/alerting/routes/', redirectSearch: 'tab=mute_timings', }) ); setUpdating(true); saveAction.unwrap().finally(() => { setUpdating(false); }); }; return ( {provenance && } {loading && } {showError && } {result && !loading && !showError && (
{ if (!muteTiming) { const existingMuteTiming = config?.mute_time_intervals?.find(({ name }) => value === name); return existingMuteTiming ? `Mute timing already exists for "${value}"` : true; } return; }, })} className={styles.input} data-testid={'mute-timing-name'} /> Cancel
)}
); }; const getStyles = (theme: GrafanaTheme2) => ({ input: css` width: 400px; `, submitButton: css` margin-right: ${theme.spacing(1)}; `, }); export default MuteTimingForm;