RuleState.tsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { css } from '@emotion/css';
  2. import React, { FC, useMemo } from 'react';
  3. import { GrafanaTheme2, intervalToAbbreviatedDurationString } from '@grafana/data';
  4. import { HorizontalGroup, Spinner, useStyles2 } from '@grafana/ui';
  5. import { CombinedRule } from 'app/types/unified-alerting';
  6. import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
  7. import { isAlertingRule, isRecordingRule, getFirstActiveAt } from '../../utils/rules';
  8. import { AlertStateTag } from './AlertStateTag';
  9. interface Props {
  10. rule: CombinedRule;
  11. isDeleting: boolean;
  12. isCreating: boolean;
  13. }
  14. export const RuleState: FC<Props> = ({ rule, isDeleting, isCreating }) => {
  15. const style = useStyles2(getStyle);
  16. const { promRule } = rule;
  17. // return how long the rule has been in it's firing state, if any
  18. const forTime = useMemo(() => {
  19. if (
  20. promRule &&
  21. isAlertingRule(promRule) &&
  22. promRule.alerts?.length &&
  23. promRule.state !== PromAlertingRuleState.Inactive
  24. ) {
  25. // find earliest alert
  26. const firstActiveAt = getFirstActiveAt(promRule);
  27. // calculate time elapsed from earliest alert
  28. if (firstActiveAt) {
  29. return (
  30. <span title={String(firstActiveAt)} className={style.for}>
  31. for{' '}
  32. {intervalToAbbreviatedDurationString(
  33. {
  34. start: firstActiveAt,
  35. end: new Date(),
  36. },
  37. false
  38. )}
  39. </span>
  40. );
  41. }
  42. }
  43. return null;
  44. }, [promRule, style]);
  45. if (isDeleting) {
  46. return (
  47. <HorizontalGroup align="flex-start">
  48. <Spinner />
  49. deleting
  50. </HorizontalGroup>
  51. );
  52. } else if (isCreating) {
  53. return (
  54. <HorizontalGroup align="flex-start">
  55. {' '}
  56. <Spinner />
  57. creating
  58. </HorizontalGroup>
  59. );
  60. } else if (promRule && isAlertingRule(promRule)) {
  61. return (
  62. <HorizontalGroup align="flex-start">
  63. <AlertStateTag state={promRule.state} />
  64. {forTime}
  65. </HorizontalGroup>
  66. );
  67. } else if (promRule && isRecordingRule(promRule)) {
  68. return <>Recording rule</>;
  69. }
  70. return <>n/a</>;
  71. };
  72. const getStyle = (theme: GrafanaTheme2) => ({
  73. for: css`
  74. font-size: ${theme.typography.bodySmall.fontSize};
  75. color: ${theme.colors.text.secondary};
  76. white-space: nowrap;
  77. padding-top: 2px;
  78. `,
  79. });