Alerting: Load alerting state view based on prom primary feature toggle (#95045)
This commit is contained in:
@@ -71,7 +71,7 @@ const STATE_TITLES: Record<PromAlertingRuleState, string> = {
|
||||
const RulesByState = ({ state, rules }: { state: PromAlertingRuleState; rules: CombinedRule[] }) => {
|
||||
const { page, pageItems, numberOfPages, onPageChange } = usePagination(rules, 1, DEFAULT_PER_PAGE_PAGINATION);
|
||||
|
||||
const isFiringState = state !== PromAlertingRuleState.Firing;
|
||||
const isNotFiringState = state !== PromAlertingRuleState.Firing;
|
||||
const hasRulesMatchingState = rules.length > 0;
|
||||
|
||||
return (
|
||||
@@ -82,7 +82,7 @@ const RulesByState = ({ state, rules }: { state: PromAlertingRuleState; rules: C
|
||||
<Counter value={rules.length} />
|
||||
</Stack>
|
||||
}
|
||||
collapsed={isFiringState || hasRulesMatchingState}
|
||||
collapsed={isNotFiringState || hasRulesMatchingState}
|
||||
pagination={
|
||||
<Pagination
|
||||
currentPage={page}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { render, userEvent, screen } from 'test/test-utils';
|
||||
import { render, userEvent, screen, waitFor } from 'test/test-utils';
|
||||
import { byRole } from 'testing-library-selector';
|
||||
|
||||
import { setPluginLinksHook } from '@grafana/runtime';
|
||||
@@ -35,6 +35,12 @@ const user = userEvent.setup();
|
||||
setupMswServer();
|
||||
|
||||
describe('RulesTable RBAC', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('Grafana rules action buttons', () => {
|
||||
const grafanaRule = getGrafanaRule({ name: 'Grafana' });
|
||||
|
||||
@@ -45,7 +51,7 @@ describe('RulesTable RBAC', () => {
|
||||
|
||||
render(<RulesTable rules={[grafanaRule]} />);
|
||||
|
||||
expect(ui.actionButtons.edit.query()).not.toBeInTheDocument();
|
||||
await waitFor(() => expect(ui.actionButtons.edit.query()).not.toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('Should not render Delete button for users without the delete permission', async () => {
|
||||
@@ -55,18 +61,18 @@ describe('RulesTable RBAC', () => {
|
||||
|
||||
render(<RulesTable rules={[grafanaRule]} />);
|
||||
|
||||
await user.click(ui.actionButtons.more.get());
|
||||
await user.click(await ui.actionButtons.more.find());
|
||||
|
||||
expect(ui.moreActionItems.delete.query()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render Edit button for users with the update permission', () => {
|
||||
it('Should render Edit button for users with the update permission', async () => {
|
||||
mocks.useAlertRuleAbility.mockImplementation((_rule, action) => {
|
||||
return action === AlertRuleAction.Update ? [true, true] : [false, false];
|
||||
});
|
||||
render(<RulesTable rules={[grafanaRule]} />);
|
||||
|
||||
expect(ui.actionButtons.edit.get()).toBeInTheDocument();
|
||||
expect(await ui.actionButtons.edit.find()).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render Delete button for users with the delete permission', async () => {
|
||||
@@ -76,8 +82,7 @@ describe('RulesTable RBAC', () => {
|
||||
|
||||
render(<RulesTable rules={[grafanaRule]} />);
|
||||
|
||||
expect(ui.actionButtons.more.get()).toBeInTheDocument();
|
||||
await user.click(ui.actionButtons.more.get());
|
||||
await user.click(await ui.actionButtons.more.find());
|
||||
expect(ui.moreActionItems.delete.get()).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -129,14 +134,14 @@ describe('RulesTable RBAC', () => {
|
||||
describe('Cloud rules action buttons', () => {
|
||||
const cloudRule = getCloudRule({ name: 'Cloud' });
|
||||
|
||||
it('Should not render Edit button for users without the update permission', () => {
|
||||
it('Should not render Edit button for users without the update permission', async () => {
|
||||
mocks.useAlertRuleAbility.mockImplementation((_rule, action) => {
|
||||
return action === AlertRuleAction.Update ? [true, false] : [true, true];
|
||||
});
|
||||
|
||||
render(<RulesTable rules={[cloudRule]} />);
|
||||
|
||||
expect(ui.actionButtons.edit.query()).not.toBeInTheDocument();
|
||||
await waitFor(() => expect(ui.actionButtons.edit.query()).not.toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('Should not render Delete button for users without the delete permission', async () => {
|
||||
@@ -146,18 +151,18 @@ describe('RulesTable RBAC', () => {
|
||||
|
||||
render(<RulesTable rules={[cloudRule]} />);
|
||||
|
||||
await user.click(ui.actionButtons.more.get());
|
||||
await user.click(await ui.actionButtons.more.find());
|
||||
expect(ui.moreActionItems.delete.query()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render Edit button for users with the update permission', () => {
|
||||
it('Should render Edit button for users with the update permission', async () => {
|
||||
mocks.useAlertRuleAbility.mockImplementation((_rule, action) => {
|
||||
return action === AlertRuleAction.Update ? [true, true] : [false, false];
|
||||
});
|
||||
|
||||
render(<RulesTable rules={[cloudRule]} />);
|
||||
|
||||
expect(ui.actionButtons.edit.get()).toBeInTheDocument();
|
||||
expect(await ui.actionButtons.edit.find()).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render Delete button for users with the delete permission', async () => {
|
||||
@@ -167,8 +172,8 @@ describe('RulesTable RBAC', () => {
|
||||
|
||||
render(<RulesTable rules={[cloudRule]} />);
|
||||
|
||||
await user.click(ui.actionButtons.more.get());
|
||||
expect(ui.moreActionItems.delete.get()).toBeInTheDocument();
|
||||
await user.click(await ui.actionButtons.more.find());
|
||||
expect(await ui.moreActionItems.delete.find()).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useEffect, useMemo } from 'react';
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Pagination, Tooltip, useStyles2 } from '@grafana/ui';
|
||||
import { LoadingPlaceholder, Pagination, Tooltip, useStyles2 } from '@grafana/ui';
|
||||
import { CombinedRule } from 'app/types/unified-alerting';
|
||||
|
||||
import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants';
|
||||
@@ -63,9 +63,18 @@ export const RulesTable = ({
|
||||
|
||||
const { pageItems, page, numberOfPages, onPageChange } = usePagination(rules, 1, DEFAULT_PER_PAGE_PAGINATION);
|
||||
|
||||
const { result: rulesWithRulerDefinitions, status: rulerRulesLoadingStatus } = useLazyLoadRulerRules(pageItems);
|
||||
const [lazyLoadRules, { result: rulesWithRulerDefinitions, status: rulerRulesLoadingStatus }] =
|
||||
useLazyLoadRulerRules(pageItems);
|
||||
const isLoadingRulerGroup = useMemo(
|
||||
() => !rulerRulesLoadingStatus || rulerRulesLoadingStatus === 'loading',
|
||||
[rulerRulesLoadingStatus]
|
||||
);
|
||||
|
||||
const isLoadingRulerGroup = rulerRulesLoadingStatus === 'loading';
|
||||
useEffect(() => {
|
||||
if (pageItems.length > 0) {
|
||||
lazyLoadRules.execute();
|
||||
}
|
||||
}, [lazyLoadRules, pageItems, rulerRulesLoadingStatus]);
|
||||
|
||||
const items = useMemo((): RuleTableItemProps[] => {
|
||||
return rulesWithRulerDefinitions.map((rule, ruleIdx) => {
|
||||
@@ -82,6 +91,10 @@ export const RulesTable = ({
|
||||
return <div className={cx(wrapperClass, styles.emptyMessage)}>{emptyMessage}</div>;
|
||||
}
|
||||
|
||||
if (isLoadingRulerGroup) {
|
||||
return <LoadingPlaceholder text="Loading..." />;
|
||||
}
|
||||
|
||||
const TableComponent = showGuidelines ? DynamicTableWithGuidelines : DynamicTable;
|
||||
|
||||
return (
|
||||
@@ -114,8 +127,11 @@ function useLazyLoadRulerRules(rules: CombinedRule[]) {
|
||||
const [fetchRulerRuleGroup] = useLazyGetRuleGroupForNamespaceQuery();
|
||||
const [fetchDsFeatures] = useLazyDiscoverDsFeaturesQuery();
|
||||
|
||||
const [actions, state] = useAsync(async () => {
|
||||
const result = Promise.all(
|
||||
return useAsync(async () => {
|
||||
if (!prometheusRulesPrimary) {
|
||||
return rules;
|
||||
}
|
||||
return Promise.all(
|
||||
rules.map(async (rule) => {
|
||||
const dsFeatures = await fetchDsFeatures(
|
||||
{ rulesSourceName: getRulesSourceName(rule.namespace.rulesSource) },
|
||||
@@ -140,20 +156,7 @@ function useLazyLoadRulerRules(rules: CombinedRule[]) {
|
||||
return rule;
|
||||
})
|
||||
);
|
||||
return result;
|
||||
}, rules);
|
||||
|
||||
useEffect(() => {
|
||||
if (prometheusRulesPrimary) {
|
||||
actions.execute();
|
||||
} else {
|
||||
// We need to reset the actions to update the rules if they changed
|
||||
// Otherwise useAsync acts like a cache and always return the first rules passed to it
|
||||
actions.reset();
|
||||
}
|
||||
}, [rules, actions]);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
export const getStyles = (theme: GrafanaTheme2) => ({
|
||||
|
||||
Reference in New Issue
Block a user