2025-03-01 22:36:07 -08:00
import { useState } from "react" ;
import {
Dialog ,
DialogContent ,
DialogActions ,
Button ,
Typography ,
Box ,
Tabs ,
2025-03-07 16:43:29 -08:00
Tab
2025-03-01 22:36:07 -08:00
} from "@mui/material" ;
import { useTheme } from "@emotion/react" ;
2025-03-04 15:56:09 -08:00
import TextInput from "../Inputs/TextInput" ;
import Checkbox from "../Inputs/Checkbox" ;
2025-03-07 16:56:00 -08:00
import TabPanel from "./TabPanel" ;
2025-03-01 22:36:07 -08:00
const NotificationIntegrationModal = ({
open ,
onClose ,
monitor ,
setMonitor
}) => {
const theme = useTheme ();
const [ tabValue , setTabValue ] = useState ( 0 );
const [ integrations , setIntegrations ] = useState ({
slack : monitor ? . notifications ? . some ( n => n . type === "slack" ) || false ,
slackWebhook : monitor ? . notifications ? . find ( n => n . type === "slack" ) ? . webhook || "" ,
discord : monitor ? . notifications ? . some ( n => n . type === "discord" ) || false ,
discordWebhook : monitor ? . notifications ? . find ( n => n . type === "discord" ) ? . webhook || "" ,
telegram : monitor ? . notifications ? . some ( n => n . type === "telegram" ) || false ,
telegramToken : monitor ? . notifications ? . find ( n => n . type === "telegram" ) ? . token || "" ,
telegramChatId : monitor ? . notifications ? . find ( n => n . type === "telegram" ) ? . chatId || "" ,
webhook : monitor ? . notifications ? . some ( n => n . type === "webhook" ) || false ,
webhookUrl : monitor ? . notifications ? . find ( n => n . type === "webhook" ) ? . url || "" ,
});
const handleChangeTab = ( event , newValue ) => {
setTabValue ( newValue );
};
const handleIntegrationChange = ( type , checked ) => {
setIntegrations ( prev => ({
... prev ,
[ type ] : checked
}));
};
const handleInputChange = ( type , value ) => {
setIntegrations ( prev => ({
... prev ,
[ type ] : value
}));
};
const handleTestNotification = ( type ) => {
console . log ( `Testing ${ type } notification` );
2025-03-04 15:56:09 -08:00
//implement the test notification functionality
2025-03-01 22:36:07 -08:00
};
const handleSave = () => {
2025-03-04 15:56:09 -08:00
//notifications array for selected integrations
2025-03-01 22:36:07 -08:00
const notifications = [...( monitor ? . notifications || [])];
const existingTypes = [ "slack" , "discord" , "telegram" , "webhook" ];
const filteredNotifications = notifications . filter (
notification => ! existingTypes . includes ( notification . type )
);
if ( integrations . slack ) {
filteredNotifications . push ({
type : "slack" ,
webhook : integrations . slackWebhook
});
}
if ( integrations . discord ) {
filteredNotifications . push ({
type : "discord" ,
webhook : integrations . discordWebhook
});
}
if ( integrations . telegram ) {
filteredNotifications . push ({
type : "telegram" ,
token : integrations . telegramToken ,
chatId : integrations . telegramChatId
});
}
if ( integrations . webhook ) {
filteredNotifications . push ({
type : "webhook" ,
url : integrations . webhookUrl
});
}
// Update monitor with new notifications
setMonitor ( prev => ({
... prev ,
notifications : filteredNotifications
}));
onClose ();
};
return (
< Dialog
open = { open }
onClose = { onClose }
fullWidth
maxWidth = "md"
sx = {{
'& .MuiDialog-paper' : {
2025-03-04 15:56:09 -08:00
maxWidth : '775px'
2025-03-01 22:36:07 -08:00
}
}}
>
< DialogContent >
2025-03-04 15:56:09 -08:00
< Box sx = {{ display : 'flex' , height : '300px' }}>
2025-03-01 22:36:07 -08:00
{ /* Left sidebar with tabs */ }
< Box sx = {{
borderRight : 1 ,
borderColor : 'divider' ,
minWidth : '200px' ,
2025-03-06 17:56:30 -08:00
pr : theme . spacing ( 10 )
2025-03-01 22:36:07 -08:00
}}>
2025-03-06 17:56:30 -08:00
< Typography variant = "subtitle1" sx = {{
my : theme . spacing ( 1 ),
fontWeight : 'bold' ,
fontSize : '0.9rem' ,
color : theme . palette . primary . contrastTextSecondary
}}>
Add or edit notifications
2025-03-01 22:36:07 -08:00
</ Typography >
< Tabs
orientation = "vertical"
variant = "scrollable"
value = { tabValue }
onChange = { handleChangeTab }
aria - label = "Notification tabs"
>
2025-03-06 17:16:45 -08:00
< Tab label = "Slack" orientation = "vertical" />
< Tab label = "Discord" orientation = "vertical" />
< Tab label = "Telegram" orientation = "vertical" />
< Tab label = "Webhooks" orientation = "vertical" />
2025-03-01 22:36:07 -08:00
</ Tabs >
</ Box >
{ /* Right side content */ }
2025-03-06 17:56:30 -08:00
< Box sx = {{ flex : 1 , pl : theme . spacing ( 7.5 ) }}>
2025-03-01 22:36:07 -08:00
{ /* Slack Tab */ }
< TabPanel value = { tabValue } index = { 0 }>
2025-03-06 17:56:30 -08:00
< Typography variant = "subtitle1" component = "h4" sx = {{
fontWeight : 'bold' ,
color : theme . palette . primary . contrastTextSecondary
}}> Slack </ Typography >
< Typography sx = {{
mt : theme . spacing ( 0.5 ),
mb : theme . spacing ( 1.5 ),
color : theme . palette . primary . contrastTextTertiary
}}>
2025-03-01 22:36:07 -08:00
To enable Slack notifications , create a Slack app and enable incoming webhooks . After that , simply provide the webhook URL here .
</ Typography >
2025-03-06 17:56:30 -08:00
< Box sx = {{ pl : theme . spacing ( 1.5 ) }}>
< Checkbox
id = "enable-slack"
label = "Enable Slack notifications"
isChecked = { integrations . slack }
onChange = {( e ) => handleIntegrationChange ( 'slack' , e . target . checked )}
/>
</ Box >
2025-03-01 22:36:07 -08:00
2025-03-06 17:56:30 -08:00
< Box sx = {{ mt : theme . spacing ( 1 ) }}>
< Typography sx = {{
mb : theme . spacing ( 2 ),
fontWeight : 'bold' ,
color : theme . palette . primary . contrastTextSecondary
}}> Webhook URL </ Typography >
2025-03-01 22:36:07 -08:00
< TextInput
id = "slack-webhook"
type = "text"
placeholder = "https://hooks.slack.com/services/..."
value = { integrations . slackWebhook }
onChange = {( e ) => handleInputChange ( 'slackWebhook' , e . target . value )}
disabled = { ! integrations . slack }
/>
</ Box >
2025-03-06 17:56:30 -08:00
< Box sx = {{ mt : theme . spacing ( 1 ) }}>
2025-03-01 22:36:07 -08:00
< Button
variant = "text"
color = "info"
onClick = {() => handleTestNotification ( 'slack' )}
disabled = { ! integrations . slack || ! integrations . slackWebhook }
>
Test notification
</ Button >
</ Box >
</ TabPanel >
{ /* Discord Tab */ }
< TabPanel value = { tabValue } index = { 1 }>
2025-03-06 17:56:30 -08:00
< Typography variant = "subtitle1" component = "h4" sx = {{
fontWeight : 'bold' ,
color : theme . palette . primary . contrastTextSecondary
}}> Discord </ Typography >
< Typography sx = {{
mt : theme . spacing ( 0.5 ),
mb : theme . spacing ( 1.5 ),
color : theme . palette . primary . contrastTextTertiary
}}>
2025-03-01 22:36:07 -08:00
To send data to a Discord channel from Checkmate via Discord notifications using webhooks , you can use Discord 's incoming Webhooks feature.
</Typography>
2025-03-06 17:56:30 -08:00
<Box sx={{ pl: theme.spacing(1.5) }}>
2025-03-01 22:36:07 -08:00
<Checkbox
id="enable-discord"
label="Enable Discord notifications"
isChecked={integrations.discord}
onChange={(e) => handleIntegrationChange(' discord ', e.target.checked)}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
<Typography sx={{
mb: theme.spacing(2),
fontWeight: ' bold ',
color: theme.palette.primary.contrastTextSecondary
}}>Discord Webhook URL</Typography>
2025-03-01 22:36:07 -08:00
<TextInput
id="discord-webhook"
type="text"
placeholder="https://discord.com/api/webhooks/..."
value={integrations.discordWebhook}
onChange={(e) => handleInputChange(' discordWebhook ', e.target.value)}
disabled={!integrations.discord}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
2025-03-01 22:36:07 -08:00
<Button
variant="text"
color="info"
onClick={() => handleTestNotification(' discord ')}
disabled={!integrations.discord || !integrations.discordWebhook}
>
Test notification
</Button>
</Box>
</TabPanel>
{/* Telegram Tab */}
<TabPanel value={tabValue} index={2}>
2025-03-06 17:56:30 -08:00
<Typography variant="subtitle1" component="h4" sx={{
fontWeight: ' bold ',
color: theme.palette.primary.contrastTextSecondary
}}>Telegram</Typography>
<Typography sx={{
mt: theme.spacing(0.5),
mb: theme.spacing(1.5),
color: theme.palette.primary.contrastTextTertiary
}}>
2025-03-01 22:36:07 -08:00
To enable Telegram notifications, create a Telegram bot using BotFather, an official bot for creating and managing Telegram bots. Then, get the API token and chat ID and write them down here.
</Typography>
2025-03-06 17:56:30 -08:00
<Box sx={{ pl: theme.spacing(1.5) }}>
2025-03-01 22:36:07 -08:00
<Checkbox
id="enable-telegram"
label="Enable Telegram notifications"
isChecked={integrations.telegram}
onChange={(e) => handleIntegrationChange(' telegram ', e.target.checked)}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
<Typography sx={{
mb: theme.spacing(2),
fontWeight: ' bold ',
color: theme.palette.primary.contrastTextSecondary
}}>Your bot token</Typography>
2025-03-01 22:36:07 -08:00
<TextInput
id="telegram-token"
type="text"
placeholder="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
value={integrations.telegramToken}
onChange={(e) => handleInputChange(' telegramToken ', e.target.value)}
disabled={!integrations.telegram}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
<Typography sx={{
mb: theme.spacing(2),
fontWeight: ' bold ',
color: theme.palette.primary.contrastTextSecondary
}}>Your Chat ID</Typography>
2025-03-01 22:36:07 -08:00
<TextInput
id="telegram-chat-id"
type="text"
placeholder="-1001234567890"
value={integrations.telegramChatId}
onChange={(e) => handleInputChange(' telegramChatId ', e.target.value)}
disabled={!integrations.telegram}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
2025-03-01 22:36:07 -08:00
<Button
variant="text"
color="info"
onClick={() => handleTestNotification(' telegram ')}
disabled={!integrations.telegram || !integrations.telegramToken || !integrations.telegramChatId}
>
Test notification
</Button>
</Box>
</TabPanel>
{/* Webhooks Tab */}
<TabPanel value={tabValue} index={3}>
2025-03-06 17:56:30 -08:00
<Typography variant="subtitle1" component="h4" sx={{
fontWeight: ' bold ',
color: theme.palette.primary.contrastTextSecondary
}}>Webhooks</Typography>
<Typography sx={{
mt: theme.spacing(0.5),
mb: theme.spacing(1.5),
color: theme.palette.primary.contrastTextTertiary
}}>
2025-03-01 22:36:07 -08:00
You can set up a custom webhook to receive notifications when incidents occur.
</Typography>
2025-03-06 17:56:30 -08:00
<Box sx={{ pl: theme.spacing(1.5) }}>
2025-03-01 22:36:07 -08:00
<Checkbox
id="enable-webhook"
label="Enable Webhook notifications"
isChecked={integrations.webhook}
onChange={(e) => handleIntegrationChange(' webhook ', e.target.checked)}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
<Typography sx={{
mb: theme.spacing(2),
fontWeight: ' bold ',
color: theme.palette.primary.contrastTextSecondary
}}>Webhook URL</Typography>
2025-03-01 22:36:07 -08:00
<TextInput
id="webhook-url"
type="text"
placeholder="https://your-server.com/webhook"
value={integrations.webhookUrl}
onChange={(e) => handleInputChange(' webhookUrl ', e.target.value)}
disabled={!integrations.webhook}
/>
</Box>
2025-03-06 17:56:30 -08:00
<Box sx={{ mt: theme.spacing(1) }}>
2025-03-01 22:36:07 -08:00
<Button
variant="text"
color="info"
onClick={() => handleTestNotification(' webhook ')}
disabled={!integrations.webhook || !integrations.webhookUrl}
>
Test notification
</Button>
</Box>
</TabPanel>
</Box>
</Box>
</DialogContent>
2025-03-04 15:56:09 -08:00
<DialogActions sx={{
p: theme.spacing(4),
display: ' flex ',
justifyContent: ' flex - end ',
2025-03-06 17:56:30 -08:00
mb: theme.spacing(5),
mr: theme.spacing(5)
}}>
2025-03-01 22:36:07 -08:00
<Button
variant="contained"
color="accent"
onClick={handleSave}
2025-03-04 15:56:09 -08:00
sx={{
width: ' 120 px '
}}
2025-03-01 22:36:07 -08:00
>
Save
</ Button >
</ DialogActions >
</ Dialog >
);
};
export default NotificationIntegrationModal ;