forked from grafana.jool/grafana-jool
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
5.7 KiB
157 lines
5.7 KiB
import React, { useMemo } from 'react';
|
|
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
|
import { Alert, Field, FieldSet, Input, Button, LinkButton, useStyles2 } from '@grafana/ui';
|
|
import { FormProvider, useForm } from 'react-hook-form';
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { useDispatch } from 'react-redux';
|
|
import { css } from '@emotion/css';
|
|
import {
|
|
AlertmanagerConfig,
|
|
AlertManagerCortexConfig,
|
|
MuteTimeInterval,
|
|
} from 'app/plugins/datasource/alertmanager/types';
|
|
import { AlertManagerPicker } from '../AlertManagerPicker';
|
|
import { useAlertManagerSourceName } from '../../hooks/useAlertManagerSourceName';
|
|
import { updateAlertManagerConfigAction } from '../../state/actions';
|
|
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
|
|
import { initialAsyncRequestState } from '../../utils/redux';
|
|
import { MuteTimingFields } from '../../types/mute-timing-form';
|
|
import { createMuteTiming, defaultTimeInterval } from '../../utils/mute-timings';
|
|
import { makeAMLink } from '../../utils/misc';
|
|
import { renameMuteTimings } from '../../utils/alertmanager';
|
|
import { MuteTimingTimeInterval } from './MuteTimingTimeInterval';
|
|
|
|
interface Props {
|
|
muteTiming?: MuteTimeInterval;
|
|
showError?: boolean;
|
|
}
|
|
|
|
const useDefaultValues = (muteTiming?: MuteTimeInterval): MuteTimingFields => {
|
|
return useMemo(() => {
|
|
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,
|
|
}));
|
|
|
|
return {
|
|
name: muteTiming.name,
|
|
time_intervals: intervals,
|
|
};
|
|
}, [muteTiming]);
|
|
};
|
|
|
|
const MuteTimingForm = ({ muteTiming, showError }: Props) => {
|
|
const dispatch = useDispatch();
|
|
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName();
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const defaultAmCortexConfig = { alertmanager_config: {}, template_files: {} };
|
|
const amConfigs = useUnifiedAlertingSelector((state) => state.amConfigs);
|
|
const { result = defaultAmCortexConfig, loading } =
|
|
(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],
|
|
},
|
|
};
|
|
|
|
dispatch(
|
|
updateAlertManagerConfigAction({
|
|
newConfig,
|
|
oldConfig: result,
|
|
alertManagerSourceName: alertManagerSourceName!,
|
|
successMessage: 'Mute timing saved',
|
|
redirectPath: '/alerting/routes/',
|
|
})
|
|
);
|
|
};
|
|
|
|
return (
|
|
<AlertingPageWrapper pageId="am-routes">
|
|
<AlertManagerPicker current={alertManagerSourceName} onChange={setAlertManagerSourceName} disabled />
|
|
{result && !loading && (
|
|
<FormProvider {...formApi}>
|
|
<form onSubmit={formApi.handleSubmit(onSubmit)} data-testid="mute-timing-form">
|
|
{showError && <Alert title="No matching mute timing found" />}
|
|
<FieldSet label={'Create mute timing'}>
|
|
<Field
|
|
required
|
|
label="Name"
|
|
description="A unique name for the mute timing"
|
|
invalid={!!formApi.formState.errors?.name}
|
|
error={formApi.formState.errors.name?.message}
|
|
>
|
|
<Input
|
|
{...formApi.register('name', {
|
|
required: true,
|
|
validate: (value) => {
|
|
if (!muteTiming) {
|
|
const existingMuteTiming = config?.mute_time_intervals?.find(({ name }) => value === name);
|
|
return existingMuteTiming ? `Mute timing already exists for "${value}"` : true;
|
|
}
|
|
return value.length > 0 || 'Name is required';
|
|
},
|
|
})}
|
|
className={styles.input}
|
|
data-testid={'mute-timing-name'}
|
|
/>
|
|
</Field>
|
|
<MuteTimingTimeInterval />
|
|
<LinkButton
|
|
type="button"
|
|
variant="secondary"
|
|
href={makeAMLink('/alerting/routes/', alertManagerSourceName)}
|
|
>
|
|
Cancel
|
|
</LinkButton>
|
|
<Button type="submit" className={styles.submitButton}>
|
|
{muteTiming ? 'Save' : 'Submit'}
|
|
</Button>
|
|
</FieldSet>
|
|
</form>
|
|
</FormProvider>
|
|
)}
|
|
</AlertingPageWrapper>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
|
input: css`
|
|
width: 400px;
|
|
`,
|
|
submitButton: css`
|
|
margin-left: ${theme.spacing(1)};
|
|
`,
|
|
});
|
|
|
|
export default MuteTimingForm;
|
|
|