Skip to content

Commit

Permalink
Merge pull request #82 from side-peek/feat/#80-project-comment-contro…
Browse files Browse the repository at this point in the history
…ller

프로젝트 댓글 저장/수정/삭제/조회(목록) api 컨트롤러 및 스웨거 설정
  • Loading branch information
Sehee-Lee-01 authored Mar 5, 2024
2 parents 6db026d + 24f0d1d commit 7f87e15
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package sixgaezzang.sidepeek.comments.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sixgaezzang.sidepeek.comments.dto.request.CommentRequest;
import sixgaezzang.sidepeek.comments.dto.response.CommentResponse;
import sixgaezzang.sidepeek.common.annotation.Login;

@RestController
@RequestMapping("/projects/{projectId}/comments")
@Tag(name = "Project Comment", description = "Project Comment API")
@RequiredArgsConstructor
public class CommentController {

@PostMapping
@Operation(summary = "댓글 생성")
@ApiResponse(responseCode = "201", description = "댓글 생성 성공")
public ResponseEntity<CommentResponse> save(
@Schema(description = "로그인한 회원 식별자", example = "1")
@Login
Long loginId,

@Schema(description = "생성할 댓글의 프로젝트 식별자", example = "1")
@PathVariable
Long projectId,

@Valid
@RequestBody
CommentRequest request
) {
return null;
}

@PutMapping("/{id}")
@Operation(summary = "댓글 수정")
@ApiResponse(responseCode = "200", description = "댓글 수정 성공")
public ResponseEntity<CommentResponse> update(
@Schema(description = "로그인한 회원 식별자", example = "1")
@Login
Long loginId,

@Schema(description = "수정할 댓글의 프로젝트 식별자", example = "1")
@PathVariable
Long projectId,

@Schema(description = "수정할 댓글 식별자", example = "1")
@PathVariable(value = "id")
Long commentId,

@Valid
@RequestBody
CommentRequest request
) {
return null;
}

@DeleteMapping("/{id}")
@Operation(summary = "댓글 삭제")
@ApiResponse(responseCode = "204", description = "댓글 삭제 성공")
public ResponseEntity<Void> delete(
@Schema(description = "로그인한 회원 식별자", example = "1")
@Login
Long loginId,

@Schema(description = "삭제할 댓글의 프로젝트 식별자", example = "1")
@PathVariable
Long projectId,

@Schema(description = "삭제할 댓글 식별자", example = "1")
@PathVariable(value = "id")
Long commentId
) {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sixgaezzang.sidepeek.comments.dto.request;

import static sixgaezzang.sidepeek.comments.exception.message.CommentErrorMessage.CONTENT_IS_NULL;
import static sixgaezzang.sidepeek.comments.exception.message.CommentErrorMessage.CONTENT_OVER_MAX_LENGTH;
import static sixgaezzang.sidepeek.comments.exception.message.CommentErrorMessage.IS_ANONYMOUS_IS_NULL;
import static sixgaezzang.sidepeek.comments.util.CommentConstant.MAX_COMMENT_LENGTH;
import static sixgaezzang.sidepeek.common.util.CommonConstant.MIN_ID;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

@Schema(description = "댓글 생성/수정 요청 정보")
public record CommentRequest(
@Schema(description = "댓글 작성자 식별자", example = "1")
@Min(value = MIN_ID, message = "작성자 id는 " + MIN_ID + "보다 작을 수 없습니다.")
Long ownerId,

@Schema(description = "익명 댓글 여부", example = "false")
@NotNull(message = IS_ANONYMOUS_IS_NULL)
Boolean isAnonymous,

@Schema(description = "댓글 내용", example = "우와 이 프로젝트 대박인데요?")
@Size(max = MAX_COMMENT_LENGTH, message = CONTENT_OVER_MAX_LENGTH)
@NotBlank(message = CONTENT_IS_NULL)
String content
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package sixgaezzang.sidepeek.comments.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;

@Schema(description = "댓글 목록 응답 정보")
public record CommentListResponse(
@Schema(description = "댓글 목록 정보(오래된 순)")
List<CommentResponse> comments
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sixgaezzang.sidepeek.comments.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import sixgaezzang.sidepeek.users.dto.response.UserSummary;
// TODO: 대댓글 반영 부탁해용!!

@Schema(description = "댓글 응답 정보")
public record CommentResponse(
@Schema(description = "댓글 식별자", example = "1")
Long id,

@Schema(description = "댓글 작성자 정보(익명 댓글은 null)")
UserSummary owner,

@Schema(description = "댓글 작성자와 로그인 사용자 일치 여부")
boolean isOwner,

@Schema(description = "익명 댓글 여부")
boolean isAnonymous,

@Schema(description = "댓글 내용", example = "우와 이 프로젝트 대박인데요?")
String content,

@Schema(description = "댓글 생성 시각", example = "2024-03-02 20:17:00", type = "string")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createdAt
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package sixgaezzang.sidepeek.comments.exception.message;

import static sixgaezzang.sidepeek.comments.util.CommentConstant.MAX_COMMENT_LENGTH;

public class CommentErrorMessage {
// isAnonymous
public static final String IS_ANONYMOUS_IS_NULL = "익명 댓글 여부를 입력해주세요.";

// content
public static final String CONTENT_IS_NULL = "댓글 내용을 입력해주세요.";
public static final String CONTENT_OVER_MAX_LENGTH = "댓글은 " + MAX_COMMENT_LENGTH + "자 이하여야 합니다.";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package sixgaezzang.sidepeek.comments.util;

public class CommentConstant {
public static final int MAX_COMMENT_LENGTH = 300;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ public List<ProjectSkillSummary> saveAll(Project project, List<ProjectSkillSaveR
.map(ProjectSkillSummary::from)
.toList();
}



public List<ProjectSkill> findAll(Project project) {
return projectSkillRepository.findAllByProject(project);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ public static void validateDescription(String description) {
validateTextLength(description, DESCRIPTION_OVER_MAX_LENGTH);
}


public static void validateOwnerId(Long ownerId) {
Assert.notNull(ownerId, OWNER_ID_IS_NULL);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package sixgaezzang.sidepeek.projects.service;


import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
import static sixgaezzang.sidepeek.projects.exception.message.FileErrorMessage.OVERVIEW_IMAGE_OVER_MAX_COUNT;
Expand Down Expand Up @@ -84,7 +83,6 @@ void setup() {
assertThat(savedImageUrls).isNull();
}


@Test
void 목록_개수가_최대를_넘어서_파일_목록_저장에_실패한다() {
// given, when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ class ProjectSkillServiceTest {

@Autowired
ProjectSkillService projectSkillService;

@Autowired
ProjectSkillRepository projectSkillRepository;

@Autowired
SkillRepository skillRepository;

@Autowired
ProjectRepository projectRepository;

@Autowired
UserRepository userRepository;

Expand Down

0 comments on commit 7f87e15

Please sign in to comment.