Skip to content

Commit f54c435

Browse files
committed
Apply fixes and improvements suggested by @dannykopping
1 parent c4d4afb commit f54c435

File tree

3 files changed

+101
-51
lines changed

3 files changed

+101
-51
lines changed

site/src/pages/DeploySettingsPage/NotificationsPage/NotificationEvents.stories.tsx

+28-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default meta;
2323

2424
type Story = StoryObj<typeof NotificationEvents>;
2525

26-
export const NoEmailSmarthost: Story = {
26+
export const SMTPNotConfigured: Story = {
2727
args: {
2828
deploymentValues: {
2929
notifications: {
@@ -38,7 +38,7 @@ export const NoEmailSmarthost: Story = {
3838
},
3939
};
4040

41-
export const NoWebhookEndpoint: Story = {
41+
export const WebhookNotConfigured: Story = {
4242
args: {
4343
deploymentValues: {
4444
notifications: {
@@ -47,6 +47,8 @@ export const NoWebhookEndpoint: Story = {
4747
},
4848
email: {
4949
smarthost: "smtp.example.com",
50+
from: "localhost",
51+
hello: "localhost",
5052
},
5153
},
5254
} as DeploymentValues,
@@ -58,7 +60,8 @@ export const Toggle: Story = {
5860
spyOn(API, "updateNotificationTemplateMethod").mockResolvedValue();
5961
const user = userEvent.setup();
6062
const canvas = within(canvasElement);
61-
const option = await canvas.findByText("Workspace Marked as Dormant");
63+
const tmpl = MockNotificationTemplates[4];
64+
const option = await canvas.findByText(tmpl.name);
6265
const li = option.closest("li");
6366
if (!li) {
6467
throw new Error("Could not find li");
@@ -67,5 +70,27 @@ export const Toggle: Story = {
6770
name: "Webhook",
6871
});
6972
await user.click(toggleButton);
73+
await within(document.body).findByText("Notification method updated");
74+
},
75+
};
76+
77+
export const ToggleError: Story = {
78+
play: async ({ canvasElement }) => {
79+
spyOn(API, "updateNotificationTemplateMethod").mockRejectedValue({});
80+
const user = userEvent.setup();
81+
const canvas = within(canvasElement);
82+
const tmpl = MockNotificationTemplates[4];
83+
const option = await canvas.findByText(tmpl.name);
84+
const li = option.closest("li");
85+
if (!li) {
86+
throw new Error("Could not find li");
87+
}
88+
const toggleButton = within(li).getByRole("button", {
89+
name: "Webhook",
90+
});
91+
await user.click(toggleButton);
92+
await within(document.body).findByText(
93+
"Failed to update notification method",
94+
);
7095
},
7196
};

site/src/pages/DeploySettingsPage/NotificationsPage/NotificationEvents.tsx

+71-48
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import ListItemText, { listItemTextClasses } from "@mui/material/ListItemText";
88
import ToggleButton from "@mui/material/ToggleButton";
99
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
1010
import Tooltip from "@mui/material/Tooltip";
11+
import { getErrorMessage } from "api/errors";
1112
import {
1213
type selectTemplatesByGroup,
1314
updateNotificationTemplateMethod,
1415
} from "api/queries/notifications";
1516
import type { DeploymentValues } from "api/typesGenerated";
1617
import { Alert } from "components/Alert/Alert";
17-
import { displaySuccess } from "components/GlobalSnackbar/utils";
18+
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
1819
import { Stack } from "components/Stack/Stack";
1920
import {
2021
type NotificationMethod,
@@ -39,58 +40,67 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
3940
templatesByGroup,
4041
deploymentValues,
4142
}) => {
43+
// Webhook
4244
const hasWebhookNotifications = Object.values(templatesByGroup)
4345
.flat()
4446
.some((t) => t.method === "webhook");
45-
const hasEmailNotifications = Object.values(templatesByGroup)
47+
const webhookValues = deploymentValues.notifications?.webhook ?? {};
48+
const isWebhookConfigured = requiredFieldsArePresent(webhookValues, [
49+
"endpoint",
50+
]);
51+
52+
// SMTP
53+
const hasSMTPNotifications = Object.values(templatesByGroup)
4654
.flat()
4755
.some((t) => t.method === "smtp");
56+
const smtpValues = deploymentValues.notifications?.email ?? {};
57+
const isSMTPConfigured = requiredFieldsArePresent(smtpValues, [
58+
"smarthost",
59+
"from",
60+
"hello",
61+
]);
4862

4963
return (
5064
<Stack spacing={4}>
51-
{hasWebhookNotifications &&
52-
deploymentValues.notifications?.webhook.endpoint === "" && (
53-
<Alert
54-
severity="warning"
55-
actions={
56-
<Button
57-
variant="text"
58-
size="small"
59-
component="a"
60-
target="_blank"
61-
rel="noreferrer"
62-
href={docs("/cli/server#--notifications-webhook-endpoint")}
63-
>
64-
Read the docs
65-
</Button>
66-
}
67-
>
68-
Webhook notifications are enabled, but no endpoint has been
69-
configured.
70-
</Alert>
71-
)}
65+
{hasWebhookNotifications && !isWebhookConfigured && (
66+
<Alert
67+
severity="warning"
68+
actions={
69+
<Button
70+
variant="text"
71+
size="small"
72+
component="a"
73+
target="_blank"
74+
rel="noreferrer"
75+
href={docs("/admin/notifications#webhook")}
76+
>
77+
Read the docs
78+
</Button>
79+
}
80+
>
81+
Webhook notifications are enabled, but not properly configured.
82+
</Alert>
83+
)}
7284

73-
{hasEmailNotifications &&
74-
deploymentValues.notifications?.email.smarthost === "" && (
75-
<Alert
76-
severity="warning"
77-
actions={
78-
<Button
79-
variant="text"
80-
size="small"
81-
component="a"
82-
target="_blank"
83-
rel="noreferrer"
84-
href={docs("/cli/server#--notifications-email-smarthost")}
85-
>
86-
Read the docs
87-
</Button>
88-
}
89-
>
90-
SMTP notifications are enabled, but no smarthost has been
91-
configured.
92-
</Alert>
93-
)}
85+
{hasSMTPNotifications && !isSMTPConfigured && (
86+
<Alert
87+
severity="warning"
88+
actions={
89+
<Button
90+
variant="text"
91+
size="small"
92+
component="a"
93+
target="_blank"
94+
rel="noreferrer"
95+
href={docs("/admin/notifications#smtp-email")}
96+
>
97+
Read the docs
98+
</Button>
99+
}
100+
>
101+
SMTP notifications are enabled but not properly configured.
102+
</Alert>
103+
)}
94104

95105
{Object.entries(templatesByGroup).map(([group, templates]) => (
96106
<Card
@@ -131,6 +141,13 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
131141
);
132142
};
133143

144+
function requiredFieldsArePresent(
145+
obj: Record<string, string | undefined>,
146+
fields: string[],
147+
): boolean {
148+
return fields.every((field) => Boolean(obj[field]));
149+
}
150+
134151
type MethodToggleGroupProps = {
135152
templateId: string;
136153
options: NotificationMethod[];
@@ -155,10 +172,16 @@ const MethodToggleGroup: FC<MethodToggleGroupProps> = ({
155172
aria-label="Notification method"
156173
css={styles.toggleGroup}
157174
onChange={async (_, method) => {
158-
await updateMethodMutation.mutateAsync({
159-
method,
160-
});
161-
displaySuccess("Notification method updated");
175+
try {
176+
await updateMethodMutation.mutateAsync({
177+
method,
178+
});
179+
displaySuccess("Notification method updated");
180+
} catch (error) {
181+
displayError(
182+
getErrorMessage(error, "Failed to update notification method"),
183+
);
184+
}
162185
}}
163186
>
164187
{options.map((method) => {

site/src/pages/DeploySettingsPage/NotificationsPage/storybookUtils.ts

+2
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ export const baseMeta = {
203203
},
204204
email: {
205205
smarthost: "smtp.example.com",
206+
from: "localhost",
207+
hello: "localhost",
206208
},
207209
},
208210
} as DeploymentValues,

0 commit comments

Comments
 (0)