Skip to content

Commit

Permalink
feat: add endpoint to mark a review request as viewed (#550)
Browse files Browse the repository at this point in the history
* feat: add endpoint to mark a review request as viewed

* fix: use upsert for updateReviewRequestLastViewedAt
  • Loading branch information
dcshzj authored and alexanderleegs committed Mar 16, 2023
1 parent ab0d59e commit 6d882c9
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 11 deletions.
68 changes: 68 additions & 0 deletions src/routes/v2/authenticated/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,70 @@ export class ReviewsRouter {
return res.status(200).json()
}

markReviewRequestAsViewed: RequestHandler<
{ siteName: string; requestId: number },
string | ResponseErrorBody,
never,
unknown,
{ userWithSiteSessionData: UserWithSiteSessionData }
> = async (req, res) => {
// Step 1: Check that the site exists
const { siteName, requestId: prNumber } = req.params
const site = await this.sitesService.getBySiteName(siteName)

if (!site) {
return res.status(404).send({
message: "Please ensure that the site exists!",
})
}

// Step 2: Check that user exists.
// Having session data is proof that this user exists
// as otherwise, they would be rejected by our middleware
const { userWithSiteSessionData } = res.locals

// Check if they are a collaborator
const role = await this.collaboratorsService.getRole(
siteName,
userWithSiteSessionData.isomerUserId
)

if (!role) {
return res.status(400).send({
message: "User is not a collaborator of this site!",
})
}

// Step 3: Retrieve review request
const possibleReviewRequest = await this.reviewRequestService.getReviewRequest(
site,
prNumber
)

if (isIsomerError(possibleReviewRequest)) {
logger.error({
message: "Invalid review request requested",
method: "markReviewRequestAsViewed",
meta: {
userId: userWithSiteSessionData.isomerUserId,
email: userWithSiteSessionData.email,
siteName,
prNumber,
},
})
return res.status(404).json({ message: possibleReviewRequest.message })
}

// Step 4: Mark review request as viewed
await this.reviewRequestService.markReviewRequestAsViewed(
userWithSiteSessionData,
site,
possibleReviewRequest.id
)

return res.status(200).json()
}

getReviewRequest: RequestHandler<
{ siteName: string; requestId: number },
{ reviewRequest: ReviewRequestDto } | ResponseErrorBody,
Expand Down Expand Up @@ -786,6 +850,10 @@ export class ReviewsRouter {
"/:requestId",
attachReadRouteHandlerWrapper(this.getReviewRequest)
)
router.post(
"/:requestId/viewed",
attachWriteRouteHandlerWrapper(this.markReviewRequestAsViewed)
)
router.post(
"/:requestId/merge",
attachWriteRouteHandlerWrapper(this.mergeReviewRequest)
Expand Down
45 changes: 34 additions & 11 deletions src/services/review/ReviewRequestService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,18 +285,41 @@ export default class ReviewRequestService {
const { isomerUserId: userId } = sessionData
const { id: reviewRequestId } = reviewRequest

await this.reviewRequestView.update(
{
lastViewedAt: new Date(),
await this.reviewRequestView.upsert({
reviewRequestId,
siteId: site.id,
userId,
lastViewedAt: new Date(),
})
}

markReviewRequestAsViewed = async (
sessionData: UserWithSiteSessionData,
site: Site,
requestId: number
): Promise<void> => {
const { isomerUserId: userId } = sessionData

const reviewRequestView = await this.reviewRequestView.findOne({
where: {
siteId: site.id,
userId,
reviewRequestId: requestId,
},
{
where: {
reviewRequestId,
siteId: site.id,
userId,
},
}
)
})

// We only want to create the entry if it does not exist
// (i.e. the review request has never been viewed before)
if (!reviewRequestView) {
await this.reviewRequestView.create({
reviewRequestId: requestId,
siteId: site.id,
userId,
// This field represents the user opening the review request
// itself, which the user has not done so yet at this stage.
lastViewedAt: null,
})
}
}

deleteAllReviewRequestViews = async (
Expand Down

0 comments on commit 6d882c9

Please sign in to comment.