import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; import { Alert, Button, Field, Input, LinkButton, TextArea, useStyles2 } from '@grafana/ui'; import { useCleanup } from 'app/core/hooks/useCleanup'; import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types'; import React, { FC } from 'react'; import { useForm, Validate } from 'react-hook-form'; import { useDispatch } from 'react-redux'; import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector'; import { updateAlertManagerConfigAction } from '../../state/actions'; import { makeAMLink } from '../../utils/misc'; import { ensureDefine } from '../../utils/templates'; interface Values { name: string; content: string; } const defaults: Values = Object.freeze({ name: '', content: '', }); interface Props { existing?: Values; config: AlertManagerCortexConfig; alertManagerSourceName: string; } export const TemplateForm: FC = ({ existing, alertManagerSourceName, config }) => { const styles = useStyles2(getStyles); const dispatch = useDispatch(); useCleanup((state) => state.unifiedAlerting.saveAMConfig); const { loading, error } = useUnifiedAlertingSelector((state) => state.saveAMConfig); const submit = (values: Values) => { // wrap content in "define" if it's not already wrapped, in case user did not do it/ // it's not obvious that this is needed for template to work const content = ensureDefine(values.name, values.content); // add new template to template map const template_files = { ...config.template_files, [values.name]: content, }; // delete existing one (if name changed, otherwise it was overwritten in previous step) if (existing && existing.name !== values.name) { delete template_files[existing.name]; } // make sure name for the template is configured on the alertmanager config object const templates = [ ...(config.alertmanager_config.templates ?? []).filter((name) => name !== existing?.name), values.name, ]; const newConfig: AlertManagerCortexConfig = { template_files, alertmanager_config: { ...config.alertmanager_config, templates, }, }; dispatch( updateAlertManagerConfigAction({ alertManagerSourceName, newConfig, oldConfig: config, successMessage: 'Template saved.', redirectPath: '/alerting/notifications', }) ); }; const { handleSubmit, register, formState: { errors }, } = useForm({ mode: 'onSubmit', defaultValues: existing ?? defaults, }); const validateNameIsUnique: Validate = (name: string) => { return !config.template_files[name] || existing?.name === name ? true : 'Another template with this name already exists.'; }; return (

{existing ? 'Edit message template' : 'Create message template'}

{error && ( {error.message || (error as any)?.data?.message || String(error)} )} You can use the{' '} Go templating language .{' '} More info about alertmanager templates } label="Content" error={errors?.content?.message} invalid={!!errors.content?.message} required >