Skip to content

Commit

Permalink
좋아요 기능, Popular 페이지 렌더링, hover 효과 및 프로필 사진 등록
Browse files Browse the repository at this point in the history
  • Loading branch information
youjungHwang committed Jan 25, 2023
1 parent 974dd2e commit 221e11c
Show file tree
Hide file tree
Showing 18 changed files with 250 additions and 69 deletions.
1 change: 0 additions & 1 deletion src/main/java/com/photo/config/auth/CustomUserDetails.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.photo.domain.user.User;
import lombok.Data;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

Expand Down
21 changes: 17 additions & 4 deletions src/main/java/com/photo/domain/image/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.photo.domain.BaseTimeEntity;
import com.photo.domain.likes.Likes;
import com.photo.domain.user.User;
import lombok.*;
import javax.persistence.*;
import java.util.List;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@Entity
Expand All @@ -18,18 +21,28 @@ public class Image extends BaseTimeEntity {
private String caption;
private String imageUrl;

@JsonIgnoreProperties({"images"})
@JsonIgnoreProperties({"images"}) //
@JoinColumn(name = "userId")
@ManyToOne(fetch = FetchType.LAZY)
private User user;

@JsonIgnoreProperties({"image"})
@OneToMany(mappedBy = "image")
private List<Likes> likes;

@Transient
@Setter
private boolean likesState;

@Transient
@Setter
private int likesCount;


@Builder
public Image(String caption, String imageUrl, User user) {
this.caption = caption;
this.imageUrl = imageUrl;
this.user = user;
}



}
4 changes: 4 additions & 0 deletions src/main/java/com/photo/domain/image/ImageRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface ImageRepository extends JpaRepository<Image, Integer> {

@Query(value = "SELECT * FROM image WHERE userId IN (SELECT toUserId FROM follow WHERE fromUserId = :sessionId)", nativeQuery = true)
Page<Image> cFeed (@Param(value = "sessionId") int sessionId, @Param(value = "pageable") Pageable pageable);

@Query(value = "SELECT i.* FROM image i INNER JOIN (SELECT imageId, COUNT(imageId) likesCount FROM likes GROUP BY imageId) c ON i.id = c.imageId ORDER BY likesCount DESC", nativeQuery = true)
List<Image> cPopularImages();

}
19 changes: 19 additions & 0 deletions src/main/java/com/photo/domain/likes/LikesRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.photo.domain.likes;

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

public interface LikesRepository extends JpaRepository<Likes, Integer> {

@Modifying
@Query(value = "INSERT INTO likes(imageId, userId, createdDate) VALUES(:imageId, :sessionId, now())", nativeQuery = true)
int cLikes(@Param(value = "imageId") int imageId, @Param(value = "sessionId") int sessionId);

@Modifying
@Query(value = "DELETE FROM likes WHERE imageId =:imageId AND userId =:sessionId", nativeQuery = true)
int cUnLikes(@Param(value = "imageId") int imageId, @Param(value = "sessionId") int sessionId);


}
19 changes: 19 additions & 0 deletions src/main/java/com/photo/service/ImageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

