add test notificaiton button and methods

This commit is contained in:
Alex Holliday committed 2025-06-10 12:07:31 +08:00
1 parent 1ed317d0cb
commit e6493df881
8 files changed
+135 -90

No files matched your search

+26
View File
@@ -152,10 +152,36 @@ const useEditNotification = () => {
return [editNotification, isLoading, error];
};
const useTestNotification = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const { t } = useTranslation();
const testNotification = async (notification) => {
try {
setIsLoading(true);
await networkService.testNotification({ notification });
createToast({
body: t("notifications.test.success"),
});
} catch (error) {
setError(error);
createToast({
body: t("notifications.test.failed"),
});
} finally {
setIsLoading(false);
}
};
return [testNotification, isLoading, error];
};
export {
useCreateNotification,
useGetNotificationsByTeamId,
useDeleteNotification,
useGetNotificationById,
useEditNotification,
useTestNotification,
};
@@ -16,6 +16,7 @@ import {
useCreateNotification,
useGetNotificationById,
useEditNotification,
useTestNotification,
} from "../../../Hooks/useNotifications";
import {
notificationEmailValidation,
@@ -35,6 +36,8 @@ const CreateNotifications = () => {
const [createNotification, isCreating, createNotificationError] =
useCreateNotification();
const [editNotification, isEditing, editNotificationError] = useEditNotification();
const [testNotification, isTesting, testNotificationError] = useTestNotification();
const BREADCRUMBS = [
{ name: "notifications", path: "/notifications" },
{ name: "create", path: "/notifications/create" },
@@ -178,6 +181,56 @@ const CreateNotifications = () => {
setNotification(newNotification);
};
const onTestNotification = () => {
const form = {
...notification,
type: NOTIFICATION_TYPES.find((type) => type._id === notification.type).value,
};
if (notification.type === 2) {
form.type = "webhook";
}
let error = null;
if (form.type === "email") {
error = notificationEmailValidation.validate(
{ notificationName: form.notificationName, address: form.address },
{ abortEarly: false }
).error;
} else if (form.type === "webhook") {
form.config = {
platform: form.config.platform,
webhookUrl: form.config.webhookUrl,
};
error = notificationWebhookValidation.validate(
{ notificationName: form.notificationName, config: form.config },
{ abortEarly: false }
).error;
} else if (form.type === "pager_duty") {
form.config = {
platform: form.config.platform,
routingKey: form.config.routingKey,
};
error = notificationPagerDutyValidation.validate(
{ notificationName: form.notificationName, config: form.config },
{ abortEarly: false }
).error;
}
if (error) {
const newErrors = {};
error.details.forEach((err) => {
newErrors[err.path[0]] = err.message;
});
createToast({ body: "Please check the form for errors." });
setErrors(newErrors);
return;
}
testNotification(form);
};
return (
<Stack gap={theme.spacing(10)}>
<Breadcrumbs list={BREADCRUMBS} />
@@ -357,7 +410,16 @@ const CreateNotifications = () => {
<Stack
direction="row"
justifyContent="flex-end"
spacing={theme.spacing(2)}
>
<Button
loading={isCreating || isEditing || notificationIsLoading}
variant="contained"
color="secondary"
onClick={onTestNotification}
>
Test notification
</Button>
<Button
loading={isCreating || isEditing || notificationIsLoading}
type="submit"
+10 -1
View File
@@ -56,7 +56,16 @@ const Notifications = () => {
id: "target",
content: "Target",
render: (row) => {
return row.address || row.config?.webhookUrl || row.config?.routingKey;
const type = row.type;
if (type === "email") {
return row.address;
}
if (type === "webhook") {
return row.config?.webhookUrl;
}
if (type === "pager_duty") {
return row.config?.routingKey;
}
},
},
{
+4 -11
View File
@@ -703,18 +703,11 @@ class NetworkService {
* @returns {Promise<AxiosResponse>} The response from the axios POST request.
*/
async testNotification(config) {
return this.axiosInstance.post(
"/notifications/test-webhook",
{
platform: config.platform,
...config.payload,
return this.axiosInstance.post("/notifications/test", config.notification, {
headers: {
"Content-Type": "application/json",
},
{
headers: {
"Content-Type": "application/json",
},
}
);
});
}
/**
+4
View File
@@ -363,6 +363,10 @@
"edit": {
"success": "Notification updated successfully",
"failed": "Failed to update notification"
},
"test": {
"success": "Test notification sent successfully",
"failed": "Failed to send test notification"
}
},
"testLocale": "testLocale",
+17 -77
View File
@@ -24,7 +24,6 @@ class NotificationController {
this.statusService = statusService;
this.db = db;
this.triggerNotification = this.triggerNotification.bind(this);
this.testWebhook = this.testWebhook.bind(this);
}
async triggerNotification(req, res, next) {
@@ -85,94 +84,35 @@ class NotificationController {
};
}
handleTelegramTest(botToken, chatId) {
if (!botToken || !chatId) {
return {
isValid: false,
error: {
msg: this.stringService.telegramRequiresBotTokenAndChatId,
status: 400,
},
};
}
return {
isValid: true,
notification: {
type: NOTIFICATION_TYPES.WEBHOOK,
platform: PLATFORMS.TELEGRAM,
config: { botToken, chatId },
},
};
}
handleWebhookTest(webhookUrl, platform) {
if (webhookUrl === null) {
return {
isValid: false,
error: {
msg: this.stringService.webhookUrlRequired,
status: 400,
},
};
}
return {
isValid: true,
notification: {
type: NOTIFICATION_TYPES.WEBHOOK,
platform: platform,
config: { webhookUrl },
},
};
}
async testWebhook(req, res, next) {
testNotification = async (req, res, next) => {
console.log("TESTING");
try {
const { webhookUrl, platform, botToken, chatId } = req.body;
const notification = req.body;
if (platform === null) {
return res.error({
msg: this.stringService.platformRequired,
status: 400,
if (notification?.type === "email") {
console.log("HANDLE EMAIL");
return res.success({
msg: this.stringService.emailSendSuccess,
});
}
// Platform-specific handling
const platformHandlers = {
[PLATFORMS.TELEGRAM]: () => this.handleTelegramTest(botToken, chatId),
// Default handler for webhook-based platforms (Slack, Discord, etc.)
default: () => this.handleWebhookTest(webhookUrl, platform),
};
const handler = platformHandlers[platform] || platformHandlers.default;
const handlerResult = handler();
if (!handlerResult.isValid) {
return res.error(handlerResult.error);
}
const networkResponse = this.createTestNetworkResponse();
const result = await this.notificationService.sendWebhookNotification(
networkResponse,
handlerResult.notification
);
if (result && result !== false) {
if (notification?.type === "webhook") {
const success =
await this.notificationService.sendTestWebhookNotification(notification);
if (!success) {
return res.error({
msg: this.stringService.webhookSendFailed,
status: 400,
});
}
return res.success({
msg: this.stringService.webhookSendSuccess,
});
} else {
return res.error({
msg: this.stringService.testNotificationFailed,
status: 400,
});
}
} catch (error) {
next(handleError(error, SERVICE_NAME, "testWebhook"));
}
}
};
createNotification = async (req, res, next) => {
try {
+1 -1
View File
@@ -13,7 +13,7 @@ class NotificationRoutes {
this.router.post("/trigger", this.notificationController.triggerNotification);
this.router.post("/test-webhook", this.notificationController.testWebhook);
this.router.post("/test", this.notificationController.testNotification);
this.router.post("/", this.notificationController.createNotification);
+11
View File
@@ -95,6 +95,17 @@ class NotificationService {
return MESSAGE_FORMATTERS[platform](messageText, chatId);
}
sendTestWebhookNotification = async (notification) => {
const config = notification.config;
const response = await this.networkService.requestWebhook(
config.platform,
config.webhookUrl,
"This is a test notification"
);
return response.status;
};
/**
* Sends a webhook notification to a specified platform.
*