grafana/public/app/features/alerting/unified/Receivers.tsx
Konrad Lalik 65d7d466d7
Alerting: Improved RBAC for Alert managers (#48344)
* Initial support for grafana or cloud only alert managers

* Handle missing alert manager

* Refactor code, fix tests

* Fix redirect url

* Bring back the test

* Improve missing alert manager warning, add useAlertManagerSourceName tests

* Fix lint errors

* Rename alert manager hook

* Refactor alert manager label creation

* Improve warnings' messages

* Fix linter

* Fix warning condition in RuleEditor
2022-05-05 13:34:58 +02:00

126 lines
5.2 KiB
TypeScript

import React, { FC, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
import { AlertManagerPicker } from './components/AlertManagerPicker';
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
import { NoAlertManagerWarning } from './components/NoAlertManagerWarning';
import { EditReceiverView } from './components/receivers/EditReceiverView';
import { EditTemplateView } from './components/receivers/EditTemplateView';
import { GlobalConfigForm } from './components/receivers/GlobalConfigForm';
import { NewReceiverView } from './components/receivers/NewReceiverView';
import { NewTemplateView } from './components/receivers/NewTemplateView';
import { ReceiversAndTemplatesView } from './components/receivers/ReceiversAndTemplatesView';
import { useAlertManagerSourceName } from './hooks/useAlertManagerSourceName';
import { useAlertManagersByPermission } from './hooks/useAlertManagerSources';
import { useUnifiedAlertingSelector } from './hooks/useUnifiedAlertingSelector';
import { fetchAlertManagerConfigAction, fetchGrafanaNotifiersAction } from './state/actions';
import { GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
import { initialAsyncRequestState } from './utils/redux';
const Receivers: FC = () => {
const alertManagers = useAlertManagersByPermission('notification');
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);
const dispatch = useDispatch();
const location = useLocation();
const isRoot = location.pathname.endsWith('/alerting/notifications');
const configRequests = useUnifiedAlertingSelector((state) => state.amConfigs);
const {
result: config,
loading,
error,
} = (alertManagerSourceName && configRequests[alertManagerSourceName]) || initialAsyncRequestState;
const receiverTypes = useUnifiedAlertingSelector((state) => state.grafanaNotifiers);
const shouldLoadConfig = isRoot || !config;
useEffect(() => {
if (alertManagerSourceName && shouldLoadConfig) {
dispatch(fetchAlertManagerConfigAction(alertManagerSourceName));
}
}, [alertManagerSourceName, dispatch, shouldLoadConfig]);
useEffect(() => {
if (
alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME &&
!(receiverTypes.result || receiverTypes.loading || receiverTypes.error)
) {
dispatch(fetchGrafanaNotifiersAction());
}
}, [alertManagerSourceName, dispatch, receiverTypes]);
const disableAmSelect = !isRoot;
if (!alertManagerSourceName) {
return isRoot ? (
<AlertingPageWrapper pageId="receivers">
<NoAlertManagerWarning availableAlertManagers={alertManagers} />
</AlertingPageWrapper>
) : (
<Redirect to="/alerting/notifications" />
);
}
return (
<AlertingPageWrapper pageId="receivers">
<AlertManagerPicker
current={alertManagerSourceName}
disabled={disableAmSelect}
onChange={setAlertManagerSourceName}
dataSources={alertManagers}
/>
{error && !loading && (
<Alert severity="error" title="Error loading Alertmanager config">
{error.message || 'Unknown error.'}
</Alert>
)}
{loading && !config && <LoadingPlaceholder text="loading configuration..." />}
{config && !error && (
<Switch>
<Route exact={true} path="/alerting/notifications">
<ReceiversAndTemplatesView config={config} alertManagerName={alertManagerSourceName} />
</Route>
<Route exact={true} path="/alerting/notifications/templates/new">
<NewTemplateView config={config} alertManagerSourceName={alertManagerSourceName} />
</Route>
<Route exact={true} path="/alerting/notifications/templates/:name/edit">
{({ match }: RouteChildrenProps<{ name: string }>) =>
match?.params.name && (
<EditTemplateView
alertManagerSourceName={alertManagerSourceName}
config={config}
templateName={decodeURIComponent(match?.params.name)}
/>
)
}
</Route>
<Route exact={true} path="/alerting/notifications/receivers/new">
<NewReceiverView config={config} alertManagerSourceName={alertManagerSourceName} />
</Route>
<Route exact={true} path="/alerting/notifications/receivers/:name/edit">
{({ match }: RouteChildrenProps<{ name: string }>) =>
match?.params.name && (
<EditReceiverView
alertManagerSourceName={alertManagerSourceName}
config={config}
receiverName={decodeURIComponent(match?.params.name)}
/>
)
}
</Route>
<Route exact={true} path="/alerting/notifications/global-config">
<GlobalConfigForm config={config} alertManagerSourceName={alertManagerSourceName} />
</Route>
</Switch>
)}
</AlertingPageWrapper>
);
};
export default withErrorBoundary(Receivers, { style: 'page' });