Files
grafana/public/app/features/alerting/unified/RuleEditor.tsx
Sonia Aguilar 9a252c763a Alerting: Add notification policies preview in alert creation (#68839)
* Add notification policies preview in alert rule form
Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>

* Refactor using new useGetPotentialInstances hook and apply some style changes

* Add notification policy detail modal

* Use backtesting api for simulating  potential alert instances

* Fix logic to travserse all the children from the root route

* Split notification preview by alert manager

* Add instance count to matching policy header and fix some styles

* Move some logic to a new hook useGetAlertManagersSourceNames to make the code more clean

* Fix some tests

* Add initial test for NotificationPreview

* Use button to preview potential instances

* Add link to contact point details

* Add route matching result details

* Show AlertManager image in the routing preview list

* Add tests setup, add single AM preview test

* Handle no matchers and no labels use case

* Update some style in collapse component and fix policy path in modal

* Update modal styles

* Update styles

* Update collapse header styling

* Normalize tree nodes should happen before findMatchingRoutes call

* Fix findMatchingRoutes and findMatchingAlertGroups methods after reabasing

* Move instances matching to the web worker code

* Fix config fetching for vanilla prometheus AMs

* Add tests

* Add tests mocks

* Fix tests after adding web worker

* Display matching labels for each matching alert instance

* Add minor css improvements

* Revert changes added in Collapse component as we don't use it anymore

* Move the route details modal to a separate file

* Move NotificationRoute and preview hook into separate files

* Fix Alertmanager preview tests

* Fix tests

* Move matcher code to a separate file, improve matcher mock

* Add permissions control for contact point edit view link

* Fix from and to for the temporal use of backtesting api

* Fix tests, add lazy loading of the preview component

Co-authored-by: Sonia Aguilar <soniaaguilarpeiron@gmail.com>

* Fix preview test

* Add onclick on the header div so it collapse and expands when clicking on it, and update styles to be consistent with the rest of tables

* Adapt the code to the new rule testing endpoint definition

* Fix tests

* small changes after reviewing the final code

* compute entire inherited tree before computing the routes map

* Throw error in case of not having receiver in routesByIdMap and add test for the use case of inheriting receiver from parent to check UI throws no errors

* Add list of labels in the policy route path that produces the policy matchers to match potential instances

* Use color determined by the key, in label tags when hovering matchers in the policy tree

* Remove labels in modal and handle empty string as receiver to inherit from parent as we do with undefined

* Revert "Add list of labels in the policy route path that produces the policy matchers to match potential instances"

This reverts commit ee73ae9cf9.

* fix inheritance for computeInheritedTree

* Fix message shown when preview has not been executed yet

* First round for adressing PR review comments

* Adress the rest of PR review commments

* Update texts and rename id prop in NotificaitonStep to alertUid

---------

Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2023-06-19 13:32:17 +02:00

85 lines
2.9 KiB
TypeScript

import React, { useCallback } from 'react';
import { useAsync } from 'react-use';
import { NavModelItem } from '@grafana/data';
import { withErrorBoundary } from '@grafana/ui';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { useDispatch } from 'app/types';
import { AlertWarning } from './AlertWarning';
import { CloneRuleEditor } from './CloneRuleEditor';
import { ExistingRuleEditor } from './ExistingRuleEditor';
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
import { AlertRuleForm } from './components/rule-editor/AlertRuleForm';
import { useURLSearchParams } from './hooks/useURLSearchParams';
import { fetchRulesSourceBuildInfoAction } from './state/actions';
import { useRulesAccess } from './utils/accessControlHooks';
import * as ruleId from './utils/rule-id';
type RuleEditorProps = GrafanaRouteComponentProps<{ id?: string }>;
const defaultPageNav: Partial<NavModelItem> = {
icon: 'bell',
id: 'alert-rule-view',
};
const getPageNav = (state: 'edit' | 'add') => {
if (state === 'edit') {
return { ...defaultPageNav, id: 'alert-rule-edit', text: 'Edit rule' };
} else if (state === 'add') {
return { ...defaultPageNav, id: 'alert-rule-add', text: 'Add rule' };
}
return undefined;
};
const RuleEditor = ({ match }: RuleEditorProps) => {
const dispatch = useDispatch();
const [searchParams] = useURLSearchParams();
const { id } = match.params;
const identifier = ruleId.tryParse(id, true);
const copyFromId = searchParams.get('copyFrom') ?? undefined;
const copyFromIdentifier = ruleId.tryParse(copyFromId);
const { loading = true } = useAsync(async () => {
if (identifier) {
await dispatch(fetchRulesSourceBuildInfoAction({ rulesSourceName: identifier.ruleSourceName }));
}
}, [dispatch]);
const { canCreateGrafanaRules, canCreateCloudRules, canEditRules } = useRulesAccess();
const getContent = useCallback(() => {
if (loading) {
return;
}
if (!identifier && !canCreateGrafanaRules && !canCreateCloudRules) {
return <AlertWarning title="Cannot create rules">Sorry! You are not allowed to create rules.</AlertWarning>;
}
if (identifier && !canEditRules(identifier.ruleSourceName)) {
return <AlertWarning title="Cannot edit rules">Sorry! You are not allowed to edit rules.</AlertWarning>;
}
if (identifier) {
return <ExistingRuleEditor key={id} identifier={identifier} id={id} />;
}
if (copyFromIdentifier) {
return <CloneRuleEditor sourceRuleId={copyFromIdentifier} />;
}
// new alert rule
return <AlertRuleForm />;
}, [canCreateCloudRules, canCreateGrafanaRules, canEditRules, copyFromIdentifier, id, identifier, loading]);
return (
<AlertingPageWrapper isLoading={loading} pageId="alert-list" pageNav={getPageNav(identifier ? 'edit' : 'add')}>
{getContent()}
</AlertingPageWrapper>
);
};
export default withErrorBoundary(RuleEditor, { style: 'page' });