Skip to content

Commit

Permalink
refactor: #15 conflict 해결
Browse files Browse the repository at this point in the history
  • Loading branch information
ehs208 committed Nov 8, 2024
2 parents 3a86f5f + 238ac7d commit 96ee630
Show file tree
Hide file tree
Showing 31 changed files with 797 additions and 101 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
package com.leets.xcellentbe.domain.article.controller;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

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;

import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/api/articles")
@RequestMapping("/api/article")
@RequiredArgsConstructor
public class ArticleController {

private final ArticleService articleService;

@GetMapping("/{customId}/list")
Expand All @@ -37,4 +49,71 @@ public ResponseEntity<GlobalResponseDto<List<ArticlesResponseDto>>> getMediaArti
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) {
if (mediaFiles == null) {
mediaFiles = Collections.emptyList();
}
ArticleCreateResponseDto responseDto = articleService.createArticle(request, articleCreateRequestDto,
mediaFiles);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(responseDto));
}

//게시글 삭제(소프트)
@PatchMapping("/{articleId}")
@Operation(summary = "게시글 삭제", description = "게시글을 삭제(상태 변경)합니다.")
public ResponseEntity<GlobalResponseDto<Void>> deleteArticle(
HttpServletRequest request,
@PathVariable UUID articleId) {
articleService.deleteArticle(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success());
}

//게시글 조회
@GetMapping("/{articleId}")
@Operation(summary = "게시글 조회", description = "해당 ID의 게시글을 조회합니다.")
public ResponseEntity<GlobalResponseDto<ArticleResponseDto>> getArticle(
HttpServletRequest request,
@PathVariable UUID articleId) {
ArticleResponseDto articleResponseDto = articleService.getArticle(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(articleResponseDto));
}

//메인 페이지 게시글 조회
@GetMapping
@Operation(summary = "게시글 목록 조회(스크롤)", description = "페이징을 적용하여 게시글 목록을 조회합니다.")
public ResponseEntity<GlobalResponseDto<List<ArticleResponseDto>>> getArticles(
HttpServletRequest request,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime cursor,
@RequestParam(defaultValue = "10") int size) {
List<ArticleResponseDto> articles = articleService.getArticles(request, cursor, size);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(articles));
}

//리포스트 작성
@PostMapping("/{articleId}/repost")
@Operation(summary = "게시글 리포스트", description = "게시글을 리포스트합니다.")
public ResponseEntity<GlobalResponseDto<ArticleCreateResponseDto>> rePostArticle(
HttpServletRequest request,
@PathVariable UUID articleId) {
ArticleCreateResponseDto responseDto = articleService.rePostArticle(request, articleId);
return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(responseDto));
}

