From b0ba94f31626dc56905cf1ec4c1cbd055bc03cab Mon Sep 17 00:00:00 2001 From: Leo <108552997+lpskdl@users.noreply.github.com> Date: Thu, 6 Oct 2022 11:18:43 +0200 Subject: [PATCH] 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 --- .../features/alerting/unified/Silences.tsx | 9 ++-- .../components/amroutes/MuteTimingForm.tsx | 16 ++++++- .../unified/hooks/useSilenceNavData.test.tsx | 47 +++++++++++++++++++ .../unified/hooks/useSilenceNavData.ts | 32 +++++++++++++ 4 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 public/app/features/alerting/unified/hooks/useSilenceNavData.test.tsx create mode 100644 public/app/features/alerting/unified/hooks/useSilenceNavData.ts diff --git a/public/app/features/alerting/unified/Silences.tsx b/public/app/features/alerting/unified/Silences.tsx index 8f12db15b24..46f6cc58f58 100644 --- a/public/app/features/alerting/unified/Silences.tsx +++ b/public/app/features/alerting/unified/Silences.tsx @@ -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 ? ( - + ) : ( @@ -70,7 +72,7 @@ const Silences: FC = () => { } return ( - + { {alertsRequest.error?.message || 'Unknown error.'} )} - {loading && } {result && !error && ( diff --git a/public/app/features/alerting/unified/components/amroutes/MuteTimingForm.tsx b/public/app/features/alerting/unified/components/amroutes/MuteTimingForm.tsx index 1048b21c4f7..e7779c10bbb 100644 --- a/public/app/features/alerting/unified/components/amroutes/MuteTimingForm.tsx +++ b/public/app/features/alerting/unified/components/amroutes/MuteTimingForm.tsx @@ -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 = { + 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 ( - + ({ + ...jest.requireActual('react-router-dom'), + useRouteMatch: jest.fn(), +})); + +const setup = () => { + let result: ReturnType; + function TestComponent() { + result = useSilenceNavData(); + return null; + } + + render(); + + 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', + }); + }); +}); diff --git a/public/app/features/alerting/unified/hooks/useSilenceNavData.ts b/public/app/features/alerting/unified/hooks/useSilenceNavData.ts new file mode 100644 index 00000000000..9757d385f3b --- /dev/null +++ b/public/app/features/alerting/unified/hooks/useSilenceNavData.ts @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react'; +import { useRouteMatch } from 'react-router-dom'; + +import { NavModelItem } from '@grafana/data'; + +const defaultPageNav: Partial = { + icon: 'bell-slash', + breadcrumbs: [{ title: 'Silences', url: 'alerting/silences' }], +}; + +export function useSilenceNavData() { + const { isExact, path } = useRouteMatch(); + const [pageNav, setPageNav] = useState | 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; +}