Navigation: Use page nav in silence and policy notification pages (#55753)

* use pagenav in mutetiming form

* use pagenav in alert policy page

* use pageNav for Silence page

* added missing breadcrumbs
This commit is contained in:
Leo
2022-10-06 11:18:43 +02:00
committed by GitHub
parent 3aacda5579
commit b0ba94f316
4 changed files with 98 additions and 6 deletions
@@ -1,7 +1,7 @@
import React, { FC, useCallback, useEffect } from 'react';
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
import { Alert, withErrorBoundary } from '@grafana/ui';
import { Silence } from 'app/plugins/datasource/alertmanager/types';
import { useDispatch } from 'app/types';
@@ -13,6 +13,7 @@ import SilencesEditor from './components/silences/SilencesEditor';
import SilencesTable from './components/silences/SilencesTable';
import { useAlertManagerSourceName } from './hooks/useAlertManagerSourceName';
import { useAlertManagersByPermission } from './hooks/useAlertManagerSources';
import { useSilenceNavData } from './hooks/useSilenceNavData';
import { useUnifiedAlertingSelector } from './hooks/useUnifiedAlertingSelector';
import { fetchAmAlertsAction, fetchSilencesAction } from './state/actions';
import { SILENCES_POLL_INTERVAL_MS } from './utils/constants';
@@ -30,6 +31,7 @@ const Silences: FC = () => {
: undefined;
const location = useLocation();
const pageNav = useSilenceNavData();
const isRoot = location.pathname.endsWith('/alerting/silences');
const { currentData: amFeatures } = featureDiscoveryApi.useDiscoverAmFeaturesQuery(
@@ -61,7 +63,7 @@ const Silences: FC = () => {
if (!alertManagerSourceName) {
return isRoot ? (
<AlertingPageWrapper pageId="silences">
<AlertingPageWrapper pageId="silences" pageNav={pageNav}>
<NoAlertManagerWarning availableAlertManagers={alertManagers} />
</AlertingPageWrapper>
) : (
@@ -70,7 +72,7 @@ const Silences: FC = () => {
}
return (
<AlertingPageWrapper pageId="silences">
<AlertingPageWrapper pageId="silences" isLoading={loading} pageNav={pageNav}>
<AlertManagerPicker
disabled={!isRoot}
current={alertManagerSourceName}
@@ -94,7 +96,6 @@ const Silences: FC = () => {
{alertsRequest.error?.message || 'Unknown error.'}
</Alert>
)}
{loading && <LoadingPlaceholder text="loading silences..." />}
{result && !error && (
<Switch>
<Route exact path="/alerting/silences">
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import React, { useMemo } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { GrafanaTheme2 } from '@grafana/data';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { Alert, Field, FieldSet, Input, Button, LinkButton, useStyles2 } from '@grafana/ui';
import {
AlertmanagerConfig,
@@ -58,6 +58,11 @@ const useDefaultValues = (muteTiming?: MuteTimeInterval): MuteTimingFields => {
}, [muteTiming]);
};
const defaultPageNav: Partial<NavModelItem> = {
icon: 'sitemap',
breadcrumbs: [{ title: 'Notification Policies', url: 'alerting/routes' }],
};
const MuteTimingForm = ({ muteTiming, showError, provenance }: Props) => {
const dispatch = useDispatch();
const alertManagers = useAlertManagersByPermission('notification');
@@ -104,7 +109,14 @@ const MuteTimingForm = ({ muteTiming, showError, provenance }: Props) => {
};
return (
<AlertingPageWrapper pageId="am-routes">
<AlertingPageWrapper
pageId="am-routes"
pageNav={{
...defaultPageNav,
id: muteTiming ? 'alert-policy-edit' : 'alert-policy-new',
text: muteTiming ? 'Edit mute timing' : 'New mute timing',
}}
>
<AlertManagerPicker
current={alertManagerSourceName}
onChange={setAlertManagerSourceName}
@@ -0,0 +1,47 @@
import { render } from '@testing-library/react';
import React from 'react';
import { useRouteMatch } from 'react-router-dom';
import { useSilenceNavData } from './useSilenceNavData';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useRouteMatch: jest.fn(),
}));
const setup = () => {
let result: ReturnType<typeof useSilenceNavData>;
function TestComponent() {
result = useSilenceNavData();
return null;
}
render(<TestComponent />);
return { result };
};
describe('useSilenceNavData', () => {
it('should return correct nav data when route is "/alerting/silence/new"', () => {
(useRouteMatch as jest.Mock).mockReturnValue({ isExact: true, path: '/alerting/silence/new' });
const { result } = setup();
expect(result).toEqual({
icon: 'bell-slash',
breadcrumbs: [{ title: 'Silences', url: 'alerting/silences' }],
id: 'silence-new',
text: 'Add silence',
});
});
it('should return correct nav data when route is "/alerting/silence/:id/edit"', () => {
(useRouteMatch as jest.Mock).mockReturnValue({ isExact: true, path: '/alerting/silence/:id/edit' });
const { result } = setup();
expect(result).toEqual({
icon: 'bell-slash',
breadcrumbs: [{ title: 'Silences', url: 'alerting/silences' }],
id: 'silence-edit',
text: 'Edit silence',
});
});
});
@@ -0,0 +1,32 @@
import { useEffect, useState } from 'react';
import { useRouteMatch } from 'react-router-dom';
import { NavModelItem } from '@grafana/data';
const defaultPageNav: Partial<NavModelItem> = {
icon: 'bell-slash',
breadcrumbs: [{ title: 'Silences', url: 'alerting/silences' }],
};
export function useSilenceNavData() {
const { isExact, path } = useRouteMatch();
const [pageNav, setPageNav] = useState<Pick<NavModelItem, 'id' | 'text' | 'icon'> | undefined>();
useEffect(() => {
if (path === '/alerting/silence/new') {
setPageNav({
...defaultPageNav,
id: 'silence-new',
text: 'Add silence',
});
} else if (path === '/alerting/silence/:id/edit') {
setPageNav({
...defaultPageNav,
id: 'silence-edit',
text: 'Edit silence',
});
}
}, [path, isExact]);
return pageNav;
}