@RequiredArgsConstructor
Expand All @@ -22,11 +23,29 @@ public class ImageService {

private final ImageRepository imageRepository;

@Transactional(readOnly = true)
public List<Image> popularImages() {
return imageRepository.cPopularImages();
}

@Transactional(readOnly = true)
public Page<Image> Feed(int sessionId, Pageable pageable) {
Page<Image> images = imageRepository.cFeed(sessionId, pageable);

images.forEach((image -> {
image.setLikesCount(image.getLikes().size());

image.getLikes().forEach((like) -> {
if(like.getUser().getId() == sessionId) {
image.setLikesState(true);
}
});

}));

return images;
}

@Value("${file.path}")
private String imageUploadRoute;

Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/photo/service/LikesService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.photo.service;

import com.photo.domain.likes.LikesRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Service
public class LikesService {

private final LikesRepository likesRepository;

@Transactional
public void ImageLikes(int imageId, int sessionId) {
likesRepository.cLikes(imageId, sessionId);
}
@Transactional
public void ImageUnLikes(int imageId, int sessionId) {
likesRepository.cUnLikes(imageId, sessionId);
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/photo/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@
import com.photo.domain.follow.FollowRepository;
import com.photo.domain.user.User;
import com.photo.domain.user.UserRepository;
import com.photo.handler.exception.CustomApiException;
import com.photo.handler.exception.CustomException;
import com.photo.handler.exception.CustomValidationApiException;
import com.photo.web.dto.user.UserProfileDto;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;



@RequiredArgsConstructor
Expand All @@ -20,6 +29,29 @@ public class UserService {
private final FollowRepository followRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;

@Value("${file.path}")
private String imageUploadRoute;

@Transactional
public User profileImageUpdate(int sessionId, MultipartFile profileImageFile) {
UUID uuid = UUID.randomUUID();
String imageFileName = uuid+"_"+profileImageFile.getOriginalFilename();

Path imageFilePath = Paths.get(imageUploadRoute+imageFileName);

try{
Files.write(imageFilePath, profileImageFile.getBytes());
}catch (Exception e){
e.printStackTrace();
}

User userEntity = userRepository.findById(sessionId).orElseThrow(
() -> new CustomApiException("유저를 찾을 수 없습니다."));
userEntity.setProfileImageUrl(imageFileName);

return userEntity;

}

@Transactional(readOnly = true)
public UserProfileDto profile(int pageUserId, int sessionId) {
Expand All @@ -38,6 +70,10 @@ public UserProfileDto profile(int pageUserId, int sessionId) {
dto.setFollowState(followState == 1);
dto.setFollowCount(followCount);

userEntity.getImages().forEach((image) -> {
image.setLikesCount(image.getLikes().size());
});

return dto;
}

Expand Down
11 changes: 8 additions & 3 deletions src/main/java/com/photo/web/ImageController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.photo.web;

import com.photo.config.auth.CustomUserDetails;
import com.photo.domain.image.Image;
import com.photo.handler.exception.CustomValidationException;
import com.photo.service.ImageService;
import com.photo.web.dto.image.ImageUploadDto;
Expand All @@ -11,6 +12,8 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;


@RequiredArgsConstructor
@Controller
Expand All @@ -27,12 +30,15 @@ public String feed(@AuthenticationPrincipal CustomUserDetails customUserDetails,
@GetMapping("/image/popular")
public String popular(@AuthenticationPrincipal CustomUserDetails customUserDetails, Model model) {
model.addAttribute("sessionId", customUserDetails.getUser().getId());

List<Image> images = imageService.popularImages();
model.addAttribute("images", images);
return "/image/popular";
}


@GetMapping("/image/upload")
public String upload() {
public String upload(@AuthenticationPrincipal CustomUserDetails customUserDetails, Model model) {
model.addAttribute("sessionId", customUserDetails.getUser().getId());
return "image/upload";
}

Expand All @@ -41,7 +47,6 @@ public String imageUpload(@AuthenticationPrincipal CustomUserDetails customUserD
if(imageUploadDto.getFile().isEmpty()) {
throw new CustomValidationException("이미지가 첨부되지 않았습니다.",null);
}

imageService.imageUpload(customUserDetails, imageUploadDto);
return "redirect:/user/"+customUserDetails.getUser().getId();
}
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/com/photo/web/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ public String profile(@PathVariable int pageUserId, Model model, @Authentication
UserProfileDto userProfileDto = userService.profile(pageUserId, customUserDetails.getUser().getId());
model.addAttribute("dto", userProfileDto);
model.addAttribute("sessionId", customUserDetails.getUser().getId());

return "user/profile";
}

@GetMapping("/user/{id}/update")
public String update(@PathVariable int id, @AuthenticationPrincipal CustomUserDetails customUserDetails, Model model) {
model.addAttribute("sessionUser", customUserDetails.getUser());

return "user/update";
}
}
18 changes: 15 additions & 3 deletions src/main/java/com/photo/web/api/ImageApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.photo.config.auth.CustomUserDetails;
import com.photo.domain.image.Image;
import com.photo.service.ImageService;
import com.photo.service.LikesService;
import com.photo.web.dto.ResDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
Expand All @@ -12,22 +13,33 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;


@RequiredArgsConstructor
@RestController
public class ImageApiController {

private final ImageService imageService;
private final LikesService likesService;

@GetMapping("/api/feed")
public ResponseEntity<?> Feed(@AuthenticationPrincipal CustomUserDetails customUserDetails,
@PageableDefault(size=4, sort="id", direction = Sort.Direction.DESC) Pageable pageable){
@PageableDefault(size=4, sort="id", direction = Sort.Direction.DESC) Pageable pageable){
Page<Image> images = imageService.Feed(customUserDetails.getUser().getId(), pageable);
return new ResponseEntity<>(new ResDto<>(1,"피드 성공", images), HttpStatus.OK);
}

@PostMapping("/api/image/{imageId}/likes")
public ResponseEntity<?> ImageLikes(@PathVariable int imageId, @AuthenticationPrincipal CustomUserDetails customUserDetails){
likesService.ImageLikes(imageId, customUserDetails.getUser().getId());
return new ResponseEntity<>(new ResDto<>(1,"좋아요 성공",null), HttpStatus.CREATED);
}

@DeleteMapping("/api/image/{imageId}/likes")
public ResponseEntity<?> ImageUnLikes(@PathVariable int imageId, @AuthenticationPrincipal CustomUserDetails customUserDetails){
likesService.ImageUnLikes(imageId, customUserDetails.getUser().getId());
return new ResponseEntity<>(new ResDto<>(1,"좋아요 취소 성공",null), HttpStatus.OK);
}

}
11 changes: 9 additions & 2 deletions src/main/java/com/photo/web/api/UserApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.util.HashMap;
Expand All @@ -31,13 +32,19 @@ public class UserApiController {
private final UserService userService;
private final FollowService followService;

@PutMapping("/api/user/{sessionId}/profileImageUrl")
public ResponseEntity<?> profileImageUpdate(@PathVariable int sessionId, MultipartFile profileImageFile,
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
User userEntity = userService.profileImageUpdate(sessionId, profileImageFile);
customUserDetails.setUser(userEntity);
return new ResponseEntity<>(new ResDto<>(1, "회원 프로필 사진 변경 성공", null), HttpStatus.OK);
}


@GetMapping("/api/user/{pageUserId}/follow")
public ResponseEntity<?> followList(@PathVariable int pageUserId, @AuthenticationPrincipal CustomUserDetails customUserDetails) {
List<FollowInfoDto> followInfoDto = followService.followInfoList(customUserDetails.getUser().getId(), pageUserId);

return new ResponseEntity<>(new ResDto<>(1, "구독자 정보 리스트 불러오기 성공", followInfoDto), HttpStatus.OK);

}

@PutMapping("/api/user/{id}")
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/photo/web/dto/ResDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

@Data
@AllArgsConstructor
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/photo/web/dto/auth/SignupReqDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,4 @@ public User toEntity() {
.build();
}


}
1 change: 0 additions & 1 deletion src/main/java/com/photo/web/dto/follow/FollowInfoDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ public FollowInfoDto(Object[] object) {
this.equalUserState = Integer.parseInt(String.valueOf(object[4]));
}


}

0 comments on commit 221e11c

Please sign in to comment.