Skip to content

Commit

Permalink
Merge pull request #19 from Leets-Official/feat/#15/작성한-게시글미디어-조회-기능-구현
Browse files Browse the repository at this point in the history
[feat] 작성한 게시글미디어 조회 기능 구현
  • Loading branch information
ehs208 authored Nov 9, 2024
2 parents 238ac7d + 8cc4f47 commit 844a6e1
Show file tree
Hide file tree
Showing 15 changed files with 200 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,5 @@ jobs:
sudo docker ps
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/xcellent-be
sudo docker run -d -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/xcellent-be
sudo docker run -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKER_USERNAME }}/xcellent-be
sudo docker image prune -f
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.leets.xcellentbe.domain.article.dto.ArticleCreateRequestDto;
import com.leets.xcellentbe.domain.article.dto.ArticleCreateResponseDto;
import com.leets.xcellentbe.domain.article.dto.ArticleResponseDto;
import com.leets.xcellentbe.domain.article.dto.ArticlesResponseDto;
import com.leets.xcellentbe.domain.article.service.ArticleService;
import com.leets.xcellentbe.global.response.GlobalResponseDto;

Expand All @@ -34,17 +35,33 @@
public class ArticleController {
private final ArticleService articleService;

@GetMapping("/{customId}/list")
@Operation(summary = "특정 사용자의 게시글 조회", description = "특정 사용자의 게시글을 조회합니다.")
public ResponseEntity<GlobalResponseDto<List<ArticlesResponseDto>>> getArticles(@PathVariable String customId) {
return ResponseEntity.status(HttpStatus.OK)
.body(GlobalResponseDto.success(articleService.getArticles(customId, false)));
}

@GetMapping("/{customId}/list/media")
@Operation(summary = "특정 사용자의 미디어 게시글 조회", description = "특정 사용자의 미디어 게시글을 조회합니다.")
public ResponseEntity<GlobalResponseDto<List<ArticlesResponseDto>>> getMediaArticles(
@PathVariable String customId) {
return ResponseEntity.status(HttpStatus.OK)
.body(GlobalResponseDto.success(articleService.getArticles(customId, true)));
}

//게시글 작성
@PostMapping
@Operation(summary = "게시글 작성", description = "새 게시글을 작성합니다.")
public ResponseEntity<GlobalResponseDto<ArticleCreateResponseDto>> createArticle(
HttpServletRequest request,
@RequestBody ArticleCreateRequestDto articleCreateRequestDto,
@RequestParam(value = "mediaFiles", required = false) List<MultipartFile> mediaFiles){
@RequestParam(value = "mediaFiles", required = false) List<MultipartFile> mediaFiles) {
if (mediaFiles == null) {
mediaFiles = Collections.emptyList();
}
ArticleCreateResponseDto responseDto = articleService.createArticle(request, articleCreateRequestDto, mediaFiles);
ArticleCreateResponseDto responseDto = articleService.createArticle(request, articleCreateRequestDto,
mediaFiles);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(responseDto));
}

