Skip to content

Commit

Permalink
feat: enhance alert notifications by integrating AlertFeedService for…
Browse files Browse the repository at this point in the history
… state change and note posting events
  • Loading branch information
simlarsen committed Jan 17, 2025
1 parent c19913a commit eb216e5
Show file tree
Hide file tree
Showing 8 changed files with 504 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Common/Server/Services/AlertInternalNoteService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,83 @@
import ObjectID from "../../Types/ObjectID";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertInternalNote";
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
import AlertFeedService from "./AlertFeedService";
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
import { Blue500 } from "../../Types/BrandColors";
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";

export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}

public override async onCreateSuccess(
_onCreate: OnCreate<Model>,
createdItem: Model,
): Promise<Model> {
const userId: ObjectID | null | undefined =
createdItem.createdByUserId || createdItem.createdByUser?.id;

await AlertFeedService.createAlertFeed({
alertId: createdItem.alertId!,
projectId: createdItem.projectId!,
alertFeedEventType: AlertFeedEventType.PrivateNote,
displayColor: Blue500,
userId: userId || undefined,

feedInfoInMarkdown: `**Posted Internal / Private Note**
${createdItem.note}
`,
});

return createdItem;
}

public override async onUpdateSuccess(
onUpdate: OnUpdate<Model>,
_updatedItemIds: Array<ObjectID>,
): Promise<OnUpdate<Model>> {
if (onUpdate.updateBy.data.note) {
const updatedItems: Array<Model> = await this.findBy({
query: onUpdate.updateBy.query,
limit: LIMIT_PER_PROJECT,
skip: 0,
props: {
isRoot: true,
},
select: {
alertId: true,
projectId: true,
note: true,
createdByUserId: true,
createdByUser: {
_id: true,
},
},
});

const userId: ObjectID | null | undefined =
onUpdate.updateBy.props.userId;

for (const updatedItem of updatedItems) {
await AlertFeedService.createAlertFeed({
alertId: updatedItem.alertId!,
projectId: updatedItem.projectId!,
alertFeedEventType: AlertFeedEventType.PrivateNote,
displayColor: Blue500,
userId: userId || undefined,

feedInfoInMarkdown: `**Updated Internal / Private Note**
${updatedItem.note}
`,
});
}
}
return onUpdate;
}
}

export default new Service();
112 changes: 112 additions & 0 deletions Common/Server/Services/AlertOwnerTeamService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,122 @@
import Team from "../../Models/DatabaseModels/Team";
import ObjectID from "../../Types/ObjectID";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertOwnerTeam";
import TeamService from "./TeamService";
import AlertFeedService from "./AlertFeedService";
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
import { Gray500, Red500 } from "../../Types/BrandColors";

export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}

protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>,
): Promise<OnDelete<Model>> {
const itemsToDelete: Model[] = await this.findBy({
query: deleteBy.query,
limit: deleteBy.limit,
skip: deleteBy.skip,
props: {
isRoot: true,
},
select: {
alertId: true,
projectId: true,
teamId: true,
},
});

return {
carryForward: {
itemsToDelete: itemsToDelete,
},
deleteBy: deleteBy,
};
}

protected override async onDeleteSuccess(
onDelete: OnDelete<Model>,
_itemIdsBeforeDelete: Array<ObjectID>,
): Promise<OnDelete<Model>> {
const deleteByUserId: ObjectID | undefined =
onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;

const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;

for (const item of itemsToDelete) {
const alertId: ObjectID | undefined = item.alertId;
const projectId: ObjectID | undefined = item.projectId;
const teamId: ObjectID | undefined = item.teamId;

if (alertId && teamId && projectId) {
const team: Team | null = await TeamService.findOneById({
id: teamId,
select: {
name: true,
},
props: {
isRoot: true,
},
});

if (team && team.name) {
await AlertFeedService.createAlertFeed({
alertId: alertId,
projectId: projectId,
alertFeedEventType: AlertFeedEventType.OwnerTeamRemoved,
displayColor: Red500,
feedInfoInMarkdown: `**Team ${team.name}** was removed from the alert as the owner.`,
userId: deleteByUserId || undefined,
});
}
}
}

return onDelete;
}

