[v10.0.x] Alerting: Fix "show all instances" (#67837)

Alerting: Fix "show all instances" (#67833)

(cherry picked from commit dafd202bb2)

Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
This commit is contained in:
Grot (@grafanabot)
2023-06-04 02:14:48 +00:00
committed by GitHub
co-authored by Gilles De Mey
parent 600ff36f62
commit c41eb07a63
2 changed files with 41 additions and 9 deletions
@@ -1,5 +1,6 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
import { times } from 'lodash';
import React from 'react'; import React from 'react';
import { byLabelText, byRole, byTestId } from 'testing-library-selector'; import { byLabelText, byRole, byTestId } from 'testing-library-selector';
@@ -25,6 +26,7 @@ const ui = {
pending: byLabelText(/^Pending/), pending: byLabelText(/^Pending/),
}, },
instanceRow: byTestId('row'), instanceRow: byTestId('row'),
showAllInstances: byTestId('show-all'),
}; };
describe('RuleDetailsMatchingInstances', () => { describe('RuleDetailsMatchingInstances', () => {
@@ -116,6 +118,31 @@ describe('RuleDetailsMatchingInstances', () => {
expect(ui.instanceRow.get()).toHaveTextContent(alertStateToReadable(state)); 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(<RuleDetailsMatchingInstances rule={rule} enableFiltering pagination={{ itemsPerPage: 10 }} />);
// 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();
});
}); });
}); });
@@ -1,9 +1,10 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { countBy, sum } from 'lodash'; import { countBy, sum } from 'lodash';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { GrafanaTheme2 } from '@grafana/data'; 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 { MatcherFilter } from 'app/features/alerting/unified/components/alert-groups/MatcherFilter';
import { import {
AlertInstanceStateFilter, AlertInstanceStateFilter,
@@ -34,25 +35,24 @@ interface ShowMoreStats {
visibleItemsCount: number; visibleItemsCount: number;
} }
function ShowMoreInstances(props: { ruleViewPageLink: string; stats: ShowMoreStats }) { function ShowMoreInstances(props: { onClick: () => void; stats: ShowMoreStats }) {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const { ruleViewPageLink, stats } = props; const { onClick, stats } = props;
return ( return (
<div className={styles.footerRow}> <div className={styles.footerRow}>
<div> <div>
Showing {stats.visibleItemsCount} out of {stats.totalItemsCount} instances Showing {stats.visibleItemsCount} out of {stats.totalItemsCount} instances
</div> </div>
{ruleViewPageLink && ( <Button size="sm" variant="secondary" data-testid="show-all" onClick={onClick}>
<LinkButton href={ruleViewPageLink} size="sm" variant="secondary"> Show all {stats.totalItemsCount} alert instances
Show all {stats.totalItemsCount} alert instances </Button>
</LinkButton>
)}
</div> </div>
); );
} }
export function RuleDetailsMatchingInstances(props: Props): JSX.Element | null { export function RuleDetailsMatchingInstances(props: Props): JSX.Element | null {
const history = useHistory();
const { const {
rule: { promRule, namespace, instanceTotals }, rule: { promRule, namespace, instanceTotals },
itemsDisplayLimit = Number.POSITIVE_INFINITY, 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 ruleViewPageLink = createViewLink(namespace.rulesSource, props.rule, location.pathname + location.search);
const statsComponents = getComponentsFromStats(instanceTotals); const statsComponents = getComponentsFromStats(instanceTotals);
const resetFilter = () => setAlertState(undefined);
const navigateToDetailView = () => history.push(ruleViewPageLink);
const onShowMoreInstances = enableFiltering ? resetFilter : navigateToDetailView;
const footerRow = hiddenInstancesCount ? ( const footerRow = hiddenInstancesCount ? (
<ShowMoreInstances stats={stats} ruleViewPageLink={ruleViewPageLink} /> <ShowMoreInstances stats={stats} onClick={onShowMoreInstances} />
) : undefined; ) : undefined;
return ( return (