diff --git a/application/src/components/settings/notification-settings/NotificationChannelDialog.tsx b/application/src/components/settings/notification-settings/NotificationChannelDialog.tsx index 4c7fc6f..c5e62ca 100644 --- a/application/src/components/settings/notification-settings/NotificationChannelDialog.tsx +++ b/application/src/components/settings/notification-settings/NotificationChannelDialog.tsx @@ -9,7 +9,6 @@ import { import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { AlertConfiguration, alertConfigService } from "@/services/alertConfigService"; -import { WebhookConfiguration, webhookService } from "@/services/webhookService"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -62,6 +61,7 @@ const slackSchema = baseSchema.extend({ const signalSchema = baseSchema.extend({ notification_type: z.literal("signal"), signal_number: z.string().min(1, "Signal number is required"), + signal_api_endpoint: z.string().url("Must be a valid API endpoint URL"), }); const googleChatSchema = baseSchema.extend({ @@ -107,19 +107,19 @@ const notificationTypeOptions = [ value: "discord", label: "Discord", description: "Send notifications to Discord webhook", - icon: "/upload/notification/discord.png" + icon: "/upload/notification/discord.png" }, { value: "slack", label: "Slack", description: "Send notifications to Slack webhook", - icon: "/upload/notification/slack.png" + icon: "/upload/notification/slack.png" }, { value: "signal", label: "Signal", description: "Send notifications via Signal", - icon: "/upload/notification/signal.png" + icon: "/upload/notification/signal.png" }, { value: "google_chat", @@ -234,14 +234,6 @@ export const NotificationChannelDialog = ({ onClose(false); }; - const copyToClipboard = (text: string) => { - navigator.clipboard.writeText(text); - toast({ - title: "Copied", - description: "Template copied to clipboard", - }); - }; - const insertTemplate = (template: string) => { setValue("webhook_payload_template", template); }; @@ -249,39 +241,16 @@ export const NotificationChannelDialog = ({ const onSubmit = async (values: FormValues) => { setIsSubmitting(true); try { - if (values.notification_type === "webhook") { - // Handle webhook creation/update with simplified fields - const webhookData: Omit = { - name: values.notify_name, - url: values.webhook_url, - enabled: values.enabled ? "on" : "off", - method: "POST", - secret: "", - headers: "", - description: "", - payload_template: values.webhook_payload_template || defaultPayloadTemplate, - retry_count: "3", - trigger_events: "all", - user_id: "global", - }; - - if (isEditing && editingConfig?.id) { - await webhookService.updateWebhook(editingConfig.id, webhookData); - } else { - await webhookService.createWebhook(webhookData); - } + // Handle all notification types including webhook through alert_configurations + const configData = { + ...values, + service_id: values.service_id || "global", + }; + + if (isEditing && editingConfig?.id) { + await alertConfigService.updateAlertConfiguration(editingConfig.id, configData); } else { - // Handle all other notification types including Google Chat and Email - const configData = { - ...values, - service_id: values.service_id || "global", - }; - - if (isEditing && editingConfig?.id) { - await alertConfigService.updateAlertConfiguration(editingConfig.id, configData); - } else { - await alertConfigService.createAlertConfiguration(configData as any); - } + await alertConfigService.createAlertConfiguration(configData as any); } onClose(true); // Close with refresh @@ -435,22 +404,40 @@ export const NotificationChannelDialog = ({ )} {notificationType === "signal" && ( - ( - - Signal Number - - - - - Signal phone number to send notifications to - - - - )} - /> + <> + ( + + Signal Number + + + + + Signal phone number to send notifications to + + + + )} + /> + ( + + Signal API Endpoint + + + + + The Rest API endpoint for your Signal service + + + + )} + /> + )} {notificationType === "google_chat" && ( diff --git a/application/src/services/alertConfigService.ts b/application/src/services/alertConfigService.ts index 80f899e..7dff9e5 100644 --- a/application/src/services/alertConfigService.ts +++ b/application/src/services/alertConfigService.ts @@ -11,6 +11,7 @@ export interface AlertConfiguration { telegram_chat_id?: string; discord_webhook_url?: string; signal_number?: string; + signal_api_endpoint?: string; notify_name: string; bot_token?: string; template_id?: string; @@ -27,10 +28,14 @@ export interface AlertConfiguration { smtp_password?: string; webhook_id?: string; channel_id?: string; + // Webhook fields for alert_configurations + webhook_url?: string; + webhook_payload_template?: string; } export const alertConfigService = { async getAlertConfigurations(): Promise { + try { const response = await pb.collection('alert_configurations').getList(1, 50); return response.items as AlertConfiguration[]; @@ -45,7 +50,7 @@ export const alertConfigService = { }, async createAlertConfiguration(config: Omit): Promise { - + try { // Build the configuration object with proper field mapping const cleanConfig: any = { @@ -55,7 +60,7 @@ export const alertConfigService = { enabled: config.enabled, template_id: config.template_id || "", }; - + // Add type-specific fields based on notification type if (config.notification_type === "telegram") { cleanConfig.telegram_chat_id = config.telegram_chat_id || ""; @@ -66,24 +71,33 @@ export const alertConfigService = { cleanConfig.slack_webhook_url = config.slack_webhook_url || ""; } else if (config.notification_type === "signal") { cleanConfig.signal_number = config.signal_number || ""; + cleanConfig.signal_api_endpoint = config.signal_api_endpoint || ""; } else if (config.notification_type === "google_chat") { cleanConfig.google_chat_webhook_url = config.google_chat_webhook_url || ""; - } else if (config.notification_type === "email") { + + } else if (config.notification_type === "email") { + cleanConfig.email_address = config.email_address || ""; cleanConfig.email_sender_name = config.email_sender_name || ""; cleanConfig.smtp_server = config.smtp_server || ""; cleanConfig.smtp_port = config.smtp_port || ""; cleanConfig.smtp_password = config.smtp_password || ""; - } + } else if (config.notification_type === "webhook") { + + cleanConfig.webhook_url = config.webhook_url || ""; + cleanConfig.webhook_payload_template = config.webhook_payload_template || ""; + + } const result = await pb.collection('alert_configurations').create(cleanConfig); - + toast({ title: "Success", description: "Notification channel created successfully", }); return result as AlertConfiguration; - } catch (error) { + } catch (error) { + // Try to get more details from the error if (error && typeof error === 'object') { } @@ -99,7 +113,17 @@ export const alertConfigService = { async updateAlertConfiguration(id: string, config: Partial): Promise { try { - const result = await pb.collection('alert_configurations').update(id, config); + // Build the update config with proper field mapping + const updateConfig: any = {}; + + // Copy all provided fields + Object.keys(config).forEach(key => { + if (config[key as keyof AlertConfiguration] !== undefined) { + updateConfig[key] = config[key as keyof AlertConfiguration]; + } + }); + + const result = await pb.collection('alert_configurations').update(id, updateConfig); toast({ title: "Success", description: "Notification channel updated successfully",