This commit is contained in:
@@ -962,4 +962,8 @@ export const enum timeMessage {
|
||||
INVALID_TIME_RANGE = "زمان پایان باید بعد از زمان شروع باشد!",
|
||||
TIME_ALREADY_STARTED = "برای این تسک یک زمان در حال اجرا وجود دارد!",
|
||||
NO_RUNNING_TIME = "زمان در حال اجرایی برای این تسک پیدا نشد!"
|
||||
}
|
||||
|
||||
export const enum taskCommentMessage {
|
||||
TASK_COMMENT_NOT_FOUND = "نظر مورد نظر پیدا نشد!"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Controller, Post, Patch, Delete, Param, Body, Get } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
|
||||
import { TaskCommentService } from "../providers/task-comment.service";
|
||||
import { CreateTaskCommentDto } from "../dto/task-comment/create-task-comment.dto";
|
||||
import { UpdateTaskCommentDto } from "../dto/task-comment/update-task-comment.dto";
|
||||
import { TMTaskComment } from "../entities/task-comment.entity";
|
||||
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
||||
import { AdminRoute } from "../../../common/decorators/admin.decorator";
|
||||
import { UserDec } from "../../../common/decorators/user.decorator";
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@ApiTags("Task Manager - Comments")
|
||||
@Controller("task-manager/comments")
|
||||
export class TaskCommentController {
|
||||
constructor(private readonly taskCommentService: TaskCommentService) {}
|
||||
|
||||
@Get("task/:taskId")
|
||||
@ApiOperation({ summary: "Get all comments for a task" })
|
||||
@ApiParam({ name: "taskId", description: "Task ID" })
|
||||
getTaskComments(@Param("taskId") taskId: string): Promise<TMTaskComment[]> {
|
||||
return this.taskCommentService.getTaskComments(taskId);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: "Create a new comment" })
|
||||
@ApiResponse({ status: 201, description: "Comment created", type: TMTaskComment })
|
||||
@ApiResponse({ status: 404, description: "Task not found" })
|
||||
create(@UserDec("id") userId: string, @Body() body: CreateTaskCommentDto): Promise<TMTaskComment> {
|
||||
return this.taskCommentService.create(userId, body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
@ApiOperation({ summary: "Update a comment" })
|
||||
@ApiParam({ name: "id", description: "Comment ID" })
|
||||
@ApiResponse({ status: 200, description: "Comment updated", type: TMTaskComment })
|
||||
@ApiResponse({ status: 404, description: "Comment or Task not found" })
|
||||
update(@Param("id") id: string, @Body() body: UpdateTaskCommentDto): Promise<TMTaskComment> {
|
||||
return this.taskCommentService.update(id, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
@ApiOperation({ summary: "Delete a comment" })
|
||||
@ApiParam({ name: "id", description: "Comment ID" })
|
||||
@ApiResponse({ status: 200, description: "Comment deleted" })
|
||||
@ApiResponse({ status: 404, description: "Comment not found" })
|
||||
remove(@Param("id") id: string): Promise<void> {
|
||||
return this.taskCommentService.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsString, IsNotEmpty, IsUUID } from "class-validator";
|
||||
|
||||
export class CreateTaskCommentDto {
|
||||
@ApiProperty({ description: "Comment content", example: "Please review this task before closing." })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
content: string;
|
||||
|
||||
@ApiProperty({ description: "ID of the task this comment belongs to", example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" })
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
taskId: string;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
import { CreateTaskCommentDto } from "./create-task-comment.dto";
|
||||
|
||||
export class UpdateTaskCommentDto extends PartialType(CreateTaskCommentDto) {}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
|
||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { TMTask } from "./task.entity";
|
||||
|
||||
@Entity("tm_task_comments")
|
||||
export class TMTaskComment extends BaseEntity {
|
||||
@Column({ type: "text" })
|
||||
content: string;
|
||||
|
||||
// --- Relations ---
|
||||
|
||||
@ManyToOne(() => User, {
|
||||
nullable: false,
|
||||
onDelete: "RESTRICT",
|
||||
})
|
||||
@JoinColumn({ name: "userId" })
|
||||
user: User;
|
||||
|
||||
@Column({ type: "uuid" })
|
||||
userId: string;
|
||||
|
||||
@ManyToOne(() => TMTask, (task) => task.comments, {
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
})
|
||||
@JoinColumn({ name: "taskId" })
|
||||
task: TMTask;
|
||||
|
||||
@Column({ type: "uuid" })
|
||||
taskId: string;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { TMRemark } from "./remark.entity";
|
||||
import { TMAttachment } from "./attachment.entity";
|
||||
import { TMCheckListItem } from "./check-list-item.entity";
|
||||
import { TMTime } from "./time.entity";
|
||||
import { TMTaskComment } from "./task-comment.entity";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { Ticket } from "../../tickets/entities/ticket.entity";
|
||||
|
||||
@@ -67,6 +68,11 @@ export class TMTask extends BaseEntity {
|
||||
})
|
||||
times: TMTime[];
|
||||
|
||||
@OneToMany(() => TMTaskComment, (comment) => comment.task, {
|
||||
cascade: ["insert", "update"],
|
||||
})
|
||||
comments: TMTaskComment[];
|
||||
|
||||
@ManyToMany(() => User, (user) => user.tasks)
|
||||
@JoinTable({
|
||||
name: "tm_task_users",
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Injectable, NotFoundException } from "@nestjs/common";
|
||||
import { TaskCommentRepository } from "../repositories/task-comment.repository";
|
||||
import { TMTaskComment } from "../entities/task-comment.entity";
|
||||
import { CreateTaskCommentDto } from "../dto/task-comment/create-task-comment.dto";
|
||||
import { UpdateTaskCommentDto } from "../dto/task-comment/update-task-comment.dto";
|
||||
import { taskCommentMessage } from "../../../common/enums/message.enum";
|
||||
import { TaskService } from "./task.service";
|
||||
|
||||
@Injectable()
|
||||
export class TaskCommentService {
|
||||
constructor(
|
||||
private readonly taskCommentRepository: TaskCommentRepository,
|
||||
private readonly taskService: TaskService,
|
||||
) {}
|
||||
|
||||
async findOneOrFail(id: string): Promise<TMTaskComment> {
|
||||
const comment = await this.taskCommentRepository.findOne({
|
||||
where: { id },
|
||||
relations: { user: true, task: true },
|
||||
});
|
||||
if (!comment) throw new NotFoundException(taskCommentMessage.TASK_COMMENT_NOT_FOUND);
|
||||
return comment;
|
||||
}
|
||||
|
||||
async getTaskComments(taskId: string): Promise<TMTaskComment[]> {
|
||||
await this.taskService.findOneOrFail(taskId);
|
||||
|
||||
return this.taskCommentRepository.find({
|
||||
where: { taskId },
|
||||
relations: { user: true },
|
||||
order: { createdAt: "DESC" },
|
||||
});
|
||||
}
|
||||
|
||||
async create(userId: string, dto: CreateTaskCommentDto): Promise<TMTaskComment> {
|
||||
await this.taskService.findOneOrFail(dto.taskId);
|
||||
|
||||
const comment = this.taskCommentRepository.create({
|
||||
...dto,
|
||||
userId,
|
||||
});
|
||||
return this.taskCommentRepository.save(comment);
|
||||
}
|
||||
|
||||
async update(id: string, dto: UpdateTaskCommentDto): Promise<TMTaskComment> {
|
||||
const comment = await this.findOneOrFail(id);
|
||||
|
||||
if (dto.taskId) {
|
||||
await this.taskService.findOneOrFail(dto.taskId);
|
||||
}
|
||||
|
||||
Object.assign(comment, dto);
|
||||
return this.taskCommentRepository.save(comment);
|
||||
}
|
||||
|
||||
async remove(id: string): Promise<void> {
|
||||
await this.findOneOrFail(id);
|
||||
await this.taskCommentRepository.delete(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { InjectRepository } from "@nestjs/typeorm";
|
||||
import { Repository } from "typeorm";
|
||||
import { TMTaskComment } from "../entities/task-comment.entity";
|
||||
|
||||
@Injectable()
|
||||
export class TaskCommentRepository extends Repository<TMTaskComment> {
|
||||
constructor(
|
||||
@InjectRepository(TMTaskComment) taskCommentRepository: Repository<TMTaskComment>,
|
||||
) {
|
||||
super(taskCommentRepository.target, taskCommentRepository.manager, taskCommentRepository.queryRunner);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { TMRemark } from "./entities/remark.entity";
|
||||
import { TMAttachment } from "./entities/attachment.entity";
|
||||
import { TMCheckListItem } from "./entities/check-list-item.entity";
|
||||
import { TMTime } from "./entities/time.entity";
|
||||
import { TMTaskComment } from "./entities/task-comment.entity";
|
||||
import { WorkspaceRepository } from "./repositories/workspace.repository";
|
||||
import { WorkspaceController } from "./controllers/workspace.controller";
|
||||
import { WorkspaceService } from "./providers/workspace.service";
|
||||
@@ -35,10 +36,13 @@ import { AttachmentService } from "./providers/attachment.service";
|
||||
import { TimeController } from "./controllers/time.controller";
|
||||
import { TimeRepository } from "./repositories/time.repository";
|
||||
import { TimeService } from "./providers/time.service";
|
||||
import { TaskCommentController } from "./controllers/task-comment.controller";
|
||||
import { TaskCommentRepository } from "./repositories/task-comment.repository";
|
||||
import { TaskCommentService } from "./providers/task-comment.service";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([TMWorkspace, TMProject, TMTaskPhase, TMTask, TMRemark, TMAttachment, TMCheckListItem, TMTime, User, Ticket]),
|
||||
TypeOrmModule.forFeature([TMWorkspace, TMProject, TMTaskPhase, TMTask, TMRemark, TMAttachment, TMCheckListItem, TMTime, TMTaskComment, User, Ticket]),
|
||||
],
|
||||
controllers: [
|
||||
WorkspaceController,
|
||||
@@ -49,6 +53,7 @@ import { TimeService } from "./providers/time.service";
|
||||
RemarkController,
|
||||
AttachmentController,
|
||||
TimeController,
|
||||
TaskCommentController,
|
||||
],
|
||||
providers: [
|
||||
WorkspaceRepository,
|
||||
@@ -67,6 +72,8 @@ import { TimeService } from "./providers/time.service";
|
||||
AttachmentService,
|
||||
TimeRepository,
|
||||
TimeService,
|
||||
TaskCommentRepository,
|
||||
TaskCommentService,
|
||||
]
|
||||
})
|
||||
export class TaskManagerModule {}
|
||||
|
||||
Reference in New Issue
Block a user