diff --git a/db/knex_migrations/2024-10-17-0000-notifications-path-as-name.js b/db/knex_migrations/2024-10-17-0000-notifications-path-as-name.js new file mode 100644 index 000000000..3a4e6be91 --- /dev/null +++ b/db/knex_migrations/2024-10-17-0000-notifications-path-as-name.js @@ -0,0 +1,12 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("notification", function (table) { + table.boolean("use_path_as_name").notNullable().defaultTo(true); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("notification", function (table) { + table.dropColumn("use_path_as_name"); + }); +}; diff --git a/server/client.js b/server/client.js index 72f0a4e8e..f37a84330 100644 --- a/server/client.js +++ b/server/client.js @@ -26,7 +26,15 @@ async function sendNotificationList(socket) { for (let bean of list) { let notificationObject = bean.export(); notificationObject.isDefault = (notificationObject.isDefault === 1); + notificationObject.usePathAsName = (notificationObject.usePathAsName === 1); notificationObject.active = (notificationObject.active === 1); + + const configObject = JSON.parse(notificationObject.config); + if ( !("usePathAsName" in configObject)) { + configObject.usePathAsName = notificationObject.usePathAsName; + notificationObject.config = JSON.stringify(configObject); + } + result.push(notificationObject); } diff --git a/server/model/monitor.js b/server/model/monitor.js index 9a30a6689..d8dcf78ef 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -385,7 +385,8 @@ class Monitor extends BeanModel { if (children.length > 0) { bean.status = UP; - bean.msg = "All children up and running"; + bean.msg = ""; + let errorChildNames = []; for (const child of children) { if (!child.active) { // Ignore inactive childs @@ -402,10 +403,22 @@ class Monitor extends BeanModel { } else if (bean.status === PENDING && lastBeat.status === DOWN) { bean.status = lastBeat.status; } + + if (lastBeat && (lastBeat.status === PENDING || lastBeat.status === DOWN)) { + const childMonitor = await Monitor.getMonitor(lastBeat.monitor_id); + if (errorChildNames.length > 0) { + bean.msg += "\r\n"; + } + + bean.msg += "- " + childMonitor.name + ":\r\n" + lastBeat.msg.trim().replace(/^/gm, " "); + errorChildNames.push(childMonitor.name); + } } - if (bean.status !== UP) { - bean.msg = "Child inaccessible"; + if (bean.status === UP) { + bean.msg = "All children up and running"; + } else if (bean.status === PENDING || bean.status === DOWN) { + bean.msg = "Some Children are having problems (" + errorChildNames.join(", ") + ")\r\n" + bean.msg; } } else { // Set status pending if group is empty @@ -1326,8 +1339,10 @@ class Monitor extends BeanModel { for (let notification of notificationList) { try { const heartbeatJSON = bean.toJSON(); - const monitorData = [{ id: monitor.id, - active: monitor.active + const monitorData = [{ + id: monitor.id, + name: monitor.name, + active: monitor.active, }]; const preloadData = await Monitor.preparePreloadData(monitorData); // Prevent if the msg is undefined, notifications such as Discord cannot send out. @@ -1604,6 +1619,20 @@ class Monitor extends BeanModel { }; } + /** + * Gets Monitor with specific ID + * @param {number} monitorID ID of monitor to get + * @returns {Promise>} Children + */ + static async getMonitor(monitorID) { + return await R.getRow(` + SELECT * FROM monitor + WHERE id = ? + `, [ + monitorID, + ]); + } + /** * Gets Parent of the monitor * @param {number} monitorID ID of monitor to get diff --git a/server/notification.js b/server/notification.js index e7977eb4a..e2e8bee62 100644 --- a/server/notification.js +++ b/server/notification.js @@ -178,6 +178,9 @@ class Notification { * @throws Error with fail msg */ static async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + if (notification.usePathAsName && monitorJSON) { + monitorJSON["name"] = monitorJSON["pathName"]; + } if (this.providerList[notification.type]) { return this.providerList[notification.type].send(notification, msg, monitorJSON, heartbeatJSON); } else { @@ -213,6 +216,8 @@ class Notification { bean.user_id = userID; bean.config = JSON.stringify(notification); bean.is_default = notification.isDefault || false; + bean.use_path_as_name = notification.usePathAsName; + await R.store(bean); if (notification.applyExisting) { diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index f6d728029..d6d1f90e8 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -41,6 +41,16 @@
+
+ + +
+
+ If your monitor is inside a group, the name will show the full path of the monitor. For example "Group A / Monitor 1". +
+ +
+
@@ -95,6 +105,7 @@ export default { /** @type { null | keyof NotificationFormList } */ type: null, isDefault: false, + usePathAsName: false, // Do not set default value here, please scroll to show() } }; @@ -264,6 +275,7 @@ export default { name: "", type: "telegram", isDefault: false, + usePathAsName: true, }; }