TemplatesTable.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import React, { FC, Fragment, useMemo, useState } from 'react';
  2. import { useDispatch } from 'react-redux';
  3. import { ConfirmModal, useStyles2 } from '@grafana/ui';
  4. import { contextSrv } from 'app/core/services/context_srv';
  5. import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types';
  6. import { Authorize } from '../../components/Authorize';
  7. import { deleteTemplateAction } from '../../state/actions';
  8. import { getAlertTableStyles } from '../../styles/table';
  9. import { getNotificationsPermissions } from '../../utils/access-control';
  10. import { makeAMLink } from '../../utils/misc';
  11. import { CollapseToggle } from '../CollapseToggle';
  12. import { DetailsField } from '../DetailsField';
  13. import { ActionIcon } from '../rules/ActionIcon';
  14. import { ReceiversSection } from './ReceiversSection';
  15. interface Props {
  16. config: AlertManagerCortexConfig;
  17. alertManagerName: string;
  18. }
  19. export const TemplatesTable: FC<Props> = ({ config, alertManagerName }) => {
  20. const dispatch = useDispatch();
  21. const [expandedTemplates, setExpandedTemplates] = useState<Record<string, boolean>>({});
  22. const tableStyles = useStyles2(getAlertTableStyles);
  23. const permissions = getNotificationsPermissions(alertManagerName);
  24. const templateRows = useMemo(() => Object.entries(config.template_files), [config]);
  25. const [templateToDelete, setTemplateToDelete] = useState<string>();
  26. const deleteTemplate = () => {
  27. if (templateToDelete) {
  28. dispatch(deleteTemplateAction(templateToDelete, alertManagerName));
  29. }
  30. setTemplateToDelete(undefined);
  31. };
  32. return (
  33. <ReceiversSection
  34. title="Message templates"
  35. description="Templates construct the messages that get sent to the contact points."
  36. addButtonLabel="New template"
  37. addButtonTo={makeAMLink('/alerting/notifications/templates/new', alertManagerName)}
  38. showButton={contextSrv.hasPermission(permissions.create)}
  39. >
  40. <table className={tableStyles.table} data-testid="templates-table">
  41. <colgroup>
  42. <col className={tableStyles.colExpand} />
  43. <col />
  44. <col />
  45. </colgroup>
  46. <thead>
  47. <tr>
  48. <th></th>
  49. <th>Template</th>
  50. <Authorize actions={[permissions.update, permissions.delete]}>
  51. <th>Actions</th>
  52. </Authorize>
  53. </tr>
  54. </thead>
  55. <tbody>
  56. {!templateRows.length && (
  57. <tr className={tableStyles.evenRow}>
  58. <td colSpan={3}>No templates defined.</td>
  59. </tr>
  60. )}
  61. {templateRows.map(([name, content], idx) => {
  62. const isExpanded = !!expandedTemplates[name];
  63. return (
  64. <Fragment key={name}>
  65. <tr key={name} className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
  66. <td>
  67. <CollapseToggle
  68. isCollapsed={!expandedTemplates[name]}
  69. onToggle={() => setExpandedTemplates({ ...expandedTemplates, [name]: !isExpanded })}
  70. />
  71. </td>
  72. <td>{name}</td>
  73. <Authorize actions={[permissions.update, permissions.delete]}>
  74. <td className={tableStyles.actionsCell}>
  75. <Authorize actions={[permissions.update]}>
  76. <ActionIcon
  77. to={makeAMLink(
  78. `/alerting/notifications/templates/${encodeURIComponent(name)}/edit`,
  79. alertManagerName
  80. )}
  81. tooltip="edit template"
  82. icon="pen"
  83. />
  84. </Authorize>
  85. <Authorize actions={[permissions.delete]}>
  86. <ActionIcon
  87. onClick={() => setTemplateToDelete(name)}
  88. tooltip="delete template"
  89. icon="trash-alt"
  90. />
  91. </Authorize>
  92. </td>
  93. </Authorize>
  94. </tr>
  95. {isExpanded && (
  96. <tr className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
  97. <td></td>
  98. <td colSpan={2}>
  99. <DetailsField label="Description" horizontal={true}>
  100. <pre>{content}</pre>
  101. </DetailsField>
  102. </td>
  103. </tr>
  104. )}
  105. </Fragment>
  106. );
  107. })}
  108. </tbody>
  109. </table>
  110. {!!templateToDelete && (
  111. <ConfirmModal
  112. isOpen={true}
  113. title="Delete template"
  114. body={`Are you sure you want to delete template "${templateToDelete}"?`}
  115. confirmText="Yes, delete"
  116. onConfirm={deleteTemplate}
  117. onDismiss={() => setTemplateToDelete(undefined)}
  118. />
  119. )}
  120. </ReceiversSection>
  121. );
  122. };