diff --git a/.betterer.results b/.betterer.results index 2251c15fce8..7adb2e1459c 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1406,12 +1406,9 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings. Wrap text with ", "13"], [0, 0, 0, "No untranslated strings. Wrap text with ", "14"] ], - "public/app/features/alerting/unified/NotificationPolicies.tsx:5381": [ + "public/app/features/alerting/unified/NotificationPoliciesPage.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"] + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"] ], "public/app/features/alerting/unified/PanelAlertTabContent.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], @@ -1711,10 +1708,8 @@ exports[`better eslint`] = { ], "public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "1"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "2"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"] + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"] ], "public/app/features/alerting/unified/components/notification-policies/ContactPointSelector.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], @@ -1760,18 +1755,18 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "18"] ], "public/app/features/alerting/unified/components/notification-policies/Filters.tsx:5381": [ - [0, 0, 0, "No untranslated strings. Wrap text with ", "0"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "1"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "2"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "5"] + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"] ], "public/app/features/alerting/unified/components/notification-policies/Modals.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"] ], + "public/app/features/alerting/unified/components/notification-policies/NotificationPoliciesList.tsx:5381": [ + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"] + ], "public/app/features/alerting/unified/components/notification-policies/Policy.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], @@ -2579,9 +2574,7 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "No untranslated strings. Wrap text with ", "1"], [0, 0, 0, "No untranslated strings. Wrap text with ", "2"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "3"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "5"] + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"] ], "public/app/features/alerting/unified/components/silences/SilencesTable.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], diff --git a/public/app/features/alerting/routes.tsx b/public/app/features/alerting/routes.tsx index 55f0708b674..839d5db06c4 100644 --- a/public/app/features/alerting/routes.tsx +++ b/public/app/features/alerting/routes.tsx @@ -47,7 +47,10 @@ export function getAlertingRoutes(cfg = config): RouteDescriptor[] { ...PERMISSIONS_TIME_INTERVALS_MODIFY, ]), component: importAlertingComponent( - () => import(/* webpackChunkName: "AlertAmRoutes" */ 'app/features/alerting/unified/NotificationPolicies') + () => + import( + /* webpackChunkName: "NotificationPoliciesPage" */ 'app/features/alerting/unified/NotificationPoliciesPage' + ) ), }, { diff --git a/public/app/features/alerting/unified/NotificationPolicies.test.tsx b/public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx similarity index 99% rename from public/app/features/alerting/unified/NotificationPolicies.test.tsx rename to public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx index b034266ac1f..2bbb102b58b 100644 --- a/public/app/features/alerting/unified/NotificationPolicies.test.tsx +++ b/public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx @@ -32,7 +32,8 @@ import { } from 'app/plugins/datasource/alertmanager/types'; import { AccessControlAction } from 'app/types'; -import NotificationPolicies, { findRoutesMatchingFilters } from './NotificationPolicies'; +import NotificationPolicies from './NotificationPoliciesPage'; +import { findRoutesMatchingFilters } from './components/notification-policies/NotificationPoliciesList'; import { grantUserPermissions, mockDataSource, diff --git a/public/app/features/alerting/unified/NotificationPoliciesPage.tsx b/public/app/features/alerting/unified/NotificationPoliciesPage.tsx new file mode 100644 index 00000000000..6b4d1b9b5e7 --- /dev/null +++ b/public/app/features/alerting/unified/NotificationPoliciesPage.tsx @@ -0,0 +1,113 @@ +import { css } from '@emotion/css'; +import { useState } from 'react'; + +import { GrafanaTheme2, UrlQueryMap } from '@grafana/data'; +import { Tab, TabContent, TabsBar, useStyles2, withErrorBoundary } from '@grafana/ui'; +import { useQueryParams } from 'app/core/hooks/useQueryParams'; +import { useMuteTimings } from 'app/features/alerting/unified/components/mute-timings/useMuteTimings'; +import { NotificationPoliciesList } from 'app/features/alerting/unified/components/notification-policies/NotificationPoliciesList'; +import { AlertmanagerAction, useAlertmanagerAbility } from 'app/features/alerting/unified/hooks/useAbilities'; + +import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper'; +import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning'; +import { MuteTimingsTable } from './components/mute-timings/MuteTimingsTable'; +import { useAlertmanager } from './state/AlertmanagerContext'; + +enum ActiveTab { + NotificationPolicies = 'notification_policies', + MuteTimings = 'mute_timings', +} + +const NotificationPoliciesTabs = () => { + const styles = useStyles2(getStyles); + + // Alertmanager logic and data hooks + const { selectedAlertmanager = '' } = useAlertmanager(); + const [policiesSupported, canSeePoliciesTab] = useAlertmanagerAbility(AlertmanagerAction.ViewNotificationPolicyTree); + const [timingsSupported, canSeeTimingsTab] = useAlertmanagerAbility(AlertmanagerAction.ViewMuteTiming); + const availableTabs = [ + canSeePoliciesTab && ActiveTab.NotificationPolicies, + canSeeTimingsTab && ActiveTab.MuteTimings, + ].filter((tab) => !!tab); + const { data: muteTimings = [] } = useMuteTimings({ + alertmanager: selectedAlertmanager, + skip: !canSeeTimingsTab, + }); + + // Tab state management + const [queryParams, setQueryParams] = useQueryParams(); + const { tab } = getActiveTabFromUrl(queryParams, availableTabs[0]); + const [activeTab, setActiveTab] = useState(tab); + + const muteTimingsTabActive = activeTab === ActiveTab.MuteTimings; + const policyTreeTabActive = activeTab === ActiveTab.NotificationPolicies; + + const numberOfMuteTimings = muteTimings.length; + + return ( + <> + + + {policiesSupported && canSeePoliciesTab && ( + { + setActiveTab(ActiveTab.NotificationPolicies); + setQueryParams({ tab: ActiveTab.NotificationPolicies }); + }} + /> + )} + {timingsSupported && canSeeTimingsTab && ( + { + setActiveTab(ActiveTab.MuteTimings); + setQueryParams({ tab: ActiveTab.MuteTimings }); + }} + /> + )} + + + {policyTreeTabActive && } + {muteTimingsTabActive && } + + + ); +}; + +const getStyles = (theme: GrafanaTheme2) => ({ + tabContent: css({ + marginTop: theme.spacing(2), + }), +}); + +interface QueryParamValues { + tab: ActiveTab; +} + +function getActiveTabFromUrl(queryParams: UrlQueryMap, defaultTab: ActiveTab): QueryParamValues { + let tab = defaultTab; + + if (queryParams.tab === ActiveTab.NotificationPolicies) { + tab = ActiveTab.NotificationPolicies; + } + + if (queryParams.tab === ActiveTab.MuteTimings) { + tab = ActiveTab.MuteTimings; + } + + return { + tab, + }; +} + +const NotificationPoliciesPage = () => ( + + + +); + +export default withErrorBoundary(NotificationPoliciesPage, { style: 'page' }); diff --git a/public/app/features/alerting/unified/__snapshots__/NotificationPolicies.test.tsx.snap b/public/app/features/alerting/unified/__snapshots__/NotificationPoliciesPage.test.tsx.snap similarity index 100% rename from public/app/features/alerting/unified/__snapshots__/NotificationPolicies.test.tsx.snap rename to public/app/features/alerting/unified/__snapshots__/NotificationPoliciesPage.test.tsx.snap diff --git a/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx b/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx index eb63d6cbec6..8be77b512d8 100644 --- a/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx +++ b/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx @@ -19,7 +19,7 @@ import { MuteTimingsTable } from './MuteTimingsTable'; const renderWithProvider = (alertManagerSource?: string) => { return render( - + ); }; diff --git a/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.tsx b/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.tsx index 3047edf92ac..0443ab96607 100644 --- a/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.tsx +++ b/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.tsx @@ -9,6 +9,7 @@ import { ALL_MUTE_TIMINGS, useExportMuteTimingsDrawer, } from 'app/features/alerting/unified/components/mute-timings/useExportMuteTimingsDrawer'; +import { useAlertmanager } from 'app/features/alerting/unified/state/AlertmanagerContext'; import { PROVENANCE_ANNOTATION } from 'app/features/alerting/unified/utils/k8s/constants'; import { Authorize } from '../../components/Authorize'; @@ -22,21 +23,18 @@ import { Spacer } from '../Spacer'; import { MuteTiming, useMuteTimings } from './useMuteTimings'; import { renderTimeIntervals } from './util'; -interface MuteTimingsTableProps { - alertManagerSourceName: string; - hideActions?: boolean; -} - type TableItem = { id: string; data: MuteTiming; }; -export const MuteTimingsTable = ({ alertManagerSourceName, hideActions }: MuteTimingsTableProps) => { +export const MuteTimingsTable = () => { + const { selectedAlertmanager: alertManagerSourceName = '', hasConfigurationAPI } = useAlertmanager(); + const hideActions = !hasConfigurationAPI; const styles = useStyles2(getStyles); const [ExportAllDrawer, showExportAllDrawer] = useExportMuteTimingsDrawer(); - const { data, isLoading, error } = useMuteTimings({ alertmanager: alertManagerSourceName }); + const { data, isLoading, error } = useMuteTimings({ alertmanager: alertManagerSourceName ?? '' }); const items = useMemo((): TableItem[] => { const muteTimings = data || []; @@ -73,10 +71,10 @@ export const MuteTimingsTable = ({ alertManagerSourceName, hideActions }: MuteTi return (
- + Enter specific time intervals when not to send notifications or freeze notifications for recurring periods of time. - + {!hideActions && items.length > 0 && ( @@ -86,7 +84,7 @@ export const MuteTimingsTable = ({ alertManagerSourceName, hideActions }: MuteTi variant="primary" href={makeAMLink('alerting/routes/mute-timing/new', alertManagerSourceName)} > - Add mute timing + Add mute timing )} diff --git a/public/app/features/alerting/unified/components/notification-policies/Filters.tsx b/public/app/features/alerting/unified/components/notification-policies/Filters.tsx index 5fb6c57459e..dfb6b3be323 100644 --- a/public/app/features/alerting/unified/components/notification-policies/Filters.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/Filters.tsx @@ -3,7 +3,9 @@ import { debounce, isEqual } from 'lodash'; import { useCallback, useEffect, useRef } from 'react'; import { Button, Field, Icon, Input, Label, Stack, Text, Tooltip, useStyles2 } from '@grafana/ui'; +import { Trans } from 'app/core/internationalization'; import { ContactPointSelector } from 'app/features/alerting/unified/components/notification-policies/ContactPointSelector'; +import { AlertmanagerAction, useAlertmanagerAbility } from 'app/features/alerting/unified/hooks/useAbilities'; import { ObjectMatcher, RouteWithID } from 'app/plugins/datasource/alertmanager/types'; import { useURLSearchParams } from '../../hooks/useURLSearchParams'; @@ -25,6 +27,7 @@ const NotificationPoliciesFilter = ({ onChangeMatchers, matchingCount, }: NotificationPoliciesFilterProps) => { + const [contactPointsSupported, canSeeContactPoints] = useAlertmanagerAbility(AlertmanagerAction.ViewContactPoint); const [searchParams, setSearchParams] = useURLSearchParams(); const searchInputRef = useRef(null); const { queryString, contactPoint } = getNotificationPoliciesFilters(searchParams); @@ -68,13 +71,13 @@ const NotificationPoliciesFilter = ({ label={
+
} > @@ -97,24 +100,26 @@ const NotificationPoliciesFilter = ({ defaultValue={queryString} /> - - { - setSearchParams({ contactPoint: option?.value?.name }); - }, - width: 28, - isClearable: true, - }} - selectedContactPointName={searchParams.get('contactPoint') ?? undefined} - /> - + {contactPointsSupported && canSeeContactPoints && ( + + { + setSearchParams({ contactPoint: option?.value?.name }); + }, + width: 28, + isClearable: true, + }} + selectedContactPointName={searchParams.get('contactPoint') ?? undefined} + /> + + )} {hasFilters && ( {matchingCount === 0 && 'No policies matching filters.'} diff --git a/public/app/features/alerting/unified/NotificationPolicies.tsx b/public/app/features/alerting/unified/components/notification-policies/NotificationPoliciesList.tsx similarity index 53% rename from public/app/features/alerting/unified/NotificationPolicies.tsx rename to public/app/features/alerting/unified/components/notification-policies/NotificationPoliciesList.tsx index b4f4ace4e25..7e6d6c893bc 100644 --- a/public/app/features/alerting/unified/NotificationPolicies.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/NotificationPoliciesList.tsx @@ -1,102 +1,50 @@ -import { css } from '@emotion/css'; import { useEffect, useMemo, useState } from 'react'; import { useAsyncFn } from 'react-use'; -import { GrafanaTheme2, UrlQueryMap } from '@grafana/data'; -import { - Alert, - Button, - LoadingPlaceholder, - Stack, - Tab, - TabContent, - TabsBar, - useStyles2, - withErrorBoundary, -} from '@grafana/ui'; +import { Alert, Button, Stack } from '@grafana/ui'; import { useAppNotification } from 'app/core/copy/appNotification'; -import { useQueryParams } from 'app/core/hooks/useQueryParams'; import { Trans } from 'app/core/internationalization'; import { useContactPointsWithStatus } from 'app/features/alerting/unified/components/contact-points/useContactPoints'; -import { useMuteTimings } from 'app/features/alerting/unified/components/mute-timings/useMuteTimings'; import { AlertmanagerAction, useAlertmanagerAbility } from 'app/features/alerting/unified/hooks/useAbilities'; +import { FormAmRoute } from 'app/features/alerting/unified/types/amroutes'; +import { addUniqueIdentifierToRoute } from 'app/features/alerting/unified/utils/amroutes'; +import { ERROR_NEWER_CONFIGURATION } from 'app/features/alerting/unified/utils/k8s/errors'; +import { isErrorMatchingCode, stringifyErrorLike } from 'app/features/alerting/unified/utils/misc'; +import { computeInheritedTree } from 'app/features/alerting/unified/utils/notification-policies'; import { ObjectMatcher, Route, RouteWithID } from 'app/plugins/datasource/alertmanager/types'; -import { alertmanagerApi } from './api/alertmanagerApi'; -import { useGetContactPointsState } from './api/receiversApi'; -import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper'; -import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning'; -import { MuteTimingsTable } from './components/mute-timings/MuteTimingsTable'; -import { - NotificationPoliciesFilter, - findRoutesByMatchers, - findRoutesMatchingPredicate, -} from './components/notification-policies/Filters'; -import { - useAddPolicyModal, - useAlertGroupsModal, - useDeletePolicyModal, - useEditPolicyModal, -} from './components/notification-policies/Modals'; -import { Policy } from './components/notification-policies/Policy'; -import { - useNotificationPolicyRoute, - useUpdateNotificationPolicyRoute, -} from './components/notification-policies/useNotificationPolicyRoute'; -import { isLoading as isPending, useAsync } from './hooks/useAsync'; -import { useAlertmanager } from './state/AlertmanagerContext'; -import { FormAmRoute } from './types/amroutes'; -import { useRouteGroupsMatcher } from './useRouteGroupsMatcher'; -import { addUniqueIdentifierToRoute } from './utils/amroutes'; -import { ERROR_NEWER_CONFIGURATION } from './utils/k8s/errors'; -import { isErrorMatchingCode, stringifyErrorLike } from './utils/misc'; -import { computeInheritedTree } from './utils/notification-policies'; +import { useAlertmanager } from '../../state/AlertmanagerContext'; + +import { alertmanagerApi } from './../../api/alertmanagerApi'; +import { useGetContactPointsState } from './../../api/receiversApi'; +import { isLoading as isPending, useAsync } from './../../hooks/useAsync'; +import { useRouteGroupsMatcher } from './../../useRouteGroupsMatcher'; import { InsertPosition, addRouteToReferenceRoute, cleanRouteIDs, mergePartialAmRouteWithRouteTree, omitRouteFromRouteTree, -} from './utils/routeTree'; +} from './../../utils/routeTree'; +import { NotificationPoliciesFilter, findRoutesByMatchers, findRoutesMatchingPredicate } from './Filters'; +import { useAddPolicyModal, useAlertGroupsModal, useDeletePolicyModal, useEditPolicyModal } from './Modals'; +import { Policy } from './Policy'; +import { useNotificationPolicyRoute, useUpdateNotificationPolicyRoute } from './useNotificationPolicyRoute'; -enum ActiveTab { - NotificationPolicies = 'notification_policies', - MuteTimings = 'mute_timings', -} - -const AmRoutes = () => { - const styles = useStyles2(getStyles); +export const NotificationPoliciesList = () => { const appNotification = useAppNotification(); - const [policiesSupported, canSeePoliciesTab] = useAlertmanagerAbility(AlertmanagerAction.ViewNotificationPolicyTree); - const [timingsSupported, canSeeTimingsTab] = useAlertmanagerAbility(AlertmanagerAction.ViewMuteTiming); - const [contactPointsSupported, canSeeContactPointsStatus] = useAlertmanagerAbility( - AlertmanagerAction.ViewContactPoint - ); - const availableTabs = [ - canSeePoliciesTab && ActiveTab.NotificationPolicies, - canSeeTimingsTab && ActiveTab.MuteTimings, - ].filter((tab) => !!tab); + const [contactPointsSupported, canSeeContactPoints] = useAlertmanagerAbility(AlertmanagerAction.ViewContactPoint); + const [_, canSeeAlertGroups] = useAlertmanagerAbility(AlertmanagerAction.ViewAlertGroups); const { useGetAlertmanagerAlertGroupsQuery } = alertmanagerApi; - const [queryParams, setQueryParams] = useQueryParams(); - const { tab } = getActiveTabFromUrl(queryParams, availableTabs[0]); - - const [activeTab, setActiveTab] = useState(tab); - const [contactPointFilter, setContactPointFilter] = useState(); const [labelMatchersFilter, setLabelMatchersFilter] = useState([]); const { selectedAlertmanager, hasConfigurationAPI, isGrafanaAlertmanager } = useAlertmanager(); const { getRouteGroupsMap } = useRouteGroupsMatcher(); - const { data: muteTimings = [] } = useMuteTimings({ - alertmanager: selectedAlertmanager ?? '', - skip: !canSeeTimingsTab, - }); - - const shouldFetchContactPoints = - policiesSupported && canSeePoliciesTab && contactPointsSupported && canSeeContactPointsStatus; + const shouldFetchContactPoints = contactPointsSupported && canSeeContactPoints; const contactPointsState = useGetContactPointsState( // Workaround to not try and call this API when we don't have access to the policies tab shouldFetchContactPoints ? (selectedAlertmanager ?? '') : '' @@ -107,7 +55,7 @@ const AmRoutes = () => { isLoading, error: resultError, refetch: refetchNotificationPolicyRoute, - } = useNotificationPolicyRoute({ alertmanager: selectedAlertmanager ?? '' }, { skip: !canSeePoliciesTab }); + } = useNotificationPolicyRoute({ alertmanager: selectedAlertmanager ?? '' }); // We make the assumption that the first policy is the default one // At the time of writing, this will be always the case for the AM config response, and the K8S API @@ -118,14 +66,14 @@ const AmRoutes = () => { const { currentData: alertGroups, refetch: refetchAlertGroups } = useGetAlertmanagerAlertGroupsQuery( { amSourceName: selectedAlertmanager ?? '' }, - { skip: !canSeePoliciesTab || !canSeeAlertGroups || !selectedAlertmanager } + { skip: !canSeeAlertGroups || !selectedAlertmanager } ); const { contactPoints: receivers } = useContactPointsWithStatus({ alertmanager: selectedAlertmanager ?? '', fetchPolicies: false, - fetchStatuses: canSeeContactPointsStatus, - skip: !canSeePoliciesTab, + fetchStatuses: true, + skip: !shouldFetchContactPoints, }); const rootRoute = useMemo(() => { @@ -244,104 +192,65 @@ const AmRoutes = () => { return null; } - const numberOfMuteTimings = muteTimings.length; const hasPoliciesData = rootRoute && !resultError && !isLoading; const hasPoliciesError = !!resultError && !isLoading; - const muteTimingsTabActive = activeTab === ActiveTab.MuteTimings; - const policyTreeTabActive = activeTab === ActiveTab.NotificationPolicies; - return ( <> - - - {policiesSupported && canSeePoliciesTab && ( - { - setActiveTab(ActiveTab.NotificationPolicies); - setQueryParams({ tab: ActiveTab.NotificationPolicies }); - }} - /> - )} - {timingsSupported && canSeeTimingsTab && ( - { - setActiveTab(ActiveTab.MuteTimings); - setQueryParams({ tab: ActiveTab.MuteTimings }); - }} - /> - )} - - - {isLoading && } - - {policyTreeTabActive && ( - <> - {hasPoliciesError && ( - - {stringifyErrorLike(resultError) || 'Unknown error.'} - - )} - {/* show when there is an update error */} - {isErrorMatchingCode(updateError, ERROR_NEWER_CONFIGURATION) && ( - - - - The notification policy tree has been updated by another user. - - - - - )} - {hasPoliciesData && ( - - {rootRoute && ( - - )} - {rootRoute && ( - - )} - - )} - {addModal} - {editModal} - {deleteModal} - {alertInstancesModal} - - )} - {muteTimingsTabActive && ( - - )} - + {hasPoliciesError && ( + + {stringifyErrorLike(resultError) || 'Unknown error.'} + + )} + {/* show when there is an update error */} + {isErrorMatchingCode(updateError, ERROR_NEWER_CONFIGURATION) && ( + + + + The notification policy tree has been updated by another user. + + + + + )} + {hasPoliciesData && ( + + {rootRoute && ( + + )} + {rootRoute && ( + + )} + + )} + {addModal} + {editModal} + {deleteModal} + {alertInstancesModal} ); }; @@ -429,37 +338,3 @@ function findMapIntersection(...matchingRoutes: FilterResult[]): FilterResult { return result; } - -const getStyles = (theme: GrafanaTheme2) => ({ - tabContent: css({ - marginTop: theme.spacing(2), - }), -}); - -interface QueryParamValues { - tab: ActiveTab; -} - -function getActiveTabFromUrl(queryParams: UrlQueryMap, defaultTab: ActiveTab): QueryParamValues { - let tab = defaultTab; - - if (queryParams.tab === ActiveTab.NotificationPolicies) { - tab = ActiveTab.NotificationPolicies; - } - - if (queryParams.tab === ActiveTab.MuteTimings) { - tab = ActiveTab.MuteTimings; - } - - return { - tab, - }; -} - -const NotificationPoliciesPage = () => ( - - - -); - -export default withErrorBoundary(NotificationPoliciesPage, { style: 'page' }); diff --git a/public/app/features/alerting/unified/components/notification-policies/Policy.tsx b/public/app/features/alerting/unified/components/notification-policies/Policy.tsx index fedb129ecd6..7f2d800390d 100644 --- a/public/app/features/alerting/unified/components/notification-policies/Policy.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/Policy.tsx @@ -35,7 +35,6 @@ import { } from 'app/plugins/datasource/alertmanager/types'; import { ReceiversState } from 'app/types'; -import { RoutesMatchingFilters } from '../../NotificationPolicies'; import { AlertmanagerAction, useAlertmanagerAbilities, useAlertmanagerAbility } from '../../hooks/useAbilities'; import { getAmMatcherFormatter } from '../../utils/alertmanager'; import { MatcherFormatter, normalizeMatchers } from '../../utils/matchers'; @@ -51,6 +50,7 @@ import { Spacer } from '../Spacer'; import { GrafanaPoliciesExporter } from '../export/GrafanaPoliciesExporter'; import { Matchers } from './Matchers'; +import { RoutesMatchingFilters } from './NotificationPoliciesList'; import { TIMING_OPTIONS_DEFAULTS, TimingOptions } from './timingOptions'; interface PolicyComponentProps { @@ -742,7 +742,7 @@ const TimeIntervals: FC<{ timings: string[]; alertManagerSourceName: string }> = href={createMuteTimingLink(timing, alertManagerSourceName)} color={canSeeMuteTimings ? 'primary' : 'secondary'} variant="bodySmall" - inline={false} + inline={canSeeMuteTimings ? false : undefined} > {timing} diff --git a/public/app/features/alerting/unified/components/silences/SilencesFilter.tsx b/public/app/features/alerting/unified/components/silences/SilencesFilter.tsx index 1e28a3bd4d6..06fef5c8388 100644 --- a/public/app/features/alerting/unified/components/silences/SilencesFilter.tsx +++ b/public/app/features/alerting/unified/components/silences/SilencesFilter.tsx @@ -5,6 +5,7 @@ import { FormEvent, useState } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { Button, Field, Icon, Input, Label, Stack, Tooltip, useStyles2 } from '@grafana/ui'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; +import { Trans } from 'app/core/internationalization'; import { parsePromQLStyleMatcherLoose } from '../../utils/matchers'; import { getSilenceFiltersFromUrlParams } from '../../utils/misc'; @@ -48,7 +49,7 @@ export const SilencesFilter = () => { label={