Skip to content
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

feature: 게시글 전체, 상세조회 #13 #16

Merged
merged 1 commit into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ dependencies {

// S3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@
import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.hackathon.TimeLapse.apiPayload.ApiResponse;
Expand All @@ -30,32 +26,42 @@
@RequestMapping("/api/article")
public class ArticleController {

private final ArticleService articleService;
private final S3Service s3Service;
private final ImageService imageService;

@PostMapping(value = "", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public ApiResponse<ArticleResponseDTO.createArticleResultDTO> createArticle(
@RequestPart @Valid ArticleRequestDTO.createArticleDTO request,
@RequestPart List<MultipartFile> files
) throws IOException {
long memberId = Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getName());
log.info("[*] memberId: " + memberId);
System.out.println(files.get(0));
List<String> uploadedFilesLinks = s3Service.uploadMultipleFiles(files);
Article article = articleService.createArticle(memberId, request, uploadedFilesLinks);

List<Image> images = new ArrayList<>();
for (String url : uploadedFilesLinks) {
Image image = Image.builder()
.image_url(url)
.article(article)
.build();
images.add(image);
}
imageService.addImages(article.getId(), new ImageRequestDTO.addImagesDTO(uploadedFilesLinks));

return ApiResponse.onSuccess(ArticleConverter.toCreateReviewResultDTO(article));
}
private final ArticleService articleService;
private final S3Service s3Service;
private final ImageService imageService;

@PostMapping(value = "", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public ApiResponse<ArticleResponseDTO.createArticleResultDTO> createArticle(
@RequestPart @Valid ArticleRequestDTO.createArticleDTO request,
@RequestPart List<MultipartFile> files
) throws IOException {
Long memberId = request.getMemberId();
List<String> uploadedFilesLinks = s3Service.uploadMultipleFiles(files);
Article article = articleService.createArticle(memberId, request, uploadedFilesLinks);

List<Image> images = new ArrayList<>();
for (String url : uploadedFilesLinks) {
Image image = Image.builder()
.image_url(url)
.article(article)
.build();
images.add(image);
}
imageService.addImages(article.getId(), new ImageRequestDTO.addImagesDTO(uploadedFilesLinks));

return ApiResponse.onSuccess(ArticleConverter.toCreateReviewResultDTO(article));
}

@GetMapping("/")
public ApiResponse<ArticleResponseDTO.ArticleListDTO> getAllArticles(@RequestParam(name = "memberId") Long memberId) {
ArticleResponseDTO.ArticleListDTO articles = articleService.getAllArticles(memberId);
return ApiResponse.onSuccess(articles);
}

@GetMapping("/{articleId}")
public ApiResponse<ArticleResponseDTO.ArticleDetailDTO> getArticleDetail(@PathVariable Long articleId) {
ArticleResponseDTO.ArticleDetailDTO article = articleService.getArticleDetail(articleId);
return ApiResponse.onSuccess(article);
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.hackathon.TimeLapse.article;

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

public class ArticleConverter {
public static Article toArticle(ArticleRequestDTO.createArticleDTO request){
Expand All @@ -19,4 +21,41 @@ public static ArticleResponseDTO.createArticleResultDTO toCreateReviewResultDTO(
.createdAt(LocalDateTime.now())
.build();
}

public static ArticleResponseDTO.ArticleSummaryDTO toSummaryDTO(Article article) {
String imageUrl = article.getImageList().isEmpty() ? null : article.getImageList().get(0).getImage_url();
return new ArticleResponseDTO.ArticleSummaryDTO(
article.getId(),
imageUrl
);
}

public static ArticleResponseDTO.ArticleDetailDTO toDetailDTO(Article article) {
List<String> imageUrls = article.getImageList().stream()
.map(image -> image.getImage_url())
.collect(Collectors.toList());
return new ArticleResponseDTO.ArticleDetailDTO(
article.getId(),
article.getTitle(),
article.getDescription(),
article.getLatitude(),
article.getLongitude(),
article.getStatus(),
imageUrls
);
}

public static ArticleResponseDTO.LatestArticleDTO toLatestArticleDTO(Article article) {
return new ArticleResponseDTO.LatestArticleDTO(
article.getLatitude(),
article.getLongitude()
);
}

public static ArticleResponseDTO.ArticleListDTO toArticleListDTO(List<Article> articles, Article latestArticle) {
List<ArticleResponseDTO.ArticleSummaryDTO> articleDTOs = articles.stream()
.map(ArticleConverter::toSummaryDTO)
.collect(Collectors.toList());
return new ArticleResponseDTO.ArticleListDTO(articleDTOs, toLatestArticleDTO(latestArticle));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.hackathon.TimeLapse.article;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

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

public interface ArticleRepository extends JpaRepository<Article, Long> {
@Query("SELECT a FROM Article a WHERE a.member.id = :memberId ORDER BY a.createdAt DESC")
List<Article> findTopByMemberIdOrderByCreatedAtDesc(@Param("memberId") Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class ArticleRequestDTO {

@Getter
public static class createArticleDTO {
@NotNull
private Long memberId;
@NotNull
private Double latitude;
@NotNull
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.hackathon.TimeLapse.article;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;

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

public class ArticleResponseDTO {
@Builder
Expand All @@ -17,4 +15,45 @@ public static class createArticleResultDTO{
LocalDateTime createdAt;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class ArticleSummaryDTO {
private Long id;
private String imageUrl;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class ArticleDetailDTO {
private Long id;
private String title;
private String description;
private Double latitude;
private Double longitude;
private Long status;
private List<String> imageUrls;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class ArticleListDTO {
private List<ArticleSummaryDTO> articles;
private LatestArticleDTO latestArticle;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class LatestArticleDTO {
private Double latitude;
private Double longitude;
}

}
31 changes: 29 additions & 2 deletions src/main/java/com/hackathon/TimeLapse/article/ArticleService.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.hackathon.TimeLapse.article;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import com.hackathon.TimeLapse.apiPayload.exception.ArticleNotFoundException;
import com.hackathon.TimeLapse.apiPayload.exception.MemberNotFoundException;
import com.hackathon.TimeLapse.image.ImageService;
import com.hackathon.TimeLapse.member.MemberRepository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -12,19 +16,42 @@ public class ArticleService {
private final ArticleRepository articleRepository;
private final MemberRepository memberRepository;

@PersistenceContext
private EntityManager entityManager;

public ArticleService(ArticleRepository articleRepository, MemberRepository memberRepository) {
this.articleRepository = articleRepository;
this.memberRepository = memberRepository;
}

@Transactional
public Article createArticle(Long memberId, ArticleRequestDTO.createArticleDTO request,
List<String> uploadedFilesLinks) {
List<String> uploadedFilesLinks) {
Article article = ArticleConverter.toArticle(request);

article.setMember(memberRepository.findById(memberId)
.orElseThrow(() -> new MemberNotFoundException("Member not found with id: " + memberId)));

return articleRepository.save(article);
}

@Transactional
public ArticleResponseDTO.ArticleListDTO getAllArticles(Long memberId) {
List<Article> articles = articleRepository.findAll();
articles.forEach(article -> {
article.getImageList().size(); // 초기화
});

List<Article> latestArticles = articleRepository.findTopByMemberIdOrderByCreatedAtDesc(memberId);
Article latestArticle = latestArticles.isEmpty() ? null : latestArticles.get(0);

return ArticleConverter.toArticleListDTO(articles, latestArticle);
}

@Transactional
public ArticleResponseDTO.ArticleDetailDTO getArticleDetail(Long articleId) {
Article article = articleRepository.findById(articleId)
.orElseThrow(() -> new ArticleNotFoundException("Article not found with id: " + articleId));
return ArticleConverter.toDetailDTO(article);
}
}
Loading