Skip to content

Commit

Permalink
Feat(#54): resolved rebase conflicts
Browse files Browse the repository at this point in the history
Feat(#54): 커뮤니티 API 기초 구현

Feat(#54): 게시글 상세 조회 시 태그 포함

Feat(#54): todo 작성

Feat(#54): 게시글 생성 시 이미지 업로드 bug fix

Feat(#54): 게시글 상세 조회 시 좋아요 여부와 작성자 프로필 사진 url 반환

Feat(#54): 게시글 상세 조회 시 좋아요 여부와 작성자 프로필 사진 url 반환

Feat(#54): 게시글 리스트 조회 시, 좋아요 누른 여부를 포함

Feat(#54): todo 주석 제거 및 더미데이터 제거

Feat(#54): 썸네일 이미지 관련 요구사항 적용
- 첫 이미지를 썸네일 이미지로 지정

Feat(#54): 게시물 카테고리 수정
- 일상, 교통, 치안, 기타

Hotfix: npe fix

Feat(#54): rename field for resolve rebase conflict

Docs(#54): update todo

Fix(#54): 좋아요 버그 수정

Fix(#54): 스웨거 jwt 버그 수정

Feat(#54): 게시글/댓글 좋아요 api 구현

Feat(#54): 알림 저장 시 닉네임도 저장

Feat(#54): 좋아요 관련 예외 로직

Feat(#54): 푸시 알림 태그 구분

Feat(#54): 푸시 알림 발송 시 db 에 저장

Feat(#54): 게시글 좋아요 api (wip)

Feat(#54): 게시글 좋아요 api (wip)

Feat(#54): improvement community apis
- 게시글 작성 시, 작성자의 주소 로깅
- 게시글에 댓글 등록 시 푸시 알림 전송

Feat(#54): improvement community apis
- 게시글 작성 시, 작성자의 주소 로깅
- 게시글에 댓글 등록 시 푸시 알림 전송

Feat(#54): catch exception

Docs(#54): todo 작성

Feat(#54): 게시글 수정하기 api 구현 및 게시글 삭제 http method 를 patch 로 변경

Feat(#54): 대댓글 계층형 조회 api 구현

Feat(#54): 대댓글 작성 api 구현

Feat(#54): 게시글에 댓글 작성하기 api 구현

Feat(#54): 게시글 조회 no offset paging api 구현

Feat(#54): removed test api for fcm

Feat(#54): removed test api for fcm

Feat(#54): 게시글 상세 조회 시, 제목 및 내용 포함

Feat(#54): 게시글 상세 조회 및 삭제 API 구현

Docs(#54): 게시글 작성 API

Feat(#54): removed Qclass

Feat(#54): 게시글 활성화 상태 필드 추가

Feat(#54): 게시글 작성 API 구현

Feat(#54): rename CommunityParticipant
- to ArticleParticipant

Feat(#54): 게시글, 댓글, 커뮤니티 참여자 레포지토리 구현

Feat(#54): relocate s3Provider

Docs(#54): 프로필 사진 업로드 api
- swagger api summary, description

Feat(#54): 커뮤니티 엔티티 설계
- Article: 동네생활 게시글
- ArticleTag: 게시글 태그
- CommentEntity: 댓글
- CommunityParticipant: 게시글 참여자

Feat(#54): 회원 프로필 사진 업로드 API 구현

Feat(#54): 회원 엔티티 필드 추가
- 프로필 사진, 닉네임, 실명, fcm 토큰

Feat(#54): implement SecurityContextProvider
- for parsing principal from jwt token

Feat(#54): member extends baseTimeEntity
  • Loading branch information
versatile0010 committed Nov 16, 2023
1 parent 9d418ad commit da90752
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ public class ArticleController {
1. title 은 글 제목 입니다 (not null)
2. content 는 글 내용 입니다 (not null)
3. articleTag 는 게시글 태그 입니다. LIFE(일상), FRAUD(사기), SAFETY(안전), REPORT(제보)
3. articleTag 는 게시글 태그 입니다. LIFE(일상), TRAFFIC(교통), SAFETY(치안), NONE(기타) -> 영어로 보내주세요
4. imageList 는 이미지 (MultiPart) 리스트 입니다.
5. thumbNailImageIdx 는 썸네일 이미지의 인덱스 입니다. (0,1,2, ...
5. imageList 의 첫 원소를 썸네일로 지정합니다.
imageList 에 이미지를 담아서 보내는 경우,
idx 에 따라서 썸네일 이미지를 결정합니다.
""")

@PostMapping
public ResponseEntity<UploadArticleResponse> uploadArticle(@RequestBody @Valid UploadArticleRequest request) {
public ResponseEntity<UploadArticleResponse> uploadArticle(@ModelAttribute @Valid UploadArticleRequest request) {
return ResponseEntity.created(URI.create("/api/articles"))
.body(articleService.uploadArticle(request));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class UploadArticleRequest {

// 이미지 관련
private List<MultipartFile> imageList; // 이미지 리스트
private Long thumbNailImageIdx; // 썸네일 이미지의 순서 (0,1,2,...)

private Double longitude;
private Double latitude;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.numberone.backend.domain.article.dto.response;

import com.numberone.backend.domain.article.entity.Article;
import com.numberone.backend.domain.article.entity.ArticleStatus;
import com.numberone.backend.domain.article.entity.ArticleTag;
import com.numberone.backend.domain.member.entity.Member;
import lombok.*;

Expand All @@ -22,18 +24,26 @@ public class GetArticleDetailResponse {
private LocalDateTime modifiedAt;
private String title;
private String content;
private boolean isLiked;
private ArticleTag articleTag;

// 작성자 관련
private String memberName;
private String memberNickName;
private String address; // todo: 더미 데이터
private String ownerName;
private String ownerNickName;
private String address;
private Long ownerMemberId;
private String ownerProfileImageUrl;

// 이미지 관련
private List<String> imageUrls;
private String thumbNailImageUrl;

public static GetArticleDetailResponse of(Article article, List<String> imageUrls, String thumbNailImageUrl, Member member){
public static GetArticleDetailResponse of(
Article article,
List<String> imageUrls,
String thumbNailImageUrl,
Member owner,
List<Long> memberLikedArticleList) {
return GetArticleDetailResponse.builder()
.articleId(article.getId())
.title(article.getTitle())
Expand All @@ -45,13 +55,17 @@ public static GetArticleDetailResponse of(Article article, List<String> imageUrl
)
.createdAt(article.getCreatedAt())
.modifiedAt(article.getModifiedAt())
.ownerMemberId(member.getId())
.memberName(member.getRealName())
.memberNickName(member.getNickName())
.ownerMemberId(owner.getId())
.ownerName(owner.getRealName())
.ownerNickName(owner.getNickName())
.imageUrls(imageUrls)
.thumbNailImageUrl(thumbNailImageUrl)
.address("서울시 광진구 자양동") // 교체
.address(article.getAddress())
.ownerProfileImageUrl(owner.getProfileImageUrl())
.isLiked(memberLikedArticleList.contains(article.getId()))
.articleTag(article.getArticleTag())
.build();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import lombok.*;

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

@ToString
Expand All @@ -32,6 +33,7 @@ public class GetArticleListResponse {

private Integer articleLikeCount;
private Integer commentCount;
private Boolean isLiked;


@QueryProjection
Expand All @@ -57,7 +59,7 @@ public void setThumbNailImageUrl(String thumbNailImageUrl){
this.thumbNailImageUrl = thumbNailImageUrl;
}

public void updateInfo(Optional<Member> owner, Optional<ArticleImage> articleImage){
public void updateInfo(Optional<Member> owner, Optional<ArticleImage> articleImage, List<Long> memberLikedArticleIdList){
owner.ifPresentOrElse(
o -> setOwnerNickName(o.getNickName()),
() -> setOwnerNickName("알 수 없는 사용자")
Expand All @@ -66,7 +68,7 @@ public void updateInfo(Optional<Member> owner, Optional<ArticleImage> articleIma
image -> setThumbNailImageUrl(image.getImageUrl()),
() -> setThumbNailImageUrl("")
);
this.isLiked = memberLikedArticleIdList.contains(id);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class ModifyArticleResponse {
private String thumbNailImageUrl;

// 작성자 주소
private String address; // todo: 더미 데이터
private String address;

public static ModifyArticleResponse of(Article article, List<String> imageUrls, String thumbNailImageUrl){
return ModifyArticleResponse.builder()
Expand All @@ -34,7 +34,7 @@ public static ModifyArticleResponse of(Article article, List<String> imageUrls,
.modifiedAt(article.getModifiedAt())
.imageUrls(imageUrls)
.thumbNailImageUrl(thumbNailImageUrl)
.address("서울시 광진구 자양동")
.address(article.getAddress())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class UploadArticleResponse {
private String thumbNailImageUrl;

// 작성자 주소
private String address; // todo: 더미 데이터
private String address;

public static UploadArticleResponse of(Article article, List<String> imageUrls, String thumbNailImageUrl){
return UploadArticleResponse.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class Article extends BaseTimeEntity {

@ColumnDefault("0")
@Comment("게시글 좋아요 개수")
private Integer likeCount; // todo: 동시성 처리
private Integer likeCount;

@ColumnDefault("0")
@Comment("게시글에 달린 댓글 개수")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
@RequiredArgsConstructor
public enum ArticleTag {
LIFE, // 일상
FRAUD, // 사기
TRAFFIC, // 교통
SAFETY, // 치안
REPORT; // 제보
NONE; // 기타
private String value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import com.numberone.backend.domain.comment.dto.response.CreateCommentResponse;
import com.numberone.backend.domain.comment.entity.CommentEntity;
import com.numberone.backend.domain.comment.repository.CommentRepository;
import com.numberone.backend.domain.like.entity.ArticleLike;
import com.numberone.backend.domain.like.repository.ArticleLikeRepository;
import com.numberone.backend.domain.member.entity.Member;
import com.numberone.backend.domain.member.repository.MemberRepository;
import com.numberone.backend.domain.notification.entity.NotificationTag;
Expand Down Expand Up @@ -50,6 +52,7 @@ public class ArticleService {
private final ArticleParticipantRepository articleParticipantRepository;
private final ArticleImageRepository articleImageRepository;
private final CommentRepository commentRepository;
private final ArticleLikeRepository articleLikeRepository;
private final S3Provider s3Provider;
private final LocationProvider locationProvider;
private final FcmMessageProvider fcmMessageProvider;
Expand All @@ -68,6 +71,7 @@ public UploadArticleResponse uploadArticle(UploadArticleRequest request) {
owner.getId(),
request.getArticleTag())
);

articleParticipantRepository.save(
new ArticleParticipant(article, owner)
);
Expand All @@ -89,7 +93,7 @@ public UploadArticleResponse uploadArticle(UploadArticleRequest request) {
new ArticleImage(article, imageUrl)
);
articleImages.add(savedArticleImage);
if (Objects.equals(i, request.getThumbNailImageIdx())) {
if (i == 0) {
thumbNailImageUrl = imageUrl;
thumbNailImageId = savedArticleImage.getId();
}
Expand All @@ -104,6 +108,7 @@ public UploadArticleResponse uploadArticle(UploadArticleRequest request) {
Double latitude = request.getLatitude();
Double longitude = request.getLongitude();
if (latitude != null && longitude != null) {
// 주소가 null 이 아닌 경우에만 api 요청하여 update
String address = locationProvider.pos2address(request.getLatitude(), request.getLongitude());
article.updateAddress(address);
}
Expand All @@ -122,10 +127,12 @@ public DeleteArticleResponse deleteArticle(Long articleId) {

public GetArticleDetailResponse getArticleDetail(Long articleId) {
String principal = SecurityContextProvider.getAuthenticatedUserEmail();
Member owner = memberRepository.findByEmail(principal)
Member member = memberRepository.findByEmail(principal) // 회원
.orElseThrow(NotFoundMemberException::new);
Article article = articleRepository.findById(articleId)
.orElseThrow(NotFoundArticleException::new);
Member owner = memberRepository.findById(article.getArticleOwnerId()) // 작성자
.orElseThrow(NotFoundMemberException::new);

List<String> imageUrls = articleImageRepository.findByArticle(article)
.stream()
Expand All @@ -140,26 +147,38 @@ public GetArticleDetailResponse getArticleDetail(Long articleId) {
thumbNailImageUrl = thumbNailImage.get().getImageUrl();
}

return GetArticleDetailResponse.of(article, imageUrls, thumbNailImageUrl, owner);
// 내가 좋아요 한 게시글의 ID 리스트
List<Long> memberLikedArticleIdList = articleLikeRepository.findByMember(member)
.stream().map(ArticleLike::getArticleId)
.toList();

return GetArticleDetailResponse.of(article, imageUrls, thumbNailImageUrl, owner, memberLikedArticleIdList);
}

public Slice<GetArticleListResponse> getArticleListPaging(ArticleSearchParameter param, Pageable pageable) {
String principal = SecurityContextProvider.getAuthenticatedUserEmail();
Member member = memberRepository.findByEmail(principal)
.orElseThrow(NotFoundMemberException::new);
List<Long> memberLikedArticleIdList = articleLikeRepository.findByMember(member)
.stream().map(ArticleLike::getArticleId)
.toList();
return new SliceImpl<>(
articleRepository.getArticlesNoOffSetPaging(param, pageable)
.stream()
.peek(this::updateArticleInfo)
.toList()
);
.peek(article -> {
updateArticleInfo(article, memberLikedArticleIdList);
})
.toList());
}

public void updateArticleInfo(GetArticleListResponse articleInfo) {
public void updateArticleInfo(GetArticleListResponse articleInfo, List<Long> memberLikedArticleIdList) {
Long ownerId = articleInfo.getOwnerId();
Long thumbNailImageUrlId = articleInfo.getThumbNailImageId();

Optional<Member> owner = memberRepository.findById(ownerId);
Optional<ArticleImage> articleImage = articleImageRepository.findById(thumbNailImageUrlId);

articleInfo.updateInfo(owner, articleImage);
articleInfo.updateInfo(owner, articleImage, memberLikedArticleIdList);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class CommentEntity extends BaseTimeEntity {
private Integer depth;

@Comment("댓글 좋아요 개수")
private Integer likeCount; // todo: 동시성 처리
private Integer likeCount;

@Comment("댓글 내용")
private String content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
@Tag(name = "members", description = "사용자 관련 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/members")
public class MemberController {
private final MemberService memberService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public void create(String email, String realName) {
public void initMemberData(String email, OnboardingRequest onboardingRequest) {
Member member = memberRepository.findByEmail(email)
.orElseThrow(NotFoundMemberException::new);
member.setOnboardingData(onboardingRequest.getNickname(), onboardingRequest.getFcmToken());
notificationDisasterRepository.deleteAllByMemberId(member.getId());
member.setOnboardingData(onboardingRequest.getNickname(), onboardingRequest.getFcmToken());
notificationRegionRepository.deleteAllByMemberId(member.getId());
for (OnboardingAddress address : onboardingRequest.getAddresses()) {
notificationRegionRepository.save(NotificationRegion.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void sendFcm(Member member, NotificationMessage notificationMessage, Noti
String token = member.getFcmToken();
if (Objects.isNull(token)){
log.error("해당 회원의 fcm 토큰이 존재하지 않아, 푸시알람을 전송할 수 없습니다.");
// todo : 예외 핸들링
return;
}

Expand Down

0 comments on commit da90752

Please sign in to comment.