Skip to content

Commit

Permalink
Merge pull request #109 from modern-agile-team/feature/comment
Browse files Browse the repository at this point in the history
Add(2swo/comment-reComment) 대댓글 기능 추가
  • Loading branch information
2swo authored Nov 10, 2023
2 parents e591021 + 31a7179 commit 8330b67
Show file tree
Hide file tree
Showing 18 changed files with 555 additions and 43 deletions.
4 changes: 4 additions & 0 deletions src/comments/comment.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ import { CommentsService } from './services/comments.services';
import { TokenService } from 'src/auth/services/token.service';
import { CommentsRepository } from './repository/comments.repository';
import { TokenRepository } from 'src/auth/repositories/token.repository';
import { ReCommentsService } from './services/recomments.services';
import { ReCommentsRepository } from './repository/recomments.repository';

@Module({
imports: [TypeOrmModule.forFeature([Comment, ReComment])],
controllers: [CommentsController],
providers: [
CommentsService,
CommentsRepository,
ReCommentsService,
ReCommentsRepository,
TokenService,
TokenRepository,
],
Expand Down
44 changes: 42 additions & 2 deletions src/comments/controllers/comments.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,22 @@ import { CommentsService } from '../services/comments.services';
import { TokenService } from 'src/auth/services/token.service';
import { CreateCommentDto } from '../dto/create-comment-dto';
import { ApiAddComment } from '../swagger-decoratros/add-comment-decorators';
import { ApiGetAllComment } from '../swagger-decoratros/get-all-comment-decoratros';
import { ApiGetAllComment } from '../swagger-decoratros/get-all-comment-decorators';
import { commentResponseDTO } from '../dto/get-all-comment-dto';
import { ApiUpdateComment } from '../swagger-decoratros/patch-comment-decoratros';
import { ApiUpdateComment } from '../swagger-decoratros/patch-comment-decorators';
import { ApiDeleteComment } from '../swagger-decoratros/delete-comment-decorator';
import { ReCommentsService } from '../services/recomments.services';
import { CreateReCommentDto } from '../dto/create-recomment-dto';
import { ReComment } from '../entities/recomment.entity';
import { ApiAddReComment } from '../swagger-decoratros/add-recomment-decorators';
import { ApiUpdateReComment } from '../swagger-decoratros/patch-recomment-decorator';

@Controller('comments')
@ApiTags('Comment API')
export class CommentsController {
constructor(
private readonly commentsService: CommentsService,
private readonly recommentsService: ReCommentsService,
private tokenService: TokenService,
) {}

Expand All @@ -38,6 +44,21 @@ export class CommentsController {
return await this.commentsService.create(createCommentDto, userId, boardId);
}

@Post('/Re')
@ApiAddReComment()
async createReComment(
@Headers('access_token') accessToken: string,
@Query('commentId') commentId: number,
@Body() createReCommentDto: CreateReCommentDto,
): Promise<ReComment> {
const userId = await this.tokenService.decodeToken(accessToken);
return await this.recommentsService.create(
createReCommentDto,
userId,
commentId,
);
}

@Get('')
@ApiGetAllComment()
async getComment(
Expand All @@ -57,6 +78,15 @@ export class CommentsController {
return this.commentsService.updateComment(commentId, commentData);
}

@Patch('/Re')
@ApiUpdateReComment()
async updateReComment(
@Query('reCommentId') reCommentId: number,
@Body() recommentData: Partial<ReComment>,
): Promise<ReComment> {
return this.recommentsService.updateReComment(reCommentId, recommentData);
}

@Delete('')
@ApiDeleteComment()
async deleteComment(
Expand All @@ -66,4 +96,14 @@ export class CommentsController {
const userId = await this.tokenService.decodeToken(accessToken);
await this.commentsService.deleteComment(commentId, userId);
}

@Delete('/Re')
@ApiDeleteComment()
async deleteReComment(
@Query('reCommentId') reCommentId: number,
@Headers('access_token') accessToken: string,
) {
const userId = await this.tokenService.decodeToken(accessToken);
await this.recommentsService.deleteReComment(reCommentId, userId);
}
}
6 changes: 6 additions & 0 deletions src/comments/dto/create-recomment-dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IsString } from 'class-validator';

export class CreateReCommentDto {
@IsString()
content: string;
}
13 changes: 11 additions & 2 deletions src/comments/dto/get-all-comment-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ import { UserImage } from 'src/users/entities/user-image.entity';
export class commentResponseDTO {
id: number;
content: string;
commentowner: true | false;
userId: {
commentowner: boolean;
user: {
name: string;
userImage: UserImage | UserImage[];
};
reComment: {
id: number;
content: string;
reCommentowner: boolean;
user: {
name: string;
userImage: UserImage | UserImage[];
};
}[];
}
11 changes: 11 additions & 0 deletions src/comments/dto/get-all-recomment-dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { UserImage } from 'src/users/entities/user-image.entity';

export class reCommentResponseDTO {
id: number;
content: string;
reCommentowner: boolean;
user: {
name: string;
userImage: UserImage | UserImage[];
};
}
6 changes: 6 additions & 0 deletions src/comments/dto/update-recomment-dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IsString } from 'class-validator';

export class UpdateReCommentDto {
@IsString()
content: string;
}
7 changes: 7 additions & 0 deletions src/comments/entities/comment.entity.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Board } from 'src/boards/entities/board.entity';
import { User } from 'src/users/entities/user.entity';
import { ReComment } from './recomment.entity';
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';

Expand All @@ -23,6 +25,11 @@ export class Comment {
@Column({ name: 'user_id' })
userId: number;

@OneToMany(() => ReComment, (reComment) => reComment.comment, {
onDelete: 'CASCADE',
})
reComment: ReComment[];

@ManyToOne(() => Board)
@JoinColumn({ name: 'board_id' })
board: Board;
Expand Down
2 changes: 1 addition & 1 deletion src/comments/entities/recomment.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ReComment {
@Column({ name: 'user_id' })
userId: number;

@ManyToOne(() => Comment)
@ManyToOne(() => Comment, (comment) => comment.reComment)
@JoinColumn({ name: 'comment_id' })
comment: Comment;

Expand Down
9 changes: 6 additions & 3 deletions src/comments/repository/comments.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ export class CommentsRepository {
const query = this.entityManager
.createQueryBuilder(Comment, 'comment')
.innerJoinAndSelect('comment.user', 'user')
.innerJoinAndSelect('user.userImage', 'userImage')
.where('comment.boardId = :boardId', { boardId });

.leftJoinAndSelect('comment.reComment', 'reComment')
.leftJoinAndSelect('reComment.user', 'reCommentUser')
.leftJoinAndSelect('reCommentUser.userImage', 'reCommentUserImage')
.leftJoinAndSelect('user.userImage', 'userImage')
.where('comment.boardId = :boardId', { boardId })
.groupBy('comment.id');
return query.getMany();
}

Expand Down
57 changes: 57 additions & 0 deletions src/comments/repository/recomments.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { ReComment } from '../entities/recomment.entity';
import { CreateReCommentDto } from '../dto/create-recomment-dto';

@Injectable()
export class ReCommentsRepository {
constructor(private readonly entityManager: EntityManager) {}
async createReComment(
recommentData: CreateReCommentDto,
userId: number,
commentId: number,
): Promise<ReComment> {
const reComment = new ReComment();
reComment.content = recommentData.content;
reComment.userId = userId;
reComment.commentId = commentId;
return await this.entityManager.save(ReComment, reComment);
}

async findReCommentByCommentId(commentId: number): Promise<ReComment[]> {
const query = this.entityManager
.createQueryBuilder(ReComment, 'reComment')
.innerJoinAndSelect('reComment.user', 'user')
.innerJoinAndSelect('user.userImage', 'userImage')
.where('reComment.commentId = :commentId', { commentId });
return query.getMany();
}

async findOneReComment(id: number): Promise<ReComment> {
return this.entityManager.findOne(ReComment, {
relations: ['user', 'user.userImage'],
where: { id },
});
}

async updateReComment(
id: number,
commentData: Partial<CreateReCommentDto>,
): Promise<ReComment> {
const existingReComment = await this.entityManager.findOne(ReComment, {
relations: ['user', 'user.userImage'],
where: { id },
});
for (const key in commentData) {
if (commentData.hasOwnProperty(key)) {
existingReComment[key] = commentData[key];
}
}
await this.entityManager.save(ReComment, existingReComment);
return existingReComment;
}

async deleteReComment(reComment: ReComment): Promise<void> {
await this.entityManager.remove(ReComment, reComment);
}
}
14 changes: 12 additions & 2 deletions src/comments/services/comments.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,26 @@ export class CommentsService {
const comments =
await this.CommentRepository.findCommentsByBoardId(boardId);
if (!comments) {
throw new Error('댓글을 찾을 수 없습니다.');
return []; // 에러 말고 리턴으로 빈 배열
}
return comments.map((comment) => ({
id: comment.id,
content: comment.content,
commentowner: comment.userId === userId,
userId: {
user: {
name: comment.user.name,
userImage: comment.user.userImage ? comment.user.userImage : [],
},
reComment: (comment.reComment || []).map((reComment) => ({
//예외처리 , reComment가 없을경우 빈 배열
id: reComment.id,
content: reComment.content,
reCommentowner: reComment.userId === userId,
user: {
name: reComment.user.name,
userImage: reComment.user.userImage ? reComment.user.userImage : [],
},
})),
}));
}

Expand Down
78 changes: 78 additions & 0 deletions src/comments/services/recomments.services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Injectable } from '@nestjs/common';
import { CreateReCommentDto } from '../dto/create-recomment-dto';
import { ReComment } from '../entities/recomment.entity';
import { ReCommentsRepository } from '../repository/recomments.repository';
import { UpdateReCommentDto } from '../dto/update-recomment-dto';
import { reCommentResponseDTO } from '../dto/get-all-recomment-dto';

@Injectable()
export class ReCommentsService {
constructor(private reCommentRepository: ReCommentsRepository) {}
async create(
recommentData: CreateReCommentDto,
userId: number,
commentId: number,
): Promise<ReComment> {
try {
return await this.reCommentRepository.createReComment(
recommentData,
userId,
commentId,
);
} catch (error) {
console.log(error);
}
}

async updateReComment(
reCommentId: number,
reCommentData: Partial<UpdateReCommentDto>,
): Promise<ReComment | undefined> {
const existingComment =
await this.reCommentRepository.findOneReComment(reCommentId);
for (const key in reCommentData) {
if (reCommentData.hasOwnProperty(key)) {
existingComment[key] = reCommentData[key];
}
}
const updatedReComment = await this.reCommentRepository.updateReComment(
reCommentId,
existingComment,
);
return updatedReComment;
}

async findAllReComments(
commentId: number,
userId: number,
): Promise<reCommentResponseDTO[]> {
const reComments =
await this.reCommentRepository.findReCommentByCommentId(commentId);
if (!reComments) {
return [];
}
return reComments.map((reComment) => ({
id: reComment.id,
content: reComment.content,
reCommentowner: reComment.userId === userId,
user: {
name: reComment.user.name,
userImage: reComment.user.userImage ? reComment.user.userImage : [],
},
}));
}

async deleteReComment(reCommentId: number, userId: number): Promise<void> {
const reComment =
await this.reCommentRepository.findOneReComment(reCommentId);

if (!reComment) {
throw new Error('존재하지 않는 댓글입니다.');
}

if (reComment.userId !== userId) {
throw new Error('작성한 댓글이 아닙니다.');
}
await this.reCommentRepository.deleteReComment(reComment);
}
}
Loading

0 comments on commit 8330b67

Please sign in to comment.