//리포스트 삭제
@PatchMapping("/{articleId}/unRepost")
@Operation(summary = "리포스트 삭제", description = "리포스트를 삭제합니다.")
public ResponseEntity<GlobalResponseDto<Void>> deleteRepost(
HttpServletRequest request,
@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
@@ -1,9 +1,12 @@
package com.leets.xcellentbe.domain.article.domain;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import com.leets.xcellentbe.domain.articleMedia.domain.ArticleMedia;
import com.leets.xcellentbe.domain.hashtag.domain.Hashtag;
import com.leets.xcellentbe.domain.shared.BaseTimeEntity;
import com.leets.xcellentbe.domain.shared.DeletedStatus;
import com.leets.xcellentbe.domain.user.domain.User;

Expand All @@ -20,17 +23,19 @@
import jakarta.persistence.OneToMany;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Article {

public class Article extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID postId;
private UUID articleId;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
Expand All @@ -42,29 +47,94 @@ public class Article {
private String content;

@NotNull
@Column
@Column(columnDefinition = "VARCHAR(30)")
@Enumerated(EnumType.STRING)
private DeletedStatus deletedStatus;

@NotNull
@Column
private Boolean isPinned;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "repost_id")
private Article reArticle;
private Article rePost;

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "hashtag_id")
@OneToMany(mappedBy = "article")
private List<Hashtag> hashtags;

public Article(User writer, String content, DeletedStatus deletedStatus, Boolean isPinned, Article reArticle,
@OneToMany(mappedBy = "article")
private List<ArticleMedia> mediaList;

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 Article(User writer, String content, DeletedStatus deletedStatus, Article rePost,
List<Hashtag> hashtags) {
this.writer = writer;
this.content = content;
this.deletedStatus = deletedStatus;
this.isPinned = isPinned;
this.reArticle = reArticle;
this.rePost = rePost;
this.hashtags = hashtags;
}

public static Article createArticle(User writer, String content) {
return Article.builder()
.writer(writer)
.content(content)
.deletedStatus(DeletedStatus.NOT_DELETED)
.build();
}

public void addRepost(Article rePost) {
this.rePost = rePost;
}

public void addHashtag(List<Hashtag> hashtags) {
if (this.hashtags == null) {
this.hashtags = new ArrayList<>();
}
this.hashtags.addAll(hashtags);
}

public void deleteArticle() {
this.deletedStatus = DeletedStatus.DELETED;
}

public void addMedia(List<ArticleMedia> mediaList) {
if (this.mediaList == null) {
this.mediaList = new ArrayList<>();
}
this.mediaList.addAll(mediaList);
}

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

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

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

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

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

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

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

}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
package com.leets.xcellentbe.domain.article.domain.repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

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;

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.postId = pm.article.postId WHERE p.writer = :user")
@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,10 @@
package com.leets.xcellentbe.domain.article.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class ArticleCreateRequestDto {
private String content;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.leets.xcellentbe.domain.article.dto;

import java.util.UUID;

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

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

@Getter
@NoArgsConstructor
public class ArticleCreateResponseDto {

private UUID articleId;

@Builder
private ArticleCreateResponseDto(UUID articleId, String message) {
this.articleId = articleId;
}

public static ArticleCreateResponseDto from(Article article) {
return ArticleCreateResponseDto.builder()
.articleId(article.getArticleId())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.leets.xcellentbe.domain.article.dto;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import com.leets.xcellentbe.domain.article.domain.Article;
import com.leets.xcellentbe.domain.articleMedia.domain.ArticleMedia;
import com.leets.xcellentbe.domain.hashtag.domain.Hashtag;
import com.leets.xcellentbe.domain.shared.DeletedStatus;

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

@Getter
@NoArgsConstructor
public class ArticleResponseDto {
private UUID articleId;
private Long writerId;
private String content;
private DeletedStatus deletedStatus;
private List<String> hashtags;
private UUID rePostId;
private List<String> mediaUrls;
private int viewCnt;
private int rePostCnt;
private int likeCnt;
private int commentCnt;
private boolean owner;

@Builder
private ArticleResponseDto(UUID articleId, Long writerId, String content, DeletedStatus deletedStatus,
List<String> hashtags, UUID rePostId, List<String> mediaUrls, int viewCnt,
int rePostCnt, int likeCnt, int commentCnt, boolean owner) {
this.articleId = articleId;
this.writerId = writerId;
this.content = content;
this.deletedStatus = deletedStatus;
this.hashtags = hashtags;
this.rePostId = rePostId;
this.mediaUrls = mediaUrls;
this.viewCnt = viewCnt;
this.rePostCnt = rePostCnt;
this.likeCnt = likeCnt;
this.commentCnt = commentCnt;
this.owner = owner;
}

public static ArticleResponseDto from(Article article, boolean isOwner) {
return ArticleResponseDto.builder()
.articleId(article.getArticleId())
.content(article.getContent())
.deletedStatus(article.getDeletedStatus())
.writerId(article.getWriter().getUserId())
.hashtags(article.getHashtags() != null ? article.getHashtags()
.stream()
.map(Hashtag::getContent)
.collect(Collectors.toList()) : null)
.rePostId(article.getRePost() != null ? article.getRePost().getArticleId() : null)
.mediaUrls(article.getMediaList() != null ? article.getMediaList()
.stream()
.map(ArticleMedia::getFilePath) // 이미지 URL로 매핑
.collect(Collectors.toList()) : null)
.viewCnt(article.getViewCnt())
.rePostCnt(article.getRepostCnt())
.likeCnt(article.getLikeCnt())
.commentCnt(article.getCommentCnt())
.owner(isOwner)
.build();
}
}
Loading

0 comments on commit 96ee630

Please sign in to comment.