Skip to content

Commit

Permalink
Feat: new release (#291)
Browse files Browse the repository at this point in the history
* chore: fix offset and refactor pending review limits (#284)

* chore: add merged review status to admin review params (#287)

chore(feat): add merged status to review for admin (#285)

* chore(feat): add merged status to review for admin

* chore: effect review comments

Co-authored-by: nully0x <[email protected]>

* fix: expired condition not return merged reviews (#289)

fix: expired condition not return merged reviews (#288)

* fix: expired review inference not return merged reviews

* chore: remove unused buildIsInactiveCondition logic

* fix: account for expired but not archived reviews

* chore: rename 'buildIsExpiredAndArchivedOrNotArchivedCondition' to 'buidIsExpiredCondition' for simplicity.

Also added comments explaining why we have the combined logic

---------

Co-authored-by: nully0x <[email protected]>
  • Loading branch information
Extheoisah and nully0x authored May 28, 2024
1 parent a4f9d48 commit aca86d2
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 240 deletions.
2 changes: 1 addition & 1 deletion api/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DB_URL=postgres://postgres:postgres@localhost:5432/postgres
DB_URL="postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
NODE_ENV=development
PORT=8080
JWT_SECRET=''
Expand Down
14 changes: 0 additions & 14 deletions api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,3 @@ migrate:
undo-migrate:
yarn run migrate:undo


# move along, this is for mocking
create-mock-network:
docker network create queuer || true

start-mock-deps:
docker run --network=queuer --name transcription-db -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres
docker run --network=queuer --name transcription-redis -p 6379:6379 -d redis

build-mock:
docker build -t transcription .

run-mock:
docker run --network=queuer transcription
211 changes: 29 additions & 182 deletions api/app/controllers/review.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,8 @@ import { Request, Response } from "express";
import { Op } from "sequelize";

import { Review, Transaction, Transcript, User } from "../db/models";
import {
DB_QUERY_LIMIT,
DB_START_PAGE,
QUERY_REVIEW_STATUS,
HOUR_END_OF_DAY,
MINUTE_END_OF_DAY,
SECOND_END_OF_DAY,
MILLISECOND_END_OF_DAY,
} from "../utils/constants";
import {
buildIsActiveCondition,
buildIsInActiveCondition,
buildIsPendingCondition,
} from "../utils/review.inference";
import { DB_QUERY_LIMIT, DB_START_PAGE } from "../utils/constants";
import { buildCondition, buildReviewResponse } from "../utils/review.inference";
import { parseMdToJSON } from "../helpers/transcript";
import axios from "axios";
import { BaseParsedMdContent, TranscriptAttributes } from "../types/transcript";
Expand Down Expand Up @@ -95,10 +83,10 @@ export async function create(req: Request, res: Response) {

// Retrieve all reviews from the database.
export async function findAll(req: Request, res: Response) {
let queryStatus = req.query.status;
const queryStatus = req.query.status as string | undefined;
const userId = Number(req.body.userId);
const page: number = Number(req.query.page) || 1;
const limit: number = Number(req.query.limit) || 5;
const page: number = Number(req.query.page) || DB_START_PAGE;
const limit: number = Number(req.query.limit) || DB_QUERY_LIMIT;
const offset: number = (page - 1) * limit;

const user = await User.findOne({
Expand All @@ -114,59 +102,26 @@ export async function findAll(req: Request, res: Response) {
return;
}

let groupedCondition = {};
const currentTime = new Date().getTime();

const userIdCondition = { userId: { [Op.eq]: user.id } };

// add condition if query exists
if (Boolean(user.id)) {
groupedCondition = { ...groupedCondition, ...userIdCondition };
}
if (queryStatus) {
switch (queryStatus) {
case QUERY_REVIEW_STATUS.ACTIVE:
const activeCondition = buildIsActiveCondition(currentTime);
groupedCondition = { ...groupedCondition, ...activeCondition };
break;
case QUERY_REVIEW_STATUS.PENDING:
const pendingCondition = buildIsPendingCondition();
groupedCondition = { ...groupedCondition, ...pendingCondition };
break;
case QUERY_REVIEW_STATUS.INACTIVE:
const inActiveCondition = buildIsInActiveCondition(currentTime);
groupedCondition = { ...groupedCondition, ...inActiveCondition };
break;
default:
break;
}
}
const { condition } = buildCondition({
status: queryStatus,
userId: user.id,
});

try {
const totalItems = await Review.count({
where: groupedCondition,
where: condition,
});
const totalPages = Math.ceil(totalItems / limit);
const hasNextPage = page < totalPages;
const hasPreviousPage = page > 1;

const data = await Review.findAll({
where: groupedCondition,
limit: limit,
offset: offset,
where: condition,
limit,
offset,
order: [["createdAt", "DESC"]],
include: { model: Transcript },
});

const response = {
totalItems: totalItems,
itemsPerPage: limit,
totalPages: totalPages,
currentPage: page,
hasNextPage,
hasPreviousPage,
data,
};
const response = buildReviewResponse(data, page, limit, totalItems);

res.status(200).send(response);
} catch (error) {
console.log(error);
Expand Down Expand Up @@ -279,124 +234,28 @@ export const getAllReviewsForAdmin = async (req: Request, res: Response) => {
const transcriptId = Number(req.query.transcriptId);
const userId = Number(req.query.userId);
const mergedAt = req.query.mergedAt as string;
const submittedAt = req.query.submittedAt as string;
const status = req.query.status as string;
const userSearch = req.query.user as string;
const page: number = Number(req.query.page) || DB_START_PAGE;
const limit: number = Number(req.query.limit) || DB_QUERY_LIMIT;

const condition: {
[key: string | number]: any;
} = {};

const userCondition: {
[Op.or]?: {
email?: { [Op.iLike]: string };
githubUsername?: { [Op.iLike]: string };
}[];
} = {};

if (status) {
const currentTime = new Date().getTime();
switch (status) {
case QUERY_REVIEW_STATUS.ACTIVE:
const activeCondition = buildIsActiveCondition(currentTime);
condition[Op.and as unknown as keyof typeof Op] = activeCondition;
break;

case "expired":
const expiredCondition = buildIsInActiveCondition(currentTime);
condition[Op.and as unknown as keyof typeof Op] = expiredCondition;
break;

case QUERY_REVIEW_STATUS.PENDING:
const pendingCondition = buildIsPendingCondition();
condition[Op.and as unknown as keyof typeof Op] = pendingCondition;
break;

default:
break;
}
}

// Check if the mergedAt parameter is provided in the query
if (Boolean(mergedAt)) {
// Convert the mergedAt string to a Date object
const date = new Date(mergedAt as string);

// Calculate the start of the day (00:00:00.000) for the mergedAt date
const startOfDay = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate()
);

// Calculate the end of the day (23:59:59.999) for the mergedAt date
const endOfDay = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
HOUR_END_OF_DAY,
MINUTE_END_OF_DAY,
SECOND_END_OF_DAY,
MILLISECOND_END_OF_DAY
);

// Set the condition for mergedAt to filter records within the specified day
condition.mergedAt = {
[Op.gte]: startOfDay,
[Op.lte]: endOfDay,
};
}

if (Boolean(transcriptId)) {
condition.transcriptId = { [Op.eq]: transcriptId };
}
if (Boolean(userId)) {
condition.userId = { [Op.eq]: userId };
}

// Check if the mergedAt parameter is provided in the query for all time zone support
if (Boolean(mergedAt)) {
// Convert the mergedAt string to a Date object
const date = new Date(mergedAt as string);

// Calculate the start of the day (00:00:00.000) for the mergedAt date
const startOfDay = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate()
);

// Calculate the end of the day (23:59:59.999) for the mergedAt date
const endOfDay = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
HOUR_END_OF_DAY,
MINUTE_END_OF_DAY,
SECOND_END_OF_DAY,
MILLISECOND_END_OF_DAY
);

// Set the condition for mergedAt to filter records within the specified day
condition.mergedAt = {
[Op.gte]: startOfDay,
[Op.lte]: endOfDay,
};
}

if (userSearch) {
const searchCondition = { [Op.iLike]: `%${userSearch.toLowerCase()}%` };
userCondition[Op.or] = [
{ email: searchCondition },
{ githubUsername: searchCondition },
];
}
const offset = Math.max(0, (page - 1) * limit);

const { condition, userCondition } = buildCondition({
status,
transcriptId,
userId,
mergedAt,
userSearch,
submittedAt,
});

try {
const reviews = await Review.findAll({
where: condition,
order: [["createdAt", "DESC"]],
offset,
limit,
include: [
{ model: Transcript, required: true, attributes: { exclude: ["id"] } },
{
Expand All @@ -421,19 +280,7 @@ export const getAllReviewsForAdmin = async (req: Request, res: Response) => {
],
});

const totalPages = Math.ceil(reviewCount / limit);
const hasNextPage = page < totalPages;
const hasPreviousPage = page > 1;

const response = {
totalItems: reviewCount,
totalPages,
currentPage: page,
itemsPerPage: limit,
hasNextPage,
hasPreviousPage,
data: reviews,
};
const response = buildReviewResponse(reviews, page, limit, reviewCount);

res.status(200).json(response);
} catch (error) {
Expand Down
37 changes: 30 additions & 7 deletions api/app/controllers/transcript.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import {
buildIsPendingCondition,
getTotalWords,
} from "../utils/review.inference";
import { DB_QUERY_LIMIT, MAXPENDINGREVIEWS } from "../utils/constants";
import {
DB_QUERY_LIMIT,
DB_START_PAGE,
MAX_PENDING_REVIEWS,
MERGED_REVIEWS_THRESHOLD,
} from "../utils/constants";

import { generateUniqueHash } from "../helpers/transcript";
import { redis } from "../db";
import {
Expand Down Expand Up @@ -96,7 +102,7 @@ export async function create(req: Request, res: Response) {

// Retrieve all unarchived and queued transcripts from the database.
export async function findAll(req: Request, res: Response) {
const page: number = Number(req.query.page) || 1;
const page: number = Number(req.query.page) || DB_START_PAGE;
const limit: number = Number(req.query.limit) || DB_QUERY_LIMIT;
const offset: number = (page - 1) * limit;
let condition = {
Expand Down Expand Up @@ -135,6 +141,7 @@ export async function findAll(req: Request, res: Response) {
totalItems,
itemsPerPage: limit,
totalPages,
currentPage: Number(page),
hasNextPage,
hasPreviousPage,
data: cachedTranscripts,
Expand Down Expand Up @@ -194,7 +201,7 @@ export async function findAll(req: Request, res: Response) {
totalItems: totalItems,
itemsPerPage: limit,
totalPages: totalPages,
currentPage: page,
currentPage: Number(page),
hasNextPage,
hasPreviousPage,
data,
Expand Down Expand Up @@ -347,7 +354,7 @@ export async function claim(req: Request, res: Response) {
const transcriptId = req.params.id;

const uid = req.body.claimedBy;
const branchUrl = req.body.branchUrl
const branchUrl = req.body.branchUrl;
const currentTime = new Date().getTime();
const activeCondition = buildIsActiveCondition(currentTime);
const pendingCondition = buildIsPendingCondition();
Expand All @@ -366,12 +373,28 @@ export async function claim(req: Request, res: Response) {
return;
}

// if user has successfully reviewed fewer than 3 transcripts
// allow to claim only 1 transcript and return if user has already has a pending review
// if user has successfully reviewed 3 or more transcripts, allow to have 6 pending reviews
const successfulReviews = await Review.findAll({
where: { ...userCondition, mergedAt: { [Op.ne]: null } },
});
const pendingReview = await Review.findAll({
where: { ...userCondition, ...pendingCondition },
});
if (pendingReview.length >= MAXPENDINGREVIEWS) {
if (
successfulReviews.length <= MERGED_REVIEWS_THRESHOLD &&
pendingReview.length
) {
res.status(500).send({
message:
"You have a pending review, finish it first before claiming another!",
});
return;
}
if (pendingReview.length >= MAX_PENDING_REVIEWS) {
res.status(500).send({
message: "User has too many pending reviews, clear some and try again!",
message: `You have ${pendingReview.length} pending reviews, clear some and try again!`,
});
return;
}
Expand All @@ -382,7 +405,7 @@ export async function claim(req: Request, res: Response) {
};

if (branchUrl) {
review.branchUrl = branchUrl
review.branchUrl = branchUrl;
}

try {
Expand Down
2 changes: 1 addition & 1 deletion api/app/controllers/webhook.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,4 @@ export async function handlePushEvent(req: Request, res: Response) {
return handleError(error, res);
}
return res.sendStatus(200);
}
}
Loading

0 comments on commit aca86d2

Please sign in to comment.