Created
April 12, 2023 09:11
-
-
Save dosandk/77916b2466818493dab927f47e778892 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { HttpException, HttpStatus, Injectable, NotFoundException } from '@nestjs/common'; | |
| import { InjectModel } from '@nestjs/mongoose'; | |
| import { Model, Types } from 'mongoose'; | |
| import { TaskDto } from './dto/task.dto'; | |
| import { Task } from './types/task.interface'; | |
| import { Track } from '../tracks/types/track.interface'; | |
| import { User } from '../users/types/user.interface'; | |
| import { TaskInProgress } from './types/task-in-progress.interface'; | |
| import { SaveTaskProgressDto } from './dto/save-task-progress.dto'; | |
| import { AddCommentDto } from './dto/comments/add-comment.dto'; | |
| import { DeleteCommentDto } from './dto/comments/delete-comment.dto'; | |
| import { UpdateCommentDto } from './dto/comments/update-comment.dto'; | |
| import { UserUpdate } from 'src/users/dto/user-update.dto'; | |
| import { UsersRepository } from 'src/users/users.repository'; | |
| import { TasksInProgressRepository } from './tasks-in-progress.repository'; | |
| import { reviewStatuses } from './models/task-in-progress.model'; | |
| import { TASKS_RESPONSE_MESSAGES, USER_RESPONSE_MESSAGES } from 'src/shared/constants'; | |
| @Injectable() | |
| export class TasksService { | |
| constructor( | |
| @InjectModel('Track') private readonly trackModel: Model<Track>, | |
| @InjectModel('Task') private readonly taskModel: Model<Task>, | |
| @InjectModel('Comment') private readonly commentModel: Model<Comment>, | |
| private userRepository: UsersRepository, | |
| private tasksInProgressRepository: TasksInProgressRepository | |
| ) {} | |
| async findAll({ skip, limit }): Promise<Task[]> { | |
| return await this.taskModel.find({}, null, { skip, limit }); | |
| } | |
| async create(task: TaskDto): Promise<Task> { | |
| const { trackId } = task; | |
| const track = await this.trackModel.findOne({ trackId }).exec(); | |
| const newTask = new this.taskModel({ | |
| ...task | |
| }); | |
| const taskDocument = await newTask.save(); | |
| if (track) { | |
| track.tasks.push(taskDocument._id); | |
| await track.save(); | |
| } | |
| return taskDocument; | |
| } | |
| getUserMentorId(user: User) { | |
| const userMentorId = user.mentor; | |
| if (!userMentorId) { | |
| throw new HttpException(USER_RESPONSE_MESSAGES.userWithoutMentor, HttpStatus.BAD_REQUEST); | |
| } | |
| return userMentorId; | |
| } | |
| async findTaskInProgressByUserAndTaskIds( | |
| taskId: string, | |
| userId: string | |
| ): Promise<TaskInProgress> { | |
| return this.tasksInProgressRepository.findOne({ taskId, userId }); | |
| } | |
| async updateUserInProgressTasks( | |
| task: Task, | |
| user: User, | |
| saveTaskProgressDto: SaveTaskProgressDto | |
| ): Promise<TaskInProgress> { | |
| const newTaskInProgress = await this.createTaskInProgress(task, user, saveTaskProgressDto); | |
| const userUpdates = [ | |
| { | |
| key: 'tasksInProgress', | |
| value: [...user.tasksInProgress, newTaskInProgress._id] | |
| } | |
| ]; | |
| await this.updateUser(user._id, userUpdates); | |
| return newTaskInProgress; | |
| } | |
| async updateTaskInProgress({ | |
| taskInProgress, | |
| saveTaskProgressDto, | |
| mentorId, | |
| tasksStatus | |
| }: any): Promise<TaskInProgress> { | |
| const { solutionCode, isCompleted, taskName } = saveTaskProgressDto; | |
| taskInProgress.solutionCode = solutionCode; | |
| taskInProgress.isCompleted = isCompleted; | |
| taskInProgress.taskName = taskName; | |
| if (mentorId) { | |
| taskInProgress.reviewer = mentorId; | |
| } | |
| if (tasksStatus) { | |
| taskInProgress.isReviewedByMentor = tasksStatus; | |
| } | |
| return taskInProgress.save(); | |
| } | |
| async createTaskInProgress( | |
| task: Task, | |
| user: User, | |
| saveTaskProgressDto: SaveTaskProgressDto | |
| ): Promise<TaskInProgress> { | |
| const { solutionCode, isCompleted, isReviewedByMentor, reviewer, taskName } = saveTaskProgressDto; | |
| const newTaskInProgress = await this.tasksInProgressRepository.create({ | |
| userId: user._id, | |
| taskId: task._id, | |
| solutionCode, | |
| isCompleted, | |
| isReviewedByMentor: isReviewedByMentor || reviewStatuses.Null, | |
| reviewer, | |
| taskName | |
| }); | |
| return newTaskInProgress; | |
| } | |
| // TODO: rename | |
| async foo (saveTaskProgressDto) { | |
| const [task, user] = await Promise.all([ | |
| this.taskModel.findOne({ taskId: saveTaskProgressDto.taskName }), | |
| this.userRepository.findOne({ _id: new Types.ObjectId(saveTaskProgressDto.userId) }) | |
| ]); | |
| return [task, user]; | |
| } | |
| async saveProgress(saveTaskProgressDto: SaveTaskProgressDto): Promise<TaskInProgress> { | |
| const [task, user] = await this.foo(saveTaskProgressDto); | |
| const taskInProgress = await this.findTaskInProgressByUserAndTaskIds(task._id, user._id); | |
| if (taskInProgress) { | |
| return this.updateTaskInProgress({ taskInProgress, saveTaskProgressDto }); | |
| } | |
| return this.updateUserInProgressTasks(task, user, saveTaskProgressDto); | |
| } | |
| async getTaskInProgressByUserId(taskName: string, userId: string) { | |
| const taskInProgress = await this.tasksInProgressRepository.findOne({ | |
| userId: new Types.ObjectId(userId), | |
| taskName | |
| }); | |
| if (!taskInProgress) { | |
| throw new HttpException(TASKS_RESPONSE_MESSAGES.taskNotFound, HttpStatus.BAD_REQUEST); | |
| } | |
| return taskInProgress; | |
| } | |
| async sendTaskToReview(saveTaskProgressDto: SaveTaskProgressDto): Promise<TaskInProgress> { | |
| const [task, user] = await this.foo(saveTaskProgressDto); | |
| const mentorId = this.getUserMentorId(user); | |
| const taskInProgress = await this.findTaskInProgressByUserAndTaskIds(task._id, user._id); | |
| if (taskInProgress) { | |
| return this.updateTaskInProgress({ | |
| taskInProgress, | |
| saveTaskProgressDto, | |
| mentorId, | |
| reviewStatuses: reviewStatuses.InPending | |
| }); | |
| } | |
| // createUserTaskInProgress | |
| return this.updateUserInProgressTasks(task, user, saveTaskProgressDto); | |
| } | |
| async getTasksInReviewForMentor(mentorId: string) { | |
| const tasksInReview = await this.tasksInProgressRepository.find({ | |
| reviewer: new Types.ObjectId(mentorId), | |
| isReviewedByMentor: reviewStatuses.InPending | |
| }); | |
| if (!tasksInReview) { | |
| throw new HttpException(TASKS_RESPONSE_MESSAGES.tasksNotFound, HttpStatus.BAD_REQUEST); | |
| } | |
| return tasksInReview; | |
| } | |
| async getComments(userId: string, taskId: string): Promise<Comment[]> { | |
| const task = await this.getUserTask(userId, taskId); | |
| return (await task.populate('comments')).comments as Comment[]; | |
| } | |
| async addComment({ userId, taskId, body }: AddCommentDto): Promise<TaskInProgress> { | |
| const task = await this.getUserTask(userId, taskId); | |
| const comment = new this.commentModel({ | |
| taskId: task._id, | |
| date: new Date().toISOString(), | |
| body | |
| }); | |
| const commentDoc = await comment.save(); | |
| (task.comments as Types.ObjectId[]).push(commentDoc._id); | |
| return await task.save(); | |
| } | |
| async deleteComment({ userId, taskId, commentId }: DeleteCommentDto): Promise<TaskInProgress> { | |
| await this.commentModel.findByIdAndDelete(commentId); | |
| return await this.tasksInProgressRepository.findOneAndUpdate( | |
| { userId, taskId }, | |
| { $pull: { comments: commentId } }, | |
| { new: true } | |
| ); | |
| } | |
| async updateComment({ commentId, body }: UpdateCommentDto): Promise<Comment> { | |
| return await this.commentModel.findByIdAndUpdate( | |
| commentId, | |
| { body, date: new Date().toISOString() }, | |
| { new: true } | |
| ); | |
| } | |
| async getUserTasks( | |
| userId: string, | |
| { isMetadata, isCompleted }: { isMetadata?: boolean; isCompleted?: boolean } | |
| ): Promise<TaskInProgress[]> { | |
| const populateOptions = { | |
| path: 'tasksInProgress', | |
| populate: { | |
| path: 'taskId' | |
| } | |
| }; | |
| if (isCompleted !== undefined) { | |
| populateOptions['match'] = { isCompleted }; | |
| } | |
| if (isMetadata) { | |
| populateOptions['select'] = { userId: 0, __v: 0 }; | |
| } | |
| const user = await this.userRepository.findOne({ _id: new Types.ObjectId(userId) }); | |
| const populatedUser = await user.populate(populateOptions); | |
| return populatedUser.tasksInProgress as TaskInProgress[]; | |
| } | |
| async getUserTask(userId: string, taskId: string): Promise<TaskInProgress> { | |
| const tasks: any[] = await this.getUserTasks(userId, { isMetadata: false }); | |
| return tasks.find(task => task.taskId._id.toString() === taskId); | |
| } | |
| private async updateUser(userId: string, updates: UserUpdate[]): Promise<User> { | |
| const currentUser = await this.userRepository.findOne({ _id: new Types.ObjectId(userId) }); | |
| if (!currentUser) { | |
| throw new NotFoundException(`There isn't any user with id: ${userId}`); | |
| } | |
| updates.forEach(({ key, value }) => (currentUser[key] = value)); | |
| return await currentUser.save(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment