mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Navigation: use navId and pageNav on Alerting - Contact Points page (#54451)
This commit is contained in:
parent
a70aba1384
commit
066710a7bc
@ -610,7 +610,7 @@ func (hs *HTTPServer) buildAlertNavLinks(c *models.ReqContext) []*dtos.NavLink {
|
|||||||
if hasAccess(ac.ReqOrgAdminOrEditor, ac.EvalAny(ac.EvalPermission(ac.ActionAlertingNotificationsRead), ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead))) {
|
if hasAccess(ac.ReqOrgAdminOrEditor, ac.EvalAny(ac.EvalPermission(ac.ActionAlertingNotificationsRead), ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead))) {
|
||||||
alertChildNavs = append(alertChildNavs, &dtos.NavLink{
|
alertChildNavs = append(alertChildNavs, &dtos.NavLink{
|
||||||
Text: "Contact points", Id: "receivers", Url: hs.Cfg.AppSubURL + "/alerting/notifications",
|
Text: "Contact points", Id: "receivers", Url: hs.Cfg.AppSubURL + "/alerting/notifications",
|
||||||
Icon: "comment-alt-share",
|
Icon: "comment-alt-share", SubTitle: "Manage the settings of your contact points",
|
||||||
})
|
})
|
||||||
alertChildNavs = append(alertChildNavs, &dtos.NavLink{Text: "Notification policies", Id: "am-routes", Url: hs.Cfg.AppSubURL + "/alerting/routes", Icon: "sitemap"})
|
alertChildNavs = append(alertChildNavs, &dtos.NavLink{Text: "Notification policies", Id: "am-routes", Url: hs.Cfg.AppSubURL + "/alerting/routes", Icon: "sitemap"})
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ const unifiedRoutes: RouteDescriptor[] = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/alerting/notifications/templates/new',
|
path: '/alerting/notifications/:type/new',
|
||||||
roles: evaluateAccess(
|
roles: evaluateAccess(
|
||||||
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
||||||
['Editor', 'Admin']
|
['Editor', 'Admin']
|
||||||
@ -182,7 +182,7 @@ const unifiedRoutes: RouteDescriptor[] = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/alerting/notifications/templates/:id/edit',
|
path: '/alerting/notifications/:type/:id/edit',
|
||||||
roles: evaluateAccess(
|
roles: evaluateAccess(
|
||||||
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
||||||
['Editor', 'Admin']
|
['Editor', 'Admin']
|
||||||
@ -192,27 +192,7 @@ const unifiedRoutes: RouteDescriptor[] = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/alerting/notifications/receivers/new',
|
path: '/alerting/notifications/:type',
|
||||||
roles: evaluateAccess(
|
|
||||||
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
|
||||||
['Editor', 'Admin']
|
|
||||||
),
|
|
||||||
component: SafeDynamicImport(
|
|
||||||
() => import(/* webpackChunkName: "NotificationsListPage" */ 'app/features/alerting/unified/Receivers')
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/alerting/notifications/receivers/:id/edit',
|
|
||||||
roles: evaluateAccess(
|
|
||||||
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
|
||||||
['Editor', 'Admin']
|
|
||||||
),
|
|
||||||
component: SafeDynamicImport(
|
|
||||||
() => import(/* webpackChunkName: "NotificationsListPage" */ 'app/features/alerting/unified/Receivers')
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/alerting/notifications/global-config',
|
|
||||||
roles: evaluateAccess(
|
roles: evaluateAccess(
|
||||||
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
[AccessControlAction.AlertingNotificationsWrite, AccessControlAction.AlertingNotificationsExternalWrite],
|
||||||
['Editor', 'Admin']
|
['Editor', 'Admin']
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React, { FC, useEffect } from 'react';
|
import React, { FC, useEffect } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
|
import { Redirect, Route, RouteChildrenProps, Switch, useLocation, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
|
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
|
||||||
|
|
||||||
import { AlertManagerPicker } from './components/AlertManagerPicker';
|
import { AlertManagerPicker } from './components/AlertManagerPicker';
|
||||||
@ -25,6 +26,9 @@ const Receivers: FC = () => {
|
|||||||
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);
|
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
type PageType = 'receivers' | 'templates' | 'global-config';
|
||||||
|
|
||||||
|
const { id, type } = useParams<{ id?: string; type?: PageType }>();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const isRoot = location.pathname.endsWith('/alerting/notifications');
|
const isRoot = location.pathname.endsWith('/alerting/notifications');
|
||||||
|
|
||||||
@ -56,9 +60,30 @@ const Receivers: FC = () => {
|
|||||||
|
|
||||||
const disableAmSelect = !isRoot;
|
const disableAmSelect = !isRoot;
|
||||||
|
|
||||||
|
let pageNav: NavModelItem | undefined;
|
||||||
|
if (type === 'receivers' || type === 'templates') {
|
||||||
|
const objectText = type === 'receivers' ? 'contact point' : 'message template';
|
||||||
|
if (id) {
|
||||||
|
pageNav = {
|
||||||
|
text: id,
|
||||||
|
subTitle: `Edit the settings for a specific ${objectText}`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
pageNav = {
|
||||||
|
text: `New ${objectText}`,
|
||||||
|
subTitle: `Create a new ${objectText} for your notifications`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else if (type === 'global-config') {
|
||||||
|
pageNav = {
|
||||||
|
text: 'Global config',
|
||||||
|
subTitle: 'Manage your global configuration',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (!alertManagerSourceName) {
|
if (!alertManagerSourceName) {
|
||||||
return isRoot ? (
|
return isRoot ? (
|
||||||
<AlertingPageWrapper pageId="receivers">
|
<AlertingPageWrapper pageId="receivers" pageNav={pageNav}>
|
||||||
<NoAlertManagerWarning availableAlertManagers={alertManagers} />
|
<NoAlertManagerWarning availableAlertManagers={alertManagers} />
|
||||||
</AlertingPageWrapper>
|
</AlertingPageWrapper>
|
||||||
) : (
|
) : (
|
||||||
@ -67,7 +92,7 @@ const Receivers: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AlertingPageWrapper pageId="receivers">
|
<AlertingPageWrapper pageId="receivers" pageNav={pageNav}>
|
||||||
<AlertManagerPicker
|
<AlertManagerPicker
|
||||||
current={alertManagerSourceName}
|
current={alertManagerSourceName}
|
||||||
disabled={disableAmSelect}
|
disabled={disableAmSelect}
|
||||||
|
@ -1,23 +1,17 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { Page } from 'app/core/components/Page/Page';
|
import { Page } from 'app/core/components/Page/Page';
|
||||||
import { getNavModel } from 'app/core/selectors/navModel';
|
|
||||||
import { StoreState } from 'app/types/store';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
pageId: string;
|
pageId: string;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
|
pageNav?: NavModelItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AlertingPageWrapper: FC<Props> = ({ children, pageId, isLoading }) => {
|
export const AlertingPageWrapper: FC<Props> = ({ children, pageId, pageNav, isLoading }) => {
|
||||||
const navModel = getNavModel(
|
|
||||||
useSelector((state: StoreState) => state.navIndex),
|
|
||||||
pageId
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page navModel={navModel}>
|
<Page pageNav={pageNav} navId={pageId}>
|
||||||
<Page.Contents isLoading={isLoading}>{children}</Page.Contents>
|
<Page.Contents isLoading={isLoading}>{children}</Page.Contents>
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { css } from '@emotion/css';
|
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { useForm, FormProvider } from 'react-hook-form';
|
import { useForm, FormProvider } from 'react-hook-form';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { Alert, Button, HorizontalGroup, LinkButton } from '@grafana/ui';
|
||||||
import { Alert, Button, HorizontalGroup, LinkButton, useStyles2 } from '@grafana/ui';
|
|
||||||
import { useCleanup } from 'app/core/hooks/useCleanup';
|
import { useCleanup } from 'app/core/hooks/useCleanup';
|
||||||
import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types';
|
import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types';
|
||||||
|
|
||||||
@ -36,7 +34,6 @@ export const GlobalConfigForm: FC<Props> = ({ config, alertManagerSourceName })
|
|||||||
|
|
||||||
const { loading, error } = useUnifiedAlertingSelector((state) => state.saveAMConfig);
|
const { loading, error } = useUnifiedAlertingSelector((state) => state.saveAMConfig);
|
||||||
const readOnly = isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName);
|
const readOnly = isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName);
|
||||||
const styles = useStyles2(getStyles);
|
|
||||||
|
|
||||||
const formAPI = useForm<FormValues>({
|
const formAPI = useForm<FormValues>({
|
||||||
// making a copy here beacuse react-hook-form will mutate these, and break if the object is frozen. for real.
|
// making a copy here beacuse react-hook-form will mutate these, and break if the object is frozen. for real.
|
||||||
@ -74,7 +71,6 @@ export const GlobalConfigForm: FC<Props> = ({ config, alertManagerSourceName })
|
|||||||
return (
|
return (
|
||||||
<FormProvider {...formAPI}>
|
<FormProvider {...formAPI}>
|
||||||
<form onSubmit={handleSubmit(onSubmitCallback)}>
|
<form onSubmit={handleSubmit(onSubmitCallback)}>
|
||||||
<h4 className={styles.heading}>Global config</h4>
|
|
||||||
{error && (
|
{error && (
|
||||||
<Alert severity="error" title="Error saving receiver">
|
<Alert severity="error" title="Error saving receiver">
|
||||||
{error.message || String(error)}
|
{error.message || String(error)}
|
||||||
@ -116,9 +112,3 @@ export const GlobalConfigForm: FC<Props> = ({ config, alertManagerSourceName })
|
|||||||
</FormProvider>
|
</FormProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => ({
|
|
||||||
heading: css`
|
|
||||||
margin: ${theme.spacing(4, 0)};
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
Loading…
Reference in New Issue
Block a user