Skip to content

Commit

Permalink
Merge pull request #18 from J2KB-3rd-Season/kyudong
Browse files Browse the repository at this point in the history
게시글 기능 구현
  • Loading branch information
enjay27 authored Jun 11, 2021
2 parents d5e280a + 3d74167 commit 0b9b80d
Show file tree
Hide file tree
Showing 15 changed files with 423 additions and 95 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/devin/dev/SampleData.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void createReplies() {
for (UserDetailsDto userDto : userDtos) {
for (PostDetailsDto postDto : postDtos) {
for (int i = 0; i < 2; i++) {
DefaultResponse<ReplyDto> response = replyService.reply(userDto.getId(), postDto.getPostId(),
DefaultResponse<ReplyDto> response = replyService.reply(userDto.getId(), postDto.getPost_id(),
"reply_content_" + i,
List.of("reply_img_1", "reply_img_2", "reply_img_3"));
replyDtos.add(response.getData());
Expand Down
42 changes: 37 additions & 5 deletions src/main/java/com/devin/dev/controller/post/PostController.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,57 @@
package com.devin.dev.controller.post;

import com.devin.dev.controller.reply.ReplyOrderCondition;
import com.devin.dev.dto.post.PostDetailsDto;
import com.devin.dev.model.DefaultResponse;
import com.devin.dev.security.JwtAuthTokenProvider;
import com.devin.dev.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.data.domain.Pageable;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequiredArgsConstructor
public class PostController {

private final PostService postService;

@GetMapping("/postlist/posts")
public DefaultResponse<?> getPostList(@RequestParam(defaultValue = "-1")Long id,
@PageableDefault(page = 0, sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) {
public DefaultResponse<?> getPostList(@RequestParam(defaultValue = "-1") Long id,
@PageableDefault(page = 0, sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) {
return postService.getPostInfoList(id, pageable);
}

@GetMapping("/postlist/{id}")
public DefaultResponse<PostDetailsDto> getPostDetails(
@PathVariable("id") Long postId,
@RequestParam(defaultValue = "true", name = "sort_reply") boolean sort_reply) {
ReplyOrderCondition replyOrderCondition = new ReplyOrderCondition();
if (!sort_reply) {
replyOrderCondition.setLatestDate(true);
} else {
replyOrderCondition.setLikeCount(true);
}
return postService.getPost(postId, replyOrderCondition);
}

@GetMapping("/postlist")
public DefaultResponse<?> getPostListByCondition(
PostSearchCondition condition,
@PageableDefault(page = 0, sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) {
return postService.getPostInfoListByCondition(condition, pageable);
}

@DeleteMapping("/post/{id}")
public DefaultResponse<PostDetailsDto> deletePost(@PathVariable("id") Long postId) {
return postService.deletePost(postId);
}

@PostMapping("/post")
public DefaultResponse<?> post(@RequestBody PostForm form, HttpServletRequest request) {
return postService.post(request, form);
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/devin/dev/controller/post/PostForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.devin.dev.controller.post;

import lombok.Data;

import java.util.List;

@Data
public class PostForm {
private String title;
private String content;
private List<String> post_images;
private List<String> post_tags;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.devin.dev.controller.reply;

import lombok.Data;

@Data
public class ReplyOrderCondition {
private boolean likeCount;
private boolean latestDate;
}
59 changes: 39 additions & 20 deletions src/main/java/com/devin/dev/dto/post/PostDetailsDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,61 @@
import com.querydsl.core.annotations.QueryProjection;
import lombok.Data;

import java.util.ArrayList;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Data
public class PostDetailsDto {

private Long postId;
private Long userId;
private Long post_id;
private Long publisher_id;
private String publisher_name;
private String publisher_profile;
private Long publisher_exp;
private String title;
private String username;
private String content;
private PostStatus status;
private Integer replyQuantity;
private List<String> imagePaths;
private List<String> post_images;
private List<String> post_tags;
private boolean status_accept;
private LocalDateTime date_create;
private LocalDateTime date_update;
private Integer reply_num;
private List<PostReplyDto> reply;

@QueryProjection
public PostDetailsDto(Long postId, Long userId, String title, String username, String content, PostStatus status, Integer replyQuantity, List<String> imagePaths) {
this.postId = postId;
this.userId = userId;
public PostDetailsDto(Long post_id, Long publisher_id, String publisher_name, String publisher_profile, Long publisher_exp, String title, String content, List<String> post_images, List<String> post_tags, boolean status_accept, boolean like_post, LocalDateTime date_create, LocalDateTime date_update, Integer reply_num, List<PostReplyDto> replyDtos) {
this.post_id = post_id;
this.publisher_id = publisher_id;
this.publisher_name = publisher_name;
this.publisher_profile = publisher_profile;
this.publisher_exp = publisher_exp;
this.title = title;
this.username = username;
this.content = content;
this.status = status;
this.replyQuantity = replyQuantity;
this.imagePaths = imagePaths;
this.post_images = post_images;
this.post_tags = post_tags;
this.status_accept = status_accept;
this.date_create = date_create;
this.date_update = date_update;
this.reply_num = reply_num;
this.reply = replyDtos;
}

public PostDetailsDto(Post post) {
this.postId = post.getId();
this.userId = post.getUser().getId();
this.post_id = post.getId();
this.publisher_id = post.getUser().getId();
this.publisher_name = post.getUser().getName();
this.publisher_profile = post.getUser().getProfile();
this.publisher_exp = post.getUser().getExp();
this.title = post.getTitle();
this.username = post.getUser().getName();
this.content = post.getContent();
this.status = post.getStatus();
this.replyQuantity = post.getReplies().size();
this.imagePaths = post.getImages().stream().map(PostImage::getPath).collect(Collectors.toList());
this.post_images = post.getImages().stream().map(PostImage::getPath).collect(Collectors.toList());
this.post_tags = post.getPostTags();
this.status_accept = post.getStatus() == PostStatus.SELECTED;
this.date_create = post.getCreatedDate();
this.date_update = post.getLastModifiedDate();
this.reply_num = post.getReplies().size();
this.reply = post.getReplies().stream().map(PostReplyDto::new).collect(Collectors.toList());
}
}
49 changes: 40 additions & 9 deletions src/main/java/com/devin/dev/dto/post/PostReplyDto.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
package com.devin.dev.dto.post;

import com.devin.dev.entity.reply.Reply;
import com.devin.dev.entity.reply.ReplyImage;
import com.devin.dev.entity.reply.ReplyStatus;
import com.querydsl.core.annotations.QueryProjection;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Data
public class PostReplyDto {

private Long postId;
private Long userId;
private String username;
private Long reply_id;
private Long publisher_id;
private String publisher_name;
private String publisher_profile;
private Long publisher_exp;
private String content;
private List<String> imagePaths;
private List<String> reply_images;
private boolean status_accept;
private Integer like_num;
private LocalDateTime date_create;
private LocalDateTime date_update;

@QueryProjection
public PostReplyDto(Long postId, Long userId, String username, String content, List<String> imagePaths) {
this.postId = postId;
this.userId = userId;
this.username = username;
public PostReplyDto(Long reply_id, Long publisher_id, String publisher_name, String publisher_profile, Long publisher_exp, String content, List<String> reply_images, boolean status_accept, boolean like_reply, Integer like_num, LocalDateTime date_create, LocalDateTime date_update) {
this.reply_id = reply_id;
this.publisher_id = publisher_id;
this.publisher_name = publisher_name;
this.publisher_profile = publisher_profile;
this.publisher_exp = publisher_exp;
this.content = content;
this.imagePaths = imagePaths;
this.reply_images = reply_images;
this.status_accept = status_accept;
this.like_num = like_num;
this.date_create = date_create;
this.date_update = date_update;
}

public PostReplyDto(Reply reply) {
this.reply_id = reply.getId();
this.publisher_id = reply.getUser().getId();
this.publisher_name = reply.getUser().getName();
this.publisher_profile = reply.getUser().getProfile();
this.publisher_exp = reply.getUser().getExp();
this.content = reply.getContent();
this.reply_images = reply.getImages().stream().map(ReplyImage::getPath).collect(Collectors.toList());
this.status_accept = ReplyStatus.SELECTED == reply.getStatus();
this.like_num = reply.getLikes().size();
this.date_create = reply.getCreatedDate();
this.date_update = reply.getLastModifiedDate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.devin.dev.repository.post;

import com.devin.dev.entity.post.PostLike;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PostLikeRepository extends JpaRepository<PostLike, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package com.devin.dev.repository.post;

import com.devin.dev.controller.post.PostSearchCondition;
import com.devin.dev.controller.reply.ReplyOrderCondition;
import com.devin.dev.dto.post.PostDetailsDto;
import com.devin.dev.dto.post.PostInfoDto;
import com.devin.dev.dto.post.PostSimpleDto;
import com.devin.dev.entity.post.Post;
import com.devin.dev.entity.user.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Optional;

public interface PostRepositoryQuery {

Page<String> findPostnamePageByUser(User user, Pageable pageable);

Page<PostSimpleDto> findPostDtoPageWithCondition(PostSearchCondition condition, Pageable pageable);
Page<PostInfoDto> findPostInfoDtoPageByCondition(PostSearchCondition condition, Pageable pageable);

List<PostSimpleDto> findPostDtoByUser(User user);

Page<Post> findAllByTagId(Long id, Pageable pageable);

Optional<PostDetailsDto> findPostDetailsById(Long id, ReplyOrderCondition condition);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.devin.dev.repository.post;

import com.devin.dev.controller.post.PostSearchCondition;
import com.devin.dev.dto.post.PostSimpleDto;
import com.devin.dev.dto.post.QPostSimpleDto;
import com.devin.dev.controller.reply.ReplyOrderCondition;
import com.devin.dev.dto.post.*;
import com.devin.dev.entity.post.*;
import com.devin.dev.entity.reply.QReply;
import com.devin.dev.entity.reply.QReplyImage;
import com.devin.dev.entity.reply.QReplyLike;
import com.devin.dev.entity.user.User;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
Expand All @@ -16,10 +20,17 @@
import org.springframework.transaction.annotation.Transactional;

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

import static com.devin.dev.entity.post.QPost.post;
import static com.devin.dev.entity.post.QPostImage.postImage;
import static com.devin.dev.entity.post.QPostLike.postLike;
import static com.devin.dev.entity.post.QPostTag.postTag;
import static com.devin.dev.entity.post.QSubject.subject;
import static com.devin.dev.entity.reply.QReply.reply;
import static com.devin.dev.entity.reply.QReplyImage.replyImage;
import static com.devin.dev.entity.reply.QReplyLike.replyLike;
import static com.devin.dev.entity.user.QUser.user;
import static org.springframework.util.StringUtils.hasText;

Expand Down Expand Up @@ -55,18 +66,12 @@ public Page<String> findPostnamePageByUser(User user, Pageable pageable) {
*/
@Override
public Page<PostSimpleDto> findPostDtoPageWithCondition(PostSearchCondition condition, Pageable pageable) {
QueryResults<PostSimpleDto> results = queryFactory
.selectDistinct(new QPostSimpleDto(
post.title,
user.name,
post.content,
post.status,
post.replies.size()
))
public Page<PostInfoDto> findPostInfoDtoPageByCondition(PostSearchCondition condition, Pageable pageable) {
QueryResults<Post> results = queryFactory
.selectDistinct(post)
.from(post)
.innerJoin(post.user, user)
.innerJoin(post.tags, postTag)
.leftJoin(post.user, user)
.leftJoin(post.tags, postTag)
.where(
usernameLike(condition.getUsername()),
titleLike(condition.getTitle()),
Expand All @@ -76,7 +81,9 @@ public Page<PostSimpleDto> findPostDtoPageWithCondition(PostSearchCondition cond
.limit(pageable.getPageSize())
.fetchResults();

List<PostSimpleDto> content = results.getResults();
List<Post> posts = results.getResults();

List<PostInfoDto> content = posts.stream().map(PostInfoDto::new).collect(Collectors.toList());

long total = results.getTotal();

Expand Down Expand Up @@ -113,6 +120,31 @@ public Page<Post> findAllByTagId(Long id, Pageable pageable) {
return new PageImpl<>(content, pageable, total);
}

@Override
public Optional<PostDetailsDto> findPostDetailsById(Long id, ReplyOrderCondition condition) {
Post result = queryFactory
.select(post)
.from(post)
.innerJoin(post.replies, reply).fetchJoin()
.innerJoin(post.user, user).fetchJoin()
.innerJoin(reply.user, user).fetchJoin()
.where(post.id.eq(id))
.orderBy(
replyOrder(condition)
)
.fetchOne();

Optional<PostDetailsDto> postDetailsDtoOptional;

postDetailsDtoOptional = result != null ? Optional.of(new PostDetailsDto(result)) : Optional.empty();

return postDetailsDtoOptional;
}

private OrderSpecifier<?> replyOrder(ReplyOrderCondition condition) {
return condition.isLatestDate() ? reply.lastModifiedDate.asc() : reply.likes.size().asc();
}

private BooleanExpression usernameLike(String username) {
return hasText(username) ? user.name.contains(username) : null;
}
Expand All @@ -133,4 +165,5 @@ private BooleanExpression tagsInclude(List<String> tags) {

return postTag.in(where);//(where);
}

}
Loading

0 comments on commit 0b9b80d

Please sign in to comment.