mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
213 lines
7.5 KiB
TypeScript
213 lines
7.5 KiB
TypeScript
import { Fragment, useState } from 'react';
|
|
|
|
import { logError } from '@grafana/runtime';
|
|
import { Badge, ConfirmModal, Tooltip, useStyles2 } from '@grafana/ui';
|
|
import { useAppNotification } from 'app/core/copy/appNotification';
|
|
import { t, Trans } from 'app/core/internationalization';
|
|
import { CodeText } from 'app/features/alerting/unified/components/common/TextVariants';
|
|
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
|
|
|
import { Authorize } from '../../components/Authorize';
|
|
import { AlertmanagerAction } from '../../hooks/useAbilities';
|
|
import { getAlertTableStyles } from '../../styles/table';
|
|
import { makeAMLink, stringifyErrorLike } from '../../utils/misc';
|
|
import { CollapseToggle } from '../CollapseToggle';
|
|
import { DetailsField } from '../DetailsField';
|
|
import { ProvisioningBadge } from '../Provisioning';
|
|
import {
|
|
NotificationTemplate,
|
|
useDeleteNotificationTemplate,
|
|
useNotificationTemplateMetadata,
|
|
} from '../contact-points/useNotificationTemplates';
|
|
import { ActionIcon } from '../rules/ActionIcon';
|
|
|
|
import { TemplateEditor } from './TemplateEditor';
|
|
|
|
interface Props {
|
|
alertManagerName: string;
|
|
templates: NotificationTemplate[];
|
|
}
|
|
|
|
export const TemplatesTable = ({ alertManagerName, templates }: Props) => {
|
|
const appNotification = useAppNotification();
|
|
const [deleteTemplate] = useDeleteNotificationTemplate({ alertmanager: alertManagerName });
|
|
|
|
const tableStyles = useStyles2(getAlertTableStyles);
|
|
|
|
const [templateToDelete, setTemplateToDelete] = useState<NotificationTemplate | undefined>();
|
|
|
|
const onDeleteTemplate = async () => {
|
|
if (templateToDelete) {
|
|
try {
|
|
await deleteTemplate.execute({ uid: templateToDelete.uid });
|
|
appNotification.success('Template deleted', `Template ${templateToDelete.title} has been deleted`);
|
|
} catch (error) {
|
|
appNotification.error('Error deleting template', `Error deleting template ${templateToDelete.title}`);
|
|
|
|
const loggableError = error instanceof Error ? error : new Error(stringifyErrorLike(error));
|
|
logError(loggableError);
|
|
}
|
|
}
|
|
setTemplateToDelete(undefined);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<table className={tableStyles.table} data-testid="templates-table">
|
|
<colgroup>
|
|
<col className={tableStyles.colExpand} />
|
|
<col />
|
|
<col />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th></th>
|
|
<th>Template</th>
|
|
<Authorize
|
|
actions={[
|
|
AlertmanagerAction.CreateNotificationTemplate,
|
|
AlertmanagerAction.UpdateNotificationTemplate,
|
|
AlertmanagerAction.DeleteNotificationTemplate,
|
|
]}
|
|
>
|
|
<th>Actions</th>
|
|
</Authorize>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{!templates.length && (
|
|
<tr className={tableStyles.evenRow}>
|
|
<td colSpan={3}>No templates defined.</td>
|
|
</tr>
|
|
)}
|
|
{templates.map((notificationTemplate, idx) => (
|
|
<TemplateRow
|
|
key={notificationTemplate.uid}
|
|
notificationTemplate={notificationTemplate}
|
|
idx={idx}
|
|
alertManagerName={alertManagerName}
|
|
onDeleteClick={setTemplateToDelete}
|
|
/>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
|
|
{!!templateToDelete && (
|
|
<ConfirmModal
|
|
isOpen={true}
|
|
title="Delete template"
|
|
body={`Are you sure you want to delete template "${templateToDelete.title}"?`}
|
|
confirmText="Yes, delete"
|
|
onConfirm={onDeleteTemplate}
|
|
onDismiss={() => setTemplateToDelete(undefined)}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
interface TemplateRowProps {
|
|
notificationTemplate: NotificationTemplate;
|
|
idx: number;
|
|
alertManagerName: string;
|
|
onDeleteClick: (template: NotificationTemplate) => void;
|
|
}
|
|
|
|
function TemplateRow({ notificationTemplate, idx, alertManagerName, onDeleteClick }: TemplateRowProps) {
|
|
const tableStyles = useStyles2(getAlertTableStyles);
|
|
const isGrafanaAlertmanager = alertManagerName === GRAFANA_RULES_SOURCE_NAME;
|
|
|
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
const { isProvisioned } = useNotificationTemplateMetadata(notificationTemplate);
|
|
|
|
const { uid, title: name, content: template, missing } = notificationTemplate;
|
|
const misconfiguredBadgeText = t('alerting.templates.misconfigured-badge-text', 'Misconfigured');
|
|
return (
|
|
<Fragment key={uid}>
|
|
<tr className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
|
|
<td>
|
|
<CollapseToggle isCollapsed={!isExpanded} onToggle={() => setIsExpanded(!isExpanded)} />
|
|
</td>
|
|
<td>
|
|
{name} {isProvisioned && <ProvisioningBadge />}{' '}
|
|
{missing && !isGrafanaAlertmanager && (
|
|
<Tooltip
|
|
content={
|
|
<>
|
|
<Trans i18nKey="alerting.templates.misconfigured-warning">This template is misconfigured.</Trans>
|
|
<br />
|
|
<Trans i18nKey="alerting.templates.misconfigured-warning-details">
|
|
Templates must be defined in both the <CodeText content="template_files" /> and{' '}
|
|
<CodeText content="templates" /> sections of your alertmanager configuration.
|
|
</Trans>
|
|
</>
|
|
}
|
|
>
|
|
<span>
|
|
<Badge text={misconfiguredBadgeText} color="orange" />
|
|
</span>
|
|
</Tooltip>
|
|
)}
|
|
</td>
|
|
<td className={tableStyles.actionsCell}>
|
|
{isProvisioned && (
|
|
<ActionIcon
|
|
to={makeAMLink(`/alerting/notifications/templates/${encodeURIComponent(uid)}/edit`, alertManagerName)}
|
|
tooltip="view template"
|
|
icon="file-alt"
|
|
/>
|
|
)}
|
|
{!isProvisioned && (
|
|
<Authorize actions={[AlertmanagerAction.UpdateNotificationTemplate]}>
|
|
<ActionIcon
|
|
to={makeAMLink(`/alerting/notifications/templates/${encodeURIComponent(uid)}/edit`, alertManagerName)}
|
|
tooltip="edit template"
|
|
icon="pen"
|
|
/>
|
|
</Authorize>
|
|
)}
|
|
<Authorize actions={[AlertmanagerAction.CreateContactPoint]}>
|
|
<ActionIcon
|
|
to={makeAMLink(
|
|
`/alerting/notifications/templates/${encodeURIComponent(uid)}/duplicate`,
|
|
alertManagerName
|
|
)}
|
|
tooltip="Copy template"
|
|
icon="copy"
|
|
/>
|
|
</Authorize>
|
|
{!isProvisioned && (
|
|
<Authorize actions={[AlertmanagerAction.DeleteNotificationTemplate]}>
|
|
<ActionIcon
|
|
onClick={() => onDeleteClick(notificationTemplate)}
|
|
tooltip="delete template"
|
|
icon="trash-alt"
|
|
/>
|
|
</Authorize>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
{isExpanded && (
|
|
<tr className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
|
|
<td></td>
|
|
<td colSpan={2}>
|
|
<DetailsField label="Description" horizontal={true}>
|
|
<TemplateEditor
|
|
width={'auto'}
|
|
height={'auto'}
|
|
autoHeight={true}
|
|
value={template}
|
|
showLineNumbers={false}
|
|
monacoOptions={{
|
|
readOnly: true,
|
|
scrollBeyondLastLine: false,
|
|
}}
|
|
/>
|
|
</DetailsField>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</Fragment>
|
|
);
|
|
}
|