Skip to content

Commit

Permalink
Feat(#54): 게시글에 댓글 작성하기 api 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
versatile0010 committed Nov 13, 2023
1 parent 2a4b9c2 commit a32c30b
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import com.numberone.backend.domain.article.dto.request.UploadArticleRequest;
import com.numberone.backend.domain.article.dto.response.*;
import com.numberone.backend.domain.article.service.ArticleService;
import com.numberone.backend.domain.comment.dto.request.CreateCommentRequest;
import com.numberone.backend.domain.comment.dto.response.CreateCommentResponse;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import jakarta.websocket.server.PathParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -64,28 +65,46 @@ public ResponseEntity<GetArticleDetailResponse> getArticleDetails(@PathVariable(


@Operation(summary = "게시글 리스트 조회 no offset Paging API 입니다.", description = """
요청 예시 url 은 다음과 같습니다.
`/api/articles?size=5`
size 는 페이지의 사이즈를 의미하고, default 는 20 입니다.
정렬 순서는 articleId 순입니다. ( = 생성 시간 순 )
ModelAttribute 로 lastArticleId 와 tag 를 넘겨주세요 ( 둘 다 nullable )
tag 가 null 이면, tag 상관 없이 전체 조회를 수행합니다.
tag 가 null 이 아니면, 해당 tag 에 해당하는 게시글만 조회합니다.
lastArticleId 는 직전에 조회한 게시글 중 가장 먀지막(작은) articleId 를 의미합니다.
- 첫 페이지를 요청할 경우에는 lastArticleId 를 null 로 보내야합니다.
- 첫 페이지 이후에 대한 요청은, 직전 페이지 요청에서 얻어온 lastArticleId 를 넣어서 보내면 그 다음 페이지를 호출합니다.
""")
요청 예시 url 은 다음과 같습니다.
`/api/articles?size=5`
size 는 페이지의 사이즈를 의미하고, default 는 20 입니다.
정렬 순서는 articleId 순입니다. ( = 생성 시간 순 )
ModelAttribute 로 lastArticleId 와 tag 를 넘겨주세요 ( 둘 다 nullable )
tag 가 null 이면, tag 상관 없이 전체 조회를 수행합니다.
tag 가 null 이 아니면, 해당 tag 에 해당하는 게시글만 조회합니다.
lastArticleId 는 직전에 조회한 게시글 중 가장 먀지막(작은) articleId 를 의미합니다.
- 첫 페이지를 요청할 경우에는 lastArticleId 를 null 로 보내야합니다.
- 첫 페이지 이후에 대한 요청은, 직전 페이지 요청에서 얻어온 lastArticleId 를 넣어서 보내면 그 다음 페이지를 호출합니다.
""")
@GetMapping
public ResponseEntity<Slice<GetArticleListResponse>> getArticlePages(
Pageable pageable,
@ModelAttribute ArticleSearchParameter param){
@ModelAttribute ArticleSearchParameter param) {
return ResponseEntity.ok(articleService.getArticleListPaging(param, pageable));
}

@Operation(summary = "게시글에 댓글 작성하기", description = """
게시글에 댓글을 작성하는 API 입니다.
게시글 아이디는 Path Parameter 으로 넘겨주세요 (article-id)
""")
@PostMapping("comments/{article-id}")
public ResponseEntity<CreateCommentResponse> createComment(
@PathVariable("article-id") Long articleId,
@RequestBody @Valid CreateCommentRequest request) {
return ResponseEntity.created(
URI.create(String.format("/api/articles/comment/%s", articleId)))
.body(articleService.createComment(articleId, request));

}



}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
import com.numberone.backend.domain.articleimage.repository.ArticleImageRepository;
import com.numberone.backend.domain.articleparticipant.entity.ArticleParticipant;
import com.numberone.backend.domain.articleparticipant.repository.ArticleParticipantRepository;
import com.numberone.backend.domain.comment.dto.request.CreateCommentRequest;
import com.numberone.backend.domain.comment.dto.response.CreateCommentResponse;
import com.numberone.backend.domain.comment.entity.CommentEntity;
import com.numberone.backend.domain.comment.repository.CommentRepository;
import com.numberone.backend.domain.member.entity.Member;
import com.numberone.backend.domain.member.repository.MemberRepository;
import com.numberone.backend.domain.token.util.SecurityContextProvider;
Expand Down Expand Up @@ -40,6 +44,7 @@ public class ArticleService {
private final MemberRepository memberRepository;
private final ArticleParticipantRepository articleParticipantRepository;
private final ArticleImageRepository articleImageRepository;
private final CommentRepository commentRepository;
private final S3Provider s3Provider;

@Transactional
Expand All @@ -57,7 +62,7 @@ public UploadArticleResponse uploadArticle(UploadArticleRequest request) {
request.getArticleTag())
);
articleParticipantRepository.save(
new ArticleParticipant(article, owner.getId())
new ArticleParticipant(article, owner)
);

// 2. 이미지 업로드
Expand Down Expand Up @@ -141,4 +146,20 @@ public void updateArticleInfo(GetArticleListResponse articleInfo) {
articleInfo.updateInfo(owner, articleImage);
}

@Transactional
public CreateCommentResponse createComment(Long articleId, CreateCommentRequest request){
String principal = SecurityContextProvider.getAuthenticatedUserEmail();
Member member = memberRepository.findByEmail(principal)
.orElseThrow(NotFoundMemberException::new);
Article article = articleRepository.findById(articleId)
.orElseThrow(NotFoundArticleException::new);
CommentEntity savedComment = commentRepository.save(
new CommentEntity(request.getContent(), article)
);

articleParticipantRepository.save(new ArticleParticipant(article, member));

return CreateCommentResponse.of(savedComment);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.numberone.backend.config.basetime.BaseTimeEntity;
import com.numberone.backend.domain.article.entity.Article;
import com.numberone.backend.domain.member.entity.Member;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
Expand All @@ -28,8 +29,8 @@ public class ArticleParticipant extends BaseTimeEntity {
@Comment("회원 id")
private Long memberId;

public ArticleParticipant(Article article, Long memberId){
public ArticleParticipant(Article article, Member member){
this.article = article;
this.memberId= memberId;
this.memberId= member.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.numberone.backend.domain.comment.dto.request;

import com.numberone.backend.config.basetime.BaseTimeEntity;
import jakarta.validation.constraints.NotNull;
import lombok.*;

@ToString
@Builder
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class CreateCommentRequest {

@NotNull
private String content;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.numberone.backend.domain.comment.dto.response;

import com.numberone.backend.domain.comment.entity.CommentEntity;
import lombok.*;

import java.time.LocalDateTime;

@ToString
@Builder
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class CreateCommentResponse {
private LocalDateTime createdAt;
private Long commentId;

public static CreateCommentResponse of (CommentEntity comment){
return CreateCommentResponse.builder()
.createdAt(comment.getCreatedAt())
.commentId(comment.getId())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,14 @@ public class CommentEntity extends BaseTimeEntity {

@Comment("댓글 좋아요 개수")
private Integer likeCount; // todo: 동시성 처리

@Comment("댓글 내용")
private String content;

public CommentEntity(String content, Article article){
this.depth = 0;
this.content = content;
this.article = article;
}

}

0 comments on commit a32c30b

Please sign in to comment.