From b44d1429202f0539c88bc262e0d641a508b9ad7a Mon Sep 17 00:00:00 2001 From: Skorpios Date: Sat, 1 Mar 2025 22:36:07 -0800 Subject: [PATCH] Implemented notification modal. --- src/Pages/Uptime/Create/index.jsx | 15 +- .../NotificationIntegrationModal.jsx | 413 ++++++++++++++++++ 2 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 src/Pages/Uptime/Details/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx diff --git a/src/Pages/Uptime/Create/index.jsx b/src/Pages/Uptime/Create/index.jsx index edad33d20..b9bb7eb8f 100644 --- a/src/Pages/Uptime/Create/index.jsx +++ b/src/Pages/Uptime/Create/index.jsx @@ -23,6 +23,7 @@ import Radio from "../../../Components/Inputs/Radio"; import Checkbox from "../../../Components/Inputs/Checkbox"; import Select from "../../../Components/Inputs/Select"; import ConfigBox from "../../../Components/ConfigBox"; +import NotificationIntegrationModal from "../Details/Components/NotificationIntegrationModal/NotificationIntegrationModal"; const CreateMonitor = () => { const MS_PER_MINUTE = 60000; const SELECT_VALUES = [ @@ -80,6 +81,11 @@ const CreateMonitor = () => { ]; // State + const [isNotificationModalOpen, setIsNotificationModalOpen] = useState(false); + + const handleOpenNotificationModal = () => { + setIsNotificationModalOpen(true); + }; const [errors, setErrors] = useState({}); const [https, setHttps] = useState(true); const [monitor, setMonitor] = useState({ @@ -411,7 +417,7 @@ const CreateMonitor = () => { @@ -512,6 +518,13 @@ const CreateMonitor = () => { + + setIsNotificationModalOpen(false)} + monitor={monitor} + setMonitor={setMonitor} + /> ); }; diff --git a/src/Pages/Uptime/Details/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx b/src/Pages/Uptime/Details/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx new file mode 100644 index 000000000..eca6a78d0 --- /dev/null +++ b/src/Pages/Uptime/Details/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx @@ -0,0 +1,413 @@ +import { useState } from "react"; +import { + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, + Stack, + Typography, + Box, + Tabs, + Tab, + Divider +} from "@mui/material"; +import { useTheme } from "@emotion/react"; +import TextInput from "../../../../../../src/Components/Inputs/TextInput"; +import Checkbox from "../../../../../../src/Components/Inputs/Checkbox"; + +// Tab Panel component +function TabPanel({ children, value, index, ...other }) { + return ( + + ); +} + +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 testNotificationButtonStyle = { + textDecoration: 'underline', + color: '#344054', + textTransform: 'none', + padding: '0 !important', + margin: 0, + fontSize: '0.9rem', + fontWeight: 'normal', + backgroundColor: 'transparent !important', + '&:hover': { + backgroundColor: 'transparent !important', + textDecoration: 'underline' + }, + '&.Mui-disabled': { + backgroundColor: 'transparent !important' + }, + minWidth: '0 !important', + boxShadow: 'none !important', + border: 'none !important' + }; + + 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`); + // Here you would implement the actual test notification functionality + }; + + const handleSave = () => { + // Create notifications array based on selected integrations + const notifications = [...(monitor?.notifications || [])]; + + // Filter out existing integrations that will be updated + const existingTypes = ["slack", "discord", "telegram", "webhook"]; + const filteredNotifications = notifications.filter( + notification => !existingTypes.includes(notification.type) + ); + + // Add selected integrations + 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 ( + + + + + {/* Left sidebar with tabs */} + + + Add or edit notifications + + + + + + + + + + + {/* Right side content */} + + {/* Slack Tab */} + + Slack + + To enable Slack notifications, create a Slack app and enable incoming webhooks. After that, simply provide the webhook URL here. + + + + handleIntegrationChange('slack', e.target.checked)} + /> + + + + Webhook URL + handleInputChange('slackWebhook', e.target.value)} + disabled={!integrations.slack} + /> + + + + + + + + {/* Discord Tab */} + + Discord + + To send data to a Discord channel from Checkmate via Discord notifications using webhooks, you can use Discord's incoming Webhooks feature. + + + + handleIntegrationChange('discord', e.target.checked)} + /> + + + + Discord Webhook URL + handleInputChange('discordWebhook', e.target.value)} + disabled={!integrations.discord} + /> + + + + + + + + {/* Telegram Tab */} + + Telegram + + 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. + + + + handleIntegrationChange('telegram', e.target.checked)} + /> + + + + Your bot token + handleInputChange('telegramToken', e.target.value)} + disabled={!integrations.telegram} + /> + + + + Your Chat ID + handleInputChange('telegramChatId', e.target.value)} + disabled={!integrations.telegram} + /> + + + + + + + + {/* Webhooks Tab */} + + Webhooks + + You can set up a custom webhook to receive notifications when incidents occur. + + + + handleIntegrationChange('webhook', e.target.checked)} + /> + + + + Webhook URL + handleInputChange('webhookUrl', e.target.value)} + disabled={!integrations.webhook} + /> + + + + + + + + + + + + + + ); +}; + +export default NotificationIntegrationModal; \ No newline at end of file