AlertInstances.tsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { css } from '@emotion/css';
  2. import { noop } from 'lodash';
  3. import pluralize from 'pluralize';
  4. import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
  5. import { GrafanaTheme2, PanelProps } from '@grafana/data';
  6. import { Icon, useStyles2 } from '@grafana/ui';
  7. import { AlertInstancesTable } from 'app/features/alerting/unified/components/rules/AlertInstancesTable';
  8. import { sortAlerts } from 'app/features/alerting/unified/utils/misc';
  9. import { Alert } from 'app/types/unified-alerting';
  10. import { GroupMode, UnifiedAlertListOptions } from './types';
  11. import { filterAlerts } from './util';
  12. interface Props {
  13. alerts: Alert[];
  14. options: PanelProps<UnifiedAlertListOptions>['options'];
  15. }
  16. export const AlertInstances: FC<Props> = ({ alerts, options }) => {
  17. // when custom grouping is enabled, we will always uncollapse the list of alert instances
  18. const defaultShowInstances = options.groupMode === GroupMode.Custom ? true : options.showInstances;
  19. const [displayInstances, setDisplayInstances] = useState<boolean>(defaultShowInstances);
  20. const styles = useStyles2(getStyles);
  21. const toggleDisplayInstances = useCallback(() => {
  22. setDisplayInstances((display) => !display);
  23. }, []);
  24. const filteredAlerts = useMemo(
  25. (): Alert[] => filterAlerts(options, sortAlerts(options.sortOrder, alerts)) ?? [],
  26. [alerts, options]
  27. );
  28. const hiddenInstances = alerts.length - filteredAlerts.length;
  29. const uncollapsible = filteredAlerts.length > 0;
  30. const toggleShowInstances = uncollapsible ? toggleDisplayInstances : noop;
  31. useEffect(() => {
  32. if (filteredAlerts.length === 0) {
  33. setDisplayInstances(false);
  34. }
  35. }, [filteredAlerts]);
  36. return (
  37. <div>
  38. {options.groupMode === GroupMode.Default && (
  39. <div className={uncollapsible ? styles.clickable : ''} onClick={() => toggleShowInstances()}>
  40. {uncollapsible && <Icon name={displayInstances ? 'angle-down' : 'angle-right'} size={'md'} />}
  41. <span>{`${filteredAlerts.length} ${pluralize('instance', filteredAlerts.length)}`}</span>
  42. {hiddenInstances > 0 && <span>, {`${hiddenInstances} hidden by filters`}</span>}
  43. </div>
  44. )}
  45. {displayInstances && <AlertInstancesTable instances={filteredAlerts} />}
  46. </div>
  47. );
  48. };
  49. const getStyles = (_: GrafanaTheme2) => ({
  50. clickable: css`
  51. cursor: pointer;
  52. `,
  53. });