1import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
2import React, { FC, useEffect } from 'react';
3import { useDispatch } from 'react-redux';
4import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
5import { AlertingPageWrapper } from './components/AlertingPageWrapper';
6import { AlertManagerPicker } from './components/AlertManagerPicker';
7import { EditReceiverView } from './components/receivers/EditReceiverView';
8import { EditTemplateView } from './components/receivers/EditTemplateView';
9import { GlobalConfigForm } from './components/receivers/GlobalConfigForm';
10import { NewReceiverView } from './components/receivers/NewReceiverView';
11import { NewTemplateView } from './components/receivers/NewTemplateView';
12import { ReceiversAndTemplatesView } from './components/receivers/ReceiversAndTemplatesView';
13import { useAlertManagerSourceName } from './hooks/useAlertManagerSourceName';
14import { useUnifiedAlertingSelector } from './hooks/useUnifiedAlertingSelector';
15import { fetchAlertManagerConfigAction, fetchGrafanaNotifiersAction } from './state/actions';
16import { GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
17import { initialAsyncRequestState } from './utils/redux';
18
19const Receivers: FC = () => {
20  const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName();
21  const dispatch = useDispatch();
22
23  const location = useLocation();
24  const isRoot = location.pathname.endsWith('/alerting/notifications');
25
26  const configRequests = useUnifiedAlertingSelector((state) => state.amConfigs);
27
28  const { result: config, loading, error } =
29    (alertManagerSourceName && configRequests[alertManagerSourceName]) || initialAsyncRequestState;
30  const receiverTypes = useUnifiedAlertingSelector((state) => state.grafanaNotifiers);
31
32  const shouldLoadConfig = isRoot || !config;
33
34  useEffect(() => {
35    if (alertManagerSourceName && shouldLoadConfig) {
36      dispatch(fetchAlertManagerConfigAction(alertManagerSourceName));
37    }
38  }, [alertManagerSourceName, dispatch, shouldLoadConfig]);
39
40  useEffect(() => {
41    if (alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME && !(receiverTypes.result || receiverTypes.loading)) {
42      dispatch(fetchGrafanaNotifiersAction());
43    }
44  }, [alertManagerSourceName, dispatch, receiverTypes]);
45
46  const disableAmSelect = !isRoot;
47
48  if (!alertManagerSourceName) {
49    return <Redirect to="/alerting/notifications" />;
50  }
51
52  return (
53    <AlertingPageWrapper pageId="receivers">
54      <AlertManagerPicker
55        current={alertManagerSourceName}
56        disabled={disableAmSelect}
57        onChange={setAlertManagerSourceName}
58      />
59      {error && !loading && (
60        <Alert severity="error" title="Error loading Alertmanager config">
61          {error.message || 'Unknown error.'}
62        </Alert>
63      )}
64      {loading && !config && <LoadingPlaceholder text="loading configuration..." />}
65      {config && !error && (
66        <Switch>
67          <Route exact={true} path="/alerting/notifications">
68            <ReceiversAndTemplatesView config={config} alertManagerName={alertManagerSourceName} />
69          </Route>
70          <Route exact={true} path="/alerting/notifications/templates/new">
71            <NewTemplateView config={config} alertManagerSourceName={alertManagerSourceName} />
72          </Route>
73          <Route exact={true} path="/alerting/notifications/templates/:name/edit">
74            {({ match }: RouteChildrenProps<{ name: string }>) =>
75              match?.params.name && (
76                <EditTemplateView
77                  alertManagerSourceName={alertManagerSourceName}
78                  config={config}
79                  templateName={decodeURIComponent(match?.params.name)}
80                />
81              )
82            }
83          </Route>
84          <Route exact={true} path="/alerting/notifications/receivers/new">
85            <NewReceiverView config={config} alertManagerSourceName={alertManagerSourceName} />
86          </Route>
87          <Route exact={true} path="/alerting/notifications/receivers/:name/edit">
88            {({ match }: RouteChildrenProps<{ name: string }>) =>
89              match?.params.name && (
90                <EditReceiverView
91                  alertManagerSourceName={alertManagerSourceName}
92                  config={config}
93                  receiverName={decodeURIComponent(match?.params.name)}
94                />
95              )
96            }
97          </Route>
98          <Route exact={true} path="/alerting/notifications/global-config">
99            <GlobalConfigForm config={config} alertManagerSourceName={alertManagerSourceName} />
100          </Route>
101        </Switch>
102      )}
103    </AlertingPageWrapper>
104  );
105};
106
107export default withErrorBoundary(Receivers, { style: 'page' });
108