Expand All @@ -53,7 +70,7 @@ public ResponseEntity<GlobalResponseDto<ArticleCreateResponseDto>> createArticle
@Operation(summary = "게시글 삭제", description = "게시글을 삭제(상태 변경)합니다.")
public ResponseEntity<GlobalResponseDto<Void>> deleteArticle(
HttpServletRequest request,
@PathVariable UUID articleId){
@PathVariable UUID articleId) {
articleService.deleteArticle(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success());
}
Expand All @@ -63,7 +80,7 @@ public ResponseEntity<GlobalResponseDto<Void>> deleteArticle(
@Operation(summary = "게시글 조회", description = "해당 ID의 게시글을 조회합니다.")
public ResponseEntity<GlobalResponseDto<ArticleResponseDto>> getArticle(
HttpServletRequest request,
@PathVariable UUID articleId){
@PathVariable UUID articleId) {
ArticleResponseDto articleResponseDto = articleService.getArticle(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(articleResponseDto));
}
Expand All @@ -84,7 +101,7 @@ public ResponseEntity<GlobalResponseDto<List<ArticleResponseDto>>> getArticles(
@Operation(summary = "게시글 리포스트", description = "게시글을 리포스트합니다.")
public ResponseEntity<GlobalResponseDto<ArticleCreateResponseDto>> rePostArticle(
HttpServletRequest request,
@PathVariable UUID articleId){
@PathVariable UUID articleId) {
ArticleCreateResponseDto responseDto = articleService.rePostArticle(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(responseDto));
}
Expand All @@ -94,8 +111,9 @@ public ResponseEntity<GlobalResponseDto<ArticleCreateResponseDto>> rePostArticle
@Operation(summary = "리포스트 삭제", description = "리포스트를 삭제합니다.")
public ResponseEntity<GlobalResponseDto<Void>> deleteRepost(
HttpServletRequest request,
@PathVariable UUID articleId){
@PathVariable UUID articleId) {
articleService.deleteRepost(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success());

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)

public class Article extends BaseTimeEntity {

@Id
Expand Down Expand Up @@ -62,15 +63,23 @@ public class Article extends BaseTimeEntity {

private int viewCnt, repostCnt, likeCnt, commentCnt;


@Builder
private Article(User writer, String content, DeletedStatus deletedStatus) {
this.writer = writer;
this.content = content;
this.deletedStatus = DeletedStatus.NOT_DELETED;
}

public static Article createArticle(User writer, String content){
public Article(User writer, String content, DeletedStatus deletedStatus, Article rePost,
List<Hashtag> hashtags) {
this.writer = writer;
this.content = content;
this.deletedStatus = deletedStatus;
this.rePost = rePost;
this.hashtags = hashtags;
}

public static Article createArticle(User writer, String content) {
return Article.builder()
.writer(writer)
.content(content)
Expand All @@ -83,7 +92,7 @@ public void addRepost(Article rePost) {
}

public void addHashtag(List<Hashtag> hashtags) {
if(this.hashtags == null){
if (this.hashtags == null) {
this.hashtags = new ArrayList<>();
}
this.hashtags.addAll(hashtags);
Expand All @@ -100,30 +109,32 @@ public void addMedia(List<ArticleMedia> mediaList) {
this.mediaList.addAll(mediaList);
}

public void updateViewCount() {
public void updateViewCount() {
this.viewCnt++;
}

public void plusRepostCount() {
public void plusRepostCount() {
this.repostCnt++;
}

public void minusRepostCount() {
this.repostCnt--;
}

public void plusLikeCount() {
public void plusLikeCount() {
this.likeCnt++;
}

public void minusLikeCount() {
this.likeCnt--;
}
public void plusCommentCount() {

public void plusCommentCount() {
this.commentCnt++;
}

public void minusCommentCount() {
this.commentCnt--;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import com.leets.xcellentbe.domain.article.domain.Article;
import com.leets.xcellentbe.domain.article.dto.ArticlesWithMediaDto;
import com.leets.xcellentbe.domain.user.domain.User;

import io.lettuce.core.dynamic.annotation.Param;

@Repository
public interface ArticleRepository extends JpaRepository<Article, UUID> {
@Query("SELECT new com.leets.xcellentbe.domain.article.dto.ArticlesWithMediaDto(p, pm.filePath) FROM Article p LEFT JOIN PostMedia pm ON p.articleId = pm.article.articleId WHERE p.writer = :user")
List<ArticlesWithMediaDto[]> findPostsByWriter(User user);

@Query("SELECT a FROM Article a ORDER BY a.createdAt DESC")
List<Article> findRecentArticles(Pageable pageable);

@Query("SELECT a FROM Article a WHERE a.createdAt < :cursor ORDER BY a.createdAt DESC")
List<Article> findRecentArticles(@Param("cursor") LocalDateTime cursor, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.leets.xcellentbe.domain.article.dto;

import java.util.List;

import com.leets.xcellentbe.domain.article.domain.Article;
import com.leets.xcellentbe.domain.hashtag.domain.Hashtag;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@Getter
public class ArticlesResponseDto {
private String writer;
private String content;
private Boolean isPinned;
private List<Hashtag> hashtags;
private Article rePost;
private List<String> filePath;

@Builder
private ArticlesResponseDto(String writer, String content, Boolean isPinned, List<Hashtag> hashtags,
Article rePost,
List<String> filePath) {
this.writer = writer;
this.content = content;
this.isPinned = isPinned;
this.hashtags = hashtags;
this.rePost = rePost;
this.filePath = filePath;
}

public static ArticlesResponseDto of(Article article, List<String> filePath) {
return ArticlesResponseDto.builder()
.writer(article.getWriter().getUserName())
.content(article.getContent())
.hashtags(article.getHashtags())
.rePost(article.getRePost())
.filePath(filePath)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.leets.xcellentbe.domain.article.dto;

import com.leets.xcellentbe.domain.article.domain.Article;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ArticlesWithMediaDto {
private Article article;
private String filePath;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

Expand All @@ -17,6 +19,8 @@
import com.leets.xcellentbe.domain.article.dto.ArticleCreateRequestDto;
import com.leets.xcellentbe.domain.article.dto.ArticleCreateResponseDto;
import com.leets.xcellentbe.domain.article.dto.ArticleResponseDto;
import com.leets.xcellentbe.domain.article.dto.ArticlesResponseDto;
import com.leets.xcellentbe.domain.article.dto.ArticlesWithMediaDto;
import com.leets.xcellentbe.domain.article.exception.ArticleNotFoundException;
import com.leets.xcellentbe.domain.article.exception.DeleteForbiddenException;
import com.leets.xcellentbe.domain.articleMedia.domain.ArticleMedia;
Expand All @@ -36,18 +40,49 @@
@Transactional
@RequiredArgsConstructor
public class ArticleService {

private final ArticleRepository articleRepository;
private final ArticleMediaRepository articleMediaRepository;
private final UserRepository userRepository;
private final HashtagService hashtagService;
private final S3UploadMediaService s3UploadMediaService;
private final JwtService jwtService;

public List<ArticlesResponseDto> getArticles(String customId, boolean mediaOnly) {
User user = getUser(customId);
List<ArticlesWithMediaDto[]> posts = getPosts(user);

Map<Article, List<String>> groupedPosts = groupPostsByFilePath(posts, mediaOnly);

return groupedPosts.entrySet().stream()
.map(entry -> ArticlesResponseDto.of(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}

// 게시글 파일 경로 그룹화 (미디어 필터링 조건 추가)
private Map<Article, List<String>> groupPostsByFilePath(List<ArticlesWithMediaDto[]> posts, boolean mediaOnly) {
return posts.stream()
.flatMap(Arrays::stream)
.filter(post -> !mediaOnly || post.getFilePath() != null) // 미디어 있는 경우만 필터링
.collect(Collectors.groupingBy(
ArticlesWithMediaDto::getArticle,
Collectors.mapping(ArticlesWithMediaDto::getFilePath, Collectors.toList())
));
}

// 유저 정보로 게시글 조회
private List<ArticlesWithMediaDto[]> getPosts(User user) {
return articleRepository.findPostsByWriter(user);
}

// 유저 정보 조회
private User getUser(String customId) {
return userRepository.findByCustomId(customId).orElseThrow(UserNotFoundException::new);
}

//게시글 작성
public ArticleCreateResponseDto createArticle(HttpServletRequest request,
ArticleCreateRequestDto articleCreateRequestDto,
List<MultipartFile> mediaFiles) {
ArticleCreateRequestDto articleCreateRequestDto,
List<MultipartFile> mediaFiles) {
User writer = getUser(request);
String content = articleCreateRequestDto.getContent();
//게시글 생성
Expand All @@ -70,8 +105,8 @@ public ArticleCreateResponseDto createArticle(HttpServletRequest request,
public List<ArticleMedia> saveArticleMedia(List<MultipartFile> mediaFiles, Article article) {
List<ArticleMedia> articleMediaList = new ArrayList<>();

for(MultipartFile multipartFile : mediaFiles) {
String fileUrl = s3UploadMediaService.upload(multipartFile,"article");
for (MultipartFile multipartFile : mediaFiles) {
String fileUrl = s3UploadMediaService.upload(multipartFile, "article");
ArticleMedia media = ArticleMedia.createArticleMedia(article, fileUrl);
articleMediaRepository.save(media);
articleMediaList.add(media);
Expand All @@ -86,10 +121,9 @@ public void deleteArticle(HttpServletRequest request, UUID articleId) {
Article targetArticle = articleRepository.findById(articleId)
.orElseThrow(ArticleNotFoundException::new);

if(!(targetArticle.getWriter().getUserId().equals(user.getUserId()))){
if (!(targetArticle.getWriter().getUserId().equals(user.getUserId()))) {
throw new DeleteForbiddenException();
}
else{
} else {
targetArticle.deleteArticle();
deleteMediaByArticle(articleId);
hashtagService.deleteHashtags(targetArticle);
Expand Down Expand Up @@ -163,10 +197,9 @@ public void deleteRepost(HttpServletRequest request, UUID articleId) {
User user = getUser(request);
Article targetArticle = articleRepository.findById(articleId)
.orElseThrow(ArticleNotFoundException::new);
if(!(targetArticle.getWriter().getUserId().equals(user.getUserId()))){
if (!(targetArticle.getWriter().getUserId().equals(user.getUserId()))) {
throw new DeleteForbiddenException();
}
else {
} else {
targetArticle.deleteArticle();
targetArticle.getRePost().minusRepostCount();
}
Expand All @@ -181,5 +214,6 @@ private User getUser(HttpServletRequest request) {
.orElseThrow(UserNotFoundException::new);

return user;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ public class ArticleLike extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID ArticleLikeId;
private UUID PostLikeId;

@NotNull
@Column
private DeletedStatus deletedStatus;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)

@JoinColumn(name = "article_id")
private Article article;

Expand Down
Loading

0 comments on commit 844a6e1

Please sign in to comment.