public override async onCreateSuccess(
onCreate: OnCreate<Model>,
createdItem: Model,
): Promise<Model> {
// add alert feed.

const alertId: ObjectID | undefined = createdItem.alertId;
const projectId: ObjectID | undefined = createdItem.projectId;
const teamId: ObjectID | undefined = createdItem.teamId;
const createdByUserId: ObjectID | undefined =
createdItem.createdByUserId || onCreate.createBy.props.userId;

if (alertId && teamId && projectId) {
const team: Team | null = await TeamService.findOneById({
id: teamId,
select: {
name: true,
},
props: {
isRoot: true,
},
});

if (team && team.name) {
await AlertFeedService.createAlertFeed({
alertId: alertId,
projectId: projectId,
alertFeedEventType: AlertFeedEventType.OwnerTeamAdded,
displayColor: Gray500,
feedInfoInMarkdown: `**Team ${team.name}** was added to the alert as the owner.`,
userId: createdByUserId || undefined,
});
}
}

return createdItem;
}
}

export default new Service();
114 changes: 114 additions & 0 deletions Common/Server/Services/AlertOwnerUserService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,124 @@
import User from "../../Models/DatabaseModels/User";
import ObjectID from "../../Types/ObjectID";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertOwnerUser";
import UserService from "./UserService";
import AlertFeedService from "./AlertFeedService";
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
import { Gray500, Red500 } from "../../Types/BrandColors";

export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}

protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>,
): Promise<OnDelete<Model>> {
const itemsToDelete: Model[] = await this.findBy({
query: deleteBy.query,
limit: deleteBy.limit,
skip: deleteBy.skip,
props: {
isRoot: true,
},
select: {
alertId: true,
projectId: true,
userId: true,
},
});

return {
carryForward: {
itemsToDelete: itemsToDelete,
},
deleteBy: deleteBy,
};
}

protected override async onDeleteSuccess(
onDelete: OnDelete<Model>,
_itemIdsBeforeDelete: Array<ObjectID>,
): Promise<OnDelete<Model>> {
const deleteByUserId: ObjectID | undefined =
onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;

const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;

for (const item of itemsToDelete) {
const alertId: ObjectID | undefined = item.alertId;
const projectId: ObjectID | undefined = item.projectId;
const userId: ObjectID | undefined = item.userId;

if (alertId && userId && projectId) {
const user: User | null = await UserService.findOneById({
id: userId,
select: {
name: true,
email: true,
},
props: {
isRoot: true,
},
});

if (user && user.name) {
await AlertFeedService.createAlertFeed({
alertId: alertId,
projectId: projectId,
alertFeedEventType: AlertFeedEventType.OwnerUserRemoved,
displayColor: Red500,
feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was removed from the alert as the owner.`,
userId: deleteByUserId || undefined,
});
}
}
}

return onDelete;
}

public override async onCreateSuccess(
onCreate: OnCreate<Model>,
createdItem: Model,
): Promise<Model> {
// add alert feed.

const alertId: ObjectID | undefined = createdItem.alertId;
const projectId: ObjectID | undefined = createdItem.projectId;
const userId: ObjectID | undefined = createdItem.userId;
const createdByUserId: ObjectID | undefined =
createdItem.createdByUserId || onCreate.createBy.props.userId;

if (alertId && userId && projectId) {
const user: User | null = await UserService.findOneById({
id: userId,
select: {
name: true,
email: true,
},
props: {
isRoot: true,
},
});

if (user && user.name) {
await AlertFeedService.createAlertFeed({
alertId: alertId,
projectId: projectId,
alertFeedEventType: AlertFeedEventType.OwnerUserAdded,
displayColor: Gray500,
feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was added to the alert as the owner.`,
userId: createdByUserId || undefined,
});
}
}

return createdItem;
}
}

export default new Service();
Loading

0 comments on commit eb216e5

Please sign in to comment.