1
1
import { useState , useMemo } from "react" ;
2
2
import { useTranslation } from "react-i18next" ;
3
+
3
4
import {
4
5
Dialog ,
5
6
DialogContent ,
@@ -8,11 +9,29 @@ import {
8
9
Typography ,
9
10
Box ,
10
11
Tabs ,
11
- Tab
12
+ Tab ,
13
+ CircularProgress
12
14
} from "@mui/material" ;
13
15
import { useTheme } from "@emotion/react" ;
14
16
import TabPanel from "./TabPanel" ;
15
17
import TabComponent from "./TabComponent" ;
18
+ import useNotifications from "../Hooks/useNotification" ;
19
+
20
+ // Define constants for notification types to avoid magic values
21
+ const NOTIFICATION_TYPES = {
22
+ SLACK : 'slack' ,
23
+ DISCORD : 'discord' ,
24
+ TELEGRAM : 'telegram' ,
25
+ WEBHOOK : 'webhook'
26
+ } ;
27
+
28
+ // Define constants for field IDs
29
+ const FIELD_IDS = {
30
+ WEBHOOK : 'webhook' ,
31
+ TOKEN : 'token' ,
32
+ CHAT_ID : 'chatId' ,
33
+ URL : 'url'
34
+ } ;
16
35
17
36
const NotificationIntegrationModal = ( {
18
37
open,
@@ -26,60 +45,75 @@ const NotificationIntegrationModal = ({
26
45
const theme = useTheme ( ) ;
27
46
const [ tabValue , setTabValue ] = useState ( 0 ) ;
28
47
48
+ const [ loading , _ , sendTestNotification ] = useNotifications ( ) ;
49
+
50
+ // Helper to get the field state key with error handling
51
+ const getFieldKey = ( typeId , fieldId ) => {
52
+ if ( typeof typeId !== 'string' || typeId === '' ) {
53
+ throw new Error ( 'Invalid typeId provided to getFieldKey' ) ;
54
+ }
55
+
56
+ if ( typeof fieldId !== 'string' || fieldId === '' ) {
57
+ throw new Error ( 'Invalid fieldId provided to getFieldKey' ) ;
58
+ }
59
+
60
+ return `${ typeId } ${ fieldId . charAt ( 0 ) . toUpperCase ( ) + fieldId . slice ( 1 ) } ` ;
61
+ } ;
62
+
29
63
// Define notification types
30
64
const DEFAULT_NOTIFICATION_TYPES = [
31
65
{
32
- id : 'slack' ,
66
+ id : NOTIFICATION_TYPES . SLACK ,
33
67
label : t ( 'notifications.slack.label' ) ,
34
68
description : t ( 'notifications.slack.description' ) ,
35
69
fields : [
36
70
{
37
- id : 'webhook' ,
71
+ id : FIELD_IDS . WEBHOOK ,
38
72
label : t ( 'notifications.slack.webhookLabel' ) ,
39
73
placeholder : t ( 'notifications.slack.webhookPlaceholder' ) ,
40
74
type : 'text'
41
75
}
42
76
]
43
77
} ,
44
78
{
45
- id : 'discord' ,
79
+ id : NOTIFICATION_TYPES . DISCORD ,
46
80
label : t ( 'notifications.discord.label' ) ,
47
81
description : t ( 'notifications.discord.description' ) ,
48
82
fields : [
49
83
{
50
- id : 'webhook' ,
84
+ id : FIELD_IDS . WEBHOOK ,
51
85
label : t ( 'notifications.discord.webhookLabel' ) ,
52
86
placeholder : t ( 'notifications.discord.webhookPlaceholder' ) ,
53
87
type : 'text'
54
88
}
55
89
]
56
90
} ,
57
91
{
58
- id : 'telegram' ,
92
+ id : NOTIFICATION_TYPES . TELEGRAM ,
59
93
label : t ( 'notifications.telegram.label' ) ,
60
94
description : t ( 'notifications.telegram.description' ) ,
61
95
fields : [
62
96
{
63
- id : 'token' ,
97
+ id : FIELD_IDS . TOKEN ,
64
98
label : t ( 'notifications.telegram.tokenLabel' ) ,
65
99
placeholder : t ( 'notifications.telegram.tokenPlaceholder' ) ,
66
100
type : 'text'
67
101
} ,
68
102
{
69
- id : 'chatId' ,
103
+ id : FIELD_IDS . CHAT_ID ,
70
104
label : t ( 'notifications.telegram.chatIdLabel' ) ,
71
105
placeholder : t ( 'notifications.telegram.chatIdPlaceholder' ) ,
72
106
type : 'text'
73
107
}
74
108
]
75
109
} ,
76
110
{
77
- id : 'webhook' ,
111
+ id : NOTIFICATION_TYPES . WEBHOOK ,
78
112
label : t ( 'notifications.webhook.label' ) ,
79
113
description : t ( 'notifications.webhook.description' ) ,
80
114
fields : [
81
115
{
82
- id : 'url' ,
116
+ id : FIELD_IDS . URL ,
83
117
label : t ( 'notifications.webhook.urlLabel' ) ,
84
118
placeholder : t ( 'notifications.webhook.urlPlaceholder' ) ,
85
119
type : 'text'
@@ -101,7 +135,7 @@ const NotificationIntegrationModal = ({
101
135
102
136
// Add state for each field in the notification type
103
137
type . fields . forEach ( field => {
104
- const fieldKey = ` ${ type . id } ${ field . id . charAt ( 0 ) . toUpperCase ( ) + field . id . slice ( 1 ) } ` ;
138
+ const fieldKey = getFieldKey ( type . id , field . id ) ;
105
139
state [ fieldKey ] = monitor ?. notifications ?. find ( n => n . type === type . id ) ?. [ field . id ] || "" ;
106
140
} ) ;
107
141
} ) ;
@@ -129,11 +163,26 @@ const NotificationIntegrationModal = ({
129
163
} ) ) ;
130
164
} ;
131
165
132
- const handleTestNotification = ( type ) => {
133
- console . log ( `Testing ${ type } notification` ) ;
134
- //implement the test notification functionality
166
+ const handleTestNotification = async ( type ) => {
167
+ // Get the notification type details
168
+ const notificationType = activeNotificationTypes . find ( t => t . id === type ) ;
169
+
170
+ if ( typeof notificationType === "undefined" ) {
171
+ return ;
172
+ }
173
+
174
+ // Prepare config object based on notification type
175
+ const config = { } ;
176
+
177
+ // Add each field value to the config object
178
+ notificationType . fields . forEach ( field => {
179
+ const fieldKey = getFieldKey ( type , field . id ) ;
180
+ config [ field . id ] = integrations [ fieldKey ] ;
181
+ } ) ;
182
+
183
+ await sendTestNotification ( type , config ) ;
135
184
} ;
136
-
185
+
137
186
const handleSave = ( ) => {
138
187
//notifications array for selected integrations
139
188
const notifications = [ ...( monitor ?. notifications || [ ] ) ] ;
@@ -155,7 +204,7 @@ const NotificationIntegrationModal = ({
155
204
156
205
// Add each field value to the notification object
157
206
type . fields . forEach ( field => {
158
- const fieldKey = ` ${ type . id } ${ field . id . charAt ( 0 ) . toUpperCase ( ) + field . id . slice ( 1 ) } ` ;
207
+ const fieldKey = getFieldKey ( type . id , field . id ) ;
159
208
notificationObject [ field . id ] = integrations [ fieldKey ] ;
160
209
} ) ;
161
210
@@ -240,6 +289,7 @@ const NotificationIntegrationModal = ({
240
289
handleIntegrationChange = { handleIntegrationChange }
241
290
handleInputChange = { handleInputChange }
242
291
handleTestNotification = { handleTestNotification }
292
+ isLoading = { loading }
243
293
/>
244
294
</ TabPanel >
245
295
) ) }
@@ -257,13 +307,14 @@ const NotificationIntegrationModal = ({
257
307
variant = "contained"
258
308
color = "accent"
259
309
onClick = { handleSave }
310
+ loading = { loading }
260
311
sx = { {
261
312
width : 'auto' ,
262
313
minWidth : theme . spacing ( 60 ) ,
263
314
px : theme . spacing ( 8 )
264
315
} }
265
316
>
266
- { t ( 'common.save' , 'Save ') }
317
+ { t ( 'commonSave ' ) }
267
318
</ Button >
268
319
</ DialogActions >
269
320
</ Dialog >
0 commit comments