Skip to content

Commit e8a7b7e

Browse files
authored
feat: add notifications troubleshooting tab (#16650)
1 parent fcc9b05 commit e8a7b7e

File tree

4 files changed

+137
-39
lines changed

4 files changed

+137
-39
lines changed

site/src/api/api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,6 +2297,10 @@ class ApiMethods {
22972297
return res.data;
22982298
};
22992299

2300+
postTestNotification = async () => {
2301+
await this.axios.post<void>("/api/v2/notifications/test");
2302+
};
2303+
23002304
requestOneTimePassword = async (
23012305
req: TypesGen.RequestOneTimePasscodeRequest,
23022306
) => {

site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationsPage.tsx

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import {
44
selectTemplatesByGroup,
55
systemNotificationTemplates,
66
} from "api/queries/notifications";
7+
import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge";
78
import { Loader } from "components/Loader/Loader";
9+
import { SettingsHeader } from "components/SettingsHeader/SettingsHeader";
810
import { TabLink, Tabs, TabsList } from "components/Tabs/Tabs";
911
import { useSearchParamsKey } from "hooks/useSearchParamsKey";
1012
import { useDeploymentSettings } from "modules/management/DeploymentSettingsProvider";
@@ -14,9 +16,11 @@ import type { FC } from "react";
1416
import { Helmet } from "react-helmet-async";
1517
import { useQueries } from "react-query";
1618
import { deploymentGroupHasParent } from "utils/deployOptions";
19+
import { docs } from "utils/docs";
1720
import { pageTitle } from "utils/page";
1821
import OptionsTable from "../OptionsTable";
1922
import { NotificationEvents } from "./NotificationEvents";
23+
import { Troubleshooting } from "./Troubleshooting";
2024

2125
export const NotificationsPage: FC = () => {
2226
const { deploymentConfig } = useDeploymentSettings();
@@ -40,48 +44,62 @@ export const NotificationsPage: FC = () => {
4044
<Helmet>
4145
<title>{pageTitle("Notifications Settings")}</title>
4246
</Helmet>
43-
<Section
44-
title="Notifications"
47+
<SettingsHeader
48+
title={
49+
<>
50+
Notifications
51+
<span css={{ position: "relative", top: "-6px" }}>
52+
<FeatureStageBadge
53+
contentType={"beta"}
54+
size="lg"
55+
css={{ marginBottom: "5px", fontSize: "0.75rem" }}
56+
/>
57+
</span>
58+
</>
59+
}
4560
description="Control delivery methods for notifications on this deployment."
46-
layout="fluid"
47-
featureStage={"beta"}
48-
>
49-
<Tabs active={tabState.value}>
50-
<TabsList>
51-
<TabLink to="?tab=events" value="events">
52-
Events
53-
</TabLink>
54-
<TabLink to="?tab=settings" value="settings">
55-
Settings
56-
</TabLink>
57-
</TabsList>
58-
</Tabs>
61+
docsHref={docs("/admin/monitoring/notifications")}
62+
/>
63+
<Tabs active={tabState.value}>
64+
<TabsList>
65+
<TabLink to="?tab=events" value="events">
66+
Events
67+
</TabLink>
68+
<TabLink to="?tab=settings" value="settings">
69+
Settings
70+
</TabLink>
71+
<TabLink to="?tab=troubleshooting" value="troubleshooting">
72+
Troubleshooting
73+
</TabLink>
74+
</TabsList>
75+
</Tabs>
5976

60-
<div css={styles.content}>
61-
{ready ? (
62-
tabState.value === "events" ? (
63-
<NotificationEvents
64-
templatesByGroup={templatesByGroup.data}
65-
deploymentConfig={deploymentConfig.config}
66-
defaultMethod={castNotificationMethod(
67-
dispatchMethods.data.default,
68-
)}
69-
availableMethods={dispatchMethods.data.available.map(
70-
castNotificationMethod,
71-
)}
72-
/>
73-
) : (
74-
<OptionsTable
75-
options={deploymentConfig.options.filter((o) =>
76-
deploymentGroupHasParent(o.group, "Notifications"),
77-
)}
78-
/>
79-
)
77+
<div css={styles.content}>
78+
{ready ? (
79+
tabState.value === "events" ? (
80+
<NotificationEvents
81+
templatesByGroup={templatesByGroup.data}
82+
deploymentConfig={deploymentConfig.config}
83+
defaultMethod={castNotificationMethod(
84+
dispatchMethods.data.default,
85+
)}
86+
availableMethods={dispatchMethods.data.available.map(
87+
castNotificationMethod,
88+
)}
89+
/>
90+
) : tabState.value === "troubleshooting" ? (
91+
<Troubleshooting />
8092
) : (
81-
<Loader />
82-
)}
83-
</div>
84-
</Section>
93+
<OptionsTable
94+
options={deploymentConfig.options.filter((o) =>
95+
deploymentGroupHasParent(o.group, "Notifications"),
96+
)}
97+
/>
98+
)
99+
) : (
100+
<Loader />
101+
)}
102+
</div>
85103
</>
86104
);
87105
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { spyOn, userEvent, within } from "@storybook/test";
3+
import { API } from "api/api";
4+
import { Troubleshooting } from "./Troubleshooting";
5+
import { baseMeta } from "./storybookUtils";
6+
7+
const meta: Meta<typeof Troubleshooting> = {
8+
title: "pages/DeploymentSettingsPage/NotificationsPage/Troubleshooting",
9+
component: Troubleshooting,
10+
...baseMeta,
11+
};
12+
13+
export default meta;
14+
15+
type Story = StoryObj<typeof Troubleshooting>;
16+
17+
export const TestNotification: Story = {
18+
play: async ({ canvasElement }) => {
19+
spyOn(API, "postTestNotification").mockResolvedValue();
20+
const user = userEvent.setup();
21+
const canvas = within(canvasElement);
22+
23+
const sendButton = canvas.getByRole("button", {
24+
name: "Send notification",
25+
});
26+
await user.click(sendButton);
27+
await within(document.body).findByText("Test notification sent");
28+
},
29+
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useTheme } from "@emotion/react";
2+
import LoadingButton from "@mui/lab/LoadingButton";
3+
import { API } from "api/api";
4+
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
5+
import type { FC } from "react";
6+
import { useMutation } from "react-query";
7+
8+
export const Troubleshooting: FC = () => {
9+
const { mutate: sendTestNotificationApi, isLoading } = useMutation(
10+
API.postTestNotification,
11+
{
12+
onSuccess: () => displaySuccess("Test notification sent"),
13+
onError: () => displayError("Failed to send test notification"),
14+
},
15+
);
16+
17+
const theme = useTheme();
18+
return (
19+
<>
20+
<div
21+
css={{
22+
fontSize: 14,
23+
color: theme.palette.text.secondary,
24+
lineHeight: "160%",
25+
marginBottom: 16,
26+
}}
27+
>
28+
Send a test notification to troubleshoot your notification settings.
29+
</div>
30+
<div>
31+
<span>
32+
<LoadingButton
33+
variant="outlined"
34+
loading={isLoading}
35+
size="small"
36+
css={{ minWidth: "auto", aspectRatio: "1" }}
37+
onClick={() => {
38+
sendTestNotificationApi();
39+
}}
40+
>
41+
Send notification
42+
</LoadingButton>
43+
</span>
44+
</div>
45+
</>
46+
);
47+
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy