diff --git a/public/app/features/alerting/unified/NotificationPoliciesPage.tsx b/public/app/features/alerting/unified/NotificationPoliciesPage.tsx index e1a7b724abc..d48a41850db 100644 --- a/public/app/features/alerting/unified/NotificationPoliciesPage.tsx +++ b/public/app/features/alerting/unified/NotificationPoliciesPage.tsx @@ -38,13 +38,14 @@ import { withPageErrorBoundary } from './withPageErrorBoundary'; import { AlertmanagerGroup, Receiver, Route, ROUTES_META_SYMBOL } from '../../../plugins/datasource/alertmanager/types'; import { stringifyErrorLike } from './utils/misc'; import { + useCreateRoutingTree, useDeleteRoutingTree, useListNotificationPolicyRoutes, useRootRouteSearch, } from './components/notification-policies/useNotificationPolicyRoute'; import { useURLSearchParams } from './hooks/useURLSearchParams'; import { usePagination } from './hooks/usePagination'; -import { useDeleteRoutingTreeModal } from './components/notification-policies/components/Modals'; +import { useCreateRoutingTreeModal, useDeleteRoutingTreeModal } from './components/notification-policies/components/Modals'; import { ALL_ROUTING_TREES, useExportRoutingTree } from './components/notification-policies/useExportRoutingTree'; import { K8sAnnotations, ROOT_ROUTE_NAME } from './utils/k8s/constants'; import ConditionalWrap from './components/ConditionalWrap'; @@ -52,10 +53,11 @@ import { ProvisioningBadge } from './components/Provisioning'; import { getAnnotation } from './utils/k8s/utils'; import { Spacer } from './components/Spacer'; import MoreButton from './components/MoreButton'; -import { useContactPointsWithStatus } from './components/contact-points/useContactPoints'; +import { useGrafanaContactPoints } from './components/contact-points/useContactPoints'; import { useAlertGroupsModal } from './components/notification-policies/Modals'; import { normalizeMatchers } from './utils/matchers'; import { RoutingTreeFilter } from './components/notification-policies/components/RoutingTreeFilter'; +import {config} from '@grafana/runtime'; enum ActiveTab { NotificationPolicies = 'notification_policies', @@ -126,7 +128,9 @@ const NotificationPoliciesTabs = () => { const PolicyTreeTab = () => { const { isGrafanaAlertmanager } = useAlertmanager(); - if (!isGrafanaAlertmanager) { + const useMultiplePoliciesView = config.featureToggles.alertingMultiplePolicies; + + if (!isGrafanaAlertmanager || !useMultiplePoliciesView) { return ; } @@ -138,7 +142,6 @@ const PolicyTreeTab = () => { const DEFAULT_PAGE_SIZE = 10; const PolicyTreeTabContents = () => { - const { selectedAlertmanager } = useAlertmanager(); const [queryParams] = useURLSearchParams(); const [[createPoliciesSupported, createPoliciesAllowed], [exportPoliciesSupported, exportPoliciesAllowed]] = @@ -151,18 +154,21 @@ const PolicyTreeTabContents = () => { currentData: allPolicies, isLoading, error: fetchPoliciesError, - } = useListNotificationPolicyRoutes({ alertmanager: selectedAlertmanager ?? '' }); + } = useListNotificationPolicyRoutes(); const [ExportDrawer, showExportDrawer] = useExportRoutingTree(); + + const [createTrigger] = useCreateRoutingTree(); + const [CreateModal, showCreateModal] = useCreateRoutingTreeModal(createTrigger.execute); + const search = queryParams.get('search'); const [contactPointsSupported, canSeeContactPoints] = useAlertmanagerAbility(AlertmanagerAction.ViewContactPoint); const shouldFetchContactPoints = contactPointsSupported && canSeeContactPoints; - const { contactPoints: receivers } = useContactPointsWithStatus({ - alertmanager: selectedAlertmanager ?? '', - fetchPolicies: false, - fetchStatuses: true, + const { contactPoints: receivers } = useGrafanaContactPoints({ skip: !shouldFetchContactPoints, + fetchStatuses: false, + fetchPolicies: false, }); if (isLoading) { @@ -177,15 +183,15 @@ const PolicyTreeTabContents = () => { {createPoliciesSupported && ( - showCreateModal()} > Create policy - + )} {exportPoliciesSupported && ( + + + } + /> + + ); + }, [route, error, handleSubmit, handleDismiss, isLoading, showModal, styles.input]); + + return [modalElement, handleShow, handleDismiss] as const; +}; + interface ErrorModalProps extends Pick { error: unknown; } diff --git a/public/app/features/alerting/unified/components/notification-policies/useNotificationPolicyRoute.ts b/public/app/features/alerting/unified/components/notification-policies/useNotificationPolicyRoute.ts index f6627088fb8..43b9ce970f8 100644 --- a/public/app/features/alerting/unified/components/notification-policies/useNotificationPolicyRoute.ts +++ b/public/app/features/alerting/unified/components/notification-policies/useNotificationPolicyRoute.ts @@ -35,6 +35,7 @@ import uFuzzy from '@leeoniya/ufuzzy'; import { useMemo } from 'react'; const { + useCreateNamespacedRoutingTreeMutation, useDeleteNamespacedRoutingTreeMutation, useListNamespacedRoutingTreeQuery, useReplaceNamespacedRoutingTreeMutation, @@ -83,13 +84,11 @@ export const useNotificationPolicyRoute = ( return k8sApiSupported ? k8sRouteQuery : amConfigQuery; }; -export const useListNotificationPolicyRoutes = ({ alertmanager }: BaseAlertmanagerArgs, { skip }: Skippable = {}) => { - const k8sApiSupported = shouldUseK8sApi(alertmanager); - +export const useListNotificationPolicyRoutes = ({ skip }: Skippable = {}) => { return useListNamespacedRoutingTreeQuery( { namespace: getAPINamespace() }, { - skip: skip || !k8sApiSupported, + skip: skip, selectFromResult: (result) => { return { ...result, @@ -267,6 +266,48 @@ export function useDeleteRoutingTree() { }); } +export function useCreateRoutingTree() { + const [createNamespacedRoutingTree] = useCreateNamespacedRoutingTreeMutation(); + + return useAsync(async (partialFormRoute: Partial) => { + const namespace = getAPINamespace(); + + const { + name, + overrideGrouping, + groupBy, + overrideTimings, + groupWaitValue, + groupIntervalValue, + repeatIntervalValue, + receiver, + } = partialFormRoute; + + // This does not "inherit" from any existing route, as this is a new routing tree. If not set, it will use the system + // defaults. Currently supported by group_by, group_wait, group_interval, and repeat_interval + const USE_DEFAULTS = undefined; + + const newRoute: Route = { + name: name, + group_by: overrideGrouping ? groupBy : USE_DEFAULTS, + group_wait: overrideTimings && groupWaitValue ? groupWaitValue : USE_DEFAULTS, + group_interval: overrideTimings && groupIntervalValue ? groupIntervalValue : USE_DEFAULTS, + repeat_interval: overrideTimings && repeatIntervalValue ? repeatIntervalValue : USE_DEFAULTS, + receiver: receiver, + }; + + // defaults(newRoute, TIMING_OPTIONS_DEFAULTS) + + // Create the K8s route object + const routeObject = createKubernetesRoutingTreeSpec(newRoute); + + return createNamespacedRoutingTree({ + namespace, + comGithubGrafanaGrafanaPkgApisAlertingNotificationsV0Alpha1RoutingTree: cleanKubernetesRouteIDs(routeObject), + }).unwrap(); + }); +} + const fuzzyFinder = new uFuzzy({ intraMode: 1, intraIns: 1,