-
Notifications
You must be signed in to change notification settings - Fork 3
[feat] 퀴즈 조회, 수정, 삭제 API 구현 #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
098dc1d
:sparkles: 퀴즈 조회, 수정, 삭제 API 구현
silver-eunjoo c26c489
chore: Java 스타일 수정
a0fd2f9
:recycle: refactor : StringUtils.isBlank 적용 및 로그 수정
silver-eunjoo 0147325
chore: Java 스타일 수정
e7ddc83
:sparkles: feat: 퀴즈 목록 조회 최신순으로 정렬
silver-eunjoo 9ed7545
chore: Java 스타일 수정
f7ded66
Merge branch 'dev' into feat/23
silver-eunjoo db0e8ff
chore: Java 스타일 수정
5885b66
:recycle: refactor : default 문자열 상수로 빼기
silver-eunjoo 780f03b
:recycle: refactor : StringUtils import문 수정, 메서드명 수정
silver-eunjoo 6d9483c
chore: Java 스타일 수정
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,31 @@ | ||
| package io.f1.backend.domain.quiz.app; | ||
|
|
||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.pageQuizToPageQuizListResponse; | ||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.quizCreateRequestToQuiz; | ||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.quizToQuizCreateResponse; | ||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.toQuizListPageResponse; | ||
|
|
||
| import static java.nio.file.Files.deleteIfExists; | ||
|
|
||
| import io.f1.backend.domain.question.app.QuestionService; | ||
| import io.f1.backend.domain.question.dto.QuestionRequest; | ||
| import io.f1.backend.domain.quiz.dao.QuizRepository; | ||
| import io.f1.backend.domain.quiz.dto.QuizCreateRequest; | ||
| import io.f1.backend.domain.quiz.dto.QuizCreateResponse; | ||
| import io.f1.backend.domain.quiz.dto.QuizListPageResponse; | ||
| import io.f1.backend.domain.quiz.dto.QuizListResponse; | ||
| import io.f1.backend.domain.quiz.dto.QuizUpdateRequest; | ||
| import io.f1.backend.domain.quiz.entity.Quiz; | ||
| import io.f1.backend.domain.user.dao.UserRepository; | ||
| import io.f1.backend.domain.user.entity.User; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| import org.apache.commons.lang3.StringUtils; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.data.domain.Pageable; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
|
|
@@ -23,8 +34,10 @@ | |
| import java.nio.file.Path; | ||
| import java.nio.file.Paths; | ||
| import java.util.List; | ||
| import java.util.NoSuchElementException; | ||
| import java.util.UUID; | ||
|
|
||
| @Slf4j | ||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class QuizService { | ||
|
|
@@ -35,6 +48,8 @@ public class QuizService { | |
| @Value("${file.default-thumbnail-url}") | ||
| private String defaultThumbnailPath; | ||
|
|
||
| private final String DEFAULT = "default"; | ||
|
|
||
| // TODO : 시큐리티 구현 이후 삭제해도 되는 의존성 주입 | ||
| private final UserRepository userRepository; | ||
| private final QuestionService questionService; | ||
|
|
@@ -92,6 +107,92 @@ private String getExtension(String filename) { | |
| return filename.substring(filename.lastIndexOf(".") + 1); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void deleteQuiz(Long quizId) { | ||
|
|
||
| Quiz quiz = | ||
| quizRepository | ||
| .findById(quizId) | ||
| .orElseThrow(() -> new NoSuchElementException("존재하지 않는 퀴즈입니다.")); | ||
|
|
||
| // TODO : util 메서드에서 사용자 ID 꺼내쓰는 식으로 수정하기 | ||
| if (1L != quiz.getCreator().getId()) { | ||
| throw new RuntimeException("권한이 없습니다."); | ||
| } | ||
|
|
||
| deleteThumbnailFile(quiz.getThumbnailUrl()); | ||
| quizRepository.deleteById(quizId); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void updateQuiz(Long quizId, MultipartFile thumbnailFile, QuizUpdateRequest request) | ||
| throws IOException { | ||
|
|
||
| Quiz quiz = | ||
| quizRepository | ||
| .findById(quizId) | ||
| .orElseThrow(() -> new NoSuchElementException("존재하지 않는 퀴즈입니다.")); | ||
|
|
||
| if (request.title() != null) { | ||
| quiz.changeTitle(request.title()); | ||
| } | ||
|
|
||
| if (request.description() != null) { | ||
| quiz.changeDescription(request.description()); | ||
| } | ||
|
|
||
| if (thumbnailFile != null && !thumbnailFile.isEmpty()) { | ||
| validateImageFile(thumbnailFile); | ||
| String newThumbnailPath = convertToThumbnailPath(thumbnailFile); | ||
|
|
||
| deleteThumbnailFile(quiz.getThumbnailUrl()); | ||
| quiz.changeThumbnailUrl(newThumbnailPath); | ||
| } | ||
| } | ||
|
|
||
| private void deleteThumbnailFile(String oldFilename) { | ||
| if (oldFilename.contains(DEFAULT)) { | ||
| return; | ||
| } | ||
|
|
||
| // oldFilename : /images/thumbnail/123asd.jpg | ||
| // filename : 123asd.jpg | ||
| String filename = oldFilename.substring(oldFilename.lastIndexOf("/") + 1); | ||
| Path filePath = Paths.get(uploadPath, filename).toAbsolutePath(); | ||
|
|
||
| try { | ||
| boolean deleted = deleteIfExists(filePath); | ||
| if (deleted) { | ||
| log.info("기존 썸네일 삭제 완료 : {}", filePath); | ||
| } else { | ||
| log.info("기존 썸네일 존재 X : {}", filePath); | ||
| } | ||
| } catch (IOException e) { | ||
| log.error("기존 썸네일 삭제 중 오류 : {}", filePath); | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public QuizListPageResponse getQuizzes(String title, String creator, Pageable pageable) { | ||
|
|
||
| Page<Quiz> quizzes; | ||
|
|
||
| // 검색어가 있을 때 | ||
| if (StringUtils.isBlank(title)) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L5-참고의견]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉 import가 잘못됐네요 ! 감사합니다 ! 혹시 멘토링 때 그 차이점이 뭐라고 하셨나요? |
||
| quizzes = quizRepository.findQuizzesByTitleContaining(title, pageable); | ||
| } else if (StringUtils.isBlank(creator)) { | ||
| quizzes = quizRepository.findQuizzesByCreator_NicknameContaining(creator, pageable); | ||
| } else { // 검색어가 없을 때 혹은 빈 문자열일 때 | ||
| quizzes = quizRepository.findAll(pageable); | ||
| } | ||
|
|
||
| Page<QuizListResponse> quizListResponses = pageQuizToPageQuizListResponse(quizzes); | ||
|
|
||
| return toQuizListPageResponse(quizListResponses); | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public Quiz getQuizById(Long quizId) { | ||
| return quizRepository | ||
| .findById(quizId) | ||
|
|
||
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
6 changes: 6 additions & 0 deletions
6
backend/src/main/java/io/f1/backend/domain/quiz/dto/QuizListPageResponse.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package io.f1.backend.domain.quiz.dto; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record QuizListPageResponse( | ||
| int totalPages, int currentPage, long totalElements, List<QuizListResponse> quiz) {} |
9 changes: 9 additions & 0 deletions
9
backend/src/main/java/io/f1/backend/domain/quiz/dto/QuizListResponse.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package io.f1.backend.domain.quiz.dto; | ||
|
|
||
| public record QuizListResponse( | ||
| Long quizId, | ||
| String title, | ||
| String description, | ||
| String creatorNickname, | ||
| int numberOfQuestion, | ||
| String thumbnailUrl) {} |
3 changes: 3 additions & 0 deletions
3
backend/src/main/java/io/f1/backend/domain/quiz/dto/QuizUpdateRequest.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package io.f1.backend.domain.quiz.dto; | ||
|
|
||
| public record QuizUpdateRequest(String title, String description) {} |
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
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분은 지금 퀴즈리스트에 대한 정렬이 적용이 된건가요?.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
퀴즈 리스트에 대한 정렬은 적용되지 않았습니다 !
따로 정한 기준은 없었던 것 같은데,,, 제가 기억이 안 나는 걸까요..? 혹시 어떤 정렬을 해야 할까요?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[L4-변경제안]
최신순, 인기순 정렬을 변경하는 기능은 정의하지 않았지만, 디폴트 정렬은 있어야 사용자에게 일관적인 리스트를 보여줄 수 있다고 생각합니다!(명시하지않아서 디폴트 정렬로 나오는 것 같지만, 안정적으로 명시하는게 좋다는 의견입니다) 현재 1번부터 나오는 asc라면 desc로 정렬하면(최신순) 어떨까하는 의견입니다. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오..! 그렇군요. 페이징을 처음해봐서 정렬까지 같이 처리해주는 기능이 있는지 몰랐는데 디폴트로 정렬기준이 있다면 아주 유용하고 좋을 것 같습니다. 의견 반영해서 커밋 다시 올렸습니다. 좋은 의견 감사합니다 !!