diff --git a/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.test.tsx b/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.test.tsx index d3d5b197067..774f2ea7c79 100644 --- a/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.test.tsx +++ b/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.test.tsx @@ -1,5 +1,6 @@ import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { times } from 'lodash'; import React from 'react'; import { byLabelText, byRole, byTestId } from 'testing-library-selector'; @@ -25,6 +26,7 @@ const ui = { pending: byLabelText(/^Pending/), }, instanceRow: byTestId('row'), + showAllInstances: byTestId('show-all'), }; describe('RuleDetailsMatchingInstances', () => { @@ -116,6 +118,31 @@ describe('RuleDetailsMatchingInstances', () => { expect(ui.instanceRow.get()).toHaveTextContent(alertStateToReadable(state)); } ); + + it('should correctly filter instances', async () => { + const event = userEvent.setup(); + + const rule = mockCombinedRule({ + promRule: mockPromAlertingRule({ + alerts: times(100, () => mockPromAlert({ state: GrafanaAlertState.Normal })), + }), + instanceTotals: { + inactive: 100, + }, + }); + + render(); + + // should show all instances by default + expect(ui.showAllInstances.query()).not.toBeInTheDocument(); + + // filter by "error" state, should have no instances in that state + await event.click(ui.grafanaStateButton.error.get()); + + // click "show all" instances + await event.click(ui.showAllInstances.get()); + expect(ui.showAllInstances.query()).not.toBeInTheDocument(); + }); }); }); diff --git a/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.tsx b/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.tsx index c52170a4d6c..76add623041 100644 --- a/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.tsx +++ b/public/app/features/alerting/unified/components/rules/RuleDetailsMatchingInstances.tsx @@ -1,9 +1,10 @@ import { css, cx } from '@emotion/css'; import { countBy, sum } from 'lodash'; import React, { useMemo, useState } from 'react'; +import { useHistory } from 'react-router-dom'; import { GrafanaTheme2 } from '@grafana/data'; -import { LinkButton, useStyles2 } from '@grafana/ui'; +import { Button, useStyles2 } from '@grafana/ui'; import { MatcherFilter } from 'app/features/alerting/unified/components/alert-groups/MatcherFilter'; import { AlertInstanceStateFilter, @@ -34,25 +35,24 @@ interface ShowMoreStats { visibleItemsCount: number; } -function ShowMoreInstances(props: { ruleViewPageLink: string; stats: ShowMoreStats }) { +function ShowMoreInstances(props: { onClick: () => void; stats: ShowMoreStats }) { const styles = useStyles2(getStyles); - const { ruleViewPageLink, stats } = props; + const { onClick, stats } = props; return (
Showing {stats.visibleItemsCount} out of {stats.totalItemsCount} instances
- {ruleViewPageLink && ( - - Show all {stats.totalItemsCount} alert instances - - )} +
); } export function RuleDetailsMatchingInstances(props: Props): JSX.Element | null { + const history = useHistory(); const { rule: { promRule, namespace, instanceTotals }, itemsDisplayLimit = Number.POSITIVE_INFINITY, @@ -98,8 +98,13 @@ export function RuleDetailsMatchingInstances(props: Props): JSX.Element | null { const ruleViewPageLink = createViewLink(namespace.rulesSource, props.rule, location.pathname + location.search); const statsComponents = getComponentsFromStats(instanceTotals); + const resetFilter = () => setAlertState(undefined); + const navigateToDetailView = () => history.push(ruleViewPageLink); + + const onShowMoreInstances = enableFiltering ? resetFilter : navigateToDetailView; + const footerRow = hiddenInstancesCount ? ( - + ) : undefined; return (