Skip to content

feat: add bulk edit monitor notifications endpoint#3376

Open
ashu130698 wants to merge 12 commits intobluewave-labs:developfrom
ashu130698:feat/bulk-edit-notifications
Open

feat: add bulk edit monitor notifications endpoint#3376
ashu130698 wants to merge 12 commits intobluewave-labs:developfrom
ashu130698:feat/bulk-edit-notifications

Conversation

@ashu130698
Copy link

The changes

Added a PATCH endpoint at /api/v1/notifications for bulk updating
notification channels on multiple monitors. Supports 3 actions:
add, remove, and set. Backend only - frontend will follow in a
separate PR.

Fixes #2320

  • I deployed the application locally.
  • I have performed a self-review and testing of my code.
  • I have included the issue # in the PR.
  • I have added i18n support to visible strings (N/A - no UI in this PR)
  • I have not included any files that are not related to my pull request
  • I didn't use any hardcoded values
  • I made sure font sizes, color choices etc are all referenced from the theme (N/A - no UI)
  • My PR is granular and targeted to one specific feature.
  • I ran npm run format in server and client directories.
  • I took a screenshot or a video (N/A - no UI in this PR)

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eb2d8b8d3b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

action: "add" | "remove" | "set",
teamId: string
): Promise<number> => {
const objectIds = monitorIds.map((id) => new mongoose.Types.ObjectId(id));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle malformed monitor IDs as client errors

Converting each monitorId with new mongoose.Types.ObjectId(id) will throw when any ID is not a 24-char hex string, and this path currently bubbles into the global error handler as a 500. For requests with one typoed ID, the whole bulk update fails with a server error instead of a 400 validation error, which makes the endpoint brittle for user-provided input.

Useful? React with 👍 / 👎.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in latest commit

Comment on lines +167 to +168
if (!notificationIds || !Array.isArray(notificationIds) || notificationIds.length === 0) {
throw new AppError({ message: "Notification IDs are required", status: 400 });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow empty notification list for set action

The controller requires notificationIds.length > 0 for every action, which makes action: "set" unable to clear notifications from selected monitors. Monitors support having no notifications, so this blocks a valid bulk-edit scenario (replace with an empty set) and forces clients to do extra per-monitor workarounds.

Useful? React with 👍 / 👎.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in latest commit

Copy link
Collaborator

@ajhollid ajhollid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, it looks decent.

We do require validation handled by Zod, please see the validation dir to see examples of other validation schemas.

Other than that some nitpicks here and there.

Thanks for the clean PR, looking forward to revisions!

try {
const teamId = requireTeamId(req.user?.teamId);

const { monitorIds, notificationIds, action } = req.body;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Body input must be validated, see the validations directory for examples of validation

Comment on lines +163 to +173
if (!monitorIds || !Array.isArray(monitorIds) || monitorIds.length === 0) {
throw new AppError({ message: "Monitor IDs are required", status: 400 });
}

if (!notificationIds || !Array.isArray(notificationIds)) {
throw new AppError({ message: "Notification IDs must be an array", status: 400 });
}

if (!action || !["add", "remove", "set"].includes(action)) {
throw new AppError({ message: "Action must be 'add', 'remove', or 'set'", status: 400 });
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These will not be necessary after validation is performed

await MonitorModel.updateMany({ notifications: notificationId }, { $pull: { notifications: notificationId } });
};

bulkUpdateNotifications = async (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be named updateNotifications, no need to note that it is a bulk operation, the pluralization of Notification already indicates that.

Comment on lines +316 to +326
switch (action) {
case "add":
update = { $addToSet: { notifications: { $each: notificationIds } } };
break;
case "remove":
update = { $pull: { notifications: { $in: notificationIds } } };
break;
case "set":
update = { $set: { notifications: notificationIds } };
break;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we fall through here? Let's be defensive and have a default case

@ashu130698
Copy link
Author

Thanks for the review! I've added Joi validation, renamed to updateNotifications, and added a default case in the switch. Let me know if anything else needs changes

Copy link
Author

@ashu130698 ashu130698 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved conflicts and added Uptime UI

Copy link
Collaborator

@ajhollid ajhollid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR should be back end focused only, please remove UI, that should be reviewed in a separate PR.

@ajhollid
Copy link
Collaborator

ajhollid commented Mar 6, 2026

Resolved conflicts and added Uptime UI

This PR should be entirely focused on the back end so we can carefully review the implementation. Adding UI should be done in a separate PR where it will be reviewed on its own merit.

The larger and more complex PRs are the less likley they are to be reviewed or merged. Thanks!

…ection for uptime monitors"

This reverts commit 27dd565.
@ashu130698
Copy link
Author

Thanks for the feedback! I've removed all the frontend UI code from this PR so it's strictly backend. I'll open a separate UI PR once this is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bulk edit monitor notification settings

2 participants