@@ -8,13 +8,14 @@ import ListItemText, { listItemTextClasses } from "@mui/material/ListItemText";
8
8
import ToggleButton from "@mui/material/ToggleButton" ;
9
9
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup" ;
10
10
import Tooltip from "@mui/material/Tooltip" ;
11
+ import { getErrorMessage } from "api/errors" ;
11
12
import {
12
13
type selectTemplatesByGroup ,
13
14
updateNotificationTemplateMethod ,
14
15
} from "api/queries/notifications" ;
15
16
import type { DeploymentValues } from "api/typesGenerated" ;
16
17
import { Alert } from "components/Alert/Alert" ;
17
- import { displaySuccess } from "components/GlobalSnackbar/utils" ;
18
+ import { displayError , displaySuccess } from "components/GlobalSnackbar/utils" ;
18
19
import { Stack } from "components/Stack/Stack" ;
19
20
import {
20
21
type NotificationMethod ,
@@ -39,58 +40,67 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
39
40
templatesByGroup,
40
41
deploymentValues,
41
42
} ) => {
43
+ // Webhook
42
44
const hasWebhookNotifications = Object . values ( templatesByGroup )
43
45
. flat ( )
44
46
. 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 )
46
54
. flat ( )
47
55
. some ( ( t ) => t . method === "smtp" ) ;
56
+ const smtpValues = deploymentValues . notifications ?. email ?? { } ;
57
+ const isSMTPConfigured = requiredFieldsArePresent ( smtpValues , [
58
+ "smarthost" ,
59
+ "from" ,
60
+ "hello" ,
61
+ ] ) ;
48
62
49
63
return (
50
64
< 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
+ ) }
72
84
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
+ ) }
94
104
95
105
{ Object . entries ( templatesByGroup ) . map ( ( [ group , templates ] ) => (
96
106
< Card
@@ -131,6 +141,13 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
131
141
) ;
132
142
} ;
133
143
144
+ function requiredFieldsArePresent (
145
+ obj : Record < string , string | undefined > ,
146
+ fields : string [ ] ,
147
+ ) : boolean {
148
+ return fields . every ( ( field ) => Boolean ( obj [ field ] ) ) ;
149
+ }
150
+
134
151
type MethodToggleGroupProps = {
135
152
templateId : string ;
136
153
options : NotificationMethod [ ] ;
@@ -155,10 +172,16 @@ const MethodToggleGroup: FC<MethodToggleGroupProps> = ({
155
172
aria-label = "Notification method"
156
173
css = { styles . toggleGroup }
157
174
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
+ }
162
185
} }
163
186
>
164
187
{ options . map ( ( method ) => {
0 commit comments