Alerting: Make receiver optional in routing preview and handle fallback case (#104639)
This commit is contained in:
+3
-4
@@ -73,14 +73,13 @@ function NotificationPreviewByAlertManager({
|
||||
if (!route) {
|
||||
return null;
|
||||
}
|
||||
if (!receiver) {
|
||||
throw new Error('Receiver not found');
|
||||
}
|
||||
return (
|
||||
<NotificationRoute
|
||||
instanceMatches={instanceMatches}
|
||||
route={route}
|
||||
receiver={receiver}
|
||||
// If we can't find a receiver, it might just be because the user doesn't have access
|
||||
receiver={receiver ? receiver : undefined}
|
||||
receiverNameFromRoute={route?.receiver ? route.receiver : undefined}
|
||||
key={routeId}
|
||||
routesByIdMap={routesByIdMap}
|
||||
alertManagerSourceName={alertManagerSource.name}
|
||||
|
||||
+26
-14
@@ -18,25 +18,34 @@ import { Spacer } from '../../Spacer';
|
||||
|
||||
import { NotificationPolicyMatchers } from './NotificationPolicyMatchers';
|
||||
import { NotificationRouteDetailsModal } from './NotificationRouteDetailsModal';
|
||||
import UnknownContactPointDetails from './UnknownContactPointDetails';
|
||||
import { RouteWithPath } from './route';
|
||||
|
||||
function NotificationRouteHeader({
|
||||
route,
|
||||
receiver,
|
||||
routesByIdMap,
|
||||
instancesCount,
|
||||
alertManagerSourceName,
|
||||
expandRoute,
|
||||
onExpandRouteClick,
|
||||
}: {
|
||||
export interface ReceiverNameProps {
|
||||
/** Receiver name taken from route definition. Used as a fallback when full receiver details cannot be found (in case of RBAC restrictions) */
|
||||
receiverNameFromRoute?: string;
|
||||
}
|
||||
|
||||
interface NotificationRouteHeaderProps extends ReceiverNameProps {
|
||||
route: RouteWithPath;
|
||||
receiver: Receiver;
|
||||
receiver?: Receiver;
|
||||
routesByIdMap: Map<string, RouteWithPath>;
|
||||
instancesCount: number;
|
||||
alertManagerSourceName: string;
|
||||
expandRoute: boolean;
|
||||
onExpandRouteClick: (expand: boolean) => void;
|
||||
}) {
|
||||
}
|
||||
|
||||
function NotificationRouteHeader({
|
||||
route,
|
||||
receiver,
|
||||
receiverNameFromRoute,
|
||||
routesByIdMap,
|
||||
instancesCount,
|
||||
alertManagerSourceName,
|
||||
expandRoute,
|
||||
onExpandRouteClick,
|
||||
}: NotificationRouteHeaderProps) {
|
||||
const styles = useStyles2(getStyles);
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
|
||||
@@ -76,7 +85,7 @@ function NotificationRouteHeader({
|
||||
<span className={styles.textMuted}>
|
||||
<Trans i18nKey="alerting.notification-route-header.delivered-to">@ Delivered to</Trans>
|
||||
</span>{' '}
|
||||
{receiver.name}
|
||||
{receiver ? receiver.name : <UnknownContactPointDetails receiverName={receiverNameFromRoute} />}
|
||||
</div>
|
||||
|
||||
<div className={styles.verticalBar} />
|
||||
@@ -92,6 +101,7 @@ function NotificationRouteHeader({
|
||||
onClose={() => setShowDetails(false)}
|
||||
route={route}
|
||||
receiver={receiver}
|
||||
receiverNameFromRoute={receiverNameFromRoute}
|
||||
routesByIdMap={routesByIdMap}
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
/>
|
||||
@@ -100,9 +110,9 @@ function NotificationRouteHeader({
|
||||
);
|
||||
}
|
||||
|
||||
interface NotificationRouteProps {
|
||||
interface NotificationRouteProps extends ReceiverNameProps {
|
||||
route: RouteWithPath;
|
||||
receiver: Receiver;
|
||||
receiver?: Receiver;
|
||||
instanceMatches: AlertInstanceMatch[];
|
||||
routesByIdMap: Map<string, RouteWithPath>;
|
||||
alertManagerSourceName: string;
|
||||
@@ -112,6 +122,7 @@ export function NotificationRoute({
|
||||
route,
|
||||
instanceMatches,
|
||||
receiver,
|
||||
receiverNameFromRoute,
|
||||
routesByIdMap,
|
||||
alertManagerSourceName,
|
||||
}: NotificationRouteProps) {
|
||||
@@ -126,6 +137,7 @@ export function NotificationRoute({
|
||||
<NotificationRouteHeader
|
||||
route={route}
|
||||
receiver={receiver}
|
||||
receiverNameFromRoute={receiverNameFromRoute}
|
||||
routesByIdMap={routesByIdMap}
|
||||
instancesCount={instanceMatches.length}
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
|
||||
+13
-6
@@ -14,6 +14,8 @@ import { createContactPointSearchLink } from '../../../utils/misc';
|
||||
import { Authorize } from '../../Authorize';
|
||||
import { Matchers } from '../../notification-policies/Matchers';
|
||||
|
||||
import { ReceiverNameProps } from './NotificationRoute';
|
||||
import UnknownContactPointDetails from './UnknownContactPointDetails';
|
||||
import { RouteWithPath, hasEmptyMatchers, isDefaultPolicy } from './route';
|
||||
|
||||
interface Props {
|
||||
@@ -51,10 +53,10 @@ function PolicyPath({ route, routesByIdMap, matcherFormatter }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
interface NotificationRouteDetailsModalProps {
|
||||
interface NotificationRouteDetailsModalProps extends ReceiverNameProps {
|
||||
onClose: () => void;
|
||||
route: RouteWithPath;
|
||||
receiver: Receiver;
|
||||
receiver?: Receiver;
|
||||
routesByIdMap: Map<string, RouteWithPath>;
|
||||
alertManagerSourceName: string;
|
||||
}
|
||||
@@ -63,6 +65,7 @@ export function NotificationRouteDetailsModal({
|
||||
onClose,
|
||||
route,
|
||||
receiver,
|
||||
receiverNameFromRoute,
|
||||
routesByIdMap,
|
||||
alertManagerSourceName,
|
||||
}: NotificationRouteDetailsModalProps) {
|
||||
@@ -107,13 +110,17 @@ export function NotificationRouteDetailsModal({
|
||||
<Stack gap={1} direction="column">
|
||||
<Trans i18nKey="alerting.notification-route-details-modal.contact-point">Contact point</Trans>
|
||||
|
||||
<span className={styles.textMuted}>{receiver.name}</span>
|
||||
<span className={styles.textMuted}>
|
||||
{receiver ? receiver.name : <UnknownContactPointDetails receiverName={receiverNameFromRoute} />}
|
||||
</span>
|
||||
</Stack>
|
||||
<Authorize actions={[AlertmanagerAction.UpdateContactPoint]}>
|
||||
<Stack gap={1} direction="row" alignItems="center">
|
||||
<TextLink href={createContactPointSearchLink(receiver.name, alertManagerSourceName)} external>
|
||||
<Trans i18nKey="alerting.notification-route-details-modal.see-details-link">See details</Trans>
|
||||
</TextLink>
|
||||
{receiver ? (
|
||||
<TextLink href={createContactPointSearchLink(receiver.name, alertManagerSourceName)} external>
|
||||
<Trans i18nKey="alerting.notification-route-details-modal.see-details-link">See details</Trans>
|
||||
</TextLink>
|
||||
) : null}
|
||||
</Stack>
|
||||
</Authorize>
|
||||
</div>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { Tooltip } from '@grafana/ui';
|
||||
import { Trans, t } from 'app/core/internationalization';
|
||||
|
||||
const UnknownContactPointDetails = ({ receiverName }: { receiverName?: string }) => (
|
||||
<span style={{ cursor: 'help' }}>
|
||||
<Tooltip
|
||||
content={t(
|
||||
'alerting.unknown-contact-point-details.unknown-contact-point-tooltip',
|
||||
'Details could not be found. This may be because you do not have access to the contact point'
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
{receiverName ? (
|
||||
receiverName
|
||||
) : (
|
||||
<Trans i18nKey="alerting.unknown-contact-point-details.unknown-contact-point">Unknown contact point</Trans>
|
||||
)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
|
||||
export default UnknownContactPointDetails;
|
||||
@@ -2353,6 +2353,10 @@
|
||||
"type-selector-button": {
|
||||
"add-expression": "Add expression"
|
||||
},
|
||||
"unknown-contact-point-details": {
|
||||
"unknown-contact-point": "Unknown contact point",
|
||||
"unknown-contact-point-tooltip": "Details could not be found. This may be because you do not have access to the contact point"
|
||||
},
|
||||
"unknown-rule-list-item": {
|
||||
"title-unknown-rule-type": "Unknown rule type"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user