PanelAlertTabContent.tsx 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import { css } from '@emotion/css';
  2. import React, { FC } from 'react';
  3. import { GrafanaTheme2 } from '@grafana/data';
  4. import { selectors } from '@grafana/e2e-selectors';
  5. import { Alert, CustomScrollbar, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
  6. import { contextSrv } from 'app/core/services/context_srv';
  7. import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
  8. import { NewRuleFromPanelButton } from './components/panel-alerts-tab/NewRuleFromPanelButton';
  9. import { RulesTable } from './components/rules/RulesTable';
  10. import { usePanelCombinedRules } from './hooks/usePanelCombinedRules';
  11. import { getRulesPermissions } from './utils/access-control';
  12. interface Props {
  13. dashboard: DashboardModel;
  14. panel: PanelModel;
  15. }
  16. export const PanelAlertTabContent: FC<Props> = ({ dashboard, panel }) => {
  17. const styles = useStyles2(getStyles);
  18. const { errors, loading, rules } = usePanelCombinedRules({
  19. dashboard,
  20. panel,
  21. poll: true,
  22. });
  23. const permissions = getRulesPermissions('grafana');
  24. const canCreateRules = contextSrv.hasPermission(permissions.create);
  25. const alert = errors.length ? (
  26. <Alert title="Errors loading rules" severity="error">
  27. {errors.map((error, index) => (
  28. <div key={index}>Failed to load Grafana rules state: {error.message || 'Unknown error.'}</div>
  29. ))}
  30. </Alert>
  31. ) : null;
  32. if (loading && !rules.length) {
  33. return (
  34. <div className={styles.innerWrapper}>
  35. {alert}
  36. <LoadingPlaceholder text="Loading rules..." />
  37. </div>
  38. );
  39. }
  40. if (rules.length) {
  41. return (
  42. <CustomScrollbar autoHeightMin="100%">
  43. <div className={styles.innerWrapper}>
  44. {alert}
  45. <RulesTable rules={rules} />
  46. {!!dashboard.meta.canSave && canCreateRules && (
  47. <NewRuleFromPanelButton className={styles.newButton} panel={panel} dashboard={dashboard} />
  48. )}
  49. </div>
  50. </CustomScrollbar>
  51. );
  52. }
  53. return (
  54. <div aria-label={selectors.components.PanelAlertTabContent.content} className={styles.noRulesWrapper}>
  55. {alert}
  56. {!!dashboard.uid && (
  57. <>
  58. <p>There are no alert rules linked to this panel.</p>
  59. {!!dashboard.meta.canSave && canCreateRules && <NewRuleFromPanelButton panel={panel} dashboard={dashboard} />}
  60. </>
  61. )}
  62. {!dashboard.uid && !!dashboard.meta.canSave && (
  63. <Alert severity="info" title="Dashboard not saved">
  64. Dashboard must be saved before alerts can be added.
  65. </Alert>
  66. )}
  67. </div>
  68. );
  69. };
  70. const getStyles = (theme: GrafanaTheme2) => ({
  71. newButton: css`
  72. margin-top: ${theme.spacing(3)};
  73. `,
  74. innerWrapper: css`
  75. padding: ${theme.spacing(2)};
  76. `,
  77. noRulesWrapper: css`
  78. margin: ${theme.spacing(2)};
  79. background-color: ${theme.colors.background.secondary};
  80. padding: ${theme.spacing(3)};
  81. `,
  82. });